diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..e69de29b diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..eeb586b3 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..750d3f75 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,2251 @@ + .----------------------. +--| X-Chat ChangeLog |-------------------------------------------- + `----------------------' + +To see more details of bugs, go to this URL: +http://sf.net/tracker/?func=detail&atid=100239&group_id=239&aid=NUMBER +Where "NUMBER" is the bug number. + +This log DOES NOT apply to XChat for Windows. + +There are always more changes than listed here, these are just the +highlights. The full CVS log is available at www.xchat.org/cvslog/ + +------------------------------------------------------------------------------ + 2.8.10 - dd/mm/yyyy +------------------------------------------------------------------------------ + - Perl (Lian Wan Situ) + * Added two new options to hook_print, run_after_event and filter. See + documentation for details. + * When building on Windows, generate the name of the DLL for the Perl + library based on information from the header files instead of hardcoding + the value. + * Fixed a bug in the reinit handling code. The bug prevented the plugin from + cleaning up properly. Which includes unloading scripts and removing + their GUI entries. + +------------------------------------------------------------------------------ + 2.8.8 - 30/May/2010 +------------------------------------------------------------------------------ + + - Made balloon time adjustable via /set input_balloon_time (Nicoleau Fabien). + - Fixed a crash in the /SET command if a boolean value was loaded from config + file that isn't set to 0 or 1. + - Added -on and -off parameters to the /SET command. This can be used to set + bits, for example gui_tweaks. + - Made scrolling backwards for the search window act better (Richard Hitt). + - [2045483] Made ESC key close the search window (Richard Rowell). + - Improved the reconnect logic. If a network is already open but disconnected, + it'll now get re-used if you use the Network List and connect to that same + network. + - Improved scrollback reloading speed significantly (Soeren Sandmann Pedersen). + - [2957047] Handle CTCPs when IDmsg is used correctly (Lian Wan Situ). + - [2987626] Allow /GHOST's password arg to be optional (Ori Avtalion). + - Added networks: 7-indonesia, ChattingAway, GeekShed, TURLINet. + - When switching tabs, make the treeview only scroll if the selected item + isn't visible [treeview-less-jumping.diff] (Brian Evans). + - Selecting an item in the nickmenu will now copy it to clipboard (Alex + Kutepow). + - New icons for notification area (systray): file offer, message and highlight + (Brian Evans). + - Defined a comparison routine for contexts in Python (Brian Evans). + - For the auto-join command, added an 'x' filler for empty keys. This works + around a bug in ircd-seven. + - When a single channel MODE changes, xchat will no longer re-issue a MODE + request for the titlebar display, but figure the new modes intelligently + (Brian Evans). + - Various text event changes (Brian Evans): + 1. Added "Private Action", "Private Action to Dialog", "SSL Message". + 2. Added "Identified text" parameter all the 'action' events. + 3. Added a $3 parameter to "Server Text". + - Perl (Lian Wan Situ) + * Fixed a bug that resulted in timer hooks being leaked because + "return REMOVE" from a timer callback was not unhooking like it was + supposed to + * Reverted the unintentional change to how the server argument of print() + and command() is interepreted when it is undef + * Add hook_fd to the 'hooks' export tag + * Fixed a leak in XS_Xchat_get_list(Vincent Pit) + * Change Xchat::register so that scripts calling it without a name or + version will still show up in the plugins and scripts window. + * Added calls to PERL_SYS_INIT3 and PERL_SYS_TERM which are required on + some platforms + * Added some additional guards to prevents bits of scripts from spilling + into each other + * Added "modes", "win_ptr" and "xchatdirfs" to the list of keys that are + returned by context_info() + * Changed the information displayed in the "Plugins & Scripts" for scripts + that do not call register() to show up as "" for the name and description + and "unknown" for the version + * /reloadall will now reload scripts in the same order they were loaded + * Make xchat_send_modes available as Xchat::send_modes + * Add support for getting the network list using Xchat::get_list( "networks" ) + * Xchat::strip_code will now strip off ANSI escape codes as well + + +------------------------------------------------------------------------------ + 2.8.6 - 11/Jun/2008 +------------------------------------------------------------------------------ + + - Updated translations (de, fi, fr, hu, lt, nb, ru, th, zh_CN). + - Fixed creation of ~/.xchat2/scrollback/ paths (xc284-scrollbmkdir.diff). + - Fixed a leak of file descriptors related to the scrollback feature + (resource leak) (xc284-fix-scrollbfdleak.diff). + - Stopped scrollback files growing too large by fixing the file-shrink code. + - Put a "Display scrollback from previous session" into the Setup GUI + (logging section) so people can turn this off without typing commands. + - Made /away work even when the reason setting is empty. + - Using /part on a channel that contains a quotation mark now works [1800855]. + - Changed the default encoding to "IRC" (CP1252/Unicode Hybrid) for both Unix + and Windows. + - Fixed a possible Channel List crash if you searched many times while the + download was still going. + - Fixed alert balloons failing if the text contained "<" characters [1827629]. + - The Drag&Drop files to userlist feature has been enabled again. + - Removed the /set tab_icons setting and made it automatic (see FAQ for more + info about icons). + - Fixed a bug in creating files (save channel list, rawlog etc) that would set + the wrong permissions. + - Added command line argument --command=COMMAND which can be used in + conjuction with --existing (E.K.L.). This sends any xchat command to an + existing (running) client. + - A private SSL key/certificate can now be loaded from ~/.xchat2/client.pem. + - The Alerts settings now accept wildcards, instead of partitial string match + [1807563]. + - Changing away status during reconnect/disconnect will now remember it. + - You can now change your Away/Back status (all networks) in the tray menu. + - Favorite Channels / Auto-Join-List management: + * Network List window now has a "..." button to edit the auto-join-list in + a more friendly way. + * Channel(text area), Tree/Tab and Channel-List right-click menus now have a + "Add to Favorites" function. + * Previous limit of 300 bytes has been overcome. Now up to 2 KB worth of + channels/keys can be joined and it will be automatically split into + multiple lines, if necessary. + * Per-Channel settings now save to disk, including Logging and Scrollback + settings. + * /ChanOpt has been re-worked to be more like /Set. + - 'hostname:port' syntax is now accepted, if it's not an IPv6 address. + - The Userlist right-click menu now has icons and an option to add to friends + list. If you've edited this menu before you'll still get the old one. To get + the new one delete ~/.xchat2/popup.conf while XChat isn't running. + - ~/.xchat2/startup.txt is now loaded on launch (like /LOAD -e). Put any + commands you want executed at startup here. + - The lag-o-meter now has a full scale of 1.0 seconds. + - libnotify is now opened directly instead of using 'notify-send' to open + tray/balloon alerts. + - Added support for QuakeNet's /AUTH for nick password, when numeric 005 + NETWORK=QuakeNet is detected. + - You can now copy with IRC attributes and mIRC colors if CTRL key is down + when a selection is finished (on mouse release). This replaces the old + "Color paste" feature. + - Added a 'compact' flag to gui_tweaks. This'll make the userlist and tree + spacing smaller. E.g. type /set -or gui_tweaks 32 and restart to turn it on. + - The /CLEAR command takes a number as paramater (how many lines to clear). + - When there's missing information in the Userlist right-click menu, it'll + issue a silent /WHOIS and fill it in. This includes retrieving a person's + away-reason. + - Perl (Lian Wan Situ) + * /reloadall will now reload all the scripts that are currently load instead + of simply reruning the autoload routine + * gtk/glib/gdk errors and warnings have been redirected back to stderr so + they will no longer show up in the text box as a result of having the Perl + plugin loaded + * Check if the user has perl 5.6 instead of 5.8 and give an warning dialog + if they do (Peter Zelezny) + * Changed timer callbacks so that they are executed in the context that they + were created in + * Modified Xchat::print and Xchat::command to accept array references in + addition to strings for the channel and server parameters + - Plugin API: + * xchat_emit_print() will now trigger Sound, Blink, Icon etc type events, + depending on user's settings. + * Fixed a bug where not all 32 elements were available in word[]/word_eol[]. + + +------------------------------------------------------------------------------ + 2.8.4 - 01/Jul/2007 +------------------------------------------------------------------------------ + + - Updated translations (cs, de, ko, mk, sv, vi). + - System-Tray balloons now get the xchat icon instead of a generic one. + - Fixed the notify-send zombies (released as xc282-fixtrayzombies.diff). + - Fixed underscore ('_') in real names in the nick-name right-click menu being + drawn as a underline. + - ut2004:// URLs are now underlined too. + - /set gui_tray_flags 4 will now enable a "Minimize to tray" feature. Clicking + the window minimize button will minimize to tray instead of the task-bar. + - Fixed bug: [1680762] Notify fails if network name contains spaces. + - Extended tclConfig.sh search paths so it hopefully works on Ubuntu now. + - Added a feature that reloads conversations from last time you used XChat + (type /set text_replay 0 to disable it). + - Fixed /LASTLOG printing everything twice if you had Indented Nicks off. + - The CTRL-F keybinding (Find) is now disabled when using Emacs keys. + - Added /SET gui_tweaks. See http://forum.xchat.org/viewtopic.php?p=13766 + - Fixed opening URLs on KDE that didn't begin with http:// or other protocol. + - A better quit dialog which warns you if you're connected to IRC or have + active file transfers. + - Fixed: [1741525] Cycle selected channel (Luca Falavigna). + - Fixed: [1737249] Doesn't recognize nicks with halfop mode on hovering. + - The userlist and treeview can now be placed on the same side, with a resize + handle in between them. They can also be dragged and dropped into place. + - When you hide the userlist using the View menu, the resize handle now + disappears too. It also disappears when you have a server tab in focus. + - If you have a tree on one side and userlist on the other, they'll both now + have a resize handle, previously the tree's size was fixed. + - The userlist can be hidden and shown with CTRL+F7. + - [1735116] Channel List's minimum users spin-button can now be set downward + even on networks that sent a list of channels of only a larger size. In this + case the Download button will flash to indicate you need to download a new + list. + - Changing the channel switcher type (Tree or Tabs) is also possible in the + setup dialog. + - The Ban List window now lists exceptions too (mode +e). + - Script and Plugin related changes: + * /SETTEXT with no argument now clears the input box. + * Python: Added a xchat.strip method for stripping IRC attributes and mIRC + color codes. + * C-API and Perl: Returning 0 from a FD hook will now remove the hook and + free all associated memory. + * /MENU now supports a $CHAN root aswell (see plugin20.html). + * Fixed GDK warning when using /MENU to add a key binding to a popup menu. + + +------------------------------------------------------------------------------ + 2.8.2 - 01/Apr/2007 +------------------------------------------------------------------------------ + + - Updated translations (be, ca, cs, el, hu, sv, uk, zh_CN). + - Fixed the "Save As" function saving to the wrong folder in the URL Grabber. + - Fixed a bug in the "Copy Selected Link" URL right-click on non-ASCII chars. + - Fixed small bug: #100239 buffer overflow in setup dialog. + - Overhauled the Alerts section of the settings and added support for opening + system-tray balloons (libnotify required). + - Implemented /TRAY -b command on unix. + - Nick serv authentication is now sent without the ":" when using the + /NICKSERV or /NS method. #1655733. + - Added command line argument: + --minimize=level Begin minimized. Level 0=Normal 1=Iconified 2=Tray + - Plugin API: + * Added "modes" to xchat_get_info(). Returns the current channel modes, if + they are known. + * Fixed "event_event name" for xchat_get_info() to match the docs exactly, + but 2.8.0 (mis)behaviour works too. + - Perl (Lian Wan Situ) + * Execute the shutdown callback before removing the hooks so commands + created by the script can be used in the callback. + + +------------------------------------------------------------------------------ + 2.8.0 - 03/Jan/2007 +------------------------------------------------------------------------------ + + - Updated translations (cs, de, gl, hu). + - XChat now requires at least GTK+ 2.10. + - Added a system tray icon (aka Notification Area). This is probably the + biggest feature addition in this series. Also added a /TRAY command so + scripts can manipulate the icon. + - Added partial support for numeric 005 token ELIST (min users only). + - Brand new channel list window: GtkTreeView, nicer layout, less CPU power + when downloading very large list, uses less memory, supports regexp/ + patternmatch/substring search and supports downloading LIST with minusers to + save time (only on some networks that support ELIST). + - Overhauled URL opening on Unix, it now tries xdg-open first, then auto- + detects Gnome or KDE to run gnome-open or kfmclient. URLs with quotes + should also work now (changed to execv()). + - Settings: Warn the user when trying to put the tree on the top/bottom. + - Fixed DCC ack reading so it doesn't use MSG_PEEK. + - Channel modes are no longer shown in the titlebar if they contain a key. + - Added /GUI APPLY command, which does that same as pressing OK in the + settings window (e.g use it after /set). Mainly for scripters. + - Allow changing the logging folder if the log filename is set to a full path + in the settings window (starts with a '/'). + - Added 'Your Action' text event. + - Separated out /away and /back commands so it's obvious what they'll do. + - Changes to /MENU command (See plugin20.html for details): + * Now works for popup menus too. + * Allows creation of radio menu items. + * -p arg can now to be negative to give a position offset from right/bottom. + * -i arg to specify an icon file. + - Plugin API: + * Added event_text to xchat_get_info(). + - Perl (Lian Wan Situ) + * Fixed hook_command so that it won't override the help message for builtin + commands unless a help message was specified. + * Perl Win32: Warn the user about trying to load 64-bit ActivePerl. + + +------------------------------------------------------------------------------ + 2.6.8 - 16/Oct/2006 +------------------------------------------------------------------------------ + + - Updated translations (be, de, el, es, fi, hu, it, ja, lt, pt, ru, sv, vi). + - Removed "xchat-remote" and "dbus.so", it's now apart of the "xchat" binary. + There is now a new dbus interface, see src/common/dbus/README for details. + (Claessens Xavier). + - Python: Fixed "restricted mode" errors on win32 [1512076]. + - Special-cased BRASnet for nickserv. + - Fixed using the /MENU args -p and -e at the same time. + - Fixed /reconnect and auto-reconnect issue [1525383]. + - Plugin API: + * Added fields: lag, queue to the "channels" list. + * Added fields: sizehigh to the "dcc" list. + * Added fields: networks to the "notify" list. + * Handle gracefully plugins that try to execute commands with invalid UTF-8. + * Added /GETFILE command, to open a file dialog. + * Command hooks that start with a period ('.') will now be hidden from /HELP + and /HELP -l. + - Fixed: [1544960] quitting via tabs behaves bad on bncs. + - Fixed: [1551620] --version flag needs display. + - Fixed: [1539236] problem with the /url command (irc:// handling). + - Fixed: [1568931] treeview problem: closing tabs by holding shift and + clicking. + - "Clear" button in Ban List window now has a 'Are you sure?' dialog for + safety. + - The notify list can now contain entries specific to only one or more IRC + networks. + - Userlist popup menu and buttons: added %e for 'current network name'. + - Added option: 'Flash taskbar on any private messages'. + - Added a new encoding choice: "IRC (Latin-1/UTF-8 hybrid)". + How it works is described at: http://forum.xchat.org/viewtopic.php?t=3180 + - Added /LastLog -r . + - The DCC windows have been remodeled and are much nicer now. Ported to + GtkTreeView, the buttons are context sensitive, the window remembers its + size and uploads and downloads are combined in one window. + - Perl (Lian Wan Situ) + * Changed Xchat::print and Xchat::command to return false if they are called + with either no arguments or undef + * Changed Xchat::user_info so that it works even if the nick parameter + contains color codes + + +---------------------------------------------------------------------- + 2.6.6 - 18/Jul/2006 +---------------------------------------------------------------------- + + - Updated translations (es, fr, sr). + - Fixed connecting to a IRC server via proxy (bug in 2.6.4 only). + - Fixed the invisible cursor color when using GTKSpell and a black + input box (when "Use the text box font & colors" is ON). + - Allow loading a cert/privatekey file from ~/.xchat2/.pem + - Improved the fallback routine when you receive non-UTF8 messages. It + can now handle CP1252 from mIRC users and the ISO-8859-15 Euro symbol. + - Added CHANOPT command for setting channel specific options such as showing + of joins and part, beep on message and color paste (Lian Wan Situ). + - /CLEAR HISTORY will clear your command history. + - Fixed a crash if you left a Ban-List window open after closing the + associated channel and then clicking Refresh. + - Added an option of using 'Last-Spoke' nick completion order in Settings > + Input Box. + - The /QUERY command now has -nofocus arg, which scripts might find useful. + - You can now /set gui_url_mod 0, to allow left-clicking URLs (default is + 4, for CTRL). + - XChat will now respect gtk-button-images=0 set in ~/.gtkrc-2.0. + - Added a ./configure option to use your preferred spelling library: + --enable-spell=type. Where type can be: none static libsexy gtkspell. + Note that using gtkspell will force the inputbox to become a GtkTextView. + - Advanced users can /set tab_small 2, to get _extra_ small tabs. + - Added /SPLAY . + - Plugin API: + * The second args to xchat_list_int and xchat_list_str can now be NULL as + a shortcut to "channels" list for current context only. + * Added bits 6-8 to the field "flags" in the "channels" list. + * /GUI MSGBOX can now contain Pango markup. + * Added -m arg to /MENU. See plugin20.html for more. + - Perl (Lian Wan Situ) + * Fixed a bug with Xchat::print that prevents printing out a + single 0(Lian Wan Situ) + * Fixed a bug in Xchat::get_prefs that was clobbering the stack(Sergio Luis) + * Allow scripts that use a non-existent function for the shutdown callback + to be unloaded(Lian Wan Situ) + * Added check in set_context for undef + * Added the fields from get_list "channels" for the current context to the + result of context_info + + +---------------------------------------------------------------------- + 2.6.4 - 08/Jun/2006 +---------------------------------------------------------------------- + + - Updated translations (de, el, es, gl, hu, nl, sv, vi, zh_TW). + - Fixed opening a irc:// URL via "xchat -a --url=abc123" command while + "Skip serverlist on startup" is off. This fix is only relevant when + opening an initial instance of xchat (i.e not via dbus). + - Fixed the tree layout "flashing" (redrawing slowly) after you + switched to tabs and back to tree. + - Fixed plugin/script get_list("users") causing a critical GDK warning + when not executed from the front-most tab. + - Added spelling support in the input-box via GTKSpell. + - Improved the error reporting when connecting through a Socks proxy. + - DCC file transfers via http/socks45/wingate proxy is now supported + (Damjan Jovanovic & me). + - Fixed Socks 5 failing on 64-bit CPUs. + - Added support for connecting through a Microsoft ISA Proxy, requires + libntlm at build time (Pavel Fedin). + - You can now mark and copy timestamps if you hold down SHIFT. + - Timestamps are now preserved in the /lastlog command. Also fixed a + bug where the separator line disappeared during /lastlog. + - Added a Browse button to the DCC download folder setting. + - Made the setup window a little neater and Gnome-like. + - Improved the notify window a little and fixed a small memory leak. + - Fixed CTCPs being truncated in the RawLog window. + - Added an option to open a "Save As..." dialog when receiving a + DCC file offer. + - Fixed a crash if you try to remove a network from the list while + it's in a auto-reconnect delay [debian bug #364858]. + - Python: Fixed some memory usage bugs. + - Perl: Turned on utf8 flag for things that should have it on. + + +---------------------------------------------------------------------- + 2.6.2 - 27/Mar/2006 +---------------------------------------------------------------------- + + - Updated translations (de, fr, ja, sv). + - Made "/server freenode" send auto-join channels but not + "/server irc://freenode". + - Fixed building of xchat-text (although not recommended!). + - Fixed using Strip mIRC colors & Color nicks at the same time. + - Fixed a bug in timestamp drawing using non-fixed-width font [1404341]. + - Fixed display of realname in the nick-name right-click menu when it + contains a '<' or '&' character [1403069]. + - Added support for UniBG's nickserv (ongeboren). + - The move-to-complete-dir routine now treats encoding/UTF8 correctly. + - Show help when using wrong args for /DCC, instead of silence. + - Support receiving 2048 bytes per line from server and dcc-chat, so we + can support 512 UTF-8 characters that some servers now send. + - Added /gui detach and /gui attach commands for scripters. + - The server list window now remembers its size. + - TCL: Added 'selected' flag to users list. + - Perl: + * Fixed strip_code so that it no longer takes off extra commas (LifeIsPain) + * Fixed filename checks so that '/load "filenameWithoutSpaces.pl"' + will also work (Lian Wan Situ). + * Fixed hook_fd to work with sockets on Windows (Vince Pit). + + +---------------------------------------------------------------------- + 2.6.1 - 06/Jan/2006 +---------------------------------------------------------------------- + + - Updated translations (de, el, fi, fr, gl, hu, ko, nl, pa, sq, vi). + - Added support for log rotation based on time or date. + - Double-click in tree layout will now expand/collapse (Lian Wan Situ). + - Keys to move tabs around now work in Tree layout too (Lian Wan Situ/Me). + - Largely re-written "Search Text" function with much better + behaviour and match case on/off and search backwards options + (Richard Hitt and Me). + - The parent row in the tree layout now changes color if you have + that group collapsed (Lian Wan Situ). + - Fixed crash when trying to Detach or Close a utility tab via + right-click, when it's not the currently focused tab. + - Made DCC resume handle case-insensitive file systems properly. + - Fixed the flashing when you click on a colored treeview row. + - Fixed auto-completion during /exec -o [1375530]. + - Added "Join Channel" menu item to the Server menu. + - Unshade the Disconnect menu item when a connection is in progress. + - Fixed a possible crash in changing color settings before changing + to/from the tree layout (SF bug #1349088). + - Added "Auto accept file offers" to the File Transfer settings. + - Added support for brackets "<>" around nicknames in cut and paste, + without displaying them (hidden text) (Camillo Lugaresi). + - Fixed opening URL irc://NetWork/#channel not joining the channel + [1362155]. + - Fixed the nickname label becoming small when you're marked Back + if you have "Small tabs" turned on. + - The textevents GUI has been re-written to use GtkTreeView. + - Randomized DNS lookups on Mac OS X on hostnames that return + multiple IP numbers (SG / CL). + - Added a dialog window to help newbies join a channel. + - Opening irc:// URLs will now JOIN only if you are already connected + to the network. + - Plugin API (Lian Wan Situ): + * Added selected flag to "users" list. + * Added "id" to xchat_get_prefs. + * Changed xchat_find_context (ph, channel, NULL) to return results + from the same server group as the current context when possible. + - Perl (Lian Wan Situ): + * using emit_print/command/recv will no longer trigger their own + callbacks. + * Fix compiling issues with versions older than 5.8.2. + * Make all scripts appear in the "Plugins and Scripts" window, even + those that do not call register(). + + +---------------------------------------------------------------------- + 2.6.0 - 03/Nov/2005 +---------------------------------------------------------------------- + + - Updated translations (nl, zh_TW). + - Message boxes are now warning, error or info with appropriate icon. + - Red marker line feature enabled by default. + - Added /SEND [file] which will automatically switch to PSEND + when detecting a private net address. + - Simplified default nick-right-click menu. + - Show "Last Talk" in nick-right-click menu as "minutes ago". + - Strip mIRC colour from away message in right-click menu. + - Warn when opening banlist in non-channel. + - Reorganised and simplified IRC/Server menus and new View menu. + - The editable Server menu is no more, if you want it type + /set gui_usermenu 1 and restart. + - Option to view channels in tabs or tree structure. + - Shorter titlebar text for better viewing in taskbar. + - Disabled key-search in server list, as GTK's auto-find does this + better. + - Removed "Connect in new tab" button in server list, it now does it + intelligently. Use stock Connect icon. + - Removed "Tint (shade) transparency" item from settings and figure + it out based on tint values. + - When closing a tab, re-focus the one near by, instead of always the + last. + - Firefox style close button. + - The lag and throttle metres now have tooltips that give you real + information (hover the pointer over them). + - Added workaround to show on-join ChanServ notices in the right tab. + - Tab scroll buttons are now side-by-side when in vertical mode. + - Automatically change key shortcut of "Marked Away" if the + translation already uses ALT-A for the Help menu (e.g _Aide in + French). + - Your nickname in the bottom-left corner now turns gray when you are + marked away, just like the userlist. + - Introduced a delay before joining channels, to allow for FreeNode's + short comings. If a umode +e is received it'll send auto-join + channels immediately. + - Plugin API: Added win_ptr to xchat_get_info. + - Non-irc (utility) tabs can now be detached aswell. + - Fixed behaviour problems of the userlist pane, which might be set + incorrectly if the window was resized while a server-tab is focued. + - Added a confirm-dialog when trying to close a server-tab with + children. + - Server list's edit window now gives you an option of a network + specific "Second choice" nickname. + - Auto detect RusNet and use /NICKSERV to identify instead of /MSG. + - Added /Ghost command. + - Fixed: The WHOIS away-line ignored irc_whois_front setting. + - Scroll-wheel now works while hovering over a tab (Lian Wan Situ). + - The input box right-click menu now has bold, underline and italic. + - Added xchat-remote for launching irc:// URLs in existing xchat + and other functions (Claessens Xavier). + - WIN32: Auto-loading perl scripts now also works from: + C:\Program Files\XChat\Plugins\ + - Better command-line parameter parsing via GOption. + - Tab completion order can now be in "last talk" order if you + /set completion_sort 1. + - "Channel Action" and "Channel Action Hilight" now have a 3rd + argument of "Mode char", just like normal message events. The last + talk time is also now updated on actions. + - Reworked the Character Chart window so you can find your char. + - Perl: + - fixed so that printf and commandf are exported + - print and printf can also be called as prnt and prntf, this is to + avoid clashing with the builtins. + - Deprioritized MODE/WHO to reduce join lag. + - WIN32: Mask out more invalid filename characters when writing to + log files. + + +---------------------------------------------------------------------- + 2.4.5 - 10/Sep/2005 +---------------------------------------------------------------------- + + - Updated translations (cs, el, fr, gl, it, nl, sl, sr, vi, zh_TW). + - Fixed incorrect information displayed in Plugins & scripts window + under unix (xc244-fixpluginns.diff). + - Added "/set irc_whois_front 1" option to show WHOIS in front tab. + - Lots of speed ups under the hood, mainly in handling of URL + highlighting during mouse motion. Also now allows underlining + .name and .info domains [1230265]. + - Moved the "Insert color code" menu into the input box's right- + click menu. + - Fixed "Your Message" messing up when starting with a comma + [1230269]. + - Added /id command to identify yourself to nickserv. + - Added /gui MSGBOX for scripters. + - Added /menu command which lets plugins/scripts add their own + menu items. + - Added support for passive DCC chat via /DCC PCHAT . + - Added support for DCC sending and receiving very large files + (above 4 GB). + - Improved layout of "Info" button in the DCC windows. + - Improved layout of the nick-name right-click menu. + - Improved /help command's display of plugins/script commands. + - Fixed two bugs in detaching tabs (or CTRL-I) [1228926]. + - Added /uselect command for scripters to select nick names in the + channel userlist (Daniel P. Stasinski). + - Fixed possible crashes while using the SJIS (Japanese) charset. + - Fixed various memory leaks in right-click menus. + + +---------------------------------------------------------------------- + 2.4.4 - 20/Jun/2005 +---------------------------------------------------------------------- + + - Updated translations (hi, ko, lt, pa, ru, vi, zh_TW). + - People's away message is now shown in the right-click menu, if + known (Christopher Aillon). + - The "Bind to:" setting can now be set to 0.0.0.0 [1176256]. + - Plugin API: Don't crash if a print-event closes the current context + and doesn't eat the event [1175674]. + - Disabled parsing of quotation marks for /JOIN, so you can join + channels with a quote in them (Dan Fruehauf). + - Fixed truncation of the URL in the right-click menu. Now handles + UTF-8 properly [1188229]. + - Fixed use of CP1255 charset, which would chop the last char when + receiving messages [1122089]. + - The DCC windows now allow multiple selection and the columns auto + resize (Dan Fruehauf). + - Added "CTCP Sound to Channel" event [1159445]. + - You can now drag and drop files into dialog windows to start file + transfers. + - Perl: + - Fix to allow fully qualified variable names to work as well. + - Enabled individual script unloading. + - Enabled reloading scripts using XS modules. + - Fixed handling of filenames with spaces in them. + - Added /reload which works like /load but it will do an unload first + it is not necessary to use the full path with this command, just + the file name is enough. + - Fix print callbacks for cases where there are NULL elements between + non-NULL elements. + - Fixed: "XChat can't ban users with long idents" (Dan Fruehauf) + [1159447]. + - Implemented taskbar flashing on unix. Requires a window manager + or taskbar that supports XUrgency flag (Adil). + + +---------------------------------------------------------------------- + 2.4.3 - 31/Mar/2005 +---------------------------------------------------------------------- + + - Updated translations (de, sq, zh_CN). + - Fixed crash of server list connect button when no network is + selected while using GTK's auto-find feature [1166669]. + - Fixed handling of WhoIs Special event on some networks where it + could chop off the first character [1164315]. + - Plugin API changes: Added "nickserv" field to xchat_get_info. + - Python: Fixed get_list() incorrectly failing when the list + contained a time field [1171525]. + - Perl: Make scripts using calls with fully qualified subs work again + [1170139] (Lian Wan Situ). + - Fixed input-box input-method (GTK I.M.) problem [1168239]. + - Fixed: Ignore and Notify windows incorrectly used the stock CLOSE + button instead of DELETE [1170655]. + - Placed Close/Connect buttons in correct position in server list + [1165474]. + + +---------------------------------------------------------------------- + 2.4.2 +---------------------------------------------------------------------- + + - Updated translations (ca, de, lt, nl, ru, sk, sr, vi). + - Added command line args -u and -p. + - Fixed handling of "MODE -o+o nick nick" (#1094026). + - Plugin API changes: + * Added "Key Press" print event. + * Added "state_cursor" for xchat_get_prefs. + * Added xchat_strip and xchat_free functions. + * Added "lasttalk" field to "users" list. + * Added "charset" field to xchat_get_info. + - Perl plugin changes (Lian Wan Situ): + * Move each script into their own unique package/namespace. Scripts + containing multiple packages will not be loaded. + * When warning messages are emitted you will now be told which + script it came from. + * Xchat::set_context will now accept Xchat::set_context( $channel ) + and Xchat::set_context( $channel, $server ) in addition to + Xchat::set_context( $context ). + * Fix display of loaded scripts in the Plugins and Scripts window. + - TCL: Fixed crash with invalidated TCL timer (#1110306) (Daniel P. + Stasinski). + - /TIMER now supports timeouts to one decimal place. + - Fixed possible crash of open-file dialog on 64-bit machines. + - Pressing CTRL-O in the DCC Receive window will now open your + downloads folder. + - Win32: Default download folder changed to "My Documents\Downloads". + - Added -quiet arg to the /charset command. + - The /country command now supports a wildcard search. + - The user is now warned when real/user name is left blank in the + server list window. + - Added the /URL command. + - Added a text event for all unknown WHOIS reply lines. + - Added /ALLCHANL which sends to the current server only. + - Actions (/ME) are now treated like PRIV/CHAN for purposes of the + ignore list. + + +---------------------------------------------------------------------- + 2.4.1 +---------------------------------------------------------------------- + + - Updated translations (ca, de, eu, it, ko, mk, nb, nl, pt, ru, sl, + sq, uk, zh_TW). + - Fixed custom marker-line color not reloading. + - Brought back the "Connect to selected server only" option in the + Serverlist edit window (it's like the reverse of "Cycle until + connected" in 2.0.x). + - You can now move networks and servers via Shift+Up/Down (in the + ServerList window). + - Small efficiency improvements in receiving dcc. It will now not + send ACKs while the input buffer is non-empty. + - Python: Fixed crash when a timer callback routine executes + xchat.unhook() and returns false. + - Fixed playing sound files with spaces in them. + - Added support for NickServ on DalNet and FreeNode. + - Plugin API: Added xchat_get_info(ph,"inputbox");. + - Added /settext and /setcursor commands for scripters. + - You can now scroll tabs with the mouse-wheel while hovering over + the arrow buttons. + - Fixed connecting to a SSL server via http proxy (#1054152). + - Fixed: Opened server tab doesn't count as "requested" (#1044227). + + +---------------------------------------------------------------------- + 2.4.0 +---------------------------------------------------------------------- + + - Updated translations (ca, de, eu, it, ko, lt, nl, sk, sr, zh_CN). + - Fixed a possible crash in loading pevents.conf. + - Made default URL handlers work with Firefox 0.9.x by adding the + "-a firefox" argument. + - Plugin API: Added xchat_get_info field "libdirfs". + - Fixed crash when trying to dcc send a filename which has encoding + that doesn't match G_FILENAME_ENCODING. + + +---------------------------------------------------------------------- + 2.1.1 +---------------------------------------------------------------------- + + - Updated translations (de, kr, lt, sk, sr, zh_CN). + - Added some rudimentary support for the IDENTIFY-MSG feature. + - Perl: Added Xchat::context_info (Lian Situ). + - TCL: Added support for time fields in getlist (Daniel P.Stasinski). + - Added "Open Dialog" event, so you can add a sound-file to it. + - The standard beep can now be overridden with a sound-file. + - Fixed tab-nick-completion's cycling behaviour. + - New keyboard shortcut for line up and down (shift-arrow up/down). + - Fixed: [986958] tab completion with GTK Input-Methods. + + +---------------------------------------------------------------------- + 2.1.0 +---------------------------------------------------------------------- + + - Updated translations (eu). + - Tab nick completion fixes: Crash with space-tab and glib critical + warning (Ian Kumlien). + - Heavily reworked the Preferences window. It should be alot clearer + now, and more gnome-like. + - 'Pop new tabs to front' setting now has three options (Kyoshiro). + - New colors and text-events, using a white background. + - Config files are not saved to disk unless you edit the defaults. + This makes it easier to change language (for print events, popup + menu etc). + - Brand new Server List window. Now much simpler and intuitive. Also + includes an entry box for NickServ password. + - The vertical separator line now has its own pointer when you hover + over it (Richard Gobeille). + - Alphabetical tab sorting now works and is enabled by default. + - Added "Small Tabs" option (reduces the font size). + - Brand new Sound-Events editor in the Preferences window. + - Added socks5 authentication support (Benjamin Foster). + - Win32: fixed auto-loading of TCL scripts. + + +---------------------------------------------------------------------- + 2.0.10 +---------------------------------------------------------------------- + + - Updated translations (ru, sr). + - Fixed compiling on systems other than linux/freebsd [969643]. + (Samuel Mimram). + - Fixed compiling with an old version of GTK (2.0.x). + - Further BiDi fixes in xtext (Ilya Konstantinov). + - Brand-new tab completion code (Ian Kumlien). This also fixes: + Tab expansion not working behind umlauts [956127]. + Plugin commands can now be tab-completed too (Frank Thieme). + - Fixed parsing URIs on userlist drag-n-drop (Jonas Heylen). + - Added Sort button to the server list window (David Oftedal and + Tim-Philipp Mueller). + - Tab button selection fix (Guillaume Knispel). + - Added marker-line feature. Shows a red-line to indicate the place + where you last read up to (Thomas Kockerbauer). + - The "Get my IP from Server" feature now works on networks that + hide your hostname too (by using the USERHOST command). + - Win32: Fixed CPS calculation for file transfers [824934]. + - Fixed: Ping timeout when the system clock changes [789140]. + - Fixed: Private messages delivered to status window when nickname + is the same as the network [977550]. + - Maximised window-state is now saved. + - Double middle-clicking a nickname in the text area will now select + it in the userlist. + - Included a work-around to stop X-Sys plugin crashing with GTK 2.4. + - Fixed: /list output going to the current tab [970746]. + - Fixed: Serverlist crash while editing a port-number, and switching + to another network before pressing enter [968652]. + - Made it possible to execute multiple "Connect Command:"s in the + ServerList window, when they're separated by ctrl-shift-a. + + +---------------------------------------------------------------------- + 2.0.9 +---------------------------------------------------------------------- + + - Updated translations (bg, cs, de, en_GB, eu, fi, lt, nl, ru, sk, + uk, wa). + - Fixed the Socks5 overflow security bug. + - DCC IP address setting can now be a hostname too (Flavio + Chierichetti) [773229]. + - Don't try random DCC ports when a range is set (mib) [889987]. + - Fix: Spurious nick completion (mib) [916944]. + - Serverlist passwd box is now masked (Cristian Peraferrer) [920113]. + - Fix: Sometimes messes up the tab order on reconnect (Gabor Szeder) + [941773]. + - Fix: Crashes when setting $CHARSET to nonexistant charset [945855]. + - Plugin API: Added some fields to the "channels" list. + - Plugin API: Added "win_status" and "xchatdirfs" fields to + xchat_get_info. + - Plugin API: Added xchat_send_modes() function. + - Fix: Unload, then reload a plugin on FreeBSD fails (Kevin Leung). + - Plugins should now work on HPUX too. + - Perl-plugin: Fixes for 3 arg version of emit_print, unhooking the + same hook multiple times and get_list returning correct values for + address32 field and some memory leaks (Lian Situ). + - Made menu keybindings work when the menubar is hidden on GTK 2.4. + - Added support for the new GTK 2.4 file chooser dialog. + - Fix for BiDi in xtext (Ilya Konstantinov). + - Smaller bug fixes [962211] [958599] [950353] and + [945617] (Frederic Krueger). + + +---------------------------------------------------------------------- + 2.0.8 +---------------------------------------------------------------------- + + - Updated translations (az, es, fi, lt, mk, nl, ru, sk, sl, sr, sv, + zh_CN). + - Added color, flash and iconify args to /GUI command (this is for + use in scripts and plugins only). + - Plugin API: Added "notify" list. + - Plugin API: Added id, users, flags fields for "channels" list. + - Win32: Better error messages for file i/o and winsock errors. + - New Perl interface (with backward compatibility)! (Lian Situ). + - Fixed command-character buglet [873541]. + - Win32: Improved incorrect CPS display for file transfers. + - Added "Copy Selected URL" option to URL popupmenu (Mike Battersby). + - Added work-around for "Get my IP from server" not working on PTNet + (Mario Freitas). + - Fixed: Alt+numbers do not work with X Input Method [896968] (Marius + Gedminas). + - Added support for "+port" to indicate SSL connections. + - Fixed non-ASCII chars in time-stamp bug [918445]. + - Smaller bug fixes: [870073] [890891]. + + +---------------------------------------------------------------------- + 2.0.7 +---------------------------------------------------------------------- + + - Updated translations (fi, nl). + - Fixed dcc psend crash [858539]. + - Fixed bug where an error message was erroneously displayed while + transfering files with fast-send turned off. Also, allow fastsend + to be used with psend (Daniel Dubois). + - Print more informative messages when Perl scripts fail to load + (Andy). + - Win32: Added native sound playing support. + - Win32: Fixed possible crash upon exit while still connected. + - Fixed notify's Lastseen column for offline users [864185]. + - Report more informative error when DCC write to disk fails. + - Fixed crash when xchat.conf contains oversized strings [750403]. + + +---------------------------------------------------------------------- + 2.0.6 +---------------------------------------------------------------------- + + - Updated translations (de, lt, sl, sr). + - Fixed detection of Python on amd64 (Mads Martin Joergensen). + - Don't loose editbox contents when pressing up, then down arrow + (Ricky Clarkson). + - Fixed missing dcc flag on new ignores via gui. + - Fixed missing separator bar on PseudoColor displays. + - Fixed some 64-bit issues (xc205-fix64bit.diff). + - Apply tint changes instantly. + - Fixed DCC resume with mirc >= 6.1. + - Python plugin changes: + * Fixed the reentrancy problem which made xchat freeze when some + python code made xchat trigger a python callback somewhere. + * Implemented xchat_emit_print() and xchat_get_prefs() support. + * Fixed softspace support for python 2.3. This problem was making + print statements yield an extra space at the next line start. + * Other minor changes. + (Gustavo Niemeyer, Gustavo J. A. M. Carneiro, Marko Kreen). + - Fixed request of a MODE on a channel you're not in changing the + current titlebar [820998]. + - Restored compatibility with older Perl that lacks call_pv(). + - Use sigaction inplace of signal() for better compatibility. + - Win32: Don't try to open logfiles with a "\" in them, windows wont + allow it. Instead, the "\" is replaced by a "_". + - Backported HTTP authentication code from 1.8.11 (you can now + specify a username and password for HTTP proxies). + - When beep on highlight is on, beep on channel actions too + (Christopher A. Aillon) + - Added active dcc send feature (/dcc PSEND). More info here: + http://mail.nl.linux.org/xchat-discuss/2003-10/msg00124.html + (Daniel Dubois and Emmanuel Jeandel). + - URL Handlers menu now removes programs that arn't in PATH. + - Added "away" users field for plugin API. + - Smaller bug fixes: 822199, 786267, 783172, 811971, 756048, 844919. + + +---------------------------------------------------------------------- + 2.0.5 +---------------------------------------------------------------------- + + - Updated translations (ca, fi, lt, nl, sk, sv, zh_CN). + - Fixed detection of Python 2.3 in configure script (anonymous). + - DCC Send file-selection dialog now supports multi-select. + - Reset away status after auto-reconnect from a ping timeout. + - Perl: Fixed IRC::user_info always matching the first entry. + - More C89 fixes for non-gcc compilers (Albert Chin). [781809]. + - xtext: now double buffered and flicker free. Also some efficiency + tweaks for exposure events and multi-wrapped lines. + - Removed buggy numeric 338 support [783945]. + - Nick completion in dialogs and channel completion (Jay Cornwall). + - Print informative error messages when dcc resume isn't possible. + - Fixed performance of dcc recv, send and chat windows. + - Fixed tab-arrow buttons show/hide (Lloyd Williams) [783681]. + - Fixed lastlog bugs [791220]. + - win32: Faster tinting, and uses MMX when in 16 or 32bit color. + - Execute /sigusr2 on receiving SIGUSR2 signal (Michael Guidero). + - /IGNORE command and window now have an extra "DCC" category. + - Alert user when logfiles fail to open (Jay Cornwall). + - Fixed missing underlining of IP numbers (2.0.4 only). + - Allow accepting DCC sends from ports below 1024. + - Connect to URL given on commandline even if 'No Serverlist on + Startup' is off [804648]. + - Fixed problem in allocating colors while in 8bit PseudoColor. + - xtext: tinting now shades towards your background color, making it + usable with white backgrounds. Tints can also use XShm for extra + speed with --enable-shm at ./configure time (experimental). + - Perl: IRC::add_print_handler callbacks now get parameters in + $_[1...x], with $_[0] left for compatibility (Lian wan Situ). + - Perl: added command_with_channel command (Alexander Werth) + [801711]. + - Smaller bug fixes: [798655]. + + +---------------------------------------------------------------------- + 2.0.4 +---------------------------------------------------------------------- + + - Updated translations (lt, sv, zh_CN). + - Fixed crash on tinted transparency (xc203-fixtint.diff). + - Fixed incorrect dcc cps calculation (xc203-fix-cps.diff). + - Allow fullpath and relative filenames for Text Events sound files + (Anthony Dragunov). + - Added /GUI command (mainly for use by scripts). + - Solaris build fixes for ipv6. + - Added -n, --no-plugins command-line arg. + - Added a feature to change the color of away users. + - Moved default dcc and sound dirs inside ~/.xchat2/ (SilvereX). + - Fixed bug [753742] When server tab and query had the same name, + private messages could go to the wrong tab. + - Support others users too, when expanding ~ in filenames (Neox). + [767514]. + - Underline "ipnumber:port" style urls too (Alex & dobler). + - Added support for ircu numerics 330 and 338 (phaseburn). + - C89 fixes, should now compile with HP UX and Sun C Compilers + (Albert Chin). [777106]. + - Smaller bug fixes: [773245] [779166]. + - Close tabs on shift-leftclick (Jay Cornwall). + + +---------------------------------------------------------------------- + 2.0.3 +---------------------------------------------------------------------- + + - Updated translations (ca, fr, ja, sv). + - Fixed URL grabber not filling up (xc202-fixurlg.diff). + - Fixed crash when holding down Ctrl-I (xc202-fixdetach.diff). + - Use Shift-Ctrl-W for Close only when Emacs key theme is enabled. + - Fixed corrupt left margin with indent-nicks off and timestamp on. + - Remove invalid chars from inbound text when conversion fails. Fall + back to ISO-8859-1 when using UTF-8 only (Ilya Konstantinov). + - Fixed perl IRC::get_info(3) crash when not connected [732496]. + - Fixed crash on long output lines for /exec -o [731187]. + - Made "Move completed files to:" and "Save nickname in filenames" + work at the same time (Matthew Gabeler-Lee). + - xtext: fix redraw when new additions not on current page. + - win32: Added /set identd 0 switch to turn off built-in identd. + - Added 6-8 for perl's IRC::get_info to retreive network, host and + topic (Ryan). + - Iterate in alpha order instead of op-alpha for nickcompletion + (Gauss_Z88). + - Fixed ChannelList crash on invalid regex match string. + - Added hide join/parts setting to gui (Jason Wies). + - Added Delete All button to ignore window (Mohammed Sameer). + - Don't allow adding empty names to notify list [741589]. + - Made message fragmentation code utf8 friendly so it always splits + on a multibyte char boundary [748653]. + - Support 2 to 4 GB files in DCC (contrary to 1.9.4 changelog, it + didn't work until now). + - Python: Fixed crash when returning 0 from a timer (Steve Green). + - Multihead fixes for popup menus. + - Added support for numeric 307 and 320 "is an identified user". + - Allow setting a blank topic via the GUI [720407]. + + +---------------------------------------------------------------------- + 2.0.2 +---------------------------------------------------------------------- + + - Updated translations (lt, ms, nl, pt, sv, zh_CN). + - Fixed a few minor mem leaks in the server and user list. + - Changes to: UrlGrabber, Notify, Plugins, Ignore and Banlist GUIs. + Changed GtkCList to GtkTreeview, and general enhancement to these + guis (Vincent Ho). + - win32: made it possible to compile with ipv6. + - Added /MOP. + - Fixed pageup/pagedown wrong window bug [710784]. + - Fixed no timestamps in top-level windows bug [710787]. + - Fixed first word being skipped in perl add_command_handler("", cb); + [711802]. + - Fixed WHOIS away line appearing in different tab [695932]. + - win32: fixed transparency [699425]. + - win32: fixed ssl "Error 2" connection bug. + - Made all toplevel dialog windows transients of the main window. + - Show filesize/pos in DCC window as KB and MB (Aaron Chernosky). + - Added /set tab_dnd 0/1 option. + - Fixed userlist insertion/deletion GUI performance problem [704233]. + - Each toplevel window now has a "role". + - Smaller bugs fixed: [698449] [718851]. + - TCL plugin fixes for context lookups (Daniel P. Stasinski). + - Changed Close Tab keybinding to Shift-Ctrl-W to avoid conflict with + emacs editing. + - Used a new algorithm for Userlist and UrlGrabber. This one does + insertion, lookup and deletion in O(log n). + + +---------------------------------------------------------------------- + 2.0.1 +---------------------------------------------------------------------- + + - Updated translations (am, ca, lt). + - Save serverlist before connecting (Joe Drew). + - OpenBSD compile fixes. + - (Encoding) Fallback outgoing text to "?" for unconvertable chars. + [674798]. + - Hide tab scrolling buttons when they're not needed. + - Fixed --disable-xlib compiles. + - Fixed use of %h in dialog-tab buttons [688937]. + - Fixed printing/logging timestamps that contain invalid utf8 + [688548]. + - Added "Resizable userlist" option (default ON). + - Strip colors on topic change. + - Fixed (snotice) and (notice) tabs being swapped [687437]. + - Made more strings translatable. + - Allow loading empty text events [691191]. + - Fixed xtext race condition [678874]. + - Added ability to show/hide the channel-mode buttons (default OFF). + - Use the network name in server-tab rather than full hostname. + - Added keybindings for moving tab-families, default is ctrl-shift + PageUp and PageDown (Vincent Ho). + - Added 'Beep on highlighted messages' option (Jirka Kosina). + - Use DND to detach tabs. + - Interpret %C, %B etc in quit reasons. + - Added more items to the right-click tab menu. + - Some misc UI cleanups. + + +---------------------------------------------------------------------- + 2.0.0 +---------------------------------------------------------------------- + + - Updated translations (de, es, lt, nl, sk, sl). + - Fixed half cut off dates in notify window. + - Fixed tabs loosing red/blue color when being renamed. + - Fixed initial query tabs not being truncated. + - Make tabs red on channel actions too. + - Configure script python detection fixes (Johan Dahlin). + - Added /charset command. + - Don't auto remove stalled DCCs unless dcc_remove setting is on. + - Avoid recursive UserCommand buffer overflow. + - Added xchat_emit_print() to plugin interface. + - Left and Right positioned tabs are possible again (Lloyd Williams). + - Added /timer -repeat and -quiet args. + - Possible tcl plugin crash fixes (Daniel P. Stasinski). + - Group multiple op/voice in one print event. + - Fixed plugin loading on solaris. + - Python fixes (Gustavo Niemeyer): + * Fixed bug which made Python plugins crash randomly. + * Introduced a new xchat.hook_unload() function, as requested by + many people. This will call a given callback at module unload + time. + * Now /py load will succeed if filename is the name of a + file inside "xchatdir" (~/.xchat2). + * Fixed some leakings. + + +---------------------------------------------------------------------- + 2.0.0pre1 +---------------------------------------------------------------------- + + - Updated translations (sv, es, am, el, lv, no). + - Fixed possible blank userlist after another tab was detached. + - Changed default keybinding for next/prev-tab to ctrl-pageup/down, + as per standard. + - Added IPAddress field to "DCC SEND Offer" text event. + - Fixed perl IRC::print_with_channel 1.8.x incompatibility. + - xtext: Fixed bugs in new scrolling code. + - Use filesystem encoding for log filenames. + - Focus the inputbox when left-clicking in xtext. + - Focus the inputbox when typing while the userlist is in focus. + - Fixed bug where text typed could be sent to the wrong window after + a detach. + - New default icon again, this one scales better (Dagmar d'Surreal). + - Send /LIST args on galaxynet. + - Added settings to change inputbox and userlist styles to the same + as the main text area. + - Don't allow the Perl plugin to be loaded twice (Ian Kumlien). + - Fixed servlist crash on 'use global' off and empty nick field. + - Added missing address field to Perl's IRC::dcc_list. + - Added irc_conf_mode setting (via /set only). + - Save xchat.conf safely (Michael Witrant). + - Added support for numeric 005 token NAMESX. + - Added TCL Plugin (Daniel P. Stasinski). + - Added 'Add' button to serverlist, due to popular demand. + - Update intl/ to 0.11.4. + - Win32 fixes/makefile for python plugin (James Potts). + - Win32: fixed clipboard bugs and dcc receive. + - Plugin iface: Added dcc-list fields "address32" and "port". + - Try to use pkg-config to find openssl. + - Report errno/strerror on dcc failures. + - Python print buffering fixes (Gustavo Niemeyer). + - Treat NOTICE +#channel correctly. + - Check for common unix paths and don't treat them as commands. + + +---------------------------------------------------------------------- + 1.9.8 +---------------------------------------------------------------------- + + - Added Amharic translation (Daniel Yacob). + - Updated Spanish translation (Pablo del Campo). + - Updated Lithuanian translation (Rimas Kudelis). + - Updated Latvian translation (Artis Trops). + - Fixed serverlist entry box text corruption (xc197-fixservlist.diff) + - Fixed the non-mmx tinted-tranparency code crashing. + - Fixed interpretation of mIRC color 99 [653094]. + - Use Pango renderer by default, for better i18n. + - Scroll 1/10 of a page with the mouse wheel (Soeren Sandmann). + - Reimplemented -a, --no-auto argument. + - Fixed a bug in entering text with GTK2 IMs [653751]. + - Final fix for filenames' encoding in DCC. + - New unicode character chart window. + - xtext: properly recalculate text widths after a font change. + - Fixed perl IRC::dcc_list 1.8.x incompatibility (Charles Lopes). + - xtext: Implemented scrolling instead of full redraws when not using + a background image or transparency. This improves scrolling on + machines that draw AA text very slowly. + - Reimplemented 'Move front tab left/right' keybinding. + - Provide default usermenu and buttons for translation. + - New default icon (Dagmar d'Surreal). + - Report the average KBs when a transfer is finished. + - Attempt to create dcc-download dir when changed in the setup gui. + - Apply character set conversions to DCC Chat aswell (Steve Green). + - xtext: Fixed hilight-text in scrollback after new addition bug. + - Channellist gui cleanup. + - Renamed a few defines in xchat-plugin.h to avoid namespace + pollution. + - Fixed loading background image crash (from 1.9.7). + - Fixed broken drawing of mIRC color 0. + + +---------------------------------------------------------------------- + 1.9.7 +---------------------------------------------------------------------- + + - Updated Swedish translation (Christian Rose). + - Updated Spanish translation (Pablo del Campo). + - Updated Dutch translation (Bart Coppens). + - Added /GETSTR and /GETINT. + - Misc. serverlist bug fixes (Shaun Guth). + - Plugin changes/fixes: + * Added xchat_get_info("network"). + * Added new function: xchat_hook_fd(). + * Fixed "DCC Chat Text" event (Daniel P. Stasinski). + * Added "Open Context" print event. + * Fixed implementation of EAT_ return codes. + * Keep the leading ":" in server events passed to plugins. + * Added hack to make plugins possible on win32. + * Fixed /unload crash. + - Fixed changing tabs via keyboard. + - Added a few keyboard accelerators to the menubar. + - Fixed close-tab-0 crash. + - Fixed userlist popup menu disappearing on button-release. + - Fixed color paste. + - Added a character set selector to the serverlist. + - Send DCC filenames in system encoding (gets converted if a charset + is chosen in the serverlist). + - Fixed possible Search Text crash. + - Removed --enable-japanese-conv configure option (isn't this + superseded by the new charset selector?). + - Use --enable-openssl by default. + - Fixed your nick not changing in dialog windows. + - xtext: deal better with invalid utf8. + - Made it possible to do /server . + - win32: backported tint/transparency code from 1.8.10. + + +---------------------------------------------------------------------- + 1.9.6 +---------------------------------------------------------------------- + + - Updated Spanish translation (Pablo del Campo). + - Added Estonian translation (Ilmar Kerm). + - Made switching to dialog tabs faster: + * Draw xtext only once when switching to a dialog tab. + * Do not recalculate the tinted-transparency. + - Fixed another text-off-the-bottom bug. + - Fixed background color other than black not working. + - Fixed dialog windows not being logged (Joanne Hunter). + - Fixed topic entry box going blank bug. + - Added Insert-color-code and encoding submenu in the bottom-right + button. + - Apply more settings without needing a restart: + * Background image. + * Time stamp text on/off. + * Palette changes. + - Implemented %n for log-filename-mask. + - Reconfigured the menubar a bit. + - Validate inbound utf8 text to avoid reading beyond buffer and + fall back to iso-8859-1. + - win32 compile fixes. + - Don't convert commas to %2c in urls. + - Auto open dialog when dcc chat offer connects (Steve Green). + - Make setting "Open Utilities in: Windows" work. + - Added a way to reorder networks in the serverlist window (still + want to add DND later). + + +---------------------------------------------------------------------- + 1.9.5 +---------------------------------------------------------------------- + + - Fixed the PL_perl_destruct_level crash (Bernard Blackham). + - Fixed the perl readdir crash. + - Added tab scrolling buttons (Lloyd Williams). + - Added DCC throttle and better CPS calculation (Richard Fuchs). + - Added three configurable tab-highlight colors (Nehal Mistry and + Joanne Hunter). + - Added dynamic support for two levels above Op (red & purple icons). + - Changed the op/voice icons, now more macosx like. + - Serverlist progress: + * Now remembers your last network selection. + * Non-global User/real/nick are now implemented. + * Added all 1.8.x default servers. + - Added Clear Rawlog button. + - Throttle and Lag meter settings implemented. + - Fixed /lastlog. + - xtext: Fixed exposure-before-print crash. + - xtext: Fixed providing UTF8 selection data. + - xtext: Fixed text scrolling past the bottom bug. + - Added DCC-completed-dir setting, which can move completed DCC files + to a different directory (Chris Morgan). + - Update build environment to autoconf 2.53. + - Cleanup various configure.in/Makefile.am scripts. Use libtool to + build perl and python plugins (John). + - Added support for numeric 005 options: CHARSET=UTF-8 and + CASEMAPPING=ascii. + - Delinking/Relinking IRC windows re-implemented. + - Dialog window buttons re-implemented. + - Gnome2-ify the desktop file. Install to $(datadir)/applications. + + +---------------------------------------------------------------------- + 1.9.4 +---------------------------------------------------------------------- + + - Make DCC support up to 4GB files (previously 2GB). + - Fixed possible crash when receiving a message from a channel that + was already parted. + - Fixed random /part reasons not working. + - Fixed compile on RHL 8.0. + - Fixed xchat-text connect crash. + - Updated included intl/ to 0.10.38. + - Update transparency when background image changes. + - Fixed the progress-connecting-bar appearing in all tabs. + - More IRC protocol abstractions; tcpsend2 (James D. Taylor). + - New server list GUI almost complete. + - Merged some small 1.8.11 fixes. + - Reopen logfiles on SIGUSR1. + - Added Tint RGB settings (foser). + + +---------------------------------------------------------------------- + 1.9.3 +---------------------------------------------------------------------- + + - Updated Spanish translation (Pablo Gonzalo del Campo). + - Updated Swedish translation (Christian Rose). + - Added mIRC's passive dcc support, receiving only (Richard Fuchs). + - Added InputBox settings to settings GUI. + - Make DCC support up to 4GB files (previously 2GB). untested. + - Fix checks for Xft.h in configure script. + - Fix perl add_message_handler() xchat 1.8.x incompatability. + - Fix default DCCRECV text event using bad $ variable and crashing. + - Fix /query #foo, /join #foo crash. + - Fix utf8-conversion-fail sending truncated text. + - Use $datadir/locale for LOCALEDIR (Albert Chin-A-Young). + - More work done on Serverlist 2, but not fully functional yet. + - Pasting from one tab to another now works. + + +---------------------------------------------------------------------- + 1.9.2 +---------------------------------------------------------------------- + + - Fixed DCC Chat offer crash (1.9.1 bug only). + - xtext: Xft tweaks. Included Pango backend for when Xft can't be + used directly. + - xtext: improved rendering selections (less unnecessary redrawing). + - xtext: fixed marking multibyte utf8 chars. + - Included brand new Python interface plugin (Gustavo Niemeyer). + - Perl is now a plugin. + - Plugin API: Changed xchat_unhook() return value and type. + - Plugin API: Added "ignore" list. + - Plugin gui window can now load/unload scripts aswell. + - Plugins are now autoloaded from $libdir/xchat/plugins. + - Double-click userlist works again. + - Strip spaces from join-channel in serverlist (Mathias Hasselmann). + - The menu in the bottom right corner now works. + + +---------------------------------------------------------------------- + 1.9.1 +---------------------------------------------------------------------- + + - Fixed serverlist and rawlog crashes. + - Fixed some 64-bit issues (Elliot Lee). + - Fixed unrealized xtext crashes and warnings (Elliot Lee). + - Removed --disable-glib configure option. + - Added Save rawlog button. + - Auto detect socklen_t. + - All new plugin interface. See plugins/plugin20.html. + - Made perl.c use the new plugin interface. + - Made the whole system use the cmdchar setting. This means all + usercommands, popup commands etc mustn't start with a "/" char. + - Removed the mail checker, it's now a plugin. + - Cleaned up some text events code. Added/Changed/Removed some + events too. TextEvents window now lists them alphabetically. + - Convert inputbox from utf8 to locale before sending (xLoneStar). + - Use ~/.xchat2/ for all configs (may change to ~/.xchat-2.0 + when stable). + - Made DCC GUI display KB/s instead of cps. + - Ignore code cleanups; ignore.conf no longer compatible. + - Created the start of an IRC protocol abstraction layer. + - Plugged JCode memory leak. + - Ask before quiting when some DCCs still active. + - Rewrote most of the maingui code. Now there's only one virtual + tab that is re-filled with new information when switching tabs. + - Added right-click tab menu. + - Plugged potential /dns security hole. + - Converted userlist to GtkTreeView. + - Right-click userlist menu now works with a multi-selection. + - Drag and drop to userlist no longer requires libgnome. + - Included an ircII style /timer plugin. + - Now accepts irc:// URLs on the command line. + - Tabs are now ordered in server groups. + - Make gettext use utf8 (teuf). + - Whole new setup window. + - Notify gui has an add dialog window. + - Nickname on the bottom left is clickable. + - Cleaned up /set variable names. + - Made scrollwheel work with GTK+ 2.0 (Lloyd Williams). + - xtext: Added XFT support. + - xtext: Added UTF8 selection support. + + +---------------------------------------------------------------------- + 1.9.0 +---------------------------------------------------------------------- + + - Ported to GTK+ 2.0 (BIG!). + + +---------------------------------------------------------------------- + 1.8.7 +---------------------------------------------------------------------- + + - Updated Swedish translation (Christian Rose). + - Updated Russian translation (Anton Farygin). + - Added Latvian translation (Artis Trops). + - Made a work-around for a refresh glitch when delinking a tab under + gnome (the topic bar was overlapped). + - Fixed the need for signed chars (e.g. on PPC and s390). + - Fixed background garbage being drawn when using hidden tabs. + - Cleaned up alot of the nick completion code. Fixed some behaviour + too (Mukund, dinkles, me). + - Connect Cmd is executed again if you get auto-reconnected. + - Added safe-gaurd to stop duplicate nicks in userlist. + - Added an option to automatically remove finished/failed dccs + from the list. Use /set dcc_remove ON to enable it. + - Added an option to truncate long channel tabs. Use: + /set truncchans xx, where xx is the max chars (Jyrki Muukkonen). + - Made the default popup menu, dialog buttons, userlist buttons, + usermenu and urlhandlers translatable (via gettext). + - MMX tinting is now built on any x86 machine (it's checked at + runtime anyway). + - Added "Automatic Unmark Away" option in setup->away (Mads Martin). + - Immediately abort file transfers when out of space. + - Fixed a serious CTCP reply vulnerability. + + +---------------------------------------------------------------------- + 1.8.6 +---------------------------------------------------------------------- + + - Updated Danish translation (Morten Brix Pedersen). + - Updated Spanish translation (Antonio de la Torre). + - Updated French translation (Olivier Berger). + - The server "Connect cmd" is now executed before auto-join-channels, + so you can use it to authenticate to nickserv etc. + - Fixed autoresume again, for the last time... no, really. + - Fixed sending parts for all channels instead of one quit when you + exit the whole program (helps bncs). + - Autocomplete in the middle of a sentence won't jump to the end of + the textbox (Darell Tan). + - Fixed the buggy 1.8.5 outbound queue. It now sends privmsg/notice + with a lower priority, but never out-of-order. + + +---------------------------------------------------------------------- + 1.8.5 +---------------------------------------------------------------------- + + - Updated Slovak translation (Stano Visnovsky). + - Updated Swedish translation (Christian Rose). + - Updated Spanish translation (Antonio de la Torre). + - Updated Hebrew translation (Dan Fruehauf). + - Some fixes to the MODE parser. + - Added ability to customize dialog tab buttons (Oskar Liljeblad). + - Added an extra field in the EditServer window to enter a command + to execute after logging in. + - /load -e can now load a file of commands to execute. + - Added ability to change the log timestamp format (Jyrki Muukkonen). + - Fixed default keybinding for Shift-PageUp (Mukund). + - Changed the outbound throttle behaviour. Now only privmsgs and + notices go to the back of the queue, everything else goes to the + front. + - Made it possible to compile with older than 5.6 perl again. + - The main window's size and position is now saved on exit. Use + /set mainwindow_save OFF to revert to the old behaviour. + - Avoid auto-resuming the same file from two different people + (without breaking autoresume this time). + - Removed /sslserver and added a -ssl arg to /server, /reconnect, + /servchan and /newserver. + - Added support for /server irc://host:port/channel. + - Added some mmx asm code written by Willem Monsuwe for tinting + transparency. Use --disable-mmx to revert to gdk-pixbuf method. + - Fixed resetting your away status after an auto-reconnect. + + +---------------------------------------------------------------------- + 1.8.4 +---------------------------------------------------------------------- + + - Updated Spanish translation (Antonio de la Torre and Manuel + Garca Aguilar). + - Updated Russian translation (Valek Filippov). + - Fixed lockup when a file being offered is shortened before being + accepted. + - Fixed ** ERROR **: file python.c: line 743 (pysH_Eget_users): + assertion failed: (cur->hostname). + - /kickban now deops and bans in one line (-o+b) (Felix Nawothnig). + - Auto-nickcompletion now uses the nicksuffix setting (Mukund). + - win32: change log-filenames with a | character to _. + - When binding to a set hostname/ip, it would try to bind to port + 65535 - fixed. + - Fixed crash when closing a dcc chat in a perl-dcc-chat-callback. + - Added option "Beep on Channel Messages" and a Beep button to the + toolbox ("<" button in the botton right) (Jason Wies). + - Avoid auto-resuming the same file from two different people. + - /close -m now closes all dialog/query windows. + + +---------------------------------------------------------------------- + 1.8.3 +---------------------------------------------------------------------- + + - xtext: marked text goes to clipboard aswell as primary selection. + - xtext: some speedup optimizations. + - xtext: fixed a problem when rendering a fixed-width font with + missing chars. + - Fixed hints for "You're kicked" text event, which showed the $ vars + incorrectly. + - When a user is seen to quit or join a channel you're in, your + notify list will be modified instantly. No notify textevent is + shown if it happened in the front-most tab (Alexander Hvostov). + - Fixed binding server connects to different interface/address + (ipv4 only) (Claus Riemann). + - Avoid negative ping timeout when system clock changes. + - Updated Italian translation (Stefano Fava). + - Updated Spanish translation (Antonio de la Torre). + - Added text event "Channel Notice" so you can differentiate between + private and channel notices (Fuentes Xavier). + - Added ability to dcc send filenames with spaces. See "Fill Spaces" + setting in Setup->File Transfer (Fuentes Xavier). + - Included some makefiles for ms visual c. + + +---------------------------------------------------------------------- + 1.8.2 +---------------------------------------------------------------------- + + - Fixed kick messages showing only the first word of the reason. + - Fixed GTK warnings thrown up when closing a dialog window. + - Fixed a bug in sending quit reasons. + - Fixed a problem with handling op/voice modes that caused halfops to + appear in the userlist when using bahamut. + - Kanji conversion is now turned ON when locale is ja (Akira TAGOH). + - Saved some memory when loading .conf files (about 40k). + - When changing fonts, it now changes in the inputbox without having + to restart. + - Added safeguard to stop recursive user commands. + - Added two /set variables dialog_width and dialog_height. Use these + to set the default size of dialog windows. + - Win32: fixed crash of 'Auto Accept DCC Send' menu item. + + +---------------------------------------------------------------------- + 1.8.1 +---------------------------------------------------------------------- + + - Fixed crash in having server tabs ON and channel tabs OFF. + - Fixed crash when closing the channel list window AFTER all its + server windows were closed. + - Fixed potential crash of the font dialog in settings. + - Made /exec read data line-by-line (Richard Fuchs). + - Disabled the menubar while in shelltabs (it was dangerous to use it + anyway). + - Fixed the banlist window's Unban, which selected the wrong rows + sometimes. + - The Perl interpreter is now started only when loading the first + script, to save memory when not using scripts. + - Fixed lag/throttle meters not updating when set to text-only. + - Fixed two small memory leaks. + - Directories in your logmask are now created, so you can use masks + like "%c/%y.log" in Setup->Logging (Tobias v. Koch). + - xtext: FontSet rendering speedups. + - Win32: made word and line selection work in xtext. + - Win32: added url handler that sends to windows' shell. + - Win32: rendering 8bit characters should now work. + + +---------------------------------------------------------------------- + 1.8.0 +---------------------------------------------------------------------- + + - Fixed a memory leak in popup menus. + - Fixed crash in receiving private actions. + - Added /set variable 'perccolor'. Options effect input box are now: + perccolor: parse %C,%B,%U etc (default ON). + percascii: parse %XXX (where XXX is an ascii value) (default OFF). + Note: if perccolor is OFF, percascii will not work. + - Win32: Fixed incorrect calculation of ping time. + - Win32: Server lookup and connect is now threaded. + - Win32: Server connection error now reported correctly. + - Win32: A simple identd server is now builtin. + - Win32: Copying text from xtext to clipboard now works. + - Updated Swedish translation (Christian Rose). + - Updated Spanish translation (Antonio de la Torre). + + +---------------------------------------------------------------------- + 1.7.8 +---------------------------------------------------------------------- + + - xtext: Fixed parsing of "%C2, " to match mIRC, i.e. bg color is not + reset, fg changes to 2 and the comma is printed (Fuentes Xavier). + - xtext: a fix for multibyte text wrapping (Tetsuo YAMAMOTO). + - Made notify NOT announce everyone offline when you first login. + - Multiple WATCHes are sent on one line for notifies, to reduce lag. + - Added an internal /unban command which takes multiple masks. You + might want to remove the old usercommand (Tobias v. Koch). + - Banlist window now sends multiple modes per line. + - Fixed a memory leak in perl (Martin Persson). + - Removed the tooltip for userlistinfo, it seemed to cause corruption + on some gtk+ themes. + - Made xchat not interpret %C,%B etc when percascii is OFF, .e.g: + /set percascii OFF + - Fixed ops/voice counts when networks allow you to voice/op people + that are already voiced/oped (like EFnet). + - Fixed building with --disable-glib. + - IPv6 reverted to off by default, use --enable-ipv6 to enable. + - Win32 fixes: dcc send/recv now works and fixed a bug in loading + some .conf files by using the O_BINARY flag. + - Changed the xchat icon - old one was a bit too dark. + - Updated Greek translation (Fanis Dokianakis). + + +---------------------------------------------------------------------- + 1.7.7 +---------------------------------------------------------------------- + + - Re-added support for '+' channels when there's no 005 numeric. + - Made the new $3 null terminated (works better that way). + - Fixed Doubleclick-user when disabling userlist icons. + - Fixed SSL build. + - Win32 port (some code from Alex Badea's 1.5.11win32 port used). + - More code cleanups, removed all extern prototypes from fe-gtk/. + - Titlebar text now shows unknown channel modes too. + - Made persist chans work with /reconnect aswell. + - Avoid pastes of common unix directories being treated as irc + commands (Chema Celorio). + - Removed the Delete word forward/backward functions from + KeyBindings. GTK handles these already, why were they ever there? + - Made %h work for dialog windows' popup menu too. + - Fixed treeview not setting channels red and blue. + - The info above the userlist now gets a tooltip which gives you + some extra info. + - The nickgad (to the left of your nickname) now gets a text prefix + char if userlist icons are disabled. + - Timestamp format is now configurable in Setup->IRC Input/Output. + + +---------------------------------------------------------------------- + 1.7.6 +---------------------------------------------------------------------- + + - xtext: tweaks to make url highlights less flickery. + - Added some support for ircd numeric 005. MODES>=6, CHANTYPES, + CHANMODES, WATCH and PREFIX are supported. This means dynamic + support of different channel and user modes. The userlist icons + only support *@%+ though (admin, op, half op, voice), will have to + find a way to make these dynamic in the future. Also, made a new + file modes.c and rewrote mode handling in general to support this, + so what did I break? + - Added option 'Userlist icons' (default ON). Lets you turn off + userlist icons for ops, voice etc and get the plain text @+ (in + Setup->Interface). Might be useful for ircd's that have weird + and wacky access levels. + - Added support for WATCH command for use in notify list. Numeric 005 + must list WATCH for this to work. + - Added an extra arg $3 for channel message printevents. This is the + prefix char of the person talking, e.g. '@' for Ops. + - Resolve irc-server name only if using a non-socks4 proxy. This + allows you to connect even with a non-working dns. Also made the + socks5 code more "correct" (Richard Fuchs). + - Some code cleanups, got rid of most of the extern functions in c + files and moved them to h files. + - Perl has a valid context at startup again (broken in 1.7.4). + - Fixed leak of awaymessages for "Show away once" feature. + + +---------------------------------------------------------------------- + 1.7.5 +---------------------------------------------------------------------- + + - Fixed some buggy catalogs for gettext 0.10.37 (OpenBSD users). + Compiling with 0.10.35 will now break, there's always + ./configure disable-nls. + - Fixed python autoloading due to new serverlistcode (Richard Fuchs). + - Made perl/python/plugins autoload when first irc window is open + (rather than when serverlist opens), incase they need to print. + - Changed serverlist opening behaviour. It now obays the + 'No ServerList on startup' setting regardless of auto-connects. + - Fixed buggy Quit menu item (1.7.4 bug). + - DCC cleanups, including some endian fixes. + - DCC windows don't go to front when new xfers appear (1.7.3 bug). + - Rewrites to a few vital xtext functions. This seems to have speed + up rendering with a FontSet and fix the -/+1 line bug. + - Fixed Shelltab not opening sometimes (actually a 1.7.4 ipv6 bug). + - Added ability to change font for Shelltabs only: + /set font_shell + + +---------------------------------------------------------------------- + 1.7.4 +---------------------------------------------------------------------- + + - On startup, serverlist now opens without any other windows, looks + neater, less confusing for newbies. If you disable serverlist at + startup, a normal irc will open instead. + - Made a few things more userfriendly, "DCC Send" -> "File Send". No + need to refer to the protocol in the GUI! + - Fixed a xtext bug rendering a background color of 1 incorrectly. + - Unprintable characters used to cause problems to xtext (who would + have thought gdk_char_width returns a different value to + gdk_text_width?) - fixed. + - xtext renders only once when switching tabs (used to render twice + because gtk gives us 2 expose signals, why?). + - When you change your nick it changes in the titlebar now too. + Server name is now reported in dialog windows' titlebar. + - Having Strip mIRC Color ON will now strip it from dcc chats too. + - Added (really this time) perl functions add_user_list, + sub_user_list, clear_user_list for manipulating the userlist of a + channel (Lloyd Williams). + - Various code cleanups, including a rewrite of the IPv6 code. + Removed /6server and 'Use IPv6' check-box in the serverlist. It + automatically handles IPv6/IPv4 addresses now. + - Added a check-box in the serverlist edit window for "Use Proxy". + + +---------------------------------------------------------------------- + 1.7.3 +---------------------------------------------------------------------- + + - Added server hostname as $3 for quit print event (Bjorn Olievier). + - Some fixes to the gnomepanel code. Panel no longer asks to restart + applet on quit, removing the applet doesn't exit xchat (George). + - Fixed fd leaks in /exec and python (Richard Fuchs). + - user@host gets logged in query windows (Richard Fuchs). + - Fixed the 'Marked Away' & 'Save Settings on exit' check menu items + (when using --disable-gnome). + - Workaround for ipv6 build failing on some glibcs (Tobias von Koch). + - DCC won't try to resume if local file is bigger than remote offer. + - Fixed xtext drawing/wordwrap and textmarking bugs. + - Horizontal scrollbar appears in channellist window when needed. + - Fixed color paste. Does this affect multibyte pasting? Please + report (Darell Tan). + - Fixed titlebar text for notices/snotices tabs. + - The topic box gets a tooltip of the current topic. + + +---------------------------------------------------------------------- + 1.7.2 +---------------------------------------------------------------------- + + - Fixed some Python mem leaks and signal/event handlers can now + return non-null integer to tell xchat to stop processing the event + (like perl handling functions) (Richard Fuchs). + - Got rid of the Linger timeout. This was a lame solution to stop the + loss of QUIT messages when closing the socket too early. Now xchat + just delays closing sockets by 5 seconds (even on quiting the app). + No more 1 second delay when you close a tab or the whole app! + - Fixed some memory leaks in the banlist window. + - Added 'B' channel-mode button to access the banlist. + - Added Turkish translation (Ozgur Dogan GUNES). + - Updated Spanish translation (Antonio de la Torre). + - Fixed the throttle setting (which was reversed! who did that?). + - Added IRC::notify_list. (Matthew Gabeler-Lee). + - Don't crash when bind fails for dcc send. + - Don't send garbage to server when ban_type is invalid. + - Rewrote a whole heap of bad code in maingui.c. When opening a new + tab/window it always uses the same functions instead of having the + code repeated a few times. This is pretty big so expect some things + to break. This also means dcc/chanlist etc tabs get the < > buttons + too. + - /KICKBAN now deops users first (Tobias von Koch). + + +---------------------------------------------------------------------- + 1.7.1 +---------------------------------------------------------------------- + + - Turning off server tabs should work again (1.7.0 bug). + - Some ipv6 fixes. + - Added a few TextEvents that used to be hardcoded. + - Updated jcode (Takuo Kitame). + - Fixed possible crash in palette window (1.7.0 bug). + - Rewrote the EscapeCode->mIRC color conversion for /exec. + - Added option to explicitly set your dcc IP (Jim Seymour). + - Added Opera and w3m to default URL Handlers. + - New serverlist/window icon - just for a change. + - Updated Korean translation (Kim SeungBaeck). + - Added hook_timeout to the XChat.XChat() python class so you can + XChat.XChat().hook_timeout(delay, handler). It is a one time + function like the perl version (Donald Kjer). + - /RECONNECT can now takes args like /SERVER, the difference + being that it'll rejoin all your channels (Angel). + + +---------------------------------------------------------------------- + 1.7.0 +---------------------------------------------------------------------- + + - Updated German translation (Benedikt Roth). + - Updated Spanish translation (Antonio de la Torre). + - Updated Japanese translation (Takuo Kitame). + - Added Norwegian translation (Kjartan Maraas). + - Fix for bug in 1.4.x serverlist.conf loading. + - Away status and reason is re-send to the server if you get + disconnected (Daniel Rall). + - Added option to have one tab for notices, configurable under + Inferface/Window layout (Alex Badea). + - Added another meter component that measures the server send queue + from the throttle system (pref: throttlemeter), added UI support + for showing the lag and throttle as either progress bars, info + boxes, both, or none (Alex Badea). + - Added a command to flush the send queue (/FLUSHQ) and one for + forcing a new lag check (/LAGCHECK) (Alex Badea). + - Added option 'persist_chans', when ON once a session is created + for a channel, no other channel will be assigned to that session, + regardless of any parts or kicks (Alex Badea). + - Compile errors while loading a perl script are printed on the main + window. Warnings issued by perl scripts are also printed on the + main window. This allows script writers to use the perl command + 'warn' to point out strange things. Perl errors no longer make + xchat crash. The error message is written on the main window and + the command execution is stopped (Frodo Baggins). + - Added IPv6 support for making server connections. See + ./configure --enable-ipv6 and /6SERVER command (\\bonxo\\@IRCnet). + - Added Banlist window (Salvatore Insalaco). + - You can now specify which dir ssl is in, e.g.: ./configure + --enable-openssl=/usr/local/ssl (Richard Fuchs). + - Added InterScan proxy traversal support (is this the correct name + for this proxy? Looks like a httpd proxy to me) (Alex Riesen). + - Added Japanese code conversion support, see ./configure + --enable-japanese-conv (Takuo Kitame). + - xtext: smooth (pixel-based) scrolling. + + +---------------------------------------------------------------------- + 1.6.4 +---------------------------------------------------------------------- + + - Fix for using a DCC port range (Lawrence Gold). + - Fix for building on UnixWare 7 (Ronald Joe Record). + - Added Chinese translations - zh_TW.Big5 and zh_CN (Kevin Peng and + Anthony Fok Tung-Ling). + - Added Finnish translation (Jarkko Ranta). + - Revamped the default URLHandlers to add Galeon and Mozilla. + - Clicking Accept on a DCC chat that you offered would loop - fixed. + - Fixed percentage display for DCC receive (Matthew Gabeler-Lee). + - Fixed bug in indent and timestamps (Dmitriy Zavin). + - Fixed crash bug in xchat-text and DCC send being aborted remotely. + - Made /lastlog more efficient for very large scrollback buffers. + - Beep on private actions too (Richard Fuchs). + - /MSG'ing a channel or nick will show up in the destination tab + instead (Richard Fuchs). + + +---------------------------------------------------------------------- + 1.6.3 +---------------------------------------------------------------------- + + - Updated Swedish translation (Christian Rose). + - Updated Spanish translation (Antonio de la Torre). + - Right-click toggle menu items used to crash under gnome (bug in + gnome-libs?) - work around. + - xtext: Efficiency improvements: text mark, word and line select. + - xtext: fixes for multibyte characters (UNO Takeshi). + - Fixed bug in resizing a tinted-transparent window (deb bug #79674). + - Some OS2 compilation fixes (pla). + - Fixed PONG parsing (Stefano Barbato). + - Fixed a leak of file descriptors. + - Fixed /ALLSERV. + - Fixed /BAN to replace ~ with * in username (Stefan Scholl). + - Fixed /ME through DCC CHAT while not connected to server (#81031). + - Work-around for UnrealIRCd's duplicate /NAMES bug. + - Fixed DCC receiving filenames with spaces. + + +---------------------------------------------------------------------- + 1.6.2 +---------------------------------------------------------------------- + + - xtext: Fixed the mark-clear bug (gnome bug #34584). + - Updated German translation (Tamer Fahmy). + - Commas are replaced with %2c in URLs, as to not confuse poor old + Netscape (deb bug #70905). + - Bluestring to 300 chars (deb bug #79138). + - Added option /SET percascii, which can disable/enable translation + of %XXX into an ascii value while typing (deb bug #76122). + - New hotkey hook: key_action_put_history. Only inserts line into + history, but doesn't send it to the server (DaP). + - Lots of SSL updates: + * Make accept_invalid_cert optional on /sslserver (DaP). + * Print verbose information of SSL session on connect (DaP). + * Clean up code at X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT checking + (DaP). + + +---------------------------------------------------------------------- + 1.6.1 +---------------------------------------------------------------------- + + - xtext: Fixed lockup with certain sized fonts. + - xtext: Made some changes to improve efficiency when using really + large scrollback buffers (only noticable when doublebuffer off). + - Fixed a bug in /help crashing on longer than 10 char UserCommands. + - Fixed autoreconnect while using a proxy server. + - Never-give-up ReConnect does just that (even more so than before :) + - Fixed the channelmode buttons mouse-over problem. + - Fixed percentage display for large files in dcc recv/send gui. + - StartTime in dcc chat gui no longer Jan 1 1970. + - Fixed DCC send behind IP-Nat (Bernhard Valenti) + . + - Added Lithuanian translation (Gediminas Paulauskas). + - The < > buttons arn't shown for non-tab windows (Aaron Lehmann). + - Fixed the (-1,-1) transparency problem for non-tab windows. + + +---------------------------------------------------------------------- + 1.6.0 +---------------------------------------------------------------------- + + - xtext: More efficient handling of expose events, text marking and + url highlighting when double buffer is OFF. + - xtext: Fixed a very rare bug that could cause BadGC errors or the + separator bar not to be drawn. + - Fixed crash in right-clicking URLs in the URL Grabber window. + - If Check-For-Replace is in the keybindings for Return, it'll + actually work again. + - USER login command now sends your nodename instead of 'localhost' + to please some IRCNet servers. + - Updated Swedish translation (Christian Rose). + + +---------------------------------------------------------------------- + 1.5.11 +---------------------------------------------------------------------- + + - Updated Slovak translation (Stano Visnovsky). + - Updated Swedish translation (Christian Rose). + - Updated Greek translation (Fanis Dokianakis). + - Updated Spanish translation (Antonio de la Torre). + - If Never-Give-Up Reconnect is ON, it won't give up on DNS failer. + - '/me is back' is sent again when Announce Away Messages is ON. + - If channelmode buttons were OFF and you joined a channel with a + userlimit xchat would crash - fixed. + - /sslserver's password arg. is now optional (Daniel Richards). + - SSL accepts self signed certs (Daniel Richards). + - Fixed the unnecessary window resizes when opening a new tab. + - Changed the tinting code a bit (thanks gnapster :). + - Transparent shell tabs update too when they are moved. + + +---------------------------------------------------------------------- + 1.5.10 +---------------------------------------------------------------------- + + - Added "Enable double buffer" toggle in Setup->Channel windows. + - Double buffer is now OFF by default (seems to use less CPU). + - Timestamps didn't turn ON while indent was OFF - fixed. + - Updated Swedish translation (Christian Rose). + - Added some extra text events: Channel Msg hilight, Channel + Action hilight (near top of the list). No more cardcoded color + codes! Also hilighting in actions works, and you can make the whole + message hilighted if you change the event text. + - Initial window size is actually set to your settings (this will + never be perfect I guess, sometimes to the window still resizes + itself without warning). + - Hidemenubar setting didn't work properly for non-tabs and when + delinking windows - fixed. + - Notices appear in front tab even when server tabs are enabled. + - Changed Away behaviour again. No more /back, /away with no args + brings you back. The menu-item's state is what the server tells + it, it even changes when you switch tabs to another server. Xchat + assumes you are not away when you first connect. irc::get_info(5) + returns the away state. One day the other UserModes menu items will + show correct states. Is everyone happy now? + - Translation tables didn't work for outgoing text - fixed. + - Cleaned up a few xchat.conf names, a few settings may not load up + from 1.5.9 - just set them again. + + +---------------------------------------------------------------------- + 1.5.9 +---------------------------------------------------------------------- + + - Updated Spanish translation (Antonio de la Torre). + - Added Hebrew translation (Dan Fruehauf). + - Fixed crash bug when partreason was not set. + - Dialog tabs obay the hidetopicbar setting now too (the one in the + right-click menu). + - Cleaned up the settings gui: the whole window is more compact now, + some toggles in two columns, numbers use a spin-button, entry boxes + are larger and option-menus are more consistant. + - The "o=xx v=xx t=xx" display is finally changed. + - Changed most of xtext.c to use gdk instead of Xlib. + - Added configure option: + --disable-xlib disable use of xlib (for non X11 systems) + This might help compile xchat on other GTK supported systems like + BeOS and Win32 (havn't tried it though). + - Neater /set list. + - You can now set a nickname per server (see serverlist edit window). + - Changed the behaviour of /away and added /back (James Crawford). + - Away reason can now be a text file of random reasons too. + + +---------------------------------------------------------------------- + 1.5.7 -> 1.5.8 +---------------------------------------------------------------------- + + - Updated Spanish translation (Antonio de la Torre). + - Updated Swedish translation (Christian Rose). + - Updated Greek translation (Dokianakis Fanis). + - Updated German translation (Tamer Fahmy). + - Added Catalan translation (Pablo Saratxaga). + - Added option "Always timestamp logs" which timestamps log files + even if on-screen timestamps are off (Mike Guidero). + - Added entry "Part Reason: ". Also part and quit reasons can be + a filename of random reasons (filename relative to ~/.xchat/). + - Took out /unban as a internal command, add it as a usercommand + /quote MODE %c -b &2 instead. + - Added a text event for banlist. Try /banlist and it'll be a bit + more readable now. + - Changed output throttle system (undernet style) (Alex Badea). + - Added 1 second linger socket option to stop QUIT msgs from being + lost (they still get lost sometimes, why?). + + +---------------------------------------------------------------------- + 1.5.6 -> 1.5.7 +---------------------------------------------------------------------- + + - Fixed transparency-leak problems in 1.5.6 + - New code to create shaded transparency, taken from latest zvt. + (is it better?) + - URL handlers are now executed without a shell. + (http://www.securityfocus.com/vdb/bottom.html?vid=1601) + - Fixed a bug in xchat.conf and serverlist.conf loading. + - When spliting msgs (longer than the IRC 512 limit), it used to + loose some chars - fixed. + - Added feature to choose DCC port range (Lars Sundqvist). + - Fixed perl-stack overflow probs in irc::userlist() and others. + Added perl functions user_list_short() and perl_script_list() + (Mike Guidero). + - MHz is now detected on FreeBSD 4.x/5.x (Jonathan Perkin). + - It's now possible to "/dcc close chat nick" within a DCC perl + input handler without crashing xchat. (Geoffrey Higginson). + - Fixed a problem with the usermenu not updating sometimes. + + +---------------------------------------------------------------------- + 1.5.5 -> 1.5.6 +---------------------------------------------------------------------- + + - Added option pingtimeout, which pings the server instead. + /set pingtimeout 90 is default (small values will malfunction). + You also need the lagometer enabled for this to work. + - No longer using fnmatch() for ignore etc (because the way it + handles [ and ]). Using function from ircu2.10.08. + - Some fixes to code & configure.in to make it compile using + Solaris C (Albert Chin). + - New Spanish translation (Antonio de la Torre). + - New Russian translation (Alex Samorukov). + - New Hungarian translation (Horvath Szabolcs). + - Added Portuguese translation (Vitor Antunes). + - Added Slovak translation (Martin Pekar). + - Added /allserv and /allchan . They send a command to + all currently connected servers and joined channels. Also added + usercommands /ame and /amsg which make use of this. + - Added sock5 traversal, see Setup->Proxy Server (Alex Badea). + (The numbers for proxy_type are now 0=disabled, 1=wingate, + 2=socks4, 3=socks5). + - A few more buffer overflow checks (nick & channel length). + - Mapped mIRC color 99 to "no background" (mIRC lame!). + - Some efficiency tweaks to xtext. + - Added SSL support (see --enable-openssl and /help server) (DaP). + This seems to be highly experimental, as I don't know of any IRC + servers that can do SSL yet. + - Changed history behaviour, more like GNU (DaP). + i.e. Doesn't wrap and the bottom line is blank. + - Added option "InputBox Always In Focus" (DaP). + - Added option "Show Nickgad" (DaP). + - Added option "Show invites in the active Window" (DaP). + - Added option "Send /Whois" in notifies section, which sends a + /whois when someone comes online (DaP). + - Added an event for numeric 341, you inivited someone (DaP). + - Title bar text changed/improved a bit (DaP). + - Added actions for EditKeyBindings: MoveFrontTabLeft and + MoveFrontTabRight, like the <> buttons, but for keyboard (DaP). + - Implemented timeout events in the text frontend (Alex Badea and + fixed by me :). + - Dcc Recv/Send tabs won't resize the window when open. + - Added configure option --disable-glib. + - Transparent windows update when background changes (Aaron Lehmann). + - serverlist.conf is slightly changed! You WILL be able to load your + old 1.5.5 or 1.4.x server list, but older versions WON'T load lists + from 1.5.6, so backup your serverlist.conf if you need to. + + +---------------------------------------------------------------------- + 1.5.4 -> 1.5.5 +---------------------------------------------------------------------- + + - Fix for show/hide menu under gnome. + - Added -a and --noauto arg (don't auto connect to any servers). + - Added internal /list command, which sends the correct args according + to ircd type (it detects undernet and dalnet to send >0,<10000). + Remove any old /list usercommands you might have. + - /op /deop ... etc send up to six modes per line if using undernet. + - As discussed in the mailinglist, changed DCC resume to send and + expect to receive ACKs as an absolute, rather than an offset from + the resume point. It *should* work with mIRC now, but break with + old versions of xchat and probably BitchX. + - Added option "Limited Tab Highlighting" (Francis Litterio). + + +---------------------------------------------------------------------- + 1.5.3 -> 1.5.4 +---------------------------------------------------------------------- + + - Lack of gdk_pixbuf is detected correctly now (configure script). + - textmarking is no longer a timeout event, is this better or worse? + - Added Turkish translation (Fatih Demir). + - Added Russian translation (Valek Filippov). + - Added Ukrainian translation (Yuri Syrota). + - Added configure option --disable-zvt. Also, zvt shell tab can be + compiled in even without gnome (and is by default, if gnome-config + can be found to provide the LDFLAGS). + - Added "Delete Word Forward" function in Edit Key Bindings. Bind + this to Alt-d for that emacs feel (Francis Litterio). + - Ping times show one extra decimal place. + - You can now hide the menubar too, click left mouse in the text area + to get a popup version of the menu (middle mouse in dialogs). + - Added the proxy settings to the GUI, Setup->IRC->Proxy Server. + - Added a keyword TOGGLE for usermenu. Delete your old usermenu.conf + to see the new default one. + - Configure script now cleans up the CFLAGS & LDFLAGS (removes + duplicate words), let's hope this doesn't break on some boxses. + + +---------------------------------------------------------------------- + 1.5.2 -> 1.5.3 +---------------------------------------------------------------------- + + - Fixed a rare overflow bug in auto_insert(). + - Pressing OK in the settings window on slow machines (p233?) was + pretty slow, maybe it's faster now. + - Corrected some inputgad behaviour (Aaron Lehmann). + - Fix for 64bit machines (alpha) in xtext (word clicks). + - Updated German translation (Benedikt Roth). + - Updated Danish translation (Birger Langkjer). + - If you disconnect (/discon, /quit...) a server during the reconnect + delay, it is actually removed now. + - Added option "Give the userlist style" (DaP). + - Translation tables support can be turned off (--disable-trans), for + you minimalist freaks. + - Added Hebrew support, compile time: --enable-hebrew, run time: + /set hebrew 0/1 (Dan Aloni). + - Added new setting, "nick completion character" (Francis Litterio). + - Added new setting, "Old-style Nickname Completion", which makes it + act much like 1.4.x (Francis Litterio). + - Added "Delete Word" function to EditKeyBindings (Francis Litterio). + - Now using gdk-pixbuf for decoding pictures and tinted transparency. + (Tints don't seem to work 100% yet). (Andreas Persenius). + - Added halfop support (mode +h). This includes support in the + userlist, /hop, /dehop, /mdehop and new textevents (Elizandro G. Roos). + + +---------------------------------------------------------------------- + 1.5.1 -> 1.5.2 +---------------------------------------------------------------------- + + - --disable-gnome should work again. + - Fixed a bug in right-click nick menu. + - Should compile with glibc 2.1.3 (no more 'struct user' errors). + - Added Romanian translation (Dan Damian). + - CTCP flood protection won't kick in for ACTIONs. + - Removed the theme code. + - Made pixmaps.c, all code to decode/free/etc pixmaps is in here. + - WM_HINTS icon is set for the app. + - Removed the "-c" flag (it's automatic now). + + +---------------------------------------------------------------------- + 1.5.0 -> 1.5.1 +---------------------------------------------------------------------- + + - Shell tabs are now delinkable. + - Added a "show/hide topic bar" button (bottom right), I didn't know + where else to put this. + - Hidding the userlist is saved and any new tabs/windows open will + have the userlist hidden. + - You can now turn off/on perl warnings with /set perlwarnings 0/1. + - Tab-key nick completion even more like GNU readline (Gerard Daubar). + - Rewrote the function that handles %variables in userlist buttons, + user commands and ctcp replies (all use the same function now), + please report any bugs (especially if someone can overflow you from + remote ;) - as a consequence, you can use % and & (word/word_eol) + for ctcp replies now. Also added %m for machine info. + - Nickname-popup-menu, URLmenu and Usermenu all use the same code now + (it means you can make submenus in all 3). + - Double eval back in perl.c + - Dialogs/querys also have a toolbox button (just for consistancy). + - Added lagometer (/set lagometer 0 to turn it off), this isn't quiet + finished yet (and doesn't work on IRCNet because it refuses to + reply to pings correctly). + + +---------------------------------------------------------------------- + 1.4.2 -> 1.5.0 +---------------------------------------------------------------------- + + - Some changes & cleanups to the parser code (inbound/outbound). + - Ran all source through indent, using: + indent -bli0 -bls -ce -ts3 -i3 + (please use this in your patches, I used GNU indent 2.2.4). + - If you send a message (channel or query window) longer than 512 + bytes (maximum allowed by the ircd) it will be split into two + smaller messages instead of being truncated. + - Some gui touchups and changes. + - You can now enable/disable the output throttle with /set throttle. + - Added /timer. + - Overhauled the ChannelList window (Joshua Gough). + - Added proxy traversal support for socks and wingate, no gui yet so + use /set proxy_host, proxy_port, proxy_type (1=socks, 2=wingate). + - Added /userlist. + - Opaque-window-move used to be slow on some windowmanagers even + with transparency turned off - fixed. + - Tab-key completion is more like GNU readline (Wes Peters). + - Now possible to use modules in perl scripts (Andreas Scherbaum). + - irc::get_info(4) returns the current xchat dir (Mike Guidero). + - Added irc::get_prefs() (returns a /set variable) (Leo Cacciari). + - /set is now possible. + - Added Show-Userhost-in-Userlist option (Nicolas Dimitrijevic). + - Build tree cleaned up so 'make dist' can work. + - Added flood protection from CTCP and mass-dialogs-opening (Bruj0) + rdiazleven@ubp.edu.ar. (see variables *_limit). + + +---------------------------------------------------------------------- + 1.4.1 -> 1.4.2 +---------------------------------------------------------------------- + + - Compilation fixes for IRIX (David Kaelbling). + - Compilation fixes for AIX (Rodrigo Barbosa). + - Compilation fixes for OpenBSD. + - Should now compile with certain beta/alpha versions of Perl. + - "Scrollbar snapping to top" bug fixed. + - Corrected some text marking behaviour. + - Made use of fnmatch(), if available (for chanlist, ignore etc). + - Configure script is now generated with a sane version of autoconf. + - Alt-minus and Alt-plus now wrap around (AGL). + + +---------------------------------------------------------------------- + 1.4.0 -> 1.4.1 +---------------------------------------------------------------------- + + - Fixed a bug that could make new text not appear while marking text. + - xtext: Further improved performance when double buffering is turned + off (marking text & URL hilights are almost flicker free). + - xtext: Double buffer is now freed at each render operation, this + should reduce memory usage if you have many tabs open. + - If you closed a server while it was in the reconnect-delay, xchat + would crash - fixed. + - No more zombies when doing /discon while connection in progress. + - Added "/clear all" command (Paul de Regt). + - Hilights only work on full word matches now (Brendan O'Dea). + - Some Solaris compilation fixes (David Morgan). + - Danish translation updated (Birger Langkjer). + - Italian translation updated (Stefano Fava). + - Greek translation added (Fanis Dokianakis). + - Dutch translation upated (Arjan Scherpenisse). + - Removed some very old translations: fr_CA, no, pl, ru and sv. + (If someone wants to update these, you're welcome to). + - Channel mode "+h nick" (half Op) is now reported correctly (still + not supported in the userlist though). + - Having indent nicks OFF in channel windows and ON in dialog windows + didn't work - fixed. + - Sometimes ignores wouldn't save - fixed. + + +http://www.xchat.org diff --git a/HACKING b/HACKING new file mode 100644 index 00000000..8f45aff5 --- /dev/null +++ b/HACKING @@ -0,0 +1,51 @@ +Just some tips if you're going to help with xchat code (patches etc): + +* Use tabs, not spaces, to indent code. + +* Use a tab size of 3 (most editors will let you choose this). + Type :set ts=3 in vim/gvim. + +* Try to stick to the same consistant coding style: + +void +routine (void) +{ + if (function (a, b, c)) + { + x = a + 1; + } +} + + (vertically aligned braces, a space after if, while, functions etc). + +* Don't use "//" C++ style comments, some compilers don't like them. + +* When opening a file with unix level functions (open, read/write, close) + as opposed to the C-level functions (fopen, fwrite/fread, fclose), use + the OFLAGS macro. This makes sure it'll work on Win32 aswell as unix e.g: + + fh = open ("file", OFLAGS | O_RDONLY); + +* Use closesocket() for sockets, and close() for normal files. + +* Don't read() from sockets, instead use recv(). + +* Please provide unified format diffs (run diff -u). + +* Call your patch something more meaningfull than xchat.diff (I get a + million of these files!). + +* To make a really nice and clean patch, do something like this: + +Have two directories, unpacked from the original archive: +xchat-2.0.0/ +xchat-2.0.0p1/ +Then edit/compile the xchat-2.0.0p1 directory. When you're done, make +a patch with: + +cd xchat-2.0.0p1 +make distclean +cd .. +diff -urN xchat-2.0.0 xchat-2.0.0p1 > xchat-something.diff + +If using nmake (Windows) replace "make distclean" with "nmake -f makefile.msc clean" \ No newline at end of file diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..2773a1ce --- /dev/null +++ b/INSTALL @@ -0,0 +1,49 @@ +X-Chat Requirements: +~~~~~~~~~~~~~~~~~~~~ + + - GTK 2.6+ (it comes with your Linux) + + Optional: + + - Perl (http://www.perl.org) + - Python (http://www.python.org) + - TCL (http://tcl.activestate.com) + - OpenSSL (http://www.openssl.org) + + + +X-Chat Compiling and Installation: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Type this: + + ./configure + make + +Become root and type: + + make install + + +Other Options +~~~~~~~~~~~~~ + +To get a full list of compile options, type: + + ./configure --help + + +If you do not have GNU Gettext installed, instead use: + + ./configure --disable-nls + + +If you want to disable Perl you can do: + + ./configure --disable-perl + + +If you want to install a smaller stripped binary (without debug) do: + + make install-strip + diff --git a/INSTALL.w32 b/INSTALL.w32 new file mode 100644 index 00000000..846741a0 --- /dev/null +++ b/INSTALL.w32 @@ -0,0 +1,117 @@ +COMPILING ON WIN32 +~~~~~~~~~~~~~~~~~~ +It is not easy! Be warned! You need either one of these compilers: + + * Mingw (http://www.mingw.org) + * MS Visual C + +Note: This source code is meant for Linux/Unix like systems. Compiling this for +Windows will produce a below-par quality product. The official XChat for Windows +is not built with this unix source code. + + +Getting GTK +~~~~~~~~~~~ + +You also need GTK+ 2.10 for win32. Altough the GTK packages from the GIMP +website are larger and harder to install they work very well. + + 1) Get the following packages from: + http://www.gimp.org/~tml/gimp/win32/downloads.html + + - gtk+-2.4.3.tar.gz + - gtk+-dev-2.4.3.tar.gz + - dirent.zip + - gettext-runtime-0.13.1.zip + - gettext-tools-0.13.1.zip + - atk-1.6.0.zip + - atk-dev-1.6.0.zip + - pango-1.4.0.zip + - pango-dev-1.4.0.zip + - libpng (http://gnuwin32.sourceforge.net/packages/libpng.htm) Binaries & Developer files. + - GNU libiconv (Not source files) + - glib-2.4.2.zip + - glib-dev-2.4.2.zip + - pkgconfig-0.15.zip + - Zlib121-dll.zip + + 2) Extract all files to a suitable place such as c:\devtools + + 3) Windows 2000, XP & 2003 users: + - Start->(Settings->)Control Panel->System Applet + - Advanced Tab->Environment Variables + - Under "User variables for " append ";C:\devtools" to the end of the PATH Variable + - Click Ok twice and close the Control Panel + + For Windows 9x users your basicly on your own for now. + + +Mingw +~~~~~ + + I havn't tried this yet, but ./configure --disable-xlib would be a start. + + +MS Visual C +~~~~~~~~~~~ + + + 1) Edit src\makeinc.msc + + You need to change the variables GLIB, GTK and LIBS to point + the correct paths for your harddrive. Use the program pkg-config + to find this information. + + a) paste the output of `pkg-config glib-2.0 --msvc-syntax --cflags` + to the GLIB = ... line. + + b) paste the output of `pkg-config gtk+-2.0 --msvc-syntax --cflags` + to the GTK = ... line. + + c) paste the output of `pkg-config gtk+-2.0 --msvc-syntax --libs` + to the LIBS = ... line. + + 2) In MSVC's includes directory, copy io.h to unistd.h. + + MS VC++ 6 + ~~~~~~~~~ + + 3) Download Platform SDK from http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ + (you only need Core SDK) - ~200 MB Download (Be warned). + 4) Open the build enviroment. + + a) If your planning on developing modifications to the xchat code go: + Start->Programs->Microsoft Platform SDK...->Open Build Enviroment...->(Choose OS)->... (Debug) + + b) If your compiling just to use xchat and wish to no recieve debug messages: + Start->Programs->Microsoft Platform SDK...->Open Build Enviroment...->(Choose OS)->... (Retail) + 5) Change directory into where you have download the xchat source to and type this: + cd src + nmake -f makefile.msc clean + nmake -f makefile.msc + 6) Copy fe-gtk\xchat.exe to another place. + MS VC++ 7 (.NET) + ~~~~~~~~~~~~~~~~ + + 3) Open the Visual Studio .NET Command Prompt + + 4) Change directory into where you have download the xchat source to and type this: + cd src + nmake -f makefile.msc clean + nmake -f makefile.msc + 5) Copy fe-gtk\xchat.exe to another place. + + +Common problems: +~~~~~~~~~~~~~~~~ + + * gdk-pixbuf-csource must be in PATH. + FIX: See step 3 for setting up GTK + + * You might need to install dirent.zip manually. + FIX: Copy C:\devtools\include\dirent.h to C:\devtools\include\glib-2.0\dirent.h + + * Include path to libintl.h should be in GLIB= (makeinc.msc). + FIX: Copy C:\devtools\include\libintl.h to C:\devtools\include\glib-2.0\libintl.h + + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..f86b4ed7 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,12 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = po intl src plugins + +EXTRA_DIST = autogen.sh HACKING INSTALL.w32 faq.html xchat.png \ + xchat.desktop xchat.spec config.h.w32 xchat.ico + +icon_DATA = xchat.png +icondir = $(datadir)/pixmaps + +util_DATA = xchat.desktop +utildir = $(datadir)/applications diff --git a/README b/README new file mode 100644 index 00000000..809a903c --- /dev/null +++ b/README @@ -0,0 +1,103 @@ +X-Chat README +~~~~~~~~~~~~~ + X-Chat ("xchat") Copyright (c) 1998-2010 By Peter Zelezny. + + This program is released under the GPL v2 with the additional exemption + that compiling, linking, and/or using OpenSSL is allowed. You may + provide binary packages linked to the OpenSSL libraries, provided that + all other requirements of the GPL are met. + See file COPYING for details. + + +What is it? +~~~~~~~~~~~ + X-Chat is an IRC client for UNIX operating systems. I.R.C. is Internet + Relay Chat, see http://irchelp.org for more information about IRC in + general. Xchat runs on most BSD and POSIX compliant operating systems. + + +Requirements: +~~~~~~~~~~~~~ + * GTK+ 2.10 (this is available at http://www.gtk.org). + + X-Chat is known to work on, at least: + + * Linux + * FreeBSD + * OpenBSD + * NetBSD + * Solaris + * AIX + * IRIX + * DEC/Compaq Tru64 UNIX + * HP-UX 10.20 and 11 + * MacOS X + * Windows XP/2000/Vista/7 + + +Notes for packagers: +~~~~~~~~~~~~~~~~~~~~ + + If you need your packages to work on i386, you don't need to compile with + --disable-mmx, because it's also checked at run-time. + + +Python Scripts: +~~~~~~~~~~~~~~~ + Scripts for 1.8.x are not compatible, and a brand new interface has be + written. Documentation can be found here: http://xchat.org/docs/. + Consider using the Python interface for your scripts, it's a very nice + API, allows for loading/unloading individual scripts, and gives you + almost all the features of the C-Plugin API. + + +Perl Scripts: +~~~~~~~~~~~~~ + Scripts for 1.8.x are compatible with the following exceptions: + +* IRC::command will not interpret %C, %B, %U etc. + +* user_list and user_list_short: + If a user has both op and voice, only the op flag will be 1. + +* add_user_list/sub_user_list/clear_user_list + These functions do nothing. + +* notify_list + Not implemented. Always returns an empty list. + +* server_list + Lists servers that are not connected aswell. + +* Some print events may have new names and some were added. + +* Text printed by scripts must now be UTF8. + +* Text passed to scripts (via add_message_handler) will be encoded in UTF8. + + +Autoloading Perl Scripts and Plugins +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * X-Chat automatically loads, at startup: + ~/.xchat2/*.pl Perl scripts + ~/.xchat2/*.py Python scripts + ~/.xchat2/*.so Plugins + $(libdir)/xchat/plugins/*.so plugins + (this usually translates to /usr/lib/xchat/plugins/*.so) + + +Control Codes: +~~~~~~~~~~~~~~ + %% - A single percentage sign + %C - Control-C (mIRC color code) + %B - Bold Text + %U - Underline Text + %R - Reverse Text + %O - Reset all Text attributes + %XXX - ASCII XXX (where XXX is a decimal 3 digit number) + (Eg: %007 sends a BEEP) + + %Cforeground,background will produce a color code, eg: %C03,10 + + These are now disabled by default (see Settings > Prefs > Input Box). + Instead you can insert the real codes via ctrl-k, ctrl-b and ctrl-o. diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 00000000..0c711739 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,40 @@ +dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) +dnl +dnl example +dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local + +AC_DEFUN([AS_AC_EXPAND], +[ + EXP_VAR=[$1] + FROM_VAR=[$2] + + dnl first expand prefix and exec_prefix if necessary + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + dnl if no prefix given, then use /usr/local, the default prefix + if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + fi + dnl if no exec_prefix given, then use prefix + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + dnl loop until it doesn't change anymore + while true; do + new_full_var="`eval echo $full_var`" + if test "x$new_full_var"="x$full_var"; then break; fi + full_var=$new_full_var + done + + dnl clean up + full_var=$new_full_var + AC_SUBST([$1], "$full_var") + + dnl restore prefix and exec_prefix + prefix=$prefix_save + exec_prefix=$exec_prefix_save +]) diff --git a/autogen.sh b/autogen.sh new file mode 100644 index 00000000..4f69c071 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,113 @@ +#!/bin/bash +have_automake=false + +if automake --version < /dev/null > /dev/null 2>&1 ; then + automake_version=`automake --version | grep 'automake (GNU automake)' | sed 's/^[^0-9]*\(.*\)/\1/'` + case $automake_version in + 1.2*|1.3*|1.4|1.4*|1.5*|1.6*|1.7*|1.8*) + ;; + *) + have_automake=true + ;; + esac +fi +if $have_automake ; then + AUTOMAKE="automake" + ACLOCAL="aclocal" +else + if automake-1.9 --version < /dev/null > /dev/null 2>&1 ; then + AUTOMAKE="automake-1.9" + ACLOCAL="aclocal-1.9" + else + echo "automake missing or too old. This requires atleast automake 1.9" + exit 1 + fi +fi + +# ------ START GETTEXT ------ + +echo searching for GNU gettext intl directory... + +dirs="/usr/share /usr/local/share /opt/share /usr /usr/local /opt /usr/gnu/share /opt/local /opt/local/share" +found=0 +for try in $dirs; do + echo -n " -> $try/gettext/intl... " + if test -d $try/gettext/intl; then + echo found it + found=1 + break + fi + echo no +done +if test "$found" != 1; then + echo ERROR: Cannot find gettext/intl directory. + echo ERROR: Install GNU gettext in /usr or /usr/local prefix. + exit 7 +fi; + +echo copying gettext intl files... +if test -f $try/gettext/mkinstalldirs; then + ln -s $try/gettext/mkinstalldirs mkinstalldirs +fi +intldir="$try/gettext/intl" +if test ! -d intl; then + mkdir intl +fi +olddir=`pwd` +cd $intldir +for file in *; do + if test $file != COPYING.LIB-2.0 && test $file != COPYING.LIB-2.1; then + rm -f $olddir/intl/$file + cp $intldir/$file $olddir/intl/ + fi +done +cp -f $try/gettext/po/Makefile.in.in $olddir/po/ +cd $olddir +if test -f intl/plural.c; then + sleep 2 + touch intl/plural.c +fi + +# ------ END GETTEXT ------ + + +echo running $ACLOCAL... +$ACLOCAL $ACLOCAL_FLAGS +if test "$?" != "0"; then + echo aclocal failed, stopping. + exit 2 +fi +echo running libtoolize... +libtoolize --force +if test "$?" != "0"; then + echo libtoolize failed, stopping. + exit 3 +fi +echo running autoheader... +autoheader +if test "$?" != "0"; then + echo autoheader failed, stopping. + exit 4 +fi +echo running $AUTOMAKE... +$AUTOMAKE -a --foreign +if test "$?" != "0"; then + echo automake failed, stopping. + exit 5 +fi +echo running autoconf... +autoconf +if test "$?" != "0"; then + echo autoconf failed, stopping. + exit 6 +fi + +echo if no errors occured, run ./configure --enable-maintainer-mode +exit 0 + +#autogen.sh generates: +# aclocal.m4 Makefile.in config.guess config.sub ltmain.sh +# configure install-sh missing mkinstalldirs depcomp +# +#configure generates: +# config.status libtool Makefile.in diff --git a/config.h.w32 b/config.h.w32 new file mode 100644 index 00000000..24bd394b --- /dev/null +++ b/config.h.w32 @@ -0,0 +1,12 @@ +#define LOCALEDIR "./locale" +#define ENABLE_NLS +#define USE_GMODULE +#define USE_PLUGIN +#define PACKAGE_NAME "xchat" +#define PACKAGE_VERSION "2.8.8-Unofficial" +#define XCHATLIBDIR "." +#define XCHATSHAREDIR "." +#define OLD_PERL +#ifndef USE_IPV6 +#define socklen_t int +#endif diff --git a/config.rpath b/config.rpath new file mode 100644 index 00000000..3f1bef34 --- /dev/null +++ b/config.rpath @@ -0,0 +1,571 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2005 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +cc_basename=`echo "$CC" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + darwin*) + case "$cc_basename" in + xlc*) + wl='-Wl,' + ;; + esac + ;; + mingw* | pw32* | os2*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + newsos6) + ;; + linux*) + case $cc_basename in + icc* | ecc*) + wl='-Wl,' + ;; + pgcc | pgf77 | pgf90) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + esac + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + sco3.2v5*) + ;; + solaris*) + wl='-Wl,' + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + case "$host_os" in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we cannot use + # them. + ld_shlibs=no + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sunos4*) + hardcode_direct=yes + ;; + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = yes; then + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if test "$GCC" = yes ; then + : + else + case "$cc_basename" in + xlc*) + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd1*) + ld_shlibs=no + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10* | hpux11*) + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=no + ;; + ia64*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + *) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + openbsd*) + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + sco3.2v5*) + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4.2uw2*) + hardcode_direct=yes + hardcode_minus_L=no + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + ;; + sysv5*) + hardcode_libdir_flag_spec= + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. +libname_spec='lib$name' +case "$host_os" in + aix3*) + ;; + aix4* | aix5*) + ;; + amigaos*) + ;; + beos*) + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32*) + shrext=.dll + ;; + darwin* | rhapsody*) + shrext=.dylib + ;; + dgux*) + ;; + freebsd1*) + ;; + kfreebsd*-gnu) + ;; + freebsd*) + ;; + gnu*) + ;; + hpux9* | hpux10* | hpux11*) + case "$host_cpu" in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux*) + ;; + knetbsd*-gnu) + ;; + netbsd*) + ;; + newsos6) + ;; + nto-qnx*) + ;; + openbsd*) + ;; + os2*) + libname_spec='$name' + shrext=.dll + ;; + osf3* | osf4* | osf5*) + ;; + sco3.2v5*) + ;; + solaris*) + ;; + sunos4*) + ;; + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + ;; + sysv4*MP*) + ;; + uts4*) + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' </dev/null` + if test "_$PERL_CFLAGS" = _ ; then + AC_MSG_RESULT([not found, building without perl.]) + perl=no + else + PERL_LDFLAGS=`$perlpath -MExtUtils::Embed -e ldopts |$sedpath 's/-lgdbm //'` + PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-ldb //'` + PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lndbm //'` + if test "$system" = "Linux"; then + PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lnsl //'` + PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lposix //'` + fi + PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lc //'` + AC_MSG_RESULT(ok) + +# oldLIBS=$LIBS +# LIBS="$LIBS $PERL_LDFLAGS" +# AC_CHECK_FUNC(eval_pv) +# AC_CHECK_FUNC(call_pv) +# LIBS=$oldLIBS + + AC_MSG_CHECKING(for perl >= 5.8.0) + PERL_VER=`$perlpath -e 'print $]>= 5.008?"yes":"no"'` + if test "$PERL_VER" = "yes"; then + AC_MSG_RESULT(yes) + AC_MSG_CHECKING(if perl plugin will be backward compatible) + if test "$perl_old" = "yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(OLD_PERL) + else + AC_MSG_RESULT(no) + fi + else + AC_MSG_RESULT(no) + echo "perl version too old, building without perl." + perl=no + fi + fi +fi + +dnl ********************************************************************* +dnl ** PYTHON *********************************************************** +dnl ********************************************************************* + +if test "$python" = yes; then + AC_PATH_PROG(pythonpath, python2) + if test "_$pythonpath" = _ ; then + AC_PATH_PROG(pythonpath, python) + fi + if test "_$pythonpath" = _ ; then + python=no + else + AC_MSG_CHECKING(Python version) + changequote(<<, >>)dnl + PY_VER=`$pythonpath -c 'import distutils.sysconfig; print distutils.sysconfig.get_config_vars("VERSION")[0];'` + PY_LIB=`$pythonpath -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib(standard_lib=1);'` + PY_INC=`$pythonpath -c 'import distutils.sysconfig; print distutils.sysconfig.get_config_vars("INCLUDEPY")[0];'` + $pythonpath -c "import sys; map(int,sys.version[:3].split('.')) >= [2,2] or sys.exit(1)" + changequote([, ])dnl + AC_MSG_RESULT($PY_VER) + if test "$?" != "1"; then + AC_MSG_CHECKING(Python compile flags) + PY_PREFIX=`$pythonpath -c 'import sys; print sys.prefix'` + PY_EXEC_PREFIX=`$pythonpath -c 'import sys; print sys.exec_prefix'` + if test -f $PY_INC/Python.h; then + PY_LIBS="-L$PY_LIB/config -lpython$PY_VER -lpthread -lutil" + PY_CFLAGS="-I$PY_INC" + AC_MSG_RESULT(ok) + else + python=no + AC_MSG_RESULT([Can't find Python.h]) + fi + else + echo "Python too old. Only 2.2 or above is supported." + python=no + fi + fi +fi + +dnl ********************************************************************* +dnl ** TCL ************************************************************** +dnl ********************************************************************* + +AC_MSG_CHECKING(for location of tclConfig.sh) +dirs="$tcl /lib /usr/lib /usr/tcl/lib /usr/lib/tcl8.4 /usr/local/lib /usr/local/tcl-8.4/lib /usr/local/tcl/lib /opt/lib /usr/lib/tcl8.3" +found=0 +if test "$tcl" != "no"; then + tcl=no + for try in $dirs; do + if test -f $try/tclConfig.sh; then + found=1 + . $try/tclConfig.sh + TCL_LIBS="$TCL_LIB_SPEC $TCL_LIBS" + TCL_CFLAGS="-I${TCL_PREFIX}/include $TCL_INCLUDE_SPEC" + tcl=yes + AC_MSG_RESULT($try/tclConfig.sh) + break + fi + done + if test "$found" -eq 0 ; then + AC_MSG_RESULT([tclConfig.sh not found - use the --enable-tcl option]) + fi +fi + +dnl ********************************************************************* +dnl ** IPv6 ************************************************************* +dnl ********************************************************************* + +dnl purely for Solaris +AC_CHECK_FUNC(select, , + AC_CHECK_LIB(socket, select, , + AC_CHECK_LIB(nsl, select, , + AC_CHECK_LIB(inet, select, , + AC_CHECK_LIB(cposix, select, , + AC_CHECK_LIB(net, select, , + AC_MSG_WARN(i can not find select. you might need to help me))))))) +AC_CHECK_LIB(socket, select) + +if test "$ipv6" = yes; then + AC_CHECK_FUNCS(getaddrinfo, have_getaddrinfo=yes) + AC_MSG_CHECKING(whether to enable IPv6 support) + if test "$have_getaddrinfo" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(USE_IPV6) + else + ipv6=no + AC_MSG_RESULT(no) + fi +fi + +dnl ********************************************************************* +dnl ** OPENSSL ********************************************************** +dnl ********************************************************************* + +retry=no +if test "$openssl" != no; then + AC_PATH_PROG(pkgconfigpath, pkg-config) + AC_MSG_CHECKING(for openssl through pkg-config) + if $pkgconfigpath openssl --exists; then + CPPFLAGS="$CPPFLAGS `$pkgconfigpath openssl --cflags`" + LIBS="$LIBS `$pkgconfigpath openssl --libs`" + AC_DEFINE(USE_OPENSSL) + AC_MSG_RESULT(yes) + openssl=yes + else + AC_MSG_RESULT(no) + retry=yes + fi +fi + +if test "$retry" = "yes"; then + unset openssl_path ac_cv_lib_ssl_SSL_new ac_cv_header_openssl_ssl_h + if test "$openssl" != yes; then + openssl_path=$openssl + fi + openssl=no + SAVED_LIBS=$LIBS + LIBS="$LIBS -lcrypto" + if test -n "$openssl_path"; then + LIBS="-L$openssl_path/lib $LIBS" + fi + AC_CHECK_LIB(ssl, SSL_new, have_openssl=yes) + LIBS=$SAVED_LIBS + if test "$have_openssl" = yes; then + SAVED_CPPFLAGS=$CPPFLAGS + if test -n "$openssl_path"; then + CPPFLAGS="-I$openssl_path/include $CPPFLAGS" + fi + AC_CHECK_HEADERS(openssl/ssl.h, have_openssl_h=yes) + if test "$have_openssl_h" = yes; then + openssl=yes + AC_DEFINE(USE_OPENSSL) + LIBS="$LIBS -lssl -lcrypto" + if test -n "$openssl_path"; then + LIBS="-L$openssl_path/lib $LIBS" + fi + else + CPPFLAGS=$SAVED_CPPFLAGS + fi + fi +fi + +dnl ********************************************************************* +dnl ** LIBPROXY ********************************************************* +dnl ********************************************************************* + +PKG_CHECK_MODULES([LIBPROXY], [libproxy-1.0], [libproxy=1], [libproxy=0]) +AC_DEFINE_UNQUOTED([USE_LIBPROXY], [$libproxy], [Use libproxy]) + +dnl ********************************************************************* +dnl ** PLUGIN *********************************************************** +dnl ********************************************************************* + +if test "$plugin" = yes; then + AC_CHECK_FUNCS(dlopen, have_dl=yes) + if test "$have_dl" != yes; then + AC_CHECK_LIB(dl, dlopen, have_dl=yes) + if test "$have_dl" = yes; then + LIBS="$LIBS -ldl" + fi + fi + if test "$have_dl" = yes; then + AC_DEFINE(USE_PLUGIN) + AC_PATH_PROG(pkgconfigpath, pkg-config) + dnl we just need the -Wl,--export-dynamic, but not -lgmodule-2.0 + RDYNAMIC_FLAGS="`$pkgconfigpath gmodule-2.0 --libs | $sedpath 's/ -lgmodule-2.0//'`" + LIBS="$LIBS $RDYNAMIC_FLAGS" + if test "$LD" = ""; then + VS="`ld --help | grep version-script 2> /dev/null`" + else + VS="`$LD --help | grep version-script 2> /dev/null`" + fi + if test "$VS" != ""; then + GUI_LIBS="$GUI_LIBS -Wl,--version-script,\$(srcdir)/../version-script" + fi + else + plugin=no + fi +fi + +dnl ####################################################################### +dnl # Check for DBUS libraries +dnl ####################################################################### + +if test "x$dbus" = "xyes" ; then + PKG_CHECK_MODULES(DBUS, [dbus-1 >= 0.60 dbus-glib-1 >= 0.60 gthread-2.0], dbus=yes, [ + AC_MSG_RESULT(no) + dbus=no + ]) + AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool, no) + AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal, no) + if test "x$DBUS_BINDING_TOOL" = "xno" || test "x$GLIB_GENMARSHAL" = "xno" || test "x$dbus" = "xno" ; then + dbus="no" + else + COMMON_LIBS="$COMMON_LIBS $DBUS_LIBS $LIBPROXY_LIBS" + COMMON_CFLAGS="$COMMON_CFLAGS $DBUS_CFLAGS" + AC_DEFINE(USE_DBUS) + AS_AC_EXPAND(DATADIR, $datadir) + + DBUS_SERVICES_DIR="$DATADIR/dbus-1/services" + AC_SUBST(DBUS_SERVICES_DIR) + AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for DBUS is]) + fi +fi + +dnl ********************************************************************* +dnl ** SPELL ************************************************************ +dnl ********************************************************************* + +if test "$spell" = "gtkspell" ; then + PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, [], [ + AC_MSG_RESULT(no) + spell=no + ]) + if test "$spell" != "no" ; then + GUI_LIBS="$GUI_LIBS $GTKSPELL_LIBS" + GUI_CFLAGS="$GUI_CFLAGS $GTKSPELL_CFLAGS" + AC_DEFINE(USE_GTKSPELL) + fi +fi + +if test "$spell" = "libsexy" ; then + PKG_CHECK_MODULES([LIBSEXY], [libsexy >= 0.1.8], libsexy=yes, AC_MSG_RESULT(no)) + if test "$libsexy" = "yes" ; then + GUI_LIBS="$GUI_LIBS $LIBSEXY_LIBS" + GUI_CFLAGS="$GUI_CFLAGS $LIBSEXY_CFLAGS" + AC_DEFINE(USE_LIBSEXY) + else + dnl use builtin static one + spell="static" + fi +fi + +if test "$spell" = "static" ; then + AC_DEFINE(USE_LIBSEXY) +fi + +dnl ********************************************************************* +dnl ** CONDITIONALS ***************************************************** +dnl ********************************************************************* + +AM_CONDITIONAL(USE_OPENSSL, test "x$openssl" = "xyes") +AM_CONDITIONAL(USE_LIBSEXY, test "x$spell" = "xstatic") +AM_CONDITIONAL(DO_TEXT, test "x$textfe" = "xyes") +AM_CONDITIONAL(DO_GTK, test "x$gtkfe" = "xyes") +AM_CONDITIONAL(DO_PERL, test "x$perl" = "xyes") +AM_CONDITIONAL(DO_PYTHON, test "x$python" = "xyes") +AM_CONDITIONAL(DO_TCL, test "x$tcl" = "xyes") +AM_CONDITIONAL(DO_PLUGIN, test "x$plugin" = "xyes") +AM_CONDITIONAL(USE_DBUS, test "x$dbus" = "xyes") +AM_CONDITIONAL(DO_GCONF, test "x$GCONFTOOL" != "xno") + +dnl ********************************************************************* +dnl ** SOCKS5 *********************************************************** +dnl ********************************************************************* + +if test "$socks" = yes; then + socks=no + AC_CHECK_LIB(socks5, SOCKSconnect, have_socks=yes) + if test "$have_socks" = yes; then + AC_CHECK_HEADERS(socks.h, have_socks_h=yes) + if test "$have_socks_h" = yes; then + socks=yes + AC_DEFINE(SOCKS) + LIBS="$LIBS -lsocks5" + fi + fi +fi + +dnl ********************************************************************* +dnl ** MS PROXY ********************************************************* +dnl ********************************************************************* + +have_ntlm="no" +if test "x$ntlm" = "xyes" ; then + have_ntlm="no" + AC_CHECK_LIB(ntlm, ntlm_smb_encrypt, have_ntlm=yes) + if test "$have_ntlm" = yes; then + LIBS="$LIBS -lntlm" + AC_DEFINE(USE_MSPROXY) + fi +fi + +dnl ********************************************************************* +dnl ** XShm ************************************************************* +dnl ********************************************************************* + +if test "$shm" = yes; then + oldl=$LIBS + oldc=$CPPFLAGS + LIBS="$LIBS `$pkgconfigpath --libs-only-L xft`" + CPPFLAGS="$CPPFLAGS `$pkgconfigpath --cflags-only-I xft`" + shm=no + AC_CHECK_LIB(Xext, XShmAttach, shm=yes) + if test "$shm" = yes; then + shm=no + AC_CHECK_HEADERS(sys/ipc.h, shm=yes) + if test "$shm" = yes; then + shm=no + AC_CHECK_HEADERS(sys/shm.h, shm=yes) + fi + fi + + LIBS=$oldl + if test "$shm" = yes; then + GUI_LIBS="$GUI_LIBS `$pkgconfigpath --libs-only-L xft` -lX11 -lXext" + AC_DEFINE(USE_SHM) + else + CPPFLAGS=$oldc + fi +fi + +dnl ********************************************************************* +dnl ** MMX ************************************************************** +dnl ********************************************************************* + +dnl we don't need mmx on *this* machine, just i386, because +dnl it's checked at runtime. +if test "$mmx" = "yes"; then + case $host_cpu in + i386|i486|i586|i686|i786|k6|k7) + mmx=yes + ;; + *) + mmx=no + esac + if test "$system" = "OpenBSD"; then + dnl openbsd fails because mmx_cmod doesn't prefix its symbols with underscore. + dnl xtext.o: Undefined symbol `_shade_ximage_15_mmx' referenced from text segment + mmx=no + fi + if test "$mmx" = "yes"; then + AC_DEFINE(USE_MMX) + fi +fi + +AM_CONDITIONAL(USE_MMX, test "$mmx" = "yes") + +dnl ********************************************************************* +dnl ** GCC FLAGS ******************************************************** +dnl ********************************************************************* + +dnl Only use -Wall and -pipe if we have gcc +if test "x$GCC" = "xyes"; then + if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then + CFLAGS="$CFLAGS -Wall" + fi + if test "$system" = "Linux" -o "$system" = "FreeBSD"; then + if test -z "`echo "$CFLAGS" | grep "\-pipe" 2> /dev/null`" ; then + CFLAGS="$CFLAGS -pipe" + fi + fi + if test -z "`echo "$CFLAGS" | grep "\-g " 2> /dev/null`" ; then + CFLAGS="$CFLAGS -g" + fi +fi + +dnl does this compiler support -Wno-pointer-sign ? +AC_MSG_CHECKING([if gcc accepts -Wno-pointer-sign ]) + +safe_CFLAGS=$CFLAGS +CFLAGS="-Wno-pointer-sign" + +AC_TRY_COMPILE(, [ +int main () { return 0 ; } +], +[ +no_pointer_sign=yes +AC_MSG_RESULT([yes]) +], [ +no_pointer_sign=no +AC_MSG_RESULT([no]) +]) +CFLAGS=$safe_CFLAGS + +if test x$no_pointer_sign = xyes; then + CFLAGS="$CFLAGS -Wno-pointer-sign" +fi + +dnl does this compiler support -funsigned-char ? +AC_MSG_CHECKING([if gcc accepts -funsigned-char ]) + +safe_CFLAGS=$CFLAGS +CFLAGS="-funsigned-char" + +AC_TRY_COMPILE(, [ +int main () { return 0 ; } +], +[ +unsigned_char=yes +AC_MSG_RESULT([yes]) +], [ +unsigned_char=no +AC_MSG_RESULT([no]) +]) +CFLAGS=$safe_CFLAGS + +if test x$unsigned_char = xyes; then + CFLAGS="$CFLAGS -funsigned-char" +fi + +dnl ********************************************************************* +dnl ** FUNCTIONS/LIBS/CFLAGS ******************************************** +dnl ********************************************************************* + +AC_MSG_CHECKING(for modern sigaction) +dnl libc5 on linux and FreeBSD 3.x doesn't have siginfo_t +dnl and the sa_sigation field. +AC_TRY_COMPILE( + [#include ], + [struct sigaction act; + siginfo_t *si; + act.sa_sigaction = 0;], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(USE_SIGACTION) + ], + AC_MSG_RESULT(no)) + +AC_PATH_PROG(gdkpixbufcsourcepath, gdk-pixbuf-csource) +AC_SUBST(gdkpixbufcsourcepath) +if test "$gtkfe" != no -a "_$gdkpixbufcsourcepath" = _; then + AC_MSG_ERROR("Cannot find gdk-pixbuf-csource: Install GTK+ 2.0\!") +fi + +dnl if we don't have this, use g_snprintf instead +AC_CHECK_FUNCS(snprintf vsnprintf memrchr strtoull) + +AC_CHECK_FUNC(gethostbyname, , + AC_CHECK_LIB(resolv, gethostbyname, , + AC_CHECK_LIB(nsl, gethostbyname))) + +AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(nsl, gethostname)) + +dnl necessary for IRIX +AC_CHECK_HEADERS(strings.h) + +dnl Check for type in sys/socket.h - from Squid source (GPL) +AC_CACHE_CHECK(for socklen_t, ac_cv_type_socklen_t, [ +AC_EGREP_CPP([socklen_t[^a-zA-Z_0-9]], [#include +#include +#if STDC_HEADERS +#include +#include +#endif], +ac_cv_type_socklen_t=yes, +ac_cv_type_socklen_t=no) +]) +if test $ac_cv_type_socklen_t = no; then + AC_DEFINE(socklen_t, int) +fi + +dnl Mac OS X and Darwin use lookupd, which caches DNS queries by default +AC_EGREP_CPP(lookupd, dnl +[#if (defined(__APPLE__) && defined(__MACH__)) + lookupd +#endif], AC_DEFINE([LOOKUPD],1,[Define to 1 if the system uses lookupd])) + +dnl freebsd needs this +LIBS="$LIBS $INTLLIBS" +CFLAGS="$CFLAGS $CPPFLAGS" + +GUI_LIBS="$GUI_LIBS $COMMON_LIBS" + +dnl make these visible to all Makefiles +AC_SUBST(GUI_LIBS) +AC_SUBST(GUI_CFLAGS) +AC_SUBST(COMMON_LIBS) +AC_SUBST(COMMON_CFLAGS) +AC_SUBST(PERL_CFLAGS) +AC_SUBST(PERL_LDFLAGS) +AC_SUBST(PY_CFLAGS) +AC_SUBST(PY_LIBS) +AC_SUBST(TCL_LIBS) +AC_SUBST(TCL_CFLAGS) +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) + + +PLUGIN_INCLUDES='-I$(top_srcdir)/plugins' +AC_SUBST(PLUGIN_INCLUDES) + +dnl for plugin.c and pixmaps.c +test "x$prefix" = xNONE && prefix="$ac_default_prefix" +test "x$exec_prefix" = xNONE && exec_prefix="$prefix" + +AC_DEFINE_UNQUOTED(PREFIX, "${prefix}") + +XCHATLIBDIR=`eval echo ${libdir}/xchat` +AC_DEFINE_UNQUOTED(XCHATLIBDIR, "$XCHATLIBDIR") + +XCHATSHAREDIR=`eval echo ${datadir}` +AC_DEFINE_UNQUOTED(XCHATSHAREDIR, "$XCHATSHAREDIR") + +dnl for plugins/xxx/Makefile.am +xchatlibdir=${libdir}/xchat +AC_SUBST(xchatlibdir) + +AC_OUTPUT([ +Makefile +src/Makefile +src/common/Makefile +src/common/dbus/Makefile +src/fe-text/Makefile +src/fe-gtk/Makefile +src/pixmaps/Makefile +plugins/Makefile +plugins/python/Makefile +plugins/perl/Makefile +plugins/tcl/Makefile +intl/Makefile +po/Makefile.in +]) + +echo +echo xchat $VERSION +echo +echo Building GTK+ Interface .... : $gtkfe +echo Building TEXT Interface .... : $textfe +echo +echo PLUGINS: Perl: $perl Python: $python TCL: $tcl +echo +echo mmx tinting ......... : $mmx\ spelling .............. : $spell +echo XShm tinting ........ : $shm\ plugin interface ...... : $plugin +if test "$xft" = no; then + echo text backend ........ : pango\ nls/gettext ........... : $USE_NLS +else + echo text backend ........ : xft\ nls/gettext ........... : $USE_NLS +fi +echo openssl support ..... : $openssl\ ipv6 support .......... : $ipv6 +echo dbus support ........ : $dbus\ msproxy ntlm \(ISA\) .... : $have_ntlm +echo +echo The binary will be installed in $prefix/bin +echo + +if test "$gtkfe" = no; then + echo Warning: The GTK \(GUI\) frontend will not be built. + echo +fi + +if test "$spell" = "gtkspell"; then + echo Warning: GTK SPELL is not the recommended spelling library. + echo +fi + +echo configure complete, now type \'make\' and pray. +echo diff --git a/faq.html b/faq.html new file mode 100644 index 00000000..4f4c1cde --- /dev/null +++ b/faq.html @@ -0,0 +1,537 @@ + + +XCHAT FAQ + + + + +

X-Chat 2.8 Frequently Asked Questions

+ +

1. Section One: Compiling and Installing.

+

+1. I get this error: /bin/sh: no: command not found +

+2. How do I compile X-Chat on my Sun OS system? +

+

+ +

2. Section Two: Using X-Chat.

+

+1. How do I enable identd in X-Chat? (How do I get rid of the ~ in front of my username?) +

+2. How do I auto join more than one channel with keys? +

+3. How do I autoconnect and join a channel when X-Chat loads? +

+4. How do I cut and paste in X-Chat? +

+5. How do I connect through a proxy? +

+6. How do I show @ and + in front of nicknames that are Op and Voice when they talk? +

+7. How do I change the Op and Voice userlist icons and Tree View icons? +

+8. How do I set different ban types? +

+9. Why can't I see accented-letters/umlauts/upper-ascii-chars in X-Chat? +

+10. Why does the timestamp overlap some nicknames? +

+11. How do I turn on Conference mode where I will not see join or part messages? +

+12. How can I run the /dccserver command? +

+13. Why doesn't DCC send work behind a router (IPNat/ADSL)? +

+14. How do I execute multiple commands in one line? +

+15. How do I enable Emacs key bindings in XChat? +

+16. I get this error: "Unknown file type abc.yz. Maybe you need to install the Perl or Python plugin?" +

+17. How do I play sound files on certain events? +

+18. How do I auto-load scripts at startup? +

+19. How do I minimize X-Chat to the System Tray (Notification Area)? +

+20. Can I select and copy text with the time stamps? +

+21. What's the deal with opening URLs in XChat on Linux/Unix? +

+22. Where are the log files saved to? +

+23. How do I rotate log files every so often? +

+24. How do I enable graphical smilies (emoticons)? +

+

+ +

3. Section Three: Contributions, Development and Bugs.

+

+1. Why does X-Chat leak so much memory? +

+2. My copy of X-Chat crashes, what can I do? +

+3. Can I write a new language translation for X-Chat? +

+ +

+ +

1. Section One: Compiling and Installing.

+ +

1. I get this error: /bin/sh: no: command not found

+

+If you get an error something like: +

+
+Making all in po
+make[2]: Entering directory `/home/zed/xchat/files/xchat-1.8.7/po'
+file=./`echo ca | sed 's,.*/,,'`.gmo \
+  && rm -f $file && PATH=../src:$PATH no -o $file ca.po
+/bin/sh: no: command not found
+make[2]: *** [ca.gmo] Error 127
+make[2]: Leaving directory `/home/zed/xchat/files/xchat-1.8.7/po'
+make[1]: *** [all-recursive] Error 1
+make[1]: Leaving directory `/home/zed/xchat/files/xchat-1.8.7'
+make: *** [all-recursive-am] Error 2
+
+

+It means you don't have GNU gettext installed. There are two solutions: +

+
    +
  • Install GNU gettext and try again.
  • +
  • Use ./configure --disable-nls. This will disable foreign +language support and all menus and GUI will be in English only.
  • +
+ +

2. How do I compile X-Chat on my Sun OS system?

+

+ X-Chat uses GNU gettext which in turn requires gmake, either install that + and or use ./configure --disable-nls with Sun's own make. +

+ +

2. Section Two: Using X-Chat.

+ +

1. How do I enable identd in X-Chat?

+

+UNIX:
+ Identd isn't actually apart of X-Chat. You will need to download and install + your own ident server. Most distributions, including Fedora, come with an + ident server program called oidentd. Make sure it is enabled in + /etc/xinetd.conf or read you distribution's documentation. + + As an alternative, you can try this experimental identd server: xchat_auth + +

WINDOWS:
+ The win32 version of X-Chat comes with a built-in identd server. It is + enabled by default, but can be disabled with /set identd 0. +

+ +

2. How do I auto join more than one channel with keys?

+

+ In the Server list's channel column enter multiple channels and separate + them by commas, eg: "#linux,#warez,#chat". Do not put spaces between the + channels. If the channels also have keys (passwords), then the syntax is: + "#channel1,#channel2,#channel3 key1,key2,key3" +

+

+ Example: If you want to join #abc and #talk without keys, but #linux with + a key of "secret", you would enter: "#linux,#abc,#talk secret". +

+ +

3. How do I autoconnect and join a channel when X-Chat loads?

+

+In the Server list, select the Network you want to auto-connect to, click Edit +and turn ON the "Auto connect to this network at startup" checkbox. +

+ +

4. How do I cut and paste in X-Chat?

+

+It's exactly the same as any other X application. You simply mark the text +you want, and then press middle mouse button to paste (if you only have a +2 button mouse, press left and right buttons at once). +

+ +

5. How do I connect through a proxy?

+

+Go to the menus, Settings -> Preferences -> Network Setup and fill in the requested +information there. Authentication (using a username and password) is +only supported for HTTP and Socks5. +

+ +

6. How do I show @ and + in front of nicknames that are Op and Voice when they talk?

+

+To display @ and + characters next to nicknames as they talk, do the following: +

+

+In the menus, open up Settings -> Advanced -> Text Events. Find the +Channel Message event in the list. The $3 code can be inserted to +print the user's mode-character (e.g. @ or +). For example, you might want +to change the default: + +

%C18%H<%H$4$1%H>%H%O$t$2

To: +

%C18%H<%H$4$3$1%H>%H%O$t$2 +

Don't forget to press Enter, so the changes take effect in the +list at the top of the window. +

+ +

7. How do I change the Op and Voice userlist icons and Tree View icons?

+

+Unix/Linux +
The default icons are hard coded (compiled) in. You can override them by creating +some PNG files in ${PREFIX}/share/xchat. ${PREFIX} is usually /usr, so that +would translate to /usr/share/xchat. If you compiled from source tarball without +specifying a prefix, it will be /usr/local instead. +
+
+Windows +
Your own custom icons can be placed in C:\Program Files\XChat\Icons. Image format +may be PNG or ICO. PNG support on Windows 2000 may require installing GDI+, but it's +standard on XP or newer. +

+ +
+ + + + + + + + + + + + + + + + + + +
NameDescription
op.pngUserlist: Op
hop.pngUserlist: Half-Op
voice.pngUserlist: Voice
red.pngUserlist: Owner
purple.pngUserlist: Founder
server.pngTree: Server
channel.pngTree: Channel
dialog.pngTree: Dialog/Query
util.pngTree: Utility (Channel List, DCC etc)
message.pngTray: Message
highlight.pngTray: Highlighted Message
fileoffer.pngTray: DCC
xchat.pngMain XChat icon
+
+ +
Tree View icons: Type /set tab_icons 1 to enable them and then restart XChat. +
+ +

8. How do I set different ban types?

+

+ Three ways: +

+
    +
  • + Right click the nickname in the userlist, and choose a ban type from the + "Kick/Ban" submenu. +
  • +
  • + You can also do it manually: + + /ban <nick> <ban type> + + where the <ban type> is a number from 0 to 3. +
  • + +
  • + /set irc_ban_type <ban type> + sets the default ban type to use for all bans. The different types are: + +
      +
    • 0 *!*@*.host
    • +
    • 1 *!*@domain
    • +
    • 2 *!*user@*.host
    • +
    • 3 *!*user@domain
    • +
    + +
  • +
+ +

9. Why can't I see accented-letters/umlauts/upper-ascii-chars in X-Chat?

+

+Refer to http://xchat.org/encoding/.
+Note: Log files are always written in UTF-8/Unicode. +

+ +

10. Why does the timestamp overlap some nicknames?

+

+Some networks allow very long nicknames (up to 32 letters). It can be annoying to have +the separator bar move too far to the right, just for one long nick. Therefore, it has +a set limit for the distance it will move to the right. If you use a large font, you +may need to adjust this distance. It is set in pixels, for example: +

+
+      /set text_max_indent 320
+
+ +

+Once you adjust this setting high enough, overlapping timestamps and nicknames should +not occur. The adjustment will not take effect immediately, a restart may be needed. +

+ +

11. How do I turn on Conference mode where I will not see join or part messages?

+

+Right-click on the tab you want to change. In the submenu of the channel +name, there's a toggle-item "Show join/part messages", simply turn this off. +

If you want to turn this option on globally, type:

+
/set irc_conf_mode 1
+

Then all channels you join after setting this will start with "Show join/part messages" turned off.

+ +

12. How can I run the /dccserver command?

+

+In short you can not do this (easily). This is a mIRC only proprietary feature +that is quite nonstandard. There is no code for doing this, mainly because +/dccserver runs on port 59 which in turn would require running X-Chat as +root. Why do you need this anyway? Just use normal DCC. +

+Unofficial unix patches are available here. +

Update: DCC Server feature has been added in the official Windows release 2.4.1b. +

+ +

13. Why doesn't DCC send work behind a router (IPNat/ADSL)?

+

+ If you are behind a IP-NAT or ADSL router, you will most likely have + an address like 192.168.0.1. This address is not usable on the Internet, and + must be translated. +

+ When offering a DCC file, xchat will tell the receiver your address. If it says + 192.168.0.1, the receiver will not be able to connect. One way to make it send + your "real" address is to enable the "Get my IP from IRC Server" option in xchat. + This option is available in Preferences -> File Transfers. When you turn it + ON, you will have to re-login to the server before it'll take effect. +

+ You will also need to forward some ports for use in DCC send. You may pick almost + any port range you wish, for example, in xchat set: +

+
		First DCC send port: 4990
+		 Last DCC send port: 5000
+
+

+ This will allow you to send up to ten files at the same time, which should be plenty + for most people. Lastly, configure your router/modem to forward ports 4990-5000 to + your PC's address. You'll have to consult your router/modem's manual on how to do this. +

+ +

14. How do I execute multiple commands in one line?

+

+ There are three ways to do this: +

+
    +
  • /LOAD -e <textfile>, where <textfile> is a full pathname to a file +containing commands on each line.
  • +
  • +Separate your commands with CTRL-SHIFT-u-a (CTRL-SHIFT-a on older GTK+ and Windows). This will appear as a little box with numbers on it.
  • +
  • You can create two UserCommands, with the same name, and then execute +the UserCommand. It will be executed in the same order as it's written +in the UserCommands GUI.
  • +
+ +

15. How do I enable Emacs key bindings in XChat?

+

+The standard Emacs key bindings, such as CTRL-w, CTRL-u etc, are supported by +GTK+ 2.0, but normally disabled. If you run Gnome 2, you can re-enable them in +your Gnome menu under: Preferences -> Keyboard Shortcuts. +

+

+Note: This doesn't work in the latest Gnome (2.8 and newer). In this case, you need +to run "gconf-editor", and directly change the key /desktop/gnome/interface/gtk_key_theme +from "Default" to "Emacs". Then you need to re-start XChat. +

+

+If you don't use Gnome 2, but still want Emacs key bindings, it's beyond the +scope of this document. You might find some hints here: +GTK+ 2.4.0 release notes. +

+ +

16. I get this error: "Unknown file type abc.yz. Maybe you need to install the Perl or Python plugin?"

+

+If you get this error when trying to load a Perl or Python script, it means +the plugin for running those scripts isn't loaded. +

+
    +
  • The Perl, Python and TCL plugins come with XChat in the same archive.
  • +
  • During ./configure, it will check for Perl, Python and TCL libs and headers, you should check if it failed there.
  • +
  • The plugins directory can be found by issuing the shell command +
    xchat -p
    +
  • +
  • All *.so files are auto-loaded at startup (*.dll on Windows).
  • +
  • If you downloaded a binary package, maybe the packager decided to exclude the Perl or Python plugins.
  • +
+ +

17. How do I play sound files on certain events?

+

+In the menus, go to: Settings > Preferences > Sound. +Select the event you want to make a sound on, then type in a +sound filename (or use the Browse button). +

+ +

18. How do I auto-load scripts at startup?

+

+You just have to place the scripts into XChat's data directory. XChat +will auto-load scripts if they have the right extension .e.g If a filename +ends in .pl, it will be loaded as a Perl script. +This data directory is different on each platform: +

+Windows +

+It depends on your version of Windows and where it stores the +Application Data folder. On Windows XP it is usually: +

+C:\Documents and Settings\username\Application Data\X-Chat 2\ +
or simply: +
+C:\Program Files\XChat\Plugins\ +


+UNIX +

+~/.xchat2/ +Where "~" represents your home directory i.e.: $HOME/.xchat2/ +

+ +

19. How do I minimize X-Chat to the System Tray (Notification Area)?

+

+There are two plugins available that allow this: +
Unix: SysTray Plugin +
Windows: xTray +

+

+Note that XChat 2.8.0+ has its own tray feature, but you can disable it +in Settings > Preferences > Alerts and still run these plugins, if you prefer. +

+ +

20. Can I select and copy text with the time stamps?

+

+Yes, but this requires at least XChat 2.6.3. Simply hold down SHIFT while marking +the text and the time stamps will be included. +

+ +

21. What's the deal with opening URLs in XChat on Unix/Linux?

+

+Right-clicking on a URL and selecting Open Link in Browser will open the link +in your "preferred browser". In Gnome, your preferred browser can be changed in System > Preferences > More Preferences > Preferred Applications. +

+Notes for 2.8.0 or newer: +

+Everything should just work automatically without any changes from you. Here's how the current +logic works: +

+ +
    +
  • First, it tries to run xdg-open, which is a universal URL handler from freedesktop.org. Most modern Linux desktops will have this now, or in the near future.
  • +
  • If xdg-open doesn't exist, it will try to detect a running Gnome or KDE desktop. This is done via the environment variables GNOME_DESKTOP_SESSION_ID and KDE_FULL_SESSION.
  • +
  • If Gnome is detected, it will execute: gnome-open <url>
  • +
  • If KDE is detected, it will execute: kfmclient exec <url>
  • +
+ +

+Notes for 2.6.8 or older: +

+If you're not using Gnome, e.g KDE or some other desktop environment, you're fresh out of luck! +
Note for Debian and Ubuntu: Integration with Gnome is broken on this distro! Please set +sensible-browser instead. We have no control over what the Debian packagers do, so complain +to them for this screw up. Example: +sudo update-alternatives --set x-www-browser /usr/bin/firefox + +

+More details +

+While holding down CTRL you can single left-click a URL to open it in your preferred browser. If you really want to change this to plain left-click you can type: /set gui_url_mod 0, provided you have XChat 2.6.6 or newer. +

+You can also add more items to the right-click menu in XChat: Settings > Advanced > URL Handlers. +
For example, you could add an entry like !firefox -a firefox -remote 'openURL(%s,new-tab)' +
But this kind of messing around shouldn't be necessary, it just works automatically in Gnome, KDE and Windows with 2.8.0+! +

+ +

22. Where are the log files saved to?

+

+UNIX +
+
~/.xchat2/xchatlogs/ +
where ~ represents your home directory. +
+
+
Windows +
+
Windows XP/2000: C:\Documents and Settings\username\Application Data\X-Chat 2\xchatlogs +
Windows Vista/7: C:\Users\username\AppData\Roaming\X-Chat 2\xchatlogs +

+ +

23. How do I rotate log files every so often?

+

+Requires: 2.6.1+ +

+By default settings, no rotation occurs, your log files will just keep getting larger. +

+Go to Settings > Preferences > Logging and change the log filename to any one of these: +

+
+ + + + + +
SettingExample filename that would be written
%Y-%m-%d/%n-%c.log 2006-12-30/FreeNode-#channel.log
%n/%Y-%m-%d/%c.logFreeNode/2006-12-30/#channel.log
%n/%c.logFreeNode/#channel.log (no rotation)
+
+

+%Y, %m and %d represents the current year, month and day respectively. %n is the +network name, e.g. "FreeNode" or "UnderNet", and finally, %c is the channel. In these +examples, a new log filename and folder would be created after midnight. +

+You can find more possibilities at http://xchat.org/docs/log/. +

+ +

24. How do I enable graphical smilies (emoticons)?

+

+This feature is only available in the official Windows XChat release. You have to +TICK this feature during installation. If you didn't do this, you can simply run +the installer again, and TICK the "Eye Candy Theme" when given the option. +

+If you want to use the graphical theme, but disable it just for smilies (i.e leave +it ON for things like Join/Part, Modes etc only), type this command and restart: +

+/set text_emoticons off +

+ +

3. Section Three: Contributions, Development and Bugs.

+ +

1. Why does X-Chat leak so much memory?

+

+The simple answer is, it doesn't! There are some GTK+ pixmap based themes around that +leak a lot of memory. Please try using a different theme and see if that resolves the +problem. X-Chat itself only allocates about 40kb of memory through malloc()! +

+ +

2. My copy of X-Chat crashes, what can I do?

+

+Firstly, make sure it's the latest stable version of X-Chat. Stable versions have +an EVEN middle number, e.g.: 2.8.0 or 2.8.1. Often late fixes are placed in this +directory: 2.8.x patches +

+ If you still experience crashes, you should consider running it through GDB. This + will help us find a fix quickly, and it's easy to do! See here. +

+ +

3. Can I write a new language translation for X-Chat?

+

+You sure can, but I don't accept translations directly. They must be done through the +Translation Project. +All the relevant information should be on that page. +

+ + + diff --git a/plugins/Make.plugin b/plugins/Make.plugin new file mode 100644 index 00000000..4a4c56fd --- /dev/null +++ b/plugins/Make.plugin @@ -0,0 +1,38 @@ +# Makefile stub for creating standalone plugin distributions. + +plugin_dist: pg_dist pg_dist/config.status + pgi=`cd $(srcdir)/.. && pwd`; cd pg_dist; \ + $(MAKE) $(AM_MAKEFLAGS) PLUGIN_INCLUDES=-I$$pgi distcheck dist + +pg_dist: pg_distdir pg_dist/configure.in pg_dist/install-sh + cd pg_dist \ + && libtoolize --copy --force --automake \ + && automake --copy --add-missing --foreign \ + && autoconf -l ../$(top_srcdir) + +pg_distdir: $(DISTFILES) + test -d pg_dist || mkdir pg_dist + for dfile in $(DISTFILES); do \ + test -f $$dfile && cp $$dfile pg_dist \ + || test -f $(srcdir)/$$dfile && cp $(srcdir)/$$dfile pg_dist; done + sed '/Make.plugin/d' < $(srcdir)/Makefile.am > pg_dist/Makefile.am + +pg_dist/configure.in: $(srcdir)/../plugin-conf.in + rm -f pg_dist/configure.in + test -f $(srcdir)/config.stub \ + && cat $(srcdir)/config.stub > pg_dist/configure.in || true + cat $(srcdir)/../plugin-conf.in | \ + sed 's%@PLUGIN_VERSION@%$(PLUGIN_VERSION)%; \ + s%@PLUGIN@%$(PLUGIN)%' >> pg_dist/configure.in + +pg_dist/install-sh: pg_distdir + cp $(top_srcdir)/install-sh pg_dist + +pg_dist/config.status: pg_dist/configure + cd pg_dist \ + && test -f config.status && $(SHELL) ./config.status --recheck \ + || $(SHELL) ./configure --enable-maintainer-mode + +DISTCLEANFILES = pg_dist/* pg_dist + +# diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 00000000..d90f813a --- /dev/null +++ b/plugins/Makefile.am @@ -0,0 +1,21 @@ +# temp. solution while mailcheck & xdcc arn't in SUBDIRS +EXTRA_DIST = plugin20.html Make.plugin plugin-conf.in \ + xdcc/xdcc.c \ + xdcc/Makefile.am + +noinst_HEADERS = xchat-plugin.h + +if DO_PYTHON +pythondir = python +endif + +if DO_PERL +perldir = perl +endif + +if DO_TCL +tcldir = tcl +endif + +#SUBDIRS = . $(pythondir) $(perldir) mailcheck xdcc +SUBDIRS = . $(pythondir) $(perldir) $(tcldir) diff --git a/plugins/mailcheck/Makefile.am b/plugins/mailcheck/Makefile.am new file mode 100644 index 00000000..bda04229 --- /dev/null +++ b/plugins/mailcheck/Makefile.am @@ -0,0 +1,25 @@ +## Process with automake to produce Makefile.in + +# To create a standalone tarball of your plugin run the plugin_dist +# target. Note: you must configure the main source tree with +# --enable-maintainer-mode + +# These two must be defined. +PLUGIN=mailcheck +PLUGIN_VERSION=0.1 + +# This file must be in the form PLUGIN-config.h.in, it can be empty but +# must exist +EXTRA_DIST = mailcheck-config.h.in + +# Remember to include this line in your Makefile.am +include @top_srcdir@/plugins/Make.plugin + +libdir = $(xchatdir)/plugins + +lib_LTLIBRARIES = mailcheck.la +mailcheck_la_SOURCES = mailcheck.c +mailcheck_la_LDFLAGS = -avoid-version -module +INCLUDES = $(COMMON_CFLAGS) $(PLUGIN_INCLUDES) + +DISTCLEANFILES = pg_dir/* diff --git a/plugins/mailcheck/mailcheck.c b/plugins/mailcheck/mailcheck.c new file mode 100644 index 00000000..19011ab3 --- /dev/null +++ b/plugins/mailcheck/mailcheck.c @@ -0,0 +1,94 @@ +/* XCHAT 2.0 PLUGIN: Mail checker */ + +#include +#include +#include +#include +#include +#include + +#include "xchat-plugin.h" + + +static xchat_plugin *ph; /* plugin handle */ + +static int +mail_items(char *file) +{ + FILE *fp; + int items; + char buf[512]; + + fp = fopen(file, "r"); + if(!fp) + return 1; + + items = 0; + while(fgets(buf, sizeof buf, fp)) + { + if(!strncmp(buf, "From ", 5)) + items++; + } + fclose(fp); + + return items; +} + +static void +xchat_mail_check (void) +{ + static int last_size = -1; + int size; + struct stat st; + char buf[512]; + char *maildir; + + maildir = getenv("MAIL"); + if(!maildir) + { + snprintf (buf, sizeof(buf), "/var/spool/mail/%s", getenv("USER")); + maildir = buf; + } + + if(stat(maildir, &st) < 0) + return; + + size = st.st_size; + + if(last_size == -1) + { + last_size = size; + return; + } + + if(size > last_size) + { + xchat_printf(ph, + "-\0033-\0039-\017\tYou have new mail (%d messages, %d bytes total).", + mail_items(maildir), size); + } + + last_size = size; +} + +static int timeout_cb(void *userdata) +{ + xchat_mail_check(); + + return 1; +} + +int xchat_plugin_init(xchat_plugin *plugin_handle, + char **plugin_name, char **plugin_desc, char **plugin_version, + char *arg) +{ + ph = plugin_handle; + + *plugin_name = "MailCheck"; + *plugin_desc = "Checks your mailbox every 30 seconds"; + *plugin_version = "0.1"; + + xchat_hook_timer(ph, 30000, timeout_cb, 0); + + return 1; +} diff --git a/plugins/perl/Makefile.am b/plugins/perl/Makefile.am new file mode 100644 index 00000000..816ae67c --- /dev/null +++ b/plugins/perl/Makefile.am @@ -0,0 +1,20 @@ + +EXTRA_DIST=alt_completion.pl xchat2-perldocs.html xchat2-perl.html \ + generate_header lib/Xchat.pm lib/Xchat/Embed.pm lib/Xchat/List/Network.pm \ + lib/Xchat/List/Network/Entry.pm lib/Xchat/List/Network/AutoJoin.pm \ + lib/IRC.pm + +libdir = $(xchatlibdir)/plugins + +lib_LTLIBRARIES = perl.la +perl_la_SOURCES = perl.c +perl_la_LDFLAGS = -avoid-version -module +perl_la_LIBADD = $(PERL_LDFLAGS) +BUILT_SOURCES = xchat.pm.h irc.pm.h +#CFLAGS = @CFLAGS@ -Wno-unused +INCLUDES = $(PERL_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/.. +CLEANFILES = xchat.pm.h irc.pm.h +xchat.pm.h irc.pm.h: lib/Xchat.pm lib/Xchat/Embed.pm \ + lib/Xchat/List/Network.pm lib/Xchat/List/Network/Entry.pm \ + lib/Xchat/List/Network/AutoJoin.pm lib/IRC.pm + perl generate_header diff --git a/plugins/perl/alt_completion.pl b/plugins/perl/alt_completion.pl new file mode 100644 index 00000000..2572fb81 --- /dev/null +++ b/plugins/perl/alt_completion.pl @@ -0,0 +1,507 @@ +use strict; +use warnings; +use Xchat (); +use File::Spec (); +use File::Basename qw(fileparse); + +# if the last time you addressed someone was greater than this many minutes +# ago, ignore it +# this avoids having people you have talked to a long time ago coming up too +# early in the completion list +# Setting this to 0 will disable the check which is effectively the same as +# setting it to infinity +my $last_use_threshold = 10; # 10 minutes + +# added to the front of a completion the same way as a suffix, only if +# the word is at the beginning of the line +my $prefix = ''; + +# ignore leading non-alphanumeric characters: -[\]^_`{|} +# Assuming you have the following nicks in a channel: +# [SomeNick] _SomeNick_ `SomeNick SomeNick SomeOtherNick +# when $ignore_leading_non_alnum is set to 0 +# s will cycle through SomeNick and SomeOtherNick +# when $ignore_leading_non_alnum is set to 1 +# s will cycle through [SomeNick] _SomeNick_ `SomeNick SomeNick +# SomeOtherNick +my $ignore_leading_non_alnum = 0; + +# enable path completion +my $path_completion = 1; +my $base_path = ''; + +Xchat::register( + "Tab Completion", "1.0401", "Alternative tab completion behavior" +); +Xchat::hook_print( "Key Press", \&complete ); +Xchat::hook_print( "Close Context", \&close_context ); +Xchat::hook_print( "Focus Tab", \&focus_tab ); +Xchat::hook_print( "Part", \&clean_selected ); +Xchat::hook_print( "Part with Reason", \&clean_selected ); +Xchat::hook_command( "", \&track_selected ); + +sub SHIFT() { 1 } +sub CTRL() { 4 } +sub ALT() { 8 } + +sub TAB() { 0xFF09 } +sub LEFT_TAB() { 0xFE20 } + +my %completions; +my %last_visit; +my %selected; +my %escape_map = ( + '[' => qr![\[{]!, + '{' => qr![\[{]!, + '}' => qr![\]}]!, + ']' => qr![\]}]!, + '\\' => qr![\\\|]!, + '|' => qr![\\\|]!, + '.' => qr!\.!, + '^' => qr!\^!, + '$' => qr!\$!, + '*' => qr!\*!, + '+' => qr!\+!, + '?' => qr!\?!, + '(' => qr!\(!, + ')' => qr!\)!, + '-' => qr!\-!, +); + +my $escapes = join "", keys %escape_map; +$escapes = qr/[\Q$escapes\E]/; + +# used to determine if a word is the start of a path +my $path_pattern = qr{^(?:~|/|[[:alpha:]]:\\)}; + +sub complete { + my ($key, $modifiers) = @{$_[0]}; + # if $_[0][0] contains the value of the key pressed + # $_[0][1] contains modifiers + # the value for tab is 0xFF09 + # the value for shift-tab(Left Tab) is 0xFE20 + # we don't care about other keys + + # the key must be a tab and left tab + return Xchat::EAT_NONE unless $key == TAB || $key == LEFT_TAB; + + # if it is a tab then it must not have any modifiers + return Xchat::EAT_NONE if $key == TAB && $modifiers & (CTRL|ALT|SHIFT); + + # loop backwards for shift+tab/left tab + my $delta = $modifiers & SHIFT ? -1 : 1; + my $context = Xchat::get_context; + $completions{$context} ||= {}; + + my $completions = $completions{$context}; + $completions->{pos} ||= -1; + + my $suffix = Xchat::get_prefs( "completion_suffix" ); + $suffix =~ s/^\s+//; + + my $input = Xchat::get_info( "inputbox" ); + my $cursor_pos = Xchat::get_info( "state_cursor" ); + my $left = substr( $input, 0, $cursor_pos ); + my $right = substr( $input, $cursor_pos ); + my $length = length $left; + + # trim spaces from the end of $left to avoid grabbing the wrong word + # this is mainly needed for completion at the very beginning where a space + # is added after the completion + $left =~ s/\s+$//; + + # always add one to the index because + # 1) if a space is found we want the position after it + # 2) if a space isn't found then we get back -1 + my $word_start = rindex( $left, " " ) + 1; + my $word = substr( $left, $word_start ); + $left = substr( $left, 0, -length $word ); + + if( $cursor_pos == $completions->{pos} ) { + my $previous_word = $completions->{completed}; + my $new_left = $input; + substr( $new_left, $cursor_pos ) = ""; + + if( $previous_word and $new_left =~ s/(\Q$previous_word\E)$// ) { + $word = $1; + $word_start = length( $new_left ); + $left = $new_left; + } + } + + my $command_char = Xchat::get_prefs( "input_command_char" ); + # ignore commands + if( ($word !~ m{^[${command_char}]}) + or ( $word =~ m{^[${command_char}]} and $word_start != 0 ) ) { + + if( $cursor_pos == length $input # end of input box + # not a valid nick char + && $input =~ /(?{pos} # not continuing a completion + && $word !~ m{^(?:[&#/~]|[[:alpha:]]:\\)} # not a channel or path + ) { + # check for path completion + unless( $path_completion and $word =~ $path_pattern ) { + $word_start = $cursor_pos; + $left = $input; + $length = length $length; + $right = ""; + $word = ""; + } + } + + if( $word_start == 0 && $prefix && $word =~ /^\Q$prefix/ ) { + $word =~ s/^\Q$prefix//; + } + + my $completed; # this is going to be the "completed" word + + # for parital completions and channel names so a : isn't added + #$completions->{skip_suffix} = ($word =~ /^[&#]/) ? 1 : 0; + + # continuing from a previous completion + if( + exists $completions->{matches} && @{$completions->{matches}} + && $cursor_pos == $completions->{pos} + && $word =~ /^\Q$completions->{matches}[$completions->{index}]/ + ) { + $completions->{index} += $delta; + + if( $completions->{index} < 0 ) { + $completions->{index} += @{$completions->{matches}}; + } else { + $completions->{index} %= @{$completions->{matches}}; + } + + } else { + + if( $word =~ /^[&#]/ ) { + # channel name completion + $completions->{matches} = [ matching_channels( $word ) ]; + $completions->{skip_suffix} = 0; + } elsif( $path_completion and $word =~ $path_pattern ) { + # file name completion + $completions->{matches} = [ matching_files( $word ) ]; + $completions->{skip_suffix} = 1; + } else { + # nick completion + # fix $word so { equals [, ] equals }, \ equals | + # and escape regex metacharacters + $word =~ s/($escapes)/$escape_map{$1}/g; + + $completions->{matches} = [ matching_nicks( $word ) ]; + $completions->{skip_suffix} = 0; + } + $completions->{index} = 0; + + } + $completed = $completions->{matches}[ $completions->{index} ]; + $completions->{completed} = $completed; + + my $completion_amount = Xchat::get_prefs( "completion_amount" ); + + # don't cycle if the number of possible completions is greater than + # completion_amount + if( + @{$completions->{matches}} > $completion_amount + && @{$completions->{matches}} != 1 + ) { + # don't print if we tabbed in the beginning and the list of possible + # completions includes all nicks in the channel + my $context_type = Xchat::context_info->{type}; + if( $context_type != 2 # not a channel + or @{$completions->{matches}} < Xchat::get_list("users") + ) { + Xchat::print( join " ", @{$completions->{matches}}, "\n" ); + } + + $completed = lcs( $completions->{matches} ); + $completions->{skip_suffix} = 1; + } + + if( $completed ) { + + if( $word_start == 0 && !$completions->{skip_suffix} ) { + # at the start of the line append completion suffix + Xchat::command( "settext $prefix$completed$suffix$right"); + $completions->{pos} = length( "$prefix$completed$suffix" ); + } else { + Xchat::command( "settext $left$completed$right" ); + $completions->{pos} = length( "$left$completed" ); + } + + Xchat::command( "setcursor $completions->{pos}" ); + } + +=begin +# debugging stuff + local $, = " "; + my $input_length = length $input; + Xchat::print [ + qq{input[$input]}, + qq{input_length[$input_length]}, + qq{cursor[$cursor_pos]}, + qq{start[$word_start]}, + qq{length[$length]}, + qq{left[$left]}, + qq{word[$word]}, qq{right[$right]}, + qq{completed[}. ($completed||""). qq{]}, + qq{pos[$completions->{pos}]}, + ]; + use Data::Dumper; + local $Data::Dumper::Indent = 0; + Xchat::print Dumper $completions->{matches}; +=cut + + return Xchat::EAT_ALL; + } else { + return Xchat::EAT_NONE; + } +} + + +# all channels starting with $word +sub matching_channels { + my $word = shift; + + # for use in compare_channels(); + our $current_chan; + local $current_chan = Xchat::get_info( "channel" ); + + my $conn_id = Xchat::get_info( "id" ); + $word =~ s/^[&#]+//; + + return + map { $_->[1]->{channel} } + sort compare_channels map { + my $chan = $_->{channel}; + $chan =~ s/^[#&]+//; + + # comparisons will be done based only on the name + # matching name, same connection, only channels + $chan =~ /^$word/i && $_->{id} == $conn_id ? + [ $chan, $_ ] : + () + } channels(); +} + +sub channels { + return grep { $_->{type} == 2 } Xchat::get_list( "channels" ); +} + +sub compare_channels { + # package variable, value set in matching_channels() + our $current_chan; + + # turn off warnings generated from channels that have not yet been visited + # since the script was loaded + no warnings "uninitialized"; + + # the current channel is always first, then ordered by most recently visited + return + $a->[1]{channel} eq $current_chan ? -1 : + $b->[1]{channel} eq $current_chan ? 1 : + $last_visit{ $b->[1]{context} } <=> $last_visit{ $a->[1]{context} } + || $a->[1]{channel} cmp $b->[1]{channel}; + +} + +sub matching_nicks { + my $word_re = shift; + + # for use in compare_nicks() + our ($my_nick, $selections, $now); + local $my_nick = Xchat::get_info( "nick" ); + local $selections = $selected{ Xchat::get_context() }; + local $now = time; + + my $pattern = $ignore_leading_non_alnum ? + qr/^[\-\[\]^_`{|}\\]*$word_re/i : qr/^$word_re/i; + return + map { $_->{nick} } + sort compare_nicks grep { + $_->{nick} =~ $pattern; + } Xchat::get_list( "users" ) + +} + +sub max { + return unless @_; + my $max = shift; + for(@_) { + $max = $_ if $_ > $max; + } + return $max; +} + +sub compare_times { + # package variables set in matching_nicks() + our $selections; + our $now; + + for my $nick ( $a->{nick}, $b->{nick} ) { + # turn off the warnings that get generated from users who have yet + # to speak since the script was loaded + no warnings "uninitialized"; + + if( $last_use_threshold + && (( $now - $selections->{$nick}) > ($last_use_threshold * 60)) ) { + delete $selections->{ $nick } + } + } + my $a_time = $selections->{ $a->{nick} } || 0 ; + my $b_time = $selections->{ $b->{nick} } || 0 ; + + if( $a_time || $b_time ) { + return $b_time <=> $a_time; + } elsif( !$a_time && !$b_time ) { + return $b->{lasttalk} <=> $a->{lasttalk}; + } + +} + +sub compare_nicks { + # more package variables, value set in matching_nicks() + our $my_nick; + + # our own nick is always last, then ordered by the people we spoke to most + # recently and the people who were speaking most recently + return + $a->{nick} eq $my_nick ? 1 : + $b->{nick} eq $my_nick ? -1 : + compare_times() + || Xchat::nickcmp( $a->{nick}, $b->{nick} ); + +# $selections->{ $b->{nick} } <=> $selections->{ $a->{nick} } +# || $b->{lasttalk} <=> $a->{lasttalk} + +} + +sub matching_files { + my $word = shift; + + my ($file, $input_dir) = fileparse( $word ); + + my $dir = expand_tilde( $input_dir ); + + if( opendir my $dir_handle, $dir ) { + my @files; + + if( $file ) { + @files = grep { + #Xchat::print( $_ ); + /^\Q$file/ } readdir $dir_handle; + } else { + @files = readdir $dir_handle; + } + + return map { + File::Spec->catfile( $input_dir, $_ ); + } sort + grep { !/^[.]{1,2}$/ } @files; + } else { + return (); + } +} + +# Remove completion related data for tabs that are closed +sub close_context { + my $context = Xchat::get_context; + delete $completions{$context}; + delete $last_visit{$context}; + return Xchat::EAT_NONE; +} + +# track visit times +sub focus_tab { + $last_visit{Xchat::get_context()} = time(); + return Xchat::EAT_NONE; +} + +# keep track of the last time a message was addressed to someone +# a message is considered addressed to someone if their nick is used followed +# by the completion suffix +sub track_selected { + my $input = $_[1][0]; + return Xchat::EAT_NONE unless defined $input; + + my $suffix = Xchat::get_prefs( "completion_suffix" ); + for( grep defined, $input =~ /^(.+)\Q$suffix/, $_[0][0] ) { + if( in_channel( $_ ) ) { + $selected{Xchat::get_context()}{$_} = time(); + last; + } + } + + return Xchat::EAT_NONE; +} + +# if a user is in the current channel +# user_info() can also be used instead of the loop +sub in_channel { + my $target = shift; + for my $nick ( nicks() ) { + if( $nick eq $target ) { + return 1; + } + } + + return 0; +} + +# list of nicks in the current channel +sub nicks { + return map { $_->{nick} } Xchat::get_list( "users" ); +} + +# remove people from the selected list when they leave the channel +sub clean_selected { + delete $selected{ Xchat::get_context() }{$_[0][0]}; + return Xchat::EAT_NONE; +} + +# Longest common substring +# Used for partial completion when using non-cycling completion +sub lcs { + my @nicks = @{+shift}; + return "" if @nicks == 0; + return $nicks[0] if @nicks == 1; + + my $substring = shift @nicks; + + while(@nicks) { + $substring = common_string( $substring, shift @nicks ); + } + + return $substring; +} + +sub common_string { + my ($nick1, $nick2) = @_; + my $index = 0; + + $index++ while( + ($index < length $nick1) && ($index < length $nick2) && + lc(substr( $nick1, $index, 1 )) eq lc(substr( $nick2, $index, 1 )) + ); + + + return substr( $nick1, 0, $index ); +} + +sub expand_tilde { + my $file = shift; + + $file =~ s/^~/home_dir()/e; + return $file; +} + +sub home_dir { + return $base_path if $base_path; + + if ( $^O eq "MSWin32" ) { + return $ENV{USERPROFILE}; + } else { + return ((getpwuid($>))[7] || $ENV{HOME} || $ENV{LOGDIR}); + } +} diff --git a/plugins/perl/char_count.pl b/plugins/perl/char_count.pl new file mode 100644 index 00000000..418046f4 --- /dev/null +++ b/plugins/perl/char_count.pl @@ -0,0 +1,101 @@ + +use strict; +use warnings; +use Xchat qw(:all); +use Glib qw(TRUE FALSE); +use Gtk2 -init; + +sub get_inputbox { + my $widget = Glib::Object->new_from_pointer( get_info( "win_ptr" ), 0 ); + my $input_box; + + my @containers = ($widget); + + while( @containers ) { + my $container = shift @containers; + + for my $child ( $container->get_children ) { + if( $child->get( "name" ) eq 'xchat-inputbox' ) { + $input_box = $child; + last; + } elsif( $child->isa( "Gtk2::Container" ) ) { + push @containers, $child; + } + } + } + return $input_box; +} + +sub get_hbox { + my $widget = shift; + my $hbox; + + while( $widget->parent ) { + if( $widget->parent->isa( "Gtk2::HBox" ) ) { + return $widget->parent; + } + $widget = $widget->parent; + } + +} + +my $input_box = get_inputbox(); + +if( $input_box ) { + my $hbox = get_hbox( $input_box ); + if( $hbox ) { + my $label = Gtk2::Label->new(); + $label->set_alignment( 0.5, ($label->get_alignment)[1] ); + $hbox->pack_end( $label, 0, 0, 5 ); + $label->show(); + + my $update_label = sub { + my $ctx_type = context_info->{"type"}; + hook_timer( 0, sub { + if( $ctx_type == 2 || $ctx_type == 3 ) { + my $count = length get_info "inputbox"; + $label->set_text( $count ? $count : "" ); + } else { + $label->set_text( "" ); + } + return REMOVE; + }); + return EAT_NONE; + }; + + hook_print( "Key Press", $update_label ); + hook_print( "Focus Tab", $update_label ); + hook_print( "Focus Window", $update_label ); + hook_command( "", + sub { + $label->set_text( "" ); + return EAT_NONE; + } + ); + + my @handlers; + my $buffer = $input_box->get_buffer; + my $handler = sub { $update_label->(); return TRUE }; + + if( $buffer->isa( "Gtk2::TextBuffer" ) ) { + push @handlers, $buffer->signal_connect( "changed", $handler ); + } elsif( $buffer->isa( "Gtk2::EntryBuffer" ) ) { + push @handlers, + $buffer->signal_connect( "deleted-text", $handler ); + $buffer->signal_connect( "inserted-text", $handler ); + } + + register( "Character Counter", "1.0.0", + "Display the number of characters in the inputbox", + sub { + $hbox->remove( $label ); + $buffer->signal_handler_disconnect( $_ ) for @handlers; + } + ); + } else { + prnt "Counldn't find hbox"; + } + +} else { + prnt "Couldn't fint input box"; +} diff --git a/plugins/perl/generate_header b/plugins/perl/generate_header new file mode 100644 index 00000000..d6c8a65f --- /dev/null +++ b/plugins/perl/generate_header @@ -0,0 +1,50 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +sub header { + my $file = shift; + open my $input, "<", $file or die "Couldn't open '$file':$!"; + my @file = <$input>; + close $file; + return toc(@file); +} + +sub toc { + my @lines = @_; + for( @lines ) { + if( /^\s*$/s ) { $_ = qq{"\\n"\n}; next; } + if( /^\s*#/ ) { $_ = qq{"\\n"\n}; next; } + s/\\/\\\\/g; # double the number of \'s + s/"/\\"/g; + s/^\s*/"/; + s/\n/\\n"\n/; + } + return @lines; +} + +for my $files ( + [ "xchat.pm.h", # output file + "lib/Xchat.pm", # input files + "lib/Xchat/Embed.pm", + "lib/Xchat/List/Network.pm", + "lib/Xchat/List/Network/Entry.pm", + "lib/Xchat/List/Network/AutoJoin.pm", + ], + [ "irc.pm.h", # output file + "lib/IRC.pm" # input file + ] +) { + my ($output,@inputs) = @$files; + + open my $header, ">", $output or die "Couldn't open '$output': $!"; + + for my $input ( @inputs ) { + print $header qq["{\\n"\n]; + print $header qq{"#line 1 \\"$input\\"\\n"\n}; + print $header header( $input ); + print $header qq["}\\n"\n]; + } + close $header; +} diff --git a/plugins/perl/generate_html b/plugins/perl/generate_html new file mode 100644 index 00000000..c144ce7e --- /dev/null +++ b/plugins/perl/generate_html @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use File::Basename qw(dirname); + +sub __DIR__ { + return dirname +(caller 0)[1]; +} + +# this must go before use Pod::Html to use our private copy +use lib __DIR__ . '/lib'; +use Pod::Html; + +chdir( __DIR__ ) or die $!; +pod2html( +# "pod2html", + "--header", + "--infile=lib/Xchat.pod", + "--outfile=xchat2-perl.html", +); + +#system( qw(tidy -m -i -xml -utf8 -quiet xchat2-perl.html) ); +unlink( "pod2htmd.tmp" ); +unlink( "pod2htmi.tmp" ); + +exec( "./syntax_highlight", "xchat2-perl.html" ) + or die $!; diff --git a/plugins/perl/lib/IRC.pm b/plugins/perl/lib/IRC.pm new file mode 100644 index 00000000..c22a8e73 --- /dev/null +++ b/plugins/perl/lib/IRC.pm @@ -0,0 +1,257 @@ + +package IRC; +sub IRC::register { + my ($script_name, $version, $callback) = @_; + my $package = caller; + $callback = Xchat::Embed::fix_callback( $package, $callback) if $callback; + Xchat::register( $script_name, $version, undef, $callback ); +} + + +sub IRC::add_command_handler { + my ($command, $callback) = @_; + my $package = caller; + + $callback = Xchat::Embed::fix_callback( $package, $callback ); + + # starting index for word_eol array + # this is for compatibility with '' as the command + my $start_index = $command ? 1 : 0; + + Xchat::hook_command( $command, + sub { + no strict 'refs'; + return &{$callback}($_[1][$start_index]); + } + ); + return; +} + +sub IRC::add_message_handler { + my ($message, $callback) = @_; + my $package = caller; + $callback = Xchat::Embed::fix_callback( $package, $callback ); + + Xchat::hook_server( $message, + sub { + no strict 'refs'; + return &{$callback}( $_[1][0] ); + } + ); + return; +} + +sub IRC::add_print_handler { + my ($event, $callback) = @_; + my $package = caller; + $callback = Xchat::Embed::fix_callback( $package, $callback ); + Xchat::hook_print( $event, + sub { + my @word = @{$_[0]}; + no strict 'refs'; + return &{$callback}( join( ' ', @word[0..3] ), @word ); + } + ); + return; +} + +sub IRC::add_timeout_handler { + my ($timeout, $callback) = @_; + my $package = caller; + $callback = Xchat::Embed::fix_callback( $package, $callback ); + Xchat::hook_timer( $timeout, + sub { + no strict 'refs'; + &{$callback}; + return 0; + } + ); + return; +} + +sub IRC::command { + my $command = shift; + if( $command =~ m{^/} ) { + $command =~ s{^/}{}; + Xchat::command( $command ); + } else { + Xchat::command( qq[say $command] ); + } +} + +sub IRC::command_with_channel { + my ($command, $channel, $server) = @_; + my $old_ctx = Xchat::get_context; + my $ctx = Xchat::find_context( $channel, $server ); + + if( $ctx ) { + Xchat::set_context( $ctx ); + IRC::command( $command ); + Xchat::set_context( $ctx ); + } +} + +sub IRC::command_with_server { + my ($command, $server) = @_; + my $old_ctx = Xchat::get_context; + my $ctx = Xchat::find_context( undef, $server ); + + if( $ctx ) { + Xchat::set_context( $ctx ); + IRC::command( $command ); + Xchat::set_context( $ctx ); + } +} + +sub IRC::dcc_list { + my @dccs; + for my $dcc ( Xchat::get_list( 'dcc' ) ) { + push @dccs, $dcc->{nick}; + push @dccs, $dcc->{file} ? $dcc->{file} : ''; + push @dccs, @{$dcc}{qw(type status cps size)}; + push @dccs, $dcc->{type} == 0 ? $dcc->{pos} : $dcc->{resume}; + push @dccs, $dcc->{address32}; + push @dccs, $dcc->{destfile} ? $dcc->{destfile} : ''; + } + return @dccs; +} + +sub IRC::channel_list { + my @channels; + for my $channel ( Xchat::get_list( 'channels' ) ) { + push @channels, @{$channel}{qw(channel server)}, + Xchat::context_info( $channel->{context} )->{nick}; + } + return @channels; +} + +sub IRC::get_info { + my $id = shift; + my @ids = qw(version nick channel server xchatdir away network host topic); + + if( $id >= 0 && $id <= 8 && $id != 5 ) { + my $info = Xchat::get_info($ids[$id]); + return defined $info ? $info : ''; + } else { + if( $id == 5 ) { + return Xchat::get_info( 'away' ) ? 1 : 0; + } else { + return 'Error2'; + } + } +} + +sub IRC::get_prefs { + return 'Unknown variable' unless defined $_[0]; + my $result = Xchat::get_prefs(shift); + return defined $result ? $result : 'Unknown variable'; +} + +sub IRC::ignore_list { + my @ignores; + for my $ignore ( Xchat::get_list( 'ignore' ) ) { + push @ignores, $ignore->{mask}; + my $flags = $ignore->{flags}; + push @ignores, $flags & 1, $flags & 2, $flags & 4, $flags & 8, $flags & 16, + $flags & 32, ':'; + } + return @ignores; +} + +sub IRC::print { + Xchat::print( $_ ) for @_; + return; +} + +sub IRC::print_with_channel { + Xchat::print( @_ ); +} + +sub IRC::send_raw { + Xchat::commandf( qq[quote %s], shift ); +} + +sub IRC::server_list { + my @servers; + for my $channel ( Xchat::get_list( 'channels' ) ) { + push @servers, $channel->{server} if $channel->{server}; + } + return @servers; +} + +sub IRC::user_info { + my $user; + if( @_ > 0 ) { + $user = Xchat::user_info( shift ); + } else { + $user = Xchat::user_info(); + } + + my @info; + if( $user ) { + push @info, $user->{nick}; + if( $user->{host} ) { + push @info, $user->{host}; + } else { + push @info, 'FETCHING'; + } + push @info, $user->{prefix} eq '@' ? 1 : 0; + push @info, $user->{prefix} eq '+' ? 1 : 0; + } + return @info; +} + +sub IRC::user_list { + my ($channel, $server) = @_; + my $ctx = Xchat::find_context( $channel, $server ); + my $old_ctx = Xchat::get_context; + + if( $ctx ) { + Xchat::set_context( $ctx ); + my @users; + for my $user ( Xchat::get_list( 'users' ) ) { + push @users, $user->{nick}; + if( $user->{host} ) { + push @users, $user->{host}; + } else { + push @users, 'FETCHING'; + } + push @users, $user->{prefix} eq '@' ? 1 : 0; + push @users, $user->{prefix} eq '+' ? 1 : 0; + push @users, ':'; + } + Xchat::set_context( $old_ctx ); + return @users; + } else { + return; + } +} + +sub IRC::user_list_short { + my ($channel, $server) = @_; + my $ctx = Xchat::find_context( $channel, $server ); + my $old_ctx = Xchat::get_context; + + if( $ctx ) { + Xchat::set_context( $ctx ); + my @users; + for my $user ( Xchat::get_list( 'users' ) ) { + my $nick = $user->{nick}; + my $host = $user->{host} || 'FETCHING'; + push @users, $nick, $host; + } + Xchat::set_context( $old_ctx ); + return @users; + } else { + return; + } + +} + +sub IRC::add_user_list {} +sub IRC::sub_user_list {} +sub IRC::clear_user_list {} +sub IRC::notify_list {} +sub IRC::perl_script_list {} + +1 diff --git a/plugins/perl/lib/Pod/Html.pm b/plugins/perl/lib/Pod/Html.pm new file mode 100644 index 00000000..3695564b --- /dev/null +++ b/plugins/perl/lib/Pod/Html.pm @@ -0,0 +1,2399 @@ +package Pod::Html; +use strict; +require Exporter; + +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); +$VERSION = 1.08; +@ISA = qw(Exporter); +@EXPORT = qw(pod2html htmlify); +@EXPORT_OK = qw(anchorify); + +use Carp; +use Config; +use Cwd; +use File::Spec; +use File::Spec::Unix; +use Getopt::Long; + +use locale; # make \w work right in non-ASCII lands + +=head1 NAME + +Pod::Html - module to convert pod files to HTML + +=head1 SYNOPSIS + + use Pod::Html; + pod2html([options]); + +=head1 DESCRIPTION + +Converts files from pod format (see L) to HTML format. It +can automatically generate indexes and cross-references, and it keeps +a cache of things it knows how to cross-reference. + +=head1 FUNCTIONS + +=head2 pod2html + + pod2html("pod2html", + "--podpath=lib:ext:pod:vms", + "--podroot=/usr/src/perl", + "--htmlroot=/perl/nmanual", + "--libpods=perlfunc:perlguts:perlvar:perlrun:perlop", + "--recurse", + "--infile=foo.pod", + "--outfile=/perl/nmanual/foo.html"); + +pod2html takes the following arguments: + +=over 4 + +=item backlink + + --backlink="Back to Top" + +Adds "Back to Top" links in front of every C heading (except for +the first). By default, no backlinks are generated. + +=item cachedir + + --cachedir=name + +Creates the item and directory caches in the given directory. + +=item css + + --css=stylesheet + +Specify the URL of a cascading style sheet. Also disables all HTML/CSS +C + + + +$block +END_OF_HEAD + + # load/reload/validate/cache %Pages and %Items + get_cache( $Dircache, $Itemcache, \@Podpath, $Podroot, $Recurse ); + + # scan the pod for =item directives + scan_items( \%Local_Items, "", @poddata ); + + # put an index at the top of the file. note, if $Doindex is 0 we + # still generate an index, but surround it with an html comment. + # that way some other program can extract it if desired. + $index =~ s/--+/-/g; + + my $hr = ( $Doindex and $index ) ? qq(
) : ""; + + unless ($Doindex) { + $index = qq(\n); + } + + print HTML << "END_OF_INDEX"; + + +
+

+$index +$hr +
+ + +END_OF_INDEX + + # now convert this file + my $after_item; # set to true after an =item + my $need_dd = 0; + warn "Converting input file $Podfile\n" if $Verbose; + foreach my $i ( 0 .. $#poddata ) { + $_ = $poddata[$i]; + $Paragraph = $i + 1; + if (/^(=.*)/s) { # is it a pod directive? + $Ignore = 0; + $after_item = 0; + $need_dd = 0; + $_ = $1; + if (/^=begin\s+(\S+)\s*(.*)/si) { # =begin + process_begin( $1, $2 ); + } elsif (/^=end\s+(\S+)\s*(.*)/si) { # =end + process_end( $1, $2 ); + } elsif (/^=cut/) { # =cut + process_cut(); + } elsif (/^=pod/) { # =pod + process_pod(); + } else { + next if @Begin_Stack && $Begin_Stack[-1] ne 'html'; + + if (/^=(head[1-6])\s+(.*\S)/s) { # =head[1-6] heading + process_head( $1, $2, $Doindex && $index ); + } elsif (/^=item\s*(.*\S)?/sm) { # =item text + $need_dd = process_item($1); + $after_item = 1; + } elsif (/^=over\s*(.*)/) { # =over N + process_over(); + } elsif (/^=back/) { # =back + process_back($need_dd); + } elsif (/^=for\s+(\S+)\s*(.*)/si) { # =for + process_for( $1, $2 ); + } else { + /^=(\S*)\s*/; + warn "$0: $Podfile: unknown pod directive '$1' in " + . "paragraph $Paragraph. ignoring.\n" + unless $Quiet; + } + } + $Top = 0; + } else { + next if $Ignore; + next if @Begin_Stack && $Begin_Stack[-1] ne 'html'; + print HTML and next if @Begin_Stack && $Begin_Stack[-1] eq 'html'; + print HTML "
\n" if $need_dd; + my $text = $_; + if ( $text =~ /\A\s+/ ) { + process_pre( \$text ); + print HTML "
\n$text
\n"; + + } else { + process_text( \$text ); + + # experimental: check for a paragraph where all lines + # have some ...\t...\t...\n pattern + if ( $text =~ /\t/ ) { + my @lines = split( "\n", $text ); + if ( @lines > 1 ) { + my $all = 2; + foreach my $line (@lines) { + if ( $line =~ /\S/ && $line !~ /\t/ ) { + $all--; + last if $all == 0; + } + } + if ( $all > 0 ) { + $text =~ s/\t+//g; + $text =~ s/^//gm; + $text = + '' + . $text + . '
'; + } + } + } + ## end of experimental + + if ($after_item) { + $After_Lpar = 1; + } + print HTML "

$text

\n"; + } + print HTML "
\n" if $need_dd; + $after_item = 0; + } + } + + # finish off any pending directives + finish_list(); + + # link to page index + print HTML "

$Backlink

\n" + if $Doindex + and $index + and $Backlink; + + print HTML < + + +END_OF_TAIL + + # close the html file + close(HTML); + + warn "Finished\n" if $Verbose; +} + +############################################################################## + +sub usage { + my $podfile = shift; + warn "$0: $podfile: @_\n" if @_; + die < --infile= --outfile= + --podpath=:...: --podroot= + --libpods=:...: --recurse --verbose --index + --netscape --norecurse --noindex --cachedir= + + --backlink - set text for "back to top" links (default: none). + --cachedir - directory for the item and directory cache files. + --css - stylesheet URL + --flush - flushes the item and directory caches. + --[no]header - produce block header/footer (default is no headers). + --help - prints this message. + --hiddendirs - search hidden directories in podpath + --htmldir - directory for resulting HTML files. + --htmlroot - http-server base directory from which all relative paths + in podpath stem (default is /). + --[no]index - generate an index at the top of the resulting html + (default behaviour). + --infile - filename for the pod to convert (input taken from stdin + by default). + --libpods - colon-separated list of pages to search for =item pod + directives in as targets of C<> and implicit links (empty + by default). note, these are not filenames, but rather + page names like those that appear in L<> links. + --outfile - filename for the resulting html file (output sent to + stdout by default). + --podpath - colon-separated list of directories containing library + pods (empty by default). + --podroot - filesystem base directory from which all relative paths + in podpath stem (default is .). + --[no]quiet - suppress some benign warning messages (default is off). + --[no]recurse - recurse on those subdirectories listed in podpath + (default behaviour). + --title - title that will appear in resulting html file. + --[no]verbose - self-explanatory (off by default). + --[no]netscape - deprecated, has no effect. for backwards compatibility only. + +END_OF_USAGE + +} + +sub parse_command_line { + my ( + $opt_backlink, $opt_cachedir, $opt_css, $opt_flush, + $opt_header, $opt_help, $opt_htmldir, $opt_htmlroot, + $opt_index, $opt_infile, $opt_libpods, $opt_netscape, + $opt_outfile, $opt_podpath, $opt_podroot, $opt_quiet, + $opt_recurse, $opt_title, $opt_verbose, $opt_hiddendirs + ); + + unshift @ARGV, split ' ', $Config{pod2html} if $Config{pod2html}; + my $result = GetOptions( + 'backlink=s' => \$opt_backlink, + 'cachedir=s' => \$opt_cachedir, + 'css=s' => \$opt_css, + 'flush' => \$opt_flush, + 'header!' => \$opt_header, + 'help' => \$opt_help, + 'hiddendirs!' => \$opt_hiddendirs, + 'htmldir=s' => \$opt_htmldir, + 'htmlroot=s' => \$opt_htmlroot, + 'index!' => \$opt_index, + 'infile=s' => \$opt_infile, + 'libpods=s' => \$opt_libpods, + 'netscape!' => \$opt_netscape, + 'outfile=s' => \$opt_outfile, + 'podpath=s' => \$opt_podpath, + 'podroot=s' => \$opt_podroot, + 'quiet!' => \$opt_quiet, + 'recurse!' => \$opt_recurse, + 'title=s' => \$opt_title, + 'verbose!' => \$opt_verbose, + ); + usage( "-", "invalid parameters" ) if not $result; + + usage("-") if defined $opt_help; # see if the user asked for help + $opt_help = ""; # just to make -w shut-up. + + @Podpath = split( ":", $opt_podpath ) if defined $opt_podpath; + @Libpods = split( ":", $opt_libpods ) if defined $opt_libpods; + + $Backlink = $opt_backlink if defined $opt_backlink; + $Cachedir = $opt_cachedir if defined $opt_cachedir; + $Css = $opt_css if defined $opt_css; + $Header = $opt_header if defined $opt_header; + $Htmldir = $opt_htmldir if defined $opt_htmldir; + $Htmlroot = $opt_htmlroot if defined $opt_htmlroot; + $Doindex = $opt_index if defined $opt_index; + $Podfile = $opt_infile if defined $opt_infile; + $HiddenDirs = $opt_hiddendirs if defined $opt_hiddendirs; + $Htmlfile = $opt_outfile if defined $opt_outfile; + $Podroot = $opt_podroot if defined $opt_podroot; + $Quiet = $opt_quiet if defined $opt_quiet; + $Recurse = $opt_recurse if defined $opt_recurse; + $Title = $opt_title if defined $opt_title; + $Verbose = $opt_verbose if defined $opt_verbose; + + warn "Flushing item and directory caches\n" + if $opt_verbose && defined $opt_flush; + $Dircache = "$Cachedir/pod2htmd.tmp"; + $Itemcache = "$Cachedir/pod2htmi.tmp"; + if ( defined $opt_flush ) { + 1 while unlink( $Dircache, $Itemcache ); + } +} + +my $Saved_Cache_Key; + +sub get_cache { + my ( $dircache, $itemcache, $podpath, $podroot, $recurse ) = @_; + my @cache_key_args = @_; + + # A first-level cache: + # Don't bother reading the cache files if they still apply + # and haven't changed since we last read them. + + my $this_cache_key = cache_key(@cache_key_args); + + return if $Saved_Cache_Key and $this_cache_key eq $Saved_Cache_Key; + + # load the cache of %Pages and %Items if possible. $tests will be + # non-zero if successful. + my $tests = 0; + if ( -f $dircache && -f $itemcache ) { + warn "scanning for item cache\n" if $Verbose; + $tests = load_cache( $dircache, $itemcache, $podpath, $podroot ); + } + + # if we didn't succeed in loading the cache then we must (re)build + # %Pages and %Items. + if ( !$tests ) { + warn "scanning directories in pod-path\n" if $Verbose; + scan_podpath( $podroot, $recurse, 0 ); + } + $Saved_Cache_Key = cache_key(@cache_key_args); +} + +sub cache_key { + my ( $dircache, $itemcache, $podpath, $podroot, $recurse ) = @_; + return join( '!', + $dircache, $itemcache, $recurse, @$podpath, $podroot, stat($dircache), + stat($itemcache) ); +} + +# +# load_cache - tries to find if the caches stored in $dircache and $itemcache +# are valid caches of %Pages and %Items. if they are valid then it loads +# them and returns a non-zero value. +# +sub load_cache { + my ( $dircache, $itemcache, $podpath, $podroot ) = @_; + my ($tests); + local $_; + + $tests = 0; + + open( CACHE, "<$itemcache" ) + || die "$0: error opening $itemcache for reading: $!\n"; + $/ = "\n"; + + # is it the same podpath? + $_ = ; + chomp($_); + $tests++ if ( join( ":", @$podpath ) eq $_ ); + + # is it the same podroot? + $_ = ; + chomp($_); + $tests++ if ( $podroot eq $_ ); + + # load the cache if its good + if ( $tests != 2 ) { + close(CACHE); + return 0; + } + + warn "loading item cache\n" if $Verbose; + while () { + /(.*?) (.*)$/; + $Items{$1} = $2; + } + close(CACHE); + + warn "scanning for directory cache\n" if $Verbose; + open( CACHE, "<$dircache" ) + || die "$0: error opening $dircache for reading: $!\n"; + $/ = "\n"; + $tests = 0; + + # is it the same podpath? + $_ = ; + chomp($_); + $tests++ if ( join( ":", @$podpath ) eq $_ ); + + # is it the same podroot? + $_ = ; + chomp($_); + $tests++ if ( $podroot eq $_ ); + + # load the cache if its good + if ( $tests != 2 ) { + close(CACHE); + return 0; + } + + warn "loading directory cache\n" if $Verbose; + while () { + /(.*?) (.*)$/; + $Pages{$1} = $2; + } + + close(CACHE); + + return 1; +} + +# +# scan_podpath - scans the directories specified in @podpath for directories, +# .pod files, and .pm files. it also scans the pod files specified in +# @Libpods for =item directives. +# +sub scan_podpath { + my ( $podroot, $recurse, $append ) = @_; + my ( $pwd, $dir ); + my ( $libpod, $dirname, $pod, @files, @poddata ); + + unless ($append) { + %Items = (); + %Pages = (); + } + + # scan each directory listed in @Podpath + $pwd = getcwd(); + chdir($podroot) + || die "$0: error changing to directory $podroot: $!\n"; + foreach $dir (@Podpath) { + scan_dir( $dir, $recurse ); + } + + # scan the pods listed in @Libpods for =item directives + foreach $libpod (@Libpods) { + + # if the page isn't defined then we won't know where to find it + # on the system. + next unless defined $Pages{$libpod} && $Pages{$libpod}; + + # if there is a directory then use the .pod and .pm files within it. + # NOTE: Only finds the first so-named directory in the tree. + # if ($Pages{$libpod} =~ /([^:]*[^(\.pod|\.pm)]):/) { + if ( $Pages{$libpod} =~ /([^:]*(?; + close(POD); + clean_data( \@poddata ); + + scan_items( \%Items, "$dirname/$pod", @poddata ); + } + + # use the names of files as =item directives too. +### Don't think this should be done this way - confuses issues.(WL) +### foreach $pod (@files) { +### $pod =~ /^(.*)(\.pod|\.pm)$/; +### $Items{$1} = "$dirname/$1.html" if $1; +### } + } elsif ( $Pages{$libpod} =~ /([^:]*\.pod):/ + || $Pages{$libpod} =~ /([^:]*\.pm):/ ) + { + + # scan the .pod or .pm file for =item directives + $pod = $1; + open( POD, "<$pod" ) + || die "$0: error opening $pod for input: $!\n"; + @poddata = ; + close(POD); + clean_data( \@poddata ); + + scan_items( \%Items, "$pod", @poddata ); + } else { + warn "$0: shouldn't be here (line " . __LINE__ . "\n" unless $Quiet; + } + } + @poddata = (); # clean-up a bit + + chdir($pwd) + || die "$0: error changing to directory $pwd: $!\n"; + + # cache the item list for later use + warn "caching items for later use\n" if $Verbose; + open( CACHE, ">$Itemcache" ) + || die "$0: error open $Itemcache for writing: $!\n"; + + print CACHE join( ":", @Podpath ) . "\n$podroot\n"; + foreach my $key ( keys %Items ) { + print CACHE "$key $Items{$key}\n"; + } + + close(CACHE); + + # cache the directory list for later use + warn "caching directories for later use\n" if $Verbose; + open( CACHE, ">$Dircache" ) + || die "$0: error open $Dircache for writing: $!\n"; + + print CACHE join( ":", @Podpath ) . "\n$podroot\n"; + foreach my $key ( keys %Pages ) { + print CACHE "$key $Pages{$key}\n"; + } + + close(CACHE); +} + +# +# scan_dir - scans the directory specified in $dir for subdirectories, .pod +# files, and .pm files. notes those that it finds. this information will +# be used later in order to figure out where the pages specified in L<> +# links are on the filesystem. +# +sub scan_dir { + my ( $dir, $recurse ) = @_; + my ( $t, @subdirs, @pods, $pod, $dirname, @dirs ); + local $_; + + @subdirs = (); + @pods = (); + + opendir( DIR, $dir ) + || die "$0: error opening directory $dir: $!\n"; + while ( defined( $_ = readdir(DIR) ) ) { + if ( -d "$dir/$_" + && $_ ne "." + && $_ ne ".." + && ( $HiddenDirs || !/^\./ ) ) + { # directory + $Pages{$_} = "" unless defined $Pages{$_}; + $Pages{$_} .= "$dir/$_:"; + push( @subdirs, $_ ); + } elsif (/\.pod\z/) { # .pod + s/\.pod\z//; + $Pages{$_} = "" unless defined $Pages{$_}; + $Pages{$_} .= "$dir/$_.pod:"; + push( @pods, "$dir/$_.pod" ); + } elsif (/\.html\z/) { # .html + s/\.html\z//; + $Pages{$_} = "" unless defined $Pages{$_}; + $Pages{$_} .= "$dir/$_.pod:"; + } elsif (/\.pm\z/) { # .pm + s/\.pm\z//; + $Pages{$_} = "" unless defined $Pages{$_}; + $Pages{$_} .= "$dir/$_.pm:"; + push( @pods, "$dir/$_.pm" ); + } elsif ( -T "$dir/$_" ) { # script(?) + local *F; + if ( open( F, "$dir/$_" ) ) { + my $line; + while ( defined( $line = ) ) { + if ( $line =~ /^=(?:pod|head1)/ ) { + $Pages{$_} = "" unless defined $Pages{$_}; + $Pages{$_} .= "$dir/$_.pod:"; + last; + } + } + close(F); + } + } + } + closedir(DIR); + + # recurse on the subdirectories if necessary + if ($recurse) { + foreach my $subdir (@subdirs) { + scan_dir( "$dir/$subdir", $recurse ); + } + } +} + +# +# scan_headings - scan a pod file for head[1-6] tags, note the tags, and +# build an index. +# +sub scan_headings { + my ( $sections, @data ) = @_; + my ( $tag, $which_head, $otitle, $listdepth, $index ); + + local $Ignore = 0; + + $listdepth = 0; + $index = ""; + + # scan for =head directives, note their name, and build an index + # pointing to each of them. + foreach my $line (@data) { + if ( $line =~ /^=(head)([1-6])\s+(.*)/ ) { + ( $tag, $which_head, $otitle ) = ( $1, $2, $3 ); + + my $title = depod($otitle); + my $name = anchorify($title); + $$sections{$name} = 1; + $title = process_text( \$otitle ); + + while ( $which_head != $listdepth ) { + if ( $which_head > $listdepth ) { + $index .= "\n" + . ( "\t" x ($listdepth) ) + . ( $listdepth > 0 ? qq{
  • \n} + . "\t"x($listdepth + 1): "" ) + . "
      "; + $listdepth++; + } elsif ( $which_head < $listdepth ) { + $listdepth--; + $index .= "\n" + . ( "\t" x $listdepth ) + . ( $listdepth > 0 ? "\t" : "" ) + . "
    " + . ( $listdepth >= 0 ? "\n" . ("\t"x$listdepth) + . "
  • " : "" ) + . "\n"; + } + } + + $index .= "\n" + . ( "\t" x $listdepth ) . "
  • " + . "" + . $title + . "
  • "; + } + } + + # finish off the lists + while ( $listdepth-- ) { + $index .= "\n" . ( "\t" x $listdepth ) + . ($listdepth > 0 ? "\t" : "") + ."\n" + . ($listdepth > 0 ? ("\t" x $listdepth) . "" : "" ); + } + + # get rid of bogus lists + $index =~ s,\t*
      \s*
    \n,,g; + + return $index; +} + +# +# scan_items - scans the pod specified by $pod for =item directives. we +# will use this information later on in resolving C<> links. +# +sub scan_items { + my ( $itemref, $pod, @poddata ) = @_; + my ( $i, $item ); + local $_; + + $pod =~ s/\.pod\z//; + $pod .= ".html" if $pod; + + foreach $i ( 0 .. $#poddata ) { + my $txt = depod( $poddata[$i] ); + + # figure out what kind of item it is. + # Build string for referencing this item. + if ( $txt =~ /\A=item\s+\*\s*(.*)\Z/s ) { # bullet + next unless $1; + $item = $1; + } elsif ( $txt =~ /\A=item\s+(?>\d+\.?)\s*(.*)\Z/s ) { # numbered list + $item = $1; + } elsif ( $txt =~ /\A=item\s+(.*)\Z/s ) { # plain item + $item = $1; + } else { + next; + } + my $fid = fragment_id($item); + $$itemref{$fid} = "$pod" if $fid; + } +} + +# +# process_head - convert a pod head[1-6] tag and convert it to HTML format. +# +sub process_head { + my ( $tag, $heading, $hasindex ) = @_; + + # figure out the level of the =head + $tag =~ /head([1-6])/; + my $level = $1; + + if ($Listlevel) { + warn +"$0: $Podfile: unterminated list at =head in paragraph $Paragraph. ignoring.\n" + unless $Quiet; + while ($Listlevel) { + process_back(); + } + } + + print HTML "

    \n"; + if ( $level == 1 && !$Top ) { + print HTML "$Backlink\n" + if $hasindex and $Backlink; + print HTML "

    \n
    \n"; + } else { + print HTML "

    \n"; + } + + my $name = anchorify( depod($heading) ); + my $convert = process_text( \$heading ); + $convert =~ s{]+>}{}g; + print HTML "$convert\n"; +} + +# +# emit_item_tag - print an =item's text +# Note: The global $EmittedItem is used for inhibiting self-references. +# +my $EmittedItem; + +sub emit_item_tag($$$) { + my ( $otext, $text, $compact ) = @_; + my $item = fragment_id( depod($text), -generate ); + Carp::confess( "Undefined fragment '$text' (" + . depod($text) + . ") from fragment_id() in emit_item_tag() in $Podfile" ) + if !defined $item; + $EmittedItem = $item; + ### print STDERR "emit_item_tag=$item ($text)\n"; + + print HTML ''; + if ( $Items_Named{$item}++ ) { + print HTML process_text( \$otext ); + } else { + my $name = $item; + $name = anchorify($name); + print HTML +#qq{}, + process_text( \$otext ), + # '' + ; + } + print HTML "\n"; + undef($EmittedItem); +} + +sub emit_li { + my ($tag) = @_; + if ( $Items_Seen[$Listlevel]++ == 0 ) { + push( @Listend, "" ); + print HTML "<$tag>\n"; + } + my $emitted = $tag eq 'dl' ? 'dt' : 'li'; + print HTML "<$emitted>"; + return $emitted; +} + +# +# process_item - convert a pod item tag and convert it to HTML format. +# +sub process_item { + my ($otext) = @_; + my $need_dd = 0; # set to 1 if we need a
    after an item + + # lots of documents start a list without doing an =over. this is + # bad! but, the proper thing to do seems to be to just assume + # they did do an =over. so warn them once and then continue. + if ( $Listlevel == 0 ) { + warn +"$0: $Podfile: unexpected =item directive in paragraph $Paragraph. ignoring.\n" + unless $Quiet; + process_over(); + } + + # formatting: insert a paragraph if preceding item has >1 paragraph + if ($After_Lpar) { + print HTML $need_dd ? "\n" : "\n" if $After_Lpar; + $After_Lpar = 0; + } + + # remove formatting instructions from the text + my $text = depod($otext); + + my $emitted; # the tag actually emitted, used for closing + + # all the list variants: + if ( $text =~ /\A\*/ ) { # bullet + $emitted = emit_li('ul'); + if ( $text =~ /\A\*\s+(\S.*)\Z/s ) { # with additional text + my $tag = $1; + $otext =~ s/\A\*\s+//; + emit_item_tag( $otext, $tag, 1 ); + } + print HTML "" + } elsif ( $text =~ /\A\d+/ ) { # numbered list + $emitted = emit_li('ol'); + if ( $text =~ /\A(?>\d+\.?)\s*(\S.*)\Z/s ) { # with additional text + my $tag = $1; + $otext =~ s/\A\d+\.?\s*//; + emit_item_tag( $otext, $tag, 1 ); + } + print HTML ""; + } else { # definition list + $emitted = emit_li('dl'); + if ( $text =~ /\A(.+)\Z/s ) { # should have text + emit_item_tag( $otext, $text, 1 ); + } + $need_dd = 1; + } + print HTML "\n"; + return $need_dd; +} + +# +# process_over - process a pod over tag and start a corresponding HTML list. +# +sub process_over { + + # start a new list + $Listlevel++; + push( @Items_Seen, 0 ); + $After_Lpar = 0; +} + +# +# process_back - process a pod back tag and convert it to HTML format. +# +sub process_back { + my $need_dd = shift; + if ( $Listlevel == 0 ) { + warn +"$0: $Podfile: unexpected =back directive in paragraph $Paragraph. ignoring.\n" + unless $Quiet; + return; + } + + # close off the list. note, I check to see if $Listend[$Listlevel] is + # defined because an =item directive may have never appeared and thus + # $Listend[$Listlevel] may have never been initialized. + $Listlevel--; + if ( defined $Listend[$Listlevel] ) { + print HTML $need_dd ? "\n" : "\n" if $After_Lpar; + print HTML $Listend[$Listlevel]; + print HTML "\n"; + pop(@Listend); + } + $After_Lpar = 0; + + # clean up item count + pop(@Items_Seen); +} + +# +# process_cut - process a pod cut tag, thus start ignoring pod directives. +# +sub process_cut { + $Ignore = 1; +} + +# +# process_pod - process a pod tag, thus stop ignoring pod directives +# until we see a corresponding cut. +# +sub process_pod { + + # no need to set $Ignore to 0 cause the main loop did it +} + +# +# process_for - process a =for pod tag. if it's for html, spit +# it out verbatim, if illustration, center it, otherwise ignore it. +# +sub process_for { + my ( $whom, $text ) = @_; + if ( $whom =~ /^(pod2)?html$/i ) { + print HTML $text; + } elsif ( $whom =~ /^illustration$/i ) { + 1 while chomp $text; + for my $ext (qw[.png .gif .jpeg .jpg .tga .pcl .bmp]) { + $text .= $ext, last if -r "$text$ext"; + } + print HTML +qq{

    $text illustration

    }; + } +} + +# +# process_begin - process a =begin pod tag. this pushes +# whom we're beginning on the begin stack. if there's a +# begin stack, we only print if it us. +# +sub process_begin { + my ( $whom, $text ) = @_; + $whom = lc($whom); + push( @Begin_Stack, $whom ); + if ( $whom =~ /^(pod2)?html$/ ) { + print HTML $text if $text; + } +} + +# +# process_end - process a =end pod tag. pop the +# begin stack. die if we're mismatched. +# +sub process_end { + my ( $whom, $text ) = @_; + $whom = lc($whom); + if ( !defined $Begin_Stack[-1] or $Begin_Stack[-1] ne $whom ) { + Carp::confess( + "Unmatched begin/end at chunk $Paragraph in pod $Podfile\n"); + } + pop(@Begin_Stack); +} + +# +# process_pre - indented paragraph, made into
    
    +#
    +sub process_pre {
    +	my ($text) = @_;
    +	my ($rest);
    +	return if $Ignore;
    +
    +	$rest = $$text;
    +
    +	# insert spaces in place of tabs
    +	$rest =~ s#(.+)#
    +	    my $line = $1;
    +            1 while $line =~ s/(\t+)/' ' x ((length($1) * 8) - $-[0] % 8)/e;
    +	    $line;
    +	#eg;
    +
    +	# convert some special chars to HTML escapes
    +	$rest = html_escape($rest);
    +
    +	# try and create links for all occurrences of perl.* within
    +	# the preformatted text.
    +	$rest =~ s{
    +	         (\s*)(perl\w+)
    +	      }{
    +		 if ( defined $Pages{$2} ){	# is a link
    +		     qq($1$2);
    +		 } elsif (defined $Pages{dosify($2)}) {	# is a link
    +		     qq($1$2);
    +		 } else {
    +		     "$1$2";
    +		 }
    +	      }xeg;
    +	$rest =~ s{
    +		 ('
    +	|			# or:
    +	    [$punc]*		# 0 or more punctuation
    +	    (?:			#   followed
    +		[^$any]		#   by a non-url char
    +	    |			#   or
    +		$		#   end of the string
    +	    )			#
    +	|			# or else
    +	    $			#   then end of the string
    +        )
    +      }{$1}igox;
    +
    +	# text should be as it is (verbatim)
    +	$$text = $rest;
    +}
    +
    +#
    +# pure text processing
    +#
    +# pure_text/inIS_text: differ with respect to automatic C<> recognition.
    +# we don't want this to happen within IS
    +#
    +sub pure_text($) {
    +	my $text = shift();
    +	process_puretext( $text, 1 );
    +}
    +
    +sub inIS_text($) {
    +	my $text = shift();
    +	process_puretext( $text, 0 );
    +}
    +
    +#
    +# process_puretext - process pure text (without pod-escapes) converting
    +#  double-quotes and handling implicit C<> links.
    +#
    +sub process_puretext {
    +	my ( $text, $notinIS ) = @_;
    +
    +	## Guessing at func() or [\$\@%&]*var references in plain text is destined
    +	## to produce some strange looking ref's. uncomment to disable:
    +	## $notinIS = 0;
    +
    +	my ( @words, $lead, $trail );
    +
    +	# keep track of leading and trailing white-space
    +	$lead  = ( $text =~ s/\A(\s+)//s ? $1 : "" );
    +	$trail = ( $text =~ s/(\s+)\Z//s ? $1 : "" );
    +
    +	# split at space/non-space boundaries
    +	@words = split( /(?<=\s)(?=\S)|(?<=\S)(?=\s)/, $text );
    +
    +	# process each word individually
    +	foreach my $word (@words) {
    +
    +		# skip space runs
    +		next if $word =~ /^\s*$/;
    +
    +		# see if we can infer a link or a function call
    +		#
    +		# NOTE: This is a word based search, it won't automatically
    +		# mark "substr($var, 1, 2)" because the 1st word would be "substr($var"
    +		# User has to enclose those with proper C<>
    +
    +		if (
    +			   $notinIS
    +			&& $word =~ m/
    +		^([a-z_]{2,})                 # The function name
    +		\(
    +		    ([0-9][a-z]*              # Manual page(1) or page(1M)
    +		    |[^)]*[\$\@\%][^)]+       # ($foo), (1, @foo), (%hash)
    +		    |                         # ()
    +		    )
    +		\)
    +		([.,;]?)$                     # a possible punctuation follows
    +	    /xi
    +			)
    +		{
    +
    +			# has parenthesis so should have been a C<> ref
    +			## try for a pagename (perlXXX(1))?
    +			my ( $func, $args, $rest ) = ( $1, $2, $3 || '' );
    +			if ( $args =~ /^\d+$/ ) {
    +				my $url = page_sect( $word, '' );
    +				if ( defined $url ) {
    +					$word =
    +qq(the $word manpage$rest);
    +					next;
    +				}
    +			}
    +			## try function name for a link, append tt'ed argument list
    +			$word = emit_C( $func, '', "($args)" ) . $rest;
    +
    +#### disabled. either all (including $\W, $\w+{.*} etc.) or nothing.
    +##      } elsif( $notinIS && $word =~ /^[\$\@%&*]+\w+$/) {
    +##	    # perl variables, should be a C<> ref
    +##	    $word = emit_C( $word );
    +
    +		} elsif ( $word =~ m,^\w+://\w, ) {
    +
    +			# looks like a URL
    +			# Don't relativize it: leave it as the author intended
    +			$word = qq($word);
    +		} elsif ( $word =~ /[\w.-]+\@[\w-]+\.\w/ ) {
    +
    +			# looks like an e-mail address
    +			my ( $w1, $w2, $w3 ) = ( "", $word, "" );
    +			( $w1, $w2, $w3 ) = ( "(", $1, ")$2" ) if $word =~ /^\((.*?)\)(,?)/;
    +			( $w1, $w2, $w3 ) = ( "<", $1, ">$2" )
    +				if $word =~ /^<(.*?)>(,?)/;
    +			$word = qq($w1$w2$w3);
    +		} else {
    +			$word = html_escape($word) if $word =~ /["&<>]/;
    +		}
    +	}
    +
    +	# put everything back together
    +	return $lead . join( '', @words ) . $trail;
    +}
    +
    +#
    +# process_text - handles plaintext that appears in the input pod file.
    +# there may be pod commands embedded within the text so those must be
    +# converted to html commands.
    +#
    +
    +sub process_text1($$;$$);
    +sub pattern ($) { $_[0] ? '\s+' . ( '>' x ( $_[0] + 1 ) ) : '>' }
    +sub closing ($) { local ($_) = shift; ( defined && s/\s+\z// ) ? length : 0 }
    +
    +sub process_text {
    +	return if $Ignore;
    +	my ($tref) = @_;
    +	my $res = process_text1( 0, $tref );
    +	$res =~ s/\s+$//s;
    +	$$tref = $res;
    +}
    +
    +sub process_text_rfc_links {
    +	my $text = shift;
    +
    +	# For every "RFCnnnn" or "RFC nnn", link it to the authoritative
    +	# ource. Do not use the /i modifier here. Require "RFC" to be written in
    +	#  in capital letters.
    +
    +	$text =~ s{
    +	(?<=[^<>[:alpha:]])           # Make sure this is not an URL already
    +	(RFC\s*([0-9]{1,5}))(?![0-9]) # max 5 digits
    +    }
    +    {$1}gx;
    +
    +	$text;
    +}
    +
    +sub process_text1($$;$$) {
    +	my ( $lev, $rstr, $func, $closing ) = @_;
    +	my $res = '';
    +
    +	unless ( defined $func ) {
    +		$func = '';
    +		$lev++;
    +	}
    +
    +	if ( $func eq 'B' ) {
    +
    +		# B - boldface
    +		$res = '' . process_text1( $lev, $rstr ) . '';
    +
    +	} elsif ( $func eq 'C' ) {
    +
    +		# C - can be a ref or 
    +		# need to extract text
    +		my $par = go_ahead( $rstr, 'C', $closing );
    +
    +		## clean-up of the link target
    +		my $text = depod($par);
    +
    +		### my $x = $par =~ /[BI]call emit_C($par) lev=$lev, par with BI=$x\n";
    +
    +		$res = emit_C( $text, $lev > 1 || ( $par =~ /[BI] - convert to character
    +		$$rstr =~ s/^([^>]*)>//;
    +		my $escape = $1;
    +		$escape =~ s/^(\d+|X[\dA-F]+)$/#$1/i;
    +		$res = "&$escape;";
    +
    +	} elsif ( $func eq 'F' ) {
    +
    +		# F - italicize
    +		$res = '' . process_text1( $lev, $rstr ) . '';
    +
    +	} elsif ( $func eq 'I' ) {
    +
    +		# I - italicize
    +		$res = '' . process_text1( $lev, $rstr ) . '';
    +
    +	} elsif ( $func eq 'L' ) {
    +
    +		# L - link
    +		## L => produce text, use cross-ref for linking
    +		## L => make text from cross-ref
    +		## need to extract text
    +		my $par = go_ahead( $rstr, 'L', $closing );
    +
    +		# some L<>'s that shouldn't be:
    +		# a) full-blown URL's are emitted as-is
    +		if ( $par =~ m{^\w+://}s ) {
    +			return make_URL_href($par);
    +		}
    +
    +		# b) C<...> is stripped and treated as C<>
    +		if ( $par =~ /^C<(.*)>$/ ) {
    +			my $text = depod($1);
    +			return emit_C( $text, $lev > 1 || ( $par =~ /[BI] L<$par> to page $page, ident $ident\n";
    +
    +		} elsif ( $par =~ m{^(.*?)/"?(.*?)"?$} ) {    # [name]/"section"
    +			    # even though this should be a "section", we go for ident first
    +			( $page, $ident ) = ( $1, $2 );
    +			### print STDERR "--> L<$par> to page $page, section $section\n";
    +
    +		} elsif ( $par =~ /\s/ ) {  # this must be a section with missing quotes
    +			( $page, $section ) = ( '', $par );
    +			### print STDERR "--> L<$par> to void page, section $section\n";
    +
    +		} else {
    +			( $page, $section ) = ( $par, '' );
    +			### print STDERR "--> L<$par> to page $par, void section\n";
    +		}
    +
    +		# now, either $section or $ident is defined. the convoluted logic
    +		# below tries to resolve L<> according to what the user specified.
    +		# failing this, we try to find the next best thing...
    +		my ( $url, $ltext, $fid );
    +
    +	RESOLVE: {
    +			if ( defined $ident ) {
    +				## try to resolve $ident as an item
    +				( $url, $fid ) = coderef( $page, $ident );
    +				if ($url) {
    +					if ( !defined($linktext) ) {
    +						$linktext = $ident;
    +						$linktext .= " in " if $ident && $page;
    +						$linktext .= "the $page manpage" if $page;
    +					}
    +					###  print STDERR "got coderef url=$url\n";
    +					last RESOLVE;
    +				}
    +				## no luck: go for a section (auto-quoting!)
    +				$section = $ident;
    +			}
    +			## now go for a section
    +			my $htmlsection = htmlify($section);
    +			$url = page_sect( $page, $htmlsection );
    +			if ($url) {
    +				if ( !defined($linktext) ) {
    +					$linktext = $section;
    +					$linktext .= " in " if $section && $page;
    +					$linktext .= "the $page manpage" if $page;
    +				}
    +				### print STDERR "got page/section url=$url\n";
    +				last RESOLVE;
    +			}
    +			## no luck: go for an ident
    +			if ($section) {
    +				$ident = $section;
    +			} else {
    +				$ident = $page;
    +				$page  = undef();
    +			}
    +			( $url, $fid ) = coderef( $page, $ident );
    +			if ($url) {
    +				if ( !defined($linktext) ) {
    +					$linktext = $ident;
    +					$linktext .= " in " if $ident && $page;
    +					$linktext .= "the $page manpage" if $page;
    +				}
    +				### print STDERR "got section=>coderef url=$url\n";
    +				last RESOLVE;
    +			}
    +
    +			# warning; show some text.
    +			$linktext = $opar unless defined $linktext;
    +			warn
    +"$0: $Podfile: cannot resolve L<$opar> in paragraph $Paragraph.\n"
    +				unless $Quiet;
    +		}
    +
    +		# now we have a URL or just plain code
    +		$$rstr = $linktext . '>' . $$rstr;
    +		if ( defined($url) ) {
    +			$res = "" . process_text1( $lev, $rstr ) . '';
    +		} else {
    +			$res = '' . process_text1( $lev, $rstr ) . '';
    +		}
    +
    +	} elsif ( $func eq 'S' ) {
    +
    +		# S - non-breaking spaces
    +		$res = process_text1( $lev, $rstr );
    +		$res =~ s/ / /g;
    +
    +	} elsif ( $func eq 'X' ) {
    +
    +		# X<> - ignore
    +		warn "$0: $Podfile: invalid X<> in paragraph $Paragraph.\n"
    +			unless $$rstr =~ s/^[^>]*>//
    +				or $Quiet;
    +	} elsif ( $func eq 'Z' ) {
    +
    +		# Z<> - empty
    +		warn "$0: $Podfile: invalid Z<> in paragraph $Paragraph.\n"
    +			unless $$rstr =~ s/^>//
    +				or $Quiet;
    +
    +	} else {
    +		my $term = pattern $closing;
    +		while ( $$rstr =~ s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|$term)//s ) {
    +
    +			# all others: either recurse into new function or
    +			# terminate at closing angle bracket(s)
    +			my $pt = $1;
    +			$pt .= $2 if !$3 && $lev == 1;
    +			$res .= $lev == 1 ? pure_text($pt) : inIS_text($pt);
    +			return $res if !$3 && $lev > 1;
    +			if ($3) {
    +				$res .= process_text1( $lev, $rstr, $3, closing $4 );
    +			}
    +		}
    +		if ( $lev == 1 ) {
    +			$res .= pure_text($$rstr);
    +		} elsif ( !$Quiet ) {
    +			my $snippet = substr( $$rstr, 0, 60 );
    +			warn
    +"$0: $Podfile: undelimited $func<> in paragraph $Paragraph: '$snippet'.\n"
    +
    +		}
    +		$res = process_text_rfc_links($res);
    +	}
    +	return $res;
    +}
    +
    +#
    +# go_ahead: extract text of an IS (can be nested)
    +#
    +sub go_ahead($$$) {
    +	my ( $rstr, $func, $closing ) = @_;
    +	my $res     = '';
    +	my @closing = ($closing);
    +	while ( $$rstr =~
    +		s/\A(.*?)(([BCEFILSXZ])<(<+\s+)?|@{[pattern $closing[0]]})//s )
    +	{
    +		$res .= $1;
    +		unless ($3) {
    +			shift @closing;
    +			return $res unless @closing;
    +		} else {
    +			unshift @closing, closing $4;
    +		}
    +		$res .= $2;
    +	}
    +	unless ($Quiet) {
    +		my $snippet = substr( $$rstr, 0, 60 );
    +		warn
    +"$0: $Podfile: undelimited $func<> in paragraph $Paragraph (go_ahead): '$snippet'.\n";
    +	}
    +	return $res;
    +}
    +
    +#
    +# emit_C - output result of C
    +#    $text is the depod-ed text
    +#
    +sub emit_C($;$$) {
    +	my ( $text, $nocode, $args ) = @_;
    +	$args = '' unless defined $args;
    +	my $res;
    +	my ( $url, $fid ) = coderef( undef(), $text );
    +
    +	# need HTML-safe text
    +	my $linktext = html_escape("$text$args");
    +
    +	if ( $text !~ /^[\$@%]/
    +		&& defined($url)
    +		&& ( !defined($EmittedItem) || $EmittedItem ne $fid ) )
    +	{
    +		$res = "$linktext";
    +	} elsif ( 0 && $nocode ) {
    +		$res = $linktext;
    +	} else {
    +		$res = "$linktext";
    +	}
    +	return $res;
    +}
    +
    +#
    +# html_escape: make text safe for HTML
    +#
    +sub html_escape {
    +	my $rest = $_[0];
    +	$rest =~ s/&/&/g;
    +	$rest =~ s//>/g;
    +	$rest =~ s/"/"/g;
    +
    +	# ' is only in XHTML, not HTML4.  Be conservative
    +	#$rest   =~ s/'/'/g;
    +	return $rest;
    +}
    +
    +#
    +# dosify - convert filenames to 8.3
    +#
    +sub dosify {
    +	my ($str) = @_;
    +	return lc($str) if $^O eq 'VMS';    # VMS just needs casing
    +	if ($Is83) {
    +		$str = lc $str;
    +		$str =~ s/(\.\w+)/substr ($1,0,4)/ge;
    +		$str =~ s/(\w+)/substr ($1,0,8)/ge;
    +	}
    +	return $str;
    +}
    +
    +#
    +# page_sect - make a URL from the text of a L<>
    +#
    +sub page_sect($$) {
    +	my ( $page, $section ) = @_;
    +	my ( $linktext, $page83, $link );    # work strings
    +
    +	# check if we know that this is a section in this page
    +	if ( !defined $Pages{$page} && defined $Sections{$page} ) {
    +		$section = $page;
    +		$page    = "";
    +		### print STDERR "reset page='', section=$section\n";
    +	}
    +
    +	$page83 = dosify($page);
    +	$page = $page83 if ( defined $Pages{$page83} );
    +	if ( $page eq "" ) {
    +		$link = "#" . anchorify($section);
    +	} elsif ( $page =~ /::/ ) {
    +		$page =~ s,::,/,g;
    +
    +		# Search page cache for an entry keyed under the html page name,
    +		# then look to see what directory that page might be in.  NOTE:
    +		# this will only find one page. A better solution might be to produce
    +		# an intermediate page that is an index to all such pages.
    +		my $page_name = $page;
    +		$page_name =~ s,^.*/,,s;
    +		if ( defined( $Pages{$page_name} )
    +			&& $Pages{$page_name} =~ /([^:]*$page)\.(?:pod|pm):/ )
    +		{
    +			$page = $1;
    +		} else {
    +
    +			# NOTE: This branch assumes that all A::B pages are located in
    +			# $Htmlroot/A/B.html . This is often incorrect, since they are
    +			# often in $Htmlroot/lib/A/B.html or such like. Perhaps we could
    +			# analyze the contents of %Pages and figure out where any
    +			# cousins of A::B are, then assume that.  So, if A::B isn't found,
    +			# but A::C is found in lib/A/C.pm, then A::B is assumed to be in
    +			# lib/A/B.pm. This is also limited, but it's an improvement.
    +			# Maybe a hints file so that the links point to the correct places
    +			# nonetheless?
    +
    +		}
    +		$link = "$Htmlroot/$page.html";
    +		$link .= "#" . anchorify($section) if ($section);
    +	} elsif ( !defined $Pages{$page} ) {
    +		$link = "";
    +	} else {
    +		$section = anchorify($section) if $section ne "";
    +		### print STDERR "...section=$section\n";
    +
    +		# if there is a directory by the name of the page, then assume that an
    +		# appropriate section will exist in the subdirectory
    +		#	if ($section ne "" && $Pages{$page} =~ /([^:]*[^(\.pod|\.pm)]):/) {
    +		if ( $section ne "" && $Pages{$page} =~ /([^:]*(?, Foo.(pod|pm) is preferred to A/Foo.(pod|pm)
    +			if ( $Pages{$page} =~ /([^:]*)\.(?:pod|pm):/ ) {
    +				$link = "$Htmlroot/$1.html$section";
    +			} else {
    +				$link = "";
    +			}
    +		}
    +	}
    +
    +	if ($link) {
    +
    +		# Here, we take advantage of the knowledge that $Htmlfileurl ne ''
    +		# implies $Htmlroot eq ''. This means that the link in question
    +		# needs a prefix of $Htmldir if it begins with '/'. The test for
    +		# the initial '/' is done to avoid '#'-only links, and to allow
    +		# for other kinds of links, like file:, ftp:, etc.
    +		my $url;
    +		if ( $Htmlfileurl ne '' ) {
    +			$link = "$Htmldir$link" if $link =~ m{^/}s;
    +			$url = relativize_url( $link, $Htmlfileurl );
    +
    +			# print( "  b: [$link,$Htmlfileurl,$url]\n" );
    +		} else {
    +			$url = $link;
    +		}
    +		return $url;
    +
    +	} else {
    +		return undef();
    +	}
    +}
    +
    +#
    +# relativize_url - convert an absolute URL to one relative to a base URL.
    +# Assumes both end in a filename.
    +#
    +sub relativize_url {
    +	my ( $dest, $source ) = @_;
    +
    +	my ( $dest_volume, $dest_directory, $dest_file ) =
    +		File::Spec::Unix->splitpath($dest);
    +	$dest = File::Spec::Unix->catpath( $dest_volume, $dest_directory, '' );
    +
    +	my ( $source_volume, $source_directory, $source_file ) =
    +		File::Spec::Unix->splitpath($source);
    +	$source =
    +		File::Spec::Unix->catpath( $source_volume, $source_directory, '' );
    +
    +	my $rel_path = '';
    +	if ( $dest ne '' ) {
    +		$rel_path = File::Spec::Unix->abs2rel( $dest, $source );
    +	}
    +
    +	if (   $rel_path ne ''
    +		&& substr( $rel_path, -1 ) ne '/'
    +		&& substr( $dest_file, 0, 1 ) ne '#' )
    +	{
    +		$rel_path .= "/$dest_file";
    +	} else {
    +		$rel_path .= "$dest_file";
    +	}
    +
    +	return $rel_path;
    +}
    +
    +#
    +# coderef - make URL from the text of a C<>
    +#
    +sub coderef($$) {
    +	my ( $page, $item ) = @_;
    +	my ($url);
    +
    +	my $fid = fragment_id($item);
    +
    +	if ( defined($page) && $page ne "" ) {
    +
    +		# we have been given a $page...
    +		$page =~ s{::}{/}g;
    +
    +		Carp::confess(
    +"Undefined fragment '$item' from fragment_id() in coderef() in $Podfile"
    +		) if !defined $fid;
    +
    +		# Do we take it? Item could be a section!
    +		my $base = $Items{$fid} || "";
    +		$base =~ s{[^/]*/}{};
    +		if ( $base ne "$page.html" ) {
    +			###   print STDERR "coderef( $page, $item ): items{$fid} = $Items{$fid} = $base => discard page!\n";
    +			$page = undef();
    +		}
    +
    +	} else {
    +
    +		# no page - local items precede cached items
    +		if ( defined($fid) ) {
    +			if ( exists $Local_Items{$fid} ) {
    +				$page = $Local_Items{$fid};
    +			} else {
    +				$page = $Items{$fid};
    +			}
    +		}
    +	}
    +
    +	# if there was a pod file that we found earlier with an appropriate
    +	# =item directive, then create a link to that page.
    +	if ( defined $page ) {
    +		if ($page) {
    +			if ( exists $Pages{$page} and $Pages{$page} =~ /([^:.]*)\.[^:]*:/ )
    +			{
    +				$page = $1 . '.html';
    +			}
    +			my $link = "$Htmlroot/$page#" . anchorify($fid);
    +
    +			# Here, we take advantage of the knowledge that $Htmlfileurl
    +			# ne '' implies $Htmlroot eq ''.
    +			if ( $Htmlfileurl ne '' ) {
    +				$link = "$Htmldir$link";
    +				$url = relativize_url( $link, $Htmlfileurl );
    +			} else {
    +				$url = $link;
    +			}
    +		} else {
    +			$url = "#" . anchorify($fid);
    +		}
    +
    +		confess "url has space: $url" if $url =~ /"[^"]*\s[^"]*"/;
    +	}
    +	return ( $url, $fid );
    +}
    +
    +#
    +# Adapted from Nick Ing-Simmons' PodToHtml package.
    +sub relative_url {
    +	my $source_file      = shift;
    +	my $destination_file = shift;
    +
    +	my $source = URI::file->new_abs($source_file);
    +	my $uo = URI::file->new( $destination_file, $source )->abs;
    +	return $uo->rel->as_string;
    +}
    +
    +#
    +# finish_list - finish off any pending HTML lists.  this should be called
    +# after the entire pod file has been read and converted.
    +#
    +sub finish_list {
    +	while ( $Listlevel > 0 ) {
    +		print HTML "\n";
    +		$Listlevel--;
    +	}
    +}
    +
    +#
    +# htmlify - converts a pod section specification to a suitable section
    +# specification for HTML. Note that we keep spaces and special characters
    +# except ", ? (Netscape problem) and the hyphen (writer's problem...).
    +#
    +sub htmlify {
    +	my ($heading) = @_;
    +	$heading =~ s/(\s+)/ /g;
    +	$heading =~ s/\s+\Z//;
    +	$heading =~ s/\A\s+//;
    +
    +	# The hyphen is a disgrace to the English language.
    +	# $heading =~ s/[-"?]//g;
    +	$heading =~ s/["?]//g;
    +	$heading = lc($heading);
    +	return $heading;
    +}
    +
    +#
    +# similar to htmlify, but turns non-alphanumerics into underscores
    +#
    +sub anchorify {
    +	my ($anchor) = @_;
    +	$anchor =~ s/\([^)]*\)//;
    +	$anchor = htmlify($anchor);
    +	$anchor =~ s/\W/_/g;
    +	$anchor =~ tr/_/_/s;
    +	return $anchor;
    +}
    +
    +#
    +# depod - convert text by eliminating all interior sequences
    +# Note: can be called with copy or modify semantics
    +#
    +my %E2c;
    +$E2c{lt}     = '<';
    +$E2c{gt}     = '>';
    +$E2c{sol}    = '/';
    +$E2c{verbar} = '|';
    +$E2c{amp}    = '&';    # in Tk's pods
    +
    +sub depod1($;$$);
    +
    +sub depod($) {
    +	my $string;
    +	if ( ref( $_[0] ) ) {
    +		$string = ${ $_[0] };
    +		${ $_[0] } = depod1( \$string );
    +	} else {
    +		$string = $_[0];
    +		depod1( \$string );
    +	}
    +}
    +
    +sub depod1($;$$) {
    +	my ( $rstr, $func, $closing ) = @_;
    +	my $res = '';
    +	return $res unless defined $$rstr;
    +	if ( !defined($func) ) {
    +
    +		# skip to next begin of an interior sequence
    +		while ( $$rstr =~ s/\A(.*?)([BCEFILSXZ])<(<+[^\S\n]+)?//s ) {
    +
    +			# recurse into its text
    +			$res .= $1 . depod1( $rstr, $2, closing $3);
    +		}
    +		$res .= $$rstr;
    +	} elsif ( $func eq 'E' ) {
    +
    +		# E - convert to character
    +		$$rstr =~ s/^([^>]*)>//;
    +		$res .= $E2c{$1} || "";
    +	} elsif ( $func eq 'X' ) {
    +
    +		# X<> - ignore
    +		$$rstr =~ s/^[^>]*>//;
    +	} elsif ( $func eq 'Z' ) {
    +
    +		# Z<> - empty
    +		$$rstr =~ s/^>//;
    +	} else {
    +
    +		# all others: either recurse into new function or
    +		# terminate at closing angle bracket
    +		my $term = pattern $closing;
    +		while ( $$rstr =~ s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|$term)//s ) {
    +			$res .= $1;
    +			last unless $3;
    +			$res .= depod1( $rstr, $3, closing $4 );
    +		}
    +		## If we're here and $2 ne '>': undelimited interior sequence.
    +		## Ignored, as this is called without proper indication of where we are.
    +		## Rely on process_text to produce diagnostics.
    +	}
    +	return $res;
    +}
    +
    +{
    +	my %seen;    # static fragment record hash
    +
    +	sub fragment_id_readable {
    +		my $text     = shift;
    +		my $generate = shift;    # optional flag
    +
    +		my $orig = $text;
    +
    +		# leave the words for the fragment identifier,
    +		# change everything else to underbars.
    +		$text =~
    +			s/[^A-Za-z0-9_]+/_/g;    # do not use \W to avoid locale dependency.
    +		$text =~ s/_{2,}/_/g;
    +		$text =~ s/\A_//;
    +		$text =~ s/_\Z//;
    +
    +		unless ($text) {
    +
    +			# Nothing left after removing punctuation, so leave it as is
    +			# E.g. if option is named: "=item -#"
    +
    +			$text = $orig;
    +		}
    +
    +		if ($generate) {
    +			if ( exists $seen{$text} ) {
    +
    +				# This already exists, make it unique
    +				$seen{$text}++;
    +				$text = $text . $seen{$text};
    +			} else {
    +				$seen{$text} = 1;    # first time seen this fragment
    +			}
    +		}
    +
    +		$text;
    +	}
    +}
    +
    +my @HC;
    +
    +sub fragment_id_obfuscated {         # This was the old "_2d_2d__"
    +	my $text     = shift;
    +	my $generate = shift;            # optional flag
    +
    +	# text? Normalize by obfuscating the fragment id to make it unique
    +	$text =~ s/\s+/_/sg;
    +
    +	$text =~ s{(\W)}{
    +        defined( $HC[ord($1)] ) ? $HC[ord($1)]
    +        : ( $HC[ord($1)] = sprintf( "%%%02X", ord($1) ) ) }gxe;
    +	$text = substr( $text, 0, 50 );
    +
    +	$text;
    +}
    +
    +#
    +# fragment_id - construct a fragment identifier from:
    +#   a) =item text
    +#   b) contents of C<...>
    +#
    +
    +sub fragment_id {
    +	my $text     = shift;
    +	my $generate = shift;    # optional flag
    +
    +	$text =~ s/\s+\Z//s;
    +	if ($text) {
    +
    +		# a method or function?
    +		return $1 if $text =~ /(\w+)\s*\(/;
    +		return $1 if $text =~ /->\s*(\w+)\s*\(?/;
    +
    +		# a variable name?
    +		return $1 if $text =~ /^([\$\@%*]\S+)/;
    +
    +		# some pattern matching operator?
    +		return $1 if $text =~ m|^(\w+/).*/\w*$|;
    +
    +		# fancy stuff... like "do { }"
    +		return $1 if $text =~ m|^(\w+)\s*{.*}$|;
    +
    +		# honour the perlfunc manpage: func [PAR[,[ ]PAR]...]
    +		# and some funnies with ... Module ...
    +		return $1 if $text =~ m{^([a-z\d_]+)(\s+[A-Z,/& ][A-Z\d,/& ]*)?$};
    +		return $1 if $text =~ m{^([a-z\d]+)\s+Module(\s+[A-Z\d,/& ]+)?$};
    +
    +		return fragment_id_readable( $text, $generate );
    +	} else {
    +		return;
    +	}
    +}
    +
    +#
    +# make_URL_href - generate HTML href from URL
    +# Special treatment for CGI queries.
    +#
    +sub make_URL_href($;$) {
    +	my ($url) = shift;
    +	my $linktext = shift || $url;
    +	if ( $url !~ s{^(http:[-\w/#~:.+=&%@!]+)(\?.*)$}{$1}i ) {
    +		$url = "$linktext";
    +	}
    +	return $url;
    +}
    +
    +1;
    diff --git a/plugins/perl/lib/Xchat.pm b/plugins/perl/lib/Xchat.pm
    new file mode 100644
    index 00000000..74914882
    --- /dev/null
    +++ b/plugins/perl/lib/Xchat.pm
    @@ -0,0 +1,506 @@
    +BEGIN {
    +	$INC{'Xchat.pm'} = 'DUMMY';
    +}
    +
    +$SIG{__WARN__} = sub {
    +	my $message = shift @_;
    +	my ($package) = caller;
    +	
    +	# redirect Gtk/Glib errors and warnings back to STDERR
    +	my $message_levels =	qr/ERROR|CRITICAL|WARNING|MESSAGE|INFO|DEBUG/i;
    +	if( $message =~ /^(?:Gtk|GLib|Gdk)(?:-\w+)?-$message_levels/i ) {
    +		print STDERR $message;
    +	} else {
    +
    +		if( defined &Xchat::Internal::print ) {
    +			Xchat::print( $message );
    +		} else {
    +			warn $message;
    +		}
    +	}
    +};
    +
    +use File::Spec ();
    +use File::Basename ();
    +use File::Glob ();
    +use List::Util ();
    +use Symbol();
    +use Time::HiRes ();
    +use Carp ();
    +
    +package Xchat;
    +use base qw(Exporter);
    +use strict;
    +use warnings;
    +
    +sub PRI_HIGHEST ();
    +sub PRI_HIGH ();
    +sub PRI_NORM ();
    +sub PRI_LOW ();
    +sub PRI_LOWEST ();
    +
    +sub EAT_NONE ();
    +sub EAT_XCHAT ();
    +sub EAT_PLUIN ();
    +sub EAT_ALL ();
    +
    +sub KEEP ();
    +sub REMOVE ();
    +sub FD_READ ();
    +sub FD_WRITE ();
    +sub FD_EXCEPTION ();
    +sub FD_NOTSOCKET ();
    +
    +sub get_context;
    +sub Xchat::Internal::context_info;
    +sub Xchat::Internal::print;
    +
    +our %EXPORT_TAGS = (
    +	constants => [
    +		qw(PRI_HIGHEST PRI_HIGH PRI_NORM PRI_LOW PRI_LOWEST), # priorities
    +		qw(EAT_NONE EAT_XCHAT EAT_PLUGIN EAT_ALL), # callback return values
    +		qw(FD_READ FD_WRITE FD_EXCEPTION FD_NOTSOCKET), # fd flags
    +		qw(KEEP REMOVE), # timers
    +	],
    +	hooks => [
    +		qw(hook_server hook_command hook_print hook_timer hook_fd unhook),
    +	],
    +	util => [
    +		qw(register nickcmp strip_code send_modes), # misc
    +		qw(print prnt printf prntf command commandf emit_print), # output
    +		qw(find_context get_context set_context), # context
    +		qw(get_info get_prefs get_list context_info user_info), # input
    +	],
    +);
    +
    +$EXPORT_TAGS{all} = [ map { @{$_} } @EXPORT_TAGS{qw(constants hooks util)}];
    +our @EXPORT = @{$EXPORT_TAGS{constants}};
    +our @EXPORT_OK = @{$EXPORT_TAGS{all}};
    +
    +sub register {
    +	my $package = Xchat::Embed::find_pkg();
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +	my $filename = $pkg_info->{filename};
    +	my ($name, $version, $description, $callback) = @_;
    +	
    +	if( defined $pkg_info->{gui_entry} ) {
    +		Xchat::print( "Xchat::register called more than once in "
    +			. $pkg_info->{filename} );
    +		return ();
    +	}
    +	
    +	$description = "" unless defined $description;
    +	$pkg_info->{shutdown} = $callback;
    +	unless( $name && $name =~ /[[:print:]\w]/ ) {
    +		$name = "Not supplied";
    +	}
    +	unless( $version && $version =~ /\d+(?:\.\d+)?/ ) {
    +		$version = "NaN";
    +	}
    +	$pkg_info->{gui_entry} =
    +		Xchat::Internal::register( $name, $version, $description, $filename );
    +	# keep with old behavior
    +	return ();
    +}
    +
    +sub _process_hook_options {
    +	my ($options, $keys, $store) = @_;
    +
    +	unless( @$keys == @$store ) {
    +		die 'Number of keys must match the size of the store';
    +	}
    +
    +	my @results;
    +
    +	if( ref( $options ) eq 'HASH' ) {
    +		for my $index ( 0 .. @$keys - 1 ) {
    +			my $key = $keys->[$index];
    +			if( exists( $options->{ $key } ) && defined( $options->{ $key } ) ) {
    +				${$store->[$index]} = $options->{ $key };
    +			}
    +		}
    +	}
    +
    +}
    +
    +sub hook_server {
    +	return undef unless @_ >= 2;
    +	my $message = shift;
    +	my $callback = shift;
    +	my $options = shift;
    +	my $package = Xchat::Embed::find_pkg();
    +	
    +	$callback = Xchat::Embed::fix_callback( $package, $callback );
    +	
    +	my ($priority, $data) = ( Xchat::PRI_NORM, undef );
    +	_process_hook_options(
    +		$options,
    +		[qw(priority data)],
    +		[\($priority, $data)],
    +	);
    +	
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +	my $hook = Xchat::Internal::hook_server(
    +		$message, $priority, $callback, $data
    +	);
    +	push @{$pkg_info->{hooks}}, $hook if defined $hook;
    +	return $hook;
    +}
    +
    +sub hook_command {
    +	return undef unless @_ >= 2;
    +	my $command = shift;
    +	my $callback = shift;
    +	my $options = shift;
    +	my $package = Xchat::Embed::find_pkg();
    +
    +	$callback = Xchat::Embed::fix_callback( $package, $callback );
    +	
    +	my ($priority, $help_text, $data) = ( Xchat::PRI_NORM, undef, undef );
    +	_process_hook_options(
    +		$options,
    +		[qw(priority help_text data)],
    +		[\($priority, $help_text, $data)],
    +	);
    +	
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +	my $hook = Xchat::Internal::hook_command(
    +		$command, $priority, $callback, $help_text, $data
    +	);
    +	push @{$pkg_info->{hooks}}, $hook if defined $hook;
    +	return $hook;
    +}
    +
    +sub hook_print {
    +	return undef unless @_ >= 2;
    +	my $event = shift;
    +	my $callback = shift;
    +	my $options = shift;
    +	my $package = Xchat::Embed::find_pkg();
    +
    +	$callback = Xchat::Embed::fix_callback( $package, $callback );
    +	
    +	my ($priority, $run_after, $filter, $data) = ( Xchat::PRI_NORM, 0, 0, undef );
    +	_process_hook_options(
    +		$options,
    +		[qw(priority run_after_event filter data)],
    +		[\($priority, $run_after, $filter, $data)],
    +	);
    +	
    +	if( $run_after and $filter ) {
    +		Carp::carp( "Xchat::hook_print's run_after_event and filter options are mutually exclusive, you can only use of them at a time per hook" );
    +		return;
    +	}
    +
    +	if( $run_after ) {
    +		my $cb = $callback;
    +		$callback = sub {
    +			my @args = @_;
    +			hook_timer( 0, sub {
    +				$cb->( @args );
    +
    +				if( ref $run_after eq 'CODE' ) {
    +					$run_after->( @args );
    +				}
    +				return REMOVE;
    +			});
    +			return EAT_NONE;
    +		};
    +	}
    +
    +	if( $filter ) {
    +		my $cb = $callback;
    +		$callback = sub {
    +			my @args = @{$_[0]};
    +			my $last_arg = @args - 1;
    +
    +			my @new = $cb->( \@args, $_[1], $event );
    +
    +			# a filter can either return the new results or it can modify
    +			# @_ in place. 
    +			if( @new ) {
    +				emit_print( $event, @new[ 0 .. $last_arg ] );
    +				return EAT_ALL;
    +			} elsif(
    +				join( "\0", @{$_[0]} ) ne join( "\0", @args[ 0 .. $last_arg ] )
    +			) {
    +				emit_print( $event, @args[ 0 .. $last_arg ] );
    +				return EAT_ALL;
    +			}
    +
    +			return EAT_NONE;
    +		};
    +
    +	}
    +
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +	my $hook = Xchat::Internal::hook_print(
    +		$event, $priority, $callback, $data
    +	);
    +	push @{$pkg_info->{hooks}}, $hook if defined $hook;
    +	return $hook;
    +}
    +
    +sub hook_timer {
    +	return undef unless @_ >= 2;
    +	my ($timeout, $callback, $data) = @_;
    +	my $package = Xchat::Embed::find_pkg();
    +
    +	$callback = Xchat::Embed::fix_callback( $package, $callback );
    +
    +	if(
    +		ref( $data ) eq 'HASH' && exists( $data->{data} )
    +		&& defined( $data->{data} )
    +	) {
    +		$data = $data->{data};
    +	}
    +	
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +	my $hook = Xchat::Internal::hook_timer( $timeout, $callback, $data, $package );
    +	push @{$pkg_info->{hooks}}, $hook if defined $hook;
    +	return $hook;
    +}
    +
    +sub hook_fd {
    +	return undef unless @_ >= 2;
    +	my ($fd, $callback, $options) = @_;
    +	return undef unless defined $fd && defined $callback;
    +
    +	my $fileno = fileno $fd;
    +	return undef unless defined $fileno; # no underlying fd for this handle
    +	
    +	my ($package) = Xchat::Embed::find_pkg();
    +	$callback = Xchat::Embed::fix_callback( $package, $callback );
    +	
    +	my ($flags, $data) = (Xchat::FD_READ, undef);
    +	_process_hook_options(
    +		$options,
    +		[qw(flags data)],
    +		[\($flags, $data)],
    +	);
    +	
    +	my $cb = sub {
    +		my $userdata = shift;
    +		return $userdata->{CB}->(
    +			$userdata->{FD}, $userdata->{FLAGS}, $userdata->{DATA},
    +		);
    +	};
    +	
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +	my $hook = Xchat::Internal::hook_fd(
    +		$fileno, $cb, $flags, {
    +			DATA => $data, FD => $fd, CB => $callback, FLAGS => $flags,
    +		}
    +	);
    +	push @{$pkg_info->{hooks}}, $hook if defined $hook;
    +	return $hook;
    +}
    +
    +sub unhook {
    +	my $hook = shift @_;
    +	my $package = shift @_;
    +	($package) = caller unless $package;
    +	my $pkg_info = Xchat::Embed::pkg_info( $package );
    +
    +	if( defined( $hook )
    +		&& $hook =~ /^\d+$/
    +		&& grep { $_ == $hook } @{$pkg_info->{hooks}} ) {
    +		$pkg_info->{hooks} = [grep { $_ != $hook } @{$pkg_info->{hooks}}];
    +		return Xchat::Internal::unhook( $hook );
    +	}
    +	return ();
    +}
    +
    +sub _do_for_each {
    +	my ($cb, $channels, $servers) = @_;
    +
    +	# not specifying any channels or servers is not the same as specifying
    +	# undef for both
    +	# - not specifying either results in calling the callback inthe current ctx
    +	# - specifying undef for for both results in calling the callback in the
    +	#   front/currently selected tab
    +	if( @_ == 3 && !($channels || $servers) ) { 
    +		$channels = [ undef ];
    +		$servers = [ undef ];
    +	} elsif( !($channels || $servers) ) {
    +		$cb->();
    +		return 1;
    +	}
    +
    +	$channels = [ $channels ] unless ref( $channels ) eq 'ARRAY';
    +
    +	if( $servers ) {
    +		$servers = [ $servers ] unless ref( $servers ) eq 'ARRAY';
    +	} else {
    +		$servers = [ undef ];
    +	}
    +
    +	my $num_done = 0;
    +	my $old_ctx = Xchat::get_context();
    +	for my $server ( @$servers ) {
    +		for my $channel ( @$channels ) {
    +			if( Xchat::set_context( $channel, $server ) ) {
    +				$cb->();
    +				$num_done++
    +			}
    +		}
    +	}
    +	Xchat::set_context( $old_ctx );
    +	return $num_done;
    +}
    +
    +sub print {
    +	my $text = shift @_;
    +	return "" unless defined $text;
    +	if( ref( $text ) eq 'ARRAY' ) {
    +		if( $, ) {
    +			$text = join $, , @$text;
    +		} else {
    +			$text = join "", @$text;
    +		}
    +	}
    +	
    +	return _do_for_each(
    +		sub { Xchat::Internal::print( $text ); },
    +		@_
    +	);
    +}
    +
    +sub printf {
    +	my $format = shift;
    +	Xchat::print( sprintf( $format, @_ ) );
    +}
    +
    +# make Xchat::prnt() and Xchat::prntf() as aliases for Xchat::print() and 
    +# Xchat::printf(), mainly useful when these functions are exported
    +sub prnt {
    +	goto &Xchat::print;
    +}
    +
    +sub prntf {
    +	goto &Xchat::printf;
    +}
    +
    +sub command {
    +	my $command = shift;
    +	return "" unless defined $command;
    +	my @commands;
    +	
    +	if( ref( $command ) eq 'ARRAY' ) {
    +		@commands = @$command;
    +	} else {
    +		@commands = ($command);
    +	}
    +	
    +	return _do_for_each(
    +		sub { Xchat::Internal::command( $_ ) foreach @commands },
    +		@_
    +	);
    +}
    +
    +sub commandf {
    +	my $format = shift;
    +	Xchat::command( sprintf( $format, @_ ) );
    +}
    +
    +sub set_context {
    +	my $context;
    +	if( @_ == 2 ) {
    +		my ($channel, $server) = @_;
    +		$context = Xchat::find_context( $channel, $server );
    +	} elsif( @_ == 1 ) {
    +		if( defined $_[0] && $_[0] =~ /^\d+$/ ) {
    +			$context = $_[0];
    +		} else {
    +			$context = Xchat::find_context( $_[0] );
    +		}
    +	} elsif( @_ == 0 ) {
    +		$context = Xchat::find_context();
    +	}
    +	return $context ? Xchat::Internal::set_context( $context ) : 0;
    +}
    +
    +sub get_info {
    +	my $id = shift;
    +	my $info;
    +	
    +	if( defined( $id ) ) {
    +		if( grep { $id eq $_ } qw(state_cursor id) ) {
    +			$info = Xchat::get_prefs( $id );
    +		} else {
    +			$info = Xchat::Internal::get_info( $id );
    +		}
    +	}
    +	return $info;
    +}
    +
    +sub user_info {
    +	my $nick = Xchat::strip_code(shift @_ || Xchat::get_info( "nick" ));
    +	my $user;
    +	for (Xchat::get_list( "users" ) ) {
    +		if ( Xchat::nickcmp( $_->{nick}, $nick ) == 0 ) {
    +			$user = $_;
    +			last;
    +		}
    +	}
    +	return $user;
    +}
    +
    +sub context_info {
    +	my $ctx = shift @_ || Xchat::get_context;
    +	my $old_ctx = Xchat::get_context;
    +	my @fields = (
    +		qw(away channel charset host id inputbox libdirfs modes network),
    +		qw(nick nickserv server topic version win_ptr win_status),
    +		qw(xchatdir xchatdirfs state_cursor),
    +	);
    +
    +	if( Xchat::set_context( $ctx ) ) {
    +		my %info;
    +		for my $field ( @fields ) {
    +			$info{$field} = Xchat::get_info( $field );
    +		}
    +		
    +		my $ctx_info = Xchat::Internal::context_info;
    +		@info{keys %$ctx_info} = values %$ctx_info;
    +		
    +		Xchat::set_context( $old_ctx );
    +		return %info if wantarray;
    +		return \%info;
    +	} else {
    +		return undef;
    +	}
    +}
    +
    +sub get_list {
    +	unless( grep { $_[0] eq $_ } qw(channels dcc ignore notify users networks) ) {
    +		Carp::carp( "'$_[0]' does not appear to be a valid list name" );
    +	}
    +	if( $_[0] eq 'networks' ) {
    +		return Xchat::List::Network->get();
    +	} else {
    +		return Xchat::Internal::get_list( $_[0] );
    +	}
    +}
    +
    +sub strip_code {
    +	my $pattern = qr<
    +		\cB| #Bold
    +		\cC\d{0,2}(?:,\d{1,2})?| #Color
    +		\e\[(?:\d{1,2}(?:;\d{1,2})*)?m| # ANSI color code
    +		\cG| #Beep
    +		\cO| #Reset
    +		\cV| #Reverse
    +		\c_  #Underline
    +	>x;
    +		
    +	if( defined wantarray ) {
    +		my $msg = shift;
    +		$msg =~ s/$pattern//g;
    +		return $msg;
    +	} else {
    +		$_[0] =~ s/$pattern//g if defined $_[0];
    +	}
    +}
    +
    +1
    diff --git a/plugins/perl/lib/Xchat.pod b/plugins/perl/lib/Xchat.pod
    new file mode 100644
    index 00000000..a55a9bce
    --- /dev/null
    +++ b/plugins/perl/lib/Xchat.pod
    @@ -0,0 +1,1326 @@
    +=head1 X-Chat 2 Perl Interface
    +
    +=head2 Introduction
    +
    +This is the new Perl interface for X-Chat 2.  However, due to changes in
    +xchat's plugin code you will need xchat 2.0.8 or above to load this.  Scripts
    +written using the old interface will continue to work. If there are any
    +problems, questions, comments or suggestions please email them to the address
    +on the bottom of this page.
    +
    +=head2 Constants
    +
    +=head3 Priorities
    +
    +=over 3
    +
    +=item *
    +C 
    +
    +=item *
    +C 
    +
    +=item *
    +C 
    +
    +=item *
    +C 
    +
    +=item *
    +C 
    +
    +=back
    +
    +=head3 Return values
    +
    +=over 3
    +
    +=item *
    +C     - pass the event along
    +
    +=item *
    +C    - don't let xchat see this event
    +
    +=item *
    +C   - don't let other scripts and plugins see this event but xchat will still see it
    +
    +=item *
    +C      - don't let anything else see this event
    +
    +=back
    +
    +=head4 Timer and fd hooks
    +
    +=over 3
    +
    +=item *
    +C         - keep the timer going or hook watching the handle
    +
    +=item *
    +C       - remove the timer or hook watching the handle
    +
    +=back
    +
    +=head3 hook_fd flags
    +
    +=over 3
    +
    +=item *
    +C			- invoke the callback when the handle is ready for reading
    +
    +=item *
    +C		- invoke the callback when the handle is ready for writing
    +
    +=item *
    +C	- invoke the callback if an exception occurs
    +
    +=item *
    +C	- indicate that the handle being hooked is not a socket
    +
    +=back
    +
    +=head2 Functions
    +
    +=head3 C 
    +
    +=over 3
    +
    +=item *
    +C<$name>             -  The name of this script
    +
    +=item *
    +C<$version>          -  This script's version
    +
    +=item *
    +C<$description>   -  A description for this script
    +
    +=item *
    +C<$callback>      -  This is a function that will be called when the is script
    +                     unloaded. This can be either a reference to a
    +                     function or an anonymous sub reference.
    +
    +=back
    +
    +This is the first thing to call in every script.
    +
    +=head3 C 
    +
    +=head3 C 
    +
    +=head3 C 
    +
    +=head3 C 
    +
    +=head3 C
    +
    +These functions can be to intercept various events.
    +hook_server can be used to intercept any incoming message from the IRC server.
    +hook_command can be used to intercept any command, if the command doesn't currently exist then a new one is created.
    +hook_print can be used to intercept any of the events listed in Setttings-EAdvanced-EText Events
    +hook_timer can be used to create a new timer
    +
    +
    +=over 3
    +
    +=item *
    +C<$message>       -  server message to hook such as PRIVMSG
    +
    +=item *
    +C<$command>       -  command to intercept, without the leading /
    +
    +=item *
    +C<$event>      -  one of the events listed in Settings-EAdvanced-EText Events
    +
    +=item *
    +C<$timeout>       -  timeout in milliseconds
    +
    +=item *
    +C<$handle>     - the I/O handle you want to monitor with hook_fd. This must be something that has a fileno. See perldoc -f fileno or L
    +
    +=item *
    +C<$callback>   -  callback function, this is called whenever
    +                  the hooked event is trigged, the following are
    +                  the conditions that will trigger the different hooks.
    +                  This can be either a reference to a
    +                  function or an anonymous sub reference.
    +
    +=item *
    +\%options   -  a hash reference containing addional options for the hooks
    +
    +=back
    +
    +Valid keys for \%options:
    +
    +=begin html
    +
    +
    +
    +   
    +   
    +   
    +
    +   
    +      
    +
    +   
    +
    +   
    +      
    +   
    +
    +   
    +      
    +   
    +
    +
    data Additional data that is to be associated with the
    + hook. For timer hooks this value can be provided either as
    + Xchat::hook_timer( $timeout, $cb,{data=>$data})
    + or Xchat::hook_timer( $timeout, $cb, $data ).
    + However, this means that hook_timer cannot be provided
    + with a hash reference containing data as a key.
    + + example:
    + my $options = { data => [@arrayOfStuff] };
    + Xchat::hook_timer( $timeout, $cb, $options );
    +
    + In this example, the timer's data will be
    + [@arrayOfStuff] and not { data => [@arrayOfStuff] }
    +
    + This key is valid for all of the hook functions.
    +
    + Default is undef.
    +
    priority Sets the priority for the hook.
    + It can be set to one of the + Xchat::PRI_* constants.
    +
    + This key only applies to server, command + and print hooks.
    +
    + Default is Xchat::PRI_NORM. +
    help_text Text displayed for /help $command.
    +
    + This key only applies to command hooks.
    +
    + Default is "". +
    flags Specify the flags for a fd hook.
    +
    + See hook fd flags section for valid values.
    +
    + On Windows if the handle is a pipe you specify
    + Xchat::FD_NOTSOCKET in addition to any other flags you might be using.
    +
    + This key only applies to fd hooks.
    + Default is Xchat::FD_READ +
    + +=end html + +=head4 When callbacks are invoked + +Each of the hooks will be triggered at different times depending on the type +of hook. + +=begin html + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Hook Type When the callback will be invoked
    server hooks a $message message is + received from the server +
    command hooks the $command command is + executed, either by the user or from a script +
    print hooks X-Chat is about to print the message for the + $event event +
    timer hooks called every $timeout milliseconds + (1000 millisecond is 1 second)
    + the callback will be executed in the same context where + the hook_timer was called, if the context no longer exists + then it will execute in a random context +
    fd hooks depends on the flags that were passed to hook_fd
    + See hook_fd flags section. +
    + +=end html + + +The value return from these hook functions can be passed to C +to remove the hook. + +=head4 Callback Arguments + +All callback functions will receive their arguments in C<@_> like every +other Perl subroutine. + +=begin html + +

    +Server and command callbacks
    +
    +$_[0] - array reference containing the IRC message or command and +arguments broken into words
    +example:
    +/command arg1 arg2 arg3
    +$_[0][0] - command
    +$_[0][1] - arg1
    +$_[0][2] - arg2
    +$_[0][3] - arg3
    +
    +$_[1] - array reference containing the Nth word to the last word
    +example:
    +/command arg1 arg2 arg3
    +$_[1][0] - command arg1 arg2 arg3
    +$_[1][1] - arg1 arg2 arg3
    +$_[1][2] - arg2 arg3
    +$_[1][3] - arg3
    +
    +$_[2] - the data that was passed to the hook function
    +
    +Print callbacks
    +
    +$_[0] - array reference containing the values for the + text event see Settings->Advanced->Text Events
    +$_[1] - the data that was passed to the hook function
    +
    +Timer callbacks
    +
    +$_[0] - the data that was passed to the hook function
    +
    + +fd callbacks
    +
    +$_[0] - the handle that was passed to hook_fd
    +$_[1] - flags indicating why the callback was called
    +$_[2] - the data that was passed to the hook function
    +

    + +=end html + +=head4 Callback return values + +All server, command and print callbacks should return one of +the C constants. +Timer callbacks can return Xchat::REMOVE to remove +the timer or Xchat::KEEP to keep it going + +=head4 Miscellaneous Hook Related Information + +For server hooks, if C<$message> is "RAW LINE" then C<$cb> will be called for +every IRC message than X-Chat receives. + +For command hooks if C<$command> is "" then C<$cb> will be called for +messages entered by the user that is not a command. + +For print hooks besides those events listed in +Settings-EAdvanced-EText Events, these additional events can be used. + +=begin html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Event Description
    "Open Context" a new context is created
    "Close Context" a context has been close
    "Focus Tab" when a tab is brought to the front
    "Focus Window" when a top level window is focused or the + main tab window is focused by the window manager +
    "DCC Chat Text" when text from a DCC Chat arrives. + $_[0] will have these values
    +
    + $_[0][0] - Address
    + $_[0][1] - Port
    + $_[0][2] - Nick
    + $_[0][3] - Message
    +
    "Key Press" used for intercepting key presses
    + $_[0][0] - key value
    + $_[0][1] - state bitfield, 1 - shift, 4 - control, 8 - alt
    + $_[0][2] - string version of the key which might be empty for unprintable keys
    + $_[0][3] - length of the string in $_[0][2]
    +
    + +=end html + +=head3 C + +=over 3 + +=item * +C<$hook> - the hook that was previously returned by one of the C functions + +=back + + +This function is used to removed a hook previously added with one of +the C functions + +It returns the data that was passed to the C function when +the hook was added + + +=head3 C + +=over 3 + +=item * +C<$text> - the text to print + +=item * +C<\@lines> - array reference containing lines of text to be printed + all the elements will be joined together before printing + +=item * +C<$channel> - channel or tab with the given name where C<$text> + will be printed + +=item * +C<$server> - specifies that the text will be printed in a channel or tab + that is associated with C<$server> + +=back + +The first argument can either be a string or an array reference of strings. +Either or both of C<$channel> and C<$server> can be undef. + +If called as C, it will always return true. +If called with either the channel or the channel and the server +specified then it will return true if a context is found and +false otherwise. The text will not be printed if the context +is not found. The meaning of setting C<$channel> or C<$server> to +undef is the same as +L. + + +=head3 C + +=over 3 + +=item * +C<$format> - a format string, see "perldoc -f L" for further detail + +=item * +LIST - list of values for the format fields + +=back + +=head3 C + +=over 3 + +=item * +C<$command> - the command to execute, without the leading / + +=item * +C<\@commands> - array reference containing a list of commands to execute + +=item * +C<$channel> - channel or tab with the given name where C<$command> will be executed + +=item * +C<$server> - specifies that the command will be executed in a channel or tab that is associated with C<$server> + +=back + +The first argument can either be a string or an array reference of strings. +Either or both of C<$channel> and C<$server> can be undef. + +If called as C, it will always return true. +If called with either the channel or the channel and the server +specified then it will return true if a context is found and false +otherwise. The command will not be executed if the context is not found. +The meaning of setting C<$channel> or C<$server> to undef is the same +as find_context. + + +=head3 C + +=over 3 + +=item * +C<$format> - a format string, see "perldoc -f L" for further detail + +=item * +LIST - list of values for the format fields + +=back + +=head3 C + +=over 3 + +=item * +C<$channel> - name of a channel + +=item * +C<$server> - name of a server + +=back + +Either or both of C<$channel> and $server can be undef. Calling +C is the same as calling +C and +C is +the same as C. + +If C<$server> is undef, find any channel named $channel. +If C<$channel> is undef, find the front most window +or tab named C<$server>.If both $channel and +C<$server> are undef, find the currently focused tab or window. + +Return the context found for one of the above situations or undef if such +a context cannot be found. + + +=head3 C + +=over 3 + +=back + +Returns the current context. + +=head3 C + +=over 3 + +=item * +C<$context> - context value as returned from L,L or one + of the fields in the list of hashrefs returned by list_get + +=item * +C<$channel> - name of a channel you want to switch context to + +=item * +C<$server> - name of a server you want to switch context to + +=back + +See L for more details on C<$channel> and C<$server>. + +Returns true on success, false on failure + +=head3 C + +=over 3 + +=item * +C<$id> - one of the following case sensitive values + +=back + +=begin html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ID Return value
    away away reason or undef if you are not away
    channel current channel name
    charset character-set used in the current context
    event_text <Event Name> text event format string for <Event name>
    + Example: +
    + my $channel_msg_format = Xchat::get_info( "event_text Channel Message" ); +
    +
    host real hostname of the current server
    id connection id
    inputbox contents of the inputbox
    libdirfsthe system wide directory where xchat will look for plugins. + this string is in the same encoding as the local file system
    modes the current channels modes or undef if not known
    network current network name or undef
    nick current nick
    nickserv nickserv password for this network or undef
    server current server name
    + (what the server claims to be) undef if not connected +
    state_cursorcurrent inputbox cursor position in characters
    topic current channel topic
    version xchat version number
    win_statusstatus of the xchat window, possible values are "active", "hidden" + and "normal"
    win_ptr native window pointer, GtkWindow * on Unix, HWND on Win32.
    + On Unix if you have the Glib module installed you can use my $window = Glib::Object->new_from_pointer( Xchat::get_info( "win_ptr" ) ); to get a Gtk2::Window object.
    + Additionally when you have detached tabs, each of the windows will return a different win_ptr for the different Gtk2::Window objects.
    + See char_count.pl for a longer example of a script that uses this to show how many characters you currently have in your input box. +
    xchatdir xchat config directory encoded in UTF-8
    + examples:
    + /home/user/.xchat2
    + C:\Documents and Settings\user\Application Data\X-Chat 2 +
    xchatdirfs same as xchatdir except encoded in the locale file system encoding
    + +

    This function is used to retrieve certain information about the current +context.

    + +=end html + +=head3 C + +=over 3 + +=item * +C<$name> - name of a X-Chat setting (available through the /set command) + +=back + +This function provides a way to retrieve X-Chat's setting information. + +Returns C if there is no setting called called C<$name>. + + +=head3 C + +=over 3 + +=item * +C<$event> - name from the Event column in Settings-EAdvanced-EText Events + +=item * +LIST - this depends on the Description column on the bottom of Settings-EAdvanced-EText Events + +=back + +This functions is used to generate one of the events listed under +Settings-EAdvanced-EText Events + +Note: when using this function you MUST return Xchat::EAT_ALL otherwise you will end up with duplicate events. +One is the original and the second is the one you emit. + +Returns true on success, false on failure + +=head3 C + +=over 3 + +=item * +C<$target> - a single nick to set the mode on + +=item * +C<\@targets> - an array reference of the nicks to set the mode on + +=item * +C<$sign> - the mode sign, either '+' or '-' + +=item * +C<$mode> - the mode character such as 'o' and 'v', this can only be one character long + +=item * +C<$modes_per_line> - an optional argument maximum number of modes to send per at once, pass 0 use the current server's maximum (default) + +=back + +Send multiple mode changes for the current channel. It may send multiple MODE lines if the request doesn't fit on one. + +Example: + +=begin html +<
    + +use strict; +use warning; +use Xchat qw(:all); + +hook_command( "MODES", sub { + my (undef, $who, $sign, $mode) = @{$_[0]}; + + my @targets = split /,/, $who; + if( @targets > 1 ) { + send_modes( \@targets, $sign, $mode, 1 ); + } else { + send_modes( $who, $sign, $mode ); + } + + return EAT_XCHAT; +}); + + +
    + +=end html + +=head3 C + +=over 3 + +=item * +C<$nick1, $nick2> - the two nicks or channel names that are to be compared + +=back + +The comparsion is based on the current server. Either a RFC1459 compliant +string compare or plain ascii will be using depending on the server. The +comparison is case insensitive. + +Returns a number less than, equal to or greater than zero if +C<$nick1> is +found respectively, to be less than, to match, or be greater than +C<$nick2>. + + +=head3 C + +=over 3 + +=item * +C<$name> - name of the list, one of the following: +"channels", "dcc", "ignore", "notify", "users" + +=back + +This function will return a list of hash references. The hash references +will have different keys depend on the list. An empty list is returned +if there is no such list. + +=begin html + +

    "channels" - list of channels, querys and their server

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Description
    channel tab name
    chantypeschannel types supported by the server, typically "#&"
    context can be used with set_context
    flags Server Bits:
    + 0 - Connected
    + 1 - Connecting
    + 2 - Away
    + 3 - EndOfMotd(Login complete)
    + 4 - Has WHOX
    + 5 - Has IDMSG (FreeNode)
    +
    +

    The following correspond to the /chanopt command

    + 6 - Hide Join/Part Message (text_hidejoinpart)
    + 7 - unused (was for color paste)
    + 8 - Beep on message (alert_beep)
    + 9 - Blink Tray (alert_tray)
    + 10 - Blink Task Bar (alert_taskbar)
    +

    Example of checking if the current context has Hide Join/Part messages set:

    +
    + +if( Xchat::context_info->{flags} & (1 << 6) ) { + Xchat::print( "Hide Join/Part messages is enabled" ); +} + +
    + +
    id Unique server ID
    laglag in milliseconds
    maxmodes Maximum modes per line
    network network name to which this channel belongs
    nickprefixes Nickname prefixes e.g. "+@"
    nickmodes Nickname mode chars e.g. "vo"
    queuenumber of bytes in the send queue
    server server name to which this channel belongs
    type the type of this context
    + 1 - server
    + 2 - channel
    + 3 - dialog
    +
    users Number of users in this channel
    + +

    "dcc" - list of DCC file transfers

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    address32 address of the remote user(ipv4 address)
    cps bytes per second(speed)
    destfile destination full pathname
    file file name
    nicknick of the person this DCC connection is connected to
    port TCP port number
    pos bytes sent/received
    poshigh bytes sent/received, high order 32 bits
    resume point at which this file was resumed
    + (zero if it was not resumed) +
    resumehigh point at which this file was resumed, high order 32 bits
    +
    size file size in bytes low order 32 bits
    sizehigh file size in bytes, high order 32 bits (when the files is > 4GB)
    status DCC Status:
    + 0 - queued
    + 1 - active
    + 2 - failed
    + 3 - done
    + 4 - connecting
    + 5 - aborted +
    type DCC Type:
    + 0 - send
    + 1 - receive
    + 2 - chatrecv
    + 3 - chatsend +
    + +

    "ignore" - current ignore list

    + + + + + + + + + + + + + + +
    Key Value
    mask ignore mask. e.g: *!*@*.aol.com
    flags Bit field of flags.
    + 0 - private
    + 1 - notice
    + 2 - channel
    + 3 - ctcp
    + 4 - invite
    + 5 - unignore
    + 6 - nosave
    + 7 - dcc
    +
    + +

    "notify" - list of people on notify

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    networkscomma separated list of networks where you will be notfified about this user's online/offline status or undef if you will be notificed on every network you are connected to
    nick nickname
    flags 0 = is online
    on time when user came online
    off time when user went offline
    seen time when user was last verified still online
    + +

    the values indexed by on, off and seen can be passed to localtime +and gmtime, see perldoc -f localtime and perldoc -f gmtime for more +detail

    + +

    "users" - list of users in the current channel

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    away away status(boolean)
    lasttalklast time a user was seen talking, this is the an epoch time(number of seconds since a certain date, that date depends on the OS)
    nick nick name
    hosthost name in the form: user@host or undef if not known
    prefix prefix character, .e.g: @ or +
    realnameReal name or undef
    selectedselected status in the user list, only works when retrieving the user list of the focused tab. You can use the /USELECT command to select the nicks
    + +

    "networks" - list of networks and the associated settings from network list

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    autojoins An object with the following methods:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MethodDescription
    channels()returns a list of this networks' autojoin channels in list context, a count of the number autojoin channels in scalar context
    keys()returns a list of the keys to go with the channels, the order is the same as the channels, if a channel doesn't have a key, '' will be returned in it's place
    pairs()a combination of channels() and keys(), returns a list of (channels, keys) pairs. This can be assigned to a hash for a mapping from channel to key.
    as_hash()return the pairs as a hash reference
    as_string()the original string that was used to construct this autojoin object, this can be used with the JOIN command to join all the channels in the autojoin list
    as_array()return an array reference of hash references consisting of the keys "channel" and "key"
    as_bool()returns true if the network has autojoins and false otherwise
    +
    connect_commands An array reference containing the connect commands for a network. An empty array if there aren't any
    encoding the encoding for the network
    flags + a hash reference corresponding to the checkboxes in the network edit window + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    allow_invalidtrue if "Accept invalid SSL certificate" is checked
    autoconnecttrue if "Auto connect to this network at startup" is checked
    cycletrue if "Connect to selected server only" is NOT checked
    use_globaltrue if "Use global user information" is checked
    use_proxytrue if "Bypass proxy server" is NOT checked
    use_ssltrue if "Use SSL for all the servers on this network" is checked
    +
    irc_nick1Corresponds with the "Nick name" field in the network edit window
    irc_nick2Corresponds with the "Second choice" field in the network edit window
    irc_real_nameCorresponds with the "Real name" field in the network edit window
    irc_user_nameCorresponds with the "User name" field in the network edit window
    networkName of the network
    nickserv_passwordCorresponds with the "Nickserv password" field in the network edit window
    selectedIndex into the list of servers in the "servers" key, this is used if the "cycle" flag is false
    server_passwordCorresponds with the "Server password" field in the network edit window
    serversAn array reference of hash references with a "host" and "port" key. If a port is not specified then 6667 will be used.
    + +=end html + +=head3 C + +=over 3 + +=item * +C<$nick> - the nick to look for, if this is not given your own nick will be + used as default + +=back + +This function is mainly intended to be used as a shortcut for when you need +to retrieve some information about only one user in a channel. Otherwise it +is better to use L. +If C<$nick> is found a hash reference containing the same keys as those in the +"users" list of L is returned otherwise undef is returned. +Since it relies on L this function can only be used in a +channel context. + +=head3 C + +=over 3 + +=item * +C<$context> - context returned from L, L and L, this is the context that you want infomation about. If this is omitted, it will default to current context. + +=back + +This function will return the information normally retrieved with L, except this is for the context that is passed in. The information will be returned in the form of a hash. The keys of the hash are the C<$id> you would normally supply to L as well as all the keys that are valid for the items in the "channels" list from L. Use of this function is more efficient than calling get_list( "channels" ) and searching through the result. + +=begin html + +

    Example:

    +
    +use strict; +use warnings; +use Xchat qw(:all); # imports all the functions documented on this page + +register( "User Count", "0.1", + "Print out the number of users on the current channel" ); + +hook_command( "UCOUNT", \&display_count ); + +sub display_count { + prnt "There are " . context_info()->{users} . " users in this channel."; + return EAT_XCHAT; +} +
    + +=end html + +=head3 C + +=over 3 + +=item * +C<$string> - string to remove codes from + +=back + +This function will remove bold, color, beep, reset, reverse and underline codes from C<$string>. It will also remove ANSI escape codes which might get used by certain terminal based clients. If it is called in void context C<$string> will be modified otherwise a modified copy of C<$string> is returned. + +=head2 Examples + +=head3 Asynchronous DNS resolution with hook_fd + +=begin html + +
    + +use strict; +use warnings; +use Xchat qw(:all); +use Net::DNS; + +hook_command( "BGDNS", sub { + my $host = $_[0][1]; + my $resolver = Net::DNS::Resolver->new; + my $sock = $resolver->bgsend( $host ); + + hook_fd( $sock, sub { + my $ready_sock = $_[0]; + my $packet = $resolver->bgread( $ready_sock ); + + if( $packet->authority && (my @answers = $packet->answer ) ) { + + if( @answers ) { + prnt "$host:"; + my $padding = " " x (length( $host ) + 2); + for my $answer ( @answers ) { + prnt $padding . $answer->rdatastr . ' ' . $answer->type; + } + } + } else { + prnt "Unable to resolve $host"; + } + + return REMOVE; + }, + { + flags => FD_READ, + }); + + return EAT_XCHAT; +}); + +
    + +=end html + +=head2 Contact Information + +Contact Lian Wan Situ at Eatmcmnky [at] yahoo.comE for questions, comments and +corrections about this page or the Perl plugin itself. You can also find me +in #xchat on FreeNode under the nick Khisanth. diff --git a/plugins/perl/lib/Xchat/Embed.pm b/plugins/perl/lib/Xchat/Embed.pm new file mode 100644 index 00000000..dffbaf5e --- /dev/null +++ b/plugins/perl/lib/Xchat/Embed.pm @@ -0,0 +1,253 @@ +package Xchat::Embed; +use strict; +use warnings; +# list of loaded scripts keyed by their package names +our %scripts; + +sub load { + my $file = expand_homedir( shift @_ ); + my $package = file2pkg( $file ); + + if( exists $scripts{$package} ) { + my $pkg_info = pkg_info( $package ); + my $filename = File::Basename::basename( $pkg_info->{filename} ); + Xchat::printf( + qq{'%s' already loaded from '%s'.\n}, + $filename, $pkg_info->{filename} + ); + Xchat::print( + 'If this is a different script then it rename and try '. + 'loading it again.' + ); + return 2; + } + + if( open my $source_handle, $file ) { + my $source = do {local $/; <$source_handle>}; + close $source_handle; + # we shouldn't care about things after __END__ + $source =~ s/^__END__.*//ms; + + if( + my @replacements = $source =~ + m/^\s*package ((?:[^\W:]+(?:::)?)+)\s*?;/mg + ) { + + if ( @replacements > 1 ) { + Xchat::print( + "Too many package defintions, only 1 is allowed\n" + ); + return 1; + } + + my $original_package = shift @replacements; + + # remove original package declaration + $source =~ s/^(package $original_package\s*;)/#$1/m; + + # fixes things up for code calling subs with fully qualified names + $source =~ s/${original_package}:://g; + } + + # this must come before the eval or the filename will not be found in + # Xchat::register + $scripts{$package}{filename} = $file; + $scripts{$package}{loaded_at} = Time::HiRes::time(); + + my $full_path = File::Spec->rel2abs( $file ); + $source =~ s/^/#line 1 "$full_path"\n\x7Bpackage $package;/; + + # make sure we add the closing } even if the last line is a comment + if( $source =~ /^#.*\Z/m ) { + $source =~ s/^(?=#.*\Z)/\x7D/m; + } else { + $source =~ s/\Z/\x7D/; + } + + _do_eval( $source ); + + unless( exists $scripts{$package}{gui_entry} ) { + $scripts{$package}{gui_entry} = + Xchat::Internal::register( + "", "unknown", "", $file + ); + } + + if( $@ ) { + # something went wrong + $@ =~ s/\(eval \d+\)/$file/g; + Xchat::print( "Error loading '$file':\n$@\n" ); + # make sure the script list doesn't contain false information + unload( $scripts{$package}{filename} ); + return 1; + } + } else { + Xchat::print( "Error opening '$file': $!\n" ); + return 2; + } + + return 0; +} + +sub _do_eval { + no strict; + no warnings; + eval $_[0]; +} + +sub unload { + my $file = shift @_; + my $package = file2pkg( $file ); + my $pkg_info = pkg_info( $package ); + + if( $pkg_info ) { + # take care of the shutdown callback + if( exists $pkg_info->{shutdown} ) { + # allow incorrectly written scripts to be unloaded + eval { + if( ref $pkg_info->{shutdown} eq 'CODE' ) { + $pkg_info->{shutdown}->(); + } elsif ( $pkg_info->{shutdown} ) { + no strict 'refs'; + &{$pkg_info->{shutdown}}; + } + }; + } + + if( exists $pkg_info->{hooks} ) { + for my $hook ( @{$pkg_info->{hooks}} ) { + Xchat::unhook( $hook, $package ); + } + } + + + if( exists $pkg_info->{gui_entry} ) { + plugingui_remove( $pkg_info->{gui_entry} ); + } + + Symbol::delete_package( $package ); + delete $scripts{$package}; + return Xchat::EAT_ALL; + } else { + Xchat::print( qq{"$file" is not loaded.\n} ); + return Xchat::EAT_NONE; + } +} + +sub unload_all { + for my $package ( keys %scripts ) { + unload( $scripts{$package}->{filename} ); + } + + return Xchat::EAT_ALL; +} + +sub reload { + my $file = shift @_; + my $package = file2pkg( $file ); + my $pkg_info = pkg_info( $package ); + my $fullpath = $file; + + if( $pkg_info ) { + $fullpath = $pkg_info->{filename}; + unload( $file ); + } + + load( $fullpath ); + return Xchat::EAT_ALL; +} + +sub reload_all { + my @dirs = Xchat::get_info( "xchatdirfs" ) || Xchat::get_info( "xchatdir" ); + push @dirs, File::Spec->catdir( $dirs[0], "plugins" ); + for my $dir ( @dirs ) { + my $auto_load_glob = File::Spec->catfile( $dir, "*.pl" ); + my @scripts = map { $_->{filename} } + sort { $a->{loaded_at} <=> $b->{loaded_at} } values %scripts; + push @scripts, File::Glob::bsd_glob( $auto_load_glob ); + + my %seen; + @scripts = grep { !$seen{ $_ }++ } @scripts; + + unload_all(); + for my $script ( @scripts ) { + if( !pkg_info( file2pkg( $script ) ) ) { + load( $script ); + } + } + } +} + +sub expand_homedir { + my $file = shift @_; + + if ( $^O eq "MSWin32" ) { + $file =~ s/^~/$ENV{USERPROFILE}/; + } else { + $file =~ s{^~}{ + (getpwuid($>))[7] || $ENV{HOME} || $ENV{LOGDIR} + }ex; + } + return $file; +} + +sub file2pkg { + my $string = File::Basename::basename( shift @_ ); + $string =~ s/\.pl$//i; + $string =~ s|([^A-Za-z0-9/])|'_'.unpack("H*",$1)|eg; + return "Xchat::Script::" . $string; +} + +sub pkg_info { + my $package = shift @_; + return $scripts{$package}; +} + +sub find_external_pkg { + my $level = 1; + + while( my @frame = caller( $level ) ) { + return @frame if $frame[0] !~ /^Xchat/; + $level++; + } + +} + +sub find_pkg { + my $level = 1; + + while( my ($package, $file, $line) = caller( $level ) ) { + return $package if $package =~ /^Xchat::Script::/; + $level++; + } + + my @frame = find_external_pkg(); + my $location; + + if( $frame[0] or $frame[1] ) { + $location = $frame[1] ? $frame[1] : "package $frame[0]"; + $location .= " line $frame[2]"; + } else { + $location = "unknown location"; + } + + die "Unable to determine which script this hook belongs to. at $location\n"; + +} + +sub fix_callback { + my ($package, $callback) = @_; + + unless( ref $callback ) { + # change the package to the correct one in case it was hardcoded + $callback =~ s/^.*:://; + $callback = qq[${package}::$callback]; + + no strict 'subs'; + $callback = \&{$callback}; + } + + return $callback; +} + +1 diff --git a/plugins/perl/lib/Xchat/List/Network.pm b/plugins/perl/lib/Xchat/List/Network.pm new file mode 100644 index 00000000..da2f52dd --- /dev/null +++ b/plugins/perl/lib/Xchat/List/Network.pm @@ -0,0 +1,32 @@ +package Xchat::List::Network; +use strict; +use warnings; +use Storable qw(dclone); +my $last_modified; +my @servers; + +sub get { + my $server_file = Xchat::get_info( "xchatdirfs" ) . "/servlist_.conf"; + + # recreate the list only if the server list file has changed + if( -f $server_file && + (!defined $last_modified || $last_modified != -M $server_file ) ) { + $last_modified = -M _; + + if( open my $fh, "<", $server_file ) { + local $/ = "\n\n"; + while( my $record = <$fh> ) { + chomp $record; + next if $record =~ /^v=/; # skip the version line + push @servers, Xchat::List::Network::Entry::parse( $record ); + } + } else { + warn "Unable to open '$server_file': $!"; + } + } + + my $clone = dclone( \@servers ); + return @$clone; +} + +1 diff --git a/plugins/perl/lib/Xchat/List/Network/AutoJoin.pm b/plugins/perl/lib/Xchat/List/Network/AutoJoin.pm new file mode 100644 index 00000000..16036a9d --- /dev/null +++ b/plugins/perl/lib/Xchat/List/Network/AutoJoin.pm @@ -0,0 +1,82 @@ +package Xchat::List::Network::AutoJoin; +use strict; +use warnings; + +use overload +# '%{}' => \&as_hash, +# '@{}' => \&as_array, + '""' => 'as_string', + '0+' => 'as_bool'; + +sub new { + my $class = shift; + my $line = shift; + + my @autojoins; + + if ( $line ) { + my ( $channels, $keys ) = split / /, $line, 2; + my @channels = split /,/, $channels; + my @keys = split /,/, ($keys || ''); + + for my $channel ( @channels ) { + my $key = shift @keys; + $key = '' unless defined $key; + + push @autojoins, { + channel => $channel, + key => $key, + }; + } + } + return bless \@autojoins, $class; +} + +sub channels { + my $self = shift; + + if( wantarray ) { + return map { $_->{channel} } @$self; + } else { + return scalar @$self; + } +} + +sub keys { + my $self = shift; + return map { $_->{key} } @$self ; + +} + +sub pairs { + my $self = shift; + + my @channels = $self->channels; + my @keys = $self->keys; + + my @pairs = map { $_ => shift @keys } @channels; +} + +sub as_hash { + my $self = shift; + return +{ $self->pairs }; +} + +sub as_string { + my $self = shift; + return join " ", + join( ",", $self->channels ), + join( ",", $self->keys ); +} + +sub as_array { + my $self = shift; + return [ map { \%$_ } @$self ]; +} + +sub as_bool { + my $self = shift; + return $self->channels ? 1 : ""; +} + +1 diff --git a/plugins/perl/lib/Xchat/List/Network/Entry.pm b/plugins/perl/lib/Xchat/List/Network/Entry.pm new file mode 100644 index 00000000..e40b48bd --- /dev/null +++ b/plugins/perl/lib/Xchat/List/Network/Entry.pm @@ -0,0 +1,105 @@ +package Xchat::List::Network::Entry; +use strict; +use warnings; + +my %key_for = ( + I => "irc_nick1", + i => "irc_nick2", + U => "irc_user_name", + R => "irc_real_name", + P => "server_password", + B => "nickserv_password", + N => "network", + D => "selected", + E => "encoding", +); +my $letter_key_re = join "|", keys %key_for; + +sub parse { + my $data = shift; + my $entry = { + irc_nick1 => undef, + irc_nick2 => undef, + irc_user_name => undef, + irc_real_name => undef, + server_password => undef, + + # the order of the channels need to be maintained + # list of { channel => .., key => ... } + autojoins => Xchat::List::Network::AutoJoin->new( '' ), + connect_commands => [], + flags => {}, + selected => undef, + encoding => undef, + servers => [], + nickserv_password => undef, + network => undef, + }; + + my @fields = split /\n/, $data; + chomp @fields; + + for my $field ( @fields ) { + SWITCH: for ( $field ) { + /^($letter_key_re)=(.*)/ && do { + $entry->{ $key_for{ $1 } } = $2; + last SWITCH; + }; + + /^J.(.*)/ && do { + $entry->{ autojoins } = + Xchat::List::Network::AutoJoin->new( $1 ); + }; + + /^F.(.*)/ && do { + $entry->{ flags } = parse_flags( $1 ); + }; + + /^S.(.+)/ && do { + push @{$entry->{servers}}, parse_server( $1 ); + }; + + /^C.(.+)/ && do { + push @{$entry->{connect_commands}}, $1; + }; + } + } + +# $entry->{ autojoins } = $entry->{ autojoin_channels }; + return $entry; +} + +sub parse_flags { + my $value = shift || 0; + my %flags; + + $flags{ "cycle" } = $value & 1 ? 1 : 0; + $flags{ "use_global" } = $value & 2 ? 1 : 0; + $flags{ "use_ssl" } = $value & 4 ? 1 : 0; + $flags{ "autoconnect" } = $value & 8 ? 1 : 0; + $flags{ "use_proxy" } = $value & 16 ? 1 : 0; + $flags{ "allow_invalid" } = $value & 32 ? 1 : 0; + + return \%flags; +} + +sub parse_server { + my $data = shift; + if( $data ) { + my ($host, $port) = split /\//, $data; + unless( $port ) { + my @parts = split /:/, $host; + + # if more than 2 then we are probably dealing with a IPv6 address + # if less than 2 then no port was specified + if( @parts == 2 ) { + $port = $parts[1]; + } + } + + $port ||= 6667; + return { host => $host, port => $port }; + } +} + +1 diff --git a/plugins/perl/perl.c b/plugins/perl/perl.c new file mode 100644 index 00000000..a29ce65a --- /dev/null +++ b/plugins/perl/perl.c @@ -0,0 +1,1522 @@ +/* X-Chat 2.0 PERL Plugin + * Copyright (C) 1998-2002 Peter Zelezny. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef ENABLE_NLS +#include +#endif +#ifdef WIN32 +#include +#endif + +#undef PACKAGE +#include "../../config.h" /* for #define OLD_PERL */ +#include "xchat-plugin.h" + +static xchat_plugin *ph; /* plugin handle */ + +static int perl_load_file (char *script_name); + +#ifdef WIN32 +/* STRINGIFY is from perl's CORE/config.h */ +#ifndef PERL_REQUIRED_VERSION + #define PERL_REQUIRED_VERSION STRINGIFY(PERL_REVISION) "." STRINGIFY(PERL_VERSION) +#endif + +#ifndef PERL_DLL + #define PERL_DLL "perl" STRINGIFY(PERL_REVISION) STRINGIFY(PERL_VERSION) ".dll" +#endif + +static DWORD +child (char *str) +{ + MessageBoxA (0, str, "Perl DLL Error", + MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); + return 0; +} + +static void +thread_mbox (char *str) +{ + DWORD tid; + + CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) child, + str, 0, &tid)); +} + +#endif + +/* leave this before XSUB.h, to avoid readdir() being redefined */ + +static void +perl_auto_load_from_path (const char *path) +{ + DIR *dir; + struct dirent *ent; + + dir = opendir (path); + if (dir) { + while ((ent = readdir (dir))) { + int len = strlen (ent->d_name); + if (len > 3 && strcasecmp (".pl", ent->d_name + len - 3) == 0) { + char *file = malloc (len + strlen (path) + 2); + sprintf (file, "%s/%s", path, ent->d_name); + perl_load_file (file); + free (file); + } + } + closedir (dir); + } +} + +static int +perl_auto_load (void *unused) +{ + const char *xdir; + char *sub_dir; +#ifdef WIN32 + int copied = 0; + char *slash = NULL; +#endif + + /* get the dir in local filesystem encoding (what opendir() expects!) */ + xdir = xchat_get_info (ph, "xchatdirfs"); + if (!xdir) /* xchatdirfs is new for 2.0.9, will fail on older */ + xdir = xchat_get_info (ph, "xchatdir"); + + /* autoload from ~/.xchat2/ or ${APPDATA}\X-Chat 2\ on win32 */ + perl_auto_load_from_path (xdir); + + sub_dir = malloc (strlen (xdir) + 9); + strcpy (sub_dir, xdir); + strcat (sub_dir, "/plugins"); + perl_auto_load_from_path (sub_dir); + free (sub_dir); + +#ifdef WIN32 + /* autoload from C:\program files\xchat\plugins\ */ + sub_dir = malloc (1025 + 9); + copied = GetModuleFileName( 0, sub_dir, 1024 ); + sub_dir[copied] = '\0'; + slash = strrchr( sub_dir, '\\' ); + if( slash != NULL ) { + *slash = '\0'; + } + perl_auto_load_from_path ( strncat (sub_dir, "\\plugins", 9)); + free (sub_dir); +#endif + return 0; +} + +#include +#define WIN32IOP_H +#include +#include + +typedef struct +{ + SV *callback; + SV *userdata; + xchat_hook *hook; /* required for timers */ + xchat_context *ctx; /* allow timers to remember their context */ + SV *package; /* need to track the package name when removing hooks + by returning REMOVE + */ + unsigned int depth; +} HookData; + +static PerlInterpreter *my_perl = NULL; +extern void boot_DynaLoader (pTHX_ CV * cv); + +/* + this is used for autoload and shutdown callbacks +*/ +static int +execute_perl (SV * function, char *args) +{ + + int count, ret_value = 1; + + dSP; + ENTER; + SAVETMPS; + + PUSHMARK (SP); + XPUSHs (sv_2mortal (newSVpv (args, 0))); + PUTBACK; + + count = call_sv (function, G_EVAL | G_SCALAR); + SPAGAIN; + if (SvTRUE (ERRSV)) { + xchat_printf(ph, "Perl error: %s\n", SvPV_nolen (ERRSV)); + if (!SvOK (POPs)) {} /* remove undef from the top of the stack */ + } else if (count != 1) { + xchat_printf (ph, "Perl error: expected 1 value from %s, " + "got: %d\n", SvPV_nolen (function), count); + } else { + ret_value = POPi; + } + PUTBACK; + FREETMPS; + LEAVE; + + return ret_value; +} + +static char * +get_filename (char *word[], char *word_eol[]) +{ + int len; + char *file; + + len = strlen (word[2]); + + /* if called as /load "filename.pl" the only difference between word and + * word_eol will be the two quotes + */ + + if (strchr (word[2], ' ') != NULL + || (strlen (word_eol[2]) - strlen(word[2])) == 2 ) + { + file = word[2]; + } else { + file = word_eol[2]; + } + + len = strlen (file); + + if (len > 3 && strncasecmp (".pl", file + len - 3, 3) == 0) { + return file; + } + + return NULL; +} + +static SV * +list_item_to_sv ( xchat_list *list, const char *const *fields ) +{ + HV *hash = newHV(); + SV *field_value; + const char *field; + int field_index = 0; + const char *field_name; + int name_len; + + while (fields[field_index] != NULL) { + field_name = fields[field_index] + 1; + name_len = strlen (field_name); + + switch (fields[field_index][0]) { + case 's': + field = xchat_list_str (ph, list, field_name); + if (field != NULL) { + field_value = newSVpvn (field, strlen (field)); + } else { + field_value = &PL_sv_undef; + } + break; + case 'p': + field_value = newSViv (PTR2IV (xchat_list_str (ph, list, + field_name))); + break; + case 'i': + field_value = newSVuv (xchat_list_int (ph, list, field_name)); + break; + case 't': + field_value = newSVnv (xchat_list_time (ph, list, field_name)); + break; + default: + field_value = &PL_sv_undef; + } + hv_store (hash, field_name, name_len, field_value, 0); + field_index++; + } + return sv_2mortal (newRV_noinc ((SV *) hash)); +} + +static AV * +array2av (char *array[]) +{ + int count = 0; + SV *temp = NULL; + AV *av = newAV(); + sv_2mortal ((SV *)av); + + for ( + count = 1; + count < 32 && array[count] != NULL && array[count][0] != 0; + count++ + ) { + temp = newSVpv (array[count], 0); + SvUTF8_on (temp); + av_push (av, temp); + } + + return av; +} + +static int +fd_cb (int fd, int flags, void *userdata) +{ + HookData *data = (HookData *) userdata; + int retVal = 0; + int count = 0; + + dSP; + ENTER; + SAVETMPS; + + PUSHMARK (SP); + XPUSHs (data->userdata); + PUTBACK; + + count = call_sv (data->callback, G_EVAL); + SPAGAIN; + + if (SvTRUE (ERRSV)) { + xchat_printf (ph, "Error in fd callback %s", SvPV_nolen (ERRSV)); + if (!SvOK (POPs)) {} /* remove undef from the top of the stack */ + retVal = XCHAT_EAT_ALL; + } else { + if (count != 1) { + xchat_print (ph, "Fd handler should only return 1 value."); + retVal = XCHAT_EAT_NONE; + } else { + retVal = POPi; + if (retVal == 0) { + /* if 0 is returned, the fd is going to get unhooked */ + PUSHMARK (SP); + XPUSHs (sv_2mortal (newSViv (PTR2IV (data->hook)))); + PUTBACK; + + call_pv ("Xchat::unhook", G_EVAL); + SPAGAIN; + + SvREFCNT_dec (data->callback); + + if (data->userdata) { + SvREFCNT_dec (data->userdata); + } + free (data); + } + } + + } + + PUTBACK; + FREETMPS; + LEAVE; + + return retVal; +} + +static int +timer_cb (void *userdata) +{ + HookData *data = (HookData *) userdata; + int retVal = 0; + int count = 0; + + dSP; + ENTER; + SAVETMPS; + + PUSHMARK (SP); + XPUSHs (data->userdata); + PUTBACK; + + if (data->ctx) { + xchat_set_context (ph, data->ctx); + } + count = call_sv (data->callback, G_EVAL); + SPAGAIN; + + if (SvTRUE (ERRSV)) { + xchat_printf (ph, "Error in timer callback %s", SvPV_nolen (ERRSV)); + if (!SvOK (POPs)) {} /* remove undef from the top of the stack */ + retVal = XCHAT_EAT_ALL; + } else { + if (count != 1) { + xchat_print (ph, "Timer handler should only return 1 value."); + retVal = XCHAT_EAT_NONE; + } else { + retVal = POPi; + if (retVal == 0) { + /* if 0 is return the timer is going to get unhooked */ + PUSHMARK (SP); + XPUSHs (sv_2mortal (newSViv (PTR2IV (data->hook)))); + XPUSHs (sv_mortalcopy (data->package)); + PUTBACK; + + call_pv ("Xchat::unhook", G_EVAL); + SPAGAIN; + } + } + + } + + PUTBACK; + FREETMPS; + LEAVE; + + return retVal; +} + +static int +server_cb (char *word[], char *word_eol[], void *userdata) +{ + HookData *data = (HookData *) userdata; + int retVal = 0; + int count = 0; + + dSP; + ENTER; + SAVETMPS; + + if (data->depth) + return XCHAT_EAT_NONE; + + /* xchat_printf (ph, */ + /* "Recieved %d words in server callback", av_len (wd)); */ + PUSHMARK (SP); + XPUSHs (newRV_noinc ((SV *) array2av (word))); + XPUSHs (newRV_noinc ((SV *) array2av (word_eol))); + XPUSHs (data->userdata); + PUTBACK; + + data->depth++; + count = call_sv (data->callback, G_EVAL); + data->depth--; + SPAGAIN; + if (SvTRUE (ERRSV)) { + xchat_printf (ph, "Error in server callback %s", SvPV_nolen (ERRSV)); + if (!SvOK (POPs)) {} /* remove undef from the top of the stack */ + retVal = XCHAT_EAT_NONE; + } else { + if (count != 1) { + xchat_print (ph, "Server handler should only return 1 value."); + retVal = XCHAT_EAT_NONE; + } else { + retVal = POPi; + } + + } + + PUTBACK; + FREETMPS; + LEAVE; + + return retVal; +} + +static int +command_cb (char *word[], char *word_eol[], void *userdata) +{ + HookData *data = (HookData *) userdata; + int retVal = 0; + int count = 0; + + dSP; + ENTER; + SAVETMPS; + + if (data->depth) + return XCHAT_EAT_NONE; + + /* xchat_printf (ph, "Recieved %d words in command callback", */ + /* av_len (wd)); */ + PUSHMARK (SP); + XPUSHs (newRV_noinc ((SV *) array2av (word))); + XPUSHs (newRV_noinc ((SV *) array2av (word_eol))); + XPUSHs (data->userdata); + PUTBACK; + + data->depth++; + count = call_sv (data->callback, G_EVAL); + data->depth--; + SPAGAIN; + if (SvTRUE (ERRSV)) { + xchat_printf (ph, "Error in command callback %s", SvPV_nolen (ERRSV)); + if (!SvOK (POPs)) {} /* remove undef from the top of the stack */ + retVal = XCHAT_EAT_XCHAT; + } else { + if (count != 1) { + xchat_print (ph, "Command handler should only return 1 value."); + retVal = XCHAT_EAT_NONE; + } else { + retVal = POPi; + } + + } + + PUTBACK; + FREETMPS; + LEAVE; + + return retVal; +} + +static int +print_cb (char *word[], void *userdata) +{ + + HookData *data = (HookData *) userdata; + SV *temp = NULL; + int retVal = 0; + int count = 1; + int last_index = 31; + /* must be initialized after SAVETMPS */ + AV *wd = NULL; + + dSP; + ENTER; + SAVETMPS; + + if (data->depth) + return XCHAT_EAT_NONE; + + wd = newAV (); + sv_2mortal ((SV *) wd); + + /* need to scan backwards to find the index of the last element since some + events such as "DCC Timeout" can have NULL elements in between non NULL + elements */ + + while (last_index >= 0 + && (word[last_index] == NULL || word[last_index][0] == 0)) { + last_index--; + } + + for (count = 1; count <= last_index; count++) { + if (word[count] == NULL) { + av_push (wd, &PL_sv_undef); + } else if (word[count][0] == 0) { + av_push (wd, newSVpvn ("",0)); + } else { + temp = newSVpv (word[count], 0); + SvUTF8_on (temp); + av_push (wd, temp); + } + } + + /*xchat_printf (ph, "Recieved %d words in print callback", av_len (wd)+1); */ + PUSHMARK (SP); + XPUSHs (newRV_noinc ((SV *) wd)); + XPUSHs (data->userdata); + PUTBACK; + + data->depth++; + count = call_sv (data->callback, G_EVAL); + data->depth--; + SPAGAIN; + if (SvTRUE (ERRSV)) { + xchat_printf (ph, "Error in print callback %s", SvPV_nolen (ERRSV)); + if (!SvOK (POPs)) {} /* remove undef from the top of the stack */ + retVal = XCHAT_EAT_NONE; + } else { + if (count != 1) { + xchat_print (ph, "Print handler should only return 1 value."); + retVal = XCHAT_EAT_NONE; + } else { + retVal = POPi; + } + + } + + PUTBACK; + FREETMPS; + LEAVE; + + return retVal; +} + +/* custom IRC perl functions for scripting */ + +/* Xchat::Internal::register (scriptname, version, desc, shutdowncallback, filename) + * + */ + +static +XS (XS_Xchat_register) +{ + char *name, *version, *desc, *filename; + void *gui_entry; + dXSARGS; + if (items != 4) { + xchat_printf (ph, + "Usage: Xchat::Internal::register(scriptname, version, desc, filename)"); + } else { + name = SvPV_nolen (ST (0)); + version = SvPV_nolen (ST (1)); + desc = SvPV_nolen (ST (2)); + filename = SvPV_nolen (ST (3)); + + gui_entry = xchat_plugingui_add (ph, filename, name, + desc, version, NULL); + + XSRETURN_IV (PTR2IV (gui_entry)); + + } +} + + +/* Xchat::print(output) */ +static +XS (XS_Xchat_print) +{ + + char *text = NULL; + + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::Internal::print(text)"); + } else { + text = SvPV_nolen (ST (0)); + xchat_print (ph, text); + } + XSRETURN_EMPTY; +} + +static +XS (XS_Xchat_emit_print) +{ + char *event_name; + int RETVAL; + int count; + + dXSARGS; + if (items < 1) { + xchat_print (ph, "Usage: Xchat::emit_print(event_name, ...)"); + } else { + event_name = (char *) SvPV_nolen (ST (0)); + RETVAL = 0; + + /* we need to figure out the number of defined values passed in */ + for (count = 0; count < items; count++) { + if (!SvOK (ST (count))) { + break; + } + } + + switch (count) { + case 1: + RETVAL = xchat_emit_print (ph, event_name, NULL); + break; + case 2: + RETVAL = xchat_emit_print (ph, event_name, + SvPV_nolen (ST (1)), NULL); + break; + case 3: + RETVAL = xchat_emit_print (ph, event_name, + SvPV_nolen (ST (1)), + SvPV_nolen (ST (2)), NULL); + break; + case 4: + RETVAL = xchat_emit_print (ph, event_name, + SvPV_nolen (ST (1)), + SvPV_nolen (ST (2)), + SvPV_nolen (ST (3)), NULL); + break; + case 5: + RETVAL = xchat_emit_print (ph, event_name, + SvPV_nolen (ST (1)), + SvPV_nolen (ST (2)), + SvPV_nolen (ST (3)), + SvPV_nolen (ST (4)), NULL); + break; + + } + + XSRETURN_IV (RETVAL); + } +} + +static +XS (XS_Xchat_send_modes) +{ + AV *p_targets = NULL; + int modes_per_line = 0; + char sign; + char mode; + int i = 0; + const char **targets; + int target_count = 0; + SV **elem; + + dXSARGS; + if (items < 3 || items > 4) { + xchat_print (ph, + "Usage: Xchat::send_modes( targets, sign, mode, modes_per_line)" + ); + } else { + if (SvROK (ST (0))) { + p_targets = (AV*) SvRV (ST (0)); + target_count = av_len (p_targets) + 1; + targets = malloc (target_count * sizeof (char *)); + for (i = 0; i < target_count; i++ ) { + elem = av_fetch (p_targets, i, 0); + + if (elem != NULL) { + targets[i] = SvPV_nolen (*elem); + } else { + targets[i] = ""; + } + } + } else{ + targets = malloc (sizeof (char *)); + targets[0] = SvPV_nolen (ST (0)); + target_count = 1; + } + + if (target_count == 0) { + XSRETURN_EMPTY; + } + + sign = (SvPV_nolen (ST (1)))[0]; + mode = (SvPV_nolen (ST (2)))[0]; + + if (items == 4 ) { + modes_per_line = (int) SvIV (ST (3)); + } + + xchat_send_modes (ph, targets, target_count, modes_per_line, sign, mode); + free (targets); + } +} +static +XS (XS_Xchat_get_info) +{ + SV *temp = NULL; + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::get_info(id)"); + } else { + SV *id = ST (0); + const char *RETVAL; + + RETVAL = xchat_get_info (ph, SvPV_nolen (id)); + if (RETVAL == NULL) { + XSRETURN_UNDEF; + } + + if (!strncmp ("win_ptr", SvPV_nolen (id), 7) + || !strncmp ("gtkwin_ptr", SvPV_nolen (id), 10)) + { + XSRETURN_IV (PTR2IV (RETVAL)); + } else { + + if ( + !strncmp ("libdirfs", SvPV_nolen (id), 8) || + !strncmp ("xchatdirfs", SvPV_nolen (id), 10) + ) { + XSRETURN_PV (RETVAL); + } else { + temp = newSVpv (RETVAL, 0); + SvUTF8_on (temp); + PUSHMARK (SP); + XPUSHs (sv_2mortal (temp)); + PUTBACK; + } + } + } +} + +static +XS (XS_Xchat_context_info) +{ + const char *const *fields; + dXSARGS; + + if (items > 0 ) { + xchat_print (ph, "Usage: Xchat::Internal::context_info()"); + } + fields = xchat_list_fields (ph, "channels" ); + XPUSHs (list_item_to_sv (NULL, fields)); + XSRETURN (1); +} + +static +XS (XS_Xchat_get_prefs) +{ + const char *str; + int integer; + SV *temp = NULL; + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::get_prefs(name)"); + } else { + + + switch (xchat_get_prefs (ph, SvPV_nolen (ST (0)), &str, &integer)) { + case 0: + XSRETURN_UNDEF; + break; + case 1: + temp = newSVpv (str, 0); + SvUTF8_on (temp); + SP -= items; + sp = mark; + XPUSHs (sv_2mortal (temp)); + PUTBACK; + break; + case 2: + XSRETURN_IV (integer); + break; + case 3: + if (integer) { + XSRETURN_YES; + } else { + XSRETURN_NO; + } + } + } +} + +/* Xchat::Internal::hook_server(name, priority, callback, userdata) */ +static +XS (XS_Xchat_hook_server) +{ + + char *name; + int pri; + SV *callback; + SV *userdata; + xchat_hook *hook; + HookData *data; + + dXSARGS; + + if (items != 4) { + xchat_print (ph, + "Usage: Xchat::Internal::hook_server(name, priority, callback, userdata)"); + } else { + name = SvPV_nolen (ST (0)); + pri = (int) SvIV (ST (1)); + callback = ST (2); + userdata = ST (3); + data = NULL; + data = malloc (sizeof (HookData)); + if (data == NULL) { + XSRETURN_UNDEF; + } + + data->callback = sv_mortalcopy (callback); + SvREFCNT_inc (data->callback); + data->userdata = sv_mortalcopy (userdata); + SvREFCNT_inc (data->userdata); + data->depth = 0; + data->package = NULL; + hook = xchat_hook_server (ph, name, pri, server_cb, data); + + XSRETURN_IV (PTR2IV (hook)); + } +} + +/* Xchat::Internal::hook_command(name, priority, callback, help_text, userdata) */ +static +XS (XS_Xchat_hook_command) +{ + char *name; + int pri; + SV *callback; + char *help_text = NULL; + SV *userdata; + xchat_hook *hook; + HookData *data; + + dXSARGS; + + if (items != 5) { + xchat_print (ph, + "Usage: Xchat::Internal::hook_command(name, priority, callback, help_text, userdata)"); + } else { + name = SvPV_nolen (ST (0)); + pri = (int) SvIV (ST (1)); + callback = ST (2); + + /* leave the help text has NULL if the help text is undefined to avoid + * overriding the default help message for builtin commands */ + if (SvOK(ST (3))) { + help_text = SvPV_nolen (ST (3)); + } + + userdata = ST (4); + data = NULL; + + data = malloc (sizeof (HookData)); + if (data == NULL) { + XSRETURN_UNDEF; + } + + data->callback = sv_mortalcopy (callback); + SvREFCNT_inc (data->callback); + data->userdata = sv_mortalcopy (userdata); + SvREFCNT_inc (data->userdata); + data->depth = 0; + data->package = NULL; + hook = xchat_hook_command (ph, name, pri, command_cb, help_text, data); + + XSRETURN_IV (PTR2IV (hook)); + } + +} + +/* Xchat::Internal::hook_print(name, priority, callback, [userdata]) */ +static +XS (XS_Xchat_hook_print) +{ + + char *name; + int pri; + SV *callback; + SV *userdata; + xchat_hook *hook; + HookData *data; + dXSARGS; + if (items != 4) { + xchat_print (ph, + "Usage: Xchat::Internal::hook_print(name, priority, callback, userdata)"); + } else { + name = SvPV_nolen (ST (0)); + pri = (int) SvIV (ST (1)); + callback = ST (2); + data = NULL; + userdata = ST (3); + + data = malloc (sizeof (HookData)); + if (data == NULL) { + XSRETURN_UNDEF; + } + + data->callback = sv_mortalcopy (callback); + SvREFCNT_inc (data->callback); + data->userdata = sv_mortalcopy (userdata); + SvREFCNT_inc (data->userdata); + data->depth = 0; + data->package = NULL; + hook = xchat_hook_print (ph, name, pri, print_cb, data); + + XSRETURN_IV (PTR2IV (hook)); + } +} + +/* Xchat::Internal::hook_timer(timeout, callback, userdata) */ +static +XS (XS_Xchat_hook_timer) +{ + int timeout; + SV *callback; + SV *userdata; + xchat_hook *hook; + SV *package; + HookData *data; + + dXSARGS; + + if (items != 4) { + xchat_print (ph, + "Usage: Xchat::Internal::hook_timer(timeout, callback, userdata, package)"); + } else { + timeout = (int) SvIV (ST (0)); + callback = ST (1); + data = NULL; + userdata = ST (2); + package = ST (3); + + data = malloc (sizeof (HookData)); + if (data == NULL) { + XSRETURN_UNDEF; + } + + data->callback = sv_mortalcopy (callback); + SvREFCNT_inc (data->callback); + data->userdata = sv_mortalcopy (userdata); + SvREFCNT_inc (data->userdata); + data->ctx = xchat_get_context (ph); + data->package = sv_mortalcopy (package); + SvREFCNT_inc (data->package); + hook = xchat_hook_timer (ph, timeout, timer_cb, data); + data->hook = hook; + + XSRETURN_IV (PTR2IV (hook)); + } +} + +/* Xchat::Internal::hook_fd(fd, callback, flags, userdata) */ +static +XS (XS_Xchat_hook_fd) +{ + int fd; + SV *callback; + int flags; + SV *userdata; + xchat_hook *hook; + HookData *data; + + dXSARGS; + + if (items != 4) { + xchat_print (ph, + "Usage: Xchat::Internal::hook_fd(fd, callback, flags, userdata)"); + } else { + fd = (int) SvIV (ST (0)); + callback = ST (1); + flags = (int) SvIV (ST (2)); + userdata = ST (3); + data = NULL; + +#ifdef WIN32 + if ((flags & XCHAT_FD_NOTSOCKET) == 0) { + /* this _get_osfhandle if from win32iop.h in the perl distribution, + * not the one provided by Windows + */ + fd = _get_osfhandle(fd); + if (fd < 0) { + xchat_print(ph, "Invalid file descriptor"); + XSRETURN_UNDEF; + } + } +#endif + + data = malloc (sizeof (HookData)); + if (data == NULL) { + XSRETURN_UNDEF; + } + + data->callback = sv_mortalcopy (callback); + SvREFCNT_inc (data->callback); + data->userdata = sv_mortalcopy (userdata); + SvREFCNT_inc (data->userdata); + data->package = NULL; + hook = xchat_hook_fd (ph, fd, flags, fd_cb, data); + data->hook = hook; + + XSRETURN_IV (PTR2IV (hook)); + } +} + +static +XS (XS_Xchat_unhook) +{ + xchat_hook *hook; + HookData *userdata; + int retCount = 0; + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::unhook(hook)"); + } else { + hook = INT2PTR (xchat_hook *, SvUV (ST (0))); + userdata = (HookData *) xchat_unhook (ph, hook); + + if (userdata != NULL) { + if (userdata->callback != NULL) { + SvREFCNT_dec (userdata->callback); + } + + if (userdata->userdata != NULL) { + XPUSHs (sv_mortalcopy (userdata->userdata)); + SvREFCNT_dec (userdata->userdata); + retCount = 1; + } + + if (userdata->package != NULL) { + SvREFCNT_dec (userdata->package); + } + free (userdata); + } + XSRETURN (retCount); + } + XSRETURN_EMPTY; +} + +/* Xchat::Internal::command(command) */ +static +XS (XS_Xchat_command) +{ + char *cmd = NULL; + + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::Internal::command(command)"); + } else { + cmd = SvPV_nolen (ST (0)); + xchat_command (ph, cmd); + + } + XSRETURN_EMPTY; +} + +static +XS (XS_Xchat_find_context) +{ + char *server = NULL; + char *chan = NULL; + xchat_context *RETVAL; + + dXSARGS; + if (items > 2) + xchat_print (ph, "Usage: Xchat::find_context ([channel, [server]])"); + { + + switch (items) { + case 0: /* no server name and no channel name */ + /* nothing to do, server and chan are already NULL */ + break; + case 1: /* channel name only */ + /* change channel value only if it is true or 0 */ + /* otherwise leave it as null */ + if (SvTRUE (ST (0)) || SvNIOK (ST (0))) { + chan = SvPV_nolen (ST (0)); + /* xchat_printf( ph, "XSUB - find_context( %s, NULL )", chan ); */ + } + /* else { xchat_print( ph, "XSUB - find_context( NULL, NULL )" ); } */ + /* chan is already NULL */ + break; + case 2: /* server and channel */ + /* change channel value only if it is true or 0 */ + /* otherwise leave it as NULL */ + if (SvTRUE (ST (0)) || SvNIOK (ST (0))) { + chan = SvPV_nolen (ST (0)); + /* xchat_printf( ph, "XSUB - find_context( %s, NULL )", SvPV_nolen(ST(0) )); */ + } + + /* else { xchat_print( ph, "XSUB - 2 arg NULL chan" ); } */ + /* change server value only if it is true or 0 */ + /* otherwise leave it as NULL */ + if (SvTRUE (ST (1)) || SvNIOK (ST (1))) { + server = SvPV_nolen (ST (1)); + /* xchat_printf( ph, "XSUB - find_context( NULL, %s )", SvPV_nolen(ST(1) )); */ + } + /* else { xchat_print( ph, "XSUB - 2 arg NULL server" ); } */ + break; + } + + RETVAL = xchat_find_context (ph, server, chan); + if (RETVAL != NULL) { + /* xchat_print (ph, "XSUB - context found"); */ + XSRETURN_IV (PTR2IV (RETVAL)); + } else { + /* xchat_print (ph, "XSUB - context not found"); */ + XSRETURN_UNDEF; + } + } +} + +static +XS (XS_Xchat_get_context) +{ + dXSARGS; + if (items != 0) { + xchat_print (ph, "Usage: Xchat::get_context()"); + } else { + XSRETURN_IV (PTR2IV (xchat_get_context (ph))); + } +} + +static +XS (XS_Xchat_set_context) +{ + xchat_context *ctx; + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::set_context(ctx)"); + } else { + ctx = INT2PTR (xchat_context *, SvUV (ST (0))); + XSRETURN_IV ((IV) xchat_set_context (ph, ctx)); + } +} + +static +XS (XS_Xchat_nickcmp) +{ + dXSARGS; + if (items != 2) { + xchat_print (ph, "Usage: Xchat::nickcmp(s1, s2)"); + } else { + XSRETURN_IV ((IV) xchat_nickcmp (ph, SvPV_nolen (ST (0)), + SvPV_nolen (ST (1)))); + } +} + +static +XS (XS_Xchat_get_list) +{ + SV *name; + xchat_list *list; + const char *const *fields; + int count = 0; /* return value for scalar context */ + dXSARGS; + + if (items != 1) { + xchat_print (ph, "Usage: Xchat::get_list(name)"); + } else { + SP -= items; /*remove the argument list from the stack */ + + name = ST (0); + + list = xchat_list_get (ph, SvPV_nolen (name)); + + if (list == NULL) { + XSRETURN_EMPTY; + } + + if (GIMME_V == G_SCALAR) { + while (xchat_list_next (ph, list)) { + count++; + } + xchat_list_free (ph, list); + XSRETURN_IV ((IV) count); + } + + fields = xchat_list_fields (ph, SvPV_nolen (name)); + while (xchat_list_next (ph, list)) { + XPUSHs (list_item_to_sv (list, fields)); + } + xchat_list_free (ph, list); + + PUTBACK; + return; + } +} + +static +XS (XS_Xchat_Embed_plugingui_remove) +{ + void *gui_entry; + dXSARGS; + if (items != 1) { + xchat_print (ph, "Usage: Xchat::Embed::plugingui_remove(handle)"); + } else { + gui_entry = INT2PTR (void *, SvUV (ST (0))); + xchat_plugingui_remove (ph, gui_entry); + } + XSRETURN_EMPTY; +} + +/* xs_init is the second argument perl_parse. As the name hints, it + initializes XS subroutines (see the perlembed manpage) */ +static void +xs_init (pTHX) +{ + HV *stash; + SV *version; + /* This one allows dynamic loading of perl modules in perl + scripts by the 'use perlmod;' construction */ + newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); + /* load up all the custom IRC perl functions */ + newXS ("Xchat::Internal::register", XS_Xchat_register, __FILE__); + newXS ("Xchat::Internal::hook_server", XS_Xchat_hook_server, __FILE__); + newXS ("Xchat::Internal::hook_command", XS_Xchat_hook_command, __FILE__); + newXS ("Xchat::Internal::hook_print", XS_Xchat_hook_print, __FILE__); + newXS ("Xchat::Internal::hook_timer", XS_Xchat_hook_timer, __FILE__); + newXS ("Xchat::Internal::hook_fd", XS_Xchat_hook_fd, __FILE__); + newXS ("Xchat::Internal::unhook", XS_Xchat_unhook, __FILE__); + newXS ("Xchat::Internal::print", XS_Xchat_print, __FILE__); + newXS ("Xchat::Internal::command", XS_Xchat_command, __FILE__); + newXS ("Xchat::Internal::set_context", XS_Xchat_set_context, __FILE__); + newXS ("Xchat::Internal::get_info", XS_Xchat_get_info, __FILE__); + newXS ("Xchat::Internal::context_info", XS_Xchat_context_info, __FILE__); + newXS ("Xchat::Internal::get_list", XS_Xchat_get_list, __FILE__); + + newXS ("Xchat::find_context", XS_Xchat_find_context, __FILE__); + newXS ("Xchat::get_context", XS_Xchat_get_context, __FILE__); + newXS ("Xchat::get_prefs", XS_Xchat_get_prefs, __FILE__); + newXS ("Xchat::emit_print", XS_Xchat_emit_print, __FILE__); + newXS ("Xchat::send_modes", XS_Xchat_send_modes, __FILE__); + newXS ("Xchat::nickcmp", XS_Xchat_nickcmp, __FILE__); + + newXS ("Xchat::Embed::plugingui_remove", XS_Xchat_Embed_plugingui_remove, + __FILE__); + + stash = get_hv ("Xchat::", TRUE); + if (stash == NULL) { + exit (1); + } + + newCONSTSUB (stash, "PRI_HIGHEST", newSViv (XCHAT_PRI_HIGHEST)); + newCONSTSUB (stash, "PRI_HIGH", newSViv (XCHAT_PRI_HIGH)); + newCONSTSUB (stash, "PRI_NORM", newSViv (XCHAT_PRI_NORM)); + newCONSTSUB (stash, "PRI_LOW", newSViv (XCHAT_PRI_LOW)); + newCONSTSUB (stash, "PRI_LOWEST", newSViv (XCHAT_PRI_LOWEST)); + + newCONSTSUB (stash, "EAT_NONE", newSViv (XCHAT_EAT_NONE)); + newCONSTSUB (stash, "EAT_XCHAT", newSViv (XCHAT_EAT_XCHAT)); + newCONSTSUB (stash, "EAT_PLUGIN", newSViv (XCHAT_EAT_PLUGIN)); + newCONSTSUB (stash, "EAT_ALL", newSViv (XCHAT_EAT_ALL)); + newCONSTSUB (stash, "FD_READ", newSViv (XCHAT_FD_READ)); + newCONSTSUB (stash, "FD_WRITE", newSViv (XCHAT_FD_WRITE)); + newCONSTSUB (stash, "FD_EXCEPTION", newSViv (XCHAT_FD_EXCEPTION)); + newCONSTSUB (stash, "FD_NOTSOCKET", newSViv (XCHAT_FD_NOTSOCKET)); + newCONSTSUB (stash, "KEEP", newSViv (1)); + newCONSTSUB (stash, "REMOVE", newSViv (0)); + + version = get_sv( "Xchat::VERSION", 1 ); + sv_setpv( version, PACKAGE_VERSION ); +} + +static void +perl_init (void) +{ + int warn; + int arg_count; + char *perl_args[] = { "", "-e", "0", "-w" }; + char *env[] = { "" }; + static const char xchat_definitions[] = { + /* Redefine the $SIG{__WARN__} handler to have XChat + printing warnings in the main window. (TheHobbit) */ +#include "xchat.pm.h" + }; +#ifdef OLD_PERL + static const char irc_definitions[] = { +#include "irc.pm.h" + }; +#endif +#ifdef ENABLE_NLS + + /* Problem is, dynamicaly loaded modules check out the $] + var. It appears that in the embedded interpreter we get + 5,00503 as soon as the LC_NUMERIC locale calls for a comma + instead of a point in separating integer and decimal + parts. I realy can't understant why... The following + appears to be an awful workaround... But it'll do until I + (or someone else :)) found the "right way" to solve this + nasty problem. (TheHobbit ) */ + + setlocale (LC_NUMERIC, "C"); + +#endif + + warn = 0; + xchat_get_prefs (ph, "perl_warnings", NULL, &warn); + arg_count = warn ? 4 : 3; + + PERL_SYS_INIT3 (&arg_count, (char ***)&perl_args, (char ***)&env); + my_perl = perl_alloc (); + perl_construct (my_perl); + PL_exit_flags |= PERL_EXIT_DESTRUCT_END; + perl_parse (my_perl, xs_init, arg_count, perl_args, (char **)NULL); + + /* + Now initialising the perl interpreter by loading the + perl_definition array. + */ + + eval_pv (xchat_definitions, TRUE); +#ifdef OLD_PERL + eval_pv (irc_definitions, TRUE); +#endif + +} + + +static int +perl_load_file (char *filename) +{ +#ifdef WIN32 + static HMODULE lib = NULL; + + if (!lib) { + lib = LoadLibraryA (PERL_DLL); + if (!lib) { + if (GetLastError () == ERROR_BAD_EXE_FORMAT) + /* http://forum.xchat.org/viewtopic.php?t=3277 */ + thread_mbox ("Cannot use this " PERL_DLL "\n\n" + "32-bit ActivePerl is required."); + else { + /* a lot of people install this old version */ + lib = LoadLibraryA ("perl56.dll"); + if (lib) { + FreeLibrary (lib); + lib = NULL; + thread_mbox ("Cannot open " PERL_DLL "\n\n" + "You must have ActivePerl " PERL_REQUIRED_VERSION " installed in order to\n" + "run perl scripts.\n\n" + "I have found Perl 5.6, but that is too old."); + } else { + thread_mbox ("Cannot open " PERL_DLL "\n\n" + "You must have ActivePerl " PERL_REQUIRED_VERSION " installed in order to\n" + "run perl scripts.\n\n" + "http://www.activestate.com/ActivePerl/\n\n" + "Make sure perl's bin directory is in your PATH."); + } + } + /* failure */ + return FALSE; + } + + /* success */ + FreeLibrary (lib); + } +#endif + + if (my_perl == NULL) { + perl_init (); + } + + return execute_perl (sv_2mortal (newSVpv ("Xchat::Embed::load", 0)), + filename); + +} + +static void +perl_end (void) +{ + + if (my_perl != NULL) { + execute_perl (sv_2mortal (newSVpv ("Xchat::Embed::unload_all", 0)), ""); + PL_perl_destruct_level = 1; + perl_destruct (my_perl); + perl_free (my_perl); + PERL_SYS_TERM(); + my_perl = NULL; + } + +} + +static int +perl_command_unloadall (char *word[], char *word_eol[], void *userdata) +{ + if (my_perl != NULL) { + execute_perl (sv_2mortal (newSVpv ("Xchat::Embed::unload_all", 0)), ""); + return XCHAT_EAT_XCHAT; + } + + return XCHAT_EAT_XCHAT; +} + +static int +perl_command_reloadall (char *word[], char *word_eol[], void *userdata) +{ + if (my_perl != NULL) { + execute_perl (sv_2mortal (newSVpv ("Xchat::Embed::reload_all", 0)), ""); + + return XCHAT_EAT_XCHAT; + } else { + perl_auto_load( NULL ); + } + return XCHAT_EAT_XCHAT; +} + +static int +perl_command_load (char *word[], char *word_eol[], void *userdata) +{ + char *file = get_filename (word, word_eol); + + if (file != NULL ) + { + perl_load_file (file); + return XCHAT_EAT_XCHAT; + } + + return XCHAT_EAT_NONE; +} + +static int +perl_command_unload (char *word[], char *word_eol[], void *userdata) +{ + char *file = get_filename (word, word_eol); + + if (my_perl != NULL && file != NULL) { + execute_perl (sv_2mortal (newSVpv ("Xchat::Embed::unload", 0)), file); + return XCHAT_EAT_XCHAT; + } + + return XCHAT_EAT_NONE; +} + +static int +perl_command_reload (char *word[], char *word_eol[], void *userdata) +{ + char *file = get_filename (word, word_eol); + + if (my_perl != NULL && file != NULL) { + execute_perl (sv_2mortal (newSVpv ("Xchat::Embed::reload", 0)), file); + return XCHAT_EAT_XCHAT; + } + + return XCHAT_EAT_XCHAT; +} + +void +xchat_plugin_get_info (char **name, char **desc, char **version, + void **reserved) +{ + *name = "Perl"; + *desc = "Perl scripting interface"; + *version = PACKAGE_VERSION; + if (reserved) + *reserved = NULL; +} + + +/* Reinit safeguard */ + +static int initialized = 0; + +int +xchat_plugin_init (xchat_plugin * plugin_handle, char **plugin_name, + char **plugin_desc, char **plugin_version, char *arg) +{ + if (initialized != 0) { + xchat_print (plugin_handle, "Perl interface already loaded\n"); + return 0; + } + + ph = plugin_handle; + initialized = 1; + + *plugin_name = "Perl"; + *plugin_desc = "Perl scripting interface"; + *plugin_version = PACKAGE_VERSION; + + xchat_hook_command (ph, "load", XCHAT_PRI_NORM, perl_command_load, 0, 0); + xchat_hook_command (ph, "unload", XCHAT_PRI_NORM, perl_command_unload, 0, + 0); + xchat_hook_command (ph, "reload", XCHAT_PRI_NORM, perl_command_reload, 0, + 0); + xchat_hook_command (ph, "pl_reload", XCHAT_PRI_NORM, perl_command_reload, 0, + 0); + xchat_hook_command (ph, "unloadall", XCHAT_PRI_NORM, + perl_command_unloadall, 0, 0); + xchat_hook_command (ph, "reloadall", XCHAT_PRI_NORM, + perl_command_reloadall, 0, 0); + + /*perl_init (); */ + xchat_hook_timer (ph, 0, perl_auto_load, NULL ); + + xchat_print (ph, "Perl interface loaded\n"); + + return 1; +} + +int +xchat_plugin_deinit (xchat_plugin * plugin_handle) +{ + perl_end (); + + initialized = 0; + xchat_print (plugin_handle, "Perl interface unloaded\n"); + + return 1; +} diff --git a/plugins/perl/perl.def b/plugins/perl/perl.def new file mode 100644 index 00000000..a2ec6566 --- /dev/null +++ b/plugins/perl/perl.def @@ -0,0 +1,4 @@ +EXPORTS + xchat_plugin_init + xchat_plugin_deinit + xchat_plugin_get_info \ No newline at end of file diff --git a/plugins/perl/syntax_highlight b/plugins/perl/syntax_highlight new file mode 100644 index 00000000..96d57003 --- /dev/null +++ b/plugins/perl/syntax_highlight @@ -0,0 +1,69 @@ +#!/usr/bin/env perl +use 5.010; +use strict; +use warnings; +use Text::VimColor; +use HTML::TokeParser::Simple; +use HTML::Entities qw(decode_entities); +use Path::Class; + +my $html_file = shift; +my $reader = file( $html_file )->openr; +unlink $html_file; +my $writer = file( $html_file )->openw; + +my $parser = HTML::TokeParser::Simple->new( $reader ); + +while( my $token = $parser->get_token ) { + + my $class_name = $token->get_attr( "class" ); + + if( $token->is_start_tag( "div" ) + && ( $class_name && $class_name =~ qr/\bexample\b/ ) + ) { + my $start_tag = $token; + $start_tag->set_attr( class => $class_name . " synNormal" ); + my @content; + my $end_tag; + + EXAMPLE: + while( $token = $parser->get_token ) { + if( $token->is_end_tag( "div" ) ) { + $end_tag = $token; + last EXAMPLE; + } + + if( $token->is_text ) { + push @content, decode_entities( $token->as_is ); + } + } + + my $code = join "", @content; +# say $code; + my $vim = Text::VimColor->new( + string => $code, + filetype => "perl", + vim_options => [qw( -RXZ -i NONE -u NONE -N -n)], + ); + my $html = $vim->html; + $html =~ s/^\s+//; + $html =~ s/\s+$//; + + print $writer $start_tag->as_is; + + my $lines = $html =~ tr/\n/\n/; + + say $writer "
    "; + for my $line ( 0 .. $lines ) { + say $writer "
    ",1 + $line,"
    "; + } + say $writer "
    "; + + print $writer "
    ";
    +		say $writer $html;
    +		say $writer "
    "; + print $writer $end_tag->as_is; + } else { + print $writer $token->as_is; + } +} diff --git a/plugins/perl/xchat2-perl.html b/plugins/perl/xchat2-perl.html new file mode 100644 index 00000000..38dd3912 --- /dev/null +++ b/plugins/perl/xchat2-perl.html @@ -0,0 +1,1166 @@ + + + + +X-Chat 2 Perl Interface + + + + + + + + +
    + X-Chat 2 Perl Interface +
    + + + +
    +

    + + + +
    +
    + + +

    +

    +

    X-Chat 2 Perl Interface

    +

    +

    +

    Introduction

    +

    This is the new Perl interface for X-Chat 2. However, due to changes in +xchat's plugin code you will need xchat 2.0.8 or above to load this. Scripts +written using the old interface will continue to work. If there are any +problems, questions, comments or suggestions please email them to the address +on the bottom of this page.

    +

    +

    +

    Constants

    +

    +

    +

    Priorities

    +
      +
    • Xchat::PRI_HIGHEST +
    • +
    • Xchat::PRI_HIGH +
    • +
    • Xchat::PRI_NORM +
    • +
    • Xchat::PRI_LOW +
    • +
    • Xchat::PRI_LOWEST +
    • +
    +

    +

    +

    Return values

    +
      +
    • Xchat::EAT_NONE - pass the event along +
    • +
    • Xchat::EAT_XCHAT - don't let xchat see this event +
    • +
    • Xchat::EAT_PLUGIN - don't let other scripts and plugins see this event but xchat will still see it +
    • +
    • Xchat::EAT_ALL - don't let anything else see this event +
    • +
    +

    +

    +

    Timer and fd hooks

    +
      +
    • Xchat::KEEP - keep the timer going or hook watching the handle +
    • +
    • Xchat::REMOVE - remove the timer or hook watching the handle +
    • +
    +

    +

    +

    hook_fd flags

    +
      +
    • Xchat::FD_READ - invoke the callback when the handle is ready for reading +
    • +
    • Xchat::FD_WRITE - invoke the callback when the handle is ready for writing +
    • +
    • Xchat::FD_EXCEPTION - invoke the callback if an exception occurs +
    • +
    • Xchat::FD_NOTSOCKET - indicate that the handle being hooked is not a socket +
    • +
    +

    +

    +

    Functions

    +

    +

    +

    Xchat::register( $name, $version, [$description,[$callback]] )

    +
      +
    • $name - The name of this script +
    • +
    • $version - This script's version +
    • +
    • $description - A description for this script +
    • +
    • $callback - This is a function that will be called when the is script + unloaded. This can be either a reference to a + function or an anonymous sub reference. +
    • +
    +

    This is the first thing to call in every script.

    +

    +

    +

    Xchat::hook_server( $message, $callback, [\%options] )

    +

    +

    +

    Xchat::hook_command( $command, $callback, [\%options] )

    +

    +

    +

    Xchat::hook_print( $event,$callback, [\%options] )

    +

    +

    +

    Xchat::hook_timer( $timeout,$callback, [\%options | $data] )

    +

    +

    +

    Xchat::hook_fd( $handle, $callback, [ \%options ] )

    +

    These functions can be to intercept various events. +hook_server can be used to intercept any incoming message from the IRC server. +hook_command can be used to intercept any command, if the command doesn't currently exist then a new one is created. +hook_print can be used to intercept any of the events listed in Setttings->Advanced->Text Events +hook_timer can be used to create a new timer

    +
    +

    Valid keys for \%options:

    + + + + + + + +
    data Additional data that is to be associated with the
    + hook. For timer hooks this value can be provided either as
    + Xchat::hook_timer( $timeout, $cb,{data=>$data})
    + or Xchat::hook_timer( $timeout, $cb, $data ).
    + However, this means that hook_timer cannot be provided
    + with a hash reference containing data as a key.
    example:
    + my $options = { data => [@arrayOfStuff] };
    + Xchat::hook_timer( $timeout, $cb, $options );
    +
    + In this example, the timer's data will be
    + [@arrayOfStuff] and not { data => [@arrayOfStuff] }
    +
    + This key is valid for all of the hook functions.
    +
    + Default is undef.
    +
    priority Sets the priority for the hook.
    + It can be set to one of the + Xchat::PRI_* constants.
    +
    + This key only applies to server, command + and print hooks.
    +
    + Default is Xchat::PRI_NORM. +
    help_text Text displayed for /help $command.
    +
    + This key only applies to command hooks.
    +
    + Default is "". +
    flags Specify the flags for a fd hook.
    +
    + See hook fd flags section for valid values.
    +
    + On Windows if the handle is a pipe you specify
    + Xchat::FD_NOTSOCKET in addition to any other flags you might be using.
    +
    + This key only applies to fd hooks.
    + Default is Xchat::FD_READ +

    +

    +

    When callbacks are invoked

    +

    Each of the hooks will be triggered at different times depending on the type +of hook.

    + + + + + + + + + + + + + +
    Hook Type When the callback will be invoked
    server hooks a $message message is + received from the server +
    command hooks the $command command is + executed, either by the user or from a script +
    print hooks X-Chat is about to print the message for the + $event event +
    timer hooks called every $timeout milliseconds + (1000 millisecond is 1 second)
    + the callback will be executed in the same context where + the hook_timer was called, if the context no longer exists + then it will execute in a random context +
    fd hooks depends on the flags that were passed to hook_fd
    + See hook_fd flags section. +

    The value return from these hook functions can be passed to Xchat::unhook +to remove the hook.

    +

    +

    +

    Callback Arguments

    +

    All callback functions will receive their arguments in @_ like every +other Perl subroutine.

    +

    +Server and command callbacks
    +
    +$_[0] - array reference containing the IRC message or command and +arguments broken into words
    +example:
    +/command arg1 arg2 arg3
    +$_[0][0] - command
    +$_[0][1] - arg1
    +$_[0][2] - arg2
    +$_[0][3] - arg3
    +
    +$_[1] - array reference containing the Nth word to the last word
    +example:
    +/command arg1 arg2 arg3
    +$_[1][0] - command arg1 arg2 arg3
    +$_[1][1] - arg1 arg2 arg3
    +$_[1][2] - arg2 arg3
    +$_[1][3] - arg3
    +
    +$_[2] - the data that was passed to the hook function
    +
    +Print callbacks
    +
    +$_[0] - array reference containing the values for the + text event see Settings->Advanced->Text Events
    +$_[1] - the data that was passed to the hook function
    +
    +Timer callbacks
    +
    +$_[0] - the data that was passed to the hook function
    +
    fd callbacks
    +
    +$_[0] - the handle that was passed to hook_fd
    +$_[1] - flags indicating why the callback was called
    +$_[2] - the data that was passed to the hook function
    +

    +

    +

    Callback return values

    +

    All server, command and print callbacks should return one of +the Xchat::EAT_* constants. +Timer callbacks can return Xchat::REMOVE to remove +the timer or Xchat::KEEP to keep it going

    +

    +

    +

    Miscellaneous Hook Related Information

    +

    For server hooks, if $message is "RAW LINE" then $cb will be called for +every IRC message than X-Chat receives.

    +

    For command hooks if $command is "" then $cb will be called for +messages entered by the user that is not a command.

    +

    For print hooks besides those events listed in +Settings->Advanced->Text Events, these additional events can be used.

    + + + + + + + + + + + + + + + +
    Event Description
    "Open Context" a new context is created
    "Close Context" a context has been close
    "Focus Tab" when a tab is brought to the front
    "Focus Window" when a top level window is focused or the + main tab window is focused by the window manager +
    "DCC Chat Text" when text from a DCC Chat arrives. + $_[0] will have these values
    +
    + $_[0][0] - Address
    + $_[0][1] - Port
    + $_[0][2] - Nick
    + $_[0][3] - Message
    +
    "Key Press" used for intercepting key presses
    + $_[0][0] - key value
    + $_[0][1] - state bitfield, 1 - shift, 4 - control, 8 - alt
    + $_[0][2] - string version of the key which might be empty for unprintable keys
    + $_[0][3] - length of the string in $_[0][2]
    +

    +

    +

    Xchat::unhook( $hook )

    +
      +
    • $hook - the hook that was previously returned by one of the Xchat::hook_* functions +
    • +
    +

    This function is used to removed a hook previously added with one of +the Xchat::hook_* functions

    +

    It returns the data that was passed to the Xchat::hook_* function when +the hook was added

    +

    +

    +

    Xchat::print( $text | \@lines, [$channel,[$server]] )

    +
      +
    • $text - the text to print +
    • +
    • \@lines - array reference containing lines of text to be printed + all the elements will be joined together before printing +
    • +
    • $channel - channel or tab with the given name where $text + will be printed +
    • +
    • $server - specifies that the text will be printed in a channel or tab + that is associated with $server +
    • +
    +

    The first argument can either be a string or an array reference of strings. +Either or both of $channel and $server can be undef.

    +

    If called as Xchat::print( $text ), it will always return true. +If called with either the channel or the channel and the server +specified then it will return true if a context is found and +false otherwise. The text will not be printed if the context +is not found. The meaning of setting $channel or $server to +undef is the same as +find_context.

    +

    +

    +

    Xchat::printf( $format, LIST )

    + +

    +

    +

    Xchat::command( $command | \@commands, [$channel,[$server]] )

    +
      +
    • $command - the command to execute, without the leading / +
    • +
    • \@commands - array reference containing a list of commands to execute +
    • +
    • $channel - channel or tab with the given name where $command will be executed +
    • +
    • $server - specifies that the command will be executed in a channel or tab that is associated with $server +
    • +
    +

    The first argument can either be a string or an array reference of strings. +Either or both of $channel and $server can be undef.

    +

    If called as Xchat::command( $command ), it will always return true. +If called with either the channel or the channel and the server +specified then it will return true if a context is found and false +otherwise. The command will not be executed if the context is not found. +The meaning of setting $channel or $server to undef is the same +as find_context.

    +

    +

    +

    Xchat::commandf( $format, LIST )

    + +

    +

    +

    Xchat::find_context( [$channel, [$server]] )

    +
      +
    • $channel - name of a channel +
    • +
    • $server - name of a server +
    • +
    +

    Either or both of $channel and $server can be undef. Calling +Xchat::find_context() is the same as calling +Xchat::find_context( undef, undef) and +Xchat::find_context( $channel ) is +the same as Xchat::find_context( $channel, undef ).

    +

    If $server is undef, find any channel named $channel. +If $channel is undef, find the front most window +or tab named $server.If both $channel and +$server are undef, find the currently focused tab or window.

    +

    Return the context found for one of the above situations or undef if such +a context cannot be found.

    +

    +

    +

    Xchat::get_context()

    +

    Returns the current context.

    +

    +

    +

    Xchat::set_context( $context | $channel,[$server] )

    + +

    See find_context for more details on $channel and $server.

    +

    Returns true on success, false on failure

    +

    +

    +

    Xchat::get_info( $id )

    +
      +
    • $id - one of the following case sensitive values +
    • +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ID Return value
    away away reason or undef if you are not away
    channel current channel name
    charset character-set used in the current context
    event_text <Event Name> text event format string for <Event name>
    + Example: +
    +
    1
    +
    +
    my $channel_msg_format = Xchat::get_info( "event_text Channel Message" );
    +
    +
    +
    host real hostname of the current server
    id connection id
    inputbox contents of the inputbox
    libdirfsthe system wide directory where xchat will look for plugins. + this string is in the same encoding as the local file system
    modes the current channels modes or undef if not known
    network current network name or undef
    nick current nick
    nickserv nickserv password for this network or undef
    server current server name
    + (what the server claims to be) undef if not connected +
    state_cursorcurrent inputbox cursor position in characters
    topic current channel topic
    version xchat version number
    win_statusstatus of the xchat window, possible values are "active", "hidden" + and "normal"
    win_ptr native window pointer, GtkWindow * on Unix, HWND on Win32.
    + On Unix if you have the Glib module installed you can use my $window = Glib::Object->new_from_pointer( Xchat::get_info( "win_ptr" ) ); to get a Gtk2::Window object.
    + Additionally when you have detached tabs, each of the windows will return a different win_ptr for the different Gtk2::Window objects.
    + See char_count.pl for a longer example of a script that uses this to show how many characters you currently have in your input box. +
    xchatdir xchat config directory encoded in UTF-8
    + examples:
    + /home/user/.xchat2
    + C:\Documents and Settings\user\Application Data\X-Chat 2 +
    xchatdirfs same as xchatdir except encoded in the locale file system encoding

    This function is used to retrieve certain information about the current +context.

    +

    +

    Xchat::get_prefs( $name )

    +
      +
    • $name - name of a X-Chat setting (available through the /set command) +
    • +
    +

    This function provides a way to retrieve X-Chat's setting information.

    +

    Returns undef if there is no setting called called $name.

    +

    +

    +

    Xchat::emit_print( $event, LIST )

    +
      +
    • $event - name from the Event column in Settings->Advanced->Text Events +
    • +
    • LIST - this depends on the Description column on the bottom of Settings->Advanced->Text Events +
    • +
    +

    This functions is used to generate one of the events listed under +Settings->Advanced->Text Events

    +

    Note: when using this function you MUST return Xchat::EAT_ALL otherwise you will end up with duplicate events. +One is the original and the second is the one you emit.

    +

    Returns true on success, false on failure

    +

    +

    +

    Xchat::send_modes( $target | \@targets, $sign, $mode, [ $modes_per_line ] )

    +
      +
    • $target - a single nick to set the mode on +
    • +
    • \@targets - an array reference of the nicks to set the mode on +
    • +
    • $sign - the mode sign, either '+' or '-' +
    • +
    • $mode - the mode character such as 'o' and 'v', this can only be one character long +
    • +
    • $modes_per_line - an optional argument maximum number of modes to send per at once, pass 0 use the current server's maximum (default) +
    • +
    +

    Send multiple mode changes for the current channel. It may send multiple MODE lines if the request doesn't fit on one.

    +

    Example:

    +<
    +
    1
    +
    2
    +
    3
    +
    4
    +
    5
    +
    6
    +
    7
    +
    8
    +
    9
    +
    10
    +
    11
    +
    12
    +
    13
    +
    14
    +
    +
    use strict;
    +use warning;
    +use Xchat qw(:all);
    +
    +hook_command( "MODES", sub {
    +   my (undef, $who, $sign, $mode) = @{$_[0]};
    +   my @targets = split /,/, $who;
    +   if( @targets > 1 ) {
    +      send_modes( \@targets, $sign, $mode, 1 );
    +   } else {
    +      send_modes( $who, $sign, $mode );
    +   }
    +   return EAT_XCHAT;
    +});
    +
    +

    +

    +

    Xchat::nickcmp( $nick1, $nick2 )

    +
      +
    • $nick1, $nick2 - the two nicks or channel names that are to be compared +
    • +
    +

    The comparsion is based on the current server. Either a RFC1459 compliant +string compare or plain ascii will be using depending on the server. The +comparison is case insensitive.

    +

    Returns a number less than, equal to or greater than zero if +$nick1 is +found respectively, to be less than, to match, or be greater than +$nick2.

    +

    +

    +

    Xchat::get_list( $name )

    +
      +
    • $name - name of the list, one of the following: +"channels", "dcc", "ignore", "notify", "users" +
    • +
    +

    This function will return a list of hash references. The hash references +will have different keys depend on the list. An empty list is returned +if there is no such list.

    +

    "channels" - list of channels, querys and their server

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Description
    channel tab name
    chantypeschannel types supported by the server, typically "#&"
    context can be used with set_context
    flags Server Bits:
    + 0 - Connected
    + 1 - Connecting
    + 2 - Away
    + 3 - EndOfMotd(Login complete)
    + 4 - Has WHOX
    + 5 - Has IDMSG (FreeNode)
    +
    +

    The following correspond to the /chanopt command

    + 6 - Hide Join/Part Message (text_hidejoinpart)
    + 7 - unused (was for color paste)
    + 8 - Beep on message (alert_beep)
    + 9 - Blink Tray (alert_tray)
    + 10 - Blink Task Bar (alert_taskbar)
    +

    Example of checking if the current context has Hide Join/Part messages set:

    +
    +
    1
    +
    2
    +
    3
    +
    +
    if( Xchat::context_info->{flags} & (1 << 6) ) {
    +  Xchat::print( "Hide Join/Part messages is enabled" );
    +}
    +
    +
    id Unique server ID
    laglag in milliseconds
    maxmodes Maximum modes per line
    network network name to which this channel belongs
    nickprefixes Nickname prefixes e.g. "+@"
    nickmodes Nickname mode chars e.g. "vo"
    queuenumber of bytes in the send queue
    server server name to which this channel belongs
    type the type of this context
    + 1 - server
    + 2 - channel
    + 3 - dialog
    +
    users Number of users in this channel

    "dcc" - list of DCC file transfers

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    address32 address of the remote user(ipv4 address)
    cps bytes per second(speed)
    destfile destination full pathname
    file file name
    nicknick of the person this DCC connection is connected to
    port TCP port number
    pos bytes sent/received
    poshigh bytes sent/received, high order 32 bits
    resume point at which this file was resumed
    + (zero if it was not resumed) +
    resumehigh point at which this file was resumed, high order 32 bits
    +
    size file size in bytes low order 32 bits
    sizehigh file size in bytes, high order 32 bits (when the files is > 4GB)
    status DCC Status:
    + 0 - queued
    + 1 - active
    + 2 - failed
    + 3 - done
    + 4 - connecting
    + 5 - aborted +
    type DCC Type:
    + 0 - send
    + 1 - receive
    + 2 - chatrecv
    + 3 - chatsend +

    "ignore" - current ignore list

    + + + + + + +
    Key Value
    mask ignore mask. e.g: *!*@*.aol.com
    flags Bit field of flags.
    + 0 - private
    + 1 - notice
    + 2 - channel
    + 3 - ctcp
    + 4 - invite
    + 5 - unignore
    + 6 - nosave
    + 7 - dcc
    +

    "notify" - list of people on notify

    + + + + + + + + + + + + + + + + + +
    Key Value
    networkscomma separated list of networks where you will be notfified about this user's online/offline status or undef if you will be notificed on every network you are connected to
    nick nickname
    flags 0 = is online
    on time when user came online
    off time when user went offline
    seen time when user was last verified still online

    the values indexed by on, off and seen can be passed to localtime +and gmtime, see perldoc -f localtime and perldoc -f gmtime for more +detail

    "users" - list of users in the current channel

    + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    away away status(boolean)
    lasttalklast time a user was seen talking, this is the an epoch time(number of seconds since a certain date, that date depends on the OS)
    nick nick name
    hosthost name in the form: user@host or undef if not known
    prefix prefix character, .e.g: @ or +
    realnameReal name or undef
    selectedselected status in the user list, only works when retrieving the user list of the focused tab. You can use the /USELECT command to select the nicks

    "networks" - list of networks and the associated settings from network list

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Key Value
    autojoins An object with the following methods:
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MethodDescription
    channels()returns a list of this networks' autojoin channels in list context, a count of the number autojoin channels in scalar context
    keys()returns a list of the keys to go with the channels, the order is the same as the channels, if a channel doesn't have a key, '' will be returned in it's place
    pairs()a combination of channels() and keys(), returns a list of (channels, keys) pairs. This can be assigned to a hash for a mapping from channel to key.
    as_hash()return the pairs as a hash reference
    as_string()the original string that was used to construct this autojoin object, this can be used with the JOIN command to join all the channels in the autojoin list
    as_array()return an array reference of hash references consisting of the keys "channel" and "key"
    as_bool()returns true if the network has autojoins and false otherwise
    +
    connect_commands An array reference containing the connect commands for a network. An empty array if there aren't any
    encoding the encoding for the network
    flags + a hash reference corresponding to the checkboxes in the network edit window + + + + + + + + + + + + + + + + + + + + +
    allow_invalidtrue if "Accept invalid SSL certificate" is checked
    autoconnecttrue if "Auto connect to this network at startup" is checked
    cycletrue if "Connect to selected server only" is NOT checked
    use_globaltrue if "Use global user information" is checked
    use_proxytrue if "Bypass proxy server" is NOT checked
    use_ssltrue if "Use SSL for all the servers on this network" is checked
    +
    irc_nick1Corresponds with the "Nick name" field in the network edit window
    irc_nick2Corresponds with the "Second choice" field in the network edit window
    irc_real_nameCorresponds with the "Real name" field in the network edit window
    irc_user_nameCorresponds with the "User name" field in the network edit window
    networkName of the network
    nickserv_passwordCorresponds with the "Nickserv password" field in the network edit window
    selectedIndex into the list of servers in the "servers" key, this is used if the "cycle" flag is false
    server_passwordCorresponds with the "Server password" field in the network edit window
    serversAn array reference of hash references with a "host" and "port" key. If a port is not specified then 6667 will be used.

    +

    +

    Xchat::user_info( [$nick] )

    +
      +
    • $nick - the nick to look for, if this is not given your own nick will be + used as default +
    • +
    +

    This function is mainly intended to be used as a shortcut for when you need +to retrieve some information about only one user in a channel. Otherwise it +is better to use get_list. +If $nick is found a hash reference containing the same keys as those in the +"users" list of get_list is returned otherwise undef is returned. +Since it relies on get_list this function can only be used in a +channel context.

    +

    +

    +

    Xchat::context_info( [$context] )

    + +

    This function will return the information normally retrieved with get_info, except this is for the context that is passed in. The information will be returned in the form of a hash. The keys of the hash are the $id you would normally supply to get_info as well as all the keys that are valid for the items in the "channels" list from get_list. Use of this function is more efficient than calling get_list( "channels" ) and searching through the result.

    +

    Example:

    +
    +
    1
    +
    2
    +
    3
    +
    4
    +
    5
    +
    6
    +
    7
    +
    8
    +
    9
    +
    10
    +
    11
    +
    +
    use strict;
    +use warnings;
    +use Xchat qw(:all); # imports all the functions documented on this page
    +
    +register( "User Count", "0.1",
    +   "Print out the number of users on the current channel" );
    +hook_command( "UCOUNT", \&display_count );
    +sub display_count {
    +   prnt "There are " . context_info()->{users} . " users in this channel.";
    +   return EAT_XCHAT;
    +}
    +
    +

    +

    +

    Xchat::strip_code( $string )

    +
      +
    • $string - string to remove codes from +
    • +
    +

    This function will remove bold, color, beep, reset, reverse and underline codes from $string. It will also remove ANSI escape codes which might get used by certain terminal based clients. If it is called in void context $string will be modified otherwise a modified copy of $string is returned.

    +

    +

    +

    Examples

    +

    +

    +

    Asynchronous DNS resolution with hook_fd

    +
    +
    1
    +
    2
    +
    3
    +
    4
    +
    5
    +
    6
    +
    7
    +
    8
    +
    9
    +
    10
    +
    11
    +
    12
    +
    13
    +
    14
    +
    15
    +
    16
    +
    17
    +
    18
    +
    19
    +
    20
    +
    21
    +
    22
    +
    23
    +
    24
    +
    25
    +
    26
    +
    27
    +
    28
    +
    29
    +
    30
    +
    31
    +
    32
    +
    33
    +
    34
    +
    35
    +
    +
    use strict;
    +use warnings;
    +use Xchat qw(:all);
    +use Net::DNS;
    +   
    +hook_command( "BGDNS", sub {
    +   my $host = $_[0][1];
    +   my $resolver = Net::DNS::Resolver->new;
    +   my $sock = $resolver->bgsend( $host );
    +   
    +   hook_fd( $sock, sub {
    +      my $ready_sock = $_[0];
    +      my $packet = $resolver->bgread( $ready_sock );
    +      
    +      if( $packet->authority && (my @answers = $packet->answer ) ) {
    +         
    +         if( @answers ) {
    +            prnt "$host:";
    +            my $padding = " " x (length( $host ) + 2);
    +            for my $answer ( @answers ) {
    +               prnt $padding . $answer->rdatastr . ' ' . $answer->type;
    +            }
    +         }
    +      } else {
    +         prnt "Unable to resolve $host";
    +      }
    +      
    +      return REMOVE;
    +   },
    +   {
    +      flags => FD_READ,
    +   });
    +   
    +   return EAT_XCHAT;
    +});
    +
    +
    + +

    +

    +

    Contact Information

    +

    Contact Lian Wan Situ at <atmcmnky [at] yahoo.com> for questions, comments and +corrections about this page or the Perl plugin itself. You can also find me +in #xchat on FreeNode under the nick Khisanth.

    + + +
    + X-Chat 2 Perl Interface +
    + + + + diff --git a/plugins/perl/xchat2-perldocs.html b/plugins/perl/xchat2-perldocs.html new file mode 100644 index 00000000..10d8f314 --- /dev/null +++ b/plugins/perl/xchat2-perldocs.html @@ -0,0 +1,475 @@ +XChat - IRC (chat) client for UNIX + + + +

    This interface is deprecated

    + + + + + +
    +
    +

    Xchat Perl Docs

    + + +
    + + +
    + +Introduction +
    +
    + +
    +

    Good Hello!

    +

    The purpose of this page is to give people some quick documentation on the +things that they will encounter when they try to code scripts for X-Chat. +It is not meant to be a comprehensive programming tutorial, +by any means. If that's what you're looking for, then you can just keep on +looking.

    +

    If you're going to do any scripting with X-Chat at all, you will +need to know perl. It also won't hurt to have had experience writing tcl for +eggdrops or ircII scripts. Otherwise you're going to have to be very careful +to avoid creating conditions which could flood you offline or do other +not-so-optimal things. ;) Thankfully, it shouldn't take most intelligent +people more than a week (month on the outside) enough perl to do some nice +things in it. +Perl is a very flexible language.

    +

    You should probably also go read (or at least skim over and then carefully +bookmark this copy of the thing that defines how IRC works: RFC 1459. +Other documents that scripters might find useful would be this +nice list of server +numerics, and this list of changes +for Hybrid 6 which is something everyone on EFNet should read. In fact, I +strongly suggest saving copies of these documents to your local +hard drive, because you will be back to look at them again soon.

    +

    One last thing... While you may hear that RFC 1459 isn't being followed very +well, and this is partly true, do your absolute best to stick with RFC-compliant +behaviours anyway because otherwise there's a good chance that your script will +never interoperate properly with others, or at least just piss off a lot of other +people. Pay special attention to section 2.2 of the RFC.

    +
    + + +
    +Standard Disclaimer + +
    +This documentation is provided on an "as-is" basis and comes with no warranty of accuracy or usefulness, either expressed or implied. It is subject to change without any notice, and may contain omissions or errors which could cause your genitalia to shrivel and fall off, or spontaneously combust. If you have any further questions,
    please feel free to seek professional help.
    +
    + + +
    + + +
    + +About Handlers +
    +
    + +
    +There are [currently] four basic ways to make things call the subroutines you write for X-Chat and they are: +
    • message handlers - Triggered by messagse sent from the IRC server to your client
    • +
    • command handlers - triggered by / commands typed in by the user at the keyboard
    • +
    • timeout handlers - triggered by gtk+
    • +
    • print handlers - triggered just before xchat calls its built in print handlers for events
    +
    + + +
    + + +
    + +About Exit Codes +
    +
    + +
    +These are very important. Every time you set up a handler, it takes precedent over the built-in functions and commands of X-Chat. That is, whatever thing which triggered your subroutine will go to your code before it goes to X-Chat to be dealt with. In this way you can replace almost every built-in function that the client has with your own routines. The thing to remember is that if your code exits by hitting the end of your subroutine, or by a plain 'return' statement, processing of the event will go on to whatever other things have set up hooks for the event, and then (provided nothing else exits with a return value of 1) to X-Chat itself. There is only one problem with this, (which is solved by the brokering handler that I'll explain that later) and that is that you cannot really control what order the custom routines get called. Normally they will execute in order of which ones were installed first, but a single script has no real way of knowing this. Beware. +
    + + +
    + + +
    + +About @_ +
    +
    + +
    +If you've never heard of @_ before, then you've obviously not coded in perl. When a message handler triggers, the raw line from the IRC server is passed to the subroutine you specify in @_. When a command handler is triggered, only the arguments are passed to the routine through @_ and they are not broken into a list, but left as one long string. You'll have to parse those yourself with split. (I advise using s/\s+/ /g to collapse the blank space to single space first.) When a timer handler is triggered, I *think* absolutely nothing is passed in @_, but it's not like anything terrifically important could be passed along anyway. Be especially careful when setting up message handlers for mode changes, since the modes are not broken up into individual events like they are with eggdrop. The upside of this is that X-Chat has no mode hooks of it's own, so you don't have to worry about it too much. (This is not the case with the brokering handler, however.) +
    + + +
    + + +
    + +About Context +
    +
    + +
    +There are some really nice things about coding for X-Chat, and the biggest one is that it's fairly good about determining the proper context for things. If a server sends something that triggers a message handler, then you can be sure that unless you specify otherwise, that your IRC::print or IRC::command function call will go back to that server and that server alone. If you really really need to know what the current context is, use the IRC::get_info function as detailed below. +
    + +
    + + +
    + + +
    + +script initialization commands +
    +
    + + +
    + + +
    + +IRC::register(scriptname, version, shutdownroutine, unused); +
    +
    + +
    +

    This is the first function your script should call, example:

    +

    IRC::register ("my script", "1.0", "", "");

    +

    The "shutdownroutine" arg is a function that will be called when X-Chat shuts down, so you get a chance to save config files etc. You can omit this arg, it is optional. The "unused" arg is reserved for future use, for now just provide "". This function also returns X-Chat's version number.

    +
    + + +
    + + +
    + +Handler initialization commands +
    +
    + + +
    + + +
    + +IRC::add_message_handler(message, subroutine_name); +
    +
    + +
    +

    This function allows you to set up hooks to subroutines so that when a particular message arrives from the IRC server that you are connected to, it can be passed to a subroutine to be dealt with appropriately. The message argument is essentially the second solid token from the raw line sent by the IRC server, and X-Chat doesn't know that some numeric messages have associated text messages, so for now set up a handler for both if you want to be sure odd servers don't screw up your expectations. (Read: fear IRCNet.) The entire line sent by the IRC server will be passed to your subroutine in @_. For the completely uninitiated, messages are things like 'PRIVMSG', 'NOTICE', '372', etc.

    +
    + + +
    + + +
    + +IRC::add_command_handler(command, subroutine_name); +
    +
    + +
    +

    This function allows you to set up hooks for actual commands that the user can type into the text window. The arguments are passed to the subroutine via @_, and arrive as a single string. @_ will be null if no arguments are supplied. It's recommended that you be sure and collapse the excess whitespace with s/\s+/ /g before attempting to chop the line up with split. As mentioned earlier, exiting with an undefined return value will allow the command to be parsed by other handlers, while using a return value of 1 will signal the program that no further parsing needs to be done with this command.

    +
    + + +
    + + +
    + +IRC::add_timeout_handler(interval, subroutine_name); +
    +
    + +
    +

    This function allows you to set up hooks for subroutines to be called at a particular interval. The interval is measured in milliseconds, so don't use a particularly small value unless you wish to drive the CPU load through the roof. 1000ms = 1 second. No values will be passed to the routine via @_ and return values don't affect anything either.

    +
    + + +
    + + +
    + +IRC::add_print_handler(message, subroutine_name); +
    +
    + +
    +

    This function allows you to catch the system messages (those who generally start by three stars) and to execute a function each time an event appear. The events are those you can see in "Settings->Edit Events Texts". message is the name of the event (you can find it in the Edit Events box, "Events" column) , subroutine_name is the name of the function that will get messages. Be carrful: all the arguments are sent to function in $_[0] separated by spaces.

    +
    + + +
    + + +
    + +Output commands +
    +
    + + +
    + + +
    + +IRC::print(text); +
    +
    + +
    +This is a very simple routine. All it does is put the contents of the text string to the current window. The current window will be whichever window a command was typed into when called from a command handler, or in whichever window the message command is appropriate to if it is called from within a message handler. As with any perl program, newlines are not assumed, so don't forget to end the line with \n if you don't want things to look screwey. +
    + + +
    + + +
    + +IRC::print_with_channel( text, channelname, servername ); +
    +
    + +
    +This routine does the same thing as IRC::Print does, except it allows you to direct the output to a specific window. It returns 1 on success, 0 on fail. +
    + + +
    + + +
    + +IRC::command(text); +
    +
    + +
    +This routine allows you to execute commands in the current context. The text string containing the command will be parsed by everything that would normally parse a command, including your own command handlers, so be careful. Newlines are assumed, thankfully. +
    + + +
    + + +
    + +IRC::command_with_server(text, servername); +
    +
    + +
    +This routine allows you to specify the context of the server for which the command will be executed. It's not particularly useful unless you're managing a connection manually, yet the command still exists for it's usefulness in doing things like managing a bnc connection, etc. Newlines are assumed here as well. +
    + + +
    + + +
    + +IRC::send_raw(text); +
    +
    + +
    +This routine is very useful in that it allows you to send a string directly to the IRC server you are connected to. It is assumed that the server will be the one you first connected to if there is no clear context for the command, otherwise it will go to whatever server triggered the message handler or command handler window. You must specify newlines here always or you can be guaranteed that strange things will happen. The text message you specify should be a proper RAW IRC message, so don't play with it if you don't know how to do these. Additionally, while newlines are also not assumed here as with the IRC::print function, the RFC specifies that newlines are a CR+LF pair, even if most servers will accept a mere newline. It's best to play it safe and use \r\n instead of just \n. +
    + + +
    + + +
    + +Information retrieval commands +
    +
    + + +
    + + +
    + +IRC::get_info(integer); +
    +
    + +
    +This function returns a bit of selected information depending on what the value of the integer is. +Here's a list of the currently supported values: +
    • 0 - xchat version
    • +
    • 1 - your nickname
    • +
    • 2 - channel
    • +
    • 3 - server
    • +
    • 4 - xchatdir
    • +
    • 5 - away status
    • +
    • 6 - network name
    • +
    • 7 - server hostname
    • +
    • 8 - channel topic
    +

    If you are requesting information that isn't available in the current context, then it will return null.

    +

    Any numbers other than the above will return an error message.

    +
    + + +
    + + +
    + +IRC::get_prefs(var); +
    +
    + +
    +This command lets you read the preferences that are set in the xchat configuration file. Just look at the xchat.conf dir to see what variables are available to use with this command. Returns the value of the variable requested or "Unknown Variable" if the variable isn't available. +
    + + +
    + + +
    + +IRC::user_info( nickname ); +
    +
    + +
    +Returns a flat list of information on the nickname specified consisting of... nickname, nick host, and whether they have op or voice in the current context. +
    + + +
    + + +
    + +IRC::channel_list( ); +
    +
    + +
    +This command returns a flat list which contains the current channel, server, and nickname for all channels the client is currently in. You'll have to break the list up into groups of three yourself. No arguments are necessary, or used [currently]. +
    + + +
    + + +
    + +IRC::server_list( ); +
    +
    + +
    +This command returns a flat list of servers. (Note, it is incompatible with xchat 1.8 in that it also returns a list of servers you are NOT connected to as well.) +
    + + +
    + + +
    + +IRC::user_list(channel, server); +
    +
    + +
    +

    Works very much like the dcc_list command below, except that is returns information about the users on the channel provided as first argument. The second argument is the server and is optional.

    +

    NOTE: If a user has both op and voice, only the op flag will be set to 1 by this command in xchat2.

    +
    + + +
    + + +
    + +IRC::user_list_short(channel, server); +
    +
    + +
    +

    A simpler version of IRC::user_list that returns pairs of nick & user@host suitable for assigning to a hash.

    +

    NOTE: If a user has both op and voice, only the op flag will be set to 1 by this command in xchat2.

    +
    + + +
    + + +
    + +IRC::dcc_list( ); +
    +
    + +
    +This command does essentially the same thing as channel_list, giving you the details of each DCC connection currently in progress. I have no idea exactly what is returned because I haven't had a chance to poke at this one much, but suffice it to say that it's a flat list, and the first time you play with it the meaning of the returned values should be pretty obvious. +
    + + +
    + + +
    + +IRC::ignore_list( ); +
    +
    + +
    +This command returns a flat list of the contents of your ignore list. You'll have to play with it a little as I have not had a chance to yet. Works basically the same as the other list commands. +
    + + +
    + + +
    + +Unimplemented commands that were available in xchat 1.8.x +
    +
    + +
    +add_user_list , sub_user_list , clear_user_list, notify_list were available in xchat 1.8.x but are not implemented in xchat 2 at this time. +
    + +
    +
    +

    +This document originally written by Dagmar d'Surreal on March 26th, 1998 for xchat 1.4
    +Updated on July 30th, 1999 by Peter Zelezny
    +Updated on May 16th, 2003 by DaNumber8 to comply with the perl plugin for xchat2 version 2.0.3
    + diff --git a/plugins/perl/xcperl_build.bat b/plugins/perl/xcperl_build.bat new file mode 100644 index 00000000..6f569c47 --- /dev/null +++ b/plugins/perl/xcperl_build.bat @@ -0,0 +1,43 @@ +perl generate_header + +gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\ActivePerl-5.8.9\perl\lib\CORE" -L "C:\ActivePerl-5.8.9\perl\bin" -c perl.c -o perl5.8.9.o + +dllwrap --def perl.def --dllname xcperl5.8.9.dll "C:\ActivePerl-5.8.9\perl\bin\perl58.dll" perl5.8.9.o + +strip xcperl5.8.9.dll + + + +gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\Perl\lib\CORE" -L "C:\Perl\bin" -c perl.c -o perl5.10.0.o + +dllwrap --def perl.def --dllname xcperl5.10.0.dll "C:\Perl\bin\perl510.dll" perl5.10.0.o + +strip xcperl5.10.0.dll + + +gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\ActivePerl-5.10.1\perl\lib\CORE" -L "C:\ActivePerl-5.10.1\perl\bin" -c perl.c -o perl5.10.1.o + +dllwrap --def perl.def --dllname xcperl5.10.1.dll "C:\ActivePerl-5.10.1\perl\bin\perl510.dll" perl5.10.1.o + +strip xcperl5.10.1.dll + + +gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\ActivePerl-5.12.1\perl\lib\CORE" -L "C:\ActivePerl-5.12.1\perl\bin" -c perl.c -o perl5.12.1.o + +dllwrap --def perl.def --dllname xcperl5.12.1.dll "C:\ActivePerl-5.12.1\perl\bin\perl512.dll" perl5.12.1.o + +strip xcperl5.12.1.dll + +gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\strawberry-perl-5.10.1.3\perl\lib\CORE" -L "C:\strawberry-perl-5.10.1.3\perl\bin" -c perl.c -o perl-strawberry5.10.1.o + +dllwrap --def perl.def --dllname xcperl-strawberry5.10.1.dll "C:\strawberry-perl-5.10.1.3\perl\bin\perl510.dll" perl5.10.1.o + +strip xcperl-strawberry5.10.1.dll + + +gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\strawberry-perl-5.12.1.0-portable\perl\lib\CORE" -L "C:\strawberry-perl-5.12.1.0-portable\perl\bin" -c perl.c -o perl-strawberry5.12.1.o + +dllwrap --def perl.def --dllname xcperl-strawberry5.12.1.dll "C:\strawberry-perl-5.12.1.0-portable\perl\bin\perl512.dll" perl5.12.1.o + +strip xcperl-strawberry5.12.1.dll + diff --git a/plugins/plugin-conf.in b/plugins/plugin-conf.in new file mode 100644 index 00000000..d05792b1 --- /dev/null +++ b/plugins/plugin-conf.in @@ -0,0 +1,20 @@ + +AC_INIT(@PLUGIN@-config.h.in) +AM_CONFIG_HEADER(@PLUGIN@-config.h) +AM_INIT_AUTOMAKE(xchat-@PLUGIN@, @PLUGIN_VERSION@) +AM_MAINTAINER_MODE +AM_DISABLE_STATIC +AM_PROG_LIBTOOL + +AC_ARG_WITH(plugin-includes, +[ --with-plugin-includes directory containing xchat-plugin.h], + PLUGIN_INCLUDES=$enableval) + +AC_SUBST(PLUGIN_INCLUDES) + +xchatlibdir=${libdir}/xchat +AC_SUBST(xchatlibdir) + +AC_OUTPUT( +Makefile +) diff --git a/plugins/plugin20.html b/plugins/plugin20.html new file mode 100644 index 00000000..787c048b --- /dev/null +++ b/plugins/plugin20.html @@ -0,0 +1,1002 @@ + + + +XChat 2.0 Plugin Interface + + + + +

    XChat 2.0 Plugin Interface

    + + +plugin20.html revision 2.86 +
    Latest version of this document is available at:
    http://xchat.org/docs/plugin20.html + +

    1. Documentation:

    +
    +1.0 Introduction +
    1.1 Sample plugin +
    1.2 What is word and word_eol? +
    1.3 Lists and fields +
    1.4 Plugins on Windows (Win32) +
    1.5 Controlling the GUI +
      1.5.1 Basic Control +
      1.5.2 Custom Menu Items +
      1.5.3 System Tray +
    1.6 Handling UTF-8/Unicode strings +
    + +

    2. Function reference:

    +
    +xchat_hook_command +
    xchat_hook_fd +
    xchat_hook_print +
    xchat_hook_server +
    xchat_hook_timer +
    xchat_unhook +
    +
    xchat_command +
    xchat_commandf +
    xchat_print +
    xchat_printf +
    xchat_emit_print +
    xchat_send_modes +
    +
    xchat_find_context +
    xchat_get_context +
    xchat_get_info +
    xchat_get_prefs +
    xchat_set_context +
    +
    xchat_nickcmp +
    xchat_strip +
    xchat_free +
    +
    xchat_list_get +
    xchat_list_free +
    xchat_list_fields (not documented yet) +
    xchat_list_next +
    xchat_list_str +
    xchat_list_int +
    xchat_list_time +
    +
    xchat_plugingui_add (not documented yet) +
    xchat_plugingui_remove (not documented yet) +

    + +

    Introduction

    +Plugins for XChat are written in C. The interface aims to keep 100% +binary compatability. This means that if you upgrade XChat, you will +not need to recompile your plugins, they'll continue to work. The +interface doesn't depend on any structures and offsets, so compiler +versions shouldn't have an impact either. The only real requirement of +an XChat plugin, is that it define a "xchat_plugin_init" symbol. This +is your entry point function, see the example below. You should make +all your global variables and functions static, so that a symbol +is not exported. There is no harm in exporting these symbols, but they +are not necessary and only pollute the name-space. Plugins are compiled as shared objects +(.so files), for example: +

    +Most UNIX systems:
    +	gcc -Wl,--export-dynamic -Wall -O1 -shared -fPIC myplugin.c -o myplugin.so
    +
    +MacOSX:
    +	gcc -no-cpp-precomp -g -O2 -Wall -bundle -flat_namespace -undefined suppress -o myplugin.so myplugin.c
    +
    + +See the Windows section on how to compile a plugin +using visual studio. +

    +All strings passed to and from plugins are encoded in UTF-8, regardless +of locale. What does this mean? +


    + +

    Sample plugin

    +This simple plugin autoOps anyone who joins a channel you're in. It also +adds a new command /AUTOOPTOGGLE, which can be used to turn the feature ON +or OFF. Every XChat plugin must define an xchat_plugin_init function, this +is the normal entry point. xchat_plugin_deinit is optional. +
    +
    +
    +
    +#include "xchat-plugin.h"
    +
    +#define PNAME "AutoOp"
    +#define PDESC "Auto Ops anyone that joins"
    +#define PVERSION "0.1"
    +
    +static xchat_plugin *ph;   /* plugin handle */
    +static int enable = 1;
    +
    +static int join_cb(char *word[], void *userdata)
    +{
    +   if (enable)
    +      /* Op ANYONE who joins */
    +      xchat_commandf(ph, "OP %s", word[1]);
    +   /* word[1] is the nickname, as in the Settings->Advanced->TextEvents window in xchat */
    +
    +   return XCHAT_EAT_NONE;  /* don't eat this event, xchat needs to see it! */
    +}
    +
    +static int autooptoggle_cb(char *word[], char *word_eol[], void *userdata)
    +{
    +   if (!enable)
    +   {
    +      enable = 1;
    +      xchat_print(ph, "AutoOping now enabled!\n");
    +   } else
    +   {
    +      enable = 0;
    +      xchat_print(ph, "AutoOping now disabled!\n");
    +   }
    +
    +   return XCHAT_EAT_ALL;   /* eat this command so xchat and other plugins can't process it */
    +}
    +
    +void xchat_plugin_get_info(char **name, char **desc, char **version, void **reserved)
    +{
    +   *name = PNAME;
    +   *desc = PDESC;
    +   *version = PVERSION;
    +}
    +
    +int xchat_plugin_init(xchat_plugin *plugin_handle,
    +                      char **plugin_name,
    +                      char **plugin_desc,
    +                      char **plugin_version,
    +                      char *arg)
    +{
    +   /* we need to save this for use with any xchat_* functions */
    +   ph = plugin_handle;
    +
    +   /* tell xchat our info */
    +   *plugin_name = PNAME;
    +   *plugin_desc = PDESC;
    +   *plugin_version = PVERSION;
    +
    +   xchat_hook_command(ph, "AutoOpToggle", XCHAT_PRI_NORM, autooptoggle_cb, "Usage: AUTOOPTOGGLE, Turns OFF/ON Auto Oping", 0);
    +   xchat_hook_print(ph, "Join", XCHAT_PRI_NORM, join_cb, 0);
    +
    +   xchat_print(ph, "AutoOpPlugin loaded successfully!\n");
    +
    +   return 1;       /* return 1 for success */
    +}
    +
    +
    +
    + +

    What's word and word_eol?

    + +They are arrays of strings. They contain the parameters the user entered +for the particular command. For example, if you executed: + +
    +/command NICK hi there
    +
    +word[1] is command
    +word[2] is NICK
    +word[3] is hi
    +word[4] is there
    +
    +word_eol[1] is command NICK hi there
    +word_eol[2] is NICK hi there
    +word_eol[3] is hi there
    +word_eol[4] is there
    +
    +These arrays are simply provided for your convenience. You are NOT allowed +to alter them. Both arrays are limited to 32 elements (index 31). word[0] and +word_eol[0] are reserved and should not be read. +


    +

    Lists and Fields

    +Lists of information (DCCs, Channels, Userlist etc) can be retreived +with xchat_list_get. All fields are READ ONLY and must be copied if +needed for a long time after calling xchat_list_str. The types of lists and fields available are: +
    + +"channels" - list of channels, querys and their servers. +
    + + + + + + + + + + + + + + + +
    NameDescriptionType
    channelChannel or query namestring
    chantypesChannel types e.g. "#!&"
    (Added in version 2.0.9. Older versions will return NULL)
    string
    context(xchat_context *) pointer. Can be used with xchat_set_contextstring
    flagsServer/Channel Bits:
    + + + + + + + + + + + + + +
    Bit #ValueDescription
    01Connected
    12Connecting in Progress
    24You are away
    38End of MOTD (Login complete)
    416Has WHOX (ircu)
    532Has IDMSG (FreeNode)
    664Hide Join/Part Messages
    7128unused (was Color Paste in old versions)
    8256Beep on Message
    9512Blink Tray
    101024Blink Task Bar
    +
    (Bits 0-5 added in 2.0.9. Bits 6-8 added in 2.6.6. Bit 9 added in 2.8.0. Bit 10 in 2.8.6)
    int
    idUnique server ID
    (Added in version 2.0.8. Older versions will return -1)
    int
    lagLag in milliseconds
    (Added in version 2.6.8. Older versions will return -1)
    int
    maxmodesMaximum modes per line
    (Added in version 2.0.9. Older versions will return -1)
    int
    networkNetwork name to which this channel belongs
    (Added in version 2.0.2. Older versions will return NULL)
    string
    nickprefixesNickname prefixes e.g. "@+"
    (Added in version 2.0.9. Older versions will return NULL)
    string
    nickmodesNickname mode chars e.g. "ov"
    (Added in version 2.0.9. Older versions will return NULL)
    string
    queueNumber of bytes in the send-queue
    (Added in version 2.6.8. Older versions will return -1)
    int
    serverServer name to which this channel belongsstring
    typeType of context this is: 1-Server 2-Channel 3-Dialog
    (Added in version 2.0.2. Older versions will return -1)
    int
    usersNumber of users in this channel
    (Added in version 2.0.8. Older versions will return -1)
    int
    +
    + +"dcc" - list of DCC file transfers. Fields: +
    + + + + + + + + + + + + + + + +
    NameDescriptionType
    address32Address of the remote user (ipv4 address)int
    cpsBytes per second (speed)int
    destfileDestination full pathnamestring
    fileFile namestring
    nickNickname of person who the file is from/tostring
    portTCP port numberint
    posBytes sent/receivedint
    poshighBytes sent/received, high order 32 bitsint
    resumePoint at which this file was resumed (or zero if it was not resumed)int
    resumehighPoint at which this file was resumed, high order 32 bitsint
    sizeFile size in bytes, low order 32 bits (cast it to unsigned)int
    sizehighFile size in bytes, high order 32 bitsint
    statusDCC Status: 0-Queued 1-Active 2-Failed 3-Done 4-Connecting 5-Abortedint
    typeDCC Type: 0-Send 1-Receive 2-ChatRecv 3-ChatSendint
    +
    + +"ignore" - current ignore list. +
    + + + +
    NameDescriptionType
    maskIgnore mask. .e.g: *!*@*.aol.comstring
    flagsBit field of flags. 0=Private 1=Notice 2=Channel 3=Ctcp
    +4=Invite 5=UnIgnore 6=NoSave 7=DCC
    int
    +
    + +"notify" - list of people on notify. +
    + + + + + + + +
    NameDescriptionType
    networksNetworks to which this nick applies. Comma separated. May be NULL. +
    (Added in version 2.6.8)
    string
    nickNicknamestring
    flagsBit field of flags. 0=Is online.int
    onTime when user came online.time_t
    offTime when user went offline.time_t
    seenTime when user the user was last verified still online.time_t
    +The entire "notify" list was added in xchat 2.0.8. Fields are +only valid for the context when xchat_list_get() was called +(i.e. you get information about the user ON THAT ONE SERVER ONLY). You +may cycle through the "channels" list to find notify information for every +server. +
    + +"users" - list of users in the current channel. +
    + + + + + + + + +
    NameDescriptionType
    awayAway status (boolean)
    (Added in version 2.0.6. Older versions will return -1)
    int
    lasttalkLast time the user was seen talking
    (Added in version 2.4.2. Older versions will return -1)
    time_t
    nickNick namestring
    hostHost name in the form: user@host (or NULL if not known).string
    prefixPrefix character, .e.g: @ or +. Points to a single char.string
    realnameReal name or NULL
    (Added in version 2.8.6)
    string
    selectedSelected status in the user list, only works for retrieving the user list of the focused tab
    (Added in version 2.6.1. Older versions will return -1)
    int
    +
    + +
    + +Example: +
    +
    +   list = xchat_list_get(ph, "dcc");
    +   if(list)
    +   {
    +      xchat_print(ph, "--- DCC LIST ------------------\n"
    +                      "File  To/From   KB/s   Position\n");
    +
    +      while(xchat_list_next(ph, list))
    +      {
    +         xchat_printf(ph, "%6s %10s %.2f  %d\n",
    +             xchat_list_str(ph, list, "file"),
    +             xchat_list_str(ph, list, "nick"),
    +             xchat_list_int(ph, list, "cps") / 1024,
    +             xchat_list_int(ph, list, "pos"));
    +      }
    +
    +      xchat_list_free(ph, list);
    +   }
    +
    + +
    + +

    Plugins on Windows (Win32)

    +Yes, it can be done. All you need is either +MSVC (Visual Studio) or +MINGW, both these compilers are free to download. +Simply compile your plugin as a DLL. You should have the following files: + +
      +
    • xchat-plugin.h - Main Plugin header
    • +
    • plugin.c - Your plugin, you need to write this one :)
    • +
    • plugin.def - A simple text file containing the following:
    • +
    +
    +EXPORTS
    +  xchat_plugin_init
    +  xchat_plugin_deinit
    +  xchat_plugin_get_info
    +
    + +
    Leave out xchat_plugin_deinit if you don't intend to define that +function. Then, to compile, type this at your command prompt:

    +
    +MSVC +
     cl -O1 -MD -G5 -DWIN32 -c plugin.c
    +
     link /DLL /out:plugin.dll /SUBSYSTEM:WINDOWS plugin.obj /def:plugin.def /base:0x00d40000 +

    +GCC (MINGW) +
     gcc -Wall -Os -DWIN32 -c plugin.c
    +
     dllwrap --def plugin.def --dllname plugin.dll plugin.o

    +
    +
    For a complete example, have a look at the source code of the DNS Plugin, which also contains a Makefile. +

    +Caveat: Plugins compiled on Win32 MUST have a +global variable called ph, which is the plugin_handle, much like +in the sample plugin above. +

    + +

    Controlling the GUI

    +

    +A simple way to perform basic GUI functions is to use the /GUI command. +You can execute this command through the input-box, or by calling +xchat_command(ph, "GUI .....");. +

    +
    + + + + + + + + + + + +
    GUI ATTACHSame function as "Attach Window" in the XChat menu (new for 2.6.2).
    GUI DETACHSame function as "Detach Tab" in the XChat menu (new for 2.6.2).
    GUI APPLYSimilar to clicking OK in the settings window. Execute this after /SET to activate GUI changes (new for 2.8.0)
    GUI COLOR nChange the tab color of the current context, where n is a number from 0 to 3.
    GUI FOCUSFocus the current window or tab.
    GUI FLASHFlash the taskbar button. It will flash only if the window isn't focused and will stop when it is focused by the user.
    GUI HIDEHide the main xchat window completely (this is used by the Systray plugin).
    GUI ICONIFYIconify (minimize to taskbar) the current xchat window.
    GUI MSGBOX textDisplays a asynchronous message box with your text (new for 2.4.5).
    GUI SHOWShow the main xchat window (if currently hidden).
    +
    +

    +Note, the FLASH, ICONIFY and COLOR args were added in xchat 2.0.8, they +will not work with previous versions. +

    +Starting from 2.4.5 you can add your own items to the menu bar. The menu command has this syntax: +
    +	MENU [-eX] [-i<ICONFILE>] [-k<mod>,<key>] [-m] [-pX] [-rX,group] [-tX] {ADD|DEL} <path> [command] [unselect command]
    +For example: +
    +	MENU -p5 ADD FServe
    +	MENU ADD "FServe/Show File List" "fs list"
    +	MENU ADD FServe/-
    +	MENU -k4,101 -t1 ADD "FServe/Enabled" "fs on" "fs off"
    +	MENU -e0 ADD "FServe/Do Something" "fs action"
    +
    +In the example above, it would be recommended to execute "MENU DEL FServe" inside your xchat_plugin_deinit function. The special item with name "-" will add a separator line. +

    +Parameters and flags: +
    + + + + + + + + +
    -eXSet enable flag to X. -e0 for disable, -e1 for enable. This lets you create a disabled (shaded) item.
    -iFILEUse an icon filename FILE (new for 2.8.0). Not supported for toggles or radio items.
    -k<mod>,<key>Specify a keyboard shortcut. "mod" is the modifier which is a bitwise OR of: 1-SHIFT 4-CTRL 8-ALT in decimal. "key" is the key value in decimal, e.g. -k5,101 would specify SHIFT-CTRL-E.
    -mSpecify that this label should be treated as Pango Markup language. Since forward slash ("/") is already used in menu paths, you should replace closing tags with an ASCII 003 instead e.g.: xchat_command(ph, "MENU -m ADD \"<b>Bold Menu<\003b>\""); (new for 2.6.6).
    -pXSpecify a menu item's position number. e.g. -p5 will cause the item to be inserted in the 5th place. New for 2.8.0: If the position is a negative number, it will be used as an offset from the bottom/right-most item.
    -rX,groupSpecify a radio menu item, with initial state X and a group name (new for 2.8.0). The group name should be the exact label of another menu item (without the path) that this item will be grouped with. For radio items, only a select command will be executed (no unselect command).
    -tXSpecify a toggle menu item with an initial state. -t0 for an "unticked" item and -t1 for a "ticked" item.
    +
    + +If you want to change an item's toggle state or enabled flag, +just ADD an item with exactly the same name and command and specify the -tX -eX parameters you need. +

    It's also possible to add items to XChat's existing menus, for example:
    +
    	MENU ADD "Settings/Sub Menu"
    +	MENU -t0 ADD "Settings/Sub Menu/My Setting" myseton mysetoff
    +
    +However, internal names and layouts of XChat's menu may change in the future, so use at own risk. +

    +Here is an example of Radio items: +
    	MENU ADD "Language"
    +	MENU -r1,"English" ADD "Language/English" cmd1
    +	MENU -r0,"English" ADD "Language/Spanish" cmd2
    +	MENU -r0,"English" ADD "Language/German" cmd3
    +
    +From 2.8.0, you can also change menus other than the main one (i.e popup menus). Currently they are: +
    + + + + + + + + +
    Root NameMenu
    $TABTab menu (right click a channel/query tab or treeview row)
    $TRAYSystem Tray menu
    $URLURL link menu
    $NICKUserlist nick-name popup menu
    $CHANMenu when clicking a channel in the text area (since 2.8.4)
    +
    +
    +	Example: MENU -p0 ADD "$TAB/Cycle Channel" cycle
    +
    + +
    +Starting from 2.8.0 you can manipulate XChat's system tray icon using the /TRAY command: +
    + Usage: 
    + TRAY -f <timeout> <file1> [<file2>] Flash tray between two icons. Leave off file2 to use default xchat icon.
    + TRAY -f <filename>                  Set tray to a fixed icon.
    + TRAY -i <number>                    Flash tray with an internal icon.
    +                                     2=Message 5=Highlight 8=Private 11=File
    + TRAY -t <text>                      Set the tray tooltip.
    + TRAY -b <title> <text>              Set the tray balloon.
    +                                     Supported on Windows from 2.8.1 and 2.8.2 on Linux (libnotify required on Linux).
    +
    +Filenames can be ICO or PNG format. PNG format is supported on Linux/BSD and Windows XP (but requires installation of GDI+ on Windows 2000). Set a timeout of -1 to use XChat's default. +

    + +

    Handling UTF-8/Unicode strings

    +

    +The XChat plugin API specifies that strings passed to and from xchat must be encoded in UTF-8. +

    +What does this mean for the plugin programmer? You just have to be a little careful when +passing strings obtained from IRC to system calls. For example, if you're writing a file-server +bot, someone might message you a filename. Can you pass this filename directly to open()? Maybe! +If you're lazy... The correct thing to do is to convert the string to "system locale encoding", +otherwise your plugin will fail on non-ascii characters. +

    +Here are examples on how to do this conversion on Unix and Windows. In this example, someone will +CTCP you the message "SHOWFILE <filename>". +

    +

    +
    +static int ctcp_cb(char *word[], char *word_eol[], void *userdata)
    +{
    +	if(strcmp(word[1], "SHOWFILE") == 0)
    +	{
    +		get_file_name(nick, word[2]);
    +	}
    +
    +	return XCHAT_EAT_XCHAT;
    +}
    +
    +static void get_file_name(char *nick, char *fname)
    +{
    +	char buf[256];
    +	FILE *fp;
    +
    +	/* the fname is in UTF-8, because it came from the xchat API */
    +
    #ifdef _WIN32
    +	wchar_t wide_name[MAX_PATH];
    +
    +	/* convert UTF-8 to WIDECHARs (aka UTF-16LE) */
    +	if (MultiByteToWideChar(CP_UTF8, 0, fname, -1, wide_name, MAX_PATH) < 1)
    +		return;
    +
    +	/* now we have WIDECHARs, so we can _wopen() or CreateFileW(). */
    +	/* _wfopen actually requires NT4, Win2000, XP or newer. */
    +	fp = _wfopen(wide_name, "r");
    +
    #else
    +	char *loc_name;
    +
    +	/* convert UTF-8 to System Encoding */
    +	loc_name = g_filename_from_utf8(fname, -1, 0, 0, 0);
    +	if(!loc_name)
    +		return;
    +
    +	/* now open using the system's encoding */
    +	fp = fopen(loc_name, "r");
    +	g_free(loc_name);
    +
    #endif
    +	if (fp)
    +	{
    +		while (fgets (buf, sizeof(buf), fp))
    +		{
    +			/* send every line to the user that requested it */
    +			xchat_commandf (ph, "QUOTE NOTICE %s :%s", nick, buf);
    +		}
    +		fclose (fp);
    +	}
    +}
    +
    + + + +

    + +

    Functions

    + +

     xchat_hook_command() 

    +Prototype: xchat_hook *xchat_hook_command(xchat_plugin *ph, const char *name, int pri, xchat_cmd_cb *callb, const char *help_text, void *userdata); +
    +
    Description: Adds a new /command. This allows your program to +handle commands entered at the input box. To capture text without a "/" at +the start (non-commands), you may hook a special name of "". i.e xchat_hook_command(ph, "", ...);. +
    +Starting from version 2.6.8, commands hooked that begin with a period ('.') will be hidden in /HELP and /HELP -l. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    name: Name of the command (without the forward slash). +
    pri: Priority of this command. Use XCHAT_PRI_NORM. +
    callb: Callback function. This will be called when the user executes the given command name. +
    help_text: String of text to display when the user executes /help for this command. May be NULL if you're lazy. +
    userdata: Pointer passed to the callback function.
    +Returns: Pointer to the hook. Can be passed to xchat_unhook. +
    +
    Example: +
    +
    +static int onotice_cb(char *word[], char *word_eol[], void *userdata)
    +{
    +	if(word_eol[2][0] == 0)
    +	{
    +		xchat_printf(ph, "Second arg must be the message!\n");
    +		return XCHAT_EAT_ALL;
    +	}
    +
    +	xchat_commandf(ph, "NOTICE @%s :%s", xchat_get_info(ph, "channel"), word_eol[2]);
    +	return XCHAT_EAT_ALL;
    +}
    +
    +xchat_hook_command(ph, "ONOTICE", XCHAT_PRI_NORM, onotice_cb,
    +                   "Usage: ONOTICE <message> Sends a notice to all ops", NULL);
    +
    +
    +
    + +

     xchat_hook_fd() 

    +Prototype: xchat_hook *xchat_hook_fd(xchat_plugin *ph, int fd, int flags, xchat_fd_cb *callb, void *userdata); +
    +
    Description: Hooks a socket or file descriptor. WIN32: Passing a pipe from MSVCR71, MSVCR80 or other variations is not supported at this time. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    fd: The file descriptor or socket. +
    flags: One or more of XCHAT_FD_READ, XCHAT_FD_WRITE, XCHAT_FD_EXCEPTION, XCHAT_FD_NOTSOCKET. Use bitwise OR to combine them. +XCHAT_FD_NOTSOCKET tells xchat that the provided fd is not a socket, but a "MSVCRT.DLL" pipe. +
    callb: Callback function. This will be called when the socket is available for reading/writing or exception (depending on your chosen flags) +
    userdata: Pointer passed to the callback function.
    +Returns: Pointer to the hook. Can be passed to xchat_unhook. +


    + +

     xchat_hook_print() 

    +Prototype: xchat_hook *xchat_hook_print(xchat_plugin *ph, const char *name, int pri, xchat_print_cb *callb, void *userdata); +
    +
    Description: Registers a function to trap any print events. +The event names may be any available in the "Advanced > Text Events" window. +There are also some extra "special" events you may hook using this function. +Currently they are:
    +"Open Context" - Called when a new xchat_context is created. +
    "Close Context" - Called when a xchat_context pointer is closed. +
    "Focus Tab" - Called when a tab is brought to front. +
    "Focus Window" - Called a toplevel window is focused, or the main +tab-window is focused by the window manager. +
    "DCC Chat Text" - Called when some text from a DCC Chat arrives. It provides these elements in the word[] array:
    word[1] Address +
    word[2] Port +
    word[3] Nick +
    word[4] The Message +
    +"Key Press" - Called when some keys are pressed in the input-box (since 2.4.2). It provides these elements in the word[] array:
    word[1] Key Value +
    word[2] State Bitfield (shift, capslock, alt) +
    word[3] String version of the key +
    word[4] Length of the string (may be 0 for unprintable keys) +
    +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    name: Name of the print event (as in Edit Event Texts Window). +
    pri: Priority of this command. Use XCHAT_PRI_NORM. +
    callb: Callback function. This will be called when this event name is printed. +
    userdata: Pointer passed to the callback function.
    +Returns: Pointer to the hook. Can be passed to xchat_unhook. +
    +
    Example: +
    +
    +static int youpart_cb(char *word[], void *userdata)
    +{
    +	xchat_printf(ph, "You have left channel %s\n", word[3]);
    +	return XCHAT_EAT_XCHAT;	/* dont let xchat do its normal printing */
    +}
    +
    +xchat_hook_print(ph, "You Part", XCHAT_PRI_NORM, youpart_cb, NULL);
    +
    +
    +
    + +

     xchat_hook_server() 

    +Prototype: xchat_hook *xchat_hook_server(xchat_plugin *ph, const char *name, int pri, xchat_serv_cb *callb, void *userdata); +
    +
    Description: Registers a function to be called when a certain server event occurs. You can +use this to trap PRIVMSG, NOTICE, PART, a server numeric etc... If you want to +hook every line that comes from the IRC server, you may use the special name of "RAW LINE". +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    name: Name of the server event. +
    pri: Priority of this command. Use XCHAT_PRI_NORM. +
    callb: Callback function. This will be called when this event is received from the server. +
    userdata: Pointer passed to the callback function.
    +Returns: Pointer to the hook. Can be passed to xchat_unhook. +
    +
    Example: +
    +
    +static int kick_cb(char *word[], char *word_eol[], void *userdata)
    +{
    +	xchat_printf(ph, "%s was kicked from %s (reason=%s)\n", word[4], word[3], word_eol[5]);
    +	return XCHAT_EAT_NONE;	/* don't eat this event, let other plugins and xchat see it too */
    +}
    +
    +xchat_hook_server(ph, "KICK", XCHAT_PRI_NORM, kick_cb, NULL);
    +
    +
    +
    + +

     xchat_hook_timer() 

    +Prototype: xchat_hook *xchat_hook_timer(xchat_plugin *ph, int timeout, xchat_timer_cb *callb, void *userdata); +
    +
    Description: Registers a function to be called every "timeout" milliseconds. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    timeout: Timeout in milliseconds (1000 is 1 second). +
    callb: Callback function. This will be called every "timeout" milliseconds. +
    userdata: Pointer passed to the callback function.
    +Returns: Pointer to the hook. Can be passed to xchat_unhook. +
    +
    Example: +
    +
    +static xchat_hook *myhook;
    +
    +static int stop_cb(char *word[], char *word_eol[], void *userdata)
    +{
    +	if(myhook != NULL)
    +	{
    +		xchat_unhook(ph, myhook);
    +		myhook = NULL;
    +		xchat_print(ph, "Timeout removed!\n");
    +	}
    +
    +	return XCHAT_EAT_ALL;
    +}
    +
    +static int timeout_cb(void *userdata)
    +{
    +	xchat_print(ph, "Annoying message every 5 seconds! Type /STOP to stop it.\n");
    +	return 1;	/* return 1 to keep the timeout going */
    +}
    +
    +myhook = xchat_hook_timer(ph, 5000, timeout_cb, NULL);
    +xchat_hook_command(ph, "STOP", XCHAT_PRI_NORM, stop_cb, NULL, NULL);
    +

    +
    + +

     xchat_unhook() 

    +Prototype: void *xchat_unhook(xchat_plugin *ph, xchat_hook *hook); +
    +
    Description: Unhooks any hook registered with xchat_hook_print/server/timer/command. When plugins are unloaded, all of its hooks are automatically +removed, so you don't need to call this within your xchat_plugin_deinit() function. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    hook: Pointer to the hook, as returned by xchat_hook_*. +
    +Returns: The userdata you originally gave to xchat_hook_*. +

    + +

     xchat_command() 

    +Prototype: void xchat_command(xchat_plugin *ph, const char *command); +
    +
    Description: Executes a command as if it were typed in xchat's input box. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    command: Command to execute, without the forward slash "/". +

    +
    + +

     xchat_commandf() 

    +Prototype: void xchat_commandf(xchat_plugin *ph, const char *format, ...); +
    +
    Description: Executes a command as if it were typed in xchat's input box and provides string formating like printf. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    format: The format string. +

    +
    + +

     xchat_print() 

    +Prototype: void xchat_print(xchat_plugin *ph, const char *text); +
    +
    Description: Prints some text to the current tab/window. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    text: Text to print. May contain mIRC color codes. +

    +
    + +

     xchat_printf() 

    +Prototype: void xchat_printf(xchat_plugin *ph, const char *format, ...); +
    +
    Description: Prints some text to the current tab/window and provides formating like printf. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    format: The format string. +

    +
    + +

     xchat_emit_print() 

    +Prototype: int xchat_emit_print(xchat_plugin *ph, const char *event_name, ...); +
    +
    Description: Generates a print event. This can be any +event found in the Preferences > Advanced > Text Events window. The vararg parameter list +MUST always be NULL terminated. Special care should be taken when calling this function +inside a print callback (from xchat_hook_print), as not to cause endless recursion. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    event_name: Text event to print. +

    +
    +Returns: 1-Success 0-Failure. +

    +Example: +
    +xchat_emit_print(ph, "Channel Message", "John", "Hi there", "@", NULL);
    +
    +

    + +

     xchat_send_modes() (new for 2.0.9)

    +Prototype: void xchat_send_modes (xchat_plugin *ph, const char *targets[], int ntargets, int modes_per_line, char sign, char mode) +
    +
    Description: Sends a number of channel mode changes to the current channel. For example, you can Op a whole +group of people in one go. It may send multiple MODE lines if the request doesn't fit on one. Pass 0 for +modes_per_line to use the current server's maximum possible. This function should only be called while +in a channel context. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    targets: Array of targets (strings). The names of people whom the action will be performed on. +
    ntargets: Number of elements in the array given. +
    modes_per_line: Maximum modes to send per line. +
    sign: Mode sign, '-' or '+'. +
    mode: Mode char, e.g. 'o' for Ops.
    +
    +Example: (Ops the three names given) +
    +const char *names_to_Op[] = {"John", "Jack", "Jill"};
    +xchat_send_modes(ph, names_to_Op, 3, 0, '+', 'o');
    +
    +

    + +

     xchat_find_context() 

    +Prototype: xchat_context *xchat_find_context(xchat_plugin *ph, const char *servname, const char *channel); +
    +
    Description: Finds a context based on a channel and servername. If servname is NULL, it finds any channel (or query) by the given name. If channel is NULL, it finds the front-most tab/window of the given servname. If NULL is given for both arguments, the currently focused tab/window will be returned.
    +Changed in 2.6.1. If servname is NULL, it finds the channel (or query) by the given name in the same server group as the current context. If that doesn't exists then find any by the given name. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    servname: Servername or NULL. +
    channel: Channelname or NULL. +
    +
    +Returns: Context pointer (for use with xchat_set_context) or NULL. +


    + +

     xchat_get_context() 

    +Prototype: xchat_context *xchat_get_context(xchat_plugin *ph); +
    +
    Description: Returns the current context for your plugin. You can use this later with xchat_set_context. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    +
    +Returns: Context pointer (for use with xchat_set_context). +


    + +

     xchat_get_info() 

    +Prototype: const char *xchat_get_info(xchat_plugin *ph, const char *id); +
    +
    Description: Returns information based on your current context. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    id: ID of the information you want. Currently supported IDs are (case sensitive): +
    + + + + + + + + + + + + + + + + + + + + +
    awayaway reason or NULL if you are not away.
    channelcurrent channel name.
    charsetcharacter-set used in the current context (since 2.4.2).
    event_text <name>text event format string for name (since 2.8.2).
    gtkwin_ptr(GtkWindow *) (since 2.8.9).
    hostreal hostname of the server you connected to.
    inputboxthe input-box contents, what the user has typed (since 2.4.1).
    libdirfslibrary directory. e.g. /usr/lib/xchat. The same directory used for auto-loading plugins (since 2.4.0).This string isn't necessarily UTF-8, but local file system encoding.
    modeschannel modes, if known, or NULL (since 2.8.1).
    networkcurrent network name or NULL.
    nickyour current nick name.
    nickservnickserv password for this network or NULL (since 2.4.3).
    servercurrent server name (what the server claims to be). NULL if you are not connected.
    topiccurrent channel topic.
    versionxchat version number.
    win_ptrnative window pointer. Unix: (GtkWindow *) Win32: HWND (since 2.6.0).
    win_statuswindow status: "active", "hidden" or "normal" (since 2.0.9).
    xchatdirxchat config directory, e.g.: /home/user/.xchat2 This string is encoded in UTF-8, which means you _should_ convert it to "locale" encoding before using functions like open() or OpenFile(). For best Unicode support on Linux, convert this string using g_filename_from_utf8 and on Windows convert this string to UTF-16LE (wide) and use OpenFileW() etc.
    xchatdirfsxchat config directory, e.g.: /home/user/.xchat2 (since 2.0.9).This string is encoded in local file system encoding, making it ideal for direct use with functions like open() or OpenFile(). For real Unicode support on Windows, it's best not to use xchatdirfs, but xchatdir instead.
    +
    +
    +Returns: A string of the requested information, or NULL. This string must +not be freed and must be copied if needed after the call to xchat_get_info. +


    + +

     xchat_get_prefs() 

    +Prototype: int xchat_get_prefs(xchat_plugin *ph, const char *name, const char **string, int *integer); +
    +
    Description: Provides xchat's setting information (that which is available through the /set command). +A few extra bits of information are available that don't appear in the /set list, currently they are: +
    +
    + + + +
    state_cursorCurrent input-box cursor position (characters, not bytes). Since 2.4.2.
    idUnique server id. Since 2.6.1.
    +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    name: Setting name required. +
    string: Pointer-pointer which to set. +
    integer: Pointer to an integer to set, if setting is a Boolean or Integer type. +
    +Returns: 0-Failed 1-Returned a string 2-Returned an Integer 3-Returned a Boolean. +

    Example: +
    +
    +{
    +	int i;
    +	const char *str;
    +
    +	if (xchat_get_prefs (ph, "irc_nick1", &str, &i) == 1)
    +	{
    +		xchat_printf (ph, "Current nickname setting: %s\n", str);
    +	}
    +}
    +
    +

    + + +

     xchat_set_context() 

    +Prototype: int xchat_set_context(xchat_plugin *ph, xchat_context *ctx); +
    +
    Description: Changes your current context to the one given. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    ctx: Context to change to (obtained with xchat_get_context or xchat_find_context). +
    +
    +Returns: 1 for success, 0 for failure. +


    + +

     xchat_nickcmp() 

    +Prototype: int xchat_nickcmp(xchat_plugin *ph, const char *s1, const char *s2); +
    +
    Description: Performs a nick name comparision, based on the current server connection. This might be a RFC1459 compliant string compare, or +plain ascii (in the case of DALNet). Use this to compare channels and nicknames. The function works the same way as strcasecmp. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    s1: String to compare. +
    s2: String to compare s1 to. +
    +
    +Quote from RFC1459: +
    + Because of IRC's scandanavian origin, the characters {}| are + considered to be the lower case equivalents of the characters []\, + respectively. This is a critical issue when determining the + equivalence of two nicknames. +
    +Returns: + An integer + less than, equal to, or greater than zero if s1 is found, + respectively, to be less than, to match, or be greater than s2. +


    + +

     xchat_strip() (new for 2.4.2)

    +Prototype: char *xchat_strip(xchat_plugin *ph, const char *str, int len, int flags); +
    +
    Description: Strips mIRC color codes and/or text attributes (bold, underlined etc) from the given string and returns a newly allocated string. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    str: String to strip. +
    len: Length of the string (or -1 for NULL terminated). +
    flags: Bit-field of flags: 0-Strip mIRC colors, 1-Strip text attributes. +
    +
    +Returns: +A newly allocated string or NULL for failure. You must free this string with xchat_free. +

    Example: +
    +
    +{
    +	char *new_text;
    +
    +	/* strip both colors and attributes by using the 0 and 1 bits (1 BITWISE-OR 2) */
    +	new_text = xchat_strip(ph, "\00312Blue\003 \002Bold!\002", -1, 1 | 2);
    +
    +	if(new_text)
    +	{
    +		/* new_text should now contain only "Blue Bold!" */
    +		xchat_printf(ph, "%s\n", new_text);
    +		xchat_free(ph, new_text);
    +	}
    +}
    +
    + +

    + +

     xchat_free() (new for 2.4.2)

    +Prototype: void xchat_free(xchat_plugin *ph, void *ptr); +
    +
    Description: Frees a string returned by xchat_* functions. Currently only used to free strings from xchat_strip. +
    +
    Arguments: +
    ph: Plugin handle (as given to xchat_plugin_init). +
    ptr: Pointer to free. +
    +
    + +

    + + + diff --git a/plugins/python/Makefile.am b/plugins/python/Makefile.am new file mode 100644 index 00000000..1e4adff8 --- /dev/null +++ b/plugins/python/Makefile.am @@ -0,0 +1,10 @@ +EXTRA_DIST = + +libdir = $(xchatlibdir)/plugins + +lib_LTLIBRARIES = python.la +python_la_SOURCES = python.c +python_la_LDFLAGS = -avoid-version -module +python_la_LIBADD = $(PY_LIBS) +INCLUDES = $(PY_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/.. + diff --git a/plugins/python/python.c b/plugins/python/python.c new file mode 100644 index 00000000..fd682082 --- /dev/null +++ b/plugins/python/python.c @@ -0,0 +1,2257 @@ +/* +* Copyright (c) 2002-2003 Gustavo Niemeyer +* +* XChat Python Plugin Interface +* +* Xchat Python Plugin Interface is free software; you can redistribute +* it and/or modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 of the +* License, or (at your option) any later version. +* +* pybot is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this file; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Thread support + * ============== + * + * The python interpreter has a global interpreter lock. Any thread + * executing must acquire it before working with data accessible from + * python code. Here we must also care about xchat not being + * thread-safe. We do this by using an xchat lock, which protects + * xchat instructions from being executed out of time (when this + * plugin is not "active"). + * + * When xchat calls python code: + * - Change the current_plugin for the executing plugin; + * - Release xchat lock + * - Acquire the global interpreter lock + * - Make the python call + * - Release the global interpreter lock + * - Acquire xchat lock + * + * When python code calls xchat: + * - Release the global interpreter lock + * - Acquire xchat lock + * - Restore context, if necessary + * - Make the xchat call + * - Release xchat lock + * - Acquire the global interpreter lock + * + * Inside a timer, so that individual threads have a chance to run: + * - Release xchat lock + * - Go ahead threads. Have a nice time! + * - Acquire xchat lock + * + */ + +#include +#include +#include +#include +#include +#include + +#include "xchat-plugin.h" +#include "Python.h" +#include "structmember.h" +#include "pythread.h" + +#define VERSION_MAJOR 0 +#define VERSION_MINOR 1 + +#ifdef WIN32 +#undef WITH_THREAD /* Thread support locks up xchat on Win32. */ +#define VERSION "0.8/2.4" /* Linked to python24.dll */ +#else +#define VERSION "0.8" +#endif + +#define NONE 0 +#define ALLOW_THREADS 1 +#define RESTORE_CONTEXT 2 + +#ifdef WITH_THREAD +#define ACQUIRE_XCHAT_LOCK() PyThread_acquire_lock(xchat_lock, 1) +#define RELEASE_XCHAT_LOCK() PyThread_release_lock(xchat_lock) +#define BEGIN_XCHAT_CALLS(x) \ + do { \ + PyObject *calls_plugin = NULL; \ + PyThreadState *calls_thread; \ + if ((x) & RESTORE_CONTEXT) \ + calls_plugin = Plugin_GetCurrent(); \ + calls_thread = PyEval_SaveThread(); \ + ACQUIRE_XCHAT_LOCK(); \ + if (!((x) & ALLOW_THREADS)) { \ + PyEval_RestoreThread(calls_thread); \ + calls_thread = NULL; \ + } \ + if (calls_plugin) \ + xchat_set_context(ph, \ + Plugin_GetContext(calls_plugin)); \ + while (0) +#define END_XCHAT_CALLS() \ + RELEASE_XCHAT_LOCK(); \ + if (calls_thread) \ + PyEval_RestoreThread(calls_thread); \ + } while(0) +#else +#define ACQUIRE_XCHAT_LOCK() +#define RELEASE_XCHAT_LOCK() +#define BEGIN_XCHAT_CALLS(x) +#define END_XCHAT_CALLS() +#endif + +#ifdef WITH_THREAD + +#define BEGIN_PLUGIN(plg) \ + do { \ + xchat_context *begin_plugin_ctx = xchat_get_context(ph); \ + RELEASE_XCHAT_LOCK(); \ + Plugin_AcquireThread(plg); \ + Plugin_SetContext(plg, begin_plugin_ctx); \ + } while (0) +#define END_PLUGIN(plg) \ + do { \ + Plugin_ReleaseThread(plg); \ + ACQUIRE_XCHAT_LOCK(); \ + } while (0) + +#else /* !WITH_THREAD (win32) */ + +static PyThreadState *pTempThread; + +#define BEGIN_PLUGIN(plg) \ + do { \ + xchat_context *begin_plugin_ctx = xchat_get_context(ph); \ + RELEASE_XCHAT_LOCK(); \ + PyEval_AcquireLock(); \ + pTempThread = PyThreadState_Swap(((PluginObject *)(plg))->tstate); \ + Plugin_SetContext(plg, begin_plugin_ctx); \ + } while (0) +#define END_PLUGIN(plg) \ + do { \ + ((PluginObject *)(plg))->tstate = PyThreadState_Swap(pTempThread); \ + PyEval_ReleaseLock(); \ + ACQUIRE_XCHAT_LOCK(); \ + } while (0) + +#endif /* !WITH_THREAD */ + +#define Plugin_Swap(x) \ + PyThreadState_Swap(((PluginObject *)(x))->tstate) +#define Plugin_AcquireThread(x) \ + PyEval_AcquireThread(((PluginObject *)(x))->tstate) +#define Plugin_ReleaseThread(x) \ + Util_ReleaseThread(((PluginObject *)(x))->tstate) +#define Plugin_GetFilename(x) \ + (((PluginObject *)(x))->filename) +#define Plugin_GetName(x) \ + (((PluginObject *)(x))->name) +#define Plugin_GetVersion(x) \ + (((PluginObject *)(x))->version) +#define Plugin_GetDesc(x) \ + (((PluginObject *)(x))->description) +#define Plugin_GetHooks(x) \ + (((PluginObject *)(x))->hooks) +#define Plugin_GetContext(x) \ + (((PluginObject *)(x))->context) +#define Plugin_SetFilename(x, y) \ + ((PluginObject *)(x))->filename = (y); +#define Plugin_SetName(x, y) \ + ((PluginObject *)(x))->name = (y); +#define Plugin_SetVersion(x, y) \ + ((PluginObject *)(x))->version = (y); +#define Plugin_SetDescription(x, y) \ + ((PluginObject *)(x))->description = (y); +#define Plugin_SetHooks(x, y) \ + ((PluginObject *)(x))->hooks = (y); +#define Plugin_SetContext(x, y) \ + ((PluginObject *)(x))->context = (y); + +#define HOOK_XCHAT 1 +#define HOOK_UNLOAD 2 + +/* ===================================================================== */ +/* Object definitions */ + +typedef struct { + PyObject_HEAD + int softspace; /* We need it for print support. */ +} XChatOutObject; + +typedef struct { + PyObject_HEAD + xchat_context *context; +} ContextObject; + +typedef struct { + PyObject_HEAD + const char *listname; + PyObject *dict; +} ListItemObject; + +typedef struct { + PyObject_HEAD + char *name; + char *version; + char *filename; + char *description; + GSList *hooks; + PyThreadState *tstate; + xchat_context *context; + void *gui; +} PluginObject; + +typedef struct { + int type; + PyObject *plugin; + PyObject *callback; + PyObject *userdata; + void *data; /* A handle, when type == HOOK_XCHAT */ +} Hook; + + +/* ===================================================================== */ +/* Function declarations */ + +static PyObject *Util_BuildList(char *word[]); +static void Util_Autoload(); +static char *Util_Expand(char *filename); + +static int Callback_Command(char *word[], char *word_eol[], void *userdata); +static int Callback_Print(char *word[], void *userdata); +static int Callback_Timer(void *userdata); +static int Callback_ThreadTimer(void *userdata); + +static PyObject *XChatOut_New(); +static PyObject *XChatOut_write(PyObject *self, PyObject *args); +static void XChatOut_dealloc(PyObject *self); + +static void Context_dealloc(PyObject *self); +static PyObject *Context_set(ContextObject *self, PyObject *args); +static PyObject *Context_command(ContextObject *self, PyObject *args); +static PyObject *Context_prnt(ContextObject *self, PyObject *args); +static PyObject *Context_get_info(ContextObject *self, PyObject *args); +static PyObject *Context_get_list(ContextObject *self, PyObject *args); +static PyObject *Context_compare(ContextObject *a, ContextObject *b, int op); +static PyObject *Context_FromContext(xchat_context *context); +static PyObject *Context_FromServerAndChannel(char *server, char *channel); + +static PyObject *Plugin_New(char *filename, PyMethodDef *xchat_methods, + PyObject *xcoobj); +static PyObject *Plugin_GetCurrent(); +static PluginObject *Plugin_ByString(char *str); +static Hook *Plugin_AddHook(int type, PyObject *plugin, PyObject *callback, + PyObject *userdata, void *data); +static void Plugin_RemoveHook(PyObject *plugin, Hook *hook); +static void Plugin_RemoveAllHooks(PyObject *plugin); + +static PyObject *Module_xchat_command(PyObject *self, PyObject *args); +static PyObject *Module_xchat_prnt(PyObject *self, PyObject *args); +static PyObject *Module_xchat_get_context(PyObject *self, PyObject *args); +static PyObject *Module_xchat_find_context(PyObject *self, PyObject *args, + PyObject *kwargs); +static PyObject *Module_xchat_get_info(PyObject *self, PyObject *args); +static PyObject *Module_xchat_hook_command(PyObject *self, PyObject *args, + PyObject *kwargs); +static PyObject *Module_xchat_hook_server(PyObject *self, PyObject *args, + PyObject *kwargs); +static PyObject *Module_xchat_hook_print(PyObject *self, PyObject *args, + PyObject *kwargs); +static PyObject *Module_xchat_hook_timer(PyObject *self, PyObject *args, + PyObject *kwargs); +static PyObject *Module_xchat_unhook(PyObject *self, PyObject *args); +static PyObject *Module_xchat_get_info(PyObject *self, PyObject *args); +static PyObject *Module_xchat_get_list(PyObject *self, PyObject *args); +static PyObject *Module_xchat_get_lists(PyObject *self, PyObject *args); +static PyObject *Module_xchat_nickcmp(PyObject *self, PyObject *args); +static PyObject *Module_xchat_strip(PyObject *self, PyObject *args); + +static void IInterp_Exec(char *command); +static int IInterp_Cmd(char *word[], char *word_eol[], void *userdata); + +static void Command_PyList(); +static void Command_PyLoad(char *filename); +static void Command_PyUnload(char *name); +static void Command_PyReload(char *name); +static void Command_PyAbout(); +static int Command_Py(char *word[], char *word_eol[], void *userdata); + +/* ===================================================================== */ +/* Static declarations and definitions */ + +staticforward PyTypeObject Plugin_Type; +staticforward PyTypeObject XChatOut_Type; +staticforward PyTypeObject Context_Type; +staticforward PyTypeObject ListItem_Type; + +static PyThreadState *main_tstate = NULL; +static void *thread_timer = NULL; + +static xchat_plugin *ph; +static GSList *plugin_list = NULL; + +static PyObject *interp_plugin = NULL; +static PyObject *xchatout = NULL; + +#ifdef WITH_THREAD +static PyThread_type_lock xchat_lock = NULL; +#endif + +static const char usage[] = "\ +Usage: /PY LOAD \n\ + UNLOAD \n\ + RELOAD \n\ + LIST\n\ + EXEC \n\ + CONSOLE\n\ + ABOUT\n\ +\n"; + +static const char about[] = "\ +\n\ +X-Chat Python Interface " VERSION "\n\ +\n\ +Copyright (c) 2002-2003 Gustavo Niemeyer \n\ +\n"; + + +/* ===================================================================== */ +/* Utility functions */ + +static PyObject * +Util_BuildList(char *word[]) +{ + PyObject *list; + int listsize = 0; + int i; + while (word[listsize] && word[listsize][0]) + listsize++; + list = PyList_New(listsize); + if (list == NULL) { + PyErr_Print(); + return NULL; + } + for (i = 0; i != listsize; i++) { + PyObject *o = PyString_FromString(word[i]); + if (o == NULL) { + Py_DECREF(list); + PyErr_Print(); + return NULL; + } + PyList_SetItem(list, i, o); + } + return list; +} + +static void +Util_Autoload_from (const char *dir_name) +{ +#ifndef PATH_MAX +#define PATH_MAX 1024 /* Hurd doesn't define it */ +#endif + char oldcwd[PATH_MAX]; + struct dirent *ent; + DIR *dir; + if (getcwd(oldcwd, PATH_MAX) == NULL) + return; + if (chdir(dir_name) != 0) + return; + dir = opendir("."); + if (dir == NULL) + return; + while ((ent = readdir(dir))) { + int len = strlen(ent->d_name); + if (len > 3 && strcmp(".py", ent->d_name+len-3) == 0) + Command_PyLoad(ent->d_name); + } + closedir(dir); + chdir(oldcwd); +} + +static void +Util_Autoload() +{ + /* we need local filesystem encoding for chdir, opendir etc */ + + /* auto-load from ~/.xchat2/ or %APPDATA%\X-Chat 2\ */ + Util_Autoload_from(xchat_get_info(ph, "xchatdirfs")); + +#ifdef WIN32 /* also auto-load C:\Program Files\XChat\Plugins\*.py */ + Util_Autoload_from(XCHATLIBDIR"/plugins"); +#endif +} + +static char * +Util_Expand(char *filename) +{ + char *expanded; + + /* Check if this is an absolute path. */ + if (g_path_is_absolute(filename)) { + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + return g_strdup(filename); + else + return NULL; + } + + /* Check if it starts with ~/ and expand the home if positive. */ + if (*filename == '~' && *(filename+1) == '/') { + expanded = g_build_filename(g_get_home_dir(), + filename+2, NULL); + if (g_file_test(expanded, G_FILE_TEST_EXISTS)) + return expanded; + else { + g_free(expanded); + return NULL; + } + } + + /* Check if it's in the current directory. */ + expanded = g_build_filename(g_get_current_dir(), + filename, NULL); + if (g_file_test(expanded, G_FILE_TEST_EXISTS)) + return expanded; + g_free(expanded); + + /* Check if ~/.xchat2/ exists. */ + expanded = g_build_filename(xchat_get_info(ph, "xchatdir"), + filename, NULL); + if (g_file_test(expanded, G_FILE_TEST_EXISTS)) + return expanded; + g_free(expanded); + + return NULL; +} + +/* Similar to PyEval_ReleaseThread, but accepts NULL thread states. */ +static void +Util_ReleaseThread(PyThreadState *tstate) +{ + PyThreadState *old_tstate; + if (tstate == NULL) + Py_FatalError("PyEval_ReleaseThread: NULL thread state"); + old_tstate = PyThreadState_Swap(NULL); + if (old_tstate != tstate && old_tstate != NULL) + Py_FatalError("PyEval_ReleaseThread: wrong thread state"); + PyEval_ReleaseLock(); +} + +/* ===================================================================== */ +/* Hookable functions. These are the entry points to python code, besides + * the load function, and the hooks for interactive interpreter. */ + +static int +Callback_Command(char *word[], char *word_eol[], void *userdata) +{ + Hook *hook = (Hook *) userdata; + PyObject *retobj; + PyObject *word_list, *word_eol_list; + int ret = 0; + + BEGIN_PLUGIN(hook->plugin); + + word_list = Util_BuildList(word+1); + if (word_list == NULL) { + END_PLUGIN(hook->plugin); + return 0; + } + word_eol_list = Util_BuildList(word_eol+1); + if (word_eol_list == NULL) { + Py_DECREF(word_list); + END_PLUGIN(hook->plugin); + return 0; + } + + retobj = PyObject_CallFunction(hook->callback, "(OOO)", word_list, + word_eol_list, hook->userdata); + Py_DECREF(word_list); + Py_DECREF(word_eol_list); + + if (retobj == Py_None) { + ret = XCHAT_EAT_NONE; + Py_DECREF(retobj); + } else if (retobj) { + ret = PyInt_AsLong(retobj); + Py_DECREF(retobj); + } else { + PyErr_Print(); + } + + END_PLUGIN(hook->plugin); + + return ret; +} + +/* No Callback_Server() here. We use Callback_Command() as well. */ + +static int +Callback_Print(char *word[], void *userdata) +{ + Hook *hook = (Hook *) userdata; + PyObject *retobj; + PyObject *word_list; + PyObject *word_eol_list; + char **word_eol; + char *word_eol_raw; + int listsize = 0; + int next = 0; + int i; + int ret = 0; + + /* Cut off the message identifier. */ + word += 1; + + /* XChat doesn't provide a word_eol for print events, so we + * build our own here. */ + while (word[listsize] && word[listsize][0]) + listsize++; + word_eol = (char **) g_malloc(sizeof(char*)*(listsize+1)); + if (word_eol == NULL) { + xchat_print(ph, "Not enough memory to alloc word_eol " + "for python plugin callback."); + return 0; + } + /* First build a word clone, but NULL terminated. */ + memcpy(word_eol, word, listsize*sizeof(char*)); + word_eol[listsize] = NULL; + /* Then join it. */ + word_eol_raw = g_strjoinv(" ", word_eol); + if (word_eol_raw == NULL) { + xchat_print(ph, "Not enough memory to alloc word_eol_raw " + "for python plugin callback."); + return 0; + } + /* And rebuild the real word_eol. */ + for (i = 0; i != listsize; i++) { + word_eol[i] = word_eol_raw+next; + next += strlen(word[i])+1; + } + word_eol[i] = ""; + + BEGIN_PLUGIN(hook->plugin); + + word_list = Util_BuildList(word); + if (word_list == NULL) { + g_free(word_eol_raw); + g_free(word_eol); + END_PLUGIN(hook->plugin); + return 0; + } + word_eol_list = Util_BuildList(word_eol); + if (word_eol_list == NULL) { + g_free(word_eol_raw); + g_free(word_eol); + Py_DECREF(word_list); + END_PLUGIN(hook->plugin); + return 0; + } + + retobj = PyObject_CallFunction(hook->callback, "(OOO)", word_list, + word_eol_list, hook->userdata); + Py_DECREF(word_list); + Py_DECREF(word_eol_list); + + g_free(word_eol_raw); + g_free(word_eol); + if (retobj == Py_None) { + ret = XCHAT_EAT_NONE; + Py_DECREF(retobj); + } else if (retobj) { + ret = PyInt_AsLong(retobj); + Py_DECREF(retobj); + } else { + PyErr_Print(); + } + + END_PLUGIN(hook->plugin); + + return ret; +} + +static int +Callback_Timer(void *userdata) +{ + Hook *hook = (Hook *) userdata; + PyObject *retobj; + int ret = 0; + PyObject *plugin; + + plugin = hook->plugin; + + BEGIN_PLUGIN(hook->plugin); + + retobj = PyObject_CallFunction(hook->callback, "(O)", hook->userdata); + + if (retobj) { + ret = PyObject_IsTrue(retobj); + Py_DECREF(retobj); + } else { + PyErr_Print(); + } + + /* Returning 0 for this callback unhooks itself. */ + if (ret == 0) + Plugin_RemoveHook(plugin, hook); + + END_PLUGIN(plugin); + + return ret; +} + +#ifdef WITH_THREAD +static int +Callback_ThreadTimer(void *userdata) +{ + RELEASE_XCHAT_LOCK(); + usleep(1); + ACQUIRE_XCHAT_LOCK(); + return 1; +} +#endif + +/* ===================================================================== */ +/* XChatOut object */ + +/* We keep this information global, so we can reset it when the + * deinit function is called. */ +/* XXX This should be somehow bound to the printing context. */ +static char *xchatout_buffer = NULL; +static int xchatout_buffer_size = 0; +static int xchatout_buffer_pos = 0; + +static PyObject * +XChatOut_New() +{ + XChatOutObject *xcoobj; + xcoobj = PyObject_New(XChatOutObject, &XChatOut_Type); + if (xcoobj != NULL) + xcoobj->softspace = 0; + return (PyObject *) xcoobj; +} + +static void +XChatOut_dealloc(PyObject *self) +{ + self->ob_type->tp_free((PyObject *)self); +} + +/* This is a little bit complex because we have to buffer data + * until a \n is received, since xchat breaks the line automatically. + * We also crop the last \n for this reason. */ +static PyObject * +XChatOut_write(PyObject *self, PyObject *args) +{ + int new_buffer_pos, data_size, print_limit, add_space; + char *data, *pos; + if (!PyArg_ParseTuple(args, "s#:write", &data, &data_size)) + return NULL; + if (!data_size) { + Py_INCREF(Py_None); + return Py_None; + } + BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS); + if (((XChatOutObject *)self)->softspace) { + add_space = 1; + ((XChatOutObject *)self)->softspace = 0; + } else { + add_space = 0; + } + if (xchatout_buffer_size-xchatout_buffer_pos < data_size+add_space) { + char *new_buffer; + /* This buffer grows whenever needed, and does not + * shrink. If we ever implement unloading of the + * python interface, we must find some way to free + * this buffer as well. */ + xchatout_buffer_size += data_size*2+16; + new_buffer = g_realloc(xchatout_buffer, xchatout_buffer_size); + if (new_buffer == NULL) { + xchat_print(ph, "Not enough memory to print"); + /* The system is out of resources. Let's help. */ + g_free(xchatout_buffer); + xchatout_buffer = NULL; + xchatout_buffer_size = 0; + xchatout_buffer_pos = 0; + /* Return something valid, since we have + * already warned the user, and he probably + * won't be able to notice this exception. */ + goto exit; + } + xchatout_buffer = new_buffer; + } + memcpy(xchatout_buffer+xchatout_buffer_pos, data, data_size); + print_limit = new_buffer_pos = xchatout_buffer_pos+data_size; + pos = xchatout_buffer+print_limit; + if (add_space && *(pos-1) != '\n') { + *pos = ' '; + *(pos+1) = 0; + new_buffer_pos++; + } + while (*pos != '\n' && print_limit > xchatout_buffer_pos) { + pos--; + print_limit--; + } + if (*pos == '\n') { + /* Crop it, inserting the string limiter there. */ + *pos = 0; + xchat_print(ph, xchatout_buffer); + if (print_limit < new_buffer_pos) { + /* There's still data to be printed. */ + print_limit += 1; /* Include the limiter. */ + xchatout_buffer_pos = new_buffer_pos-print_limit; + memmove(xchatout_buffer, xchatout_buffer+print_limit, + xchatout_buffer_pos); + } else { + xchatout_buffer_pos = 0; + } + } else { + xchatout_buffer_pos = new_buffer_pos; + } + +exit: + END_XCHAT_CALLS(); + Py_INCREF(Py_None); + return Py_None; +} + +#define OFF(x) offsetof(XChatOutObject, x) + +static PyMemberDef XChatOut_members[] = { + {"softspace", T_INT, OFF(softspace), 0}, + {0} +}; + +static PyMethodDef XChatOut_methods[] = { + {"write", XChatOut_write, METH_VARARGS}, + {NULL, NULL} +}; + +statichere PyTypeObject XChatOut_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "xchat.XChatOut", /*tp_name*/ + sizeof(XChatOutObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + XChatOut_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + PyObject_GenericGetAttr,/*tp_getattro*/ + PyObject_GenericSetAttr,/*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + XChatOut_methods, /*tp_methods*/ + XChatOut_members, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + PyType_GenericNew, /*tp_new*/ + _PyObject_Del, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + + +/* ===================================================================== */ +/* Context object */ + +static void +Context_dealloc(PyObject *self) +{ + self->ob_type->tp_free((PyObject *)self); +} + +static PyObject * +Context_set(ContextObject *self, PyObject *args) +{ + PyObject *plugin = Plugin_GetCurrent(); + Plugin_SetContext(plugin, self->context); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Context_command(ContextObject *self, PyObject *args) +{ + char *text; + if (!PyArg_ParseTuple(args, "s:command", &text)) + return NULL; + BEGIN_XCHAT_CALLS(ALLOW_THREADS); + xchat_set_context(ph, self->context); + xchat_command(ph, text); + END_XCHAT_CALLS(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Context_prnt(ContextObject *self, PyObject *args) +{ + char *text; + if (!PyArg_ParseTuple(args, "s:prnt", &text)) + return NULL; + BEGIN_XCHAT_CALLS(ALLOW_THREADS); + xchat_set_context(ph, self->context); + xchat_print(ph, text); + END_XCHAT_CALLS(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Context_emit_print(ContextObject *self, PyObject *args) +{ + char *argv[10]; + char *name; + int res; + memset(&argv, 0, sizeof(char*)*10); + if (!PyArg_ParseTuple(args, "s|ssssss:print_event", &name, + &argv[0], &argv[1], &argv[2], + &argv[3], &argv[4], &argv[5], + &argv[6], &argv[7], &argv[8])) + return NULL; + BEGIN_XCHAT_CALLS(ALLOW_THREADS); + xchat_set_context(ph, self->context); + res = xchat_emit_print(ph, name, argv[0], argv[1], argv[2], + argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8]); + END_XCHAT_CALLS(); + return PyInt_FromLong(res); +} + +static PyObject * +Context_get_info(ContextObject *self, PyObject *args) +{ + const char *info; + char *name; + if (!PyArg_ParseTuple(args, "s:get_info", &name)) + return NULL; + BEGIN_XCHAT_CALLS(NONE); + xchat_set_context(ph, self->context); + info = xchat_get_info(ph, name); + END_XCHAT_CALLS(); + if (info == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(info); +} + +static PyObject * +Context_get_list(ContextObject *self, PyObject *args) +{ + PyObject *plugin = Plugin_GetCurrent(); + xchat_context *saved_context = Plugin_GetContext(plugin); + PyObject *ret; + Plugin_SetContext(plugin, self->context); + ret = Module_xchat_get_list((PyObject*)self, args); + Plugin_SetContext(plugin, saved_context); + return ret; +} + +/* needed to make context1 == context2 work */ +static PyObject * +Context_compare(ContextObject *a, ContextObject *b, int op) +{ + PyObject *ret; + /* check for == */ + if (op == Py_EQ) + ret = (a->context == b->context ? Py_True : Py_False); + /* check for != */ + else if (op == Py_NE) + ret = (a->context != b->context ? Py_True : Py_False); + /* only makes sense as == and != */ + else + { + PyErr_SetString(PyExc_TypeError, "contexts are either equal or not equal"); + ret = NULL; + } + + return ret; +} + +static PyMethodDef Context_methods[] = { + {"set", (PyCFunction) Context_set, METH_NOARGS}, + {"command", (PyCFunction) Context_command, METH_VARARGS}, + {"prnt", (PyCFunction) Context_prnt, METH_VARARGS}, + {"emit_print", (PyCFunction) Context_emit_print, METH_VARARGS}, + {"get_info", (PyCFunction) Context_get_info, METH_VARARGS}, + {"get_list", (PyCFunction) Context_get_list, METH_VARARGS}, + {NULL, NULL} +}; + +statichere PyTypeObject Context_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "xchat.Context", /*tp_name*/ + sizeof(ContextObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + Context_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + PyObject_GenericGetAttr,/*tp_getattro*/ + PyObject_GenericSetAttr,/*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + (richcmpfunc)Context_compare, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + Context_methods, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + PyType_GenericNew, /*tp_new*/ + _PyObject_Del, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +static PyObject * +Context_FromContext(xchat_context *context) +{ + ContextObject *ctxobj = PyObject_New(ContextObject, &Context_Type); + if (ctxobj != NULL) + ctxobj->context = context; + return (PyObject *) ctxobj; +} + +static PyObject * +Context_FromServerAndChannel(char *server, char *channel) +{ + ContextObject *ctxobj; + xchat_context *context; + BEGIN_XCHAT_CALLS(NONE); + context = xchat_find_context(ph, server, channel); + END_XCHAT_CALLS(); + if (context == NULL) + return NULL; + ctxobj = PyObject_New(ContextObject, &Context_Type); + if (ctxobj == NULL) + return NULL; + ctxobj->context = context; + return (PyObject *) ctxobj; +} + + +/* ===================================================================== */ +/* ListItem object */ + +#undef OFF +#define OFF(x) offsetof(ListItemObject, x) + +static PyMemberDef ListItem_members[] = { + {"__dict__", T_OBJECT, OFF(dict), 0}, + {0} +}; + +static void +ListItem_dealloc(PyObject *self) +{ + Py_DECREF(((ListItemObject*)self)->dict); + self->ob_type->tp_free((PyObject *)self); +} + +static PyObject * +ListItem_repr(PyObject *self) +{ + return PyString_FromFormat("<%s list item at %p>", + ((ListItemObject*)self)->listname, self); +} + +statichere PyTypeObject ListItem_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "xchat.ListItem", /*tp_name*/ + sizeof(ListItemObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + ListItem_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + ListItem_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + PyObject_GenericGetAttr,/*tp_getattro*/ + PyObject_GenericSetAttr,/*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + ListItem_members, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + OFF(dict), /*tp_dictoffset*/ + 0, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + PyType_GenericNew, /*tp_new*/ + _PyObject_Del, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +static PyObject * +ListItem_New(const char *listname) +{ + ListItemObject *item; + item = PyObject_New(ListItemObject, &ListItem_Type); + if (item != NULL) { + /* listname parameter must be statically allocated. */ + item->listname = listname; + item->dict = PyDict_New(); + if (item->dict == NULL) { + Py_DECREF(item); + item = NULL; + } + } + return (PyObject *) item; +} + + +/* ===================================================================== */ +/* Plugin object */ + +#define GET_MODULE_DATA(x, force) \ + o = PyObject_GetAttrString(m, "__module_" #x "__"); \ + if (o == NULL) { \ + if (force) { \ + xchat_print(ph, "Module has no __module_" #x "__ " \ + "defined"); \ + goto error; \ + } \ + plugin->x = g_strdup(""); \ + } else {\ + if (!PyString_Check(o)) { \ + xchat_print(ph, "Variable __module_" #x "__ " \ + "must be a string"); \ + goto error; \ + } \ + plugin->x = g_strdup(PyString_AsString(o)); \ + if (plugin->x == NULL) { \ + xchat_print(ph, "Not enough memory to allocate " #x); \ + goto error; \ + } \ + } + +static PyObject * +Plugin_New(char *filename, PyMethodDef *xchat_methods, PyObject *xcoobj) +{ + PluginObject *plugin = NULL; + PyObject *m, *o; + char *argv[] = {"", 0}; + + if (filename) { + char *old_filename = filename; + filename = Util_Expand(filename); + if (filename == NULL) { + xchat_printf(ph, "File not found: %s", old_filename); + return NULL; + } + } + + /* Allocate plugin structure. */ + plugin = PyObject_New(PluginObject, &Plugin_Type); + if (plugin == NULL) { + xchat_print(ph, "Can't create plugin object"); + goto error; + } + + Plugin_SetName(plugin, NULL); + Plugin_SetVersion(plugin, NULL); + Plugin_SetFilename(plugin, NULL); + Plugin_SetDescription(plugin, NULL); + Plugin_SetHooks(plugin, NULL); + Plugin_SetContext(plugin, xchat_get_context(ph)); + + /* Start a new interpreter environment for this plugin. */ + PyEval_AcquireLock(); + plugin->tstate = Py_NewInterpreter(); + if (plugin->tstate == NULL) { + xchat_print(ph, "Can't create interpreter state"); + goto error; + } + + PySys_SetArgv(1, argv); + PySys_SetObject("__plugin__", (PyObject *) plugin); + + /* Set stdout and stderr to xchatout. */ + Py_INCREF(xcoobj); + PySys_SetObject("stdout", xcoobj); + Py_INCREF(xcoobj); + PySys_SetObject("stderr", xcoobj); + + /* Add xchat module to the environment. */ + m = Py_InitModule("xchat", xchat_methods); + if (m == NULL) { + xchat_print(ph, "Can't create xchat module"); + goto error; + } + + PyModule_AddIntConstant(m, "EAT_NONE", XCHAT_EAT_NONE); + PyModule_AddIntConstant(m, "EAT_XCHAT", XCHAT_EAT_XCHAT); + PyModule_AddIntConstant(m, "EAT_PLUGIN", XCHAT_EAT_PLUGIN); + PyModule_AddIntConstant(m, "EAT_ALL", XCHAT_EAT_ALL); + PyModule_AddIntConstant(m, "PRI_HIGHEST", XCHAT_PRI_HIGHEST); + PyModule_AddIntConstant(m, "PRI_HIGH", XCHAT_PRI_HIGH); + PyModule_AddIntConstant(m, "PRI_NORM", XCHAT_PRI_NORM); + PyModule_AddIntConstant(m, "PRI_LOW", XCHAT_PRI_LOW); + PyModule_AddIntConstant(m, "PRI_LOWEST", XCHAT_PRI_LOWEST); + + o = Py_BuildValue("(ii)", VERSION_MAJOR, VERSION_MINOR); + if (o == NULL) { + xchat_print(ph, "Can't create version tuple"); + goto error; + } + PyObject_SetAttrString(m, "__version__", o); + + if (filename) { +#ifdef WIN32 + PyObject* PyFileObject = PyFile_FromString(filename, "r"); + if (PyFileObject == NULL) { + xchat_printf(ph, "Can't open file %s: %s\n", + filename, strerror(errno)); + goto error; + } + + if (PyRun_SimpleFile(PyFile_AsFile(PyFileObject), filename) != 0) { + xchat_printf(ph, "Error loading module %s\n", + filename); + goto error; + } + + plugin->filename = filename; + filename = NULL; +#else + FILE *fp; + + plugin->filename = filename; + + /* It's now owned by the plugin. */ + filename = NULL; + + /* Open the plugin file. */ + fp = fopen(plugin->filename, "r"); + if (fp == NULL) { + xchat_printf(ph, "Can't open file %s: %s\n", + plugin->filename, strerror(errno)); + goto error; + } + + /* Run the plugin. */ + if (PyRun_SimpleFile(fp, plugin->filename) != 0) { + xchat_printf(ph, "Error loading module %s\n", + plugin->filename); + fclose(fp); + goto error; + } + fclose(fp); +#endif + m = PyDict_GetItemString(PyImport_GetModuleDict(), + "__main__"); + if (m == NULL) { + xchat_print(ph, "Can't get __main__ module"); + goto error; + } + GET_MODULE_DATA(name, 1); + GET_MODULE_DATA(version, 0); + GET_MODULE_DATA(description, 0); + plugin->gui = xchat_plugingui_add(ph, plugin->filename, + plugin->name, + plugin->description, + plugin->version, NULL); + } + + PyEval_ReleaseThread(plugin->tstate); + + return (PyObject *) plugin; + +error: + g_free(filename); + + if (plugin) { + if (plugin->tstate) + Py_EndInterpreter(plugin->tstate); + Py_DECREF(plugin); + } + PyEval_ReleaseLock(); + + return NULL; +} + +static PyObject * +Plugin_GetCurrent() +{ + PyObject *plugin; + plugin = PySys_GetObject("__plugin__"); + if (plugin == NULL) + PyErr_SetString(PyExc_RuntimeError, "lost sys.__plugin__"); + return plugin; +} + +static PluginObject * +Plugin_ByString(char *str) +{ + GSList *list; + PluginObject *plugin; + char *basename; + list = plugin_list; + while (list != NULL) { + plugin = (PluginObject *) list->data; + basename = g_path_get_basename(plugin->filename); + if (basename == NULL) + break; + if (strcasecmp(plugin->name, str) == 0 || + strcasecmp(plugin->filename, str) == 0 || + strcasecmp(basename, str) == 0) { + g_free(basename); + return plugin; + } + g_free(basename); + list = list->next; + } + return NULL; +} + +static Hook * +Plugin_AddHook(int type, PyObject *plugin, PyObject *callback, + PyObject *userdata, void *data) +{ + Hook *hook = (Hook *) g_malloc(sizeof(Hook)); + if (hook == NULL) { + PyErr_NoMemory(); + return NULL; + } + hook->type = type; + hook->plugin = plugin; + Py_INCREF(callback); + hook->callback = callback; + Py_INCREF(userdata); + hook->userdata = userdata; + hook->data = NULL; + Plugin_SetHooks(plugin, g_slist_append(Plugin_GetHooks(plugin), + hook)); + + return hook; +} + +static void +Plugin_RemoveHook(PyObject *plugin, Hook *hook) +{ + GSList *list; + /* Is this really a hook of the running plugin? */ + list = g_slist_find(Plugin_GetHooks(plugin), hook); + if (list) { + /* Ok, unhook it. */ + if (hook->type == HOOK_XCHAT) { + /* This is an xchat hook. Unregister it. */ + BEGIN_XCHAT_CALLS(NONE); + xchat_unhook(ph, (xchat_hook*)hook->data); + END_XCHAT_CALLS(); + } + Plugin_SetHooks(plugin, + g_slist_remove(Plugin_GetHooks(plugin), + hook)); + Py_DECREF(hook->callback); + Py_DECREF(hook->userdata); + g_free(hook); + } +} + +static void +Plugin_RemoveAllHooks(PyObject *plugin) +{ + GSList *list = Plugin_GetHooks(plugin); + while (list) { + Hook *hook = (Hook *) list->data; + if (hook->type == HOOK_XCHAT) { + /* This is an xchat hook. Unregister it. */ + BEGIN_XCHAT_CALLS(NONE); + xchat_unhook(ph, (xchat_hook*)hook->data); + END_XCHAT_CALLS(); + } + Py_DECREF(hook->callback); + Py_DECREF(hook->userdata); + g_free(hook); + list = list->next; + } + Plugin_SetHooks(plugin, NULL); +} + +static void +Plugin_Delete(PyObject *plugin) +{ + PyThreadState *tstate = ((PluginObject*)plugin)->tstate; + GSList *list = Plugin_GetHooks(plugin); + while (list) { + Hook *hook = (Hook *) list->data; + if (hook->type == HOOK_UNLOAD) { + PyObject *retobj; + retobj = PyObject_CallFunction(hook->callback, "(O)", + hook->userdata); + if (retobj) { + Py_DECREF(retobj); + } else { + PyErr_Print(); + PyErr_Clear(); + } + } + list = list->next; + } + Plugin_RemoveAllHooks(plugin); + xchat_plugingui_remove(ph, ((PluginObject *)plugin)->gui); + Py_DECREF(plugin); + /*PyThreadState_Swap(tstate); needed? */ + Py_EndInterpreter(tstate); +} + +static void +Plugin_dealloc(PluginObject *self) +{ + g_free(self->filename); + g_free(self->name); + g_free(self->version); + g_free(self->description); + self->ob_type->tp_free((PyObject *)self); +} + +statichere PyTypeObject Plugin_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "xchat.Plugin", /*tp_name*/ + sizeof(PluginObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Plugin_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + PyObject_GenericGetAttr,/*tp_getattro*/ + PyObject_GenericSetAttr,/*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + PyType_GenericNew, /*tp_new*/ + _PyObject_Del, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + + +/* ===================================================================== */ +/* XChat module */ + +static PyObject * +Module_xchat_command(PyObject *self, PyObject *args) +{ + char *text; + if (!PyArg_ParseTuple(args, "s:command", &text)) + return NULL; + BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS); + xchat_command(ph, text); + END_XCHAT_CALLS(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Module_xchat_prnt(PyObject *self, PyObject *args) +{ + char *text; + if (!PyArg_ParseTuple(args, "s:prnt", &text)) + return NULL; + BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS); + xchat_print(ph, text); + END_XCHAT_CALLS(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Module_xchat_emit_print(PyObject *self, PyObject *args) +{ + char *argv[10]; + char *name; + int res; + memset(&argv, 0, sizeof(char*)*10); + if (!PyArg_ParseTuple(args, "s|ssssss:print_event", &name, + &argv[0], &argv[1], &argv[2], + &argv[3], &argv[4], &argv[5], + &argv[6], &argv[7], &argv[8])) + return NULL; + BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS); + res = xchat_emit_print(ph, name, argv[0], argv[1], argv[2], + argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8]); + END_XCHAT_CALLS(); + return PyInt_FromLong(res); +} + +static PyObject * +Module_xchat_get_info(PyObject *self, PyObject *args) +{ + const char *info; + char *name; + if (!PyArg_ParseTuple(args, "s:get_info", &name)) + return NULL; + BEGIN_XCHAT_CALLS(RESTORE_CONTEXT); + info = xchat_get_info(ph, name); + END_XCHAT_CALLS(); + if (info == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(info); +} + +static PyObject * +Module_xchat_get_prefs(PyObject *self, PyObject *args) +{ + PyObject *res; + const char *info; + int integer; + char *name; + int type; + if (!PyArg_ParseTuple(args, "s:get_prefs", &name)) + return NULL; + BEGIN_XCHAT_CALLS(NONE); + type = xchat_get_prefs(ph, name, &info, &integer); + END_XCHAT_CALLS(); + switch (type) { + case 0: + Py_INCREF(Py_None); + res = Py_None; + break; + case 1: + res = PyString_FromString((char*)info); + break; + case 2: + case 3: + res = PyInt_FromLong(integer); + break; + default: + PyErr_Format(PyExc_RuntimeError, + "unknown get_prefs type (%d), " + "please report", type); + res = NULL; + break; + } + return res; +} + +static PyObject * +Module_xchat_get_context(PyObject *self, PyObject *args) +{ + PyObject *plugin; + PyObject *ctxobj; + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + ctxobj = Context_FromContext(Plugin_GetContext(plugin)); + if (ctxobj == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return ctxobj; +} + +static PyObject * +Module_xchat_find_context(PyObject *self, PyObject *args, PyObject *kwargs) +{ + char *server = NULL; + char *channel = NULL; + PyObject *ctxobj; + char *kwlist[] = {"server", "channel", 0}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zz:find_context", + kwlist, &server, &channel)) + return NULL; + ctxobj = Context_FromServerAndChannel(server, channel); + if (ctxobj == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return ctxobj; +} + +static PyObject * +Module_xchat_hook_command(PyObject *self, PyObject *args, PyObject *kwargs) +{ + char *name; + PyObject *callback; + PyObject *userdata = Py_None; + int priority = XCHAT_PRI_NORM; + char *help = NULL; + PyObject *plugin; + Hook *hook; + char *kwlist[] = {"name", "callback", "userdata", + "priority", "help", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|Oiz:hook_command", + kwlist, &name, &callback, &userdata, + &priority, &help)) + return NULL; + + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + + hook = Plugin_AddHook(HOOK_XCHAT, plugin, callback, userdata, NULL); + if (hook == NULL) + return NULL; + + BEGIN_XCHAT_CALLS(NONE); + hook->data = (void*)xchat_hook_command(ph, name, priority, + Callback_Command, help, hook); + END_XCHAT_CALLS(); + + return PyInt_FromLong((long)hook); +} + +static PyObject * +Module_xchat_hook_server(PyObject *self, PyObject *args, PyObject *kwargs) +{ + char *name; + PyObject *callback; + PyObject *userdata = Py_None; + int priority = XCHAT_PRI_NORM; + PyObject *plugin; + Hook *hook; + char *kwlist[] = {"name", "callback", "userdata", "priority", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|Oi:hook_server", + kwlist, &name, &callback, &userdata, + &priority)) + return NULL; + + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + + hook = Plugin_AddHook(HOOK_XCHAT, plugin, callback, userdata, NULL); + if (hook == NULL) + return NULL; + + BEGIN_XCHAT_CALLS(NONE); + hook->data = (void*)xchat_hook_server(ph, name, priority, + Callback_Command, hook); + END_XCHAT_CALLS(); + + return PyInt_FromLong((long)hook); +} + +static PyObject * +Module_xchat_hook_print(PyObject *self, PyObject *args, PyObject *kwargs) +{ + char *name; + PyObject *callback; + PyObject *userdata = Py_None; + int priority = XCHAT_PRI_NORM; + PyObject *plugin; + Hook *hook; + char *kwlist[] = {"name", "callback", "userdata", "priority", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|Oi:hook_print", + kwlist, &name, &callback, &userdata, + &priority)) + return NULL; + + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + + hook = Plugin_AddHook(HOOK_XCHAT, plugin, callback, userdata, NULL); + if (hook == NULL) + return NULL; + + BEGIN_XCHAT_CALLS(NONE); + hook->data = (void*)xchat_hook_print(ph, name, priority, + Callback_Print, hook); + END_XCHAT_CALLS(); + + return PyInt_FromLong((long)hook); +} + + +static PyObject * +Module_xchat_hook_timer(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int timeout; + PyObject *callback; + PyObject *userdata = Py_None; + PyObject *plugin; + Hook *hook; + char *kwlist[] = {"timeout", "callback", "userdata", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO|O:hook_timer", + kwlist, &timeout, &callback, + &userdata)) + return NULL; + + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + + hook = Plugin_AddHook(HOOK_XCHAT, plugin, callback, userdata, NULL); + if (hook == NULL) + return NULL; + + BEGIN_XCHAT_CALLS(NONE); + hook->data = (void*)xchat_hook_timer(ph, timeout, + Callback_Timer, hook); + END_XCHAT_CALLS(); + + return PyInt_FromLong((long)hook); +} + +static PyObject * +Module_xchat_hook_unload(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *callback; + PyObject *userdata = Py_None; + PyObject *plugin; + Hook *hook; + char *kwlist[] = {"callback", "userdata", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:hook_unload", + kwlist, &callback, &userdata)) + return NULL; + + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + + hook = Plugin_AddHook(HOOK_UNLOAD, plugin, callback, userdata, NULL); + if (hook == NULL) + return NULL; + + return PyInt_FromLong((long)hook); +} + +static PyObject * +Module_xchat_unhook(PyObject *self, PyObject *args) +{ + PyObject *plugin; + Hook *hook; + if (!PyArg_ParseTuple(args, "l:unhook", &hook)) + return NULL; + plugin = Plugin_GetCurrent(); + if (plugin == NULL) + return NULL; + Plugin_RemoveHook(plugin, hook); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Module_xchat_get_list(PyObject *self, PyObject *args) +{ + xchat_list *list; + PyObject *l; + const char *name; + const char *const *fields; + int i; + + if (!PyArg_ParseTuple(args, "s:get_list", &name)) + return NULL; + /* This function is thread safe, and returns statically + * allocated data. */ + fields = xchat_list_fields(ph, "lists"); + for (i = 0; fields[i]; i++) { + if (strcmp(fields[i], name) == 0) { + /* Use the static allocated one. */ + name = fields[i]; + break; + } + } + if (fields[i] == NULL) { + PyErr_SetString(PyExc_KeyError, "list not available"); + return NULL; + } + l = PyList_New(0); + if (l == NULL) + return NULL; + BEGIN_XCHAT_CALLS(RESTORE_CONTEXT); + list = xchat_list_get(ph, (char*)name); + if (list == NULL) + goto error; + fields = xchat_list_fields(ph, (char*)name); + while (xchat_list_next(ph, list)) { + PyObject *o = ListItem_New(name); + if (o == NULL || PyList_Append(l, o) == -1) { + Py_XDECREF(o); + goto error; + } + Py_DECREF(o); /* l is holding a reference */ + for (i = 0; fields[i]; i++) { + const char *fld = fields[i]+1; + PyObject *attr = NULL; + const char *sattr; + int iattr; + switch(fields[i][0]) { + case 's': + sattr = xchat_list_str(ph, list, (char*)fld); + attr = PyString_FromString(sattr?sattr:""); + break; + case 'i': + iattr = xchat_list_int(ph, list, (char*)fld); + attr = PyInt_FromLong((long)iattr); + break; + case 'p': + sattr = xchat_list_str(ph, list, (char*)fld); + if (strcmp(fld, "context") == 0) { + attr = Context_FromContext( + (xchat_context*)sattr); + break; + } + default: /* ignore unknown (newly added?) types */ + continue; + } + if (attr == NULL) + goto error; + PyObject_SetAttrString(o, (char*)fld, attr); /* add reference on attr in o */ + Py_DECREF(attr); /* make o own attr */ + } + } + xchat_list_free(ph, list); + goto exit; +error: + if (list) + xchat_list_free(ph, list); + Py_DECREF(l); + l = NULL; + +exit: + END_XCHAT_CALLS(); + return l; +} + +static PyObject * +Module_xchat_get_lists(PyObject *self, PyObject *args) +{ + PyObject *l, *o; + const char *const *fields; + int i; + /* This function is thread safe, and returns statically + * allocated data. */ + fields = xchat_list_fields(ph, "lists"); + l = PyList_New(0); + if (l == NULL) + return NULL; + for (i = 0; fields[i]; i++) { + o = PyString_FromString(fields[i]); + if (o == NULL || PyList_Append(l, o) == -1) { + Py_DECREF(l); + Py_XDECREF(o); + return NULL; + } + Py_DECREF(o); /* l is holding a reference */ + } + return l; +} + +static PyObject * +Module_xchat_nickcmp(PyObject *self, PyObject *args) +{ + char *s1, *s2; + if (!PyArg_ParseTuple(args, "ss:nickcmp", &s1, &s2)) + return NULL; + return PyInt_FromLong((long) xchat_nickcmp(ph, s1, s2)); +} + +static PyObject * +Module_xchat_strip(PyObject *self, PyObject *args) +{ + PyObject *result; + char *str, *str2; + int len = -1, flags = 1 | 2; + if (!PyArg_ParseTuple(args, "s|ii:strip", &str, &len, &flags)) + return NULL; + str2 = xchat_strip(ph, str, len, flags); + result = PyString_FromString(str2); + xchat_free(ph, str2); + return result; +} + +static PyMethodDef Module_xchat_methods[] = { + {"command", Module_xchat_command, + METH_VARARGS}, + {"prnt", Module_xchat_prnt, + METH_VARARGS}, + {"emit_print", Module_xchat_emit_print, + METH_VARARGS}, + {"get_info", Module_xchat_get_info, + METH_VARARGS}, + {"get_prefs", Module_xchat_get_prefs, + METH_VARARGS}, + {"get_context", Module_xchat_get_context, + METH_NOARGS}, + {"find_context", (PyCFunction)Module_xchat_find_context, + METH_VARARGS|METH_KEYWORDS}, + {"hook_command", (PyCFunction)Module_xchat_hook_command, + METH_VARARGS|METH_KEYWORDS}, + {"hook_server", (PyCFunction)Module_xchat_hook_server, + METH_VARARGS|METH_KEYWORDS}, + {"hook_print", (PyCFunction)Module_xchat_hook_print, + METH_VARARGS|METH_KEYWORDS}, + {"hook_timer", (PyCFunction)Module_xchat_hook_timer, + METH_VARARGS|METH_KEYWORDS}, + {"hook_unload", (PyCFunction)Module_xchat_hook_unload, + METH_VARARGS|METH_KEYWORDS}, + {"unhook", Module_xchat_unhook, + METH_VARARGS}, + {"get_list", Module_xchat_get_list, + METH_VARARGS}, + {"get_lists", Module_xchat_get_lists, + METH_NOARGS}, + {"nickcmp", Module_xchat_nickcmp, + METH_VARARGS}, + {"strip", Module_xchat_strip, + METH_VARARGS}, + {NULL, NULL} +}; + + +/* ===================================================================== */ +/* Python interactive interpreter functions */ + +static void +IInterp_Exec(char *command) +{ + PyObject *m, *d, *o; + char *buffer; + int len; + + BEGIN_PLUGIN(interp_plugin); + + m = PyImport_AddModule("__main__"); + if (m == NULL) { + xchat_print(ph, "Can't get __main__ module"); + goto fail; + } + d = PyModule_GetDict(m); + len = strlen(command); + buffer = (char *) g_malloc(len+2); + if (buffer == NULL) { + xchat_print(ph, "Not enough memory for command buffer"); + goto fail; + } + memcpy(buffer, command, len); + buffer[len] = '\n'; + buffer[len+1] = 0; + o = PyRun_StringFlags(buffer, Py_single_input, d, d, NULL); + g_free(buffer); + if (o == NULL) { + PyErr_Print(); + goto fail; + } + Py_DECREF(o); + if (Py_FlushLine()) + PyErr_Clear(); + +fail: + END_PLUGIN(interp_plugin); + + return; +} + +static int +IInterp_Cmd(char *word[], char *word_eol[], void *userdata) +{ + char *channel = (char *) xchat_get_info(ph, "channel"); + if (channel && channel[0] == '>' && strcmp(channel, ">>python<<") == 0) { + xchat_printf(ph, ">>> %s\n", word_eol[1]); + IInterp_Exec(word_eol[1]); + return 1; + } + return 0; +} + + +/* ===================================================================== */ +/* Python command handling */ + +static void +Command_PyList() +{ + GSList *list; + list = plugin_list; + if (list == NULL) { + xchat_print(ph, "No python modules loaded"); + } else { + xchat_print(ph, + "Name Version Filename Description\n" + "---- ------- -------- -----------\n"); + while (list != NULL) { + PluginObject *plg = (PluginObject *) list->data; + char *basename = g_path_get_basename(plg->filename); + xchat_printf(ph, "%-12s %-8s %-20s %-10s\n", + plg->name, + *plg->version ? plg->version + : "", + basename, + *plg->description ? plg->description + : ""); + g_free(basename); + list = list->next; + } + xchat_print(ph, "\n"); + } +} + +static void +Command_PyLoad(char *filename) +{ + PyObject *plugin; + RELEASE_XCHAT_LOCK(); + plugin = Plugin_New(filename, Module_xchat_methods, xchatout); + ACQUIRE_XCHAT_LOCK(); + if (plugin) + plugin_list = g_slist_append(plugin_list, plugin); +} + +static void +Command_PyUnload(char *name) +{ + PluginObject *plugin = Plugin_ByString(name); + if (!plugin) { + xchat_print(ph, "Can't find a python plugin with that name"); + } else { + BEGIN_PLUGIN(plugin); + Plugin_Delete((PyObject*)plugin); + END_PLUGIN(plugin); + plugin_list = g_slist_remove(plugin_list, plugin); + } +} + +static void +Command_PyReload(char *name) +{ + PluginObject *plugin = Plugin_ByString(name); + if (!plugin) { + xchat_print(ph, "Can't find a python plugin with that name"); + } else { + char *filename = strdup(plugin->filename); + Command_PyUnload(filename); + Command_PyLoad(filename); + g_free(filename); + } +} + +static void +Command_PyAbout() +{ + xchat_print(ph, about); +} + +static int +Command_Py(char *word[], char *word_eol[], void *userdata) +{ + char *cmd = word[2]; + int ok = 0; + if (strcasecmp(cmd, "LIST") == 0) { + ok = 1; + Command_PyList(); + } else if (strcasecmp(cmd, "EXEC") == 0) { + if (word[3][0]) { + ok = 1; + IInterp_Exec(word_eol[3]); + } + } else if (strcasecmp(cmd, "LOAD") == 0) { + if (word[3][0]) { + ok = 1; + Command_PyLoad(word[3]); + } + } else if (strcasecmp(cmd, "UNLOAD") == 0) { + if (word[3][0]) { + ok = 1; + Command_PyUnload(word[3]); + } + } else if (strcasecmp(cmd, "RELOAD") == 0) { + if (word[3][0]) { + ok = 1; + Command_PyReload(word[3]); + } + } else if (strcasecmp(cmd, "CONSOLE") == 0) { + ok = 1; + xchat_command(ph, "QUERY >>python<<"); + } else if (strcasecmp(cmd, "ABOUT") == 0) { + ok = 1; + Command_PyAbout(); + } + if (!ok) + xchat_print(ph, usage); + return XCHAT_EAT_ALL; +} + +static int +Command_Load(char *word[], char *word_eol[], void *userdata) +{ + int len = strlen(word[2]); + if (len > 3 && strcasecmp(".py", word[2]+len-3) == 0) { + Command_PyLoad(word[2]); + return XCHAT_EAT_XCHAT; + } + return XCHAT_EAT_NONE; +} + +static int +Command_Unload(char *word[], char *word_eol[], void *userdata) +{ + int len = strlen(word[2]); + if (len > 3 && strcasecmp(".py", word[2]+len-3) == 0) { + Command_PyUnload(word[2]); + return XCHAT_EAT_XCHAT; + } + return XCHAT_EAT_NONE; +} + +/* ===================================================================== */ +/* Autoload function */ + +/* ===================================================================== */ +/* (De)initialization functions */ + +static int initialized = 0; +static int reinit_tried = 0; + +void +xchat_plugin_get_info(char **name, char **desc, char **version, void **reserved) +{ + *name = "Python"; + *version = VERSION; + *desc = "Python scripting interface"; + if (reserved) + *reserved = NULL; +} + +int +xchat_plugin_init(xchat_plugin *plugin_handle, + char **plugin_name, + char **plugin_desc, + char **plugin_version, + char *arg) +{ + char *argv[] = {"", 0}; + + ph = plugin_handle; + + /* Block double initalization. */ + if (initialized != 0) { + xchat_print(ph, "Python interface already loaded"); + /* deinit is called even when init fails, so keep track + * of a reinit failure. */ + reinit_tried++; + return 0; + } + initialized = 1; + + *plugin_name = "Python"; + *plugin_version = VERSION; + *plugin_desc = "Python scripting interface"; + + /* Initialize python. */ + Py_SetProgramName("xchat"); + Py_Initialize(); + PySys_SetArgv(1, argv); + + Plugin_Type.ob_type = &PyType_Type; + Context_Type.ob_type = &PyType_Type; + XChatOut_Type.ob_type = &PyType_Type; + + xchatout = XChatOut_New(); + if (xchatout == NULL) { + xchat_print(ph, "Can't allocate xchatout object"); + return 0; + } + +#ifdef WITH_THREAD + PyEval_InitThreads(); + xchat_lock = PyThread_allocate_lock(); + if (xchat_lock == NULL) { + xchat_print(ph, "Can't allocate xchat lock"); + Py_DECREF(xchatout); + xchatout = NULL; + return 0; + } +#endif + + main_tstate = PyEval_SaveThread(); + + interp_plugin = Plugin_New(NULL, Module_xchat_methods, xchatout); + if (interp_plugin == NULL) { + xchat_print(ph, "Plugin_New() failed.\n"); +#ifdef WITH_THREAD + PyThread_free_lock(xchat_lock); +#endif + Py_DECREF(xchatout); + xchatout = NULL; + return 0; + } + + + xchat_hook_command(ph, "", XCHAT_PRI_NORM, IInterp_Cmd, 0, 0); + xchat_hook_command(ph, "PY", XCHAT_PRI_NORM, Command_Py, usage, 0); + xchat_hook_command(ph, "LOAD", XCHAT_PRI_NORM, Command_Load, 0, 0); + xchat_hook_command(ph, "UNLOAD", XCHAT_PRI_NORM, Command_Unload, 0, 0); +#ifdef WITH_THREAD + thread_timer = xchat_hook_timer(ph, 300, Callback_ThreadTimer, NULL); +#endif + + xchat_print(ph, "Python interface loaded\n"); + + Util_Autoload(); + return 1; +} + +int +xchat_plugin_deinit() +{ + GSList *list; + + /* A reinitialization was tried. Just give up and live the + * environment as is. We are still alive. */ + if (reinit_tried) { + reinit_tried--; + return 1; + } + + list = plugin_list; + while (list != NULL) { + PyObject *plugin = (PyObject *) list->data; + BEGIN_PLUGIN(plugin); + Plugin_Delete(plugin); + END_PLUGIN(plugin); + list = list->next; + } + g_slist_free(plugin_list); + plugin_list = NULL; + + /* Reset xchatout buffer. */ + g_free(xchatout_buffer); + xchatout_buffer = NULL; + xchatout_buffer_size = 0; + xchatout_buffer_pos = 0; + + if (interp_plugin) { + Py_DECREF(interp_plugin); + interp_plugin = NULL; + } + + /* Switch back to the main thread state. */ + if (main_tstate) { + PyThreadState_Swap(main_tstate); + main_tstate = NULL; + } + Py_Finalize(); + +#ifdef WITH_THREAD + if (thread_timer != NULL) { + xchat_unhook(ph, thread_timer); + thread_timer = NULL; + } + PyThread_free_lock(xchat_lock); +#endif + + xchat_print(ph, "Python interface unloaded\n"); + initialized = 0; + + return 1; +} + diff --git a/plugins/tcl/Makefile.am b/plugins/tcl/Makefile.am new file mode 100644 index 00000000..804fc83b --- /dev/null +++ b/plugins/tcl/Makefile.am @@ -0,0 +1,10 @@ + +EXTRA_DIST=printevents.h tclplugin.h README + +libdir = $(xchatlibdir)/plugins + +lib_LTLIBRARIES = tcl.la +tcl_la_SOURCES = tclplugin.c +tcl_la_LDFLAGS = -avoid-version -module +tcl_la_LIBADD = $(TCL_LIBS) +INCLUDES = $(TCL_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/.. diff --git a/plugins/tcl/README b/plugins/tcl/README new file mode 100644 index 00000000..e46635ef --- /dev/null +++ b/plugins/tcl/README @@ -0,0 +1,55 @@ +Please read this document before asking questions. + +(1) WHAT IS THE TCL PLUGIN? + + The XChat Tcl Plugin adds the complete Tcl scripting language to the + XChat 1.9.x and 2.x IRC client. The design philosophy behind the tcl + plugin was to give all the power of the C API. yet completely shield + the user from all the complexities of it. It is lightly modeled after + after Xircon; an old windows TCL enabled client with a little bit of + eggdrop functionality to it. + + Features: + * Uses the popular TCL scripting language. + * Familiar to eggdrop bot owners. + * Adds many new XChat specific commands to the Tcl language for + handling of events, user commands, timers, etc. + * It's actually documented! (Hey, what a concept!) + * Works with XChat 1.9.x and 2.x. + * Open source (GPL) + + The supplied documentation for Tcl Plugin commands can be + found in doc/tclplugin.html + + For a comprehensive list of IRC server tokens, see + doc/tokens.txt + + +(2) HOW TO GET TCL PLUGIN + + You can always find the latest version of the Tcl Plugin at: + + http://www.scriptkitties.com/tclplugin + + You must also have Tcl 8.3 or higher installed on your system. + + Tcl can be obtained from: + + http://sourceforge.net/projects/tcl + http://tcl.activestate.com (pre-compiled binaries) + + Tcl Man Pages + + http://tcl.activestate.com/man/ + + Tcl Tutorials: + + http://hegel.ittc.ukans.edu/topics/tcltk/tutorial-noplugin/ + http://jan.netcomp.monash.edu.au/ProgrammingUnix/tcl/tcl_tut.html + http://users.belgacom.net/bruno.champagne/tcl.html + + +(3) QUICK STARTUP + + SEE 'INSTALL' + diff --git a/plugins/tcl/printevents.h b/plugins/tcl/printevents.h new file mode 100644 index 00000000..dfea4aea --- /dev/null +++ b/plugins/tcl/printevents.h @@ -0,0 +1,319 @@ +/*************************************************************************** + printevents.h - TCL plugin header file + ------------------------------------------------- + begin : Sat Nov 9 17:31:20 MST 2002 + copyright : Copyright 2002-2007 Daniel P. Stasinski + email : mooooooo@avenues.org + generated : Mon May 21 06:03:00 PM MST 2007 + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +typedef struct { + char *event; + char *emit; + int argc; + xchat_hook *hook; +} print_event; + +enum +{ + CHAT, + XC_APPFOCUS, + XC_TABOPEN, + XC_TABCLOSE, + XC_TABFOCUS, + XC_KEYPRESS, + XC_ADDNOTIFY, + XC_BANLIST, + XC_BANNED, + XC_BEEP, + XC_CHANGENICK, + XC_CHANACTION, + XC_HCHANACTION, + XC_CHANBAN, + XC_CHANDATE, + XC_CHANDEHOP, + XC_CHANDEOP, + XC_CHANDEVOICE, + XC_CHANEXEMPT, + XC_CHANHOP, + XC_CHANINVITE, + XC_CHANLISTHEAD, + XC_CHANMSG, + XC_CHANMODEGEN, + XC_CHANMODES, + XC_HCHANMSG, + XC_CHANNOTICE, + XC_CHANOP, + XC_CHANRMEXEMPT, + XC_CHANRMINVITE, + XC_CHANRMKEY, + XC_CHANRMLIMIT, + XC_CHANSETKEY, + XC_CHANSETLIMIT, + XC_CHANUNBAN, + XC_CHANVOICE, + XC_CONNECTED, + XC_CONNECT, + XC_CONNFAIL, + XC_CTCPGEN, + XC_CTCPGENC, + XC_CTCPSEND, + XC_CTCPSND, + XC_CTCPSNDC, + XC_DCCCHATABORT, + XC_DCCCONCHAT, + XC_DCCCHATF, + XC_DCCCHATOFFER, + XC_DCCCHATOFFERING, + XC_DCCCHATREOFFER, + XC_DCCCONFAIL, + XC_DCCGENERICOFFER, + XC_DCCHEAD, + XC_MALFORMED, + XC_DCCOFFER, + XC_DCCIVAL, + XC_DCCRECVABORT, + XC_DCCRECVCOMP, + XC_DCCCONRECV, + XC_DCCRECVERR, + XC_DCCFILEERR, + XC_DCCRENAME, + XC_DCCRESUMEREQUEST, + XC_DCCSENDABORT, + XC_DCCSENDCOMP, + XC_DCCCONSEND, + XC_DCCSENDFAIL, + XC_DCCSENDOFFER, + XC_DCCSTALL, + XC_DCCTOUT, + XC_DELNOTIFY, + XC_DISCON, + XC_FOUNDIP, + XC_GENMSG, + XC_IGNOREADD, + XC_IGNORECHANGE, + XC_IGNOREFOOTER, + XC_IGNOREHEADER, + XC_IGNOREREMOVE, + XC_IGNOREEMPTY, + XC_INVITE, + XC_INVITED, + XC_JOIN, + XC_KEYWORD, + XC_KICK, + XC_KILL, + XC_MSGSEND, + XC_MOTD, + XC_MOTDSKIP, + XC_NICKCLASH, + XC_NICKFAIL, + XC_NODCC, + XC_NOCHILD, + XC_NOTICE, + XC_NOTICESEND, + XC_NOTIFYEMPTY, + XC_NOTIFYHEAD, + XC_NOTIFYNUMBER, + XC_NOTIFYOFFLINE, + XC_NOTIFYONLINE, + XC_OPENDIALOG, + XC_PART, + XC_PARTREASON, + XC_PINGREP, + XC_PINGTIMEOUT, + XC_PRIVMSG, + XC_DPRIVMSG, + XC_ALREADYPROCESS, + XC_QUIT, + XC_RAWMODES, + XC_WALLOPS, + XC_RESOLVINGUSER, + XC_SERVERCONNECTED, + XC_SERVERERROR, + XC_SERVERLOOKUP, + XC_SERVNOTICE, + XC_SERVTEXT, + XC_STOPCONNECT, + XC_TOPIC, + XC_NEWTOPIC, + XC_TOPICDATE, + XC_UKNHOST, + XC_USERLIMIT, + XC_USERSONCHAN, + XC_WHOIS_AUTH, + XC_WHOIS5, + XC_WHOIS2, + XC_WHOIS6, + XC_WHOIS_ID, + XC_WHOIS4, + XC_WHOIS4T, + XC_WHOIS1, + XC_WHOIS_REALHOST, + XC_WHOIS3, + XC_WHOIS_SPECIAL, + XC_UJOIN, + XC_UKICK, + XC_UPART, + XC_UPARTREASON, + XC_UACTION, + XC_UINVITE, + XC_UCHANMSG, + XC_UCHANGENICK, + XC_SIZE +}; + +static print_event xc[] = { + { "CHAT", "DCC Chat Text", -1, NULL }, + { "XC_APPFOCUS", "Focus Window", -3, NULL }, + { "XC_TABOPEN", "Open Context", -2, NULL }, + { "XC_TABCLOSE", "Close Context", -2, NULL }, + { "XC_TABFOCUS", "Focus Tab", -2, NULL }, + { "XC_KEYPRESS", "Key Press", 4, NULL }, + { "XC_ADDNOTIFY", "Add Notify", 1, NULL }, + { "XC_BANLIST", "Ban List", 4, NULL }, + { "XC_BANNED", "Banned", 1, NULL }, + { "XC_BEEP", "Beep", 0, NULL }, + { "XC_CHANGENICK", "Change Nick", 2, NULL }, + { "XC_CHANACTION", "Channel Action", 3, NULL }, + { "XC_HCHANACTION", "Channel Action Hilight", 3, NULL }, + { "XC_CHANBAN", "Channel Ban", 2, NULL }, + { "XC_CHANDATE", "Channel Creation", 2, NULL }, + { "XC_CHANDEHOP", "Channel DeHalfOp", 2, NULL }, + { "XC_CHANDEOP", "Channel DeOp", 2, NULL }, + { "XC_CHANDEVOICE", "Channel DeVoice", 2, NULL }, + { "XC_CHANEXEMPT", "Channel Exempt", 2, NULL }, + { "XC_CHANHOP", "Channel Half-Operator", 2, NULL }, + { "XC_CHANINVITE", "Channel INVITE", 2, NULL }, + { "XC_CHANLISTHEAD", "Channel List", 0, NULL }, + { "XC_CHANMSG", "Channel Message", 4, NULL }, + { "XC_CHANMODEGEN", "Channel Mode Generic", 4, NULL }, + { "XC_CHANMODES", "Channel Modes", 2, NULL }, + { "XC_HCHANMSG", "Channel Msg Hilight", 4, NULL }, + { "XC_CHANNOTICE", "Channel Notice", 3, NULL }, + { "XC_CHANOP", "Channel Operator", 2, NULL }, + { "XC_CHANRMEXEMPT", "Channel Remove Exempt", 2, NULL }, + { "XC_CHANRMINVITE", "Channel Remove Invite", 2, NULL }, + { "XC_CHANRMKEY", "Channel Remove Keyword", 1, NULL }, + { "XC_CHANRMLIMIT", "Channel Remove Limit", 1, NULL }, + { "XC_CHANSETKEY", "Channel Set Key", 2, NULL }, + { "XC_CHANSETLIMIT", "Channel Set Limit", 2, NULL }, + { "XC_CHANUNBAN", "Channel UnBan", 2, NULL }, + { "XC_CHANVOICE", "Channel Voice", 2, NULL }, + { "XC_CONNECTED", "Connected", 0, NULL }, + { "XC_CONNECT", "Connecting", 3, NULL }, + { "XC_CONNFAIL", "Connection Failed", 1, NULL }, + { "XC_CTCPGEN", "CTCP Generic", 2, NULL }, + { "XC_CTCPGENC", "CTCP Generic to Channel", 3, NULL }, + { "XC_CTCPSEND", "CTCP Send", 2, NULL }, + { "XC_CTCPSND", "CTCP Sound", 2, NULL }, + { "XC_CTCPSNDC", "CTCP Sound to Channel", 3, NULL }, + { "XC_DCCCHATABORT", "DCC CHAT Abort", 1, NULL }, + { "XC_DCCCONCHAT", "DCC CHAT Connect", 2, NULL }, + { "XC_DCCCHATF", "DCC CHAT Failed", 4, NULL }, + { "XC_DCCCHATOFFER", "DCC CHAT Offer", 1, NULL }, + { "XC_DCCCHATOFFERING", "DCC CHAT Offering", 1, NULL }, + { "XC_DCCCHATREOFFER", "DCC CHAT Reoffer", 1, NULL }, + { "XC_DCCCONFAIL", "DCC Conection Failed", 3, NULL }, + { "XC_DCCGENERICOFFER", "DCC Generic Offer", 2, NULL }, + { "XC_DCCHEAD", "DCC Header", 0, NULL }, + { "XC_MALFORMED", "DCC Malformed", 2, NULL }, + { "XC_DCCOFFER", "DCC Offer", 3, NULL }, + { "XC_DCCIVAL", "DCC Offer Not Valid", 0, NULL }, + { "XC_DCCRECVABORT", "DCC RECV Abort", 2, NULL }, + { "XC_DCCRECVCOMP", "DCC RECV Complete", 4, NULL }, + { "XC_DCCCONRECV", "DCC RECV Connect", 3, NULL }, + { "XC_DCCRECVERR", "DCC RECV Failed", 4, NULL }, + { "XC_DCCFILEERR", "DCC RECV File Open Error", 2, NULL }, + { "XC_DCCRENAME", "DCC Rename", 2, NULL }, + { "XC_DCCRESUMEREQUEST", "DCC RESUME Request", 3, NULL }, + { "XC_DCCSENDABORT", "DCC SEND Abort", 2, NULL }, + { "XC_DCCSENDCOMP", "DCC SEND Complete", 3, NULL }, + { "XC_DCCCONSEND", "DCC SEND Connect", 3, NULL }, + { "XC_DCCSENDFAIL", "DCC SEND Failed", 3, NULL }, + { "XC_DCCSENDOFFER", "DCC SEND Offer", 4, NULL }, + { "XC_DCCSTALL", "DCC Stall", 3, NULL }, + { "XC_DCCTOUT", "DCC Timeout", 3, NULL }, + { "XC_DELNOTIFY", "Delete Notify", 1, NULL }, + { "XC_DISCON", "Disconnected", 1, NULL }, + { "XC_FOUNDIP", "Found IP", 1, NULL }, + { "XC_GENMSG", "Generic Message", 2, NULL }, + { "XC_IGNOREADD", "Ignore Add", 1, NULL }, + { "XC_IGNORECHANGE", "Ignore Changed", 1, NULL }, + { "XC_IGNOREFOOTER", "Ignore Footer", 0, NULL }, + { "XC_IGNOREHEADER", "Ignore Header", 0, NULL }, + { "XC_IGNOREREMOVE", "Ignore Remove", 1, NULL }, + { "XC_IGNOREEMPTY", "Ignorelist Empty", 0, NULL }, + { "XC_INVITE", "Invite", 1, NULL }, + { "XC_INVITED", "Invited", 3, NULL }, + { "XC_JOIN", "Join", 3, NULL }, + { "XC_KEYWORD", "Keyword", 1, NULL }, + { "XC_KICK", "Kick", 4, NULL }, + { "XC_KILL", "Killed", 2, NULL }, + { "XC_MSGSEND", "Message Send", 2, NULL }, + { "XC_MOTD", "Motd", 1, NULL }, + { "XC_MOTDSKIP", "MOTD Skipped", 0, NULL }, + { "XC_NICKCLASH", "Nick Clash", 2, NULL }, + { "XC_NICKFAIL", "Nick Failed", 0, NULL }, + { "XC_NODCC", "No DCC", 0, NULL }, + { "XC_NOCHILD", "No Running Process", 0, NULL }, + { "XC_NOTICE", "Notice", 2, NULL }, + { "XC_NOTICESEND", "Notice Send", 2, NULL }, + { "XC_NOTIFYEMPTY", "Notify Empty", 0, NULL }, + { "XC_NOTIFYHEAD", "Notify Header", 0, NULL }, + { "XC_NOTIFYNUMBER", "Notify Number", 1, NULL }, + { "XC_NOTIFYOFFLINE", "Notify Offline", 3, NULL }, + { "XC_NOTIFYONLINE", "Notify Online", 3, NULL }, + { "XC_OPENDIALOG", "Open Dialog", 0, NULL }, + { "XC_PART", "Part", 3, NULL }, + { "XC_PARTREASON", "Part with Reason", 4, NULL }, + { "XC_PINGREP", "Ping Reply", 2, NULL }, + { "XC_PINGTIMEOUT", "Ping Timeout", 1, NULL }, + { "XC_PRIVMSG", "Private Message", 3, NULL }, + { "XC_DPRIVMSG", "Private Message to Dialog", 3, NULL }, + { "XC_ALREADYPROCESS", "Process Already Running", 0, NULL }, + { "XC_QUIT", "Quit", 3, NULL }, + { "XC_RAWMODES", "Raw Modes", 2, NULL }, + { "XC_WALLOPS", "Receive Wallops", 2, NULL }, + { "XC_RESOLVINGUSER", "Resolving User", 2, NULL }, + { "XC_SERVERCONNECTED", "Server Connected", 0, NULL }, + { "XC_SERVERERROR", "Server Error", 1, NULL }, + { "XC_SERVERLOOKUP", "Server Lookup", 1, NULL }, + { "XC_SERVNOTICE", "Server Notice", 2, NULL }, + { "XC_SERVTEXT", "Server Text", 2, NULL }, + { "XC_STOPCONNECT", "Stop Connection", 1, NULL }, + { "XC_TOPIC", "Topic", 2, NULL }, + { "XC_NEWTOPIC", "Topic Change", 3, NULL }, + { "XC_TOPICDATE", "Topic Creation", 3, NULL }, + { "XC_UKNHOST", "Unknown Host", 0, NULL }, + { "XC_USERLIMIT", "User Limit", 1, NULL }, + { "XC_USERSONCHAN", "Users On Channel", 2, NULL }, + { "XC_WHOIS_AUTH", "WhoIs Authenticated", 3, NULL }, + { "XC_WHOIS5", "WhoIs Away Line", 2, NULL }, + { "XC_WHOIS2", "WhoIs Channel/Oper Line", 2, NULL }, + { "XC_WHOIS6", "WhoIs End", 1, NULL }, + { "XC_WHOIS_ID", "WhoIs Identified", 2, NULL }, + { "XC_WHOIS4", "WhoIs Idle Line", 2, NULL }, + { "XC_WHOIS4T", "WhoIs Idle Line with Signon", 3, NULL }, + { "XC_WHOIS1", "WhoIs Name Line", 4, NULL }, + { "XC_WHOIS_REALHOST", "WhoIs Real Host", 4, NULL }, + { "XC_WHOIS3", "WhoIs Server Line", 2, NULL }, + { "XC_WHOIS_SPECIAL", "WhoIs Special", 3, NULL }, + { "XC_UJOIN", "You Join", 3, NULL }, + { "XC_UKICK", "You Kicked", 4, NULL }, + { "XC_UPART", "You Part", 3, NULL }, + { "XC_UPARTREASON", "You Part with Reason", 4, NULL }, + { "XC_UACTION", "Your Action", 3, NULL }, + { "XC_UINVITE", "Your Invitation", 3, NULL }, + { "XC_UCHANMSG", "Your Message", 4, NULL }, + { "XC_UCHANGENICK", "Your Nick Changing", 2, NULL } +}; + diff --git a/plugins/tcl/tclplugin.c b/plugins/tcl/tclplugin.c new file mode 100644 index 00000000..17dc7556 --- /dev/null +++ b/plugins/tcl/tclplugin.c @@ -0,0 +1,2290 @@ +/*************************************************************************** + tclplugin.c - Tcl plugin for xchat 1.9.x / 2.x.x + -------------------------------------------------s + begin : Sat Nov 19 17:31:20 MST 2002 + copyright : Copyright 2002-2010 Daniel P. Stasinski + email : daniel@avenues.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +static char RCSID[] = "$Id: tclplugin.c,v 1.64 2010/03/10 04:24:16 mooooooo Exp $"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#define bzero(mem, sz) memset((mem), 0, (sz)) +#define bcopy(src, dest, count) memmove((dest), (src), (count)) +#else +#include +#endif + +#include "xchat-plugin.h" +#include "tclplugin.h" +#include "printevents.h" + +static int nexttimerid = 0; +static int nexttimerindex = 0; +static timer timers[MAX_TIMERS]; + +static char VERSION[16]; + +static int initialized = 0; +static int reinit_tried = 0; +static Tcl_Interp *interp = NULL; +static xchat_plugin *ph; +static xchat_hook *raw_line_hook; +static xchat_hook *Command_TCL_hook; +static xchat_hook *Command_Source_hook; +static xchat_hook *Command_Reload_hook; +static xchat_hook *Command_Load_hook; +static xchat_hook *Event_Handler_hook; +static xchat_hook *Null_Command_hook; + +static int complete_level = 0; +static t_complete complete[MAX_COMPLETES + 1]; +static Tcl_HashTable cmdTablePtr; +static Tcl_HashTable aliasTablePtr; + +static int nextprocid = 0x1000; +#define PROCPREFIX "__xctcl_" + +static char unknown[] = { +"rename unknown iunknown\n" +"proc ::unknown {args} {\n" +" global errorInfo errorCode\n" +" if { [string index [lindex $args 0] 0] == \"/\" } {\n" +" command \"[string range [join $args \" \"] 1 end]\"\n" +" } else {\n" +" set code [catch {uplevel iunknown $args} msg]\n" +" if {$code == 1} {\n" +" set new [split $errorInfo \\n]\n" +" set new [join [lrange $new 0 [expr {[llength $new] - 8}]] \\n]\n" +" return -code error -errorcode $errorCode -errorinfo $new $msg\n" +" } else {\n" +" return -code $code $msg\n" +" }\n" +" }\n" +"}\n" +"proc unsupported0 {from to {bytes \"\"}} {\n" +" set b [expr {$bytes == \"\" ? \"\" : \"-size [list $bytes]\"}]\n" +" eval [list fcopy $from $to] $b\n" +"}\n" +}; + +static char sourcedirs[] = { + "set files [lsort [glob -nocomplain -directory [xchatdir] \"*.tcl\"]]\n" + "set init [lsearch -glob $files \"*/init.tcl\"]\n" + "if { $init > 0 } {\n" + "set initfile [lindex $files $init]\n" + "set files [lreplace $files $init $init]\n" + "set files [linsert $files 0 $initfile]\n" "}\n" "foreach f $files {\n" "if { [catch { source $f } errMsg] } {\n" "puts \"Tcl plugin\\tError sourcing \\\"$f\\\" ($errMsg)\"\n" "} else {\n" "puts \"Tcl plugin\\tSourced \\\"$f\\\"\"\n" "}\n" "}\n" +}; + +static char inlinetcl[] = { +"proc splitsrc { } {\n" +"uplevel \"scan \\$_src \\\"%\\\\\\[^!\\\\\\]!%\\\\\\[^@\\\\\\]@%s\\\" _nick _ident _host\"\n" +"}\n" + +"proc ::exit { } {\n" +"puts \"Using 'exit' is bad\"\n" +"}\n" + +"proc ::away { args } { return [eval [join [list getinfo $args away]]] }\n" +"proc ::channel { args } { return [eval [join [list getinfo $args channel]]] }\n" +"proc ::tab { args } { return [eval [join [list getinfo $args channel]]] }\n" +"proc ::charset { args } { return [eval [join [list getinfo $args charset]]] }\n" +"proc ::host { args } { return [eval [join [list getinfo $args host]]] }\n" +"proc ::inputbox { args } { return [eval [join [list getinfo $args inputbox]]] }\n" +"proc ::libdirfs { args } { return [eval [join [list getinfo $args libdirfs]]] }\n" +"proc ::network { args } { return [eval [join [list getinfo $args network]]] }\n" +"proc ::nickserv { args } { return [eval [join [list getinfo $args nickserv]]] }\n" +"proc ::server { args } { return [eval [join [list getinfo $args server]]] }\n" +"proc ::version { args } { return [eval [join [list getinfo $args version]]] }\n" +"proc ::win_status { args } { return [eval [join [list getinfo $args win_status]]] }\n" +"proc ::xchatdir { args } { return [eval [join [list getinfo $args xchatdir]]] }\n" +"proc ::xchatdirfs { args } { return [eval [join [list getinfo $args xchatdirfs]]] }\n" + +"proc ::color { {arg {}} } { return \"\\003$arg\" }\n" +"proc ::bold { } { return \"\\002\" }\n" +"proc ::underline { } { return \"\\037\" }\n" +"proc ::reverse { } { return \"\\026\" }\n" +"proc ::reset { } { return \"\\017\" }\n" + +"proc ::__xctcl_errorInfo { } {\n" +" set text [split $::errorInfo \\n]\n" +" puts [string trim [join [lrange $text 0 [expr {[llength $text] - 4}]] \\n]]\n" +"}\n" + +"proc ::bgerror { message } {\n" +" set text [split $::errorInfo \\n]\n" +" puts [string trim [join [lrange $text 0 [expr {[llength $text] - 4}]] \\n]]\n" +"}\n" +}; + +static void NiceErrorInfo () +{ + Tcl_Eval(interp, "::__xctcl_errorInfo"); +} + +static void Tcl_MyDStringAppend(Tcl_DString * ds, char *string) +{ + Tcl_DStringAppend(ds, string, strlen(string)); +} + +static char *InternalProcName(int value) +{ + static char result[32]; + sprintf(result, "%s%08x", PROCPREFIX, value); + return result; +} + +static int SourceInternalProc(int id, const char *args, const char *source) +{ + Tcl_DString ds; + int result; + Tcl_DStringInit(&ds); + + Tcl_MyDStringAppend(&ds, "proc "); + Tcl_MyDStringAppend(&ds, InternalProcName(id)); + Tcl_MyDStringAppend(&ds, " { "); + Tcl_MyDStringAppend(&ds, args); + Tcl_MyDStringAppend(&ds, " } {\n"); + Tcl_MyDStringAppend(&ds, source); + Tcl_MyDStringAppend(&ds, "\n}\n\n"); + + result = Tcl_Eval(interp, ds.string); + + Tcl_DStringFree(&ds); + + return result; +} + +static int EvalInternalProc(const char *procname, int ct, ...) +{ + Tcl_DString ds; + int result; + va_list ap; + char *buf; + + Tcl_DStringInit(&ds); + + Tcl_MyDStringAppend(&ds, procname); + + if (ct) { + va_start(ap, ct); + while (ct--) { + if ((buf = va_arg(ap, char *)) != NULL) + Tcl_DStringAppendElement(&ds, buf); + else + Tcl_MyDStringAppend(&ds, " \"\""); + } + va_end(ap); + } + + result = Tcl_Eval(interp, ds.string); + + Tcl_DStringFree(&ds); + + return result; +} + + +static void DeleteInternalProc(const char *proc) +{ + Tcl_DString ds; + + Tcl_DStringInit(&ds); + Tcl_MyDStringAppend(&ds, "rename "); + Tcl_MyDStringAppend(&ds, proc); + Tcl_MyDStringAppend(&ds, " {}"); + Tcl_Eval(interp, ds.string); + Tcl_DStringFree(&ds); +} + +static char *StrDup(const char *string, int *length) +{ + char *result; + + if (string == NULL) + return NULL; + + *length = strlen(string); + result = Tcl_Alloc(*length + 1); + strncpy(result, string, *length); + result[*length] = 0; + + return result; +} + +static char *myitoa(long value) +{ + static char result[32]; + sprintf(result, "%ld", value); + return result; +} + +static xchat_context *atoctx(const char *nptr) +{ + int isnum = 1; + int x = 0; + + if (!nptr) + return NULL; + + while (isnum && nptr[x]) { + if (!isdigit(nptr[x++])) + isnum--; + } + + if (isnum && x) + return (xchat_context *) atol(nptr); + else + return NULL; +} + +static xchat_context *xchat_smart_context(const char *arg1, const char *arg2) +{ + const char *server, *s, *n; + xchat_context *result = NULL; + xchat_context *ctx = NULL; + xchat_context *actx = NULL; + xchat_list *list; + + if (arg1 == NULL) + return xchat_get_context(ph);; + + if (arg1 && arg2) { + result = xchat_find_context(ph, arg1, arg2); + if (result == NULL) + result = xchat_find_context(ph, arg2, arg1); + return result; + } else { + + actx = atoctx(arg1); + + server = xchat_get_info(ph, "server"); + + list = xchat_list_get(ph, "channels"); + + if (list != NULL) { + + while (xchat_list_next(ph, list)) { + + ctx = (xchat_context *)xchat_list_str(ph, list, "context"); + + if (actx) { + if (ctx == actx) { + result = ctx; + break; + } + } else { + + s = xchat_list_str(ph, list, "server"); + + if (xchat_list_int(ph, list, "type") == 1) { + if (strcasecmp(arg1, s) == 0) { + result = ctx; + break; + } + n = xchat_list_str(ph, list, "network"); + if (n) { + if (strcasecmp(arg1, n) == 0) { + result = ctx; + break; + } + } + } else { + if ((strcasecmp(server, s) == 0) && (strcasecmp(arg1, xchat_list_str(ph, list, "channel")) == 0)) { + result = ctx; + break; + } + } + } + } + + xchat_list_free(ph, list); + } + + } + + return result; +} + +static void queue_nexttimer() +{ + int x; + time_t then; + + nexttimerindex = 0; + then = (time_t) 0x7fffffff; + + for (x = 1; x < MAX_TIMERS; x++) { + if (timers[x].timerid) { + if (timers[x].timestamp < then) { + then = timers[x].timestamp; + nexttimerindex = x; + } + } + } +} + +static int insert_timer(int seconds, int count, const char *script) +{ + int x; + int dummy; + time_t now; + int id; + + if (script == NULL) + return (-1); + + id = (nextprocid++ % INT_MAX) + 1; + + now = time(NULL); + + for (x = 1; x < MAX_TIMERS; x++) { + if (timers[x].timerid == 0) { + if (SourceInternalProc(id, "", script) == TCL_ERROR) { + xchat_printf(ph, "\0039TCL plugin\003\tERROR (timer %d) ", timers[x].timerid); + NiceErrorInfo (); + return (-1); + } + timers[x].timerid = (nexttimerid++ % INT_MAX) + 1; + timers[x].timestamp = now + seconds; + timers[x].count = count; + timers[x].seconds = seconds; + timers[x].procPtr = StrDup(InternalProcName(id), &dummy); + queue_nexttimer(); + return (timers[x].timerid); + } + } + + return (-1); +} + +static void do_timer() +{ + xchat_context *origctx; + time_t now; + int index; + + if (!nexttimerindex) + return; + + now = time(NULL); + + if (now < timers[nexttimerindex].timestamp) + return; + + index = nexttimerindex; + origctx = xchat_get_context(ph); + if (EvalInternalProc(timers[index].procPtr, 0) == TCL_ERROR) { + xchat_printf(ph, "\0039TCL plugin\003\tERROR (timer %d) ", timers[index].timerid); + NiceErrorInfo (); + } + xchat_set_context(ph, origctx); + + if (timers[index].count != -1) + timers[index].count--; + + if (timers[index].count == 0) { + timers[index].timerid = 0; + if (timers[index].procPtr != NULL) { + DeleteInternalProc(timers[index].procPtr); + Tcl_Free(timers[index].procPtr); + } + timers[index].procPtr = NULL; + } else { + timers[index].timestamp += timers[index].seconds; + } + + queue_nexttimer(); + + return; + +} + +static int Server_raw_line(char *word[], char *word_eol[], void *userdata) +{ + char *src, *cmd, *dest, *rest; + char *chancmd = NULL; + char *procList; + Tcl_HashEntry *entry = NULL; + xchat_context *origctx; + int len; + int dummy; + char *string = NULL; + int ctcp = 0; + int count; + int list_argc, proc_argc; + const char **list_argv, **proc_argv; + int private = 0; + + if (word[0][0] == 0) + return XCHAT_EAT_NONE; + + if (complete_level == MAX_COMPLETES) + return XCHAT_EAT_NONE; + + complete_level++; + complete[complete_level].defresult = XCHAT_EAT_NONE; /* XCHAT_EAT_PLUGIN; */ + complete[complete_level].result = XCHAT_EAT_NONE; + complete[complete_level].word = word; + complete[complete_level].word_eol = word_eol; + + if (word[1][0] == ':') { + src = word[1]; + cmd = word[2]; + dest = word[3]; + rest = word_eol[4]; + } else { + src = ""; + cmd = word[1]; + if (word_eol[2][0] == ':') { + dest = ""; + rest = word_eol[2]; + } else { + dest = word[2]; + rest = word_eol[3]; + } + } + + if (src[0] == ':') + src++; + if (dest[0] == ':') + dest++; + if (rest[0] == ':') + rest++; + + if (rest[0] == 0x01) { + rest++; + if (strcasecmp("PRIVMSG", cmd) == 0) { + if (strncasecmp(rest, "ACTION ", 7) == 0) { + cmd = "ACTION"; + rest += 7; + } else + cmd = "CTCP"; + } else if (!strcasecmp("NOTICE", cmd)) + cmd = "CTCR"; + ctcp = 1; + } else if (!strcasecmp("NOTICE", cmd) && (strchr(src, '!') == NULL)) { + cmd = "SNOTICE"; + } else if (rest[0] == '!') { + chancmd = word[4] + 1; + } + + if (chancmd != NULL) { + string = StrDup(chancmd, &dummy); + Tcl_UtfToUpper(string); + if ((entry = Tcl_FindHashEntry(&cmdTablePtr, string)) == NULL) { + Tcl_Free(string); + } else { + cmd = chancmd; + rest = word_eol[5]; + } + } + + if (entry == NULL) { + string = StrDup(cmd, &dummy); + Tcl_UtfToUpper(string); + entry = Tcl_FindHashEntry(&cmdTablePtr, string); + } + + if (entry != NULL) { + + procList = Tcl_GetHashValue(entry); + + if (isalpha(dest[0])) + private = 1; + + rest = StrDup(rest, &len); + if (ctcp) { + if (rest != NULL) { + if ((len > 1) && (rest[len - 1] == 0x01)) + rest[len - 1] = 0; + } + } + + if (Tcl_SplitList(interp, procList, &list_argc, &list_argv) == TCL_OK) { + + for (count = 0; count < list_argc; count++) { + + if (Tcl_SplitList(interp, list_argv[count], &proc_argc, &proc_argv) != TCL_OK) + continue; + + origctx = xchat_get_context(ph); + if (EvalInternalProc(proc_argv[1], 7, src, dest, cmd, rest, word_eol[1], proc_argv[0], myitoa(private)) == TCL_ERROR) { + xchat_printf(ph, "\0039TCL plugin\003\tERROR (on %s %s) ", cmd, proc_argv[0]); + NiceErrorInfo (); + } + xchat_set_context(ph, origctx); + + Tcl_Free((char *) proc_argv); + + if ((complete[complete_level].result == XCHAT_EAT_PLUGIN) || (complete[complete_level].result == XCHAT_EAT_ALL)) + break; + + } + + Tcl_Free((char *) list_argv); + + } + + Tcl_Free(rest); + + } + + if (string) + Tcl_Free(string); + + return complete[complete_level--].result; + +} + +static int Print_Hook(char *word[], void *userdata) +{ + char *procList; + Tcl_HashEntry *entry; + xchat_context *origctx; + int count; + int list_argc, proc_argc; + const char **list_argv, **proc_argv; + Tcl_DString ds; + int x; + + if (complete_level == MAX_COMPLETES) + return XCHAT_EAT_NONE; + + complete_level++; + complete[complete_level].defresult = XCHAT_EAT_NONE; /* XCHAT_EAT_PLUGIN; */ + complete[complete_level].result = XCHAT_EAT_NONE; + complete[complete_level].word = word; + complete[complete_level].word_eol = word; + + if ((entry = Tcl_FindHashEntry(&cmdTablePtr, xc[(int) userdata].event)) != NULL) { + + procList = Tcl_GetHashValue(entry); + + if (Tcl_SplitList(interp, procList, &list_argc, &list_argv) == TCL_OK) { + + for (count = 0; count < list_argc; count++) { + + if (Tcl_SplitList(interp, list_argv[count], &proc_argc, &proc_argv) != TCL_OK) + continue; + + origctx = xchat_get_context(ph); + + Tcl_DStringInit(&ds); + + if ((int) userdata == CHAT) { + Tcl_DStringAppend(&ds, word[3], strlen(word[3])); + Tcl_DStringAppend(&ds, "!*@", 3); + Tcl_DStringAppend(&ds, word[1], strlen(word[1])); + if (EvalInternalProc(proc_argv[1], 7, ds.string, word[2], xc[(int) userdata].event, word[4], "", proc_argv[0], "0") == TCL_ERROR) { + xchat_printf(ph, "\0039TCL plugin\003\tERROR (on %s %s) ", xc[(int) userdata].event, proc_argv[0]); + NiceErrorInfo (); + } + } else { + if (xc[(int) userdata].argc > 0) { + for (x = 0; x <= xc[(int) userdata].argc; x++) + Tcl_DStringAppendElement(&ds, word[x]); + } + if (EvalInternalProc(proc_argv[1], 7, "", "", xc[(int) userdata].event, "", ds.string, proc_argv[0], "0") == TCL_ERROR) { + xchat_printf(ph, "\0039Tcl plugin\003\tERROR (on %s %s) ", xc[(int) userdata].event, proc_argv[0]); + NiceErrorInfo (); + } + } + + Tcl_DStringFree(&ds); + + xchat_set_context(ph, origctx); + + Tcl_Free((char *) proc_argv); + + if ((complete[complete_level].result == XCHAT_EAT_PLUGIN) || (complete[complete_level].result == XCHAT_EAT_ALL)) + break; + + } + + Tcl_Free((char *) list_argv); + + } + } + + return complete[complete_level--].result; +} + + +static int tcl_timerexists(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int x; + int timerid; + + BADARGS(2, 2, " schedid"); + + if (Tcl_GetInt(irp, argv[1], &timerid) != TCL_OK) { + Tcl_AppendResult(irp, "Invalid timer id", NULL); + return TCL_ERROR; + } + + if (timerid) { + for (x = 1; x < MAX_TIMERS; x++) { + if (timers[x].timerid == timerid) { + Tcl_AppendResult(irp, "1", NULL); + return TCL_OK; + } + } + } + + Tcl_AppendResult(irp, "0", NULL); + + return TCL_OK; +} + +static int tcl_killtimer(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int x; + int timerid; + + BADARGS(2, 2, " timerid"); + + if (Tcl_GetInt(irp, argv[1], &timerid) != TCL_OK) { + Tcl_AppendResult(irp, "Invalid timer id", NULL); + return TCL_ERROR; + } + + if (timerid) { + for (x = 1; x < MAX_TIMERS; x++) { + if (timers[x].timerid == timerid) { + timers[x].timerid = 0; + if (timers[x].procPtr != NULL) { + DeleteInternalProc(timers[x].procPtr); + Tcl_Free(timers[x].procPtr); + } + timers[x].procPtr = NULL; + break; + } + } + } + + queue_nexttimer(); + + return TCL_OK; +} + +static int tcl_timers(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int x; + Tcl_DString ds; + time_t now; + + BADARGS(1, 1, ""); + + now = time(NULL); + + Tcl_DStringInit(&ds); + + for (x = 1; x < MAX_TIMERS; x++) { + if (timers[x].timerid) { + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, myitoa((long)timers[x].timerid)); + Tcl_DStringAppendElement(&ds, myitoa((long)timers[x].timestamp - now)); + Tcl_DStringAppendElement(&ds, timers[x].procPtr); + Tcl_DStringAppendElement(&ds, myitoa((long)timers[x].seconds)); + Tcl_DStringAppendElement(&ds, myitoa((long)timers[x].count)); + Tcl_DStringEndSublist(&ds); + } + } + + Tcl_AppendResult(interp, ds.string, NULL); + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_timer(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int seconds; + int timerid; + int repeat = 0; + int count = 0; + int first = 1; + char reply[32]; + + BADARGS(3, 6, " ?-repeat? ?-count times? seconds {script | procname ?args?}"); + + while (argc--) { + if (strcasecmp(argv[first], "-repeat") == 0) { + repeat++; + } else if (strcasecmp(argv[first], "-count") == 0) { + if (Tcl_GetInt(irp, argv[++first], &count) != TCL_OK) + return TCL_ERROR; + } else { + break; + } + first++; + } + + if (repeat && !count) + count = -1; + + if (!count) + count = 1; + + if (Tcl_GetInt(irp, argv[first++], &seconds) != TCL_OK) + return TCL_ERROR; + + if ((timerid = insert_timer(seconds, count, argv[first++])) == -1) { + Tcl_AppendResult(irp, "0", NULL); + return TCL_ERROR; + } + + sprintf(reply, "%d", timerid); + + Tcl_AppendResult(irp, reply, NULL); + + queue_nexttimer(); + + return TCL_OK; +} + +static int tcl_on(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int newentry; + char *procList; + Tcl_HashEntry *entry; + char *token; + int dummy; + Tcl_DString ds; + int index; + int count; + int list_argc, proc_argc; + int id; + const char **list_argv, **proc_argv; + + BADARGS(4, 4, " token label {script | procname ?args?}"); + + id = (nextprocid++ % INT_MAX) + 1; + + if (SourceInternalProc(id, "_src _dest _cmd _rest _raw _label _private", argv[3]) == TCL_ERROR) { + xchat_printf(ph, "\0039Tcl plugin\003\tERROR (on %s:%s) ", argv[1], argv[2]); + NiceErrorInfo (); + return TCL_OK; + } + + token = StrDup(argv[1], &dummy); + Tcl_UtfToUpper(token); + + Tcl_DStringInit(&ds); + + entry = Tcl_CreateHashEntry(&cmdTablePtr, token, &newentry); + if (!newentry) { + procList = Tcl_GetHashValue(entry); + if (Tcl_SplitList(interp, procList, &list_argc, &list_argv) == TCL_OK) { + for (count = 0; count < list_argc; count++) { + if (Tcl_SplitList(interp, list_argv[count], &proc_argc, &proc_argv) != TCL_OK) + continue; + if (strcmp(proc_argv[0], argv[2])) { + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, proc_argv[0]); + Tcl_DStringAppendElement(&ds, proc_argv[1]); + Tcl_DStringEndSublist(&ds); + } else { + DeleteInternalProc(proc_argv[1]); + } + Tcl_Free((char *) proc_argv); + } + Tcl_Free((char *) list_argv); + } + Tcl_Free(procList); + } + + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, argv[2]); + Tcl_DStringAppendElement(&ds, InternalProcName(id)); + Tcl_DStringEndSublist(&ds); + + procList = StrDup(ds.string, &dummy); + + Tcl_SetHashValue(entry, procList); + + if ((strncmp(token, "XC_", 3) == 0) || (strcmp(token, "CHAT") == 0)) { + for (index = 0; index < XC_SIZE; index++) { + if (strcmp(xc[index].event, token) == 0) { + if (xc[index].hook == NULL) { + xc[index].hook = xchat_hook_print(ph, xc[index].emit, XCHAT_PRI_NORM, Print_Hook, (void *) index); + break; + } + } + } + } + + Tcl_Free(token); + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_off(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + char *procList; + Tcl_HashEntry *entry; + char *token; + int dummy; + Tcl_DString ds; + int index; + int count; + int list_argc, proc_argc; + const char **list_argv, **proc_argv; + + BADARGS(2, 3, " token ?label?"); + + token = StrDup(argv[1], &dummy); + Tcl_UtfToUpper(token); + + Tcl_DStringInit(&ds); + + if ((entry = Tcl_FindHashEntry(&cmdTablePtr, token)) != NULL) { + + procList = Tcl_GetHashValue(entry); + + if (argc == 3) { + if (Tcl_SplitList(interp, procList, &list_argc, &list_argv) == TCL_OK) { + for (count = 0; count < list_argc; count++) { + if (Tcl_SplitList(interp, list_argv[count], &proc_argc, &proc_argv) != TCL_OK) + continue; + if (strcmp(proc_argv[0], argv[2])) { + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, proc_argv[0]); + Tcl_DStringAppendElement(&ds, proc_argv[1]); + Tcl_DStringEndSublist(&ds); + } else + DeleteInternalProc(proc_argv[1]); + Tcl_Free((char *) proc_argv); + } + Tcl_Free((char *) list_argv); + } + } + + Tcl_Free(procList); + + if (ds.length) { + procList = StrDup(ds.string, &dummy); + Tcl_SetHashValue(entry, procList); + } else { + Tcl_DeleteHashEntry(entry); + } + + if (!ds.length) { + if ((strncmp(token, "XC_", 3) == 0) || (strcmp(token, "CHAT") == 0)) { + for (index = 0; index < XC_SIZE; index++) { + if (strcmp(xc[index].event, token) == 0) { + if (xc[index].hook != NULL) { + xchat_unhook(ph, xc[index].hook); + xc[index].hook = NULL; + break; + } + } + } + } + } + } + + Tcl_Free(token); + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_alias(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int newentry; + alias *aliasPtr; + Tcl_HashEntry *entry; + char *string; + const char *help = NULL; + int dummy; + int id; + + BADARGS(3, 4, " name ?help? {script | procname ?args?}"); + + string = StrDup(argv[1], &dummy); + Tcl_UtfToUpper(string); + + if (strlen(argv[argc - 1])) { + + if (argc == 4) + help = argv[2]; + + id = (nextprocid++ % INT_MAX) + 1; + + if (SourceInternalProc(id, "_cmd _rest", argv[argc - 1]) == TCL_ERROR) { + xchat_printf(ph, "\0039Tcl plugin\003\tERROR (alias %s) ", argv[1]); + NiceErrorInfo (); + return TCL_OK; + } + + entry = Tcl_CreateHashEntry(&aliasTablePtr, string, &newentry); + if (newentry) { + aliasPtr = (alias *) Tcl_Alloc(sizeof(alias)); + if (string[0] == '@') + aliasPtr->hook = NULL; + else + aliasPtr->hook = xchat_hook_command(ph, string, XCHAT_PRI_NORM, Command_Alias, help, 0); + } else { + aliasPtr = Tcl_GetHashValue(entry); + DeleteInternalProc(aliasPtr->procPtr); + Tcl_Free(aliasPtr->procPtr); + } + + aliasPtr->procPtr = StrDup(InternalProcName(id), &dummy); + + Tcl_SetHashValue(entry, aliasPtr); + + } else { + + if ((entry = Tcl_FindHashEntry(&aliasTablePtr, string)) != NULL) { + aliasPtr = Tcl_GetHashValue(entry); + DeleteInternalProc(aliasPtr->procPtr); + Tcl_Free(aliasPtr->procPtr); + if (aliasPtr->hook) + xchat_unhook(ph, aliasPtr->hook); + Tcl_Free((char *) aliasPtr); + Tcl_DeleteHashEntry(entry); + } + } + + Tcl_Free(string); + + return TCL_OK; +} + +static int tcl_complete(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + BADARGS(1, 2, " ?EAT_NONE|EAT_XCHAT|EAT_PLUGIN|EAT_ALL?"); + + if (argc == 2) { + if (Tcl_GetInt(irp, argv[1], &complete[complete_level].result) != TCL_OK) { + if (strcasecmp("EAT_NONE", argv[1]) == 0) + complete[complete_level].result = XCHAT_EAT_NONE; + else if (strcasecmp("EAT_XCHAT", argv[1]) == 0) + complete[complete_level].result = XCHAT_EAT_XCHAT; + else if (strcasecmp("EAT_PLUGIN", argv[1]) == 0) + complete[complete_level].result = XCHAT_EAT_PLUGIN; + else if (strcasecmp("EAT_ALL", argv[1]) == 0) + complete[complete_level].result = XCHAT_EAT_ALL; + else + BADARGS(1, 2, " ?EAT_NONE|EAT_XCHAT|EAT_PLUGIN|EAT_ALL?"); + } + } else + complete[complete_level].result = complete[complete_level].defresult; + + return TCL_RETURN; +} + +static int tcl_command(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *origctx; + xchat_context *ctx = NULL; + const char *string = NULL; + + BADARGS(2, 4, " ?server|network|context? ?#channel|nick? text"); + + origctx = xchat_get_context(ph); + + switch (argc) { + case 2: + ctx = origctx; + break; + case 3: + ctx = xchat_smart_context(argv[1], NULL); + break; + case 4: + ctx = xchat_smart_context(argv[1], argv[2]); + break; + default:; + } + + CHECKCTX(ctx); + + string = argv[argc - 1]; + + if (string[0] == '/') + string++; + + xchat_set_context(ph, ctx); + xchat_command(ph, string); + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_raw(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *origctx; + xchat_context *ctx = NULL; + const char *string = NULL; + + BADARGS(2, 4, " ?server|network|context? ?#channel|nick? text"); + + origctx = xchat_get_context(ph); + + switch (argc) { + case 2: + ctx = origctx; + break; + case 3: + ctx = xchat_smart_context(argv[1], NULL); + break; + case 4: + ctx = xchat_smart_context(argv[1], argv[2]); + break; + default:; + } + + CHECKCTX(ctx); + + string = argv[argc - 1]; + + xchat_set_context(ph, ctx); + xchat_commandf(ph, "RAW %s", string); + xchat_set_context(ph, origctx); + + return TCL_OK; +} + + +static int tcl_prefs(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int i; + const char *str; + + BADARGS(2, 2, " name"); + + switch (xchat_get_prefs (ph, argv[1], &str, &i)) { + case 1: + Tcl_AppendResult(irp, str, NULL); + break; + case 2: + case 3: + Tcl_AppendResult(irp, myitoa(i), NULL); + break; + default: + Tcl_AppendResult(irp, NULL); + } + + return TCL_OK; +} + +static int tcl_info(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[], char *id) +{ + char *result; + int max_argc; + xchat_context *origctx, *ctx; + + if (id == NULL) { + BADARGS(2, 3, " ?server|network|context? id"); + max_argc = 3; + } else { + BADARGS(1, 2, " ?server|network|context?"); + max_argc = 2; + } + + origctx = xchat_get_context(ph); + + if (argc == max_argc) { + ctx = xchat_smart_context(argv[1], NULL); + CHECKCTX(ctx); + xchat_set_context(ph, ctx); + } + + if (id == NULL) + id = argv[argc-1]; + + if ((result = xchat_get_info(ph, id)) == NULL) + result = ""; + + Tcl_AppendResult(irp, result, NULL); + + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_me(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + return tcl_info(cd, irp, argc, argv, "nick"); +} + +static int tcl_getinfo(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + return tcl_info(cd, irp, argc, argv, NULL); +} + +static int tcl_getlist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_list *list = NULL; + const char *name = NULL; + const char * const *fields; + const char *field; + const char *sattr; + int iattr; + int i; + time_t t; + Tcl_DString ds; + xchat_context *origctx; + xchat_context *ctx = NULL; + + origctx = xchat_get_context(ph); + + BADARGS(1, 2, " list"); + + Tcl_DStringInit(&ds); + + fields = xchat_list_fields(ph, "lists"); + + if (argc == 1) { + for (i = 0; fields[i] != NULL; i++) { + Tcl_DStringAppendElement(&ds, fields[i]); + } + goto done; + } + + for (i = 0; fields[i] != NULL; i++) { + if (strcmp(fields[i], argv[1]) == 0) { + name = fields[i]; + break; + } + } + + if (name == NULL) + goto done; + + list = xchat_list_get(ph, name); + if (list == NULL) + goto done; + + fields = xchat_list_fields(ph, name); + + Tcl_DStringStartSublist(&ds); + for (i = 0; fields[i] != NULL; i++) { + field = fields[i] + 1; + Tcl_DStringAppendElement(&ds, field); + } + Tcl_DStringEndSublist(&ds); + + while (xchat_list_next(ph, list)) { + + Tcl_DStringStartSublist(&ds); + + for (i = 0; fields[i] != NULL; i++) { + + field = fields[i] + 1; + + switch (fields[i][0]) { + case 's': + sattr = xchat_list_str(ph, list, (char *) field); + Tcl_DStringAppendElement(&ds, sattr); + break; + case 'i': + iattr = xchat_list_int(ph, list, (char *) field); + Tcl_DStringAppendElement(&ds, myitoa((long)iattr)); + break; + case 't': + t = xchat_list_time(ph, list, (char *) field); + Tcl_DStringAppendElement(&ds, myitoa((long)t)); + break; + case 'p': + sattr = xchat_list_str(ph, list, (char *) field); + if (strcmp(field, "context") == 0) { + ctx = (xchat_context *) sattr; + Tcl_DStringAppendElement(&ds, myitoa((long)ctx)); + } else + Tcl_DStringAppendElement(&ds, "*"); + break; + default: + Tcl_DStringAppendElement(&ds, "*"); + break; + } + } + + Tcl_DStringEndSublist(&ds); + + } + + xchat_list_free(ph, list); + + done: + + xchat_set_context(ph, origctx); + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +/* + * tcl_xchat_puts - stub for tcl puts command + * This is modified from the original internal "puts" command. It redirects + * stdout to the current context, while still allowing all normal puts features + */ + +static int tcl_xchat_puts(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + Tcl_Channel chan; + const char *string; + int newline; + const char *channelId = NULL; + int result; + int mode; + int trap_stdout = 0; + + switch (argc) { + + case 2: + string = argv[1]; + newline = 1; + trap_stdout = 1; + break; + + case 3: + if (strcmp(argv[1], "-nonewline") == 0) { + newline = 0; + trap_stdout = 1; + } else { + newline = 1; + channelId = argv[1]; + } + string = argv[2]; + break; + + case 4: + if (strcmp(argv[1], "-nonewline") == 0) { + channelId = argv[2]; + string = argv[3]; + } else { + if (strcmp(argv[3], "nonewline") != 0) { + Tcl_AppendResult(interp, "bad argument \"", argv[3], "\": should be \"nonewline\"", (char *) NULL); + return TCL_ERROR; + } + channelId = argv[1]; + string = argv[2]; + } + newline = 0; + break; + + default: + Tcl_AppendResult(interp, argv, "?-nonewline? ?channelId? string", NULL); + return TCL_ERROR; + } + + if (!trap_stdout && (strcmp(channelId, "stdout") == 0)) + trap_stdout = 1; + + if (trap_stdout) { + if (newline) + xchat_printf(ph, "%s\n", string); + else + xchat_print(ph, string); + return TCL_OK; + } + + chan = Tcl_GetChannel(interp, channelId, &mode); + if (chan == (Tcl_Channel) NULL) { + return TCL_ERROR; + } + if ((mode & TCL_WRITABLE) == 0) { + Tcl_AppendResult(interp, "channel \"", channelId, "\" wasn't opened for writing", (char *) NULL); + return TCL_ERROR; + } + + result = Tcl_Write(chan, string, strlen(string)); + if (result < 0) { + goto error; + } + if (newline != 0) { + result = Tcl_WriteChars(chan, "\n", 1); + if (result < 0) { + goto error; + } + } + return TCL_OK; + + error: + Tcl_AppendResult(interp, "error writing \"", channelId, "\": ", Tcl_PosixError(interp), (char *) NULL); + + return TCL_ERROR; +} + +static int tcl_print(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *origctx; + xchat_context *ctx = NULL; + const char *string = NULL; + + BADARGS(2, 4, " ?server|network|context? ?#channel|nick? text"); + + origctx = xchat_get_context(ph); + + switch (argc) { + case 2: + ctx = origctx; + break; + case 3: + ctx = xchat_smart_context(argv[1], NULL); + break; + case 4: + ctx = xchat_smart_context(argv[1], argv[2]); + break; + default:; + } + + CHECKCTX(ctx); + + string = argv[argc - 1]; + + xchat_set_context(ph, ctx); + xchat_print(ph, string); + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_setcontext(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *ctx = NULL; + + BADARGS(2, 2, " context"); + + ctx = xchat_smart_context(argv[1], NULL); + + CHECKCTX(ctx); + + xchat_set_context(ph, ctx); + + return TCL_OK; +} + +static int tcl_findcontext(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *ctx = NULL; + + BADARGS(1, 3, " ?server|network|context? ?channel?"); + + switch (argc) { + case 1: + ctx = xchat_find_context(ph, NULL, NULL); + break; + case 2: + ctx = xchat_smart_context(argv[1], NULL); + break; + case 3: + ctx = xchat_smart_context(argv[1], argv[2]); + break; + default:; + } + + CHECKCTX(ctx); + + Tcl_AppendResult(irp, myitoa((long)ctx), NULL); + + return TCL_OK; +} + +static int tcl_getcontext(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *ctx = NULL; + + BADARGS(1, 1, ""); + + ctx = xchat_get_context(ph); + + Tcl_AppendResult(irp, myitoa((long)ctx), NULL); + + return TCL_OK; +} + +static int tcl_channels(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + const char *server, *channel; + xchat_list *list; + Tcl_DString ds; + xchat_context *origctx; + xchat_context *ctx; + + origctx = xchat_get_context(ph); + + BADARGS(1, 2, " ?server|network|context?"); + + if (argc == 2) { + ctx = xchat_smart_context(argv[1], NULL); + CHECKCTX(ctx); + xchat_set_context(ph, ctx); + } + + server = (char *) xchat_get_info(ph, "server"); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "channels"); + + if (list != NULL) { + while (xchat_list_next(ph, list)) { + if (xchat_list_int(ph, list, "type") != 2) + continue; + if (strcasecmp(server, xchat_list_str(ph, list, "server")) != 0) + continue; + channel = xchat_list_str(ph, list, "channel"); + Tcl_DStringAppendElement(&ds, channel); + } + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_servers(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + const char *server; + xchat_list *list; + Tcl_DString ds; + + BADARGS(1, 1, ""); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "channels"); + + if (list != NULL) { + while (xchat_list_next(ph, list)) { + if (xchat_list_int(ph, list, "type") == 1) { + server = xchat_list_str(ph, list, "server"); + Tcl_DStringAppendElement(&ds, server); + } + } + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_queries(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + const char *server, *channel; + xchat_list *list; + Tcl_DString ds; + xchat_context *origctx; + xchat_context *ctx; + + origctx = xchat_get_context(ph); + + BADARGS(1, 2, " ?server|network|context?"); + + if (argc == 2) { + ctx = xchat_smart_context(argv[1], NULL); + CHECKCTX(ctx); + xchat_set_context(ph, ctx); + } + + server = (char *) xchat_get_info(ph, "server"); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "channels"); + + if (list != NULL) { + while (xchat_list_next(ph, list)) { + if (xchat_list_int(ph, list, "type") != 3) + continue; + if (strcasecmp(server, xchat_list_str(ph, list, "server")) != 0) + continue; + channel = xchat_list_str(ph, list, "channel"); + Tcl_DStringAppendElement(&ds, channel); + } + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_users(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *origctx, *ctx = NULL; + xchat_list *list; + Tcl_DString ds; + + BADARGS(1, 3, " ?server|network|context? ?channel?"); + + origctx = xchat_get_context(ph); + + switch (argc) { + case 1: + ctx = origctx; + break; + case 2: + ctx = xchat_smart_context(argv[1], NULL); + break; + case 3: + ctx = xchat_smart_context(argv[1], argv[2]); + break; + default:; + } + + CHECKCTX(ctx); + + xchat_set_context(ph, ctx); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "users"); + + if (list != NULL) { + + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, "nick"); + Tcl_DStringAppendElement(&ds, "host"); + Tcl_DStringAppendElement(&ds, "prefix"); + Tcl_DStringAppendElement(&ds, "away"); + Tcl_DStringAppendElement(&ds, "lasttalk"); + Tcl_DStringAppendElement(&ds, "selected"); + Tcl_DStringEndSublist(&ds); + + while (xchat_list_next(ph, list)) { + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "nick")); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "host")); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "prefix")); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "away"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_time(ph, list, "lasttalk"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "selected"))); + Tcl_DStringEndSublist(&ds); + } + + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_notifylist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_list *list; + Tcl_DString ds; + + BADARGS(1, 1, ""); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "notify"); + + if (list != NULL) { + + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, "nick"); + Tcl_DStringAppendElement(&ds, "flags"); + Tcl_DStringAppendElement(&ds, "on"); + Tcl_DStringAppendElement(&ds, "off"); + Tcl_DStringAppendElement(&ds, "seen"); + Tcl_DStringAppendElement(&ds, "networks"); + Tcl_DStringEndSublist(&ds); + + while (xchat_list_next(ph, list)) { + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "nick")); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "flags")); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_time(ph, list, "on"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_time(ph, list, "off"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_time(ph, list, "seen"))); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "networks")); + Tcl_DStringEndSublist(&ds); + } + + xchat_list_free(ph, list); + + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_chats(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_list *list; + Tcl_DString ds; + + BADARGS(1, 1, ""); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "dcc"); + + if (list != NULL) { + while (xchat_list_next(ph, list)) { + switch (xchat_list_int(ph, list, "type")) { + case 2: + case 3: + if (xchat_list_int(ph, list, "status") == 1) + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "nick")); + break; + } + } + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_ignores(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_list *list; + Tcl_DString ds; + int flags; + + BADARGS(1, 1, ""); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "ignore"); + + if (list != NULL) { + + while (xchat_list_next(ph, list)) { + Tcl_DStringStartSublist(&ds); + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "mask")); + Tcl_DStringStartSublist(&ds); + flags = xchat_list_int(ph, list, "flags"); + if (flags & 1) + Tcl_DStringAppendElement(&ds, "PRIVMSG"); + if (flags & 2) + Tcl_DStringAppendElement(&ds, "NOTICE"); + if (flags & 4) + Tcl_DStringAppendElement(&ds, "CHANNEL"); + if (flags & 8) + Tcl_DStringAppendElement(&ds, "CTCP"); + if (flags & 16) + Tcl_DStringAppendElement(&ds, "INVITE"); + if (flags & 32) + Tcl_DStringAppendElement(&ds, "UNIGNORE"); + if (flags & 64) + Tcl_DStringAppendElement(&ds, "NOSAVE"); + Tcl_DStringEndSublist(&ds); + Tcl_DStringEndSublist(&ds); + } + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + return TCL_OK; +} + +static int tcl_dcclist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_list *list; + Tcl_DString ds; + int dcctype; + + BADARGS(1, 1, ""); + + Tcl_DStringInit(&ds); + + list = xchat_list_get(ph, "dcc"); + + if (list != NULL) { + + while (xchat_list_next(ph, list)) { + Tcl_DStringStartSublist(&ds); + dcctype = xchat_list_int(ph, list, "type"); + switch (dcctype) { + case 0: + Tcl_DStringAppendElement(&ds, "filesend"); + break; + case 1: + Tcl_DStringAppendElement(&ds, "filerecv"); + break; + case 2: + Tcl_DStringAppendElement(&ds, "chatrecv"); + break; + case 3: + Tcl_DStringAppendElement(&ds, "chatsend"); + break; + } + switch (xchat_list_int(ph, list, "status")) { + case 0: + Tcl_DStringAppendElement(&ds, "queued"); + break; + case 1: + Tcl_DStringAppendElement(&ds, "active"); + break; + case 2: + Tcl_DStringAppendElement(&ds, "failed"); + break; + case 3: + Tcl_DStringAppendElement(&ds, "done"); + break; + case 4: + Tcl_DStringAppendElement(&ds, "connecting"); + break; + case 5: + Tcl_DStringAppendElement(&ds, "aborted"); + break; + } + + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "nick")); + + switch (dcctype) { + case 0: + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "file")); + break; + case 1: + Tcl_DStringAppendElement(&ds, (const char *) xchat_list_str(ph, list, "destfile")); + break; + } + + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "size"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "resume"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "pos"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "cps"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "address32"))); + Tcl_DStringAppendElement(&ds, myitoa((long)xchat_list_int(ph, list, "port"))); + Tcl_DStringEndSublist(&ds); + } + xchat_list_free(ph, list); + } + + Tcl_AppendResult(irp, ds.string, NULL); + + Tcl_DStringFree(&ds); + + return TCL_OK; +} + + +static int tcl_strip(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + char *new_text; + int flags = 1 | 2; + + BADARGS(2, 3, " text ?flags?"); + + if (argc == 3) { + if (Tcl_GetInt(irp, argv[2], &flags) != TCL_OK) + return TCL_ERROR; + } + + new_text = xchat_strip(ph, argv[1], -1, flags); + + if(new_text) { + Tcl_AppendResult(irp, new_text, NULL); + xchat_free(ph, new_text); + } + + return TCL_OK; +} + +static int tcl_topic(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + xchat_context *origctx, *ctx = NULL; + BADARGS(1, 3, " ?server|network|context? ?channel?"); + + origctx = xchat_get_context(ph); + + switch (argc) { + case 1: + ctx = origctx; + break; + case 2: + ctx = xchat_smart_context(argv[1], NULL); + break; + case 3: + ctx = xchat_smart_context(argv[1], argv[2]); + break; + default:; + } + + CHECKCTX(ctx); + + xchat_set_context(ph, ctx); + Tcl_AppendResult(irp, xchat_get_info(ph, "topic"), NULL); + xchat_set_context(ph, origctx); + + return TCL_OK; +} + +static int tcl_xchat_nickcmp(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + BADARGS(3, 3, " string1 string2"); + Tcl_AppendResult(irp, myitoa((long)xchat_nickcmp(ph, argv[1], argv[2])), NULL); + return TCL_OK; +} + +static int tcl_word(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int index; + + BADARGS(2, 2, " index"); + + if (Tcl_GetInt(irp, argv[1], &index) != TCL_OK) + return TCL_ERROR; + + if (!index || (index > 31)) + Tcl_AppendResult(interp, "", NULL); + else + Tcl_AppendResult(interp, complete[complete_level].word[index], NULL); + + return TCL_OK; +} + +static int tcl_word_eol(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]) +{ + int index; + + BADARGS(2, 2, " index"); + + if (Tcl_GetInt(irp, argv[1], &index) != TCL_OK) + return TCL_ERROR; + + if (!index || (index > 31)) + Tcl_AppendResult(interp, "", NULL); + else + Tcl_AppendResult(interp, complete[complete_level].word_eol[index], NULL); + + return TCL_OK; +} + +static int Command_Alias(char *word[], char *word_eol[], void *userdata) +{ + alias *aliasPtr; + Tcl_HashEntry *entry; + xchat_context *origctx; + int dummy; + char *string; + + if (complete_level == MAX_COMPLETES) + return XCHAT_EAT_NONE; + + complete_level++; + complete[complete_level].defresult = XCHAT_EAT_ALL; + complete[complete_level].result = XCHAT_EAT_NONE; + complete[complete_level].word = word; + complete[complete_level].word_eol = word_eol; + + string = StrDup(word[1], &dummy); + + Tcl_UtfToUpper(string); + + if ((entry = Tcl_FindHashEntry(&aliasTablePtr, string)) != NULL) { + aliasPtr = Tcl_GetHashValue(entry); + origctx = xchat_get_context(ph); + if (EvalInternalProc(aliasPtr->procPtr, 2, string, word_eol[2]) == TCL_ERROR) { + xchat_printf(ph, "\0039Tcl plugin\003\tERROR (alias %s) ", string); + NiceErrorInfo (); + } + xchat_set_context(ph, origctx); + } + + Tcl_Free(string); + + return complete[complete_level--].result; +} + +static int Null_Command_Alias(char *word[], char *word_eol[], void *userdata) +{ + alias *aliasPtr; + Tcl_HashEntry *entry; + xchat_context *origctx; + int dummy; + const char *channel; + char *string; + Tcl_DString ds; + static int recurse = 0; + + if (recurse) + return XCHAT_EAT_NONE; + + if (complete_level == MAX_COMPLETES) + return XCHAT_EAT_NONE; + + complete_level++; + complete[complete_level].defresult = XCHAT_EAT_ALL; + complete[complete_level].result = XCHAT_EAT_NONE; + complete[complete_level].word = word; + complete[complete_level].word_eol = word_eol; + + recurse++; + + channel = xchat_get_info(ph, "channel"); + Tcl_DStringInit(&ds); + Tcl_DStringAppend(&ds, "@", 1); + Tcl_DStringAppend(&ds, channel, strlen(channel)); + string = StrDup(ds.string, &dummy); + Tcl_DStringFree(&ds); + + Tcl_UtfToUpper(string); + + if ((entry = Tcl_FindHashEntry(&aliasTablePtr, string)) != NULL) { + aliasPtr = Tcl_GetHashValue(entry); + origctx = xchat_get_context(ph); + if (EvalInternalProc(aliasPtr->procPtr, 2, string, word_eol[1]) == TCL_ERROR) { + xchat_printf(ph, "\0039Tcl plugin\003\tERROR (alias %s) ", string); + NiceErrorInfo (); + } + xchat_set_context(ph, origctx); + } + + Tcl_Free(string); + + recurse--; + + return complete[complete_level--].result; +} + +static int Command_TCL(char *word[], char *word_eol[], void *userdata) +{ + const char *errorInfo; + + complete_level++; + complete[complete_level].word = word; + complete[complete_level].word_eol = word_eol; + + if (Tcl_Eval(interp, word_eol[2]) == TCL_ERROR) { + errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); + xchat_printf(ph, "\0039Tcl plugin\003\tERROR: %s ", errorInfo); + } else + xchat_printf(ph, "\0039Tcl plugin\003\tRESULT: %s ", Tcl_GetStringResult(interp)); + + complete_level--; + + return XCHAT_EAT_ALL; +} + +static int Command_Source(char *word[], char *word_eol[], void *userdata) +{ + const char *xchatdir; + Tcl_DString ds; + struct stat dummy; + int len; + const char *errorInfo; + + if (!strlen(word_eol[2])) + return XCHAT_EAT_NONE; + + complete_level++; + complete[complete_level].word = word; + complete[complete_level].word_eol = word_eol; + + len = strlen(word[2]); + + if (len > 4 && strcasecmp(".tcl", word[2] + len - 4) == 0) { + + xchatdir = xchat_get_info(ph, "xchatdir"); + + Tcl_DStringInit(&ds); + + if (stat(word_eol[2], &dummy) == 0) { + Tcl_DStringAppend(&ds, word_eol[2], strlen(word_eol[2])); + } else { + if (!strchr(word_eol[2], '/')) { + Tcl_DStringAppend(&ds, xchatdir, strlen(xchatdir)); + Tcl_DStringAppend(&ds, "/", 1); + Tcl_DStringAppend(&ds, word_eol[2], strlen(word_eol[2])); + } + } + + if (Tcl_EvalFile(interp, ds.string) == TCL_ERROR) { + errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); + xchat_printf(ph, "\0039Tcl plugin\003\tERROR: %s ", errorInfo); + } else + xchat_printf(ph, "\0039Tcl plugin\003\tSourced %s\n", ds.string); + + Tcl_DStringFree(&ds); + + complete_level--; + + return XCHAT_EAT_XCHAT; + + } else { + complete_level--; + return XCHAT_EAT_NONE; + } + +} + +static int Command_Reloadall(char *word[], char *word_eol[], void *userdata) +{ + Tcl_Plugin_DeInit(); + Tcl_Plugin_Init(); + + xchat_print(ph, "\0039Tcl plugin\003\tRehashed\n"); + + return XCHAT_EAT_ALL; +} + +static int TCL_Event_Handler(void *userdata) +{ + Tcl_DoOneEvent(TCL_DONT_WAIT); + do_timer(); + return 1; +} + +static void Tcl_Plugin_Init() +{ + int x; + const char *xchatdir; + + interp = Tcl_CreateInterp(); + + Tcl_FindExecutable(NULL); + + Tcl_Init(interp); + + nextprocid = 0x1000; + + Tcl_CreateCommand(interp, "alias", tcl_alias, NULL, NULL); + Tcl_CreateCommand(interp, "channels", tcl_channels, NULL, NULL); + Tcl_CreateCommand(interp, "chats", tcl_chats, NULL, NULL); + Tcl_CreateCommand(interp, "command", tcl_command, NULL, NULL); + Tcl_CreateCommand(interp, "complete", tcl_complete, NULL, NULL); + Tcl_CreateCommand(interp, "dcclist", tcl_dcclist, NULL, NULL); + Tcl_CreateCommand(interp, "notifylist", tcl_notifylist, NULL, NULL); + Tcl_CreateCommand(interp, "findcontext", tcl_findcontext, NULL, NULL); + Tcl_CreateCommand(interp, "getcontext", tcl_getcontext, NULL, NULL); + Tcl_CreateCommand(interp, "getinfo", tcl_getinfo, NULL, NULL); + Tcl_CreateCommand(interp, "getlist", tcl_getlist, NULL, NULL); + Tcl_CreateCommand(interp, "ignores", tcl_ignores, NULL, NULL); + Tcl_CreateCommand(interp, "killtimer", tcl_killtimer, NULL, NULL); + Tcl_CreateCommand(interp, "me", tcl_me, NULL, NULL); + Tcl_CreateCommand(interp, "on", tcl_on, NULL, NULL); + Tcl_CreateCommand(interp, "off", tcl_off, NULL, NULL); + Tcl_CreateCommand(interp, "nickcmp", tcl_xchat_nickcmp, NULL, NULL); + Tcl_CreateCommand(interp, "print", tcl_print, NULL, NULL); + Tcl_CreateCommand(interp, "prefs", tcl_prefs, NULL, NULL); + Tcl_CreateCommand(interp, "::puts", tcl_xchat_puts, NULL, NULL); + Tcl_CreateCommand(interp, "queries", tcl_queries, NULL, NULL); + Tcl_CreateCommand(interp, "raw", tcl_raw, NULL, NULL); + Tcl_CreateCommand(interp, "servers", tcl_servers, NULL, NULL); + Tcl_CreateCommand(interp, "setcontext", tcl_setcontext, NULL, NULL); + Tcl_CreateCommand(interp, "strip", tcl_strip, NULL, NULL); + Tcl_CreateCommand(interp, "timer", tcl_timer, NULL, NULL); + Tcl_CreateCommand(interp, "timerexists", tcl_timerexists, NULL, NULL); + Tcl_CreateCommand(interp, "timers", tcl_timers, NULL, NULL); + Tcl_CreateCommand(interp, "topic", tcl_topic, NULL, NULL); + Tcl_CreateCommand(interp, "users", tcl_users, NULL, NULL); + Tcl_CreateCommand(interp, "word", tcl_word, NULL, NULL); + Tcl_CreateCommand(interp, "word_eol", tcl_word_eol, NULL, NULL); + + Tcl_InitHashTable(&cmdTablePtr, TCL_STRING_KEYS); + Tcl_InitHashTable(&aliasTablePtr, TCL_STRING_KEYS); + + bzero(timers, sizeof(timers)); + nexttimerid = 0; + nexttimerindex = 0; + + for (x = 0; x < XC_SIZE; x++) + xc[x].hook = NULL; + + xchatdir = xchat_get_info(ph, "xchatdir"); + + if (Tcl_Eval(interp, unknown) == TCL_ERROR) { + xchat_printf(ph, "Error sourcing internal 'unknown' (%s)\n", Tcl_GetStringResult(interp)); + } + + if (Tcl_Eval(interp, inlinetcl) == TCL_ERROR) { + xchat_printf(ph, "Error sourcing internal 'inlinetcl' (%s)\n", Tcl_GetStringResult(interp)); + } + + if (Tcl_Eval(interp, sourcedirs) == TCL_ERROR) { + xchat_printf(ph, "Error sourcing internal 'sourcedirs' (%s)\n", Tcl_GetStringResult(interp)); + } + +} + +static void Tcl_Plugin_DeInit() +{ + int x; + char *procPtr; + alias *aliasPtr; + Tcl_HashEntry *entry; + Tcl_HashSearch search; + + /* Be sure to free all the memory for ON and ALIAS entries */ + + entry = Tcl_FirstHashEntry(&cmdTablePtr, &search); + while (entry != NULL) { + procPtr = Tcl_GetHashValue(entry); + Tcl_Free(procPtr); + entry = Tcl_NextHashEntry(&search); + } + + Tcl_DeleteHashTable(&cmdTablePtr); + + entry = Tcl_FirstHashEntry(&aliasTablePtr, &search); + while (entry != NULL) { + aliasPtr = Tcl_GetHashValue(entry); + Tcl_Free(aliasPtr->procPtr); + if (aliasPtr->hook) + xchat_unhook(ph, aliasPtr->hook); + Tcl_Free((char *) aliasPtr); + entry = Tcl_NextHashEntry(&search); + } + + Tcl_DeleteHashTable(&aliasTablePtr); + + for (x = 1; x < MAX_TIMERS; x++) { + if (timers[x].timerid) { + timers[x].timerid = 0; + if (timers[x].procPtr != NULL) + Tcl_Free(timers[x].procPtr); + timers[x].procPtr = NULL; + break; + } + } + + for (x = 0; x < XC_SIZE; x++) { + if (xc[x].hook != NULL) { + xchat_unhook(ph, xc[x].hook); + xc[x].hook = NULL; + } + } + + Tcl_DeleteInterp(interp); +} + +static void banner() +{ + xchat_printf(ph, "Tcl plugin for XChat - Version %s\n", VERSION); + xchat_print(ph, "Copyright 2002-2005 Daniel P. Stasinski\n"); + xchat_print(ph, "http://www.scriptkitties.com/tclplugin/\n"); +} + +int xchat_plugin_init(xchat_plugin * plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg) +{ +#ifdef WIN32 + HINSTANCE lib; +#endif + + strncpy(VERSION, &RCSID[19], 5); + + ph = plugin_handle; + +#ifdef WIN32 + lib = LoadLibraryA(TCL_DLL); + if (!lib) { + xchat_print(ph, "You must have ActiveTCL installed in order to run Tcl scripts.\n" "http://aspn.activestate.com/ASPN/Tcl/\n" "Make sure Tcl's bin directory is in your PATH.\n\n"); + return 0; + } + FreeLibrary(lib); +#endif + + if (initialized != 0) { + banner(); + xchat_print(ph, "Tcl plugin already loaded"); + reinit_tried++; + return 0; + } + initialized = 1; + + *plugin_name = "Tcl"; + *plugin_desc = "Tcl scripting interface"; + *plugin_version = VERSION; + + Tcl_Plugin_Init(); + + raw_line_hook = xchat_hook_server(ph, "RAW LINE", XCHAT_PRI_NORM, Server_raw_line, NULL); + Command_TCL_hook = xchat_hook_command(ph, "tcl", XCHAT_PRI_NORM, Command_TCL, 0, 0); + Command_Source_hook = xchat_hook_command(ph, "source", XCHAT_PRI_NORM, Command_Source, 0, 0); + Command_Reload_hook = xchat_hook_command(ph, "reloadall", XCHAT_PRI_NORM, Command_Reloadall, 0, 0); + Command_Load_hook = xchat_hook_command(ph, "LOAD", XCHAT_PRI_NORM, Command_Source, 0, 0); + Event_Handler_hook = xchat_hook_timer(ph, 100, TCL_Event_Handler, 0); + Null_Command_hook = xchat_hook_command(ph, "", XCHAT_PRI_NORM, Null_Command_Alias, "", 0); + + banner(); + xchat_print(ph, "Tcl interface loaded\n"); + + return 1; /* return 1 for success */ +} + +int xchat_plugin_deinit() +{ + if (reinit_tried) { + reinit_tried--; + return 1; + } + + xchat_unhook(ph, raw_line_hook); + xchat_unhook(ph, Command_TCL_hook); + xchat_unhook(ph, Command_Source_hook); + xchat_unhook(ph, Command_Reload_hook); + xchat_unhook(ph, Command_Load_hook); + xchat_unhook(ph, Event_Handler_hook); + xchat_unhook(ph, Null_Command_hook); + + Tcl_Plugin_DeInit(); + + xchat_print(ph, "Tcl interface unloaded\n"); + initialized = 0; + + return 1; +} + +void xchat_plugin_get_info(char **name, char **desc, char **version, void **reserved) +{ + strncpy(VERSION, &RCSID[19], 5); + *name = "tclplugin"; + *desc = "Tcl plugin for XChat"; + *version = VERSION; + if (reserved) + *reserved = NULL; +} + diff --git a/plugins/tcl/tclplugin.h b/plugins/tcl/tclplugin.h new file mode 100644 index 00000000..075c28f8 --- /dev/null +++ b/plugins/tcl/tclplugin.h @@ -0,0 +1,98 @@ +/*************************************************************************** + tclplugin.h - TCL plugin header file + ------------------------------------------------- + begin : Sat Nov 9 17:31:20 MST 2002 + copyright : Copyright 2002-2010 Daniel P. Stasinski + email : daniel@avenues.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#define BADARGS(nl,nh,example) \ + if ((argc<(nl)) || (argc>(nh))) { \ + Tcl_AppendResult(irp,"wrong # args: should be \"",argv[0], \ + (example),"\"",NULL); \ + return TCL_ERROR; \ + } + +#define CHECKCTX(ctx) \ + if (ctx == NULL) { \ + Tcl_AppendResult(irp, "No such server/channel/nick", NULL); \ + return TCL_ERROR; \ + } + +typedef struct { + char *procPtr; + xchat_hook *hook; +} alias; + +typedef struct { + int timerid; + time_t timestamp; + char *procPtr; + int count; + int seconds; +} timer; + +typedef struct { + int result; + int defresult; + char **word; + char **word_eol; +} t_complete; + +#define MAX_TIMERS 512 +#define MAX_COMPLETES 128 + +static char *StrDup(const char *string, int *length); +static char *myitoa(long value); +static xchat_context *xchat_smart_context(const char *arg1, const char *arg2); +static void queue_nexttimer(); +static int insert_timer(int seconds, int count, const char *script); +static void do_timer(); +static int Server_raw_line(char *word[], char *word_eol[], void *userdata); +static int Print_Hook(char *word[], void *userdata); +static int tcl_timerexists(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_killtimer(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_timers(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_timer(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_on(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_off(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_alias(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_complete(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_raw(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_command(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_xchat_puts(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_print(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_channels(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_servers(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_queries(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_users(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_chats(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_ignores(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_dcclist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_me(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_xchat_nickcmp(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_strip(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_topic(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_word(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_word_eol(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int tcl_notifylist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]); +static int Command_Alias(char *word[], char *word_eol[], void *userdata); +static int Null_Command_Alias(char *word[], char *word_eol[], void *userdata); +static int Command_TCL(char *word[], char *word_eol[], void *userdata); +static int Command_Source(char *word[], char *word_eol[], void *userdata); +static int Command_Reload(char *word[], char *word_eol[], void *userdata); +static int TCL_Event_Handler(void *userdata); +static void Tcl_Plugin_Init(); +static void Tcl_Plugin_DeInit(); +static void banner(); +int xchat_plugin_init(xchat_plugin * plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg); +int xchat_plugin_deinit(); diff --git a/plugins/xchat-plugin.h b/plugins/xchat-plugin.h new file mode 100644 index 00000000..30b19295 --- /dev/null +++ b/plugins/xchat-plugin.h @@ -0,0 +1,334 @@ +/* You can distribute this header with your plugins for easy compilation */ +#ifndef XCHAT_PLUGIN_H +#define XCHAT_PLUGIN_H + +#include + +#define XCHAT_IFACE_MAJOR 1 +#define XCHAT_IFACE_MINOR 9 +#define XCHAT_IFACE_MICRO 11 +#define XCHAT_IFACE_VERSION ((XCHAT_IFACE_MAJOR * 10000) + \ + (XCHAT_IFACE_MINOR * 100) + \ + (XCHAT_IFACE_MICRO)) + +#define XCHAT_PRI_HIGHEST 127 +#define XCHAT_PRI_HIGH 64 +#define XCHAT_PRI_NORM 0 +#define XCHAT_PRI_LOW (-64) +#define XCHAT_PRI_LOWEST (-128) + +#define XCHAT_FD_READ 1 +#define XCHAT_FD_WRITE 2 +#define XCHAT_FD_EXCEPTION 4 +#define XCHAT_FD_NOTSOCKET 8 + +#define XCHAT_EAT_NONE 0 /* pass it on through! */ +#define XCHAT_EAT_XCHAT 1 /* don't let xchat see this event */ +#define XCHAT_EAT_PLUGIN 2 /* don't let other plugins see this event */ +#define XCHAT_EAT_ALL (XCHAT_EAT_XCHAT|XCHAT_EAT_PLUGIN) /* don't let anything see this event */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xchat_plugin xchat_plugin; +typedef struct _xchat_list xchat_list; +typedef struct _xchat_hook xchat_hook; +#ifndef PLUGIN_C +typedef struct _xchat_context xchat_context; +#endif + +#ifndef PLUGIN_C +struct _xchat_plugin +{ + /* these are only used on win32 */ + xchat_hook *(*xchat_hook_command) (xchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], void *user_data), + const char *help_text, + void *userdata); + xchat_hook *(*xchat_hook_server) (xchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], void *user_data), + void *userdata); + xchat_hook *(*xchat_hook_print) (xchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], void *user_data), + void *userdata); + xchat_hook *(*xchat_hook_timer) (xchat_plugin *ph, + int timeout, + int (*callback) (void *user_data), + void *userdata); + xchat_hook *(*xchat_hook_fd) (xchat_plugin *ph, + int fd, + int flags, + int (*callback) (int fd, int flags, void *user_data), + void *userdata); + void *(*xchat_unhook) (xchat_plugin *ph, + xchat_hook *hook); + void (*xchat_print) (xchat_plugin *ph, + const char *text); + void (*xchat_printf) (xchat_plugin *ph, + const char *format, ...); + void (*xchat_command) (xchat_plugin *ph, + const char *command); + void (*xchat_commandf) (xchat_plugin *ph, + const char *format, ...); + int (*xchat_nickcmp) (xchat_plugin *ph, + const char *s1, + const char *s2); + int (*xchat_set_context) (xchat_plugin *ph, + xchat_context *ctx); + xchat_context *(*xchat_find_context) (xchat_plugin *ph, + const char *servname, + const char *channel); + xchat_context *(*xchat_get_context) (xchat_plugin *ph); + const char *(*xchat_get_info) (xchat_plugin *ph, + const char *id); + int (*xchat_get_prefs) (xchat_plugin *ph, + const char *name, + const char **string, + int *integer); + xchat_list * (*xchat_list_get) (xchat_plugin *ph, + const char *name); + void (*xchat_list_free) (xchat_plugin *ph, + xchat_list *xlist); + const char * const * (*xchat_list_fields) (xchat_plugin *ph, + const char *name); + int (*xchat_list_next) (xchat_plugin *ph, + xchat_list *xlist); + const char * (*xchat_list_str) (xchat_plugin *ph, + xchat_list *xlist, + const char *name); + int (*xchat_list_int) (xchat_plugin *ph, + xchat_list *xlist, + const char *name); + void * (*xchat_plugingui_add) (xchat_plugin *ph, + const char *filename, + const char *name, + const char *desc, + const char *version, + char *reserved); + void (*xchat_plugingui_remove) (xchat_plugin *ph, + void *handle); + int (*xchat_emit_print) (xchat_plugin *ph, + const char *event_name, ...); + int (*xchat_read_fd) (xchat_plugin *ph, + void *src, + char *buf, + int *len); + time_t (*xchat_list_time) (xchat_plugin *ph, + xchat_list *xlist, + const char *name); + char *(*xchat_gettext) (xchat_plugin *ph, + const char *msgid); + void (*xchat_send_modes) (xchat_plugin *ph, + const char **targets, + int ntargets, + int modes_per_line, + char sign, + char mode); + char *(*xchat_strip) (xchat_plugin *ph, + const char *str, + int len, + int flags); + void (*xchat_free) (xchat_plugin *ph, + void *ptr); +}; +#endif + + +xchat_hook * +xchat_hook_command (xchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], void *user_data), + const char *help_text, + void *userdata); + +xchat_hook * +xchat_hook_server (xchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], void *user_data), + void *userdata); + +xchat_hook * +xchat_hook_print (xchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], void *user_data), + void *userdata); + +xchat_hook * +xchat_hook_timer (xchat_plugin *ph, + int timeout, + int (*callback) (void *user_data), + void *userdata); + +xchat_hook * +xchat_hook_fd (xchat_plugin *ph, + int fd, + int flags, + int (*callback) (int fd, int flags, void *user_data), + void *userdata); + +void * +xchat_unhook (xchat_plugin *ph, + xchat_hook *hook); + +void +xchat_print (xchat_plugin *ph, + const char *text); + +void +xchat_printf (xchat_plugin *ph, + const char *format, ...); + +void +xchat_command (xchat_plugin *ph, + const char *command); + +void +xchat_commandf (xchat_plugin *ph, + const char *format, ...); + +int +xchat_nickcmp (xchat_plugin *ph, + const char *s1, + const char *s2); + +int +xchat_set_context (xchat_plugin *ph, + xchat_context *ctx); + +xchat_context * +xchat_find_context (xchat_plugin *ph, + const char *servname, + const char *channel); + +xchat_context * +xchat_get_context (xchat_plugin *ph); + +const char * +xchat_get_info (xchat_plugin *ph, + const char *id); + +int +xchat_get_prefs (xchat_plugin *ph, + const char *name, + const char **string, + int *integer); + +xchat_list * +xchat_list_get (xchat_plugin *ph, + const char *name); + +void +xchat_list_free (xchat_plugin *ph, + xchat_list *xlist); + +const char * const * +xchat_list_fields (xchat_plugin *ph, + const char *name); + +int +xchat_list_next (xchat_plugin *ph, + xchat_list *xlist); + +const char * +xchat_list_str (xchat_plugin *ph, + xchat_list *xlist, + const char *name); + +int +xchat_list_int (xchat_plugin *ph, + xchat_list *xlist, + const char *name); + +time_t +xchat_list_time (xchat_plugin *ph, + xchat_list *xlist, + const char *name); + +void * +xchat_plugingui_add (xchat_plugin *ph, + const char *filename, + const char *name, + const char *desc, + const char *version, + char *reserved); + +void +xchat_plugingui_remove (xchat_plugin *ph, + void *handle); + +int +xchat_emit_print (xchat_plugin *ph, + const char *event_name, ...); + +char * +xchat_gettext (xchat_plugin *ph, + const char *msgid); + +void +xchat_send_modes (xchat_plugin *ph, + const char **targets, + int ntargets, + int modes_per_line, + char sign, + char mode); + +char * +xchat_strip (xchat_plugin *ph, + const char *str, + int len, + int flags); + +void +xchat_free (xchat_plugin *ph, + void *ptr); + +#if !defined(PLUGIN_C) && defined(WIN32) +#ifndef XCHAT_PLUGIN_HANDLE +#define XCHAT_PLUGIN_HANDLE (ph) +#endif +#define xchat_hook_command ((XCHAT_PLUGIN_HANDLE)->xchat_hook_command) +#define xchat_hook_server ((XCHAT_PLUGIN_HANDLE)->xchat_hook_server) +#define xchat_hook_print ((XCHAT_PLUGIN_HANDLE)->xchat_hook_print) +#define xchat_hook_timer ((XCHAT_PLUGIN_HANDLE)->xchat_hook_timer) +#define xchat_hook_fd ((XCHAT_PLUGIN_HANDLE)->xchat_hook_fd) +#define xchat_unhook ((XCHAT_PLUGIN_HANDLE)->xchat_unhook) +#define xchat_print ((XCHAT_PLUGIN_HANDLE)->xchat_print) +#define xchat_printf ((XCHAT_PLUGIN_HANDLE)->xchat_printf) +#define xchat_command ((XCHAT_PLUGIN_HANDLE)->xchat_command) +#define xchat_commandf ((XCHAT_PLUGIN_HANDLE)->xchat_commandf) +#define xchat_nickcmp ((XCHAT_PLUGIN_HANDLE)->xchat_nickcmp) +#define xchat_set_context ((XCHAT_PLUGIN_HANDLE)->xchat_set_context) +#define xchat_find_context ((XCHAT_PLUGIN_HANDLE)->xchat_find_context) +#define xchat_get_context ((XCHAT_PLUGIN_HANDLE)->xchat_get_context) +#define xchat_get_info ((XCHAT_PLUGIN_HANDLE)->xchat_get_info) +#define xchat_get_prefs ((XCHAT_PLUGIN_HANDLE)->xchat_get_prefs) +#define xchat_list_get ((XCHAT_PLUGIN_HANDLE)->xchat_list_get) +#define xchat_list_free ((XCHAT_PLUGIN_HANDLE)->xchat_list_free) +#define xchat_list_fields ((XCHAT_PLUGIN_HANDLE)->xchat_list_fields) +#define xchat_list_str ((XCHAT_PLUGIN_HANDLE)->xchat_list_str) +#define xchat_list_int ((XCHAT_PLUGIN_HANDLE)->xchat_list_int) +#define xchat_list_time ((XCHAT_PLUGIN_HANDLE)->xchat_list_time) +#define xchat_list_next ((XCHAT_PLUGIN_HANDLE)->xchat_list_next) +#define xchat_plugingui_add ((XCHAT_PLUGIN_HANDLE)->xchat_plugingui_add) +#define xchat_plugingui_remove ((XCHAT_PLUGIN_HANDLE)->xchat_plugingui_remove) +#define xchat_emit_print ((XCHAT_PLUGIN_HANDLE)->xchat_emit_print) +#define xchat_gettext ((XCHAT_PLUGIN_HANDLE)->xchat_gettext) +#define xchat_send_modes ((XCHAT_PLUGIN_HANDLE)->xchat_send_modes) +#define xchat_strip ((XCHAT_PLUGIN_HANDLE)->xchat_strip) +#define xchat_free ((XCHAT_PLUGIN_HANDLE)->xchat_free) +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/plugins/xdcc/Makefile.am b/plugins/xdcc/Makefile.am new file mode 100644 index 00000000..24f93f16 --- /dev/null +++ b/plugins/xdcc/Makefile.am @@ -0,0 +1,7 @@ +libdir = $(xchatdir)/plugins + +lib_LTLIBRARIES = xdcc.la +xdcc_la_SOURCES = xdcc.c +xdcc_la_LDFLAGS = -avoid-version -module +INCLUDES = $(COMMON_CFLAGS) -I$(srcdir)/.. + diff --git a/plugins/xdcc/xdcc.c b/plugins/xdcc/xdcc.c new file mode 100644 index 00000000..147a3c33 --- /dev/null +++ b/plugins/xdcc/xdcc.c @@ -0,0 +1,327 @@ +/* xchat 2.0 plugin: simple xdcc server example */ + +#include +#include +#include +#include +#include + +#include "xchat-plugin.h" + +static xchat_plugin *ph; /* plugin handle */ + +static int xdcc_on = 1; +static int xdcc_slots = 3; +static GSList *file_list = 0; + +typedef struct fileoffer +{ + char *file; + char *fullpath; + char *desc; + int downloads; +} fileoffer; + + +/* find the number of open dccs */ + +static int num_open_dccs(void) +{ + xchat_list *list; + int num = 0; + + list = xchat_list_get(ph, "dcc"); + if(!list) + return 0; + + while(xchat_list_next(ph, list)) + { + /* check only ACTIVE dccs */ + if(xchat_list_int(ph, list, "status") == 1) + { + /* check only SEND dccs */ + if(xchat_list_int(ph, list, "type") == 0) + num++; + } + } + + xchat_list_free(ph, list); + + return num; +} + +static void xdcc_get(char *nick, char *host, char *arg) +{ + int num; + GSList *list; + fileoffer *offer; + + if(arg[0] == '#') + arg++; + + num = atoi(arg); + list = g_slist_nth(file_list, num - 1); + if(!list) + { + xchat_commandf(ph, "quote NOTICE %s :No such file number #%d!", nick, num); + return; + } + + if(num_open_dccs() >= xdcc_slots) + { + xchat_commandf(ph, "quote NOTICE %s :All slots full. Try again later.", nick); + return; + } + + offer = (fileoffer *) list->data; + offer->downloads++; + xchat_commandf(ph, "quote NOTICE %s :Sending offer #%d %s", nick, num, offer->file); + xchat_commandf(ph, "dcc send %s %s", nick, offer->fullpath); +} + +static void xdcc_del(char *name) +{ + GSList *list; + fileoffer *offer; + + list = file_list; + while(list) + { + offer = (fileoffer *) list->data; + if(strcasecmp(name, offer->file) == 0) + { + file_list = g_slist_remove(file_list, offer); + xchat_printf(ph, "%s [%s] removed.\n", offer->file, offer->fullpath); + free(offer->file); + free(offer->desc); + free(offer->fullpath); + free(offer); + return; + } + list = list->next; + } +} + +static void xdcc_add(char *name, char *fullpath, char *desc, int dl) +{ + fileoffer *offer; + + offer = (fileoffer *) malloc(sizeof(fileoffer)); + offer->file = strdup(name); + offer->desc = strdup(desc); + offer->fullpath = strdup(fullpath); + offer->downloads = dl; + + file_list = g_slist_append(file_list, offer); +} + +static void xdcc_list(char *nick, char *host, char *arg, char *cmd) +{ + GSList *list; + int i = 0; + fileoffer *offer; + + xchat_commandf(ph, "%s %s :XDCC List:", cmd, nick); + list = file_list; + while(list) + { + i++; + offer = (fileoffer *) list->data; + xchat_commandf(ph, "%s %s :[#%d] %s - %s [%d dl]", cmd, + nick, i, offer->file, offer->desc, offer->downloads); + list = list->next; + } + + if(i == 0) + xchat_commandf(ph, "%s %s :- list empty.", cmd, nick); + else + xchat_commandf(ph, "%s %s :%d files listed.", cmd, nick, i); +} + +static int xdcc_command(char *word[], char *word_eol[], void *userdata) +{ + if(strcasecmp(word[2], "ADD") == 0) + { + if(!word_eol[5][0]) + xchat_print(ph, "Syntax: /XDCC ADD \n"); + else + { + if(access(word[4], R_OK) == 0) + { + xdcc_add(word[3], word[4], word_eol[5], 0); + xchat_printf(ph, "%s [%s] added.\n", word[3], word[4]); + } + else + xchat_printf(ph, "Cannot read %s\n", word[4]); + } + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "DEL") == 0) + { + xdcc_del(word[3]); + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "SLOTS") == 0) + { + if(word[3][0]) + { + xdcc_slots = atoi(word[3]); + xchat_printf(ph, "XDCC slots set to %d\n", xdcc_slots); + } else + { + xchat_printf(ph, "XDCC slots: %d\n", xdcc_slots); + } + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "ON") == 0) + { + xdcc_on = TRUE; + xchat_print(ph, "XDCC now ON\n"); + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "LIST") == 0) + { + xdcc_list("", "", "", "echo"); + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "OFF") == 0) + { + xdcc_on = FALSE; + xchat_print(ph, "XDCC now OFF\n"); + return XCHAT_EAT_XCHAT; + } + + xchat_print(ph, "Syntax: XDCC ADD \n" + " XDCC DEL \n" + " XDCC SLOTS \n" + " XDCC LIST\n" + " XDCC ON\n" + " XDCC OFF\n\n"); + + return XCHAT_EAT_XCHAT; +} + +static void xdcc_remote(char *from, char *msg) +{ + char *ex, *nick, *host; + + ex = strchr(from, '!'); + if(!ex) + return; + ex[0] = 0; + nick = from; + host = ex + 1; + + if(xdcc_on == 0) + { + xchat_commandf(ph, "notice %s XDCC is turned OFF!", from); + return; + } + + if(strncasecmp(msg, "LIST", 4) == 0) + xdcc_list(nick, host, msg + 4, "quote notice"); + else if(strncasecmp(msg, "GET ", 4) == 0) + xdcc_get(nick, host, msg + 4); + else + xchat_commandf(ph, "notice %s Unknown XDCC command!", from); +} + +static int ctcp_cb(char *word[], void *userdata) +{ + char *msg = word[1]; + char *from = word[2]; + + if(strncasecmp(msg, "XDCC ", 5) == 0) + xdcc_remote(from, msg + 5); + + return XCHAT_EAT_NONE; +} + +static void xdcc_save(void) +{ + char buf[512]; + FILE *fp; + GSList *list; + fileoffer *offer; + + snprintf(buf, sizeof(buf), "%s/xdcclist.conf", xchat_get_info(ph, "xchatdir")); + + fp = fopen(buf, "w"); + if(!fp) + return; + + list = file_list; + while(list) + { + offer = (fileoffer *) list->data; + fprintf(fp, "%s\n%s\n%s\n%d\n\n\n", offer->file, offer->fullpath, + offer->desc, offer->downloads); + list = list->next; + } + + fclose(fp); +} + +static void xdcc_load(void) +{ + char buf[512]; + char file[128]; + char path[128]; + char desc[128]; + char dl[128]; + FILE *fp; + + snprintf(buf, sizeof(buf), "%s/xdcclist.conf", xchat_get_info(ph, "xchatdir")); + + fp = fopen(buf, "r"); + if(!fp) + return; + + while(fgets(file, sizeof(file), fp)) + { + file[strlen(file)-1] = 0; + fgets(path, sizeof(path), fp); + path[strlen(path)-1] = 0; + fgets(desc, sizeof(desc), fp); + desc[strlen(desc)-1] = 0; + fgets(dl, sizeof(dl), fp); + dl[strlen(dl)-1] = 0; + fgets(buf, sizeof(buf), fp); + fgets(buf, sizeof(buf), fp); + xdcc_add(file, path, desc, atoi(dl)); + } + + fclose(fp); +} + +int xchat_plugin_deinit(void) +{ + xdcc_save(); + xchat_print(ph, "XDCC List saved\n"); + return 1; +} + +int xchat_plugin_init(xchat_plugin *plugin_handle, + char **plugin_name, char **plugin_desc, char **plugin_version, + char *arg) +{ + ph = plugin_handle; + + *plugin_name = "XDCC"; + *plugin_desc = "Very simple XDCC server"; + *plugin_version = "0.1"; + + xchat_hook_command(ph, "XDCC", XCHAT_PRI_NORM, xdcc_command, 0, 0); + xchat_hook_print(ph, "CTCP Generic", XCHAT_PRI_NORM, ctcp_cb, 0); + xchat_hook_print(ph, "CTCP Generic to Channel", XCHAT_PRI_NORM, ctcp_cb, 0); + + xdcc_load(); + xchat_print(ph, "XDCC loaded. Type /XDCC for help.\n"); + + return 1; +} diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 00000000..771c7f21 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,7 @@ +DOMAIN = $(PACKAGE) +subdir = po +top_builddir = .. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ +COPYRIGHT_HOLDER = +MSGID_BUGS_ADDRESS = www.xchat.org +EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 00000000..f0f06df2 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,37 @@ +src/common/cfgfiles.c +src/common/dcc.c +src/common/ignore.c +src/common/notify.c +src/common/outbound.c +src/common/plugin.c +src/common/server.c +src/common/servlist.c +src/common/textevents.h +src/common/text.c +src/common/util.c +src/common/xchat.c +src/common/dbus/dbus-client.c +src/common/dbus/dbus-plugin.c +src/fe-gtk/about.c +src/fe-gtk/ascii.c +src/fe-gtk/banlist.c +src/fe-gtk/chanlist.c +src/fe-gtk/dccgui.c +src/fe-gtk/editlist.c +src/fe-gtk/fe-gtk.c +src/fe-gtk/fkeys.c +src/fe-gtk/gtkutil.c +src/fe-gtk/ignoregui.c +src/fe-gtk/joind.c +src/fe-gtk/maingui.c +src/fe-gtk/menu.c +src/fe-gtk/notifygui.c +src/fe-gtk/plugin-tray.c +src/fe-gtk/plugingui.c +src/fe-gtk/rawlog.c +src/fe-gtk/search.c +src/fe-gtk/servlistgui.c +src/fe-gtk/setup.c +src/fe-gtk/textgui.c +src/fe-gtk/urlgrab.c +src/fe-gtk/userlistgui.c diff --git a/po/am.po b/po/am.po new file mode 100644 index 00000000..dcd90f5b --- /dev/null +++ b/po/am.po @@ -0,0 +1,4818 @@ +# Translations into the Amharic Language. +# Copyright (C) 2002 Free Software Foundation, Inc. +# This file is distributed under the same license as the xchat package. +# Ge'ez Frontier Foundation , 2002. +# +# +msgid "" +msgstr "" +"Project-Id-Version: xchat \n" +"Report-Msgid-Bugs-To: www.xchat.org\n" +"POT-Creation-Date: 2004-01-01 23:38+1100\n" +"PO-Revision-Date: 2003-01-30 10:06+EDT\n" +"Last-Translator: Ge'ez Frontier Foundation \n" +"Language-Team: Amharic \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/common/cfgfiles.c:340 +msgid "Cannot create ~/.xchat2" +msgstr "" + +#: src/common/cfgfiles.c:634 +msgid "I'm busy" +msgstr "" + +#: src/common/cfgfiles.c:635 +#, fuzzy +msgid "Leaving" +msgstr "ላትቪያ" + +#: src/common/cfgfiles.c:679 +msgid "" +"* Running IRC as root is stupid! You should\n" +" create a User Account and use that to login.\n" +msgstr "" + +#: src/common/dcc.c:56 +msgid "Waiting" +msgstr "" + +#: src/common/dcc.c:57 +msgid "Active" +msgstr "" + +#: src/common/dcc.c:58 +msgid "Failed" +msgstr "" + +#: src/common/dcc.c:59 +msgid "Done" +msgstr "ጨርሷል" + +#: src/common/dcc.c:60 +msgid "Connect" +msgstr "አገናኝ" + +#: src/common/dcc.c:61 +msgid "Aborted" +msgstr "ውድቅ ሆኗል" + +#: src/common/dcc.c:1269 +#, c-format +msgid "Cannot access %s\n" +msgstr "" + +#: src/common/dcc.c:1801 +msgid "No active DCCs\n" +msgstr "" + +#: src/common/ignore.c:120 src/common/ignore.c:124 src/common/ignore.c:128 +#: src/common/ignore.c:132 src/common/ignore.c:136 src/common/ignore.c:140 +#: src/common/ignore.c:144 +msgid "YES " +msgstr "አዎ " + +#: src/common/ignore.c:122 src/common/ignore.c:126 src/common/ignore.c:130 +#: src/common/ignore.c:134 src/common/ignore.c:138 src/common/ignore.c:142 +#: src/common/ignore.c:146 +msgid "NO " +msgstr "አይ " + +#: src/common/ignore.c:373 +#, c-format +msgid "You are being CTCP flooded from %s, ignoring %s\n" +msgstr "" + +#: src/common/ignore.c:398 +#, c-format +msgid "You are being MSG flooded from %s, setting autodialog OFF.\n" +msgstr "" + +#: src/common/notify.c:400 +#, c-format +msgid " %-20s online\n" +msgstr "" + +#: src/common/notify.c:402 +#, c-format +msgid " %-20s offline\n" +msgstr "" + +#: src/common/outbound.c:70 +msgid "No channel joined. Try /join #\n" +msgstr "" + +#: src/common/outbound.c:76 +msgid "Not connected. Try /server []\n" +msgstr "" + +#: src/common/outbound.c:1356 +msgid "I need /bin/sh to run!\n" +msgstr "" + +#: src/common/outbound.c:1588 +msgid "" +"\n" +"Commands Available:\n" +"\n" +" " +msgstr "" + +#: src/common/outbound.c:1623 +msgid "" +"\n" +"\n" +"Type /HELP for more information, or /HELP -l\n" +"\n" +msgstr "" + +#: src/common/outbound.c:1624 +msgid "" +"User defined commands:\n" +"\n" +" " +msgstr "" + +#: src/common/outbound.c:1716 +#, c-format +msgid "Unknown arg '%s' ignored." +msgstr "" + +#: src/common/outbound.c:2426 +msgid "No such plugin found.\n" +msgstr "" + +#: src/common/outbound.c:2431 src/fe-gtk/plugingui.c:182 +msgid "That plugin is refusing to unload.\n" +msgstr "" + +#: src/common/outbound.c:2576 +msgid "ADDBUTTON , adds a button under the user-list" +msgstr "" + +#: src/common/outbound.c:2578 +msgid "ALLCHAN , sends a command to all channels you're in" +msgstr "" + +#: src/common/outbound.c:2580 +msgid "ALLSERV , sends a command to all servers you're in" +msgstr "" + +#: src/common/outbound.c:2581 +msgid "AWAY [], sets you away" +msgstr "" + +#: src/common/outbound.c:2583 +msgid "" +"BAN [], bans everyone matching the mask from the current " +"channel. If they are already on the channel this doesn't kick them (needs " +"chanop)" +msgstr "" + +#: src/common/outbound.c:2585 +msgid "CLEAR, Clears the current text window" +msgstr "" + +#: src/common/outbound.c:2586 +msgid "CLOSE, Closes the current window/tab" +msgstr "" + +#: src/common/outbound.c:2589 +msgid "COUNTRY , finds a country code, eg: au = australia" +msgstr "" + +#: src/common/outbound.c:2591 +msgid "" +"CTCP , send the CTCP message to nick, common messages are " +"VERSION and USERINFO" +msgstr "" + +#: src/common/outbound.c:2593 +msgid "CYCLE, parts current channel and immediately rejoins" +msgstr "" + +#: src/common/outbound.c:2595 +msgid "" +"\n" +"DCC GET - accept an offered file\n" +"DCC SEND [-maxcps=#] [file] - send a file to someone\n" +"DCC LIST - show DCC list\n" +"DCC CHAT - offer DCC CHAT to someone\n" +"DCC CLOSE example:\n" +" /dcc close send johnsmith file.tar.gz" +msgstr "" + +#: src/common/outbound.c:2605 +msgid "" +"DEHOP , removes chanhalf-op status from the nick on the current " +"channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2607 +msgid "DELBUTTON , deletes a button from under the user-list" +msgstr "" + +#: src/common/outbound.c:2609 +msgid "" +"DEOP , removes chanop status from the nick on the current channel " +"(needs chanop)" +msgstr "" + +#: src/common/outbound.c:2611 +msgid "" +"DEVOICE , removes voice status from the nick on the current channel " +"(needs chanop)" +msgstr "" + +#: src/common/outbound.c:2612 +msgid "DISCON, Disconnects from server" +msgstr "" + +#: src/common/outbound.c:2613 +msgid "DNS , Finds a users IP number" +msgstr "" + +#: src/common/outbound.c:2614 +msgid "ECHO , Prints text locally" +msgstr "" + +#: src/common/outbound.c:2617 +msgid "" +"EXEC [-o] , runs the command. If -o flag is used then output is " +"sent to current channel, else is printed to current text box" +msgstr "" + +#: src/common/outbound.c:2619 +msgid "EXECCONT, sends the process SIGCONT" +msgstr "" + +#: src/common/outbound.c:2622 +msgid "" +"EXECKILL [-9], kills a running exec in the current session. If -9 is given " +"the process is SIGKILL'ed" +msgstr "" + +#: src/common/outbound.c:2624 +msgid "EXECSTOP, sends the process SIGSTOP" +msgstr "" + +#: src/common/outbound.c:2625 +msgid "EXECWRITE, sends data to the processes stdin" +msgstr "" + +#: src/common/outbound.c:2629 +msgid "FLUSHQ, flushes the current server's send queue" +msgstr "" + +#: src/common/outbound.c:2631 +msgid "GATE [], proxies through a host, port defaults to 23" +msgstr "" + +#: src/common/outbound.c:2637 +msgid "HOP , gives chanhalf-op status to the nick (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2639 +msgid "" +"IGNORE \n" +" mask - host mask to ignore, eg: *!*@*.aol.com\n" +" types - types of data to ignore, one or all of:\n" +" PRIV, CHAN, NOTI, CTCP, DCC, INVI, ALL\n" +" options - NOSAVE, QUIET" +msgstr "" + +#: src/common/outbound.c:2646 +msgid "" +"INVITE [], invites someone to a channel, by default the " +"current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2647 +msgid "JOIN , joins the channel" +msgstr "" + +#: src/common/outbound.c:2649 +msgid "KICK , kicks the nick from the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2651 +msgid "" +"KICKBAN , bans then kicks the nick from the current channel (needs " +"chanop)" +msgstr "" + +#: src/common/outbound.c:2654 +msgid "LAGCHECK, forces a new lag check" +msgstr "" + +#: src/common/outbound.c:2656 +msgid "LASTLOG , searches for a string in the buffer" +msgstr "" + +#: src/common/outbound.c:2658 +msgid "LOAD , loads a plugin or script" +msgstr "" + +#: src/common/outbound.c:2661 +msgid "" +"MDEHOP, Mass deop's all chanhalf-ops in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2663 +msgid "MDEOP, Mass deop's all chanops in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2665 +msgid "" +"ME , sends the action to the current channel (actions are written in " +"the 3rd person, like /me jumps)" +msgstr "" + +#: src/common/outbound.c:2667 +msgid "" +"MKICK, Mass kicks everyone except you in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2669 +msgid "MOP, Mass op's all users in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2670 +msgid "MSG , sends a private message" +msgstr "" + +#: src/common/outbound.c:2673 +msgid "NAMES, Lists the nicks on the current channel" +msgstr "" + +#: src/common/outbound.c:2675 +msgid "NCTCP , Sends a CTCP notice" +msgstr "" + +#: src/common/outbound.c:2676 +msgid "NEWSERVER []" +msgstr "" + +#: src/common/outbound.c:2677 +msgid "NICK , sets your nick" +msgstr "" + +#: src/common/outbound.c:2680 +msgid "" +"NOTICE , sends a notice. Notices are a type of " +"message that should be auto reacted to" +msgstr "" + +#: src/common/outbound.c:2682 +msgid "NOTIFY [], lists your notify list or adds someone to it" +msgstr "" + +#: src/common/outbound.c:2684 +msgid "OP , gives chanop status to the nick (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2686 +msgid "" +"PART [] [], leaves the channel, by default the current one" +msgstr "" + +#: src/common/outbound.c:2688 +msgid "PING , CTCP pings nick or channel" +msgstr "" + +#: src/common/outbound.c:2690 +msgid "QUERY , opens up a new privmsg window to someone" +msgstr "" + +#: src/common/outbound.c:2692 +msgid "QUIT [], disconnects from the current server" +msgstr "" + +#: src/common/outbound.c:2694 +msgid "QUOTE , sends the text in raw form to the server" +msgstr "" + +#: src/common/outbound.c:2697 +msgid "" +"RECONNECT [-ssl] [] [] [], Can be called just as /" +"RECONNECT to reconnect to the current server or with /RECONNECT ALL to " +"reconnect to all the open servers" +msgstr "" + +#: src/common/outbound.c:2700 +msgid "" +"RECONNECT [] [] [], Can be called just as /RECONNECT " +"to reconnect to the current server or with /RECONNECT ALL to reconnect to " +"all the open servers" +msgstr "" + +#: src/common/outbound.c:2702 +msgid "" +"RECV , send raw data to xchat, as if it was received from the irc " +"server" +msgstr "" + +#: src/common/outbound.c:2705 +msgid "SAY , sends the text to the object in the current window" +msgstr "" + +#: src/common/outbound.c:2708 +msgid "SERVCHAN [-ssl] , connects and joins a channel" +msgstr "" + +#: src/common/outbound.c:2711 +msgid "SERVCHAN , connects and joins a channel" +msgstr "" + +#: src/common/outbound.c:2715 +msgid "" +"SERVER [-ssl] [] [], connects to a server, the " +"default port is 6667 for normal connections, and 9999 for ssl connections" +msgstr "" + +#: src/common/outbound.c:2718 +msgid "" +"SERVER [] [], connects to a server, the default port " +"is 6667" +msgstr "" + +#: src/common/outbound.c:2720 +msgid "SET []" +msgstr "" + +#: src/common/outbound.c:2723 +msgid "" +"TOPIC [], sets the topic if one is given, else shows the current topic" +msgstr "" + +#: src/common/outbound.c:2725 +msgid "UNBAN [...], unbans the specified masks." +msgstr "" + +#: src/common/outbound.c:2726 +msgid "UNIGNORE [QUIET]" +msgstr "" + +#: src/common/outbound.c:2727 +msgid "UNLOAD , unloads a plugin or script" +msgstr "" + +#: src/common/outbound.c:2730 +msgid "VOICE , gives voice status to someone (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2732 +msgid "WALLCHAN , writes the message to all channels" +msgstr "" + +#: src/common/outbound.c:2734 +msgid "" +"WALLCHOP , sends the message to all chanops on the current channel" +msgstr "" + +#: src/common/outbound.c:2767 +#, c-format +msgid "Usage: %s\n" +msgstr "አጠቃቀም፦ %s\n" + +#: src/common/outbound.c:2772 +msgid "" +"\n" +"No help available on that command.\n" +msgstr "" + +#: src/common/outbound.c:2778 +msgid "No such command.\n" +msgstr "" + +#: src/common/outbound.c:3102 +msgid "Bad arguments for user command.\n" +msgstr "" + +#: src/common/outbound.c:3266 +msgid "Too many recursive usercommands, aborting." +msgstr "" + +#: src/common/outbound.c:3339 +msgid "Unknown Command. Try /help\n" +msgstr "" + +#: src/common/plugin.c:349 src/common/plugin.c:379 +msgid "No xchat_plugin_init symbol; is this really an xchat plugin?" +msgstr "" + +#: src/common/server.c:887 +#, c-format +msgid "" +"Cannot resolve hostname %s\n" +"Check your IP Settings!\n" +msgstr "" + +#: src/common/server.c:892 +msgid "Proxy traversal failed.\n" +msgstr "" + +#: src/common/servlist.c:633 +#, c-format +msgid "Cycling to next server in %s...\n" +msgstr "" + +#: src/common/servlist.c:973 +#, c-format +msgid "" +"Warning: \"%s\" character set is unknown. No conversion will be applied for " +"network %s." +msgstr "" + +#: src/common/textevents.h:6 +msgid "-%C10-%C11-%O$t$1 added to notify list." +msgstr "" + +#: src/common/textevents.h:9 +msgid "-%C10-%C11-%O$t$1 Banlist: %C3$4 %C4$2 %C5$3%O" +msgstr "" + +#: src/common/textevents.h:12 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(You are banned)." +msgstr "" + +#: src/common/textevents.h:15 +msgid "-%C10-%C11-%O$t$1 is now known as $2" +msgstr "" + +#: src/common/textevents.h:18 +msgid "%C13*%O$t$1%O $2%O" +msgstr "" + +#: src/common/textevents.h:21 +msgid "%C13*%O$t%C8%B$1%B%O $2%O" +msgstr "" + +#: src/common/textevents.h:24 +msgid "-%C10-%C11-%O$t$1 sets ban on $2" +msgstr "" + +#: src/common/textevents.h:27 +msgid "-%C10-%C11-%O$tChannel $1 created on $2" +msgstr "" + +#: src/common/textevents.h:30 +msgid "" +"-%C10-%C11-%O$t%C11$1%O removes channel half-operator status from %C11$2" +msgstr "" + +#: src/common/textevents.h:33 +msgid "-%C10-%C11-%O$t%C11$1%O removes channel operator status from %C11$2" +msgstr "" + +#: src/common/textevents.h:36 +msgid "-%C10-%C11-%O$t%C11$1%O removes voice from %C11$2" +msgstr "" + +#: src/common/textevents.h:39 +msgid "-%C10-%C11-%O$t$1 sets exempt on $2" +msgstr "" + +#: src/common/textevents.h:42 +msgid "-%C10-%C11-%O$t%C11$1%O gives channel half-operator status to %C11$2" +msgstr "" + +#: src/common/textevents.h:45 +msgid "-%C10-%C11-%O$t$1 sets invite on $2" +msgstr "" + +#: src/common/textevents.h:48 +msgid "%UChannel Users Topic%O" +msgstr "" + +#: src/common/textevents.h:51 src/common/textevents.h:297 +msgid "%C2<%O$1%C2>%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:54 +msgid "-%C10-%C11-%O$t$1 sets mode $2$3 $4" +msgstr "" + +#: src/common/textevents.h:57 +msgid "-%C10-%C11-%O$tChannel $1 modes: $2" +msgstr "" + +#: src/common/textevents.h:60 +msgid "%C2<%C8%B$1%B%C2>%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:63 +msgid "%C12-%C13$1/$2%C12-%O$t$3%O" +msgstr "" + +#: src/common/textevents.h:66 +msgid "-%C10-%C11-%O$t%C11$1%O gives channel operator status to %C11$2" +msgstr "" + +#: src/common/textevents.h:69 +msgid "-%C10-%C11-%O$t$1 removes exempt on $2" +msgstr "" + +#: src/common/textevents.h:72 +msgid "-%C10-%C11-%O$t$1 removes invite on $2" +msgstr "" + +#: src/common/textevents.h:75 +msgid "-%C10-%C11-%O$t$1 removes channel keyword" +msgstr "" + +#: src/common/textevents.h:78 +msgid "-%C10-%C11-%O$t$1 removes user limit" +msgstr "" + +#: src/common/textevents.h:81 +msgid "-%C10-%C11-%O$t$1 sets channel keyword to $2" +msgstr "" + +#: src/common/textevents.h:84 +msgid "-%C10-%C11-%O$t$1 sets channel limit to $2" +msgstr "" + +#: src/common/textevents.h:87 +msgid "-%C10-%C11-%O$t$1 removes ban on $2" +msgstr "" + +#: src/common/textevents.h:90 +msgid "-%C10-%C11-%O$t%C11$1%O gives voice to %C11$2" +msgstr "" + +#: src/common/textevents.h:93 +msgid "-%C10-%C11-%O$tConnected. Now logging in.." +msgstr "" + +#: src/common/textevents.h:96 +msgid "-%C10-%C11-%O$tConnecting to %C11$1 %C14(%C11$2%C14)%C port %C11$3%C.." +msgstr "" + +#: src/common/textevents.h:99 +msgid "-%C10-%C11-%O$tConnection failed. Error: $1" +msgstr "" + +#: src/common/textevents.h:102 +msgid "-%C10-%C11-%O$tReceived a CTCP $1 from $2" +msgstr "" + +#: src/common/textevents.h:105 +msgid "-%C10-%C11-%O$tReceived a CTCP $1 from $2 (to $3)" +msgstr "" + +#: src/common/textevents.h:108 +msgid "%C3>%O$1%C3<%O$tCTCP $2%O" +msgstr "" + +#: src/common/textevents.h:111 +msgid "-%C10-%C11-%O$tReceived a CTCP Sound $1 from $2" +msgstr "" + +#: src/common/textevents.h:114 +msgid "-%C10-%C11-%O$tDCC CHAT to %C11$1%O aborted." +msgstr "" + +#: src/common/textevents.h:117 +msgid "" +"-%C10-%C11-%O$tDCC CHAT connection established to %C11$1 %C14[%O$2%C14]%O" +msgstr "" + +#: src/common/textevents.h:120 +msgid "-%C10-%C11-%O$tDCC CHAT to %C11$1%O lost. $4." +msgstr "" + +#: src/common/textevents.h:123 +msgid "-%C10-%C11-%O$tReceived a DCC CHAT offer from $1" +msgstr "" + +#: src/common/textevents.h:126 +msgid "-%C10-%C11-%O$tOffering DCC CHAT to $1" +msgstr "" + +#: src/common/textevents.h:129 +msgid "-%C10-%C11-%O$tAlready offering CHAT to $1" +msgstr "" + +#: src/common/textevents.h:132 +msgid "-%C10-%C11-%O$tDCC $1 connect attempt to %C11$2%O failed (err=$3)." +msgstr "" + +#: src/common/textevents.h:135 +msgid "-%C10-%C11-%O$tReceived '$1%O' from $2" +msgstr "" + +#: src/common/textevents.h:138 +msgid "" +"%C8,2 Type To/From Status Size Pos File %O%010%B%" +"C9----------------------------------------------------%O" +msgstr "" + +#: src/common/textevents.h:141 +msgid "" +"-%C10-%C11-%O$tReceived a malformed DCC request from %C11$1%O.%010-%C10-%C11-" +"%O$tContents of packet: $2" +msgstr "" + +#: src/common/textevents.h:144 +msgid "-%C10-%C11-%O$tOffering %C11$1 %Cto %C11$2%O" +msgstr "" + +#: src/common/textevents.h:147 +msgid "-%C10-%C11-%O$tNo such DCC offer." +msgstr "" + +#: src/common/textevents.h:150 +msgid "-%C10-%C11-%O$tDCC RECV %C11$2%O to %C11$1%O aborted." +msgstr "" + +#: src/common/textevents.h:153 +msgid "" +"-%C10-%C11-%O$tDCC RECV %C11$1%O from %C11$3%O complete %C14[%C11$4%O cps%" +"C14]%O." +msgstr "" + +#: src/common/textevents.h:156 +msgid "" +"-%C10-%C11-%O$tDCC RECV connection established to %C11$1 %C14[%O$2%C14]%O" +msgstr "" + +#: src/common/textevents.h:159 +msgid "-%C10-%C11-%O$tDCC RECV %C11$1%O from %C11$3%O failed. $4." +msgstr "" + +#: src/common/textevents.h:162 +msgid "-%C10-%C11-%O$tDCC RECV: Cannot open $1 for writing ($2)." +msgstr "" + +#: src/common/textevents.h:165 +msgid "" +"-%C10-%C11-%O$tThe file %C11$1%C already exists, saving it as %C11$2%O " +"instead." +msgstr "" + +#: src/common/textevents.h:168 +msgid "-%C10-%C11-%O$t%C11$1 %Chas requested to resume %C11$2 %Cfrom %C11$3%C." +msgstr "" + +#: src/common/textevents.h:171 +msgid "-%C10-%C11-%O$tDCC SEND %C11$2%O to %C11$1%O aborted." +msgstr "" + +#: src/common/textevents.h:174 +msgid "" +"-%C10-%C11-%O$tDCC SEND %C11$1%O to %C11$2%O complete %C14[%C11$3%O cps%C14]%" +"O." +msgstr "" + +#: src/common/textevents.h:177 +msgid "" +"-%C10-%C11-%O$tDCC SEND connection established to %C11$1 %C14[%O$2%C14]%O" +msgstr "" + +#: src/common/textevents.h:180 +msgid "-%C10-%C11-%O$tDCC SEND %C11$1%O to %C11$2%O failed. $3" +msgstr "" + +#: src/common/textevents.h:183 +msgid "-%C10-%C11-%O$t%C11$1 %Chas offered %C11$2 %C(%C11$3 %Cbytes)" +msgstr "" + +#: src/common/textevents.h:186 +msgid "-%C10-%C11-%O$tDCC $1 %C11$2 %Cto %C11$3 %Cstalled - aborting." +msgstr "" + +#: src/common/textevents.h:189 +msgid "-%C10-%C11-%O$tDCC $1 %C11$2 %Cto %C11$3 %Ctimed out - aborting." +msgstr "" + +#: src/common/textevents.h:192 +msgid "-%C10-%C11-%O$t$1 deleted from notify list." +msgstr "" + +#: src/common/textevents.h:195 +msgid "-%C10-%C11-%O$tDisconnected ($1)." +msgstr "" + +#: src/common/textevents.h:198 +msgid "-%C10-%C11-%O$tFound your IP: [$1]" +msgstr "" + +#: src/common/textevents.h:201 +msgid "$1$t$2" +msgstr "" + +#: src/common/textevents.h:204 +msgid "%O%C11$1%O added to ignore list." +msgstr "" + +#: src/common/textevents.h:207 +msgid "Ignore on %C11$1%O changed." +msgstr "" + +#: src/common/textevents.h:210 +msgid "%C08,02 %O" +msgstr "" + +#: src/common/textevents.h:213 +msgid "%C08,02 Hostmask PRIV NOTI CHAN CTCP DCC INVI UNIG %O" +msgstr "" + +#: src/common/textevents.h:216 +msgid "%O%C11$1%O removed from ignore list." +msgstr "" + +#: src/common/textevents.h:219 +msgid " Ignore list is empty." +msgstr "" + +#: src/common/textevents.h:222 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(Channel is invite only)." +msgstr "" + +#: src/common/textevents.h:225 +msgid "-%C10-%C11-%O$tYou have been invited to %C11$1%C by %C11$2%C (%C11$3%C)" +msgstr "" + +#: src/common/textevents.h:228 +msgid "-%C10-%C11>%O$t%B$1%B %C14(%C10$3%C14)%C has joined $2" +msgstr "" + +#: src/common/textevents.h:231 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(Requires keyword)." +msgstr "" + +#: src/common/textevents.h:234 +msgid "<%C10-%C11-%O$t$1 has kicked $2 from $3 ($4%O)" +msgstr "" + +#: src/common/textevents.h:237 +msgid "-%C10-%C11-%O$tYou have been killed by $1 ($2%O)" +msgstr "" + +#: src/common/textevents.h:240 src/common/textevents.h:264 +msgid "%C3>%O$1%C3<%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:243 src/common/textevents.h:318 +#: src/common/textevents.h:324 src/common/textevents.h:327 +msgid "-%C10-%C11-%O$t$1%O" +msgstr "" + +#: src/common/textevents.h:246 +msgid "-%C10-%C11-%O$tMOTD Skipped." +msgstr "" + +#: src/common/textevents.h:249 +msgid "-%C10-%C11-%O$t$1 already in use. Retrying with $2.." +msgstr "" + +#: src/common/textevents.h:252 +msgid "-%C10-%C11-%O$tNickname already in use. Use /NICK to try another." +msgstr "" + +#: src/common/textevents.h:255 +msgid "-%C10-%C11-%O$tNo such DCC." +msgstr "" + +#: src/common/textevents.h:258 +msgid "-%C10-%C11-%O$tNo process is currently running" +msgstr "" + +#: src/common/textevents.h:261 +msgid "%C12-%C13$1%C12-%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:267 +msgid "-%C10-%C11-%O$tNotify list is empty." +msgstr "" + +#: src/common/textevents.h:270 +msgid "%C08,02 %B-- Notify List --------------- %O" +msgstr "" + +#: src/common/textevents.h:273 +msgid "-%C10-%C11-%O$t$1 users in notify list." +msgstr "" + +#: src/common/textevents.h:276 +msgid "-%C10-%C11-%O$tNotify: $1 is offline ($2)." +msgstr "" + +#: src/common/textevents.h:279 +msgid "-%C10-%C11-%O$tNotify: $1 is online ($2)." +msgstr "" + +#: src/common/textevents.h:282 +msgid "<%C10-%C11-%O$t$1 %C14(%O$2%C14)%C has left $3" +msgstr "" + +#: src/common/textevents.h:285 +msgid "<%C10-%C11-%O$t$1 %C14(%O$2%C14)%C has left $3 %C14(%O$4%C14)%O" +msgstr "" + +#: src/common/textevents.h:288 +msgid "-%C10-%C11-%O$tPing reply from $1 : $2 second(s)" +msgstr "" + +#: src/common/textevents.h:291 +msgid "-%C10-%C11-%O$tNo ping reply for $1 seconds, disconnecting." +msgstr "" + +#: src/common/textevents.h:294 +msgid "%C12*%C13$1%C12*$t%O$2%O" +msgstr "" + +#: src/common/textevents.h:300 +msgid "-%C10-%C11-%O$tA process is already running" +msgstr "" + +#: src/common/textevents.h:303 +msgid "<%C10-%C11-%O$t$1 has quit %C14(%O$2%O%C14)%O" +msgstr "" + +#: src/common/textevents.h:306 +msgid "-%C10-%C11-%O$t$1 sets modes%B %C14[%O$2%B%C14]%O" +msgstr "" + +#: src/common/textevents.h:309 +msgid "%C12-%C13$1/Wallops%C12-%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:312 +msgid "-%C10-%C11-%O$tLooking up IP number for%C11 $1%O.." +msgstr "" + +#: src/common/textevents.h:315 +msgid "-%C10-%C11-%O$tConnected." +msgstr "" + +#: src/common/textevents.h:321 +msgid "-%C10-%C11-%O$tLooking up %C11$1%C.." +msgstr "" + +#: src/common/textevents.h:330 +msgid "-%C10-%C11-%O$tStopped previous connection attempt (pid=$1)" +msgstr "" + +#: src/common/textevents.h:333 +msgid "-%C10-%C11-%O$tTopic for %C11$1%C is %C11$2%O" +msgstr "" + +#: src/common/textevents.h:336 +msgid "-%C10-%C11-%O$tTopic for %C11$1%C set by %C11$2%C at %C11$3%O" +msgstr "" + +#: src/common/textevents.h:339 +msgid "-%C10-%C11-%O$t$1 has changed the topic to: $2%O" +msgstr "" + +#: src/common/textevents.h:342 +msgid "-%C10-%C11-%O$tUnknown host. Maybe you misspelled it?" +msgstr "" + +#: src/common/textevents.h:345 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(User limit reached)." +msgstr "" + +#: src/common/textevents.h:348 +msgid "-%C10-%C11-%O$t%C11Users on $1:%C $2" +msgstr "" + +#: src/common/textevents.h:351 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %Cis away %C14(%O$2%O%C14)" +msgstr "" + +#: src/common/textevents.h:354 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%C $2" +msgstr "" + +#: src/common/textevents.h:357 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %CEnd of WHOIS list." +msgstr "" + +#: src/common/textevents.h:360 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %O$2" +msgstr "" + +#: src/common/textevents.h:363 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %O$2 %C11$3%O" +msgstr "" + +#: src/common/textevents.h:366 +msgid "" +"-%C10-%C11-%O$t%C12[%O$1%C12] %Oreal user@host %C11$2%O, real IP %C11$3%O" +msgstr "" + +#: src/common/textevents.h:369 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%O idle %C11$2%O" +msgstr "" + +#: src/common/textevents.h:372 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%O idle %C11$2%O, signon: %C11$3%O" +msgstr "" + +#: src/common/textevents.h:375 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %C14(%O$2@$3%C14) %O: $4%O" +msgstr "" + +#: src/common/textevents.h:378 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%O $2" +msgstr "" + +#: src/common/textevents.h:381 +msgid "-%C10-%C11>%O$t%BYou%B are now talking on %C11$2%O" +msgstr "" + +#: src/common/textevents.h:384 +msgid "-%C10-%C11-%O$tYou have left channel $3" +msgstr "" + +#: src/common/textevents.h:387 +msgid "-%C10-%C11-%O$tYou have left channel $3 %C14(%O$4%C14)%O" +msgstr "" + +#: src/common/textevents.h:390 +msgid "-%C10-%C11-%O$tYou have been kicked from $2 by $3 ($4%O)" +msgstr "" + +#: src/common/textevents.h:393 +msgid "-%C10-%C11-%O$tYou're inviting %C11$1%C to %C11$2%C (%C11$3%C)" +msgstr "" + +#: src/common/textevents.h:396 +msgid "%C6<%O$1%C6>%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:399 +msgid "-%C10-%C11-%O$tYou are now known as $2" +msgstr "" + +#: src/common/text.c:304 +#, c-format +msgid "**** ENDING LOGGING AT %s\n" +msgstr "" + +#: src/common/text.c:421 +#, c-format +msgid "**** BEGIN LOGGING AT %s\n" +msgstr "" + +#: src/common/text.c:440 +#, c-format +msgid "" +"* Can't open log file(s) for writing. Check the\n" +" permissions on %s/xchatlogs" +msgstr "" + +#: src/common/text.c:651 +#, fuzzy +msgid "Left message" +msgstr "መልእክቱ" + +#: src/common/text.c:652 +#, fuzzy +msgid "Right message" +msgstr "መልእክቱ" + +#: src/common/text.c:656 +msgid "The nick of the joining person" +msgstr "" + +#: src/common/text.c:657 +msgid "The channel being joined" +msgstr "" + +#: src/common/text.c:658 src/common/text.c:702 src/common/text.c:758 +msgid "The host of the person" +msgstr "" + +#: src/common/text.c:662 src/common/text.c:667 src/common/text.c:673 +#: src/common/text.c:740 src/common/text.c:864 src/common/text.c:871 +#: src/common/text.c:876 src/common/text.c:881 src/common/text.c:886 +#: src/common/text.c:892 src/common/text.c:897 src/common/text.c:901 +#: src/common/text.c:906 src/common/text.c:912 src/common/text.c:958 +#: src/common/text.c:967 src/common/text.c:972 src/common/text.c:977 +#: src/common/text.c:986 src/common/text.c:997 src/common/text.c:1004 +#: src/common/text.c:1010 src/common/text.c:1015 src/common/text.c:1020 +#: src/common/text.c:1027 src/common/text.c:1033 src/common/text.c:1039 +#: src/common/text.c:1044 src/common/text.c:1049 src/common/text.c:1053 +#: src/common/text.c:1059 src/common/text.c:1067 src/common/text.c:1101 +#: src/common/text.c:1106 +msgid "Nickname" +msgstr "ቅጽል ስም" + +#: src/common/text.c:663 +msgid "The action" +msgstr "" + +#: src/common/text.c:668 +msgid "The text" +msgstr "ጽሑፉ" + +#: src/common/text.c:669 +msgid "Mode char" +msgstr "" + +#: src/common/text.c:674 src/common/text.c:730 src/common/text.c:736 +#: src/common/text.c:741 +msgid "The message" +msgstr "መልእክቱ" + +#: src/common/text.c:678 src/common/text.c:745 +msgid "Old nickname" +msgstr "አሮጌ ቅጽል ስም" + +#: src/common/text.c:679 src/common/text.c:746 +msgid "New nickname" +msgstr "አዲስ ቅጽል ስም" + +#: src/common/text.c:683 +msgid "Nick of person who changed the topic" +msgstr "" + +#: src/common/text.c:684 src/common/text.c:690 src/fe-gtk/chanlist.c:599 +#: src/fe-gtk/chanlist.c:700 +msgid "Topic" +msgstr "ጉዳዩ" + +#: src/common/text.c:685 src/common/text.c:689 src/common/text.c:1121 +#: src/fe-gtk/chanlist.c:597 src/fe-gtk/chanlist.c:691 +#: src/fe-gtk/ignoregui.c:175 +msgid "Channel" +msgstr "ጣቢያ" + +#: src/common/text.c:694 src/common/text.c:752 +msgid "The nickname of the kicker" +msgstr "" + +#: src/common/text.c:695 src/common/text.c:750 +msgid "The person being kicked" +msgstr "" + +#: src/common/text.c:696 src/common/text.c:703 src/common/text.c:707 +#: src/common/text.c:712 src/common/text.c:751 src/common/text.c:759 +msgid "The channel" +msgstr "ጣቢያው ሰዓቱ" + +#: src/common/text.c:697 src/common/text.c:753 src/common/text.c:760 +msgid "The reason" +msgstr "" + +#: src/common/text.c:701 src/common/text.c:757 +msgid "The nick of the person leaving" +msgstr "" + +#: src/common/text.c:708 src/common/text.c:714 +msgid "The time" +msgstr "" + +#: src/common/text.c:713 +msgid "The creator" +msgstr "" + +#: src/common/text.c:718 +msgid "Nick" +msgstr "ቅጽል" + +#: src/common/text.c:719 src/common/text.c:973 +msgid "Reason" +msgstr "" + +#: src/common/text.c:720 src/common/text.c:866 src/common/text.c:948 +msgid "Host" +msgstr "እንግዳ ተቀባይ" + +#: src/common/text.c:724 src/common/text.c:729 src/common/text.c:734 +msgid "Who it's from" +msgstr "" + +#: src/common/text.c:725 +msgid "The time in x.x format (see below)" +msgstr "" + +#: src/common/text.c:735 src/common/text.c:776 +msgid "The Channel it's going to" +msgstr "" + +#: src/common/text.c:764 +msgid "The sound" +msgstr "ድምፁ" + +#: src/common/text.c:765 src/common/text.c:770 src/common/text.c:775 +msgid "The nick of the person" +msgstr "" + +#: src/common/text.c:769 src/common/text.c:774 +msgid "The CTCP event" +msgstr "" + +#: src/common/text.c:780 +msgid "The nick of the person who set the key" +msgstr "" + +#: src/common/text.c:781 +msgid "The key" +msgstr "ቁልፉ" + +#: src/common/text.c:785 +msgid "The nick of the person who set the limit" +msgstr "" + +#: src/common/text.c:786 +msgid "The limit" +msgstr "" + +#: src/common/text.c:790 +msgid "The nick of the person who did the op'ing" +msgstr "" + +#: src/common/text.c:791 +msgid "The nick of the person who has been op'ed" +msgstr "" + +#: src/common/text.c:795 +msgid "The nick of the person who has been halfop'ed" +msgstr "" + +#: src/common/text.c:796 +msgid "The nick of the person who did the halfop'ing" +msgstr "" + +#: src/common/text.c:800 +msgid "The nick of the person who did the voice'ing" +msgstr "" + +#: src/common/text.c:801 +msgid "The nick of the person who has been voice'ed" +msgstr "" + +#: src/common/text.c:805 +msgid "The nick of the person who did the banning" +msgstr "" + +#: src/common/text.c:806 src/common/text.c:833 +msgid "The ban mask" +msgstr "" + +#: src/common/text.c:810 +msgid "The nick who removed the key" +msgstr "" + +#: src/common/text.c:814 +msgid "The nick who removed the limit" +msgstr "" + +#: src/common/text.c:818 +msgid "The nick of the person of did the deop'ing" +msgstr "" + +#: src/common/text.c:819 +msgid "The nick of the person who has been deop'ed" +msgstr "" + +#: src/common/text.c:822 +msgid "The nick of the person of did the dehalfop'ing" +msgstr "" + +#: src/common/text.c:823 +msgid "The nick of the person who has been dehalfop'ed" +msgstr "" + +#: src/common/text.c:827 +msgid "The nick of the person of did the devoice'ing" +msgstr "" + +#: src/common/text.c:828 +msgid "The nick of the person who has been devoice'ed" +msgstr "" + +#: src/common/text.c:832 +msgid "The nick of the person of did the unban'ing" +msgstr "" + +#: src/common/text.c:837 +msgid "The nick of the person who did the exempt" +msgstr "" + +#: src/common/text.c:838 src/common/text.c:843 +msgid "The exempt mask" +msgstr "" + +#: src/common/text.c:842 +msgid "The nick of the person removed the exempt" +msgstr "" + +#: src/common/text.c:847 +msgid "The nick of the person who did the invite" +msgstr "" + +#: src/common/text.c:848 src/common/text.c:853 +msgid "The invite mask" +msgstr "" + +#: src/common/text.c:852 +msgid "The nick of the person removed the invite" +msgstr "" + +#: src/common/text.c:857 +msgid "The nick of the person setting the mode" +msgstr "" + +#: src/common/text.c:858 +msgid "The mode's sign (+/-)" +msgstr "" + +#: src/common/text.c:859 +msgid "The mode letter" +msgstr "" + +#: src/common/text.c:860 +msgid "The channel it's being set on" +msgstr "" + +#: src/common/text.c:865 +msgid "Username" +msgstr "የተጠቃሚ ስም" + +#: src/common/text.c:867 +msgid "Full name" +msgstr "ሙሉ ስም" + +#: src/common/text.c:872 +msgid "Channel Membership/\"is an IRC operator\"" +msgstr "" + +#: src/common/text.c:877 +msgid "Server Information" +msgstr "" + +#: src/common/text.c:882 src/common/text.c:887 +msgid "Idle time" +msgstr "" + +#: src/common/text.c:888 +msgid "Signon time" +msgstr "" + +#: src/common/text.c:893 +msgid "Away reason" +msgstr "" + +#: src/common/text.c:902 src/common/text.c:907 src/common/text.c:915 +#: src/common/text.c:1093 +msgid "Message" +msgstr "መልእክት" + +#: src/common/text.c:908 +#, fuzzy +msgid "Account" +msgstr "ትግባር" + +#: src/common/text.c:913 +msgid "Real user@host" +msgstr "" + +#: src/common/text.c:914 +msgid "Real IP" +msgstr "" + +#: src/common/text.c:919 src/common/text.c:928 src/common/text.c:934 +#: src/common/text.c:1116 +msgid "Channel Name" +msgstr "የጣቢያ ስም" + +#: src/common/text.c:923 src/common/text.c:1079 src/fe-gtk/textgui.c:383 +msgid "Text" +msgstr "ጽሑፍ" + +#: src/common/text.c:924 src/common/text.c:930 src/common/text.c:1117 +msgid "Server Name" +msgstr "የሰርቨር ስም" + +#: src/common/text.c:929 +msgid "Nick of person who invited you" +msgstr "" + +#: src/common/text.c:935 src/fe-gtk/chanlist.c:598 +msgid "Users" +msgstr "ተጠቃሚዎች" + +#: src/common/text.c:939 +msgid "Nickname in use" +msgstr "" + +#: src/common/text.c:940 +msgid "Nick being tried" +msgstr "" + +#: src/common/text.c:944 src/common/text.c:980 src/common/text.c:991 +#: src/common/text.c:998 src/common/text.c:1011 src/common/text.c:1028 +#: src/common/text.c:1128 +msgid "Error" +msgstr "ስህተት" + +#: src/common/text.c:949 src/common/text.c:1083 +msgid "IP" +msgstr "IP" + +#: src/common/text.c:950 src/common/text.c:979 +msgid "Port" +msgstr "ፖርት" + +#: src/common/text.c:954 +msgid "PID" +msgstr "PID" + +#: src/common/text.c:962 +msgid "Channel name" +msgstr "የጣቢያን ስም" + +#: src/common/text.c:963 src/common/text.c:968 +msgid "Modes string" +msgstr "" + +#: src/common/text.c:978 src/common/text.c:1016 src/common/text.c:1021 +#: src/common/text.c:1062 +msgid "IP address" +msgstr "IP አድራሻ" + +#: src/common/text.c:984 src/common/text.c:1009 +msgid "DCC Type" +msgstr "DCC ዓይነት" + +#: src/common/text.c:985 src/common/text.c:990 src/common/text.c:995 +#: src/common/text.c:1002 src/common/text.c:1022 src/common/text.c:1026 +#: src/common/text.c:1032 src/common/text.c:1038 src/common/text.c:1045 +#: src/common/text.c:1054 src/common/text.c:1060 +msgid "Filename" +msgstr "የፋይል ስም" + +#: src/common/text.c:996 src/common/text.c:1003 +msgid "Destination filename" +msgstr "" + +#: src/common/text.c:1005 src/common/text.c:1034 +msgid "CPS" +msgstr "CPS" + +#: src/common/text.c:1040 +msgid "Pathname" +msgstr "የመተላለፊያ ስም" + +#: src/common/text.c:1055 src/fe-gtk/dccgui.c:483 src/fe-gtk/dccgui.c:633 +msgid "Position" +msgstr "ቦታ" + +#: src/common/text.c:1061 src/fe-gtk/dccgui.c:482 src/fe-gtk/dccgui.c:632 +msgid "Size" +msgstr "መጠን" + +#: src/common/text.c:1066 +msgid "DCC String" +msgstr "DCC ሐረግ" + +#: src/common/text.c:1071 +msgid "Number of notify items" +msgstr "" + +#: src/common/text.c:1075 +msgid "Servername" +msgstr "የሰርቨር ስም" + +#: src/common/text.c:1087 +msgid "Old Filename" +msgstr "አሮጌ የፋይል ስም" + +#: src/common/text.c:1088 +msgid "New Filename" +msgstr "አዲስ የፋይል ስም" + +#: src/common/text.c:1092 +msgid "Receiver" +msgstr "" + +#: src/common/text.c:1097 +msgid "Hostmask" +msgstr "" + +#: src/common/text.c:1102 +msgid "Hostname" +msgstr "የእንግዳ ተቀባይ ስም" + +#: src/common/text.c:1107 +msgid "The Packet" +msgstr "" + +#: src/common/text.c:1111 +msgid "Seconds" +msgstr "ሴኮንዶች" + +#: src/common/text.c:1115 +msgid "Nick of person who have been invited" +msgstr "" + +#: src/common/text.c:1122 +msgid "Banmask" +msgstr "" + +#: src/common/text.c:1123 +msgid "Who set the ban" +msgstr "" + +#: src/common/text.c:1124 +msgid "Ban time" +msgstr "" + +#: src/common/text.c:1162 +#, c-format +msgid "" +"Error parsing event %s.\n" +"Loading default" +msgstr "" + +#: src/common/text.c:1672 +#, c-format +msgid "" +"Cannot read sound file:\n" +"%s" +msgstr "" + +#: src/common/util.c:292 +msgid "Remote host closed socket" +msgstr "" + +#: src/common/util.c:295 +msgid "Connection refused" +msgstr "" + +#: src/common/util.c:298 +msgid "No route to host" +msgstr "" + +#: src/common/util.c:300 +msgid "Connection timed out" +msgstr "" + +#: src/common/util.c:302 +msgid "Cannot assign that address" +msgstr "" + +#: src/common/util.c:304 +msgid "Connection reset by peer" +msgstr "" + +#: src/common/util.c:733 +msgid "Andorra" +msgstr "አንዶራ" + +#: src/common/util.c:734 +msgid "United Arab Emirates" +msgstr "የተባበሩት አረብ ኤምሬትስ" + +#: src/common/util.c:735 +msgid "Afghanistan" +msgstr "አፍጋኒስታን" + +#: src/common/util.c:736 +msgid "Antigua and Barbuda" +msgstr "አንቲጓ እና ባሩዳ" + +#: src/common/util.c:737 +msgid "Anguilla" +msgstr "አንጉኢላ" + +#: src/common/util.c:738 +msgid "Albania" +msgstr "አልባኒያ" + +#: src/common/util.c:739 +msgid "Armenia" +msgstr "አርሜኒያ" + +#: src/common/util.c:740 +msgid "Netherlands Antilles" +msgstr "ኔዘርላንድስ አንቲልስ" + +#: src/common/util.c:741 +msgid "Angola" +msgstr "አንጐላ" + +#: src/common/util.c:742 +msgid "Antarctica" +msgstr "አንታርክቲካ" + +#: src/common/util.c:743 +msgid "Argentina" +msgstr "አርጀንቲና" + +#: src/common/util.c:744 +msgid "Reverse DNS" +msgstr "" + +#: src/common/util.c:745 +msgid "American Samoa" +msgstr "የአሜሪካ ሳሞአ" + +#: src/common/util.c:746 +msgid "Austria" +msgstr "ኦስትሪያ" + +#: src/common/util.c:747 +msgid "Nato Fiel" +msgstr "" + +#: src/common/util.c:748 +msgid "Australia" +msgstr "አውስትሬሊያ" + +#: src/common/util.c:749 +msgid "Aruba" +msgstr "አሩባ" + +#: src/common/util.c:750 +msgid "Azerbaijan" +msgstr "አዘርባጃን" + +#: src/common/util.c:751 +msgid "Bosnia and Herzegovina" +msgstr "ቦስኒያ እና ሄርዞጎቪኒያ" + +#: src/common/util.c:752 +msgid "Barbados" +msgstr "ባርቤዶስ" + +#: src/common/util.c:753 +msgid "Bangladesh" +msgstr "ባንግላዲሽ" + +#: src/common/util.c:754 +msgid "Belgium" +msgstr "ቤልጄም" + +#: src/common/util.c:755 +msgid "Burkina Faso" +msgstr "ቡርኪና ፋሶ" + +#: src/common/util.c:756 +msgid "Bulgaria" +msgstr "ቡልጌሪያ" + +#: src/common/util.c:757 +msgid "Bahrain" +msgstr "ባህሬን" + +#: src/common/util.c:758 +msgid "Burundi" +msgstr "ብሩንዲ" + +#: src/common/util.c:759 +msgid "Businesses" +msgstr "" + +#: src/common/util.c:760 +msgid "Benin" +msgstr "ቤኒን" + +#: src/common/util.c:761 +msgid "Bermuda" +msgstr "ቤርሙዳ" + +#: src/common/util.c:762 +msgid "Brunei Darussalam" +msgstr "ብሩኒ ዳሩሳላም" + +#: src/common/util.c:763 +msgid "Bolivia" +msgstr "ቦሊቪያ" + +#: src/common/util.c:764 +msgid "Brazil" +msgstr "ብራዚል" + +#: src/common/util.c:765 +msgid "Bahamas" +msgstr "ባሃማስ" + +#: src/common/util.c:766 +msgid "Bhutan" +msgstr "ቡህታን" + +#: src/common/util.c:767 +msgid "Bouvet Island" +msgstr "የቦውቬት ደሴት" + +#: src/common/util.c:768 +msgid "Botswana" +msgstr "ቦትስዋና" + +#: src/common/util.c:769 +msgid "Belarus" +msgstr "ቤላሩስ" + +#: src/common/util.c:770 +msgid "Belize" +msgstr "ቤሊዘ" + +#: src/common/util.c:771 +msgid "Canada" +msgstr "ካናዳ" + +#: src/common/util.c:772 +msgid "Cocos Islands" +msgstr "የኮኮስ ደሴቶች" + +#: src/common/util.c:773 +msgid "Central African Republic" +msgstr "የመካከለኛው አፍሪካ ሪፐብሊክ" + +#: src/common/util.c:774 +msgid "Congo" +msgstr "ኮንጐ" + +#: src/common/util.c:775 +msgid "Switzerland" +msgstr "ስዊዘርላንድ" + +#: src/common/util.c:776 +msgid "Cote D'ivoire" +msgstr "ኮት ዲቯር" + +#: src/common/util.c:777 +msgid "Cook Islands" +msgstr "ኩክ ደሴቶች" + +#: src/common/util.c:778 +msgid "Chile" +msgstr "ቺሊ" + +#: src/common/util.c:779 +msgid "Cameroon" +msgstr "ካሜሩን" + +#: src/common/util.c:780 +msgid "China" +msgstr "ቻይና" + +#: src/common/util.c:781 +msgid "Colombia" +msgstr "ኮሎምቢያ" + +#: src/common/util.c:782 +msgid "Internic Commercial" +msgstr "" + +#: src/common/util.c:783 +msgid "Costa Rica" +msgstr "ኮስታ ሪካ" + +#: src/common/util.c:784 +msgid "Former Czechoslovakia" +msgstr "የቀድሞው ቼኮዝሎቫኪያ" + +#: src/common/util.c:785 +msgid "Cuba" +msgstr "ኩባ" + +#: src/common/util.c:786 +msgid "Cape Verde" +msgstr "ኬፕ ቬርዴ" + +#: src/common/util.c:787 +msgid "Christmas Island" +msgstr "የገና ደሴቶች" + +#: src/common/util.c:788 +msgid "Cyprus" +msgstr "ሳይፕረስ" + +#: src/common/util.c:789 +msgid "Czech Republic" +msgstr "ቼክ ሪፑብሊክ" + +#: src/common/util.c:790 +msgid "Germany" +msgstr "ጀርመን" + +#: src/common/util.c:791 +msgid "Djibouti" +msgstr "ጂቡቲ" + +#: src/common/util.c:792 +msgid "Denmark" +msgstr "ዴንማርክ" + +#: src/common/util.c:793 +msgid "Dominica" +msgstr "ዶሚኒካ" + +#: src/common/util.c:794 +msgid "Dominican Republic" +msgstr "ዶሚኒክ ሪፑብሊክ" + +#: src/common/util.c:795 +msgid "Algeria" +msgstr "አልጄሪያ" + +#: src/common/util.c:796 +msgid "Ecuador" +msgstr "ኢኳዶር" + +#: src/common/util.c:797 +msgid "Educational Institution" +msgstr "" + +#: src/common/util.c:798 +msgid "Estonia" +msgstr "ኤስቶኒያ" + +#: src/common/util.c:799 +msgid "Egypt" +msgstr "ግብጽ" + +#: src/common/util.c:800 +msgid "Western Sahara" +msgstr "ምዕራባዊ ሳህራ" + +#: src/common/util.c:801 +msgid "Eritrea" +msgstr "ኤርትራ" + +#: src/common/util.c:802 +msgid "Spain" +msgstr "ስፔን" + +#: src/common/util.c:803 +msgid "Ethiopia" +msgstr "ኢትዮጵያ" + +#: src/common/util.c:804 +msgid "Finland" +msgstr "ፊንላንድ" + +#: src/common/util.c:805 +msgid "Fiji" +msgstr "ፊጂ" + +#: src/common/util.c:806 +msgid "Falkland Islands" +msgstr "የፎልክላንድ ደሴቶች" + +#: src/common/util.c:807 +msgid "Micronesia" +msgstr "ሚክሮኔዢያ" + +#: src/common/util.c:808 +msgid "Faroe Islands" +msgstr "የፋሮይ ደሴቶች" + +#: src/common/util.c:809 +msgid "France" +msgstr "ፈረንሳይ" + +#: src/common/util.c:810 +msgid "France, Metropolitan" +msgstr "የፈረንሳይ፣ ሜትሮ" + +#: src/common/util.c:811 +msgid "Gabon" +msgstr "ጋቦን" + +#: src/common/util.c:812 +msgid "Great Britain" +msgstr "ታላቋ ብሪታኒያ" + +#: src/common/util.c:813 +msgid "Grenada" +msgstr "ግሬናዳ" + +#: src/common/util.c:814 +msgid "Georgia" +msgstr "ጆርጂያ" + +#: src/common/util.c:815 +msgid "French Guiana" +msgstr "የፈረንሳይ ጉዊአና" + +#: src/common/util.c:816 +msgid "British Channel Isles" +msgstr "" + +#: src/common/util.c:817 +msgid "Ghana" +msgstr "ጋና" + +#: src/common/util.c:818 +msgid "Gibraltar" +msgstr "ጊብራልታር" + +#: src/common/util.c:819 +msgid "Greenland" +msgstr "ግሪንላንድ" + +#: src/common/util.c:820 +msgid "Gambia" +msgstr "ጋምቢያ" + +#: src/common/util.c:821 +msgid "Guinea" +msgstr "ጊኒ" + +#: src/common/util.c:822 +msgid "Government" +msgstr "መንግስት" + +#: src/common/util.c:823 +msgid "Guadeloupe" +msgstr "ጉዋደሉፕ" + +#: src/common/util.c:824 +msgid "Equatorial Guinea" +msgstr "ኢኳቶሪያል ጊኒ" + +#: src/common/util.c:825 +msgid "Greece" +msgstr "ግሪክ" + +#: src/common/util.c:826 +msgid "S. Georgia and S. Sandwich Isles." +msgstr "" + +#: src/common/util.c:827 +msgid "Guatemala" +msgstr "ጉዋቲማላ" + +#: src/common/util.c:828 +msgid "Guam" +msgstr "ጉዋም" + +#: src/common/util.c:829 +msgid "Guinea-Bissau" +msgstr "ጊኒ ቢሳዎ" + +#: src/common/util.c:830 +msgid "Guyana" +msgstr "ጉያና" + +#: src/common/util.c:831 +msgid "Hong Kong" +msgstr "ሆንግ ኮንግ" + +#: src/common/util.c:832 +msgid "Heard and McDonald Islands" +msgstr "የኧርድ እና የማክዶናልድ ደሴቶች" + +#: src/common/util.c:833 +msgid "Honduras" +msgstr "ሆንዱራስ" + +#: src/common/util.c:834 +msgid "Croatia" +msgstr "ክሮኤሽያ" + +#: src/common/util.c:835 +msgid "Haiti" +msgstr "ሀይቲ*" + +#: src/common/util.c:836 +msgid "Hungary" +msgstr "ሀንጋሪ" + +#: src/common/util.c:837 +msgid "Indonesia" +msgstr "ኢንዶኔዢያ" + +#: src/common/util.c:838 +msgid "Ireland" +msgstr "አየርላንድ" + +#: src/common/util.c:839 +msgid "Israel" +msgstr "እስራኤል" + +#: src/common/util.c:840 +msgid "India" +msgstr "ህንድ" + +#: src/common/util.c:841 +msgid "Informational" +msgstr "" + +#: src/common/util.c:842 +msgid "International" +msgstr "" + +#: src/common/util.c:843 +msgid "British Indian Ocean Territory" +msgstr "የብሪታኒያ ህንድ ውቂያኖስ ግዛት" + +#: src/common/util.c:844 +msgid "Iraq" +msgstr "ኢራቅ" + +#: src/common/util.c:845 +msgid "Iran" +msgstr "ኢራን" + +#: src/common/util.c:846 +msgid "Iceland" +msgstr "አይስላንድ" + +#: src/common/util.c:847 +msgid "Italy" +msgstr "ጣሊያን" + +#: src/common/util.c:848 +msgid "Jamaica" +msgstr "ጃማይካ" + +#: src/common/util.c:849 +msgid "Jordan" +msgstr "ጆርዳን" + +#: src/common/util.c:850 +msgid "Japan" +msgstr "ጃፓን" + +#: src/common/util.c:851 +msgid "Kenya" +msgstr "ኬንያ" + +#: src/common/util.c:852 +msgid "Kyrgyzstan" +msgstr "" + +#: src/common/util.c:853 +msgid "Cambodia" +msgstr "ካምቦዲያ" + +#: src/common/util.c:854 +msgid "Kiribati" +msgstr "ኪሪባቲ" + +#: src/common/util.c:855 +msgid "Comoros" +msgstr "ኮሞሮስ" + +#: src/common/util.c:856 +msgid "St. Kitts and Nevis" +msgstr "ቅዱስ ኪትስ እና ኔቪስ" + +#: src/common/util.c:857 +msgid "North Korea" +msgstr "ሰሜን ኮሪያ" + +#: src/common/util.c:858 +msgid "South Korea" +msgstr "ደቡብ ኮሪያ" + +#: src/common/util.c:859 +msgid "Kuwait" +msgstr "ክዌት" + +#: src/common/util.c:860 +msgid "Cayman Islands" +msgstr "ካይማን ደሴቶች" + +#: src/common/util.c:861 +msgid "Kazakhstan" +msgstr "ካዛኪስታን" + +#: src/common/util.c:862 +msgid "Laos" +msgstr "ላኦስ" + +#: src/common/util.c:863 +msgid "Lebanon" +msgstr "ሊባኖስ" + +#: src/common/util.c:864 +msgid "Saint Lucia" +msgstr "ሴንት ሉቺያ" + +#: src/common/util.c:865 +msgid "Liechtenstein" +msgstr "ሊችተንስታይን" + +#: src/common/util.c:866 +msgid "Sri Lanka" +msgstr "ሲሪላንካ" + +#: src/common/util.c:867 +msgid "Liberia" +msgstr "ላይቤሪያ" + +#: src/common/util.c:868 +msgid "Lesotho" +msgstr "ሌሶቶ" + +#: src/common/util.c:869 +msgid "Lithuania" +msgstr "ሊቱዌኒያ" + +#: src/common/util.c:870 +msgid "Luxembourg" +msgstr "ሉክሰምበርግ" + +#: src/common/util.c:871 +msgid "Latvia" +msgstr "ላትቪያ" + +#: src/common/util.c:872 +msgid "Libya" +msgstr "ሊቢያ" + +#: src/common/util.c:873 +msgid "Morocco" +msgstr "ሞሮኮ" + +#: src/common/util.c:874 +msgid "Monaco" +msgstr "ሞናኮ" + +#: src/common/util.c:875 +msgid "Moldova" +msgstr "ሞልዶቫ" + +#: src/common/util.c:876 +msgid "United States Medical" +msgstr "" + +#: src/common/util.c:877 +msgid "Madagascar" +msgstr "ማዳጋስካር" + +#: src/common/util.c:878 +msgid "Marshall Islands" +msgstr "ማርሻል አይላንድ" + +#: src/common/util.c:879 +msgid "Military" +msgstr "ወታደራዊ" + +#: src/common/util.c:880 +msgid "Macedonia" +msgstr "ማከዶኒያ" + +#: src/common/util.c:881 +msgid "Mali" +msgstr "ማሊ" + +#: src/common/util.c:882 +msgid "Myanmar" +msgstr "ማያንማር" + +#: src/common/util.c:883 +msgid "Mongolia" +msgstr "ሞንጎሊያ" + +#: src/common/util.c:884 +msgid "Macau" +msgstr "ማካዎ" + +#: src/common/util.c:885 +msgid "Northern Mariana Islands" +msgstr "የሰሜናዊ ማሪያና ደሴቶች" + +#: src/common/util.c:886 +msgid "Martinique" +msgstr "ማርቲኒክ" + +#: src/common/util.c:887 +msgid "Mauritania" +msgstr "ሞሪቴኒያ" + +#: src/common/util.c:888 +msgid "Montserrat" +msgstr "ሞንትሴራት" + +#: src/common/util.c:889 +msgid "Malta" +msgstr "ማልታ" + +#: src/common/util.c:890 +msgid "Mauritius" +msgstr "ማሩሸስ" + +#: src/common/util.c:891 +msgid "Maldives" +msgstr "ማልዲቭስ" + +#: src/common/util.c:892 +msgid "Malawi" +msgstr "ማላዊ" + +#: src/common/util.c:893 +msgid "Mexico" +msgstr "ሜክሲኮ" + +#: src/common/util.c:894 +msgid "Malaysia" +msgstr "ማሌዢያ" + +#: src/common/util.c:895 +msgid "Mozambique" +msgstr "ሞዛምቢክ" + +#: src/common/util.c:896 +msgid "Namibia" +msgstr "ናሚቢያ" + +#: src/common/util.c:897 +msgid "New Caledonia" +msgstr "ኒው ካሌዶኒያ" + +#: src/common/util.c:898 +msgid "Niger" +msgstr "ኒጀር" + +#: src/common/util.c:899 +msgid "Internic Network" +msgstr "" + +#: src/common/util.c:900 +msgid "Norfolk Island" +msgstr "ኖርፎልክ ደሴት" + +#: src/common/util.c:901 +msgid "Nigeria" +msgstr "ናይጄሪያ" + +#: src/common/util.c:902 +msgid "Nicaragua" +msgstr "ኒካራጓ" + +#: src/common/util.c:903 +msgid "Netherlands" +msgstr "ኔዘርላንድ" + +#: src/common/util.c:904 +msgid "Norway" +msgstr "ኖርዌ" + +#: src/common/util.c:905 +msgid "Nepal" +msgstr "ኔፓል" + +#: src/common/util.c:906 +msgid "Nauru" +msgstr "ናኡሩ" + +#: src/common/util.c:907 +msgid "Neutral Zone" +msgstr "" + +#: src/common/util.c:908 +msgid "Niue" +msgstr "ኒኡይ" + +#: src/common/util.c:909 +msgid "New Zealand" +msgstr "ኒው ዚላንድ" + +#: src/common/util.c:910 +msgid "Oman" +msgstr "ኦማን" + +#: src/common/util.c:911 +msgid "Internic Non-Profit Organization" +msgstr "" + +#: src/common/util.c:912 +msgid "Panama" +msgstr "ፓናማ" + +#: src/common/util.c:913 +msgid "Peru" +msgstr "ፔሩ" + +#: src/common/util.c:914 +msgid "French Polynesia" +msgstr "የፈረንሳይ ፖሊኔዢያ" + +#: src/common/util.c:915 +msgid "Papua New Guinea" +msgstr "ፓፑዋ ኒው ጊኒ" + +#: src/common/util.c:916 +msgid "Philippines" +msgstr "ፊሊፒንስ" + +#: src/common/util.c:917 +msgid "Pakistan" +msgstr "ፓኪስታን" + +#: src/common/util.c:918 +msgid "Poland" +msgstr "ፖላንድ" + +#: src/common/util.c:919 +msgid "St. Pierre and Miquelon" +msgstr "ቅዱስ ፒዬር እና ሚኩኤሎን" + +#: src/common/util.c:920 +msgid "Pitcairn" +msgstr "ፒትካኢርን" + +#: src/common/util.c:921 +msgid "Puerto Rico" +msgstr "ፖርታ ሪኮ" + +#: src/common/util.c:922 +msgid "Portugal" +msgstr "ፖርቱጋል" + +#: src/common/util.c:923 +msgid "Palau" +msgstr "ፓላው" + +#: src/common/util.c:924 +msgid "Paraguay" +msgstr "ፓራጓይ" + +#: src/common/util.c:925 +msgid "Qatar" +msgstr "ኳታር" + +#: src/common/util.c:926 +msgid "Reunion" +msgstr "ውህደት" + +#: src/common/util.c:927 +msgid "Romania" +msgstr "ሮሜኒያ" + +#: src/common/util.c:928 +msgid "Old School ARPAnet" +msgstr "" + +#: src/common/util.c:929 +msgid "Russian Federation" +msgstr "ራሺያ" + +#: src/common/util.c:930 +msgid "Rwanda" +msgstr "ሩዋንዳ" + +#: src/common/util.c:931 +msgid "Saudi Arabia" +msgstr "ሳውድአረቢያ" + +#: src/common/util.c:932 +msgid "Solomon Islands" +msgstr "ሰሎሞን ደሴት" + +#: src/common/util.c:933 +msgid "Seychelles" +msgstr "ሲሼልስ" + +#: src/common/util.c:934 +msgid "Sudan" +msgstr "ሱዳን" + +#: src/common/util.c:935 +msgid "Sweden" +msgstr "ስዊድን" + +#: src/common/util.c:936 +msgid "Singapore" +msgstr "ሲንጋፖር" + +#: src/common/util.c:937 +msgid "St. Helena" +msgstr "ሴንት ሄለና" + +#: src/common/util.c:938 +msgid "Slovenia" +msgstr "ስሎቬኒያ" + +#: src/common/util.c:939 +msgid "Svalbard and Jan Mayen Islands" +msgstr "የስቫልባርድ እና ዣን ማየን ደሴቶች" + +#: src/common/util.c:940 +msgid "Slovak Republic" +msgstr "ስሎቫክ ሪፐብሊክ" + +#: src/common/util.c:941 +msgid "Sierra Leone" +msgstr "ሴራሊዮን" + +#: src/common/util.c:942 +msgid "San Marino" +msgstr "ሳን ማሪኖ" + +#: src/common/util.c:943 +msgid "Senegal" +msgstr "ሴኔጋል" + +#: src/common/util.c:944 +msgid "Somalia" +msgstr "ሱማሌ" + +#: src/common/util.c:945 +msgid "Suriname" +msgstr "ሱሪናም" + +#: src/common/util.c:946 +msgid "Sao Tome and Principe" +msgstr "ሳኦ ቶሜ እና ፕሪንሲፔ" + +#: src/common/util.c:947 +msgid "Former USSR" +msgstr "" + +#: src/common/util.c:948 +msgid "El Salvador" +msgstr "ኤል ሳልቫዶር" + +#: src/common/util.c:949 +msgid "Syria" +msgstr "ሲሪያ" + +#: src/common/util.c:950 +msgid "Swaziland" +msgstr "ሱዋዚላንድ" + +#: src/common/util.c:951 +msgid "Turks and Caicos Islands" +msgstr "የቱርኮችና የካኢኮስ ደሴቶች" + +#: src/common/util.c:952 +msgid "Chad" +msgstr "ቻድ" + +#: src/common/util.c:953 +msgid "French Southern Territories" +msgstr "የፈረንሳይ ደቡባዊ ግዛቶች" + +#: src/common/util.c:954 +msgid "Togo" +msgstr "ቶጐ" + +#: src/common/util.c:955 +msgid "Thailand" +msgstr "ታይላንድ" + +#: src/common/util.c:956 +msgid "Tajikistan" +msgstr "ታጃኪስታን" + +#: src/common/util.c:957 +msgid "Tokelau" +msgstr "ቶክላው" + +#: src/common/util.c:958 +msgid "Turkmenistan" +msgstr "ቱርክሜኒስታን" + +#: src/common/util.c:959 +msgid "Tunisia" +msgstr "ቱኒዚያ" + +#: src/common/util.c:960 +msgid "Tonga" +msgstr "ቶንጋ" + +#: src/common/util.c:961 +msgid "East Timor" +msgstr "ምስራቅ ቲሞር" + +#: src/common/util.c:962 +msgid "Turkey" +msgstr "ቱርክ" + +#: src/common/util.c:963 +msgid "Trinidad and Tobago" +msgstr "ትሪኒዳድ እና ቶባጎ" + +#: src/common/util.c:964 +msgid "Tuvalu" +msgstr "ቱቫሉ" + +#: src/common/util.c:965 +msgid "Taiwan" +msgstr "ታይዋን" + +#: src/common/util.c:966 +msgid "Tanzania" +msgstr "ታንዛኒያ" + +#: src/common/util.c:967 +msgid "Ukraine" +msgstr "ዩክሬን" + +#: src/common/util.c:968 +msgid "Uganda" +msgstr "ዩጋንዳ" + +#: src/common/util.c:969 +msgid "United Kingdom" +msgstr "እንግሊዝ" + +#: src/common/util.c:970 +msgid "US Minor Outlying Islands" +msgstr "የአሜሪካ ራቅ ያሉ አናሳ ደሴቶች" + +#: src/common/util.c:971 +msgid "United States of America" +msgstr "አሜሪካ" + +#: src/common/util.c:972 +msgid "Uruguay" +msgstr "ኡራጓይ" + +#: src/common/util.c:973 +msgid "Uzbekistan" +msgstr "ዩዝበኪስታን" + +#: src/common/util.c:974 +msgid "Vatican City State" +msgstr "ቫቲካን ከተማ" + +#: src/common/util.c:975 +msgid "St. Vincent and the grenadines" +msgstr "ቅዱስ ቪንሴንት እና ግሬናዲንስ" + +#: src/common/util.c:976 +msgid "Venezuela" +msgstr "ቬንዙዌላ" + +#: src/common/util.c:977 +msgid "British Virgin Islands" +msgstr "የእንግሊዝ ድንግል ደሴቶች" + +#: src/common/util.c:978 +msgid "US Virgin Islands" +msgstr "የአሜሪካ ቨርጂን ደሴቶች" + +#: src/common/util.c:979 +msgid "Vietnam" +msgstr "ቬትናም" + +#: src/common/util.c:980 +msgid "Vanuatu" +msgstr "ቫኑአቱ" + +#: src/common/util.c:981 +msgid "Wallis and Futuna Islands" +msgstr "ዋሊስ እና ፉቱና ደሴቶች" + +#: src/common/util.c:982 +msgid "Samoa" +msgstr "ሳሞአ" + +#: src/common/util.c:983 +msgid "Yemen" +msgstr "የመን" + +#: src/common/util.c:984 +msgid "Mayotte" +msgstr "ሜይኦቴ" + +#: src/common/util.c:985 +msgid "Yugoslavia" +msgstr "ዩጎዝላቪያ" + +#: src/common/util.c:986 +msgid "South Africa" +msgstr "ደቡብ አፍሪካ" + +#: src/common/util.c:987 +msgid "Zambia" +msgstr "ዛምቢያ" + +#: src/common/util.c:988 +msgid "Zaire" +msgstr "ዛየር" + +#: src/common/util.c:989 +msgid "Zimbabwe" +msgstr "ዚምቧቤ" + +#: src/common/util.c:995 src/common/util.c:1005 src/fe-gtk/menu.c:503 +#: src/fe-gtk/menu.c:507 src/fe-gtk/menu.c:511 src/fe-gtk/menu.c:515 +#: src/fe-gtk/menu.c:519 +msgid "Unknown" +msgstr "ያልታወቀ" + +#: src/common/xchat.c:908 +msgid "Direct client-to-client" +msgstr "" + +#: src/common/xchat.c:909 +#, fuzzy +msgid "Send File" +msgstr "የድምፅ ፋይል፦" + +#: src/common/xchat.c:910 +msgid "Offer Chat" +msgstr "" + +#: src/common/xchat.c:911 +#, fuzzy +msgid "Abort Chat" +msgstr "ስለ X-ማውሪያ" + +#: src/common/xchat.c:912 src/fe-gtk/plugingui.c:74 +msgid "Version" +msgstr "ዝርያ" + +#: src/common/xchat.c:913 +#, fuzzy +msgid "Userinfo" +msgstr "ተጠቃሚ" + +#: src/common/xchat.c:914 +msgid "Clientinfo" +msgstr "" + +#: src/common/xchat.c:915 src/common/xchat.c:947 src/common/xchat.c:997 +msgid "Ping" +msgstr "" + +#: src/common/xchat.c:916 +msgid "Time" +msgstr "" + +#: src/common/xchat.c:917 +#, fuzzy +msgid "Finger" +msgstr "ኒጀር" + +#: src/common/xchat.c:918 +#, fuzzy +msgid "Oper" +msgstr "ክፈት" + +#: src/common/xchat.c:919 +msgid "Kill this user" +msgstr "" + +#: src/common/xchat.c:920 +msgid "Mode" +msgstr "" + +#: src/common/xchat.c:921 +msgid "Give Voice" +msgstr "" + +#: src/common/xchat.c:922 +msgid "Take Voice" +msgstr "" + +#: src/common/xchat.c:923 +msgid "Give Ops" +msgstr "" + +#: src/common/xchat.c:924 +msgid "Take Ops" +msgstr "" + +#: src/common/xchat.c:925 +msgid "Ignore" +msgstr "" + +#: src/common/xchat.c:926 +msgid "Ignore User" +msgstr "" + +#: src/common/xchat.c:927 +msgid "UnIgnore User" +msgstr "" + +#: src/common/xchat.c:928 +msgid "Kick/Ban" +msgstr "" + +#: src/common/xchat.c:929 src/common/xchat.c:981 +#, fuzzy +msgid "Kick" +msgstr "ቅጽል" + +#: src/common/xchat.c:930 src/common/xchat.c:931 src/common/xchat.c:932 +#: src/common/xchat.c:933 src/common/xchat.c:934 src/common/xchat.c:980 +#, fuzzy +msgid "Ban" +msgstr "ቡህታን" + +#: src/common/xchat.c:935 src/common/xchat.c:936 src/common/xchat.c:937 +#: src/common/xchat.c:938 +msgid "KickBan" +msgstr "" + +#: src/common/xchat.c:939 src/fe-gtk/dccgui.c:528 src/fe-gtk/dccgui.c:669 +msgid "Info" +msgstr "_መረጃ" + +#: src/common/xchat.c:940 +msgid "Who" +msgstr "" + +#: src/common/xchat.c:941 src/common/xchat.c:994 +msgid "WhoIs" +msgstr "" + +#: src/common/xchat.c:942 +msgid "DNS Lookup" +msgstr "" + +#: src/common/xchat.c:943 +#, fuzzy +msgid "Trace" +msgstr "ፈረንሳይ" + +#: src/common/xchat.c:944 +#, fuzzy +msgid "UserHost" +msgstr "ተጠቃሚዎች" + +#: src/common/xchat.c:945 +msgid "External" +msgstr "" + +#: src/common/xchat.c:946 +msgid "Traceroute" +msgstr "" + +#: src/common/xchat.c:948 +#, fuzzy +msgid "Telnet" +msgstr "አጥፉ" + +#: src/common/xchat.c:949 +msgid "Open Dialog Window" +msgstr "" + +#: src/common/xchat.c:961 +#, fuzzy +msgid "Disconnect" +msgstr "አገናኝ" + +#: src/common/xchat.c:962 +#, fuzzy +msgid "Reconnect" +msgstr "አገናኝ" + +#: src/common/xchat.c:963 +#, fuzzy +msgid "Leave Channel" +msgstr "ጣቢያ" + +#: src/common/xchat.c:964 +#, fuzzy +msgid "Join Channel..." +msgstr "ጣቢያ አትጫን" + +#: src/common/xchat.c:965 +msgid "Enter Channel to Join:" +msgstr "" + +#: src/common/xchat.c:966 +#, fuzzy +msgid "Server Links" +msgstr "የሰርቨር ዝርዝር..." + +#: src/common/xchat.c:967 +#, fuzzy +msgid "Ping Server" +msgstr "ሰርቨር" + +#: src/common/xchat.c:968 +#, fuzzy +msgid "Hide Version" +msgstr "ዝርያ" + +#: src/common/xchat.c:978 +#, fuzzy +msgid "Op" +msgstr "ክፈት" + +#: src/common/xchat.c:979 +msgid "DeOp" +msgstr "" + +#: src/common/xchat.c:982 +msgid "bye" +msgstr "" + +#: src/common/xchat.c:983 +#, c-format +msgid "Enter reason to kick %s:" +msgstr "" + +#: src/common/xchat.c:984 +#, fuzzy +msgid "Sendfile" +msgstr "የድምፅ ፋይል፦" + +#: src/common/xchat.c:985 +msgid "Dialog" +msgstr "" + +#: src/common/xchat.c:995 +#, fuzzy +msgid "Send" +msgstr "ተልኳል" + +#: src/common/xchat.c:996 +#, fuzzy +msgid "Chat" +msgstr "ቻድ" + +#: src/common/xchat.c:998 src/fe-gtk/banlist.c:314 src/fe-gtk/search.c:117 +#: src/fe-gtk/urlgrab.c:200 +msgid "Clear" +msgstr "ሰርዝ" + +#: src/fe-gtk/about.c:102 +msgid "About X-Chat" +msgstr "ስለ X-ማውሪያ" + +#: src/fe-gtk/about.c:124 +msgid "A multiplatform IRC Client" +msgstr "" + +#: src/fe-gtk/ascii.c:131 +msgid "Character Chart" +msgstr "" + +#: src/fe-gtk/banlist.c:148 src/fe-gtk/banlist.c:232 +msgid "You must select some bans." +msgstr "" + +#: src/fe-gtk/banlist.c:248 src/fe-gtk/ignoregui.c:174 +msgid "Mask" +msgstr "" + +#: src/fe-gtk/banlist.c:249 src/fe-gtk/dccgui.c:485 +msgid "From" +msgstr "ከ" + +#: src/fe-gtk/banlist.c:250 +msgid "Date" +msgstr "ቀን" + +#: src/fe-gtk/banlist.c:294 +#, c-format +msgid "X-Chat: Ban List (%s)" +msgstr "" + +#: src/fe-gtk/banlist.c:310 +msgid "Unban" +msgstr "" + +#: src/fe-gtk/banlist.c:312 +msgid "Crop" +msgstr "" + +#: src/fe-gtk/banlist.c:316 +msgid "Refresh" +msgstr "በድጋሚ ጀምር" + +#: src/fe-gtk/chanlist.c:120 +#, c-format +msgid "User and Channel Statistics: %d/%d Users on %d/%d Channels" +msgstr "" + +#: src/fe-gtk/chanlist.c:536 +msgid "I can't save an empty list!" +msgstr "" + +#: src/fe-gtk/chanlist.c:539 src/fe-gtk/menu.c:931 +msgid "Select an output filename" +msgstr "" + +#: src/fe-gtk/chanlist.c:607 +#, c-format +msgid "X-Chat: Channel List (%s)" +msgstr "X-ማውሪያ፦ የጣቢያ ዝርዝር (%s)" + +#: src/fe-gtk/chanlist.c:622 +msgid "List display options:" +msgstr "" + +#: src/fe-gtk/chanlist.c:634 +#, fuzzy +msgid "Minimum Users:" +msgstr "በተቻለ መጠን ተጠቃሚዎች፦" + +#: src/fe-gtk/chanlist.c:649 +#, fuzzy +msgid "Maximum Users:" +msgstr "ከፍተኛ መጠን ተጠቃሚዎች፦" + +#: src/fe-gtk/chanlist.c:664 +msgid "Regex Match:" +msgstr "" + +#: src/fe-gtk/chanlist.c:685 +msgid "Apply Match to:" +msgstr "" + +#: src/fe-gtk/chanlist.c:709 +msgid "Apply" +msgstr "ተጠቀም" + +#: src/fe-gtk/chanlist.c:751 +msgid "Refresh the list" +msgstr "ዝርዝሩን አድስ" + +#: src/fe-gtk/chanlist.c:753 +msgid "Save the list" +msgstr "ዝርዝሩን አስቀምጥ" + +#: src/fe-gtk/chanlist.c:755 src/fe-gtk/menu.c:739 +msgid "Join Channel" +msgstr "ጣቢያ አትጫን" + +#: src/fe-gtk/dccgui.c:126 +#, c-format +msgid "Send file to %s" +msgstr "" + +#: src/fe-gtk/dccgui.c:339 +#, c-format +msgid "" +" File: %s\n" +" To/From: %s\n" +" Size: %u\n" +" Port: %d\n" +" IP Number: %s\n" +"Start Time: %s Max CPS: %d\n" +msgstr "" + +#: src/fe-gtk/dccgui.c:372 +msgid "That file is not resumable." +msgstr "" + +#: src/fe-gtk/dccgui.c:376 +#, c-format +msgid "" +"Cannot access file: %s\n" +"%s.\n" +"Resuming not possible." +msgstr "" + +#: src/fe-gtk/dccgui.c:383 +msgid "" +"File in download directory is larger than file offered. Resuming not " +"possible." +msgstr "" + +#: src/fe-gtk/dccgui.c:387 +msgid "Cannot resume the same file from two people." +msgstr "" + +#: src/fe-gtk/dccgui.c:474 +msgid "MIME Type" +msgstr "የMIME ዓይነት" + +#: src/fe-gtk/dccgui.c:480 src/fe-gtk/dccgui.c:630 src/fe-gtk/dccgui.c:753 +#: src/fe-gtk/notifygui.c:110 +msgid "Status" +msgstr "ሁኔታ" + +#: src/fe-gtk/dccgui.c:481 src/fe-gtk/dccgui.c:631 src/fe-gtk/plugingui.c:75 +msgid "File" +msgstr "ፋይል" + +#: src/fe-gtk/dccgui.c:484 src/fe-gtk/dccgui.c:635 +msgid "ETA" +msgstr "ETA" + +#: src/fe-gtk/dccgui.c:494 +msgid "X-Chat: File Receive List" +msgstr "" + +#: src/fe-gtk/dccgui.c:522 src/fe-gtk/dccgui.c:668 src/fe-gtk/dccgui.c:783 +msgid "Abort" +msgstr "ውድቅ" + +#: src/fe-gtk/dccgui.c:524 src/fe-gtk/dccgui.c:784 +msgid "Accept" +msgstr "" + +#: src/fe-gtk/dccgui.c:526 +msgid "Resume" +msgstr "ቀጥል" + +#: src/fe-gtk/dccgui.c:530 +msgid "Open" +msgstr "ክፈት" + +#: src/fe-gtk/dccgui.c:634 +msgid "Ack" +msgstr "Ack" + +#: src/fe-gtk/dccgui.c:636 +msgid "To" +msgstr "ወደ" + +#: src/fe-gtk/dccgui.c:646 +msgid "X-Chat: File Send List" +msgstr "" + +#: src/fe-gtk/dccgui.c:754 +msgid "To/From" +msgstr "ወደ/ከ" + +#: src/fe-gtk/dccgui.c:755 +msgid "Recv" +msgstr "" + +#: src/fe-gtk/dccgui.c:756 +msgid "Sent" +msgstr "ተልኳል" + +#: src/fe-gtk/dccgui.c:757 +msgid "StartTime" +msgstr "" + +#: src/fe-gtk/dccgui.c:767 +msgid "X-Chat: DCC Chat List" +msgstr "X-ማውሪያ፦ የDCC ማውሪያ ዝርዝር" + +#: src/fe-gtk/editlist.c:139 +msgid "*NEW*" +msgstr "*አዲስ*" + +#: src/fe-gtk/editlist.c:140 +msgid "EDIT ME" +msgstr "እኔ ያስተካክሉ" + +#: src/fe-gtk/editlist.c:305 src/fe-gtk/plugingui.c:73 +msgid "Name" +msgstr "ስም" + +#: src/fe-gtk/editlist.c:306 +msgid "Command" +msgstr "ትእዛዝ" + +#: src/fe-gtk/editlist.c:333 +msgid "Move Up" +msgstr "ወደላይ አንቀሳቅስ" + +#: src/fe-gtk/editlist.c:337 +msgid "Move Dn" +msgstr "ወደታች አንቀሳቅስ" + +#: src/fe-gtk/editlist.c:345 +msgid "Cancel" +msgstr "ተወው" + +#: src/fe-gtk/editlist.c:349 src/fe-gtk/textgui.c:464 src/fe-gtk/urlgrab.c:204 +msgid "Save" +msgstr "አስቀምጥ" + +#: src/fe-gtk/editlist.c:357 +msgid "Add New" +msgstr "አዲስ ጨምር" + +#: src/fe-gtk/editlist.c:361 src/fe-gtk/fkeys.c:746 src/fe-gtk/ignoregui.c:378 +msgid "Delete" +msgstr "አጥፉ" + +#: src/fe-gtk/editlist.c:369 +msgid "Sort" +msgstr "ቅደም ተከተል" + +#: src/fe-gtk/editlist.c:373 +msgid "Help" +msgstr "መረጃ" + +#: src/fe-gtk/fe-gtk.c:143 +#, fuzzy +msgid "Options" +msgstr "ትግባር" + +#: src/fe-gtk/fe-gtk.c:144 +msgid "DIRECTORY" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:145 +msgid "use a different config dir" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:146 +msgid "don't auto connect" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:147 +msgid "don't auto load any plugins" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:148 +msgid "show version information" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:214 +#, c-format +msgid "" +"Failed to open font:\n" +"\n" +"%s" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:617 +msgid "Search buffer is empty.\n" +msgstr "" + +#: src/fe-gtk/fe-gtk.c:694 +#, c-format +msgid "%d bytes" +msgstr "" + +#: src/fe-gtk/fkeys.c:153 +msgid "" +"The Run Command action runs the data in Data 1 as if it has been typed into " +"the entry box where you pressed the key sequence. Thus it can contain text " +"(which will be sent to the channel/person), commands or user commands. When " +"run all \\n characters in Data 1 are used to deliminate seperate commands so " +"it is possible to run more than one command. If you want a \\ in the actual " +"text run then enter \\\\" +msgstr "" + +#: src/fe-gtk/fkeys.c:155 +msgid "" +"The Change Page command switches between pages in the notebook. Set Data 1 " +"to the page you want to switch to. If Data 2 is set to anything then the " +"switch will be relative to the current position" +msgstr "" + +#: src/fe-gtk/fkeys.c:157 +msgid "" +"The Insert in Buffer command will insert the contents of Data 1 into the " +"entry where the key sequence was pressed at the current cursor position" +msgstr "" + +#: src/fe-gtk/fkeys.c:159 +msgid "" +"The Scroll Page command scrolls the text widget up or down one page. If Data " +"1 is set to anything the page scrolls up, else it scrolls down" +msgstr "" + +#: src/fe-gtk/fkeys.c:161 +msgid "" +"The Set Buffer command sets the entry where the key sequence was entered to " +"the contents of Data 1" +msgstr "" + +#: src/fe-gtk/fkeys.c:163 +msgid "" +"The Last Command command sets the entry to contain the last command entered " +"- the same as pressing up in a shell" +msgstr "" + +#: src/fe-gtk/fkeys.c:165 +msgid "" +"The Next Command command sets the entry to contain the next command entered " +"- the same as pressing down in a shell" +msgstr "" + +#: src/fe-gtk/fkeys.c:167 +msgid "" +"This command changes the text in the entry to finish an incomplete nickname " +"or command. If Data 1 is set then double-tabbing in a string will select the " +"last nick, not the next" +msgstr "" + +#: src/fe-gtk/fkeys.c:169 +msgid "" +"This command scrolls up and down through the list of nicks. If Data 1 is set " +"to anything it will scroll up, else it scrolls down" +msgstr "" + +#: src/fe-gtk/fkeys.c:171 +msgid "" +"This command checks the last word entered in the entry against the replace " +"list and replaces it if it finds a match" +msgstr "" + +#: src/fe-gtk/fkeys.c:173 +msgid "This command moves the front tab left by one" +msgstr "" + +#: src/fe-gtk/fkeys.c:175 +msgid "This command moves the front tab right by one" +msgstr "" + +#: src/fe-gtk/fkeys.c:177 +msgid "This command moves the current tab family to the left" +msgstr "" + +#: src/fe-gtk/fkeys.c:179 +msgid "This command moves the current tab family to the right" +msgstr "" + +#: src/fe-gtk/fkeys.c:181 +msgid "Push input line into history but doesn't send to server" +msgstr "" + +#: src/fe-gtk/fkeys.c:193 +msgid "There was an error loading key bindings configuration" +msgstr "" + +#: src/fe-gtk/fkeys.c:434 src/fe-gtk/fkeys.c:435 src/fe-gtk/fkeys.c:436 +#: src/fe-gtk/fkeys.c:437 src/fe-gtk/fkeys.c:719 src/fe-gtk/fkeys.c:725 +#: src/fe-gtk/fkeys.c:730 src/fe-gtk/maingui.c:804 src/fe-gtk/maingui.c:825 +#: src/fe-gtk/maingui.c:979 src/fe-gtk/maingui.c:1018 +#: src/fe-gtk/maingui.c:2360 +msgid "" +msgstr "<ምንም>" + +#: src/fe-gtk/fkeys.c:683 +msgid "Mod" +msgstr "" + +#: src/fe-gtk/fkeys.c:684 src/fe-gtk/fkeys.c:779 +msgid "Key" +msgstr "ቁልፍ" + +#: src/fe-gtk/fkeys.c:685 +msgid "Action" +msgstr "ትግባር" + +#: src/fe-gtk/fkeys.c:694 +msgid "X-Chat: Edit Key Bindings" +msgstr "" + +#: src/fe-gtk/fkeys.c:741 +msgid "Add new" +msgstr "አዲስ ጨምር" + +#: src/fe-gtk/fkeys.c:772 +msgid "Shift" +msgstr "Shift" + +#: src/fe-gtk/fkeys.c:774 +msgid "Alt" +msgstr "Alt" + +#: src/fe-gtk/fkeys.c:776 +msgid "Ctrl" +msgstr "Ctrl" + +#: src/fe-gtk/fkeys.c:783 +msgid "Data 1" +msgstr "ዳታ 1" + +#: src/fe-gtk/fkeys.c:786 +msgid "Data 2" +msgstr "ዳታ 2" + +#: src/fe-gtk/fkeys.c:829 +msgid "Error opening keys config file\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1000 +#, c-format +msgid "" +"Unknown keyname %s in key bindings config file\n" +"Load aborted, please fix %s/keybindings.conf\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1038 +#, c-format +msgid "" +"Unknown action %s in key bindings config file\n" +"Load aborted, Please fix %s/keybindings\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1059 +#, c-format +msgid "" +"Expecting Data line (beginning Dx{:|!}) but got:\n" +"%s\n" +"\n" +"Load aborted, Please fix %s/keybindings\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1128 +#, c-format +msgid "" +"Key bindings config file is corrupt, load aborted\n" +"Please fix %s/keybindings.conf\n" +msgstr "" + +#: src/fe-gtk/gtkutil.c:146 +msgid "Cannot write to that file." +msgstr "" + +#: src/fe-gtk/gtkutil.c:148 +msgid "Cannot read that file." +msgstr "" + +#: src/fe-gtk/ignoregui.c:116 src/fe-gtk/ignoregui.c:279 +msgid "That mask already exists." +msgstr "" + +#: src/fe-gtk/ignoregui.c:176 src/fe-gtk/maingui.c:1473 +msgid "Private" +msgstr "" + +#: src/fe-gtk/ignoregui.c:177 +msgid "Notice" +msgstr "" + +#: src/fe-gtk/ignoregui.c:178 +msgid "CTCP" +msgstr "" + +#: src/fe-gtk/ignoregui.c:179 +msgid "DCC" +msgstr "" + +#: src/fe-gtk/ignoregui.c:180 +msgid "Invite" +msgstr "" + +#: src/fe-gtk/ignoregui.c:181 +msgid "Unignore" +msgstr "" + +#: src/fe-gtk/ignoregui.c:299 +msgid "Enter mask to ignore:" +msgstr "" + +#: src/fe-gtk/ignoregui.c:346 +msgid "X-Chat: Ignore list" +msgstr "" + +#: src/fe-gtk/ignoregui.c:353 +msgid "Ignore Stats:" +msgstr "" + +#: src/fe-gtk/ignoregui.c:361 +msgid "Channel:" +msgstr "ጣቢያ፦" + +#: src/fe-gtk/ignoregui.c:362 +msgid "Private:" +msgstr "" + +#: src/fe-gtk/ignoregui.c:363 +msgid "Notice:" +msgstr "" + +#: src/fe-gtk/ignoregui.c:364 +msgid "CTCP:" +msgstr "" + +#: src/fe-gtk/ignoregui.c:365 +msgid "Invite:" +msgstr "" + +#: src/fe-gtk/ignoregui.c:376 src/fe-gtk/menu.c:1236 +msgid "New" +msgstr "አዲስ" + +#: src/fe-gtk/ignoregui.c:380 +#, fuzzy +msgid "Delete All" +msgstr "አጥፉ" + +#: src/fe-gtk/maingui.c:477 +#, c-format +msgid "Topic for %s is: %s" +msgstr "" + +#: src/fe-gtk/maingui.c:481 +msgid "No topic is set" +msgstr "" + +#: src/fe-gtk/maingui.c:878 +msgid "No other tabs open, quit xchat?" +msgstr "" + +#: src/fe-gtk/maingui.c:924 +msgid "Insert color code" +msgstr "" + +#: src/fe-gtk/maingui.c:966 src/fe-gtk/menu.c:1258 +msgid "Close Tab" +msgstr "መክፈቻን ዝጋ" + +#: src/fe-gtk/maingui.c:969 src/fe-gtk/menu.c:1388 +msgid "Detach Tab" +msgstr "መክፈቻን አለያይ" + +#: src/fe-gtk/maingui.c:984 +msgid "Beep on message" +msgstr "" + +#: src/fe-gtk/maingui.c:987 +msgid "Show join/part messages" +msgstr "" + +#: src/fe-gtk/maingui.c:989 +msgid "Color paste" +msgstr "" + +#: src/fe-gtk/maingui.c:999 +msgid "Go to" +msgstr "" + +#: src/fe-gtk/maingui.c:1191 +msgid "Some file transfers still active, quit xchat?" +msgstr "" + +#: src/fe-gtk/maingui.c:1341 src/fe-gtk/maingui.c:1447 +msgid "User limit must be a number!\n" +msgstr "" + +#: src/fe-gtk/maingui.c:1469 +msgid "Topic Protection" +msgstr "" + +#: src/fe-gtk/maingui.c:1470 +msgid "No outside messages" +msgstr "" + +#: src/fe-gtk/maingui.c:1471 +msgid "Secret" +msgstr "" + +#: src/fe-gtk/maingui.c:1472 +msgid "Invite Only" +msgstr "" + +#: src/fe-gtk/maingui.c:1474 +msgid "Moderated" +msgstr "" + +#: src/fe-gtk/maingui.c:1475 +msgid "Ban List" +msgstr "" + +#: src/fe-gtk/maingui.c:1477 +msgid "Keyword" +msgstr "ቁልፍ ቃላት" + +#: src/fe-gtk/maingui.c:1489 +msgid "User Limit" +msgstr "" + +#: src/fe-gtk/maingui.c:1505 +msgid "Close this tab/window" +msgstr "" + +#: src/fe-gtk/maingui.c:1602 +msgid "Show/Hide userlist" +msgstr "" + +#: src/fe-gtk/maingui.c:1712 +msgid "" +"Unable to set transparent background!\n" +"\n" +"You may be using a non-compliant window\n" +"manager that is not currently supported.\n" +msgstr "" + +#: src/fe-gtk/maingui.c:1905 +msgid "Enter new nickname:" +msgstr "" + +#: src/fe-gtk/menu.c:141 +msgid "Host unknown" +msgstr "" + +#: src/fe-gtk/menu.c:502 +#, c-format +msgid "User: %s" +msgstr "ተጠቃሚ፦ %s" + +#: src/fe-gtk/menu.c:506 +#, c-format +msgid "Country: %s" +msgstr "አገር፦ %s" + +#: src/fe-gtk/menu.c:510 +#, c-format +msgid "Realname: %s" +msgstr "የውነት ስም፦ %s" + +#: src/fe-gtk/menu.c:514 +#, c-format +msgid "Server: %s" +msgstr "ሰርቨር፦ %s" + +#: src/fe-gtk/menu.c:518 +#, c-format +msgid "Last Msg: %s" +msgstr "የመጨረሻ መልዕክት፦ %s" + +#: src/fe-gtk/menu.c:603 +msgid "Menu Bar" +msgstr "ሜኑባር" + +#: src/fe-gtk/menu.c:604 +msgid "Topic Bar" +msgstr "ጉዳዩባር" + +#: src/fe-gtk/menu.c:608 +msgid "User List" +msgstr "የተጠቃሚ ዝርዝር" + +#: src/fe-gtk/menu.c:611 +msgid "Mode Buttons" +msgstr "" + +#: src/fe-gtk/menu.c:617 +#, fuzzy +msgid "User List Buttons" +msgstr "የተጠቃሚ ዝርዝር" + +#: src/fe-gtk/menu.c:743 +msgid "Part Channel" +msgstr "" + +#: src/fe-gtk/menu.c:745 +msgid "Cycle Channel" +msgstr "" + +#: src/fe-gtk/menu.c:768 +msgid "X-Chat: User menu" +msgstr "X-ማውሪያ፦ የተጠቃሚ ሜኑ" + +#: src/fe-gtk/menu.c:777 +msgid "Edit This Menu..." +msgstr "ይህ ሜኑ ያስተካክሉ..." + +#: src/fe-gtk/menu.c:879 +msgid "" +"*WARNING*\n" +"Auto accepting DCC to your home directory\n" +"can be dangerous and is exploitable. Eg:\n" +"Someone could send you a .bash_profile" +msgstr "" + +#: src/fe-gtk/menu.c:1001 +msgid "Settings saved." +msgstr "" + +#: src/fe-gtk/menu.c:1038 +msgid "" +"User Commands - Special codes:\n" +"\n" +"%c = current channel\n" +"%m = machine info\n" +"%n = your nick\n" +"%t = time/date\n" +"%v = xchat version\n" +"%2 = word 2\n" +"%3 = word 3\n" +"&2 = word 2 to the end of line\n" +"&3 = word 3 to the end of line\n" +"\n" +"eg:\n" +"/cmd john hello\n" +"\n" +"%2 would be \"john\"\n" +"&2 would be \"john hello\"." +msgstr "" + +#: src/fe-gtk/menu.c:1053 +msgid "" +"Userlist Buttons - Special codes:\n" +"\n" +"%a = all selected nicks\n" +"%c = current channel\n" +"%h = selected nick's hostname\n" +"%m = machine info\n" +"%n = your nick\n" +"%s = selected nick\n" +"%t = time/date\n" +msgstr "" + +#: src/fe-gtk/menu.c:1062 +msgid "" +"Dialog Buttons - Special codes:\n" +"\n" +"%a = all selected nicks\n" +"%c = current channel\n" +"%h = selected nick's hostname\n" +"%m = machine info\n" +"%n = your nick\n" +"%s = selected nick\n" +"%t = time/date\n" +msgstr "" + +#: src/fe-gtk/menu.c:1071 +msgid "" +"CTCP Replies - Special codes:\n" +"\n" +"%d = data (the whole ctcp)\n" +"%m = machine info\n" +"%s = nick who sent the ctcp\n" +"%t = time/date\n" +"%2 = word 2\n" +"%3 = word 3\n" +"&2 = word 2 to the end of line\n" +"&3 = word 3 to the end of line\n" +"\n" +msgstr "" + +#: src/fe-gtk/menu.c:1081 +#, c-format +msgid "" +"URL Handlers - Special codes:\n" +"\n" +"%s = the URL string\n" +"\n" +"Putting a ! infront of the command\n" +"indicates it should be sent to a\n" +"shell instead of X-Chat" +msgstr "" + +#: src/fe-gtk/menu.c:1090 +msgid "X-Chat: User Defined Commands" +msgstr "" + +#: src/fe-gtk/menu.c:1097 +msgid "X-Chat: Userlist Popup menu" +msgstr "" + +#: src/fe-gtk/menu.c:1104 +msgid "X-Chat: Replace" +msgstr "" + +#: src/fe-gtk/menu.c:1111 +msgid "X-Chat: URL Handlers" +msgstr "" + +#: src/fe-gtk/menu.c:1130 +msgid "X-Chat: Userlist buttons" +msgstr "" + +#: src/fe-gtk/menu.c:1137 +msgid "X-Chat: Dialog buttons" +msgstr "" + +#: src/fe-gtk/menu.c:1144 +msgid "X-Chat: CTCP Replies" +msgstr "" + +#: src/fe-gtk/menu.c:1232 +msgid "_X-Chat" +msgstr "_X-ማውሪያ" + +#: src/fe-gtk/menu.c:1233 +msgid "Server List..." +msgstr "የሰርቨር ዝርዝር..." + +#: src/fe-gtk/menu.c:1237 +msgid "Server Tab..." +msgstr "የሰርቨር መክፈቻ..." + +#: src/fe-gtk/menu.c:1238 +msgid "Channel Tab..." +msgstr "የጣቢያ መክፈቻ..." + +#: src/fe-gtk/menu.c:1239 +msgid "Server Window..." +msgstr "የሰርቨር መስኮት..." + +#: src/fe-gtk/menu.c:1240 +msgid "Channel Window..." +msgstr "የጣቢያ መስኮት..." + +#: src/fe-gtk/menu.c:1245 src/fe-gtk/menu.c:1247 +#, fuzzy +msgid "Load Plugin or Script..." +msgstr "የተጨማሪው ፕሮግራምን ጫን..." + +#: src/fe-gtk/menu.c:1251 +msgid "New Shell Tab..." +msgstr "" + +#: src/fe-gtk/menu.c:1260 +msgid "Quit" +msgstr "ውጣ" + +#: src/fe-gtk/menu.c:1262 +msgid "_IRC" +msgstr "_IRC" + +#: src/fe-gtk/menu.c:1263 +msgid "Invisible" +msgstr "" + +#: src/fe-gtk/menu.c:1264 +msgid "Receive Wallops" +msgstr "" + +#: src/fe-gtk/menu.c:1265 +msgid "Receive Server Notices" +msgstr "" + +#: src/fe-gtk/menu.c:1267 +msgid "Marked Away" +msgstr "" + +#: src/fe-gtk/menu.c:1269 +msgid "Auto Rejoin when Kicked" +msgstr "" + +#: src/fe-gtk/menu.c:1270 +msgid "Auto Reconnect to Server" +msgstr "" + +#: src/fe-gtk/menu.c:1271 +msgid "Never-give-up ReConnect" +msgstr "" + +#: src/fe-gtk/menu.c:1273 +msgid "Auto Open Dialog Windows" +msgstr "" + +#: src/fe-gtk/menu.c:1274 +msgid "Auto Accept Direct Chat" +msgstr "" + +#: src/fe-gtk/menu.c:1275 +msgid "Auto Accept Files" +msgstr "" + +#: src/fe-gtk/menu.c:1277 +msgid "_Server" +msgstr "_ሰርቨር" + +#: src/fe-gtk/menu.c:1279 +msgid "S_ettings" +msgstr "_ምርጫዎች" + +#: src/fe-gtk/menu.c:1280 +msgid "Preferences..." +msgstr "ምርጫዎች..." + +#: src/fe-gtk/menu.c:1282 +msgid "Lists" +msgstr "ዝርዝሮች" + +#: src/fe-gtk/menu.c:1283 +msgid "Auto Replace..." +msgstr "" + +#: src/fe-gtk/menu.c:1284 +msgid "CTCP Replies..." +msgstr "" + +#: src/fe-gtk/menu.c:1285 +msgid "Dialog Buttons..." +msgstr "" + +#: src/fe-gtk/menu.c:1286 +msgid "Key Bindings..." +msgstr "" + +#: src/fe-gtk/menu.c:1287 +msgid "Text Events..." +msgstr "" + +#: src/fe-gtk/menu.c:1288 +msgid "URL Handlers..." +msgstr "" + +#: src/fe-gtk/menu.c:1289 +msgid "User Commands..." +msgstr "" + +#: src/fe-gtk/menu.c:1290 +msgid "Userlist Buttons..." +msgstr "" + +#: src/fe-gtk/menu.c:1291 +msgid "Userlist Popup..." +msgstr "" + +#: src/fe-gtk/menu.c:1296 +msgid "Reload Settings" +msgstr "" + +#: src/fe-gtk/menu.c:1298 +msgid "Save Settings now" +msgstr "" + +#: src/fe-gtk/menu.c:1299 +msgid "Save Settings on exit" +msgstr "" + +#: src/fe-gtk/menu.c:1302 +msgid "_Window" +msgstr "_መስኮት" + +#: src/fe-gtk/menu.c:1303 +msgid "Ban List..." +msgstr "" + +#: src/fe-gtk/menu.c:1304 +msgid "Channel List..." +msgstr "የጣቢያ ዝርዝር..." + +#: src/fe-gtk/menu.c:1305 +msgid "Character Chart..." +msgstr "" + +#: src/fe-gtk/menu.c:1306 +msgid "Direct Chat..." +msgstr "" + +#: src/fe-gtk/menu.c:1307 +msgid "File Receive..." +msgstr "ፋይልን ተቀበል..." + +#: src/fe-gtk/menu.c:1308 +msgid "File Send..." +msgstr "ፋይልን ላክ..." + +#: src/fe-gtk/menu.c:1309 +msgid "Ignore List..." +msgstr "" + +#: src/fe-gtk/menu.c:1310 +msgid "Notify List..." +msgstr "" + +#: src/fe-gtk/menu.c:1311 +#, fuzzy +msgid "Plugins and Scripts..." +msgstr "የተጨማሪው ፕሮግራም ዝርዝር..." + +#: src/fe-gtk/menu.c:1312 +msgid "Raw Log..." +msgstr "" + +#: src/fe-gtk/menu.c:1313 +msgid "URL Grabber..." +msgstr "" + +#: src/fe-gtk/menu.c:1315 +msgid "C_lear Text" +msgstr "ጽሑፉ _ሰርዝ" + +#: src/fe-gtk/menu.c:1316 +msgid "Search Text..." +msgstr "ጽሑፉን አስስ..." + +#: src/fe-gtk/menu.c:1317 +msgid "Save Text..." +msgstr "ጽሑፉን አስቀምት..." + +#: src/fe-gtk/menu.c:1319 +msgid "_Help" +msgstr "_መረጃ" + +#: src/fe-gtk/menu.c:1320 +#, fuzzy +msgid "_Contents" +msgstr "አገናኝ" + +#: src/fe-gtk/menu.c:1321 +#, fuzzy +msgid "_About" +msgstr "ውድቅ" + +#: src/fe-gtk/menu.c:1390 +#, fuzzy +msgid "Attach Tab" +msgstr "መክፈቻን አለያይ" + +#: src/fe-gtk/notifygui.c:109 +msgid "User" +msgstr "ተጠቃሚ" + +#: src/fe-gtk/notifygui.c:111 +msgid "Server" +msgstr "ሰርቨር" + +#: src/fe-gtk/notifygui.c:112 +msgid "Last Seen" +msgstr "" + +#: src/fe-gtk/notifygui.c:149 +msgid "Offline" +msgstr "" + +#: src/fe-gtk/notifygui.c:169 +msgid "Never" +msgstr "በፍጹም" + +#: src/fe-gtk/notifygui.c:187 +msgid "Online" +msgstr "ኦንላይን" + +#: src/fe-gtk/notifygui.c:277 +msgid "Enter nickname to add:" +msgstr "" + +#: src/fe-gtk/notifygui.c:293 +msgid "X-Chat: Notify List" +msgstr "" + +#: src/fe-gtk/notifygui.c:306 src/fe-gtk/servlistgui.c:712 +msgid "Add" +msgstr "ጨምር" + +#: src/fe-gtk/notifygui.c:308 +msgid "Remove" +msgstr "አስወግድ" + +#: src/fe-gtk/plugingui.c:76 src/fe-gtk/textgui.c:387 +msgid "Description" +msgstr "መግለጫ" + +#: src/fe-gtk/plugingui.c:151 +msgid "Select a Plugin or Script to load" +msgstr "" + +#: src/fe-gtk/plugingui.c:219 +#, fuzzy +msgid "X-Chat: Plugins and Scripts" +msgstr "የX-ማውሪያ ተጨማሪ ፕሮግራሞች" + +#: src/fe-gtk/plugingui.c:225 +msgid "_Load..." +msgstr "_ጫን..." + +#: src/fe-gtk/plugingui.c:228 +msgid "_UnLoad" +msgstr "_አትጫን" + +#: src/fe-gtk/plugingui.c:232 +#, fuzzy +msgid "_Close" +msgstr "ዝጋ" + +#: src/fe-gtk/rawlog.c:78 +msgid "Save rawlog" +msgstr "" + +#: src/fe-gtk/rawlog.c:94 +#, c-format +msgid "X-Chat: Rawlog (%s)" +msgstr "" + +#: src/fe-gtk/rawlog.c:123 +msgid "Clear rawlog" +msgstr "" + +#: src/fe-gtk/rawlog.c:126 +msgid "Save rawlog..." +msgstr "" + +#: src/fe-gtk/search.c:47 +msgid "The window you opened this Search for doesn't exist anymore." +msgstr "" + +#: src/fe-gtk/search.c:91 +msgid "X-Chat: Search" +msgstr "X-ማውሪያ፦ ፈልግ" + +#: src/fe-gtk/search.c:100 +msgid "Find:" +msgstr "ፈልግ፦" + +#: src/fe-gtk/search.c:114 +msgid "Find" +msgstr "ፈልግ" + +#: src/fe-gtk/search.c:119 +msgid "Close" +msgstr "ዝጋ" + +#: src/fe-gtk/servlistgui.c:161 +#, c-format +msgid "Settings for %s" +msgstr "የ%s ምርጫዎች" + +#: src/fe-gtk/servlistgui.c:202 src/fe-gtk/servlistgui.c:275 +msgid "New Network" +msgstr "አዲስ መረብ" + +#: src/fe-gtk/servlistgui.c:370 +#, c-format +msgid "Really remove network \"%s\" and all its servers?" +msgstr "" + +#: src/fe-gtk/servlistgui.c:407 src/fe-gtk/servlistgui.c:437 +#, c-format +msgid "_Remove \"%s\"" +msgstr "_አስወግድ \"%s\"" + +#: src/fe-gtk/servlistgui.c:414 +msgid "_Add new server" +msgstr "አዲስ ሰርቨርን _ጨምር" + +#: src/fe-gtk/servlistgui.c:444 +#, c-format +msgid "Move \"%s\" _down" +msgstr "\"%s\"ን ወደ_ታች አንቀሳቅስ" + +#: src/fe-gtk/servlistgui.c:451 +#, c-format +msgid "Move \"%s\" _up" +msgstr "\"%s\"ን ወደ_ላይ አንቀሳቅስ" + +#: src/fe-gtk/servlistgui.c:462 +msgid "_Add new network" +msgstr "_አዲስ መረብ ጨምር" + +#: src/fe-gtk/servlistgui.c:826 +msgid "Global User Info" +msgstr "" + +#: src/fe-gtk/servlistgui.c:834 +msgid "Nick Names:" +msgstr "ቅጽል ስሞች፦" + +#: src/fe-gtk/servlistgui.c:853 src/fe-gtk/servlistgui.c:1056 +msgid "User Name:" +msgstr "የተጠቃሚ ስም፦" + +#: src/fe-gtk/servlistgui.c:866 src/fe-gtk/servlistgui.c:1058 +msgid "Real Name:" +msgstr "የውነት ስም፦" + +#: src/fe-gtk/servlistgui.c:908 +msgid "C_onnect" +msgstr "_አገናኝ" + +#: src/fe-gtk/servlistgui.c:916 +msgid "Connect in a _new tab" +msgstr "በአዲስ መክፈቻ _አገናኝ" + +#: src/fe-gtk/servlistgui.c:976 +msgid "Servers" +msgstr "ሰርቨሮች" + +#: src/fe-gtk/servlistgui.c:1014 +msgid "Character Set:" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1054 +msgid "Nick Name:" +msgstr "ቅጽል ስምች፦" + +#: src/fe-gtk/servlistgui.c:1059 +msgid "Server Password:" +msgstr "የሰርቨር ሚስጢራዊ ቃል፦" + +#: src/fe-gtk/servlistgui.c:1061 +msgid "Join Channels:" +msgstr "ጣቢያዎች አትጫን፦" + +#: src/fe-gtk/servlistgui.c:1063 +msgid "Channels to join, separated by commas, but not spaces!" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1064 +msgid "Connect Command:" +msgstr "አገናኝ ትዕዛዝ" + +#: src/fe-gtk/servlistgui.c:1066 +msgid "" +"Command to execute after connecting. Can be used to authenticate to NickServ" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1074 +msgid "Cycle until connected" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1075 +msgid "Use global user info" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1076 +msgid "Use secure SSL" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1077 +msgid "Auto connect at startup" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1078 +msgid "Use a proxy server" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1079 +msgid "Accept invalid cert." +msgstr "" + +#: src/fe-gtk/servlistgui.c:1088 +msgid "Settings for Selected Network" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1128 +msgid "Edit mode" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1135 +msgid "Networks" +msgstr "መረቦች" + +#: src/fe-gtk/servlistgui.c:1180 +msgid "No server list on startup" +msgstr "" + +#: src/fe-gtk/servlistgui.c:1207 +msgid "X-Chat: Server List" +msgstr "X-ማውሪያ፦ የሰርቨር ዝርዝር" + +#: src/fe-gtk/setup.c:80 +msgid "Font:" +msgstr "የፊደል ቅርጽ፦" + +#: src/fe-gtk/setup.c:81 +msgid "Background image:" +msgstr "የመደቡ ምስል፦" + +#: src/fe-gtk/setup.c:82 +msgid "Time stamp format:" +msgstr "" + +#: src/fe-gtk/setup.c:83 +msgid "See strftime manpage for details." +msgstr "" + +#: src/fe-gtk/setup.c:84 +msgid "Time stamp text" +msgstr "" + +#: src/fe-gtk/setup.c:85 +msgid "Transparent background" +msgstr "የሚያሳይ መደብ" + +#: src/fe-gtk/setup.c:86 +msgid "Indent nicks" +msgstr "" + +#: src/fe-gtk/setup.c:87 +msgid "Tint transparency" +msgstr "" + +#: src/fe-gtk/setup.c:88 +msgid "Colored nicks" +msgstr "" + +#: src/fe-gtk/setup.c:89 +msgid "Strip mIRC color" +msgstr "" + +#: src/fe-gtk/setup.c:90 +msgid "Scrollback lines:" +msgstr "" + +#: src/fe-gtk/setup.c:91 +msgid "Tint red:" +msgstr "" + +#: src/fe-gtk/setup.c:92 +msgid "Tint green:" +msgstr "" + +#: src/fe-gtk/setup.c:93 +msgid "Tint blue:" +msgstr "" + +#: src/fe-gtk/setup.c:99 +#, c-format +msgid "Interpret %nnn as an ASCII value" +msgstr "" + +#: src/fe-gtk/setup.c:100 +msgid "Automatic nick completion" +msgstr "" + +#: src/fe-gtk/setup.c:101 +msgid "Interpret %C, %B as Color, Bold etc" +msgstr "" + +#: src/fe-gtk/setup.c:102 src/fe-gtk/setup.c:134 +msgid "Use the Text box font and colors" +msgstr "" + +#: src/fe-gtk/setup.c:103 +msgid "Nick completion suffix:" +msgstr "" + +#: src/fe-gtk/setup.c:109 +msgid "Off" +msgstr "አጥፋ" + +#: src/fe-gtk/setup.c:110 +msgid "Graph" +msgstr "" + +#: src/fe-gtk/setup.c:111 +msgid "Info text" +msgstr "" + +#: src/fe-gtk/setup.c:112 +msgid "Both" +msgstr "ሁለትም" + +#: src/fe-gtk/setup.c:118 +msgid "A-Z, Ops first" +msgstr "" + +#: src/fe-gtk/setup.c:119 +msgid "A-Z" +msgstr "A-Z" + +#: src/fe-gtk/setup.c:120 +msgid "Z-A, Ops last" +msgstr "" + +#: src/fe-gtk/setup.c:121 +msgid "Z-A" +msgstr "Z-A" + +#: src/fe-gtk/setup.c:122 +msgid "Unsorted" +msgstr "" + +#: src/fe-gtk/setup.c:128 +msgid "Lag meter:" +msgstr "" + +#: src/fe-gtk/setup.c:129 +msgid "Throttle meter:" +msgstr "" + +#: src/fe-gtk/setup.c:130 +msgid "Userlist sorted by:" +msgstr "" + +#: src/fe-gtk/setup.c:131 +msgid "Double-click command:" +msgstr "" + +#: src/fe-gtk/setup.c:132 +msgid "Show hostnames in userlist" +msgstr "" + +#: src/fe-gtk/setup.c:133 +msgid "Userlist buttons enabled" +msgstr "" + +#: src/fe-gtk/setup.c:135 +msgid "Resizable userlist" +msgstr "" + +#: src/fe-gtk/setup.c:136 +msgid "Track away-status on channels smaller than:" +msgstr "" + +#: src/fe-gtk/setup.c:142 +msgid "Windows" +msgstr "መስኮቶች" + +#: src/fe-gtk/setup.c:143 src/fe-gtk/setup.c:845 +msgid "Tabs" +msgstr "መክፈቻዎች" + +#: src/fe-gtk/setup.c:149 +msgid "Bottom" +msgstr "ወደ ታች" + +#: src/fe-gtk/setup.c:150 +msgid "Top" +msgstr "ወደ ላይ" + +#: src/fe-gtk/setup.c:151 +msgid "Left" +msgstr "" + +#: src/fe-gtk/setup.c:152 +msgid "Right" +msgstr "" + +#: src/fe-gtk/setup.c:153 +msgid "Hidden" +msgstr "የተደበቀ" + +#: src/fe-gtk/setup.c:159 +msgid "Show tabs at:" +msgstr "" + +#: src/fe-gtk/setup.c:160 +msgid "Open channels in:" +msgstr "" + +#: src/fe-gtk/setup.c:161 +msgid "Open dialogs in:" +msgstr "" + +#: src/fe-gtk/setup.c:162 +msgid "Open utilities in:" +msgstr "" + +#: src/fe-gtk/setup.c:162 +msgid "Open DCC, Ignore, Notify etc, in tabs or windows?" +msgstr "" + +#: src/fe-gtk/setup.c:163 +msgid "Open tab for server messages" +msgstr "" + +#: src/fe-gtk/setup.c:164 +msgid "Open tab for server notices" +msgstr "" + +#: src/fe-gtk/setup.c:165 +msgid "Pop new tabs to front" +msgstr "" + +#: src/fe-gtk/setup.c:166 +msgid "Shorten tabs to:" +msgstr "" + +#: src/fe-gtk/setup.c:166 +msgid "letters." +msgstr "" + +#: src/fe-gtk/setup.c:172 +msgid "Download files to:" +msgstr "" + +#: src/fe-gtk/setup.c:173 +msgid "Move completed files to:" +msgstr "" + +#: src/fe-gtk/setup.c:174 +msgid "DCC IP address:" +msgstr "" + +#: src/fe-gtk/setup.c:175 +msgid "Claim you are at this address when offering files." +msgstr "" + +#: src/fe-gtk/setup.c:176 +msgid "First DCC send port:" +msgstr "" + +#: src/fe-gtk/setup.c:177 +msgid "Last DCC send port:" +msgstr "" + +#: src/fe-gtk/setup.c:178 +msgid "(Leave ports at zero for full range)." +msgstr "" + +#: src/fe-gtk/setup.c:179 +msgid "Auto open DCC send list" +msgstr "" + +#: src/fe-gtk/setup.c:180 +msgid "Convert spaces to underscore" +msgstr "" + +#: src/fe-gtk/setup.c:181 +msgid "In filenames, before sending" +msgstr "" + +#: src/fe-gtk/setup.c:182 +msgid "Auto open DCC chat list" +msgstr "" + +#: src/fe-gtk/setup.c:183 +msgid "Save nickname in filenames" +msgstr "" + +#: src/fe-gtk/setup.c:184 +msgid "Auto open DCC receive list" +msgstr "" + +#: src/fe-gtk/setup.c:185 +msgid "Get my IP from IRC server" +msgstr "" + +#: src/fe-gtk/setup.c:186 +msgid "" +"/WHOIS yourself to find your real address. Use this if you have a 192.168.*." +"* address!" +msgstr "" + +#: src/fe-gtk/setup.c:187 +msgid "Max. send CPS:" +msgstr "" + +#: src/fe-gtk/setup.c:188 src/fe-gtk/setup.c:190 +msgid "Max. speed for one transfer" +msgstr "" + +#: src/fe-gtk/setup.c:189 +msgid "Max. receive CPS:" +msgstr "" + +#: src/fe-gtk/setup.c:191 +msgid "Max. global send CPS:" +msgstr "" + +#: src/fe-gtk/setup.c:192 src/fe-gtk/setup.c:194 +msgid "Max. speed for all traffic" +msgstr "" + +#: src/fe-gtk/setup.c:193 +msgid "Max. global receive CPS:" +msgstr "" + +#: src/fe-gtk/setup.c:195 +msgid "(Leave at zero for full speed file transfers)." +msgstr "" + +#: src/fe-gtk/setup.c:201 +msgid "Default quit message:" +msgstr "" + +#: src/fe-gtk/setup.c:202 +msgid "Default part message:" +msgstr "" + +#: src/fe-gtk/setup.c:203 +msgid "Default away message:" +msgstr "" + +#: src/fe-gtk/setup.c:205 +msgid "(Can be a text file relative to ~/.xchat2/)." +msgstr "" + +#: src/fe-gtk/setup.c:207 +msgid "(Can be a text file relative to config dir)." +msgstr "" + +#: src/fe-gtk/setup.c:209 +msgid "Extra words to highlight on:" +msgstr "" + +#: src/fe-gtk/setup.c:210 +msgid "(Separate multiple words with commas)." +msgstr "" + +#: src/fe-gtk/setup.c:211 +msgid "Show away once" +msgstr "" + +#: src/fe-gtk/setup.c:211 +msgid "Show identical away messages only once" +msgstr "" + +#: src/fe-gtk/setup.c:212 +msgid "Beep on private messages" +msgstr "" + +#: src/fe-gtk/setup.c:213 +msgid "Automatically unmark away" +msgstr "" + +#: src/fe-gtk/setup.c:213 +msgid "Unmark yourself as away before sending messages" +msgstr "" + +#: src/fe-gtk/setup.c:214 +msgid "Beep on channel messages" +msgstr "" + +#: src/fe-gtk/setup.c:215 +msgid "Announce away messages" +msgstr "" + +#: src/fe-gtk/setup.c:215 +msgid "Announce your away messages to all channels" +msgstr "" + +#: src/fe-gtk/setup.c:216 +msgid "Beep on highlighted messages" +msgstr "" + +#: src/fe-gtk/setup.c:217 +msgid "Display MODEs in raw form" +msgstr "" + +#: src/fe-gtk/setup.c:218 +msgid "Whois on notify" +msgstr "" + +#: src/fe-gtk/setup.c:218 +msgid "Sends a /WHOIS when a user comes online in your notify list" +msgstr "" + +#: src/fe-gtk/setup.c:219 +msgid "Hide join/part messages" +msgstr "" + +#: src/fe-gtk/setup.c:219 +msgid "Hide channel join/part messages by default" +msgstr "" + +#: src/fe-gtk/setup.c:220 +msgid "Auto reconnect delay:" +msgstr "" + +#: src/fe-gtk/setup.c:226 +msgid "Log filename mask:" +msgstr "" + +#: src/fe-gtk/setup.c:227 +#, c-format +msgid "(%s=Server %c=Channel %n=Network)." +msgstr "" + +#: src/fe-gtk/setup.c:228 +msgid "Log timestamp format:" +msgstr "" + +#: src/fe-gtk/setup.c:229 +msgid "(See strftime manpage for details)." +msgstr "" + +#: src/fe-gtk/setup.c:230 +msgid "Enable logging of conversations" +msgstr "" + +#: src/fe-gtk/setup.c:231 +msgid "Insert timestamps in logs" +msgstr "" + +#: src/fe-gtk/setup.c:237 +msgid "(Disabled)" +msgstr "(የተበላሸ)" + +#: src/fe-gtk/setup.c:238 +msgid "Wingate" +msgstr "" + +#: src/fe-gtk/setup.c:239 +msgid "Socks4" +msgstr "" + +#: src/fe-gtk/setup.c:240 +msgid "Socks5" +msgstr "" + +#: src/fe-gtk/setup.c:241 +msgid "HTTP" +msgstr "HTTP" + +#: src/fe-gtk/setup.c:247 +msgid "Address to bind to:" +msgstr "" + +#: src/fe-gtk/setup.c:248 +msgid "(Only useful for computers with multiple addresses)." +msgstr "" + +#: src/fe-gtk/setup.c:249 +#, fuzzy +msgid "Proxy server" +msgstr "ሰርቨር" + +#: src/fe-gtk/setup.c:250 +#, fuzzy +msgid "Hostname:" +msgstr "የእንግዳ ተቀባይ ስም" + +#: src/fe-gtk/setup.c:251 +#, fuzzy +msgid "Username:" +msgstr "የተጠቃሚ ስም" + +#: src/fe-gtk/setup.c:252 +#, fuzzy +msgid "Password:" +msgstr "የሰርቨር ሚስጢራዊ ቃል፦" + +#: src/fe-gtk/setup.c:253 +#, fuzzy +msgid "Port:" +msgstr "ፖርት" + +#: src/fe-gtk/setup.c:254 +#, fuzzy +msgid "Type:" +msgstr "DCC ዓይነት" + +#: src/fe-gtk/setup.c:256 +msgid "Authenticate to the proxy server (only HTTP)" +msgstr "" + +#: src/fe-gtk/setup.c:479 +msgid "Select an Image File" +msgstr "" + +#: src/fe-gtk/setup.c:506 +msgid "Select font" +msgstr "የፊደል ቅርጹ ምረጡ" + +#: src/fe-gtk/setup.c:576 +msgid "Browse..." +msgstr "ቃኝ..." + +#: src/fe-gtk/setup.c:720 +msgid "Select color" +msgstr "ቀለም ምረጡ" + +#: src/fe-gtk/setup.c:786 +msgid "mIRC colors:" +msgstr "የmIRC ቀለሞች፦" + +#: src/fe-gtk/setup.c:794 +msgid "Foreground:" +msgstr "ፊት ለፊት፦" + +#: src/fe-gtk/setup.c:795 +msgid "Background:" +msgstr "መደቡ፦" + +#: src/fe-gtk/setup.c:797 +msgid "Mark fore:" +msgstr "" + +#: src/fe-gtk/setup.c:798 +msgid "Mark back:" +msgstr "" + +#: src/fe-gtk/setup.c:800 +msgid "New Data:" +msgstr "አዲስ ዳታ፦" + +#: src/fe-gtk/setup.c:801 +msgid "New Message:" +msgstr "አዲስ መልእክት፦" + +#: src/fe-gtk/setup.c:802 +msgid "Highlight:" +msgstr "አቅልም፦" + +#: src/fe-gtk/setup.c:803 +msgid "Away User:" +msgstr "" + +#: src/fe-gtk/setup.c:841 +msgid "Interface" +msgstr "" + +#: src/fe-gtk/setup.c:842 +msgid "Text box" +msgstr "" + +#: src/fe-gtk/setup.c:843 +msgid "Input box" +msgstr "" + +#: src/fe-gtk/setup.c:844 +msgid "User list" +msgstr "የተጠቃሚ ዝርዝር" + +#: src/fe-gtk/setup.c:846 +msgid "Colors" +msgstr "ቀለሞች" + +#: src/fe-gtk/setup.c:848 +msgid "Chatting" +msgstr "ወሪ" + +#: src/fe-gtk/setup.c:849 +msgid "General" +msgstr "አጠቃላይ" + +#: src/fe-gtk/setup.c:850 +msgid "Logging" +msgstr "" + +#: src/fe-gtk/setup.c:852 +msgid "Network" +msgstr "መረብ" + +#: src/fe-gtk/setup.c:853 +msgid "Network setup" +msgstr "የመረብ ቅንጅት" + +#: src/fe-gtk/setup.c:854 +msgid "File transfers" +msgstr "" + +#: src/fe-gtk/setup.c:959 +msgid "Categories" +msgstr "ምድብ" + +#: src/fe-gtk/setup.c:1085 +msgid "Some settings were changed that require a restart to take full effect." +msgstr "" + +#: src/fe-gtk/setup.c:1112 +msgid "X-Chat: Preferences" +msgstr "X-ማውሪያ፦ ምርጫዎች" + +#: src/fe-gtk/textgui.c:184 +msgid "There was an error parsing the string" +msgstr "" + +#: src/fe-gtk/textgui.c:192 +#, c-format +msgid "This signal is only passed %d args, $%d is invalid" +msgstr "" + +#: src/fe-gtk/textgui.c:304 src/fe-gtk/textgui.c:326 +msgid "Print Texts File" +msgstr "" + +#: src/fe-gtk/textgui.c:382 +msgid "Event" +msgstr "" + +#: src/fe-gtk/textgui.c:384 +msgid "Sound" +msgstr "ድምፅ" + +#: src/fe-gtk/textgui.c:386 +msgid "$ Number" +msgstr "$ ቍጥር" + +#: src/fe-gtk/textgui.c:396 +msgid "Edit Events" +msgstr "" + +#: src/fe-gtk/textgui.c:434 +msgid "Sound file: " +msgstr "የድምፅ ፋይል፦" + +#: src/fe-gtk/textgui.c:469 +msgid "Save As" +msgstr "በሌላ ስም አስቀምጥ" + +#: src/fe-gtk/textgui.c:474 +msgid "Load From" +msgstr "ከ...ጫን" + +#: src/fe-gtk/textgui.c:479 +msgid "Test All" +msgstr "ሁሉም ሙከራ" + +#: src/fe-gtk/urlgrab.c:97 +msgid "URL" +msgstr "" + +#: src/fe-gtk/urlgrab.c:147 +msgid "Select a file to save to" +msgstr "" + +#: src/fe-gtk/urlgrab.c:187 +msgid "X-Chat: URL Grabber" +msgstr "" + +#: src/fe-gtk/urlgrab.c:200 +#, fuzzy +msgid "Clear list" +msgstr "የተጠቃሚ ዝርዝር" + +#: src/fe-gtk/urlgrab.c:202 +msgid "Copy selected URL" +msgstr "" + +#: src/fe-gtk/urlgrab.c:202 +msgid "Copy" +msgstr "" + +#: src/fe-gtk/urlgrab.c:204 +msgid "Save list to a file" +msgstr "" + +#: src/fe-gtk/userlistgui.c:108 +#, c-format +msgid "%d ops, %d total" +msgstr "" + +#~ msgid "Error String" +#~ msgstr "ስህተት ሐረግ" + +#, fuzzy +#~ msgid "Error name" +#~ msgstr "ስህተት" + +#~ msgid "Error string" +#~ msgstr "ስህተት ሐረግ" + +#~ msgid "Yes" +#~ msgstr "አዎ" + +#~ msgid "No" +#~ msgstr "አይ" + +#~ msgid "OK" +#~ msgstr "እሺ" + +#~ msgid "port" +#~ msgstr "ፖርት" + +#~ msgid "Load plugin..." +#~ msgstr "የተጨማሪው ፕሮግራምን ጫን..." + +#~ msgid "X-Chat Homepage..." +#~ msgstr "የX-ማውሪያ ማነሻ ገጽ..." + +#~ msgid "About X-Chat..." +#~ msgstr "ስለ X-ማውሪያ..." diff --git a/po/az.po b/po/az.po new file mode 100644 index 00000000..36389e21 --- /dev/null +++ b/po/az.po @@ -0,0 +1,4808 @@ +# translation of xchat-2.0.7pre1.po to Azerbaijani Turkish +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is put in the public domain. +# Metin Amiroff , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: xchat-2.0.7pre1\n" +"Report-Msgid-Bugs-To: www.xchat.org\n" +"POT-Creation-Date: 2004-03-14 16:11+1100\n" +"PO-Revision-Date: 2004-03-12 22:22+0200\n" +"Last-Translator: Metin Amiroff \n" +"Language-Team: Azerbaijani \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/common/cfgfiles.c:342 +msgid "Cannot create ~/.xchat2" +msgstr "~/.xchat2 yaradıla bilmir" + +#: src/common/cfgfiles.c:639 +msgid "I'm busy" +msgstr "Məşğulam" + +#: src/common/cfgfiles.c:640 +msgid "Leaving" +msgstr "Gedirəm" + +#: src/common/cfgfiles.c:684 +msgid "" +"* Running IRC as root is stupid! You should\n" +" create a User Account and use that to login.\n" +msgstr "" +"IRC-ni Ali İstifadəçi olaraq işlətmək dəlilikdir.\n" +" Xahiş edirik istifadəçi hesabı yaradın.\n" + +#: src/common/dcc.c:60 +msgid "Waiting" +msgstr "Gözləyir" + +#: src/common/dcc.c:61 +msgid "Active" +msgstr "Fəal" + +#: src/common/dcc.c:62 +msgid "Failed" +msgstr "Bacarılmadı" + +#: src/common/dcc.c:63 +msgid "Done" +msgstr "Oldu" + +#: src/common/dcc.c:64 +msgid "Connect" +msgstr "Bağlan" + +#: src/common/dcc.c:65 +msgid "Aborted" +msgstr "Ləğv Edildi" + +#: src/common/dcc.c:1254 +#, c-format +msgid "Cannot access %s\n" +msgstr "%s ünvanına yetişilə bilmir\n" + +#: src/common/dcc.c:1849 +msgid "No active DCCs\n" +msgstr "Fəal DCC-lər yoxdur\n" + +#: src/common/ignore.c:120 src/common/ignore.c:124 src/common/ignore.c:128 +#: src/common/ignore.c:132 src/common/ignore.c:136 src/common/ignore.c:140 +#: src/common/ignore.c:144 +msgid "YES " +msgstr "BƏLİ " + +#: src/common/ignore.c:122 src/common/ignore.c:126 src/common/ignore.c:130 +#: src/common/ignore.c:134 src/common/ignore.c:138 src/common/ignore.c:142 +#: src/common/ignore.c:146 +msgid "NO " +msgstr "XEYİR " + +#: src/common/ignore.c:373 +#, c-format +msgid "You are being CTCP flooded from %s, ignoring %s\n" +msgstr "" + +#: src/common/ignore.c:398 +#, c-format +msgid "You are being MSG flooded from %s, setting autodialog OFF.\n" +msgstr "" + +#: src/common/notify.c:400 +#, c-format +msgid " %-20s online\n" +msgstr " %-20s xətdədir\n" + +#: src/common/notify.c:402 +#, c-format +msgid " %-20s offline\n" +msgstr " %-20s xətdə deyil\n" + +#: src/common/outbound.c:70 +msgid "No channel joined. Try /join #\n" +msgstr "Heç bir kanalda deyilsiniz. /join # əmrini verin\n" + +#: src/common/outbound.c:76 +msgid "Not connected. Try /server []\n" +msgstr "Bağlı deyilsiniz. /server [] əmrini verin\n" + +#: src/common/outbound.c:1356 +msgid "I need /bin/sh to run!\n" +msgstr "/bin/sh əmrini icra etməliyəm!\n" + +#: src/common/outbound.c:1597 +msgid "" +"\n" +"Commands Available:\n" +"\n" +" " +msgstr "" +"\n" +"Mövcud Əmrlər:\n" +"\n" +" " + +#: src/common/outbound.c:1632 +msgid "" +"\n" +"\n" +"Type /HELP for more information, or /HELP -l\n" +"\n" +msgstr "" +"\n" +"\n" +"Daha çox mə'lumat üçün /HELP <əmr> ya da or /HELP -l yazın\n" +"\n" + +#: src/common/outbound.c:1633 +msgid "" +"User defined commands:\n" +"\n" +" " +msgstr "" +"İstifadəçi tə'yinli əmrlər:\n" +"\n" +" " + +#: src/common/outbound.c:1725 +#, c-format +msgid "Unknown arg '%s' ignored." +msgstr "" + +#: src/common/outbound.c:2435 +msgid "No such plugin found.\n" +msgstr "" + +#: src/common/outbound.c:2440 src/fe-gtk/plugingui.c:182 +msgid "That plugin is refusing to unload.\n" +msgstr "" + +#: src/common/outbound.c:2585 +msgid "ADDBUTTON , adds a button under the user-list" +msgstr "" + +#: src/common/outbound.c:2587 +msgid "ALLCHAN , sends a command to all channels you're in" +msgstr "" + +#: src/common/outbound.c:2589 +msgid "ALLSERV , sends a command to all servers you're in" +msgstr "" + +#: src/common/outbound.c:2590 +msgid "AWAY [], sets you away" +msgstr "" + +#: src/common/outbound.c:2592 +msgid "" +"BAN [], bans everyone matching the mask from the current " +"channel. If they are already on the channel this doesn't kick them (needs " +"chanop)" +msgstr "" + +#: src/common/outbound.c:2594 +msgid "CLEAR, Clears the current text window" +msgstr "" + +#: src/common/outbound.c:2595 +msgid "CLOSE, Closes the current window/tab" +msgstr "" + +#: src/common/outbound.c:2598 +msgid "COUNTRY , finds a country code, eg: au = australia" +msgstr "" + +#: src/common/outbound.c:2600 +msgid "" +"CTCP , send the CTCP message to nick, common messages are " +"VERSION and USERINFO" +msgstr "" + +#: src/common/outbound.c:2602 +msgid "CYCLE, parts current channel and immediately rejoins" +msgstr "" + +#: src/common/outbound.c:2604 +msgid "" +"\n" +"DCC GET - accept an offered file\n" +"DCC SEND [-maxcps=#] [file] - send a file to someone\n" +"DCC LIST - show DCC list\n" +"DCC CHAT - offer DCC CHAT to someone\n" +"DCC CLOSE example:\n" +" /dcc close send johnsmith file.tar.gz" +msgstr "" + +#: src/common/outbound.c:2614 +msgid "" +"DEHOP , removes chanhalf-op status from the nick on the current " +"channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2616 +msgid "DELBUTTON , deletes a button from under the user-list" +msgstr "" + +#: src/common/outbound.c:2618 +msgid "" +"DEOP , removes chanop status from the nick on the current channel " +"(needs chanop)" +msgstr "" + +#: src/common/outbound.c:2620 +msgid "" +"DEVOICE , removes voice status from the nick on the current channel " +"(needs chanop)" +msgstr "" + +#: src/common/outbound.c:2621 +msgid "DISCON, Disconnects from server" +msgstr "" + +#: src/common/outbound.c:2622 +msgid "DNS , Finds a users IP number" +msgstr "" + +#: src/common/outbound.c:2623 +msgid "ECHO , Prints text locally" +msgstr "" + +#: src/common/outbound.c:2626 +msgid "" +"EXEC [-o] , runs the command. If -o flag is used then output is " +"sent to current channel, else is printed to current text box" +msgstr "" + +#: src/common/outbound.c:2628 +msgid "EXECCONT, sends the process SIGCONT" +msgstr "" + +#: src/common/outbound.c:2631 +msgid "" +"EXECKILL [-9], kills a running exec in the current session. If -9 is given " +"the process is SIGKILL'ed" +msgstr "" + +#: src/common/outbound.c:2633 +msgid "EXECSTOP, sends the process SIGSTOP" +msgstr "" + +#: src/common/outbound.c:2634 +msgid "EXECWRITE, sends data to the processes stdin" +msgstr "" + +#: src/common/outbound.c:2638 +msgid "FLUSHQ, flushes the current server's send queue" +msgstr "" + +#: src/common/outbound.c:2640 +msgid "GATE [], proxies through a host, port defaults to 23" +msgstr "" + +#: src/common/outbound.c:2646 +msgid "HOP , gives chanhalf-op status to the nick (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2648 +msgid "" +"IGNORE \n" +" mask - host mask to ignore, eg: *!*@*.aol.com\n" +" types - types of data to ignore, one or all of:\n" +" PRIV, CHAN, NOTI, CTCP, DCC, INVI, ALL\n" +" options - NOSAVE, QUIET" +msgstr "" + +#: src/common/outbound.c:2655 +msgid "" +"INVITE [], invites someone to a channel, by default the " +"current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2656 +msgid "JOIN , joins the channel" +msgstr "" + +#: src/common/outbound.c:2658 +msgid "KICK , kicks the nick from the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2660 +msgid "" +"KICKBAN , bans then kicks the nick from the current channel (needs " +"chanop)" +msgstr "" + +#: src/common/outbound.c:2663 +msgid "LAGCHECK, forces a new lag check" +msgstr "" + +#: src/common/outbound.c:2665 +msgid "LASTLOG , searches for a string in the buffer" +msgstr "" + +#: src/common/outbound.c:2667 +msgid "LOAD , loads a plugin or script" +msgstr "" + +#: src/common/outbound.c:2670 +msgid "" +"MDEHOP, Mass deop's all chanhalf-ops in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2672 +msgid "MDEOP, Mass deop's all chanops in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2674 +msgid "" +"ME , sends the action to the current channel (actions are written in " +"the 3rd person, like /me jumps)" +msgstr "" + +#: src/common/outbound.c:2676 +msgid "" +"MKICK, Mass kicks everyone except you in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2678 +msgid "MOP, Mass op's all users in the current channel (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2679 +msgid "MSG , sends a private message" +msgstr "" + +#: src/common/outbound.c:2682 +msgid "NAMES, Lists the nicks on the current channel" +msgstr "" + +#: src/common/outbound.c:2684 +msgid "NCTCP , Sends a CTCP notice" +msgstr "" + +#: src/common/outbound.c:2685 +msgid "NEWSERVER []" +msgstr "" + +#: src/common/outbound.c:2686 +msgid "NICK , sets your nick" +msgstr "" + +#: src/common/outbound.c:2689 +msgid "" +"NOTICE , sends a notice. Notices are a type of " +"message that should be auto reacted to" +msgstr "" + +#: src/common/outbound.c:2691 +msgid "NOTIFY [], lists your notify list or adds someone to it" +msgstr "" + +#: src/common/outbound.c:2693 +msgid "OP , gives chanop status to the nick (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2695 +msgid "" +"PART [] [], leaves the channel, by default the current one" +msgstr "" + +#: src/common/outbound.c:2697 +msgid "PING , CTCP pings nick or channel" +msgstr "" + +#: src/common/outbound.c:2699 +msgid "QUERY , opens up a new privmsg window to someone" +msgstr "" + +#: src/common/outbound.c:2701 +msgid "QUIT [], disconnects from the current server" +msgstr "" + +#: src/common/outbound.c:2703 +msgid "QUOTE , sends the text in raw form to the server" +msgstr "" + +#: src/common/outbound.c:2706 +msgid "" +"RECONNECT [-ssl] [] [] [], Can be called just as /" +"RECONNECT to reconnect to the current server or with /RECONNECT ALL to " +"reconnect to all the open servers" +msgstr "" + +#: src/common/outbound.c:2709 +msgid "" +"RECONNECT [] [] [], Can be called just as /RECONNECT " +"to reconnect to the current server or with /RECONNECT ALL to reconnect to " +"all the open servers" +msgstr "" + +#: src/common/outbound.c:2711 +msgid "" +"RECV , send raw data to xchat, as if it was received from the irc " +"server" +msgstr "" + +#: src/common/outbound.c:2714 +msgid "SAY , sends the text to the object in the current window" +msgstr "" + +#: src/common/outbound.c:2717 +msgid "SERVCHAN [-ssl] , connects and joins a channel" +msgstr "" + +#: src/common/outbound.c:2720 +msgid "SERVCHAN , connects and joins a channel" +msgstr "" + +#: src/common/outbound.c:2724 +msgid "" +"SERVER [-ssl] [] [], connects to a server, the " +"default port is 6667 for normal connections, and 9999 for ssl connections" +msgstr "" + +#: src/common/outbound.c:2727 +msgid "" +"SERVER [] [], connects to a server, the default port " +"is 6667" +msgstr "" + +#: src/common/outbound.c:2729 +msgid "SET []" +msgstr "" + +#: src/common/outbound.c:2732 +msgid "" +"TOPIC [], sets the topic if one is given, else shows the current topic" +msgstr "" + +#: src/common/outbound.c:2734 +msgid "UNBAN [...], unbans the specified masks." +msgstr "" + +#: src/common/outbound.c:2735 +msgid "UNIGNORE [QUIET]" +msgstr "" + +#: src/common/outbound.c:2736 +msgid "UNLOAD , unloads a plugin or script" +msgstr "" + +#: src/common/outbound.c:2739 +msgid "VOICE , gives voice status to someone (needs chanop)" +msgstr "" + +#: src/common/outbound.c:2741 +msgid "WALLCHAN , writes the message to all channels" +msgstr "" + +#: src/common/outbound.c:2743 +msgid "" +"WALLCHOP , sends the message to all chanops on the current channel" +msgstr "" + +#: src/common/outbound.c:2776 +#, c-format +msgid "Usage: %s\n" +msgstr "İstifadə Qaydası: %s\n" + +#: src/common/outbound.c:2781 +msgid "" +"\n" +"No help available on that command.\n" +msgstr "" +"\n" +"Bu əmrlə əlaqəli yardım mövcud deyil.\n" + +#: src/common/outbound.c:2787 +msgid "No such command.\n" +msgstr "Belə əmr yoxdur.\n" + +#: src/common/outbound.c:3111 +msgid "Bad arguments for user command.\n" +msgstr "" + +#: src/common/outbound.c:3275 +msgid "Too many recursive usercommands, aborting." +msgstr "" + +#: src/common/outbound.c:3348 +msgid "Unknown Command. Try /help\n" +msgstr "Namə'lum Əmr. Yardım üçün /help əmrini verin\n" + +#: src/common/plugin.c:353 src/common/plugin.c:383 +msgid "No xchat_plugin_init symbol; is this really an xchat plugin?" +msgstr "" + +#: src/common/server.c:888 +#, c-format +msgid "" +"Cannot resolve hostname %s\n" +"Check your IP Settings!\n" +msgstr "" +"%s qovşaq adı tapıla bilmir\n" +"IP qurğularınızı yoxlayın!\n" + +#: src/common/server.c:893 +msgid "Proxy traversal failed.\n" +msgstr "Vəkil traversalı bacarılmadı.\n" + +#: src/common/servlist.c:633 +#, c-format +msgid "Cycling to next server in %s...\n" +msgstr "%s üstündəki növbəti vericiyə keçilir...\n" + +#: src/common/servlist.c:973 +#, c-format +msgid "" +"Warning: \"%s\" character set is unknown. No conversion will be applied for " +"network %s." +msgstr "" + +#: src/common/textevents.h:6 +msgid "-%C10-%C11-%O$t$1 added to notify list." +msgstr "" + +#: src/common/textevents.h:9 +msgid "-%C10-%C11-%O$t$1 Banlist: %C3$4 %C4$2 %C5$3%O" +msgstr "" + +#: src/common/textevents.h:12 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(You are banned)." +msgstr "" + +#: src/common/textevents.h:15 +msgid "-%C10-%C11-%O$t$1 is now known as $2" +msgstr "" + +#: src/common/textevents.h:18 +msgid "%C13*%O$t$1%O $2%O" +msgstr "" + +#: src/common/textevents.h:21 +msgid "%C13*%O$t%C8%B$1%B%O $2%O" +msgstr "" + +#: src/common/textevents.h:24 +msgid "-%C10-%C11-%O$t$1 sets ban on $2" +msgstr "" + +#: src/common/textevents.h:27 +msgid "-%C10-%C11-%O$tChannel $1 created on $2" +msgstr "" + +#: src/common/textevents.h:30 +msgid "" +"-%C10-%C11-%O$t%C11$1%O removes channel half-operator status from %C11$2" +msgstr "" + +#: src/common/textevents.h:33 +msgid "-%C10-%C11-%O$t%C11$1%O removes channel operator status from %C11$2" +msgstr "" + +#: src/common/textevents.h:36 +msgid "-%C10-%C11-%O$t%C11$1%O removes voice from %C11$2" +msgstr "" + +#: src/common/textevents.h:39 +msgid "-%C10-%C11-%O$t$1 sets exempt on $2" +msgstr "" + +#: src/common/textevents.h:42 +msgid "-%C10-%C11-%O$t%C11$1%O gives channel half-operator status to %C11$2" +msgstr "" + +#: src/common/textevents.h:45 +msgid "-%C10-%C11-%O$t$1 sets invite on $2" +msgstr "" + +#: src/common/textevents.h:48 +msgid "%UChannel Users Topic%O" +msgstr "%UKanalı İstifadəçi Mövzu%O" + +#: src/common/textevents.h:51 src/common/textevents.h:297 +msgid "%C2<%O$1%C2>%O$t$2%O" +msgstr "%C2<%O$1%C2>%O$t$2%O" + +#: src/common/textevents.h:54 +msgid "-%C10-%C11-%O$t$1 sets mode $2$3 $4" +msgstr "" + +#: src/common/textevents.h:57 +msgid "-%C10-%C11-%O$tChannel $1 modes: $2" +msgstr "" + +#: src/common/textevents.h:60 +msgid "%C2<%C8%B$1%B%C2>%O$t$2%O" +msgstr "%C2<%C8%B$1%B%C2>%O$t$2%O" + +#: src/common/textevents.h:63 +msgid "%C12-%C13$1/$2%C12-%O$t$3%O" +msgstr "%C12-%C13$1/$2%C12-%O$t$3%O" + +#: src/common/textevents.h:66 +msgid "-%C10-%C11-%O$t%C11$1%O gives channel operator status to %C11$2" +msgstr "" + +#: src/common/textevents.h:69 +msgid "-%C10-%C11-%O$t$1 removes exempt on $2" +msgstr "" + +#: src/common/textevents.h:72 +msgid "-%C10-%C11-%O$t$1 removes invite on $2" +msgstr "" + +#: src/common/textevents.h:75 +msgid "-%C10-%C11-%O$t$1 removes channel keyword" +msgstr "" + +#: src/common/textevents.h:78 +msgid "-%C10-%C11-%O$t$1 removes user limit" +msgstr "" + +#: src/common/textevents.h:81 +msgid "-%C10-%C11-%O$t$1 sets channel keyword to $2" +msgstr "" + +#: src/common/textevents.h:84 +msgid "-%C10-%C11-%O$t$1 sets channel limit to $2" +msgstr "" + +#: src/common/textevents.h:87 +msgid "-%C10-%C11-%O$t$1 removes ban on $2" +msgstr "" + +#: src/common/textevents.h:90 +msgid "-%C10-%C11-%O$t%C11$1%O gives voice to %C11$2" +msgstr "" + +#: src/common/textevents.h:93 +msgid "-%C10-%C11-%O$tConnected. Now logging in.." +msgstr "" + +#: src/common/textevents.h:96 +msgid "-%C10-%C11-%O$tConnecting to %C11$1 %C14(%C11$2%C14)%C port %C11$3%C.." +msgstr "" + +#: src/common/textevents.h:99 +msgid "-%C10-%C11-%O$tConnection failed. Error: $1" +msgstr "" + +#: src/common/textevents.h:102 +msgid "-%C10-%C11-%O$tReceived a CTCP $1 from $2" +msgstr "" + +#: src/common/textevents.h:105 +msgid "-%C10-%C11-%O$tReceived a CTCP $1 from $2 (to $3)" +msgstr "" + +#: src/common/textevents.h:108 +msgid "%C3>%O$1%C3<%O$tCTCP $2%O" +msgstr "%C3>%O$1%C3<%O$tCTCP $2%O" + +#: src/common/textevents.h:111 +msgid "-%C10-%C11-%O$tReceived a CTCP Sound $1 from $2" +msgstr "" + +#: src/common/textevents.h:114 +msgid "-%C10-%C11-%O$tDCC CHAT to %C11$1%O aborted." +msgstr "" + +#: src/common/textevents.h:117 +msgid "" +"-%C10-%C11-%O$tDCC CHAT connection established to %C11$1 %C14[%O$2%C14]%O" +msgstr "" + +#: src/common/textevents.h:120 +msgid "-%C10-%C11-%O$tDCC CHAT to %C11$1%O lost. $4." +msgstr "" + +#: src/common/textevents.h:123 +msgid "-%C10-%C11-%O$tReceived a DCC CHAT offer from $1" +msgstr "" + +#: src/common/textevents.h:126 +msgid "-%C10-%C11-%O$tOffering DCC CHAT to $1" +msgstr "" + +#: src/common/textevents.h:129 +msgid "-%C10-%C11-%O$tAlready offering CHAT to $1" +msgstr "" + +#: src/common/textevents.h:132 +msgid "-%C10-%C11-%O$tDCC $1 connect attempt to %C11$2%O failed (err=$3)." +msgstr "" + +#: src/common/textevents.h:135 +msgid "-%C10-%C11-%O$tReceived '$1%O' from $2" +msgstr "" + +#: src/common/textevents.h:138 +msgid "" +"%C8,2 Type To/From Status Size Pos File %O%010%B%" +"C9----------------------------------------------------%O" +msgstr "" + +#: src/common/textevents.h:141 +msgid "" +"-%C10-%C11-%O$tReceived a malformed DCC request from %C11$1%O.%010-%C10-%C11-" +"%O$tContents of packet: $2" +msgstr "" + +#: src/common/textevents.h:144 +msgid "-%C10-%C11-%O$tOffering %C11$1 %Cto %C11$2%O" +msgstr "" + +#: src/common/textevents.h:147 +msgid "-%C10-%C11-%O$tNo such DCC offer." +msgstr "" + +#: src/common/textevents.h:150 +msgid "-%C10-%C11-%O$tDCC RECV %C11$2%O to %C11$1%O aborted." +msgstr "" + +#: src/common/textevents.h:153 +msgid "" +"-%C10-%C11-%O$tDCC RECV %C11$1%O from %C11$3%O complete %C14[%C11$4%O cps%" +"C14]%O." +msgstr "" + +#: src/common/textevents.h:156 +msgid "" +"-%C10-%C11-%O$tDCC RECV connection established to %C11$1 %C14[%O$2%C14]%O" +msgstr "" + +#: src/common/textevents.h:159 +msgid "-%C10-%C11-%O$tDCC RECV %C11$1%O from %C11$3%O failed. $4." +msgstr "" + +#: src/common/textevents.h:162 +msgid "-%C10-%C11-%O$tDCC RECV: Cannot open $1 for writing ($2)." +msgstr "" + +#: src/common/textevents.h:165 +msgid "" +"-%C10-%C11-%O$tThe file %C11$1%C already exists, saving it as %C11$2%O " +"instead." +msgstr "" + +#: src/common/textevents.h:168 +msgid "-%C10-%C11-%O$t%C11$1 %Chas requested to resume %C11$2 %Cfrom %C11$3%C." +msgstr "" + +#: src/common/textevents.h:171 +msgid "-%C10-%C11-%O$tDCC SEND %C11$2%O to %C11$1%O aborted." +msgstr "" + +#: src/common/textevents.h:174 +msgid "" +"-%C10-%C11-%O$tDCC SEND %C11$1%O to %C11$2%O complete %C14[%C11$3%O cps%C14]%" +"O." +msgstr "" + +#: src/common/textevents.h:177 +msgid "" +"-%C10-%C11-%O$tDCC SEND connection established to %C11$1 %C14[%O$2%C14]%O" +msgstr "" + +#: src/common/textevents.h:180 +msgid "-%C10-%C11-%O$tDCC SEND %C11$1%O to %C11$2%O failed. $3" +msgstr "" + +#: src/common/textevents.h:183 +msgid "-%C10-%C11-%O$t%C11$1 %Chas offered %C11$2 %C(%C11$3 %Cbytes)" +msgstr "" + +#: src/common/textevents.h:186 +msgid "-%C10-%C11-%O$tDCC $1 %C11$2 %Cto %C11$3 %Cstalled - aborting." +msgstr "" + +#: src/common/textevents.h:189 +msgid "-%C10-%C11-%O$tDCC $1 %C11$2 %Cto %C11$3 %Ctimed out - aborting." +msgstr "" + +#: src/common/textevents.h:192 +msgid "-%C10-%C11-%O$t$1 deleted from notify list." +msgstr "" + +#: src/common/textevents.h:195 +msgid "-%C10-%C11-%O$tDisconnected ($1)." +msgstr "-%C10-%C11-%O$tBağlantı kəsildi ($1)." + +#: src/common/textevents.h:198 +msgid "-%C10-%C11-%O$tFound your IP: [$1]" +msgstr "" + +#: src/common/textevents.h:201 +msgid "$1$t$2" +msgstr "$1$t$2" + +#: src/common/textevents.h:204 +msgid "%O%C11$1%O added to ignore list." +msgstr "" + +#: src/common/textevents.h:207 +msgid "Ignore on %C11$1%O changed." +msgstr "" + +#: src/common/textevents.h:210 +msgid "%C08,02 %O" +msgstr "" +"%C08,02 %O" + +#: src/common/textevents.h:213 +msgid "%C08,02 Hostmask PRIV NOTI CHAN CTCP DCC INVI UNIG %O" +msgstr "" +"%C08,02 Hostmask PRIV NOTI CHAN CTCP DCC INVI UNIG %O" + +#: src/common/textevents.h:216 +msgid "%O%C11$1%O removed from ignore list." +msgstr "%O%C11$1%O rədd siyahısından silindi." + +#: src/common/textevents.h:219 +msgid " Ignore list is empty." +msgstr " Rədd siyahısı boşdur." + +#: src/common/textevents.h:222 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(Channel is invite only)." +msgstr "" + +#: src/common/textevents.h:225 +msgid "-%C10-%C11-%O$tYou have been invited to %C11$1%C by %C11$2%C (%C11$3%C)" +msgstr "" + +#: src/common/textevents.h:228 +msgid "-%C10-%C11>%O$t%B$1%B %C14(%C10$3%C14)%C has joined $2" +msgstr "" + +#: src/common/textevents.h:231 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(Requires keyword)." +msgstr "" + +#: src/common/textevents.h:234 +msgid "<%C10-%C11-%O$t$1 has kicked $2 from $3 ($4%O)" +msgstr "" + +#: src/common/textevents.h:237 +msgid "-%C10-%C11-%O$tYou have been killed by $1 ($2%O)" +msgstr "" + +#: src/common/textevents.h:240 src/common/textevents.h:264 +msgid "%C3>%O$1%C3<%O$t$2%O" +msgstr "%C3>%O$1%C3<%O$t$2%O" + +#: src/common/textevents.h:243 src/common/textevents.h:318 +#: src/common/textevents.h:324 src/common/textevents.h:327 +msgid "-%C10-%C11-%O$t$1%O" +msgstr "-%C10-%C11-%O$t$1%O" + +#: src/common/textevents.h:246 +msgid "-%C10-%C11-%O$tMOTD Skipped." +msgstr "" + +#: src/common/textevents.h:249 +msgid "-%C10-%C11-%O$t$1 already in use. Retrying with $2.." +msgstr "" + +#: src/common/textevents.h:252 +msgid "-%C10-%C11-%O$tNickname already in use. Use /NICK to try another." +msgstr "" + +#: src/common/textevents.h:255 +msgid "-%C10-%C11-%O$tNo such DCC." +msgstr "" + +#: src/common/textevents.h:258 +msgid "-%C10-%C11-%O$tNo process is currently running" +msgstr "" + +#: src/common/textevents.h:261 +msgid "%C12-%C13$1%C12-%O$t$2%O" +msgstr "%C12-%C13$1%C12-%O$t$2%O" + +#: src/common/textevents.h:267 +msgid "-%C10-%C11-%O$tNotify list is empty." +msgstr "" + +#: src/common/textevents.h:270 +msgid "%C08,02 %B-- Notify List --------------- %O" +msgstr "" + +#: src/common/textevents.h:273 +msgid "-%C10-%C11-%O$t$1 users in notify list." +msgstr "" + +#: src/common/textevents.h:276 +msgid "-%C10-%C11-%O$tNotify: $1 is offline ($2)." +msgstr "" + +#: src/common/textevents.h:279 +msgid "-%C10-%C11-%O$tNotify: $1 is online ($2)." +msgstr "" + +#: src/common/textevents.h:282 +msgid "<%C10-%C11-%O$t$1 %C14(%O$2%C14)%C has left $3" +msgstr "" + +#: src/common/textevents.h:285 +msgid "<%C10-%C11-%O$t$1 %C14(%O$2%C14)%C has left $3 %C14(%O$4%C14)%O" +msgstr "" + +#: src/common/textevents.h:288 +msgid "-%C10-%C11-%O$tPing reply from $1 : $2 second(s)" +msgstr "" + +#: src/common/textevents.h:291 +msgid "-%C10-%C11-%O$tNo ping reply for $1 seconds, disconnecting." +msgstr "" + +#: src/common/textevents.h:294 +msgid "%C12*%C13$1%C12*$t%O$2%O" +msgstr "%C12*%C13$1%C12*$t%O$2%O" + +#: src/common/textevents.h:300 +msgid "-%C10-%C11-%O$tA process is already running" +msgstr "" + +#: src/common/textevents.h:303 +msgid "<%C10-%C11-%O$t$1 has quit %C14(%O$2%O%C14)%O" +msgstr "" + +#: src/common/textevents.h:306 +msgid "-%C10-%C11-%O$t$1 sets modes%B %C14[%O$2%B%C14]%O" +msgstr "" + +#: src/common/textevents.h:309 +msgid "%C12-%C13$1/Wallops%C12-%O$t$2%O" +msgstr "" + +#: src/common/textevents.h:312 +msgid "-%C10-%C11-%O$tLooking up IP number for%C11 $1%O.." +msgstr "" + +#: src/common/textevents.h:315 +msgid "-%C10-%C11-%O$tConnected." +msgstr "" + +#: src/common/textevents.h:321 +msgid "-%C10-%C11-%O$tLooking up %C11$1%C.." +msgstr "" + +#: src/common/textevents.h:330 +msgid "-%C10-%C11-%O$tStopped previous connection attempt (pid=$1)" +msgstr "" + +#: src/common/textevents.h:333 +msgid "-%C10-%C11-%O$tTopic for %C11$1%C is %C11$2%O" +msgstr "" + +#: src/common/textevents.h:336 +msgid "-%C10-%C11-%O$tTopic for %C11$1%C set by %C11$2%C at %C11$3%O" +msgstr "" + +#: src/common/textevents.h:339 +msgid "-%C10-%C11-%O$t$1 has changed the topic to: $2%O" +msgstr "" + +#: src/common/textevents.h:342 +msgid "-%C10-%C11-%O$tUnknown host. Maybe you misspelled it?" +msgstr "-%C10-%C11-%O$tNamə'lum qovşaq. Bəlkə onu səhv yazmışsınız?" + +#: src/common/textevents.h:345 +msgid "-%C10-%C11-%O$tCannot join%C11 %B$1 %O(User limit reached)." +msgstr "" + +#: src/common/textevents.h:348 +msgid "-%C10-%C11-%O$t%C11Users on $1:%C $2" +msgstr "" + +#: src/common/textevents.h:351 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %Cis away %C14(%O$2%O%C14)" +msgstr "" + +#: src/common/textevents.h:354 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%C $2" +msgstr "" + +#: src/common/textevents.h:357 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %CEnd of WHOIS list." +msgstr "" + +#: src/common/textevents.h:360 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %O$2" +msgstr "" + +#: src/common/textevents.h:363 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %O$2 %C11$3%O" +msgstr "" + +#: src/common/textevents.h:366 +msgid "" +"-%C10-%C11-%O$t%C12[%O$1%C12] %Oreal user@host %C11$2%O, real IP %C11$3%O" +msgstr "" + +#: src/common/textevents.h:369 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%O idle %C11$2%O" +msgstr "" + +#: src/common/textevents.h:372 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%O idle %C11$2%O, signon: %C11$3%O" +msgstr "" + +#: src/common/textevents.h:375 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12] %C14(%O$2@$3%C14) %O: $4%O" +msgstr "" + +#: src/common/textevents.h:378 +msgid "-%C10-%C11-%O$t%C12[%O$1%C12]%O $2" +msgstr "" + +#: src/common/textevents.h:381 +msgid "-%C10-%C11>%O$t%BYou%B are now talking on %C11$2%O" +msgstr "" + +#: src/common/textevents.h:384 +msgid "-%C10-%C11-%O$tYou have left channel $3" +msgstr "" + +#: src/common/textevents.h:387 +msgid "-%C10-%C11-%O$tYou have left channel $3 %C14(%O$4%C14)%O" +msgstr "" + +#: src/common/textevents.h:390 +msgid "-%C10-%C11-%O$tYou have been kicked from $2 by $3 ($4%O)" +msgstr "" + +#: src/common/textevents.h:393 +msgid "-%C10-%C11-%O$tYou're inviting %C11$1%C to %C11$2%C (%C11$3%C)" +msgstr "" + +#: src/common/textevents.h:396 +msgid "%C6<%O$1%C6>%O$t$2%O" +msgstr "%C6<%O$1%C6>%O$t$2%O" + +#: src/common/textevents.h:399 +msgid "-%C10-%C11-%O$tYou are now known as $2" +msgstr "" + +#: src/common/text.c:304 +#, c-format +msgid "**** ENDING LOGGING AT %s\n" +msgstr "" + +#: src/common/text.c:421 +#, c-format +msgid "**** BEGIN LOGGING AT %s\n" +msgstr "" + +#: src/common/text.c:440 +#, c-format +msgid "" +"* Can't open log file(s) for writing. Check the\n" +" permissions on %s/xchatlogs" +msgstr "" + +#: src/common/text.c:651 +msgid "Left message" +msgstr "Sol ismarış" + +#: src/common/text.c:652 +msgid "Right message" +msgstr "Sağ ismarış" + +#: src/common/text.c:656 +msgid "The nick of the joining person" +msgstr "Daxil olan şəxsin ləqəbi" + +#: src/common/text.c:657 +msgid "The channel being joined" +msgstr "Daxil olunan kanal" + +#: src/common/text.c:658 src/common/text.c:702 src/common/text.c:758 +msgid "The host of the person" +msgstr "Şəxsin qovşağı" + +#: src/common/text.c:662 src/common/text.c:667 src/common/text.c:673 +#: src/common/text.c:740 src/common/text.c:864 src/common/text.c:871 +#: src/common/text.c:876 src/common/text.c:881 src/common/text.c:886 +#: src/common/text.c:892 src/common/text.c:897 src/common/text.c:901 +#: src/common/text.c:906 src/common/text.c:912 src/common/text.c:958 +#: src/common/text.c:967 src/common/text.c:972 src/common/text.c:977 +#: src/common/text.c:986 src/common/text.c:997 src/common/text.c:1004 +#: src/common/text.c:1010 src/common/text.c:1015 src/common/text.c:1020 +#: src/common/text.c:1027 src/common/text.c:1033 src/common/text.c:1039 +#: src/common/text.c:1044 src/common/text.c:1049 src/common/text.c:1053 +#: src/common/text.c:1059 src/common/text.c:1067 src/common/text.c:1101 +#: src/common/text.c:1106 +msgid "Nickname" +msgstr "Ləqəb" + +#: src/common/text.c:663 +msgid "The action" +msgstr "Gedişat" + +#: src/common/text.c:668 +msgid "The text" +msgstr "Mətn" + +#: src/common/text.c:669 +msgid "Mode char" +msgstr "Mod hərfi" + +#: src/common/text.c:674 src/common/text.c:730 src/common/text.c:736 +#: src/common/text.c:741 +msgid "The message" +msgstr "İsmarış" + +#: src/common/text.c:678 src/common/text.c:745 +msgid "Old nickname" +msgstr "Köhnə ləqəb" + +#: src/common/text.c:679 src/common/text.c:746 +msgid "New nickname" +msgstr "Yeni ləqəb" + +#: src/common/text.c:683 +msgid "Nick of person who changed the topic" +msgstr "Mövzunu dəyişdirən şəxsin ləqəbi" + +#: src/common/text.c:684 src/common/text.c:690 src/fe-gtk/chanlist.c:599 +#: src/fe-gtk/chanlist.c:700 +msgid "Topic" +msgstr "Mövzu" + +#: src/common/text.c:685 src/common/text.c:689 src/common/text.c:1121 +#: src/fe-gtk/chanlist.c:597 src/fe-gtk/chanlist.c:691 +#: src/fe-gtk/ignoregui.c:175 +msgid "Channel" +msgstr "Kanal" + +#: src/common/text.c:694 src/common/text.c:752 +msgid "The nickname of the kicker" +msgstr "Atanın ləqəbi" + +#: src/common/text.c:695 src/common/text.c:750 +msgid "The person being kicked" +msgstr "Atılanın ləqəbi" + +#: src/common/text.c:696 src/common/text.c:703 src/common/text.c:707 +#: src/common/text.c:712 src/common/text.c:751 src/common/text.c:759 +msgid "The channel" +msgstr "Kanal" + +#: src/common/text.c:697 src/common/text.c:753 src/common/text.c:760 +msgid "The reason" +msgstr "Səbəb" + +#: src/common/text.c:701 src/common/text.c:757 +msgid "The nick of the person leaving" +msgstr "Ayrılan şəxsin ləqəbi" + +#: src/common/text.c:708 src/common/text.c:714 +msgid "The time" +msgstr "Vaxt" + +#: src/common/text.c:713 +msgid "The creator" +msgstr "Yaradıcı" + +#: src/common/text.c:718 +msgid "Nick" +msgstr "Ləqəb" + +#: src/common/text.c:719 src/common/text.c:973 +msgid "Reason" +msgstr "Səbəb" + +#: src/common/text.c:720 src/common/text.c:866 src/common/text.c:948 +msgid "Host" +msgstr "Qovşaq" + +#: src/common/text.c:724 src/common/text.c:729 src/common/text.c:734 +msgid "Who it's from" +msgstr "Mənşəyi" + +#: src/common/text.c:725 +msgid "The time in x.x format (see below)" +msgstr "x.x şəklində vaxt (alta baxın)" + +#: src/common/text.c:735 src/common/text.c:776 +msgid "The Channel it's going to" +msgstr "Getdiyi kanal" + +#: src/common/text.c:764 +msgid "The sound" +msgstr "Səs" + +#: src/common/text.c:765 src/common/text.c:770 src/common/text.c:775 +msgid "The nick of the person" +msgstr "Şəxsin ləqəbi" + +#: src/common/text.c:769 src/common/text.c:774 +msgid "The CTCP event" +msgstr "CTCP hadisəsi" + +#: src/common/text.c:780 +msgid "The nick of the person who set the key" +msgstr "Üçarı seçən şəxsin ləqəbi" + +#: src/common/text.c:781 +msgid "The key" +msgstr "Açar" + +#: src/common/text.c:785 +msgid "The nick of the person who set the limit" +msgstr "Hüdudu seçən şəxsin ləqəbi" + +#: src/common/text.c:786 +msgid "The limit" +msgstr "Hüdud" + +#: src/common/text.c:790 +msgid "The nick of the person who did the op'ing" +msgstr "Oplayan şəxsin ləqəbi" + +#: src/common/text.c:791 +msgid "The nick of the person who has been op'ed" +msgstr "Oplanan şəxsin ləqəbi" + +#: src/common/text.c:795 +msgid "The nick of the person who has been halfop'ed" +msgstr "Yarı oplanan şəxsin ləqəbi" + +#: src/common/text.c:796 +msgid "The nick of the person who did the halfop'ing" +msgstr "Yarı oplayan şəxsin ləqəbi" + +#: src/common/text.c:800 +msgid "The nick of the person who did the voice'ing" +msgstr "Voice-layan şəxsin ləqəbi" + +#: src/common/text.c:801 +msgid "The nick of the person who has been voice'ed" +msgstr "Voice-lanan şəxsin ləqəbi" + +#: src/common/text.c:805 +msgid "The nick of the person who did the banning" +msgstr "Banlayan şəxsin ləqəbi" + +#: src/common/text.c:806 src/common/text.c:833 +msgid "The ban mask" +msgstr "Ban maskası" + +#: src/common/text.c:810 +msgid "The nick who removed the key" +msgstr "Açarı ləğv edənin ləqəbi" + +#: src/common/text.c:814 +msgid "The nick who removed the limit" +msgstr "Hüdüdu ləğv edənin ləqəbi" + +#: src/common/text.c:818 +msgid "The nick of the person of did the deop'ing" +msgstr "" + +#: src/common/text.c:819 +msgid "The nick of the person who has been deop'ed" +msgstr "" + +#: src/common/text.c:822 +msgid "The nick of the person of did the dehalfop'ing" +msgstr "/" + +#: src/common/text.c:823 +msgid "The nick of the person who has been dehalfop'ed" +msgstr "" + +#: src/common/text.c:827 +msgid "The nick of the person of did the devoice'ing" +msgstr "/" + +#: src/common/text.c:828 +msgid "The nick of the person who has been devoice'ed" +msgstr "" + +#: src/common/text.c:832 +msgid "The nick of the person of did the unban'ing" +msgstr "" + +#: src/common/text.c:837 +msgid "The nick of the person who did the exempt" +msgstr "" + +#: src/common/text.c:838 src/common/text.c:843 +msgid "The exempt mask" +msgstr "Exempt maskası" + +#: src/common/text.c:842 +msgid "The nick of the person removed the exempt" +msgstr "" + +#: src/common/text.c:847 +msgid "The nick of the person who did the invite" +msgstr "" + +#: src/common/text.c:848 src/common/text.c:853 +msgid "The invite mask" +msgstr "Dəvət maskası" + +#: src/common/text.c:852 +msgid "The nick of the person removed the invite" +msgstr "" + +#: src/common/text.c:857 +msgid "The nick of the person setting the mode" +msgstr "" + +#: src/common/text.c:858 +msgid "The mode's sign (+/-)" +msgstr "Modun işarəsi (+/-)" + +#: src/common/text.c:859 +msgid "The mode letter" +msgstr "Mod hərfi" + +#: src/common/text.c:860 +msgid "The channel it's being set on" +msgstr "" + +#: src/common/text.c:865 +msgid "Username" +msgstr "İstifadəçi adı" + +#: src/common/text.c:867 +msgid "Full name" +msgstr "Tam ad" + +#: src/common/text.c:872 +msgid "Channel Membership/\"is an IRC operator\"" +msgstr "" + +#: src/common/text.c:877 +msgid "Server Information" +msgstr "Verici Haqqında" + +#: src/common/text.c:882 src/common/text.c:887 +msgid "Idle time" +msgstr "Passiv olma vaxtı" + +#: src/common/text.c:888 +msgid "Signon time" +msgstr "Giriş vaxtı" + +#: src/common/text.c:893 +msgid "Away reason" +msgstr "Uzaqlaşma səbəbi" + +#: src/common/text.c:902 src/common/text.c:907 src/common/text.c:915 +#: src/common/text.c:1093 +msgid "Message" +msgstr "İsmarış" + +#: src/common/text.c:908 +msgid "Account" +msgstr "Hesab" + +#: src/common/text.c:913 +msgid "Real user@host" +msgstr "Həqiqi istifadəçi@qovşaq" + +#: src/common/text.c:914 +msgid "Real IP" +msgstr "Həqiqi IP" + +#: src/common/text.c:919 src/common/text.c:928 src/common/text.c:934 +#: src/common/text.c:1116 +msgid "Channel Name" +msgstr "Kanal Adı" + +#: src/common/text.c:923 src/common/text.c:1079 src/fe-gtk/textgui.c:383 +msgid "Text" +msgstr "Mətn" + +#: src/common/text.c:924 src/common/text.c:930 src/common/text.c:1117 +msgid "Server Name" +msgstr "Verici Adı" + +#: src/common/text.c:929 +msgid "Nick of person who invited you" +msgstr "Sizi dəvət edən şəxsin ləqəbi" + +#: src/common/text.c:935 src/fe-gtk/chanlist.c:598 +msgid "Users" +msgstr "İstifadəçilər" + +#: src/common/text.c:939 +msgid "Nickname in use" +msgstr "Ləqəb istifadədədir" + +#: src/common/text.c:940 +msgid "Nick being tried" +msgstr "Ləqəb sınanır" + +#: src/common/text.c:944 src/common/text.c:980 src/common/text.c:991 +#: src/common/text.c:998 src/common/text.c:1011 src/common/text.c:1028 +#: src/common/text.c:1128 src/common/util.c:348 +msgid "Error" +msgstr "Xəta" + +#: src/common/text.c:949 src/common/text.c:1083 +msgid "IP" +msgstr "IP" + +#: src/common/text.c:950 src/common/text.c:979 +msgid "Port" +msgstr "Port" + +#: src/common/text.c:954 +msgid "PID" +msgstr "PID" + +#: src/common/text.c:962 +msgid "Channel name" +msgstr "Kanal adı" + +#: src/common/text.c:963 src/common/text.c:968 +msgid "Modes string" +msgstr "Mod qatarı" + +#: src/common/text.c:978 src/common/text.c:1016 src/common/text.c:1021 +#: src/common/text.c:1062 +msgid "IP address" +msgstr "IP ünvanı" + +#: src/common/text.c:984 src/common/text.c:1009 +msgid "DCC Type" +msgstr "DCC Növü" + +#: src/common/text.c:985 src/common/text.c:990 src/common/text.c:995 +#: src/common/text.c:1002 src/common/text.c:1022 src/common/text.c:1026 +#: src/common/text.c:1032 src/common/text.c:1038 src/common/text.c:1045 +#: src/common/text.c:1054 src/common/text.c:1060 +msgid "Filename" +msgstr "Fayl adı" + +#: src/common/text.c:996 src/common/text.c:1003 +msgid "Destination filename" +msgstr "Hədəf fayl adı" + +#: src/common/text.c:1005 src/common/text.c:1034 +msgid "CPS" +msgstr "CPS" + +#: src/common/text.c:1040 +msgid "Pathname" +msgstr "Cığır adı" + +#: src/common/text.c:1055 src/fe-gtk/dccgui.c:483 src/fe-gtk/dccgui.c:633 +msgid "Position" +msgstr "Mövqe" + +#: src/common/text.c:1061 src/fe-gtk/dccgui.c:482 src/fe-gtk/dccgui.c:632 +msgid "Size" +msgstr "Böyüklük" + +#: src/common/text.c:1066 +msgid "DCC String" +msgstr "DCC Qatarı" + +#: src/common/text.c:1071 +msgid "Number of notify items" +msgstr "Bildiriş üzvləri ədədi" + +#: src/common/text.c:1075 +msgid "Servername" +msgstr "Verici adı" + +#: src/common/text.c:1087 +msgid "Old Filename" +msgstr "Köhnə Fayl Adı" + +#: src/common/text.c:1088 +msgid "New Filename" +msgstr "Yeni Fayl Adı" + +#: src/common/text.c:1092 +msgid "Receiver" +msgstr "Alıcı" + +#: src/common/text.c:1097 +msgid "Hostmask" +msgstr "Qovşaq Maskası" + +#: src/common/text.c:1102 +msgid "Hostname" +msgstr "Qovşaq Adı" + +#: src/common/text.c:1107 +msgid "The Packet" +msgstr "Paket" + +#: src/common/text.c:1111 +msgid "Seconds" +msgstr "Saniyə" + +#: src/common/text.c:1115 +msgid "Nick of person who have been invited" +msgstr "Dəvət edilən şəxsin ləqəbi" + +#: src/common/text.c:1122 +msgid "Banmask" +msgstr "Ban Maskası" + +#: src/common/text.c:1123 +msgid "Who set the ban" +msgstr "Banı qoyan" + +#: src/common/text.c:1124 +msgid "Ban time" +msgstr "Ban vaxtı" + +#: src/common/text.c:1162 +#, c-format +msgid "" +"Error parsing event %s.\n" +"Loading default" +msgstr "" + +#: src/common/text.c:1672 +#, c-format +msgid "" +"Cannot read sound file:\n" +"%s" +msgstr "" + +#: src/common/util.c:292 +msgid "Remote host closed socket" +msgstr "Uzaq qovşaq soketi bağladı" + +#: src/common/util.c:297 +msgid "Connection refused" +msgstr "Bağlantı rədd edildi" + +#: src/common/util.c:300 +msgid "No route to host" +msgstr "Uzaq qovşaq yoxdur" + +#: src/common/util.c:302 +msgid "Connection timed out" +msgstr "Bağlantı vaxtı doldu" + +#: src/common/util.c:304 +msgid "Cannot assign that address" +msgstr "Bu ünvan verilə bilməz" + +#: src/common/util.c:306 +msgid "Connection reset by peer" +msgstr "Bağlantı düyün tərəfindən sıfırlandı" + +#: src/common/util.c:771 +msgid "Andorra" +msgstr "Andorra" + +#: src/common/util.c:772 +msgid "United Arab Emirates" +msgstr "Birləşmiş Ərəb Əmirlikləri" + +#: src/common/util.c:773 +msgid "Afghanistan" +msgstr "Əfqanıstan" + +#: src/common/util.c:774 +msgid "Antigua and Barbuda" +msgstr "Antiqua və Barbuda" + +#: src/common/util.c:775 +msgid "Anguilla" +msgstr "Anquilla" + +#: src/common/util.c:776 +msgid "Albania" +msgstr "Albaniya" + +#: src/common/util.c:777 +msgid "Armenia" +msgstr "Ermənistan" + +#: src/common/util.c:778 +msgid "Netherlands Antilles" +msgstr "Holland Antilləri" + +#: src/common/util.c:779 +msgid "Angola" +msgstr "Anqola" + +#: src/common/util.c:780 +msgid "Antarctica" +msgstr "Antarktika" + +#: src/common/util.c:781 +msgid "Argentina" +msgstr "Argentina" + +#: src/common/util.c:782 +msgid "Reverse DNS" +msgstr "Reverse DNS" + +#: src/common/util.c:783 +msgid "American Samoa" +msgstr "Amerikan Samoa" + +#: src/common/util.c:784 +msgid "Austria" +msgstr "Avstriya" + +#: src/common/util.c:785 +msgid "Nato Fiel" +msgstr "Nato Fiel" + +#: src/common/util.c:786 +msgid "Australia" +msgstr "Avstraliya" + +#: src/common/util.c:787 +msgid "Aruba" +msgstr "Aruba" + +#: src/common/util.c:788 +msgid "Azerbaijan" +msgstr "Azərbaycan" + +#: src/common/util.c:789 +msgid "Bosnia and Herzegovina" +msgstr "Bosniya və Herzoqovina" + +#: src/common/util.c:790 +msgid "Barbados" +msgstr "Barbados" + +#: src/common/util.c:791 +msgid "Bangladesh" +msgstr "Banqladeş" + +#: src/common/util.c:792 +msgid "Belgium" +msgstr "Belçika" + +#: src/common/util.c:793 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#: src/common/util.c:794 +msgid "Bulgaria" +msgstr "Bolqarıstan" + +#: src/common/util.c:795 +msgid "Bahrain" +msgstr "Bahreyn" + +#: src/common/util.c:796 +msgid "Burundi" +msgstr "Burundi" + +#: src/common/util.c:797 +msgid "Businesses" +msgstr "Təşkilatlar" + +#: src/common/util.c:798 +msgid "Benin" +msgstr "Benin" + +#: src/common/util.c:799 +msgid "Bermuda" +msgstr "Bermuda" + +#: src/common/util.c:800 +msgid "Brunei Darussalam" +msgstr "Bruney Darüssəlim" + +#: src/common/util.c:801 +msgid "Bolivia" +msgstr "Boliviya" + +#: src/common/util.c:802 +msgid "Brazil" +msgstr "Braziliya" + +#: src/common/util.c:803 +msgid "Bahamas" +msgstr "Bahamalar" + +#: src/common/util.c:804 +msgid "Bhutan" +msgstr "Butan" + +#: src/common/util.c:805 +msgid "Bouvet Island" +msgstr "Buvet Adası" + +#: src/common/util.c:806 +msgid "Botswana" +msgstr "Botsvana" + +#: src/common/util.c:807 +msgid "Belarus" +msgstr "Belarusiya" + +#: src/common/util.c:808 +msgid "Belize" +msgstr "Beliz" + +#: src/common/util.c:809 +msgid "Canada" +msgstr "Kanada" + +#: src/common/util.c:810 +msgid "Cocos Islands" +msgstr "Kakos Adaları" + +#: src/common/util.c:811 +msgid "Central African Republic" +msgstr "Mərkəzi Afrika Respublikası" + +#: src/common/util.c:812 +msgid "Congo" +msgstr "Konqo" + +#: src/common/util.c:813 +msgid "Switzerland" +msgstr "İsveçrə" + +#: src/common/util.c:814 +msgid "Cote D'ivoire" +msgstr "Kot Divuar" + +#: src/common/util.c:815 +msgid "Cook Islands" +msgstr "Kuku Adaları" + +#: src/common/util.c:816 +msgid "Chile" +msgstr "Çili" + +#: src/common/util.c:817 +msgid "Cameroon" +msgstr "Kamerun" + +#: src/common/util.c:818 +msgid "China" +msgstr "Çin" + +#: src/common/util.c:819 +msgid "Colombia" +msgstr "Kolumbiya" + +#: src/common/util.c:820 +msgid "Internic Commercial" +msgstr "Internic Təşkilatı" + +#: src/common/util.c:821 +msgid "Costa Rica" +msgstr "Kosta Rika" + +#: src/common/util.c:822 +msgid "Former Czechoslovakia" +msgstr "Köhnə Çexoslovakiya" + +#: src/common/util.c:823 +msgid "Cuba" +msgstr "Kuba" + +#: src/common/util.c:824 +msgid "Cape Verde" +msgstr "Keyp Verde" + +#: src/common/util.c:825 +msgid "Christmas Island" +msgstr "Kristmas Adası" + +#: src/common/util.c:826 +msgid "Cyprus" +msgstr "Kipr" + +#: src/common/util.c:827 +msgid "Czech Republic" +msgstr "Çex Respublikası" + +#: src/common/util.c:828 +msgid "Germany" +msgstr "Almaniya" + +#: src/common/util.c:829 +msgid "Djibouti" +msgstr "Cibuti" + +#: src/common/util.c:830 +msgid "Denmark" +msgstr "Danimarka" + +#: src/common/util.c:831 +msgid "Dominica" +msgstr "Dominik" + +#: src/common/util.c:832 +msgid "Dominican Republic" +msgstr "Dominikan Respublikası" + +#: src/common/util.c:833 +msgid "Algeria" +msgstr "Əlcəzair" + +#: src/common/util.c:834 +msgid "Ecuador" +msgstr "Ekvador" + +#: src/common/util.c:835 +msgid "Educational Institution" +msgstr "Tədris Təşkilatı" + +#: src/common/util.c:836 +msgid "Estonia" +msgstr "Estoniya" + +#: src/common/util.c:837 +msgid "Egypt" +msgstr "Misir" + +#: src/common/util.c:838 +msgid "Western Sahara" +msgstr "Qərbi Saxara" + +#: src/common/util.c:839 +msgid "Eritrea" +msgstr "Eritre" + +#: src/common/util.c:840 +msgid "Spain" +msgstr "İspaniya" + +#: src/common/util.c:841 +msgid "Ethiopia" +msgstr "Efiopiya" + +#: src/common/util.c:842 +msgid "Finland" +msgstr "Finlandiya" + +#: src/common/util.c:843 +msgid "Fiji" +msgstr "Fici" + +#: src/common/util.c:844 +msgid "Falkland Islands" +msgstr "Falkland Adaları" + +#: src/common/util.c:845 +msgid "Micronesia" +msgstr "Mikroneziya" + +#: src/common/util.c:846 +msgid "Faroe Islands" +msgstr "Faro Adaları" + +#: src/common/util.c:847 +msgid "France" +msgstr "Fransa" + +#: src/common/util.c:848 +msgid "France, Metropolitan" +msgstr "Fransa, Metropolitan" + +#: src/common/util.c:849 +msgid "Gabon" +msgstr "Qabon" + +#: src/common/util.c:850 +msgid "Great Britain" +msgstr "Böyük Britaniya" + +#: src/common/util.c:851 +msgid "Grenada" +msgstr "Qrenada" + +#: src/common/util.c:852 +msgid "Georgia" +msgstr "Gürcüstan" + +#: src/common/util.c:853 +msgid "French Guiana" +msgstr "Fransız Gvineyası" + +#: src/common/util.c:854 +msgid "British Channel Isles" +msgstr "Britaniya Kanal Adaları" + +#: src/common/util.c:855 +msgid "Ghana" +msgstr "Qana" + +#: src/common/util.c:856 +msgid "Gibraltar" +msgstr "Gibraltar" + +#: src/common/util.c:857 +msgid "Greenland" +msgstr "Qrinland" + +#: src/common/util.c:858 +msgid "Gambia" +msgstr "Qambiya" + +#: src/common/util.c:859 +msgid "Guinea" +msgstr "Qvineya" + +#: src/common/util.c:860 +msgid "Government" +msgstr "Hökümət" + +#: src/common/util.c:861 +msgid "Guadeloupe" +msgstr "Quadelup" + +#: src/common/util.c:862 +msgid "Equatorial Guinea" +msgstr "Ekvatorial Qvineya" + +#: src/common/util.c:863 +msgid "Greece" +msgstr "Yunanıstan" + +#: src/common/util.c:864 +msgid "S. Georgia and S. Sandwich Isles." +msgstr "S. Georgia və S. Sandwich Adaları." + +#: src/common/util.c:865 +msgid "Guatemala" +msgstr "Quatemala" + +#: src/common/util.c:866 +msgid "Guam" +msgstr "Quam" + +#: src/common/util.c:867 +msgid "Guinea-Bissau" +msgstr "Qvineya Bissau" + +#: src/common/util.c:868 +msgid "Guyana" +msgstr "Quyana" + +#: src/common/util.c:869 +msgid "Hong Kong" +msgstr "Honq Konq" + +#: src/common/util.c:870 +msgid "Heard and McDonald Islands" +msgstr "Hird Adası və Mkdonald Adaları" + +#: src/common/util.c:871 +msgid "Honduras" +msgstr "Honduras" + +#: src/common/util.c:872 +msgid "Croatia" +msgstr "Xırvatıstan" + +#: src/common/util.c:873 +msgid "Haiti" +msgstr "Haiti" + +#: src/common/util.c:874 +msgid "Hungary" +msgstr "Macarıstan" + +#: src/common/util.c:875 +msgid "Indonesia" +msgstr "İndoneziya" + +#: src/common/util.c:876 +msgid "Ireland" +msgstr "İrlandiya" + +#: src/common/util.c:877 +msgid "Israel" +msgstr "İsrail" + +#: src/common/util.c:878 +msgid "India" +msgstr "Hindistan" + +#: src/common/util.c:879 +msgid "Informational" +msgstr "Məlumat verici" + +#: src/common/util.c:880 +msgid "International" +msgstr "Beynəlmilləl" + +#: src/common/util.c:881 +msgid "British Indian Ocean Territory" +msgstr "Britaniya Hind Okeanı Sahəsi" + +#: src/common/util.c:882 +msgid "Iraq" +msgstr "İraq" + +#: src/common/util.c:883 +msgid "Iran" +msgstr "İran" + +#: src/common/util.c:884 +msgid "Iceland" +msgstr "İslandiya" + +#: src/common/util.c:885 +msgid "Italy" +msgstr "İtaliya" + +#: src/common/util.c:886 +msgid "Jamaica" +msgstr "Yamayka" + +#: src/common/util.c:887 +msgid "Jordan" +msgstr "İordaniya" + +#: src/common/util.c:888 +msgid "Japan" +msgstr "Yaponiya" + +#: src/common/util.c:889 +msgid "Kenya" +msgstr "Kenya" + +#: src/common/util.c:890 +msgid "Kyrgyzstan" +msgstr "Qırğızıstan" + +#: src/common/util.c:891 +msgid "Cambodia" +msgstr "Kambodiya" + +#: src/common/util.c:892 +msgid "Kiribati" +msgstr "Kiribati" + +#: src/common/util.c:893 +msgid "Comoros" +msgstr "Komor" + +#: src/common/util.c:894 +msgid "St. Kitts and Nevis" +msgstr "St. Kitts və Nevis" + +#: src/common/util.c:895 +msgid "North Korea" +msgstr "Şimali Koreya" + +#: src/common/util.c:896 +msgid "South Korea" +msgstr "Cənubi Koreya" + +#: src/common/util.c:897 +msgid "Kuwait" +msgstr "Küveyt" + +#: src/common/util.c:898 +msgid "Cayman Islands" +msgstr "Kayman Adaları" + +#: src/common/util.c:899 +msgid "Kazakhstan" +msgstr "Qazaxstan" + +#: src/common/util.c:900 +msgid "Laos" +msgstr "Laos" + +#: src/common/util.c:901 +msgid "Lebanon" +msgstr "Livan" + +#: src/common/util.c:902 +msgid "Saint Lucia" +msgstr "Müqəddəs Lusiya" + +#: src/common/util.c:903 +msgid "Liechtenstein" +msgstr "Lixtenşteyn" + +#: src/common/util.c:904 +msgid "Sri Lanka" +msgstr "Şri Lanka" + +#: src/common/util.c:905 +msgid "Liberia" +msgstr "Liberiya" + +#: src/common/util.c:906 +msgid "Lesotho" +msgstr "Lesoto" + +#: src/common/util.c:907 +msgid "Lithuania" +msgstr "Litva" + +#: src/common/util.c:908 +msgid "Luxembourg" +msgstr "Lüksemburq" + +#: src/common/util.c:909 +msgid "Latvia" +msgstr "Latviya" + +#: src/common/util.c:910 +msgid "Libya" +msgstr "Liviya" + +#: src/common/util.c:911 +msgid "Morocco" +msgstr "Mərakeş" + +#: src/common/util.c:912 +msgid "Monaco" +msgstr "Monako" + +#: src/common/util.c:913 +msgid "Moldova" +msgstr "Moldova" + +#: src/common/util.c:914 +msgid "United States Medical" +msgstr "ABŞ Medikalı" + +#: src/common/util.c:915 +msgid "Madagascar" +msgstr "Madaqaskar" + +#: src/common/util.c:916 +msgid "Marshall Islands" +msgstr "Marşal Adaları" + +#: src/common/util.c:917 +msgid "Military" +msgstr "Silahlı Qüvvələr" + +#: src/common/util.c:918 +msgid "Macedonia" +msgstr "Makedoniya" + +#: src/common/util.c:919 +msgid "Mali" +msgstr "Mali" + +#: src/common/util.c:920 +msgid "Myanmar" +msgstr "Myanmar" + +#: src/common/util.c:921 +msgid "Mongolia" +msgstr "Monqolustan" + +#: src/common/util.c:922 +msgid "Macau" +msgstr "Makau" + +#: src/common/util.c:923 +msgid "Northern Mariana Islands" +msgstr "Şimali Marian Adaları" + +#: src/common/util.c:924 +msgid "Martinique" +msgstr "Martiniq" + +#: src/common/util.c:925 +msgid "Mauritania" +msgstr "Mavritaniya" + +#: src/common/util.c:926 +msgid "Montserrat" +msgstr "Montserrat" + +#: src/common/util.c:927 +msgid "Malta" +msgstr "Malta" + +#: src/common/util.c:928 +msgid "Mauritius" +msgstr "Maurit" + +#: src/common/util.c:929 +msgid "Maldives" +msgstr "Maldiv" + +#: src/common/util.c:930 +msgid "Malawi" +msgstr "Malavi" + +#: src/common/util.c:931 +msgid "Mexico" +msgstr "Meksika" + +#: src/common/util.c:932 +msgid "Malaysia" +msgstr "Malayziya" + +#: src/common/util.c:933 +msgid "Mozambique" +msgstr "Mozambiq" + +#: src/common/util.c:934 +msgid "Namibia" +msgstr "Namibiya" + +#: src/common/util.c:935 +msgid "New Caledonia" +msgstr "Yeni Kaledoniya" + +#: src/common/util.c:936 +msgid "Niger" +msgstr "Niger" + +#: src/common/util.c:937 +msgid "Internic Network" +msgstr "Internic Şəbəkəsi" + +#: src/common/util.c:938 +msgid "Norfolk Island" +msgstr "Norfolk Adaları" + +#: src/common/util.c:939 +msgid "Nigeria" +msgstr "Nigeriya" + +#: src/common/util.c:940 +msgid "Nicaragua" +msgstr "Nikaraqua" + +#: src/common/util.c:941 +msgid "Netherlands" +msgstr "Hollandiya" + +#: src/common/util.c:942 +msgid "Norway" +msgstr "Norveç" + +#: src/common/util.c:943 +msgid "Nepal" +msgstr "Nepal" + +#: src/common/util.c:944 +msgid "Nauru" +msgstr "Nauru" + +#: src/common/util.c:945 +msgid "Neutral Zone" +msgstr "Neytral Zona" + +#: src/common/util.c:946 +msgid "Niue" +msgstr "Niu" + +#: src/common/util.c:947 +msgid "New Zealand" +msgstr "Yeni Zellandiya" + +#: src/common/util.c:948 +msgid "Oman" +msgstr "Oman" + +#: src/common/util.c:949 +msgid "Internic Non-Profit Organization" +msgstr "Internic Təşkilatı" + +#: src/common/util.c:950 +msgid "Panama" +msgstr "Panama" + +#: src/common/util.c:951 +msgid "Peru" +msgstr "Peru" + +#: src/common/util.c:952 +msgid "French Polynesia" +msgstr "Fransız Poloneziyası" + +#: src/common/util.c:953 +msgid "Papua New Guinea" +msgstr "Papua Yeni Qvineya" + +#: src/common/util.c:954 +msgid "Philippines" +msgstr "Filippinlər" + +#: src/common/util.c:955 +msgid "Pakistan" +msgstr "Pakistan" + +#: src/common/util.c:956 +msgid "Poland" +msgstr "Polşa" + +#: src/common/util.c:957 +msgid "St. Pierre and Miquelon" +msgstr "St. Pierre və Miquelon" + +#: src/common/util.c:958 +msgid "Pitcairn" +msgstr "Pitkairn" + +#: src/common/util.c:959 +msgid "Puerto Rico" +msgstr "Puerto Riko" + +#: src/common/util.c:960 +msgid "Portugal" +msgstr "Portuqaliya" + +#: src/common/util.c:961 +msgid "Palau" +msgstr "Palau" + +#: src/common/util.c:962 +msgid "Paraguay" +msgstr "Paraqvay" + +#: src/common/util.c:963 +msgid "Qatar" +msgstr "Katar" + +#: src/common/util.c:964 +msgid "Reunion" +msgstr "Reyunion" + +#: src/common/util.c:965 +msgid "Romania" +msgstr "Rumıniya" + +#: src/common/util.c:966 +msgid "Old School ARPAnet" +msgstr "Old School ARPAnet" + +#: src/common/util.c:967 +msgid "Russian Federation" +msgstr "Rusiya Federasiyası" + +#: src/common/util.c:968 +msgid "Rwanda" +msgstr "Ruanda" + +#: src/common/util.c:969 +msgid "Saudi Arabia" +msgstr "Səudiyyə Ərəbistan" + +#: src/common/util.c:970 +msgid "Solomon Islands" +msgstr "Solomon Adaları" + +#: src/common/util.c:971 +msgid "Seychelles" +msgstr "Seyşel" + +#: src/common/util.c:972 +msgid "Sudan" +msgstr "Sudan" + +#: src/common/util.c:973 +msgid "Sweden" +msgstr "İsveç" + +#: src/common/util.c:974 +msgid "Singapore" +msgstr "Sinqapur" + +#: src/common/util.c:975 +msgid "St. Helena" +msgstr "St. Helena" + +#: src/common/util.c:976 +msgid "Slovenia" +msgstr "Sloveniya" + +#: src/common/util.c:977 +msgid "Svalbard and Jan Mayen Islands" +msgstr "Svalbard və Jan Mayen Adaları" + +#: src/common/util.c:978 +msgid "Slovak Republic" +msgstr "Slovakiya Respublikası" + +#: src/common/util.c:979 +msgid "Sierra Leone" +msgstr "Siera Lione" + +#: src/common/util.c:980 +msgid "San Marino" +msgstr "San Marino" + +#: src/common/util.c:981 +msgid "Senegal" +msgstr "Seneqal" + +#: src/common/util.c:982 +msgid "Somalia" +msgstr "Somali" + +#: src/common/util.c:983 +msgid "Suriname" +msgstr "Surinam" + +#: src/common/util.c:984 +msgid "Sao Tome and Principe" +msgstr "Sao Tome və Prinsip" + +#: src/common/util.c:985 +msgid "Former USSR" +msgstr "Köhnə SSSR" + +#: src/common/util.c:986 +msgid "El Salvador" +msgstr "El Salvador" + +#: src/common/util.c:987 +msgid "Syria" +msgstr "Siriya" + +#: src/common/util.c:988 +msgid "Swaziland" +msgstr "Svaziland" + +#: src/common/util.c:989 +msgid "Turks and Caicos Islands" +msgstr "Türk və Kaykos Adaları" + +#: src/common/util.c:990 +msgid "Chad" +msgstr "Çad" + +#: src/common/util.c:991 +msgid "French Southern Territories" +msgstr "Cənubi Fransız Sahələri" + +#: src/common/util.c:992 +msgid "Togo" +msgstr "Toqo" + +#: src/common/util.c:993 +msgid "Thailand" +msgstr "Tayland" + +#: src/common/util.c:994 +msgid "Tajikistan" +msgstr "Tacikistan" + +#: src/common/util.c:995 +msgid "Tokelau" +msgstr "Tokelo" + +#: src/common/util.c:996 +msgid "Turkmenistan" +msgstr "Türkmənistan" + +#: src/common/util.c:997 +msgid "Tunisia" +msgstr "Tunis" + +#: src/common/util.c:998 +msgid "Tonga" +msgstr "Tonqa" + +#: src/common/util.c:999 +msgid "East Timor" +msgstr "Şərqi Timor" + +#: src/common/util.c:1000 +msgid "Turkey" +msgstr "Türkiyə" + +#: src/common/util.c:1001 +msgid "Trinidad and Tobago" +msgstr "Trinidad və Tobaqo" + +#: src/common/util.c:1002 +msgid "Tuvalu" +msgstr "Tuvalu" + +#: src/common/util.c:1003 +msgid "Taiwan" +msgstr "Tayvan" + +#: src/common/util.c:1004 +msgid "Tanzania" +msgstr "Tanzaniya" + +#: src/common/util.c:1005 +msgid "Ukraine" +msgstr "Ukrayna" + +#: src/common/util.c:1006 +msgid "Uganda" +msgstr "Uqanda" + +#: src/common/util.c:1007 +msgid "United Kingdom" +msgstr "Birləşmiş Krallıq" + +#: src/common/util.c:1008 +msgid "US Minor Outlying Islands" +msgstr "ABŞ Yaxını Adalar" + +#: src/common/util.c:1009 +msgid "United States of America" +msgstr "Amerika Birləşmiş Ştatları" + +#: src/common/util.c:1010 +msgid "Uruguay" +msgstr "Uruqvay" + +#: src/common/util.c:1011 +msgid "Uzbekistan" +msgstr "Özbəkistan" + +#: src/common/util.c:1012 +msgid "Vatican City State" +msgstr "Vatikan Şəhər Höküməti" + +#: src/common/util.c:1013 +msgid "St. Vincent and the grenadines" +msgstr "St. Vincent və qrenadinlər" + +#: src/common/util.c:1014 +msgid "Venezuela" +msgstr "Venezuela" + +#: src/common/util.c:1015 +msgid "British Virgin Islands" +msgstr "Britaniya Virgin Adaları" + +#: src/common/util.c:1016 +msgid "US Virgin Islands" +msgstr "ABŞ Virgin Adaları" + +#: src/common/util.c:1017 +msgid "Vietnam" +msgstr "Vyetnam" + +#: src/common/util.c:1018 +msgid "Vanuatu" +msgstr "Vanuatu" + +#: src/common/util.c:1019 +msgid "Wallis and Futuna Islands" +msgstr "Vallis və Futuna Adaları" + +#: src/common/util.c:1020 +msgid "Samoa" +msgstr "Samoa" + +#: src/common/util.c:1021 +msgid "Yemen" +msgstr "Yəmən" + +#: src/common/util.c:1022 +msgid "Mayotte" +msgstr "Mayot" + +#: src/common/util.c:1023 +msgid "Yugoslavia" +msgstr "Yuqoslaviya" + +#: src/common/util.c:1024 +msgid "South Africa" +msgstr "Cənubi Afrika" + +#: src/common/util.c:1025 +msgid "Zambia" +msgstr "Zambiya" + +#: src/common/util.c:1026 +msgid "Zaire" +msgstr "Zair" + +#: src/common/util.c:1027 +msgid "Zimbabwe" +msgstr "Zimbabve" + +#: src/common/util.c:1033 src/common/util.c:1043 src/fe-gtk/menu.c:513 +#: src/fe-gtk/menu.c:517 src/fe-gtk/menu.c:521 src/fe-gtk/menu.c:525 +#: src/fe-gtk/menu.c:529 +msgid "Unknown" +msgstr "Namə'lum" + +#: src/common/xchat.c:917 +msgid "Direct client-to-client" +msgstr "Birbaşa client-to-client" + +#: src/common/xchat.c:918 +msgid "Send File" +msgstr "Fayl Yolla" + +#: src/common/xchat.c:919 +msgid "Offer Chat" +msgstr "Söhbət Təklif Et" + +#: src/common/xchat.c:920 +msgid "Abort Chat" +msgstr "Söhbəti Sonlandır" + +#: src/common/xchat.c:921 src/fe-gtk/plugingui.c:74 +msgid "Version" +msgstr "Buraxılış" + +#: src/common/xchat.c:922 +msgid "Userinfo" +msgstr "İstifadəçi mə'lumatı" + +#: src/common/xchat.c:923 +msgid "Clientinfo" +msgstr "Alıcı mə'lumatı" + +#: src/common/xchat.c:924 src/common/xchat.c:956 src/common/xchat.c:1006 +msgid "Ping" +msgstr "Ping" + +#: src/common/xchat.c:925 +msgid "Time" +msgstr "Saat" + +#: src/common/xchat.c:926 +msgid "Finger" +msgstr "Finger" + +#: src/common/xchat.c:927 +msgid "Oper" +msgstr "Oper" + +#: src/common/xchat.c:928 +msgid "Kill this user" +msgstr "Bu istifadəçini kill et" + +#: src/common/xchat.c:929 +msgid "Mode" +msgstr "Mod" + +#: src/common/xchat.c:930 +msgid "Give Voice" +msgstr "Voice Ver" + +#: src/common/xchat.c:931 +msgid "Take Voice" +msgstr "Voice Al" + +#: src/common/xchat.c:932 +msgid "Give Ops" +msgstr "Op Ver" + +#: src/common/xchat.c:933 +msgid "Take Ops" +msgstr "Op Al" + +#: src/common/xchat.c:934 +msgid "Ignore" +msgstr "Rədd Et" + +#: src/common/xchat.c:935 +msgid "Ignore User" +msgstr "İstifadəçini Rədd Et" + +#: src/common/xchat.c:936 +msgid "UnIgnore User" +msgstr "İstifadəçidən Rəddi Sil" + +#: src/common/xchat.c:937 +msgid "Kick/Ban" +msgstr "Kick/Ban" + +#: src/common/xchat.c:938 src/common/xchat.c:990 +msgid "Kick" +msgstr "Kick-lə" + +#: src/common/xchat.c:939 src/common/xchat.c:940 src/common/xchat.c:941 +#: src/common/xchat.c:942 src/common/xchat.c:943 src/common/xchat.c:989 +msgid "Ban" +msgstr "Ban-la" + +#: src/common/xchat.c:944 src/common/xchat.c:945 src/common/xchat.c:946 +#: src/common/xchat.c:947 +msgid "KickBan" +msgstr "KickBan-la" + +#: src/common/xchat.c:948 src/fe-gtk/dccgui.c:528 src/fe-gtk/dccgui.c:669 +msgid "Info" +msgstr "Mə'lumat" + +#: src/common/xchat.c:949 +msgid "Who" +msgstr "Who" + +#: src/common/xchat.c:950 src/common/xchat.c:1003 +msgid "WhoIs" +msgstr "WhoIs" + +#: src/common/xchat.c:951 +msgid "DNS Lookup" +msgstr "DNS Lookup" + +#: src/common/xchat.c:952 +msgid "Trace" +msgstr "Trace" + +#: src/common/xchat.c:953 +msgid "UserHost" +msgstr "İstifadəçi Qovşağı" + +#: src/common/xchat.c:954 +msgid "External" +msgstr "Xarici" + +#: src/common/xchat.c:955 +msgid "Traceroute" +msgstr "Traceroute" + +#: src/common/xchat.c:957 +msgid "Telnet" +msgstr "Telnet" + +#: src/common/xchat.c:958 +msgid "Open Dialog Window" +msgstr "Dialoq Pəncərəsini Aç" + +#: src/common/xchat.c:970 +msgid "Disconnect" +msgstr "Bağlantını Kəs" + +#: src/common/xchat.c:971 +msgid "Reconnect" +msgstr "Yenidən Bağlan" + +#: src/common/xchat.c:972 +msgid "Leave Channel" +msgstr "Kanaldan Çıx" + +#: src/common/xchat.c:973 +msgid "Join Channel..." +msgstr "Kanala Daxil Ol..." + +#: src/common/xchat.c:974 +msgid "Enter Channel to Join:" +msgstr "Daxil Olunacaq Kanalı Bildir:" + +#: src/common/xchat.c:975 +msgid "Server Links" +msgstr "Verici Körpüləri" + +#: src/common/xchat.c:976 +msgid "Ping Server" +msgstr "Vericini Pinglə" + +#: src/common/xchat.c:977 +msgid "Hide Version" +msgstr "Buraxılışı Gizlət" + +#: src/common/xchat.c:987 +msgid "Op" +msgstr "Op" + +#: src/common/xchat.c:988 +msgid "DeOp" +msgstr "DeOp" + +#: src/common/xchat.c:991 +msgid "bye" +msgstr "Di ha!" + +#: src/common/xchat.c:992 +#, c-format +msgid "Enter reason to kick %s:" +msgstr "Kickləmə səbəbi %s:" + +#: src/common/xchat.c:993 +msgid "Sendfile" +msgstr "Fayl yolla" + +#: src/common/xchat.c:994 +msgid "Dialog" +msgstr "Dialoq" + +#: src/common/xchat.c:1004 +msgid "Send" +msgstr "Yolla" + +#: src/common/xchat.c:1005 +msgid "Chat" +msgstr "Söhbət" + +#: src/common/xchat.c:1007 src/fe-gtk/banlist.c:314 src/fe-gtk/search.c:117 +#: src/fe-gtk/urlgrab.c:200 +msgid "Clear" +msgstr "Təmizlə" + +#: src/fe-gtk/about.c:102 +msgid "About X-Chat" +msgstr "X-Chat Haqqında" + +#: src/fe-gtk/about.c:124 +msgid "A multiplatform IRC Client" +msgstr "Çox Platformlu IRC Alıcısı" + +#: src/fe-gtk/ascii.c:131 +msgid "Character Chart" +msgstr "Hərf Cədvəli" + +#: src/fe-gtk/banlist.c:148 src/fe-gtk/banlist.c:232 +msgid "You must select some bans." +msgstr "Bir iki ban seçməlisiniz." + +#: src/fe-gtk/banlist.c:248 src/fe-gtk/ignoregui.c:174 +msgid "Mask" +msgstr "Maska" + +#: src/fe-gtk/banlist.c:249 src/fe-gtk/dccgui.c:485 +msgid "From" +msgstr "Göndərən" + +#: src/fe-gtk/banlist.c:250 +msgid "Date" +msgstr "Tarix" + +#: src/fe-gtk/banlist.c:294 +#, c-format +msgid "X-Chat: Ban List (%s)" +msgstr "X-Chat: Ban Siyahısı (%s)" + +#: src/fe-gtk/banlist.c:310 +msgid "Unban" +msgstr "Unban" + +#: src/fe-gtk/banlist.c:312 +msgid "Crop" +msgstr "Kəs" + +#: src/fe-gtk/banlist.c:316 +msgid "Refresh" +msgstr "Yenilə" + +#: src/fe-gtk/chanlist.c:120 +#, c-format +msgid "User and Channel Statistics: %d/%d Users on %d/%d Channels" +msgstr "" +"İstifadəçi və Kanal Statistikaları: %d/%d istifadəçi toplam %d/%d kanalda" + +#: src/fe-gtk/chanlist.c:536 +msgid "I can't save an empty list!" +msgstr "Boş siyahını qeyd etmək olmaz axı!" + +#: src/fe-gtk/chanlist.c:539 src/fe-gtk/menu.c:941 +msgid "Select an output filename" +msgstr "Çıxış fay adını seç" + +#: src/fe-gtk/chanlist.c:607 +#, c-format +msgid "X-Chat: Channel List (%s)" +msgstr "X-Chat: Kanal Siyahısı (%s)" + +#: src/fe-gtk/chanlist.c:622 +msgid "List display options:" +msgstr "Görünüş seçimlərini göstər:" + +#: src/fe-gtk/chanlist.c:634 +msgid "Minimum Users:" +msgstr "Ən Az İstifadəçi:" + +#: src/fe-gtk/chanlist.c:649 +msgid "Maximum Users:" +msgstr "Ən Çox İstifadəçi:" + +#: src/fe-gtk/chanlist.c:664 +msgid "Regex Match:" +msgstr "Regex Axtarışı:" + +#: src/fe-gtk/chanlist.c:685 +msgid "Apply Match to:" +msgstr "Axtarışı Buna Tətbiq Et:" + +#: src/fe-gtk/chanlist.c:709 +msgid "Apply" +msgstr "Tətbiq Et" + +#: src/fe-gtk/chanlist.c:751 +msgid "Refresh the list" +msgstr "Siyahını yenilə" + +#: src/fe-gtk/chanlist.c:753 +msgid "Save the list" +msgstr "Siyahını qeyd qt" + +#: src/fe-gtk/chanlist.c:755 src/fe-gtk/menu.c:749 +msgid "Join Channel" +msgstr "Kanala Daxil Ol" + +#: src/fe-gtk/dccgui.c:126 +#, c-format +msgid "Send file to %s" +msgstr "Faylı %s-a yolla" + +#: src/fe-gtk/dccgui.c:339 +#, c-format +msgid "" +" File: %s\n" +" To/From: %s\n" +" Size: %u\n" +" Port: %d\n" +" IP Number: %s\n" +"Start Time: %s Max CPS: %d\n" +msgstr "" +" Fayl: %s\n" +" Alıcı/Göndərən: %s\n" +" Böyüklük: %u\n" +" Port: %d\n" +" IP Nömrəsi: %s\n" +"Başlanğıc Vaxtı: %s Maksimal CPS: %d\n" + +#: src/fe-gtk/dccgui.c:372 +msgid "That file is not resumable." +msgstr "Bu fayl davam etdirilə bilən deyil." + +#: src/fe-gtk/dccgui.c:376 +#, c-format +msgid "" +"Cannot access file: %s\n" +"%s.\n" +"Resuming not possible." +msgstr "" +"Fayla yetişilə bilmir: %s\n" +"%s.\n" +"Davam etdirmə mümkün olmayacaqdır." + +#: src/fe-gtk/dccgui.c:383 +msgid "" +"File in download directory is larger than file offered. Resuming not " +"possible." +msgstr "" +"Endirilən fayl təklif olunandan daha böyükdür. Davam etdirmə mümkün deyil." + +#: src/fe-gtk/dccgui.c:387 +msgid "Cannot resume the same file from two people." +msgstr "Eyni fayl iki nəfərdən davam etdirilə bilməz." + +#: src/fe-gtk/dccgui.c:474 +msgid "MIME Type" +msgstr "MIME Növü" + +#: src/fe-gtk/dccgui.c:480 src/fe-gtk/dccgui.c:630 src/fe-gtk/dccgui.c:753 +#: src/fe-gtk/notifygui.c:110 +msgid "Status" +msgstr "Vəziyyət" + +#: src/fe-gtk/dccgui.c:481 src/fe-gtk/dccgui.c:631 src/fe-gtk/plugingui.c:75 +msgid "File" +msgstr "Fayl" + +#: src/fe-gtk/dccgui.c:484 src/fe-gtk/dccgui.c:635 +msgid "ETA" +msgstr "ETA" + +#: src/fe-gtk/dccgui.c:494 +msgid "X-Chat: File Receive List" +msgstr "X-Chat: Fayl Alış Sıyahısı" + +#: src/fe-gtk/dccgui.c:522 src/fe-gtk/dccgui.c:668 src/fe-gtk/dccgui.c:783 +msgid "Abort" +msgstr "Ləğv Et" + +#: src/fe-gtk/dccgui.c:524 src/fe-gtk/dccgui.c:784 +msgid "Accept" +msgstr "Qəbul Et" + +#: src/fe-gtk/dccgui.c:526 +msgid "Resume" +msgstr "Davam Et" + +#: src/fe-gtk/dccgui.c:530 +msgid "Open" +msgstr "Aç" + +#: src/fe-gtk/dccgui.c:634 +msgid "Ack" +msgstr "Ack" + +#: src/fe-gtk/dccgui.c:636 +msgid "To" +msgstr "Alıcı" + +#: src/fe-gtk/dccgui.c:646 +msgid "X-Chat: File Send List" +msgstr "X-Chat: Fayl Göndəriş Siyahısı" + +#: src/fe-gtk/dccgui.c:754 +msgid "To/From" +msgstr "ALıcı/Göndərən" + +#: src/fe-gtk/dccgui.c:755 +msgid "Recv" +msgstr "Alc" + +#: src/fe-gtk/dccgui.c:756 +msgid "Sent" +msgstr "Gnd" + +#: src/fe-gtk/dccgui.c:757 +msgid "StartTime" +msgstr "Başlanğıc Vaxtı" + +#: src/fe-gtk/dccgui.c:767 +msgid "X-Chat: DCC Chat List" +msgstr "X-Chat: DCC Söhbət Siyahısı" + +#: src/fe-gtk/editlist.c:139 +msgid "*NEW*" +msgstr "*YENİ*" + +#: src/fe-gtk/editlist.c:140 +msgid "EDIT ME" +msgstr "MƏNİ DÜZƏLT" + +#: src/fe-gtk/editlist.c:305 src/fe-gtk/plugingui.c:73 +msgid "Name" +msgstr "Ad" + +#: src/fe-gtk/editlist.c:306 +msgid "Command" +msgstr "Əmr" + +#: src/fe-gtk/editlist.c:333 +msgid "Move Up" +msgstr "Yuxarı Daşı" + +#: src/fe-gtk/editlist.c:337 +msgid "Move Dn" +msgstr "Aşağı Daşı" + +#: src/fe-gtk/editlist.c:345 +msgid "Cancel" +msgstr "Ləğv Et" + +#: src/fe-gtk/editlist.c:349 src/fe-gtk/textgui.c:464 src/fe-gtk/urlgrab.c:204 +msgid "Save" +msgstr "Qeyd Et" + +#: src/fe-gtk/editlist.c:357 +msgid "Add New" +msgstr "Yenisini Əlavə Et" + +#: src/fe-gtk/editlist.c:361 src/fe-gtk/fkeys.c:746 src/fe-gtk/ignoregui.c:378 +msgid "Delete" +msgstr "Sil" + +#: src/fe-gtk/editlist.c:369 +msgid "Sort" +msgstr "Nizamla" + +#: src/fe-gtk/editlist.c:373 +msgid "Help" +msgstr "Yardım" + +#: src/fe-gtk/fe-gtk.c:143 +msgid "Options" +msgstr "Seçimlər" + +#: src/fe-gtk/fe-gtk.c:144 +msgid "DIRECTORY" +msgstr "CƏRGƏ" + +#: src/fe-gtk/fe-gtk.c:145 +msgid "use a different config dir" +msgstr "başqa quraşdırma cərgəsi işlət" + +#: src/fe-gtk/fe-gtk.c:146 +msgid "don't auto connect" +msgstr "qətiyyən avtomatik bağlanma" + +#: src/fe-gtk/fe-gtk.c:147 +msgid "don't auto load any plugins" +msgstr "heç bir əlavəni avtomatik yükləmə" + +#: src/fe-gtk/fe-gtk.c:148 +msgid "show version information" +msgstr "buraxılış mə'lumatını göstər" + +#: src/fe-gtk/fe-gtk.c:233 +#, c-format +msgid "" +"Failed to open font:\n" +"\n" +"%s" +msgstr "" +"Yazə növü açıla bilmədi:\n" +"\n" +"%s" + +#: src/fe-gtk/fe-gtk.c:592 +msgid "Search buffer is empty.\n" +msgstr "Axtarış bufferi boşdur.\n" + +#: src/fe-gtk/fe-gtk.c:669 +#, c-format +msgid "%d bytes" +msgstr "%d bayt" + +#: src/fe-gtk/fkeys.c:153 +msgid "" +"The Run Command action runs the data in Data 1 as if it has been typed into " +"the entry box where you pressed the key sequence. Thus it can contain text " +"(which will be sent to the channel/person), commands or user commands. When " +"run all \\n characters in Data 1 are used to deliminate seperate commands so " +"it is possible to run more than one command. If you want a \\ in the actual " +"text run then enter \\\\" +msgstr "" + +#: src/fe-gtk/fkeys.c:155 +msgid "" +"The Change Page command switches between pages in the notebook. Set Data 1 " +"to the page you want to switch to. If Data 2 is set to anything then the " +"switch will be relative to the current position" +msgstr "" + +#: src/fe-gtk/fkeys.c:157 +msgid "" +"The Insert in Buffer command will insert the contents of Data 1 into the " +"entry where the key sequence was pressed at the current cursor position" +msgstr "" + +#: src/fe-gtk/fkeys.c:159 +msgid "" +"The Scroll Page command scrolls the text widget up or down one page. If Data " +"1 is set to anything the page scrolls up, else it scrolls down" +msgstr "" + +#: src/fe-gtk/fkeys.c:161 +msgid "" +"The Set Buffer command sets the entry where the key sequence was entered to " +"the contents of Data 1" +msgstr "" + +#: src/fe-gtk/fkeys.c:163 +msgid "" +"The Last Command command sets the entry to contain the last command entered " +"- the same as pressing up in a shell" +msgstr "" + +#: src/fe-gtk/fkeys.c:165 +msgid "" +"The Next Command command sets the entry to contain the next command entered " +"- the same as pressing down in a shell" +msgstr "" + +#: src/fe-gtk/fkeys.c:167 +msgid "" +"This command changes the text in the entry to finish an incomplete nickname " +"or command. If Data 1 is set then double-tabbing in a string will select the " +"last nick, not the next" +msgstr "" + +#: src/fe-gtk/fkeys.c:169 +msgid "" +"This command scrolls up and down through the list of nicks. If Data 1 is set " +"to anything it will scroll up, else it scrolls down" +msgstr "" + +#: src/fe-gtk/fkeys.c:171 +msgid "" +"This command checks the last word entered in the entry against the replace " +"list and replaces it if it finds a match" +msgstr "" + +#: src/fe-gtk/fkeys.c:173 +msgid "This command moves the front tab left by one" +msgstr "" + +#: src/fe-gtk/fkeys.c:175 +msgid "This command moves the front tab right by one" +msgstr "" + +#: src/fe-gtk/fkeys.c:177 +msgid "This command moves the current tab family to the left" +msgstr "" + +#: src/fe-gtk/fkeys.c:179 +msgid "This command moves the current tab family to the right" +msgstr "" + +#: src/fe-gtk/fkeys.c:181 +msgid "Push input line into history but doesn't send to server" +msgstr "" + +#: src/fe-gtk/fkeys.c:193 +msgid "There was an error loading key bindings configuration" +msgstr "" + +#: src/fe-gtk/fkeys.c:434 src/fe-gtk/fkeys.c:435 src/fe-gtk/fkeys.c:436 +#: src/fe-gtk/fkeys.c:437 src/fe-gtk/fkeys.c:719 src/fe-gtk/fkeys.c:725 +#: src/fe-gtk/fkeys.c:730 src/fe-gtk/maingui.c:884 src/fe-gtk/maingui.c:905 +#: src/fe-gtk/maingui.c:1059 src/fe-gtk/maingui.c:1101 +#: src/fe-gtk/maingui.c:2443 +msgid "" +msgstr "" + +#: src/fe-gtk/fkeys.c:683 +msgid "Mod" +msgstr "Mod" + +#: src/fe-gtk/fkeys.c:684 src/fe-gtk/fkeys.c:779 +msgid "Key" +msgstr "Düymə" + +#: src/fe-gtk/fkeys.c:685 +msgid "Action" +msgstr "Gedişat" + +#: src/fe-gtk/fkeys.c:694 +msgid "X-Chat: Edit Key Bindings" +msgstr "X-Chat: Qısa Yolları Dəyişdir" + +#: src/fe-gtk/fkeys.c:741 +msgid "Add new" +msgstr "Yenisini əlavə et" + +#: src/fe-gtk/fkeys.c:772 +msgid "Shift" +msgstr "Shift" + +#: src/fe-gtk/fkeys.c:774 +msgid "Alt" +msgstr "Alt" + +#: src/fe-gtk/fkeys.c:776 +msgid "Ctrl" +msgstr "Ctrl" + +#: src/fe-gtk/fkeys.c:783 +msgid "Data 1" +msgstr "Verilən 1" + +#: src/fe-gtk/fkeys.c:786 +msgid "Data 2" +msgstr "Verilən 2" + +#: src/fe-gtk/fkeys.c:829 +msgid "Error opening keys config file\n" +msgstr "Düymə quraşdırma faylı açıla bilmədi\n" + +#: src/fe-gtk/fkeys.c:1000 +#, c-format +msgid "" +"Unknown keyname %s in key bindings config file\n" +"Load aborted, please fix %s/keybindings.conf\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1038 +#, c-format +msgid "" +"Unknown action %s in key bindings config file\n" +"Load aborted, Please fix %s/keybindings\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1059 +#, c-format +msgid "" +"Expecting Data line (beginning Dx{:|!}) but got:\n" +"%s\n" +"\n" +"Load aborted, Please fix %s/keybindings\n" +msgstr "" + +#: src/fe-gtk/fkeys.c:1128 +#, c-format +msgid "" +"Key bindings config file is corrupt, load aborted\n" +"Please fix %s/keybindings.conf\n" +msgstr "" + +#: src/fe-gtk/gtkutil.c:146 +msgid "Cannot write to that file." +msgstr "Bu fayla yazıla bilmir." + +#: src/fe-gtk/gtkutil.c:148 +msgid "Cannot read that file." +msgstr "Bu fayl oxuna bilmir." + +#: src/fe-gtk/ignoregui.c:116 src/fe-gtk/ignoregui.c:279 +msgid "That mask already exists." +msgstr "Bu maska onsuz da mövcuddur." + +#: src/fe-gtk/ignoregui.c:176 src/fe-gtk/maingui.c:1556 +msgid "Private" +msgstr "Şəxsi" + +#: src/fe-gtk/ignoregui.c:177 +msgid "Notice" +msgstr "Bildiriş" + +#: src/fe-gtk/ignoregui.c:178 +msgid "CTCP" +msgstr "CTCP" + +#: src/fe-gtk/ignoregui.c:179 +msgid "DCC" +msgstr "DCC" + +#: src/fe-gtk/ignoregui.c:180 +msgid "Invite" +msgstr "Dəvət Et" + +#: src/fe-gtk/ignoregui.c:181 +msgid "Unignore" +msgstr "Qəbul Et" + +#: src/fe-gtk/ignoregui.c:299 +msgid "Enter mask to ignore:" +msgstr "Rədd ediləcək maskanı bildir:" + +#: src/fe-gtk/ignoregui.c:346 +msgid "X-Chat: Ignore list" +msgstr "X-Chat: Rədd siyahısı" + +#: src/fe-gtk/ignoregui.c:353 +msgid "Ignore Stats:" +msgstr "Rədd Statistikaları:" + +#: src/fe-gtk/ignoregui.c:361 +msgid "Channel:" +msgstr "Kanal:" + +#: src/fe-gtk/ignoregui.c:362 +msgid "Private:" +msgstr "Şəxsi:" + +#: src/fe-gtk/ignoregui.c:363 +msgid "Notice:" +msgstr "Bildiriş:" + +#: src/fe-gtk/ignoregui.c:364 +msgid "CTCP:" +msgstr "CTCP:" + +#: src/fe-gtk/ignoregui.c:365 +msgid "Invite:" +msgstr "Dəvət:" + +#: src/fe-gtk/ignoregui.c:376 src/fe-gtk/menu.c:1246 +msgid "New" +msgstr "Yeni" + +#: src/fe-gtk/ignoregui.c:380 +msgid "Delete All" +msgstr "Hamısı Sil" + +#: src/fe-gtk/maingui.c:557 +#, c-format +msgid "Topic for %s is: %s" +msgstr "%s mövzusu: %s" + +#: src/fe-gtk/maingui.c:561 +msgid "No topic is set" +msgstr "Mövzu seçilməyib" + +#: src/fe-gtk/maingui.c:958 +msgid "No other tabs open, quit xchat?" +msgstr "Açıq səkmə qalmadı, xchat sonlandırılsın?" + +#: src/fe-gtk/maingui.c:1004 +msgid "Insert color code" +msgstr "Rəng kodu daxil et" + +#: src/fe-gtk/maingui.c:1046 src/fe-gtk/menu.c:1268 +msgid "Close Tab" +msgstr "Səkməni Bağla" + +#: src/fe-gtk/maingui.c:1049 src/fe-gtk/menu.c:1398 +msgid "Detach Tab" +msgstr "Səkməni Ayır" + +#: src/fe-gtk/maingui.c:1064 +msgid "Beep on message" +msgstr "İsmarış gələndə səs çal" + +#: src/fe-gtk/maingui.c:1067 +msgid "Show join/part messages" +msgstr "join/part ismarışlarını göstər" + +#: src/fe-gtk/maingui.c:1069 +msgid "Color paste" +msgstr "Rəngli yapışdır" + +#: src/fe-gtk/maingui.c:1079 +msgid "Go to" +msgstr "Get" + +#: src/fe-gtk/maingui.c:1274 +msgid "Some file transfers still active, quit xchat?" +msgstr "Bə'zi fayl transferləri hələ də fəaldır, xchat sonlandırılsın?" + +#: src/fe-gtk/maingui.c:1424 src/fe-gtk/maingui.c:1530 +msgid "User limit must be a number!\n" +msgstr "İstifadəçi hüdüdu nömrə olmalıdır!\n" + +#: src/fe-gtk/maingui.c:1552 +msgid "Topic Protection" +msgstr "Mövzu Qoruması" + +#: src/fe-gtk/maingui.c:1553 +msgid "No outside messages" +msgstr "Xarici ismarışlar göstərilməsin" + +#: src/fe-gtk/maingui.c:1554 +msgid "Secret" +msgstr "Gizli" + +#: src/fe-gtk/maingui.c:1555 +msgid "Invite Only" +msgstr "Ancaq Dəvət Et" + +#: src/fe-gtk/maingui.c:1557 +msgid "Moderated" +msgstr "Modereytlənmiş" + +#: src/fe-gtk/maingui.c:1558 +msgid "Ban List" +msgstr "Ban Siyahısı" + +#: src/fe-gtk/maingui.c:1560 +msgid "Keyword" +msgstr "Açar Kəlmə" + +#: src/fe-gtk/maingui.c:1572 +msgid "User Limit" +msgstr "İstifadəçi Hüdüdu" + +#: src/fe-gtk/maingui.c:1588 +msgid "Close this tab/window" +msgstr "Bu səkmə/pəncərəni bağla" + +#: src/fe-gtk/maingui.c:1685 +msgid "Show/Hide userlist" +msgstr "İstifadəçi siyahısını göstər/gizlət" + +#: src/fe-gtk/maingui.c:1795 +msgid "" +"Unable to set transparent background!\n" +"\n" +"You may be using a non-compliant window\n" +"manager that is not currently supported.\n" +msgstr "" + +#: src/fe-gtk/maingui.c:1988 +msgid "Enter new nickname:" +msgstr "Yeni ləqəb bildir:" + +#: src/fe-gtk/menu.c:151 +msgid "Host unknown" +msgstr "Namə'lum qovşaq" + +#: src/fe-gtk/menu.c:512 +#, c-format +msgid "User: %s" +msgstr "İstifadəçi: %s" + +#: src/fe-gtk/menu.c:516 +#, c-format +msgid "Country: %s" +msgstr "Ölkə: %s" + +#: src/fe-gtk/menu.c:520 +#, c-format +msgid "Realname: %s" +msgstr "Həqiqi ad: %s" + +#: src/fe-gtk/menu.c:524 +#, c-format +msgid "Server: %s" +msgstr "Verici: %s" + +#: src/fe-gtk/menu.c:528 +#, c-format +msgid "Last Msg: %s" +msgstr "Son ismarış: %s" + +#: src/fe-gtk/menu.c:613 +msgid "Menu Bar" +msgstr "Menyu Çubuğu" + +#: src/fe-gtk/menu.c:614 +msgid "Topic Bar" +msgstr "Mövzu Çubuğu" + +#: src/fe-gtk/menu.c:618 +msgid "User List" +msgstr "İstifadəçi Siyahısı" + +#: src/fe-gtk/menu.c:621 +msgid "Mode Buttons" +msgstr "Mod Düymələri" + +#: src/fe-gtk/menu.c:627 +msgid "User List Buttons" +msgstr "İstifadəçi Siyahısı Düymələri" + +#: src/fe-gtk/menu.c:753 +msgid "Part Channel" +msgstr "Part Kanalı" + +#: src/fe-gtk/menu.c:755 +msgid "Cycle Channel" +msgstr "Cycle Kanalı" + +#: src/fe-gtk/menu.c:778 +msgid "X-Chat: User menu" +msgstr "X-Chat: İstifadəçi menyusu" + +#: src/fe-gtk/menu.c:787 +msgid "Edit This Menu..." +msgstr "Bu Menyunu Dəyişdir..." + +#: src/fe-gtk/menu.c:889 +msgid "" +"*WARNING*\n" +"Auto accepting DCC to your home directory\n" +"can be dangerous and is exploitable. Eg:\n" +"Someone could send you a .bash_profile" +msgstr "" + +#: src/fe-gtk/menu.c:1011 +msgid "Settings saved." +msgstr "Qurğular qeyd edildi." + +#: src/fe-gtk/menu.c:1048 +msgid "" +"User Commands - Special codes:\n" +"\n" +"%c = current channel\n" +"%m = machine info\n" +"%n = your nick\n" +"%t = time/date\n" +"%v = xchat version\n" +"%2 = word 2\n" +"%3 = word 3\n" +"&2 = word 2 to the end of line\n" +"&3 = word 3 to the end of line\n" +"\n" +"eg:\n" +"/cmd john hello\n" +"\n" +"%2 would be \"john\"\n" +"&2 would be \"john hello\"." +msgstr "" + +#: src/fe-gtk/menu.c:1063 +msgid "" +"Userlist Buttons - Special codes:\n" +"\n" +"%a = all selected nicks\n" +"%c = current channel\n" +"%h = selected nick's hostname\n" +"%m = machine info\n" +"%n = your nick\n" +"%s = selected nick\n" +"%t = time/date\n" +msgstr "" + +#: src/fe-gtk/menu.c:1072 +msgid "" +"Dialog Buttons - Special codes:\n" +"\n" +"%a = all selected nicks\n" +"%c = current channel\n" +"%h = selected nick's hostname\n" +"%m = machine info\n" +"%n = your nick\n" +"%s = selected nick\n" +"%t = time/date\n" +msgstr "" + +#: src/fe-gtk/menu.c:1081 +msgid "" +"CTCP Replies - Special codes:\n" +"\n" +"%d = data (the whole ctcp)\n" +"%m = machine info\n" +"%s = nick who sent the ctcp\n" +"%t = time/date\n" +"%2 = word 2\n" +"%3 = word 3\n" +"&2 = word 2 to the end of line\n" +"&3 = word 3 to the end of line\n" +"\n" +msgstr "" + +#: src/fe-gtk/menu.c:1091 +#, c-format +msgid "" +"URL Handlers - Special codes:\n" +"\n" +"%s = the URL string\n" +"\n" +"Putting a ! infront of the command\n" +"indicates it should be sent to a\n" +"shell instead of X-Chat" +msgstr "" + +#: src/fe-gtk/menu.c:1100 +msgid "X-Chat: User Defined Commands" +msgstr "X-Chat: İstifadəçi Tə'yinli Əmrlər" + +#: src/fe-gtk/menu.c:1107 +msgid "X-Chat: Userlist Popup menu" +msgstr "X-Chat: İstifadəçi siyahısı popup menyusu" + +#: src/fe-gtk/menu.c:1114 +msgid "X-Chat: Replace" +msgstr "X-Chat: Əvəz Et" + +#: src/fe-gtk/menu.c:1121 +msgid "X-Chat: URL Handlers" +msgstr "X-Chat: URL Açıcıları" + +#: src/fe-gtk/menu.c:1140 +msgid "X-Chat: Userlist buttons" +msgstr "X-Chat: İstifadəçi siyahısı düymələri" + +#: src/fe-gtk/menu.c:1147 +msgid "X-Chat: Dialog buttons" +msgstr "X-Chat: Dialoq düymələri" + +#: src/fe-gtk/menu.c:1154 +msgid "X-Chat: CTCP Replies" +msgstr "X-Chat: CTCP Cavabları" + +#: src/fe-gtk/menu.c:1242 +msgid "_X-Chat" +msgstr "_X-Chat" + +#: src/fe-gtk/menu.c:1243 +msgid "Server List..." +msgstr "Verici Siyahısı..." + +#: src/fe-gtk/menu.c:1247 +msgid "Server Tab..." +msgstr "Verici Səkməsi..." + +#: src/fe-gtk/menu.c:1248 +msgid "Channel Tab..." +msgstr "Kanal Səkməsi..." + +#: src/fe-gtk/menu.c:1249 +msgid "Server Window..." +msgstr "Verici Pəncərəsi..." + +#: src/fe-gtk/menu.c:1250 +msgid "Channel Window..." +msgstr "Kanal Pəncərəsi..." + +#: src/fe-gtk/menu.c:1255 src/fe-gtk/menu.c:1257 +msgid "Load Plugin or Script..." +msgstr "Əlavə ya da skript yüklə..." + +#: src/fe-gtk/menu.c:1261 +msgid "New Shell Tab..." +msgstr "Yeni Qabıq Səkməsi..." + +#: src/fe-gtk/menu.c:1270 +msgid "Quit" +msgstr "Çıx" + +#: src/fe-gtk/menu.c:1272 +msgid "_IRC" +msgstr "_IRC" + +#: src/fe-gtk/menu.c:1273 +msgid "Invisible" +msgstr "Gizli" + +#: src/fe-gtk/menu.c:1274 +msgid "Receive Wallops" +msgstr "Wallopları al" + +#: src/fe-gtk/menu.c:1275 +msgid "Receive Server Notices" +msgstr "Verici bildirişlərini al" + +#: src/fe-gtk/menu.c:1277 +msgid "Marked Away" +msgstr "Uzaqda" + +#: src/fe-gtk/menu.c:1279 +msgid "Auto Rejoin when Kicked" +msgstr "Kick-lənəndə avtomatik olaraq yenidən daxil ol" + +#: src/fe-gtk/menu.c:1280 +msgid "Auto Reconnect to Server" +msgstr "Vericiyə avtomatik olaraq yenidən bağlan" + +#: src/fe-gtk/menu.c:1281 +msgid "Never-give-up ReConnect" +msgstr "Qətiyyən yenidən bağlanmağı sonlandırma" + +#: src/fe-gtk/menu.c:1283 +msgid "Auto Open Dialog Windows" +msgstr "Dialoq pəncərələrini avtomatik aç" + +#: src/fe-gtk/menu.c:1284 +msgid "Auto Accept Direct Chat" +msgstr "Birbaşa söhbəti avtomatik qəbul et" + +#: src/fe-gtk/menu.c:1285 +msgid "Auto Accept Files" +msgstr "Faylları avtomatik qəbul et " + +#: src/fe-gtk/menu.c:1287 +msgid "_Server" +msgstr "_Verici" + +#: src/fe-gtk/menu.c:1289 +msgid "S_ettings" +msgstr "_Qurğular" + +#: src/fe-gtk/menu.c:1290 +msgid "Preferences..." +msgstr "Seçimlər..." + +#: src/fe-gtk/menu.c:1292 +msgid "Lists" +msgstr "Siyahılar" + +#: src/fe-gtk/menu.c:1293 +msgid "Auto Replace..." +msgstr "Avtomatik Əvəz Et..." + +#: src/fe-gtk/menu.c:1294 +msgid "CTCP Replies..." +msgstr "CTCP Cavabları..." + +#: src/fe-gtk/menu.c:1295 +msgid "Dialog Buttons..." +msgstr "Dialoq Düymələri..." + +#: src/fe-gtk/menu.c:1296 +msgid "Key Bindings..." +msgstr "Qısa Yollar..." + +#: src/fe-gtk/menu.c:1297 +msgid "Text Events..." +msgstr "Mətn Hadisələri..." + +#: src/fe-gtk/menu.c:1298 +msgid "URL Handlers..." +msgstr "URL Açıcıları..." + +#: src/fe-gtk/menu.c:1299 +msgid "User Commands..." +msgstr "İstifadəçi Əmrləri..." + +#: src/fe-gtk/menu.c:1300 +msgid "Userlist Buttons..." +msgstr "İstifadəçi Siyahısı Düymələri..." + +#: src/fe-gtk/menu.c:1301 +msgid "Userlist Popup..." +msgstr "İstifadəçi Siyahısı Popup-ı..." + +#: src/fe-gtk/menu.c:1306 +msgid "Reload Settings" +msgstr "Qurğuları Yenilə" + +#: src/fe-gtk/menu.c:1308 +msgid "Save Settings now" +msgstr "Qurğuları indi qeyd et" + +#: src/fe-gtk/menu.c:1309 +msgid "Save Settings on exit" +msgstr "Qurğuları çıxışda qeyd et" + +#: src/fe-gtk/menu.c:1312 +msgid "_Window" +msgstr "_Pəncərə" + +#: src/fe-gtk/menu.c:1313 +msgid "Ban List..." +msgstr "Ban Siyahısı..." + +#: src/fe-gtk/menu.c:1314 +msgid "Channel List..." +msgstr "Kanal Siyahısı..." + +#: src/fe-gtk/menu.c:1315 +msgid "Character Chart..." +msgstr "Hərf Cədvəli..." + +#: src/fe-gtk/menu.c:1316 +msgid "Direct Chat..." +msgstr "Birbaşa Söhbət..." + +#: src/fe-gtk/menu.c:1317 +msgid "File Receive..." +msgstr "Fayl Alışı..." + +#: src/fe-gtk/menu.c:1318 +msgid "File Send..." +msgstr "Fayl Göndərilməsi..." + +#: src/fe-gtk/menu.c:1319 +msgid "Ignore List..." +msgstr "Rədd Siyahısı..." + +#: src/fe-gtk/menu.c:1320 +msgid "Notify List..." +msgstr "Bildiriş Siyahısı..." + +#: src/fe-gtk/menu.c:1321 +msgid "Plugins and Scripts..." +msgstr "Əlavələr və Skriptlər..." + +#: src/fe-gtk/menu.c:1322 +msgid "Raw Log..." +msgstr "Xam Qeyd..." + +#: src/fe-gtk/menu.c:1323 +msgid "URL Grabber..." +msgstr "URL Alıcısı..." + +#: src/fe-gtk/menu.c:1325 +msgid "C_lear Text" +msgstr "Mətni _Təmizlə" + +#: src/fe-gtk/menu.c:1326 +msgid "Search Text..." +msgstr "Mətni Axtar..." + +#: src/fe-gtk/menu.c:1327 +msgid "Save Text..." +msgstr "Mətni Qeyd Et..." + +#: src/fe-gtk/menu.c:1329 +msgid "_Help" +msgstr "_Yardım" + +#: src/fe-gtk/menu.c:1330 +msgid "_Contents" +msgstr "_Məzmun" + +#: src/fe-gtk/menu.c:1331 +msgid "_About" +msgstr "_Haqqında" + +#: src/fe-gtk/menu.c:1400 +msgid "Attach Tab" +msgstr "Səkməni İlişdir" + +#: src/fe-gtk/notifygui.c:109 +msgid "User" +msgstr "İstifadəçi" + +#: src/fe-gtk/notifygui.c:111 +msgid "Server" +msgstr "Verici" + +#: src/fe-gtk/notifygui.c:112 +msgid "Last Seen" +msgstr "Son Görülmüşdür" + +#: src/fe-gtk/notifygui.c:149 +msgid "Offline" +msgstr "Xətdən Xaric" + +#: src/fe-gtk/notifygui.c:169 +msgid "Never" +msgstr "Qətiyyən" + +#: src/fe-gtk/notifygui.c:187 +msgid "Online" +msgstr "Xətdə" + +#: src/fe-gtk/notifygui.c:277 +msgid "Enter nickname to add:" +msgstr "Əlavə ediləcək ləqəbi yazın:" + +#: src/fe-gtk/notifygui.c:293 +msgid "X-Chat: Notify List" +msgstr "X-Chat: Bildiriş Siyahısı" + +#: src/fe-gtk/notifygui.c:306 src/fe-gtk/servlistgui.c:717 +msgid "Add" +msgstr "Əlavə Et" + +#: src/fe-gtk/notifygui.c:308 +msgid "Remove" +msgstr "Sil" + +#: src/fe-gtk/plugingui.c:76 src/fe-gtk/textgui.c:387 +msgid "Description" +msgstr "İzahat" + +#: src/fe-gtk/plugingui.c:151 +msgid "Select a Plugin or Script to load" +msgstr "Yüklənəcək Əlavə ya da Skripti Seç" + +#: src/fe-gtk/plugingui.c:219 +msgid "X-Chat: Plugins and Scripts" +msgstr "X-Chat: Əlavələr və Skriptlər" + +#: src/fe-gtk/plugingui.c:225 +msgid "_Load..." +msgstr "_Yüklə..." + +#: src/fe-gtk/plugingui.c:228 +msgid "_UnLoad" +msgstr "Çı_xart" + +#: src/fe-gtk/plugingui.c:232 +msgid "_Close" +msgstr "_Bağla" + +#: src/fe-gtk/rawlog.c:78 +msgid "Save rawlog" +msgstr "Xam qeydi qeyd et" + +#: src/fe-gtk/rawlog.c:94 +#, c-format +msgid "X-Chat: Rawlog (%s)" +msgstr "X-Chat: Xam qeyd (%s)" + +#: src/fe-gtk/rawlog.c:123 +msgid "Clear rawlog" +msgstr "Xam qeydi təmizlə" + +#: src/fe-gtk/rawlog.c:126 +msgid "Save rawlog..." +msgstr "Xam qeydi qeyd et..." + +#: src/fe-gtk/search.c:47 +msgid "The window you opened this Search for doesn't exist anymore." +msgstr "Bu axtarışı açtığınız pəncərə artıq mövcud deyil." + +#: src/fe-gtk/search.c:91 +msgid "X-Chat: Search" +msgstr "X-Chat: Axtarış" + +#: src/fe-gtk/search.c:100 +msgid "Find:" +msgstr "Axtar:" + +#: src/fe-gtk/search.c:114 +msgid "Find" +msgstr "Axtar" + +#: src/fe-gtk/search.c:119 +msgid "Close" +msgstr "Bağla" + +#: src/fe-gtk/servlistgui.c:161 +#, c-format +msgid "Settings for %s" +msgstr "%s qurğuları" + +#: src/fe-gtk/servlistgui.c:202 src/fe-gtk/servlistgui.c:275 +msgid "New Network" +msgstr "Yeni Şəbəkə" + +#: src/fe-gtk/servlistgui.c:370 +#, c-format +msgid "Really remove network \"%s\" and all its servers?" +msgstr "Həqiqətən də \"%s\" şəbəkəsi və bütün onun vericiləri silinsin?" + +#: src/fe-gtk/servlistgui.c:407 src/fe-gtk/servlistgui.c:437 +#, c-format +msgid "_Remove \"%s\"" +msgstr "\"%s\" şəbəkəsini _sil" + +#: src/fe-gtk/servlistgui.c:414 +msgid "_Add new server" +msgstr "_Yeni verici əlavə et" + +#: src/fe-gtk/servlistgui.c:444 +#, c-format +msgid "Move \"%s\" _down" +msgstr "\"%s\" şəbəkəsini _aşağı daşı" + +#: src/fe-gtk/servlistgui.c:451 +#, c-format +msgid "Move \"%s\" _up" +msgstr "\"%s\" şəbəkəsini _yuxarı daşı" + +#: src/fe-gtk/servlistgui.c:462 +msgid "_Add new network" +msgstr "Yeni şəbəkə əla_və et" + +#: src/fe-gtk/servlistgui.c:831 +msgid "Global User Info" +msgstr "Ümumi İstifadəçi Mə'lumatları" + +#: src/fe-gtk/servlistgui.c:839 +msgid "Nick Names:" +msgstr "Ləqəblər:" + +#: src/fe-gtk/servlistgui.c:858 src/fe-gtk/servlistgui.c:1061 +msgid "User Name:" +msgstr "İstifadəçi Adı:" + +#: src/fe-gtk/servlistgui.c:871 src/fe-gtk/servlistgui.c:1063 +msgid "Real Name:" +msgstr "Həqiqi Adınız:" + +#: src/fe-gtk/servlistgui.c:913 +msgid "C_onnect" +msgstr "_Bağlan" + +#: src/fe-gtk/servlistgui.c:921 +msgid "Connect in a _new tab" +msgstr "Yeni səkmədə _bağlan" + +#: src/fe-gtk/servlistgui.c:981 +msgid "Servers" +msgstr "Vericilər" + +#: src/fe-gtk/servlistgui.c:1019 +msgid "Character Set:" +msgstr "Hərf Dəstəsi:" + +#: src/fe-gtk/servlistgui.c:1059 +msgid "Nick Name:" +msgstr "Ləqəb:" + +#: src/fe-gtk/servlistgui.c:1064 +msgid "Server Password:" +msgstr "Verici Şifrəsi:" + +#: src/fe-gtk/servlistgui.c:1066 +msgid "Join Channels:" +msgstr "Bağlanacaq Kanallar:" + +#: src/fe-gtk/servlistgui.c:1068 +msgid "Channels to join, separated by commas, but not spaces!" +msgstr "Daxil olunacaq kanallar (vegüllə ayırın)" + +#: src/fe-gtk/servlistgui.c:1069 +msgid "Connect Command:" +msgstr "Bağlanma Əmri:" + +#: src/fe-gtk/servlistgui.c:1071 +msgid "" +"Command to execute after connecting. Can be used to authenticate to NickServ" +msgstr "" +"Bağlandıqdan sonra icra ediləcək əmr. Məsələn NickServ-ə qeyd olmaq üçün" + +#: src/fe-gtk/servlistgui.c:1079 +msgid "Cycle until connected" +msgstr "Bağlanana qədər sına" + +#: src/fe-gtk/servlistgui.c:1080 +msgid "Use global user info" +msgstr "Ümumi istifadəçi mə'lumatını işlət" + +#: src/fe-gtk/servlistgui.c:1081 +msgid "Use secure SSL" +msgstr "E'tibarlı SSL işlət" + +#: src/fe-gtk/servlistgui.c:1082 +msgid "Auto connect at startup" +msgstr "Avtomatik bağlan" + +#: src/fe-gtk/servlistgui.c:1083 +msgid "Use a proxy server" +msgstr "Vəkil vericisi işlət" + +#: src/fe-gtk/servlistgui.c:1084 +msgid "Accept invalid cert." +msgstr "Hökmsüz vəs. qəbulu" + +#: src/fe-gtk/servlistgui.c:1093 +msgid "Settings for Selected Network" +msgstr "Seçili Şəbəkənin Qurğuları" + +#: src/fe-gtk/servlistgui.c:1133 +msgid "Edit mode" +msgstr "Təfərruatlar" + +#: src/fe-gtk/servlistgui.c:1140 +msgid "Networks" +msgstr "Şəbəkələr" + +#: src/fe-gtk/servlistgui.c:1185 +msgid "No server list on startup" +msgstr "Başlanğıcda verici siyahısını göstərmə" + +#: src/fe-gtk/servlistgui.c:1212 +msgid "X-Chat: Server List" +msgstr "X-Chat: Verici Siyahı" + +#: src/fe-gtk/setup.c:84 +msgid "Font:" +msgstr "Yazı növü:" + +#: src/fe-gtk/setup.c:85 +msgid "Background image:" +msgstr "Arxa plan rəsmi:" + +#: src/fe-gtk/setup.c:86 +msgid "Time stamp format:" +msgstr "Tarix mühürü şəkli:" + +#: src/fe-gtk/setup.c:87 +msgid "See strftime manpage for details." +msgstr "Təfərruatlar üçün strftime man səhifəsinə baxın" + +#: src/fe-gtk/setup.c:88 +msgid "Time stamp text" +msgstr "Tarix mühürü mətni" + +#: src/fe-gtk/setup.c:89 +msgid "Transparent background" +msgstr "Şəffaf arxa plan" + +#: src/fe-gtk/setup.c:90 +msgid "Indent nicks" +msgstr "Ləqəbləri çərtmələ" + +#: src/fe-gtk/setup.c:91 +msgid "Tint transparency" +msgstr "Rəngli şəffaflıq" + +#: src/fe-gtk/setup.c:92 +msgid "Colored nicks" +msgstr "Rəngli ləqəblər" + +#: src/fe-gtk/setup.c:93 +msgid "Strip mIRC color" +msgstr "mIRC rənglərini göstərmə" + +#: src/fe-gtk/setup.c:94 +msgid "Scrollback lines:" +msgstr "Geri dönüş sətiri miqdarı:" + +#: src/fe-gtk/setup.c:95 +msgid "Tint red:" +msgstr "Qırmızı:" + +#: src/fe-gtk/setup.c:96 +msgid "Tint green:" +msgstr "Yaşıl:" + +#: src/fe-gtk/setup.c:97 +msgid "Tint blue:" +msgstr "Mavi:" + +#: src/fe-gtk/setup.c:103 +#, c-format +msgid "Interpret %nnn as an ASCII value" +msgstr "%nnn-ı ASCII qiyməti olaraq qəbul et" + +#: src/fe-gtk/setup.c:104 +msgid "Automatic nick completion" +msgstr "Avtomatik ləqəb tamamlaması" + +#: src/fe-gtk/setup.c:105 +msgid "Interpret %C, %B as Color, Bold etc" +msgstr "" + +#: src/fe-gtk/setup.c:106 src/fe-gtk/setup.c:138 +msgid "Use the Text box font and colors" +msgstr "Söhbət pəncərəsi yazı növü və rənglərini işlət" + +#: src/fe-gtk/setup.c:107 +msgid "Nick completion suffix:" +msgstr "" + +#: src/fe-gtk/setup.c:113 +msgid "Off" +msgstr "Bağlı" + +#: src/fe-gtk/setup.c:114 +msgid "Graph" +msgstr "Qrafika" + +#: src/fe-gtk/setup.c:115 +msgid "Info text" +msgstr "Mə'lumat mətni" + +#: src/fe-gtk/setup.c:116 +msgid "Both" +msgstr "Hər ikisi də" + +#: src/fe-gtk/setup.c:122 +msgid "A-Z, Ops first" +msgstr "A-Z, Əvvəlcə Oplar" + +#: src/fe-gtk/setup.c:123 +msgid "A-Z" +msgstr "A-Z" + +#: src/fe-gtk/setup.c:124 +msgid "Z-A, Ops last" +msgstr "Z-A, Oplar Sonda" + +#: src/fe-gtk/setup.c:125 +msgid "Z-A" +msgstr "Z-A" + +#: src/fe-gtk/setup.c:126 +msgid "Unsorted" +msgstr "Nizamsız" + +#: src/fe-gtk/setup.c:132 +msgid "Lag meter:" +msgstr "Lag ölçəni:" + +#: src/fe-gtk/setup.c:133 +msgid "Throttle meter:" +msgstr "Throttle ölçəni:" + +#: src/fe-gtk/setup.c:134 +msgid "Userlist sorted by:" +msgstr "İstifadəçi siyahısının nizamlanma şəkli:" + +#: src/fe-gtk/setup.c:135 +msgid "Double-click command:" +msgstr "Cüt təqlama əmri:" + +#: src/fe-gtk/setup.c:136 +msgid "Show hostnames in userlist" +msgstr "İstifadəçi siyahısında qovşaq adlarını göstər" + +#: src/fe-gtk/setup.c:137 +msgid "Userlist buttons enabled" +msgstr "İstifadəçi siyahısı düymələrini göstər" + +#: src/fe-gtk/setup.c:139 +msgid "Resizable userlist" +msgstr "Böyüklüyü dəyişdirilə bilən istifadəçi siyahısı" + +#: src/fe-gtk/setup.c:140 +msgid "Track away-status on channels smaller than:" +msgstr "" + +#: src/fe-gtk/setup.c:146 +msgid "Windows" +msgstr "Pəncərələrdə" + +#: src/fe-gtk/setup.c:147 src/fe-gtk/setup.c:906 +msgid "Tabs" +msgstr "Səkmələrdə" + +#: src/fe-gtk/setup.c:153 +msgid "Bottom" +msgstr "Altda" + +#: src/fe-gtk/setup.c:154 +msgid "Top" +msgstr "Üstdə" + +#: src/fe-gtk/setup.c:155 +msgid "Left" +msgstr "Solda" + +#: src/fe-gtk/setup.c:156 +msgid "Right" +msgstr "Sağda" + +#: src/fe-gtk/setup.c:157 +msgid "Hidden" +msgstr "Göstərmə" + +#: src/fe-gtk/setup.c:163 +msgid "Show tabs at:" +msgstr "Səkmələrin göstərilmə şəkli:" + +#: src/fe-gtk/setup.c:164 +msgid "Open channels in:" +msgstr "Kanalların açılma şəkli:" + +#: src/fe-gtk/setup.c:165 +msgid "Open dialogs in:" +msgstr "Dialoqların açılma şəkli:" + +#: src/fe-gtk/setup.c:166 +msgid "Open utilities in:" +msgstr "Vasitələrin açılma şəkli:" + +#: src/fe-gtk/setup.c:166 +msgid "Open DCC, Ignore, Notify etc, in tabs or windows?" +msgstr "" +"DCC Açılması, Rədd Etmə, Bildirişlər səkmələrdəmi yoxsa pəncərələrdəmi " +"açılsın?" + +#: src/fe-gtk/setup.c:167 +msgid "Open tab for server messages" +msgstr "Verici ismarışları üçün səkmə aç" + +#: src/fe-gtk/setup.c:168 +msgid "Open tab for server notices" +msgstr "Verici bildirişləri üçün səkmə aç" + +#: src/fe-gtk/setup.c:169 +msgid "Pop new tabs to front" +msgstr "Yeni səkmələri qabağa gətir" + +#: src/fe-gtk/setup.c:170 +msgid "Shorten tabs to:" +msgstr "Tabların böyüklüyü:" + +#: src/fe-gtk/setup.c:170 +msgid "letters." +msgstr "hərf." + +#: src/fe-gtk/setup.c:176 +msgid "Download files to:" +msgstr "Faylları buraya endir:" + +#: src/fe-gtk/setup.c:177 +msgid "Move completed files to:" +msgstr "Tamamlanan faylları buraya daşı:" + +#: src/fe-gtk/setup.c:178 +msgid "DCC IP address:" +msgstr "DCC IP ünvanı:" + +#: src/fe-gtk/setup.c:179 +msgid "Claim you are at this address when offering files." +msgstr "Fayl təklif edəndə bu ünvanda olduğunu bildir." + +#: src/fe-gtk/setup.c:180 +msgid "First DCC send port:" +msgstr "Birinci DCC göndərmə portu:" + +#: src/fe-gtk/setup.c:181 +msgid "Last DCC send port:" +msgstr "Sonuncu DCC göndərmə portu:" + +#: src/fe-gtk/setup.c:182 +msgid "(Leave ports at zero for full range)." +msgstr "(Tam aralıq üçün portları boş buraxın)" + +#: src/fe-gtk/setup.c:183 +msgid "Auto open DCC send list" +msgstr "DCC göndərmə siyahısını avtomatik aç" + +#: src/fe-gtk/setup.c:184 +msgid "Convert spaces to underscore" +msgstr "Boşluqları alt cızıqlara dönüşdür" + +#: src/fe-gtk/setup.c:185 +msgid "In filenames, before sending" +msgstr "Fayl adlarında, göndərmədən əvvəl" + +#: src/fe-gtk/setup.c:186 +msgid "Auto open DCC chat list" +msgstr "DCC söhbət siyahısını avtomatik aç" + +#: src/fe-gtk/setup.c:187 +msgid "Save nickname in filenames" +msgstr "Fayl adlarına ləqəbi qeyd et" + +#: src/fe-gtk/setup.c:188 +msgid "Auto open DCC receive list" +msgstr "DCC alış siyahısını avtomatik aç" + +#: src/fe-gtk/setup.c:189 +msgid "Get my IP from IRC server" +msgstr "IP-mi IRC vericisindən al" + +#: src/fe-gtk/setup.c:190 +msgid "" +"/WHOIS yourself to find your real address. Use this if you have a 192.168.*." +"* address!" +msgstr "" +"Həqiqi ünvanınızı bilmək üçün özünüzü /WHOIS-ləyin. Əgər 192.168.*.* bənzəri " +"ünvanınız varsa bunu işlədin." + +#: src/fe-gtk/setup.c:191 +msgid "Max. send CPS:" +msgstr "Maks. göndərmə CPS-i:" + +#: src/fe-gtk/setup.c:192 src/fe-gtk/setup.c:194 +msgid "Max. speed for one transfer" +msgstr "Bir transfer üçün maksimal sür'ət" + +#: src/fe-gtk/setup.c:193 +msgid "Max. receive CPS:" +msgstr "Maks. alış CPS-i:" + +#: src/fe-gtk/setup.c:195 +msgid "Max. global send CPS:" +msgstr "Maks. qlobal göndərmə CPS-i:" + +#: src/fe-gtk/setup.c:196 src/fe-gtk/setup.c:198 +msgid "Max. speed for all traffic" +msgstr "Bütün alış verişlər üçün maksimal sür'ət" + +#: src/fe-gtk/setup.c:197 +msgid "Max. global receive CPS:" +msgstr "Maks. qlobal alış CPS-i:" + +#: src/fe-gtk/setup.c:199 +msgid "(Leave at zero for full speed file transfers)." +msgstr "(Tam sür'ətli transferlər üçün boş buraxın)" + +#: src/fe-gtk/setup.c:205 +msgid "Default quit message:" +msgstr "Ön qurğulu çıxış ismarışı:" + +#: src/fe-gtk/setup.c:206 +msgid "Default part message:" +msgstr "Ön qurğulu part ismarışı:" + +#: src/fe-gtk/setup.c:207 +msgid "Default away message:" +msgstr "Ön qurğulu uzaqda ismarışı:" + +#: src/fe-gtk/setup.c:209 +msgid "(Can be a text file relative to ~/.xchat2/)." +msgstr "" + +#: src/fe-gtk/setup.c:211 +msgid "(Can be a text file relative to config dir)." +msgstr "" + +#: src/fe-gtk/setup.c:213 +msgid "Extra words to highlight on:" +msgstr "İşıqlandırılacaq əlavə kəlmələr:" + +#: src/fe-gtk/setup.c:214 +msgid "(Separate multiple words with commas)." +msgstr "" + +#: src/fe-gtk/setup.c:215 +msgid "Show away once" +msgstr "Uzaqda cəziyyətini bir dəfə göstər" + +#: src/fe-gtk/setup.c:215 +#, fuzzy +msgid "Show identical away messages only once" +msgstr "Göstər" + +#: src/fe-gtk/setup.c:216 +#, fuzzy +msgid "Beep on private messages" +msgstr "açık xüsusi" + +#: src/fe-gtk/setup.c:217 +msgid "Automatically unmark away" +msgstr "" + +#: src/fe-gtk/setup.c:217 +#, fuzzy +msgid "Unmark yourself as away before sending messages" +msgstr "əvvəl" + +#: src/fe-gtk/setup.c:218 +#, fuzzy +msgid "Beep on channel messages" +msgstr "açık" + +#: src/fe-gtk/setup.c:219 +msgid "Announce away messages" +msgstr "" + +#: src/fe-gtk/setup.c:219 +msgid "Announce your away messages to all channels" +msgstr "" + +#: src/fe-gtk/setup.c:220 +#, fuzzy +msgid "Beep on highlighted messages" +msgstr "açık" + +#: src/fe-gtk/setup.c:221 +#, fuzzy +msgid "Display MODEs in raw form" +msgstr "Göstər in" + +#: src/fe-gtk/setup.c:222 +#, fuzzy +msgid "Whois on notify" +msgstr "açık" + +#: src/fe-gtk/setup.c:222 +#, fuzzy +msgid "Sends a /WHOIS when a user comes online in your notify list" +msgstr "a a in" + +#: src/fe-gtk/setup.c:223 +#, fuzzy +msgid "Hide join/part messages" +msgstr "Gizlət" + +#: src/fe-gtk/setup.c:223 +#, fuzzy +msgid "Hide channel join/part messages by default" +msgstr "Gizlət ön qurğulu" + +#: src/fe-gtk/setup.c:224 +#, fuzzy +msgid "Auto reconnect delay:" +msgstr "Avtomatik:" + +#: src/fe-gtk/setup.c:230 +msgid "Log filename mask:" +msgstr "" + +#: src/fe-gtk/setup.c:231 +#, c-format +msgid "(%s=Server %c=Channel %n=Network)." +msgstr "(%s=Verici %c=Kanal %n=Şəbəkə)" + +#: src/fe-gtk/setup.c:232 +msgid "Log timestamp format:" +msgstr "" + +#: src/fe-gtk/setup.c:233 +#, fuzzy +msgid "(See strftime manpage for details)." +msgstr "Baxın." + +#: src/fe-gtk/setup.c:234 +#, fuzzy +msgid "Enable logging of conversations" +msgstr "Fəallaşdır /" + +#: src/fe-gtk/setup.c:235 +msgid "Insert timestamps in logs" +msgstr "Qeydlərə tarix mühürünü daxil et" + +#: src/fe-gtk/setup.c:241 +msgid "(Disabled)" +msgstr "(Qeyri fəaldır)" + +#: src/fe-gtk/setup.c:242 +msgid "Wingate" +msgstr "Wingate" + +#: src/fe-gtk/setup.c:243 +msgid "Socks4" +msgstr "Socks4" + +#: src/fe-gtk/setup.c:244 +msgid "Socks5" +msgstr "Socks5" + +#: src/fe-gtk/setup.c:245 +msgid "HTTP" +msgstr "HTTP" + +#: src/fe-gtk/setup.c:251 +msgid "Address to bind to:" +msgstr "Yapışdırılacaq ünvan:" + +#: src/fe-gtk/setup.c:252 +msgid "(Only useful for computers with multiple addresses)." +msgstr "" + +#: src/fe-gtk/setup.c:253 +msgid "Proxy server" +msgstr "Vəkil vericisi" + +#: src/fe-gtk/setup.c:254 +msgid "Hostname:" +msgstr "Qovşaq adı:" + +#: src/fe-gtk/setup.c:255 +msgid "Username:" +msgstr "İstifadəçi adı:" + +#: src/fe-gtk/setup.c:256 +msgid "Password:" +msgstr "Şifrə:" + +#: src/fe-gtk/setup.c:257 +msgid "Port:" +msgstr "Qapı:" + +#: src/fe-gtk/setup.c:258 +msgid "Type:" +msgstr "Növ:" + +#: src/fe-gtk/setup.c:260 +msgid "Authenticate to the proxy server (only HTTP)" +msgstr "Vəkil vericisinə tanıt (Ancaq HTTP)" + +#: src/fe-gtk/setup.c:483 +msgid "Select an Image File" +msgstr "Rəsm faylı seç" + +#: src/fe-gtk/setup.c:530 +msgid "Select font" +msgstr "Yazı növü seç" + +#: src/fe-gtk/setup.c:604 +msgid "Browse..." +msgstr "Gəz..." + +#: src/fe-gtk/setup.c:768 +msgid "Select color" +msgstr "Rəng seç" + +#: src/fe-gtk/setup.c:834 +msgid "mIRC colors:" +msgstr "mIRC rəngləri:" + +#: src/fe-gtk/setup.c:843 +msgid "Foreground:" +msgstr "Ön plan:" + +#: src/fe-gtk/setup.c:844 +msgid "Background:" +msgstr "Arxa plan:" + +#: src/fe-gtk/setup.c:846 +msgid "Mark fore:" +msgstr "Ön işarə:" + +#: src/fe-gtk/setup.c:847 +msgid "Mark back:" +msgstr "Arxa işarə:" + +#: src/fe-gtk/setup.c:849 +msgid "Away User:" +msgstr "Uzaq İstifadəçi:" + +#: src/fe-gtk/setup.c:851 +#, fuzzy +msgid "Tab colors" +msgstr "mIRC rəngləri:" + +#: src/fe-gtk/setup.c:862 +msgid "New Data:" +msgstr "Yeni Mə'lumat:" + +#: src/fe-gtk/setup.c:863 +msgid "New Message:" +msgstr "Yeni İsmarış:" + +#: src/fe-gtk/setup.c:864 +msgid "Highlight:" +msgstr "İşıqlandırma:" + +#: src/fe-gtk/setup.c:902 +msgid "Interface" +msgstr "Ara üz" + +#: src/fe-gtk/setup.c:903 +msgid "Text box" +msgstr "Söhbət pəncərəsi" + +#: src/fe-gtk/setup.c:904 +msgid "Input box" +msgstr "Giriş qutusu" + +#: src/fe-gtk/setup.c:905 +msgid "User list" +msgstr "İstifadəçi siyahısı" + +#: src/fe-gtk/setup.c:907 +msgid "Colors" +msgstr "Rənglər" + +#: src/fe-gtk/setup.c:909 +msgid "Chatting" +msgstr "Söhbət" + +#: src/fe-gtk/setup.c:910 +msgid "General" +msgstr "Ümumi" + +#: src/fe-gtk/setup.c:911 +msgid "Logging" +msgstr "Qeyd" + +#: src/fe-gtk/setup.c:913 +msgid "Network" +msgstr "Şəbəkə" + +#: src/fe-gtk/setup.c:914 +msgid "Network setup" +msgstr "Şəbəkə qurğusu" + +#: src/fe-gtk/setup.c:915 +msgid "File transfers" +msgstr "Fayl transferləri" + +#: src/fe-gtk/setup.c:1020 +msgid "Categories" +msgstr "Kateqoriyalar" + +#: src/fe-gtk/setup.c:1146 +msgid "Some settings were changed that require a restart to take full effect." +msgstr "" +"Bə'zi seçimlərin tətbiq edilməsi üçün proqramı yenidən başlatmalısınız." + +#: src/fe-gtk/setup.c:1173 +msgid "X-Chat: Preferences" +msgstr "X-Chat: Seçimlər" + +#: src/fe-gtk/textgui.c:184 +msgid "There was an error parsing the string" +msgstr "Qatar oxunanda xəta yarandı" + +#: src/fe-gtk/textgui.c:192 +#, c-format +msgid "This signal is only passed %d args, $%d is invalid" +msgstr "" + +#: src/fe-gtk/textgui.c:304 src/fe-gtk/textgui.c:326 +msgid "Print Texts File" +msgstr "Mətn Faylını Çap Et" + +#: src/fe-gtk/textgui.c:382 +msgid "Event" +msgstr "Hadisə" + +#: src/fe-gtk/textgui.c:384 +msgid "Sound" +msgstr "Səs" + +#: src/fe-gtk/textgui.c:386 +msgid "$ Number" +msgstr "$ Nömrəsi" + +#: src/fe-gtk/textgui.c:396 +msgid "Edit Events" +msgstr "Hadisələri Dəyişdir" + +#: src/fe-gtk/textgui.c:434 +msgid "Sound file: " +msgstr "Səs faylı: " + +#: src/fe-gtk/textgui.c:469 +msgid "Save As" +msgstr "Fərqli Qeyd Et" + +#: src/fe-gtk/textgui.c:474 +msgid "Load From" +msgstr "Buradan Yüklə" + +#: src/fe-gtk/textgui.c:479 +msgid "Test All" +msgstr "Hamısı Sına" + +#: src/fe-gtk/urlgrab.c:97 +msgid "URL" +msgstr "URL" + +#: src/fe-gtk/urlgrab.c:147 +msgid "Select a file to save to" +msgstr "Qeyd ediləcək fayl seç" + +#: src/fe-gtk/urlgrab.c:187 +msgid "X-Chat: URL Grabber" +msgstr "X-Chat: URL Alıcısı" + +#: src/fe-gtk/urlgrab.c:200 +msgid "Clear list" +msgstr "Siyahını təmizlə" + +#: src/fe-gtk/urlgrab.c:202 +msgid "Copy selected URL" +msgstr "Seçili URL-ni Köçür" + +#: src/fe-gtk/urlgrab.c:202 +msgid "Copy" +msgstr "Köçür" + +#: src/fe-gtk/urlgrab.c:204 +msgid "Save list to a file" +msgstr "Siyahını fayla qeyd et" + +#: src/fe-gtk/userlistgui.c:108 +#, c-format +msgid "%d ops, %d total" +msgstr "%d op, %d toplam" + +#~ msgid "Error String" +#~ msgstr "Xətalı Qatar" + +#~ msgid "Error name" +#~ msgstr "Xəta adı" + +#~ msgid "Error string" +#~ msgstr "Xəta qatarı" diff --git a/po/be.po b/po/be.po new file mode 100644 index 00000000..5ab10312 --- /dev/null +++ b/po/be.po @@ -0,0 +1,5278 @@ +# translation of xchat-2.8.1.po to Belarusian +# This file is put in the public domain. +# Pavel Piatruk , 2006, 2007. +msgid "" +msgstr "" +"Project-Id-Version: xchat 2.8.1\n" +"Report-Msgid-Bugs-To: www.xchat.org\n" +"POT-Creation-Date: 2007-03-28 14:09+1000\n" +"PO-Revision-Date: 2007-05-23 12:27+0300\n" +"Last-Translator: Pavel Piatruk \n" +"Language-Team: Belarusian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.10.2\n" + +#: src/common/cfgfiles.c:354 +msgid "Cannot create ~/.xchat2" +msgstr "Не магу стварыць ~/.xchat2" + +#: src/common/cfgfiles.c:704 +msgid "I'm busy" +msgstr "Я заняты" + +#: src/common/cfgfiles.c:705 +msgid "Leaving" +msgstr "Выходжу" + +#: src/common/cfgfiles.c:751 +msgid "" +"* Running IRC as root is stupid! You should\n" +" create a User Account and use that to login.\n" +msgstr "" +"* Выконваць IRC з-пад root'a - глупства.\n" +" Вы павінны стварыць карыстальніцкі\n" +" рахунак у сістэме і ўжываць яго\n" + +#: src/common/dcc.c:67 +msgid "Waiting" +msgstr "Чаканне" + +#: src/common/dcc.c:68 +msgid "Active" +msgstr "Актыўны" + +#: src/common/dcc.c:69 +msgid "Failed" +msgstr "Памылка" + +#: src/common/dcc.c:70 +msgid "Done" +msgstr "Выканана" + +#: src/common/dcc.c:71 src/fe-gtk/menu.c:775 +msgid "Connect" +msgstr "Злучэнне" + +#: src/common/dcc.c:72 +msgid "Aborted" +msgstr "Перарвана" + +#: src/common/dcc.c:1886 src/common/outbound.c:2450 +#, c-format +msgid "Cannot access %s\n" +msgstr "Няма доступу да %s\n" + +#: src/common/dcc.c:1887 src/common/text.c:918 src/common/text.c:956 +#: src/common/text.c:967 src/common/text.c:974 src/common/text.c:987 +#: src/common/text.c:1004 src/common/text.c:1104 src/common/util.c:352 +msgid "Error" +msgstr "Памылка" + +#: src/common/dcc.c:2375 +#, c-format +msgid "%s is offering \"%s\". Do you want to accept?" +msgstr "%s прапануе \"%s\". Вы згодны?" + +#: src/common/dcc.c:2586 +msgid "No active DCCs\n" +msgstr "Няма актыўных каналаў данніх (DCC)\n" + +#: src/common/ignore.c:120 src/common/ignore.c:124 src/common/ignore.c:128 +#: src/common/ignore.c:132 src/common/ignore.c:136 src/common/ignore.c:140 +#: src/common/ignore.c:144 +msgid "YES " +msgstr "Так " + +#: src/common/ignore.c:122 src/common/ignore.c:126 src/common/ignore.c:130 +#: src/common/ignore.c:134 src/common/ignore.c:138 src/common/ignore.c:142 +#: src/common/ignore.c:146 +msgid "NO " +msgstr "Не " + +#: src/common/ignore.c:377 +#, c-format +msgid "You are being CTCP flooded from %s, ignoring %s\n" +msgstr "Вас затапліваюць CTCP запытамі з %s, %s ігнаруецца\n" + +#: src/common/ignore.c:402 +#, c-format +msgid "You are being MSG flooded from %s, setting gui_auto_open_dialog OFF.\n" +msgstr "Вас затапліваюць паведамленнямі з %s, аўтадыялог адключаны\n" + +#: src/common/notify.c:449 +#, c-format +msgid " %-20s online\n" +msgstr " %-20s у сеціве\n" + +#: src/common/notify.c:451 +#, c-format +msgid " %-20s offline\n" +msgstr " %-20s адключаны\n" + +#: src/common/outbound.c:72 +msgid "No channel joined. Try /join #\n" +msgstr "Не зайшлі на канал. Паспрабуйце /join #\n" + +#: src/common/outbound.c:78 +msgid "Not connected. Try /server []\n" +msgstr "Няма злучэння. Паспрабуйце /server <вузел> [<порт>]\n" + +#: src/common/outbound.c:339 +#, c-format +msgid "Already marked away: %s\n" +msgstr "Ужо пазначаны адышэдшым: %s\n" + +#: src/common/outbound.c:409 +msgid "Already marked back.\n" +msgstr "Ужо пазначаны вярнуўшымся.\n" + +#: src/common/outbound.c:1812 +msgid "I need /bin/sh to run!\n" +msgstr "Для запуску патрэбна праграма /bin/sh !\n" + +#: src/common/outbound.c:2183 +msgid "Commands Available:" +msgstr "Даступныя каманды:" + +#: src/common/outbound.c:2197 +msgid "User defined commands:" +msgstr "Вызначаныя карыстальнікам каманды:" + +#: src/common/outbound.c:2213 +msgid "Plugin defined commands:" +msgstr "Вызначаныя плагінам каманды:" + +#: src/common/outbound.c:2224 +msgid "Type /HELP for more information, or /HELP -l" +msgstr "Набярыце /HELP <каманда> для даведкі ці /HELP -l" + +#: src/common/outbound.c:2299 +#, c-format +msgid "Unknown arg '%s' ignored." +msgstr "Невядомы аргумент '%s' праігнараваны." + +#: src/common/outbound.c:3238 +msgid "No such plugin found.\n" +msgstr "Плагін не знойдзены.\n" + +#: src/common/outbound.c:3243 src/fe-gtk/plugingui.c:186 +msgid "That plugin is refusing to unload.\n" +msgstr "Гэты плагін немагчыма выгрузіць.\n" + +#: src/common/outbound.c:3512 +msgid "ADDBUTTON , adds a button under the user-list" +msgstr "ADDBUTTON <імя> <дзеянне>, дадае кнопку пад спісам карыстальнікаў" + +#: src/common/outbound.c:3514 +msgid "ALLCHAN , sends a command to all channels you're in" +msgstr "ALLCHAN <каманда>, дасылае каманду на ўсе каналы, куды вы зайшлі" + +#: src/common/outbound.c:3516 +msgid "ALLCHANL , sends a command to all channels you're in" +msgstr "ALLCHANL <каманда>, дасылае каманду на ўсе каналы, куды вы зайшлі" + +#: src/common/outbound.c:3518 +msgid "ALLSERV , sends a command to all servers you're in" +msgstr "ALLSERV <каманда>, дасылае каманду на ўсе серверы, з якімі вы злучаны" + +#: src/common/outbound.c:3519 +msgid "AWAY [], sets you away" +msgstr "AWAY [<прычына>], усталяваць статус \"адыйшоў\"" + +#: src/common/outbound.c:3520 +msgid "BACK, sets you back (not away)" +msgstr "BACK, пазначае вас вярнуўшымся (не адышэдшым)" + +#: src/common/outbound.c:3522 +msgid "BAN [], bans everyone matching the mask from the current channel. If they are already on the channel this doesn't kick them (needs chanop)" +msgstr "BAN <маска> [<тыпзабароны>], забараняе доступ да канала кожнаму, хто адпавядае маске. Калі гэткія карыстальнікі ўжо на канале, яны не будуць выпхнутыя. (Трэба правы аператара)" + +#: src/common/outbound.c:3524 +msgid "" +"Set per channel options\n" +"CHANOPT CONFMODE ON|OFF - Toggle conf mode/showing of join and part messages\n" +"CHANOPT COLORPASTE ON|OFF - Toggle color paste\n" +"CHANOPT BEEP ON|OFF - Toggle beep on message\n" +"CHANOPT TRAY ON|OFF - Toggle tray blink on message" +msgstr "" +"Наладкі адносна канала\n" +"CHANOPT CONFMODE ON|OFF - Пераключыцца паміж рэжымам канферэнцыі і паказам уваходных і выходзячых паведамленняў\n" +"CHANOPT COLORPASTE ON|OFF - Пераключыць устаўку колераў\n" +"CHANOPT BEEP ON|OFF - Пераключыць пішчанне пры паведамленнях \n" +"CHANOPT TRAY ON|OFF - Пераключыць мірганне ў сподку пры паведамленнях" + +#: src/common/outbound.c:3531 +msgid "CLEAR [ALL|HISTORY], Clears the current text window or command history" +msgstr "CLEAR, Ачышчае бягучае тэкставае акно або гісторыю каманд" + +#: src/common/outbound.c:3532 +msgid "CLOSE, Closes the current window/tab" +msgstr "CLOSE, Закрывае бягучае акно ці ўкладку" + +#: src/common/outbound.c:3535 +msgid "COUNTRY [-s] , finds a country code, eg: au = australia" +msgstr "COUNTRY [-s] <код|маска>, шукае код краіны, напрыклад: au = australia" + +#: src/common/outbound.c:3537 +msgid "CTCP , send the CTCP message to nick, common messages are VERSION and USERINFO" +msgstr "CTCP <мянушка> <паведамленне>, дасылае мянушцы CTCP-паведамленне, напрыклад, VERSION ці USERINFO" + +#: src/common/outbound.c:3539 +msgid "CYCLE, parts current channel and immediately rejoins" +msgstr "CYCLE, выйсці з бягучага канала і адразу зайсці зноў" + +#: src/common/outbound.c:3541 +msgid "" +"\n" +"DCC GET - accept an offered file\n" +"DCC SEND [-maxcps=#] [file] - send a file to someone\n" +"DCC PSEND [-maxcps=#] [file] - send a file using passive mode\n" +"DCC LIST - show DCC list\n" +"DCC CHAT - offer DCC CHAT to someone\n" +"DCC PCHAT - offer DCC CHAT using passive mode\n" +"DCC CLOSE example:\n" +" /dcc close send johnsmith file.tar.gz" +msgstr "" +"\n" +"DCC GET <мянушка> - дазволіць прапанаваны файл\n" +"DCC SEND [-maxcps=#] <мянушка> [файл] - даслаць файл камусьці\n" +"DCC PSEND [-maxcps=#] <мянушка> [файл] - даслаць файл у пасіўным рэжыме\n" +"DCC LIST - паказаць спіс DCC\n" +"DCC CHAT <мянушка> - прапанаваць DCC CHAT камусьці\n" +"DCC PCHAT <мянушка> - прапанаваць DCC CHAT у пасіўным рэжыме\n" +"DCC CLOSE <тып> <мянушка> <файл> напрыклад:\n" +" /dcc close send johnsmith file.tar.gz" + +#: src/common/outbound.c:3553 +msgid "DEHOP , removes chanhalf-op status from the nick on the current channel (needs chanop)" +msgstr "DEHOP <мянушка>, выдаляе статус паўаператара ў мянушкі на бягучым канале (патрэбен статус аператара)" + +#: src/common/outbound.c:3555 +msgid "DELBUTTON , deletes a button from under the user-list" +msgstr "DELBUTTON <імя>, выдаляе кнопку пад спісам карыстальнікаў" + +#: src/common/outbound.c:3557 +msgid "DEOP , removes chanop status from the nick on the current channel (needs chanop)" +msgstr "DEOP <мянушка>, выдаляе статус аператара ў мянушкі на бягучым канале (патрэбен статус аператара)" + +#: src/common/outbound.c:3559 +msgid "DEVOICE , removes voice status from the nick on the current channel (needs chanop)" +msgstr "DEVOICE <мянушка>, выдаляе права голасу ў мянушкі на бягучым канале (патрэбен статус аператара)" + +#: src/common/outbound.c:3560 +msgid "DISCON, Disconnects from server" +msgstr "DISCON, Адлучыцца ад сервера" + +#: src/common/outbound.c:3561 +msgid "DNS , Finds a users IP number" +msgstr "DNS <мянушка|вузел|ip>, Знайсці IP-адрас карыстальніка" + +#: src/common/outbound.c:3562 +msgid "ECHO , Prints text locally" +msgstr "ECHO <тэкст>, Выводзіць тэкст на лакальнай машыне" + +#: src/common/outbound.c:3565 +msgid "EXEC [-o] , runs the command. If -o flag is used then output is sent to current channel, else is printed to current text box" +msgstr "EXEC [-o] <каманда>, запускае каманду. Калі ўжыты параметр -o, вывад будзе дасланы ў бягучы канал, інакш у бягучае тэкставае акно" + +#: src/common/outbound.c:3567 +msgid "EXECCONT, sends the process SIGCONT" +msgstr "EXECCONT, дасылае працэсу сігнал SIGCONT" + +#: src/common/outbound.c:3570 +msgid "EXECKILL [-9], kills a running exec in the current session. If -9 is given the process is SIGKILL'ed" +msgstr "EXECKILL [-9], забівае выконваючуюся каманду ў бягучай сесіі. Калі адзначаны флаг -9, працэсу дасылается сігнал SIGKILL" + +#: src/common/outbound.c:3572 +msgid "EXECSTOP, sends the process SIGSTOP" +msgstr "EXECSTOP, дасылае працэсу сігнал SIGSTOP" + +#: src/common/outbound.c:3573 +msgid "EXECWRITE, sends data to the processes stdin" +msgstr "EXECWRITE, дасылае данні на стандартны ўваход працэса (stdin)" + +#: src/common/outbound.c:3577 +msgid "FLUSHQ, flushes the current server's send queue" +msgstr "FLUSHQ, скінуць чаргу дасылкі на бягучы сервер" + +#: src/common/outbound.c:3579 +msgid "GATE [], proxies through a host, port defaults to 23" +msgstr "GATE <вузел> [<порт>], далучыцца праз вузел, прадвызначаны порт 23" + +#: src/common/outbound.c:3583 +msgid "GHOST , Kills a ghosted nickname" +msgstr "GHOST <мянушка> <пароль>, Выпхнуць з канала карыстальніка-здань" + +#: src/common/outbound.c:3588 +msgid "HOP , gives chanhalf-op status to the nick (needs chanop)" +msgstr "HOP <мянушка>, даць правы паў-аператара карыстальніку (патрэбна мець правы аператара)" + +#: src/common/outbound.c:3589 +msgid "ID , identifies yourself to nickserv" +msgstr "ID <пароль>, ідэнтыфікаваць сябе nickserv" + +#: src/common/outbound.c:3591 +msgid "" +"IGNORE \n" +" mask - host mask to ignore, eg: *!*@*.aol.com\n" +" types - types of data to ignore, one or all of:\n" +" PRIV, CHAN, NOTI, CTCP, DCC, INVI, ALL\n" +" options - NOSAVE, QUIET" +msgstr "" +"IGNORE <маска> <тыпы..> <уласцівасці..>\n" +" маска - маска для ігнаравання, напрыклад: *!*@*.aol.com\n" +" тыпы - тыпы дадзеных для ігнаравання:\n" +" PRIV, CHAN, NOTI, CTCP, DCC, INVI, ALL\n" +" уласцівасці - NOSAVE, QUIET" + +#: src/common/outbound.c:3598 +msgid "INVITE [], invites someone to a channel, by default the current channel (needs chanop)" +msgstr "INVITE <мянушка> [<канал>], запрасіць кагосьці на канал, калі назва канала не пазначана - на бягучы канал (патрэбен статус аператара)" + +#: src/common/outbound.c:3599 +msgid "JOIN , joins the channel" +msgstr "JOIN <канал>, увайсці на канал" + +#: src/common/outbound.c:3601 +msgid "KICK , kicks the nick from the current channel (needs chanop)" +msgstr "KICK <мянушка>, выпхнуць карыстальніка з бягучага канала (патрэбен статус аператара)" + +#: src/common/outbound.c:3603 +msgid "KICKBAN , bans then kicks the nick from the current channel (needs chanop)" +msgstr "KICKBAN <мянушка>, забараняе, а потым выпіхвае карыстальніка з бягучага канала (патрэбен статус аператара)" + +#: src/common/outbound.c:3606 +msgid "LAGCHECK, forces a new lag check" +msgstr "LAGCHECK, выканаць праверку сігнала" + +#: src/common/outbound.c:3608 +msgid "LASTLOG , searches for a string in the buffer" +msgstr "LASTLOG <радок>, знайсці радок у буферы" + +#: src/common/outbound.c:3610 +msgid "LOAD [-e] , loads a plugin or script" +msgstr "LOAD [-e] <файл>, загрузіць плагін ці скрыпт" + +#: src/common/outbound.c:3613 +msgid "MDEHOP, Mass deop's all chanhalf-ops in the current channel (needs chanop)" +msgstr "MDEHOP, Адабраць паў-аператара ва ўсіх карыстальнікаў бягучага канала (патрэбен статус аператара)" + +#: src/common/outbound.c:3615 +msgid "MDEOP, Mass deop's all chanops in the current channel (needs chanop)" +msgstr "MDEOP, Адабраць аператара ва ўсіх карыстальнікаў бягучага канала (патрабуе статус аператара)" + +#: src/common/outbound.c:3617 +msgid "ME , sends the action to the current channel (actions are written in the 3rd person, like /me jumps)" +msgstr "ME <дзеянне>, дасылае дзеянне на бягучы канал (дзеянні пішуцца ад трэцяй асобы, напрыклад, /me скача)" + +#: src/common/outbound.c:3621 +msgid "MKICK, Mass kicks everyone except you in the current channel (needs chanop)" +msgstr "MKICK, Выпхнуць усіх карыстальнікаў з бягучага канала, акрамя вас (патрэбен статус аператара)" + +#: src/common/outbound.c:3624 +msgid "MOP, Mass op's all users in the current channel (needs chanop)" +msgstr "MOP, Надаць усім карыстальнікам бягучага канала статус аператара (патрэбен статус аператара)" + +#: src/common/outbound.c:3625 +msgid "MSG , sends a private message" +msgstr "MSG <мянушка> <паведамленне>, дасылае асабістае паведамленне" + +#: src/common/outbound.c:3628 +msgid "NAMES, Lists the nicks on the current channel" +msgstr "NAMES, Пералічыць мянушкі карыстальнікаў на бягучым канале" + +#: src/common/outbound.c:3630 +msgid "NCTCP , Sends a CTCP notice" +msgstr "NCTCP <мянушка> <паведамленне>, Дасылае CTCP-абвяшчэнне" + +#: src/common/outbound.c:3631 +msgid "NEWSERVER [-noconnect] []" +msgstr "NEWSERVER [-noconnect] []" + +#: src/common/outbound.c:3632 +msgid "NICK , sets your nick" +msgstr "NICK <мянушка>, змяняе вашую мянушку" + +#: src/common/outbound.c:3635 +msgid "NOTICE , sends a notice. Notices are a type of message that should be auto reacted to" +msgstr "NOTICE <мянушка/канал> <паведамленне>, дасылае абвяшчэнне. Абвяшчэнні гэта тып паведамленняў, на якія трэба аўтаматычна рэагаваць" + +#: src/common/outbound.c:3637 +msgid "NOTIFY [-n network1[,network2,...]] [], displays your notify list or adds someone to it" +msgstr "NOTIFY [-n сеціва1[,сеціва2]] [<мянушка>], пералічвае ваш спіс абвяшчэнняў ці дадае некага ў яго" + +#: src/common/outbound.c:3639 +msgid "OP , gives chanop status to the nick (needs chanop)" +msgstr "OP , дае мянушцы статус аператара канала (патрэбен статус аператара)" + +#: src/common/outbound.c:3641 +msgid "PART [] [], leaves the channel, by default the current one" +msgstr "PART [<канал>] [<прычына>], выйсці з канала, калі канал не вызначаны, то з бягучага" + +#: src/common/outbound.c:3643 +msgid "PING , CTCP pings nick or channel" +msgstr "PING <мянушка | канал>, CTCP пінг мянушкі ці канала" + +#: src/common/outbound.c:3645 +msgid "QUERY [-nofocus] , opens up a new privmsg window to someone" +msgstr "QUERY [-nofocus] <мянушка>, адкрывае дыялог для асабістай размовы" + +#: src/common/outbound.c:3647 +msgid "QUIT [], disconnects from the current server" +msgstr "QUIT [<прычына>], адлучыцца ад бягучага сервера" + +#: src/common/outbound.c:3649 +msgid "QUOTE , sends the text in raw form to the server" +msgstr "QUOTE <тэкст>, даслаць тэкст у неапрацованай форме да сервера" + +#: src/common/outbound.c:3652 +msgid "RECONNECT [-ssl] [] [] [], Can be called just as /RECONNECT to reconnect to the current server or with /RECONNECT ALL to reconnect to all the open servers" +msgstr "RECONNECT [-ssl] [<вузел>] [<порт>] [<пароль>], Можа быць выклікана як /RECONNECT для перадалучэння да бягучага сервера ці /RECONNECT ALL для перадалучэння да ўсіх адкрытых сервераў" + +#: src/common/outbound.c:3655 +msgid "RECONNECT [] [] [], Can be called just as /RECONNECT to reconnect to the current server or with /RECONNECT ALL to reconnect to all the open servers" +msgstr "RECONNECT [-ssl] [<вузел>] [<порт>] [<пароль>], Можа быць выклікана як /RECONNECT для перадалучэння да бягучага сервера ці /RECONNECT ALL для перадалучэння да ўсіх адкрытых сервераў" + +#: src/common/outbound.c:3657 +msgid "RECV , send raw data to xchat, as if it was received from the irc server" +msgstr "RECV <>, дасылае неапрацованыя дадзеныя xchat, як яны былі атрыманы з IRC-сервера" + +#: src/common/outbound.c:3660 +msgid "SAY , sends the text to the object in the current window" +msgstr "SAY <тэкст>, дасылае тэкст аб'екту ў бягучым акне" + +#: src/common/outbound.c:3661 +msgid "SEND []" +msgstr "SEND []" + +#: src/common/outbound.c:3664 +msgid "SERVCHAN [-ssl] , connects and joins a channel" +msgstr "SERVCHAN [-ssl] <вузел> <порт> <канал>, злучыцца і ўвайсці на канал" + +#: src/common/outbound.c:3667 +msgid "SERVCHAN , connects and joins a channel" +msgstr "SERVCHAN <вузел> <порт> <канал>, злучыцца і ўвайсці на канал" + +#: src/common/outbound.c:3671 +msgid "SERVER [-ssl] [] [], connects to a server, the default port is 6667 for normal connections, and 9999 for ssl connections" +msgstr "SERVER [-ssl] <вузел> [<порт>] [<пароль>], злучыцца з серверам, прадвызначаны порт 6667, для звычайнай сувязі і 9999 для ssl-злучэнняў" + +#: src/common/outbound.c:3674 +msgid "SERVER [] [], connects to a server, the default port is 6667" +msgstr "SERVER <вузел> [<порт>] [<пароль>], злучыцца з серверам, прадвызначаны порт 6667" + +#: src/common/outbound.c:3676 +msgid "SET [-e] [-quiet] []" +msgstr "SET [-e] [-quiet] <пераменная> [<значэнне>]" + +#: src/common/outbound.c:3677 +msgid "SETCURSOR [-|+]" +msgstr "SETCURSOR [-|+]<пазіцыя>" + +#: src/common/outbound.c:3682 +msgid "TOPIC [], sets the topic if one is given, else shows the current topic" +msgstr "TOPIC [<тэма>], усталяваць тэму, калі яна вызначана, інакш вывесці бягучую тэму" + +#: src/common/outbound.c:3684 +msgid "" +"\n" +"TRAY -f [] Blink tray between two icons.\n" +"TRAY -f Set tray to a fixed icon.\n" +"TRAY -i Blink tray with an internal icon.\n" +"TRAY -t Set the tray tooltip.\n" +"TRAY -b <text> Set the tray balloon." +msgstr "" +"\n" +"TRAY -f <timeout> <file1> [<file2>] Мірганне ў сподку між двума значкамі.\n" +"TRAY -f <filename> Замацаваць значку ў сподкавым элеменце.\n" +"TRAY -i <number> Мірганне ў сподку ўнутранай значкай.\n" +"TRAY -t <text> Усталяваць тэкст сподкавага элемента.\n" +"TRAY -b <title> <text> Усталяваць выплыўны тэкст сподкавага элемента." + +#: src/common/outbound.c:3691 +msgid "UNBAN <mask> [<mask>...], unbans the specified masks." +msgstr "UNBAN <маска> [<маска>...], зняць забарону з вызначаных масак." + +#: src/common/outbound.c:3692 +msgid "UNIGNORE <mask> [QUIET]" +msgstr "UNIGNORE <mask> [QUIET]" + +#: src/common/outbound.c:3693 +msgid "UNLOAD <name>, unloads a plugin or script" +msgstr "UNLOAD <імя>, выгрузіць плагін ці скрыпт" + +#: src/common/outbound.c:3694 +msgid "URL <url>, opens a URL in your browser" +msgstr "URL <url>, адкрыць URL у вашым браўзеры" + +#: src/common/outbound.c:3696 +msgid "USELECT [-a] [-s] <nick1> <nick2> etc, highlights nick(s) in channel userlist" +msgstr "USELECT [-a] [-s] <мянушка1> <мянушка2> і г.д., падсвечваць вызначаную(ыя) мянушку(і) ў спісе карыстальнікаў" + +#: src/common/outbound.c:3699 +msgid "VOICE <nick>, gives voice status to someone (needs chanop)" +msgstr "VOICE <мянушка>, даць голас камусьці (патрэбен статус аператара канала)" + +#: src/common/outbound.c:3701 +msgid "WALLCHAN <message>, writes the message to all channels" +msgstr "WALLCHAN <паведамленне>, напісаць паведамленне ва ўсіх каналах" + +#: src/common/outbound.c:3703 +msgid "WALLCHOP <message>, sends the message to all chanops on the current channel" +msgstr "WALLCHOP <паведамленне>, даслаць паведамленне ўсім аператарам бягучага канала" + +#: src/common/outbound.c:3736 +#, c-format +msgid "Usage: %s\n" +msgstr "Карыстанне: %s\n" + +#: src/common/outbound.c:3741 +msgid "" +"\n" +"No help available on that command.\n" +msgstr "" +"\n" +"Ніякай даведкі не існуе для гэтай каманды.\n" + +#: src/common/outbound.c:3747 +msgid "No such command.\n" +msgstr "Няма гэткай каманды.\n" + +#: src/common/outbound.c:4077 +msgid "Bad arguments for user command.\n" +msgstr "Дрэнныя аргументы карыстальніцкай каманды.\n" + +#: src/common/outbound.c:4233 +msgid "Too many recursive usercommands, aborting." +msgstr "Зашмат рэкурсіўных падкаманд, перарываюся." + +#: src/common/outbound.c:4310 +msgid "Unknown Command. Try /help\n" +msgstr "Невядомая каманда. Паспрабуйце /help\n" + +#: src/common/plugin.c:356 src/common/plugin.c:397 +msgid "No xchat_plugin_init symbol; is this really an xchat plugin?" +msgstr "Няма сімвала xchat_plugin_init; ці гэта сапраўды плагін Xchat?" + +#: src/common/server.c:634 +msgid "Are you sure this is a SSL capable server and port?\n" +msgstr "Ці вы ўпэўнены, што гэта сумяшчальны з SSL сервер і порт?\n" + +#: src/common/server.c:1025 +#, c-format +msgid "" +"Cannot resolve hostname %s\n" +"Check your IP Settings!\n" +msgstr "" +"Немагчыма знайсці імя %s\n" +"Праверце вашыя наладкі IP!\n" + +#: src/common/server.c:1030 +msgid "Proxy traversal failed.\n" +msgstr "Не атрымліваецца злучыцца з проксі.\n" + +#: src/common/servlist.c:643 +#, c-format +msgid "Cycling to next server in %s...\n" +msgstr "Спрабую іншы сервер %s...\n" + +#: src/common/servlist.c:1074 +#, c-format +msgid "Warning: \"%s\" character set is unknown. No conversion will be applied for network %s." +msgstr "Увага: \"%s\" знаказбор невядомы. Ніякага пераўтварэння знакаў для сеціва %s не будзе." + +#: src/common/textevents.h:6 +msgid "%C22*%O$t$1 added to notify list." +msgstr "%C22*%O$t$1 дададзены ў спіс абвяшчэнняў." + +#: src/common/textevents.h:9 +msgid "%C22*%O$t$1 Banlist:%C19 $4%C20 $2%C21 $3" +msgstr "%C22*%O$t$1 Спіс забароненых:%C19 $4%C20 $2%C21 $3" + +#: src/common/textevents.h:12 +msgid "%C22*%O$tCannot join%C26 %B$1 %O(You are banned)." +msgstr "%C22*%O$tНемагчыма ўвайсці на%C26 %B$1 %O(Вы пад забаронаю)." + +#: src/common/textevents.h:18 +msgid "%C22*%O$t$1 is now known as $2" +msgstr "%C22*%O$t$1 вядомы як $2" + +#: src/common/textevents.h:27 +msgid "%C22*%O$t$1 sets ban on $2" +msgstr "%C22*%O$t$1 выставіў забарону на $2" + +#: src/common/textevents.h:30 +msgid "%C22*%O$tChannel $1 created on $2" +msgstr "%C22*%O$tКанал $1 створаны на $2" + +#: src/common/textevents.h:33 +msgid "%C22*%O$t%C26$1%O removes channel half-operator status from%C26 $2" +msgstr "%C22*%O$t%C26$1%O адабраў статус паў-аператара канала ў%C26 $2" + +#: src/common/textevents.h:36 +msgid "%C22*%O$t%C26$1%O removes channel operator status from%C26 $2" +msgstr "%C22*%O$t%C26$1%O адабраў статус аператара канала ў%C26 $2" + +#: src/common/textevents.h:39 +msgid "%C22*%O$t%C26$1%O removes voice from%C26 $2" +msgstr "%C22*%O$t%C26$1%O адабраў голас у%C26 $2" + +#: src/common/textevents.h:42 +msgid "%C22*%O$t$1 sets exempt on $2" +msgstr "%C22*%O$t$1 усталяваў выключэнне на $2" + +#: src/common/textevents.h:45 +msgid "%C22*%O$t%C26$1%O gives channel half-operator status to%C26 $2" +msgstr "%C22*%O$t%C26$1%O даў статус паў-аператара канала%C26 $2" + +#: src/common/textevents.h:48 +msgid "%C22*%O$t$1 sets invite on $2" +msgstr "%C22*%O$t$1 усталяваў запрашэнне на $2" + +#: src/common/textevents.h:51 +msgid "%UChannel Users Topic" +msgstr "%UКанал Карыст. Тэма" + +#: src/common/textevents.h:57 +msgid "%C22*%O$t$1 sets mode $2$3 $4" +msgstr "%C22*%O$t$1 усталяваў рэжым $2$3 $4" + +#: src/common/textevents.h:60 +msgid "%C22*%O$t%C22Channel $1 modes: $2" +msgstr "%C22*%O$t%C22Рэжымы канала $1: $2" + +#: src/common/textevents.h:69 +msgid "%C22*%O$t%C26$1%O gives channel operator status to%C26 $2" +msgstr "%C22*%O$t%C26$1%O даў статус аператара канала %C26 $2" + +#: src/common/textevents.h:72 +msgid "%C22*%O$t$1 removes exempt on $2" +msgstr "%C22*%O$t$1 выдаліў выключэнне на $2" + +#: src/common/textevents.h:75 +msgid "%C22*%O$t$1 removes invite on $2" +msgstr "%C22*%O$t$1 выдаліў запрашэнне на $2" + +#: src/common/textevents.h:78 +msgid "%C22*%O$t$1 removes channel keyword" +msgstr "%C22*%O$t$1 выдаліў ключавое слова канала" + +#: src/common/textevents.h:81 +msgid "%C22*%O$t$1 removes user limit" +msgstr "%C22*%O$t$1 выдаліў абмежаванне карыстальніка" + +#: src/common/textevents.h:84 +msgid "%C22*%O$t$1 sets channel keyword to $2" +msgstr "%C22*%O$t$1 усталяваў ключавое слова канала: $2" + +#: src/common/textevents.h:87 +msgid "%C22*%O$t$1 sets channel limit to $2" +msgstr "%C22*%O$t$1 усталяваў абмежаванне канала ў $2" + +#: src/common/textevents.h:90 +msgid "%C22*%O$t$1 removes ban on $2" +msgstr "%C22*%O$t$1 выдаліў забарону на $2" + +#: src/common/textevents.h:93 +msgid "%C22*%O$t%C26$1%O gives voice to%C26 $2" +msgstr "%C22*%O$t%C26$1%O даў голас%C26 $2" + +#: src/common/textevents.h:96 +msgid "%C22*%O$t%C22Connected. Now logging in..." +msgstr "%C22*%O$t%C22Злучана. Уваход..." + +#: src/common/textevents.h:99 +msgid "%C22*%O$t%C22Connecting to $1 ($2) port $3%O..." +msgstr "%C22*%O$t%C22Злучэнне з $1 ($2), порт $3%O..." + +#: src/common/textevents.h:102 +msgid "%C21*%O$t%C21Connection failed. Error: $1" +msgstr "Злучэнне не атрымалася. Памылка: $1" + +#: src/common/textevents.h:105 +msgid "%C22*%O$tReceived a CTCP $1 from $2" +msgstr "%C22*%O$tАтрымана CTCP $1 ад $2" + +#: src/common/textevents.h:108 +msgid "%C22*%O$tReceived a CTCP $1 from $2 (to $3)" +msgstr "%C22*%O$tАтрымана CTCP $1 ад $2 (да $3)" + +#: src/common/textevents.h:111 +msgid "%C19>%O$1%C19<%O$tCTCP $2" +msgstr "%C19>%O$1%C19<%O$tCTCP $2" + +#: src/common/textevents.h:114 +msgid "%C22*%O$tReceived a CTCP Sound $1 from $2" +msgstr "%C22*%O$tАтрыманы CTCP-гук $1 ад $2" + +#: src/common/textevents.h:117 +msgid "%C22*%O$tReceived a CTCP Sound $1 from $2 (to $3)" +msgstr "%C22*%O$tАтрыманы CTCP-гук $1 ад $2 (да $3)" + +#: src/common/textevents.h:120 +msgid "%C22*%O$tDCC CHAT to %C26$1%O aborted." +msgstr "%C22*%O$tDCC CHAT з %C26$1%O перарвана." + +#: src/common/textevents.h:123 +msgid "%C22*%O$tDCC CHAT connection established to %C26$1 %C30[%O$2%C30]" +msgstr "%C22*%O$tDCC CHAT злучэнне ўсталявана з %C26$1 %C30[%O$2%C30]" + +#: src/common/textevents.h:126 +msgid "%C22*%O$tDCC CHAT to %C26$1%O lost ($4)." +msgstr "%C22*%O$tDCC CHAT з %C26$1%O страчана ($4)." + +#: src/common/textevents.h:129 +msgid "%C22*%O$tReceived a DCC CHAT offer from $1" +msgstr "%C22*%O$tАтрымана прапанова DCC CHAT ад $1" + +#: src/common/textevents.h:132 +msgid "%C22*%O$tOffering DCC CHAT to $1" +msgstr "%C22*%O$tПрапануецца DCC CHAT $1" + +#: src/common/textevents.h:135 +msgid "%C22*%O$tAlready offering CHAT to $1" +msgstr "%C22*%O$tУжо прапануецца CHAT to $1" + +#: src/common/textevents.h:138 +msgid "%C22*%O$tDCC $1 connect attempt to%C26 $2%O failed (err=$3)." +msgstr "%C22*%O$tDCC $1 спроба злучэння з%C26 $2%O не ўдалася (err=$3)." + +#: src/common/textevents.h:141 +msgid "%C22*%O$tReceived '$1%O' from $2" +msgstr "%C22*%O$tАтрымана '$1%O' ад $2" + +#: src/common/textevents.h:144 +#, c-format +msgid "%C24,18 Type To/From Status Size Pos File " +msgstr "%C24,18 Тып Да/Ад Статус Памер Паз Файл " + +#: src/common/textevents.h:147 +msgid "%C22*%O$tReceived a malformed DCC request from %C26$1%O.%010%C22*%O$tContents of packet: $2" +msgstr "%C22*%O$tАтрыманы няправільны DCC запыт ад %C26$1%O.%010%C22*%O$tЗмест пакета: $2" + +#: src/common/textevents.h:150 +msgid "%C22*%O$tOffering%C26 $1%O to%C26 $2" +msgstr "%C22*%O$tПрапанова%C26 $1%O да%C26 $2" + +#: src/common/textevents.h:153 +msgid "%C22*%O$tNo such DCC offer." +msgstr "%C22*%O$tНяма гэткай прапановы DCC." + +#: src/common/textevents.h:156 +msgid "%C22*%O$tDCC RECV%C26 $2%O to%C26 $1%O aborted." +msgstr "%C22*%O$tDCC RECV%C26 $2%O да%C26 $1%O перарвана." + +#: src/common/textevents.h:159 +msgid "%C22*%O$tDCC RECV%C26 $1%O from%C26 $3%O complete %C30[%C26$4%O cps%C30]%O." +msgstr "%C22*%O$tDCC RECV%C26 $1%O ад%C26 $3%O завершана %C30[%C26$4%O cps%C30]%O." + +#: src/common/textevents.h:162 +msgid "%C22*%O$tDCC RECV connection established to%C26 $1 %C30[%O$2%C30]" +msgstr "%C22*%O$tDCC RECV злучэнне ўсталявана з%C26 $1 %C30[%O$2%C30]" + +#: src/common/textevents.h:165 +msgid "%C22*%O$tDCC RECV%C26 $1%O from%C26 $3%O failed ($4)." +msgstr "%C22*%O$tDCC RECV%C26 $1%O з%C26 $3%O не атрымалася ($4)." + +#: src/common/textevents.h:168 +msgid "%C22*%O$tDCC RECV: Cannot open $1 for writing ($2)." +msgstr "%C22*%O$tDCC RECV: Немагчыма адкрыць $1 для запісу ($2)." + +#: src/common/textevents.h:171 +msgid "%C22*%O$tThe file%C26 $1%C already exists, saving it as%C26 $2%O instead." +msgstr "%C22*%O$tФайл%C26 $1%C ужо існуе, захоўваю як %C26 $2%O." + +#: src/common/textevents.h:174 +msgid "%C22*%O$t%C26$1 %Ohas requested to resume%C26 $2 %Cfrom%C26 $3%C." +msgstr "%C22*%O$t%C26$1 %Oзапытаў працяг%C26 $2 %Cз%C26 $3%C." + +#: src/common/textevents.h:177 +msgid "%C22*%O$tDCC SEND%C26 $2%O to%C26 $1%O aborted." +msgstr "%C22*%O$tDCC SEND%C26 $2%O да%C26 $1%O перарвана." + +#: src/common/textevents.h:180 +msgid "%C22*%O$tDCC SEND%C26 $1%O to%C26 $2%O complete %C30[%C26$3%O cps%C30]%O." +msgstr "%C22*%O$tDCC SEND%C26 $1%O з%C26 $2%O завершана %C30[%C26$3%O cps%C30]%O." + +#: src/common/textevents.h:183 +msgid "%C22*%O$tDCC SEND connection established to%C26 $1 %C30[%O$2%C30]" +msgstr "%C22*%O$tDCC SEND злучэнне ўсталявана з %C26 $1 %C30[%O$2%C30]" + +#: src/common/textevents.h:186 +msgid "%C22*%O$tDCC SEND%C26 $1%O to%C26 $2%O failed. $3" +msgstr "%C22*%O$tDCC SEND%C26 $1%O да%C26 $2%O не атрымалася. $3" + +#: src/common/textevents.h:189 +msgid "%C22*%O$t%C26$1 %Ohas offered%C26 $2 %O(%C26$3 %Obytes)" +msgstr "%C22*%O$t%C26$1 %Oпрапанаваў%C26 $2 %O(%C26$3 %Oбайтаў)" + +#: src/common/textevents.h:192 +msgid "%C22*%O$tDCC $1%C26 $2 %Oto%C26 $3 %Cstalled - aborting." +msgstr "%C22*%O$tDCC $1%C26 $2 %Oда%C26 $3 %C перарвана: страчана хуткасць." + +#: src/common/textevents.h:195 +msgid "%C22*%O$tDCC $1%C26 $2 %Oto%C26 $3 %Otimed out - aborting." +msgstr "%C22*%O$tDCC $1%C26 $2 %Oда%C26 $3 %O перарвана: выйшаў час." + +#: src/common/textevents.h:198 +msgid "%C22*%O$t$1 deleted from notify list." +msgstr "%C22*%O$t$1 выдалены са спіса абвяшчэнняў" + +#: src/common/textevents.h:201 +msgid "%C22*%O$tDisconnected ($1)." +msgstr "%C22*%O$tЗлучэнне страчана ($1)." + +#: src/common/textevents.h:204 +msgid "%C22*%O$tFound your IP: [$1]" +msgstr "%C22*%O$tЗнойдзены ваш IP: [$1]" + +#: src/common/textevents.h:210 +msgid "%O%C26$1%O added to ignore list." +msgstr "%O%C26$1%O дададзены ў спіс ігнараванняў." + +#: src/common/textevents.h:213 +msgid "Ignore on %C26$1%O changed." +msgstr "Ігнараванне %C26$1%O зменена." + +#: src/common/textevents.h:216 +#, c-format +msgid "%C24,18 " +msgstr "%C24,18 " + +#: src/common/textevents.h:219 +#, c-format +msgid "%C24,18 Hostmask PRIV NOTI CHAN CTCP DCC INVI UNIG " +msgstr "%C24,18 Маска вузла PRIV NOTI CHAN CTCP DCC INVI UNIG " + +#: src/common/textevents.h:222 +msgid "%O%C26$1%O removed from ignore list." +msgstr "%O%C26$1%O выдалены са спісу ігнараванняў." + +#: src/common/textevents.h:225 +msgid " Ignore list is empty." +msgstr " Спіс ігнараванняў пусты." + +#: src/common/textevents.h:228 +msgid "%C22*%O$tCannot join%C26 %B$1 %O(Channel is invite only)." +msgstr "%C22*%O$tНемагчыма ўвайсці на%C26 %B$1 %O(Уваход толькі па запрашэннях)." + +#: src/common/textevents.h:231 +msgid "%C22*%O$tYou have been invited to%C26 $1%O by%C26 $2%C (%C26$3%C)" +msgstr "%C22*%O$tВы былі запрошаны на%C26 $1%O by%C26 $2%C (%C26$3%C)" + +#: src/common/textevents.h:234 +msgid "%C19*%O$t%C19%B$1 %B($3) has joined $2" +msgstr "%C19*%O$t%C19%B$1 %B($3) увайшоў на $2" + +#: src/common/textevents.h:237 +msgid "%C22*%O$tCannot join%C26 %B$1 %O(Requires keyword)." +msgstr "%C22*%O$tНемагчыма увайсці на%C26 %B$1 %O(Патрэбна ключавое слова)." + +#: src/common/textevents.h:240 +msgid "%C21*%O$t%C21$1 has kicked $2 from $3 ($4%O%C21)" +msgstr "%C21*%O$t%C21$1 выпхнуў $2 з $3 ($4%O%C21)" + +#: src/common/textevents.h:243 +msgid "%C22*%O$tYou have been killed by $1 ($2%O%C22)" +msgstr "%C22*%O$t $1 выпхнуў вас ($2%O%C22)" + +#: src/common/textevents.h:252 +msgid "%C22*%O$t%C22MOTD Skipped." +msgstr "%C22*%O$t%C22\"Паведамленне дня\" прапушчана." + +#: src/common/textevents.h:255 +msgid "%C22*%O$t$1 already in use. Retrying with $2..." +msgstr "%C22*%O$t$1 ужо выкарыстоўваецца. Спрабую $2..." + +#: src/common/textevents.h:258 +msgid "%C22*%O$tNickname already in use. Use /NICK to try another." +msgstr "%C22*%O$tМянушка ўжо кімсьці выкарыстоўваецца. Паспрабуйце каманду /NICK для выбару іншай." + +#: src/common/textevents.h:261 +msgid "%C22*%O$tNo such DCC." +msgstr "%C22*%O$tНяма гэткага DCC." + +#: src/common/textevents.h:264 +msgid "%C22*%O$tNo process is currently running" +msgstr "%C22*%O$tЗараз няма працуючых працэсаў" + +#: src/common/textevents.h:273 +msgid "$tNotify list is empty." +msgstr "$tСпіс абвяшчэнняў пусты." + +#: src/common/textevents.h:276 +msgid "%C24,18 %B Notify List " +msgstr "%C24,18 %B Спіс абвяшчэнняў " + +#: src/common/textevents.h:279 +msgid "%C22*%O$t$1 users in notify list." +msgstr "%C22*%O$t$1 карыстальнікаў у спісе абвяшчэнняў." + +#: src/common/textevents.h:282 +msgid "%C22*%O$tNotify: $1 is offline ($3)." +msgstr "%C22*%O$tАбвяшчэнне: $1 адключыўся ($3)." + +#: src/common/textevents.h:285 +msgid "%C22*%O$tNotify: $1 is online ($3)." +msgstr "%C22*%O$tАбвяшчэнне: $1 падключыўся ($3)." + +#: src/common/textevents.h:291 +msgid "%C23*%O$t%C23$1 (%O%C23$2) has left $3" +msgstr "%C23*%O$t%C23$1 (%O%C23$2) выйшаў з $3" + +#: src/common/textevents.h:294 +msgid "%C23*%O$t%C23$1 (%O%C23$2) has left $3 (%O%C23%B%B$4%O%C23)" +msgstr "%C23*%O$t%C23$1 (%O%C23$2) выйшаў з $3 (%O%C23%B%B$4%O%C23)" + +#: src/common/textevents.h:297 +msgid "%C22*%O$tPing reply from $1: $2 second(s)" +msgstr "%C22*%O$tАдказ на пінг ад $1: $2 сек" + +#: src/common/textevents.h:300 +msgid "%C22*%O$tNo ping reply for $1 seconds, disconnecting." +msgstr "%C22*%O$tНе атрымана адказаў на пінг на працягу $1 сек, разлучаемся." + +#: src/common/textevents.h:309 +msgid "%C22*%O$tA process is already running" +msgstr "%C22*%O$tПрацэс ужо запушчаны" + +#: src/common/textevents.h:312 +msgid "%C23*%O$t%C23$1 has quit (%O%C23%B%B$2%O%C23)" +msgstr "%C23*%O$t%C23$1 зыйшоў (%O%C23%B%B$2%O%C23)" + +#: src/common/textevents.h:315 +msgid "%C22*%O$t$1 sets modes%B %C30[%O$2%B%C30]" +msgstr "%C22*%O$t$1 усталяваў рэжым%B %C30[%O$2%B%C30]" + +#: src/common/textevents.h:318 +msgid "%C28-%C29$1/Wallops%C28-%O$t$2" +msgstr "%C28-%C29$1/Wallops%C28-%O$t$2" + +#: src/common/textevents.h:321 +msgid "%C22*%O$tLooking up IP number for%C26 $1%O..." +msgstr "%C22*%O$tШукаецца нумар IP %C26 $1%O..." + +#: src/common/textevents.h:324 +msgid "%C22*%O$t%C22Connected." +msgstr "%C22*%O$t%C22Злучана." + +#: src/common/textevents.h:330 +msgid "%C22*%O$t%C22Looking up $1" +msgstr "%C22*%O$t%C22Шукаецца $1" + +#: src/common/textevents.h:339 +msgid "%C22*%O$tStopped previous connection attempt (pid=$1)" +msgstr "%C22*%O$tСпынена папярэдняя спроба злучэння (pid=$1)" + +#: src/common/textevents.h:342 +msgid "%C29*%O$t%C29Topic for $1%C %C29is: $2" +msgstr "%C29*%O$t%C29Тэма для $1%C %C29: $2" + +#: src/common/textevents.h:345 +msgid "%C22*%O$t$1 has changed the topic to: $2" +msgstr "%C22*%O$t$1 змяніў тэму на: $2" + +#: src/common/textevents.h:348 +msgid "%C29*%O$t%C29Topic for $1%C %C29set by $2%C %C29at $3" +msgstr "%C29*%O$t%C29Тэма для $1%C %C29усталявана $2%C %C29у $3" + +#: src/common/textevents.h:351 +msgid "%C22*%O$tUnknown host. Maybe you misspelled it?" +msgstr "%C22*%O$tНевядомы хост. Магчыма, вы памыліліся?" + +#: src/common/textevents.h:354 +msgid "%C22*%O$tCannot join%C26 %B$1 %O(User limit reached)." +msgstr "%C22*%O$tНемагчыма ўвасці на %C26 %B$1 %O(Дасягнута карыстальніцкае абмежаванне)." + +#: src/common/textevents.h:357 +msgid "%C22*%O$t%C26Users on $1:%C $2" +msgstr "%C22*%O$t%C26Карыстальнікі на $1:%C $2" + +#: src/common/textevents.h:360 +msgid "%C22*%O$t%C28[%O$1%C28] %O$2%C27 $3" +msgstr "%C22*%O$t%C28[%O$1%C28] %O$2%C27 $3" + +#: src/common/textevents.h:363 +msgid "%C22*%O$t%C28[%O$1%C28] %Cis away %C30(%O$2%O%C30)" +msgstr "%C22*%O$t%C28[%O$1%C28] %Cадыйшоў %C30(%O$2%O%C30)" + +#: src/common/textevents.h:366 src/common/textevents.h:372 +#: src/common/textevents.h:387 src/common/textevents.h:390 +msgid "%C22*%O$t%C28[%O$1%C28]%O $2" +msgstr "%C22*%O$t%C28[%O$1%C28]%O $2" + +#: src/common/textevents.h:369 +msgid "%C22*%O$t%C28[%O$1%C28] %OEnd of WHOIS list." +msgstr "%C22*%O$t%C28[%O$1%C28] %OКанец спіса WHOIS." + +#: src/common/textevents.h:375 +msgid "%C22*%O$t%C28[%O$1%C28]%O idle%C26 $2" +msgstr "%C22*%O$t%C28[%O$1%C28]%O без дзеянняў%C26 $2" + +#: src/common/textevents.h:378 +msgid "%C22*%O$t%C28[%O$1%C28]%O idle%C26 $2%O, signon:%C26 $3" +msgstr "%C22*%O$t%C28[%O$1%C28]%O бяздзейны%C26 $2%O, увайшоў:%C26 $3" + +#: src/common/textevents.h:381 +msgid "%C22*%O$t%C28[%O$1%C28] %C30(%O$2@$3%C30)%O: $4" +msgstr "%C22*%O$t%C28[%O$1%C28] %C30(%O$2@$3%C30)%O: $4" + +#: src/common/textevents.h:384 +msgid "%C22*%O$t%C28[%O$1%C28] %Oreal user@host%C27 $2%O, real IP%C27 $3" +msgstr "%C22*%O$t%C28[%O$1%C28] %Oсапраўдны user@host%C27 $2%O, сапраўдны IP%C27 $3" + +#: src/common/textevents.h:393 +msgid "%C19*%O$t%C19Now talking on $2" +msgstr "%C19*%O$t%C19Размаўляем на $2" + +#: src/common/textevents.h:396 +msgid "%C23*$tYou have been kicked from $2 by $3 ($4%O%C23)" +msgstr "%C23*$t$3 выпхнуў вас з $2 ($4%O%C23)" + +#: src/common/textevents.h:399 +#, c-format +msgid "%C23*$tYou have left channel $3" +msgstr "%C23*$tВы выйшлі з канала $3" + +#: src/common/textevents.h:402 +msgid "%C23*$tYou have left channel $3 (%O%C23%B%B$4%O%C23)" +msgstr "%C23*$tВы выйшлі з канала $3 (%O%C23%B%B$4%O%C23)" + +#: src/common/textevents.h:408 +msgid "%C22*%O$tYou've invited%C26 $1%O to%C26 $2%O (%C26$3%O)" +msgstr "%C22*%O$tВы запрошаны %C26 $1%O на %C26 $2%O (%C26$3%O)" + +#: src/common/textevents.h:414 +msgid "%C22*%O$tYou are now known as $2" +msgstr "%C22*%O$tЦяпер вы вядомы як $2" + +#: src/common/text.c:61 +#, c-format +msgid "**** ENDING LOGGING AT %s\n" +msgstr "**** КАНЕЦ УВАХОДУ НА %s\n" + +#: src/common/text.c:270 +#, c-format +msgid "**** BEGIN LOGGING AT %s\n" +msgstr "**** ПАЧАТАК УВАХОДУ НА %s\n" + +#: src/common/text.c:289 +#, c-format +msgid "" +"* Can't open log file(s) for writing. Check the\n" +" permissions on %s/xchatlogs" +msgstr "" +"* Немагчыма адкрыць лог-файл(ы) для запісу. Праверце\n" +" правы на %s/xchatlogs" + +#: src/common/text.c:625 +msgid "Left message" +msgstr "Левае паведамленне" + +#: src/common/text.c:626 +msgid "Right message" +msgstr "Правае паведамленне" + +#: src/common/text.c:630 +msgid "The nick of the joining person" +msgstr "Мянушка ўваходзячай асобы" + +#: src/common/text.c:631 +msgid "The channel being joined" +msgstr "Канал для ўваходу" + +#: src/common/text.c:632 src/common/text.c:679 src/common/text.c:730 +msgid "The host of the person" +msgstr "Хост гэтай асобы" + +#: src/common/text.c:636 src/common/text.c:642 src/common/text.c:649 +#: src/common/text.c:837 src/common/text.c:844 src/common/text.c:849 +#: src/common/text.c:854 src/common/text.c:859 src/common/text.c:865 +#: src/common/text.c:870 src/common/text.c:874 src/common/text.c:880 +#: src/common/text.c:886 src/common/text.c:932 src/common/text.c:943 +#: src/common/text.c:948 src/common/text.c:953 src/common/text.c:962 +#: src/common/text.c:973 src/common/text.c:980 src/common/text.c:986 +#: src/common/text.c:991 src/common/text.c:996 src/common/text.c:1003 +#: src/common/text.c:1009 src/common/text.c:1015 src/common/text.c:1020 +#: src/common/text.c:1025 src/common/text.c:1029 src/common/text.c:1035 +#: src/common/text.c:1043 src/common/text.c:1077 src/common/text.c:1082 +msgid "Nickname" +msgstr "Мянушка" + +#: src/common/text.c:637 +msgid "The action" +msgstr "Дзеянне" + +#: src/common/text.c:638 src/common/text.c:644 +msgid "Mode char" +msgstr "Знак рэжыму" + +#: src/common/text.c:643 +msgid "The text" +msgstr "Тэкст" + +#: src/common/text.c:645 src/common/text.c:651 +msgid "Identified text" +msgstr "Вылучаны тэкст" + +#: src/common/text.c:650 src/common/text.c:707 src/common/text.c:713 +msgid "The message" +msgstr "Паведамленне" + +#: src/common/text.c:655 src/common/text.c:717 +msgid "Old nickname" +msgstr "Старая мянушка" + +#: src/common/text.c:656 src/common/text.c:718 +msgid "New nickname" +msgstr "Новая мянушка" + +#: src/common/text.c:660 +msgid "Nick of person who changed the topic" +msgstr "Мянушка асобы, якая змяніла тэму" + +#: src/common/text.c:661 src/common/text.c:667 src/fe-gtk/chanlist.c:718 +#: src/fe-gtk/chanlist.c:821 +msgid "Topic" +msgstr "Тэма" + +#: src/common/text.c:662 src/common/text.c:666 src/common/text.c:1097 +#: src/fe-gtk/chanlist.c:716 src/fe-gtk/ignoregui.c:176 +msgid "Channel" +msgstr "Канал" + +#: src/common/text.c:671 src/common/text.c:724 +msgid "The nickname of the kicker" +msgstr "Мянушка асобы, якая выпхнула вас" + +#: src/common/text.c:672 src/common/text.c:722 +msgid "The person being kicked" +msgstr "Асоба, якую выпхнулі" + +#: src/common/text.c:673 src/common/text.c:680 src/common/text.c:684 +#: src/common/text.c:689 src/common/text.c:723 src/common/text.c:731 +#: src/common/text.c:738 +msgid "The channel" +msgstr "Канал" + +#: src/common/text.c:674 src/common/text.c:725 src/common/text.c:732 +msgid "The reason" +msgstr "Прычына" + +#: src/common/text.c:678 src/common/text.c:729 +msgid "The nick of the person leaving" +msgstr "Мянушка асобы, што выходзіць" + +#: src/common/text.c:685 src/common/text.c:691 +msgid "The time" +msgstr "Час" + +#: src/common/text.c:690 +msgid "The creator" +msgstr "Стваральнік" + +#: src/common/text.c:695 src/fe-gtk/dccgui.c:763 src/fe-gtk/dccgui.c:994 +msgid "Nick" +msgstr "Мянушка" + +#: src/common/text.c:696 src/common/text.c:949 +msgid "Reason" +msgstr "Прычына" + +#: src/common/text.c:697 src/common/text.c:839 src/common/text.c:922 +msgid "Host" +msgstr "Хост" + +#: src/common/text.c:701 src/common/text.c:706 src/common/text.c:711 +msgid "Who it's from" +msgstr "Адкуль" + +#: src/common/text.c:702 +msgid "The time in x.x format (see below)" +msgstr "Час у фармаце x.x (глядзі ніжэй)" + +#: src/common/text.c:712 src/common/text.c:749 +msgid "The Channel it's going to" +msgstr "Спіс каналаў" + +#: src/common/text.c:736 +msgid "The sound" +msgstr "Гук" + +#: src/common/text.c:737 src/common/text.c:743 src/common/text.c:748 +msgid "The nick of the person" +msgstr "Мянушка гэтай асобы" + +#: src/common/text.c:742 src/common/text.c:747 +msgid "The CTCP event" +msgstr "CTCP падзея" + +#: src/common/text.c:753 +msgid "The nick of the person who set the key" +msgstr "Мянушка асобы, якая ўсталявала ключ" + +#: src/common/text.c:754 +msgid "The key" +msgstr "Ключ" + +#: src/common/text.c:758 +msgid "The nick of the person who set the limit" +msgstr "Мянушка асобы, якая ўсталявала абмежаванне" + +#: src/common/text.c:759 +msgid "The limit" +msgstr "Абмежаванне" + +#: src/common/text.c:763 +msgid "The nick of the person who did the op'ing" +msgstr "Мянушка асобы, якая дала статус аператара" + +#: src/common/text.c:764 +msgid "The nick of the person who has been op'ed" +msgstr "Мянушка асобы, якая атрымала статус аператара" + +#: src/common/text.c:768 +msgid "The nick of the person who has been halfop'ed" +msgstr "Мянушка асобы, якая атрымала статус паў-аператара" + +#: src/common/text.c:769 +msgid "The nick of the person who did the halfop'ing" +msgstr "Мянушка асобы, якая дала статус паў-аператара" + +#: src/common/text.c:773 +msgid "The nick of the person who did the voice'ing" +msgstr "Мянушка асобы, якая дала голас" + +#: src/common/text.c:774 +msgid "The nick of the person who has been voice'ed" +msgstr "Мянушка асобы, якая атрымала голас" + +#: src/common/text.c:778 +msgid "The nick of the person who did the banning" +msgstr "Мянушка асобы, якая ўсталявала забарону" + +#: src/common/text.c:779 src/common/text.c:806 +msgid "The ban mask" +msgstr "Маска забароны" + +#: src/common/text.c:783 +msgid "The nick who removed the key" +msgstr "Мянушка, якая выдаліла ключ" + +#: src/common/text.c:787 +msgid "The nick who removed the limit" +msgstr "Мянушка, якая выдаліла абмежаванне" + +#: src/common/text.c:791 +msgid "The nick of the person of did the deop'ing" +msgstr "Мянушка асобы, якая адабрала статус аператара" + +#: src/common/text.c:792 +msgid "The nick of the person who has been deop'ed" +msgstr "Мянушка асобы, у якой быў адабраны статус аператара" + +#: src/common/text.c:795 +msgid "The nick of the person of did the dehalfop'ing" +msgstr "Мянушка асобы, якая адабрала статус паў-аператара" + +#: src/common/text.c:796 +msgid "The nick of the person who has been dehalfop'ed" +msgstr "Мянушка асобы, у якой быў адабраны статус паў-аператара" + +#: src/common/text.c:800 +msgid "The nick of the person of did the devoice'ing" +msgstr "Мянушка асобы, якая адабрала голас" + +#: src/common/text.c:801 +msgid "The nick of the person who has been devoice'ed" +msgstr "Мянушка асобы, у якой быў адабраны голас" + +#: src/common/text.c:805 +msgid "The nick of the person of did the unban'ing" +msgstr "Мянушка асобы, якая зняла забарону" + +#: src/common/text.c:810 +msgid "The nick of the person who did the exempt" +msgstr "Мянушка асобы, якая ўсталявала выключэнне" + +#: src/common/text.c:811 src/common/text.c:816 +msgid "The exempt mask" +msgstr "Маска выключэння" + +#: src/common/text.c:815 +msgid "The nick of the person removed the exempt" +msgstr "Мянушка асобы, якая выдаліла выключэнне" + +#: src/common/text.c:820 +msgid "The nick of the person who did the invite" +msgstr "Мянушка асобы, якая зрабіла запрашэнне" + +#: src/common/text.c:821 src/common/text.c:826 +msgid "The invite mask" +msgstr "Маска запрашэння" + +#: src/common/text.c:825 +msgid "The nick of the person removed the invite" +msgstr "Мянушка асобы, якая выдаліла запрашэнне" + +#: src/common/text.c:830 +msgid "The nick of the person setting the mode" +msgstr "Мянушка асобы, якая ўсталявала рэжым" + +#: src/common/text.c:831 +msgid "The mode's sign (+/-)" +msgstr "Знак рэжыму (+/-)" + +#: src/common/text.c:832 +msgid "The mode letter" +msgstr "Сімвал рэжыму" + +#: src/common/text.c:833 +msgid "The channel it's being set on" +msgstr "Канал для ўжыцця" + +#: src/common/text.c:838 +msgid "Username" +msgstr "Імя карыстальніка" + +#: src/common/text.c:840 +msgid "Full name" +msgstr "Поўнае імя" + +#: src/common/text.c:845 +msgid "Channel Membership/\"is an IRC operator\"" +msgstr "Член канала /\"аператар IRC\"" + +#: src/common/text.c:850 +msgid "Server Information" +msgstr "Інфармацыя аб серверы" + +#: src/common/text.c:855 src/common/text.c:860 +msgid "Idle time" +msgstr "Час бяздзеяння" + +#: src/common/text.c:861 +msgid "Signon time" +msgstr "Час з уваходу" + +#: src/common/text.c:866 +msgid "Away reason" +msgstr "Прычына адыходу" + +#: src/common/text.c:875 src/common/text.c:881 src/common/text.c:889 +#: src/common/text.c:1069 +msgid "Message" +msgstr "Паведамленне" + +#: src/common/text.c:882 +msgid "Account" +msgstr "Рахунак" + +#: src/common/text.c:887 +msgid "Real user@host" +msgstr "Сапраўдны user@host" + +#: src/common/text.c:888 +msgid "Real IP" +msgstr "Сапраўдны IP" + +#: src/common/text.c:893 src/common/text.c:902 src/common/text.c:908 +#: src/common/text.c:938 src/common/text.c:1092 +msgid "Channel Name" +msgstr "Назва канала" + +#: src/common/text.c:897 src/common/text.c:1055 src/fe-gtk/menu.c:1206 +#: src/fe-gtk/menu.c:1385 src/fe-gtk/textgui.c:387 +msgid "Text" +msgstr "Тэкст" + +#: src/common/text.c:898 src/common/text.c:904 src/common/text.c:933 +#: src/common/text.c:1051 src/common/text.c:1093 +msgid "Server Name" +msgstr "Назва сервера" + +#: src/common/text.c:903 +msgid "Nick of person who invited you" +msgstr "Мянушка асобы, якая запрасіла вас" + +#: src/common/text.c:909 src/fe-gtk/chanlist.c:717 +msgid "Users" +msgstr "Карыстальнікі" + +#: src/common/text.c:913 +msgid "Nickname in use" +msgstr "Мянушка выкарыстоўваецца" + +#: src/common/text.c:914 +msgid "Nick being tried" +msgstr "Спрабуемая мянушка" + +#: src/common/text.c:923 src/common/text.c:1059 +msgid "IP" +msgstr "IP" + +#: src/common/text.c:924 src/common/text.c:955 +msgid "Port" +msgstr "Порт" + +#: src/common/text.c:934 src/fe-gtk/notifygui.c:139 src/fe-gtk/setup.c:1647 +msgid "Network" +msgstr "Сеціва" + +#: src/common/text.c:939 src/common/text.c:944 +msgid "Modes string" +msgstr "Радок рэжымаў" + +#: src/common/text.c:954 src/common/text.c:992 src/common/text.c:997 +#: src/common/text.c:1038 +msgid "IP address" +msgstr "IP адрас" + +#: src/common/text.c:960 src/common/text.c:985 +msgid "DCC Type" +msgstr "Тып DCC" + +#: src/common/text.c:961 src/common/text.c:966 src/common/text.c:971 +#: src/common/text.c:978 src/common/text.c:998 src/common/text.c:1002 +#: src/common/text.c:1008 src/common/text.c:1014 src/common/text.c:1021 +#: src/common/text.c:1030 src/common/text.c:1036 +msgid "Filename" +msgstr "Імя файла" + +#: src/common/text.c:972 src/common/text.c:979 +msgid "Destination filename" +msgstr "Назва файла ў атрымальніка" + +#: src/common/text.c:981 src/common/text.c:1010 +msgid "CPS" +msgstr "CPS(знакаў у секунду)" + +#: src/common/text.c:1016 +msgid "Pathname" +msgstr "Шлях" + +#: src/common/text.c:1031 src/fe-gtk/dccgui.c:759 +msgid "Position" +msgstr "Пазіцыя" + +#: src/common/text.c:1037 src/fe-gtk/dccgui.c:758 +msgid "Size" +msgstr "Памер" + +#: src/common/text.c:1042 +msgid "DCC String" +msgstr "Радок DCC" + +#: src/common/text.c:1047 +msgid "Number of notify items" +msgstr "Колькасць абвяшчэнняў" + +#: src/common/text.c:1063 +msgid "Old Filename" +msgstr "Старое імя файла" + +#: src/common/text.c:1064 +msgid "New Filename" +msgstr "Новае імя файла" + +#: src/common/text.c:1068 +msgid "Receiver" +msgstr "Атрымальнік" + +#: src/common/text.c:1073 +msgid "Hostmask" +msgstr "Маска камп'ютэра" + +#: src/common/text.c:1078 +msgid "Hostname" +msgstr "Назва камп'ютэра" + +#: src/common/text.c:1083 +msgid "The Packet" +msgstr "Пакет" + +#: src/common/text.c:1087 +msgid "Seconds" +msgstr "Секунды" + +#: src/common/text.c:1091 +msgid "Nick of person who have been invited" +msgstr "Мянушка запрошанай асобы" + +#: src/common/text.c:1098 +msgid "Banmask" +msgstr "Маска забароны" + +#: src/common/text.c:1099 +msgid "Who set the ban" +msgstr "Хто ўсталяваў забарону" + +#: src/common/text.c:1100 +msgid "Ban time" +msgstr "Час забароны" + +#: src/common/text.c:1140 +#, c-format +msgid "" +"Error parsing event %s.\n" +"Loading default." +msgstr "" +"Памылка апрацоўкі падзеі %s.\n" +"Ужываем стандартныя паводзіны." + +#: src/common/text.c:1833 +#, c-format +msgid "" +"Cannot read sound file:\n" +"%s" +msgstr "" +"Немагчыма прачытаць гукавы файл:\n" +"%s" + +#: src/common/util.c:296 +msgid "Remote host closed socket" +msgstr "Аддалены вузел закрыў сокет" + +#: src/common/util.c:301 +msgid "Connection refused" +msgstr "У злучэнні адмоўлена" + +#: src/common/util.c:304 +msgid "No route to host" +msgstr "Няма шляху да вузла" + +#: src/common/util.c:306 +msgid "Connection timed out" +msgstr "Час злучэння выйшаў" + +#: src/common/util.c:308 +msgid "Cannot assign that address" +msgstr "Немагчыма ўжыць гэта адрас" + +#: src/common/util.c:310 +msgid "Connection reset by peer" +msgstr "Злучэнне пераўсталяваны тым бокам" + +#: src/common/util.c:839 +msgid "Ascension Island" +msgstr "Узнясення астравы" + +#: src/common/util.c:840 +msgid "Andorra" +msgstr "Андора" + +#: src/common/util.c:841 +msgid "United Arab Emirates" +msgstr "Злучаныя Арабскія Эміраты" + +#: src/common/util.c:842 +msgid "Afghanistan" +msgstr "Аўганістан" + +#: src/common/util.c:843 +msgid "Antigua and Barbuda" +msgstr "Антыгуа і Барбуда" + +#: src/common/util.c:844 +msgid "Anguilla" +msgstr "Ангілья" + +#: src/common/util.c:845 +msgid "Albania" +msgstr "Албанія" + +#: src/common/util.c:846 +msgid "Armenia" +msgstr "Арменія" + +#: src/common/util.c:847 +msgid "Netherlands Antilles" +msgstr "Нідэрландскія Антылы" + +#: src/common/util.c:848 +msgid "Angola" +msgstr "Ангола" + +#: src/common/util.c:849 +msgid "Antarctica" +msgstr "Антарктыка" + +#: src/common/util.c:850 +msgid "Argentina" +msgstr "Аргентына" + +#: src/common/util.c:851 +msgid "Reverse DNS" +msgstr "Адваротны DNS" + +#: src/common/util.c:852 +msgid "American Samoa" +msgstr "Амерыканскае Самоа" + +#: src/common/util.c:853 +msgid "Austria" +msgstr "Аўстрыя" + +#: src/common/util.c:854 +msgid "Nato Fiel" +msgstr "НАТО Фэйл" + +#: src/common/util.c:855 +msgid "Australia" +msgstr "Аўстралія" + +#: src/common/util.c:856 +msgid "Aruba" +msgstr "Аруба" + +#: src/common/util.c:857 +msgid "Aland Islands" +msgstr "Аланавы астравы" + +#: src/common/util.c:858 +msgid "Azerbaijan" +msgstr "Азербайджан" + +#: src/common/util.c:859 +msgid "Bosnia and Herzegovina" +msgstr "Боснія і Герцагавіна" + +#: src/common/util.c:860 +msgid "Barbados" +msgstr "Барбадос" + +#: src/common/util.c:861 +msgid "Bangladesh" +msgstr "Бангладэш" + +#: src/common/util.c:862 +msgid "Belgium" +msgstr "Бельгія" + +#: src/common/util.c:863 +msgid "Burkina Faso" +msgstr "Буркіна Фасо" + +#: src/common/util.c:864 +msgid "Bulgaria" +msgstr "Баўгарыя" + +#: src/common/util.c:865 +msgid "Bahrain" +msgstr "Бахрэйн" + +#: src/common/util.c:866 +msgid "Burundi" +msgstr "Бурундзі" + +#: src/common/util.c:867 +msgid "Businesses" +msgstr "Бізнесовыя" + +#: src/common/util.c:868 +msgid "Benin" +msgstr "Бенін" + +#: src/common/util.c:869 +msgid "Bermuda" +msgstr "Бэрмуды" + +#: src/common/util.c:870 +msgid "Brunei Darussalam" +msgstr "Брунэй" + +#: src/common/util.c:871 +msgid "Bolivia" +msgstr "Балівія" + +#: src/common/util.c:872 +msgid "Brazil" +msgstr "Бразілія" + +#: src/common/util.c:873 +msgid "Bahamas" +msgstr "Багамы" + +#: src/common/util.c:874 +msgid "Bhutan" +msgstr "Бутан" + +#: src/common/util.c:875 +msgid "Bouvet Island" +msgstr "Востраў Бувет" + +#: src/common/util.c:876 +msgid "Botswana" +msgstr "Батсвана" + +#: src/common/util.c:877 +msgid "Belarus" +msgstr "Беларусь" + +#: src/common/util.c:878 +msgid "Belize" +msgstr "Белізе" + +#: src/common/util.c:879 +msgid "Canada" +msgstr "Канада" + +#: src/common/util.c:880 +msgid "Cocos Islands" +msgstr "Какос астравы" + +#: src/common/util.c:881 +msgid "Democratic Republic of Congo" +msgstr "Дэмакратычная Рэспубліка Конга" + +#: src/common/util.c:882 +msgid "Central African Republic" +msgstr "Цэнтральна-Афрыканская Рэспубліка" + +#: src/common/util.c:883 +msgid "Congo" +msgstr "Конга" + +#: src/common/util.c:884 +msgid "Switzerland" +msgstr "Швейцарыя" + +#: src/common/util.c:885 +msgid "Cote d'Ivoire" +msgstr "Кот д'Івуар" + +#: src/common/util.c:886 +msgid "Cook Islands" +msgstr "Астравы Кука" + +#: src/common/util.c:887 +msgid "Chile" +msgstr "Чылі" + +#: src/common/util.c:888 +msgid "Cameroon" +msgstr "Камерун" + +#: src/common/util.c:889 +msgid "China" +msgstr "Кітай" + +#: src/common/util.c:890 +msgid "Colombia" +msgstr "Калумбія" + +#: src/common/util.c:891 +msgid "Internic Commercial" +msgstr "Камерцыйныя Адрасы" + +#: src/common/util.c:892 +msgid "Costa Rica" +msgstr "Коста Рыка" + +#: src/common/util.c:893 +msgid "Serbia and Montenegro" +msgstr "Сербія і Чарнагорыя" + +#: src/common/util.c:894 +msgid "Cuba" +msgstr "Куба" + +#: src/common/util.c:895 +msgid "Cape Verde" +msgstr "Кабо Вердэ" + +#: src/common/util.c:896 +msgid "Christmas Island" +msgstr "Востраў Каляд" + +#: src/common/util.c:897 +msgid "Cyprus" +msgstr "Кіпр" + +#: src/common/util.c:898 +msgid "Czech Republic" +msgstr "Чэхія" + +#: src/common/util.c:899 +msgid "Germany" +msgstr "Нямеччына" + +#: src/common/util.c:900 +msgid "Djibouti" +msgstr "Джыбуці" + +#: src/common/util.c:901 +msgid "Denmark" +msgstr "Данія" + +#: src/common/util.c:902 +msgid "Dominica" +msgstr "Дамініка" + +#: src/common/util.c:903 +msgid "Dominican Republic" +msgstr "Дамініканская Рэспубліка" + +#: src/common/util.c:904 +msgid "Algeria" +msgstr "Алжыр" + +#: src/common/util.c:905 +msgid "Ecuador" +msgstr "Эквадор" + +#: src/common/util.c:906 +msgid "Educational Institution" +msgstr "Адукацыйныя" + +#: src/common/util.c:907 +msgid "Estonia" +msgstr "Эстонія" + +#: src/common/util.c:908 +msgid "Egypt" +msgstr "Егіпет" + +#: src/common/util.c:909 +msgid "Western Sahara" +msgstr "Заходняя Сахара" + +#: src/common/util.c:910 +msgid "Eritrea" +msgstr "Эрытрэя" + +#: src/common/util.c:911 +msgid "Spain" +msgstr "Гішпанія" + +#: src/common/util.c:912 +msgid "Ethiopia" +msgstr "Эфіёпія" + +#: src/common/util.c:913 +msgid "European Union" +msgstr "Еўразвяз" + +#: src/common/util.c:914 +msgid "Finland" +msgstr "Фінляндыя" + +#: src/common/util.c:915 +msgid "Fiji" +msgstr "Фіджы" + +#: src/common/util.c:916 +msgid "Falkland Islands" +msgstr "Фалклендскія астравы (Мальвіны)" + +#: src/common/util.c:917 +msgid "Micronesia" +msgstr "Федэрацыя Мiкранэзіі" + +#: src/common/util.c:918 +msgid "Faroe Islands" +msgstr "Астравы Фароэ" + +#: src/common/util.c:919 +msgid "France" +msgstr "Францыя" + +#: src/common/util.c:920 +msgid "Gabon" +msgstr "Габон" + +#: src/common/util.c:921 +msgid "Great Britain" +msgstr "Вялікая Брытанія" + +#: src/common/util.c:922 +msgid "Grenada" +msgstr "Грэнада" + +#: src/common/util.c:923 +msgid "Georgia" +msgstr "Грузія" + +#: src/common/util.c:924 +msgid "French Guiana" +msgstr "Французская Грэнада" + +#: src/common/util.c:925 +msgid "British Channel Isles" +msgstr "Брытанскія астравы Канала" + +#: src/common/util.c:926 +msgid "Ghana" +msgstr "Гана" + +#: src/common/util.c:927 +msgid "Gibraltar" +msgstr "Гібралтар" + +#: src/common/util.c:928 +msgid "Greenland" +msgstr "Грынланд" + +#: src/common/util.c:929 +msgid "Gambia" +msgstr "Гамбія" + +#: src/common/util.c:930 +msgid "Guinea" +msgstr "Гвінея" + +#: src/common/util.c:931 +msgid "Government" +msgstr "Урад" + +#: src/common/util.c:932 +msgid "Guadeloupe" +msgstr "Гвадэлупа" + +#: src/common/util.c:933 +msgid "Equatorial Guinea" +msgstr "Экватарыяльная Гвінэя" + +#: src/common/util.c:934 +msgid "Greece" +msgstr "Грэцыя" + +#: src/common/util.c:935 +msgid "S. Georgia and S. Sandwich Isles" +msgstr "Св.Георгія і Св.Сэндвіча астравы" + +#: src/common/util.c:936 +msgid "Guatemala" +msgstr "Гватэмала" + +#: src/common/util.c:937 +msgid "Guam" +msgstr "Гуам" + +#: src/common/util.c:938 +msgid "Guinea-Bissau" +msgstr "Гвінея-Бісаў" + +#: src/common/util.c:939 +msgid "Guyana" +msgstr "Гвіяна" + +#: src/common/util.c:940 +msgid "Hong Kong" +msgstr "Гонг-Конг" + +#: src/common/util.c:941 +msgid "Heard and McDonald Islands" +msgstr "Астравы Гэарда і МакДональда " + +#: src/common/util.c:942 +msgid "Honduras" +msgstr "Гандурас" + +#: src/common/util.c:943 +msgid "Croatia" +msgstr "Харватыя" + +#: src/common/util.c:944 +msgid "Haiti" +msgstr "Гаіці" + +#: src/common/util.c:945 +msgid "Hungary" +msgstr "Вугоршчына" + +#: src/common/util.c:946 +msgid "Indonesia" +msgstr "Інданэзія" + +#: src/common/util.c:947 +msgid "Ireland" +msgstr "Ірландыя" + +#: src/common/util.c:948 +msgid "Israel" +msgstr "Ізраіль" + +#: src/common/util.c:949 +msgid "Isle of Man" +msgstr "Востраў Мэн" + +#: src/common/util.c:950 +msgid "India" +msgstr "Індыя" + +#: src/common/util.c:951 +msgid "Informational" +msgstr "Інфармацыйныя" + +#: src/common/util.c:952 +msgid "International" +msgstr "Міжнародныя" + +#: src/common/util.c:953 +msgid "British Indian Ocean Territory" +msgstr "Брытанская тэрыторыя Індыйскага акіяна" + +#: src/common/util.c:954 +msgid "Iraq" +msgstr "Ірак" + +#: src/common/util.c:955 +msgid "Iran" +msgstr "Іран" + +#: src/common/util.c:956 +msgid "Iceland" +msgstr "Ісландыя" + +#: src/common/util.c:957 +msgid "Italy" +msgstr "Італія" + +#: src/common/util.c:958 +msgid "Jersey" +msgstr "Джэрсі" + +#: src/common/util.c:959 +msgid "Jamaica" +msgstr "Ямайка" + +#: src/common/util.c:960 +msgid "Jordan" +msgstr "Ярданія" + +#: src/common/util.c:961 +msgid "Japan" +msgstr "Японія" + +#: src/common/util.c:962 +msgid "Kenya" +msgstr "Кенія" + +#: src/common/util.c:963 +msgid "Kyrgyzstan" +msgstr "Кыргызстан" + +#: src/common/util.c:964 +msgid "Cambodia" +msgstr "Камбоджа" + +#: src/common/util.c:965 +msgid "Kiribati" +msgstr "Кiрыбацi" + +#: src/common/util.c:966 +msgid "Comoros" +msgstr "Каморы" + +#: src/common/util.c:967 +msgid "St. Kitts and Nevis" +msgstr "Сэнт-Кітс і Нэвіс" + +#: src/common/util.c:968 +msgid "North Korea" +msgstr "Паўночная Карэя" + +#: src/common/util.c:969 +msgid "South Korea" +msgstr "Паўднёвая Карэя" + +#: src/common/util.c:970 +msgid "Kuwait" +msgstr "Кувэйт" + +#: src/common/util.c:971 +msgid "Cayman Islands" +msgstr "Кайманавы астравы" + +#: src/common/util.c:972 +msgid "Kazakhstan" +msgstr "Казахстан" + +#: src/common/util.c:973 +msgid "Laos" +msgstr "Лаос" + +#: src/common/util.c:974 +msgid "Lebanon" +msgstr "Ліван" + +#: src/common/util.c:975 +msgid "Saint Lucia" +msgstr "Сэнт-Люсія" + +#: src/common/util.c:976 +msgid "Liechtenstein" +msgstr "Ліхтэнштэйн" + +#: src/common/util.c:977 +msgid "Sri Lanka" +msgstr "Шры-Ланка" + +#: src/common/util.c:978 +msgid "Liberia" +msgstr "Лібэрыя" + +#: src/common/util.c:979 +msgid "Lesotho" +msgstr "Лесота" + +#: src/common/util.c:980 +msgid "Lithuania" +msgstr "Літва" + +#: src/common/util.c:981 +msgid "Luxembourg" +msgstr "Люксэмбург" + +#: src/common/util.c:982 +msgid "Latvia" +msgstr "Латвія" + +#: src/common/util.c:983 +msgid "Libya" +msgstr "Лівія" + +#: src/common/util.c:984 +msgid "Morocco" +msgstr "Марока" + +#: src/common/util.c:985 +msgid "Monaco" +msgstr "Манака" + +#: src/common/util.c:986 +msgid "Moldova" +msgstr "Малдова" + +#: src/common/util.c:987 +msgid "United States Medical" +msgstr "Злучаныя Штаты, медыцына" + +#: src/common/util.c:988 +msgid "Madagascar" +msgstr "Мадагаскар" + +#: src/common/util.c:989 +msgid "Marshall Islands" +msgstr "Маршалавы астравы" + +#: src/common/util.c:990 +msgid "Military" +msgstr "Вайсковыя" + +#: src/common/util.c:991 +msgid "Macedonia" +msgstr "Македонія" + +#: src/common/util.c:992 +msgid "Mali" +msgstr "Малі" + +#: src/common/util.c:993 +msgid "Myanmar" +msgstr "М'янма" + +#: src/common/util.c:994 +msgid "Mongolia" +msgstr "Манголія" + +#: src/common/util.c:995 +msgid "Macau" +msgstr "Макау" + +#: src/common/util.c:996 +msgid "Northern Mariana Islands" +msgstr "Паўночныя Марыянскія астравы" + +#: src/common/util.c:997 +msgid "Martinique" +msgstr "Мартыніка" + +#: src/common/util.c:998 +msgid "Mauritania" +msgstr "Маўрытанія" + +#: src/common/util.c:999 +msgid "Montserrat" +msgstr "Мантсэрат" + +#: src/common/util.c:1000 +msgid "Malta" +msgstr "Мальта" + +#: src/common/util.c:1001 +msgid "Mauritius" +msgstr "Маўрыцы" + +#: src/common/util.c:1002 +msgid "Maldives" +msgstr "Мальдывы" + +#: src/common/util.c:1003 +msgid "Malawi" +msgstr "Малаві" + +#: src/common/util.c:1004 +msgid "Mexico" +msgstr "Мэксыка" + +#: src/common/util.c:1005 +msgid "Malaysia" +msgstr "Малайзыя" + +#: src/common/util.c:1006 +msgid "Mozambique" +msgstr "Мазамбік" + +#: src/common/util.c:1007 +msgid "Namibia" +msgstr "Намібія" + +#: src/common/util.c:1008 +msgid "New Caledonia" +msgstr "Новая Каледонія" + +#: src/common/util.c:1009 +msgid "Niger" +msgstr "Нігер" + +#: src/common/util.c:1010 +msgid "Internic Network" +msgstr "Унутраныя сецівы" + +#: src/common/util.c:1011 +msgid "Norfolk Island" +msgstr "Норфалк" + +#: src/common/util.c:1012 +msgid "Nigeria" +msgstr "Нігерыя" + +#: src/common/util.c:1013 +msgid "Nicaragua" +msgstr "Нікарагуа" + +#: src/common/util.c:1014 +msgid "Netherlands" +msgstr "Галяндыя" + +#: src/common/util.c:1015 +msgid "Norway" +msgstr "Нарвэгія" + +#: src/common/util.c:1016 +msgid "Nepal" +msgstr "Нэпал" + +#: src/common/util.c:1017 +msgid "Nauru" +msgstr "Науру" + +#: src/common/util.c:1018 +msgid "Niue" +msgstr "Ніўэ" + +#: src/common/util.c:1019 +msgid "New Zealand" +msgstr "Новая Зеландыя" + +#: src/common/util.c:1020 +msgid "Oman" +msgstr "Аман" + +#: src/common/util.c:1021 +msgid "Internic Non-Profit Organization" +msgstr "Унутраныя некамерцыйныя арганізацыі" + +#: src/common/util.c:1022 +msgid "Panama" +msgstr "Панама" + +#: src/common/util.c:1023 +msgid "Peru" +msgstr "Пэру" + +#: src/common/util.c:1024 +msgid "French Polynesia" +msgstr "Французская Палінэзія" + +#: src/common/util.c:1025 +msgid "Papua New Guinea" +msgstr "Папуа Новая Гвінея" + +#: src/common/util.c:1026 +msgid "Philippines" +msgstr "Філіпіны" + +#: src/common/util.c:1027 +msgid "Pakistan" +msgstr "Пакістан" + +#: src/common/util.c:1028 +msgid "Poland" +msgstr "Польшча" + +#: src/common/util.c:1029 +msgid "St. Pierre and Miquelon" +msgstr "Сэн-П'ер і Мікелон" + +#: src/common/util.c:1030 +msgid "Pitcairn" +msgstr "Піткэрн" + +#: src/common/util.c:1031 +msgid "Puerto Rico" +msgstr "Пуэрта Рыка" + +#: src/common/util.c:1032 +msgid "Palestinian Territory" +msgstr "Палестынская тэрыторыя" + +#: src/common/util.c:1033 +msgid "Portugal" +msgstr "Партугалія" + +#: src/common/util.c:1034 +msgid "Palau" +msgstr "Палаў" + +#: src/common/util.c:1035 +msgid "Paraguay" +msgstr "Парагвай" + +#: src/common/util.c:1036 +msgid "Qatar" +msgstr "Катар" + +#: src/common/util.c:1037 +msgid "Reunion" +msgstr "Рэюньён" + +#: src/common/util.c:1038 +msgid "Romania" +msgstr "Румынія" + +#: src/common/util.c:1039 +msgid "Old School ARPAnet" +msgstr "Старое сеціва ARPAnet" + +#: src/common/util.c:1040 +msgid "Russian Federation" +msgstr "Расія" + +#: src/common/util.c:1041 +msgid "Rwanda" +msgstr "Руанда" + +#: src/common/util.c:1042 +msgid "Saudi Arabia" +msgstr "Саўдаўская Арабія" + +#: src/common/util.c:1043 +msgid "Solomon Islands" +msgstr "Саламонавы астравы" + +#: src/common/util.c:1044 +msgid "Seychelles" +msgstr "Сэйшэлы" + +#: src/common/util.c:1045 +msgid "Sudan" +msgstr "Судан" + +#: src/common/util.c:1046 +msgid "Sweden" +msgstr "Швецыя" + +#: src/common/util.c:1047 +msgid "Singapore" +msgstr "Сінгапур" + +#: src/common/util.c:1048 +msgid "St. Helena" +msgstr "Востраў Сьвятой Алены" + +#: src/common/util.c:1049 +msgid "Slovenia" +msgstr "Славенія" + +#: src/common/util.c:1050 +msgid "Svalbard and Jan Mayen Islands" +msgstr "Астравы Свальбард і Яна Майхема" + +#: src/common/util.c:1051 +msgid "Slovak Republic" +msgstr "Славакія" + +#: src/common/util.c:1052 +msgid "Sierra Leone" +msgstr "Сьера-Леонэ" + +#: src/common/util.c:1053 +msgid "San Marino" +msgstr "Сан-Марына" + +#: src/common/util.c:1054 +msgid "Senegal" +msgstr "Сенегал" + +#: src/common/util.c:1055 +msgid "Somalia" +msgstr "Самалі" + +#: src/common/util.c:1056 +msgid "Suriname" +msgstr "Сурынам" + +#: src/common/util.c:1057 +msgid "Sao Tome and Principe" +msgstr "Сан-Тамэ і Прынсіпі" + +#: src/common/util.c:1058 +msgid "Former USSR" +msgstr "Былы СССР" + +#: src/common/util.c:1059 +msgid "El Salvador" +msgstr "Сальвадор" + +#: src/common/util.c:1060 +msgid "Syria" +msgstr "Сырыя" + +#: src/common/util.c:1061 +msgid "Swaziland" +msgstr "Свазылэнд" + +#: src/common/util.c:1062 +msgid "Turks and Caicos Islands" +msgstr "Астравы Тэркс і Кайкас" + +#: src/common/util.c:1063 +msgid "Chad" +msgstr "Чад" + +#: src/common/util.c:1064 +msgid "French Southern Territories" +msgstr "Французскія паўднёвыя тэрыторыі" + +#: src/common/util.c:1065 +msgid "Togo" +msgstr "Тога" + +#: src/common/util.c:1066 +msgid "Thailand" +msgstr "Тайланд" + +#: src/common/util.c:1067 +msgid "Tajikistan" +msgstr "Таджыкістан" + +#: src/common/util.c:1068 +msgid "Tokelau" +msgstr "Такелаў" + +#: src/common/util.c:1069 src/common/util.c:1073 +msgid "East Timor" +msgstr "Усходні Тымор" + +#: src/common/util.c:1070 +msgid "Turkmenistan" +msgstr "Туркменістан" + +#: src/common/util.c:1071 +msgid "Tunisia" +msgstr "Туніс" + +#: src/common/util.c:1072 +msgid "Tonga" +msgstr "Тонга" + +#: src/common/util.c:1074 +msgid "Turkey" +msgstr "Турцыя" + +#: src/common/util.c:1075 +msgid "Trinidad and Tobago" +msgstr "Трынідад і Табага" + +#: src/common/util.c:1076 +msgid "Tuvalu" +msgstr "Тувалу" + +#: src/common/util.c:1077 +msgid "Taiwan" +msgstr "Тайвань" + +#: src/common/util.c:1078 +msgid "Tanzania" +msgstr "Злучаная Рэспубліка Танзанія" + +#: src/common/util.c:1079 +msgid "Ukraine" +msgstr "Украіна" + +#: src/common/util.c:1080 +msgid "Uganda" +msgstr "Уганда" + +#: src/common/util.c:1081 +msgid "United Kingdom" +msgstr "Аб'яднанае Каралеўства" + +#: src/common/util.c:1082 +msgid "United States of America" +msgstr "Злучаныя Штаты Амерыкі" + +#: src/common/util.c:1083 +msgid "Uruguay" +msgstr "Уругвай" + +#: src/common/util.c:1084 +msgid "Uzbekistan" +msgstr "Узбекістан" + +#: src/common/util.c:1085 +msgid "Vatican City State" +msgstr "Ватыкан" + +#: src/common/util.c:1086 +msgid "St. Vincent and the Grenadines" +msgstr "Св.Вінсент і Грэнадзіны" + +#: src/common/util.c:1087 +msgid "Venezuela" +msgstr "Венесуэла" + +#: src/common/util.c:1088 +msgid "British Virgin Islands" +msgstr "Брытанскія астравы Вірджын" + +#: src/common/util.c:1089 +msgid "US Virgin Islands" +msgstr "ЗША астравы Вірджын" + +#: src/common/util.c:1090 +msgid "Vietnam" +msgstr "В'етнам" + +#: src/common/util.c:1091 +msgid "Vanuatu" +msgstr "Вануату" + +#: src/common/util.c:1092 +msgid "Wallis and Futuna Islands" +msgstr "Воліс і Футуна астравы" + +#: src/common/util.c:1093 +msgid "Samoa" +msgstr "Самоа" + +#: src/common/util.c:1094 +msgid "Yemen" +msgstr "Йемен" + +#: src/common/util.c:1095 +msgid "Mayotte" +msgstr "Маёт" + +#: src/common/util.c:1096 +msgid "Yugoslavia" +msgstr "Югаславія" + +#: src/common/util.c:1097 +msgid "South Africa" +msgstr "Паўдневая Афрыка" + +#: src/common/util.c:1098 +msgid "Zambia" +msgstr "Забмія" + +#: src/common/util.c:1099 +msgid "Zimbabwe" +msgstr "Зімбабвэ" + +#: src/common/util.c:1109 src/common/util.c:1119 src/fe-gtk/menu.c:550 +#: src/fe-gtk/menu.c:555 src/fe-gtk/menu.c:559 src/fe-gtk/menu.c:563 +#: src/fe-gtk/menu.c:571 src/fe-gtk/menu.c:589 +msgid "Unknown" +msgstr "Невядома" + +#: src/common/xchat.c:769 src/common/xchat.c:895 +msgid "Open Dialog Window" +msgstr "Пачаць дыялог" + +#: src/common/xchat.c:770 +msgid "Send a File" +msgstr "Даслаць файл" + +#: src/common/xchat.c:771 +msgid "User Info (WHOIS)" +msgstr "Звесткі (WHOIS)" + +#: src/common/xchat.c:772 +msgid "Operator Actions" +msgstr "Дзеянні аператара" + +#: src/common/xchat.c:774 src/common/xchat.c:865 +msgid "Give Ops" +msgstr "Даць аператара" + +#: src/common/xchat.c:775 src/common/xchat.c:866 +msgid "Take Ops" +msgstr "Забраць аператара" + +#: src/common/xchat.c:776 src/common/xchat.c:869 +msgid "Give Voice" +msgstr "Даць голас" + +#: src/common/xchat.c:777 src/common/xchat.c:870 +msgid "Take Voice" +msgstr "Забраць голас" + +#: src/common/xchat.c:779 src/common/xchat.c:874 +msgid "Kick/Ban" +msgstr "Выпхнуць/забараніць" + +#: src/common/xchat.c:780 src/common/xchat.c:875 src/common/xchat.c:924 +msgid "Kick" +msgstr "Выпхнуць" + +#: src/common/xchat.c:781 src/common/xchat.c:782 src/common/xchat.c:783 +#: src/common/xchat.c:784 src/common/xchat.c:785 src/common/xchat.c:876 +#: src/common/xchat.c:877 src/common/xchat.c:878 src/common/xchat.c:879 +#: src/common/xchat.c:880 src/common/xchat.c:923 +msgid "Ban" +msgstr "Забараніць" + +#: src/common/xchat.c:786 src/common/xchat.c:787 src/common/xchat.c:788 +#: src/common/xchat.c:789 src/common/xchat.c:881 src/common/xchat.c:882 +#: src/common/xchat.c:883 src/common/xchat.c:884 +msgid "KickBan" +msgstr "Выпхнуць і забараніць" + +#: src/common/xchat.c:852 +msgid "Direct client-to-client" +msgstr "Прамое дачыненне (DCC)" + +#: src/common/xchat.c:853 +msgid "Send File" +msgstr "Даслаць файл" + +#: src/common/xchat.c:854 +msgid "Offer Chat" +msgstr "Прапанаваць размову" + +#: src/common/xchat.c:855 +msgid "Abort Chat" +msgstr "Перарваць размову" + +#: src/common/xchat.c:856 src/fe-gtk/plugingui.c:74 +msgid "Version" +msgstr "Версія" + +#: src/common/xchat.c:857 +msgid "Userinfo" +msgstr "Звесткі аб карыстальніку" + +#: src/common/xchat.c:858 +msgid "Clientinfo" +msgstr "Звесткі аб кліенце" + +#: src/common/xchat.c:859 src/common/xchat.c:893 src/common/xchat.c:941 +msgid "Ping" +msgstr "Ping" + +#: src/common/xchat.c:860 +msgid "Time" +msgstr "Час" + +#: src/common/xchat.c:861 +msgid "Finger" +msgstr "Водціск" + +#: src/common/xchat.c:862 +msgid "Oper" +msgstr "Аперацыя" + +#: src/common/xchat.c:863 +msgid "Kill this user" +msgstr "Выпхнуць карыстальніка" + +#: src/common/xchat.c:864 +msgid "Mode" +msgstr "Рэжым" + +#: src/common/xchat.c:867 +msgid "Give Half-Ops" +msgstr "Даць паў-аператара" + +#: src/common/xchat.c:868 +msgid "Take Half-Ops" +msgstr "Забраць паў-аператара" + +#: src/common/xchat.c:871 +msgid "Ignore" +msgstr "Ігнараванне" + +#: src/common/xchat.c:872 +msgid "Ignore User" +msgstr "Ігнараваць карыстальніка" + +#: src/common/xchat.c:873 +msgid "UnIgnore User" +msgstr "Не ігнараваць карыстальніка" + +#: src/common/xchat.c:885 +msgid "Info" +msgstr "Інфа" + +#: src/common/xchat.c:886 +msgid "Who" +msgstr "Хто" + +#: src/common/xchat.c:887 src/common/xchat.c:937 +msgid "WhoIs" +msgstr "Хто ёсць" + +#: src/common/xchat.c:888 +msgid "DNS Lookup" +msgstr "Прагляд DNS" + +#: src/common/xchat.c:889 +msgid "Trace" +msgstr "Trace" + +#: src/common/xchat.c:890 +msgid "UserHost" +msgstr "Камп'ютэр карыстальніка" + +#: src/common/xchat.c:891 +msgid "External" +msgstr "Вонкавы" + +#: src/common/xchat.c:892 +msgid "Traceroute" +msgstr "Traceroute" + +#: src/common/xchat.c:894 +msgid "Telnet" +msgstr "Telnet" + +#: src/common/xchat.c:906 +msgid "Leave Channel" +msgstr "Выйсці з канала" + +#: src/common/xchat.c:907 src/fe-gtk/menu.c:1392 +msgid "Join Channel..." +msgstr "Увайсці на канал..." + +#: src/common/xchat.c:908 src/fe-gtk/menu.c:1083 +msgid "Enter Channel to Join:" +msgstr "Вызначце канал для ўваходу:" + +#: src/common/xchat.c:909 +msgid "Server Links" +msgstr "Спасылкі сервера" + +#: src/common/xchat.c:910 +msgid "Ping Server" +msgstr "Пінгаваць сервер" + +#: src/common/xchat.c:911 +msgid "Hide Version" +msgstr "Схаваць версію" + +#: src/common/xchat.c:921 +msgid "Op" +msgstr "Аператар" + +#: src/common/xchat.c:922 +msgid "DeOp" +msgstr "Адабраць аператара" + +#: src/common/xchat.c:925 +msgid "bye" +msgstr "пакуль" + +#: src/common/xchat.c:926 +#, c-format +msgid "Enter reason to kick %s:" +msgstr "Увядзіце прычыну выпіхвання %s:" + +#: src/common/xchat.c:927 +msgid "Sendfile" +msgstr "Даслаць файл" + +#: src/common/xchat.c:928 +msgid "Dialog" +msgstr "Дыялог" + +#: src/common/xchat.c:938 +msgid "Send" +msgstr "Даслаць" + +#: src/common/xchat.c:939 +msgid "Chat" +msgstr "Размова" + +#: src/common/xchat.c:940 src/fe-gtk/banlist.c:341 src/fe-gtk/ignoregui.c:388 +#: src/fe-gtk/urlgrab.c:201 +msgid "Clear" +msgstr "Ачысціць" + +#: src/common/dbus/dbus-client.c:71 +msgid "Couldn't connect to session bus" +msgstr "Немагчыма злучыцца з шынай сесій (session bus)" + +#: src/common/dbus/dbus-client.c:85 +msgid "Failed to complete NameHasOwner" +msgstr "Немагчыма скончыць NameHasOwner" + +#: src/common/dbus/dbus-client.c:106 +msgid "Failed to complete Command" +msgstr "Немагчыма скончыць Command" + +#: src/common/dbus/dbus-plugin.c:30 +msgid "remote access" +msgstr "аддалены доступ" + +#: src/common/dbus/dbus-plugin.c:31 +msgid "plugin for remote access using DBUS" +msgstr "Плагін для аддаленага доступу (выкарыстоўвае DBUS)" + +#: src/common/dbus/dbus-plugin.c:897 +#, c-format +msgid "Couldn't connect to session bus: %s\n" +msgstr "Немагчыма злучыцца з шынай сесій : %s\n" + +#: src/common/dbus/dbus-plugin.c:914 +#, c-format +msgid "Failed to acquire %s: %s\n" +msgstr "Немагчыма дасягнуць %s : %s\n" + +#: src/fe-gtk/about.c:102 +msgid "About XChat" +msgstr "Аб праграме" + +#: src/fe-gtk/about.c:129 +msgid "A multiplatform IRC Client" +msgstr "Шматплатформенны кліент IRC" + +#: src/fe-gtk/ascii.c:135 +msgid "Character Chart" +msgstr "Палітра літар" + +#: src/fe-gtk/banlist.c:113 src/fe-gtk/chanlist.c:299 +#: src/fe-gtk/plugin-tray.c:209 +msgid "Not connected." +msgstr "Не злучана." + +#: src/fe-gtk/banlist.c:154 src/fe-gtk/banlist.c:257 +msgid "You must select some bans." +msgstr "Трэба выбраць некалькі забаронаў." + +#: src/fe-gtk/banlist.c:206 +#, c-format +msgid "Are you sure you want to remove all bans in %s?" +msgstr "Ці вы ўпэўнены, што хочаце выдаліць усе забароны у %s?" + +#: src/fe-gtk/banlist.c:272 src/fe-gtk/ignoregui.c:175 +msgid "Mask" +msgstr "Маска" + +#: src/fe-gtk/banlist.c:273 +msgid "From" +msgstr "Адкуль" + +#: src/fe-gtk/banlist.c:274 +msgid "Date" +msgstr "Дата" + +#: src/fe-gtk/banlist.c:317 +msgid "You can only open the Ban List window while in a channel tab." +msgstr "Вы можаце адкрыць акно са спісам забаронаў толькі пры адкрытай укладцы канала." + +#: src/fe-gtk/banlist.c:321 +#, c-format +msgid "XChat: Ban List (%s)" +msgstr "XChat: спіс забаронаў (%s)" + +#: src/fe-gtk/banlist.c:337 +msgid "Unban" +msgstr "Дазволіць" + +#: src/fe-gtk/banlist.c:339 +msgid "Crop" +msgstr "Сціснуць" + +#: src/fe-gtk/banlist.c:343 +msgid "Refresh" +msgstr "Аднавіць" + +#: src/fe-gtk/chanlist.c:111 +#, c-format +msgid "Displaying %d/%d users on %d/%d channels." +msgstr "Паказ %d/%d карыстальнікаў на %d/%d каналах." + +#: src/fe-gtk/chanlist.c:516 src/fe-gtk/menu.c:1019 src/fe-gtk/urlgrab.c:148 +msgid "Select an output filename" +msgstr "Абярыце імя файла для вываду" + +#: src/fe-gtk/chanlist.c:595 src/fe-gtk/chanlist.c:751 +msgid "_Join Channel" +msgstr "У_вайсці на канал" + +#: src/fe-gtk/chanlist.c:597 +msgid "_Copy Channel Name" +msgstr "_Капіяваць назву канала" + +#: src/fe-gtk/chanlist.c:599 +msgid "Copy _Topic Text" +msgstr "Капіяваць тэкст _тэмы" + +#: src/fe-gtk/chanlist.c:677 +#, c-format +msgid "XChat: Channel List (%s)" +msgstr "XChat: Спіс каналаў (%s)" + +#: src/fe-gtk/chanlist.c:733 +msgid "_Search" +msgstr "_Пошук" + +#: src/fe-gtk/chanlist.c:739 +msgid "_Download List" +msgstr "Спіс спа_мповак" + +#: src/fe-gtk/chanlist.c:745 +msgid "Save _List..." +msgstr "Захаваць _спіс як..." + +#: src/fe-gtk/chanlist.c:758 +msgid "Show only:" +msgstr "Паказаць толькі:" + +#: src/fe-gtk/chanlist.c:770 +msgid "channels with" +msgstr "каналы з ад" + +#: src/fe-gtk/chanlist.c:783 +msgid "to" +msgstr "да" + +#: src/fe-gtk/chanlist.c:795 +msgid "users." +msgstr "карыстальнікамі" + +#: src/fe-gtk/chanlist.c:801 +msgid "Look in:" +msgstr "Глядзець у" + +#: src/fe-gtk/chanlist.c:813 +msgid "Channel name" +msgstr "Назва канала" + +#: src/fe-gtk/chanlist.c:834 +msgid "Search type:" +msgstr "Тып пошуку:" + +#: src/fe-gtk/chanlist.c:841 +msgid "Simple Search" +msgstr "Просты пошук" + +#: src/fe-gtk/chanlist.c:842 +msgid "Pattern Match (Wildcards)" +msgstr "Узор адпавядае (Wildcards)" + +#: src/fe-gtk/chanlist.c:844 +msgid "Regular Expression" +msgstr "Рэгулярны выраз" + +#: src/fe-gtk/chanlist.c:855 src/fe-gtk/search.c:118 +msgid "Find:" +msgstr "Знайсці:" + +#: src/fe-gtk/dccgui.c:166 +#, c-format +msgid "Send file to %s" +msgstr "Даслаць файл %s" + +#: src/fe-gtk/dccgui.c:496 +msgid "That file is not resumable." +msgstr "Працяг гэтага файла немагчымы." + +#: src/fe-gtk/dccgui.c:500 +#, c-format +msgid "" +"Cannot access file: %s\n" +"%s.\n" +"Resuming not possible." +msgstr "" +"Немагчыма атрымаць доступ да файла: %s\n" +"%s.\n" +"Працяг немагчымы." + +#: src/fe-gtk/dccgui.c:507 +msgid "File in download directory is larger than file offered. Resuming not possible." +msgstr "Файл у тэчцы спампоўванняў большы за прапанаваны файл. Працяг немагчымы." + +#: src/fe-gtk/dccgui.c:511 +msgid "Cannot resume the same file from two people." +msgstr "Немагчыма працягнуць той жа самы файл з двух чалавек." + +#: src/fe-gtk/dccgui.c:740 +msgid "XChat: Uploads and Downloads" +msgstr "XChat: запампоўкі і спампоўкі" + +#: src/fe-gtk/dccgui.c:756 src/fe-gtk/dccgui.c:993 src/fe-gtk/notifygui.c:138 +msgid "Status" +msgstr "Статус" + +#: src/fe-gtk/dccgui.c:757 src/fe-gtk/plugingui.c:75 +msgid "File" +msgstr "Файл" + +#: src/fe-gtk/dccgui.c:762 +msgid "ETA" +msgstr "Прайшло часу" + +#: src/fe-gtk/dccgui.c:784 src/fe-gtk/menu.c:1386 +msgid "Both" +msgstr "Абодва" + +#: src/fe-gtk/dccgui.c:790 +msgid "Uploads" +msgstr "Запампоўкі" + +#: src/fe-gtk/dccgui.c:796 +msgid "Downloads" +msgstr "Спампоўкі" + +#: src/fe-gtk/dccgui.c:801 +msgid "Details" +msgstr "Падрабязнасці" + +#: src/fe-gtk/dccgui.c:812 +msgid "File:" +msgstr "Файл:" + +#: src/fe-gtk/dccgui.c:813 +msgid "Address:" +msgstr "Адрас:" + +#: src/fe-gtk/dccgui.c:819 src/fe-gtk/dccgui.c:1014 +msgid "Abort" +msgstr "Перарваць" + +#: src/fe-gtk/dccgui.c:820 src/fe-gtk/dccgui.c:1015 +msgid "Accept" +msgstr "Прыняць" + +#: src/fe-gtk/dccgui.c:821 +msgid "Resume" +msgstr "Працягнуць" + +#: src/fe-gtk/dccgui.c:822 +msgid "Open Folder..." +msgstr "Адкрыць тэчку..." + +#: src/fe-gtk/dccgui.c:982 +msgid "XChat: DCC Chat List" +msgstr "XChat: Спіс DCC Chat" + +#: src/fe-gtk/dccgui.c:995 +msgid "Recv" +msgstr "Прын" + +#: src/fe-gtk/dccgui.c:996 +msgid "Sent" +msgstr "Дасл" + +#: src/fe-gtk/dccgui.c:997 +msgid "Start Time" +msgstr "Час пачатку" + +#: src/fe-gtk/editlist.c:139 +msgid "*NEW*" +msgstr "*НОВЫ" + +#: src/fe-gtk/editlist.c:140 +msgid "EDIT ME" +msgstr "ЗМЯНІ МЯНЕ" + +#: src/fe-gtk/editlist.c:310 src/fe-gtk/plugingui.c:73 +msgid "Name" +msgstr "Імя" + +#: src/fe-gtk/editlist.c:311 +msgid "Command" +msgstr "Каманда" + +#: src/fe-gtk/editlist.c:339 +msgid "Move Up" +msgstr "Вышэй" + +#: src/fe-gtk/editlist.c:343 +msgid "Move Dn" +msgstr "Ніжэй" + +#: src/fe-gtk/editlist.c:351 +msgid "Cancel" +msgstr "Адмяніць" + +#: src/fe-gtk/editlist.c:355 +msgid "Save" +msgstr "Захаваць" + +#: src/fe-gtk/editlist.c:363 src/fe-gtk/fkeys.c:765 +msgid "Add New" +msgstr "Дадаць" + +#: src/fe-gtk/editlist.c:367 src/fe-gtk/fkeys.c:770 src/fe-gtk/ignoregui.c:386 +msgid "Delete" +msgstr "Выдаліць" + +#: src/fe-gtk/editlist.c:375 +msgid "Sort" +msgstr "Сартаваць" + +#: src/fe-gtk/editlist.c:379 +msgid "Help" +msgstr "Дапамога" + +#: src/fe-gtk/fe-gtk.c:122 +msgid "Don't auto connect to servers" +msgstr "Не злучацца з серверамі аўтаматычна" + +#: src/fe-gtk/fe-gtk.c:123 +msgid "Use a different config directory" +msgstr "Выкарыстоўваць іншую тэчку наладак" + +#: src/fe-gtk/fe-gtk.c:124 +msgid "Don't auto load any plugins" +msgstr "Не загружаць плагіны аўтаматычна" + +#: src/fe-gtk/fe-gtk.c:125 +msgid "Show plugin auto-load directory" +msgstr "Паказаць тэчку аўтазагрузкі плагінаў" + +#: src/fe-gtk/fe-gtk.c:126 +msgid "Show user config directory" +msgstr "Паказаць тэчку карыстальніцкіх наладак" + +#: src/fe-gtk/fe-gtk.c:127 +msgid "Open an irc://server:port/channel URL" +msgstr "Адкрыць URL, irc://server:port/channel" + +#: src/fe-gtk/fe-gtk.c:128 +msgid "Open URL in an existing XChat" +msgstr "Адкрыць URL у існуючым XChat" + +#: src/fe-gtk/fe-gtk.c:129 +msgid "Show version information" +msgstr "Паказаць звесткі аб версіі" + +#: src/fe-gtk/fe-gtk.c:249 +#, c-format +msgid "" +"Failed to open font:\n" +"\n" +"%s" +msgstr "" +"Памылка адкрыцця шрыфту:\n" +"\n" +"%s" + +#: src/fe-gtk/fe-gtk.c:621 +msgid "Search buffer is empty.\n" +msgstr "Буфер пошуку пусты.\n" + +#: src/fe-gtk/fe-gtk.c:717 +#, c-format +msgid "%d bytes" +msgstr "%d байтаў" + +#: src/fe-gtk/fe-gtk.c:718 +#, c-format +msgid "Network send queue: %d bytes" +msgstr "Сеціўная чарга дасылкі: %d байтаў" + +#: src/fe-gtk/fkeys.c:159 +msgid "The Run Command action runs the data in Data 1 as if it has been typed into the entry box where you pressed the key sequence. Thus it can contain text (which will be sent to the channel/person), commands or user commands. When run all \\n characters in Data 1 are used to deliminate seperate commands so it is possible to run more than one command. If you want a \\ in the actual text run then enter \\\\" +msgstr "Дзеянне Выканаць Каманду выконвае Данні 1 як каманду, быццам яна была ўведзена ў полі ўводу, у якім была націснута паслядоўнасць клавішаў. Можа змяшчаць тэкст (які будзе дасланы да канала ці асобы), каманды або каманды карыстальніка. Падчас выканання ўсе знакі \\n у Данніх 1 будуць скарыставаны для пазначэння падзелаў паміж камандамі, такім чынам, магчыма выканаць больш за адну каманду. Калі вы жадаеце ўжыць \\ у тэксце каманды, пішыце замест гэтага \\\\" + +#: src/fe-gtk/fkeys.c:161 +msgid "The Change Page command switches between pages in the notebook. Set Data 1 to the page you want to switch to. If Data 2 is set to anything then the switch will be relative to the current position" +msgstr "Каманда Змяніць Старонку пераключае старонкі ў нататніку. Усталюйце Данні 1 на старонку, куды трэба пераключыцца. Калі Данні 2 ўсталяваны, то будзе лічыцца адносна бягучай пазіцыі." + +#: src/fe-gtk/fkeys.c:163 +msgid "The Insert in Buffer command will insert the contents of Data 1 into the entry where the key sequence was pressed at the current cursor position" +msgstr "Каманда Ўставіць у буфер уставіць змест Данніх 1 у поле, дзе была націснута камбінацыя клавішаў, у бягучую пазіцыю курсора" + +#: src/fe-gtk/fkeys.c:165 +msgid "The Scroll Page command scrolls the text widget up or down one page or one line. Set Data 1 to either Up, Down, +1 or -1." +msgstr "Каманда Пракрутка Старонкі пракручвае тэкставае аздабленне ўніз ці ўверх на адну старонку ці на адзін радок. Усталюйце Данні 1 як Up, Down, +1 ці -1." + +#: src/fe-gtk/fkeys.c:167 +msgid "The Set Buffer command sets the entry where the key sequence was entered to the contents of Data 1" +msgstr "Каманда Усталяваць Буфер усталёўвае значэнне поля поля, дзе была націснута камбінацыя клавішаў, у значэнне Данніх 1" + +#: src/fe-gtk/fkeys.c:169 +msgid "The Last Command command sets the entry to contain the last command entered - the same as pressing up in a shell" +msgstr "Каманда Апошняя Каманда вяртае ў поле апошнюю каманду, гэтаксама ж, як у каманднай абалонцы націсканне кнопкі Ўверх" + +#: src/fe-gtk/fkeys.c:171 +msgid "The Next Command command sets the entry to contain the next command entered - the same as pressing down in a shell" +msgstr "Каманда Наступная Каманда вяртае ў поле наступную каманду, гэтаксама ж, як у каманднай абалонцы націсканне кнопкі Ўніз" + +#: src/fe-gtk/fkeys.c:173 +msgid "This command changes the text in the entry to finish an incomplete nickname or command. If Data 1 is set then double-tabbing in a string will select the last nick, not the next" +msgstr "Гэта каманда змяняе тэкст у полі для дапаўнення нескончанай мянушкі ці каманы. Калі Данні 1 усталяваныя, двайны націск табуляцыі выбярэ не наступную, а апошнюю мянушку" + +#: src/fe-gtk/fkeys.c:175 +msgid "This command scrolls up and down through the list of nicks. If Data 1 is set to anything it will scroll up, else it scrolls down" +msgstr "Гэта каманда пракручвае ўніз і ўверх спіс карыстальнікаў. Калі Данні 1 усталяваны, будзе пракрутка ўверх, інакш - уніз" + +#: src/fe-gtk/fkeys.c:177 +msgid "This command checks the last word entered in the entry against the replace list and replaces it if it finds a match" +msgstr "Гэта каманда правярае апошняе ўведзенае слова ў спіс заменаў і замяняе ў выпадку знаходжання адпаведнасці" + +#: src/fe-gtk/fkeys.c:179 +msgid "This command moves the front tab left by one" +msgstr "Гэта каманда перамяшчае пярэднюю ўкладку на адну пазіцыю ўлева" + +#: src/fe-gtk/fkeys.c:181 +msgid "This command moves the front tab right by one" +msgstr "Гэта каманда перамяшчае пярэднюю ўкладку на адну пазіцыю ўправа" + +#: src/fe-gtk/fkeys.c:183 +msgid "This command moves the current tab family to the left" +msgstr "Гэта каманда перамяшчае бягучую групу ўкладак на адну пазіцыю ўлева" + +#: src/fe-gtk/fkeys.c:185 +msgid "This command moves the current tab family to the right" +msgstr "Гэта каманда перамяшчае бягучую групу ўкладак на адну пазіцыю ўправа" + +#: src/fe-gtk/fkeys.c:187 +msgid "Push input line into history but doesn't send to server" +msgstr "Запісаць радок у журнал, але не дасылаць да сервера" + +#: src/fe-gtk/fkeys.c:198 +msgid "There was an error loading key bindings configuration" +msgstr "Памылка загрузкі наладак камбінацыяў клавішаў" + +#: src/fe-gtk/fkeys.c:450 src/fe-gtk/fkeys.c:451 src/fe-gtk/fkeys.c:452 +#: src/fe-gtk/fkeys.c:453 src/fe-gtk/fkeys.c:743 src/fe-gtk/fkeys.c:749 +#: src/fe-gtk/fkeys.c:754 src/fe-gtk/maingui.c:1375 src/fe-gtk/maingui.c:1478 +#: src/fe-gtk/maingui.c:2938 +msgid "<none>" +msgstr "<ніякі>" + +#: src/fe-gtk/fkeys.c:707 +msgid "Mod" +msgstr "Мад" + +#: src/fe-gtk/fkeys.c:708 src/fe-gtk/fkeys.c:803 +msgid "Key" +msgstr "Клавіша" + +#: src/fe-gtk/fkeys.c:709 +msgid "Action" +msgstr "Дзеянне" + +#: src/fe-gtk/fkeys.c:718 +msgid "XChat: Keyboard Shortcuts" +msgstr "XChat: Камбінацыі клавішаў" + +#: src/fe-gtk/fkeys.c:796 +msgid "Shift" +msgstr "Shift" + +#: src/fe-gtk/fkeys.c:798 +msgid "Alt" +msgstr "Alt" + +#: src/fe-gtk/fkeys.c:800 +msgid "Ctrl" +msgstr "Ctrl" + +#: src/fe-gtk/fkeys.c:807 +msgid "Data 1" +msgstr "Данні 1" + +#: src/fe-gtk/fkeys.c:810 +msgid "Data 2" +msgstr "Данні 2" + +#: src/fe-gtk/fkeys.c:852 +msgid "Error opening keys config file\n" +msgstr "Памылка адкрыцця файла наладак клавішаў\n" + +#: src/fe-gtk/fkeys.c:1019 +#, c-format +msgid "" +"Unknown keyname %s in key bindings config file\n" +"Load aborted, please fix %s/keybindings.conf\n" +msgstr "" +"Невядомая назва клавішы %s у файле наладак клавішаў\n" +"Загрузка перарвана, выпраўце %s/keybindings.conf\n" + +#: src/fe-gtk/fkeys.c:1057 +#, c-format +msgid "" +"Unknown action %s in key bindings config file\n" +"Load aborted, Please fix %s/keybindings\n" +msgstr "" +"Невядомае дзеянне %s у файле наладак клавішаў\n" +"Загрузка перарвана, выпраўце %s/keybindings\n" + +#: src/fe-gtk/fkeys.c:1078 +#, c-format +msgid "" +"Expecting Data line (beginning Dx{:|!}) but got:\n" +"%s\n" +"\n" +"Load aborted, Please fix %s/keybindings\n" +msgstr "" +"Чакаўся радок данніх (пачатак Dx{:|!}) , але атрымана:\n" +"%s\n" +"\n" +"Загрузка перарвана, выпраўце %s/keybindings\n" + +#: src/fe-gtk/fkeys.c:1147 +#, c-format +msgid "" +"Key bindings config file is corrupt, load aborted\n" +"Please fix %s/keybindings.conf\n" +msgstr "" +"Файл наладак клавішаў пашкоджаны, загрузка перарвана\n" +"Выпраўце %s/keybindings\n" + +#: src/fe-gtk/gtkutil.c:117 +msgid "Cannot write to that file." +msgstr "Немагчыма запісаць у гэты файл" + +#: src/fe-gtk/gtkutil.c:119 +msgid "Cannot read that file." +msgstr "Немагчыма прачытаць гэты файл" + +#: src/fe-gtk/ignoregui.c:117 src/fe-gtk/ignoregui.c:263 +msgid "That mask already exists." +msgstr "Гэта маска ўжо існуе" + +#: src/fe-gtk/ignoregui.c:177 src/fe-gtk/maingui.c:1949 +msgid "Private" +msgstr "Асабісты" + +#: src/fe-gtk/ignoregui.c:178 +msgid "Notice" +msgstr "Абвяшчэнне" + +#: src/fe-gtk/ignoregui.c:179 +msgid "CTCP" +msgstr "CTCP" + +#: src/fe-gtk/ignoregui.c:180 +msgid "DCC" +msgstr "DCC" + +#: src/fe-gtk/ignoregui.c:181 +msgid "Invite" +msgstr "Запрашэнне" + +#: src/fe-gtk/ignoregui.c:182 +msgid "Unignore" +msgstr "Не ігнараваць" + +#: src/fe-gtk/ignoregui.c:307 +msgid "Enter mask to ignore:" +msgstr "Увядзіце маску для ігнаравання:" + +#: src/fe-gtk/ignoregui.c:354 +msgid "XChat: Ignore list" +msgstr "XChat: Спіс ігнараванняў" + +#: src/fe-gtk/ignoregui.c:361 +msgid "Ignore Stats:" +msgstr "Статыстыка ігнараванняў:" + +#: src/fe-gtk/ignoregui.c:369 +msgid "Channel:" +msgstr "Канал:" + +#: src/fe-gtk/ignoregui.c:370 +msgid "Private:" +msgstr "Асабісты:" + +#: src/fe-gtk/ignoregui.c:371 +msgid "Notice:" +msgstr "Абвяшчэнне:" + +#: src/fe-gtk/ignoregui.c:372 +msgid "CTCP:" +msgstr "CTCP:" + +#: src/fe-gtk/ignoregui.c:373 +msgid "Invite:" +msgstr "Запрашэнне:" + +#: src/fe-gtk/ignoregui.c:384 src/fe-gtk/notifygui.c:420 +msgid "Add..." +msgstr "Дадаць..." + +#: src/fe-gtk/joind.c:83 +msgid "Channel name too short, try again." +msgstr "Імя канала занадта кароткае, паспрабуйце зноў." + +#: src/fe-gtk/joind.c:125 +msgid "XChat: Connection Complete" +msgstr "XChat: Злучэнне выканана" + +#: src/fe-gtk/joind.c:150 +#, c-format +msgid "Connection to %s complete." +msgstr "Злучэнне з %s выканана." + +#: src/fe-gtk/joind.c:159 +msgid "In the Server-List window, no channel (chat room) has been entered to be automatically joined for this network." +msgstr "У акне спіса сервераў ніводнага канала (пакоя размовы) не было ўведзена для аўтаматычнага ўваходу для гэтага сеціва." + +#: src/fe-gtk/joind.c:165 +msgid "What would you like to do next?" +msgstr "Што вы маеце рабіць наступным?" + +#: src/fe-gtk/joind.c:170 +msgid "_Nothing, I'll join a channel later." +msgstr "_Нічога, Я ўвайду на канал пазней." + +#: src/fe-gtk/joind.c:179 +msgid "_Join this channel:" +msgstr "_Увайсці на канал:" + +#: src/fe-gtk/joind.c:191 +msgid "If you know the name of the channel you want to join, enter it here." +msgstr "Калі вы ведаеце імя канала для ўваходу, увядзіце яго тут." + +#: src/fe-gtk/joind.c:198 +msgid "O_pen the Channel-List window." +msgstr "_Адкрыць акно спісу каналаў." + +#: src/fe-gtk/joind.c:205 +msgid "Retrieving the Channel-List may take a minute or two." +msgstr "Атрыманне спісу каналаў патрабуе хвіліну ці дзве." + +#: src/fe-gtk/joind.c:212 +msgid "_Always show this dialog after connecting." +msgstr "_Заўсёды паказваць гэты дыялог пасля злучэння." + +#: src/fe-gtk/maingui.c:483 +msgid "Dialog with" +msgstr "Дыялог з" + +#: src/fe-gtk/maingui.c:768 +#, c-format +msgid "Topic for %s is: %s" +msgstr "Тэма для %s : %s" + +#: src/fe-gtk/maingui.c:773 +msgid "No topic is set" +msgstr "Ніякай тэмы не ўсталявана" + +#: src/fe-gtk/maingui.c:1072 +#, c-format +msgid "This server still has %d channels or dialogs associated with it. Close them all?" +msgstr "Гэты сервер мае %d адкрытых каналаў ці дыялогаў. Ці закрыць іх усе?" + +#: src/fe-gtk/maingui.c:1151 +msgid "No other tabs open, quit xchat?" +msgstr "Усе ўкладкі закрытыя, выйсці з xchat?" + +#: src/fe-gtk/maingui.c:1326 +msgid "Insert Attribute or Color Code" +msgstr "Пакіньце ўласцівасць ці код колеру" + +#: src/fe-gtk/maingui.c:1328 +msgid "<b>Bold</b>" +msgstr "<b>Тлусты</b>" + +#: src/fe-gtk/maingui.c:1329 +msgid "<u>Underline</u>" +msgstr "<u>Падкрэслены</u>" + +#: src/fe-gtk/maingui.c:1331 +msgid "Normal" +msgstr "Звычайны" + +#: src/fe-gtk/maingui.c:1333 +msgid "Colors 0-7" +msgstr "Колеры 0-7" + +#: src/fe-gtk/maingui.c:1343 +msgid "Colors 8-15" +msgstr "Колеры 8-15" + +#: src/fe-gtk/maingui.c:1388 +msgid "Beep on message" +msgstr "Гукавы сігнал пры паведамлення" + +#: src/fe-gtk/maingui.c:1391 +msgid "Blink tray on message" +msgstr "Мірганне ў сподку пры паведамленні" + +#: src/fe-gtk/maingui.c:1394 +msgid "Show join/part messages" +msgstr "Паказваць паведамленні аб уваходзе/выхадзе" + +#: src/fe-gtk/maingui.c:1396 +msgid "Color paste" +msgstr "Колер" + +#: src/fe-gtk/maingui.c:1406 src/fe-gtk/menu.c:1906 +msgid "_Close Tab" +msgstr "Закрыць укладку" + +#: src/fe-gtk/maingui.c:1408 src/fe-gtk/menu.c:1905 +msgid "_Detach Tab" +msgstr "Адлучыць укладку" + +#: src/fe-gtk/maingui.c:1649 +msgid "Some file transfers still active, quit xchat?" +msgstr "Некаторыя перадачы файлаў актыўныя, выйсці з xchat?" + +#: src/fe-gtk/maingui.c:1817 src/fe-gtk/maingui.c:1923 +msgid "User limit must be a number!\n" +msgstr "Абмежаванне карыстальніка павінна быць лічбай!\n" + +#: src/fe-gtk/maingui.c:1945 +msgid "Topic Protection" +msgstr "Ахова тэмы" + +#: src/fe-gtk/maingui.c:1946 +msgid "No outside messages" +msgstr "Няма вонкавых паведамленняў" + +#: src/fe-gtk/maingui.c:1947 +msgid "Secret" +msgstr "Сакрэт" + +#: src/fe-gtk/maingui.c:1948 +msgid "Invite Only" +msgstr "Толькі па запрашэннях" + +#: src/fe-gtk/maingui.c:1950 +msgid "Moderated" +msgstr "Мадэраваны" + +#: src/fe-gtk/maingui.c:1951 +msgid "Ban List" +msgstr "Спіс забарон" + +#: src/fe-gtk/maingui.c:1953 +msgid "Keyword" +msgstr "Ключавое слова" + +#: src/fe-gtk/maingui.c:1965 +msgid "User Limit" +msgstr "Абмежаванне карыстальніка" + +#: src/fe-gtk/maingui.c:2076 +msgid "Show/Hide userlist" +msgstr "Паказаць/Схаваць спіс карыстальнікаў" + +#: src/fe-gtk/maingui.c:2201 +msgid "" +"Unable to set transparent background!\n" +"\n" +"You may be using a non-compliant window\n" +"manager that is not currently supported.\n" +msgstr "" +"Немагчыма ўсталяваць празрысты фон!\n" +"\n" +"Пэўна, выкарыстоўваецца несумяшчальны мэнэджэр акон\n" + +#: src/fe-gtk/maingui.c:2433 +msgid "Enter new nickname:" +msgstr "Увядзіце новую мянушку:" + +#: src/fe-gtk/menu.c:124 +msgid "Host unknown" +msgstr "Вузел невядомы" + +#: src/fe-gtk/menu.c:541 +#, c-format +msgid "<tt><b>%-11s</b></tt> %s" +msgstr "<tt><b>%-11s</b></tt> %s" + +#: src/fe-gtk/menu.c:546 src/fe-gtk/menu.c:550 +msgid "Real Name:" +msgstr "Сапраўднае імя:" + +#: src/fe-gtk/menu.c:554 +msgid "User:" +msgstr "Карыстальнік:" + +#: src/fe-gtk/menu.c:558 +msgid "Country:" +msgstr "Краіна:" + +#: src/fe-gtk/menu.c:562 +msgid "Server:" +msgstr "Сервер:" + +#: src/fe-gtk/menu.c:574 +msgid "Away Msg:" +msgstr "Паведамленне адыходу:" + +#: src/fe-gtk/menu.c:584 +#, c-format +msgid "%u minutes ago" +msgstr "%u хвілін таму" + +#: src/fe-gtk/menu.c:586 src/fe-gtk/menu.c:589 +msgid "Last Msg:" +msgstr "Апошняе паведамленне:" + +#: src/fe-gtk/menu.c:690 +msgid "The Menubar is now hidden. You can show it again by pressing F9 or right-clicking in a blank part of the main text area." +msgstr "Меню зараз схована. Яно вернецца, калі націснеце F9 ці шчоўкнеце правай кнопкай мышы на свабоднай прасторы тэкставага акна." + +#: src/fe-gtk/menu.c:777 +msgid "Open Link in Browser" +msgstr "Адкрыць спасылку ў браўзеры" + +#: src/fe-gtk/menu.c:778 +msgid "Copy Selected Link" +msgstr "Капіяваць пазначаную спасылку" + +#: src/fe-gtk/menu.c:835 src/fe-gtk/menu.c:1066 +msgid "Join Channel" +msgstr "Увайсці на канал" + +#: src/fe-gtk/menu.c:839 +msgid "Part Channel" +msgstr "Выйсці з канала" + +#: src/fe-gtk/menu.c:841 +msgid "Cycle Channel" +msgstr "Каналы па кругу" + +#: src/fe-gtk/menu.c:864 +msgid "XChat: User menu" +msgstr "XChat: Меню карыстальніка" + +#: src/fe-gtk/menu.c:873 +msgid "Edit This Menu..." +msgstr "Рэдагаваць гэтае меню..." + +#: src/fe-gtk/menu.c:1068 +msgid "Retrieve channel list..." +msgstr "Атрымаць спіс каналаў..." + +#: src/fe-gtk/menu.c:1136 +msgid "" +"User Commands - Special codes:\n" +"\n" +"%c = current channel\n" +"%e = current network name\n" +"%m = machine info\n" +"%n = your nick\n" +"%t = time/date\n" +"%v = xchat version\n" +"%2 = word 2\n" +"%3 = word 3\n" +"&2 = word 2 to the end of line\n" +"&3 = word 3 to the end of line\n" +"\n" +"eg:\n" +"/cmd john hello\n" +"\n" +"%2 would be \"john\"\n" +"&2 would be \"john hello\"." +msgstr "" +"Каманды карыстальніка - Спецыянальныя кады:\n" +"\n" +"%c = бягучы канал\n" +"%m = інфармацыя пра машыну\n" +"%n = ваша мянушка\n" +"%t = час/дата\n" +"%v = версія xchat\n" +"%2 = слова 2\n" +"%3 = слова 3\n" +"&2 = слова 2 ад канцу радка\n" +"&3 = слова 3 ад канцу радка\n" +"\n" +"напрыклад:\n" +"/cmd john hello\n" +"\n" +"%2 будзе \"john\"\n" +"&2 будзе \"john hello\"." + +#: src/fe-gtk/menu.c:1152 +msgid "" +"Userlist Buttons - Special codes:\n" +"\n" +"%a = all selected nicks\n" +"%c = current channel\n" +"%e = current network name\n" +"%h = selected nick's hostname\n" +"%m = machine info\n" +"%n = your nick\n" +"%s = selected nick\n" +"%t = time/date\n" +msgstr "" +"Кнопкі спісу карыстальнікаў- Спецыяльныя кады:\n" +"\n" +"%a = усе пазначаныя мянушкі\n" +"%c = бягучы канал\n" +"%h = назва вузла пазначанай мянушкі\n" +"%e = назва бягучага сеціва\n" +"%m = інфармацыя пра машыну\n" +"%n = ваша мянушка\n" +"%s = пазначаная мянушка\n" +"%t = час/дата\n" + +#: src/fe-gtk/menu.c:1162 +msgid "" +"Dialog Buttons - Special codes:\n" +"\n" +"%a = all selected nicks\n" +"%c = current channel\n" +"%e = current network name\n" +"%h = selected nick's hostname\n" +"%m = machine info\n" +"%n = your nick\n" +"%s = selected nick\n" +"%t = time/date\n" +msgstr "" +"Кнопкі дыялогу - Спецыяльныя кады:\n" +"\n" +"%a = усе пазначаныя мянушкі\n" +"%c = бягучы канал\n" +"%e = назва бягучага сеціва\n" +"%h = назва вузла пазначанай мянушкі\n" +"%m = інфармацыя пра машыну\n" +"%n = ваша мянушка\n" +"%s = пазначаная мянушка\n" +"%t = час/дата\n" + +#: src/fe-gtk/menu.c:1172 +msgid "" +"CTCP Replies - Special codes:\n" +"\n" +"%d = data (the whole ctcp)\n" +"%e = current network name\n" +"%m = machine info\n" +"%s = nick who sent the ctcp\n" +"%t = time/date\n" +"%2 = word 2\n" +"%3 = word 3\n" +"&2 = word 2 to the end of line\n" +"&3 = word 3 to the end of line\n" +"\n" +msgstr "" +"Адказы CTCP - Спецыянальныя кады::\n" +"\n" +"%d = данні (ctcp цалкам)\n" +"%e = назва бягучага сеціва\n" +"%m = інфармацыя пра машыну\n" +"%s = мянушка таго, хто даслаў ctcp\n" +"%t = час/дата\n" +"%2 = слова 2\n" +"%3 = слова 3\n" +"&2 = слова 2 ад канцу радка\n" +"&3 = слова 3 ад канцу радка\n" +"\n" + +#: src/fe-gtk/menu.c:1183 +#, c-format +msgid "" +"URL Handlers - Special codes:\n" +"\n" +"%s = the URL string\n" +"\n" +"Putting a ! infront of the command\n" +"indicates it should be sent to a\n" +"shell instead of XChat" +msgstr "" +"Апрацоўшчыкі URL - Спецыяльныя кады:\n" +"\n" +"%s = радок URL\n" +"\n" +"Змяшчэнне ! (клічніка) наперадзе каманды\n" +"азначае, што яе будзе апрацоўваць камандная\n" +"абалонка, а не XChat" + +#: src/fe-gtk/menu.c:1192 +msgid "XChat: User Defined Commands" +msgstr "XChat: Вызначаныя карыстальнікам каманды" + +#: src/fe-gtk/menu.c:1199 +msgid "XChat: Userlist Popup menu" +msgstr "XChat: Кантэкстнае меню спісу карыстальнікаў" + +#: src/fe-gtk/menu.c:1206 +msgid "Replace with" +msgstr "Замяніць" + +#: src/fe-gtk/menu.c:1206 +msgid "XChat: Replace" +msgstr "XChat: Замена" + +#: src/fe-gtk/menu.c:1213 +msgid "XChat: URL Handlers" +msgstr "XChat: Апрацоўчыкі URL" + +#: src/fe-gtk/menu.c:1232 +msgid "XChat: Userlist buttons" +msgstr "XChat: Кнопкі спісу карыстальнікаў" + +#: src/fe-gtk/menu.c:1239 +msgid "XChat: Dialog buttons" +msgstr "XChat: Кнопкі дыялогу" + +#: src/fe-gtk/menu.c:1246 +msgid "XChat: CTCP Replies" +msgstr "XChat: Адказы CTCP" + +#: src/fe-gtk/menu.c:1344 +msgid "_XChat" +msgstr "_XChat" + +#: src/fe-gtk/menu.c:1345 +msgid "Network Li_st..." +msgstr "Спіс _сеціў..." + +#: src/fe-gtk/menu.c:1348 +msgid "_New" +msgstr "_Новы" + +#: src/fe-gtk/menu.c:1349 +msgid "Server Tab..." +msgstr "Укладка сервера..." + +#: src/fe-gtk/menu.c:1350 +msgid "Channel Tab..." +msgstr "Укладка канала..." + +#: src/fe-gtk/menu.c:1351 +msgid "Server Window..." +msgstr "Акно сервера..." + +#: src/fe-gtk/menu.c:1352 +msgid "Channel Window..." +msgstr "Акно канала..." + +#: src/fe-gtk/menu.c:1357 src/fe-gtk/menu.c:1359 +msgid "_Load Plugin or Script..." +msgstr "Загрузіць плагін ці скрыпт..." + +#: src/fe-gtk/menu.c:1367 +msgid "_Quit" +msgstr "_Выйсці" + +#: src/fe-gtk/menu.c:1369 +msgid "_View" +msgstr "Пра_гляд" + +#: src/fe-gtk/menu.c:1371 +msgid "_Menubar" +msgstr "Меню" + +#: src/fe-gtk/menu.c:1372 +msgid "_Topicbar" +msgstr "Тэма" + +#: src/fe-gtk/menu.c:1373 +msgid "_Userlist Buttons" +msgstr "Кнопкі спісу карыстальнікаў" + +#: src/fe-gtk/menu.c:1374 +msgid "M_ode Buttons" +msgstr "Кнопкі рэжыму" + +#: src/fe-gtk/menu.c:1376 +msgid "_Layout" +msgstr "Асяроддзе" + +#: src/fe-gtk/menu.c:1378 +msgid "_Tabs" +msgstr "Укладкі" + +#: src/fe-gtk/menu.c:1379 +msgid "T_ree" +msgstr "Дрэва" + +#: src/fe-gtk/menu.c:1381 +msgid "_Network Meters" +msgstr "Вымярэнне сеціва" + +#: src/fe-gtk/menu.c:1383 +msgid "Off" +msgstr "Выкл" + +#: src/fe-gtk/menu.c:1384 +msgid "Graph" +msgstr "Графік" + +#: src/fe-gtk/menu.c:1389 +msgid "_Server" +msgstr "_Сервер" + +#: src/fe-gtk/menu.c:1390 +msgid "_Disconnect" +msgstr "_Разлучыцца" + +#: src/fe-gtk/menu.c:1391 +msgid "_Reconnect" +msgstr "_Перадалучыцца" + +#: src/fe-gtk/menu.c:1395 +msgid "Marked Away" +msgstr "Пазначыць як \"Адыйшоў\"" + +#: src/fe-gtk/menu.c:1397 +msgid "_Usermenu" +msgstr "_Меню карыстальніка" + +#: src/fe-gtk/menu.c:1399 +msgid "S_ettings" +msgstr "Наладкі" + +#: src/fe-gtk/menu.c:1400 +msgid "_Preferences" +msgstr "_Асаблівасці" + +#: src/fe-gtk/menu.c:1402 +msgid "Advanced" +msgstr "Адмысловыя" + +#: src/fe-gtk/menu.c:1403 +msgid "Auto Replace..." +msgstr "Аўтазамена..." + +#: src/fe-gtk/menu.c:1404 +msgid "CTCP Replies..." +msgstr "Адказы CTCP..." + +#: src/fe-gtk/menu.c:1405 +msgid "Dialog Buttons..." +msgstr "Кнопкі дыялогаў..." + +#: src/fe-gtk/menu.c:1406 +msgid "Keyboard Shortcuts..." +msgstr "Камбінацыі клавішаў..." + +#: src/fe-gtk/menu.c:1407 +msgid "Text Events..." +msgstr "Тэксты падзеяў..." + +#: src/fe-gtk/menu.c:1408 +msgid "URL Handlers..." +msgstr "Апрацоўшчыкі URL..." + +#: src/fe-gtk/menu.c:1409 +msgid "User Commands..." +msgstr "Каманды карыстальніка..." + +#: src/fe-gtk/menu.c:1410 +msgid "Userlist Buttons..." +msgstr "Кнопкі спісу карыстальнікаў..." + +#: src/fe-gtk/menu.c:1411 +msgid "Userlist Popup..." +msgstr "Меню спісу карыстальнікаў..." + +#: src/fe-gtk/menu.c:1414 +msgid "_Window" +msgstr "Акно" + +#: src/fe-gtk/menu.c:1415 +msgid "Ban List..." +msgstr "Спіс забароненых..." + +#: src/fe-gtk/menu.c:1416 +msgid "Channel List..." +msgstr "Спіс каналаў..." + +#: src/fe-gtk/menu.c:1417 +msgid "Character Chart..." +msgstr "Палітра літараў..." + +#: src/fe-gtk/menu.c:1418 +msgid "Direct Chat..." +msgstr "Прамыя размовы..." + +#: src/fe-gtk/menu.c:1419 +msgid "File Transfers..." +msgstr "Абмен файламі..." + +#: src/fe-gtk/menu.c:1420 +msgid "Ignore List..." +msgstr "Спіс ігнараванняў.." + +#: src/fe-gtk/menu.c:1421 +msgid "Notify List..." +msgstr "Спіс абвяшчэнняў..." + +#: src/fe-gtk/menu.c:1422 +msgid "Plugins and Scripts..." +msgstr "Плагіны і скрыпты..." + +#: src/fe-gtk/menu.c:1423 +msgid "Raw Log..." +msgstr "Журнал падзеяў..." + +#: src/fe-gtk/menu.c:1424 +msgid "URL Grabber..." +msgstr "Зборшчык URL..." + +#: src/fe-gtk/menu.c:1426 +msgid "Reset Marker Line" +msgstr "Скінуць маркер" + +#: src/fe-gtk/menu.c:1427 +msgid "C_lear Text" +msgstr "А_чысціць тэкст" + +#: src/fe-gtk/menu.c:1428 +msgid "Search Text..." +msgstr "Шукаць тэкст..." + +#: src/fe-gtk/menu.c:1429 +msgid "Save Text..." +msgstr "Захаваць тэкст" + +#: src/fe-gtk/menu.c:1431 src/fe-gtk/menu.c:1897 +msgid "_Help" +msgstr "_Дапамога" + +#: src/fe-gtk/menu.c:1432 +msgid "_Contents" +msgstr "_Змест" + +#: src/fe-gtk/menu.c:1433 +msgid "_About" +msgstr "Аб праграме" + +#: src/fe-gtk/menu.c:1910 +msgid "_Attach Window" +msgstr "_Далучыць акно" + +#: src/fe-gtk/menu.c:1911 +msgid "_Close Window" +msgstr "_Закрыць акно" + +#: src/fe-gtk/notifygui.c:137 +msgid "User" +msgstr "Карыстальнік" + +#: src/fe-gtk/notifygui.c:140 +msgid "Last Seen" +msgstr "Апошні прагляд" + +#: src/fe-gtk/notifygui.c:181 +msgid "Offline" +msgstr "Разлучаны" + +#: src/fe-gtk/notifygui.c:201 src/fe-gtk/setup.c:216 +msgid "Never" +msgstr "Ніколі" + +#: src/fe-gtk/notifygui.c:204 src/fe-gtk/notifygui.c:229 +#, c-format +msgid "%d minutes ago" +msgstr "%d хвілін таму" + +#: src/fe-gtk/notifygui.c:219 +msgid "Online" +msgstr "Злучаны" + +#: src/fe-gtk/notifygui.c:348 +msgid "Enter nickname to add:" +msgstr "Увядзіце мянушку:" + +#: src/fe-gtk/notifygui.c:376 +msgid "Notify on these networks:" +msgstr "Абвяшчаць у гэтых сецівах:" + +#: src/fe-gtk/notifygui.c:387 +msgid "Comma separated list of networks is accepted." +msgstr "Прымаецца спіс сеціваў, падзеленых коскамі." + +#: src/fe-gtk/notifygui.c:407 +msgid "XChat: Notify List" +msgstr "XChat: спіс абвяшчэнняў" + +#: src/fe-gtk/notifygui.c:424 +msgid "Remove" +msgstr "Выдаліць" + +#: src/fe-gtk/notifygui.c:428 +msgid "Open Dialog" +msgstr "Пачаць дыялог" + +#: src/fe-gtk/plugin-tray.c:155 +msgid "" +"Cannot find 'notify-send' to open balloon alerts.\n" +"Please install libnotify." +msgstr "" +"Адсутнічае 'notify-send' для адкрыцця балёнікавых выплыўных паведамленняў.\n" +"Калі ласка, устанавіце libnotify." + +#: src/fe-gtk/plugin-tray.c:206 +#, c-format +msgid "XChat: Connected to %u networks and %u channels" +msgstr "XChat: злучана з %u сецівамі і %u каналамі" + +#: src/fe-gtk/plugin-tray.c:400 +#, c-format +msgid "" +"You are connected to <b>%u</b> IRC networks.\n" +"Are you sure you want to quit?" +msgstr "" +"Вы злучаны з <b>%u</b> сецівамі IRC.\n" +"Ці ўпэўнены, што хочаце выйсці?" + +#: src/fe-gtk/plugin-tray.c:454 +msgid "_Restore" +msgstr "_Вярнуць" + +#: src/fe-gtk/plugin-tray.c:456 +msgid "_Hide" +msgstr "С_хаваць" + +#: src/fe-gtk/plugin-tray.c:459 +msgid "_Blink on" +msgstr "_Міргаць пры" + +#: src/fe-gtk/plugin-tray.c:460 src/fe-gtk/setup.c:445 +msgid "Channel Message" +msgstr "Канальным паведамленні" + +#: src/fe-gtk/plugin-tray.c:461 src/fe-gtk/setup.c:446 +msgid "Private Message" +msgstr "Асабістым паведамленні" + +#: src/fe-gtk/plugin-tray.c:462 src/fe-gtk/setup.c:447 +msgid "Highlighted Message" +msgstr "Падсвечаным паведамленні" + +#: src/fe-gtk/plugin-tray.c:466 +msgid "Quit..." +msgstr "Выхад..." + +#: src/fe-gtk/plugin-tray.c:510 src/fe-gtk/plugin-tray.c:518 +#, c-format +msgid "XChat: Highlighed message from: %s (%s)" +msgstr "XChat: Падсвечанае паведамленне ад: %s (%s)" + +#: src/fe-gtk/plugin-tray.c:513 +#, c-format +msgid "XChat: %u highlighted messages, latest from: %s (%s)" +msgstr "XChat: %u падсвечаных паведамленняў, апошняе ад: %s (%s)" + +#: src/fe-gtk/plugin-tray.c:536 src/fe-gtk/plugin-tray.c:543 +#, c-format +msgid "XChat: New public message from: %s (%s)" +msgstr "XChat: Новае агульнае паведамленне ад: %s (%s)" + +#: src/fe-gtk/plugin-tray.c:539 +#, c-format +msgid "XChat: %u new public messages." +msgstr "XChat: %u новых агульных паведамленняў." + +#: src/fe-gtk/plugin-tray.c:562 src/fe-gtk/plugin-tray.c:569 +#, c-format +msgid "XChat: Private message from: %s (%s)" +msgstr "XChat: Асабістае паведамленне ад: %s (%s)" + +#: src/fe-gtk/plugin-tray.c:565 +#, c-format +msgid "XChat: %u private messages, latest from: %s (%s)" +msgstr "XChat: %u асабістых паведамленняў, апошняе ад: %s (%s)" + +#: src/fe-gtk/plugin-tray.c:615 src/fe-gtk/plugin-tray.c:623 +#, c-format +msgid "XChat: File offer from: %s (%s)" +msgstr "XChat: прапанова файла ад: %s (%s)" + +#: src/fe-gtk/plugin-tray.c:618 +#, c-format +msgid "XChat: %u file offers, latest from: %s (%s)" +msgstr "XChat: %u прапаноў файлаў, апошняя ад: %s (%s)" + +#: src/fe-gtk/plugingui.c:76 src/fe-gtk/textgui.c:421 +msgid "Description" +msgstr "Апісанне" + +#: src/fe-gtk/plugingui.c:151 +msgid "Select a Plugin or Script to load" +msgstr "Выберыце плагін ці скрыпт для загрузкі" + +#: src/fe-gtk/plugingui.c:223 +msgid "XChat: Plugins and Scripts" +msgstr "XChat: плагіны і скрыпты" + +#: src/fe-gtk/plugingui.c:229 +msgid "_Load..." +msgstr "_Загрузіць" + +#: src/fe-gtk/plugingui.c:232 +msgid "_UnLoad" +msgstr "_Выгрузіць" + +#: src/fe-gtk/plugingui.c:236 src/fe-gtk/search.c:144 +msgid "_Close" +msgstr "_Закрыць" + +#: src/fe-gtk/rawlog.c:81 src/fe-gtk/rawlog.c:130 src/fe-gtk/textgui.c:435 +#: src/fe-gtk/urlgrab.c:205 +msgid "Save As..." +msgstr "Захаваць як..." + +#: src/fe-gtk/rawlog.c:97 +#, c-format +msgid "XChat: Rawlog (%s)" +msgstr "XChat: Журнал (%s)" + +#: src/fe-gtk/rawlog.c:127 +msgid "Clear rawlog" +msgstr "Ачысціць журнал" + +#: src/fe-gtk/search.c:57 +msgid "The window you opened this Search for doesn't exist anymore." +msgstr "Адкрытае вамі акно пошуку болей не існуе." + +#: src/fe-gtk/search.c:65 +msgid "Search hit end, not found." +msgstr "Пошук дасягнуў канца, не знойдзена." + +#: src/fe-gtk/search.c:109 +msgid "XChat: Search" +msgstr "XChat: Пошук" + +#: src/fe-gtk/search.c:127 +msgid "_Match case" +msgstr "_Улічваць рэгістр" + +#: src/fe-gtk/search.c:133 +msgid "Search _backwards" +msgstr "Пошук _назад" + +#: src/fe-gtk/search.c:146 +msgid "_Find" +msgstr "_Знайсці" + +#: src/fe-gtk/servlistgui.c:170 src/fe-gtk/servlistgui.c:269 +msgid "New Network" +msgstr "Новае сеціва" + +#: src/fe-gtk/servlistgui.c:554 +#, c-format +msgid "Really remove network \"%s\" and all its servers?" +msgstr "Сапраўды выдаліць сеціва \"%s\" і ўсе яго серверы?" + +#: src/fe-gtk/servlistgui.c:678 +msgid "User name and Real name cannot be left blank." +msgstr "Імя карыстальніка і сапраўднае імя не могуць быць пустымі." + +#: src/fe-gtk/servlistgui.c:978 +#, c-format +msgid "XChat: Edit %s" +msgstr "XChat: Рэдагаваць %s" + +#: src/fe-gtk/servlistgui.c:997 +#, c-format +msgid "Servers for %s" +msgstr "Сервера для %s" + +#: src/fe-gtk/servlistgui.c:1008 +msgid "Connect to selected server only" +msgstr "Злучацца толькі з абранымі серверамі" + +#: src/fe-gtk/servlistgui.c:1009 +msgid "Don't cycle through all the servers when the connection fails." +msgstr "Не зацыклівацца на серверах, калі злучэнні абрываюцца" + +#: src/fe-gtk/servlistgui.c:1011 +msgid "Your Details" +msgstr "Падрабязнасці" + +#: src/fe-gtk/servlistgui.c:1017 +msgid "Use global user information" +msgstr "Выкарыстоўваць глабальная звесткі" + +#: src/fe-gtk/servlistgui.c:1020 src/fe-gtk/servlistgui.c:1252 +msgid "_Nick name:" +msgstr "_Мянушка" + +#: src/fe-gtk/servlistgui.c:1024 src/fe-gtk/servlistgui.c:1259 +msgid "Second choice:" +msgstr "Другі выбар" + +#: src/fe-gtk/servlistgui.c:1028 src/fe-gtk/servlistgui.c:1273 +msgid "_User name:" +msgstr "_Імя карыстальніка" + +#: src/fe-gtk/servlistgui.c:1032 src/fe-gtk/servlistgui.c:1280 +msgid "Rea_l name:" +msgstr "Сапраўднае _імя" + +#: src/fe-gtk/servlistgui.c:1035 +msgid "Connecting" +msgstr "Злучэнне" + +#: src/fe-gtk/servlistgui.c:1041 +msgid "Auto connect to this network at startup" +msgstr "Аўтаматычна злучацца з гэтым серверам пры старце" + +#: src/fe-gtk/servlistgui.c:1043 +msgid "Use a proxy server" +msgstr "Выкарыстоўваць проксі" + +#: src/fe-gtk/servlistgui.c:1045 +msgid "Use SSL for all the servers on this network" +msgstr "Ужываць SSL для ўсіх сервераў у гэтым сеціве" + +#: src/fe-gtk/servlistgui.c:1050 +msgid "Accept invalid SSL certificate" +msgstr "Прымаць несапраўдны SSL-сертыфікат" + +#: src/fe-gtk/servlistgui.c:1056 +msgid "C_hannels to join:" +msgstr "Каналы для ўваходу:" + +#: src/fe-gtk/servlistgui.c:1058 +msgid "Channels to join, separated by commas, but not spaces!" +msgstr "Каналы для ўваходу, падзеленыя коскамі, але не прагаламі!" + +#: src/fe-gtk/servlistgui.c:1061 +msgid "Connect command:" +msgstr "Каманда злучэння" + +#: src/fe-gtk/servlistgui.c:1063 +msgid "Extra command to execute after connecting. If you need more than one, set this to LOAD -e <filename>, where <filename> is a text-file full of commands to execute." +msgstr "Дадатковыя каманды для выканання пасля злучэння. Калі патрэбна больш за адну, прапішыце LOAD -e <файл>, дзе <файл> гэта тэкставы файл з камандамі." + +#: src/fe-gtk/servlistgui.c:1066 +msgid "Nickserv password:" +msgstr "Пароль для Nickserv:" + +#: src/fe-gtk/servlistgui.c:1068 +msgid "If your nickname requires a password, enter it here. Not all IRC networks support this." +msgstr "Калі ваша мянушка патрабуе пароль, вы можаце ўвесці яго тут. Не ўсе сецівы IRC падтрымліваюць гэта" + +#: src/fe-gtk/servlistgui.c:1072 +msgid "Server password:" +msgstr "Пароль сервера:" + +#: src/fe-gtk/servlistgui.c:1074 +msgid "Password for the server, if in doubt, leave blank." +msgstr "Пароль для сервера, калі сумняваецеся, пакіньце пустым." + +#: src/fe-gtk/servlistgui.c:1077 +msgid "Character set:" +msgstr "Знаказбор:" + +#: src/fe-gtk/servlistgui.c:1147 +msgid "_Edit" +msgstr "_Рэдагаваць" + +#: src/fe-gtk/servlistgui.c:1230 +msgid "XChat: Network List" +msgstr "XChat: спіс абвяшчэнняў" + +#: src/fe-gtk/servlistgui.c:1242 +msgid "User Information" +msgstr "Звесткі аб карыстальніку" + +#: src/fe-gtk/servlistgui.c:1266 +msgid "Third choice:" +msgstr "Трэці выбар" + +#: src/fe-gtk/servlistgui.c:1326 +msgid "Networks" +msgstr "Сецівы" + +#: src/fe-gtk/servlistgui.c:1367 +msgid "Skip network list on startup" +msgstr "Не паказваць спіс сервераў пры старце" + +#: src/fe-gtk/servlistgui.c:1399 +msgid "_Edit..." +msgstr "_Змяніць..." + +#: src/fe-gtk/servlistgui.c:1406 +msgid "_Sort" +msgstr "_Упарадкаваць" + +#: src/fe-gtk/servlistgui.c:1407 +msgid "Sorts the network list in alphabetical order. Use SHIFT-UP and SHIFT-DOWN keys to move a row." +msgstr "Упарадкоўвае спіс сеціў паводле алфавіту. Выкарыстоўвайце камбінацыі SHIFT-UP ды SHIFT-DOWN, каб зрушваць слупок." + +#: src/fe-gtk/servlistgui.c:1432 +msgid "C_onnect" +msgstr "_Злучыцца" + +#: src/fe-gtk/setup.c:102 +msgid "Text Box Appearance" +msgstr "Выгляд тэкставага акна" + +#: src/fe-gtk/setup.c:103 +msgid "Font:" +msgstr "Шрыфт:" + +#: src/fe-gtk/setup.c:104 +msgid "Background image:" +msgstr "Фонавая выява:" + +#: src/fe-gtk/setup.c:105 +msgid "Scrollback lines:" +msgstr "Лініі пракруткі:" + +#: src/fe-gtk/setup.c:106 +msgid "Colored nick names" +msgstr "Каляровыя мянушкі" + +#: src/fe-gtk/setup.c:107 +msgid "Give each person on IRC a different color" +msgstr "Пазначыць кожнай персоне розны колер" + +#: src/fe-gtk/setup.c:108 +msgid "Indent nick names" +msgstr "Рабіць водступ перад мянушкамі" + +#: src/fe-gtk/setup.c:109 +msgid "Make nick names right-justified" +msgstr "Выраўняць мянушкі па правым краі" + +#: src/fe-gtk/setup.c:110 +msgid "Transparent background" +msgstr "Празрысты фон" + +#: src/fe-gtk/setup.c:111 +msgid "Show marker line" +msgstr "Паказваць маркер" + +#: src/fe-gtk/setup.c:112 +msgid "Insert a red line after the last read text." +msgstr "Устаўляць чырвоную лінію пасля апошняга прагледжанага тэксту" + +#: src/fe-gtk/setup.c:113 +msgid "Transparency Settings" +msgstr "Параметры празрыстасці" + +#: src/fe-gtk/setup.c:114 +msgid "Red:" +msgstr "Чырвоны" + +#: src/fe-gtk/setup.c:115 +msgid "Green:" +msgstr "Зялёны" + +#: src/fe-gtk/setup.c:116 +msgid "Blue:" +msgstr "Блакітны" + +#: src/fe-gtk/setup.c:118 src/fe-gtk/setup.c:361 +msgid "Time Stamps" +msgstr "Адзнакі часу" + +#: src/fe-gtk/setup.c:119 +msgid "Enable time stamps" +msgstr "Ужываць адзнакі часу" + +#: src/fe-gtk/setup.c:120 +msgid "Time stamp format:" +msgstr "Фармат адзнакаў часу" + +#: src/fe-gtk/setup.c:121 src/fe-gtk/setup.c:364 +msgid "See strftime manpage for details." +msgstr "Глядзіце man strftime" + +#: src/fe-gtk/setup.c:128 src/fe-gtk/setup.c:168 +msgid "A-Z" +msgstr "A-Z" + +#: src/fe-gtk/setup.c:129 +msgid "Last-spoke order" +msgstr "Апошнесказаны парадак " + +#: src/fe-gtk/setup.c:135 src/fe-gtk/setup.c:1635 +msgid "Input box" +msgstr "Акно ўводу" + +#: src/fe-gtk/setup.c:136 src/fe-gtk/setup.c:179 +msgid "Use the Text box font and colors" +msgstr "Шрыфт і колер як у тэкставым акне" + +#: src/fe-gtk/setup.c:138 +msgid "Spell checking" +msgstr "Праверка правапісу" + +#: src/fe-gtk/setup.c:141 +msgid "Nick Completion" +msgstr "Дапаўненне мянушак" + +#: src/fe-gtk/setup.c:142 +msgid "Automatic nick completion (without TAB key)" +msgstr "Аўтаматычнае дапаўненне мянушак (без клавішы TAB)" + +#: src/fe-gtk/setup.c:144 +msgid "Nick completion suffix:" +msgstr "Суфікс дапаўнення мянушак" + +#: src/fe-gtk/setup.c:145 +msgid "Nick completion sorted:" +msgstr "Дапаўненне сартавана" + +#: src/fe-gtk/setup.c:148 +msgid "Input Box Codes" +msgstr "Коды ў полі ўводу" + +#: src/fe-gtk/setup.c:149 +#, c-format +msgid "Interpret %nnn as an ASCII value" +msgstr "Разумець %nnn як ASCII код" + +#: src/fe-gtk/setup.c:150 +msgid "Interpret %C, %B as Color, Bold etc" +msgstr "Разумець %C, %B як Колер, Тлусты і г.д." + +#: src/fe-gtk/setup.c:167 +msgid "A-Z, Ops first" +msgstr "A-Z, Аператары першыя" + +#: src/fe-gtk/setup.c:169 +msgid "Z-A, Ops last" +msgstr "A-Z, Аператары апошнія" + +#: src/fe-gtk/setup.c:170 +msgid "Z-A" +msgstr "Z-A" + +#: src/fe-gtk/setup.c:171 +msgid "Unsorted" +msgstr "Не сартаваць" + +#: src/fe-gtk/setup.c:177 +msgid "User List" +msgstr "Спіс карыстальнікаў" + +#: src/fe-gtk/setup.c:178 +msgid "Show hostnames in user list" +msgstr "Паказваць імёны хастоў у спісе карыстальнікаў" + +#: src/fe-gtk/setup.c:180 +msgid "Resizable user list" +msgstr "Змяняемая шырыня спіса карыстальнікаў" + +#: src/fe-gtk/setup.c:181 +msgid "User list sorted by:" +msgstr "Сартаваць спіс карыстальнікаў па:" + +#: src/fe-gtk/setup.c:183 +msgid "Away tracking" +msgstr "