From bf652ec820e0d36d841832744a1c5221a4cb8f6c Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 20 Oct 2002 12:13:28 +0000 Subject: [PATCH] Merged with Irssi CVS. --- CHANGES | 4 + apps/irssi/.cvsignore | 4 +- apps/irssi/AUTHORS | 2 +- apps/irssi/COPYING | 340 ------------------ apps/irssi/NEWS | 69 ++++ apps/irssi/README | 4 +- apps/irssi/README.cygwin | 12 + apps/irssi/autogen.sh | 18 +- apps/irssi/configure.in | 27 +- apps/irssi/docs/faq.txt | 151 +++++--- apps/irssi/docs/formats.txt | 8 +- apps/irssi/docs/manual.txt | 8 +- apps/irssi/docs/perl.txt | 16 +- apps/irssi/docs/proxy.txt | 2 +- apps/irssi/docs/signals.txt | 7 - apps/irssi/docs/special_vars.txt | 1 + apps/irssi/docs/startup-HOWTO.html | 311 ++++++++-------- apps/irssi/glib-2.0.m4_ | 212 +++++++++++ apps/irssi/glib.m4_ | 196 ++++++++++ apps/irssi/irssi-config.in | 5 +- apps/irssi/irssi.cvs | 0 apps/irssi/irssi.spec.in | 2 +- apps/irssi/src/core/Makefile.am | 7 +- apps/irssi/src/core/blob.c | 8 - apps/irssi/src/core/blob.h | 16 - apps/irssi/src/core/channel-rec.h | 1 + apps/irssi/src/core/channels-setup.c | 2 + apps/irssi/src/core/channels.c | 56 ++- apps/irssi/src/core/channels.h | 6 +- apps/irssi/src/core/chat-commands.c | 29 +- apps/irssi/src/core/chat-protocols.h | 6 +- apps/irssi/src/core/chatnets.c | 3 +- apps/irssi/src/core/commands.c | 30 +- apps/irssi/src/core/core.c | 13 +- apps/irssi/src/core/expandos.c | 31 +- apps/irssi/src/core/ignore.c | 12 +- apps/irssi/src/core/ignore.h | 6 +- apps/irssi/src/core/levels.h | 56 +-- apps/irssi/src/core/log.c | 18 +- apps/irssi/src/core/log.h | 11 +- apps/irssi/src/core/misc.c | 44 ++- apps/irssi/src/core/misc.h | 7 +- apps/irssi/src/core/modules-load.c | 24 +- apps/irssi/src/core/net-nonblock.c | 2 +- apps/irssi/src/core/network-openssl.c | 305 ++++++++++++++++ apps/irssi/src/core/network.c | 60 +++- apps/irssi/src/core/network.h | 4 + apps/irssi/src/core/queries.c | 12 + apps/irssi/src/core/query-rec.h | 1 + apps/irssi/src/core/server-connect-rec.h | 4 + apps/irssi/src/core/server-setup-rec.h | 1 + apps/irssi/src/core/servers-reconnect.c | 74 ++-- apps/irssi/src/core/servers-setup.c | 4 + apps/irssi/src/core/servers.c | 192 ++++++---- apps/irssi/src/core/servers.h | 3 + apps/irssi/src/core/session.c | 15 +- apps/irssi/src/core/settings.h | 1 - apps/irssi/src/core/window-item-rec.h | 6 +- apps/irssi/src/fe-common/core/Makefile.am | 1 + apps/irssi/src/fe-common/core/autorun.c | 2 +- .../src/fe-common/core/chat-completion.c | 180 +++++++++- .../src/fe-common/core/chat-completion.h | 6 + apps/irssi/src/fe-common/core/completion.c | 122 ++++++- apps/irssi/src/fe-common/core/fe-channels.c | 53 ++- .../irssi/src/fe-common/core/fe-common-core.c | 10 +- .../src/fe-common/core/fe-core-commands.c | 23 +- apps/irssi/src/fe-common/core/fe-exec.c | 17 +- apps/irssi/src/fe-common/core/fe-ignore.c | 35 +- apps/irssi/src/fe-common/core/fe-log.c | 21 +- apps/irssi/src/fe-common/core/fe-messages.c | 36 +- apps/irssi/src/fe-common/core/fe-queries.c | 22 +- apps/irssi/src/fe-common/core/fe-server.c | 12 +- apps/irssi/src/fe-common/core/fe-settings.c | 32 +- apps/irssi/src/fe-common/core/fe-windows.c | 38 +- apps/irssi/src/fe-common/core/fe-windows.h | 3 +- apps/irssi/src/fe-common/core/hilight-text.c | 78 ++-- apps/irssi/src/fe-common/core/hilight-text.h | 9 +- apps/irssi/src/fe-common/core/keyboard.c | 4 + apps/irssi/src/fe-common/core/keyboard.h | 10 +- .../irssi/src/fe-common/core/module-formats.c | 8 +- .../irssi/src/fe-common/core/module-formats.h | 8 +- apps/irssi/src/fe-common/core/printtext.c | 2 +- apps/irssi/src/fe-common/core/themes.c | 53 ++- apps/irssi/src/fe-common/core/themes.h | 2 + .../src/fe-common/core/window-commands.c | 59 ++- apps/irssi/src/fe-common/core/window-items.c | 18 +- .../irssi/src/fe-common/core/windows-layout.c | 9 +- apps/irssi/src/fe-text/Makefile.am | 1 + apps/irssi/src/fe-text/gui-entry.c | 6 +- apps/irssi/src/fe-text/gui-readline.c | 111 ++++-- apps/irssi/src/fe-text/mainwindows-save.c | 195 ---------- apps/irssi/src/fe-text/screen.c | 286 --------------- apps/irssi/src/fe-text/screen.h | 48 --- apps/irssi/src/fe-text/statusbar.c | 5 +- apps/irssi/src/fe-text/term.c | 2 - apps/irssi/src/fe-text/textbuffer-view.c | 66 ++-- apps/irssi/src/fe-text/utf8.c | 74 ++++ apps/irssi/src/fe-text/utf8.h | 3 + apps/irssi/src/lib-config/get.c | 40 --- apps/irssi/src/lib-config/iconfig.h | 4 - apps/irssi/src/perl/common/Channel.xs | 8 - apps/irssi/src/perl/common/Core.xs | 50 +++ apps/irssi/src/perl/common/Irssi.xs | 1 - apps/irssi/src/perl/common/module.h | 2 - apps/irssi/src/perl/common/typemap | 1 - apps/irssi/src/perl/get-signals.pl | 3 - apps/irssi/src/perl/irssi-core.pl | 9 +- apps/irssi/src/perl/irssi-core.pl.h | 9 +- apps/irssi/src/perl/perl-common.c | 25 +- apps/irssi/src/perl/perl-common.h | 12 +- apps/irssi/src/perl/perl-core.c | 25 +- apps/irssi/src/perl/perl-signals-list.h | 2 - apps/irssi/src/perl/textui/TextUI.xs | 2 + apps/irssi/src/perl/ui/Themes.xs | 2 +- apps/irssi/src/perl/ui/Window.xs | 6 +- apps/irssi/src/silc/core/client_ops.c | 35 +- apps/irssi/src/silc/core/client_ops.h | 8 +- apps/irssi/src/silc/core/silc-channels.c | 32 +- apps/irssi/src/silc/core/silc-channels.h | 4 +- apps/irssi/src/silc/core/silc-core.c | 7 +- apps/irssi/src/silc/core/silc-servers.c | 26 +- apps/irssi/src/silc/core/silc-servers.h | 3 +- 122 files changed, 2646 insertions(+), 1809 deletions(-) delete mode 100644 apps/irssi/COPYING create mode 100644 apps/irssi/README.cygwin create mode 100644 apps/irssi/glib-2.0.m4_ create mode 100644 apps/irssi/glib.m4_ create mode 100644 apps/irssi/irssi.cvs delete mode 100644 apps/irssi/src/core/blob.c delete mode 100644 apps/irssi/src/core/blob.h create mode 100644 apps/irssi/src/core/network-openssl.c delete mode 100644 apps/irssi/src/fe-text/mainwindows-save.c delete mode 100644 apps/irssi/src/fe-text/screen.c delete mode 100644 apps/irssi/src/fe-text/screen.h diff --git a/CHANGES b/CHANGES index 4b4dec21..cd144626 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +Sun Oct 20 14:12:24 CEST 2002 Pekka Riikonen + + * Merged with irssi.org CVS. + Sat Oct 19 13:32:15 CEST 2002 Pekka Riikonen * ROBODoc documented lib/silcutil/silcbuffer.h and diff --git a/apps/irssi/.cvsignore b/apps/irssi/.cvsignore index bbb8ef8f..6b0f2e03 100644 --- a/apps/irssi/.cvsignore +++ b/apps/irssi/.cvsignore @@ -16,6 +16,7 @@ ltmain.sh stamp-h stamp-h.in stamp.h +stamp-h1 version.h config.h.in .exrc @@ -31,6 +32,7 @@ default-config.h default-theme.h irssi-version.h irssi-config -colorless.theme build-stamp configure-stamp +glib.m4 +glib-2.0.m4 diff --git a/apps/irssi/AUTHORS b/apps/irssi/AUTHORS index b82b08a3..093f5e94 100644 --- a/apps/irssi/AUTHORS +++ b/apps/irssi/AUTHORS @@ -1 +1 @@ -Timo Sirainen, tss@iki.fi +Timo Sirainen diff --git a/apps/irssi/COPYING b/apps/irssi/COPYING deleted file mode 100644 index 60549be5..00000000 --- a/apps/irssi/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - 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/apps/irssi/NEWS b/apps/irssi/NEWS index 458a96e5..ccdc0e4f 100644 --- a/apps/irssi/NEWS +++ b/apps/irssi/NEWS @@ -1,3 +1,72 @@ +v0.8.4 2002-03-13 Timo Sirainen + + * Continuing to fix my stupid mistakes... + + - When a queried nick did a nick change, it might have crashed irssi + - read ChangeLog for some other minor changes + +v0.8.3 2002-03-13 Timo Sirainen + + - Perl scripts handling channel parts/kicks/quits printed some + errors. + - Connecting to IPv6 servers without IPv4 record didn't work + - When queries were auto-created by you using /MSG and you had + /SET autoclose_query non-zero, the query was always destroyed + almost immediately. + - Fix to some stupid ircds not sending us 001 numeric, but + beginning from MOTD + +v0.8.2 2002-03-11 Timo Sirainen + + * Changed the list of scripts distributed with irssi. Separated + example scripts to scripts/examples/ directory. + + * Hated infobar was removed, the same info is now in topicbar in + empty windows. I don't think it would disturb anyone in there. + If you still preferred always-empty topicbars, use + /SBAR topic REMOVE topic_empty + + + Added info_eol field to theme. If true, timestamp and server tag + are added to end of line, not at beginning. + + If -4 or -6 option is used with /SERVER, irssi now forces the + connection using the given protocol or fails. + + /SET max_wildcard_modes (default 6) - if a wildcard to /OP, /DEOP, + /VOICE or /DEVOICE matches more nicks than this, -yes option is + required. This is trying to prevent accidental massops. Setting + it to 0 disables this check. + + Supports now correctly servers which use '.' char as channel owner + character in /NAMES list. Also supports multiple mode chars, eg. + @+nick (if some server actually used it). + + Never ignore kick message if you get kicked from channel. + + Sending irssi SIGHUP now does a /RELOAD - useful if you + accidentally messed up something which doesn't let you do the + /RELOAD inside irssi (eg. /SBAR prompt DISABLE). + + irssi-proxy: PROXY CTCP ON|OFF - proxy clients can send this + command to specify that they want to handle the received CTCP + requests. Useful for specifying who gets to handle DCCs. + + Added escape_char /BIND command. The next char after that would be + added as-is to input line. + - Writing lines longers than 1024 chars to input buffer crashed + irssi (stupid missing sizeof() bug :) + - Some UTF-8 fixes + - Better flood protection for lines with >100 chars + - Control characters aren't printed as-is in topicbar (or statusbars + in general) anymore + - /OPER can be now aborted by giving empty password + - Netjoin messages were buggy in +channels + - Part message parameter for /CYCLE was never used. + - Don't send -autosendcmd after /UPGRADE. + - /SET autoclose_query - now only last received private message + affects when the query is closed, ie. /WHOIS requests or nick + changes don't reset the counter. + - Foreground ANSI colors weren't working + - Deleting one character replaced cutbuffer with that character. + Also ^Y leaked memory. + - /SCRIPT LOAD looked scripts from prefix/lib dir, not prefix/share + where they were actually installed. + - Highascii chars in replaces block in theme files could have + crashed irssi. + v0.8.1 2002-02-17 Timo Sirainen * Expected bugfix release :) Worst thing was that I forgot always to diff --git a/apps/irssi/README b/apps/irssi/README index fd05732b..d6a88764 100644 --- a/apps/irssi/README +++ b/apps/irssi/README @@ -111,6 +111,6 @@ See TODO file if it is already listed in there - if not send me email.. * AUTHOR - Timo Sirainen - - tss@iki.fi + - cras@irssi.org - cras at ircnet/opn/silc - - #irssi at ircnet/opn, #irssi.fi at ircnet + - #irssi at ircnet/opn, #irssi.fi, #irssi.de and #irssi.pl at ircnet diff --git a/apps/irssi/README.cygwin b/apps/irssi/README.cygwin new file mode 100644 index 00000000..60409e5c --- /dev/null +++ b/apps/irssi/README.cygwin @@ -0,0 +1,12 @@ +Getting perl scripting to work needs a few things: + + - configure with --with-perl-staticlib + + - libperl.dll is required in linking and running irssi, it's normally + located somewhere around /usr/lib/perl5/5.6.1/cygwin/CORE/libperl5_6_1.dll + copy it to eg. /usr/bin/libperl.dll + + - -DUSEIMPORTLIB is needed to be defined while compiling src/perl directory. + It doesn't hurt to be defined everywhere, so configure irssi with: + + CFLAGS='-DUSEIMPORTLIB' ./configure --with-perl-staticlib diff --git a/apps/irssi/autogen.sh b/apps/irssi/autogen.sh index 79156309..a8daf652 100755 --- a/apps/irssi/autogen.sh +++ b/apps/irssi/autogen.sh @@ -1,10 +1,20 @@ #!/bin/sh # Run this to generate all the initial makefiles, etc. +PKG_NAME="Irssi SILC" + srcdir=`dirname $0` test -z "$srcdir" && srcdir=. -PKG_NAME="Irssi SILC" +if test ! -f $srcdir/irssi.cvs -a -f $srcdir/configure; then + echo + echo "Use ./configure instead" + echo + echo "This script should only be run if you got sources from CVS." + echo "If you really want to do this, say:" + echo " touch irssi.cvs" + exit 0 +fi if test ! -f $srcdir/configure.in; then echo -n "**Error**: Directory \`$srcdir\' does not look like the" @@ -27,7 +37,7 @@ cat docs/help/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '! # .html -> .txt with lynx echo "Documentation: html -> txt..." -lynx -dump -nolist docs/startup-HOWTO.html > docs/startup-HOWTO.txt +lynx -dump -nolist docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt echo "Checking auto* tools..." @@ -134,3 +144,7 @@ automake --add-missing --gnu $am_opt #else # echo Skipping configure process. #fi + +# make sure perl hashes have correct length +find src/perl -name *.c -o -name *.xs | xargs grep -n hv_store | perl -ne 'if (/"(\w+)",\s*(\d+)/) { print unless $2 == length $1 }' + diff --git a/apps/irssi/configure.in b/apps/irssi/configure.in index e812dee8..4333bcb4 100644 --- a/apps/irssi/configure.in +++ b/apps/irssi/configure.in @@ -7,7 +7,7 @@ if test -n "`grep '^#undef VERSION' config.h.in`"; then fi AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(Irssi-SILC, 0.8.5+) +AM_INIT_AUTOMAKE(Irssi-SILC, 0.8.6) AM_MAINTAINER_MODE @@ -15,6 +15,7 @@ AC_ISC_POSIX AC_PROG_CC AC_PROG_CPP AC_STDC_HEADERS +AC_ARG_PROGRAM AM_PROG_LIBTOOL AC_PATH_PROG(sedpath, sed) @@ -110,7 +111,7 @@ if test "x$prefix" != "xNONE"; then perl_prefix_note=yes fi -AC_ARG_WITH(tests, +AC_ARG_WITH(with-glib2, [ --with-glib2 Use GLIB 2.0 instead of 1.2], if test x$withval = xyes; then want_glib2=yes @@ -182,14 +183,6 @@ AC_ARG_WITH(perl, fi, want_perl=static) -AC_ARG_WITH(tests, -[ --with-tests Run all the tests], - if test x$withval != xno; then - TEST_DIR=test - fi, - TEST_DIR=) -AC_SUBST(TEST_DIR) - AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Enable IPv6 support], if test x$enableval = xyes; then @@ -228,7 +221,7 @@ AC_CHECK_FUNC(socket, [], [ AC_CHECK_FUNC(inet_addr, [], [ AC_CHECK_LIB(nsl, inet_addr, [ LIBS="$LIBS -lnsl" - ], -lsocket) + ]) ]) dnl * gcc specific options @@ -462,7 +455,7 @@ dnl ** if test "x$want_textui" = "xyes"; then AC_CHECK_CURSES - LIBS="$LIBS $CURSES_LIBS" + TEXTUI_LIBS="$LIBS $CURSES_LIBS" if test "x$has_curses" = "xtrue"; then AC_CHECK_FUNC(use_default_colors, AC_DEFINE(HAVE_NCURSES_USE_DEFAULT_COLORS)) AC_CHECK_FUNC(idcok, AC_DEFINE(HAVE_CURSES_IDCOK)) @@ -473,19 +466,20 @@ if test "x$want_textui" = "xyes"; then ]) else AC_CHECK_LIB(tinfo, setupterm, [ - LIBS="$LIBS -ltinfo" + TEXTUI_LIBS="$LIBS -ltinfo" want_terminfo=yes ], AC_CHECK_LIB(termlib, tgetent, [ - LIBS="$LIBS -ltermlib" + TEXTUI_LIBS="$LIBS -ltermlib" want_termcap=yes ], AC_CHECK_LIB(termcap, tgetent, [ - LIBS="$LIBS -ltermcap" + TEXTUI_LIBS="$LIBS -ltermcap" want_termcap=yes ], [ AC_ERROR(Terminfo/termcap not found - install ncurses-devel package) want_textui=no ]))) fi + AC_SUBST(TEXTUI_LIBS) if test "x$want_termcap" = "xyes"; then AC_CHECK_FUNC(tparm,, need_tparm=yes) else @@ -660,7 +654,6 @@ AM_CONDITIONAL(BUILD_TEXTUI, test "$want_textui" = "yes") AM_CONDITIONAL(BUILD_IRSSIBOT, test "$want_irssibot" = "yes") AM_CONDITIONAL(BUILD_IRSSIPROXY, test "$want_irssiproxy" = "yes") AM_CONDITIONAL(BUILD_PLUGINS, test "$want_plugins" = "yes") -AM_CONDITIONAL(BUILD_SERVERTEST, test -n "$TEST_DIR") AM_CONDITIONAL(HAVE_PERL, test "$want_perl" != "no") AM_CONDITIONAL(HAVE_STATIC_PERL, test "$want_perl" = "static") AM_CONDITIONAL(NEED_TPARM, test "$need_tparm" = "yes") @@ -737,7 +730,7 @@ done FE_COMMON_LIBS="$FE_COMMON_LIBS../fe-common/core/libfe_common_core.a" dnl ** common libraries needed by frontends -COMMON_NOUI_LIBS="$CHAT_LIBS $CORE_LIBS $INTLLIBS" +COMMON_NOUI_LIBS="$CHAT_LIBS $CORE_LIBS" COMMON_LIBS="$FE_COMMON_LIBS $COMMON_NOUI_LIBS" AC_SUBST(COMMON_NOUI_LIBS) AC_SUBST(COMMON_LIBS) diff --git a/apps/irssi/docs/faq.txt b/apps/irssi/docs/faq.txt index d8825106..499f243b 100644 --- a/apps/irssi/docs/faq.txt +++ b/apps/irssi/docs/faq.txt @@ -1,70 +1,117 @@ + FAQ + Q: Why doesn't irssi display colors even when ircii etc. displays them? -A: They force ANSI colors even if terminal doesn't support them. By default, - irssi uses colors only if terminfo/termcap so says. The correct way to - fix this would be to change your TERM environment to a value where colors - work, like xterm-color or color_xterm. If this doesn't help, then use the - evil way of /SET term_force_colors ON. +A: They force ANSI colors even if terminal doesn't support them. By + default, irssi uses colors only if terminfo/termcap so says. The + correct way to fix this would be to change your TERM environment to a + value where colors work, like xterm-color or color_xterm (eg. + TERM=xterm-color irssi). If this doesn't help, then use the evil way + of /SET term_force_colors ON. Q: How do I easily write text to channel that starts with '/' character? A: / /text -Q: Why doesn't irssi update my realname (or whatever) after I change it - with /SET realname and reconnect with /RECONNECT or /SERVER? -A: Irssi is trying to be too smart. This will be fixed in future, but for - now you should use /DISCONNECT + /CONNECT. +Q: Why doesn't irssi update my realname (or whatever) after I change it with + /SET realname and reconnect with /RECONNECT or /SERVER? +A: Irssi is trying to be too smart. This will be fixed in future, but + for now you should use /DISCONNECT and /CONNECT. -Q: I connected to some server which isn't responding but now irssi tries - to connect back to it all the time! How can I stop it? -A: Two ways. The "good way" to do it is with /DISCONNECT. Check the server - tags first with /SERVER without giving it any parameters, reconnections - are those that have tag starting with "recon" text. So most probably you're - going to do /DISCONNECT recon-1. The other way is to remove all the - reconnections with /RMRECONNS, easier but may remove some connections - you actually wanted to reconnect (if you used multiple servers..). +Q: I connected to some server which isn't responding but now irssi tries to + connect back to it all the time! How can I stop it? +A: Two ways. The "good way" to do it is with /DISCONNECT. Check the + server tags first with /SERVER without giving it any parameters, + reconnections are those that have tag starting with "recon" text. So + most probably you're going to do /DISCONNECT recon-1. The other way is + to remove all the reconnections with /RMRECONNS, easier but may remove + some connections you actually wanted to reconnect (if you used + multiple servers..). Q: How do I add seconds to timestamp? -A: "/FORMAT timestamp {timestamp %%H:%%M:%%S} " - and remember to add the +A: /FORMAT timestamp {timestamp %%H:%%M:%%S} - and remember to add the trailing space :) Q: Why does irssi say "Irssi: Channel not fully synchronized yet, try again after a while" when I try to use /BAN etc? -A: Possibly a bug in irssi, or ircd you're using does something that irssi - didn't really notice. The new code should make this happen far less often - than before, but one known reason for this is when irssi doesn't notice - that you were unable to join some channel. Currently however I don't know - of any such events irssi doesn't know about. - - Anyway, if this does happen, do "/RAWLOG SAVE ~/rawlog" soon after joining - to channel, and either try to figure out yourself why irssi didn't get - reply to WHO request, or send the whole log to tss@iki.fi. Note that the - rawlog is by default only 200 lines and it may not be enough to show all - needed information, so you might want to do /SET rawlog_lines 1000 or so. +A: Possibly a bug in irssi, or ircd you're using does something that + irssi didn't really notice. The new code should make this happen far + less often than before, but one known reason for this is when irssi + doesn't notice that you were unable to join some channel. Currently + however I don't know of any such events irssi doesn't know about. + + Anyway, if this does happen, do /RAWLOG SAVE ~/rawlog soon after + joining to channel, and either try to figure out yourself why irssi + didn't get reply to WHO request, or send the whole log to + cras@irssi.org. Note that the rawlog is by default only 200 lines and + it may not be enough to show all needed information, so you might want + to do /SET rawlog_lines 1000 or so. + + MODE +b still works fine though. Q: Where's the GUI version? A: Read http://irssi.org/?page=about Q: How do I autorejoin channels after being kicked? -A: That's evil and you shouldn't do it. If you get kicked, you should - stay out, at least until the channel forgot you existed :) Most channels - I've joined just ban you if you autorejoin after kick. If you're joined - to channels who kick people for fun, try changing channels or something. - - Anyway, if you REALLY want to do that, and you understand that you're - doing evilness, you can use the autorejoin.pl script that comes with - irssi. You'll still need to specify the channels you wish to rejoin with - /SET autorejoin_channels #chan1 #chan2 ... - -Q: How do I announce that I'm away/back in all channels I've joined? - Or how do I change my nick when setting myself away/back? -A: That's even worse than autorejoin. Who could possibly care every time you - come and go? Many channels will kick you for using this, and I for example - have added several ignores so I'd never need to see these messages. Learn - to use /AWAY command properly and tell it's existence to people who don't - know about it. /WII yournick shows your away reason much better for people - who actually want to know if you're there or not. - - You can script these behaviours if you really wish to of course. But - currently there's no public scripts for either of these, and the only way - I'm going to add such to irssi.org is if the script contains a setting to - specify which specific channels the announcement is sent. +A: That's evil and you shouldn't do it. If you get kicked, you should + stay out, at least until the channel forgot you existed :) Most + channels I've joined just ban you if you autorejoin after kick. If + you're joined to channels who kick people for fun, try changing + channels or something. + + Anyway, if you REALLY want to do that, and you understand that you're + doing evilness, you can use the autorejoin.pl script that comes with + irssi. You'll still need to specify the channels you wish to rejoin + with /SET autorejoin_channels #chan1 #chan2 ... + +Q: How do I announce that I'm away/back in all channels I've joined? Or how + do I change my nick when setting myself away/back? +A: That's even worse than autorejoin. Who could possibly care every + time you come and go? Many channels will kick you for using this, and + I for example have added several ignores so I'd never need to see + these messages. Learn to use /AWAY command properly and tell it's + existence to people who don't know about it. /WII yournick shows your + away reason much better for people who actually want to know if you're + there or not. + + You can script these behaviours if you really wish to of course. But + currently there's no public scripts for either of these, and the only + way I'm going to add such to irssi.org is if the script contains a + setting to specify which specific channels the announcement is sent. + +Q: Why does irssi autojoin on invite by default? +A: The setting is /SET join_auto_chans_on_invite - it's not the same + as regular autojoin-on-invite, which irssi doesn't even have. The only + channels that are joined on invite, are the ones you've added to + config with /CHANNEL ADD -auto. This is very useful with +i channels + when you need to first send an invite request to bot, or if you get + accidentally kicked from channel, the kicker can invite you back + immediately. + + I don't see any bad side effects with this feature, so it's ON by + default. I guess someone could start kicking/inviting you all the time + but server connection shouldn't drop because of that, and you + shouldn't join channels whose operators are that evil. + +Q: How to make UTF-8 support work with irssi? +A: xterm -u8, screen -U, /SET term_type utf-8 + +Q: Will there be /DETACH-like feature? +A: Maybe. Detach code already is there, attach is just missing :) But + I don't have much interest in coding it, and screen works just fine so + why bother? + +Q: How do I run scripts automatically at startup? +A: Put them into ~/.irssi/scripts/autorun/ directory. Or better would + be if you placed them in ~/.irssi/scripts/ and created symlinks to + autorun directory (eg. cd ~/.irssi/scripts/autorun/ ; ln -s + ../script.pl .) + +Q: How do I easily edit existing topic? +A: /TOPIC +Q: How can I have /WHOIS replies to active window? +A: Currently there's no other way than to close the status window, or + at least do /WINDOW LEVEL -CRAP in it, but that would make a lot other + messages show up in active window too. I don't have many good ideas + how this could be easily fixed inside irssi (no, kludging it to only + work with whois isn't a "fix") - it'd be possible to create a script + do this though but currently it doesn't exist. diff --git a/apps/irssi/docs/formats.txt b/apps/irssi/docs/formats.txt index d918a268..0ffef08f 100644 --- a/apps/irssi/docs/formats.txt +++ b/apps/irssi/docs/formats.txt @@ -12,7 +12,13 @@ %p %P magenta (think: purple) %c %C %6 cyan bold cyan cyan %w %W %7 white bold white white - %n %N Turn off all colors and other formatting + %n %N Changes the color to "default color", removing + all other coloring and formatting. %N is always + the terminal's default color. %n is usually too, + except in themes it changes to "previous color", + ie. hello = "%Rhello%n" and "%G{hello} world" + would print hello in red, and %n would turn back + into %G making world green. %F Blinking on/off (think: flash) %U Underline on/off %8 Reverse on/off diff --git a/apps/irssi/docs/manual.txt b/apps/irssi/docs/manual.txt index 2956e18e..7f9b2392 100644 --- a/apps/irssi/docs/manual.txt +++ b/apps/irssi/docs/manual.txt @@ -387,7 +387,7 @@ after connecting to ircnet. This is useful for automatically identifying yourself to NickServ, for example - /IRCNET ADD -autosendcmd "/msg NickServ identify secret" OPN + /IRCNET ADD -autosendcmd "/msg NickServ identify secret" freenode /IRCNET REMOVE @@ -873,7 +873,8 @@ -regexp: is a regular expression -word: must match to full words -nick: Hilight only the nick, not the whole line - -color: Print the reply with - see below + -color: Print the reply with . color is in %code format + (see docs/formats.txt) -level: Match only for messages, default is publics,msgs,notices,actions -channels: Match only in @@ -882,8 +883,7 @@ /HILIGHT without any arguments displays list of the hilights. - By default the highlighted line will be printed with white color. - You can change this with the -color argument. If is a +If is a number, Irssi will treat it as a MIRC color code. You can also use bolds (^B), underlines (^_) etc. as if you like. diff --git a/apps/irssi/docs/perl.txt b/apps/irssi/docs/perl.txt index 59c7e57a..cf390a74 100644 --- a/apps/irssi/docs/perl.txt +++ b/apps/irssi/docs/perl.txt @@ -91,11 +91,11 @@ Here's an example: } if ($data) { - $server->command("/MSG $data Hello!"); + $server->command("MSG $data Hello!"); } elsif ($witem && ($witem->{type} eq "CHANNEL" || $witem->{type} eq "QUERY")) { # there's query/channel active in window - $witem->command("/MSG ".$witem->{name}." Hello!"); + $witem->command("MSG ".$witem->{name}." Hello!"); } else { Irssi::print("Nick not given, and no active channel/query in window"); } @@ -673,14 +673,6 @@ Server::channels_join(channels, automatic) was requested by user. If channel join is "automatic", irssi doesn't jump to the window where the channel was joined. -Channel -Server::channel_create(name, automatic) - Create new channel. - -Channel -channel_create(chat_type, name, automatic) - Create new channel with specified chat type. - FIXME: should this be removed? is this useful for anything? Channel::destroy() Destroy channel. @@ -951,10 +943,6 @@ Ban->{} setby - Nick of who set the ban time - Timestamp when ban was set -Channel -Server::channel_create(name, automatic) - Create new channel. - Channel::bans() Return a list of bans in channel. diff --git a/apps/irssi/docs/proxy.txt b/apps/irssi/docs/proxy.txt index 20e51715..41875aab 100644 --- a/apps/irssi/docs/proxy.txt +++ b/apps/irssi/docs/proxy.txt @@ -19,7 +19,7 @@ You really should set some password for the proxy with: Then you'll need to configure the ports/ircnets the proxy listens in, something like: - /SET irssiproxy_ports ircnet=2777 efnet=2778 opn=2779 + /SET irssiproxy_ports ircnet=2777 efnet=2778 freenode=2779 There we have 3 different irc networks answering in 3 ports. Note that you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to diff --git a/apps/irssi/docs/signals.txt b/apps/irssi/docs/signals.txt index 9b526aef..2bf0d921 100644 --- a/apps/irssi/docs/signals.txt +++ b/apps/irssi/docs/signals.txt @@ -324,10 +324,3 @@ gui-printtext.c: statusbar-items.c: "mail counter" - -SILC ----- - -client_ops.c: - "mime", SERVER_REC, CHANNEL_REC, BLOB_REC, char *mime, char *enc, char *nick - "mime-send", SERVER_REC, WI_ITEM_REC, char *data, int data_len, char *enc, char *type diff --git a/apps/irssi/docs/special_vars.txt b/apps/irssi/docs/special_vars.txt index c56c452f..7b6640ef 100644 --- a/apps/irssi/docs/special_vars.txt +++ b/apps/irssi/docs/special_vars.txt @@ -62,6 +62,7 @@ $A .. $Z is important. $I channel you were last INVITEd to $J client version text string $K current value of CMDCHARS + $k first character in CMDCHARS $L current contents of the input line $M modes of current channel, if any $N current nickname diff --git a/apps/irssi/docs/startup-HOWTO.html b/apps/irssi/docs/startup-HOWTO.html index 5700d9f0..a5c5d472 100644 --- a/apps/irssi/docs/startup-HOWTO.html +++ b/apps/irssi/docs/startup-HOWTO.html @@ -2,7 +2,8 @@

