diff --git a/.gitignore b/.gitignore index 893f53d9..0b15f43e 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,11 @@ lt~obsolete.m4 pm_to_blib stamp-h1 +docs/help/Makefile.am +docs/help/[a-z]* +!docs/help/in +docs/help/in/Makefile.am + src/fe-text/irssi src/fe-common/irc/irc-modules.c @@ -37,17 +42,18 @@ src/perl/common/*.c src/perl/irc/*.c src/perl/textui/*.c src/perl/ui/*.c +src/perl/*/MYMETA.* +src/perl/*/Makefile.old *.a *.bs *.la *.lo *.o +*~ *.tar.bz2 *.tar.gz .deps .libs - -docs/help diff --git a/AUTHORS b/AUTHORS index 50f24ac4..d2cb58c0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -78,3 +78,6 @@ Other patches (grep for "patch" in ChangeLog) by: Ismael Luceno Thomas Karpiniec Svante Kvarnström + Ailin Nemui (Nei) + Tom Feist (shabble) + Sebastian Thorarensen diff --git a/Makefile.am b/Makefile.am index 5bb0a2d7..4f1d1112 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -ACLOCAL_AMFLAGS = -I m4 +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} # create default-config.h BUILT_SOURCES = default-config.h default-theme.h irssi-version.h @@ -27,8 +27,7 @@ pkginclude_HEADERS = irssi-config.h irssi-version.h EXTRA_DIST = \ ChangeLog \ autogen.sh \ - curses.m4 \ - README \ + README.md \ file2header.sh \ $(conf_DATA) \ $(theme_DATA) \ diff --git a/NEWS b/NEWS index e9bf9d88..d291c04f 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,11 @@ v0.8.17-head 2014-xx-xx The Irssi team + Performance enhancement of the nicklist as well as the window_item_find function. See Github PR #24. + Disallow unloading of static modules. + Allow UTF-8 characters in /bind. See Github PR #18. + + Split overlong outgoing messages instead of silently truncating them. + Adds two new options: 'split_line_end' and 'split_line_start'. + 'split_line_end' contains a string added to the end of line fragments. + 'split_line_start' contains a string added to the beginning of line + fragments. See Github PR #29. - Fixed various compiler warnings. - Fixed format_get_text Perl API. See Github PR #23. - Fixed gui_printtext_after and term_refresh_*() visibility. See Github PR #22. diff --git a/README.md b/README.md index b76c6dbd..d6577fdf 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,16 @@ [![Build Status](https://travis-ci.org/irssi/irssi.svg?branch=master)](https://travis-ci.org/irssi/irssi) -Irssi is a modular IRC client that currently has only text mode user interface, -but 80-90% of the code isn't text mode specific, so other UIs could be created -pretty easily. Also, Irssi isn't really even IRC specific anymore, there's -already a working [SILC](http://www.silcnet.org/) module available. Support for -other protocols like ICQ could be created some day too. +Irssi is a modular chat client that is most commonly known for its +text mode user interface, but 80% of the code isn't text mode +specific. We have a working but currently unmaintained GTK2 frontend +called xirssi. Irssi comes with IRC support built in, and there are +third party [ICB](https://github.com/jperkin/irssi-icb), +[SILC](http://www.silcnet.org/), +[XMPP](http://cybione.org/~irssi-xmpp/) (Jabber), +[PSYC](https://github.com/electric-blue/irssyc) and +[Quassel](https://github.com/phhusson/quassel-irssi) protocol modules +available. ## Installation diff --git a/configure.ac b/configure.ac index d409be36..2a7bee0d 100644 --- a/configure.ac +++ b/configure.ac @@ -166,6 +166,15 @@ AC_ARG_ENABLE(dane, fi, want_dane=no) +AC_ARG_ENABLE(true-color, +[ --enable-true-color Build with true color support in terminal], + if test x$enableval = xno ; then + want_truecolor=no + else + want_truecolor=yes + fi, + want_truecolor=no) + dnl ** dnl ** SSL Library checks (OpenSSL) dnl ** @@ -212,7 +221,7 @@ AC_CACHE_VAL(irssi_cv_type_socklen_t, [AC_TRY_COMPILE([ #include #include ], -[socklen_t t;], +[socklen_t t = 0; return((int)t); ], irssi_cv_type_socklen_t=yes, irssi_cv_type_socklen_t=no, )]) @@ -294,6 +303,15 @@ if test -z "$GLIB_LIBS"; then echo "*** We recommend you get the latest stable GLIB 2 version." echo "*** Compile and install it, and make sure pkg-config finds it," echo "*** by adding the path where the .pc file is located to PKG_CONFIG_PATH" + echo -n "*** Or alternatively install your distribution's package" + if test -f /etc/debian_version; then + echo : + echo "*** sudo apt-get install libglib2.0-dev" + elif test -f /etc/redhat-release; then + echo " (glib2-devel)" + else + echo . + fi echo AC_ERROR([GLIB is required to build irssi.]) @@ -375,7 +393,7 @@ if test "x$want_textui" = "xyes"; then TEXTUI_LIBS="-ltermcap" want_termcap=yes ], [ - AC_ERROR(Terminfo/termcap not found - install ncurses-devel package) + AC_ERROR(Terminfo/termcap not found - install libncurses-dev or ncurses-devel package) want_textui=no ]))) fi @@ -446,8 +464,10 @@ if test "$want_perl" != "no"; then esac dnl * check that perl's ldflags actually work - echo "main(){perl_alloc(); return 0;}" > conftest.c - $CC $CFLAGS conftest.c -o conftest $LDFLAGS $PERL_LDFLAGS 2> perl.error.tmp > /dev/null + echo "#include " > conftest.c + echo "#include " >> conftest.c + echo "int main(){perl_alloc(); return 0;}" >> conftest.c + $CC $CFLAGS $PERL_CFLAGS conftest.c -o conftest $LDFLAGS $PERL_LDFLAGS 2> perl.error.tmp > /dev/null if test ! -s conftest -a "x$ignore_perl_errors" = "x"; then perl_check_error="Error linking with perl libraries: $PERL_LDFLAGS: `cat perl.error.tmp`" AC_MSG_RESULT([error linking with perl libraries, building without Perl]) @@ -617,7 +637,7 @@ if test "x$want_ipv6" = "xyes"; then #include #include #include ], - [struct in6_addr i;], + [struct in6_addr i = in6addr_any; return &i == &i;], have_ipv6=yes, )]) if test $have_ipv6 = yes; then @@ -643,6 +663,12 @@ if test "x$want_dane" = "xyes"; then fi fi +if test "x$want_truecolor" = "xyes" -a "x$want_termcap" != "xyes" -a "x$want_terminfo" = "xyes" ; then + AC_DEFINE([TERM_TRUECOLOR], [], [true color support in terminal]) +else + want_truecolor=no +fi + AC_CONFIG_FILES([ Makefile src/Makefile @@ -724,6 +750,11 @@ else else echo "Building with Perl support ....... : NO!" echo " - $perl_check_error" + if test -f /etc/debian_version; then + echo " - Try: sudo apt-get install libperl-dev" + elif test -f /etc/redhat-release; then + echo " - Try installing perl-devel" + fi fi fi @@ -733,7 +764,7 @@ if test "x$want_perl" != "xno" -a "x$perl_mod_error" != "x"; then echo " $perl_mod_error" if test -f /etc/debian_version; then - echo " - Try: apt-get install libperl-dev" + echo " - Try: sudo apt-get install libperl-dev" fi fi @@ -758,9 +789,19 @@ echo echo "Building with IPv6 support ....... : $have_ipv6" echo "Building with SSL support ........ : $have_openssl" +if test "x$have_openssl" = "xno" -a "x$enable_ssl" = "xyes"; then + if test -f /etc/debian_version; then + echo " - Try: sudo apt-get install libssl-dev" + elif test -f /etc/redhat-release; then + echo " - Try installing openssl-devel" + else + echo " - Try installing OpenSSL development headers" + fi +fi echo "Building with 64bit DCC support .. : $offt_64bit" echo "Building with garbage collector .. : $have_gc" echo "Building with DANE support ....... : $have_dane" +echo "Building with true color support.. : $want_truecolor" echo echo "If there are any problems, read the INSTALL file." diff --git a/docs/formats.txt b/docs/formats.txt index 0ffef08f..b6063857 100644 --- a/docs/formats.txt +++ b/docs/formats.txt @@ -23,10 +23,13 @@ %U Underline on/off %8 Reverse on/off %9 %_ Bold on/off + %I Italic on/off %: Insert newline %| Marks the indentation position %# Monospace font on/off (useful with lists and GUI) %% A single % + %XAB %xAB Color from extended plane (A=1-7, B=0-Z) + %ZAABBCC %zAABBCC HTML color (in hex notation) In .theme files %n works a bit differently. See default.theme for more information. diff --git a/docs/help/in/accept.in b/docs/help/in/accept.in index 4d74fe98..699441a8 100644 --- a/docs/help/in/accept.in +++ b/docs/help/in/accept.in @@ -1,28 +1,30 @@ +%9Syntax:%9 + @SYNTAX:accept@ -MODE <+|->g -Works only in some IRC networks. +%9Parameters:%9 -ACCEPT allows you to specify who you want to receive private messages -and notices from while you are in callerid (+g) mode. -When you have user mode +g enabled, messages from other users are blocked and -the sender is notified; you are also notified but at most once per minute. -IRC operators and services can usually send through +g. + A comma-separated list of nicknames to add or remove; if no argument is + given, your accept list will be displayed. -The accept list is lost when you disconnect. -Users are automatically removed from the accept list if they quit, split -or change nick. +%9Description:%9 -The argument is a comma-separated list of nicks to add or (when prefixed -with a '-') to remove. No output is returned for users successfully added -or removed. -If no arguments are given, your accept list is displayed (ACCEPT * on the -protocol level). + Allows you to specify who you want to receive private messages and notices + from while you have callerid enabled. -Example: - /ACCEPT user1,user2,-user3,-user4 - Adds user1 and user2 and removes - user3 and user4. - -See also: IGNORE, SILENCE + When you have callerid enabled, messages from other users are blocked and + the sender is notified. + + Users are automatically removed from the accept list if they quit, split + or change nickname; the accept list is lost when you disconnect. + + This command only works on IRC servers that support the callerid user mode. + +%9Examples:%9 + + /ACCEPT mike,bob,-john,-sarah + /ACCEPT sarah,-bob + +%9See also:%9 IGNORE, SILENCE diff --git a/docs/help/in/action.in b/docs/help/in/action.in index 896e8d19..23b1a5d6 100644 --- a/docs/help/in/action.in +++ b/docs/help/in/action.in @@ -1,9 +1,23 @@ +%9Syntax:%9 + @SYNTAX:action@ -Same as ME, but gets channel or nick as an additional parameter. -Example: /ACTION #irssi yawns -(This outputs the following to #irssi: * Nick yawns) +%9Parameters:%9 -See also: ME + -: The server tag you want to send the action emote to. + + A target nickname or channel and the message. + +%9Description:%9 + + Sends an action emote to a nickname or a channel. + +%9Examples:%9 + + /ACTION #irssi is hungry! + /ACTION mike had an awesome day @ work + /ACTION -efnet #irssi is happy it's Friday + +%9See also:%9 ME diff --git a/docs/help/in/admin.in b/docs/help/in/admin.in index b5d95254..2b6f8b73 100644 --- a/docs/help/in/admin.in +++ b/docs/help/in/admin.in @@ -1,8 +1,22 @@ +%9Syntax:%9 + @SYNTAX:admin@ -Displays the administrative details about the given server. If -no server is specified, the server you are connected to is -used. If a nickname is supplied then it gives the administrative -information for that person's current server. +%9Parameters:%9 + + A nickname or server for which you want to know the administrative details; + if no argument is given, the server you are connected to will be used. + +%9Description:%9 + + Displays the administrative details of a server. + +%9Examples:%9 + + /ADMIN + /ADMIN orwell.freenode.net + /ADMIN mike + +%9See also:%9 INFO diff --git a/docs/help/in/alias.in b/docs/help/in/alias.in index 97fe395e..13fcb55a 100644 --- a/docs/help/in/alias.in +++ b/docs/help/in/alias.in @@ -1,22 +1,33 @@ +%9Syntax:%9 + @SYNTAX:alias@ -Creates a new alias or shows matching defined aliases. Without -parameters shows all defined aliases. Multiple commands can be run if -separated with ';' character. Parameters given to alias are in $0..$9 -variables, if you don't use them in your alias, all parameters are -automatically appended after it. +%9Parameters:%9 -Examples: + A name of the alias and the command to execute. You can prepend the alias + with the "-" character to remove the alias; if no argument is given, your + aliases will be displayed. -/ALIAS w - - shows all defined aliases starting with letter w. +%9Description:%9 -/ALIAS send echo Sending file $1 to $0;dcc send $0- - - creates alias 'send'. + Creates or updates an alias; you can use the ";" character to separate + multiple commands. -/ALIAS -send - - removes alias 'send'. + The parametesr given to the alias are expanded in "$[\d]" For example $0, + $1, $2, $8, $12, ... -See also: UNALIAS + If you don't use any parameters in your alias, all parameters will be + automatically appended after it. + +%9Examples:%9 + + /ALIAS + /ALIAS UH USERHOST + /ALIAS COMEBACK SAY I was hoping for a battle of wits, but you seem to be unarmed. + /ALIAS -COMEBACK + /ALIAS UNACT SCRIPT EXEC \$_->activity(0) for Irssi::windows + /ALIAS QOP ^MSG Q op $C + +%9See also:%9 BIND, UNALIAS diff --git a/docs/help/in/away.in b/docs/help/in/away.in index 8283d63d..16479856 100644 --- a/docs/help/in/away.in +++ b/docs/help/in/away.in @@ -1,28 +1,33 @@ +%9Syntax:%9 + @SYNTAX:away@ - -one - -all +%9Parameters:%9 -This command marks you as being "away". It is used to tell people that -you currently aren't paying attention to your screen. You might use it -if you are taking a nap, in the shower, getting some food, or otherwise -just aren't there at the moment. When you're "away" you will see "(zZzZ)" -in your statusbar. + -one: Marks yourself as away on the active server. + -all: Marks yourself as away on all the servers you are connected to. -Anyone who does a WHOIS on your nickname will see that you are away, -as well as your away message. Anyone doing a WHO that returns information -about you will also see that you're gone. + You away message; if no argument is given, your away status will be removed. + +%9Description:%9 -By default, if someone sends you a MSG while you are away, your client -will beep. You can turn this off by setting BEEP_WHEN_AWAY to OFF. + Marks yourself as "away"; this method is used to inform people that you + are not paying attention to your screen. -If you send a MSG to someone who is away, you will automatically be -notified of this. By default, you will only receive this notification -once. If you wish to see it every time (to tell when a person is no -longer marked away, for instance), change SHOW_AWAY_ONCE to OFF. + You might use it when you are taking a nap, in the shower, getting some + food, or otherwise engaged. When you're "away" you will see "(zZzZ)" in + your statusbar. -You can remove your away status by using AWAY with no arguments. + Anyone who does a WHOIS on your nickname will see that you are away, as + well as your away message. -See also: SET AWAY +%9Examples:%9 + + /AWAY + /AWAY I'm getting some food. + /AWAY zZzZ + /AWAY -one Feeding the cat! + +%9See also:%9 DISCONNECT diff --git a/docs/help/in/ban.in b/docs/help/in/ban.in index 8d6d02bf..c43c63dd 100644 --- a/docs/help/in/ban.in +++ b/docs/help/in/ban.in @@ -1,27 +1,42 @@ +%9Syntax:%9 + @SYNTAX:ban@ -Bans the specified nick or userhost mask. +%9Parameters:%9 -If nick is given as parameter, the ban type is used to generate the ban -mask. /SET ban_type specified the default ban type. Ban type is one of -the following: + -normal: Uses the *!*user@*.domain.tld format. + -user: Uses the *!*user@* format. + -host: Uses the *!*@host.domain.tld format. + -domain: Uses the *!*@*.domain.tld format. + -custom: Uses the custom format. - Normal - *!*user@*.domain.net - User - *!*user@* - Host - *!*@host.domain.net - Domain - *!*@*.domain.net - Custom [nick] [user] [host] [domain] + A channel and the nicknames or hostnames to ban; if no arguments are given + the bans in the active channel are displayed. -If no arguments are given the current bans in this channel are displayed. + If no ban format parameter is given, the value of the ban_type setting will + be used to generate the hostmask to ban. -Examples: - /BAN loser - Bans the nick 'loser' - /BAN -host loser - Bans the host of nick 'loser' - /BAN *!*@*.org - Bans all the users coming from any .org domain. +%9Description:%9 - /SET ban_type custom nick domain - nick!*@*.domain.net - /SET ban_type custom user host - *!user@host.domain.net + Adds one or more bans to a channel. -See also: KNOCKOUT, KICKBAN +%9Configuring the custom format:%9 + + You must set the custom ban_type to the format you would like to use. For + example, if you set the custom ban_type to "nick domain", it will generate + a ban based on the nick!*@*.domain.tld format. + +%9Examples:%9 + + /BAN + /BAN mike + /BAN -host bob + /BAN *!*@*.irssi.org + /BAN -domain sarah + + /SET ban_type custom nick domain + /SET ban_type custom user host + +%9See also:%9 KICKBAN, KNOCKOUT diff --git a/docs/help/in/beep.in b/docs/help/in/beep.in index 12df1ae7..d8a06fff 100644 --- a/docs/help/in/beep.in +++ b/docs/help/in/beep.in @@ -1,6 +1,15 @@ +%9Syntax:%9 + @SYNTAX:beep@ -Outputs the bell-character, usually causing -your terminal beep. +%9Description:%9 + + Outputs the bell-character, usually causing your terminal to beep. + +%9Examples:%9 + + /BEEP + +%9See also:%9 CLEAR diff --git a/docs/help/in/bind.in b/docs/help/in/bind.in index d48dcd69..d6151b23 100644 --- a/docs/help/in/bind.in +++ b/docs/help/in/bind.in @@ -1,48 +1,34 @@ +%9Syntax:%9 + @SYNTAX:bind@ -Bind some action to specified keystroke. Remember that all characters -in keystrokes are case-sensitive! Uppercase letter usually means that -you need to keep SHIFT pressed to get the key to work. +%9Parameters:%9 -Most most commonly used keystrokes are: + -list: Displays a list of all the bindable commands. + -delete: Removes the binding, - ^X - Ctrl-X - meta-x - Meta-x (Meta is quite often Alt-key in PCs, ESC-x works too) + A name of the binding and the command to perform; if no parameter is given, + the list of bindings will be displayed. -Irssi has by default also defined several other keys which you can use: +Details: - return - The return/enter key - space, backspace - Space / backspace - up, down, left, right - Arrow keys - cleft, cright - Ctrl-left/right - home, end, prior, next - prior = Page Up, next = Page Down - insert, delete + Adds or removes a binding; the binding itself is case-sensitive and may + contain as many characters as you want. -The keystroke can contain as many key presses as you want, and you can -define names for different key sequences to use them more easily (the -keys above are done like that). For example, you may want to manage -windows with ^W key, so that ^W^C creates new window, ^W^K kills the -active window, etc. you may do it like: + Uppercase characters usually indicate that you need to keep the shift-key + pressed to use the binding. - /BIND ^W^C /WINDOW NEW HIDE - /BIND ^W^K /WINDOW KILL +%9Examples:%9 -But maybe you wish to give these binds to other people who want to use -some other key than ^W, then it would be better done as: + /BIND + /BIND meta-c /CLEAR + /BIND meta-q change_window 16 + /BIND -delete meta-y + /BIND ^W^C /WINDOW NEW HIDE + /BIND ^W^K /WINDOW KILL + /BIND ^[[11~ command AWAY I'm off for today :) + /BIND ^[[12~ command AWAY - /BIND ^W key window - /BIND window-^C /WINDOW NEW HIDE - /BIND window-^K /WINDOW KILL +%9See also:%9 ALIAS - -To get a list of all bindable commands use /bind -list. - -Examples: - -Clear screen: - /BIND meta-c /CLEAR - -People with qwertz layout probably want to swap meta-y and meta-z: - /BIND meta-z change_window 16 - /BIND -delete meta-y diff --git a/docs/help/in/cat.in b/docs/help/in/cat.in index ea324aa3..3a3ed32b 100644 --- a/docs/help/in/cat.in +++ b/docs/help/in/cat.in @@ -1,8 +1,21 @@ +%9Syntax:%9 + @SYNTAX:cat@ -Outputs the contents of the specified file. Equivalent to -UNIX 'cat' command. +%9Parameters:%9 -See also: CD + The file to display. + +%9Description:%9 + + Displays the contents of the specified file into the active window. + +%9Examples:%9 + + /CAT /etc/network/interfaces + /CAT /home/mike/resume.txt + /CAT contact_details.txt + +%9See also:%9 CD, EXEC diff --git a/docs/help/in/cd.in b/docs/help/in/cd.in index dd62f710..bc6b7aac 100644 --- a/docs/help/in/cd.in +++ b/docs/help/in/cd.in @@ -1,8 +1,21 @@ +%9Syntax:%9 + @SYNTAX:cd@ -Changes the current working directory. Equivalent to UNIX -'cd' command. +%9Parameters:%9 -See also: DCC GET + The directory to change into. + +%9Description:%9 + + Changes the current active directory. + +%9Examples:%9 + + /CD /home/public_ftp + /CD /home/mike + /CD /var/log + +%9See also:%9 CAT diff --git a/docs/help/in/channel.in b/docs/help/in/channel.in index eb4154b4..f26b6959 100644 --- a/docs/help/in/channel.in +++ b/docs/help/in/channel.in @@ -1,35 +1,46 @@ +%9Syntax:%9 + @SYNTAX:channel@ -Irssi can automatically join to specified channels in specified -IRC networks. It can also automatically send the password when -manually joining to channel without specifying the password. +%9Parameters:%9 -/CHANNEL ADD [-auto | -noauto] [-bots ] [-botcmd ] - [] + LIST: Displays the list of configured channels. + ADD: Adds a channel to your configuration. + REMOVE: Removes a channel from your configuration. -With -bots and -botcmd arguments you can automatically send -commands to someone in channel. This is useful for automatically -getting ops for channels, for example + -auto: Automatically join the channel. + -noauto: Don't join the channel automatically. + -bots: The list of hostnames send automated commands to. + -botcmd: The automated commands to perform. -/CHANNEL ADD -auto -bots "*!bot@bothost.org bot*!*@host2.org" - -botcmd "msg $0 op mypass" #channel ircnet + The channel and network to add to the configuration; you can optionally + specify the password of a channel. -You can also use the -botcmd without -bots argument. The command is -then sent whenever you join the channel. + If no parameters are given, the list of channels you have joined will be + displayed. + +%9Description:%9 -If you want to remove some settings from existing channel record, -for example bots, just give the -bots "" parameters to it. Password -can be removed by setting it to - (or actually, "" works too). + Adds, removes or displays the configuration of channels; this method is + used to automate and simplify your workflow. -You can remove the channels with -/CHANNEL REMOVE + You can use the ADDALLCHANS command, which is a default alias, to add all + the channels you are present on into the configuration. -/CHANNEL LIST displays list of channels with settings. +%9Examples:%9 -/CHANNEL without any arguments displays list of channels you have -joined. You can also use /CHANNEL to join to channels just as with -/JOIN, like /CHANNEL #a. + /CHANNEL + /CHANNEL LIST + /CHANNEL ADD -auto #irssi Freenode + /CHANNEL ADD -auto #basementcat Quakenet secret_lair + /CHANNEL ADD -auto -bots "*!@*.irssi.org *!bot@irssi.org" -botcmd "msg $0 op WzerTrzq" #hideout Freenode + /CHANNEL ADD -auto -bots "Q!TheQBot@CServe.quakenet.org" -botcmd "^MSG Q op #irssi" #irssi Quakenet + /CHANNEL REMOVE #hideout Freenode -See also: TS, JOIN +%9Special Example:%9 + + /ADDALLCHANS + +%9See also:%9 JOIN, TS diff --git a/docs/help/in/clear.in b/docs/help/in/clear.in index b3db54ef..ad5b8bf8 100644 --- a/docs/help/in/clear.in +++ b/docs/help/in/clear.in @@ -1,9 +1,19 @@ +%9Syntax:%9 + @SYNTAX:clear@ -This command clears the current window of all text. It is useful -for wiping a screen that has rendered improperly (such as due -to a bad termcap entry) or that contains sensitive information -(such as one's OPER password). +%9Parameters:%9 + -all: Clear all the windows + + The window number to clear; if no argument is given, the active window + is used. + +%9Description:%9 + + Clears the window of all text; you may use this to clear a windows that + contains sensitive information or has rendered improperly. + +%9See also:%9 REDRAW diff --git a/docs/help/in/completion.in b/docs/help/in/completion.in index 1509bf33..140b1cb1 100644 --- a/docs/help/in/completion.in +++ b/docs/help/in/completion.in @@ -1,31 +1,34 @@ +%9Syntax:%9 + @SYNTAX:completion@ -Irssi can "complete" some words for you - you can write just first few letters -of the word and press TAB (or any other key with action word_completion -assigned). Then, irssi will choose the most probable matching word and inserts -it to the command line. You can press TAB repetitively and irssi will replace -the chosen word with another possible words matching to the letters you wrote. +%9Parameters:%9 -The words chosen usually depend on their context - they can be filenames or -command names, but most frequently they are nicks of people on same channels as -you are. However, you can have global list of own completions, which apply to -all contexts. This command is dedicated to maintaining of such a list. + -auto: Inserts the completion without pressing a word completion character. + -delete: Removes the completion from the configuration. + + A key and the value to use as a replacement. If no argument is given, the + list of completions will be displayed. -Without any parameters, /COMPLETION displays list of all user completions. +%9Description:%9 -/COMPLETION [-auto] adds completion which gets triggered when -you press TAB (or any other key with action word_completion assigned) after -writing specified and which expands to . When -auto is -specified, the completion gets triggered even when you press SPACE or ENTER (or -any other key with action check_replaces assigned) after the . If -there's already some completion in the list, it will get replaced. + Replaces or completed words or letters; you can write just the first few + letters of the word and press TAB to insert a replacement. -/COMPLETION -delete removes completion of from the user -completion list. + When a replacement has been found, Irssi will choose the most probable + matching word and replaces it; you may press TAB repeatedly to swap between + matches. + + If you want to remove a completion which has the auto parameter set, you + need to enclose the completion between "'" characters. -Note: When -auto is specified for the you want to remove you have to -quote it like /COMPLETION -delete ''. Works with doublequotes aswell. +%9Examples:%9 -See also: BIND + /COMPLETION w/h without + /COMPLETION -auto anywya anyway + /COMPLETION -delete 'anywya' + /COMPLETION -delete without + +%9See also:%9 BIND diff --git a/docs/help/in/connect.in b/docs/help/in/connect.in index c06ce999..1c1aa2bb 100644 --- a/docs/help/in/connect.in +++ b/docs/help/in/connect.in @@ -1,23 +1,40 @@ +%9Syntax:%9 + @SYNTAX:connect@ - -4, -6: specify explicitly whether to use IPv4 or IPv6 address - -ssl: use SSL when connecting - -ssl_cert: The SSL client certificate file (implies -ssl) - -ssl_pkey: The SSL client private key (if not included in the certificate file) - -ssl_pass: The password for the SSL client private key or certificate. - -ssl_verify: Verify servers SSL certificate - -ssl_cafile: File with list of CA certificates (implies -ssl_verify) - -ssl_capath: Directory with CA certificates (implies -ssl_verify) - -network: the network this connection belongs to - -ircnet: Same as -network. Deprecated. Do not use. - -host: the host - -!: don't autojoin channels - -noautosendcmd: don't execute autosendcmd - -rawlog: immediately open rawlog after connected +%9Parameters:%9 -This command makes irssi to connect to specified server. -Current connections are kept and a new one is created. + -4: Connects using IPv4. + -6: Connects using IPv6. + -ssl: Connects using SSL encryption. + -ssl_cert: The SSL client certificate file. + -ssl_pkey: The SSL client private key, if not included in the + certificate file. + -ssl_verify: Verifies the SSL certificate of the server. + -ssl_cafile: The file with the list of CA certificates. + -ssl_capath: The directory which contains the CA certificates. + -noproxy: Ignores the global proxy configuration. + -network: The network this connection belongs to. + -host: The hostname you would like to connect from. + -rawlog: Immediately open rawlog after connecting. + -!: Doesn't autojoin channels. + -noautosendcmd: Doesn't execute autosendcmd. -See also: SERVER, DISCONNECT, RMRECONNS, SCONNECT + A network or server to connect to; you can optionally specify a custom port, + password and nickname. + +%9Description:%9 + + Opens a new connection to the specified network or server; existing + connections are kept. + +%9Examples:%9 + + /CONNECT Freenode + /CONNECT -6 Freenode + /CONNECT -4 -! -host staff.irssi.org -network Freenode orwell.freenode.net + /CONNECT irc.irssi.org 6667 WzerT8zq mike + +%9See also:%9 DISCONNECT, RMRECONNS, SERVER diff --git a/docs/help/in/ctcp.in b/docs/help/in/ctcp.in index ce553649..93818061 100644 --- a/docs/help/in/ctcp.in +++ b/docs/help/in/ctcp.in @@ -1,7 +1,23 @@ +%9Syntax:%9 + @SYNTAX:ctcp@ -Sends a CTCP message. For example CTCP ACTION, or CTCP VERSION. +%9Parameters:%9 -See also: ME, ACTION + A target nickname or channel and a command. + +%9Description:%9 + + Sends a CTCP request towards the given target nickname or channel. + +%9Examples:%9 + + /CTCP mike PING + /CTCP #irssi VERSION + /CTCP bob USERINFO + /CTCP sarah CLIENTINFO + /CTCP john TIME + +%9See also:%9 ACTION, ME diff --git a/docs/help/in/cycle.in b/docs/help/in/cycle.in index 3d1ed0c2..c44a976a 100644 --- a/docs/help/in/cycle.in +++ b/docs/help/in/cycle.in @@ -1,8 +1,22 @@ +%9Syntax:%9 + @SYNTAX:cycle@ -Cycles (leaves and joins) the current channel or the specified -channel. +%9Parameters:%9 -See also: JOIN, PART + A channel and the message. If no argument is given, the active channel + will be used. + +%9Description:%9 + + Leaves and rejoins a channel. + +%9Examples:%9 + + /CYCLE + /CYCLE #irssi + /CYCLE #irssi BRB :) + +%9See also:%9 JOIN, PART diff --git a/docs/help/in/dcc.in b/docs/help/in/dcc.in index b75d5713..59ac5036 100644 --- a/docs/help/in/dcc.in +++ b/docs/help/in/dcc.in @@ -1,37 +1,45 @@ +%9Syntax:%9 + @SYNTAX:dcc@ -/DCC LIST - - Shows all the open DCC connections. -/DCC RESUME [ []] - - Resumes a DCC SEND/GET connection. -/DCC CHAT [-passive] [] - - Sends a chat connection request to remote client or accepts - a chat connection if the remote end has already sent a request. - If -passive is used then the passive DCC protocol is used (as mIRC - can do). This is useful to bypass a NAT/firewall which limit your - possibility in listening for remote connections. -/DCC GET [ []] - - Gets the file offered by remote client. The file is downloaded and - saved into the directory specified by the `dcc_download_path' setting. -/DCC SEND [-passive] [-append | -prepend | -flush | -rmtail | -rmhead] - [ ...] - - Sends a DCC SEND request to remote client. Remote end has to accept - the request before the transmission can be started. Giving multiple - files queues them. File names may contain shell expansion - characters: * ? [] ~ (~ expansion may not be supported on all - platforms). Files with spaces in their names need to be quoted (eg. - "file name"). If -passive is used then the passive DCC protocol is - used (as mIRC and xchat > 2.0.7 can do). This is useful to bypass a - NAT/firewall which limit your possibility in listening for remote - connections. -/DCC SERVER [<+|-scf> ] - - Starts a DCC SERVER on the specified port. The remote can connect - to this server and initiate chat, send and fserve requests. You can - specify + or - using any combination of the flags 's' (Send), - 'c' (Chat), or 'f' (Fserver). -/DCC CLOSE [] - - Closes a DCC-connection. Type can be either SEND, GET or CHAT. +%9Parameters:%9 -See also: CD + CHAT: Initiates or accept a chat request. + GET: Accepts a file transfer request. + RESUME: Resumes a file transfer. + SERVER: Starts a DCC server. + CLOSE: Closes a DCC connection. + LIST: Displays all the open DCC connections. + + -passive: Uses the passive DCC protocol. + -scf: Use any combination of the flags to indicate: + 's' - send + 'c' - chat + 'f' - fserver + + The nickname of the person to chat with, or the name of the file to + transfer. + +%9Description:%9 + + The DCC protocol is used to initiate client-to-client chat connections + and file transfers. + + If you are behind NAT, or if the firewall is too restrictive, you might + want to try if using the passive parameter resolved your conneciton + problem. + + You can send files which contain special character or spaces by enclosing + the filename within quotes. For example: "my file with spaces.txt". + +%9Examples:%9 + + /DCC CHAT mike + /DCC GET bob "summer vacation.mkv" + /DCC SEND sarah documents/resume.pdf + /DCC CLOSE mike + /DCC CLOSE bob "summer vacation.mkv" + +%9See also:%9 CD diff --git a/docs/help/in/dehilight.in b/docs/help/in/dehilight.in index d1202917..7c7fe152 100644 --- a/docs/help/in/dehilight.in +++ b/docs/help/in/dehilight.in @@ -1,7 +1,20 @@ +%9Syntax:%9 + @SYNTAX:dehilight@ -Removes the specified item from highlight list. +%9Parameters:%9 -See also: HILIGHT + The id or mask of the highlight to remove. + +%9Description:%9 + + Removes the specified highlight from the configuration. + +%9Examples:%9 + + /DEHILIGHT 1 + /DEHILIGHT 31 + +%9See also:%9 HILIGHT diff --git a/docs/help/in/deop.in b/docs/help/in/deop.in index e9893e6a..8c73a5c9 100644 --- a/docs/help/in/deop.in +++ b/docs/help/in/deop.in @@ -1,10 +1,23 @@ +%9Syntax:%9 + @SYNTAX:deop@ -Takes off the channel operator privileges from the -specified nick(s). +%9Parameters:%9 -Wildcards in the nick are allowed. + A list of nicknames to deop. -See also: OP +%9Description:%9 + + Removes the channel operator privileges from the given nicknames; you + may use the wildcard character "*" in a nickname. + +%9Examples:%9 + + /DEOP mike + /DEOP bob sarah + /DEOP jo*n + /DEOP * + +%9See also:%9 DEVOICE, MODE, OP, VOICE diff --git a/docs/help/in/devoice.in b/docs/help/in/devoice.in index ce090191..852a0002 100644 --- a/docs/help/in/devoice.in +++ b/docs/help/in/devoice.in @@ -1,10 +1,26 @@ +%9Syntax:%9 + @SYNTAX:devoice@ -Takes off the voice from the specified nick(s). This makes them -not to be able to send messages to the moderated (+m) channel. +%9Parameters:%9 -Wildcards in the nick are allowed. + A list of nicknames to devoice. -See also: VOICE, MODE +%9Description:%9 + + Removes the channel voice privileges from the given nicknames; you + may use the wildcard character "*" in a nickname. + + If a channel is moderated, the users will require a voice or op in + order to be able to send messages to the channel. + +%9Examples:%9 + + /DEVOICE mike + /DEVOICE bob sarah + /DEVOICE jo*n + /DEVOICE * + +%9See also:%9 DEOP, MODE, OP, VOICE diff --git a/docs/help/in/die.in b/docs/help/in/die.in index c7daf2f6..1af9c5b7 100644 --- a/docs/help/in/die.in +++ b/docs/help/in/die.in @@ -1,7 +1,15 @@ +%9Syntax:%9 + @SYNTAX:die@ -IRC operator command. Terminates the IRC server. +%9Description:%9 -See also: OPER + Terminates the IRC server; this command is reserved for IRC operators. + +%9Examples:%9 + + /DIE + +%9See also:%9 KILL, OPER, WALLOPS diff --git a/docs/help/in/disconnect.in b/docs/help/in/disconnect.in index ec5d5559..4699b79c 100644 --- a/docs/help/in/disconnect.in +++ b/docs/help/in/disconnect.in @@ -1,9 +1,25 @@ +%9Syntax:%9 + @SYNTAX:disconnect@ -Disconnects from the specified IRC-server. -The server tags can be seen with: -/SERVER +%9Parameters:%9 -See also: CONNECT, SERVER + The network to disconnect from and the message to advertise; if no parameters + are given, the active server will be used. + +%9Description:%9 + + Disconnects from one or more IRC servers; the list of all the servers you + are connected to can be retrieved via the SERVER command. + + Use the wildcard character "*" if you want to disconnect from all servers. + +%9Examples:%9 + + /DISCONNECT Freenode I'm off for today, take care! + /DISCONNECT * Vacation time :D + /DISCONNECT + +%9See also:%9 CONNECT, SERVER diff --git a/docs/help/in/echo.in b/docs/help/in/echo.in index 0a70e354..a730e282 100644 --- a/docs/help/in/echo.in +++ b/docs/help/in/echo.in @@ -1,5 +1,25 @@ +%9Syntax:%9 + @SYNTAX:echo@ -Prints text into the current window. Useful for scripts. +%9Parameters:%9 + + -current: Displays the output in the active window. + -window: Displays the ouput in the target window. + -level: Displays the output with a given message level. + + The text ouput; if no target is given, the active window will be used. + +%9Description:%9 + + Displays the given text. + +%9Examples:%9 + + /ECHO 1 + 1 = 2 :D + /ECHO -current Testing the ECHO command + /ECHO -window #irssi Special variables such as ${N} will not be expanded. + +%9See also:%9 CAT, EVAL, EXEC, LEVELS diff --git a/docs/help/in/eval.in b/docs/help/in/eval.in index 8ea0652a..74a0c536 100644 --- a/docs/help/in/eval.in +++ b/docs/help/in/eval.in @@ -1,6 +1,25 @@ +%9Syntax:%9 + @SYNTAX:eval@ -Evaluates the given commands and executes them. Internal variables -are expanded. See the special_vars.txt file in the docs-directory. +%9Parameters:%9 + + The commands to evaluate. + +%9Description:%9 + + Evaluates the given commands and executes them; you can use internal + variables and separate multiple commands by using the ";" character. + +%9Examples%9 + + /EVAL echo I am connected to ${S} on ${chatnet} as ${N} + /EVAL echo My user privileges are +${usermode}; echo Let's party! + +%9References:%9 + + https://github.com/irssi/irssi/blob/master/docs/special_vars.txt + +%9See also:%9 CAT, CD, ECHO, EXEC diff --git a/docs/help/in/exec.in b/docs/help/in/exec.in index 7b092868..2cca5ce3 100644 --- a/docs/help/in/exec.in +++ b/docs/help/in/exec.in @@ -1,41 +1,49 @@ +%9Syntax:%9 + @SYNTAX:exec@ - -: Don't print "process terminated ..." message - -nosh: Don't start command through /bin/sh - -out: Send output to active channel/query - -msg: Send output to specified nick/channel - -notice: Send output to specified nick/channel as notices - -name: Name the process so it could be accessed easier +%9Parameters:%9 - -window: Move the output of specified process to active window - -close: Forcibly close (or "forget") a process that doesn't die. - This only removes all information from irssi concerning the - process, it doesn't send SIGKILL or any other signal - to the process. - -: Send a signal to process. can be either numeric - or one of the few most common ones (hup, term, kill, ...) + -: Suppresses the process termination notification. + -nosh: Doesn't execute the command through /bin/sh. + -out: Sends the output to the active channel or query. + -msg: Sends the output to the specified nickname or channel. + -notice: Sends the output to the specified nickname or channel as notices. + -name: Gives the process the specified name. + -window: Displays the output in the active window. + -close: Forcibly closes a process that doesn't die. + -: Sends the given signal to the process. + -in: Sends text to the standard input of the process. + -interactive: Executes the process in a new window item. - -in: Send text to standard input of the specified process - -interactive: Creates a query-like window item. Text written to it is - sent to executed process, like /EXEC -in. + The command to execute; if no output parameter is given, the active window + will be used and if no parameters are given at all, the list of active + processes will be displayed. -Execute specified command in background. Output of process is printed -to active window by default, but can be also sent as messages or -notices to specified nick or channel. +%9Description:%9 -Processes can be accessed either by their ID or name if you named it. -Process identifier must always begin with '%%' character, like %%0 or -%%name. + Executes the specified command in the background; the process can be + accessed by its id or the name you gave it. -Once the process is started, its output can still be redirected -elsewhere with the -window, -msg, etc. options. You can send text to -standard input of the process with -in option. + The output of the process can be redirected to various targets, such as + a window, a channel, a nickname or a query. --close option shouldn't probably be used if there's a better way to -kill the process. It is meant to remove the processes that don't die -even with SIGKILL. This option just closes the pipes used to -communicate with the process and frees all memory it used. + The process identifier must always begin with the "%%" character. For + example %%0. -EXEC without any arguments displays the list of started processes. + If you remove a process with the close parameter, it will only make Irssi + detach from it; the process will keep running until it terminates. + +%9Examples:%9 + + /EXEC + /EXEC ls + /EXEC -msg #irssi cat unicorn.txt + /EXEC -out cat /etc/passwd | grep $USER | awk -F: '{print $5}' + /EXEC -name ssh -nosh -interactive -window ssh staff.irssi.org + /EXEC -close mailserver + /EXEC -close %%0 + +%9See also:%9 CAT, CD, ECHO, EVAL diff --git a/docs/help/in/flushbuffer.in b/docs/help/in/flushbuffer.in index c353490a..9b1400b9 100644 --- a/docs/help/in/flushbuffer.in +++ b/docs/help/in/flushbuffer.in @@ -1,6 +1,18 @@ +%9Syntax:%9 + @SYNTAX:flushbuffer@ -If either write_buffer_timeout or write_buffer_size have been set an immediate -write of the buffers is forced. +%9Description:%9 + + Forces an immediate flush of the buffers if the related settings are enabled. + +%9Examples:%9 + + /FLUSHBUFFER + + /SET write_buffer_size + /SET write_buffer_timeout + +%9See also:%9 REDRAW, SCROLLBACK diff --git a/docs/help/in/format.in b/docs/help/in/format.in index ed576c95..2b65a6b6 100644 --- a/docs/help/in/format.in +++ b/docs/help/in/format.in @@ -1,9 +1,25 @@ +%9Syntax:%9 + @SYNTAX:format@ - -reset - -delete +%9Parameters:%9 -Allows you to view/change irssi's messages. -Use this command with care. + -reset: Restores the original value. + -delete: Removes the format from the configuration. + + The module name, the format name and the value; if no arguments are given, + the list of formats are displayed. + +%9Description:%9 + + Allows you to reconfigure the way messages are displayed. + +%9Examples:%9 + + /FORMAT irc away You have left planet earth + /FORMAT core not_good_idea I'm sorry sir, this broke my irony sensor; add -YES if you really mean it! + /FORMAT -reset irc away + +%9See also:%9 RELOAD, SAVE, SET diff --git a/docs/help/in/hash.in b/docs/help/in/hash.in index 62a889f8..32dfc9c7 100644 --- a/docs/help/in/hash.in +++ b/docs/help/in/hash.in @@ -1,5 +1,22 @@ +%9Syntax:%9 + @SYNTAX:hash@ -Not available. +%9Description:%9 + + This is an ancient command that is no longer used; if you on an IRC server + that supports this command, please contact us to we can update the + documentation. + +%9Examples:%9 + + /HASH + +%9References:%9 + + http://www.irssi.org + https://github.com/irssi + +%9See also:%9 DIE, KILL, OPER diff --git a/docs/help/in/help.in b/docs/help/in/help.in index 318b8204..555e20e1 100644 --- a/docs/help/in/help.in +++ b/docs/help/in/help.in @@ -1,13 +1,27 @@ +%9Syntax:%9 + @SYNTAX:help@ -Shows help on commands. Try: - /HELP command +%9Parameters:%9 -Also try, for example: - /SET beep -or - /SET auto + The command to display the documentation for; if no argument is given, the + list of commands will be displayed. -See also: +%9Description:%9 + + Displays the documentation for the given command. + +%9Examples:%9 + + /HELP + /HELP AWAY + /HELP CONNECT + +%9References:%9 + + http://www.irssi.org + https://github.com/irssi + +%9See also:%9 CONNECT, MSG, NETWORK, SERVER diff --git a/docs/help/in/hilight.in b/docs/help/in/hilight.in index 89842933..fabbc2ea 100644 --- a/docs/help/in/hilight.in +++ b/docs/help/in/hilight.in @@ -1,32 +1,42 @@ +%9Syntax:%9 + @SYNTAX:hilight@ - -mask: Match only for nick, is a nick mask - -regexp: is a regular expression - -full: must match to full words - -nick: Hilight only the nick, not the whole line (default) - -word: Hilight only the word (default with non-public messages) - -line: Hilight the whole line with the hilight color. - -color: Print the message with . color is in %%code format - (see docs/formats.txt) - -actcolor: Color to show in statusbar activity, or don't change if %%n. - -level: Match only for messages, default is - publics,msgs,notices,actions - -channels: Match only in (comma separated list) - -priority: Priority to use when multiple hilights match. Default is 0. +%9Parameters:%9 -Examples: + -nick: Highlights only the nickname and not the whole line. + -word: Highlights only the word and not the whole line. + -line: Highlights the whole line. + -mask: Highlights all messages from users matching the mask. + -full: The text must match the full word. + -regexp: The text is a regular expression. + -color: The color the display the highlight in. + -actcolor: The color to mark the highlight activity in the statusbar. + -level: Matches only on the given message level. + -network: Matches only on the given network. + -channels: Matches only on the given channels. + -priority: The priority to use when multiple highlights match. -Hilight lines that have "mynick" word: - /HILIGHT mynick + The text to highlight on; if no argument is given, the list of highlights + will be displayed. -Hilight all messages from "mynick": - /HILIGHT -mask mynick!*@* +%9Description:%9 -Hilight lines that were written by nicks from *.fi with bold green - /HILIGHT -color %%G -mask *!*@*.fi + Highlights the keyword or pattern to make sure that you don't miss any + important messages. -For regular expressions, see `man 7 regex`. +%9Examples:%9 -See also: DEHILIGHT, SET HILIGHT + /HILIGHT + /HILIGHT mike + /HILIGHT -regexp mi+ke+ + /HILIGHT -mask bob!*@*.irssi.org -color %%G + /HILIGHT -full -color %%G -actcolor %%Y redbull + +%9References:%9 + + https://github.com/irssi/irssi/blob/master/docs/formats.txt + +%9See also:%9 DEHILIGHT, LEVELS diff --git a/docs/help/in/ignore.in b/docs/help/in/ignore.in index 26c269a4..a247dcc8 100644 --- a/docs/help/in/ignore.in +++ b/docs/help/in/ignore.in @@ -1,46 +1,46 @@ +%9Syntax:%9 + @SYNTAX:ignore@ - -regexp: is a regular expression - -full: must match to full words - -pattern: must match to the message's text - -except: *DON'T* ignore - overrides an existing ignore. - -replies: Ignore replies to nick in channels. For example - "/IGNORE -replies *!*@*.fi PUBLIC" ignores everyone - from Finland, but also anyone sending message - "tofinnishnick: blahblah". - -network: Ignore only on this network. - -ircnet: Same as -network. Deprecated. Do not use. - -channels: Ignore only in channels (comma separated list) - -time: seconds after the ignore is removed - : Either a nick mask or list of channels - : List of levels to ignore. You can use - to remove levels - from ignore (/help levels for details). - <^levels>: List of levels to NOT ignore - (/ignore -except nick notices = /ignore nick ^notices) +%9Parameters:%9 + -regexp: Indicates that the pattern is a regular expression. + -full: Indicates that the pattern must match a full word. + -pattern: The text pattern to ignore. + -except: Negates the ignore. + -replies: Also ignore nicknames who are talking to anyone who matches the ignore. + -network: Ignores only on a specific network. + -channels: Ignores only on specific channels. + -time: The timeout to automatically remove the ignore. -/IGNORE without any arguments displays list of ignores. If you want to remove -some levels of the ignore, use /IGNORE - - etc + The mask, channels and levels to ignore; if no argument is provided, the + list of ignores will be displayed. -The best match always wins, so you can have: +%9Description:%9 + + Ignores nicknames or text that matches a pattern. + + The special level "NO_ACT" can be used to ignore activity in the statusbar + without actually ignoring the message; this behaviour is somewhat special + because it is allowed in addition to other ignores for the same target. + +%9Examples:%9 + + /IGNORE + /IGNORE * JOINS /IGNORE * CTCPS - /IGNORE -except *!*@host.org CTCPS - -Examples: - - /IGNORE * JOINS - ignore joins in all channels - /IGNORE #channel ALL -PUBLIC -ACTIONS - ignore all but public/actions - /IGNORE #channel -JOINS - don't ignore joins anymore - /IGNORE -replies *!user@*.host.org ALL - ignore user and all replies - -Some suggestions for ignoring annoying public aways: - /IGNORE -regexp -pattern "is (away|gone|back)" * ACTIONS + /IGNORE -except *!*@*.irssi.org CTCPS + /IGNORE #irssi ALL -PUBLIC -ACTIONS + /IGNORE -replies *!*@*.irssi.org ALL + /IGNORE -regexp -pattern (away|gone|back|playing|returned) * ACTIONS /IGNORE *zzz* NICKS /IGNORE *afk* NICKS /IGNORE *away* NICKS + /IGNORE #irssi NO_ACT JOINS PARTS QUITS + /IGNORE mike NO_ACT -MSGS + /IGNORE -regexp -pattern + /IGNORE mike NO_ACT -MSGS -For regular expressions, see `man 7 regex`. - -See also: UNIGNORE, SILENCE, ACCEPT +%9See also:%9 ACCEPT, SILENCE, UNIGNORE diff --git a/docs/help/in/info.in b/docs/help/in/info.in index 864fe69e..275f349d 100644 --- a/docs/help/in/info.in +++ b/docs/help/in/info.in @@ -1,6 +1,21 @@ +%9Syntax:%9 + @SYNTAX:info@ -Shows information about the IRC server software and the current -server instance. +%9Parameters:%9 + + The server to display the information for; if no argument is given, the + active server will be used. + +%9Description:%9 + + Displays information about the IRC server software. + +%9Examples:%9 + + /INFO + /INFO orwell.freenode.net + +%9See also:%9 ADMIN diff --git a/docs/help/in/invite.in b/docs/help/in/invite.in index 1e7f69b1..7c0babb3 100644 --- a/docs/help/in/invite.in +++ b/docs/help/in/invite.in @@ -1,10 +1,21 @@ - + +%9Syntax:%9 + @SYNTAX:invite@ -Invites the specified nick to the current or specified channel. +%9Parameters:%9 -Example: - /INVITE buddy #mychannel + The nickname to invite and the channel to invite him or her to; if no + channel is given, the active channel will be used. -See also: MODE +%9Description:%9 + + Invites the specified nick to a channel. + +%9Examples:%9 + + /INVITE mike + /INVITE bob #irssi + +%9See also:%9 MODE, WHOIS diff --git a/docs/help/in/invitelist.in b/docs/help/in/invitelist.in index d544754b..e516b31a 100644 --- a/docs/help/in/invitelist.in +++ b/docs/help/in/invitelist.in @@ -1,9 +1,20 @@ -@SYNTAX:invitelist@ +%9Syntax:%9 -Shows the +I modes of the current channel. +I mode -allows free joins of clients with certain userhost masks -even if the channel is invite only. +INVITELIST -See also: INVITE, MODE +%9Description:%9 + + Displays the invitelist for the active channel; nicknames who match the + masks will be able to join the channel if its invite only. + + This is not a command, but a default alias. + +%9Examples:%9 + + /INVITELIST + +%9References:%9 + + /ALIAS INVITELIST MODE $C +I diff --git a/docs/help/in/ircnet.in b/docs/help/in/ircnet.in deleted file mode 100644 index 88f28156..00000000 --- a/docs/help/in/ircnet.in +++ /dev/null @@ -1,4 +0,0 @@ -IRCNET - -Deprecated. Use NETWORK instead. - diff --git a/docs/help/in/ison.in b/docs/help/in/ison.in index 0287a60e..c77e4c59 100644 --- a/docs/help/in/ison.in +++ b/docs/help/in/ison.in @@ -1,7 +1,20 @@ +%9Syntax:%9 + @SYNTAX:ison@ -Tells whether specified nicks (space-separated) are online. +%9Parameters:%9 -See also: WHOIS, WHOWAS, NOTIFY + The nicknames, separated by space, to check. + +%9Description:%9 + + Displays whether the specified nicknames are online. + +%9Examples:%9 + + /ISON mike + /ISON sarah bob + +%9See also:%9 NOTIFY, WHOAS, WHOIS diff --git a/docs/help/in/join.in b/docs/help/in/join.in index c4e21f6e..6cdfd745 100644 --- a/docs/help/in/join.in +++ b/docs/help/in/join.in @@ -1,15 +1,26 @@ +%9Syntax:%9 + @SYNTAX:join@ - -window: Join channel, placing channel window item in currently active window - -invite: Join last invited channel - -: Join channel on server with specified tag +%9Parameters:%9 -Joins a specified channel. Channel names usually begin with #-sign, -which may be omitted here. + -window Joins a channel in the active window. + -invite Joins the channel you were last invited to. + - The server tag on which you want to join the channel. -JOIN is aliased to J by default. Example: /j irssi -(This joins to the channel #irssi) + The channel names, separated by a commma, to join and the channel key. -See also: PART, WINDOW CLOSE +%9Description:%9 + + Joins the given channels. + +%9Examples:%9 + + /JOIN #irssi + /JOIN #basementcat secret_lair + /JOIN -invite + /JOIN -freenode #github,#freenode,#irssi + +%9See also:%9 KICK, PART diff --git a/docs/help/in/kick.in b/docs/help/in/kick.in index 48f58e68..00586059 100644 --- a/docs/help/in/kick.in +++ b/docs/help/in/kick.in @@ -1,16 +1,24 @@ +%9Syntax:%9 + @SYNTAX:kick@ -This command "kicks" the specified user off of the specified -channel. It is typically used to remove troublemakers, flooders, -or people otherwise making a nuisance of themselves on the channel. -The reason for the kick is recommended, but not required by the IRC -servers. +%9Parameters%9 -If the is omitted, removes the nick from the current -channel. + The channel and the nicknames, separated by a comma, to kick from the + channel and the reason thereof; if no channel is given, the active channel + will be used. -The default alias for /KICK is /K. +%9Description:%9 -See also: KNOCKOUT + Removes the given nicknames from the specified channel; this command is + typically used to remove troublemakers, flooders or people otherwise making + a nuisance of themselves. + +%9Examples:%9 + + /KICK mike Please... chill down! + /KICK #irssi bob,sarah Stop flooding! + +%9See also:%9 BAN, KICKBAN, KNOCKOUT diff --git a/docs/help/in/kickban.in b/docs/help/in/kickban.in index aff0cfb2..3aef99cf 100644 --- a/docs/help/in/kickban.in +++ b/docs/help/in/kickban.in @@ -1,10 +1,22 @@ +%9Syntax:%9 + @SYNTAX:kickban@ -Kicks off and bans a nick from the current channel. -A reason for the kick can be supplied. +%9Parameters:%9 -Default alias for /KICKBAN is /KB. + The channel and the nicknames, separated by a comma, to kickban from the + channel and the reason thereof; if no channel is given, the active channel + will be used. -See also: KNOCKOUT, BANTYPE +%9Description:%9 + + Removes and then bans the given nicknames from the specified channel. + +%9Examples:%9 + + /KICKBAN mike Please... chill down! + /KICKBAN #irssi bob,sarah You guys broke the rules for the last time. + +%9See also:%9 BAN, KICK, KNOCKOUT diff --git a/docs/help/in/kill.in b/docs/help/in/kill.in index 338871d9..37bfc584 100644 --- a/docs/help/in/kill.in +++ b/docs/help/in/kill.in @@ -1,18 +1,24 @@ +%9Syntax:%9 + @SYNTAX:kill@ -IRC operator command. +%9Parameters:%9 -KILL is used to forcibly remote a client from the irc network. -It works similarly to KICK, except that a reason must be -given (even if it is meaningless or flat-out wrong). + The nickname to remove from the network and the reason thereof. -In general, KILL is useful only as a warning tool for abusive -users. Modern irc clients (this one included) have automated -means for reconnecting to a server after a disconnection (whether -due to a KILL or something else), so KILL is by no means a -permanent solution. It is not intended as a means for personal -vendettas; this practice is generally frowned upon. +%9Description:%9 -See also: OPER + Terminates a nickname's connection from the network; this command is + reserved for IRC operators. + + You should not use this command for personal vendettas or for trolling; + these practices are generally frowned upon. + +%9Examples:%9 + + /KILL mike Get off my lawn + /KILL bob Stop breaking the network rules! + +%9See also:%9 DIE, OPER, WALLOPS diff --git a/docs/help/in/knock.in b/docs/help/in/knock.in index c7b23c56..f5c2cf53 100644 --- a/docs/help/in/knock.in +++ b/docs/help/in/knock.in @@ -1,16 +1,30 @@ +%9Syntax:%9 + @SYNTAX:knock@ -Works only in some IRC networks (hybrid-like ircds). +%9Parameters:%9 -KNOCK is a feature that lets you request access to a channel they cannot join without an invite, a key or a raised limit. + The channel you wish to get invited to. -The following conditions must be met for KNOCK to work: +%9Description:%9 - - You are not banned from the channel - - Channel is not private (+p) - - You are not already on the channel - - Channel is invite only (+i), has a key (+k) or limit is full + Sends an invitation request to the channel operators of the target channel; + this command may not work on all IRC servers. + + The following conditions must be met: -When successful KNOCK is issued, it sends a notice to channel operators. Use of KNOCK is rate limited by the server. + * You are not banned from the channel. + * The channel is not private. + * You may not be already in the channel. + * The channel must be invite only, have a key or has exceeded its user + limit. + +%9Examples:%9 + + /KNOCK #irssi + /KNOCK #freenode + /KNOCK #github + +%9See also:%9 INVITE, JOIN diff --git a/docs/help/in/knockout.in b/docs/help/in/knockout.in index 1d18b533..cbaa8dd7 100644 --- a/docs/help/in/knockout.in +++ b/docs/help/in/knockout.in @@ -1,11 +1,26 @@ +%9Syntax:%9 + @SYNTAX:knockout@ -Kicks user off the channel and bans him/her. Ban -lasts the given number of seconds or 5 minutes -by default. +%9Parameters:%9 -Default alias for /KNOCKOUT is /KN. + The time, expressed in seconds, the nicknames, separated by a comma, and the + reason thereof; if no time is provided, the ban will be lifted after 5 + minutes. -See also: BAN, KICK +%9Description:%9 + + Removes and then bans the given nicknames from the active channel; the ban + will be automatically lifted after the specified time. + + The ban will not be lifted if you leave the channel or disconnect from the + network. + +%9Examples:%9 + + /KNOCKOUT 3600 mike Your connection is unstable. + /KNOCKOUT bob,sarah Chill down a bit. + +%9See also:%9 BAN, KICK, KICKBAN diff --git a/docs/help/in/lastlog.in b/docs/help/in/lastlog.in index b7cadf8a..41522cb2 100644 --- a/docs/help/in/lastlog.in +++ b/docs/help/in/lastlog.in @@ -1,22 +1,37 @@ +%9Syntax:%9 + @SYNTAX:lastlog@ - -clear: remove all lastlog lines from window +%9Parameters:%9 - -: don't print the "Lastlog:" and "End of Lastlog" messages. - -file: write lastlog to file instead of screen - -window: which window's lastlog to check (output is always to active) - -case: Case-sensitive matching - -force: Force displaying lastlog even if it's longer than 1000 lines - -new: show only lines since last /LASTLOG - -regexp: `text' is a regular expression - -word: `text' must match to full words - -: levels to check (default is all; /help levels for details) - : text to search for, or all if empty - : maximum number of lines to show - : skip the last `start' lines + -: Doesn't print the "Lastlog:" and "End of Lastlog" messages. + -file: Output the lastlog to a file instead of the active window. + -window: Specifies the window to check. + -new: Only displays results since the previous lastlog. + -away: Only displays results since you previous away status. + -level: Specifies the levels to check. + -clear: Removes the previous results from the active window. + -count: Displays how many lines match. + -case: Performs a case-sensitive matching. + -regexp: The given text pattern is a regular expression. + -word: The text must match full words. + -force: Forces to display the lastlog, even if it exceeds 1000 lines. + -after: Only displays results after the given line number. + -before: Only displays results before the given line number. -Shows the given number of lines of log from the current window. + The pattern to search for and the maximum of lines to display; if no + parameter is given, the entire window buffer will be displayed. -See also: +%9Description:%9 + + Searches the active window for a pattern and displays the result. + +%9Examples:%9 + + /LASTLOG holiday + /LASTLOG "is on vacation" + /LASTLOG -file -force ~/mike.log "mike" + +%9See also:%9 HILIGHT, SCROLLBACK diff --git a/docs/help/in/layout.in b/docs/help/in/layout.in index d5e81438..041549d1 100644 --- a/docs/help/in/layout.in +++ b/docs/help/in/layout.in @@ -1,13 +1,28 @@ +%9Syntax:%9 + @SYNTAX:layout@ -Saves the current window layout to configuration (yes, you'll still -need to use /SAVE to save the configuration to file). Next time you run -irssi, all the channels and queries are exactly in the same windows -where they were when you called /LAYOUT SAVE. +%9Parameters:%9 -Channels aren't actually joined in those windows immediately, they're -just marked "next time you join to '#channel' in server that has tag -'ircnet' place it to this window". + SAVE: Saves your layout to the configuration. + RESET: Removes the saved layout from the configuration. + +%9Descripton:%9 + + Saves the layout of your window configuration; the next time you connect + to the server, you will join the channels in the same window as before. + + This method enables you to keep the same window layout when you start Irssi + the next time. + + You will need to use the SAVE command to confirm and commit the changes + into the configuration file. + +%9Examples:%9 + + /LAYOUT SAVE + /LAYOUT RESET + +%9See also:%9 SAVE, WINDOW -/LAYOUT RESET removes the saved layout. diff --git a/docs/help/in/levels.in b/docs/help/in/levels.in index b6ebed7e..c44a551a 100644 --- a/docs/help/in/levels.in +++ b/docs/help/in/levels.in @@ -1,35 +1,40 @@ -Message levels (or in short, levels) are used almost everywhere. -They describe what kind of messages we're dealing with. Here's a -list of them all: - CRAP - Can be almost anything - MSGS - Private messages - PUBLIC - Public messages in channel - NOTICES - Notices - SNOTES - Server notices - CTCPS - CTCP messages - ACTIONS - Actions (/me) - usually ORed with PUBLIC or MSGS - JOINS - Someone joins a channel - PARTS - Someone parts a channel - QUITS - Someone quits IRC - KICKS - Someone gets kicked from channel - MODES - Channel mode is changed - TOPICS - Channel topic is changed - WALLOPS - Wallop is received - INVITES - Invite is received - NICKS - Someone changes nick - DCC - DCC related messages - DCCMSGS - DCC chat messages - CLIENTNOTICE - Irssi's notices - CLIENTERROR - Irssi's error messages - CLIENTCRAP - Some other messages from Irssi +%9Description:%9 -And a few special ones that could be included with the -levels above: + These are the message levels that are used throughout Irssi; they describe + what kind of message is displayed. - HILIGHT - Text is highlighted - NOHILIGHT - Don't check highlighting for this message - NO_ACT - Don't trigger channel activity when printing - this message - NEVER - Never ignore or log this message + These are the common levels you can use: + + ACTIONS Actions by a nickname. + CLIENTCRAP Irssi's internal messages. + CLIENTERROR Irssi's internal error messages. + CLIENTNOTICE Irssi's internal notices. + CRAP Can be almost anything. + CTCPS CTCP messages. + DCC DCC protocol related messages. + DCCMSGS DCC chat messages. + INVITES An invite is received. + JOINS A nickname joins a channel. + KICKS A nickname gets kicked from a channel. + MODES A channel mode is modified. + MSGS Private messages. + NICKS A nickname changes to another nickname. + NOTICES Notices sent from a nickname. + PARTS A nickname leaves a channel. + PUBLIC Public messages in a channel. + QUITS A nickname disconnects from IRC. + SNOTES Notices sent from a server. + TOPICS A channel topic is modified. + WALLOPS A wallop is received. + + These are the special levels you can use: + + HILIGHT The text is highlighted. + NEVER Never ignores or logs the message. + NO_ACT Doesn't trigger any activity in the statusbar. + NOHILIGHT The text is not highlighted. + + When using levels from Irssi scripts, you need to prepend the level with + "MSGLEVEL_"; for example "CRAP" will be "MSGLEVEL_CRAP". diff --git a/docs/help/in/links.in b/docs/help/in/links.in index 95ee07c5..a2aaa689 100644 --- a/docs/help/in/links.in +++ b/docs/help/in/links.in @@ -1,9 +1,22 @@ +%9Syntax:%9 + @SYNTAX:links@ -Shows the links between the IRC servers of the -current IRC network. If a wildcard parameter is -specified, shows only the matching entries. +%9Parameters:%9 -See also: MAP + The server to search on and the string to match on; if no arguments are + given, the list of links of the active server will be displayed. + +%9Description:%9 + + Displays the links between an IRC server and its connections. + +%9Examples:%9 + + /LINKS + /LINKS ircsource.irssi.org + /LINKS ircsource.irssi.org *.hub + +%9See also:%9 LUSERS, MAP diff --git a/docs/help/in/list.in b/docs/help/in/list.in index a1f697e7..cbce105e 100644 --- a/docs/help/in/list.in +++ b/docs/help/in/list.in @@ -1,16 +1,25 @@ +%9Syntax:%9 + @SYNTAX:list@ -Lists the channel names. Trying to list all the channel -names usually causes you to be disconnected from the -server with the reason "Excess flood", as usually all -40000 channels form together and server naively attempts -to send you them. +%9Parameters:%9 -Thus, on IRCNet, you should rather use service ALIS -(Advanced Listing Service), which will allow you to query -for channel with specific name, topic, mode or usercount. -Type /SQUERY ALIS HELP to get more info about it. + -yes: Comfirms that you want to receive a large amount of data. + + The text a channel must match; if no argument is given, the list of all + channels will be displayed. + +%9Description:%9 + + Displays the channel names that match your request; requesting all channels + may cause the server to disconnect you for flooding. + +%9Examples:%9 + + /LIST + /LIST -yes + /LIST -yes *ubuntu* See also: SQUERY diff --git a/docs/help/in/load.in b/docs/help/in/load.in index 867654c7..643d09d3 100644 --- a/docs/help/in/load.in +++ b/docs/help/in/load.in @@ -1,16 +1,23 @@ +%9Syntax:%9 + @SYNTAX:load@ -Load a plugin. If full path isn't given, irssi searches the plugin from -directories: +%9Parameters%9 - ~/.irssi/modules/ - /lib/irssi/modules/ + The name of the module and submodule to load. -See plugins page of http://www.irssi.org/ to see if there's any plugins -you'd want to use. +%9Description:%9 -To load a perl script you should use /SCRIPT. + Loads a plugin; if the full path isn't given, it will attempt to load from + common directories in your installation path. -See also: UNLOAD + To load a perl script, you must use the SCRIPT command. + +%9Examples:%9 + + /LOAD fish + /LOAD ~/irssi-fish/libfish.so + +%9See also:%9 SCRIPT, UNLOAD diff --git a/docs/help/in/log.in b/docs/help/in/log.in index 09580793..647d4560 100644 --- a/docs/help/in/log.in +++ b/docs/help/in/log.in @@ -1,41 +1,48 @@ +%9Syntax:%9 + @SYNTAX:log@ - -noopen: Create the entry to log list, but don't start logging - -autoopen: Automatically open this log file at startup - -: Targets are logged only in this server - -targets: Log only in specified channels/nicks (space separated list) - -window: Log output in the window. Active window is used by default, or - you can give the window's refnum in -targets. - : File name where to log, it is parsed with - strftime(), so %%d=day, etc. see "man strftime" for - more info. - : Defaults to ALL - : ID number of log. +%9Parameters:%9 -/SET log_create_mode - Specifies what file mode to use with - the created log files. Default is 0600. + OPEN: Opens a logfile. + CLOSE: Closes a logfile. + START: Starts logging a log entry. + STOP: Stops logging a log entry. -All of these are parsed with strftime(): -/SET log_timestamp - Specifies the time stamp format. - Default is "%%H:%%M ". -/SET log_open_string - Text written to log when it's opened -/SET log_close_string - Text written to log when it's closed -/SET log_day_changed - Text written to log when day changes + -noopen: Saves the entry in the configuration, but doesn't actually + start logging. + -autoopen: Automatically opens the log at startup. + -window: Displays the output to the active window, or the window + specified in the targets parameter. + -: The server tag the targets must be on. + -targets: Logs the specified nickhames or channels. + -colors: Also log the color codes of the messages. -NOTE: Log files are locked after opened, so two Irssis can't -accidentally try to write to the same log file. + The filename of the log and the levels to match; if no argument is given, + the list of open logs will be displayed. -Examples: - -/LOG OPEN -targets cras ~/irclogs/cras.log MSGS - - Logs all messages from/to nick `cras' +%9Description:%9 -/LOG OPEN -targets #linux ~/irclogs/linux/linux-%%Y-%%m-%%d - - Logs all messages in channel #linux. Log is rotated daily, so - logs in 1. May 2000 goes to file "linux-2000-05-01", when the - day is changed, Irssi closes the log and starts logging to - "linux-2000-05-02" etc. + Opens a logfile and stores the messages of the given targets into it; the + logfiles will be locked so multiple clients cannot log to the same file. -See also: SET LOG, WINDOW LOG + You may use any of the date formats to create a logrotation; we strongly + recommend you to enable autolog if you are interested in keeping logs. + +%9Examples:%9 + + /LOG OPEN -targets mike ~/irclogs/mike.log MSGS + /LOG OPEN -targets #irssi-freenode ~/irclogs/freenode/irssi-%%Y-%%m-%%d + /LOG CLOSE ~/irclogs/freenode/irssi-%%Y-%%m-%%d + /LOG STOP ~/irclogs/freenode/irssi-%%Y-%%m-%%d + /LOG START ~/irclogs/freenode/irssi-%%Y-%%m-%%d + + /SET autolog ON + +%9References:%9 + + https://github.com/irssi/irssi/blob/master/docs/formats.txt + +%9See also:%9 SET LOG, WINDOW LOG diff --git a/docs/help/in/lusers.in b/docs/help/in/lusers.in index abcd55c4..f9edf535 100644 --- a/docs/help/in/lusers.in +++ b/docs/help/in/lusers.in @@ -1,5 +1,24 @@ +%9Syntax:%9 + @SYNTAX:lusers@ -Shows user statistics of the current IRC network. +%9Parameters:%9 + + The server to search on and the remote sever to search on; if no arguments + are given, the active server will be used. + +%9Description:%9 + + Displays the user statistics of the active or remote server. + + The parameters to search on a remote server are no longer supported on most + IRC servers; we no longer provide examples for remote LUSERS to avoid all + confusion. + +%9Examples:%9 + + /LUSERS + +%9See also:%9 LINKS, MAP diff --git a/docs/help/in/network.in b/docs/help/in/network.in index d1879b5c..b07b996e 100644 --- a/docs/help/in/network.in +++ b/docs/help/in/network.in @@ -1,22 +1,59 @@ +%9Syntax:%9 + @SYNTAX:network@ - -kicks: Maximum number of nicks in one /KICK command - -msgs: Maximum number of nicks in one /MSG command - -modes: Maximum number of mode changes in one /MODE command - -whois: Maximum number of nicks in one /WHOIS command - -cmdspeed: Same as /SET cmd_queue_speed, see section 3.1 - -cmdmax: Same as /SET cmds_max_at_once, see section 3.1 - -nick, -user, -realname: Specify what nick/user/name to use - -host: Specify what host name to use, if you have multiple - -usermode: Specify what usermode to use on this network - -autosendcmd: Command to send after connecting to a server - -With -autosendcmd argument you can automatically run any commands -after connecting to network. This is useful for automatically -identifying yourself to NickServ, for example +%9Parameters:%9 -Shows and changes the settings of defined IRC networks. + LIST: Displays the list of configured networks. + ADD: Adds a network to your configuration. + REMOVE: Removes a network from your configuration. -See also: CONNECT + -nick: Specifies the nickname to use. + -user: Specifies the user identity to use. + -realname: Specifies the real name to use. + -host: Specifies the hostname to use. + -usermode: Specifies the user modes to set on yourself. + -autosendcmd: Specifies the commands, separated by the ";" character, + and enclosed within two '"' characters, to perform after + connecting. + -querychans: Specifies the maximum number of channels to put in one MODE + or WHO command when synchronizing. + -whois: Specifies the maximum number of nicknames in one WHOIS + command. + -msgs: Specifies the maximum number of nicknames in one PRIVMSG + command. + -kicks: Specifies the maximum number of nicknames in one KICK + command. + -modes: Specifies the maximum number of nicknames in one MODE + command. + -cmdspeed: Specifies the minimum amount of time, expressed in + milliseconds, that the client must wait before sending + additional commands to the server. + -cmxmax: Specifies the maximum number of commands to perform before + starting the internal flood protection. + + The name of the network to add, edit or remove; if no parameter is given, + the list of networks will be displayed. + +%9Description:%9 + + Displays, adds, modifies or removes the network configuration of IRC + networks. + + When using the ADD parameter on a network that already exists, the + configuration will be merged with each other. + + We recommend using "WAIT 2000" between the automated commands in order to + prevent you from being kicked from the network due to flooding commands. + +%9Examples:%9 + + /NETWORK ADD -usermode +giw EFnet + /NETWORK ADD -usermode +iw -nick mike -realname "The one and only mike!" -host staff.irssi.org Freenode + /NETWORK ADD -autosendcmd "^MSG NickServ identify WzerT8zq" Freenode + /NETWORK ADD -autosendcmd "^MSG Q@CServe.quakenet.org AUTH mike WzerT8zq; WAIT 2000; OPER mike WzerT8zq; WAIT 2000; MODE mike +kXP" Quakenet + /NETWORK REMOVE Freenode + +%9See also:%9 CHANNEL, CONNECT, SERVER diff --git a/docs/help/in/server.in b/docs/help/in/server.in index 5f2909ce..9cd7c8bd 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -1,44 +1,69 @@ +%9Syntax:%9 + @SYNTAX:server@ - -4, -6: specify explicitly whether to use IPv4 or IPv6 address - -ssl: use SSL when connecting - -ssl_cert: The SSL client certificate file (implies -ssl) - -ssl_pkey: The SSL client private key (if not included in the certificate file) - -ssl_pass: The password for the SSL client private key or certificate. - -ssl_verify: Verify servers SSL certificate - -ssl_cafile: File with list of CA certificates (implies -ssl_verify) - -ssl_capath: Directory with CA certificates (implies -ssl_verify) - -noproxy: Ignore the global proxy configuration for this server - -auto: Automatically connect to server at startup - -noauto: Don't connect to server at startup (default) - -network: Specify what IRC network this server belongs to - -ircnet: Same as -network. Deprecated. Do not use - -host: Specify what host name to use, if you have multiple - -!: don't autojoin channels - -noautosendcmd: don't execute autosendcmd - -cmdspeed: Same as /SET cmd_queue_speed, see section 3.1 - -cmdmax: Same as /SET cmds_max_at_once, see section 3.1 - -port: Use this only to edit the port number of an existing server, - for new servers use the argument +%9Parameters:%9 -/SERVER disconnects the server in active window and connects -to the new one. It will take the same arguments as /CONNECT. -If you prefix the address with the + character, Irssi won't -disconnect the active server, and it will create a new window -where the server is connected (ie. /window new hide; -/connect address) + LIST: Displays the list of servers you are connected to. + CONNECT: Connects to the given server. + ADD: Adds a server to your configuration. + REMOVE: Removes a server from your configuration. + PURGE: Purges the commands queued to be sent to the server. -/SERVER without any arguments displays the list of connected - servers. + -!: Doesn't autojoin the channels. + -4: Connects using IPv4. + -6: Connects using IPv6. + -ssl: Connects using SSL encryption. + -ssl_cert: The SSL client certificate file. + -ssl_pkey: The SSL client private key, if not included in the + certificate file. + -ssl_pass: Verifies the SSL certificate of the server. + -ssl_verify: Verifies the SSL certificate of the server. + -ssl_cafile: The file with the list of CA certificates. + -ssl_capath: The directory which contains the CA certificates. + -auto: Automatically connects to the server on startup. + -noauto: Doesn't connect to the server on startup. + -network: The network the server belongs to. + -host: The hostname you would like to connect from. + -cmdspeed: Specifies the minimum amount of time, expressed in + milliseconds, that the client must wait before sending + additional commands to the server. + -cmxmax: Specifies the maximum number of commands to perform + before starting the internal flood protection. + -port: Specifies the port to connect to the server. + -noproxy: Ignores the global proxy configuration. + -rawlog: Immediately open rawlog after connecting. + -noautosendcmd: Doesn't execute autosendcmd. -/SERVER REMOVE
[] [] + The server, port and network to add, modify or remove; if no argument is + given, the list of servers you are connected to will be returned. -/SERVER LIST +%9Description:%9 -/SERVER PURGE [] + Displays, adds, modifies or removes the network configuration of IRC + servers. + + When using the ADD parameter on a server that already exists, the + configuration will be merged with each other. + + When using the command without any of the given parameters, it will + connect to the specified server; the server in the active window will be + disconnected unless you prepend the server with the "+" character; the same + method is applicable to the CONNECT parameter. -Clears the server send queue. Useful if, for example, you accidentally paste lots of text to a channel. +%9Examples:%9 -See also: CONNECT, DISCONNECT, RECONNECT, RMRECONNS + /SERVER + /SERVER chat.freenode.net + /SERVER +chat.freenode.net + /SERVER CONNECT chat.freenode.net + /SERVER CONNECT +chat.freenode.net + /SERVER ADD -network Freenode -noautosendcmd orwell.freenode.net + /SERVER ADD -! -auto -host staff.irssi.org -port 6667 -4 -network Freenode -noproxy orwell.freenode.net + /SERVER REMOVE -network Freenode orwell.freenode.net + /SERVER PURGE + /SERVER PURGE orwell.freenode.net + +%9See also:%9 CHANNEL, CONNECT, DISCONNECT, NETWORK, RECONNECT, RMRECONNS diff --git a/docs/help/in/uptime.in b/docs/help/in/uptime.in new file mode 100644 index 00000000..7a2924e2 --- /dev/null +++ b/docs/help/in/uptime.in @@ -0,0 +1,15 @@ + +%9Syntax:%9 + +@SYNTAX:uptime@ + +%9Description:%9 + + Displays how long Irssi has been running. + +%9Examples:%9 + + /UPTIME + +%9See also:%9 CONNECT, EXIT + diff --git a/docs/manual.txt b/docs/manual.txt index 43d77550..b2d0de14 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -349,7 +349,7 @@ after connecting to the network. This is useful for automatically identifying yourself to NickServ, for example - /NETWORK ADD -autosendcmd "/msg NickServ identify secret" freenode + /NETWORK ADD -autosendcmd "/^msg NickServ identify secret" freenode /NETWORK REMOVE diff --git a/irssi.conf b/irssi.conf index a92cdaff..27a70d1e 100644 --- a/irssi.conf +++ b/irssi.conf @@ -1,252 +1,358 @@ servers = ( - { address = "eu.irc6.net"; chatnet = "IRCnet"; port = "6667"; }, - { address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; }, - { address = "chat.freenode.net"; chatnet = "Freenode"; port = "6667"; }, - { address = "irc.efnet.org"; chatnet = "EFNet"; port = "6667"; }, - { address = "irc.undernet.org"; chatnet = "Undernet"; port = "6667"; }, - { address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; }, - { address = "irc.quakenet.org"; chatnet = "QuakeNet"; port = "6667"; }, - { address = "irc.oftc.net"; chatnet = "OFTC"; port = "6667"; }, + { address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; }, + { address = "irc.efnet.org"; chatnet = "EFNet"; port = "6667"; }, + { address = "irc.esper.net"; chatnet = "EsperNet"; port = "6667"; }, + { address = "chat.freenode.net"; chatnet = "Freenode"; port = "6667"; }, { address = "irc.gamesurge.net"; chatnet = "GameSurge"; port = "6667"; }, - { address = "irc.webchat.org"; chatnet = "WebChat"; port = "6667"; }, - { address = "irc.rizon.net"; chatnet = "Rizon"; port = "6667"; }, - { address = "irc.link-net.org"; chatnet = "LinkNet"; port = "6667"; }, - { address = "silc.silcnet.org"; chatnet = "SILC"; port = "706"; } + { address = "eu.irc6.net"; chatnet = "IRCnet"; port = "6667"; }, + { address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; }, + { address = "irc.ircsource.net"; chatnet = "IRCSource"; port = "6667"; }, + { address = "irc.netfuze.net"; chatnet = "NetFuze"; port = "6667"; }, + { address = "irc.oftc.net"; chatnet = "OFTC"; port = "6667"; }, + { address = "irc.quakenet.org"; chatnet = "QuakeNet"; port = "6667"; }, + { address = "irc.rizon.net"; chatnet = "Rizon"; port = "6667"; }, + { address = "silc.silcnet.org"; chatnet = "SILC"; port = "706"; }, + { address = "irc.undernet.org"; chatnet = "Undernet"; port = "6667"; } ); chatnets = { - IRCnet = { - type = "IRC"; + DALnet = { + type = "IRC"; max_kicks = "4"; - max_msgs = "5"; - max_whois = "4"; - max_query_chans = "5"; - }; + max_msgs = "20"; + max_whois = "30"; + }; EFNet = { - type = "IRC"; - max_kicks = "4"; - max_msgs = "3"; + type = "IRC"; + max_kicks = "1"; + max_msgs = "4"; + max_whois = "1"; + }; + EsperNet = { + type = "IRC"; + max_kicks = "1"; + max_msgs = "4"; max_whois = "1"; }; Freenode = { - type = "IRC"; + type = "IRC"; max_kicks = "1"; - max_msgs = "4"; + max_msgs = "4"; max_whois = "1"; }; - Undernet = { - type = "IRC"; + GameSurge = { + type = "IRC"; max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; + max_msgs = "1"; + max_whois = "1"; }; - DALnet = { - type = "IRC"; - max_kicks = "4"; - max_msgs = "3"; - max_whois = "30"; - }; - QuakeNet = { - type = "IRC"; + IRCnet = { + type = "IRC"; max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; + max_msgs = "1"; + max_whois = "1"; + }; + IRCSource = { + type = "IRC"; + max_kicks = "1"; + max_msgs = "4"; + max_whois = "1"; + }; + NetFuze = { + type = "IRC"; + max_kicks = "1"; + max_msgs = "1"; + max_whois = "1"; }; OFTC = { - type = "IRC"; + type = "IRC"; max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; + max_msgs = "1"; + max_whois = "1"; }; - GameSurge = { - type = "IRC"; + QuakeNet = { + type = "IRC"; max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; - }; - WebChat = { - type = "IRC"; - max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; + max_msgs = "1"; + max_whois = "1"; }; Rizon = { - type = "IRC"; + type = "IRC"; max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; + max_msgs = "1"; + max_whois = "1"; }; - LinkNet = { - type = "IRC"; + SILC = { + type = "SILC"; + }; + Undernet = { + type = "IRC"; max_kicks = "1"; - max_msgs = "3"; - max_whois = "30"; + max_msgs = "1"; + max_whois = "1"; }; - SILC = { type = "SILC"; }; }; channels = ( - { name = "#irssi"; chatnet = "ircnet"; autojoin = "No"; }, - { name = "silc"; chatnet = "silc"; autojoin = "No"; } + { name = "#lobby"; chatnet = "EsperNet"; autojoin = "Yes"; }, + { name = "#freenode"; chatnet = "Freenode"; autojoin = "Yes"; }, + { name = "#irssi"; chatnet = "Freenode"; autojoin = "No"; }, + { name = "#gamesurge"; chatnet = "GameSurge"; autojoin = "Yes"; }, + { name = "#irssi"; chatnet = "IRCNet"; autojoin = "No"; }, + { name = "#ircsource"; chatnet = "IRCSource"; autojoin = "Yes"; }, + { name = "#netfuze"; chatnet = "NetFuze"; autojoin = "Yes"; }, + { name = "#oftc"; chatnet = "OFTC"; autojoin = "Yes"; }, + { name = "silc"; chatnet = "SILC"; autojoin = "No"; } ); aliases = { - J = "join"; - WJOIN = "join -window"; - WQUERY = "query -window"; - LEAVE = "part"; - BYE = "quit"; - EXIT = "quit"; - SIGNOFF = "quit"; - DESCRIBE = "action"; - DATE = "time"; - HOST = "userhost"; - LAST = "lastlog"; - SAY = "msg *"; - WI = "whois"; - WII = "whois $0 $0"; - WW = "whowas"; - W = "who"; - N = "names"; - M = "msg"; - T = "topic"; - C = "clear"; - CL = "clear"; - K = "kick"; - KB = "kickban"; - KN = "knockout"; - BANS = "ban"; - B = "ban"; - MUB = "unban *"; - UB = "unban"; - IG = "ignore"; - UNIG = "unignore"; - SB = "scrollback"; - UMODE = "mode $N"; - WC = "window close"; - WN = "window new hide"; - SV = "say Irssi $J ($V) - http://irssi.org/"; - GOTO = "sb goto"; - CHAT = "dcc chat"; - RUN = "SCRIPT LOAD"; - CALC = "exec - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi"; - SBAR = "STATUSBAR"; - INVITELIST = "mode $C +I"; - Q = "QUERY"; - "MANUAL-WINDOWS" = "set use_status_window off;set autocreate_windows off;set autocreate_query_level none;set autoclose_windows off;set reuse_unused_windows on;save"; - EXEMPTLIST = "mode $C +e"; - ATAG = "WINDOW SERVER"; - UNSET = "set -clear"; - RESET = "set -default"; + ATAG = "WINDOW SERVER"; + ADDALLCHANS = "SCRIPT EXEC foreach my \\$channel (Irssi::channels()) { Irssi::command(\"CHANNEL ADD -auto \\$channel->{name} \\$channel->{server}->{tag} \\$channel->{key}\")\\;}"; + B = "BAN"; + BACK = "AWAY"; + BANS = "BAN"; + BYE = "QUIT"; + C = "CLEAR"; + CALC = "EXEC - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi"; + CHAT = "DCC CHAT"; + CUBES = "SCRIPT EXEC Irssi::active_win->print(\"%_bases\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { join '', map { \"%x0\\${_}0\\$_\" } '0'..'9','A'..'F' }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print(\"%_cubes\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { my \\$y = \\$_*6 \\; join '', map { my \\$x = \\$_ \\; map { \"%x\\$x\\$_\\$x\\$_\" } @{['0'..'9','A'..'Z']}[\\$y .. \\$y+5] } 1..6 }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) for 0..5 \\; Irssi::active_win->print(\"%_grays\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { join '', map { \"%x7\\${_}7\\$_\" } 'A'..'X' }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print(\"%_mIRC extended colours\", MSGLEVEL_CLIENTCRAP) \\; my \\$x \\; \\$x .= sprintf \"\00399,%02d%02d\",\\$_,\\$_ for 0..15 \\; Irssi::active_win->print(\\$x, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; for my \\$z (0..6) { my \\$x \\; \\$x .= sprintf \"\00399,%02d%02d\",\\$_,\\$_ for 16+(\\$z*12)..16+(\\$z*12)+11 \\; Irssi::active_win->print(\\$x, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) }"; + DATE = "TIME"; + DEHIGHLIGHT = "DEHILIGHT"; + DESCRIBE = "ACTION"; + DHL = "DEHILIGHT"; + EXEMPTLIST = "MODE $C +e"; + EXIT = "QUIT"; + GOTO = "SCROLLBACK GOTO"; + HIGHLIGHT = "HILIGHT"; + HL = "HILIGHT"; + HOST = "USERHOST"; + INVITELIST = "MODE $C +I"; + J = "JOIN"; + K = "KICK"; + KB = "KICKBAN"; + KN = "KNOCKOUT"; + LAST = "LASTLOG"; + LEAVE = "PART"; + M = "MSG"; + MUB = "UNBAN *"; + N = "NAMES"; + NMSG = "^MSG"; + P = "PART"; + Q = "QUERY"; + RESET = "SET -default"; + RUN = "SCRIPT LOAD"; + SAY = "MSG *"; + SB = "SCROLLBACK"; + SBAR = "STATUSBAR"; + SIGNOFF = "QUIT"; + SV = "MSG * Irssi $J ($V) - http://www.irssi.org"; + T = "TOPIC"; + UB = "UNBAN"; + UMODE = "MODE $N"; + UNSET = "SET -clear"; + W = "WHO"; + WC = "WINDOW CLOSE"; + WG = "WINDOW GOTO"; + WJOIN = "JOIN -window"; + WI = "WHOIS"; + WII = "WHOIS $0 $0"; + WL = "WINDOW LIST"; + WN = "WINDOW NEW HIDDEN"; + WQUERY = "QUERY -window"; + WW = "WHOWAS"; + 1 = "WINDOW GOTO 1"; + 2 = "WINDOW GOTO 2"; + 3 = "WINDOW GOTO 3"; + 4 = "WINDOW GOTO 4"; + 5 = "WINDOW GOTO 5"; + 6 = "WINDOW GOTO 6"; + 7 = "WINDOW GOTO 7"; + 8 = "WINDOW GOTO 8"; + 9 = "WINDOW GOTO 9"; + 10 = "WINDOW GOTO 10"; + 11 = "WINDOW GOTO 11"; + 12 = "WINDOW GOTO 12"; + 13 = "WINDOW GOTO 13"; + 14 = "WINDOW GOTO 14"; + 15 = "WINDOW GOTO 15"; + 16 = "WINDOW GOTO 16"; + 17 = "WINDOW GOTO 17"; + 18 = "WINDOW GOTO 18"; + 19 = "WINDOW GOTO 19"; + 20 = "WINDOW GOTO 20"; + 21 = "WINDOW GOTO 21"; + 22 = "WINDOW GOTO 22"; + 23 = "WINDOW GOTO 23"; + 24 = "WINDOW GOTO 24"; + 25 = "WINDOW GOTO 25"; + 26 = "WINDOW GOTO 26"; + 27 = "WINDOW GOTO 27"; + 28 = "WINDOW GOTO 28"; + 29 = "WINDOW GOTO 29"; + 30 = "WINDOW GOTO 30"; + 31 = "WINDOW GOTO 31"; + 32 = "WINDOW GOTO 32"; + 33 = "WINDOW GOTO 33"; + 34 = "WINDOW GOTO 34"; + 35 = "WINDOW GOTO 35"; + 36 = "WINDOW GOTO 36"; + 37 = "WINDOW GOTO 37"; + 38 = "WINDOW GOTO 38"; + 39 = "WINDOW GOTO 39"; + 40 = "WINDOW GOTO 40"; + 41 = "WINDOW GOTO 41"; + 42 = "WINDOW GOTO 42"; + 43 = "WINDOW GOTO 43"; + 44 = "WINDOW GOTO 44"; + 45 = "WINDOW GOTO 45"; + 46 = "WINDOW GOTO 46"; + 47 = "WINDOW GOTO 47"; + 48 = "WINDOW GOTO 48"; + 49 = "WINDOW GOTO 49"; + 50 = "WINDOW GOTO 50"; + 51 = "WINDOW GOTO 51"; + 52 = "WINDOW GOTO 52"; + 53 = "WINDOW GOTO 53"; + 54 = "WINDOW GOTO 54"; + 55 = "WINDOW GOTO 55"; + 56 = "WINDOW GOTO 56"; + 57 = "WINDOW GOTO 57"; + 58 = "WINDOW GOTO 58"; + 59 = "WINDOW GOTO 59"; + 60 = "WINDOW GOTO 60"; + 61 = "WINDOW GOTO 61"; + 62 = "WINDOW GOTO 62"; + 63 = "WINDOW GOTO 63"; + 64 = "WINDOW GOTO 64"; + 65 = "WINDOW GOTO 65"; + 66 = "WINDOW GOTO 66"; + 67 = "WINDOW GOTO 67"; + 68 = "WINDOW GOTO 68"; + 69 = "WINDOW GOTO 69"; + 70 = "WINDOW GOTO 70"; + 71 = "WINDOW GOTO 71"; + 72 = "WINDOW GOTO 72"; + 73 = "WINDOW GOTO 73"; + 74 = "WINDOW GOTO 74"; + 75 = "WINDOW GOTO 75"; + 76 = "WINDOW GOTO 76"; + 77 = "WINDOW GOTO 77"; + 78 = "WINDOW GOTO 78"; + 79 = "WINDOW GOTO 79"; + 80 = "WINDOW GOTO 80"; + 81 = "WINDOW GOTO 81"; + 82 = "WINDOW GOTO 82"; + 83 = "WINDOW GOTO 83"; + 84 = "WINDOW GOTO 84"; + 85 = "WINDOW GOTO 85"; + 86 = "WINDOW GOTO 86"; + 87 = "WINDOW GOTO 87"; + 88 = "WINDOW GOTO 88"; + 89 = "WINDOW GOTO 89"; + 90 = "WINDOW GOTO 90"; + 91 = "WINDOW GOTO 91"; + 92 = "WINDOW GOTO 92"; + 93 = "WINDOW GOTO 93"; + 94 = "WINDOW GOTO 94"; + 95 = "WINDOW GOTO 95"; + 96 = "WINDOW GOTO 96"; + 97 = "WINDOW GOTO 97"; + 98 = "WINDOW GOTO 98"; + 99 = "WINDOW GOTO 99"; }; statusbar = { - # formats: - # when using {templates}, the template is shown only if it's argument isn't - # empty unless no argument is given. for example {sb} is printed always, - # but {sb $T} is printed only if $T isn't empty. items = { - # start/end text in statusbars + barstart = "{sbstart}"; - barend = "{sbend}"; + barend = "{sbend}"; topicbarstart = "{topicsbstart}"; - topicbarend = "{topicsbend}"; + topicbarend = "{topicsbend}"; - # treated "normally", you could change the time/user name to whatever time = "{sb $Z}"; user = "{sb {sbnickmode $cumode}$N{sbmode $usermode}{sbaway $A}}"; - # treated specially .. window is printed with non-empty windows, - # window_empty is printed with empty windows - window = "{sb $winref:$tag/$itemname{sbmode $M}}"; + window = "{sb $winref:$tag/$itemname{sbmode $M}}"; window_empty = "{sb $winref{sbservertag $tag}}"; - prompt = "{prompt $[.15]itemname}"; + + prompt = "{prompt $[.15]itemname}"; prompt_empty = "{prompt $winname}"; - topic = " $topic"; + + topic = " $topic"; topic_empty = " Irssi v$J - http://www.irssi.org"; - # all of these treated specially, they're only displayed when needed - lag = "{sb Lag: $0-}"; - act = "{sb Act: $0-}"; + lag = "{sb Lag: $0-}"; + act = "{sb Act: $0-}"; more = "-- more --"; }; - # there's two type of statusbars. root statusbars are either at the top - # of the screen or at the bottom of the screen. window statusbars are at - # the top/bottom of each split window in screen. default = { - # the "default statusbar" to be displayed at the bottom of the window. - # contains all the normal items. + window = { - disabled = "no"; - # window, root - type = "window"; - # top, bottom + disabled = "no"; + type = "window"; placement = "bottom"; - # number - position = "1"; - # active, inactive, always - visible = "active"; + position = "1"; + visible = "active"; - # list of items in statusbar in the display order items = { - barstart = { priority = "100"; }; - time = { }; - user = { }; - window = { }; + barstart = { priority = "100"; }; + time = { }; + user = { }; + window = { }; window_empty = { }; - lag = { priority = "-1"; }; - act = { priority = "10"; }; - more = { priority = "-1"; alignment = "right"; }; - barend = { priority = "100"; alignment = "right"; }; + lag = { priority = "-1"; }; + act = { priority = "10"; }; + more = { priority = "-1"; alignment = "right"; }; + barend = { priority = "100"; alignment = "right"; }; }; }; - # statusbar to use in inactive split windows window_inact = { - type = "window"; + + type = "window"; placement = "bottom"; - position = "1"; - visible = "inactive"; + position = "1"; + visible = "inactive"; + items = { - barstart = { priority = "100"; }; - window = { }; + barstart = { priority = "100"; }; + window = { }; window_empty = { }; - more = { priority = "-1"; alignment = "right"; }; - barend = { priority = "100"; alignment = "right"; }; + more = { priority = "-1"; alignment = "right"; }; + barend = { priority = "100"; alignment = "right"; }; }; }; - # we treat input line as yet another statusbar :) It's possible to - # add other items before or after the input line item. prompt = { - type = "root"; + + type = "root"; placement = "bottom"; - # we want to be at the bottom always - position = "100"; - visible = "always"; + position = "100"; + visible = "always"; + items = { - prompt = { priority = "-1"; }; + prompt = { priority = "-1"; }; prompt_empty = { priority = "-1"; }; - # treated specially, this is the real input line. - input = { priority = "10"; }; + input = { priority = "10"; }; }; }; - # topicbar topic = { - type = "root"; + + type = "root"; placement = "top"; - position = "1"; - visible = "always"; + position = "1"; + visible = "always"; + items = { topicbarstart = { priority = "100"; }; - topic = { }; - topic_empty = { }; - topicbarend = { priority = "100"; alignment = "right"; }; + topic = { }; + topic_empty = { }; + topicbarend = { priority = "100"; alignment = "right"; }; }; }; }; diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 535bf9f8..235a9fc4 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -378,12 +378,35 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) } } if (target != NULL) { - signal_emit("server sendmsg", 4, server, target, msg, - GINT_TO_POINTER(target_type)); + char **splitmsgs; + char **tmp = NULL; + char *singlemsg[] = { msg, NULL }; + char *m; + int n = 0; + + /* + * If split_message is NULL, the server doesn't need to split + * long messages. + */ + if (server->split_message != NULL) + splitmsgs = tmp = server->split_message(server, target, + msg); + else + splitmsgs = singlemsg; + + while ((m = splitmsgs[n++])) { + signal_emit("server sendmsg", 4, server, target, m, + GINT_TO_POINTER(target_type)); + signal_emit(target_type == SEND_TARGET_CHANNEL ? + "message own_public" : + "message own_private", 4, server, m, + target, origtarget); + } + g_strfreev(tmp); + } else { + signal_emit("message own_private", 4, server, msg, target, + origtarget); } - signal_emit(target != NULL && target_type == SEND_TARGET_CHANNEL ? - "message own_public" : "message own_private", 4, - server, msg, target, origtarget); if (free_ret && target != NULL) g_free(target); cmd_params_free(free_arg); diff --git a/src/core/commands.c b/src/core/commands.c index 547f7b16..ed82f44e 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -968,7 +968,9 @@ static void cmd_cd(const char *data) if (*data == '\0') return; str = convert_home(data); - chdir(str); + if (chdir(str) != 0) { + g_warning("Failed to chdir(): %s", strerror(errno)); + } g_free(str); } diff --git a/src/core/ignore.c b/src/core/ignore.c index a7aa106f..3c45967c 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -58,30 +58,6 @@ static int ignore_check_replies_rec(IGNORE_REC *rec, CHANNEL_REC *channel, return FALSE; } -#define ignore_match_channel(rec, channel) \ - ((rec)->channels == NULL || ((channel) != NULL && \ - strarray_find((rec)->channels, (channel)) != -1)) - -static int ignore_check_replies(CHANNEL_REC *chanrec, const char *text) -{ - GSList *tmp; - - if (text == NULL || chanrec == NULL) - return FALSE; - - /* check reply ignores */ - for (tmp = ignores; tmp != NULL; tmp = tmp->next) { - IGNORE_REC *rec = tmp->data; - - if (rec->mask != NULL && rec->replies && - ignore_match_channel(rec, chanrec->name) && - ignore_check_replies_rec(rec, chanrec, text)) - return TRUE; - } - - return FALSE; -} - static int ignore_match_pattern(IGNORE_REC *rec, const char *text) { if (rec->pattern == NULL) @@ -104,8 +80,15 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) stristr(text, rec->pattern) != NULL; } +/* MSGLEVEL_NO_ACT is special in ignores, when provided to ignore_check() it's + * used as a flag to indicate it should only look at ignore items with NO_ACT. + * However we also want to allow NO_ACT combined with levels, so mask it out and + * match levels if set. */ #define ignore_match_level(rec, level) \ - ((level & (rec)->level) != 0) + (((level & MSGLEVEL_NO_ACT) != 0) ? \ + ((~MSGLEVEL_NO_ACT & level) & (rec)->level) != 0 : \ + ((rec)->level & MSGLEVEL_NO_ACT ? 0 : \ + (level & (rec)->level) != 0)) #define ignore_match_nickmask(rec, nick, nickmask) \ ((rec)->mask == NULL || \ @@ -117,6 +100,31 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) ((rec)->servertag == NULL || \ g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0) +#define ignore_match_channel(rec, channel) \ + ((rec)->channels == NULL || ((channel) != NULL && \ + strarray_find((rec)->channels, (channel)) != -1)) + +static int ignore_check_replies(CHANNEL_REC *chanrec, const char *text, int level) +{ + GSList *tmp; + + if (text == NULL || chanrec == NULL) + return FALSE; + + /* check reply ignores */ + for (tmp = ignores; tmp != NULL; tmp = tmp->next) { + IGNORE_REC *rec = tmp->data; + + if (rec->mask != NULL && rec->replies && + ignore_match_level(rec, level) && + ignore_match_channel(rec, chanrec->name) && + ignore_check_replies_rec(rec, chanrec, text)) + return TRUE; + } + + return FALSE; +} + int ignore_check(SERVER_REC *server, const char *nick, const char *host, const char *channel, const char *text, int level) { @@ -176,11 +184,18 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, if (best_match || (level & MSGLEVEL_PUBLIC) == 0) return best_match; - return ignore_check_replies(chanrec, text); + return ignore_check_replies(chanrec, text, level); } IGNORE_REC *ignore_find(const char *servertag, const char *mask, - char **channels) + char **channels) +{ + return ignore_find_noact(servertag, mask, channels, 0); +} + + +IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, + char **channels, int noact) { GSList *tmp; char **chan; @@ -202,6 +217,12 @@ IGNORE_REC *ignore_find(const char *servertag, const char *mask, continue; } + if (noact && (rec->level & MSGLEVEL_NO_ACT) == 0) + continue; + + if (!noact && (rec->level & MSGLEVEL_NO_ACT) != 0) + continue; + if ((rec->mask == NULL && mask != NULL) || (rec->mask != NULL && mask == NULL)) continue; @@ -293,10 +314,24 @@ static void ignore_remove_config(IGNORE_REC *rec) static void ignore_init_rec(IGNORE_REC *rec) { #ifdef HAVE_REGEX_H + char *errbuf; + int errcode, errbuf_len; + 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; + rec->regexp_compiled = FALSE; + if (rec->regexp && rec->pattern != NULL) { + errcode = regcomp(&rec->preg, rec->pattern, + REG_EXTENDED|REG_ICASE|REG_NOSUB); + if (errcode != 0) { + errbuf_len = regerror(errcode, &rec->preg, 0, 0); + errbuf = g_malloc(errbuf_len); + regerror(errcode, &rec->preg, errbuf, errbuf_len); + g_warning("Failed to compile regexp '%s': %s", rec->pattern, errbuf); + g_free(errbuf); + } else { + rec->regexp_compiled = TRUE; + } + } #endif } diff --git a/src/core/ignore.h b/src/core/ignore.h index 4abfaca5..46025d4c 100644 --- a/src/core/ignore.h +++ b/src/core/ignore.h @@ -32,6 +32,7 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, const char *channel, const char *text, int level); IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels); +IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact); void ignore_add_rec(IGNORE_REC *rec); void ignore_update_rec(IGNORE_REC *rec); diff --git a/src/core/levels.c b/src/core/levels.c index b47079ba..7997ba98 100644 --- a/src/core/levels.c +++ b/src/core/levels.c @@ -136,19 +136,25 @@ char *bits2level(int bits) if (bits == 0) return g_strdup(""); - if (bits == MSGLEVEL_ALL) - return g_strdup("ALL"); str = g_string_new(NULL); - if (bits & MSGLEVEL_NEVER) + if (bits & MSGLEVEL_NEVER) { g_string_append(str, "NEVER "); + bits &= ~MSGLEVEL_NEVER; + } - if (bits & MSGLEVEL_NO_ACT) + if (bits & MSGLEVEL_NO_ACT) { g_string_append(str, "NO_ACT "); + bits &= ~MSGLEVEL_NO_ACT; + } - for (n = 0; levels[n] != NULL; n++) { - if (bits & (1L << n)) - g_string_append_printf(str, "%s ", levels[n]); + if (bits == MSGLEVEL_ALL) { + g_string_append(str, "ALL "); + } else { + for (n = 0; levels[n] != NULL; n++) { + if (bits & (1L << n)) + g_string_append_printf(str, "%s ", levels[n]); + } } if (str->len > 0) g_string_truncate(str, str->len-1); diff --git a/src/core/misc.c b/src/core/misc.c index 8d821ecc..5e6087cb 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -183,7 +183,7 @@ int strarray_find(char **array, const char *item) GSList *gslist_find_string(GSList *list, const char *key) { - for (list = list; list != NULL; list = list->next) + for (; list != NULL; list = list->next) if (strcmp(list->data, key) == 0) return list; return NULL; @@ -191,7 +191,7 @@ GSList *gslist_find_string(GSList *list, const char *key) GSList *gslist_find_icase_string(GSList *list, const char *key) { - for (list = list; list != NULL; list = list->next) + for (; list != NULL; list = list->next) if (g_ascii_strcasecmp(list->data, key) == 0) return list; return NULL; @@ -268,7 +268,7 @@ GSList *hashtable_get_keys(GHashTable *hash) GList *glist_find_string(GList *list, const char *key) { - for (list = list; list != NULL; list = list->next) + for (; list != NULL; list = list->next) if (strcmp(list->data, key) == 0) return list; return NULL; @@ -276,7 +276,7 @@ GList *glist_find_string(GList *list, const char *key) GList *glist_find_icase_string(GList *list, const char *key) { - for (list = list; list != NULL; list = list->next) + for (; list != NULL; list = list->next) if (g_ascii_strcasecmp(list->data, key) == 0) return list; return NULL; @@ -966,3 +966,21 @@ char *ascii_strdown(char *str) *s = g_ascii_tolower (*s); return str; } + +char **strsplit_len(const char *str, int len) +{ + char **ret; + size_t total_len = strlen(str); + int n = total_len / len; + int i; + + if (total_len % len) + n++; + + ret = g_new(char *, n + 1); + for (i = 0; i < n; i++, str += len) + ret[i] = g_strndup(str, len); + ret[n] = NULL; + + return ret; +} diff --git a/src/core/misc.h b/src/core/misc.h index 2cb8e66a..8fb5078f 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -115,4 +115,7 @@ uoff_t str_to_uofft(const char *str); /* find `item' from a space separated `list' */ int find_substr(const char *list, const char *item); +/* split `str' into `len' sized substrings */ +char **strsplit_len(const char *str, int len); + #endif diff --git a/src/core/network.c b/src/core/network.c index 7e55d472..3659ab36 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -60,7 +60,11 @@ GIOChannel *g_io_channel_new(int handle) IPADDR ip4_any = { AF_INET, - { { { INADDR_ANY } } } +#if defined(HAVE_IPV6) && defined(IN6ADDR_ANY_INIT) + IN6ADDR_ANY_INIT +#else + { INADDR_ANY } +#endif }; int net_ip_compare(IPADDR *ip1, IPADDR *ip2) diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 20368aeb..e66f20dd 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -102,10 +102,15 @@ void rawlog_redirect(RAWLOG_REC *rawlog, const char *str) static void rawlog_dump(RAWLOG_REC *rawlog, int f) { GSList *tmp; + ssize_t ret = 1; - for (tmp = rawlog->lines; tmp != NULL; tmp = tmp->next) { - write(f, tmp->data, strlen((char *) tmp->data)); - write(f, "\n", 1); + for (tmp = rawlog->lines; ret && tmp != NULL; tmp = tmp->next) { + ret = write(f, tmp->data, strlen((char *) tmp->data)); + ret &= write(f, "\n", 1); + } + + if (ret <= 0) { + g_warning("rawlog write() failed: %s", strerror(errno)); } } diff --git a/src/core/recode.c b/src/core/recode.c index ca69b73e..029d7ff1 100644 --- a/src/core/recode.c +++ b/src/core/recode.c @@ -182,6 +182,86 @@ char *recode_out(const SERVER_REC *server, const char *str, const char *target) return recoded; } +char **recode_split(const SERVER_REC *server, const char *str, + const char *target, int len) +{ + GIConv cd = (GIConv)-1; + const char *from = translit_charset; + const char *to = translit_charset; + char *translit_to = NULL; + const char *inbuf = str; + const char *previnbuf = inbuf; + char *tmp = NULL; + char *outbuf; + gsize inbytesleft = strlen(inbuf); + gsize outbytesleft = len; + int n = 0; + char **ret; + + g_return_val_if_fail(str != NULL, NULL); + + if (settings_get_bool("recode")) { + to = find_conversion(server, target); + if (to == NULL) + /* default outgoing charset if set */ + to = settings_get_str("recode_out_default_charset"); + if (to != NULL && *to != '\0') { + if (settings_get_bool("recode_transliterate") && + !is_translit(to)) + to = translit_to = g_strconcat(to, + "//TRANSLIT", + NULL); + } else { + to = from; + } + } + + cd = g_iconv_open(to, from); + if (cd == (GIConv)-1) { + /* Fall back to splitting by byte. */ + ret = strsplit_len(str, len); + goto out; + } + + tmp = g_malloc(outbytesleft); + outbuf = tmp; + ret = g_new(char *, 1); + while (g_iconv(cd, (char **)&inbuf, &inbytesleft, &outbuf, + &outbytesleft) == -1) { + if (errno != E2BIG) { + /* + * Conversion failed. Fall back to splitting + * by byte. + */ + ret[n] = NULL; + g_strfreev(ret); + ret = strsplit_len(str, len); + goto out; + } + + /* Outbuf overflowed, split the input string. */ + ret[n++] = g_strndup(previnbuf, inbuf - previnbuf); + ret = g_renew(char *, ret, n + 1); + previnbuf = inbuf; + + /* Reset outbuf for the next substring. */ + outbuf = tmp; + outbytesleft = len; + } + /* Copy the last substring into the array. */ + ret[n++] = g_strndup(previnbuf, inbuf - previnbuf); + ret = g_renew(char *, ret, n + 1); + ret[n] = NULL; + +out: + if (cd != (GIConv)-1) + g_iconv_close(cd); + g_free(translit_to); + g_free(tmp); + + return ret; +} + void recode_update_charset(void) { const char *charset = settings_get_str("term_charset"); diff --git a/src/core/recode.h b/src/core/recode.h index c8f867cf..b70ec630 100644 --- a/src/core/recode.h +++ b/src/core/recode.h @@ -3,6 +3,8 @@ char *recode_in (const SERVER_REC *server, const char *str, const char *target); char *recode_out (const SERVER_REC *server, const char *str, const char *target); +char **recode_split(const SERVER_REC *server, const char *str, + const char *target, int len); gboolean is_valid_charset(const char *charset); gboolean is_utf8(void); void recode_update_charset(void); diff --git a/src/core/server-rec.h b/src/core/server-rec.h index 726d1c14..69e990c6 100644 --- a/src/core/server-rec.h +++ b/src/core/server-rec.h @@ -61,6 +61,9 @@ const char *(*get_nick_flags)(SERVER_REC *server); /* send public or private message to server */ void (*send_message)(SERVER_REC *server, const char *target, const char *msg, int target_type); +/* split message in case it is too long for the server to receive */ +char **(*split_message)(SERVER_REC *server, const char *target, + const char *msg); /* -- Default implementations are used if NULL -- */ CHANNEL_REC *(*channel_find_func)(SERVER_REC *server, const char *name); diff --git a/src/core/write-buffer.c b/src/core/write-buffer.c index 6f6eef8a..ffc3ae63 100644 --- a/src/core/write-buffer.c +++ b/src/core/write-buffer.c @@ -107,7 +107,9 @@ static int write_buffer_flush_rec(void *handlep, BUFFER_REC *rec) for (tmp = rec->blocks; tmp != NULL; tmp = tmp->next) { size = tmp->data != rec->active_block ? BUFFER_BLOCK_SIZE : rec->active_block_pos; - write(handle, tmp->data, size); + if (write(handle, tmp->data, size) != size) { + g_warning("Failed to write(): %s", strerror(errno)); + } } empty_blocks = g_slist_concat(empty_blocks, rec->blocks); diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index dce6890e..a475f056 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -463,7 +463,7 @@ void fe_common_core_finish_init(void) if (setup_changed) signal_emit("setup changed", 0); - autorun_startup(); + autorun_startup(); autoconnect_servers(); } diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 7c23ad94..96242f9e 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -56,8 +56,10 @@ static void ignore_print(int index, IGNORE_REC *rec) if (rec->exception) g_string_append(options, "-except "); if (rec->regexp) { g_string_append(options, "-regexp "); + if (rec->pattern == NULL) + g_string_append(options, "[INVALID! -pattern missing] "); #ifdef HAVE_REGEX_H - if (!rec->regexp_compiled) + else if (!rec->regexp_compiled) g_string_append(options, "[INVALID!] "); #endif } @@ -118,7 +120,7 @@ static void cmd_ignore(const char *data) char *patternarg, *chanarg, *mask, *levels, *timestr, *servertag; char **channels; void *free_arg; - int new_ignore, msecs; + int new_ignore, msecs, level; if (*data == '\0') { cmd_ignore_show(); @@ -138,6 +140,7 @@ static void cmd_ignore(const char *data) if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*levels == '\0') levels = "ALL"; + level = level2bits(levels, NULL); msecs = 0; timestr = g_hash_table_lookup(optlist, "time"); @@ -154,7 +157,8 @@ static void cmd_ignore(const char *data) channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(chanarg, ",", -1); - rec = patternarg != NULL ? NULL: ignore_find(servertag, mask, channels); + rec = patternarg != NULL ? NULL: ignore_find_noact(servertag, mask, channels, + (level & MSGLEVEL_NO_ACT)); new_ignore = rec == NULL; if (rec == NULL) { @@ -170,6 +174,12 @@ static void cmd_ignore(const char *data) rec->level = combine_level(rec->level, levels); + if (rec->level == MSGLEVEL_NO_ACT) { + /* If only NO_ACT was specified add all levels; it makes no + * sense on its own. */ + rec->level |= MSGLEVEL_ALL; + } + if (new_ignore && rec->level == 0) { /* tried to unignore levels from nonexisting ignore */ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, @@ -226,7 +236,10 @@ static void cmd_unignore(const char *data) chans[0] = mask; mask = NULL; } - rec = ignore_find("*", mask, (char **) chans); + rec = ignore_find_noact("*", mask, (char **) chans, 0); + if (rec == NULL) { + rec = ignore_find_noact("*", mask, (char **) chans, 1); + } } if (rec != NULL) { diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 367863c7..25c20109 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -45,16 +45,19 @@ GHashTable *printnicks; -/* convert _underlined_ and *bold* words (and phrases) to use real +/* convert _underlined_, /italics/, and *bold* words (and phrases) to use real underlining or bolding */ char *expand_emphasis(WI_ITEM_REC *item, const char *text) { GString *str; char *ret; int pos; + int emphasis_italics; g_return_val_if_fail(text != NULL, NULL); + emphasis_italics = settings_get_bool("emphasis_italics"); + str = g_string_new(text); for (pos = 0; pos < str->len; pos++) { @@ -62,9 +65,11 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text) bgn = str->str + pos; - if (*bgn == '*') + if (*bgn == '*') type = 2; /* bold */ - else if (*bgn == '_') + else if (*bgn == '/' && emphasis_italics) + type = 29; /* italics */ + else if (*bgn == '_') type = 31; /* underlined */ else continue; @@ -92,7 +97,7 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text) found = nicklist_find(CHANNEL(item), bgn) != NULL; end[1] = c; if (found) continue; - + /* check if the whole 'word' (e.g. "_foo_^") is a nick in "_foo_^ ", end will be the second _, end2 the ^ */ end2 = end; @@ -190,7 +195,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg, if (for_me) level |= MSGLEVEL_HILIGHT; - if (ignore_check(server, nick, address, target, msg, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, target, msg, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; if (settings_get_bool("emphasis")) @@ -238,13 +243,17 @@ static void sig_message_private(SERVER_REC *server, const char *msg, { QUERY_REC *query; char *freemsg = NULL; + int level = MSGLEVEL_MSGS; query = query_find(server, nick); if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg); - printformat(server, nick, MSGLEVEL_MSGS, + if (ignore_check(server, nick, address, NULL, msg, level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + + printformat(server, nick, level, query == NULL ? TXT_MSG_PRIVATE : TXT_MSG_PRIVATE_QUERY, nick, address, msg); @@ -330,7 +339,7 @@ static void sig_message_join(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_JOINS; - if (ignore_check(server, nick, address, channel, NULL, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, channel, NULL, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -343,7 +352,7 @@ static void sig_message_part(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_PARTS; - if (ignore_check(server, nick, address, channel, NULL, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, channel, NULL, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -362,7 +371,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_QUITS)) return; - if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, NULL, reason, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; print_channel = NULL; @@ -432,7 +441,7 @@ static void sig_message_kick(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_KICKS; - if (ignore_check(server, kicker, address, channel, reason, MSGLEVEL_NO_ACT)) + if (ignore_check(server, kicker, address, channel, reason, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -453,7 +462,7 @@ static void print_nick_change_channel(SERVER_REC *server, const char *channel, level = MSGLEVEL_NICKS; if (ownnick) level |= MSGLEVEL_NO_ACT; - if (!(level & MSGLEVEL_NO_ACT) && ignore_check(server, oldnick, address, channel, newnick, MSGLEVEL_NO_ACT)) + if (!(level & MSGLEVEL_NO_ACT) && ignore_check(server, oldnick, address, channel, newnick, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -532,7 +541,7 @@ static void sig_message_topic(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_TOPICS; - if (ignore_check(server, nick, address, channel, topic, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, channel, topic, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -676,6 +685,7 @@ void fe_messages_init(void) settings_add_bool("lookandfeel", "emphasis", TRUE); settings_add_bool("lookandfeel", "emphasis_replace", FALSE); settings_add_bool("lookandfeel", "emphasis_multiword", FALSE); + settings_add_bool("lookandfeel", "emphasis_italics", FALSE); settings_add_bool("lookandfeel", "show_nickmode", TRUE); settings_add_bool("lookandfeel", "show_nickmode_empty", TRUE); settings_add_bool("lookandfeel", "print_active_channel", FALSE); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index f13829db..2dec1d8a 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -387,7 +387,7 @@ void fe_server_init(void) command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove); command_bind_first("server", NULL, (SIGNAL_FUNC) server_command); command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command); - command_set_options("server add", "4 6 ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port"); + command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port noautosendcmd"); signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting); diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index aa5ea397..bf9d7154 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -588,6 +588,63 @@ static void window_print_daychange(WINDOW_REC *window, struct tm *tm) printtext_string_window(window, MSGLEVEL_NEVER, str); } +short color_24bit_256 (const unsigned char rgb[]) +{ + static const int cstep_size = 40; + static const int cstep_start = 0x5f; + + static const int gstep_size = 10; + static const int gstep_start = 0x08; + + int dist[3] = {0}; + int r[3], gr[3]; + + size_t i; + + for (i = 0; i < 3; ++i) { + const int n = rgb[i]; + gr[i] = -1; + if (n < cstep_start /2) { + r[i] = 0; + dist[i] = -cstep_size/2; + } + else { + r[i] = 1+((n-cstep_start + cstep_size /2)/cstep_size); + dist[i] = ((n-cstep_start + cstep_size /2)%cstep_size - cstep_size/2); + } + if (n < gstep_start /2) { + gr[i] = -1; + } + else { + gr[i] = ((n-gstep_start + gstep_size /2)/gstep_size); + } + } + if (r[0] == r[1] && r[1] == r[2] && + 4*abs(dist[0]) < gstep_size && 4*abs(dist[1]) < gstep_size && 4*abs(dist[2]) < gstep_size) { + /* skip gray detection */ + } + else { + const int j = r[1] == r[2] ? 0 : 1; + if ((r[0] == r[1] || r[j] == r[2]) && abs(r[j]-r[(j+1)%3]) <= 1) { + const int k = gr[1] == gr[2] ? 0 : 1; + if ((gr[0] == gr[1] || gr[k] == gr[2]) && abs(gr[k]-gr[(k+1)%3]) <= 2) { + if (gr[k] < 0) { + r[0] = r[1] = r[2] = 0; + } + else if (gr[k] > 23) { + r[0] = r[1] = r[2] = 5; + } + else { + r[0] = 6; + r[1] = (gr[k] / 6); + r[2] = gr[k]%6; + } + } + } + } + return 16 + r[0]*36 + r[1] * 6 + r[2]; +} + static void sig_print_text(void) { GSList *tmp; diff --git a/src/fe-common/core/fe-windows.h b/src/fe-common/core/fe-windows.h index 58c316ef..613f15f8 100644 --- a/src/fe-common/core/fe-windows.h +++ b/src/fe-common/core/fe-windows.h @@ -97,4 +97,6 @@ void window_bind_remove_unsticky(WINDOW_REC *window); void windows_init(void); void windows_deinit(void); +short color_24bit_256(const unsigned char rgb[]); + #endif diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index f2a82030..375b00eb 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -101,10 +101,88 @@ static void format_expand_code(const char **format, GString *out, int *flags) } } +void format_ext_color(GString *out, int bg, int color) +{ + g_string_append_c(out, 4); + if (bg && color < 0x10) + g_string_append_c(out, FORMAT_COLOR_NOCHANGE); + if (color < 0x10) + g_string_append_c(out, color+'0'); + else { + if (color < 0x60) + g_string_append_c(out, bg ? FORMAT_COLOR_EXT1_BG + : FORMAT_COLOR_EXT1); + else if (color < 0xb0) + g_string_append_c(out, bg ? FORMAT_COLOR_EXT2_BG + : FORMAT_COLOR_EXT2); + else + g_string_append_c(out, bg ? FORMAT_COLOR_EXT3_BG + : FORMAT_COLOR_EXT3); + g_string_append_c(out, FORMAT_COLOR_NOCHANGE + ((color-0x10)%0x50)); + } + if (!bg && color < 0x10) + g_string_append_c(out, FORMAT_COLOR_NOCHANGE); +} + +#ifdef TERM_TRUECOLOR +void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int *flags) +{ + unsigned int color; + unsigned char rgbx[4]; + unsigned int i; + for (i = 0; i < 4; ++i) { + rgbx[i] = (*ptr)[i + off]; + } + rgbx[3] -= 0x20; + *ptr += 4; + for (i = 0; i < 3; ++i) { + if (rgbx[3] & (0x10 << i)) + rgbx[i] -= 0x20; + } + color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2]; + if (rgbx[3] & 0x1) { + *bgcolor = color; + *flags |= GUI_PRINT_FLAG_COLOR_24_BG; + } + else { + *fgcolor = color; + *flags |= GUI_PRINT_FLAG_COLOR_24_FG; + } +} +#endif + +void format_24bit_color(GString *out, int bg, unsigned int color) +{ + unsigned char rgb[] = { color >> 16, color >> 8, color }; +#ifdef TERM_TRUECOLOR + unsigned char x = bg ? 0x1 : 0; + unsigned int i; + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_COLOR_24); + for (i = 0; i < 3; ++i) { + if (rgb[i] > 0x20) + g_string_append_c(out, rgb[i]); + else { + g_string_append_c(out, 0x20 + rgb[i]); + x |= 0x10 << i; + } + } + g_string_append_c(out, 0x20 + x); +#else /* !TERM_TRUECOLOR */ + format_ext_color(out, bg, color_24bit_256(rgb)); +#endif /* TERM_TRUECOLOR */ +} + int format_expand_styles(GString *out, const char **format, int *flags) { + int retval = 1; + char *p, fmt; + /* storage for numerical parsing code for %x/X formats. */ + int tmp; + unsigned int tmp2; + fmt = **format; switch (fmt) { case '{': @@ -129,6 +207,11 @@ int format_expand_styles(GString *out, const char **format, int *flags) g_string_append_c(out, 4); g_string_append_c(out, FORMAT_STYLE_REVERSE); break; + case 'I': + /* italic */ + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_STYLE_ITALIC); + break; case ':': /* Newline */ g_string_append_c(out, '\n'); @@ -162,6 +245,62 @@ int format_expand_styles(GString *out, const char **format, int *flags) /* code */ format_expand_code(format, out, flags); break; + case 'x': + case 'X': + if ((*format)[1] < '0' || (*format)[1] > '7') + break; + + tmp = 16 + ((*format)[1]-'0'-1)*36; + if (tmp > 231) { + if (!isalpha((*format)[2])) + break; + + tmp += (*format)[2] >= 'a' ? (*format)[2] - 'a' : (*format)[2] - 'A'; + + if (tmp > 255) + break; + } + else if (tmp > 0) { + if (!isalnum((*format)[2])) + break; + + if ((*format)[2] >= 'a') + tmp += 10 + (*format)[2] - 'a'; + else if ((*format)[2] >= 'A') + tmp += 10 + (*format)[2] - 'A'; + else + tmp += (*format)[2] - '0'; + } + else { + if (!isxdigit((*format)[2])) + break; + + tmp = g_ascii_xdigit_value((*format)[2]); + } + + retval += 2; + + format_ext_color(out, fmt == 'x', tmp); + break; + case 'z': + case 'Z': + tmp2 = 0; + for (tmp = 1; tmp < 7; ++tmp) { + if (!isxdigit((*format)[tmp])) { + tmp2 = UINT_MAX; + break; + } + tmp2 <<= 4; + tmp2 |= g_ascii_xdigit_value((*format)[tmp]); + } + + if (tmp2 == UINT_MAX) + break; + + retval += 6; + + format_24bit_color(out, fmt == 'z', tmp2); + break; default: /* check if it's a background color */ p = strchr(format_backs, fmt); @@ -195,7 +334,7 @@ int format_expand_styles(GString *out, const char **format, int *flags) return FALSE; } - return TRUE; + return retval; } void format_read_arglist(va_list va, FORMAT_REC *format, @@ -303,6 +442,7 @@ int format_get_length(const char *str) GString *tmp; int len; gboolean utf8; + int adv = 0; g_return_val_if_fail(str != NULL, 0); @@ -313,9 +453,10 @@ int format_get_length(const char *str) while (*str != '\0') { if (*str == '%' && str[1] != '\0') { str++; - if (*str != '%' && - format_expand_styles(tmp, &str, NULL)) { - str++; + if (*str != '%') { + adv = format_expand_styles(tmp, &str, NULL); + str += adv; + if (adv) continue; } @@ -340,7 +481,7 @@ int format_real_length(const char *str, int len) const char *start; const char *oldstr; gboolean utf8; - + int adv = 0; g_return_val_if_fail(str != NULL, 0); g_return_val_if_fail(len >= 0, 0); @@ -351,9 +492,10 @@ int format_real_length(const char *str, int len) while (*str != '\0' && len > 0) { if (*str == '%' && str[1] != '\0') { str++; - if (*str != '%' && - format_expand_styles(tmp, &str, NULL)) { - str++; + if (*str != '%') { + adv = format_expand_styles(tmp, &str, NULL); + str += adv; + if (adv) continue; } @@ -378,6 +520,7 @@ char *format_string_expand(const char *text, int *flags) { GString *out; char code, *ret; + int adv; g_return_val_if_fail(text != NULL, NULL); @@ -388,10 +531,13 @@ char *format_string_expand(const char *text, int *flags) while (*text != '\0') { if (code == '%') { /* color code */ - if (!format_expand_styles(out, &text, flags)) { + adv = format_expand_styles(out, &text, flags); + if (!adv) { g_string_append_c(out, '%'); g_string_append_c(out, '%'); g_string_append_c(out, *text); + } else { + text += adv - 1; } code = 0; } else { @@ -415,6 +561,7 @@ static char *format_get_text_args(TEXT_DEST_REC *dest, GString *out; char code, *ret; int need_free; + int adv; out = g_string_new(NULL); @@ -422,10 +569,13 @@ static char *format_get_text_args(TEXT_DEST_REC *dest, while (*text != '\0') { if (code == '%') { /* color code */ - if (!format_expand_styles(out, &text, &dest->flags)) { + adv = format_expand_styles(out, &text, &dest->flags); + if (!adv) { g_string_append_c(out, '%'); g_string_append_c(out, '%'); g_string_append_c(out, *text); + } else { + text += adv - 1; } code = 0; } else if (code == '$') { @@ -716,13 +866,22 @@ void format_newline(WINDOW_REC *window) "", NULL); } +#ifndef TERM_TRUECOLOR +inline static int color_24bit_256_int(unsigned int color) +{ + unsigned char rgb[] = { color >> 16, color >> 8, color }; + return color_24bit_256(rgb); +} +#endif /* !TERM_TRUECOLOR */ + /* parse ANSI color string */ static const char *get_ansi_color(THEME_REC *theme, const char *str, int *fg_ret, int *bg_ret, int *flags_ret) { static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; const char *start; - int fg, bg, flags, num; + int fg, bg, flags, num, i; + unsigned int num2; if (*str != '[') return str; @@ -749,28 +908,135 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, /* reset colors back to default */ fg = theme->default_color; bg = -1; - flags &= ~GUI_PRINT_FLAG_INDENT; + flags &= ~(GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT); break; case 1: /* hilight */ flags |= GUI_PRINT_FLAG_BOLD; break; + case 22: + /* normal */ + flags &= ~GUI_PRINT_FLAG_BOLD; + break; + case 3: + /* italic */ + flags |= GUI_PRINT_FLAG_ITALIC; + break; + case 23: + /* not italic */ + flags &= ~GUI_PRINT_FLAG_ITALIC; + break; + case 4: + /* underline */ + flags |= GUI_PRINT_FLAG_UNDERLINE; + break; + case 24: + /* not underline */ + flags &= ~GUI_PRINT_FLAG_UNDERLINE; + break; case 5: /* blink */ flags |= GUI_PRINT_FLAG_BLINK; break; + case 25: + /* steady */ + flags &= ~GUI_PRINT_FLAG_BLINK; + break; case 7: /* reverse */ flags |= GUI_PRINT_FLAG_REVERSE; break; + case 27: + /* positive */ + flags &= ~GUI_PRINT_FLAG_REVERSE; + break; + case 39: + /* reset fg */ + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + fg = theme->default_color; + break; + case 49: + /* reset bg */ + bg = -1; + flags &= ~(GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT); + break; + case 38: + case 48: + /* ANSI indexed color or RGB color */ + if (*str != ';') break; + str++; + for (num2 = 0; i_isdigit(*str); str++) + num2 = num2*10 + (*str-'0'); + + switch (num2) { + case 2: + /* RGB */ + num2 = 0; + + for (i = 0; i < 3; ++i) { + num2 <<= 8; + + if (*str != ';' && *str != ':') { + i = -1; + break; + } + str++; + for (; i_isdigit(*str); str++) + num2 = (num2&~0xff) | + (((num2&0xff) * 10 + (*str-'0'))&0xff); + } + + if (i == -1) break; +#ifdef TERM_TRUECOLOR + if (num == 38) { + flags |= GUI_PRINT_FLAG_COLOR_24_FG; + fg = num2; + } else if (num == 48) { + flags |= GUI_PRINT_FLAG_COLOR_24_BG; + bg = num2; + } +#else /* !TERM_TRUECOLOR */ + if (num == 38) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + fg = color_24bit_256_int(num2); + } else if (num == 48) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + bg = color_24bit_256_int(num2); + } +#endif + + break; + case 5: + /* indexed */ + if (*str != ';') break; + str++; + for (num2 = 0; i_isdigit(*str); str++) + num2 = num2*10 + (*str-'0'); + + if (num == 38) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + fg = num2; + } else if (num == 48) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + bg = num2; + } + + break; + } + break; default: if (num >= 30 && num <= 37) { - if (fg == -1) fg = 0; - fg = (fg & 0xf8) | ansitab[num-30]; - } - if (num >= 40 && num <= 47) { - if (bg == -1) bg = 0; - bg = (bg & 0xf8) | ansitab[num-40]; + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + fg = ansitab[num-30]; + } else if (num >= 40 && num <= 47) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + bg = ansitab[num-40]; + } else if (num >= 90 && num <= 97) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + fg = 8 + ansitab[num-90]; + } else if (num >= 100 && num <= 107) { + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + bg = 8 + ansitab[num-100]; } break; } @@ -832,7 +1098,7 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret) #define IS_COLOR_CODE(c) \ ((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \ - (c) == 15 || (c) == 22 || (c) == 27 || (c) == 31) + (c) == 15 || (c) == 22 || (c) == 27 || (c) == 29 || (c) == 31) /* Return how many characters in `str' must be skipped before `len' characters of text is skipped. */ @@ -858,6 +1124,20 @@ int strip_real_length(const char *str, int len, *last_color_len = (int) (str-mircstart); } else if (*str == 4 && str[1] != '\0') { +#ifdef TERM_TRUECOLOR + if (str[1] == FORMAT_COLOR_24 && str[2] != '\0') { + if (str[3] == '\0') str++; + else if (str[4] == '\0') str += 2; + else if (str[5] == '\0') str += 3; + else { + if (last_color_pos != NULL) + *last_color_pos = (int) (str-start); + if (last_color_len != NULL) + *last_color_len = 6; + str+=4; + } + } else +#endif if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') { if (last_color_pos != NULL) *last_color_pos = (int) (str-start); @@ -907,6 +1187,14 @@ char *strip_codes(const char *input) /* irssi color */ if (p[2] != '\0') { +#ifdef TERM_TRUECOLOR + if (p[1] == FORMAT_COLOR_24) { + if (p[3] == '\0') p += 2; + else if (p[4] == '\0') p += 3; + else if (p[5] == '\0') p += 4; + else p += 5; + } else +#endif /* TERM_TRUECOLOR */ p += 2; continue; } @@ -1007,6 +1295,9 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) case FORMAT_STYLE_REVERSE: flags ^= GUI_PRINT_FLAG_REVERSE; break; + case FORMAT_STYLE_ITALIC: + flags ^= GUI_PRINT_FLAG_ITALIC; + break; case FORMAT_STYLE_MONOSPACE: flags ^= GUI_PRINT_FLAG_MONOSPACE; break; @@ -1020,16 +1311,47 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) break; case FORMAT_STYLE_CLRTOEOL: break; + case FORMAT_COLOR_EXT1: + fgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE; + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + break; + case FORMAT_COLOR_EXT1_BG: + bgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE; + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + break; + case FORMAT_COLOR_EXT2: + fgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE; + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + break; + case FORMAT_COLOR_EXT2_BG: + bgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE; + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + break; + case FORMAT_COLOR_EXT3: + fgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE; + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + break; + case FORMAT_COLOR_EXT3_BG: + bgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE; + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + break; +#ifdef TERM_TRUECOLOR + case FORMAT_COLOR_24: + unformat_24bit_color(&ptr, 1, &fgcolor, &bgcolor, &flags); + break; +#endif default: if (*ptr != FORMAT_COLOR_NOCHANGE) { - fgcolor = (unsigned char) *ptr-'0'; + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + fgcolor = *ptr==(char)0xff ? -1 : (unsigned char) *ptr-'0'; } if (ptr[1] == '\0') break; ptr++; if (*ptr != FORMAT_COLOR_NOCHANGE) { - bgcolor = *ptr-'0'; + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + bgcolor = *ptr==(char)0xff ? -1 : *ptr-'0'; } } ptr++; @@ -1050,6 +1372,11 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) if (!hide_text_style) flags ^= GUI_PRINT_FLAG_REVERSE; break; + case 29: + /* italic */ + if (!hide_text_style) + flags ^= GUI_PRINT_FLAG_ITALIC; + break; case 31: /* underline */ if (!hide_text_style) diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h index 6c55a068..07e1832c 100644 --- a/src/fe-common/core/formats.h +++ b/src/fe-common/core/formats.h @@ -10,9 +10,12 @@ #define GUI_PRINT_FLAG_BLINK 0x0008 #define GUI_PRINT_FLAG_MIRC_COLOR 0x0010 #define GUI_PRINT_FLAG_INDENT 0x0020 +#define GUI_PRINT_FLAG_ITALIC 0x0040 #define GUI_PRINT_FLAG_NEWLINE 0x0080 #define GUI_PRINT_FLAG_CLRTOEOL 0x0100 #define GUI_PRINT_FLAG_MONOSPACE 0x0200 +#define GUI_PRINT_FLAG_COLOR_24_FG 0x0400 +#define GUI_PRINT_FLAG_COLOR_24_BG 0x0800 #define MAX_FORMAT_PARAMS 10 #define DEFAULT_FORMAT_ARGLIST_SIZE 200 @@ -121,6 +124,15 @@ char *strip_codes(const char *input); void format_send_to_gui(TEXT_DEST_REC *dest, const char *text); #define FORMAT_COLOR_NOCHANGE ('0'-1) /* don't change this, at least hilighting depends this value */ +#define FORMAT_COLOR_EXT1 ('0'-2) +#define FORMAT_COLOR_EXT2 ('0'-3) +#define FORMAT_COLOR_EXT3 ('0'-4) +#define FORMAT_COLOR_EXT1_BG ('0'-5) +#define FORMAT_COLOR_EXT2_BG ('0'-9) +#define FORMAT_COLOR_EXT3_BG ('0'-10) +#ifdef TERM_TRUECOLOR +#define FORMAT_COLOR_24 ('0'-13) +#endif #define FORMAT_STYLE_SPECIAL 0x60 #define FORMAT_STYLE_BLINK (0x01 + FORMAT_STYLE_SPECIAL) @@ -128,10 +140,13 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text); #define FORMAT_STYLE_BOLD (0x03 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_REVERSE (0x04 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_INDENT (0x05 + FORMAT_STYLE_SPECIAL) +#define FORMAT_STYLE_ITALIC (0x06 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_DEFAULTS (0x07 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_CLRTOEOL (0x08 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_MONOSPACE (0x09 + FORMAT_STYLE_SPECIAL) int format_expand_styles(GString *out, const char **format, int *flags); +void format_ext_color(GString *out, int bg, int color); +void format_24bit_color(GString *out, int bg, unsigned int color); void formats_init(void); void formats_deinit(void); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 34c5c643..4b914517 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -78,6 +78,7 @@ static void hilight_add_config(HILIGHT_REC *rec) if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE); if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE); + if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag); if (rec->channels != NULL && *rec->channels != NULL) { node = config_node_section(node, "channels", NODE_TYPE_LIST); @@ -267,6 +268,8 @@ HILIGHT_REC *hilight_match(SERVER_REC *server, const char *channel, if (!rec->nickmask && hilight_match_level(rec, level) && hilight_match_channel(rec, channel) && + (rec->servertag == NULL || + (server != NULL && g_ascii_strcasecmp(rec->servertag, server->tag) == 0)) && hilight_match_text(rec, str, match_beg, match_end)) return rec; } @@ -336,6 +339,12 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text, if (!nick_match || (dest->level & MSGLEVEL_HILIGHT)) { /* update the level / hilight info */ hilight_update_text_dest(dest, hilight); + /* Remove NO_ACT, this means explicitly defined hilights will bypass + * /IGNORE ... NO_ACT. + * (It's still possible to use /hilight -actcolor %n to hide + * hilight/beep). + */ + dest->level &= ~MSGLEVEL_NO_ACT; } if (nick_match) @@ -459,7 +468,7 @@ static void read_hilight_config(void) rec->nickmask = config_node_get_bool(node, "mask", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE); rec->regexp = config_node_get_bool(node, "regexp", FALSE); - + rec->servertag = config_node_get_str(node, "servertag", NULL); hilight_init_rec(rec); node = config_node_section(node, "channels", -1); @@ -492,6 +501,8 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->priority != 0) g_string_append_printf(options, "-priority %d ", rec->priority); + if (rec->servertag != NULL) + g_string_append_printf(options, "-network %s ", rec->servertag); if (rec->color != NULL) g_string_append_printf(options, "-color %s ", rec->color); if (rec->act_color != NULL) @@ -530,12 +541,12 @@ static void cmd_hilight_show(void) /* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp] [-color ] [-actcolor ] [-level ] - [-channels ] */ + [-network ] [-channels ] */ static void cmd_hilight(const char *data) { GHashTable *optlist; HILIGHT_REC *rec; - char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text; + char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text, *servertag; char **channels; void *free_arg; @@ -555,6 +566,7 @@ static void cmd_hilight(const char *data) priorityarg = g_hash_table_lookup(optlist, "priority"); colorarg = g_hash_table_lookup(optlist, "color"); actcolorarg = g_hash_table_lookup(optlist, "actcolor"); + servertag = g_hash_table_lookup(optlist, "network"); if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -606,6 +618,11 @@ static void cmd_hilight(const char *data) if (*actcolorarg != '\0') rec->act_color = g_strdup(actcolorarg); } + if (servertag != NULL) { + g_free_and_null(rec->servertag); + if (*servertag != '\0') + rec->servertag = g_strdup(servertag); + } hilight_create(rec); @@ -696,7 +713,7 @@ void hilight_text_init(void) command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); - command_set_options("hilight", "-color -actcolor -level -priority -channels nick word line mask full regexp"); + command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp"); } void hilight_text_deinit(void) diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index 74c58780..d54ec4b5 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -29,6 +29,7 @@ struct _HILIGHT_REC { unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ regex_t preg; #endif + char *servertag; }; extern GSList *hilights; diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index d3653f90..a5eaa38f 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -206,6 +206,7 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str, { GString *out; char *ret; + int adv; out = g_string_new(NULL); for (; *str != '\0'; str++) { @@ -255,9 +256,12 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str, break; } default: - if (!format_expand_styles(out, &str, &dest->flags)) { + adv = format_expand_styles(out, &str, &dest->flags); + if (!adv) { g_string_append_c(out, '%'); g_string_append_c(out, *str); + } else { + str += adv - 1; } break; } @@ -272,6 +276,7 @@ static char *printtext_expand_formats(const char *str, int *flags) { GString *out; char *ret; + int adv; out = g_string_new(NULL); for (; *str != '\0'; str++) { @@ -283,9 +288,12 @@ static char *printtext_expand_formats(const char *str, int *flags) if (*++str == '\0') break; - if (!format_expand_styles(out, &str, flags)) { + adv = format_expand_styles(out, &str, flags); + if (!adv) { g_string_append_c(out, '%'); g_string_append_c(out, *str); + } else { + str += adv - 1; } } diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 548836ac..d92d23fe 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -115,8 +115,8 @@ void theme_destroy(THEME_REC *rec) } static char *theme_replace_expand(THEME_REC *theme, int index, - char default_fg, char default_bg, - char *last_fg, char *last_bg, + theme_rm_col default_fg, theme_rm_col default_bg, + theme_rm_col *last_fg, theme_rm_col *last_bg, char chr, int flags) { GSList *rec; @@ -168,15 +168,44 @@ static void theme_format_append_variable(GString *str, const char **format) g_free(value); } +static inline int chr_is_valid_rgb(const char format[]) +{ + int tmp; + for (tmp = 1; tmp < 7; ++tmp) { + if (!isxdigit(format[tmp])) + return tmp; + } + return 0; +} + +static inline int chr_is_valid_ext(const char format[]) +{ + if (format[1] < '0' || format[1] > '7') + return 1; + + if (format[1] == '7') { + if (!isalpha(format[2]) || format[2] == 'y' || format[2] == 'Y' + || format[2] =='z' || format[2] == 'Z') + return 2; + } else if (format[1] == '0') { + if (!isxdigit(format[2])) + return 2; + } else if (!isalnum(format[2])) + return 2; + + return 0; +} + /* append next "item", either a character, $variable or %format */ static void theme_format_append_next(THEME_REC *theme, GString *str, const char **format, - char default_fg, char default_bg, - char *last_fg, char *last_bg, + theme_rm_col default_fg, theme_rm_col default_bg, + theme_rm_col *last_fg, theme_rm_col *last_bg, int flags) { int index; unsigned char chr; + char *t; chr = **format; if ((chr == '$' || chr == '%') && @@ -203,22 +232,50 @@ static void theme_format_append_next(THEME_REC *theme, GString *str, /* %n = change to default color */ g_string_append(str, "%n"); - if (default_bg != 'n') { + if (default_bg.m[0] != 'n') { g_string_append_c(str, '%'); - g_string_append_c(str, default_bg); + g_string_append(str, default_bg.m); } - if (default_fg != 'n') { + if (default_fg.m[0] != 'n') { g_string_append_c(str, '%'); - g_string_append_c(str, default_fg); + g_string_append(str, default_fg.m); } *last_fg = default_fg; *last_bg = default_bg; + } else if (chr == 'z' || chr == 'Z') { + if (chr_is_valid_rgb(*format) == 0) { + t = chr == 'z' ? (*last_bg).m : (*last_fg).m; + strncpy(t, *format, 7); + t[7] = '\0'; + g_string_append_c(str, '%'); + g_string_append(str, t); + (*format)+=6; + } else { + g_string_append(str, "%%"); + g_string_append_c(str, **format); + } + } else if (chr == 'x' || chr == 'X') { + if (chr_is_valid_ext(*format) == 0) { + t = chr == 'x' ? (*last_bg).m : (*last_fg).m; + strncpy(t, *format, 3); + t[3] = '\0'; + g_string_append_c(str, '%'); + g_string_append(str, t); + (*format)+=2; + } else { + g_string_append(str, "%%"); + g_string_append_c(str, **format); + } } else { - if (IS_FGCOLOR_FORMAT(chr)) - *last_fg = chr; - if (IS_BGCOLOR_FORMAT(chr)) - *last_bg = chr; + if (IS_FGCOLOR_FORMAT(chr)) { + (*last_fg).m[0] = chr; + (*last_fg).m[1] = '\0'; + } + if (IS_BGCOLOR_FORMAT(chr)) { + (*last_bg).m[0] = chr; + (*last_bg).m[1] = '\0'; + } g_string_append_c(str, '%'); g_string_append_c(str, chr); } @@ -306,7 +363,10 @@ static int data_is_empty(const char **data) char *theme_format_expand_get(THEME_REC *theme, const char **format) { GString *str; - char *ret, dummy; + char *ret; + theme_rm_col dummy, reset; + dummy.m[0] = '\0'; + strcpy(reset.m, "n"); int braces = 1; /* we start with one brace opened */ str = g_string_new(NULL); @@ -321,7 +381,7 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format) continue; } else { theme_format_append_next(theme, str, format, - 'n', 'n', + reset, reset, &dummy, &dummy, 0); continue; } @@ -343,15 +403,19 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format) /* expand a single {abstract ...data... } */ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp, - char default_fg, char default_bg, + theme_rm_col *last_fg, + theme_rm_col *last_bg, int flags) { GString *str; const char *p, *format; char *abstract, *data, *ret; + theme_rm_col default_fg, default_bg; int len; format = *formatp; + default_fg = *last_fg; + default_bg = *last_bg; /* get abstract name first */ p = format; @@ -425,7 +489,7 @@ static char *theme_format_expand_abstract(THEME_REC *theme, /* abstract may itself contain abstracts or replaces */ p = abstract; ret = theme_format_expand_data(theme, &p, default_fg, default_bg, - &default_fg, &default_bg, + last_fg, last_bg, flags | EXPAND_FLAG_LASTCOLOR_ARG); g_free(abstract); return ret; @@ -433,13 +497,13 @@ static char *theme_format_expand_abstract(THEME_REC *theme, /* expand the data part in {abstract data} */ char *theme_format_expand_data(THEME_REC *theme, const char **format, - char default_fg, char default_bg, - char *save_last_fg, char *save_last_bg, + theme_rm_col default_fg, theme_rm_col default_bg, + theme_rm_col *save_last_fg, theme_rm_col *save_last_bg, int flags) { GString *str; char *ret, *abstract; - char last_fg, last_bg; + theme_rm_col last_fg, last_bg; int recurse_flags; last_fg = default_fg; @@ -482,7 +546,7 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format, /* get a single {...} */ abstract = theme_format_expand_abstract(theme, format, - last_fg, last_bg, + &last_fg, &last_bg, recurse_flags); if (abstract != NULL) { g_string_append(str, abstract); @@ -490,13 +554,11 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format, } } - if ((flags & EXPAND_FLAG_LASTCOLOR_ARG) == 0) { /* save the last color */ if (save_last_fg != NULL) *save_last_fg = last_fg; if (save_last_bg != NULL) *save_last_bg = last_bg; - } ret = str->str; g_string_free(str, FALSE); @@ -510,7 +572,8 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format, static char *theme_format_compress_colors(THEME_REC *theme, const char *format) { GString *str; - char *ret, last_fg, last_bg; + char *ret; + char last_fg, last_bg; str = g_string_new(NULL); @@ -543,8 +606,12 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format) if (IS_FGCOLOR_FORMAT(*format)) last_fg = *format; + else if (*format == 'Z' || *format == 'X') + last_fg = '\0'; if (IS_BGCOLOR_FORMAT(*format)) last_bg = *format; + else if (*format == 'z' || *format == 'x') + last_bg = '\0'; } format++; } @@ -558,11 +625,13 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format) char *theme_format_expand(THEME_REC *theme, const char *format) { char *data, *ret; + theme_rm_col reset; + strcpy(reset.m, "n"); g_return_val_if_fail(theme != NULL, NULL); g_return_val_if_fail(format != NULL, NULL); - data = theme_format_expand_data(theme, &format, 'n', 'n', NULL, NULL, + data = theme_format_expand_data(theme, &format, reset, reset, NULL, NULL, EXPAND_FLAG_ROOT); ret = theme_format_compress_colors(theme, data); g_free(data); @@ -944,10 +1013,6 @@ static int theme_read(THEME_REC *theme, const char *path) config_get_int(config, NULL, "default_color", -1); theme->info_eol = config_get_bool(config, NULL, "info_eol", FALSE); - /* FIXME: remove after 0.7.99 */ - if (theme->default_color == 0 && - config_get_int(config, NULL, "default_real_color", -1) != -1) - theme->default_color = -1; theme_read_replaces(config, theme); if (path != NULL) diff --git a/src/fe-common/core/themes.h b/src/fe-common/core/themes.h index dcdea0fc..31cfe943 100644 --- a/src/fe-common/core/themes.h +++ b/src/fe-common/core/themes.h @@ -57,10 +57,14 @@ void theme_set_default_abstract(const char *key, const char *value); #define EXPAND_FLAG_ROOT 0x10 #define EXPAND_FLAG_LASTCOLOR_ARG 0x20 +typedef struct { + char m[8]; +} theme_rm_col; + char *theme_format_expand(THEME_REC *theme, const char *format); char *theme_format_expand_data(THEME_REC *theme, const char **format, - char default_fg, char default_bg, - char *save_last_fg, char *save_last_bg, + theme_rm_col default_fg, theme_rm_col default_bg, + theme_rm_col *save_last_fg, theme_rm_col *save_last_bg, int flags); void themes_reload(void); diff --git a/src/fe-common/irc/dcc/fe-dcc-chat-messages.c b/src/fe-common/irc/dcc/fe-dcc-chat-messages.c index 23ccc943..93e10943 100644 --- a/src/fe-common/irc/dcc/fe-dcc-chat-messages.c +++ b/src/fe-common/irc/dcc/fe-dcc-chat-messages.c @@ -25,6 +25,7 @@ #include "irc-servers.h" #include "irc-queries.h" #include "dcc-chat.h" +#include "ignore.h" #include "module-formats.h" #include "printtext.h" @@ -86,12 +87,17 @@ static void sig_message_dcc(CHAT_DCC_REC *dcc, const char *msg) TEXT_DEST_REC dest; QUERY_REC *query; char *tag; + int level = MSGLEVEL_DCCMSGS; tag = g_strconcat("=", dcc->id, NULL); query = query_find(NULL, tag); + if (ignore_check(SERVER(dcc->server), tag, dcc->addrstr, NULL, msg, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag, - MSGLEVEL_DCCMSGS, NULL); + level, NULL); printformat_dest(&dest, query != NULL ? IRCTXT_DCC_MSG_QUERY : IRCTXT_DCC_MSG, dcc->id, msg); @@ -103,12 +109,17 @@ static void sig_message_dcc_action(CHAT_DCC_REC *dcc, const char *msg) TEXT_DEST_REC dest; QUERY_REC *query; char *tag; + int level = MSGLEVEL_DCCMSGS | MSGLEVEL_ACTIONS; tag = g_strconcat("=", dcc->id, NULL); query = query_find(NULL, tag); + if (ignore_check(SERVER(dcc->server), tag, dcc->addrstr, NULL, msg, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag, - MSGLEVEL_DCCMSGS | MSGLEVEL_ACTIONS, NULL); + level, NULL); printformat_dest(&dest, query != NULL ? IRCTXT_ACTION_DCC_QUERY : IRCTXT_ACTION_DCC, dcc->id, msg); @@ -120,11 +131,16 @@ static void sig_message_dcc_ctcp(CHAT_DCC_REC *dcc, const char *cmd, { TEXT_DEST_REC dest; char *tag; + int level = MSGLEVEL_DCCMSGS | MSGLEVEL_CTCPS; tag = g_strconcat("=", dcc->id, NULL); + if (ignore_check(SERVER(dcc->server), tag, dcc->addrstr, NULL, cmd, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag, - MSGLEVEL_DCC | MSGLEVEL_CTCPS, NULL); + level, NULL); printformat_dest(&dest, IRCTXT_DCC_CTCP, dcc->id, cmd, data); g_free(tag); diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c index f2b00590..765b5340 100644 --- a/src/fe-common/irc/fe-irc-commands.c +++ b/src/fe-common/irc/fe-irc-commands.c @@ -44,6 +44,9 @@ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target; + char *subdata; + char **splitdata; + int n = 0; CMD_IRC_SERVER(server); if (!IS_IRC_ITEM(item)) @@ -53,10 +56,13 @@ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) cmd_return_error(CMDERR_NOT_CONNECTED); target = window_item_get_target(item); - irc_server_send_action(server, target, data); - - signal_emit("message irc own_action", 3, server, data, - item->visible_name); + splitdata = irc_server_split_action(server, target, data); + while ((subdata = splitdata[n++])) { + irc_server_send_action(server, target, subdata); + signal_emit("message irc own_action", 3, server, subdata, + item->visible_name); + } + g_strfreev(splitdata); } /* SYNTAX: ACTION [-] */ @@ -64,6 +70,9 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server) { GHashTable *optlist; const char *target, *text; + char *subtext; + char **splittexts; + int n = 0; void *free_arg; CMD_IRC_SERVER(server); @@ -79,10 +88,14 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server) if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); - irc_server_send_action(server, target, text); - - signal_emit("message irc own_action", 3, server, text, target); + splittexts = irc_server_split_action(server, target, text); + while ((subtext = splittexts[n++])) { + irc_server_send_action(server, target, subtext); + signal_emit("message irc own_action", 3, server, subtext, + target); + } + g_strfreev(splittexts); cmd_params_free(free_arg); } diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index fb8d1e94..a8d52745 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -170,6 +170,10 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, if (ignore_check(SERVER(server), nick, address, target, msg, level)) return; + if (ignore_check(SERVER(server), nick, address, target, msg, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + if (ischannel(*target)) item = irc_channel_find(server, target); else @@ -214,6 +218,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, const char *target) { const char *oldtarget; + int level = MSGLEVEL_NOTICES; oldtarget = target; target = skip_target(IRC_SERVER(server), target); @@ -230,18 +235,23 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, if (ignore_check(server, nick, address, ischannel(*target) ? target : NULL, - msg, MSGLEVEL_NOTICES)) + msg, level)) return; + if (ignore_check(server, nick, address, + ischannel(*target) ? target : NULL, + msg, level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + if (ischannel(*target)) { /* notice in some channel */ - printformat(server, target, MSGLEVEL_NOTICES, + printformat(server, target, level, IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg); } else { /* private notice */ privmsg_get_query(SERVER(server), nick, FALSE, MSGLEVEL_NOTICES); - printformat(server, nick, MSGLEVEL_NOTICES, + printformat(server, nick, level, IRCTXT_NOTICE_PRIVATE, nick, address, msg); } } diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 13cbfafd..f123ce4c 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -452,7 +452,7 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str) g_utf8_validate(str, -1, &ptr); len = g_utf8_pointer_to_offset(str, ptr); } else if (term_type == TERM_TYPE_BIG5) - len = strlen_big5(str); + len = strlen_big5((const unsigned char *)str); else len = strlen(str); entry_text_grow(entry, len); diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 76b116d8..cf6028b5 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -29,7 +29,14 @@ #include "gui-printtext.h" #include "gui-windows.h" -int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7 }; +int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7, + /* 16-27 */ 52, 94, 100, 58, 22, 29, 23, 24, 17, 54, 53, 89, + /* 28-39 */ 88, 130, 142, 64, 28, 35, 30, 25, 18, 91, 90, 125, + /* 40-51 */ 124, 166, 184, 106, 34, 49, 37, 33, 19, 129, 127, 161, + /* 52-63 */ 196, 208, 226, 154, 46, 86, 51, 75, 21, 171, 201, 198, + /* 64-75 */ 203, 215, 227, 191, 83, 122, 87, 111, 63, 177, 207, 205, + /* 76-87 */ 217, 223, 229, 193, 157, 158, 159, 153, 147, 183, 219, 212, + /* 88-98 */ 16, 233, 235, 237, 239, 241, 244, 247, 250, 254, 231, -1 }; static int scrollback_lines, scrollback_time, scrollback_burst_remove; static int next_xpos, next_ypos; @@ -145,22 +152,41 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view) static void get_colors(int flags, int *fg, int *bg, int *attr) { + *attr = 0; if (flags & GUI_PRINT_FLAG_MIRC_COLOR) { - /* mirc colors - real range is 0..15, but after 16 - colors wrap to 0, 1, ... */ - if (*bg >= 0) *bg = mirc_colors[*bg % 16]; - if (*fg >= 0) *fg = mirc_colors[*fg % 16]; - if (settings_get_bool("mirc_blink_fix")) - *bg &= ~0x08; + /* mirc colors - extended colours proposal */ + if (*bg >= 0) { + *bg = mirc_colors[*bg % 100]; + flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + if (settings_get_bool("mirc_blink_fix")) + *bg = term_color256map[*bg&0xff] & ~0x08; + } + if (*fg >= 0) { + *fg = mirc_colors[*fg % 100]; + flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + } } - if (*fg < 0 || *fg > 15) + if (flags & GUI_PRINT_FLAG_COLOR_24_FG) + *attr |= ATTR_FGCOLOR24; + else if (*fg < 0 || *fg > 255) { *fg = -1; - if (*bg < 0 || *bg > 15) + *attr |= ATTR_RESETFG; + } + else + *attr |= *fg; + + if (flags & GUI_PRINT_FLAG_COLOR_24_BG) + *attr |= ATTR_BGCOLOR24; + else if (*bg < 0 || *bg > 255) { *bg = -1; + *attr |= ATTR_RESETBG; + } + else + *attr |= (*bg << BG_SHIFT); - *attr = 0; if (flags & GUI_PRINT_FLAG_REVERSE) *attr |= ATTR_REVERSE; + if (flags & GUI_PRINT_FLAG_ITALIC) *attr |= ATTR_ITALIC; if (flags & GUI_PRINT_FLAG_BOLD) *attr |= ATTR_BOLD; if (flags & GUI_PRINT_FLAG_UNDERLINE) *attr |= ATTR_UNDERLINE; if (flags & GUI_PRINT_FLAG_BLINK) *attr |= ATTR_BLINK; @@ -192,9 +218,7 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor, if (window == NULL) { g_return_if_fail(next_xpos != -1); - attr |= fg >= 0 ? fg : ATTR_RESETFG; - attr |= bg >= 0 ? (bg << 4) : ATTR_RESETBG; - term_set_color(root_window, attr); + term_set_color2(root_window, attr, fg, bg); term_move(root_window, next_xpos, next_ypos); if (flags & GUI_PRINT_FLAG_CLRTOEOL) diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 2f2f37d5..a77ded49 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -81,14 +81,24 @@ static int dirty, full_redraw, dummy; static GMainLoop *main_loop; int quitting; +static const char *banner_text = + " ___ _\n" + "|_ _|_ _ _____(_)\n" + " | || '_(_-<_-< |\n" + "|___|_| /__/__/_|\n" + "Irssi v" PACKAGE_VERSION " - http://www.irssi.org"; + static const char *firsttimer_text = - "Looks like this is the first time you've run irssi.\n" - "This is just a reminder that you really should go read\n" - "startup-HOWTO if you haven't already. You can find it\n" - "and more irssi beginner info at http://www.irssi.org\n" - "\n" - "For the truly impatient people who don't like any automatic\n" - "window creation or closing, just type: /MANUAL-WINDOWS"; + "- - - - - - - - - - - - - - - - - - - - - - - - - - - -\n" + "Hi there! If this is your first time using Irssi, you\n" + "might want to go to our website and read the startup\n" + "documentation to get you going.\n\n" + "Our community and staff are available to assist you or\n" + "to answer any questions you may have.\n\n" + "Use the HELP command to get detailed information about\n" + "the available commands.\n" + "- - - - - - - - - - - - - - - - - - - - - - - - - - - -"; + static int display_firsttimer = FALSE; @@ -193,9 +203,13 @@ static void textui_finish_init(void) fe_common_core_finish_init(); signal_emit("irssi init finished", 0); + statusbar_redraw(NULL, TRUE); + + printtext_window(active_win, MSGLEVEL_CRAP, + "%s", banner_text); if (display_firsttimer) { - printtext_window(active_win, MSGLEVEL_CLIENTNOTICE, + printtext_window(active_win, MSGLEVEL_CRAP, "%s", firsttimer_text); } } diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c index 68724293..5453c2d5 100644 --- a/src/fe-text/statusbar.c +++ b/src/fe-text/statusbar.c @@ -670,6 +670,8 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only, SERVER_REC *server; WI_ITEM_REC *wiitem; char *tmpstr, *tmpstr2; + theme_rm_col reset; + strcpy(reset.m, "n"); int len; if (str == NULL) @@ -690,7 +692,7 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only, /* expand templates */ tmpstr = theme_format_expand_data(current_theme, &str, - 'n', 'n', + reset, reset, NULL, NULL, EXPAND_FLAG_ROOT | EXPAND_FLAG_IGNORE_REPLACES | diff --git a/src/fe-text/term-curses.c b/src/fe-text/term-curses.c index fc674fd3..752edd7f 100644 --- a/src/fe-text/term-curses.c +++ b/src/fe-text/term-curses.c @@ -275,25 +275,32 @@ static int get_attr(int color) { int attr; + if ((color & FG_MASK) >> 4) + color = (color & ~FG_MASK) | term_color256map[color & FG_MASK]; + if ((color & BG_MASK) >> (BG_SHIFT + 4)) + color = (color & ~BG_MASK) | (term_color256map[(color & BG_MASK) >> BG_SHIFT] << BG_SHIFT); if (!term_use_colors) - attr = (color & 0x70) ? A_REVERSE : 0; - else if ((color & 0xff) == 8 || (color & (0xff | ATTR_RESETFG)) == 0) + attr = (color & (0x7 << BG_SHIFT)) ? A_REVERSE : 0; + else if ((color & ((0xf << BG_SHIFT) | 0xf)) == 8 || (color & (FG_MASK | BG_MASK | ATTR_RESETFG)) == 0) attr = COLOR_PAIR(63); - else if ((color & 0x77) == 0) + else if ((color & ((0x7 << BG_SHIFT) | 0x7)) == 0) attr = A_NORMAL; else { if (color & ATTR_RESETFG) { - color &= ~0x0f; + color &= ~FG_MASK; color |= settings_get_int("default_color"); } - attr = COLOR_PAIR((color&7) | ((color&0x70)>>1)); + attr = COLOR_PAIR((color&0x7) | ((color&(0x7<>BG_SHIFT<<3)); } - if ((color & 0x08) || (color & ATTR_BOLD)) attr |= A_BOLD; + if ((color & 0x8) || (color & ATTR_BOLD)) attr |= A_BOLD; if (color & ATTR_BLINK) attr |= A_BLINK; if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE; if (color & ATTR_REVERSE) attr |= A_REVERSE; +#ifdef A_ITALIC + if (color & ATTR_ITALIC) attr |= A_ITALIC; +#endif return attr; } diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c index 9dfc0db4..a0b257c4 100644 --- a/src/fe-text/term-terminfo.c +++ b/src/fe-text/term-terminfo.c @@ -22,9 +22,12 @@ #include "signals.h" #include "term.h" #include "terminfo-core.h" +#include "fe-windows.h" #include "utf8.h" #include +#include +#include /* returns number of characters in the beginning of the buffer being a a single character, or -1 if more input is needed. The character will be @@ -48,7 +51,8 @@ static int vcmove, vcx, vcy, curs_visible; static int crealx, crealy, cforcemove; static int curs_x, curs_y; -static int last_fg, last_bg, last_attrs; +static unsigned int last_fg, last_bg; +static int last_attrs; static GSource *sigcont_source; static volatile sig_atomic_t got_sigcont; @@ -136,7 +140,7 @@ int term_init(void) term_set_input_type(TERM_TYPE_8BIT); term_common_init(); - g_atexit(term_deinit); + atexit(term_deinit); return TRUE; } @@ -293,49 +297,88 @@ void term_window_scroll(TERM_WINDOW *window, int count) term_lines_empty[window->y+y] = FALSE; } +inline static int term_putchar(int c) +{ + return fputc(c, current_term->out); +} + +/* copied from terminfo-core.c */ +int tputs(); + +static int termctl_set_color_24bit(int bg, unsigned int lc) +{ + static char buf[20]; + const unsigned char color[] = { lc >> 16, lc >> 8, lc }; + + if (!term_use_colors24) { + if (bg) + terminfo_set_bg(color_24bit_256(color)); + else + terminfo_set_fg(color_24bit_256(color)); + return -1; + } + + /* \e[x8;2;...;...;...m */ + sprintf(buf, "\033[%d8;2;%d;%d;%dm", bg ? 4 : 3, color[0], color[1], color[2]); + return tputs(buf, 0, term_putchar); +} + +#define COLOR_RESET UINT_MAX + /* Change active color */ +#ifdef TERM_TRUECOLOR +void term_set_color2(TERM_WINDOW *window, int col, unsigned int fgcol24, unsigned int bgcol24) +#else void term_set_color(TERM_WINDOW *window, int col) +#endif { int set_normal; - int fg = col & 0x0f; - int bg = (col & 0xf0) >> 4; - set_normal = ((col & ATTR_RESETFG) && last_fg != -1) || - ((col & ATTR_RESETBG) && last_bg != -1); + unsigned int fg = +#ifdef TERM_TRUECOLOR + (col & ATTR_FGCOLOR24) ? fgcol24 << 8 : +#endif + (col & FG_MASK); + + unsigned int bg = +#ifdef TERM_TRUECOLOR + (col & ATTR_BGCOLOR24) ? bgcol24 << 8 : +#endif + ((col & BG_MASK) >> BG_SHIFT); + + if (!term_use_colors && bg > 0) + col |= ATTR_REVERSE; + + set_normal = ((col & ATTR_RESETFG) && last_fg != COLOR_RESET) || + ((col & ATTR_RESETBG) && last_bg != COLOR_RESET); if (((last_attrs & ATTR_BOLD) && (col & ATTR_BOLD) == 0) || + ((last_attrs & ATTR_REVERSE) && (col & ATTR_REVERSE) == 0) || ((last_attrs & ATTR_BLINK) && (col & ATTR_BLINK) == 0)) { - /* we'll need to get rid of bold/blink - this can only be - done with setting the default color */ + /* we'll need to get rid of bold/blink/reverse - this + can only be done with setting the default color */ set_normal = TRUE; } if (set_normal) { - last_fg = last_bg = -1; + last_fg = last_bg = COLOR_RESET; last_attrs = 0; terminfo_set_normal(); } - if (!term_use_colors && (col & 0xf0) != 0) - col |= ATTR_REVERSE; - - /* reversed text (use standout) */ - if (col & ATTR_REVERSE) { - if ((last_attrs & ATTR_REVERSE) == 0) - terminfo_set_standout(TRUE); - } else if (last_attrs & ATTR_REVERSE) - terminfo_set_standout(FALSE); - /* set foreground color */ if (fg != last_fg && (fg != 0 || (col & ATTR_RESETFG) == 0)) { if (term_use_colors) { last_fg = fg; - terminfo_set_fg(last_fg); + if (!(fg & 0xff)) + termctl_set_color_24bit(0, last_fg >> 8); + else + terminfo_set_fg(last_fg); } } /* set background color */ - if (col & 0x80 && window->term->TI_colors == 8) + if (window && (term_color256map[bg&0xff]&8) == window->term->TI_colors) col |= ATTR_BLINK; if (col & ATTR_BLINK) current_term->set_blink(current_term); @@ -344,12 +387,19 @@ void term_set_color(TERM_WINDOW *window, int col) (bg != 0 || (col & ATTR_RESETBG) == 0)) { if (term_use_colors) { last_bg = bg; - terminfo_set_bg(last_bg); + if (!(bg & 0xff)) + termctl_set_color_24bit(1, last_bg >> 8); + else + terminfo_set_bg(last_bg); } } + /* reversed text */ + if (col & ATTR_REVERSE) + terminfo_set_reverse(); + /* bold */ - if (col & 0x08 && window->term->TI_colors == 8) + if (window && (term_color256map[fg&0xff]&8) == window->term->TI_colors) col |= ATTR_BOLD; if (col & ATTR_BOLD) terminfo_set_bold(); @@ -361,7 +411,15 @@ void term_set_color(TERM_WINDOW *window, int col) } else if (last_attrs & ATTR_UNDERLINE) terminfo_set_uline(FALSE); - last_attrs = col & ~0xff; + /* italic */ + if (col & ATTR_ITALIC) { + if ((last_attrs & ATTR_ITALIC) == 0) + terminfo_set_italic(TRUE); + } else if (last_attrs & ATTR_ITALIC) + terminfo_set_italic(FALSE); + + /* update the new attribute settings whilst ignoring color values. */ + last_attrs = col & ~( BG_MASK | FG_MASK ); } void term_move(TERM_WINDOW *window, int x, int y) @@ -463,7 +521,7 @@ void term_clrtoeol(TERM_WINDOW *window) { /* clrtoeol() doesn't necessarily understand colors */ if (last_fg == -1 && last_bg == -1 && - (last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE)) == 0) { + (last_attrs & (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_ITALIC)) == 0) { if (!term_lines_empty[vcy]) { if (vcmove) term_move_real(); terminfo_clrtoeol(); @@ -522,7 +580,7 @@ void term_stop(void) static int input_utf8(const unsigned char *buffer, int size, unichar *result) { - unichar c = g_utf8_get_char_validated(buffer, size); + unichar c = g_utf8_get_char_validated((char *)buffer, size); switch (c) { case (unichar)-1: diff --git a/src/fe-text/term.c b/src/fe-text/term.c index 38239016..4600f02e 100644 --- a/src/fe-text/term.c +++ b/src/fe-text/term.c @@ -37,6 +37,7 @@ int term_width, term_height; int term_use_colors; +int term_use_colors24; int term_type; static int force_colors; @@ -106,10 +107,28 @@ static void cmd_redraw(void) irssi_redraw(); } +int term_color256map[] = { + 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15, + 0, 0, 1, 1, 1, 1, 0, 0, 3, 1, 1, 9, 2, 2, 3, 3, 3, 3, + 2, 2, 3, 3, 3, 3, 2, 2, 3, 3, 3,11,10,10, 3, 3,11,11, + 0, 0, 5, 1, 1, 9, 0, 8, 8, 8, 9, 9, 2, 8, 8, 8, 9, 9, + 2, 8, 8, 8, 9, 9, 2, 8, 8, 3, 3,11,10,10, 3, 3,11,11, + 4, 4, 5, 5, 5, 5, 4, 8, 8, 8, 9, 9, 6, 8, 8, 8, 9, 9, + 6, 8, 8, 8, 8, 9, 6, 8, 8, 8, 7, 7, 6, 6, 8, 7, 7, 7, + 4, 4, 5, 5, 5, 5, 4, 8, 8, 8, 9, 9, 6, 8, 8, 8, 8, 9, + 6, 8, 8, 8, 7, 7, 6, 6, 8, 7, 7, 7, 6, 6, 7, 7, 7, 7, + 4, 4, 5, 5, 5,13, 4, 8, 8, 5, 5,13, 6, 8, 8, 8, 7, 7, + 6, 6, 8, 7, 7, 7, 6, 6, 7, 7, 7, 7,14,14, 7, 7, 7, 7, + 12,12, 5, 5,13,13,12,12, 5, 5,13,13, 6, 6, 8, 7, 7, 7, + 6, 6, 7, 7, 7, 7,14,14, 7, 7, 7, 7,14,14, 7, 7, 7,15, + 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 0 }; + static void read_settings(void) { const char *str; int old_colors = term_use_colors; + int old_colors24 = term_use_colors24; int old_type = term_type; /* set terminal type */ @@ -133,7 +152,14 @@ static void read_settings(void) term_use_colors = settings_get_bool("colors") && (force_colors || term_has_colors()); - if (term_use_colors != old_colors) +#ifdef TERM_TRUECOLOR + term_use_colors24 = settings_get_bool("colors_ansi_24bit") && + (force_colors || term_has_colors()); +#else + term_use_colors24 = FALSE; +#endif + + if (term_use_colors != old_colors || term_use_colors24 != old_colors24) irssi_redraw(); } @@ -149,6 +175,12 @@ void term_common_init(void) force_colors = FALSE; term_use_colors = term_has_colors() && settings_get_bool("colors"); +#ifdef TERM_TRUECOLOR + settings_add_bool("lookandfeel", "colors_ansi_24bit", FALSE); + term_use_colors24 = term_has_colors() && settings_get_bool("colors_ansi_24bit"); +#else + term_use_colors24 = FALSE; +#endif read_settings(); if (g_get_charset(&dummy)) { diff --git a/src/fe-text/term.h b/src/fe-text/term.h index 27174c83..cdcc787a 100644 --- a/src/fe-text/term.h +++ b/src/fe-text/term.h @@ -3,17 +3,24 @@ typedef struct _TERM_WINDOW TERM_WINDOW; +#define FG_MASK ( 0x00ff ) +#define BG_MASK ( 0xff00 ) +#define BG_SHIFT 8 + /* text attributes */ -#define ATTR_RESETFG 0x0100 -#define ATTR_RESETBG 0x0200 -#define ATTR_BOLD 0x0400 -#define ATTR_BLINK 0x0800 -#define ATTR_UNDERLINE 0x1000 -#define ATTR_REVERSE 0x2000 +#define ATTR_RESETFG ( 0x010000 ) +#define ATTR_RESETBG ( 0x020000 ) +#define ATTR_BOLD ( 0x040000 ) +#define ATTR_BLINK ( 0x080000 ) +#define ATTR_UNDERLINE ( 0x100000 ) +#define ATTR_REVERSE ( 0x200000 ) +#define ATTR_ITALIC ( 0x400000 ) +#define ATTR_FGCOLOR24 ( 0x1000000 ) +#define ATTR_BGCOLOR24 ( 0x2000000 ) #define ATTR_RESET (ATTR_RESETFG|ATTR_RESETBG) -#define ATTR_NOCOLORS (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_BLINK|ATTR_BOLD) +#define ATTR_NOCOLORS (ATTR_UNDERLINE|ATTR_REVERSE|ATTR_BLINK|ATTR_BOLD|ATTR_ITALIC) /* terminal types */ #define TERM_TYPE_8BIT 0 /* normal 8bit text */ @@ -25,6 +32,8 @@ typedef guint32 unichar; extern TERM_WINDOW *root_window; extern int term_width, term_height; extern int term_use_colors, term_type; +extern int term_use_colors24; +extern int term_color256map[]; /* Initialize / deinitialize terminal */ int term_init(void); @@ -63,7 +72,13 @@ void term_window_clear(TERM_WINDOW *window); /* Scroll window up/down */ void term_window_scroll(TERM_WINDOW *window, int count); +#ifdef TERM_TRUECOLOR +#define term_set_color(window, col) term_set_color2(window, (col) &~(ATTR_FGCOLOR24|ATTR_BGCOLOR24), UINT_MAX, UINT_MAX) +void term_set_color2(TERM_WINDOW *window, int col, unsigned int fgcol24, unsigned int bgcol24); +#else +#define term_set_color2(window, col, unused1, unused2) term_set_color(window, col) void term_set_color(TERM_WINDOW *window, int col); +#endif void term_move(TERM_WINDOW *window, int x, int y); void term_addch(TERM_WINDOW *window, char chr); diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index bddc93e1..d16987fe 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -94,8 +94,11 @@ static TERMINFO_REC tcaps[] = { { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) }, { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) }, { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) }, + { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) }, + { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) }, { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) }, { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) }, + { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) }, { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) }, { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) }, { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) }, @@ -313,6 +316,12 @@ static void _set_blink(TERM_REC *term) tput(tparm(term->TI_blink)); } +/* Reverse on */ +static void _set_reverse(TERM_REC *term) +{ + tput(tparm(term->TI_rev)); +} + /* Bold on */ static void _set_bold(TERM_REC *term) { @@ -331,16 +340,41 @@ static void _set_standout(TERM_REC *term, int set) tput(tparm(set ? term->TI_smso : term->TI_rmso)); } +/* Italic on/off */ +static void _set_italic(TERM_REC *term, int set) +{ + tput(tparm(set ? term->TI_sitm : term->TI_ritm)); +} + +/* Standout on (fallback for reverse) */ +static void _set_standout_on(TERM_REC *term) +{ + _set_standout(term, TRUE); +} + +inline static int color256(const TERM_REC *term, const int color) { + if (color < term->TI_colors) + return color; + + if (color < 16) + return color % term->TI_colors; + + if (color < 256) + return term_color256map[color] % term->TI_colors; + + return color % term->TI_colors; +} + /* Change foreground color */ static void _set_fg(TERM_REC *term, int color) { - tput(tparm(term->TI_fg[color % term->TI_colors])); + tput(tparm(term->TI_fg[color256(term, color)])); } /* Change background color */ static void _set_bg(TERM_REC *term, int color) { - tput(tparm(term->TI_bg[color % term->TI_colors])); + tput(tparm(term->TI_bg[color256(term, color)])); } /* Beep */ @@ -596,13 +630,17 @@ static int term_setup(TERM_REC *term) else term->repeat = _repeat_manual; - /* Bold, underline, standout */ + /* Bold, underline, standout, reverse, italics */ term->set_blink = term->TI_blink ? _set_blink : _ignore; term->set_bold = term->TI_bold ? _set_bold : _ignore; + term->set_reverse = term->TI_rev ? _set_reverse : + term->TI_smso ? _set_standout_on : _ignore; term->set_uline = term->TI_smul && term->TI_rmul ? _set_uline : _ignore_parm; term->set_standout = term->TI_smso && term->TI_rmso ? _set_standout : _ignore_parm; + term->set_italic = term->TI_sitm && term->TI_ritm ? + _set_italic : _ignore_parm; /* Create a string to set all attributes off */ str = g_string_new(NULL); @@ -612,6 +650,8 @@ static int term_setup(TERM_REC *term) g_string_append(str, term->TI_rmul); if (term->TI_rmso && (term->TI_sgr0 == NULL || strcmp(term->TI_rmso, term->TI_sgr0) != 0)) g_string_append(str, term->TI_rmso); + if (term->TI_ritm && (term->TI_sgr0 == NULL || strcmp(term->TI_ritm, term->TI_sgr0) != 0)) + g_string_append(str, term->TI_ritm); term->TI_normal = str->str; g_string_free(str, FALSE); term->set_normal = _set_normal; diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h index 9e2b76d5..6ab4637d 100644 --- a/src/fe-text/terminfo-core.h +++ b/src/fe-text/terminfo-core.h @@ -16,6 +16,8 @@ #define terminfo_set_bold() current_term->set_bold(current_term) #define terminfo_set_uline(set) current_term->set_uline(current_term, set) #define terminfo_set_standout(set) current_term->set_standout(current_term, set) +#define terminfo_set_reverse() current_term->set_reverse(current_term) +#define terminfo_set_italic(set) current_term->set_italic(current_term, set) #define terminfo_is_colors_set(term) (term->TI_fg != NULL) #define terminfo_beep(term) current_term->beep(current_term) @@ -37,8 +39,10 @@ struct _TERM_REC { void (*set_normal)(TERM_REC *term); void (*set_blink)(TERM_REC *term); void (*set_bold)(TERM_REC *term); + void (*set_reverse)(TERM_REC *term); void (*set_uline)(TERM_REC *term, int set); void (*set_standout)(TERM_REC *term, int set); + void (*set_italic)(TERM_REC *term, int set); void (*beep)(TERM_REC *term); @@ -74,8 +78,9 @@ struct _TERM_REC { int TI_colors; /* numbers of colors in TI_fg[] and TI_bg[] */ const char *TI_sgr0; /* turn off all attributes */ const char *TI_smul, *TI_rmul; /* underline on/off */ - const char *TI_smso, *TI_rmso; /* standout on/off */ - const char *TI_bold, *TI_blink; + const char *TI_smso, *TI_rmso; /* standout on/off */ + const char *TI_sitm, *TI_ritm; /* italic on/off */ + const char *TI_bold, *TI_blink, *TI_rev; const char *TI_setaf, *TI_setab, *TI_setf, *TI_setb; /* Colors - generated and dynamically allocated */ diff --git a/src/fe-text/textbuffer-view.c b/src/fe-text/textbuffer-view.c index c19b9af7..2197c1df 100644 --- a/src/fe-text/textbuffer-view.c +++ b/src/fe-text/textbuffer-view.c @@ -22,6 +22,7 @@ #include "module.h" #include "textbuffer-view.h" +#include "signals.h" #include "utf8.h" typedef struct { @@ -104,8 +105,8 @@ static void textbuffer_cache_unref(TEXT_BUFFER_CACHE_REC *cache) textbuffer_cache_destroy(cache); } -#define FGATTR (ATTR_NOCOLORS | ATTR_RESETFG | 0x0f) -#define BGATTR (ATTR_NOCOLORS | ATTR_RESETBG | 0xf0) +#define FGATTR (ATTR_NOCOLORS | ATTR_RESETFG | FG_MASK | ATTR_FGCOLOR24) +#define BGATTR (ATTR_NOCOLORS | ATTR_RESETBG | BG_MASK | ATTR_BGCOLOR24) static void update_cmd_color(unsigned char cmd, int *color) { @@ -113,14 +114,16 @@ static void update_cmd_color(unsigned char cmd, int *color) if (cmd & LINE_COLOR_BG) { /* set background color */ *color &= FGATTR; + *color &= ~ATTR_FGCOLOR24; if ((cmd & LINE_COLOR_DEFAULT) == 0) - *color |= (cmd & 0x0f) << 4; + *color |= (cmd & 0x0f) << BG_SHIFT; else { *color = (*color & FGATTR) | ATTR_RESETBG; } } else { /* set foreground color */ *color &= BGATTR; + *color &= ~ATTR_BGCOLOR24; if ((cmd & LINE_COLOR_DEFAULT) == 0) *color |= cmd & 0x0f; else { @@ -140,22 +143,53 @@ static void update_cmd_color(unsigned char cmd, int *color) case LINE_CMD_BOLD: *color ^= ATTR_BOLD; break; + case LINE_CMD_ITALIC: + *color ^= ATTR_ITALIC; + break; case LINE_CMD_COLOR0: *color &= BGATTR; + *color &= ~ATTR_FGCOLOR24; break; } } +#ifdef TERM_TRUECOLOR +static void unformat_24bit_line_color(const unsigned char **ptr, int off, int *flags, unsigned int *fg, unsigned int *bg) +{ + unsigned int color; + unsigned char rgbx[4]; + unsigned int i; + for (i = 0; i < 4; ++i) { + rgbx[i] = (*ptr)[i + off]; + } + rgbx[3] -= 0x20; + *ptr += 4; + for (i = 0; i < 3; ++i) { + if (rgbx[3] & (0x10 << i)) + rgbx[i] -= 0x20; + } + color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2]; + if (rgbx[3] & 0x1) { + *flags = (*flags & FGATTR) | ATTR_BGCOLOR24; + *bg = color; + } + else { + *flags = (*flags & BGATTR) | ATTR_FGCOLOR24; + *fg = color; + } +} +#endif + static inline unichar read_unichar(const unsigned char *data, const unsigned char **next, int *width) { - unichar chr = g_utf8_get_char_validated(data, -1); + unichar chr = g_utf8_get_char_validated((const char *) data, -1); if (chr & 0x80000000) { chr = 0xfffd; *next = data + 1; *width = 1; } else { - *next = g_utf8_next_char(data); + *next = (unsigned char *)g_utf8_next_char(data); *width = unichar_isprint(chr) ? mk_wcwidth(chr) : 1; } return chr; @@ -171,6 +205,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) unsigned char cmd; const unsigned char *ptr, *next_ptr, *last_space_ptr; int xpos, pos, indent_pos, last_space, last_color, color, linecount; + unsigned int last_bg24, last_fg24, bg24, fg24; int char_width; g_return_val_if_fail(line->text != NULL, NULL); @@ -178,6 +213,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) color = ATTR_RESETFG | ATTR_RESETBG; xpos = 0; indent_pos = view->default_indent; last_space = last_color = 0; last_space_ptr = NULL; sub = NULL; + last_bg24 = last_fg24 = UINT_MAX; indent_func = view->default_indent_func; linecount = 1; @@ -204,7 +240,18 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) /* set indentation position here - don't do it if we're too close to right border */ if (xpos < view->width-5) indent_pos = xpos; - } else + } else if (cmd == LINE_COLOR_EXT) { + color &= ~ATTR_FGCOLOR24; + color = (color & BGATTR) | *ptr++; + } else if (cmd == LINE_COLOR_EXT_BG) { + color &= ~ATTR_BGCOLOR24; + color = (color & FGATTR) | (*ptr++ << BG_SHIFT); + } +#ifdef TERM_TRUECOLOR + else if (cmd == LINE_COLOR_24) + unformat_24bit_line_color(&ptr, 0, &color, &fg24, &bg24); +#endif + else update_cmd_color(cmd, &color); continue; } @@ -236,7 +283,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) sub = g_new0(LINE_CACHE_SUB_REC, 1); if (last_space > indent_pos && last_space > 10) { /* go back to last space */ - color = last_color; + color = last_color; fg24 = last_fg24; bg24 = last_bg24; ptr = last_space_ptr; while (*ptr == ' ') ptr++; } else if (view->longword_noindent) { @@ -249,6 +296,9 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) sub->indent = xpos; sub->indent_func = indent_func; sub->color = color; +#ifdef TERM_TRUECOLOR + sub->fg24 = fg24; sub->bg24 = bg24; +#endif lines = g_slist_append(lines, sub); linecount++; @@ -260,11 +310,11 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) if (!view->utf8 && char_width > 1) { last_space = xpos; last_space_ptr = next_ptr; - last_color = color; + last_color = color; last_fg24 = fg24; last_bg24 = bg24; } else if (*ptr == ' ') { last_space = xpos; last_space_ptr = ptr; - last_color = color; + last_color = color; last_fg24 = fg24; last_bg24 = bg24; } xpos += char_width; @@ -343,6 +393,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, unsigned char *tmp; unichar chr; int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width; +#ifdef TERM_TRUECOLOR + unsigned int fg24, bg24; +#endif if (view->dirty) /* don't bother drawing anything - redraw is coming */ return 0; @@ -377,6 +430,10 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, if (indent_func == NULL) xpos = cache->lines[subline-1].indent; color = cache->lines[subline-1].color; +#ifdef TERM_TRUECOLOR + fg24 = cache->lines[subline-1].fg24; + bg24 = cache->lines[subline-1].bg24; +#endif } else { indent_func = NULL; } @@ -397,7 +454,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, if (need_move || xpos > 0) term_move(view->window, xpos, ypos); - term_set_color(view->window, color); + term_set_color2(view->window, color, fg24, bg24); if (subline == cache->count-1) { text_newline = NULL; @@ -423,8 +480,17 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, text = tmp; continue; } else { - update_cmd_color(*text, &color); - term_set_color(view->window, color); + if (*text == LINE_COLOR_EXT) + color = (color & BGATTR & ~ATTR_FGCOLOR24) | *++text; + else if (*text == LINE_COLOR_EXT_BG) + color = (color & FGATTR & ~ATTR_BGCOLOR24) | (*++text << BG_SHIFT); +#ifdef TERM_TRUECOLOR + else if (*text == LINE_COLOR_24) + unformat_24bit_line_color(&text, 1, &color, &fg24, &bg24); +#endif + else + update_cmd_color(*text, &color); + term_set_color2(view->window, color, fg24, bg24); } text++; continue; @@ -455,7 +521,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, /* low-ascii */ term_set_color(view->window, ATTR_RESET|ATTR_REVERSE); term_addch(view->window, (chr & 127)+'A'-1); - term_set_color(view->window, color); + term_set_color2(view->window, color, fg24, bg24); } } text = end; diff --git a/src/fe-text/textbuffer-view.h b/src/fe-text/textbuffer-view.h index 46da808e..ab6786e0 100644 --- a/src/fe-text/textbuffer-view.h +++ b/src/fe-text/textbuffer-view.h @@ -15,6 +15,9 @@ typedef struct { int indent; INDENT_FUNC indent_func; int color; +#ifdef TERM_TRUECOLOR + unsigned int fg24, bg24; +#endif /* first word in line belong to the end of the last word in previous line */ diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 69f5969c..24ee62bc 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -39,8 +39,8 @@ TEXT_BUFFER_REC *textbuffer_create(void) buffer = g_slice_new0(TEXT_BUFFER_REC); buffer->last_eol = TRUE; - buffer->last_fg = LINE_COLOR_DEFAULT; - buffer->last_bg = LINE_COLOR_DEFAULT | LINE_COLOR_BG; + buffer->last_fg = -1; + buffer->last_bg = -1; return buffer; } @@ -148,6 +148,7 @@ static void text_chunk_append(TEXT_BUFFER_REC *buffer, { TEXT_CHUNK_REC *chunk; int left; + int i; if (len == 0) return; @@ -166,8 +167,12 @@ static void text_chunk_append(TEXT_BUFFER_REC *buffer, } } - if (left > 0 && data[left-1] == 0) - left--; /* don't split the commands */ + for (i = 5; i > 0; --i) { + if (left >= i && data[left-i] == 0) { + left -= i; /* don't split the commands */ + break; + } + } memcpy(chunk->buffer + chunk->pos, data, left); chunk->pos += left; @@ -238,26 +243,67 @@ int textbuffer_line_exists_after(LINE_REC *line, LINE_REC *search) return FALSE; } +#ifdef TERM_TRUECOLOR +static void format_24bit_line_color(unsigned char *out, int *pos, int bg, unsigned int color) +{ + unsigned char rgb[] = { color >> 16, color >> 8, color }; + unsigned char x = bg ? 0x1 : 0; + unsigned int i; + out[(*pos)++] = LINE_COLOR_24; + for (i = 0; i < 3; ++i) { + if (rgb[i] > 0x20) + out[(*pos)++] = rgb[i]; + else { + out[(*pos)++] = 0x20 + rgb[i]; + x |= 0x10 << i; + } + } + out[(*pos)++] = 0x20 + x; +} +#endif + void textbuffer_line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line, int fg, int bg, int flags) { - unsigned char data[20]; + unsigned char data[22]; int pos; - /* get the fg & bg command chars */ - fg = fg < 0 ? LINE_COLOR_DEFAULT : fg & 0x0f; - bg = LINE_COLOR_BG | (bg < 0 ? LINE_COLOR_DEFAULT : bg & 0x0f); - pos = 0; - if (fg != buffer->last_fg) { + if (fg != buffer->last_fg + || (flags & GUI_PRINT_FLAG_COLOR_24_FG) != (buffer->last_flags & GUI_PRINT_FLAG_COLOR_24_FG)) { buffer->last_fg = fg; data[pos++] = 0; - data[pos++] = fg == 0 ? LINE_CMD_COLOR0 : fg; +#ifdef TERM_TRUECOLOR + if (flags & GUI_PRINT_FLAG_COLOR_24_FG) + format_24bit_line_color(data, &pos, 0, fg); + else +#endif + if (fg < 0) + data[pos++] = LINE_COLOR_DEFAULT; + else if (fg < 16) + data[pos++] = fg == 0 ? LINE_CMD_COLOR0 : fg; + else if (fg < 256) { + data[pos++] = LINE_COLOR_EXT; + data[pos++] = fg; + } } - if (bg != buffer->last_bg) { + if (bg != buffer->last_bg + || (flags & GUI_PRINT_FLAG_COLOR_24_BG) != (buffer->last_flags & GUI_PRINT_FLAG_COLOR_24_BG)) { buffer->last_bg = bg; data[pos++] = 0; - data[pos++] = bg; +#ifdef TERM_TRUECOLOR + if (flags & GUI_PRINT_FLAG_COLOR_24_BG) + format_24bit_line_color(data, &pos, 1, bg); + else +#endif + if (bg < 0) + data[pos++] = LINE_COLOR_BG | LINE_COLOR_DEFAULT; + else if (bg < 16) + data[pos++] = LINE_COLOR_BG | bg; + else if (bg < 256) { + data[pos++] = LINE_COLOR_EXT_BG; + data[pos++] = bg; + } } if ((flags & GUI_PRINT_FLAG_UNDERLINE) != (buffer->last_flags & GUI_PRINT_FLAG_UNDERLINE)) { @@ -276,6 +322,10 @@ void textbuffer_line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line, data[pos++] = 0; data[pos++] = LINE_CMD_BOLD; } + if ((flags & GUI_PRINT_FLAG_ITALIC) != (buffer->last_flags & GUI_PRINT_FLAG_ITALIC)) { + data[pos++] = 0; + data[pos++] = LINE_CMD_ITALIC; + } if (flags & GUI_PRINT_FLAG_INDENT) { data[pos++] = 0; data[pos++] = LINE_CMD_INDENT; @@ -318,8 +368,8 @@ LINE_REC *textbuffer_insert(TEXT_BUFFER_REC *buffer, LINE_REC *insert_after, data[len-2] == 0 && data[len-1] == LINE_CMD_EOL; if (buffer->last_eol) { - buffer->last_fg = LINE_COLOR_DEFAULT; - buffer->last_bg = LINE_COLOR_DEFAULT | LINE_COLOR_BG; + buffer->last_fg = -1; + buffer->last_bg = -1; buffer->last_flags = 0; } @@ -427,10 +477,17 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str) if (!coloring) { /* no colors, skip coloring commands */ + if (cmd == LINE_COLOR_EXT || cmd == LINE_COLOR_EXT_BG) + ptr++; +#ifdef TERM_TRUECOLOR + else if (cmd == LINE_COLOR_24) + ptr+=4; +#endif + continue; } - if ((cmd & 0x80) == 0) { + if ((cmd & LINE_CMD_EOL) == 0) { /* set color */ set_color(str, cmd); } else switch (cmd) { @@ -448,6 +505,10 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str) g_string_append_printf(str, "\004%c", FORMAT_STYLE_BOLD); break; + case LINE_CMD_ITALIC: + g_string_append_printf(str, "\004%c", + FORMAT_STYLE_ITALIC); + break; case LINE_CMD_COLOR0: g_string_append_printf(str, "\004%c%c", '0', FORMAT_COLOR_NOCHANGE); @@ -456,6 +517,17 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str) g_string_append_printf(str, "\004%c", FORMAT_STYLE_INDENT); break; + case LINE_COLOR_EXT: + format_ext_color(str, 0, *ptr++); + break; + case LINE_COLOR_EXT_BG: + format_ext_color(str, 1, *ptr++); + break; +#ifdef TERM_TRUECOLOR + case LINE_COLOR_24: + g_string_append_printf(str, "\004%c", FORMAT_COLOR_24); + break; +#endif } } } diff --git a/src/fe-text/textbuffer.h b/src/fe-text/textbuffer.h index e5d78487..eacfd447 100644 --- a/src/fe-text/textbuffer.h +++ b/src/fe-text/textbuffer.h @@ -17,6 +17,12 @@ enum { LINE_CMD_INDENT, /* if line is split, indent it at this position */ LINE_CMD_BLINK, /* enable/disable blink */ LINE_CMD_BOLD, /* enable/disable bold */ + LINE_CMD_ITALIC, /* enable/disable italic */ + LINE_COLOR_EXT, /* extended color */ + LINE_COLOR_EXT_BG, /* extended bg */ +#ifdef TERM_TRUECOLOR + LINE_COLOR_24, /* 24bit color */ +#endif }; typedef struct { diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index e5f86c20..13784f88 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -51,6 +51,12 @@ #define DEFAULT_CMDS_MAX_AT_ONCE 5 #define DEFAULT_MAX_QUERY_CHANS 1 /* more and more IRC networks are using stupid ircds.. */ +/* + * 63 is the maximum hostname length defined by the protocol. 10 is a common + * username limit on many networks. 1 is for the `@'. + */ +#define MAX_USERHOST_LEN (63 + 10 + 1) + void irc_servers_reconnect_init(void); void irc_servers_reconnect_deinit(void); @@ -74,6 +80,72 @@ static int ischannel_func(SERVER_REC *server, const char *data) return ischannel(*data); } +static char **split_line(const SERVER_REC *server, const char *line, + const char *target, int len) +{ + const char *start = settings_get_str("split_line_start"); + const char *end = settings_get_str("split_line_end"); + char *recoded_start = recode_out(server, start, target); + char *recoded_end = recode_out(server, end, target); + char **lines; + int i; + + /* + * Having the same length limit on all lines will make the first line + * shorter than necessary if `split_line_start' is set, but it makes + * the code much simpler. It's worth it. + */ + len -= strlen(recoded_start) + strlen(recoded_end); + if (len <= 0) { + /* There is no room for anything. */ + g_free(recoded_start); + g_free(recoded_end); + return NULL; + } + + lines = recode_split(server, line, target, len); + for (i = 0; lines[i] != NULL; i++) { + if (i != 0 && *start != '\0') { + /* Not the first line. */ + char *tmp = lines[i]; + lines[i] = g_strconcat(start, tmp, NULL); + g_free(tmp); + } + if (lines[i + 1] != NULL && *end != '\0') { + /* Not the last line. */ + char *tmp = lines[i]; + + if (lines[i + 2] == NULL) { + /* Next to last line. Check if we have room + * to append the last line to the current line, + * to avoid an unnecessary line break. + */ + char *recoded_l = recode_out(server, + lines[i+1], + target); + if (strlen(recoded_l) <= strlen(recoded_end)) { + lines[i] = g_strconcat(tmp, lines[i+1], + NULL); + g_free_and_null(lines[i+1]); + lines = g_renew(char *, lines, i + 2); + + g_free(recoded_l); + g_free(tmp); + break; + } + g_free(recoded_l); + } + + lines[i] = g_strconcat(tmp, end, NULL); + g_free(tmp); + } + } + + g_free(recoded_start); + g_free(recoded_end); + return lines; +} + static void send_message(SERVER_REC *server, const char *target, const char *msg, int target_type) { @@ -102,6 +174,30 @@ static void send_message(SERVER_REC *server, const char *target, g_free(recoded); } +static char **split_message(SERVER_REC *server, const char *target, + const char *msg) +{ + IRC_SERVER_REC *ircserver = IRC_SERVER(server); + int userhostlen = MAX_USERHOST_LEN; + + g_return_val_if_fail(ircserver != NULL, NULL); + g_return_val_if_fail(target != NULL, NULL); + g_return_val_if_fail(msg != NULL, NULL); + + /* + * If we have joined a channel, userhost will be set, so we can + * calculate the exact maximum length. + */ + if (ircserver->userhost != NULL) + userhostlen = strlen(ircserver->userhost); + + /* length calculation shamelessly stolen from splitlong.pl */ + return split_line(SERVER(server), msg, target, + 510 - strlen(":! PRIVMSG :") - + strlen(ircserver->nick) - userhostlen - + strlen(target)); +} + static void server_init(IRC_SERVER_REC *server) { IRC_SERVER_CONNECT_REC *conn; @@ -288,6 +384,7 @@ static void sig_connected(IRC_SERVER_REC *server) server->isnickflag = isnickflag_func; server->ischannel = ischannel_func; + server->split_message = split_message; server->send_message = send_message; server->query_find_func = (QUERY_REC *(*)(SERVER_REC *, const char *)) irc_query_find; @@ -358,6 +455,23 @@ void irc_server_send_action(IRC_SERVER_REC *server, const char *target, const ch g_free(recoded); } +char **irc_server_split_action(IRC_SERVER_REC *server, const char *target, + const char *data) +{ + int userhostlen = MAX_USERHOST_LEN; + + g_return_val_if_fail(server != NULL, NULL); + g_return_val_if_fail(target != NULL, NULL); + g_return_val_if_fail(data != NULL, NULL); + + if (server->userhost != NULL) + userhostlen = strlen(server->userhost); + + return split_line(SERVER(server), data, target, + 510 - strlen(":! PRIVMSG :\001ACTION \001") - + strlen(server->nick) - userhostlen - strlen(target)); +} + void irc_server_send_away(IRC_SERVER_REC *server, const char *reason) { char *recoded = NULL; @@ -866,6 +980,8 @@ void irc_server_init_isupport(IRC_SERVER_REC *server) void irc_servers_init(void) { settings_add_str("misc", "usermode", DEFAULT_USER_MODE); + settings_add_str("misc", "split_line_start", ""); + settings_add_str("misc", "split_line_end", ""); settings_add_time("flood", "cmd_queue_speed", DEFAULT_CMD_QUEUE_SPEED); settings_add_int("flood", "cmds_max_at_once", DEFAULT_CMDS_MAX_AT_ONCE); diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index 8c9c1cd7..7e4eeabf 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -117,7 +117,10 @@ void irc_server_purge_output(IRC_SERVER_REC *server, const char *target); char *irc_server_get_channels(IRC_SERVER_REC *server); /* INTERNAL: */ -void irc_server_send_action(IRC_SERVER_REC *server, const char *target, const char *data); +void irc_server_send_action(IRC_SERVER_REC *server, const char *target, + const char *data); +char **irc_server_split_action(IRC_SERVER_REC *server, const char *target, + const char *data); void irc_server_send_away(IRC_SERVER_REC *server, const char *reason); void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len); void irc_server_init_isupport(IRC_SERVER_REC *server); diff --git a/src/perl/textui/Statusbar.xs b/src/perl/textui/Statusbar.xs index d904ae9f..620fad9a 100644 --- a/src/perl/textui/Statusbar.xs +++ b/src/perl/textui/Statusbar.xs @@ -50,7 +50,6 @@ static void perl_statusbar_event(char *function, SBAR_ITEM_REC *item, int get_size_only) { dSP; - int retcount; SV *item_sv, **sv; HV *hv; @@ -63,7 +62,7 @@ static void perl_statusbar_event(char *function, SBAR_ITEM_REC *item, XPUSHs(sv_2mortal(newSViv(get_size_only))); PUTBACK; - retcount = perl_call_pv(function, G_EVAL|G_DISCARD); + perl_call_pv(function, G_EVAL|G_DISCARD); SPAGAIN; if (SvTRUE(ERRSV)) { diff --git a/src/perl/ui/Themes.xs b/src/perl/ui/Themes.xs index dc5f6272..ab7c1909 100644 --- a/src/perl/ui/Themes.xs +++ b/src/perl/ui/Themes.xs @@ -241,8 +241,11 @@ PPCODE: if (flags == 0) { ret = theme_format_expand(theme, format); } else { - ret = theme_format_expand_data(theme, (const char **) &format, 'n', 'n', - NULL, NULL, EXPAND_FLAG_ROOT | flags); + theme_rm_col reset; + strcpy(reset.m, "n"); + ret = theme_format_expand_data(theme, (const char **) &format, + reset, reset, NULL, NULL, + EXPAND_FLAG_ROOT | flags); } XPUSHs(sv_2mortal(new_pv(ret))); g_free_not_null(ret);