To new Irssi users (not to new IRC users ..)

-

Copyright (c) 2000-2002 by Timo Sirainen

+

Copyright (c) 2000-2002 by Timo Sirainen, release under + GNU FDL 1.1 license.

Index with some FAQ questions that are answered in the chapter:

@@ -67,41 +68,41 @@ weird non-VT compatible terminal (you most probably aren't), just say:

-     /SET term_force_colors ON
+/SET term_force_colors ON
 

I don't like automatic query windows, I don't like status window, I do like msgs window where all messages go:

-     /SET autocreate_own_query OFF
-     /SET autocreate_query_level DCCMSGS
-     /SET use_status_window OFF
-     /SET use_msgs_window ON
+/SET autocreate_own_query OFF
+/SET autocreate_query_level DCCMSGS
+/SET use_status_window OFF
+/SET use_msgs_window ON
 

Disable automatic window closing when /PARTing channel or /UNQUERYing query:

-     /SET autoclose_windows OFF
-     /SET reuse_unused_windows ON
+/SET autoclose_windows OFF
+/SET reuse_unused_windows ON
 

Here's the settings that make irssi work exactly like ircII in window management (send me a note if you can think of more):

-     /SET autocreate_own_query OFF
-     /SET autocreate_query_level NONE
-     /SET use_status_window OFF
-     /SET use_msgs_window OFF
-     /SET reuse_unused_windows ON
-     /SET windows_auto_renumber OFF
+/SET autocreate_own_query OFF
+/SET autocreate_query_level NONE
+/SET use_status_window OFF
+/SET use_msgs_window OFF
+/SET reuse_unused_windows ON
+/SET windows_auto_renumber OFF
 
-     /SET autostick_split_windows OFF
-     /SET autoclose_windows OFF
-     /SET print_active_channel ON
+/SET autostick_split_windows OFF
+/SET autoclose_windows OFF
+/SET print_active_channel ON
 

And example how to add servers:

@@ -110,7 +111,7 @@ management (send me a note if you can think of more):

joining channels)

-     /IRCNET ADD -autosendcmd "/^msg nickserv ident pass;wait -opn 2000" opn
+/IRCNET ADD -autosendcmd "/^msg nickserv ident pass;wait -freenode 2000" freenode
 

Then add some servers to different networks (ircnet is already set up @@ -118,24 +119,23 @@ for them), irc.kpnqwest.fi is used by default for IRCNet but if it fails, irc.funet.fi is tried next:

-     /SERVER ADD -auto -ircnet ircnet irc.kpnqwest.fi 6667
-     /SERVER ADD -ircnet ircnet irc.funet.fi 6667
-     /SERVER ADD -auto -ircnet efnet efnet.cs.hut.fi 6667
+/SERVER ADD -auto -ircnet ircnet irc.kpnqwest.fi 6667
+/SERVER ADD -ircnet ircnet irc.funet.fi 6667
+/SERVER ADD -auto -ircnet efnet efnet.cs.hut.fi 6667
 

Automatically join to channels after connected to server, send op request to bot after joined to efnet/#irssi:

-     /CHANNEL ADD -auto #irssi ircnet
-     /CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass"
-		  #irssi efnet
+/CHANNEL ADD -auto #irssi ircnet
+/CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass" #irssi efnet
 
If you want lines containing your nick to hilight:
-     /HILIGHT nick
+/HILIGHT nick
 

2. Basic user interface usage

@@ -149,10 +149,10 @@ created every time you /JOIN a channel or /QUERY someone. There's several ways you can change between these windows:

-     Meta-1, Meta-2, .. Meta-0 - Jump directly between windows 1-10
-     Meta-q .. Meta-o          - Jump directly between windows 11-19
-     /WINDOW <number>          - Jump to any window with specified number
-     Ctrl-P, Ctrl-N            - Jump to previous / next window
+Meta-1, Meta-2, .. Meta-0 - Jump directly between windows 1-10
+Meta-q .. Meta-o          - Jump directly between windows 11-19
+/WINDOW <number>          - Jump to any window with specified number
+Ctrl-P, Ctrl-N            - Jump to previous / next window
 

Clearly the easiest way is to use Meta-number keys. And what is the Meta @@ -161,21 +161,21 @@ it's probably the left Windows key. If they don't work directly, you'll need to set a few X resources (NOTE: these work with both xterm and rxvt):

-     XTerm*eightBitInput:   false
-     XTerm*metaSendsEscape: true
+XTerm*eightBitInput:   false
+XTerm*metaSendsEscape: true
 

With rxvt, you can also specify which key acts as Meta key. So if you want to use ALT instead of Windows key for it, use:

-     rxvt*modifier: alt
+rxvt*modifier: alt
 

You could do this by changing the X key mappings:

-    xmodmap -e "keysym Alt_L = Meta_L Alt_L"
+xmodmap -e "keysym Alt_L = Meta_L Alt_L"
 

And how exactly do you set these X resources? For Debian, there's @@ -196,16 +196,16 @@ but I think they should work pretty well now :) Here's some commands related to them:

-     /WINDOW NEW                    - Create new split window
-     /WINDOW NEW HIDE               - Create new hidden window
-     /WINDOW CLOSE                  - Close split or hidden window
+/WINDOW NEW                    - Create new split window
+/WINDOW NEW HIDE               - Create new hidden window
+/WINDOW CLOSE                  - Close split or hidden window
 
-     /WINDOW HIDE [<number>|<name>] - Make the split window hidden window
-     /WINDOW SHOW <number>|<name>   - Make the hidden window a split window
+/WINDOW HIDE [<number>|<name>] - Make the split window hidden window
+/WINDOW SHOW <number>|<name>   - Make the hidden window a split window
 
-     /WINDOW SHRINK [<lines>]       - Shrink the split window
-     /WINDOW GROW [<lines>]         - Grow the split window
-     /WINDOW BALANCE                - Balance the sizes of all split windows
+/WINDOW SHRINK [<lines>]       - Shrink the split window
+/WINDOW GROW [<lines>]         - Grow the split window
+/WINDOW BALANCE                - Balance the sizes of all split windows
 

By default, irssi uses "sticky windowing" for split windows. This means @@ -214,9 +214,9 @@ split window without some effort. For example you could have following window layout:

-     Split window 1: win#1 - Status window, win#2 - Messages window
-     Split window 2: win#3 - ircnet/#channel1, win#4 - ircnet/#channel2
-     Split window 3: win#5 - efnet/#channel1, win#6 - efnet/#channel2
+Split window 1: win#1 - Status window, win#2 - Messages window
+Split window 2: win#3 - ircnet/#channel1, win#4 - ircnet/#channel2
+Split window 3: win#5 - efnet/#channel1, win#6 - efnet/#channel2
 

When you are in win#1 and press ALT-6, irssi jumps to split window @@ -229,7 +229,7 @@ split window irssi just changes to that split window. This it the way windows work with ircii, if you prefer it you can set it with

-     /SET autostick_split_windows OFF
+/SET autostick_split_windows OFF
 

Each window can have multiple channels, queries and other "window @@ -237,22 +237,22 @@ items" inside them. If you don't like windows at all, you disable automatic creating of them with

-     /SET autocreate_windows OFF
+/SET autocreate_windows OFF
 

And if you keep all channels in one window, you most probably want the channel name printed in each line:

-     /SET print_active_channel ON
+/SET print_active_channel ON
 

If you want to group only some channels or queries in one window, use

-     /JOIN -window #channel
-     /QUERY -window nick
+/JOIN -window #channel
+/QUERY -window nick
 

3. Server and channel automation

@@ -271,15 +271,15 @@ you're connected to some network, use -autosendcmd option. Here's some examples:

-     /IRCNET ADD -autosendcmd '^msg bot invite' ircnet
-     /IRCNET ADD -autosendcmd "/^msg nickserv ident pass;wait -opn 2000" opn
+/IRCNET ADD -autosendcmd '^msg bot invite' ircnet
+/IRCNET ADD -autosendcmd "/^msg nickserv ident pass;wait -freenode 2000" freenode
 

After that you need to add your servers. For example:

-     /SERVER ADD -auto -ircnet ircnet irc.kpnqwest.fi 6667
-     /SERVER ADD -auto -ircnet worknet irc.mycompany.com 6667 password
+/SERVER ADD -auto -ircnet ircnet irc.kpnqwest.fi 6667
+/SERVER ADD -auto -ircnet worknet irc.mycompany.com 6667 password
 

The -auto option specifies that this server is @@ -291,9 +291,8 @@ fails.

And finally channels:

-     /CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass"
-		  #irssi efnet
-     /CHANNEL ADD -auto #secret ircnet password
+/CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass" #irssi efnet
+/CHANNEL ADD -auto #secret ircnet password
 

-bots and -botcmd should be the only ones @@ -313,8 +312,8 @@ queries you want. If you want to move the windows or channels around use commands:

-     /WINDOW MOVE LEFT/RIGHT/number    - move window elsewhere
-     /WINDOW ITEM MOVE <number>|<name> - move channel/query to another window
+/WINDOW MOVE LEFT/RIGHT/number    - move window elsewhere
+/WINDOW ITEM MOVE <number>|<name> - move channel/query to another window
 

When everything looks the way you like, use /LAYOUT SAVE @@ -338,7 +337,7 @@ pretty much all messages that don't clearly belong to some channel or query. Some people like it, some don't. If you want to remove it, use

-     /SET use_status_window OFF
+/SET use_status_window OFF
 

This doesn't have any effect until you restart irssi. If you want to @@ -349,19 +348,19 @@ messages go. By default it's disabled and query windows are created instead. To make all private messages go to msgs window, say:

-     /SET use_msgs_window ON
-     /SET autocreate_query_level DCCMSGS  (or if you don't want queries to
-					   dcc chats either, say NONE)
+/SET use_msgs_window ON
+/SET autocreate_query_level DCCMSGS  (or if you don't want queries to
+				      dcc chats either, say NONE)
 

use_msgs_window either doesn't have any effect until restarting irssi. To create it immediately say:

-     /WINDOW NEW HIDE     - create the window
-     /WINDOW NAME (msgs)  - name it to "(msgs)"
-     /WINDOW LEVEL MSGS   - make all private messages go to this window
-     /WINDOW MOVE 1       - move it to first window
+/WINDOW NEW HIDE     - create the window
+/WINDOW NAME (msgs)  - name it to "(msgs)"
+/WINDOW LEVEL MSGS   - make all private messages go to this window
+/WINDOW MOVE 1       - move it to first window
 

Note that neither use_msgs_window nor use_status_window have any @@ -374,7 +373,7 @@ all sorts of messages with no real classification. You can get a whole list of levels with

-     /HELP levels
+/HELP levels
 

Status window has message level ALL -MSGS, meaning that all @@ -393,7 +392,7 @@ them to one sigle window if you really want to. That being said, here's how you do connect to new server without closing the old connection:

-     /CONNECT irc.server.org
+/CONNECT irc.server.org
 

Instead of the /SERVER which disconnects the existing @@ -401,13 +400,13 @@ connection. To see list of all active connections, use /SERVER without any parameters. You should see a list of something like:

-     -!- IRCNet: irc.song.fi:6667 (IRCNet)
-     -!- OPN: tolkien.openprojects.net:6667 (OPN)
-     -!- RECON-1: 192.168.0.1:6667 () (02:59 left before reconnecting)
+-!- IRCNet: irc.song.fi:6667 (IRCNet)
+-!- freenode: irc.freenode.net:6667 (freenode)
+-!- RECON-1: 192.168.0.1:6667 () (02:59 left before reconnecting)
 
-

Here you see that we're connected to IRCNet and OPN networks. The -the IRCNet at the beginning is called the "server tag" while the +

Here you see that we're connected to IRCNet and freenode networks. +The IRCNet at the beginning is called the "server tag" while the (IRCnet) at the end shows the IRC network. Server tag specifies unique tag to refer to the server, usually it's the same as the IRC network. When the IRC network isn't known it's some part of the server name. @@ -423,13 +422,13 @@ successful and irssi will try to connect it again in 3 minutes.

reconnecting, use

-     /DISCONNECT ircnet   - disconnect server with tag "ircnet"
-     /DISCONNECT recon-1  - stop trying to reconnect to RECON-1 server
-     /RMRECONNS           - stop all server reconnections
+/DISCONNECT ircnet   - disconnect server with tag "ircnet"
+/DISCONNECT recon-1  - stop trying to reconnect to RECON-1 server
+/RMRECONNS           - stop all server reconnections
 
-     /RECONNECT recon-1   - immediately try reconnecting back to RECON-1
-     /RECONNECT ALL       - immediately try reconnecting back to all
-			    servers in reconnection queue
+/RECONNECT recon-1   - immediately try reconnecting back to RECON-1
+/RECONNECT ALL       - immediately try reconnecting back to all
+		       servers in reconnection queue
 

Now that you're connected to all your servers, you'll have to know how @@ -438,8 +437,8 @@ empty window, like status or msgs window. In it, you can specify which server to set active with

-     /WINDOW SERVER tag    - set server "tag" active
-     Ctrl-X                - set the next server in list active
+/WINDOW SERVER tag    - set server "tag" active
+Ctrl-X                - set the next server in list active
 

When the server is active, you can use it normally. When there's @@ -451,9 +450,9 @@ from.

which server it should use:

-     /MSG -tag nick message
-     /JOIN -tag #channel
-     /QUERY -tag nick
+/MSG -tag nick message
+/JOIN -tag #channel
+/QUERY -tag nick
 

/MSG tab completion also automatically adds the @@ -466,22 +465,22 @@ it is automatically set active in the window. To set the window's server sticky use

-     /WINDOW SERVER -sticky tag
+/WINDOW SERVER -sticky tag
 

This is useful if you wish to have multiple status or msgs windows, one for each server. Here's how to do them (repeat for each server)

-     /WINDOW NEW HIDE
-     /WINDOW NAME (status)
-     /WINDOW LEVEL ALL -MSGS
-     /WINDOW SERVER -sticky ircnet
+/WINDOW NEW HIDE
+/WINDOW NAME (status)
+/WINDOW LEVEL ALL -MSGS
+/WINDOW SERVER -sticky ircnet
 
-     /WINDOW NEW HIDE
-     /WINDOW NAME (msgs)
-     /WINDOW LEVEL MSGS
-     /WINDOW SERVER -sticky ircnet
+/WINDOW NEW HIDE
+/WINDOW NAME (msgs)
+/WINDOW LEVEL MSGS
+/WINDOW SERVER -sticky ircnet
 

7. /LASTLOG and jumping around in scrollback

@@ -490,9 +489,9 @@ for each server. Here's how to do them (repeat for each server)

scrollback buffer. Simplest usages are

-     /LASTLOG word     - print all lines with "word" in them
-     /LASTLOG word 10  - print last 10 occurances of "word"
-     /LASTLOG -topics  - print all topic changes
+/LASTLOG word     - print all lines with "word" in them
+/LASTLOG word 10  - print last 10 occurances of "word"
+/LASTLOG -topics  - print all topic changes
 

If there's more than 1000 lines to be printed, irssi thinks that you @@ -500,7 +499,7 @@ probably made some mistake and won't print them without -force option. If you want to save the full lastlog to file, use

-     /LASTLOG -file ~/irc.log
+/LASTLOG -file ~/irc.log
 

With -file option you don't need -force even @@ -524,8 +523,8 @@ END command.

You can configure it with:

-     /SET awaylog_level MSGS HILIGHT     - Specifies what messages to log
-     /SET awaylog_file ~/.irssi/away.log - Specifies the file to use
+/SET awaylog_level MSGS HILIGHT     - Specifies what messages to log
+/SET awaylog_file ~/.irssi/away.log - Specifies the file to use
 

Easiest way to start logging with Irssi is to use autologging. With it @@ -533,7 +532,7 @@ Irssi logs all channels and private messages to specified directory. You can turn it on with

-     /SET autolog ON
+/SET autolog ON
 

By default it logs pretty much everything execept CTCPS or CRAP @@ -541,14 +540,14 @@ You can turn it on with

yourself with

-     /SET autolog_level ALL -CRAP -CLIENTCRAP -CTCPS (this is the default)
+/SET autolog_level ALL -CRAP -CLIENTCRAP -CTCPS (this is the default)
 

By default irssi logs to ~/irclogs/<servertag>/<target>.log. You can change this with

-     /SET autolog_path ~/irclogs/$tag/$0.log (this is the default)
+/SET autolog_path ~/irclogs/$tag/$0.log (this is the default)
 

The path is automatically created if it doesn't exist. $0 specifies @@ -557,7 +556,7 @@ logs by adding date/time formats to the file name. The formats are in "man strftime" format. For example

-     /SET autolog_path ~/irclogs/%Y/$tag/$0.%m-%d.log
+/SET autolog_path ~/irclogs/%Y/$tag/$0.%m-%d.log
 

For logging only some specific channels or nicks, see /HELP @@ -579,18 +578,18 @@ that would be to see what it prints in cat. Here's an example for pressing F1 key:

-     [cras@hurina] ~% cat
-     ^[OP
+[cras@hurina] ~% cat
+^[OP
 
-

So in irssi you would use /BIND ^[OP /ECHO F1 pressed. If +

So in irssi you would use /BIND ^[OP /ECHO F1 pressed. If you use multiple terminals which have different bindings for the key, it would be better to use eg.:

-     /BIND ^[OP key F1
-     /BIND ^[11~ key F1
-     /BIND F1 /ECHO F1 pressed.
+/BIND ^[OP key F1
+/BIND ^[11~ key F1
+/BIND F1 /ECHO F1 pressed.
 

10. Proxies and IRC bouncers

@@ -606,13 +605,13 @@ to servers irc.dalnet and irc.efnet.org. First you'd need to setup the bouncer:

-     /SET use_proxy ON
-     /SET proxy_address irc.bouncer.org
-     /SET proxy_port 5000
+/SET use_proxy ON
+/SET proxy_address irc.bouncer.org
+/SET proxy_port 5000
 
-     /SET proxy_password YOUR_BNC_PASSWORD_HERE
-     /SET -clear proxy_string
-     /SET proxy_string_after conn %s %d
+/SET proxy_password YOUR_BNC_PASSWORD_HERE
+/SET -clear proxy_string
+/SET proxy_string_after conn %s %d
 

Then you'll need to add the server connections. These are done @@ -620,8 +619,8 @@ exactly as if you'd want to connect directly to them. Nothing special about them:

-     /SERVER ADD -auto -ircnet dalnet irc.dal.net
-     /SERVER ADD -auto -ircnet efnet irc.efnet.org
+/SERVER ADD -auto -ircnet dalnet irc.dal.net
+/SERVER ADD -auto -ircnet efnet irc.efnet.org
 

With the proxy /SETs however, irssi now connects to those @@ -637,9 +636,9 @@ you can just forget that your bouncer even exists.

All proxies have these settings in common:

-     /SET use_proxy ON
-     /SET proxy_address <Proxy host address>
-     /SET proxy_port <Proxy port>
+/SET use_proxy ON
+/SET proxy_address <Proxy host address>
+/SET proxy_port <Proxy port>
 

HTTP proxy

@@ -647,31 +646,31 @@ you can just forget that your bouncer even exists.

Use these settings with HTTP proxies:

-     /SET -clear proxy_password
-     /EVAL SET proxy_string CONNECT %s:%d\n\n
+/SET -clear proxy_password
+/EVAL SET proxy_string CONNECT %s:%d\n\n
 

BNC

-     /SET proxy_password your_pass
-     /SET -clear proxy_string
-     /SET proxy_string_after conn %s %d
+/SET proxy_password your_pass
+/SET -clear proxy_string
+/SET proxy_string_after conn %s %d
 

dircproxy

dircproxy separates the server connections by passwords. So, if you for example have ircnet connection with password ircpass and -openprojects connection with opnpass, you would do something like +openprojects connection with freenodepass, you would do something like this:

-     /SET -clear proxy_password
-     /SET -clear proxy_string
+/SET -clear proxy_password
+/SET -clear proxy_string
 
-     /SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
-     /SERVER ADD -auto -ircnet opn fake.opn 6667 opnpass
+/SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
+/SERVER ADD -auto -ircnet freenode fake.freenode 6667 freenodepass
 

The server name and port you give isn't used anywhere, so you can @@ -685,13 +684,13 @@ connecting to different servers. You can manage this in a bit same way as with dircproxy, by creating fake connections:

-    /SET -clear proxy_password
-    /SET -clear proxy_string
+/SET -clear proxy_password
+/SET -clear proxy_string
 
-    /IRCNET ADD -user ircnetuser ircnet
-    /SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
-    /IRCNET ADD -user opnuser opn
-    /SERVER ADD -auto -ircnet opn fake.opn 6667 opnpass
+/IRCNET ADD -user ircnetuser ircnet
+/SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
+/IRCNET ADD -user freenodeuser freenode
+/SERVER ADD -auto -ircnet freenode fake.freenode 6667 freenodepass
 

So, you'll specify the usernames with /IRCNET ADD command, @@ -717,9 +716,9 @@ ports, like you can share ircnet in port 2777 and efnet in port 2778.

Usage in proxy side:

-     /LOAD proxy
-     /SET irssiproxy_password <password>
-     /SET irssiproxy_ports <ircnet>=<port> ... (eg. ircnet=2777 efnet=2778)
+/LOAD proxy
+/SET irssiproxy_password <password>
+/SET irssiproxy_ports <ircnet>=<port> ... (eg. ircnet=2777 efnet=2778)
 

NOTE: you MUST add all the servers you @@ -728,7 +727,7 @@ are using to server and ircnet lists with /SERVER ADD and reason, and you only use one server connection, you may simply set:

-     /SET irssiproxy_ports *=2777
+/SET irssiproxy_ports *=2777
 

Usage in client side:

@@ -737,8 +736,8 @@ reason, and you only use one server connection, you may simply set:

specified in /SET irssiproxy_password. For example:

-     /SERVER ADD -ircnet ircnet my.irssi-proxy.org 2777 secret
-     /SERVER ADD -ircnet efnet my.irssi-proxy.org 2778 secret
+/SERVER ADD -ircnet ircnet my.irssi-proxy.org 2777 secret
+/SERVER ADD -ircnet efnet my.irssi-proxy.org 2778 secret
 

Irssi proxy works fine with other IRC clients as well.

@@ -755,14 +754,14 @@ proxy
settings don't have anything to do with socks however. give it with:

-     /SET proxy_password <password>
+/SET proxy_password <password>
 

Irssi's defaults for connect strings are

-     /SET proxy_string CONNECT %s %d
-     /SET proxy_string_after
+/SET proxy_string CONNECT %s %d
+/SET proxy_string_after
 

The proxy_string is sent before NICK/USER commands, the @@ -933,11 +932,11 @@ of them you might want to change (the default value is shown):

/STATUSBAR displays a list of statusbars:

-     Name                           Type   Placement Position Visible
-     window                         window bottom    0        always
-     window_inact                   window bottom    1        inactive
-     prompt                         root   bottom    100      always
-     topic                          root   top       1        always
+Name                           Type   Placement Position Visible
+window                         window bottom    0        always
+window_inact                   window bottom    1        inactive
+prompt                         root   bottom    100      always
+topic                          root   top       1        always
 

/STATUSBAR <name> prints the statusbar settings and @@ -954,18 +953,18 @@ useful only with split windows, one split window is active and the rest are inactive. These settings can be changed with:

-     STATUSBAR <name> TYPE window|root
-     STATUSBAR <name> PLACEMENT top|bottom
-     STATUSBAR <name> POSITION <num>
-     STATUSBAR <name> VISIBLE always|active|inactive
+/STATUSBAR <name> TYPE window|root
+/STATUSBAR <name> PLACEMENT top|bottom
+/STATUSBAR <name> POSITION <num>
+/STATUSBAR <name> VISIBLE always|active|inactive
 

When loading a new statusbar scripts, you'll need to also specify where you want to show it. Statusbar items can be modified with:

-     STATUSBAR <name> ADD [-before | -after <item>] [-priority #] [-alignment left|right] <item>
-     STATUSBAR <name> REMOVE <item>
+/STATUSBAR <name> ADD [-before | -after <item>] [-priority #] [-alignment left|right] <item>
+/STATUSBAR <name> REMOVE <item>
 

The item name with statusbar scripts is usually same as the script's diff --git a/apps/irssi/glib-2.0.m4_ b/apps/irssi/glib-2.0.m4_ new file mode 100644 index 00000000..0c1ae856 --- /dev/null +++ b/apps/irssi/glib-2.0.m4_ @@ -0,0 +1,212 @@ +# Configure paths for GLIB +# Owen Taylor 1997-2001 + +dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject or +dnl gthread is specified in MODULES, pass to pkg-config +dnl +AC_DEFUN(AM_PATH_GLIB_2_0, +[dnl +dnl Get the cflags and libraries from pkg-config +dnl +AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + pkg_config_args=glib-2.0 + for module in . $4 + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + esac + done + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + + no_glib="" + + if test x$PKG_CONFIG != xno ; then + if $PKG_CONFIG --atleast-pkgconfig-version 0.7 ; then + : + else + echo *** pkg-config too old; version 0.7 or better required. + no_glib=yes + PKG_CONFIG=no + fi + else + no_glib=yes + fi + + min_glib_version=ifelse([$1], ,2.0.0,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.glibtest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = g_strdup("$min_glib_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB was incorrectly installed" + echo "*** or that you have moved GLIB since it was installed. In the latter case, you" + echo "*** may want to edit the pkg-config script: $PKG_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GLIB_GENMARSHAL) + AC_SUBST(GOBJECT_QUERY) + AC_SUBST(GLIB_MKENUMS) + rm -f conf.glibtest +]) diff --git a/apps/irssi/glib.m4_ b/apps/irssi/glib.m4_ new file mode 100644 index 00000000..b8094bbf --- /dev/null +++ b/apps/irssi/glib.m4_ @@ -0,0 +1,196 @@ +# Configure paths for GLIB +# Owen Taylor 97-11-3 + +dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or +dnl gthread is specified in MODULES, pass to glib-config +dnl +AC_DEFUN(AM_PATH_GLIB, +[dnl +dnl Get the cflags and libraries from the glib-config script +dnl +AC_ARG_WITH(glib-prefix,[ --with-glib-prefix=PFX Prefix where GLIB is installed (optional)], + glib_config_prefix="$withval", glib_config_prefix="") +AC_ARG_WITH(glib-exec-prefix,[ --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)], + glib_config_exec_prefix="$withval", glib_config_exec_prefix="") +AC_ARG_ENABLE(glibtest, [ --disable-glibtest Do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + if test x$glib_config_exec_prefix != x ; then + glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix" + if test x${GLIB_CONFIG+set} != xset ; then + GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config + fi + fi + if test x$glib_config_prefix != x ; then + glib_config_args="$glib_config_args --prefix=$glib_config_prefix" + if test x${GLIB_CONFIG+set} != xset ; then + GLIB_CONFIG=$glib_config_prefix/bin/glib-config + fi + fi + + for module in . $4 + do + case "$module" in + gmodule) + glib_config_args="$glib_config_args gmodule" + ;; + gthread) + glib_config_args="$glib_config_args gthread" + ;; + esac + done + + AC_PATH_PROG(GLIB_CONFIG, glib-config, no) + min_glib_version=ifelse([$1], ,0.99.7,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + no_glib="" + if test "$GLIB_CONFIG" = "no" ; then + no_glib=yes + else + GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags` + GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs` + glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of glib-config to some extent +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.glibtest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = g_strdup("$min_glib_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If glib-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n"); + printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n"); + printf("*** before re-running configure\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the glib-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n"); + printf("*** correct copy of glib-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$GLIB_CONFIG" = "no" ; then + echo "*** The glib-config script installed by GLIB could not be found" + echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the GLIB_CONFIG environment variable to the" + echo "*** full path to glib-config." + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" + echo "***" + echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" + echo "*** came with the system with the command" + echo "***" + echo "*** rpm --erase --nodeps gtk gtk-devel" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB was incorrectly installed" + echo "*** or that you have moved GLIB since it was installed. In the latter case, you" + echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + rm -f conf.glibtest +]) diff --git a/apps/irssi/irssi-config.in b/apps/irssi/irssi-config.in index 3076247c..cd529ed0 100644 --- a/apps/irssi/irssi-config.in +++ b/apps/irssi/irssi-config.in @@ -1,6 +1,9 @@ PROG_LIBS="@PROG_LIBS@" -PERL_LDFLAGS="@PERL_LDFLAGS@" COMMON_LIBS="@COMMON_LIBS@" +PERL_LINK_LIBS="@PERL_LINK_LIBS@" +PERL_FE_LINK_LIBS="@PERL_FE_LINK_LIBS@" +PERL_LINK_FLAGS="@PERL_LINK_FLAGS@" + CHAT_MODULES="@CHAT_MODULES@" irc_MODULES="@irc_MODULES@" diff --git a/apps/irssi/irssi.cvs b/apps/irssi/irssi.cvs new file mode 100644 index 00000000..e69de29b diff --git a/apps/irssi/irssi.spec.in b/apps/irssi/irssi.spec.in index c15069cf..d902f786 100644 --- a/apps/irssi/irssi.spec.in +++ b/apps/irssi/irssi.spec.in @@ -2,7 +2,7 @@ Name: irssi Version: @VERSION@ Release: 1 -Vendor: Timo Sirainen +Vendor: Timo Sirainen Summary: Irssi is a IRC client Copyright: GPL Group: Applications/Communications diff --git a/apps/irssi/src/core/Makefile.am b/apps/irssi/src/core/Makefile.am index 0f91a4b0..6a6aeef3 100644 --- a/apps/irssi/src/core/Makefile.am +++ b/apps/irssi/src/core/Makefile.am @@ -32,6 +32,7 @@ libcore_a_SOURCES = \ net-nonblock.c \ net-sendbuffer.c \ network.c \ + network-openssl.c \ nicklist.c \ nickmatch-cache.c \ pidwait.c \ @@ -44,8 +45,7 @@ libcore_a_SOURCES = \ settings.c \ signals.c \ special-vars.c \ - write-buffer.c \ - blob.c + write-buffer.c structure_headers = \ channel-rec.h \ @@ -55,8 +55,7 @@ structure_headers = \ server-rec.h \ server-setup-rec.h \ server-connect-rec.h \ - window-item-rec.h \ - blob.h + window-item-rec.h noinst_HEADERS = \ args.h \ diff --git a/apps/irssi/src/core/blob.c b/apps/irssi/src/core/blob.c deleted file mode 100644 index 51fe5e5e..00000000 --- a/apps/irssi/src/core/blob.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "common.h" -#include "blob.h" -#include "modules.h" - -void blob_fill(BLOB_REC *blob) -{ - blob->type = module_get_uniq_id("BLOB", 0); -} diff --git a/apps/irssi/src/core/blob.h b/apps/irssi/src/core/blob.h deleted file mode 100644 index ec9e553e..00000000 --- a/apps/irssi/src/core/blob.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __BLOB_H__ -#define __BLOB_H__ - -#include "modules.h" - -struct _BLOB_REC { - int type; - void *data; - guint32 octets; -}; - -typedef struct _BLOB_REC BLOB_REC; - -void blob_fill(BLOB_REC *blob); - -#endif diff --git a/apps/irssi/src/core/channel-rec.h b/apps/irssi/src/core/channel-rec.h index f3ec5f8d..7b806ca4 100644 --- a/apps/irssi/src/core/channel-rec.h +++ b/apps/irssi/src/core/channel-rec.h @@ -2,6 +2,7 @@ #include "window-item-rec.h" +char *name; char *topic; char *topic_by; time_t topic_time; diff --git a/apps/irssi/src/core/channels-setup.c b/apps/irssi/src/core/channels-setup.c index 62d43b2c..a61ccb56 100644 --- a/apps/irssi/src/core/channels-setup.c +++ b/apps/irssi/src/core/channels-setup.c @@ -54,6 +54,8 @@ static void channel_setup_save(CHANNEL_SETUP_REC *channel) void channel_setup_create(CHANNEL_SETUP_REC *channel) { + channel->type = module_get_uniq_id("CHANNEL SETUP", 0); + if (g_slist_find(setupchannels, channel) == NULL) setupchannels = g_slist_append(setupchannels, channel); channel_setup_save(channel); diff --git a/apps/irssi/src/core/channels.c b/apps/irssi/src/core/channels.c index 1884c402..9a92b896 100644 --- a/apps/irssi/src/core/channels.c +++ b/apps/irssi/src/core/channels.c @@ -35,24 +35,37 @@ static char *get_join_data(CHANNEL_REC *channel) return g_strdup(channel->name); } -void channel_init(CHANNEL_REC *channel, int automatic) +static const char *channel_get_target(WI_ITEM_REC *item) +{ + return ((CHANNEL_REC *) item)->name; +} + +void channel_init(CHANNEL_REC *channel, SERVER_REC *server, const char *name, + const char *visible_name, int automatic) { g_return_if_fail(channel != NULL); - g_return_if_fail(channel->name != NULL); + g_return_if_fail(name != NULL); + g_return_if_fail(server != NULL); - channels = g_slist_append(channels, channel); - if (channel->server != NULL) { - channel->server->channels = - g_slist_append(channel->server->channels, channel); - } + if (visible_name == NULL) + visible_name = name; MODULE_DATA_INIT(channel); channel->type = module_get_uniq_id_str("WINDOW ITEM TYPE", "CHANNEL"); channel->destroy = (void (*) (WI_ITEM_REC *)) channel_destroy; - channel->mode = g_strdup(""); - channel->createtime = time(NULL); + channel->get_target = channel_get_target; channel->get_join_data = get_join_data; + channel->chat_type = server->chat_type; + channel->server = server; + channel->name = g_strdup(name); + channel->visible_name = g_strdup(visible_name); + channel->mode = g_strdup(""); + channel->createtime = time(NULL); + + channels = g_slist_append(channels, channel); + server->channels = g_slist_append(server->channels, channel); + signal_emit("channel created", 2, channel, GINT_TO_POINTER(automatic)); } @@ -64,8 +77,9 @@ void channel_destroy(CHANNEL_REC *channel) channel->destroying = TRUE; channels = g_slist_remove(channels, channel); - if (!channel->server->disconnected) - channel->server->channels = g_slist_remove(channel->server->channels, channel); + channel->server->channels = + g_slist_remove(channel->server->channels, channel); + signal_emit("channel destroyed", 1, channel); MODULE_DATA_DEINIT(channel); @@ -116,6 +130,26 @@ CHANNEL_REC *channel_find(SERVER_REC *server, const char *name) (void *) name); } +void channel_change_name(CHANNEL_REC *channel, const char *name) +{ + g_return_if_fail(IS_CHANNEL(channel)); + + g_free(channel->name); + channel->name = g_strdup(name); + + signal_emit("channel name changed", 1, channel); +} + +void channel_change_visible_name(CHANNEL_REC *channel, const char *name) +{ + g_return_if_fail(IS_CHANNEL(channel)); + + g_free(channel->visible_name); + channel->visible_name = g_strdup(name); + + signal_emit("window item name changed", 1, channel); +} + static CHANNEL_REC *channel_find_servers(GSList *servers, const char *name) { return gslist_foreach_find(servers, diff --git a/apps/irssi/src/core/channels.h b/apps/irssi/src/core/channels.h index 98b75ee0..0839d69b 100644 --- a/apps/irssi/src/core/channels.h +++ b/apps/irssi/src/core/channels.h @@ -19,12 +19,16 @@ struct _CHANNEL_REC { extern GSList *channels; /* Create new channel record */ -void channel_init(CHANNEL_REC *channel, int automatic); +void channel_init(CHANNEL_REC *channel, SERVER_REC *server, const char *name, + const char *visible_name, int automatic); void channel_destroy(CHANNEL_REC *channel); /* find channel by name, if `server' is NULL, search from all servers */ CHANNEL_REC *channel_find(SERVER_REC *server, const char *name); +void channel_change_name(CHANNEL_REC *channel, const char *name); +void channel_change_visible_name(CHANNEL_REC *channel, const char *name); + /* Send the auto send command to channel */ void channel_send_autocommands(CHANNEL_REC *channel); diff --git a/apps/irssi/src/core/chat-commands.c b/apps/irssi/src/core/chat-commands.c index 933cc3f5..aff0d8b7 100644 --- a/apps/irssi/src/core/chat-commands.c +++ b/apps/irssi/src/core/chat-commands.c @@ -69,7 +69,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, g_hash_table_lookup(optlist, proto->chatnet); conn = server_create_conn(proto != NULL ? proto->id : -1, addr, atoi(portstr), chatnet, password, nick); - if (proto == NULL) + if (proto == NULL) proto = chat_protocol_find_id(conn->chat_type); if (proto->not_initialized) { @@ -80,17 +80,24 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, return NULL; } + if (strchr(addr, '/') != NULL) + conn->unix_socket = TRUE; + if (g_hash_table_lookup(optlist, "6") != NULL) conn->family = AF_INET6; else if (g_hash_table_lookup(optlist, "4") != NULL) conn->family = AF_INET; + if(g_hash_table_lookup(optlist, "ssl") != NULL) + conn->use_ssl = TRUE; + if (g_hash_table_lookup(optlist, "!") != NULL) conn->no_autojoin_channels = TRUE; if (g_hash_table_lookup(optlist, "noproxy") != NULL) g_free_and_null(conn->proxy); + *rawlog_file = g_strdup(g_hash_table_lookup(optlist, "rawlog")); host = g_hash_table_lookup(optlist, "host"); @@ -105,7 +112,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, return conn; } -/* SYNTAX: CONNECT [-4 | -6] [-ircnet ] [-host ] +/* SYNTAX: CONNECT [-4 | -6] [-ssl] [-ircnet ] [-host ]

| [ [ []]] */ static void cmd_connect(const char *data) { @@ -115,7 +122,7 @@ static void cmd_connect(const char *data) conn = get_server_connect(data, NULL, &rawlog_file); if (conn != NULL) { - server = CHAT_PROTOCOL(conn)->server_connect(conn); + server = server_connect(conn); server_connect_unref(conn); if (server != NULL && rawlog_file != NULL) @@ -206,7 +213,7 @@ static void sig_default_command_server(const char *data, SERVER_REC *server, signal_emit("command server connect", 3, data, server, item); } -/* SYNTAX: SERVER [-4 | -6] [-ircnet ] [-host ] +/* SYNTAX: SERVER [-4 | -6] [-ssl] [-ircnet ] [-host ] [+]
| [ [ []]] */ static void cmd_server_connect(const char *data, SERVER_REC *server) { @@ -221,7 +228,7 @@ static void cmd_server_connect(const char *data, SERVER_REC *server) if (conn != NULL) { if (!plus_addr) update_reconnection(conn, server); - server = CHAT_PROTOCOL(conn)->server_connect(conn); + server = server_connect(conn); server_connect_unref(conn); if (server != NULL && rawlog_file != NULL) @@ -242,8 +249,11 @@ static void cmd_disconnect(const char *data, SERVER_REC *server) if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) return; - if (*tag != '\0' && strcmp(tag, "*") != 0) + if (*tag != '\0' && strcmp(tag, "*") != 0) { server = server_find_tag(tag); + if (server == NULL) + server = server_find_lookup_tag(tag); + } if (server == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); if (*msg == '\0') msg = (char *) settings_get_str("quit_message"); @@ -344,9 +354,8 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) target_type = IS_CHANNEL(item) ? SEND_TARGET_CHANNEL : SEND_TARGET_NICK; - target = item->name; - } - else if (g_hash_table_lookup(optlist, "channel") != NULL) + target = (char *) window_item_get_target(item); + } else if (g_hash_table_lookup(optlist, "channel") != NULL) target_type = SEND_TARGET_CHANNEL; else if (g_hash_table_lookup(optlist, "nick") != NULL) target_type = SEND_TARGET_NICK; @@ -434,7 +443,7 @@ void chat_commands_init(void) signal_add("default command server", (SIGNAL_FUNC) sig_default_command_server); - command_set_options("connect", "4 6 !! +host noproxy -rawlog"); + command_set_options("connect", "4 6 !! ssl +host noproxy -rawlog"); command_set_options("join", "invite"); command_set_options("msg", "channel nick"); } diff --git a/apps/irssi/src/core/chat-protocols.h b/apps/irssi/src/core/chat-protocols.h index ad8c64ba..8b7dc170 100644 --- a/apps/irssi/src/core/chat-protocols.h +++ b/apps/irssi/src/core/chat-protocols.h @@ -17,8 +17,10 @@ struct _CHAT_PROTOCOL_REC { SERVER_CONNECT_REC *(*create_server_connect) (void); void (*destroy_server_connect) (SERVER_CONNECT_REC *); - SERVER_REC *(*server_connect) (SERVER_CONNECT_REC *); - CHANNEL_REC *(*channel_create) (SERVER_REC *, const char *, int); + SERVER_REC *(*server_init_connect) (SERVER_CONNECT_REC *); + void (*server_connect) (SERVER_REC *); + CHANNEL_REC *(*channel_create) (SERVER_REC *, const char *, + const char *, int); QUERY_REC *(*query_create) (const char *, const char *, int); }; diff --git a/apps/irssi/src/core/chatnets.c b/apps/irssi/src/core/chatnets.c index 502d11d7..f7b0ec62 100644 --- a/apps/irssi/src/core/chatnets.c +++ b/apps/irssi/src/core/chatnets.c @@ -118,8 +118,7 @@ static void sig_connected(SERVER_REC *server) g_return_if_fail(IS_SERVER(server)); - if (server->connrec->chatnet == NULL || - server->session_reconnect) + if (server->connrec->chatnet == NULL || server->session_reconnect) return; rec = chatnet_find(server->connrec->chatnet); diff --git a/apps/irssi/src/core/commands.c b/apps/irssi/src/core/commands.c index 96a74008..0669dded 100644 --- a/apps/irssi/src/core/commands.c +++ b/apps/irssi/src/core/commands.c @@ -497,13 +497,17 @@ static char *cmd_get_quoted_param(char **data) quote = **data; (*data)++; pos = *data; - while (**data != '\0' && **data != quote) { + while (**data != '\0' && (**data != quote || (*data)[1] != ' ')) { if (**data == '\\' && (*data)[1] != '\0') g_memmove(*data, (*data)+1, strlen(*data)); (*data)++; } - if (**data != '\0') *(*data)++ = '\0'; + if (**data == quote) { + *(*data)++ = '\0'; + if (**data == ' ') + (*data)++; + } return pos; } @@ -653,11 +657,12 @@ typedef struct { GHashTable *options; } CMD_TEMP_REC; -static char *get_optional_channel(WI_ITEM_REC *active_item, char **data, - int require_name) +static const char * +get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name) { CHANNEL_REC *chanrec; - char *tmp, *origtmp, *channel, *ret; + const char *ret; + char *tmp, *origtmp, *channel; if (active_item == NULL) { /* no active channel in window, channel required */ @@ -670,10 +675,10 @@ static char *get_optional_channel(WI_ITEM_REC *active_item, char **data, if (strcmp(channel, "*") == 0 && !require_name) { /* "*" means active channel */ cmd_get_param(data); - ret = active_item->name; + ret = window_item_get_target(active_item); } else if (!server_ischannel(active_item->server, channel)) { /* we don't have channel parameter - use active channel */ - ret = active_item->name; + ret = window_item_get_target(active_item); } else { /* Find the channel first and use it's name if found. This allows automatic !channel -> !XXXXXchannel replaces. */ @@ -730,7 +735,7 @@ int cmd_get_params(const char *data, gpointer *free_me, int count, ...) /* optional channel as first parameter */ require_name = (count & PARAM_FLAG_OPTCHAN_NAME) == PARAM_FLAG_OPTCHAN_NAME; - arg = get_optional_channel(item, &datad, require_name); + arg = (char *) get_optional_channel(item, &datad, require_name); str = (char **) va_arg(args, char **); if (str != NULL) *str = arg; @@ -911,13 +916,8 @@ static void event_command(const char *line, SERVER_REC *server, void *item) g_return_if_fail(line != NULL); - if (*line == '\0') { - /* empty line, forget it. */ - signal_stop(); - return; - } - - cmdchar = strchr(settings_get_str("cmdchars"), *line); + cmdchar = *line == '\0' ? NULL : + strchr(settings_get_str("cmdchars"), *line); if (cmdchar != NULL && line[1] == ' ') { /* "/ text" = same as sending "text" to active channel. */ line += 2; diff --git a/apps/irssi/src/core/core.c b/apps/irssi/src/core/core.c index 0deb5090..b4e6d6e0 100644 --- a/apps/irssi/src/core/core.c +++ b/apps/irssi/src/core/core.c @@ -159,6 +159,7 @@ void core_init_paths(int argc, char *argv[]) { "home", 0, POPT_ARG_STRING, NULL, 0, "Irssi home dir location (~/.irssi)", "PATH" }, { NULL, '\0', 0, NULL } }; + const char *home; char *str; int n, len; @@ -191,11 +192,15 @@ void core_init_paths(int argc, char *argv[]) args_register(options); - if (irssi_dir == NULL) - irssi_dir = g_strdup_printf(IRSSI_DIR_FULL, get_home_dir()); + if (irssi_dir == NULL) { + home = g_get_home_dir(); + if (home == NULL) + home = "."; + + irssi_dir = g_strdup_printf(IRSSI_DIR_FULL, home); + } if (irssi_config_file == NULL) - irssi_config_file = g_strdup_printf("%s/"IRSSI_HOME_CONFIG, - irssi_dir); + irssi_config_file = g_strdup_printf("%s/"IRSSI_HOME_CONFIG, irssi_dir); session_set_binary(argv[0]); } diff --git a/apps/irssi/src/core/expandos.c b/apps/irssi/src/core/expandos.c index 2830d677..8f97836a 100644 --- a/apps/irssi/src/core/expandos.c +++ b/apps/irssi/src/core/expandos.c @@ -318,6 +318,17 @@ static char *expando_cmdchars(SERVER_REC *server, void *item, int *free_ret) return (char *) settings_get_str("cmdchars"); } +/* first CMDCHAR */ +static char *expando_cmdchar(SERVER_REC *server, void *item, int *free_ret) +{ + char str[2] = { 0, 0 }; + + str[0] = *settings_get_str("cmdchars"); + + *free_ret = TRUE; + return g_strdup(str); +} + /* modes of current channel, if any */ static char *expando_chanmode(SERVER_REC *server, void *item, int *free_ret) { @@ -358,7 +369,8 @@ static char *expando_serverversion(SERVER_REC *server, void *item, int *free_ret /* target of current input (channel or QUERY nickname) */ static char *expando_target(SERVER_REC *server, void *item, int *free_ret) { - return item == NULL ? "" : ((WI_ITEM_REC *) item)->name; + return item == NULL ? "" : + (char *) window_item_get_target((WI_ITEM_REC *) item); } /* client release date (in YYYYMMDD format) */ @@ -461,6 +473,12 @@ static char *expando_chatnet(SERVER_REC *server, void *item, int *free_ret) return server == NULL ? "" : server->connrec->chatnet; } +/* visible_name of current window item */ +static char *expando_itemname(SERVER_REC *server, void *item, int *free_ret) +{ + return item == NULL ? "" : ((WI_ITEM_REC *) item)->visible_name; +} + static void sig_message_public(SERVER_REC *server, const char *msg, const char *nick, const char *address, const char *target) @@ -578,12 +596,15 @@ void expandos_init(void) "", EXPANDO_NEVER, NULL); expando_create("K", expando_cmdchars, "setup changed", EXPANDO_ARG_NONE, NULL); + expando_create("k", expando_cmdchar, + "setup changed", EXPANDO_ARG_NONE, NULL); expando_create("M", expando_chanmode, "window changed", EXPANDO_ARG_NONE, "window item changed", EXPANDO_ARG_WINDOW, "channel mode changed", EXPANDO_ARG_WINDOW_ITEM, NULL); expando_create("N", expando_nick, "window changed", EXPANDO_ARG_NONE, + "window connect changed", EXPANDO_ARG_WINDOW, "window server changed", EXPANDO_ARG_WINDOW, "server nick changed", EXPANDO_ARG_SERVER, NULL); expando_create("O", expando_statusoper, @@ -611,6 +632,7 @@ void expandos_init(void) expando_create("W", expando_workdir, NULL); expando_create("Y", expando_realname, "window changed", EXPANDO_ARG_NONE, + "window connect changed", EXPANDO_ARG_WINDOW, "window server changed", EXPANDO_ARG_WINDOW, NULL); expando_create("Z", expando_time, "time changed", EXPANDO_ARG_NONE, NULL); @@ -630,10 +652,17 @@ void expandos_init(void) "query address changed", EXPANDO_ARG_WINDOW_ITEM, NULL); expando_create("tag", expando_servertag, "window changed", EXPANDO_ARG_NONE, + "window connect changed", EXPANDO_ARG_WINDOW, "window server changed", EXPANDO_ARG_WINDOW, NULL); expando_create("chatnet", expando_chatnet, "window changed", EXPANDO_ARG_NONE, + "window connect changed", EXPANDO_ARG_WINDOW, "window server changed", EXPANDO_ARG_WINDOW, NULL); + expando_create("itemname", expando_itemname, + "window changed", EXPANDO_ARG_NONE, + "window item changed", EXPANDO_ARG_WINDOW, + "window item name changed", EXPANDO_ARG_WINDOW_ITEM, + NULL); read_settings(); diff --git a/apps/irssi/src/core/ignore.c b/apps/irssi/src/core/ignore.c index cebbc3b0..99986dd2 100644 --- a/apps/irssi/src/core/ignore.c +++ b/apps/irssi/src/core/ignore.c @@ -264,7 +264,7 @@ static void ignore_set_config(IGNORE_REC *rec) CONFIG_NODE *node; char *levelstr; - if (rec->level == 0 || rec->unignore_time > 0) + if (rec->level == 0) return; node = iconfig_node_traverse("(ignores", TRUE); @@ -281,6 +281,9 @@ static void ignore_set_config(IGNORE_REC *rec) if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE); if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); if (rec->replies) iconfig_node_set_bool(node, "replies", TRUE); + if (rec->unignore_time != 0) + iconfig_node_set_int(node, "unignore_time", rec->unignore_time); + iconfig_node_set_str(node, "servertag", rec->servertag); if (rec->channels != NULL && *rec->channels != NULL) { node = config_node_section(node, "channels", NODE_TYPE_LIST); @@ -297,9 +300,6 @@ static int ignore_index(IGNORE_REC *find) for (tmp = ignores; tmp != NULL; tmp = tmp->next) { IGNORE_REC *rec = tmp->data; - if (rec->servertag != NULL) - continue; - if (rec == find) return index; index++; @@ -319,6 +319,7 @@ static void ignore_remove_config(IGNORE_REC *rec) static void ignore_init_rec(IGNORE_REC *rec) { #ifdef HAVE_REGEX_H + if (rec->regexp_compiled) regfree(&rec->preg); rec->regexp_compiled = !rec->regexp || rec->pattern == NULL ? FALSE : regcomp(&rec->preg, rec->pattern, REG_EXTENDED|REG_ICASE|REG_NOSUB) == 0; @@ -368,6 +369,7 @@ void ignore_update_rec(IGNORE_REC *rec) ignores = g_slist_append(ignores, rec); ignore_set_config(rec); + ignore_init_rec(rec); signal_emit("ignore changed", 1, rec); nickmatch_rebuild(nickmatch); } @@ -424,6 +426,8 @@ static void read_ignores(void) rec->regexp = config_node_get_bool(node, "regexp", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE); rec->replies = config_node_get_bool(node, "replies", FALSE); + rec->unignore_time = config_node_get_int(node, "unignore_time", 0); + rec->servertag = g_strdup(config_node_get_str(node, "servertag", 0)); node = config_node_section(node, "channels", -1); if (node != NULL) rec->channels = config_node_get_list(node); diff --git a/apps/irssi/src/core/ignore.h b/apps/irssi/src/core/ignore.h index 4056062e..4abfaca5 100644 --- a/apps/irssi/src/core/ignore.h +++ b/apps/irssi/src/core/ignore.h @@ -5,7 +5,9 @@ # include #endif -typedef struct { +typedef struct _IGNORE_REC IGNORE_REC; + +struct _IGNORE_REC { int level; /* ignore these levels */ char *mask; /* nick mask */ char *servertag; /* this is for autoignoring */ @@ -22,7 +24,7 @@ typedef struct { unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ regex_t preg; #endif -} IGNORE_REC; +}; extern GSList *ignores; diff --git a/apps/irssi/src/core/levels.h b/apps/irssi/src/core/levels.h index 2d7288f7..dec7afe7 100644 --- a/apps/irssi/src/core/levels.h +++ b/apps/irssi/src/core/levels.h @@ -7,35 +7,37 @@ needed..). */ /* Message levels */ -#define MSGLEVEL_CRAP 0x0000001 -#define MSGLEVEL_MSGS 0x0000002 -#define MSGLEVEL_PUBLIC 0x0000004 -#define MSGLEVEL_NOTICES 0x0000008 -#define MSGLEVEL_SNOTES 0x0000010 -#define MSGLEVEL_CTCPS 0x0000020 -#define MSGLEVEL_ACTIONS 0x0000040 -#define MSGLEVEL_JOINS 0x0000080 -#define MSGLEVEL_PARTS 0x0000100 -#define MSGLEVEL_QUITS 0x0000200 -#define MSGLEVEL_KICKS 0x0000400 -#define MSGLEVEL_MODES 0x0000800 -#define MSGLEVEL_TOPICS 0x0001000 -#define MSGLEVEL_WALLOPS 0x0002000 -#define MSGLEVEL_INVITES 0x0004000 -#define MSGLEVEL_NICKS 0x0008000 -#define MSGLEVEL_DCC 0x0010000 -#define MSGLEVEL_DCCMSGS 0x0020000 -#define MSGLEVEL_CLIENTNOTICE 0x0040000 -#define MSGLEVEL_CLIENTCRAP 0x0080000 -#define MSGLEVEL_CLIENTERROR 0x0100000 -#define MSGLEVEL_HILIGHT 0x0200000 +enum { + MSGLEVEL_CRAP = 0x0000001, + MSGLEVEL_MSGS = 0x0000002, + MSGLEVEL_PUBLIC = 0x0000004, + MSGLEVEL_NOTICES = 0x0000008, + MSGLEVEL_SNOTES = 0x0000010, + MSGLEVEL_CTCPS = 0x0000020, + MSGLEVEL_ACTIONS = 0x0000040, + MSGLEVEL_JOINS = 0x0000080, + MSGLEVEL_PARTS = 0x0000100, + MSGLEVEL_QUITS = 0x0000200, + MSGLEVEL_KICKS = 0x0000400, + MSGLEVEL_MODES = 0x0000800, + MSGLEVEL_TOPICS = 0x0001000, + MSGLEVEL_WALLOPS = 0x0002000, + MSGLEVEL_INVITES = 0x0004000, + MSGLEVEL_NICKS = 0x0008000, + MSGLEVEL_DCC = 0x0010000, + MSGLEVEL_DCCMSGS = 0x0020000, + MSGLEVEL_CLIENTNOTICE = 0x0040000, + MSGLEVEL_CLIENTCRAP = 0x0080000, + MSGLEVEL_CLIENTERROR = 0x0100000, + MSGLEVEL_HILIGHT = 0x0200000, -#define MSGLEVEL_ALL 0x03fffff + MSGLEVEL_ALL = 0x03fffff, -#define MSGLEVEL_NOHILIGHT 0x1000000 /* Don't highlight this message */ -#define MSGLEVEL_NO_ACT 0x2000000 /* Don't trigger channel activity */ -#define MSGLEVEL_NEVER 0x4000000 /* never ignore / never log */ -#define MSGLEVEL_LASTLOG 0x8000000 /* never ignore / never log */ + MSGLEVEL_NOHILIGHT = 0x1000000, /* Don't highlight this message */ + MSGLEVEL_NO_ACT = 0x2000000, /* Don't trigger channel activity */ + MSGLEVEL_NEVER = 0x4000000, /* never ignore / never log */ + MSGLEVEL_LASTLOG = 0x8000000 /* never ignore / never log */ +}; int level_get(const char *level); int level2bits(const char *level); diff --git a/apps/irssi/src/core/log.c b/apps/irssi/src/core/log.c index 9a131f96..e17f5c56 100644 --- a/apps/irssi/src/core/log.c +++ b/apps/irssi/src/core/log.c @@ -100,6 +100,8 @@ static char *log_filename(LOG_REC *log) int log_start_logging(LOG_REC *log) { + char *dir; + g_return_val_if_fail(log != NULL, FALSE); if (log->handle != -1) @@ -108,6 +110,16 @@ int log_start_logging(LOG_REC *log) /* Append/create log file */ g_free_not_null(log->real_fname); log->real_fname = log_filename(log); + + if (log->real_fname != NULL && + strcmp(log->real_fname, log->fname) != 0) { + /* path may contain variables (%time, $vars), + make sure the directory is created */ + dir = g_dirname(log->real_fname); + mkpath(dir, LOG_DIR_CREATE_MODE); + g_free(dir); + } + log->handle = log->real_fname == NULL ? -1 : open(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); @@ -165,7 +177,7 @@ void log_stop_logging(LOG_REC *log) static void log_rotate_check(LOG_REC *log) { - char *new_fname, *dir; + char *new_fname; g_return_if_fail(log != NULL); @@ -178,10 +190,6 @@ static void log_rotate_check(LOG_REC *log) log_stop_logging(log); signal_emit("log rotated", 1, log); - dir = g_dirname(new_fname); - mkpath(dir, LOG_DIR_CREATE_MODE); - g_free(dir); - log_start_logging(log); } g_free(new_fname); diff --git a/apps/irssi/src/core/log.h b/apps/irssi/src/core/log.h index 6ada7c65..da97fb2c 100644 --- a/apps/irssi/src/core/log.h +++ b/apps/irssi/src/core/log.h @@ -10,13 +10,16 @@ enum { typedef char *(*COLORIZE_FUNC)(const char *str); -typedef struct { +typedef struct _LOG_REC LOG_REC; +typedef struct _LOG_ITEM_REC LOG_ITEM_REC; + +struct _LOG_ITEM_REC { int type; char *name; char *servertag; -} LOG_ITEM_REC; +}; -typedef struct { +struct _LOG_REC { char *fname; /* file name, in strftime() format */ char *real_fname; /* the current expanded file name */ int handle; /* file handle */ @@ -31,7 +34,7 @@ typedef struct { unsigned int autoopen:1; /* automatically start logging at startup */ unsigned int failed:1; /* opening log failed last time */ unsigned int temp:1; /* don't save this to config file */ -} LOG_REC; +}; extern GSList *logs; diff --git a/apps/irssi/src/core/misc.c b/apps/irssi/src/core/misc.c index e030a514..886c40f1 100644 --- a/apps/irssi/src/core/misc.c +++ b/apps/irssi/src/core/misc.c @@ -26,7 +26,6 @@ #ifdef HAVE_REGEX_H # include #endif -#include typedef struct { int condition; @@ -449,25 +448,20 @@ int mkpath(const char *path, int mode) return 0; } -/* Get home directory */ -const char *get_home_dir(void) -{ - struct passwd *pw = getpwuid(getuid()); - if (!pw) { - if (g_getenv("HOME")) - return g_getenv("HOME"); - else - return "."; - } - return pw->pw_dir; -} - /* convert ~/ to $HOME */ char *convert_home(const char *path) { - return *path == '~' && (*(path+1) == '/' || *(path+1) == '\0') ? - g_strconcat((char *)get_home_dir(), path+1, NULL) : - g_strdup(path); + const char *home; + + if (*path == '~' && (*(path+1) == '/' || *(path+1) == '\0')) { + home = g_get_home_dir(); + if (home == NULL) + home = "."; + + return g_strconcat(home, path+1, NULL); + } else { + return g_strdup(path); + } } int g_istr_equal(gconstpointer v, gconstpointer v2) @@ -784,3 +778,19 @@ int expand_escape(const char **data) return strtol(digit, NULL, 8); } } + +/* Escape all '"', "'" and '\' chars with '\' */ +char *escape_string(const char *str) +{ + char *ret, *p; + + p = ret = g_malloc(strlen(str)*2+1); + while (*str != '\0') { + if (*str == '"' || *str == '\'' || *str == '\\') + *p++ = '\\'; + *p++ = *str++; + } + *p = '\0'; + + return ret; +} diff --git a/apps/irssi/src/core/misc.h b/apps/irssi/src/core/misc.h index a321bdfc..b9002c1c 100644 --- a/apps/irssi/src/core/misc.h +++ b/apps/irssi/src/core/misc.h @@ -61,10 +61,6 @@ int regexp_match(const char *str, const char *regexp); /* Create the directory and all it's parent directories */ int mkpath(const char *path, int mode); - -/* Get home directory */ -const char *get_home_dir(void); - /* convert ~/ to $HOME */ char *convert_home(const char *path); @@ -109,4 +105,7 @@ GSList *columns_sort_list(GSList *list, int rows); one after '\'. Returns the expanded character or -1 if error. */ int expand_escape(const char **data); +/* Escape all '"', "'" and '\' chars with '\' */ +char *escape_string(const char *str); + #endif diff --git a/apps/irssi/src/core/modules-load.c b/apps/irssi/src/core/modules-load.c index 69bdecdf..7b90d802 100644 --- a/apps/irssi/src/core/modules-load.c +++ b/apps/irssi/src/core/modules-load.c @@ -367,6 +367,15 @@ static void module_file_deinit_gmodule(MODULE_FILE_REC *file) g_module_close(file->gmodule); } +#else /* !HAVE_GMODULE - modules are not supported */ + +int module_load(const char *path, char **prefixes) +{ + return FALSE; +} + +#endif + void module_file_unload(MODULE_FILE_REC *file) { MODULE_REC *root; @@ -377,8 +386,10 @@ void module_file_unload(MODULE_FILE_REC *file) if (file->initialized) signal_emit("module unloaded", 2, file->root, file); +#ifdef HAVE_GMODULE if (file->gmodule != NULL) module_file_deinit_gmodule(file); +#endif g_free(file->name); g_free(file->defined_module_name); @@ -402,16 +413,3 @@ void module_unload(MODULE_REC *module) g_free(module->name); g_free(module); } - -#else /* !HAVE_GMODULE - modules are not supported */ - -int module_load(const char *path, char **prefixes) -{ - return FALSE; -} - -void module_unload(MODULE_REC *module) -{ -} - -#endif diff --git a/apps/irssi/src/core/net-nonblock.c b/apps/irssi/src/core/net-nonblock.c index 7392f429..6af87a96 100644 --- a/apps/irssi/src/core/net-nonblock.c +++ b/apps/irssi/src/core/net-nonblock.c @@ -186,7 +186,7 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe) { RESOLVED_IP_REC iprec; GIOChannel *handle; - IPADDR *ip; + IPADDR *ip; g_return_if_fail(rec != NULL); diff --git a/apps/irssi/src/core/network-openssl.c b/apps/irssi/src/core/network-openssl.c new file mode 100644 index 00000000..b9b7b4a0 --- /dev/null +++ b/apps/irssi/src/core/network-openssl.c @@ -0,0 +1,305 @@ +/* + network-ssl.c : SSL support + + Copyright (C) 2002 vjt + + 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 "module.h" +#include "network.h" + +#ifdef HAVE_OPENSSL + +#include +#include +#include +#include +#include + +/* ssl read */ +GIOError irssi_ssl_read(GIOChannel *, gchar *, guint, guint *); +/* ssl write */ +GIOError irssi_ssl_write(GIOChannel *, gchar *, guint, guint*); +/* ssl seek */ +GIOError irssi_ssl_seek(GIOChannel *, gint, GSeekType); +/* ssl close */ +void irssi_ssl_close(GIOChannel *); +#if GLIB_MAJOR_VERSION < 2 +/* ssl create watch */ +guint irssi_ssl_create_watch(GIOChannel *, gint, GIOCondition, GIOFunc, gpointer, GDestroyNotify); +#else +GSource *irssi_ssl_create_watch(GIOChannel *, GIOCondition); +#endif +/* ssl free */ +void irssi_ssl_free(GIOChannel *); + +/* ssl i/o channel object */ +typedef struct +{ + GIOChannel pad; + gint fd; + GIOChannel *giochan; + SSL *ssl; + X509 *cert; +} GIOSSLChannel; + +/* ssl function pointers */ +GIOFuncs irssi_ssl_channel_funcs = +{ + irssi_ssl_read, + irssi_ssl_write, + irssi_ssl_seek, + irssi_ssl_close, + irssi_ssl_create_watch, + irssi_ssl_free +}; + +SSL_CTX *ssl_ctx = NULL; + +#ifdef G_CAN_INLINE +G_INLINE_FUNC +#endif +gint ssl_errno(gint e) +{ + switch(e) + { + case EINVAL: + return G_IO_ERROR_INVAL; + case EINTR: + case EAGAIN: + return G_IO_ERROR_AGAIN; + default: + return G_IO_ERROR_INVAL; + } + /*UNREACH*/ + return -1; +} + +gboolean irssi_ssl_cert_step(GIOSSLChannel *chan) +{ + gint err; + switch(err = SSL_do_handshake(chan->ssl)) + { + case 1: + if(!(chan->cert = SSL_get_peer_certificate(chan->ssl))) + { + g_warning("SSL server supplied no certificate"); + return G_IO_ERROR_INVAL; + } + return G_IO_ERROR_NONE; + default: + if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) + return G_IO_ERROR_AGAIN; + return ssl_errno(errno); + } + /*UNREACH*/ + return -1; +} + +GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint *ret) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + gint err; + + if(chan->cert == NULL) + { + gint cert_err = irssi_ssl_cert_step(chan); + if(cert_err != G_IO_ERROR_NONE) + return cert_err; + } + + err = SSL_read(chan->ssl, buf, len); + if(err < 0) + { + *ret = 0; + if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) + return G_IO_ERROR_AGAIN; + return ssl_errno(errno); + } + else + { + *ret = err; + return G_IO_ERROR_NONE; + } + /*UNREACH*/ + return -1; +} + +GIOError irssi_ssl_write(GIOChannel *handle, gchar *buf, guint len, guint *ret) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + gint err; + + if(chan->cert == NULL) + { + gint cert_err = irssi_ssl_cert_step(chan); + if(cert_err != G_IO_ERROR_NONE) + return cert_err; + } + + + err = SSL_write(chan->ssl, (const char *)buf, len); + if(err < 0) + { + *ret = 0; + if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) + return G_IO_ERROR_AGAIN; + return ssl_errno(errno); + } + else + { + *ret = err; + return G_IO_ERROR_NONE; + } + /*UNREACH*/ + return -1; +} + +GIOError irssi_ssl_seek(GIOChannel *handle, gint offset, GSeekType type) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + GIOError e; + e = g_io_channel_seek(chan->giochan, offset, type); + return (e == G_IO_ERROR_NONE) ? G_IO_ERROR_NONE : G_IO_ERROR_INVAL; +} + +void irssi_ssl_close(GIOChannel *handle) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + g_io_channel_close(chan->giochan); +} + +#if GLIB_MAJOR_VERSION < 2 +guint irssi_ssl_create_watch(GIOChannel *handle, gint priority, GIOCondition cond, + GIOFunc func, gpointer data, GDestroyNotify notify) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + + return chan->giochan->funcs->io_add_watch(handle, priority, cond, func, data, notify); +} +#else +GSource *irssi_ssl_create_watch(GIOChannel *handle, GIOCondition cond) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + + return chan->giochan->funcs->io_create_watch(handle, cond); +} +#endif + +void irssi_ssl_free(GIOChannel *handle) +{ + GIOSSLChannel *chan = (GIOSSLChannel *)handle; + g_io_channel_unref(chan->giochan); + SSL_free(chan->ssl); + g_free(chan); +} + +gboolean irssi_ssl_init(void) +{ + SSL_library_init(); + SSL_load_error_strings(); + + ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + if(!ssl_ctx) + { + g_error("Initialization of the SSL library failed"); + return FALSE; + } + + return TRUE; + +} + +GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle) +{ + GIOSSLChannel *chan; + GIOChannel *gchan; + int err, fd; + SSL *ssl; + X509 *cert = NULL; + + g_return_val_if_fail(handle != NULL, NULL); + + if(!ssl_ctx && !irssi_ssl_init()) + return NULL; + + if(!(fd = g_io_channel_unix_get_fd(handle))) + return NULL; + + if(!(ssl = SSL_new(ssl_ctx))) + { + g_warning("Failed to allocate SSL structure"); + return NULL; + } + + if(!(err = SSL_set_fd(ssl, fd))) + { + g_warning("Failed to associate socket to SSL stream"); + return NULL; + } + + if((err = SSL_connect(ssl)) <= 0) + { + switch(err = SSL_get_error(ssl, err)) + { + case SSL_ERROR_SYSCALL: + if(errno == EINTR || errno == EAGAIN) + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + break; + default: + return NULL; + } + } + else if(!(cert = SSL_get_peer_certificate(ssl))) + { + g_warning("SSL server supplied no certificate"); + return NULL; + } + else + X509_free(cert); + + chan = g_new0(GIOSSLChannel, 1); + chan->fd = fd; + chan->giochan = handle; + chan->ssl = ssl; + chan->cert = cert; + g_io_channel_ref(handle); + + gchan = (GIOChannel *)chan; + gchan->funcs = &irssi_ssl_channel_funcs; + g_io_channel_init(gchan); + + return gchan; +} + +GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip) +{ + GIOChannel *gret = net_connect_ip(ip, port, my_ip); + gret = irssi_ssl_get_iochannel(gret); + return gret; +} + +#else /* HAVE_OPENSSL */ + +GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip) +{ + g_warning("Connection failed: SSL support not enabled in this build."); + errno = ENOSYS; + return NULL; +} + +#endif /* ! HAVE_OPENSSL */ diff --git a/apps/irssi/src/core/network.c b/apps/irssi/src/core/network.c index e53b0189..6b2ceab4 100644 --- a/apps/irssi/src/core/network.c +++ b/apps/irssi/src/core/network.c @@ -21,6 +21,8 @@ #include "module.h" #include "network.h" +#include + #ifndef INADDR_NONE # define INADDR_NONE INADDR_BROADCAST #endif @@ -217,7 +219,42 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) #endif { + int old_errno = errno; close(handle); + errno = old_errno; + return NULL; + } + + return g_io_channel_new(handle); +} + +/* Connect to named UNIX socket */ +GIOChannel *net_connect_unix(const char *path) +{ + struct sockaddr_un sa; + int handle, ret; + + /* create the socket */ + handle = socket(PF_UNIX, SOCK_STREAM, 0); + if (handle == -1) + return NULL; + + /* set socket options */ +#ifndef WIN32 + fcntl(handle, F_SETFL, O_NONBLOCK); +#endif + + /* connect */ + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + strncpy(sa.sun_path, path, sizeof(sa.sun_path)-1); + sa.sun_path[sizeof(sa.sun_path)-1] = '\0'; + + ret = connect(handle, (struct sockaddr *) &sa, sizeof(sa)); + if (ret < 0 && errno != EINPROGRESS) { + int old_errno = errno; + close(handle); + errno = old_errno; return NULL; } @@ -472,12 +509,16 @@ int net_ip2host(IPADDR *ip, char *host) #else unsigned long ip4; - ip4 = ntohl(ip->ip.s_addr); - g_snprintf(host, MAX_IP_LEN, "%lu.%lu.%lu.%lu", - (ip4 & 0xff000000UL) >> 24, - (ip4 & 0x00ff0000) >> 16, - (ip4 & 0x0000ff00) >> 8, - (ip4 & 0x000000ff)); + if (ip->family != AF_INET) { + strcpy(host, "0.0.0.0"); + } else { + ip4 = ntohl(ip->ip.s_addr); + g_snprintf(host, MAX_IP_LEN, "%lu.%lu.%lu.%lu", + (ip4 & 0xff000000UL) >> 24, + (ip4 & 0x00ff0000) >> 16, + (ip4 & 0x0000ff00) >> 8, + (ip4 & 0x000000ff)); + } #endif return 0; } @@ -486,15 +527,16 @@ int net_host2ip(const char *host, IPADDR *ip) { unsigned long addr; -#ifdef HAVE_IPV6 if (strchr(host, ':') != NULL) { /* IPv6 */ ip->family = AF_INET6; +#ifdef HAVE_IPV6 if (inet_pton(AF_INET6, host, &ip->ip) == 0) return -1; - } else +#else + ip->ip.s_addr = 0; #endif - { + } else { /* IPv4 */ ip->family = AF_INET; #ifdef HAVE_INET_ATON diff --git a/apps/irssi/src/core/network.h b/apps/irssi/src/core/network.h index 4c25740f..c6b08f9f 100644 --- a/apps/irssi/src/core/network.h +++ b/apps/irssi/src/core/network.h @@ -44,8 +44,12 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); +/* Connect to socket with ip address and SSL*/ +GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip); /* Connect to socket with ip address */ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); +/* Connect to named UNIX socket */ +GIOChannel *net_connect_unix(const char *path); /* Disconnect socket */ void net_disconnect(GIOChannel *handle); /* Try to let the other side close the connection, if it still isn't diff --git a/apps/irssi/src/core/queries.c b/apps/irssi/src/core/queries.c index 8ae994a2..799a6320 100644 --- a/apps/irssi/src/core/queries.c +++ b/apps/irssi/src/core/queries.c @@ -27,6 +27,11 @@ GSList *queries; +static const char *query_get_target(WI_ITEM_REC *item) +{ + return ((QUERY_REC *) item)->name; +} + void query_init(QUERY_REC *query, int automatic) { g_return_if_fail(query != NULL); @@ -37,8 +42,10 @@ void query_init(QUERY_REC *query, int automatic) MODULE_DATA_INIT(query); query->type = module_get_uniq_id_str("WINDOW ITEM TYPE", "QUERY"); query->destroy = (void (*) (WI_ITEM_REC *)) query_destroy; + query->get_target = query_get_target; query->createtime = time(NULL); query->last_unread_msg = time(NULL); + query->visible_name = g_strdup(query->name); if (query->server_tag != NULL) { query->server = server_find_tag(query->server_tag); @@ -69,6 +76,7 @@ void query_destroy(QUERY_REC *query) g_free_not_null(query->hilight_color); g_free_not_null(query->server_tag); g_free_not_null(query->address); + g_free(query->visible_name); g_free(query->name); query->type = 0; @@ -124,6 +132,10 @@ void query_change_nick(QUERY_REC *query, const char *nick) oldnick = query->name; query->name = g_strdup(nick); + + g_free(query->visible_name); + query->visible_name = g_strdup(nick); + signal_emit("query nick changed", 2, query, oldnick); signal_emit("window item name changed", 1, query); g_free(oldnick); diff --git a/apps/irssi/src/core/query-rec.h b/apps/irssi/src/core/query-rec.h index fc08d2ef..ddb85ba4 100644 --- a/apps/irssi/src/core/query-rec.h +++ b/apps/irssi/src/core/query-rec.h @@ -2,6 +2,7 @@ #include "window-item-rec.h" +char *name; char *address; char *server_tag; time_t last_unread_msg; diff --git a/apps/irssi/src/core/server-connect-rec.h b/apps/irssi/src/core/server-connect-rec.h index a59880e4..ce1e48a4 100644 --- a/apps/irssi/src/core/server-connect-rec.h +++ b/apps/irssi/src/core/server-connect-rec.h @@ -23,8 +23,12 @@ char *nick; char *username; char *realname; +GIOChannel *connect_handle; /* connect using this handle */ + /* when reconnecting, the old server status */ unsigned int reconnection:1; /* we're trying to reconnect */ unsigned int no_autojoin_channels:1; /* don't autojoin any channels */ +unsigned int unix_socket:1; /* Connect using named unix socket */ +unsigned int use_ssl:1; /* this connection uses SSL */ char *channels; char *away_reason; diff --git a/apps/irssi/src/core/server-setup-rec.h b/apps/irssi/src/core/server-setup-rec.h index f94ec9ae..d04fa1fe 100644 --- a/apps/irssi/src/core/server-setup-rec.h +++ b/apps/irssi/src/core/server-setup-rec.h @@ -18,5 +18,6 @@ unsigned int no_proxy:1; unsigned int last_failed:1; /* if last connection attempt failed */ unsigned int banned:1; /* if we're banned from this server */ unsigned int dns_error:1; /* DNS said the host doesn't exist */ +unsigned int use_ssl:1; /* this connection uses SSL */ GHashTable *module_data; diff --git a/apps/irssi/src/core/servers-reconnect.c b/apps/irssi/src/core/servers-reconnect.c index 86d900a6..cc053150 100644 --- a/apps/irssi/src/core/servers-reconnect.c +++ b/apps/irssi/src/core/servers-reconnect.c @@ -44,6 +44,17 @@ void reconnect_save_status(SERVER_CONNECT_REC *conn, SERVER_REC *server) conn->away_reason = !server->usermode_away ? NULL : g_strdup(server->away_reason); + if (!server->connected) { + /* default to channels/usermode from connect record + since server isn't fully connected yet */ + g_free_not_null(conn->channels); + conn->channels = server->connrec->no_autojoin_channels ? NULL : + g_strdup(server->connrec->channels); + + g_free_not_null(conn->channels); + conn->channels = g_strdup(server->connrec->channels); + } + signal_emit("server reconnect save status", 2, conn, server); } @@ -99,7 +110,7 @@ static int server_reconnect_timeout(void) conn = rec->conn; server_connect_ref(conn); server_reconnect_destroy(rec); - CHAT_PROTOCOL(conn)->server_connect(conn); + server_connect(conn); server_connect_unref(conn); } } @@ -164,6 +175,8 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) dest->away_reason = g_strdup(src->away_reason); dest->no_autojoin_channels = src->no_autojoin_channels; + dest->use_ssl = src->use_ssl; + return dest; } @@ -208,8 +221,8 @@ static void sig_reconnect(SERVER_REC *server) sserver->last_connect = server->connect_time == 0 ? time(NULL) : server->connect_time; sserver->last_failed = !server->connected; - if (server->banned) sserver->banned = TRUE; - if (server->dns_error) sserver->dns_error = TRUE; + sserver->banned = server->banned; + sserver->dns_error = server->dns_error; } if (sserver == NULL || conn->chatnet == NULL) { @@ -329,36 +342,50 @@ static void reconnect_all(void) while (list != NULL) { conn = list->data; - CHAT_PROTOCOL(conn)->server_connect(conn); + server_connect(conn); server_connect_unref(conn); list = g_slist_remove(list, conn); } } -/* SYNTAX: RECONNECT */ +/* SYNTAX: RECONNECT [] */ static void cmd_reconnect(const char *data, SERVER_REC *server) { SERVER_CONNECT_REC *conn; RECONNECT_REC *rec; - int tag; + char *tag, *msg; + void *free_arg; + int tagnum; + + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) + return; + + if (*tag != '\0' && strcmp(tag, "*") != 0) + server = server_find_tag(tag); - if (*data == '\0' && server != NULL) { - /* reconnect back to same server */ + if (server != NULL) { + /* reconnect connected server */ conn = server_connect_copy_skeleton(server->connrec, TRUE); if (server->connected) reconnect_save_status(conn, server); - signal_emit("command disconnect", 2, "* Reconnecting", server); + + msg = g_strconcat("* ", *msg == '\0' ? + "Reconnecting" : msg, NULL); + signal_emit("command disconnect", 2, msg, server); + g_free(msg); conn->reconnection = TRUE; - CHAT_PROTOCOL(conn)->server_connect(conn); + server_connect(conn); server_connect_unref(conn); + cmd_params_free(free_arg); return; } - if (g_strcasecmp(data, "all") == 0) { + if (g_strcasecmp(tag, "all") == 0) { /* reconnect all servers in reconnect queue */ reconnect_all(); + cmd_params_free(free_arg); return; } @@ -371,20 +398,21 @@ static void cmd_reconnect(const char *data, SERVER_REC *server) if (g_strncasecmp(data, "RECON-", 6) == 0) data += 6; - tag = atoi(data); - rec = tag <= 0 ? NULL : reconnect_find_tag(tag); + tagnum = atoi(tag); + rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum); + } - if (rec == NULL) { - signal_emit("server reconnect not found", 1, data); - return; - } + if (rec == NULL) { + signal_emit("server reconnect not found", 1, data); + } else { + conn = rec->conn; + server_connect_ref(conn); + server_reconnect_destroy(rec); + server_connect(conn); + server_connect_unref(conn); } - conn = rec->conn; - server_connect_ref(conn); - server_reconnect_destroy(rec); - CHAT_PROTOCOL(conn)->server_connect(conn); - server_connect_unref(conn); + cmd_params_free(free_arg); } static void cmd_disconnect(const char *data, SERVER_REC *server) @@ -423,7 +451,7 @@ static void read_settings(void) void servers_reconnect_init(void) { - settings_add_int("server", "server_reconnect_time", 3000); + settings_add_int("server", "server_reconnect_time", 300); reconnects = NULL; last_reconnect_tag = 0; diff --git a/apps/irssi/src/core/servers-setup.c b/apps/irssi/src/core/servers-setup.c index d16f93a7..6bdafb80 100644 --- a/apps/irssi/src/core/servers-setup.c +++ b/apps/irssi/src/core/servers-setup.c @@ -163,6 +163,8 @@ static void server_setup_fill_server(SERVER_CONNECT_REC *conn, conn->family = sserver->family; if (sserver->port > 0 && conn->port <= 0) conn->port = sserver->port; + conn->use_ssl = sserver->use_ssl; + server_setup_fill_reconn(conn, sserver); signal_emit("server setup fill server", 2, conn, sserver); @@ -391,6 +393,7 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) (g_strcasecmp(family, "inet") == 0 ? AF_INET : 0); rec->address = g_strdup(server); rec->password = g_strdup(config_node_get_str(node, "password", NULL)); + rec->use_ssl = config_node_get_bool(node, "use_ssl", FALSE); rec->port = port; rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE); rec->no_proxy = config_node_get_bool(node, "no_proxy", FALSE); @@ -420,6 +423,7 @@ static void server_setup_save(SERVER_SETUP_REC *rec) iconfig_node_set_int(node, "port", rec->port); iconfig_node_set_str(node, "password", rec->password); + iconfig_node_set_bool(node, "use_ssl", rec->use_ssl); iconfig_node_set_str(node, "own_host", rec->own_host); iconfig_node_set_str(node, "family", diff --git a/apps/irssi/src/core/servers.c b/apps/irssi/src/core/servers.c index 1e5c0b84..92a6e5ac 100644 --- a/apps/irssi/src/core/servers.c +++ b/apps/irssi/src/core/servers.c @@ -110,6 +110,7 @@ static char *server_create_tag(SERVER_CONNECT_REC *conn) server_create_address_tag(conn->address); if (conn->tag != NULL && server_find_tag(conn->tag) == NULL && + server_find_lookup_tag(conn->tag) == NULL && strncmp(conn->tag, tag, strlen(tag)) == 0) { /* use the existing tag if it begins with the same ID - this is useful when you have several connections to @@ -123,8 +124,13 @@ static char *server_create_tag(SERVER_CONNECT_REC *conn) /* then just append numbers after tag until unused is found.. */ str = g_string_new(tag); - for (num = 2; server_find_tag(str->str) != NULL; num++) + + num = 2; + while (server_find_tag(str->str) != NULL || + server_find_lookup_tag(str->str) != NULL) { g_string_sprintf(str, "%s%d", tag, num); + num++; + } g_free(tag); tag = str->str; @@ -161,16 +167,52 @@ static void server_connect_callback_init(SERVER_REC *server, GIOChannel *handle) server_connect_finished(server); } -static void server_connect_callback_readpipe(SERVER_REC *server) +static void server_real_connect(SERVER_REC *server, IPADDR *ip, + const char *unix_socket) { - SERVER_CONNECT_REC *conn; - RESOLVED_IP_REC iprec; GIOChannel *handle; - IPADDR *ip, *own_ip; - const char *errormsg; + IPADDR *own_ip; int port; - g_return_if_fail(IS_SERVER(server)); + g_return_if_fail(ip != NULL || unix_socket != NULL); + + signal_emit("server connecting", 2, server, ip); + + if (ip != NULL) { + own_ip = ip == NULL ? NULL : + (IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : + server->connrec->own_ip4); + port = server->connrec->proxy != NULL ? + server->connrec->proxy_port : server->connrec->port; + handle = server->connrec->use_ssl ? + net_connect_ip_ssl(ip, port, own_ip) : + net_connect_ip(ip, port, own_ip); + } else { + handle = net_connect_unix(unix_socket); + } + + if (handle == NULL) { + /* failed */ + if (server->connrec->use_ssl && errno == ENOSYS) + server->no_reconnect = TRUE; + + server->connection_lost = TRUE; + server_connect_failed(server, g_strerror(errno)); + } else { + server->handle = net_sendbuffer_create(handle, 0); + server->connect_tag = + g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ, + (GInputFunction) + server_connect_callback_init, + server); + } +} + +static void server_connect_callback_readpipe(SERVER_REC *server) +{ + RESOLVED_IP_REC iprec; + IPADDR *ip; + const char *errormsg; g_source_remove(server->connect_tag); server->connect_tag = -1; @@ -204,33 +246,18 @@ static void server_connect_callback_readpipe(SERVER_REC *server) &iprec.ip6 : &iprec.ip4; } - conn = server->connrec; - port = conn->proxy != NULL ? conn->proxy_port : conn->port; - own_ip = ip == NULL ? NULL : - (IPADDR_IS_V6(ip) ? conn->own_ip6 : conn->own_ip4); - - handle = NULL; if (ip != NULL) { - signal_emit("server connecting", 2, server, ip); - if (server->handle == NULL) - handle = net_connect_ip(ip, port, own_ip); - else - handle = net_sendbuffer_handle(server->handle); - } - - if (handle == NULL) { - /* failed */ - if (ip == NULL && (iprec.error == 0 || - net_hosterror_notfound(iprec.error))) { - /* IP wasn't found for the host, don't try to reconnect - back to this server */ + /* host lookup ok */ + server_real_connect(server, ip, NULL); + errormsg = NULL; + } else { + if (iprec.error == 0 || net_hosterror_notfound(iprec.error)) { + /* IP wasn't found for the host, don't try to + reconnect back to this server */ server->dns_error = TRUE; } - if (ip != NULL) { - /* connect() failed */ - errormsg = g_strerror(errno); - } else if (iprec.error == 0) { + if (iprec.error == 0) { /* forced IPv4 or IPv6 address but it wasn't found */ errormsg = server->connrec->family == AF_INET ? "IPv4 address not found for host" : @@ -240,18 +267,24 @@ static void server_connect_callback_readpipe(SERVER_REC *server) errormsg = iprec.errorstr != NULL ? iprec.errorstr : "Host lookup failed"; } + server->connection_lost = TRUE; server_connect_failed(server, errormsg); - g_free_not_null(iprec.errorstr); - return; } - if (server->handle == NULL) - server->handle = net_sendbuffer_create(handle, 0); - server->connect_tag = - g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ, - (GInputFunction) server_connect_callback_init, - server); + g_free(iprec.errorstr); +} + +SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) +{ + CHAT_PROTOCOL_REC *proto; + SERVER_REC *server; + + proto = CHAT_PROTOCOL(conn); + server = proto->server_init_connect(conn); + proto->server_connect(server); + + return server; } /* initializes server record but doesn't start connecting */ @@ -270,18 +303,19 @@ void server_connect_init(SERVER_REC *server) g_free_not_null(server->connrec->username); str = g_get_user_name(); - if (*str == '\0') str = "-"; + if (*str == '\0') str = "unknown"; server->connrec->username = g_strdup(str); } if (server->connrec->realname == NULL || *server->connrec->realname == '\0') { g_free_not_null(server->connrec->realname); str = g_get_real_name(); - if (*str == '\0') str = "-"; + if (*str == '\0') str = server->connrec->username; server->connrec->realname = g_strdup(str); } server->tag = server_create_tag(server->connrec); + server->connect_tag = -1; } /* starts connecting to server */ @@ -291,48 +325,63 @@ int server_start_connect(SERVER_REC *server) int fd[2]; g_return_val_if_fail(server != NULL, FALSE); - if (server->connrec->port <= 0) return FALSE; - - server_connect_init(server); - - if (pipe(fd) != 0) { - g_warning("server_connect(): pipe() failed."); - g_free(server->tag); - g_free(server->nick); + if (!server->connrec->unix_socket && server->connrec->port <= 0) return FALSE; - } - server->connect_pipe[0] = g_io_channel_unix_new(fd[0]); - server->connect_pipe[1] = g_io_channel_unix_new(fd[1]); - - connect_address = server->connrec->proxy != NULL ? - server->connrec->proxy : server->connrec->address; - server->connect_pid = - net_gethostbyname_nonblock(connect_address, - server->connect_pipe[1]); - server->connect_tag = - g_input_add(server->connect_pipe[0], G_INPUT_READ, - (GInputFunction) server_connect_callback_readpipe, - server); server->rawlog = rawlog_create(); - lookup_servers = g_slist_append(lookup_servers, server); + if (server->connrec->connect_handle != NULL) { + /* already connected */ + GIOChannel *handle = server->connrec->connect_handle; + + server->connrec->connect_handle = NULL; + server->handle = net_sendbuffer_create(handle, 0); + server_connect_finished(server); + } else if (server->connrec->unix_socket) { + /* connect with unix socket */ + server_real_connect(server, NULL, server->connrec->address); + } else { + /* resolve host name */ + if (pipe(fd) != 0) { + g_warning("server_connect(): pipe() failed."); + g_free(server->tag); + g_free(server->nick); + return FALSE; + } + + server->connect_pipe[0] = g_io_channel_unix_new(fd[0]); + server->connect_pipe[1] = g_io_channel_unix_new(fd[1]); + + connect_address = server->connrec->proxy != NULL ? + server->connrec->proxy : server->connrec->address; + server->connect_pid = + net_gethostbyname_nonblock(connect_address, + server->connect_pipe[1]); + server->connect_tag = + g_input_add(server->connect_pipe[0], G_INPUT_READ, + (GInputFunction) + server_connect_callback_readpipe, + server); - signal_emit("server looking", 1, server); + lookup_servers = g_slist_append(lookup_servers, server); + + signal_emit("server looking", 1, server); + } return TRUE; } static int server_remove_channels(SERVER_REC *server) { - GSList *tmp; + GSList *tmp, *next; int found; g_return_val_if_fail(server != NULL, FALSE); found = FALSE; - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + for (tmp = server->channels; tmp != NULL; tmp = next) { CHANNEL_REC *channel = tmp->data; + next = tmp->next; channel_destroy(channel); found = TRUE; } @@ -440,6 +489,16 @@ SERVER_REC *server_find_tag(const char *tag) return server; } + return NULL; +} + +SERVER_REC *server_find_lookup_tag(const char *tag) +{ + GSList *tmp; + + g_return_val_if_fail(tag != NULL, NULL); + if (*tag == '\0') return NULL; + for (tmp = lookup_servers; tmp != NULL; tmp = tmp->next) { SERVER_REC *server = tmp->data; @@ -486,6 +545,9 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) CHAT_PROTOCOL(conn)->destroy_server_connect(conn); + if (conn->connect_handle != NULL) + net_disconnect(conn->connect_handle); + g_free_not_null(conn->proxy); g_free_not_null(conn->proxy_string); g_free_not_null(conn->proxy_string_after); diff --git a/apps/irssi/src/core/servers.h b/apps/irssi/src/core/servers.h index dddde263..d6afbdf5 100644 --- a/apps/irssi/src/core/servers.h +++ b/apps/irssi/src/core/servers.h @@ -46,6 +46,7 @@ void server_ref(SERVER_REC *server); int server_unref(SERVER_REC *server); SERVER_REC *server_find_tag(const char *tag); +SERVER_REC *server_find_lookup_tag(const char *tag); SERVER_REC *server_find_chatnet(const char *chatnet); /* starts connecting to server */ @@ -53,6 +54,8 @@ int server_start_connect(SERVER_REC *server); void server_connect_ref(SERVER_CONNECT_REC *conn); void server_connect_unref(SERVER_CONNECT_REC *conn); +SERVER_REC *server_connect(SERVER_CONNECT_REC *conn); + /* initializes server record but doesn't start connecting */ void server_connect_init(SERVER_REC *server); /* Connection to server finished, fill the rest of the fields */ diff --git a/apps/irssi/src/core/session.c b/apps/irssi/src/core/session.c index b5419134..004cd4f7 100644 --- a/apps/irssi/src/core/session.c +++ b/apps/irssi/src/core/session.c @@ -146,6 +146,7 @@ static void session_save_channel(CHANNEL_REC *channel, CONFIG_REC *config, node = config_node_section(node, NULL, NODE_TYPE_BLOCK); config_node_set_str(config, node, "name", channel->name); + config_node_set_str(config, node, "visible_name", channel->visible_name); config_node_set_str(config, node, "topic", channel->topic); config_node_set_str(config, node, "topic_by", channel->topic_by); config_node_set_int(config, node, "topic_time", channel->topic_time); @@ -181,6 +182,8 @@ static void session_save_server(SERVER_REC *server, CONFIG_REC *config, config_node_set_str(config, node, "password", server->connrec->password); config_node_set_str(config, node, "nick", server->nick); + config_node_set_bool(config, node, "use_ssl", server->connrec->use_ssl); + handle = g_io_channel_unix_get_fd(net_sendbuffer_handle(server->handle)); config_node_set_int(config, node, "handle", handle); @@ -215,13 +218,14 @@ static void session_restore_channel_nicks(CHANNEL_REC *channel, static void session_restore_channel(SERVER_REC *server, CONFIG_NODE *node) { CHANNEL_REC *channel; - const char *name; + const char *name, *visible_name; name = config_node_get_str(node, "name", NULL); if (name == NULL) return; - channel = CHAT_PROTOCOL(server)->channel_create(server, name, TRUE); + visible_name = config_node_get_str(node, "visible_name", NULL); + channel = CHAT_PROTOCOL(server)->channel_create(server, name, visible_name, TRUE); channel->topic = g_strdup(config_node_get_str(node, "topic", NULL)); channel->topic_by = g_strdup(config_node_get_str(node, "topic_by", NULL)); channel->topic_time = config_node_get_int(node, "topic_time", 0); @@ -274,12 +278,13 @@ static void session_restore_server(CONFIG_NODE *node) chatnet, password, nick); if (conn != NULL) { conn->reconnection = TRUE; + conn->connect_handle = g_io_channel_unix_new(handle); - server = proto->server_connect(conn); - server->handle = net_sendbuffer_create(g_io_channel_unix_new(handle), 0); + server = proto->server_init_connect(conn); server->session_reconnect = TRUE; - signal_emit("session restore server", 2, server, node); + + proto->server_connect(server); } } diff --git a/apps/irssi/src/core/settings.h b/apps/irssi/src/core/settings.h index e0df975a..fdff3801 100644 --- a/apps/irssi/src/core/settings.h +++ b/apps/irssi/src/core/settings.h @@ -19,7 +19,6 @@ typedef struct { #define iconfig_get_str(a, b, c) config_get_str(mainconfig, a, b, c) #define iconfig_get_int(a, b, c) config_get_int(mainconfig, a, b, c) #define iconfig_get_bool(a, b, c) config_get_bool(mainconfig, a, b, c) -#define iconfig_list_find(a, b, c, d) config_list_find(mainconfig, a, b, c, d) #define iconfig_set_str(a, b, c) config_set_str(mainconfig, a, b, c) #define iconfig_set_int(a, b, c) config_set_int(mainconfig, a, b, c) diff --git a/apps/irssi/src/core/window-item-rec.h b/apps/irssi/src/core/window-item-rec.h index eeb465f4..d7b6f7db 100644 --- a/apps/irssi/src/core/window-item-rec.h +++ b/apps/irssi/src/core/window-item-rec.h @@ -6,7 +6,7 @@ GHashTable *module_data; void *window; STRUCT_SERVER_REC *server; -char *name; +char *visible_name; time_t createtime; int data_level; @@ -14,4 +14,8 @@ char *hilight_color; void (*destroy)(WI_ITEM_REC *item); +const char *(*get_target)(WI_ITEM_REC *item); +#define window_item_get_target(item) \ + ((item)->get_target(item)) + #undef STRUCT_SERVER_REC diff --git a/apps/irssi/src/fe-common/core/Makefile.am b/apps/irssi/src/fe-common/core/Makefile.am index d97433a3..920e2611 100644 --- a/apps/irssi/src/fe-common/core/Makefile.am +++ b/apps/irssi/src/fe-common/core/Makefile.am @@ -47,6 +47,7 @@ noinst_HEADERS = \ completion.h \ fe-channels.h \ fe-common-core.h \ + fe-core-commands.h \ fe-exec.h \ fe-messages.h \ fe-queries.h \ diff --git a/apps/irssi/src/fe-common/core/autorun.c b/apps/irssi/src/fe-common/core/autorun.c index 9c1050db..77513a0d 100644 --- a/apps/irssi/src/fe-common/core/autorun.c +++ b/apps/irssi/src/fe-common/core/autorun.c @@ -44,7 +44,7 @@ void autorun_startup(void) recvlen = read(f, tmpbuf, sizeof(tmpbuf)); ret = line_split(tmpbuf, recvlen, &str, &buffer); - if (ret > 0) { + if (ret > 0 && *str != '#') { eval_special_string(str, "", active_win->active_server, active_win->active); diff --git a/apps/irssi/src/fe-common/core/chat-completion.c b/apps/irssi/src/fe-common/core/chat-completion.c index df5525eb..f64dca65 100644 --- a/apps/irssi/src/fe-common/core/chat-completion.c +++ b/apps/irssi/src/fe-common/core/chat-completion.c @@ -23,6 +23,7 @@ #include "commands.h" #include "misc.h" #include "levels.h" +#include "lib-config/iconfig.h" #include "settings.h" #include "chatnets.h" @@ -34,6 +35,7 @@ #include "nicklist.h" #include "completion.h" +#include "chat-completion.h" #include "window-items.h" static int keep_privates_count, keep_publics_count; @@ -317,7 +319,7 @@ static GList *completion_msg(SERVER_REC *win_server, for (tmp = servers; tmp != NULL; tmp = tmp->next) { SERVER_REC *rec = tmp->data; - if (rec == win_server) + if (servers->next == NULL && rec == win_server) newprefix = g_strdup(prefix); else { newprefix = prefix == NULL ? @@ -484,6 +486,32 @@ static GList *completion_joinlist(GList *list1, GList *list2) return list1; } +GList *completion_get_servertags(const char *word) +{ + GList *list; + GSList *tmp; + int len; + + g_return_val_if_fail(word != NULL, NULL); + + len = strlen(word); + list = NULL; + + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + SERVER_REC *rec = tmp->data; + + if (g_strncasecmp(rec->tag, word, len) == 0) { + if (rec == active_win->active_server) + list = g_list_prepend(list, g_strdup(rec->tag)); + else + list = g_list_append(list, g_strdup(rec->tag)); + } + + } + + return list; +} + GList *completion_get_channels(SERVER_REC *server, const char *word) { GList *list; @@ -491,7 +519,6 @@ GList *completion_get_channels(SERVER_REC *server, const char *word) int len; g_return_val_if_fail(word != NULL, NULL); - g_return_val_if_fail(*word != '\0', NULL); len = strlen(word); list = NULL; @@ -501,7 +528,9 @@ GList *completion_get_channels(SERVER_REC *server, const char *word) for (; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *rec = tmp->data; - if (g_strncasecmp(rec->name, word, len) == 0) + if (g_strncasecmp(rec->visible_name, word, len) == 0) + list = g_list_append(list, g_strdup(rec->visible_name)); + else if (g_strncasecmp(rec->name, word, len) == 0) list = g_list_append(list, g_strdup(rec->name)); } @@ -518,6 +547,36 @@ GList *completion_get_channels(SERVER_REC *server, const char *word) return list; } +GList *completion_get_aliases(const char *word) +{ + CONFIG_NODE *node; + GList *list; + GSList *tmp; + int len; + + g_return_val_if_fail(word != NULL, NULL); + + len = strlen(word); + list = NULL; + + /* get the list of all aliases */ + node = iconfig_node_traverse("aliases", FALSE); + tmp = node == NULL ? NULL : config_node_first(node->value); + for (; tmp != NULL; tmp = config_node_next(tmp)) { + node = tmp->data; + + if (node->type != NODE_TYPE_KEY) + continue; + + if (len != 0 && g_strncasecmp(node->key, word, len) != 0) + continue; + + list = g_list_append(list, g_strdup(node->key)); + } + + return list; +} + static void complete_window_nicks(GList **list, WINDOW_REC *window, const char *word, const char *linestart) { @@ -739,6 +798,17 @@ static void sig_complete_connect(GList **list, WINDOW_REC *window, if (*list != NULL) signal_stop(); } +static void sig_complete_tag(GList **list, WINDOW_REC *window, + const char *word, const char *line, + int *want_space) +{ + g_return_if_fail(list != NULL); + g_return_if_fail(word != NULL); + + *list = completion_get_servertags(word); + if (*list != NULL) signal_stop(); +} + static void sig_complete_topic(GList **list, WINDOW_REC *window, const char *word, const char *line, int *want_space) @@ -757,6 +827,59 @@ static void sig_complete_topic(GList **list, WINDOW_REC *window, } } +static void sig_complete_away(GList **list, WINDOW_REC *window, + const char *word, const char *line, + int *want_space) +{ + const char *reason; + + g_return_if_fail(list != NULL); + g_return_if_fail(word != NULL); + + *want_space = FALSE; + + if (*word == '\0' && window->active_server != NULL) { + reason = SERVER(window->active_server)->away_reason; + if (reason != NULL) { + *list = g_list_append(NULL, g_strdup(reason)); + signal_stop(); + } + } +} + +static void sig_complete_unalias(GList **list, WINDOW_REC *window, + const char *word, const char *line, + int *want_space) +{ + g_return_if_fail(list != NULL); + g_return_if_fail(word != NULL); + + *list = completion_get_aliases(word); + if (*list != NULL) signal_stop(); +} + +static void sig_complete_alias(GList **list, WINDOW_REC *window, + const char *word, const char *line, + int *want_space) +{ + const char *definition; + + g_return_if_fail(list != NULL); + g_return_if_fail(word != NULL); + g_return_if_fail(line != NULL); + + if (*line != '\0') { + if ((definition = alias_find(line)) != NULL) { + *list = g_list_append(NULL, g_strdup(definition)); + signal_stop(); + } + } else { + *list = completion_get_aliases(word); + if (*list != NULL) signal_stop(); + } +} + + static void sig_complete_channel(GList **list, WINDOW_REC *window, const char *word, const char *line, int *want_space) @@ -768,6 +891,17 @@ static void sig_complete_channel(GList **list, WINDOW_REC *window, if (*list != NULL) signal_stop(); } +static void sig_complete_server(GList **list, WINDOW_REC *window, + const char *word, const char *line, + int *want_space) +{ + g_return_if_fail(list != NULL); + g_return_if_fail(word != NULL); + + *list = completion_get_servers(word); + if (*list != NULL) signal_stop(); +} + /* expand \n, \t and \\ */ static char *expand_escapes(const char *line, SERVER_REC *server, WI_ITEM_REC *item) @@ -842,10 +976,18 @@ static char *auto_complete(CHANNEL_REC *channel, const char *line) static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { - char *line, *str; + char *line, *str, *target; g_return_if_fail(data != NULL); - if (item == NULL) return; + + if (item == NULL) + return; + + if (*data == '\0') { + /* empty line, forget it. */ + signal_stop(); + return; + } line = settings_get_bool("expand_escapes") ? expand_escapes(data, server, item) : g_strdup(data); @@ -859,9 +1001,14 @@ static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item) } } - str = g_strdup_printf(IS_CHANNEL(item) ? "-channel %s %s" : - IS_QUERY(item) ? "-nick %s %s" : "%s %s", - item->name, line); + /* the nick is quoted in case it contains '-' character. also + spaces should work too now :) The nick is also escaped in case + it contains '\' characters */ + target = escape_string(window_item_get_target(item)); + str = g_strdup_printf(IS_CHANNEL(item) ? "-channel \"%s\" %s" : + IS_QUERY(item) ? "-nick \"%s\" %s" : "%s %s", + target, line); + g_free(target); signal_emit("command msg", 3, str, server, item); @@ -917,10 +1064,11 @@ void chat_completion_init(void) settings_add_bool("completion", "completion_auto", FALSE); settings_add_int("completion", "completion_keep_publics", 50); settings_add_int("completion", "completion_keep_privates", 10); - settings_add_bool("completion", "expand_escapes", FALSE); settings_add_bool("completion", "completion_nicks_lowercase", FALSE); settings_add_bool("completion", "completion_strict", FALSE); + settings_add_bool("lookandfeel", "expand_escapes", FALSE); + read_settings(); signal_add("complete word", (SIGNAL_FUNC) sig_complete_word); signal_add("complete command msg", (SIGNAL_FUNC) sig_complete_msg); @@ -931,8 +1079,15 @@ void chat_completion_init(void) signal_add("complete erase command action", (SIGNAL_FUNC) sig_erase_complete_msg); signal_add("complete command connect", (SIGNAL_FUNC) sig_complete_connect); signal_add("complete command server", (SIGNAL_FUNC) sig_complete_connect); + signal_add("complete command disconnect", (SIGNAL_FUNC) sig_complete_tag); + signal_add("complete command reconnect", (SIGNAL_FUNC) sig_complete_tag); signal_add("complete command topic", (SIGNAL_FUNC) sig_complete_topic); + signal_add("complete command away", (SIGNAL_FUNC) sig_complete_away); + signal_add("complete command unalias", (SIGNAL_FUNC) sig_complete_unalias); + signal_add("complete command alias", (SIGNAL_FUNC) sig_complete_alias); signal_add("complete command window item move", (SIGNAL_FUNC) sig_complete_channel); + signal_add("complete command server add", (SIGNAL_FUNC) sig_complete_server); + signal_add("complete command server remove", (SIGNAL_FUNC) sig_complete_server); signal_add("message public", (SIGNAL_FUNC) sig_message_public); signal_add("message join", (SIGNAL_FUNC) sig_message_join); signal_add("message private", (SIGNAL_FUNC) sig_message_private); @@ -960,8 +1115,15 @@ void chat_completion_deinit(void) signal_remove("complete erase command action", (SIGNAL_FUNC) sig_erase_complete_msg); signal_remove("complete command connect", (SIGNAL_FUNC) sig_complete_connect); signal_remove("complete command server", (SIGNAL_FUNC) sig_complete_connect); + signal_remove("complete command disconnect", (SIGNAL_FUNC) sig_complete_tag); + signal_remove("complete command reconnect", (SIGNAL_FUNC) sig_complete_tag); signal_remove("complete command topic", (SIGNAL_FUNC) sig_complete_topic); + signal_remove("complete command away", (SIGNAL_FUNC) sig_complete_away); + signal_remove("complete command unalias", (SIGNAL_FUNC) sig_complete_unalias); + signal_remove("complete command alias", (SIGNAL_FUNC) sig_complete_alias); signal_remove("complete command window item move", (SIGNAL_FUNC) sig_complete_channel); + signal_remove("complete command server add", (SIGNAL_FUNC) sig_complete_server); + signal_remove("complete command server remove", (SIGNAL_FUNC) sig_complete_server); signal_remove("message public", (SIGNAL_FUNC) sig_message_public); signal_remove("message join", (SIGNAL_FUNC) sig_message_join); signal_remove("message private", (SIGNAL_FUNC) sig_message_private); diff --git a/apps/irssi/src/fe-common/core/chat-completion.h b/apps/irssi/src/fe-common/core/chat-completion.h index 3cb70ca5..ff6098b1 100644 --- a/apps/irssi/src/fe-common/core/chat-completion.h +++ b/apps/irssi/src/fe-common/core/chat-completion.h @@ -1,6 +1,12 @@ #ifndef __CHAT_COMPLETION_H #define __CHAT_COMPLETION_H +GList *completion_get_chatnets(const char *word); +GList *completion_get_servers(const char *word); +GList *completion_get_servertags(const char *word); +GList *completion_get_channels(SERVER_REC *server, const char *word); +GList *completion_get_aliases(const char *word); + void completion_last_message_add(const char *nick); void completion_last_message_remove(const char *nick); void completion_last_message_rename(const char *oldnick, const char *newnick); diff --git a/apps/irssi/src/fe-common/core/completion.c b/apps/irssi/src/fe-common/core/completion.c index 99046b9f..7a9c9ad3 100644 --- a/apps/irssi/src/fe-common/core/completion.c +++ b/apps/irssi/src/fe-common/core/completion.c @@ -19,19 +19,16 @@ */ #include "module.h" +#include "module-formats.h" #include "signals.h" #include "commands.h" +#include "levels.h" #include "misc.h" #include "lib-config/iconfig.h" #include "settings.h" #include "completion.h" - -#define wordreplace_find(word) \ - iconfig_list_find("replaces", "text", word, "replace") - -#define completion_find(completion) \ - iconfig_list_find("completions", "short", completion, "long") +#include "printtext.h" static GList *complist; /* list of commands we're currently completing */ static char *last_line; @@ -46,6 +43,24 @@ static int last_want_space, last_line_pos; void chat_completion_init(void); void chat_completion_deinit(void); +static const char *completion_find(const char *key, int automatic) +{ + CONFIG_NODE *node; + + node = iconfig_node_traverse("completions", FALSE); + if (node == NULL || node->type != NODE_TYPE_BLOCK) + return NULL; + + node = config_node_section(node, key, -1); + if (node == NULL) + return NULL; + + if (automatic && !config_node_get_bool(node, "auto", FALSE)) + return NULL; + + return config_node_get_str(node, "value", NULL); +} + /* Return whole word at specified position in string */ char *get_word_at(const char *str, int pos, char **startpos) { @@ -85,7 +100,7 @@ char *auto_word_complete(const char *line, int *pos) g_string_erase(result, startpos, strlen(word)); /* check for words in autocompletion list */ - replace = wordreplace_find(word); + replace = completion_find(word, TRUE); if (replace == NULL) { ret = NULL; g_string_free(result, TRUE); @@ -569,7 +584,7 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, g_return_if_fail(linestart != NULL); /* check against "completion words" list */ - newword = completion_find(word); + newword = completion_find(word, FALSE); if (newword != NULL) { *list = g_list_append(*list, g_strdup(newword)); @@ -577,6 +592,16 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, return; } + if (*linestart != '\0' && (*word == '/' || *word == '~')) { + /* quite likely filename completion */ + *list = g_list_concat(*list, filename_complete(word, NULL)); + if (*list != NULL) { + *want_space = FALSE; + signal_stop(); + return; + } + } + /* command completion? */ cmdchars = settings_get_str("cmdchars"); if (*word != '\0' && *linestart == '\0' && strchr(cmdchars, *word)) { @@ -734,6 +759,79 @@ static void sig_complete_command(GList **list, WINDOW_REC *window, if (*list != NULL) signal_stop(); } +static void cmd_completion(const char *data) +{ + GHashTable *optlist; + CONFIG_NODE *node; + GSList *tmp; + char *key, *value; + void *free_arg; + int len; + + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST, + "completion", &optlist, &key, &value)) + return; + + node = iconfig_node_traverse("completions", *value != '\0'); + if (node != NULL && node->type != NODE_TYPE_BLOCK) { + /* FIXME: remove after 0.8.5 */ + iconfig_node_remove(mainconfig->mainnode, node); + node = iconfig_node_traverse("completions", *value != '\0'); + } + + if (node == NULL || (node->value == NULL && *value == '\0')) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_NO_COMPLETIONS); + cmd_params_free(free_arg); + return; + } + + if (g_hash_table_lookup(optlist, "delete") != NULL && *key != '\0') { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_COMPLETION_REMOVED, key); + + iconfig_set_str("completions", key, NULL); + signal_emit("completion removed", 1, key); + } else if (*key != '\0' && *value != '\0') { + int automatic = g_hash_table_lookup(optlist, "auto") != NULL; + + node = config_node_section(node, key, NODE_TYPE_BLOCK); + iconfig_node_set_str(node, "value", value); + if (automatic) + iconfig_node_set_bool(node, "auto", TRUE); + else + iconfig_node_set_str(node, "auto", NULL); + + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + TXT_COMPLETION_LINE, + key, value, automatic ? "yes" : "no"); + + signal_emit("completion added", 1, key); + } else { + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + TXT_COMPLETION_HEADER); + + len = strlen(key); + for (tmp = node->value; tmp != NULL; tmp = tmp->next) { + node = tmp->data; + + if (len == 0 || + g_strncasecmp(node->key, key, len) == 0) { + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + TXT_COMPLETION_LINE, node->key, + config_node_get_str(node, "value", ""), + config_node_get_bool(node, "auto", FALSE) ? "yes" : "no"); + } + } + + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + TXT_COMPLETION_FOOTER); + } + + cmd_params_free(free_arg); +} + void completion_init(void) { complist = NULL; @@ -741,6 +839,8 @@ void completion_init(void) chat_completion_init(); + command_bind("completion", NULL, (SIGNAL_FUNC) cmd_completion); + signal_add_first("complete word", (SIGNAL_FUNC) sig_complete_word); signal_add_first("complete erase", (SIGNAL_FUNC) sig_complete_erase); signal_add("complete command set", (SIGNAL_FUNC) sig_complete_set); @@ -752,6 +852,8 @@ void completion_init(void) signal_add("complete command rawlog open", (SIGNAL_FUNC) sig_complete_filename); signal_add("complete command rawlog save", (SIGNAL_FUNC) sig_complete_filename); signal_add("complete command help", (SIGNAL_FUNC) sig_complete_command); + + command_set_options("completion", "auto delete"); } void completion_deinit(void) @@ -760,6 +862,8 @@ void completion_deinit(void) chat_completion_deinit(); + command_unbind("completion", (SIGNAL_FUNC) cmd_completion); + signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word); signal_remove("complete erase", (SIGNAL_FUNC) sig_complete_erase); signal_remove("complete command set", (SIGNAL_FUNC) sig_complete_set); @@ -772,5 +876,3 @@ void completion_deinit(void) signal_remove("complete command rawlog save", (SIGNAL_FUNC) sig_complete_filename); signal_remove("complete command help", (SIGNAL_FUNC) sig_complete_command); } - - diff --git a/apps/irssi/src/fe-common/core/fe-channels.c b/apps/irssi/src/fe-common/core/fe-channels.c index 27ad4365..4ce5abeb 100644 --- a/apps/irssi/src/fe-common/core/fe-channels.c +++ b/apps/irssi/src/fe-common/core/fe-channels.c @@ -70,7 +70,7 @@ static void signal_channel_destroyed(CHANNEL_REC *channel) !channel->server->disconnected) { /* kicked out from channel */ window_bind_add(window, channel->server->tag, - channel->name); + channel->visible_name); } else if (!channel->joined || channel->left) window_auto_destroy(window); } @@ -96,12 +96,20 @@ static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item) if (item == NULL) return; if (g_slist_length(window->items) > 1 && IS_CHANNEL(item)) { - printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE, - TXT_TALKING_IN, item->name); + printformat(item->server, item->visible_name, + MSGLEVEL_CLIENTNOTICE, + TXT_TALKING_IN, item->visible_name); signal_stop(); } } +static void sig_channel_joined(CHANNEL_REC *channel) +{ + if (settings_get_bool("show_names_on_join") && + !channel->session_rejoin) + fe_channels_nicklist(channel, CHANNEL_NICKLIST_FLAG_ALL); +} + static void cmd_wjoin_pre(const char *data) { GHashTable *optlist; @@ -172,7 +180,8 @@ static void cmd_channel_list_joined(void) /* print active channel */ channel = CHANNEL(active_win->active); if (channel != NULL) - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CURRENT_CHANNEL, channel->name); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_CURRENT_CHANNEL, channel->visible_name); /* print list of all channels, their modes, server tags and nicks */ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_CHANLIST_HEADER); @@ -189,7 +198,8 @@ static void cmd_channel_list_joined(void) if (nicks->len > 1) g_string_truncate(nicks, nicks->len-1); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_CHANLIST_LINE, - channel->name, channel->mode, channel->server->tag, nicks->str); + channel->visible_name, channel->mode, + channel->server->tag, nicks->str); g_slist_free(nicklist); g_string_free(nicks, TRUE); @@ -326,13 +336,13 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) int *columns, cols, rows, last_col_rows, col, row, max_width; int item_extra, linebuf_size, formatnum; - window = window_find_closest(channel->server, channel->name, + window = window_find_closest(channel->server, channel->visible_name, MSGLEVEL_CLIENTCRAP); max_width = window->width; /* get the length of item extra stuff ("[ ] ") */ format = format_get_text(MODULE_NAME, NULL, - channel->server, channel->name, + channel->server, channel->visible_name, TXT_NAMES_NICK, " ", ""); stripped = strip_codes(format); item_extra = strlen(stripped); @@ -344,7 +354,7 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) max_width = settings_get_int("names_max_width"); /* remove width of the timestamp from max_width */ - format_create_dest(&dest, channel->server, channel->name, + format_create_dest(&dest, channel->server, channel->visible_name, MSGLEVEL_CLIENTCRAP, NULL); format = format_get_line_start(current_theme, &dest, time(NULL)); if (format != NULL) { @@ -356,8 +366,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) /* remove width of the prefix from max_width */ prefix_format = format_get_text(MODULE_NAME, NULL, - channel->server, channel->name, - TXT_NAMES_PREFIX, channel->name); + channel->server, channel->visible_name, + TXT_NAMES_PREFIX, + channel->visible_name); if (prefix_format != NULL) { stripped = strip_codes(prefix_format); max_width -= strlen(stripped); @@ -410,13 +421,14 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) rec->voice ? TXT_NAMES_NICK_VOICE : TXT_NAMES_NICK; format = format_get_text(MODULE_NAME, NULL, - channel->server, channel->name, + channel->server, + channel->visible_name, formatnum, nickmode, linebuf); g_string_append(str, format); g_free(format); if (++col == cols) { - printtext(channel->server, channel->name, + printtext(channel->server, channel->visible_name, MSGLEVEL_CLIENTCRAP, "%s", str->str); g_string_truncate(str, 0); if (prefix_format != NULL) @@ -429,7 +441,7 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) } if (str->len > strlen(prefix_format)) { - printtext(channel->server, channel->name, + printtext(channel->server, channel->visible_name, MSGLEVEL_CLIENTCRAP, "%s", str->str); } @@ -480,15 +492,17 @@ void fe_channels_nicklist(CHANNEL_REC *channel, int flags) /* display the nicks */ if ((flags & CHANNEL_NICKLIST_FLAG_COUNT) == 0) { - printformat(channel->server, channel->name, - MSGLEVEL_CLIENTCRAP, TXT_NAMES, channel->name, nicks, ops, halfops, voices, normal); + printformat(channel->server, channel->visible_name, + MSGLEVEL_CLIENTCRAP, TXT_NAMES, + channel->visible_name, + nicks, ops, halfops, voices, normal); display_sorted_nicks(channel, sorted); } g_slist_free(sorted); - printformat(channel->server, channel->name, + printformat(channel->server, channel->visible_name, MSGLEVEL_CLIENTNOTICE, TXT_ENDOFNAMES, - channel->name, nicks, ops, halfops, voices, normal); + channel->visible_name, nicks, ops, halfops, voices, normal); } /* SYNTAX: NAMES [-count | -ops -halfops -voices -normal] [ | **] */ @@ -513,7 +527,7 @@ static void cmd_names(const char *data, SERVER_REC *server, WI_ITEM_REC *item) if (!IS_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); - channel = item->name; + channel = CHANNEL(item)->name; } flags = 0; @@ -594,6 +608,7 @@ static void cmd_cycle(const char *data, SERVER_REC *server, WI_ITEM_REC *item) void fe_channels_init(void) { settings_add_bool("lookandfeel", "autoclose_windows", TRUE); + settings_add_bool("lookandfeel", "show_names_on_join", TRUE); settings_add_int("lookandfeel", "names_max_columns", 6); settings_add_int("lookandfeel", "names_max_width", 0); @@ -601,6 +616,7 @@ void fe_channels_init(void) signal_add("channel destroyed", (SIGNAL_FUNC) signal_channel_destroyed); signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed); signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected); + signal_add_last("channel joined", (SIGNAL_FUNC) sig_channel_joined); command_bind_first("join", NULL, (SIGNAL_FUNC) cmd_wjoin_pre); command_bind("join", NULL, (SIGNAL_FUNC) cmd_join); @@ -623,6 +639,7 @@ void fe_channels_deinit(void) signal_remove("channel destroyed", (SIGNAL_FUNC) signal_channel_destroyed); signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed); signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); + signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined); command_unbind("join", (SIGNAL_FUNC) cmd_wjoin_pre); command_unbind("join", (SIGNAL_FUNC) cmd_join); diff --git a/apps/irssi/src/fe-common/core/fe-common-core.c b/apps/irssi/src/fe-common/core/fe-common-core.c index 94e18fc1..32f405ac 100644 --- a/apps/irssi/src/fe-common/core/fe-common-core.c +++ b/apps/irssi/src/fe-common/core/fe-common-core.c @@ -31,6 +31,7 @@ #include "servers-setup.h" #include "autorun.h" +#include "fe-core-commands.h" #include "fe-queries.h" #include "hilight-text.h" #include "command-history.h" @@ -91,9 +92,6 @@ void fe_settings_deinit(void); void window_commands_init(void); void window_commands_deinit(void); -void fe_core_commands_init(void); -void fe_core_commands_deinit(void); - static void print_version(void) { printf(PACKAGE" " IRSSI_VERSION" (%d %04d)\n", @@ -276,6 +274,8 @@ void glog_func(const char *log_domain, GLogLevelFlags log_level, } } +#define MSGS_WINDOW_LEVELS (MSGLEVEL_MSGS|MSGLEVEL_ACTIONS|MSGLEVEL_DCCMSGS) + static void create_windows(void) { WINDOW_REC *window; @@ -289,14 +289,14 @@ static void create_windows(void) window_set_name(window, "(status)"); window_set_level(window, MSGLEVEL_ALL ^ (settings_get_bool("use_msgs_window") ? - (MSGLEVEL_MSGS|MSGLEVEL_DCCMSGS) : 0)); + MSGS_WINDOW_LEVELS : 0)); window_set_immortal(window, TRUE); } if (settings_get_bool("use_msgs_window")) { window = window_create(NULL, TRUE); window_set_name(window, "(msgs)"); - window_set_level(window, MSGLEVEL_MSGS|MSGLEVEL_DCCMSGS); + window_set_level(window, MSGS_WINDOW_LEVELS); window_set_immortal(window, TRUE); } diff --git a/apps/irssi/src/fe-common/core/fe-core-commands.c b/apps/irssi/src/fe-common/core/fe-core-commands.c index d50b23e5..b599c810 100644 --- a/apps/irssi/src/fe-common/core/fe-core-commands.c +++ b/apps/irssi/src/fe-common/core/fe-core-commands.c @@ -50,11 +50,12 @@ static int ret_texts[] = { TXT_NOT_GOOD_IDEA }; +int command_hide_output; + /* keep the whole command line here temporarily. we need it in "default command" event handler, but there we don't know if the start of the line had one or two command chars, and which one.. */ static const char *current_cmdline; -static int hide_output; static GTimeVal time_command_last, time_command_now; static int last_command_cmd, command_cmd; @@ -198,12 +199,6 @@ static void event_command(const char *data) { const char *cmdchar; - if (*data == '\0') { - /* empty line, forget it. */ - signal_stop(); - return; - } - /* save current command line */ current_cmdline = data; @@ -212,13 +207,15 @@ static void event_command(const char *data) last_command_cmd = command_cmd; g_get_current_time(&time_command_now); - command_cmd = strchr(settings_get_str("cmdchars"), *data) != NULL; + command_cmd = *data != '\0' && + strchr(settings_get_str("cmdchars"), *data) != NULL; /* /^command hides the output of the command */ - cmdchar = strchr(settings_get_str("cmdchars"), *data); + cmdchar = *data == '\0' ? NULL : + strchr(settings_get_str("cmdchars"), *data); if (cmdchar != NULL && (data[1] == '^' || (data[1] == *cmdchar && data[2] == '^'))) { - hide_output = TRUE; + command_hide_output = TRUE; signal_add_first("print starting", (SIGNAL_FUNC) sig_stop); signal_add_first("print format", (SIGNAL_FUNC) sig_stop); signal_add_first("print text", (SIGNAL_FUNC) sig_stop); @@ -227,8 +224,8 @@ static void event_command(const char *data) static void event_command_last(const char *data) { - if (hide_output) { - hide_output = FALSE; + if (command_hide_output) { + command_hide_output = FALSE; signal_remove("print starting", (SIGNAL_FUNC) sig_stop); signal_remove("print format", (SIGNAL_FUNC) sig_stop); signal_remove("print text", (SIGNAL_FUNC) sig_stop); @@ -318,7 +315,7 @@ static void event_list_subcommands(const char *command) void fe_core_commands_init(void) { - hide_output = FALSE; + command_hide_output = FALSE; command_cmd = FALSE; memset(&time_command_now, 0, sizeof(GTimeVal)); diff --git a/apps/irssi/src/fe-common/core/fe-exec.c b/apps/irssi/src/fe-common/core/fe-exec.c index 88df56ae..68ff1c43 100644 --- a/apps/irssi/src/fe-common/core/fe-exec.c +++ b/apps/irssi/src/fe-common/core/fe-exec.c @@ -54,10 +54,15 @@ static void exec_wi_destroy(EXEC_WI_REC *rec) window_item_destroy((WI_ITEM_REC *) rec); MODULE_DATA_DEINIT(rec); - g_free(rec->name); + g_free(rec->visible_name); g_free(rec); } +static const char *exec_get_target(WI_ITEM_REC *item) +{ + return ((EXEC_WI_REC *) item)->visible_name; +} + static EXEC_WI_REC *exec_wi_create(WINDOW_REC *window, PROCESS_REC *rec) { EXEC_WI_REC *item; @@ -68,7 +73,8 @@ static EXEC_WI_REC *exec_wi_create(WINDOW_REC *window, PROCESS_REC *rec) item = g_new0(EXEC_WI_REC, 1); item->type = module_get_uniq_id_str("WINDOW ITEM TYPE", "EXEC"); item->destroy = (void (*) (WI_ITEM_REC *)) exec_wi_destroy; - item->name = rec->name != NULL ? g_strdup(rec->name) : + item->get_target = exec_get_target; + item->visible_name = rec->name != NULL ? g_strdup(rec->name) : g_strdup_printf("%%%d", rec->id); item->createtime = time(NULL); @@ -411,7 +417,7 @@ static void handle_exec(const char *args, GHashTable *optlist, /* redirect output to active channel/query */ if (item == NULL) cmd_return_error(CMDERR_NOT_JOINED); - target = item->name; + target = (char *) window_item_get_target(item); target_channel = IS_CHANNEL(item); target_nick = IS_QUERY(item); } else if (g_hash_table_lookup(optlist, "msg") != NULL) { @@ -589,7 +595,7 @@ static void sig_exec_input(PROCESS_REC *rec, const char *text) 3, str, server, item); g_free(str); } else if (rec->target_item != NULL) { - printtext(NULL, rec->target_item->name, + printtext(NULL, rec->target_item->visible_name, rec->level, "%s", text); } else { printtext_window(rec->target_win, rec->level, "%s", text); @@ -612,7 +618,8 @@ static void sig_window_destroyed(WINDOW_REC *window) static void event_text(const char *data, SERVER_REC *server, EXEC_WI_REC *item) { - if (!IS_EXEC_WI(item)) return; + if (!IS_EXEC_WI(item)) + return; net_sendbuffer_send(item->process->out, data, strlen(data)); net_sendbuffer_send(item->process->out, "\n", 1); diff --git a/apps/irssi/src/fe-common/core/fe-ignore.c b/apps/irssi/src/fe-common/core/fe-ignore.c index 55a88266..4621ab26 100644 --- a/apps/irssi/src/fe-common/core/fe-ignore.c +++ b/apps/irssi/src/fe-common/core/fe-ignore.c @@ -53,25 +53,31 @@ static void ignore_print(int index, IGNORE_REC *rec) levels = bits2level(rec->level); options = g_string_new(NULL); - if (rec->exception) g_string_sprintfa(options, "-except "); + if (rec->exception) g_string_append(options, "-except "); if (rec->regexp) { - g_string_sprintfa(options, "-regexp "); + g_string_append(options, "-regexp "); #ifdef HAVE_REGEX_H if (!rec->regexp_compiled) - g_string_sprintfa(options, "[INVALID!] "); + g_string_append(options, "[INVALID!] "); #endif } - if (rec->fullword) g_string_sprintfa(options, "-full "); - if (rec->replies) g_string_sprintfa(options, "-replies "); + if (rec->fullword) g_string_append(options, "-full "); + if (rec->replies) g_string_append(options, "-replies "); if (rec->pattern != NULL) g_string_sprintfa(options, "-pattern %s ", rec->pattern); if (options->len > 1) g_string_truncate(options, options->len-1); - printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, - TXT_IGNORE_LINE, index, - key != NULL ? key : "", - levels != NULL ? levels : "", options->str); + if (index >= 0) { + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + TXT_IGNORE_LINE, index, key != NULL ? key : "", + levels != NULL ? levels : "", options->str); + } else { + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + options->len > 0 ? TXT_IGNORED_OPTIONS : TXT_IGNORED, + key != NULL ? key : "", + levels != NULL ? levels : "", options->str); + } g_string_free(options, TRUE); g_free(key); g_free(levels); @@ -134,7 +140,7 @@ static void cmd_ignore(const char *data) channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1); - rec = ignore_find(NULL, mask, channels); + rec = patternarg != NULL ? NULL: ignore_find(NULL, mask, channels); new_ignore = rec == NULL; if (rec == NULL) { @@ -221,14 +227,7 @@ static void cmd_unignore(const char *data) static void sig_ignore_created(IGNORE_REC *rec) { - char *key, *levels; - - key = ignore_get_key(rec); - levels = bits2level(rec->level); - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - TXT_IGNORED, key, levels); - g_free(key); - g_free(levels); + ignore_print(-1, rec); } static void sig_ignore_destroyed(IGNORE_REC *rec) diff --git a/apps/irssi/src/fe-common/core/fe-log.c b/apps/irssi/src/fe-common/core/fe-log.c index bebff7f5..215d4a52 100644 --- a/apps/irssi/src/fe-common/core/fe-log.c +++ b/apps/irssi/src/fe-common/core/fe-log.c @@ -475,12 +475,13 @@ static void log_single_line(WINDOW_REC *window, const char *server_tag, char **targets, **tmp; LOG_REC *log; - /* save to log created with /WINDOW LOG */ - ltoa(windownum, window->refnum); - log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, - windownum, NULL, NULL); - if (log != NULL) { - log_write_rec(log, text, level); + if (window != NULL) { + /* save to log created with /WINDOW LOG */ + ltoa(windownum, window->refnum); + log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, + windownum, NULL, NULL); + if (log != NULL) + log_write_rec(log, text, level); } if (target == NULL) @@ -591,11 +592,11 @@ static int sig_autoremove(void) return 1; } -static void sig_window_item_destroy(WINDOW_REC *window, WI_ITEM_REC *item) +static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item) { LOG_REC *log; - log = logs_find_item(LOG_ITEM_TARGET, item->name, + log = logs_find_item(LOG_ITEM_TARGET, item->visible_name, item->server == NULL ? NULL : item->server->tag, NULL); if (log != NULL && log->temp) @@ -709,7 +710,7 @@ void fe_log_init(void) command_bind("window log", NULL, (SIGNAL_FUNC) cmd_window_log); command_bind("window logfile", NULL, (SIGNAL_FUNC) cmd_window_logfile); signal_add_first("print text", (SIGNAL_FUNC) sig_printtext); - signal_add("window item destroy", (SIGNAL_FUNC) sig_window_item_destroy); + signal_add("window item remove", (SIGNAL_FUNC) sig_window_item_remove); signal_add("window refnum changed", (SIGNAL_FUNC) sig_window_refnum_changed); signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_add("log locked", (SIGNAL_FUNC) sig_log_locked); @@ -738,7 +739,7 @@ void fe_log_deinit(void) command_unbind("window log", (SIGNAL_FUNC) cmd_window_log); command_unbind("window logfile", (SIGNAL_FUNC) cmd_window_logfile); signal_remove("print text", (SIGNAL_FUNC) sig_printtext); - signal_remove("window item destroy", (SIGNAL_FUNC) sig_window_item_destroy); + signal_remove("window item remove", (SIGNAL_FUNC) sig_window_item_remove); signal_remove("window refnum changed", (SIGNAL_FUNC) sig_window_refnum_changed); signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("log locked", (SIGNAL_FUNC) sig_log_locked); diff --git a/apps/irssi/src/fe-common/core/fe-messages.c b/apps/irssi/src/fe-common/core/fe-messages.c index 44c9fb35..e210c2a2 100644 --- a/apps/irssi/src/fe-common/core/fe-messages.c +++ b/apps/irssi/src/fe-common/core/fe-messages.c @@ -227,14 +227,19 @@ static void sig_message_private(SERVER_REC *server, const char *msg, g_free_not_null(freemsg); } -static void print_own_channel_message(SERVER_REC *server, CHANNEL_REC *channel, - const char *target, const char *msg) +static void sig_message_own_public(SERVER_REC *server, const char *msg, + const char *target) { WINDOW_REC *window; + CHANNEL_REC *channel; const char *nickmode; char *freemsg = NULL; int print_channel; + channel = channel_find(server, target); + if (channel != NULL) + target = channel->visible_name; + nickmode = channel_get_nickmode(channel, server->nick); window = channel == NULL ? NULL : @@ -261,18 +266,6 @@ static void print_own_channel_message(SERVER_REC *server, CHANNEL_REC *channel, g_free_not_null(freemsg); } -static void sig_message_own_public(SERVER_REC *server, const char *msg, - const char *target) -{ - CHANNEL_REC *channel; - - g_return_if_fail(server != NULL); - g_return_if_fail(msg != NULL); - - channel = channel_find(server, target); - print_own_channel_message(server, channel, target, msg); -} - static void sig_message_own_private(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) { @@ -347,7 +340,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, if (!nicklist_find(rec, nick)) continue; - if (ignore_check(server, nick, address, rec->name, + if (ignore_check(server, nick, address, rec->visible_name, reason, MSGLEVEL_QUITS)) { count++; continue; @@ -355,17 +348,18 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, if (print_channel == NULL || active_win->active == (WI_ITEM_REC *) rec) - print_channel = rec->name; + print_channel = rec->visible_name; if (once) - g_string_sprintfa(chans, "%s,", rec->name); + g_string_sprintfa(chans, "%s,", rec->visible_name); else { window = window_item_window((WI_ITEM_REC *) rec); if (g_slist_find(windows, window) == NULL) { windows = g_slist_append(windows, window); - printformat(server, rec->name, MSGLEVEL_QUITS, + printformat(server, rec->visible_name, + MSGLEVEL_QUITS, TXT_QUIT, nick, address, reason, - rec->name); + rec->visible_name); } } count++; @@ -441,8 +435,8 @@ static void print_nick_change(SERVER_REC *server, const char *newnick, continue; windows = g_slist_append(windows, window); - print_nick_change_channel(server, channel->name, newnick, - oldnick, address, ownnick); + print_nick_change_channel(server, channel->visible_name, + newnick, oldnick, address, ownnick); msgprint = TRUE; } diff --git a/apps/irssi/src/fe-common/core/fe-queries.c b/apps/irssi/src/fe-common/core/fe-queries.c index 93f13040..8345d52f 100644 --- a/apps/irssi/src/fe-common/core/fe-queries.c +++ b/apps/irssi/src/fe-common/core/fe-queries.c @@ -30,6 +30,7 @@ #include "servers.h" #include "queries.h" +#include "fe-core-commands.h" #include "fe-windows.h" #include "window-items.h" #include "printtext.h" @@ -46,7 +47,8 @@ QUERY_REC *privmsg_get_query(SERVER_REC *server, const char *nick, g_return_val_if_fail(nick != NULL, NULL); query = query_find(server, nick); - if (query == NULL && (querycreate_level & level) != 0 && + if (query == NULL && !command_hide_output && + (querycreate_level & level) != 0 && (!own || settings_get_bool("autocreate_own_query"))) { query = CHAT_PROTOCOL(server)-> query_create(server->tag, nick, TRUE); @@ -192,23 +194,29 @@ static void cmd_window_server(const char *data) static void cmd_unquery(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { QUERY_REC *query; + char *nick; + void *free_arg; g_return_if_fail(data != NULL); - if (*data == '\0') { + if (!cmd_get_params(data, &free_arg, 1, &nick)) + return; + + if (*nick == '\0') { /* remove current query */ query = QUERY(item); - if (query == NULL) return; } else { - query = query_find(server, data); + query = query_find(server, nick); if (query == NULL) { printformat(server, NULL, MSGLEVEL_CLIENTERROR, - TXT_NO_QUERY, data); - return; + TXT_NO_QUERY, nick); } } - query_destroy(query); + if (query != NULL) + query_destroy(query); + + cmd_params_free(free_arg); } /* SYNTAX: QUERY [-window] [-] [] */ diff --git a/apps/irssi/src/fe-common/core/fe-server.c b/apps/irssi/src/fe-common/core/fe-server.c index d8f9d137..06f46777 100644 --- a/apps/irssi/src/fe-common/core/fe-server.c +++ b/apps/irssi/src/fe-common/core/fe-server.c @@ -144,6 +144,9 @@ static void cmd_server_add(const char *data) else if (g_hash_table_lookup(optlist, "4")) rec->family = AF_INET; + if (g_hash_table_lookup(optlist, "ssl")) + rec->use_ssl = TRUE; + if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE; if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE; if (g_hash_table_lookup(optlist, "proxy")) rec->no_proxy = FALSE; @@ -238,9 +241,12 @@ static void sig_server_connecting(SERVER_REC *server, IPADDR *ip) char ipaddr[MAX_IP_LEN]; g_return_if_fail(server != NULL); - g_return_if_fail(ip != NULL); - net_ip2host(ip, ipaddr); + if (ip == NULL) + ipaddr[0] = '\0'; + else + net_ip2host(ip, ipaddr); + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CONNECTING, server->connrec->address, ipaddr, server->connrec->port); } @@ -324,7 +330,7 @@ void fe_server_init(void) command_bind("server connect", NULL, (SIGNAL_FUNC) cmd_server_connect); command_bind("server add", NULL, (SIGNAL_FUNC) cmd_server_add); command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove); - command_set_options("server add", "4 6 auto noauto proxy noproxy -host -port"); + command_set_options("server add", "4 6 ssl auto noauto proxy noproxy -host -port"); signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting); diff --git a/apps/irssi/src/fe-common/core/fe-settings.c b/apps/irssi/src/fe-common/core/fe-settings.c index 70bc5cc3..7fb512e8 100644 --- a/apps/irssi/src/fe-common/core/fe-settings.c +++ b/apps/irssi/src/fe-common/core/fe-settings.c @@ -66,7 +66,7 @@ static void set_boolean(const char *key, const char *value) printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_NOT_TOGGLE); } -/* SYNTAX: SET [-clear] [ []] */ +/* SYNTAX: SET [-clear | -default] [ []] */ static void cmd_set(char *data) { GHashTable *optlist; @@ -74,13 +74,14 @@ static void cmd_set(char *data) const char *last_section; char *key, *value; void *free_arg; - int found, clear; + int found, clear, set_default; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_OPTIONS, "set", &optlist, &key, &value)) return; clear = g_hash_table_lookup(optlist, "clear") != NULL; + set_default = g_hash_table_lookup(optlist, "default") != NULL; last_section = ""; found = 0; sets = settings_get_sorted(); @@ -98,20 +99,26 @@ static void cmd_set(char *data) last_section = rec->section; } - if (clear || *value != '\0') { + if (clear || set_default || *value != '\0') { /* change the setting */ switch (rec->type) { case SETTING_TYPE_BOOLEAN: if (clear) settings_set_bool(key, FALSE); - else + else if (set_default) + settings_set_bool(key, GPOINTER_TO_INT(rec->def)); + else set_boolean(key, value); break; case SETTING_TYPE_INT: - settings_set_int(key, clear ? 0 : atoi(value)); + settings_set_int(key, clear ? 0 : + set_default ? GPOINTER_TO_INT(rec->def) : + atoi(value)); break; case SETTING_TYPE_STRING: - settings_set_str(key, clear ? "" : value); + settings_set_str(key, clear ? "" : + set_default ? rec->def : + value); break; } signal_emit("setup changed", 0); @@ -240,10 +247,17 @@ static void cmd_alias(const char *data) /* SYNTAX: UNALIAS */ static void cmd_unalias(const char *data) { + char *alias; + void *free_arg; + g_return_if_fail(data != NULL); - if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - alias_remove(data); + if (!cmd_get_params(data, &free_arg, 1, &alias)) + return; + if (*alias == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + alias_remove(alias); + cmd_params_free(free_arg); } /* SYNTAX: RELOAD [] */ @@ -327,7 +341,7 @@ void fe_settings_init(void) command_bind("unalias", NULL, (SIGNAL_FUNC) cmd_unalias); command_bind("reload", NULL, (SIGNAL_FUNC) cmd_reload); command_bind("save", NULL, (SIGNAL_FUNC) cmd_save); - command_set_options("set", "clear"); + command_set_options("set", "clear default"); signal_add("settings errors", (SIGNAL_FUNC) sig_settings_errors); } diff --git a/apps/irssi/src/fe-common/core/fe-windows.c b/apps/irssi/src/fe-common/core/fe-windows.c index af8e4297..24a32a51 100644 --- a/apps/irssi/src/fe-common/core/fe-windows.c +++ b/apps/irssi/src/fe-common/core/fe-windows.c @@ -161,11 +161,30 @@ void window_set_active(WINDOW_REC *window) void window_change_server(WINDOW_REC *window, void *server) { + SERVER_REC *active, *connect; + if (server != NULL && SERVER(server)->disconnected) return; - window->active_server = server; - signal_emit("window server changed", 2, window, server); + if (server == NULL) { + active = connect = NULL; + } else if (g_slist_find(servers, server) != NULL) { + active = server; + connect = NULL; + } else { + active = NULL; + connect = server; + } + + if (window->connect_server != connect) { + window->connect_server = connect; + signal_emit("window connect changed", 2, window, connect); + } + + if (window->active_server != active) { + window->active_server = active; + signal_emit("window server changed", 2, window, active); + } } void window_set_refnum(WINDOW_REC *window, int refnum) @@ -232,12 +251,12 @@ void window_set_immortal(WINDOW_REC *window, int immortal) } /* return active item's name, or if none is active, window's name */ -char *window_get_active_name(WINDOW_REC *window) +const char *window_get_active_name(WINDOW_REC *window) { g_return_val_if_fail(window != NULL, NULL); if (window->active != NULL) - return window->active->name; + return window->active->visible_name; return window->name; } @@ -489,7 +508,7 @@ void window_bind_remove_unsticky(WINDOW_REC *window) } } -static void sig_server_looking(SERVER_REC *server) +static void sig_server_connected(SERVER_REC *server) { GSList *tmp; @@ -519,7 +538,8 @@ static void sig_server_disconnected(SERVER_REC *server) for (tmp = windows; tmp != NULL; tmp = tmp->next) { WINDOW_REC *rec = tmp->data; - if (rec->active_server == server) { + if (rec->active_server == server || + rec->connect_server == server) { window_change_server(rec, rec->servertag != NULL ? NULL : new_server); } @@ -609,7 +629,8 @@ void windows_init(void) settings_add_str("lookandfeel", "window_default_level", "NONE"); read_settings(); - signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); + signal_add("server looking", (SIGNAL_FUNC) sig_server_connected); + signal_add("server connected", (SIGNAL_FUNC) sig_server_connected); signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_add("server connect failed", (SIGNAL_FUNC) sig_server_disconnected); signal_add("setup changed", (SIGNAL_FUNC) read_settings); @@ -620,7 +641,8 @@ void windows_deinit(void) if (daytag != -1) g_source_remove(daytag); if (daycheck == 1) signal_remove("print text", (SIGNAL_FUNC) sig_print_text); - signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking); + signal_remove("server looking", (SIGNAL_FUNC) sig_server_connected); + signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected); signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); diff --git a/apps/irssi/src/fe-common/core/fe-windows.h b/apps/irssi/src/fe-common/core/fe-windows.h index 9173459f..58c316ef 100644 --- a/apps/irssi/src/fe-common/core/fe-windows.h +++ b/apps/irssi/src/fe-common/core/fe-windows.h @@ -26,6 +26,7 @@ struct _WINDOW_REC { GSList *items; WI_ITEM_REC *active; SERVER_REC *active_server; + SERVER_REC *connect_server; char *servertag; /* active_server must be either NULL or have this tag (unless there's items in this window) */ int level; /* message level */ @@ -69,7 +70,7 @@ void window_set_level(WINDOW_REC *window, int level); void window_set_immortal(WINDOW_REC *window, int immortal); /* return active item's name, or if none is active, window's name */ -char *window_get_active_name(WINDOW_REC *window); +const char *window_get_active_name(WINDOW_REC *window); WINDOW_REC *window_find_level(void *server, int level); WINDOW_REC *window_find_closest(void *server, const char *name, int level); diff --git a/apps/irssi/src/fe-common/core/hilight-text.c b/apps/irssi/src/fe-common/core/hilight-text.c index 4d5466e2..9749504b 100644 --- a/apps/irssi/src/fe-common/core/hilight-text.c +++ b/apps/irssi/src/fe-common/core/hilight-text.c @@ -112,12 +112,38 @@ static void hilights_destroy_all(void) hilights = NULL; } -static void hilight_remove(HILIGHT_REC *rec) +static void hilight_init_rec(HILIGHT_REC *rec) +{ +#ifdef HAVE_REGEX_H + if (rec->regexp_compiled) regfree(&rec->preg); + rec->regexp_compiled = !rec->regexp ? FALSE : + regcomp(&rec->preg, rec->text, REG_EXTENDED|REG_ICASE) == 0; +#endif +} + +void hilight_create(HILIGHT_REC *rec) +{ + if (g_slist_find(hilights, rec) != NULL) { + hilights = g_slist_remove(hilights, rec); + hilight_remove_config(rec); + } + + hilights = g_slist_append(hilights, rec); + hilight_add_config(rec); + + hilight_init_rec(rec); + + signal_emit("hilight created", 1, rec); +} + +void hilight_remove(HILIGHT_REC *rec) { g_return_if_fail(rec != NULL); hilight_remove_config(rec); hilights = g_slist_remove(hilights, rec); + + signal_emit("hilight destroyed", 1, rec); hilight_destroy(rec); } @@ -435,11 +461,7 @@ static void read_hilight_config(void) rec->fullword = config_node_get_bool(node, "fullword", FALSE); rec->regexp = config_node_get_bool(node, "regexp", FALSE); -#ifdef HAVE_REGEX_H - rec->regexp_compiled = !rec->regexp ? FALSE : - regcomp(&rec->preg, rec->text, - REG_EXTENDED|REG_ICASE) == 0; -#endif + hilight_init_rec(rec); node = config_node_section(node, "channels", -1); if (node != NULL) rec->channels = config_node_get_list(node); @@ -451,6 +473,32 @@ static void read_hilight_config(void) static void hilight_print(int index, HILIGHT_REC *rec) { char *chans, *levelstr; + GString *options; + + options = g_string_new(NULL); + if (!rec->nick || !rec->word) { + if (rec->nick) g_string_append(options, "-nick "); + if (rec->word) g_string_append(options, "-word "); + } + + if (rec->nickmask) g_string_append(options, "-nickmask "); + if (rec->fullword) g_string_append(options, "-fullword "); + if (rec->regexp) { + g_string_append(options, "-regexp "); +#ifdef HAVE_REGEX_H + if (!rec->regexp_compiled) + g_string_append(options, "[INVALID!] "); +#endif + } + + if (options->len > 1) g_string_truncate(options, options->len-1); + + if (rec->priority != 0) + g_string_sprintfa(options, "-priority %d ", rec->priority); + if (rec->color != NULL) + g_string_sprintfa(options, "-color %s ", rec->color); + if (rec->act_color != NULL) + g_string_sprintfa(options, "-actcolor %s ", rec->act_color); chans = rec->channels == NULL ? NULL : g_strjoinv(",", rec->channels); @@ -460,11 +508,10 @@ static void hilight_print(int index, HILIGHT_REC *rec) TXT_HILIGHT_LINE, index, rec->text, chans != NULL ? chans : "", levelstr != NULL ? levelstr : "", - rec->nickmask ? " -mask" : "", - rec->fullword ? " -full" : "", - rec->regexp ? " -regexp" : ""); + options->str); g_free_not_null(chans); g_free_not_null(levelstr); + g_string_free(options, TRUE); } static void cmd_hilight_show(void) @@ -527,9 +574,6 @@ static void cmd_hilight(const char *data) rec->channels = channels; } else { g_strfreev(channels); - - hilight_remove_config(rec); - hilights = g_slist_remove(hilights, rec); } rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 : @@ -564,15 +608,7 @@ static void cmd_hilight(const char *data) rec->act_color = g_strdup(actcolorarg); } -#ifdef HAVE_REGEX_H - if (rec->regexp_compiled) - regfree(&rec->preg); - rec->regexp_compiled = !rec->regexp ? FALSE : - regcomp(&rec->preg, rec->text, REG_EXTENDED|REG_ICASE) == 0; -#endif - - hilights = g_slist_append(hilights, rec); - hilight_add_config(rec); + hilight_create(rec); hilight_print(g_slist_index(hilights, rec)+1, rec); cmd_params_free(free_arg); diff --git a/apps/irssi/src/fe-common/core/hilight-text.h b/apps/irssi/src/fe-common/core/hilight-text.h index 92093bb1..6e510737 100644 --- a/apps/irssi/src/fe-common/core/hilight-text.h +++ b/apps/irssi/src/fe-common/core/hilight-text.h @@ -5,7 +5,9 @@ # include #endif -typedef struct { +typedef struct _HILIGHT_REC HILIGHT_REC; + +struct _HILIGHT_REC { char *text; char **channels; /* if non-NULL, check the text only from these channels */ @@ -25,7 +27,7 @@ typedef struct { unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ regex_t preg; #endif -} HILIGHT_REC; +}; extern GSList *hilights; @@ -38,6 +40,9 @@ char *hilight_match_nick(SERVER_REC *server, const char *channel, const char *nick, const char *address, int level, const char *msg); +void hilight_create(HILIGHT_REC *rec); +void hilight_remove(HILIGHT_REC *rec); + void hilight_text_init(void); void hilight_text_deinit(void); diff --git a/apps/irssi/src/fe-common/core/keyboard.c b/apps/irssi/src/fe-common/core/keyboard.c index fb1d89fe..9bbb218a 100644 --- a/apps/irssi/src/fe-common/core/keyboard.c +++ b/apps/irssi/src/fe-common/core/keyboard.c @@ -388,6 +388,8 @@ static void key_configure_destroy(KEY_REC *rec) rec->info->keys = g_slist_remove(rec->info->keys, rec); g_hash_table_remove(keys, rec->key); + signal_emit("key destroyed", 1, rec); + if (!key_config_frozen) key_states_rescan(); @@ -421,6 +423,8 @@ static void key_configure_create(const char *id, const char *key, info->keys = g_slist_append(info->keys, rec); g_hash_table_insert(keys, rec->key, rec); + signal_emit("key created", 1, rec); + if (!key_config_frozen) key_states_rescan(); } diff --git a/apps/irssi/src/fe-common/core/keyboard.h b/apps/irssi/src/fe-common/core/keyboard.h index c508d53b..eff8966a 100644 --- a/apps/irssi/src/fe-common/core/keyboard.h +++ b/apps/irssi/src/fe-common/core/keyboard.h @@ -4,20 +4,22 @@ #include "signals.h" typedef struct _KEYBOARD_REC KEYBOARD_REC; +typedef struct _KEYINFO_REC KEYINFO_REC; +typedef struct _KEY_REC KEY_REC; -typedef struct { +struct _KEYINFO_REC { char *id; char *description; GSList *keys, *default_keys; -} KEYINFO_REC; +}; -typedef struct { +struct _KEY_REC { KEYINFO_REC *info; char *key; char *data; -} KEY_REC; +}; extern GSList *keyinfos; diff --git a/apps/irssi/src/fe-common/core/module-formats.c b/apps/irssi/src/fe-common/core/module-formats.c index 223eb3ac..2d4f02e1 100644 --- a/apps/irssi/src/fe-common/core/module-formats.c +++ b/apps/irssi/src/fe-common/core/module-formats.c @@ -153,7 +153,7 @@ FORMAT_REC fecommon_core_formats[] = { { NULL, "Highlighting", 0 }, { "hilight_header", "%#Highlights:", 0 }, - { "hilight_line", "%#$[-4]0 $1 $2 $3$4$5", 7, { 1, 0, 0, 0, 0, 0, 0 } }, + { "hilight_line", "%#$[-4]0 $1 $2 $3$4", 5, { 1, 0, 0, 0, 0 } }, { "hilight_footer", "", 0 }, { "hilight_not_found", "Highlight not found: $0", 1, { 0 } }, { "hilight_removed", "Highlight removed: $0", 1, { 0 } }, @@ -234,6 +234,7 @@ FORMAT_REC fecommon_core_formats[] = { { NULL, "Ignores", 0 }, { "ignored", "Ignoring {hilight $1} from {nick $0}", 2, { 0, 0 } }, + { "ignored_options", "Ignoring {hilight $1} from {nick $0} {comment $2}", 3, { 0, 0, 0 } }, { "unignored", "Unignored {nick $0}", 1, { 0 } }, { "ignore_not_found", "{nick $0} is not being ignored", 1, { 0 } }, { "ignore_no_ignores", "There are no ignores", 0 }, @@ -263,6 +264,11 @@ FORMAT_REC fecommon_core_formats[] = { { "set_not_boolean", "Setting {hilight $0} isn't boolean, use /SET", 1, { 0 } }, { "translation_not_found", "Error opening translation table file $0: $1", 2, { 0, 0 } }, { "translation_file_error", "Error parsing translation table file $0", 1, { 0 } }, + { "no_completions", "There's no completions", 0 }, + { "completion_removed", "Removed completion $0", 1, { 0 } }, + { "completion_header", "%#Key Value Auto", 0 }, + { "completion_line", "%#$[10]0 $[!40]1 $2", 3, { 0, 0, 0 } }, + { "completion_footer", "", 0 }, { NULL, NULL, 0 } }; diff --git a/apps/irssi/src/fe-common/core/module-formats.h b/apps/irssi/src/fe-common/core/module-formats.h index e4d74461..7cd46bab 100644 --- a/apps/irssi/src/fe-common/core/module-formats.h +++ b/apps/irssi/src/fe-common/core/module-formats.h @@ -201,6 +201,7 @@ enum { TXT_FILL_12, TXT_IGNORED, + TXT_IGNORED_OPTIONS, TXT_UNIGNORED, TXT_IGNORE_NOT_FOUND, TXT_IGNORE_NO_IGNORES, @@ -228,7 +229,12 @@ enum { TXT_SET_UNKNOWN, TXT_SET_NOT_BOOLEAN, TXT_TRANSLATION_NOT_FOUND, - TXT_TRANSLATION_FILE_ERROR + TXT_TRANSLATION_FILE_ERROR, + TXT_NO_COMPLETIONS, + TXT_COMPLETION_REMOVED, + TXT_COMPLETION_HEADER, + TXT_COMPLETION_LINE, + TXT_COMPLETION_FOOTER }; extern FORMAT_REC fecommon_core_formats[]; diff --git a/apps/irssi/src/fe-common/core/printtext.c b/apps/irssi/src/fe-common/core/printtext.c index dbd52343..e32b5943 100644 --- a/apps/irssi/src/fe-common/core/printtext.c +++ b/apps/irssi/src/fe-common/core/printtext.c @@ -70,7 +70,7 @@ void printformat_module_dest_args(const char *module, TEXT_DEST_REC *dest, str = format_get_text_theme_charargs(theme, module, dest, formatnum, arglist); - if (*str != '\0') print_line(dest, str); + if (str != NULL && *str != '\0') print_line(dest, str); g_free(str); } diff --git a/apps/irssi/src/fe-common/core/themes.c b/apps/irssi/src/fe-common/core/themes.c index ec4a994a..baa1d3e5 100644 --- a/apps/irssi/src/fe-common/core/themes.c +++ b/apps/irssi/src/fe-common/core/themes.c @@ -50,6 +50,7 @@ THEME_REC *theme_create(const char *path, const char *name) g_return_val_if_fail(name != NULL, NULL); rec = g_new0(THEME_REC, 1); + rec->refcount = 1; rec->path = g_strdup(path); rec->name = g_strdup(name); rec->abstracts = g_hash_table_new((GHashFunc) g_str_hash, @@ -83,12 +84,8 @@ static void theme_module_destroy(const char *key, MODULE_THEME_REC *rec) g_free(rec); } -void theme_destroy(THEME_REC *rec) +static void theme_real_destroy(THEME_REC *rec) { - themes = g_slist_remove(themes, rec); - - signal_emit("theme destroyed", 1, rec); - g_hash_table_foreach(rec->abstracts, (GHFunc) theme_abstract_destroy, NULL); g_hash_table_destroy(rec->abstracts); g_hash_table_foreach(rec->modules, (GHFunc) theme_module_destroy, NULL); @@ -102,6 +99,20 @@ void theme_destroy(THEME_REC *rec) g_free(rec); } +static void theme_unref(THEME_REC *rec) +{ + if (--rec->refcount == 0) + theme_real_destroy(rec); +} + +void theme_destroy(THEME_REC *rec) +{ + themes = g_slist_remove(themes, rec); + signal_emit("theme destroyed", 1, rec); + + theme_unref(rec); +} + static char *theme_replace_expand(THEME_REC *theme, int index, char default_fg, char default_bg, char *last_fg, char *last_bg, @@ -242,10 +253,11 @@ static int data_is_empty(const char **data) { /* since we don't know the real argument list, assume there's always an argument in them */ - char *arglist[] = { + static char *arglist[] = { "x", "x", "x", "x", "x", "x","x", "x", "x", "x", NULL }; + SERVER_REC *server; const char *p; char *ret; int free_ret, empty; @@ -266,8 +278,12 @@ static int data_is_empty(const char **data) /* variable - check if it's empty */ p++; - ret = parse_special((char **) &p, - active_win == NULL ? NULL : active_win->active_server, + + server = active_win == NULL ? NULL : + active_win->active_server != NULL ? + active_win->active_server : active_win->connect_server; + + ret = parse_special((char **) &p, server, active_win == NULL ? NULL : active_win->active, arglist, &free_ret, NULL, 0); p++; @@ -1207,10 +1223,20 @@ static void read_settings(void) static void themes_read(void) { + GSList *refs; char *fname; - while (themes != NULL) - theme_destroy(themes->data); + /* increase every theme's refcount, and destroy them. this way if + we want to use the theme before it's reloaded we don't crash. */ + refs = NULL; + while (themes != NULL) { + THEME_REC *theme = themes->data; + + refs = g_slist_prepend(refs, theme); + + theme->refcount++; + theme_destroy(theme); + } /* first there's default theme.. */ current_theme = theme_load("default"); @@ -1223,7 +1249,12 @@ static void themes_read(void) } window_themes_update(); - change_theme(settings_get_str("theme"), FALSE); + change_theme(settings_get_str("theme"), FALSE); + + while (refs != NULL) { + theme_unref(refs->data); + refs = g_slist_remove(refs, refs->data); + } } void themes_init(void) diff --git a/apps/irssi/src/fe-common/core/themes.h b/apps/irssi/src/fe-common/core/themes.h index 3ef7cb92..0a809b95 100644 --- a/apps/irssi/src/fe-common/core/themes.h +++ b/apps/irssi/src/fe-common/core/themes.h @@ -11,6 +11,8 @@ typedef struct { } MODULE_THEME_REC; typedef struct { + int refcount; + char *path; char *name; time_t last_modify; diff --git a/apps/irssi/src/fe-common/core/window-commands.c b/apps/irssi/src/fe-common/core/window-commands.c index bbe495aa..a8f3bb10 100644 --- a/apps/irssi/src/fe-common/core/window-commands.c +++ b/apps/irssi/src/fe-common/core/window-commands.c @@ -64,7 +64,8 @@ static void window_print_items(WINDOW_REC *win) type = module_find_id_str("WINDOW ITEM TYPE", item->type); printformat_window(win, MSGLEVEL_CLIENTCRAP, TXT_WINDOW_INFO_ITEM, - type == NULL ? "??" : type, item->name, + type == NULL ? "??" : type, + item->visible_name, item->server == NULL ? "" : item->server->tag); } @@ -279,6 +280,8 @@ static WINDOW_REC *window_highest_activity(WINDOW_REC *window) static void cmd_window_goto(const char *data) { WINDOW_REC *window; + char *target; + void *free_arg; g_return_if_fail(data != NULL); @@ -287,13 +290,18 @@ static void cmd_window_goto(const char *data) return; } - if (g_strcasecmp(data, "active") == 0) + if (!cmd_get_params(data, &free_arg, 1, &target)) + return; + + if (g_strcasecmp(target, "active") == 0) window = window_highest_activity(active_win); else - window = window_find_item(active_win->active_server, data); + window = window_find_item(active_win->active_server, target); if (window != NULL) window_set_active(window); + + cmd_params_free(free_arg); } /* SYNTAX: WINDOW NEXT */ @@ -392,6 +400,8 @@ static void cmd_window_server(const char *data) if (*tag == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); server = server_find_tag(tag); + if (server == NULL) + server = server_find_lookup_tag(tag); if (g_hash_table_lookup(optlist, "unsticky") != NULL && active_win->servertag != NULL) { @@ -616,17 +626,10 @@ static void cmd_window_move_next(void) window_refnums_move_right(active_win); } -/* SYNTAX: WINDOW MOVE | */ -static void cmd_window_move(const char *data, SERVER_REC *server, WI_ITEM_REC *item) +static void active_window_move_to(int new_refnum) { - int new_refnum, refnum; - - if (!is_numeric(data, 0)) { - command_runsub("window move", data, server, item); - return; - } + int refnum; - new_refnum = atoi(data); if (new_refnum > active_win->refnum) { for (;;) { refnum = window_refnum_next(active_win->refnum, FALSE); @@ -646,6 +649,29 @@ static void cmd_window_move(const char *data, SERVER_REC *server, WI_ITEM_REC *i } } +/* SYNTAX: WINDOW MOVE FIRST */ +static void cmd_window_move_first(void) +{ + active_window_move_to(1); +} + +/* SYNTAX: WINDOW MOVE LAST */ +static void cmd_window_move_last(void) +{ + active_window_move_to(windows_refnum_last()); +} + +/* SYNTAX: WINDOW MOVE | */ +static void cmd_window_move(const char *data, SERVER_REC *server, WI_ITEM_REC *item) +{ + if (!is_numeric(data, 0)) { + command_runsub("window move", data, server, item); + return; + } + + active_window_move_to(atoi(data)); +} + /* SYNTAX: WINDOW LIST */ static void cmd_window_list(void) { @@ -660,7 +686,7 @@ static void cmd_window_list(void) levelstr = bits2level(rec->level); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_WINDOWLIST_LINE, rec->refnum, rec->name == NULL ? "" : rec->name, - rec->active == NULL ? "" : rec->active->name, + rec->active == NULL ? "" : rec->active->visible_name, rec->active_server == NULL ? "" : ((SERVER_REC *) rec->active_server)->tag, levelstr); g_free(levelstr); @@ -737,7 +763,8 @@ static void cmd_foreach_window(const char *data) list = g_slist_remove(list, list->data); } - active_win = old; + if (g_slist_find(windows, old) != NULL) + active_win = old; } void window_commands_init(void) @@ -765,6 +792,8 @@ void window_commands_init(void) command_bind("window move", NULL, (SIGNAL_FUNC) cmd_window_move); command_bind("window move prev", NULL, (SIGNAL_FUNC) cmd_window_move_prev); command_bind("window move next", NULL, (SIGNAL_FUNC) cmd_window_move_next); + command_bind("window move first", NULL, (SIGNAL_FUNC) cmd_window_move_first); + command_bind("window move last", NULL, (SIGNAL_FUNC) cmd_window_move_last); command_bind("window list", NULL, (SIGNAL_FUNC) cmd_window_list); command_bind("window theme", NULL, (SIGNAL_FUNC) cmd_window_theme); command_bind("layout", NULL, (SIGNAL_FUNC) cmd_layout); @@ -804,6 +833,8 @@ void window_commands_deinit(void) command_unbind("window move", (SIGNAL_FUNC) cmd_window_move); command_unbind("window move prev", (SIGNAL_FUNC) cmd_window_move_prev); command_unbind("window move next", (SIGNAL_FUNC) cmd_window_move_next); + command_unbind("window move first", (SIGNAL_FUNC) cmd_window_move_first); + command_unbind("window move last", (SIGNAL_FUNC) cmd_window_move_last); command_unbind("window list", (SIGNAL_FUNC) cmd_window_list); command_unbind("window theme", (SIGNAL_FUNC) cmd_window_theme); command_unbind("layout", (SIGNAL_FUNC) cmd_layout); diff --git a/apps/irssi/src/fe-common/core/window-items.c b/apps/irssi/src/fe-common/core/window-items.c index e53e5a1d..ce4b57e0 100644 --- a/apps/irssi/src/fe-common/core/window-items.c +++ b/apps/irssi/src/fe-common/core/window-items.c @@ -23,6 +23,7 @@ #include "modules.h" #include "signals.h" #include "servers.h" +#include "channels.h" #include "settings.h" #include "levels.h" @@ -195,15 +196,23 @@ void window_item_next(WINDOW_REC *window) WI_ITEM_REC *window_item_find_window(WINDOW_REC *window, void *server, const char *name) { + CHANNEL_REC *channel; GSList *tmp; for (tmp = window->items; tmp != NULL; tmp = tmp->next) { WI_ITEM_REC *rec = tmp->data; if ((server == NULL || rec->server == server) && - g_strcasecmp(name, rec->name) == 0) return rec; + g_strcasecmp(name, rec->visible_name) == 0) + return rec; } + /* try with channel name too, it's not necessarily + same as visible_name (!channels) */ + channel = channel_find(server, name); + if (channel != NULL && window_item_window(channel) == window) + return (WI_ITEM_REC *) channel; + return NULL; } @@ -259,7 +268,7 @@ void window_item_create(WI_ITEM_REC *item, int automatic) /* is item bound to this window? */ if (item->server != NULL) { bind = window_bind_find(rec, item->server->tag, - item->name); + item->visible_name); if (bind != NULL) { if (!bind->sticky) window_bind_destroy(rec, bind); @@ -316,8 +325,9 @@ static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item) if (g_slist_length(window->items) > 1) { /* default to printing "talking with ...", you can override it it you wish */ - printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE, - TXT_TALKING_WITH, item->name); + printformat(item->server, item->visible_name, + MSGLEVEL_CLIENTNOTICE, + TXT_TALKING_WITH, item->visible_name); } } diff --git a/apps/irssi/src/fe-common/core/windows-layout.c b/apps/irssi/src/fe-common/core/windows-layout.c index a19b2942..9429c00a 100644 --- a/apps/irssi/src/fe-common/core/windows-layout.c +++ b/apps/irssi/src/fe-common/core/windows-layout.c @@ -136,6 +136,7 @@ static void sig_layout_save_item(WINDOW_REC *window, WI_ITEM_REC *item, CONFIG_NODE *node) { CONFIG_NODE *subnode; + CHAT_PROTOCOL_REC *proto; const char *type; type = module_find_id_str("WINDOW ITEM TYPE", item->type); @@ -145,9 +146,11 @@ static void sig_layout_save_item(WINDOW_REC *window, WI_ITEM_REC *item, subnode = config_node_section(node, NULL, NODE_TYPE_BLOCK); iconfig_node_set_str(subnode, "type", type); - type = chat_protocol_find_id(item->chat_type)->name; - iconfig_node_set_str(subnode, "chat_type", type); - iconfig_node_set_str(subnode, "name", item->name); + proto = item->chat_type == 0 ? NULL : + chat_protocol_find_id(item->chat_type); + if (proto != NULL) + iconfig_node_set_str(subnode, "chat_type", proto->name); + iconfig_node_set_str(subnode, "name", item->visible_name); if (item->server != NULL) iconfig_node_set_str(subnode, "tag", item->server->tag); diff --git a/apps/irssi/src/fe-text/Makefile.am b/apps/irssi/src/fe-text/Makefile.am index b6a005a2..d1d51c46 100644 --- a/apps/irssi/src/fe-text/Makefile.am +++ b/apps/irssi/src/fe-text/Makefile.am @@ -23,6 +23,7 @@ silc_LDADD = \ @PERL_FE_LINK_LIBS@ \ @PERL_LINK_FLAGS@ \ @PROG_LIBS@ \ + @TEXTUI_LIBS@ \ -L../../../lib -lsilcclient silc_LDFLAGS = -export-dynamic diff --git a/apps/irssi/src/fe-text/gui-entry.c b/apps/irssi/src/fe-text/gui-entry.c index e7e5fcc5..f6bfb27d 100644 --- a/apps/irssi/src/fe-text/gui-entry.c +++ b/apps/irssi/src/fe-text/gui-entry.c @@ -104,7 +104,11 @@ static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos) p = entry->scrstart + pos < entry->text_len ? entry->text + entry->scrstart + pos : empty_str; - for (; *p != '\0' && xpos < end_xpos; p++, xpos++) { + for (; *p != '\0'; p++) { + xpos += utf8_width(*p); + if (xpos > end_xpos) + break; + if (entry->hidden) term_addch(root_window, ' '); else if (*p >= 32 && (entry->utf8 || (*p & 127) >= 32)) diff --git a/apps/irssi/src/fe-text/gui-readline.c b/apps/irssi/src/fe-text/gui-readline.c index c23b42c7..1cabfac7 100644 --- a/apps/irssi/src/fe-text/gui-readline.c +++ b/apps/irssi/src/fe-text/gui-readline.c @@ -162,6 +162,12 @@ void handle_key(unichar key) str[utf16_char_to_utf8(key, str)] = '\0'; } + if (strcmp(str, "^") == 0) { + /* change it as ^^ */ + str[1] = '^'; + str[2] = '\0'; + } + if (escape_next_key || !key_pressed(keyboard, str)) { /* key wasn't used for anything, print it */ escape_next_key = FALSE; @@ -175,14 +181,10 @@ static void key_send_line(void) char *str, *add_history; str = gui_entry_get_text(active_entry); - if (str == NULL || (*str == '\0' && redir == NULL)) { - g_free(str); - return; - } /* we can't use gui_entry_get_text() later, since the entry might have been destroyed after we get back */ - add_history = g_strdup(str); + add_history = *str == '\0' ? NULL : g_strdup(str); history = command_history_current(active_win); translate_output(str); @@ -481,43 +483,98 @@ static void key_active_window(void) signal_emit("command window goto", 3, "active", active_win->active_server, active_win->active); } +static SERVER_REC *get_prev_server(SERVER_REC *current) +{ + int pos; + + if (current == NULL) { + return servers != NULL ? g_slist_last(servers)->data : + lookup_servers != NULL ? + g_slist_last(lookup_servers)->data : NULL; + } + + /* connect2 -> connect1 -> server2 -> server1 -> connect2 -> .. */ + + pos = g_slist_index(servers, current); + if (pos != -1) { + if (pos > 0) + return g_slist_nth(servers, pos-1)->data; + if (lookup_servers != NULL) + return g_slist_last(lookup_servers)->data; + return g_slist_last(servers)->data; + } + + pos = g_slist_index(lookup_servers, current); + g_assert(pos >= 0); + + if (pos > 0) + return g_slist_nth(lookup_servers, pos-1)->data; + if (servers != NULL) + return g_slist_last(servers)->data; + return g_slist_last(lookup_servers)->data; +} + +static SERVER_REC *get_next_server(SERVER_REC *current) +{ + GSList *pos; + + if (current == NULL) { + return servers != NULL ? servers->data : + lookup_servers != NULL ? lookup_servers->data : NULL; + } + + /* server1 -> server2 -> connect1 -> connect2 -> server1 -> .. */ + + pos = g_slist_find(servers, current); + if (pos != NULL) { + if (pos->next != NULL) + return pos->next->data; + if (lookup_servers != NULL) + return lookup_servers->data; + return servers->data; + } + + pos = g_slist_find(lookup_servers, current); + g_assert(pos != NULL); + + if (pos->next != NULL) + return pos->next->data; + if (servers != NULL) + return servers->data; + return lookup_servers->data; +} + static void key_previous_window_item(void) { SERVER_REC *server; - GSList *pos; - if (active_win->items != NULL) - signal_emit("command window item prev", 3, "", active_win->active_server, active_win->active); - else if (servers != NULL) { + if (active_win->items != NULL) { + signal_emit("command window item prev", 3, "", + active_win->active_server, active_win->active); + } else if (servers != NULL || lookup_servers != NULL) { /* change server */ - if (active_win->active_server == NULL) - server = servers->data; - else { - pos = g_slist_find(servers, active_win->active_server); - server = pos->next != NULL ? pos->next->data : servers->data; - } - signal_emit("command window server", 3, server->tag, active_win->active_server, active_win->active); + server = active_win->active_server; + if (server == NULL) + server = active_win->connect_server; + server = get_prev_server(server); + signal_emit("command window server", 3, server->tag, + active_win->active_server, active_win->active); } } static void key_next_window_item(void) { SERVER_REC *server; - int index; if (active_win->items != NULL) { signal_emit("command window item next", 3, "", active_win->active_server, active_win->active); - } - else if (servers != NULL) { + } else if (servers != NULL || lookup_servers != NULL) { /* change server */ - if (active_win->active_server == NULL) - server = servers->data; - else { - index = g_slist_index(servers, active_win->active_server); - server = index > 0 ? g_slist_nth(servers, index-1)->data : - g_slist_last(servers)->data; - } + server = active_win->active_server; + if (server == NULL) + server = active_win->connect_server; + server = get_next_server(server); signal_emit("command window server", 3, server->tag, active_win->active_server, active_win->active); } @@ -647,7 +704,7 @@ void gui_readline_init(void) key_bind("backspace", "", "backspace", NULL, (SIGNAL_FUNC) key_backspace); key_bind("delete_character", "", "delete", NULL, (SIGNAL_FUNC) key_delete_character); key_bind("delete_character", NULL, "^D", NULL, (SIGNAL_FUNC) key_delete_character); - key_bind("delete_next_word", "", NULL, NULL, (SIGNAL_FUNC) key_delete_next_word); + key_bind("delete_next_word", "meta-d", NULL, NULL, (SIGNAL_FUNC) key_delete_next_word); key_bind("delete_previous_word", "meta-backspace", NULL, NULL, (SIGNAL_FUNC) key_delete_previous_word); key_bind("delete_to_previous_space", "", "^W", NULL, (SIGNAL_FUNC) key_delete_to_previous_space); key_bind("delete_to_next_space", "", "", NULL, (SIGNAL_FUNC) key_delete_to_next_space); diff --git a/apps/irssi/src/fe-text/mainwindows-save.c b/apps/irssi/src/fe-text/mainwindows-save.c deleted file mode 100644 index 113037b1..00000000 --- a/apps/irssi/src/fe-text/mainwindows-save.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - mainwindows-save.c : irssi - - Copyright (C) 2001 Timo Sirainen - - 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 "module.h" -#include "signals.h" -#include "misc.h" -#include "lib-config/iconfig.h" -#include "settings.h" - -#include "mainwindows.h" -#include "gui-windows.h" - -static void main_window_save(MAIN_WINDOW_REC *window, CONFIG_NODE *node) -{ - GSList *tmp; - GString *str; - char num[MAX_INT_STRLEN]; - - ltoa(num, window->active->refnum); - node = config_node_section(node, num, NODE_TYPE_BLOCK); - - iconfig_node_set_int(node, "first_line", window->first_line); - iconfig_node_set_int(node, "lines", window->height); - - str = g_string_new(NULL); - for (tmp = window->sticky_windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; - g_string_sprintfa(str, "%d ", rec->refnum); - } - if (str->len > 1) { - g_string_truncate(str, str->len-1); - iconfig_node_set_str(node, "sticky", str->str); - } - g_string_free(str, TRUE); -} - -static void sig_windows_saved(void) -{ - CONFIG_NODE *node; - - iconfig_set_str(NULL, "mainwindows", NULL); - node = iconfig_node_traverse("mainwindows", TRUE); - - g_slist_foreach(mainwindows, (GFunc) main_window_save, node); -} - -static int window_node_cmp(CONFIG_NODE *n1, CONFIG_NODE *n2) -{ - return config_node_get_int(n1, "first_line", 0) < - config_node_get_int(n2, "first_line", 0) ? -1 : 1; -} - -static GSList *read_sorted_windows(CONFIG_NODE *node) -{ - GSList *tmp, *output; - - output = NULL; - for (tmp = node->value; tmp != NULL; tmp = tmp->next) { - output = g_slist_insert_sorted(output, tmp->data, - (GCompareFunc) window_node_cmp); - } - - return output; -} - -static void restore_sticky_windows(CONFIG_NODE *node, - MAIN_WINDOW_REC *mainwindow) -{ - WINDOW_REC *window; - char **sticky_list, **sticky; - - sticky_list = g_strsplit(config_node_get_str(node, "sticky", ""), " ", -1); - for (sticky = sticky_list; *sticky != NULL; sticky++) { - window = window_find_refnum(atoi(*sticky)); - if (window != NULL) { - mainwindow->sticky_windows = - g_slist_append(mainwindow->sticky_windows, - window); - } - } - g_strfreev(sticky_list); -} - -static WINDOW_REC *window_find_hidden(void) -{ - GSList *tmp; - - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; - - if (!is_window_visible(rec)) - return rec; - } - - return NULL; -} - -static void sig_windows_restored(void) -{ - MAIN_WINDOW_REC *mainwindow, *lowerwin; - WINDOW_REC *window; - CONFIG_NODE *node; - GSList *tmp, *tmp2, *sorted_windows, *sorted_config; - int count, newsize; - - node = iconfig_node_traverse("mainwindows", FALSE); - if (node == NULL) return; - - /* create all windows, shrink the lower windows to minimum size */ - lowerwin = mainwindows->data; - count = g_slist_length(node->value); - while (count > 1) { - window = window_find_hidden(); - if (window == NULL) - break; - - mainwindow = mainwindow_create(); - if (mainwindow == NULL) - break; - - mainwindow->active = window; - WINDOW_GUI(window)->parent = mainwindow; - - active_mainwin = NULL; - window_set_active(window); - - if (lowerwin->height > WINDOW_MIN_SIZE) - mainwindow_set_size(lowerwin, WINDOW_MIN_SIZE); - count--; - - lowerwin = mainwindow; - } - - sorted_config = read_sorted_windows(node); - sorted_windows = mainwindows_get_sorted(FALSE); - for (tmp = sorted_windows, tmp2 = sorted_config; - tmp != NULL && tmp2 != NULL; - tmp = tmp->next, tmp2 = tmp2->next) { - MAIN_WINDOW_REC *mainwindow = tmp->data; - CONFIG_NODE *node = tmp2->data; - - window = window_find_refnum(atoi(node->key)); - if (window == NULL) { - mainwindow_destroy(mainwindow); - continue; - } - - if (is_window_visible(window)) { - active_mainwin = WINDOW_GUI(window)->parent; - window_set_active(window_find_hidden()); - } - - active_mainwin = mainwindow; - window_set_active(window); - - restore_sticky_windows(node, mainwindow); - - newsize = config_node_get_int(node, "lines", 0); - if (newsize > 0) - mainwindow_set_size(mainwindow, newsize); - } - g_slist_free(sorted_windows); - g_slist_free(sorted_config); - - irssi_redraw(); -} - -void mainwindows_save_init(void) -{ - signal_add("windows saved", (SIGNAL_FUNC) sig_windows_saved); - signal_add("windows restored", (SIGNAL_FUNC) sig_windows_restored); -} - -void mainwindows_save_deinit(void) -{ - signal_remove("windows saved", (SIGNAL_FUNC) sig_windows_saved); - signal_remove("windows restored", (SIGNAL_FUNC) sig_windows_restored); -} diff --git a/apps/irssi/src/fe-text/screen.c b/apps/irssi/src/fe-text/screen.c deleted file mode 100644 index 3657a23d..00000000 --- a/apps/irssi/src/fe-text/screen.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - screen.c : irssi - - Copyright (C) 1999-2000 Timo Sirainen - - 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 "module.h" -#include "signals.h" -#include "misc.h" -#include "settings.h" - -#include "screen.h" -#include "gui-readline.h" -#include "mainwindows.h" - -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#include - -#ifndef COLOR_PAIRS -#define COLOR_PAIRS 64 -#endif - -#define MIN_SCREEN_WIDTH 20 - -static int scrx, scry; -static int use_colors; -static int freeze_refresh; -static int resized; - -static int init_screen_int(void); -static void deinit_screen_int(void); - -#ifdef SIGWINCH -static void sig_winch(int p) -{ - resized = TRUE; -} -#endif - -static void screen_resize(void) -{ -#if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM) - struct winsize ws; - - /* Get new window size */ - if (ioctl(0, TIOCGWINSZ, &ws) < 0) - return; - - if (ws.ws_row == LINES && ws.ws_col == COLS) { - /* Same size, abort. */ - return; - } - - if (ws.ws_col < MIN_SCREEN_WIDTH) - ws.ws_col = MIN_SCREEN_WIDTH; - - /* Resize curses terminal */ - resizeterm(ws.ws_row, ws.ws_col); -#else - deinit_screen_int(); - init_screen_int(); - mainwindows_recreate(); -#endif - - mainwindows_resize(COLS, LINES); -} - -void screen_check_resizes(void) -{ - if (!resized) - return; - screen_resize(); - resized = FALSE; -} - -static void read_signals(void) -{ -#ifndef WIN32 - int signals[] = { - SIGHUP, SIGINT, SIGQUIT, SIGTERM, - SIGALRM, SIGUSR1, SIGUSR2 - }; - char *signames[] = { - "hup", "int", "quit", "term", - "alrm", "usr1", "usr2" - }; - - const char *ignores; - struct sigaction act; - int n; - - ignores = settings_get_str("ignore_signals"); - - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - - for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) { - act.sa_handler = find_substr(ignores, signames[n]) ? - SIG_IGN : SIG_DFL; - sigaction(signals[n], &act, NULL); - } -#endif -} - -static void read_settings(void) -{ - int old_colors = use_colors; - - use_colors = settings_get_bool("colors"); - read_signals(); - if (use_colors && !has_colors()) - use_colors = FALSE; - - if (use_colors != old_colors) - irssi_redraw(); -} - -static int init_curses(void) -{ - char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - int num; -#ifndef WIN32 - struct sigaction act; -#endif - - if (!initscr()) - return FALSE; - - if (COLS < MIN_SCREEN_WIDTH) - COLS = MIN_SCREEN_WIDTH; - -#ifdef SIGWINCH - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = sig_winch; - sigaction(SIGWINCH, &act, NULL); -#endif - raw(); noecho(); idlok(stdscr, 1); -#ifdef HAVE_CURSES_IDCOK - idcok(stdscr, 1); -#endif - intrflush(stdscr, FALSE); nodelay(stdscr, TRUE); - - if (has_colors()) - start_color(); - else if (use_colors) - use_colors = FALSE; - -#ifdef HAVE_NCURSES_USE_DEFAULT_COLORS - /* this lets us to use the "default" background color for colors <= 7 so - background pixmaps etc. show up right */ - use_default_colors(); - - for (num = 1; num < COLOR_PAIRS; num++) - init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]); - - init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more - people want dark grey than white on white.. */ -#else - for (num = 1; num < COLOR_PAIRS; num++) - init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]); - init_pair(63, 0, 0); -#endif - - clear(); - return TRUE; -} - -static int init_screen_int(void) -{ - use_colors = settings_get_bool("colors"); - read_signals(); - - scrx = scry = 0; - freeze_refresh = 0; - - return init_curses(); -} - -static void deinit_screen_int(void) -{ - endwin(); -} - -/* Initialize screen, detect screen length */ -int init_screen(void) -{ - settings_add_bool("lookandfeel", "colors", TRUE); - settings_add_str("misc", "ignore_signals", ""); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); - - return init_screen_int(); -} - -/* Deinitialize screen */ -void deinit_screen(void) -{ - deinit_screen_int(); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); -} - -void set_color(WINDOW *window, int col) -{ - int attr; - - if (!use_colors) - attr = (col & 0x70) ? A_REVERSE : 0; - else if (col & ATTR_COLOR8) - attr = (A_DIM | COLOR_PAIR(63)); - else if ((col & 0x77) == 0) - attr = A_NORMAL; - else - attr = (COLOR_PAIR((col&7) + (col&0x70)/2)); - - if (col & 0x08) attr |= A_BOLD; - if (col & 0x80) attr |= A_BLINK; - - if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE; - if (col & ATTR_REVERSE) attr |= A_REVERSE; - - wattrset(window, attr); -} - -void set_bg(WINDOW *window, int col) -{ - int attr; - - if (!use_colors) - attr = (col & 0x70) ? A_REVERSE : 0; - else { - attr = (col == 8) ? - (A_DIM | COLOR_PAIR(63)) : - (COLOR_PAIR((col&7) + (col&0x70)/2)); - } - - if (col & 0x08) attr |= A_BOLD; - if (col & 0x80) attr |= A_BLINK; - - wbkgdset(window, ' ' | attr); -} - -void move_cursor(int y, int x) -{ - scry = y; - scrx = x; -} - -void screen_refresh_freeze(void) -{ - freeze_refresh++; -} - -void screen_refresh_thaw(void) -{ - if (freeze_refresh > 0) { - freeze_refresh--; - if (freeze_refresh == 0) screen_refresh(NULL); - } -} - -void screen_refresh(WINDOW *window) -{ - if (window != NULL) - wnoutrefresh(window); - if (freeze_refresh == 0) { - move(scry, scrx); - wnoutrefresh(stdscr); - doupdate(); - } -} diff --git a/apps/irssi/src/fe-text/screen.h b/apps/irssi/src/fe-text/screen.h deleted file mode 100644 index 9e6143fb..00000000 --- a/apps/irssi/src/fe-text/screen.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __SCREEN_H -#define __SCREEN_H - -#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES) -# include -#else -# include -#endif - -/* Some curseses include term.h, which #defines some things breaking irssi */ -#undef lines -#undef key_backspace -#undef tab - -#define ATTR_UNDERLINE 0x100 -#define ATTR_COLOR8 0x200 -#define ATTR_REVERSE 0x400 - -/* XXX I hope this could be integrated into BX. - * XXX Well, this should be done via libc, - * but FreeBSD libc support is quite LAME. - * Macro below are copied from lynx. - * - * clive@FreeBSD.org - */ -#ifdef WANT_BIG5 -/* XXX I didn't check the encoding range of big5+. This is standard big5. */ -#define is_big5_los(lo) (((char)0x40<=lo)&&(lo<=(char)0x7E)) /* standard */ -#define is_big5_lox(lo) (((char)0x80<=lo)&&(lo<=(char)0xFE)) /* extended */ -#define is_big5_hi(hi) (((char)0x81<=hi)&&(hi<=(char)0xFE)) -#define is_big5(hi,lo) is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo)) -#endif - -void screen_check_resizes(void); - -int init_screen(void); /* Initialize screen, detect screen length */ -void deinit_screen(void); /* Deinitialize screen */ - -void set_color(WINDOW *window, int col); -void set_bg(WINDOW *window, int col); - -void move_cursor(int y, int x); - -void screen_refresh_freeze(void); -void screen_refresh_thaw(void); -void screen_refresh(WINDOW *window); - -#endif diff --git a/apps/irssi/src/fe-text/statusbar.c b/apps/irssi/src/fe-text/statusbar.c index ef620379..689e4f9b 100644 --- a/apps/irssi/src/fe-text/statusbar.c +++ b/apps/irssi/src/fe-text/statusbar.c @@ -699,8 +699,9 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only, server = NULL; wiitem = NULL; } else { - server = active_win->active_server; - wiitem = active_win->active; + server = active_win->active_server != NULL ? + active_win->active_server : active_win->connect_server; + wiitem = active_win->active; } /* expand templates */ diff --git a/apps/irssi/src/fe-text/term.c b/apps/irssi/src/fe-text/term.c index 03004b10..a36e68fa 100644 --- a/apps/irssi/src/fe-text/term.c +++ b/apps/irssi/src/fe-text/term.c @@ -27,7 +27,6 @@ #include "mainwindows.h" #ifdef HAVE_NL_LANGINFO -# include # include #endif @@ -155,7 +154,6 @@ void term_common_init(void) read_settings(); #if defined (HAVE_NL_LANGINFO) && defined(CODESET) - setlocale(LC_CTYPE, ""); if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { term_type = TERM_TYPE_UTF8; term_set_input_type(TERM_TYPE_UTF8); diff --git a/apps/irssi/src/fe-text/textbuffer-view.c b/apps/irssi/src/fe-text/textbuffer-view.c index da69734e..77b21a2e 100644 --- a/apps/irssi/src/fe-text/textbuffer-view.c +++ b/apps/irssi/src/fe-text/textbuffer-view.c @@ -152,8 +152,10 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) LINE_CACHE_SUB_REC *sub; GSList *lines; unsigned char cmd; - const unsigned char *ptr, *last_space_ptr; + const unsigned char *ptr, *next_ptr, *last_space_ptr; int xpos, pos, indent_pos, last_space, last_color, color, linecount; + int char_len; + unichar chr; g_return_val_if_fail(line->text != NULL, NULL); @@ -196,7 +198,24 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) continue; } - if (xpos == view->width && sub != NULL && + if (!view->utf8) { + next_ptr = ptr+1; + char_len = 1; + } else { + char_len = 1; + while (ptr[char_len] != '\0' && char_len < 6) + char_len++; + + next_ptr = ptr; + chr = get_utf8_char(&next_ptr, char_len); + if (chr < 0) + char_len = 1; + else + char_len = utf8_width(chr); + next_ptr++; + } + + if (xpos + char_len > view->width && sub != NULL && (last_space <= indent_pos || last_space <= 10) && view->longword_noindent) { /* long word, remove the indentation from this line */ @@ -204,7 +223,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) sub->indent = 0; } - if (xpos == view->width) { + if (xpos + char_len > view->width) { xpos = indent_func == NULL ? indent_pos : indent_func(view, line, -1); @@ -232,15 +251,14 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) continue; } - if (view->utf8) - get_utf8_char(&ptr, 6); - - xpos++; - if (*ptr++ == ' ') { - last_space = xpos-1; + if (*ptr == ' ') { + last_space = xpos; last_space_ptr = ptr; last_color = color; } + + xpos += char_len; + ptr = next_ptr; } rec = g_malloc(sizeof(LINE_CACHE_REC)-sizeof(LINE_CACHE_SUB_REC) + @@ -309,9 +327,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, { INDENT_FUNC indent_func; LINE_CACHE_REC *cache; - const unsigned char *text, *text_newline; + const unsigned char *text, *end, *text_newline; unsigned char *tmp; - int xpos, color, drawcount, first, need_move, need_clrtoeol; + int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width; if (view->dirty) /* don't bother drawing anything - redraw is coming */ return 0; @@ -343,13 +361,14 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, if (subline > 0) { /* continuing previous line - indent it */ indent_func = cache->lines[subline-1].indent_func; - xpos = indent_func != NULL ? - indent_func(view, line, ypos) : - cache->lines[subline-1].indent; + if (indent_func == NULL) + xpos = cache->lines[subline-1].indent; color = cache->lines[subline-1].color; + } else { + indent_func = NULL; } - if (xpos == 0) + if (xpos == 0 && indent_func == NULL) need_clrtoeol = TRUE; else { /* line was indented - need to clear the @@ -357,6 +376,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, term_set_color(view->window, ATTR_RESET); term_move(view->window, 0, ypos); term_clrtoeol(view->window); + + if (indent_func != NULL) + xpos = indent_func(view, line, ypos); } if (need_move || xpos > 0) @@ -397,11 +419,16 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, continue; } - if (xpos < term_width) { - const unsigned char *end = text; - if (view->utf8) - get_utf8_char(&end, 6); + end = text; + if (view->utf8) { + unichar chr = get_utf8_char(&end, 6); + char_width = utf8_width(chr); + } else { + char_width = 1; + } + xpos += char_width; + if (xpos <= term_width) { if (*text >= 32 && (end != text || (*text & 127) >= 32)) { for (; text < end; text++) @@ -415,7 +442,6 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, } } text++; - xpos++; } if (need_clrtoeol && xpos < term_width) { diff --git a/apps/irssi/src/fe-text/utf8.c b/apps/irssi/src/fe-text/utf8.c index 2d72fe2b..4049991d 100644 --- a/apps/irssi/src/fe-text/utf8.c +++ b/apps/irssi/src/fe-text/utf8.c @@ -7,6 +7,10 @@ * Copyright (C) 1999 Tom Tromey * Copyright (C) 2000 Red Hat, Inc. * + * UTF-8 width tables based on locale data from GNU libc by + * + * Copyright (C) 1991-2002 Free Software Foundation, Inc. + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -175,3 +179,73 @@ void utf16_to_utf8(const unichar *str, char *out) } *out = '\0'; } + +static const unichar wcc[] = { + 0x0, 0x300, 0x34F, 0x360, 0x363, 0x483, 0x487, 0x488, 0x48A, 0x591, + 0x5A2, 0x5A3, 0x5BA, 0x5BB, 0x5BE, 0x5BF, 0x5C0, 0x5C1, 0x5C3, 0x5C4, + 0x5C5, 0x64B, 0x656, 0x670, 0x671, 0x6D6, 0x6E5, 0x6E7, 0x6E9, 0x6EA, + 0x6EE, 0x70F, 0x710, 0x711, 0x712, 0x730, 0x74B, 0x7A6, 0x7B1, 0x901, + 0x903, 0x93C, 0x93D, 0x941, 0x949, 0x94D, 0x94E, 0x951, 0x955, 0x962, + 0x964, 0x981, 0x982, 0x9BC, 0x9BD, 0x9C1, 0x9C5, 0x9CD, 0x9CE, 0x9E2, + 0x9E4, 0xA02, 0xA03, 0xA3C, 0xA3D, 0xA41, 0xA43, 0xA47, 0xA49, 0xA4B, + 0xA4E, 0xA70, 0xA72, 0xA81, 0xA83, 0xABC, 0xABD, 0xAC1, 0xAC6, 0xAC7, + 0xAC9, 0xACD, 0xACE, 0xB01, 0xB02, 0xB3C, 0xB3D, 0xB3F, 0xB40, 0xB41, + 0xB44, 0xB4D, 0xB4E, 0xB56, 0xB57, 0xB82, 0xB83, 0xBC0, 0xBC1, 0xBCD, + 0xBCE, 0xC3E, 0xC41, 0xC46, 0xC49, 0xC4A, 0xC4E, 0xC55, 0xC57, 0xCBF, + 0xCC0, 0xCC6, 0xCC7, 0xCCC, 0xCCE, 0xD41, 0xD44, 0xD4D, 0xD4E, 0xDCA, + 0xDCB, 0xDD2, 0xDD5, 0xDD6, 0xDD7, 0xE31, 0xE32, 0xE34, 0xE3B, 0xE47, + 0xE4F, 0xEB1, 0xEB2, 0xEB4, 0xEBA, 0xEBB, 0xEBD, 0xEC8, 0xECE, 0xF18, + 0xF1A, 0xF35, 0xF36, 0xF37, 0xF38, 0xF39, 0xF3A, 0xF71, 0xF7F, 0xF80, + 0xF85, 0xF86, 0xF88, 0xF90, 0xF98, 0xF99, 0xFBD, 0xFC6, 0xFC7, 0x102D, + 0x1031, 0x1032, 0x1033, 0x1036, 0x1038, 0x1039, 0x103A, 0x1058, 0x105A, + 0x1100, 0x1160, 0x17B7, 0x17BE, 0x17C6, 0x17C7, 0x17C9, 0x17D4, 0x180B, + 0x180F, 0x18A9, 0x18AA, 0x200B, 0x2010, 0x202A, 0x202F, 0x206A, 0x2070, + 0x20D0, 0x20E4, 0x2E80, 0x3008, 0x300C, 0x3014, 0x3016, 0x3018, 0x301C, + 0x302A, 0x3030, 0x303F, 0x3041, 0x3095, 0x3099, 0x309B, 0xA4C7, 0xAC00, + 0xD7A4, 0xF8F0, 0xF900, 0xFA2E, 0xFB1E, 0xFB1F, 0xFE20, 0xFE24, 0xFE30, + 0xFE6C, 0xFEFF, 0xFF00, 0xFF01, 0xFF5F, 0xFFE0, 0xFFE7, 0xFFF9, 0xFFFC, +#if 1 + 0x1D167, 0x1D16A, 0x1D173, 0x1D183, 0x1D185, 0x1D18C, 0x1D1AA, 0x1D1AE, + 0x20000, 0x2A6D7, 0x2F800, 0x2FA1E, 0xE0001, 0xE0002, 0xE0020, 0xE0080 +#endif +}; + +static const int wccnum = sizeof(wcc) / sizeof(wcc[0]) - 1; + +static const char wws[] = { + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, + 1, 2, 1, 2, 0, 2, 1, 2, 1, 0, 2, 1, 2, 1, 0, 2, 1, 0, 1, 0, 1, 2, 1, 0, + 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 0, 1, 0, 1, -1 +}; + +int utf8_width(unichar c) +{ + int p, q, r; + unichar d; + + if (c < wcc[1]) + return 1; + + p = 0; + q = wccnum; + + while (p < q - 1) { + r = (p + q)/2; + d = wcc[r]; + if (d < c) + p = r; + else if (d > c) + q = r; + else + return wws[r]; + } + + return wws[p]; +} diff --git a/apps/irssi/src/fe-text/utf8.h b/apps/irssi/src/fe-text/utf8.h index efc6af08..64c0e347 100644 --- a/apps/irssi/src/fe-text/utf8.h +++ b/apps/irssi/src/fe-text/utf8.h @@ -18,4 +18,7 @@ int utf16_char_to_utf8(unichar c, char *outbuf); Make sure out is at least 6 x length of str. */ void utf16_to_utf8(const unichar *str, char *out); +/* Returns width for character (0-2). */ +int utf8_width(unichar c); + #endif diff --git a/apps/irssi/src/lib-config/get.c b/apps/irssi/src/lib-config/get.c index e4c5cf07..2df0cc90 100644 --- a/apps/irssi/src/lib-config/get.c +++ b/apps/irssi/src/lib-config/get.c @@ -171,46 +171,6 @@ int config_get_bool(CONFIG_REC *rec, const char *section, const char *key, int d return i_toupper(*str) == 'T' || i_toupper(*str) == 'Y'; } -/* Return value of key `value_key' from list item where `key' is `value' */ -const char *config_list_find(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key) -{ - CONFIG_NODE *node; - - node = config_list_find_node(rec, section, key, value, value_key); - return node != NULL && node->type == NODE_TYPE_KEY ? - node->value : NULL; -} - -/* Like config_list_find(), but return node instead of it's value */ -CONFIG_NODE *config_list_find_node(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key) -{ - CONFIG_NODE *node, *keynode; - GSList *tmp; - - g_return_val_if_fail(rec != NULL, NULL); - g_return_val_if_fail(key != NULL, NULL); - g_return_val_if_fail(value_key != NULL, NULL); - - node = config_node_traverse(rec, section, FALSE); - if (node == NULL || !is_node_list(node)) return NULL; - - for (tmp = node->value; tmp != NULL; tmp = tmp->next) { - node = tmp->data; - - if (node->type != NODE_TYPE_BLOCK) - continue; - - /* key matches value? */ - keynode = config_node_find(node, key); - if (keynode == NULL || keynode->type != NODE_TYPE_KEY || - g_strcasecmp(keynode->value, value) != 0) continue; - - return config_node_find(node, value_key); - } - - return NULL; -} - char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def) { CONFIG_NODE *node; diff --git a/apps/irssi/src/lib-config/iconfig.h b/apps/irssi/src/lib-config/iconfig.h index 7ef8d791..3d6072d1 100644 --- a/apps/irssi/src/lib-config/iconfig.h +++ b/apps/irssi/src/lib-config/iconfig.h @@ -93,10 +93,6 @@ char *config_get_str(CONFIG_REC *rec, const char *section, const char *key, cons int config_get_int(CONFIG_REC *rec, const char *section, const char *key, int def); int config_get_bool(CONFIG_REC *rec, const char *section, const char *key, int def); -/* Return value of key `value_key' from list item where `key' is `value' */ -const char *config_list_find(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key); -/* Like config_list_find(), but return node instead of it's value */ -CONFIG_NODE *config_list_find_node(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key); /* Returns n'th node from list. */ CONFIG_NODE *config_node_nth(CONFIG_NODE *node, int index); /* Returns index for given key */ diff --git a/apps/irssi/src/perl/common/Channel.xs b/apps/irssi/src/perl/common/Channel.xs index f425dc2b..0692a7cc 100644 --- a/apps/irssi/src/perl/common/Channel.xs +++ b/apps/irssi/src/perl/common/Channel.xs @@ -42,14 +42,6 @@ channels_join(server, channels, automatic) CODE: server->channels_join(server, channels, automatic); -Irssi::Channel -channel_create(server, name, automatic) - Irssi::Server server - char *name - int automatic -CODE: - CHAT_PROTOCOL(server)->channel_create(server, name, automatic); - Irssi::Channel channel_find(server, name) Irssi::Server server diff --git a/apps/irssi/src/perl/common/Core.xs b/apps/irssi/src/perl/common/Core.xs index 129b2081..c3fd41ba 100644 --- a/apps/irssi/src/perl/common/Core.xs +++ b/apps/irssi/src/perl/common/Core.xs @@ -1,5 +1,6 @@ #include "module.h" #include "irssi-version.h" +#include "core.h" #define DEFAULT_COMMAND_CATEGORY "Perl scripts' commands" @@ -556,6 +557,55 @@ CODE: OUTPUT: RETVAL +int +get_gui() +CODE: + RETVAL = irssi_gui; +OUTPUT: + RETVAL + +int +IRSSI_GUI_NONE() +CODE: + RETVAL = IRSSI_GUI_NONE; +OUTPUT: + RETVAL + +int +IRSSI_GUI_TEXT() +CODE: + RETVAL = IRSSI_GUI_TEXT; +OUTPUT: + RETVAL + +int +IRSSI_GUI_GTK() +CODE: + RETVAL = IRSSI_GUI_GTK; +OUTPUT: + RETVAL + +int +IRSSI_GUI_GNOME() +CODE: + RETVAL = IRSSI_GUI_GNOME; +OUTPUT: + RETVAL + +int +IRSSI_GUI_QT() +CODE: + RETVAL = IRSSI_GUI_QT; +OUTPUT: + RETVAL + +int +IRSSI_GUI_KDE() +CODE: + RETVAL = IRSSI_GUI_KDE; +OUTPUT: + RETVAL + #******************************* MODULE = Irssi::Core PACKAGE = Irssi::Server #******************************* diff --git a/apps/irssi/src/perl/common/Irssi.xs b/apps/irssi/src/perl/common/Irssi.xs index c84918e8..67d5e96c 100644 --- a/apps/irssi/src/perl/common/Irssi.xs +++ b/apps/irssi/src/perl/common/Irssi.xs @@ -31,4 +31,3 @@ BOOT: irssi_boot(Rawlog); irssi_boot(Server); irssi_boot(Settings); - irssi_boot(Blob); diff --git a/apps/irssi/src/perl/common/module.h b/apps/irssi/src/perl/common/module.h index aa1cce47..5456f630 100644 --- a/apps/irssi/src/perl/common/module.h +++ b/apps/irssi/src/perl/common/module.h @@ -22,7 +22,6 @@ #include "channels.h" #include "queries.h" #include "nicklist.h" -#include "blob.h" #include "perl/perl-core.h" #include "perl/perl-common.h" @@ -43,4 +42,3 @@ typedef RECONNECT_REC *Irssi__Reconnect; typedef CHANNEL_REC *Irssi__Channel; typedef QUERY_REC *Irssi__Query; typedef NICK_REC *Irssi__Nick; -typedef BLOB_REC *Irssi__Blob; diff --git a/apps/irssi/src/perl/common/typemap b/apps/irssi/src/perl/common/typemap index 41bcd4c5..5b7e0c32 100644 --- a/apps/irssi/src/perl/common/typemap +++ b/apps/irssi/src/perl/common/typemap @@ -13,7 +13,6 @@ Irssi::Logitem T_PlainObj Irssi::Rawlog T_PlainObj Irssi::Module T_PlainObj Irssi::Windowitem T_IrssiObj -Irssi::Blob T_PlainObj INPUT diff --git a/apps/irssi/src/perl/get-signals.pl b/apps/irssi/src/perl/get-signals.pl index 7cd97614..df4667ce 100755 --- a/apps/irssi/src/perl/get-signals.pl +++ b/apps/irssi/src/perl/get-signals.pl @@ -51,9 +51,6 @@ while () { s/WINDOW_REC[^,]*/Irssi::UI::Window/g; s/WI_ITEM_REC[^,]*/iobject/g; - # silc - s/BLOB_REC[^,]*/siobject/g; - s/([\w\*:]+)(,|$)/"\1"\2/g; print " { \"$signal\", { $_, NULL } },\n"; } diff --git a/apps/irssi/src/perl/irssi-core.pl b/apps/irssi/src/perl/irssi-core.pl index 31fbe484..11aa0f6f 100644 --- a/apps/irssi/src/perl/irssi-core.pl +++ b/apps/irssi/src/perl/irssi-core.pl @@ -6,14 +6,15 @@ # %%s : must be second - use Irssi; use Irssi::Irc; etc.. package Irssi::Core; -use Symbol qw(delete_package); +use Symbol; sub is_static { return %d; } sub destroy { - delete_package($_[0]); + eval { $_[0]->UNLOAD() if $_[0]->can('UNLOAD'); }; + Symbol::delete_package($_[0]); } sub eval_data { @@ -29,8 +30,10 @@ sub eval_data { } die $@ if $@; - eval {$package->handler;}; + my $ret; + eval { $ret = $package->handler; }; die $@ if $@; + return $ret; } sub eval_file { diff --git a/apps/irssi/src/perl/irssi-core.pl.h b/apps/irssi/src/perl/irssi-core.pl.h index 3e4ec9a8..9c4dd606 100644 --- a/apps/irssi/src/perl/irssi-core.pl.h +++ b/apps/irssi/src/perl/irssi-core.pl.h @@ -7,14 +7,15 @@ const char *irssi_core_code = "# %%s : must be second - use Irssi; use Irssi::Irc; etc..\n" "package Irssi::Core;\n" "\n" -"use Symbol qw(delete_package);\n" +"use Symbol;\n" "\n" "sub is_static {\n" " return %d;\n" "}\n" "\n" "sub destroy {\n" -" delete_package($_[0]);\n" +" eval { $_[0]->UNLOAD() if $_[0]->can('UNLOAD'); };\n" +" Symbol::delete_package($_[0]);\n" "}\n" "\n" "sub eval_data {\n" @@ -30,8 +31,10 @@ const char *irssi_core_code = " }\n" " die $@ if $@;\n" "\n" -" eval {$package->handler;};\n" +" my $ret;\n" +" eval { $ret = $package->handler; };\n" " die $@ if $@;\n" +" return $ret;\n" "}\n" "\n" "sub eval_file {\n" diff --git a/apps/irssi/src/perl/perl-common.c b/apps/irssi/src/perl/perl-common.c index 0113bdf3..cad117fc 100644 --- a/apps/irssi/src/perl/perl-common.c +++ b/apps/irssi/src/perl/perl-common.c @@ -39,7 +39,6 @@ #include "channels.h" #include "queries.h" #include "nicklist.h" -#include "blob.h" #include "perl-common.h" @@ -220,22 +219,16 @@ char *perl_get_use_list(void) return ret; } -void irssi_callXS(void (*subaddr)(CV* cv), CV *cv, SV **mark) +void irssi_callXS(void (*subaddr)(pTHX_ CV* cv), CV *cv, SV **mark) { dSP; PUSHMARK(mark); - (*subaddr)(cv); + (*subaddr)(aTHX_ cv); PUTBACK; } -static void perl_blob_fill_hash(HV *hv, BLOB_REC *blob) -{ - hv_store(hv, "octets", 6, newSViv(blob->octets), 0); - hv_store(hv, "data", 4, newSVpv(blob->data, blob->octets), 0); -} - void perl_chatnet_fill_hash(HV *hv, CHATNET_REC *chatnet) { char *type, *chat_type; @@ -333,7 +326,7 @@ void perl_window_item_fill_hash(HV *hv, WI_ITEM_REC *item) if (item->server != NULL) { hv_store(hv, "server", 6, iobject_bless(item->server), 0); } - hv_store(hv, "name", 4, new_pv(item->name), 0); + hv_store(hv, "visible_name", 12, new_pv(item->visible_name), 0); hv_store(hv, "createtime", 10, newSViv(item->createtime), 0); hv_store(hv, "data_level", 10, newSViv(item->data_level), 0); @@ -350,6 +343,7 @@ void perl_channel_fill_hash(HV *hv, CHANNEL_REC *channel) if (channel->ownnick != NULL) hv_store(hv, "ownnick", 7, iobject_bless(channel->ownnick), 0); + hv_store(hv, "name", 4, new_pv(channel->name), 0); hv_store(hv, "topic", 5, new_pv(channel->topic), 0); hv_store(hv, "topic_by", 8, new_pv(channel->topic_by), 0); hv_store(hv, "topic_time", 10, newSViv(channel->topic_time), 0); @@ -376,6 +370,7 @@ void perl_query_fill_hash(HV *hv, QUERY_REC *query) perl_window_item_fill_hash(hv, (WI_ITEM_REC *) query); + hv_store(hv, "name", 4, new_pv(query->name), 0); hv_store(hv, "last_unread_msg", 15, newSViv(query->last_unread_msg), 0); hv_store(hv, "address", 7, new_pv(query->address), 0); hv_store(hv, "server_tag", 10, new_pv(query->server_tag), 0); @@ -425,8 +420,10 @@ static void perl_ignore_fill_hash(HV *hv, IGNORE_REC *ignore) hv_store(hv, "mask", 4, new_pv(ignore->mask), 0); hv_store(hv, "servertag", 9, new_pv(ignore->servertag), 0); av = newAV(); - for (tmp = ignore->channels; *tmp != NULL; tmp++) { - av_push(av, new_pv(*tmp)); + if (ignore->channels != NULL) { + for (tmp = ignore->channels; *tmp != NULL; tmp++) { + av_push(av, new_pv(*tmp)); + } } hv_store(hv, "channels", 8, newRV_noinc((SV*)av), 0); hv_store(hv, "pattern", 7, new_pv(ignore->pattern), 0); @@ -631,10 +628,6 @@ void perl_common_start(void) plain_stashes = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal); irssi_add_plains(core_plains); - irssi_add_object(module_get_uniq_id("BLOB", 0), 0, - "Irssi::Blob", - (PERL_OBJECT_FUNC) perl_blob_fill_hash); - use_protocols = NULL; g_slist_foreach(chat_protocols, (GFunc) perl_register_protocol, NULL); diff --git a/apps/irssi/src/perl/perl-common.h b/apps/irssi/src/perl/perl-common.h index 9fa85f07..cef0036f 100644 --- a/apps/irssi/src/perl/perl-common.h +++ b/apps/irssi/src/perl/perl-common.h @@ -32,6 +32,14 @@ SV *perl_func_sv_inc(SV *func, const char *package); extern STRLEN PL_na; #endif +#ifndef pTHX_ +# define pTHX_ +#endif + +#ifndef aTHX_ +# define aTHX_ +#endif + #define iobject_bless(object) \ ((object) == NULL ? &PL_sv_undef : \ irssi_bless_iobject((object)->type, (object)->chat_type, object)) @@ -57,10 +65,10 @@ void irssi_add_plains(PLAIN_OBJECT_INIT_REC *objects); char *perl_get_use_list(void); #define irssi_boot(x) { \ - extern void boot_Irssi__##x(CV *cv); \ + extern void boot_Irssi__##x(pTHX_ CV *cv); \ irssi_callXS(boot_Irssi__##x, cv, mark); \ } -void irssi_callXS(void (*subaddr)(CV* cv), CV *cv, SV **mark); +void irssi_callXS(void (*subaddr)(pTHX_ CV* cv), CV *cv, SV **mark); void perl_common_start(void); void perl_common_stop(void); diff --git a/apps/irssi/src/perl/perl-core.c b/apps/irssi/src/perl/perl-core.c index accd5ef4..2d300289 100644 --- a/apps/irssi/src/perl/perl-core.c +++ b/apps/irssi/src/perl/perl-core.c @@ -84,7 +84,7 @@ static void perl_script_destroy(PERL_SCRIPT_REC *script) g_free(script); } -extern void boot_DynaLoader(CV* cv); +extern void boot_DynaLoader(pTHX_ CV* cv); #if PERL_STATIC_LIBS == 1 extern void boot_Irssi(CV *cv); @@ -101,7 +101,7 @@ XS(boot_Irssi_Core) } #endif -static void xs_init(void) +static void xs_init(pTHX) { dXSUB_SYS; @@ -216,6 +216,7 @@ static int perl_script_eval(PERL_SCRIPT_REC *script) dSP; char *error; int retcount; + SV *ret; ENTER; SAVETMPS; @@ -234,19 +235,19 @@ static int perl_script_eval(PERL_SCRIPT_REC *script) error = NULL; if (SvTRUE(ERRSV)) { - error = SvPV(ERRSV, PL_na); - } else if (retcount > 0) { - error = POPp; - } + error = SvPV(ERRSV, PL_na); - if (error != NULL) { - if (*error == '\0') - error = NULL; - else { - error = g_strdup(error); + if (error != NULL) { + error = g_strdup(error); signal_emit("script error", 2, script, error); - g_free(error); + g_free(error); } + } else if (retcount > 0) { + /* if script returns 0, it means the script wanted to die + immediately without any error message */ + ret = POPs; + if (ret != &PL_sv_undef && SvIOK(ret) && SvIV(ret) == 0) + error = ""; } PUTBACK; diff --git a/apps/irssi/src/perl/perl-signals-list.h b/apps/irssi/src/perl/perl-signals-list.h index f541511c..05003c0f 100644 --- a/apps/irssi/src/perl/perl-signals-list.h +++ b/apps/irssi/src/perl/perl-signals-list.h @@ -175,8 +175,6 @@ static PERL_SIGNAL_ARGS_REC perl_signal_args[] = { "message dcc", { "siobject", "string", NULL } }, { "message dcc action", { "siobject", "string", NULL } }, { "message dcc ctcp", { "siobject", "string", "string", NULL } }, - { "mime", { "iobject", "iobject", "siobject", "string", "string", "string", NULL } }, - { "mime-send", { "iobject", "iobject", "string", "int", "string", "string", NULL } }, { NULL } }; diff --git a/apps/irssi/src/perl/textui/TextUI.xs b/apps/irssi/src/perl/textui/TextUI.xs index 8d49ac44..4e7db7b2 100644 --- a/apps/irssi/src/perl/textui/TextUI.xs +++ b/apps/irssi/src/perl/textui/TextUI.xs @@ -69,6 +69,8 @@ static void perl_statusbar_item_fill_hash(HV *hv, SBAR_ITEM_REC *item) hv_store(hv, "max_size", 8, newSViv(item->max_size), 0); hv_store(hv, "xpos", 4, newSViv(item->xpos), 0); hv_store(hv, "size", 4, newSViv(item->size), 0); + if (item->bar->parent_window != NULL) + hv_store(hv, "window", 6, plain_bless(item->bar->parent_window->active, "Irssi::UI::Window"), 0); } static PLAIN_OBJECT_INIT_REC textui_plains[] = { diff --git a/apps/irssi/src/perl/ui/Themes.xs b/apps/irssi/src/perl/ui/Themes.xs index 64a05676..7f1c5277 100644 --- a/apps/irssi/src/perl/ui/Themes.xs +++ b/apps/irssi/src/perl/ui/Themes.xs @@ -195,7 +195,7 @@ PREINIT: char *arglist[MAX_FORMAT_PARAMS+1]; int n; CODE: - format_create_dest(&dest, item->server, item->name, level, NULL); + format_create_dest(&dest, item->server, item->visible_name, level, NULL); memset(arglist, 0, sizeof(arglist)); for (n = 3; n < items && n < MAX_FORMAT_PARAMS+3; n++) { arglist[n-3] = SvPV(ST(n), PL_na); diff --git a/apps/irssi/src/perl/ui/Window.xs b/apps/irssi/src/perl/ui/Window.xs index cadff1ab..89d874ee 100644 --- a/apps/irssi/src/perl/ui/Window.xs +++ b/apps/irssi/src/perl/ui/Window.xs @@ -225,6 +225,10 @@ window_activity(window, data_level, hilight_color=NULL) char * window_get_active_name(window) Irssi::UI::Window window +CODE: + RETVAL = (char *) window_get_active_name(window); +OUTPUT: + RETVAL Irssi::Windowitem window_item_find(window, server, name) @@ -246,7 +250,7 @@ print(item, str, level=MSGLEVEL_CLIENTNOTICE) int level char *str CODE: - printtext_string(item->server, item->name, level, str); + printtext_string(item->server, item->visible_name, level, str); Irssi::UI::Window window_create(item, automatic) diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 297272ef..484c2e49 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -39,7 +39,6 @@ #include "fe-common/silc/module-formats.h" #include "core.h" -#include "blob.h" static void silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, @@ -111,20 +110,6 @@ void silc_say_error(char *msg, ...) va_end(va); } -void silc_emit_mime_sig(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel, - const char *data, SilcUInt32 data_len, - const char *encoding, const char *type, - const char *nick) -{ - BLOB_REC blob; - - blob_fill(&blob); - blob.octets = data_len; - blob.data = (char *)data; - - signal_emit("mime", 6, server, channel, &blob, encoding, type, nick); -} - /* Message for a channel. The `sender' is the nickname of the sender received in the packet. The `channel_name' is the name of the channel. */ @@ -172,10 +157,6 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, !strstr(type, "text/vnd")) { /* It is something textual, display it */ message = (const unsigned char *)data; - } else { - silc_emit_mime_sig(server, chanrec, data, data_len, - enc, type, nick->nick); - message = NULL; } } @@ -254,10 +235,6 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, !strstr(type, "text/vnd")) { /* It is something textual, display it */ message = (const unsigned char *)data; - } else { - silc_emit_mime_sig(server, NULL, data, data_len, - enc, type, sender->nickname); - message = NULL; } } @@ -1010,8 +987,6 @@ static void silc_client_join_get_users(SilcClient client, MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC, channel->channel_name, chanrec->topic); - fe_channels_nicklist(CHANNEL(chanrec), CHANNEL_NICKLIST_FLAG_ALL); - if (founder) { if (founder == conn->local_entry) printformat_module("fe-common/silc", @@ -1329,7 +1304,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, chanrec = silc_channel_find(server, channel); if (!chanrec) - chanrec = silc_channel_create(server, channel, TRUE); + chanrec = silc_channel_create(server, channel, channel, TRUE); if (topic) { g_free_not_null(chanrec->topic); @@ -2185,10 +2160,10 @@ void silc_failure(SilcClient client, SilcClientConnection conn, desired (application may start it later by calling the function silc_client_perform_key_agreement). */ -int silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context) +bool silc_key_agreement(SilcClient client, SilcClientConnection conn, + SilcClientEntry client_entry, const char *hostname, + SilcUInt16 port, SilcKeyAgreementCallback *completion, + void **context) { char portstr[12]; diff --git a/apps/irssi/src/silc/core/client_ops.h b/apps/irssi/src/silc/core/client_ops.h index 9fbf84bc..68e2b09e 100644 --- a/apps/irssi/src/silc/core/client_ops.h +++ b/apps/irssi/src/silc/core/client_ops.h @@ -58,10 +58,10 @@ void silc_get_auth_method(SilcClient client, SilcClientConnection conn, SilcGetAuthMeth completion, void *context); void silc_failure(SilcClient client, SilcClientConnection conn, SilcProtocol protocol, void *failure); -int silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context); +bool silc_key_agreement(SilcClient client, SilcClientConnection conn, + SilcClientEntry client_entry, const char *hostname, + SilcUInt16 port, SilcKeyAgreementCallback *completion, + void **context); void silc_ftp(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry, SilcUInt32 session_id, const char *hostname, SilcUInt16 port); diff --git a/apps/irssi/src/silc/core/silc-channels.c b/apps/irssi/src/silc/core/silc-channels.c index 8c03fcdb..04dd65d7 100644 --- a/apps/irssi/src/silc/core/silc-channels.c +++ b/apps/irssi/src/silc/core/silc-channels.c @@ -31,7 +31,6 @@ #include "rawlog.h" #include "misc.h" #include "settings.h" -#include "blob.h" #include "channels-setup.h" @@ -46,21 +45,10 @@ #include "silc-commands.h" -void sig_mime(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel, - BLOB_REC *blob, const char *enc, const char *type, - const char *nick) -{ - if (!(IS_SILC_SERVER(server))) - return; - - printformat_module("fe-common/silc", server, - channel == NULL ? NULL : channel->name, - MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA, - nick == NULL ? "[]" : nick, type); -} - SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server, - const char *name, int automatic) + const char *name, + const char *visible_name, + int automatic) { SILC_CHANNEL_REC *rec; @@ -69,10 +57,8 @@ SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server, rec = g_new0(SILC_CHANNEL_REC, 1); rec->chat_type = SILC_PROTOCOL; - rec->name = g_strdup(name); - rec->server = server; - - channel_init((CHANNEL_REC *) rec, automatic); + channel_init((CHANNEL_REC *)rec, (SERVER_REC *)server, name, name, + automatic); return rec; } @@ -158,7 +144,7 @@ static void command_part(const char *data, SILC_SERVER_REC *server, if (!strcmp(data, "*") || *data == '\0') { if (!IS_SILC_CHANNEL(item)) cmd_return_error(CMDERR_NOT_JOINED); - data = item->name; + data = item->visible_name; } chanrec = silc_channel_find(server, data); @@ -209,7 +195,7 @@ static void command_me(const char *data, SILC_SERVER_REC *server, if (argc < 2) cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - chanrec = silc_channel_find(server, item->name); + chanrec = silc_channel_find(server, item->visible_name); if (chanrec == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND); @@ -334,7 +320,7 @@ static void command_notice(const char *data, SILC_SERVER_REC *server, if (argc < 2) cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - chanrec = silc_channel_find(server, item->name); + chanrec = silc_channel_find(server, item->visible_name); if (chanrec == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND); @@ -990,7 +976,6 @@ void silc_channels_init(void) signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_add("server connected", (SIGNAL_FUNC) sig_connected); signal_add("server quit", (SIGNAL_FUNC) sig_server_quit); - signal_add("mime", (SIGNAL_FUNC) sig_mime); command_bind_silc("part", MODULE_NAME, (SIGNAL_FUNC) command_part); command_bind_silc("me", MODULE_NAME, (SIGNAL_FUNC) command_me); @@ -1008,7 +993,6 @@ void silc_channels_deinit(void) signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_remove("server connected", (SIGNAL_FUNC) sig_connected); signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit); - signal_remove("mime", (SIGNAL_FUNC) sig_mime); command_unbind("part", (SIGNAL_FUNC) command_part); command_unbind("me", (SIGNAL_FUNC) command_me); diff --git a/apps/irssi/src/silc/core/silc-channels.h b/apps/irssi/src/silc/core/silc-channels.h index b572712c..76962114 100644 --- a/apps/irssi/src/silc/core/silc-channels.h +++ b/apps/irssi/src/silc/core/silc-channels.h @@ -28,7 +28,9 @@ void silc_channels_deinit(void); /* Create new SILC channel record */ SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server, - const char *name, int automatic); + const char *name, + const char *visible_name, + int automatic); SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server, SilcChannelEntry entry); diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 9039a5dc..e7725f3c 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -444,9 +444,10 @@ void silc_core_init(void) rec->create_channel_setup = create_channel_setup; rec->create_server_connect = create_server_connect; rec->destroy_server_connect = destroy_server_connect; - rec->server_connect = (SERVER_REC *(*) (SERVER_CONNECT_REC *)) - silc_server_connect; - rec->channel_create = (CHANNEL_REC *(*) (SERVER_REC *, const char *, int)) + rec->server_init_connect = silc_server_init_connect; + rec->server_connect = silc_server_connect; + rec->channel_create = (CHANNEL_REC *(*) (SERVER_REC *, const char *, + const char *, int)) silc_channel_create; rec->query_create = (QUERY_REC *(*) (const char *, const char *, int)) silc_query_create; diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index dd900ce7..c3e4932f 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -323,33 +323,37 @@ static void sig_disconnected(SILC_SERVER_REC *server) } } -SILC_SERVER_REC *silc_server_connect(SILC_SERVER_CONNECT_REC *conn){ +SERVER_REC *silc_server_init_connect(SERVER_CONNECT_REC *conn) +{ SILC_SERVER_REC *server; g_return_val_if_fail(IS_SILC_SERVER_CONNECT(conn), NULL); if (conn->address == NULL || *conn->address == '\0') return NULL; if (conn->nick == NULL || *conn->nick == '\0') { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, - "Cannot connect: nickname is not set"); + silc_say_error("Cannot connect: nickname is not set"); return NULL; } server = g_new0(SILC_SERVER_REC, 1); server->chat_type = SILC_PROTOCOL; - server->connrec = conn; + server->connrec = (SILC_SERVER_CONNECT_REC *)conn; + server_connect_ref(conn); + if (server->connrec->port <= 0) server->connrec->port = 706; - server_connect_ref(SERVER_CONNECT(conn)); + server_connect_init((SERVER_REC *)server); + return (SERVER_REC *)server; +} - if (!server_start_connect((SERVER_REC *) server)) { - server_connect_unref(SERVER_CONNECT(conn)); +void silc_server_connect(SERVER_REC *server) +{ + if (!server_start_connect(server)) { + server_connect_unref(server->connrec); g_free(server); - return NULL; + return; } - - return server; } /* Return a string of all channels in server in server->channels_join() @@ -476,7 +480,7 @@ static void command_self(const char *data, SILC_SERVER_REC *server, if (IS_SILC_CHANNEL(item)) { SILC_CHANNEL_REC *chanrec; - chanrec = silc_channel_find(server, item->name); + chanrec = silc_channel_find(server, item->visible_name); if (chanrec) server->conn->current_channel = chanrec->entry; } diff --git a/apps/irssi/src/silc/core/silc-servers.h b/apps/irssi/src/silc/core/silc-servers.h index 7b319766..bf3f3b70 100644 --- a/apps/irssi/src/silc/core/silc-servers.h +++ b/apps/irssi/src/silc/core/silc-servers.h @@ -59,7 +59,8 @@ typedef struct { SilcUInt32 umode; } SILC_SERVER_REC; -SILC_SERVER_REC *silc_server_connect(SILC_SERVER_CONNECT_REC *conn); +SERVER_REC *silc_server_init_connect(SERVER_CONNECT_REC *conn); +void silc_server_connect(SERVER_REC *server); /* Return a string of all channels in server in server->channels_join() format */ -- 2.24.0