Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jari Matilainen 2014-07-08 00:02:56 +02:00
commit 99736a865d
109 changed files with 3017 additions and 1020 deletions

10
.gitignore vendored
View file

@ -25,6 +25,11 @@ lt~obsolete.m4
pm_to_blib pm_to_blib
stamp-h1 stamp-h1
docs/help/Makefile.am
docs/help/[a-z]*
!docs/help/in
docs/help/in/Makefile.am
src/fe-text/irssi src/fe-text/irssi
src/fe-common/irc/irc-modules.c src/fe-common/irc/irc-modules.c
@ -37,17 +42,18 @@ src/perl/common/*.c
src/perl/irc/*.c src/perl/irc/*.c
src/perl/textui/*.c src/perl/textui/*.c
src/perl/ui/*.c src/perl/ui/*.c
src/perl/*/MYMETA.*
src/perl/*/Makefile.old
*.a *.a
*.bs *.bs
*.la *.la
*.lo *.lo
*.o *.o
*~
*.tar.bz2 *.tar.bz2
*.tar.gz *.tar.gz
.deps .deps
.libs .libs
docs/help

View file

@ -78,3 +78,6 @@ Other patches (grep for "patch" in ChangeLog) by:
Ismael Luceno Ismael Luceno
Thomas Karpiniec Thomas Karpiniec
Svante Kvarnström Svante Kvarnström
Ailin Nemui (Nei)
Tom Feist (shabble)
Sebastian Thorarensen

View file

@ -1,4 +1,4 @@
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
# create default-config.h # create default-config.h
BUILT_SOURCES = default-config.h default-theme.h irssi-version.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 = \ EXTRA_DIST = \
ChangeLog \ ChangeLog \
autogen.sh \ autogen.sh \
curses.m4 \ README.md \
README \
file2header.sh \ file2header.sh \
$(conf_DATA) \ $(conf_DATA) \
$(theme_DATA) \ $(theme_DATA) \

5
NEWS
View file

@ -4,6 +4,11 @@ v0.8.17-head 2014-xx-xx The Irssi team <staff@irssi.org>
+ Performance enhancement of the nicklist as well as the window_item_find function. See Github PR #24. + Performance enhancement of the nicklist as well as the window_item_find function. See Github PR #24.
+ Disallow unloading of static modules. + Disallow unloading of static modules.
+ Allow UTF-8 characters in /bind. See Github PR #18. + 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 various compiler warnings.
- Fixed format_get_text Perl API. See Github PR #23. - Fixed format_get_text Perl API. See Github PR #23.
- Fixed gui_printtext_after and term_refresh_*() visibility. See Github PR #22. - Fixed gui_printtext_after and term_refresh_*() visibility. See Github PR #22.

View file

@ -2,11 +2,16 @@
[![Build Status](https://travis-ci.org/irssi/irssi.svg?branch=master)](https://travis-ci.org/irssi/irssi) [![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, Irssi is a modular chat client that is most commonly known for its
but 80-90% of the code isn't text mode specific, so other UIs could be created text mode user interface, but 80% of the code isn't text mode
pretty easily. Also, Irssi isn't really even IRC specific anymore, there's specific. We have a working but currently unmaintained GTK2 frontend
already a working [SILC](http://www.silcnet.org/) module available. Support for called xirssi. Irssi comes with IRC support built in, and there are
other protocols like ICQ could be created some day too. 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 ## Installation

View file

@ -166,6 +166,15 @@ AC_ARG_ENABLE(dane,
fi, fi,
want_dane=no) 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 **
dnl ** SSL Library checks (OpenSSL) dnl ** SSL Library checks (OpenSSL)
dnl ** dnl **
@ -212,7 +221,7 @@ AC_CACHE_VAL(irssi_cv_type_socklen_t,
[AC_TRY_COMPILE([ [AC_TRY_COMPILE([
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>], #include <sys/socket.h>],
[socklen_t t;], [socklen_t t = 0; return((int)t); ],
irssi_cv_type_socklen_t=yes, irssi_cv_type_socklen_t=yes,
irssi_cv_type_socklen_t=no, 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 "*** We recommend you get the latest stable GLIB 2 version."
echo "*** Compile and install it, and make sure pkg-config finds it," 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 "*** 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 echo
AC_ERROR([GLIB is required to build irssi.]) AC_ERROR([GLIB is required to build irssi.])
@ -375,7 +393,7 @@ if test "x$want_textui" = "xyes"; then
TEXTUI_LIBS="-ltermcap" TEXTUI_LIBS="-ltermcap"
want_termcap=yes 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 want_textui=no
]))) ])))
fi fi
@ -446,8 +464,10 @@ if test "$want_perl" != "no"; then
esac esac
dnl * check that perl's ldflags actually work dnl * check that perl's ldflags actually work
echo "main(){perl_alloc(); return 0;}" > conftest.c echo "#include <EXTERN.h>" > conftest.c
$CC $CFLAGS conftest.c -o conftest $LDFLAGS $PERL_LDFLAGS 2> perl.error.tmp > /dev/null echo "#include <perl.h>" >> 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 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`" 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]) AC_MSG_RESULT([error linking with perl libraries, building without Perl])
@ -617,7 +637,7 @@ if test "x$want_ipv6" = "xyes"; then
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#include <arpa/inet.h>], #include <arpa/inet.h>],
[struct in6_addr i;], [struct in6_addr i = in6addr_any; return &i == &i;],
have_ipv6=yes, have_ipv6=yes,
)]) )])
if test $have_ipv6 = yes; then if test $have_ipv6 = yes; then
@ -643,6 +663,12 @@ if test "x$want_dane" = "xyes"; then
fi fi
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([ AC_CONFIG_FILES([
Makefile Makefile
src/Makefile src/Makefile
@ -724,6 +750,11 @@ else
else else
echo "Building with Perl support ....... : NO!" echo "Building with Perl support ....... : NO!"
echo " - $perl_check_error" 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
fi fi
@ -733,7 +764,7 @@ if test "x$want_perl" != "xno" -a "x$perl_mod_error" != "x"; then
echo " $perl_mod_error" echo " $perl_mod_error"
if test -f /etc/debian_version; then if test -f /etc/debian_version; then
echo " - Try: apt-get install libperl-dev" echo " - Try: sudo apt-get install libperl-dev"
fi fi
fi fi
@ -758,9 +789,19 @@ echo
echo "Building with IPv6 support ....... : $have_ipv6" echo "Building with IPv6 support ....... : $have_ipv6"
echo "Building with SSL support ........ : $have_openssl" 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 64bit DCC support .. : $offt_64bit"
echo "Building with garbage collector .. : $have_gc" echo "Building with garbage collector .. : $have_gc"
echo "Building with DANE support ....... : $have_dane" echo "Building with DANE support ....... : $have_dane"
echo "Building with true color support.. : $want_truecolor"
echo echo
echo "If there are any problems, read the INSTALL file." echo "If there are any problems, read the INSTALL file."

View file

@ -23,10 +23,13 @@
%U Underline on/off %U Underline on/off
%8 Reverse on/off %8 Reverse on/off
%9 %_ Bold on/off %9 %_ Bold on/off
%I Italic on/off
%: Insert newline %: Insert newline
%| Marks the indentation position %| Marks the indentation position
%# Monospace font on/off (useful with lists and GUI) %# Monospace font on/off (useful with lists and GUI)
%% A single % %% 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 In .theme files %n works a bit differently. See default.theme
for more information. for more information.

View file

@ -1,28 +1,30 @@
%9Syntax:%9
@SYNTAX:accept@ @SYNTAX:accept@
MODE <your nick> <+|->g
Works only in some IRC networks. %9Parameters:%9
ACCEPT allows you to specify who you want to receive private messages A comma-separated list of nicknames to add or remove; if no argument is
and notices from while you are in callerid (+g) mode. given, your accept list will be displayed.
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.
The accept list is lost when you disconnect. %9Description:%9
Users are automatically removed from the accept list if they quit, split
or change nick.
The argument is a comma-separated list of nicks to add or (when prefixed Allows you to specify who you want to receive private messages and notices
with a '-') to remove. No output is returned for users successfully added from while you have callerid enabled.
or removed.
If no arguments are given, your accept list is displayed (ACCEPT * on the
protocol level).
Example: When you have callerid enabled, messages from other users are blocked and
/ACCEPT user1,user2,-user3,-user4 - Adds user1 and user2 and removes the sender is notified.
user3 and user4.
See also: IGNORE, SILENCE 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

View file

@ -1,9 +1,23 @@
%9Syntax:%9
@SYNTAX:action@ @SYNTAX:action@
Same as ME, but gets channel or nick as an additional parameter. %9Parameters:%9
Example: /ACTION #irssi yawns
(This outputs the following to #irssi: * Nick yawns)
See also: ME -<server tag>: 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

View file

@ -1,8 +1,22 @@
%9Syntax:%9
@SYNTAX:admin@ @SYNTAX:admin@
Displays the administrative details about the given server. If %9Parameters:%9
no server is specified, the server you are connected to is
used. If a nickname is supplied then it gives the administrative A nickname or server for which you want to know the administrative details;
information for that person's current server. 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

View file

@ -1,22 +1,33 @@
%9Syntax:%9
@SYNTAX:alias@ @SYNTAX:alias@
Creates a new alias or shows matching defined aliases. Without %9Parameters:%9
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.
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 %9Description:%9
- shows all defined aliases starting with letter w.
/ALIAS send echo Sending file $1 to $0;dcc send $0- Creates or updates an alias; you can use the ";" character to separate
- creates alias 'send'. multiple commands.
/ALIAS -send The parametesr given to the alias are expanded in "$[\d]" For example $0,
- removes alias 'send'. $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

View file

@ -1,28 +1,33 @@
%9Syntax:%9
@SYNTAX:away@ @SYNTAX:away@
-one %9Parameters:%9
-all
This command marks you as being "away". It is used to tell people that -one: Marks yourself as away on the active server.
you currently aren't paying attention to your screen. You might use it -all: Marks yourself as away on all the servers you are connected to.
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.
Anyone who does a WHOIS on your nickname will see that you are away, You away message; if no argument is given, your away status will be removed.
as well as your away message. Anyone doing a WHO that returns information
about you will also see that you're gone.
By default, if someone sends you a MSG while you are away, your client %9Description:%9
will beep. You can turn this off by setting BEEP_WHEN_AWAY to OFF.
If you send a MSG to someone who is away, you will automatically be Marks yourself as "away"; this method is used to inform people that you
notified of this. By default, you will only receive this notification are not paying attention to your screen.
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 can remove your away status by using AWAY with no arguments. 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.
See also: SET AWAY Anyone who does a WHOIS on your nickname will see that you are away, as
well as your away message.
%9Examples:%9
/AWAY
/AWAY I'm getting some food.
/AWAY zZzZ
/AWAY -one Feeding the cat!
%9See also:%9 DISCONNECT

View file

@ -1,27 +1,42 @@
%9Syntax:%9
@SYNTAX:ban@ @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 -normal: Uses the *!*user@*.domain.tld format.
mask. /SET ban_type specified the default ban type. Ban type is one of -user: Uses the *!*user@* format.
the following: -host: Uses the *!*@host.domain.tld format.
-domain: Uses the *!*@*.domain.tld format.
-custom: Uses the custom format.
Normal - *!*user@*.domain.net A channel and the nicknames or hostnames to ban; if no arguments are given
User - *!*user@* the bans in the active channel are displayed.
Host - *!*@host.domain.net
Domain - *!*@*.domain.net
Custom [nick] [user] [host] [domain]
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: %9Description:%9
/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.
/SET ban_type custom nick domain - nick!*@*.domain.net Adds one or more bans to a channel.
/SET ban_type custom user host - *!user@host.domain.net
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

View file

@ -1,6 +1,15 @@
%9Syntax:%9
@SYNTAX:beep@ @SYNTAX:beep@
Outputs the bell-character, usually causing %9Description:%9
your terminal beep.
Outputs the bell-character, usually causing your terminal to beep.
%9Examples:%9
/BEEP
%9See also:%9 CLEAR

View file

@ -1,48 +1,34 @@
%9Syntax:%9
@SYNTAX:bind@ @SYNTAX:bind@
Bind some action to specified keystroke. Remember that all characters %9Parameters:%9
in keystrokes are case-sensitive! Uppercase letter usually means that
you need to keep SHIFT pressed to get the key to work.
Most most commonly used keystrokes are: -list: Displays a list of all the bindable commands.
-delete: Removes the binding,
^X - Ctrl-X A name of the binding and the command to perform; if no parameter is given,
meta-x - Meta-x (Meta is quite often Alt-key in PCs, ESC-x works too) 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 Adds or removes a binding; the binding itself is case-sensitive and may
space, backspace - Space / backspace contain as many characters as you want.
up, down, left, right - Arrow keys
cleft, cright - Ctrl-left/right
home, end, prior, next - prior = Page Up, next = Page Down
insert, delete
The keystroke can contain as many key presses as you want, and you can Uppercase characters usually indicate that you need to keep the shift-key
define names for different key sequences to use them more easily (the pressed to use the binding.
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:
/BIND ^W^C /WINDOW NEW HIDE %9Examples:%9
/BIND ^W^K /WINDOW KILL
But maybe you wish to give these binds to other people who want to use /BIND
some other key than ^W, then it would be better done as: /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 %9See also:%9 ALIAS
/BIND window-^C /WINDOW NEW HIDE
/BIND window-^K /WINDOW KILL
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

View file

@ -1,8 +1,21 @@
%9Syntax:%9
@SYNTAX:cat@ @SYNTAX:cat@
Outputs the contents of the specified file. Equivalent to %9Parameters:%9
UNIX 'cat' command.
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

View file

@ -1,8 +1,21 @@
%9Syntax:%9
@SYNTAX:cd@ @SYNTAX:cd@
Changes the current working directory. Equivalent to UNIX %9Parameters:%9
'cd' command.
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

View file

@ -1,35 +1,46 @@
%9Syntax:%9
@SYNTAX:channel@ @SYNTAX:channel@
Irssi can automatically join to specified channels in specified %9Parameters:%9
IRC networks. It can also automatically send the password when
manually joining to channel without specifying the password.
/CHANNEL ADD [-auto | -noauto] [-bots <masks>] [-botcmd <command>] LIST: Displays the list of configured channels.
<channel> <network> [<password>] ADD: Adds a channel to your configuration.
REMOVE: Removes a channel from your configuration.
With -bots and -botcmd arguments you can automatically send -auto: Automatically join the channel.
commands to someone in channel. This is useful for automatically -noauto: Don't join the channel automatically.
getting ops for channels, for example -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" The channel and network to add to the configuration; you can optionally
-botcmd "msg $0 op mypass" #channel ircnet specify the password of a channel.
You can also use the -botcmd without -bots argument. The command is If no parameters are given, the list of channels you have joined will be
then sent whenever you join the channel. displayed.
If you want to remove some settings from existing channel record, %9Description:%9
for example bots, just give the -bots "" parameters to it. Password
can be removed by setting it to - (or actually, "" works too).
You can remove the channels with Adds, removes or displays the configuration of channels; this method is
/CHANNEL REMOVE <channel> <network> used to automate and simplify your workflow.
/CHANNEL LIST displays list of channels with settings. You can use the ADDALLCHANS command, which is a default alias, to add all
the channels you are present on into the configuration.
/CHANNEL without any arguments displays list of channels you have %9Examples:%9
joined. You can also use /CHANNEL to join to channels just as with
/JOIN, like /CHANNEL #a.
See also: TS, JOIN /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
%9Special Example:%9
/ADDALLCHANS
%9See also:%9 JOIN, TS

View file

@ -1,9 +1,19 @@
%9Syntax:%9
@SYNTAX:clear@ @SYNTAX:clear@
This command clears the current window of all text. It is useful %9Parameters:%9
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).
-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

View file

@ -1,31 +1,34 @@
%9Syntax:%9
@SYNTAX:completion@ @SYNTAX:completion@
Irssi can "complete" some words for you - you can write just first few letters %9Parameters:%9
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.
The words chosen usually depend on their context - they can be filenames or -auto: Inserts the completion without pressing a word completion character.
command names, but most frequently they are nicks of people on same channels as -delete: Removes the completion from the configuration.
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.
Without any parameters, /COMPLETION displays list of all user completions. A key and the value to use as a replacement. If no argument is given, the
list of completions will be displayed.
/COMPLETION [-auto] <prefix> <string> adds completion which gets triggered when %9Description:%9
you press TAB (or any other key with action word_completion assigned) after
writing <prefix> specified and which expands to <string>. 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 <prefix>. If
there's already some <prefix> completion in the list, it will get replaced.
/COMPLETION -delete <prefix> removes completion of <prefix> from the user Replaces or completed words or letters; you can write just the first few
completion list. letters of the word and press TAB to insert a replacement.
Note: When -auto is specified for the <prefix> you want to remove you have to When a replacement has been found, Irssi will choose the most probable
quote it like /COMPLETION -delete '<prefix>'. Works with doublequotes aswell. matching word and replaces it; you may press TAB repeatedly to swap between
matches.
See also: BIND If you want to remove a completion which has the auto parameter set, you
need to enclose the completion between "'" characters.
%9Examples:%9
/COMPLETION w/h without
/COMPLETION -auto anywya anyway
/COMPLETION -delete 'anywya'
/COMPLETION -delete without
%9See also:%9 BIND

View file

@ -1,23 +1,40 @@
%9Syntax:%9
@SYNTAX:connect@ @SYNTAX:connect@
-4, -6: specify explicitly whether to use IPv4 or IPv6 address %9Parameters:%9
-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
This command makes irssi to connect to specified server. -4: Connects using IPv4.
Current connections are kept and a new one is created. -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

View file

@ -1,7 +1,23 @@
%9Syntax:%9
@SYNTAX:ctcp@ @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

View file

@ -1,8 +1,22 @@
%9Syntax:%9
@SYNTAX:cycle@ @SYNTAX:cycle@
Cycles (leaves and joins) the current channel or the specified %9Parameters:%9
channel.
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

View file

@ -1,37 +1,45 @@
%9Syntax:%9
@SYNTAX:dcc@ @SYNTAX:dcc@
/DCC LIST %9Parameters:%9
- Shows all the open DCC connections.
/DCC RESUME [<nick> [<file>]]
- Resumes a DCC SEND/GET connection.
/DCC CHAT [-passive] [<nick>]
- 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 [<nick> [<file>]]
- 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]
<nick> <file> [<file> ...]
- 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> <port>]
- 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 <type> <nick> [<file>]
- Closes a DCC-connection. Type can be either SEND, GET or CHAT.
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

View file

@ -1,7 +1,20 @@
%9Syntax:%9
@SYNTAX:dehilight@ @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

View file

@ -1,10 +1,23 @@
%9Syntax:%9
@SYNTAX:deop@ @SYNTAX:deop@
Takes off the channel operator privileges from the %9Parameters:%9
specified nick(s).
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

View file

@ -1,10 +1,26 @@
%9Syntax:%9
@SYNTAX:devoice@ @SYNTAX:devoice@
Takes off the voice from the specified nick(s). This makes them %9Parameters:%9
not to be able to send messages to the moderated (+m) channel.
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

View file

@ -1,7 +1,15 @@
%9Syntax:%9
@SYNTAX:die@ @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

View file

@ -1,9 +1,25 @@
%9Syntax:%9
@SYNTAX:disconnect@ @SYNTAX:disconnect@
Disconnects from the specified IRC-server. %9Parameters:%9
The server tags can be seen with:
/SERVER
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

View file

@ -1,5 +1,25 @@
%9Syntax:%9
@SYNTAX:echo@ @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

View file

@ -1,6 +1,25 @@
%9Syntax:%9
@SYNTAX:eval@ @SYNTAX:eval@
Evaluates the given commands and executes them. Internal variables %9Parameters:%9
are expanded. See the special_vars.txt file in the docs-directory.
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

View file

@ -1,41 +1,49 @@
%9Syntax:%9
@SYNTAX:exec@ @SYNTAX:exec@
-: Don't print "process terminated ..." message %9Parameters:%9
-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
-window: Move the output of specified process to active window -: Suppresses the process termination notification.
-close: Forcibly close (or "forget") a process that doesn't die. -nosh: Doesn't execute the command through /bin/sh.
This only removes all information from irssi concerning the -out: Sends the output to the active channel or query.
process, it doesn't send SIGKILL or any other signal -msg: Sends the output to the specified nickname or channel.
to the process. -notice: Sends the output to the specified nickname or channel as notices.
-<signal>: Send a signal to process. <signal> can be either numeric -name: Gives the process the specified name.
or one of the few most common ones (hup, term, kill, ...) -window: Displays the output in the active window.
-close: Forcibly closes a process that doesn't die.
-<signal>: 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 The command to execute; if no output parameter is given, the active window
-interactive: Creates a query-like window item. Text written to it is will be used and if no parameters are given at all, the list of active
sent to executed process, like /EXEC -in. processes will be displayed.
Execute specified command in background. Output of process is printed %9Description:%9
to active window by default, but can be also sent as messages or
notices to specified nick or channel.
Processes can be accessed either by their ID or name if you named it. Executes the specified command in the background; the process can be
Process identifier must always begin with '%%' character, like %%0 or accessed by its id or the name you gave it.
%%name.
Once the process is started, its output can still be redirected The output of the process can be redirected to various targets, such as
elsewhere with the -window, -msg, etc. options. You can send text to a window, a channel, a nickname or a query.
standard input of the process with -in option.
-close option shouldn't probably be used if there's a better way to The process identifier must always begin with the "%%" character. For
kill the process. It is meant to remove the processes that don't die example %%0.
even with SIGKILL. This option just closes the pipes used to
communicate with the process and frees all memory it used.
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

View file

@ -1,6 +1,18 @@
%9Syntax:%9
@SYNTAX:flushbuffer@ @SYNTAX:flushbuffer@
If either write_buffer_timeout or write_buffer_size have been set an immediate %9Description:%9
write of the buffers is forced.
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

View file

@ -1,9 +1,25 @@
%9Syntax:%9
@SYNTAX:format@ @SYNTAX:format@
-reset %9Parameters:%9
-delete
Allows you to view/change irssi's messages. -reset: Restores the original value.
Use this command with care. -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

View file

@ -1,5 +1,22 @@
%9Syntax:%9
@SYNTAX:hash@ @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

View file

@ -1,13 +1,27 @@
%9Syntax:%9
@SYNTAX:help@ @SYNTAX:help@
Shows help on commands. Try: %9Parameters:%9
/HELP command
Also try, for example: The command to display the documentation for; if no argument is given, the
/SET beep list of commands will be displayed.
or
/SET auto
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

View file

@ -1,32 +1,42 @@
%9Syntax:%9
@SYNTAX:hilight@ @SYNTAX:hilight@
-mask: Match only for nick, <text> is a nick mask %9Parameters:%9
-regexp: <text> is a regular expression
-full: <text> 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>. 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 <level> messages, default is
publics,msgs,notices,actions
-channels: Match only in <channels> (comma separated list)
-priority: Priority to use when multiple hilights match. Default is 0.
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: The text to highlight on; if no argument is given, the list of highlights
/HILIGHT mynick will be displayed.
Hilight all messages from "mynick": %9Description:%9
/HILIGHT -mask mynick!*@*
Hilight lines that were written by nicks from *.fi with bold green Highlights the keyword or pattern to make sure that you don't miss any
/HILIGHT -color %%G -mask *!*@*.fi 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

View file

@ -1,46 +1,46 @@
%9Syntax:%9
@SYNTAX:ignore@ @SYNTAX:ignore@
-regexp: <pattern> is a regular expression %9Parameters:%9
-full: <pattern> must match to full words
-pattern: <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: <secs> seconds after the ignore is removed
<mask>: Either a nick mask or list of channels
<levels>: List of levels to ignore. You can use -<level> to remove levels
from ignore (/help levels for details).
<^levels>: List of levels to NOT ignore
(/ignore -except nick notices = /ignore nick ^notices)
-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 The mask, channels and levels to ignore; if no argument is provided, the
some levels of the ignore, use /IGNORE <mask> -<level> -<level2> etc 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 * CTCPS
/IGNORE -except *!*@host.org CTCPS /IGNORE -except *!*@*.irssi.org CTCPS
/IGNORE #irssi ALL -PUBLIC -ACTIONS
Examples: /IGNORE -replies *!*@*.irssi.org ALL
/IGNORE -regexp -pattern (away|gone|back|playing|returned) * ACTIONS
/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 *zzz* NICKS /IGNORE *zzz* NICKS
/IGNORE *afk* NICKS /IGNORE *afk* NICKS
/IGNORE *away* 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`. %9See also:%9 ACCEPT, SILENCE, UNIGNORE
See also: UNIGNORE, SILENCE, ACCEPT

View file

@ -1,6 +1,21 @@
%9Syntax:%9
@SYNTAX:info@ @SYNTAX:info@
Shows information about the IRC server software and the current %9Parameters:%9
server instance.
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

View file

@ -1,10 +1,21 @@
%9Syntax:%9
@SYNTAX:invite@ @SYNTAX:invite@
Invites the specified nick to the current or specified channel. %9Parameters:%9
Example: The nickname to invite and the channel to invite him or her to; if no
/INVITE buddy #mychannel 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

View file

@ -1,9 +1,20 @@
@SYNTAX:invitelist@ %9Syntax:%9
Shows the +I modes of the current channel. +I mode INVITELIST
allows free joins of clients with certain userhost masks
even if the channel is invite only.
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

View file

@ -1,4 +0,0 @@
IRCNET
Deprecated. Use NETWORK instead.

View file

@ -1,7 +1,20 @@
%9Syntax:%9
@SYNTAX:ison@ @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

View file

@ -1,15 +1,26 @@
%9Syntax:%9
@SYNTAX:join@ @SYNTAX:join@
-window: Join channel, placing channel window item in currently active window %9Parameters:%9
-invite: Join last invited channel
-<server tag>: Join channel on server with specified tag
Joins a specified channel. Channel names usually begin with #-sign, -window Joins a channel in the active window.
which may be omitted here. -invite Joins the channel you were last invited to.
-<server tag> The server tag on which you want to join the channel.
JOIN is aliased to J by default. Example: /j irssi The channel names, separated by a commma, to join and the channel key.
(This joins to the channel #irssi)
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

View file

@ -1,16 +1,24 @@
%9Syntax:%9
@SYNTAX:kick@ @SYNTAX:kick@
This command "kicks" the specified user off of the specified %9Parameters%9
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.
If the <channel> is omitted, removes the nick from the current The channel and the nicknames, separated by a comma, to kick from the
channel. 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

View file

@ -1,10 +1,22 @@
%9Syntax:%9
@SYNTAX:kickban@ @SYNTAX:kickban@
Kicks off and bans a nick from the current channel. %9Parameters:%9
A reason for the kick can be supplied.
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

View file

@ -1,18 +1,24 @@
%9Syntax:%9
@SYNTAX:kill@ @SYNTAX:kill@
IRC operator command. %9Parameters:%9
KILL is used to forcibly remote a client from the irc network. The nickname to remove from the network and the reason thereof.
It works similarly to KICK, except that a reason must be
given (even if it is meaningless or flat-out wrong).
In general, KILL is useful only as a warning tool for abusive %9Description:%9
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.
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

View file

@ -1,16 +1,30 @@
%9Syntax:%9
@SYNTAX:knock@ @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 Sends an invitation request to the channel operators of the target channel;
- Channel is not private (+p) this command may not work on all IRC servers.
- You are not already on the channel
- Channel is invite only (+i), has a key (+k) or limit is full
When successful KNOCK is issued, it sends a notice to channel operators. Use of KNOCK is rate limited by the server. The following conditions must be met:
* 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

View file

@ -1,11 +1,26 @@
%9Syntax:%9
@SYNTAX:knockout@ @SYNTAX:knockout@
Kicks user off the channel and bans him/her. Ban %9Parameters:%9
lasts the given number of seconds or 5 minutes
by default.
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

View file

@ -1,22 +1,37 @@
%9Syntax:%9
@SYNTAX:lastlog@ @SYNTAX:lastlog@
-clear: remove all lastlog lines from window %9Parameters:%9
-: don't print the "Lastlog:" and "End of Lastlog" messages. -: Doesn't print the "Lastlog:" and "End of Lastlog" messages.
-file: write lastlog to file instead of screen -file: Output the lastlog to a file instead of the active window.
-window: which window's lastlog to check (output is always to active) -window: Specifies the window to check.
-case: Case-sensitive matching -new: Only displays results since the previous lastlog.
-force: Force displaying lastlog even if it's longer than 1000 lines -away: Only displays results since you previous away status.
-new: show only lines since last /LASTLOG -level: Specifies the levels to check.
-regexp: `text' is a regular expression -clear: Removes the previous results from the active window.
-word: `text' must match to full words -count: Displays how many lines match.
-<level>: levels to check (default is all; /help levels for details) -case: Performs a case-sensitive matching.
<pattern>: text to search for, or all if empty -regexp: The given text pattern is a regular expression.
<count>: maximum number of lines to show -word: The text must match full words.
<start>: skip the last `start' lines -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

View file

@ -1,13 +1,28 @@
%9Syntax:%9
@SYNTAX:layout@ @SYNTAX:layout@
Saves the current window layout to configuration (yes, you'll still %9Parameters:%9
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.
Channels aren't actually joined in those windows immediately, they're SAVE: Saves your layout to the configuration.
just marked "next time you join to '#channel' in server that has tag RESET: Removes the saved layout from the configuration.
'ircnet' place it to this window".
%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.

View file

@ -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 %9Description:%9
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
And a few special ones that could be included with the These are the message levels that are used throughout Irssi; they describe
levels above: what kind of message is displayed.
HILIGHT - Text is highlighted These are the common levels you can use:
NOHILIGHT - Don't check highlighting for this message
NO_ACT - Don't trigger channel activity when printing ACTIONS Actions by a nickname.
this message CLIENTCRAP Irssi's internal messages.
NEVER - Never ignore or log this message 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".

View file

@ -1,9 +1,22 @@
%9Syntax:%9
@SYNTAX:links@ @SYNTAX:links@
Shows the links between the IRC servers of the %9Parameters:%9
current IRC network. If a wildcard parameter is
specified, shows only the matching entries.
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

View file

@ -1,16 +1,25 @@
%9Syntax:%9
@SYNTAX:list@ @SYNTAX:list@
Lists the channel names. Trying to list all the channel %9Parameters:%9
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.
Thus, on IRCNet, you should rather use service ALIS -yes: Comfirms that you want to receive a large amount of data.
(Advanced Listing Service), which will allow you to query
for channel with specific name, topic, mode or usercount. The text a channel must match; if no argument is given, the list of all
Type /SQUERY ALIS HELP to get more info about it. 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 See also: SQUERY

View file

@ -1,16 +1,23 @@
%9Syntax:%9
@SYNTAX:load@ @SYNTAX:load@
Load a plugin. If full path isn't given, irssi searches the plugin from %9Parameters%9
directories:
~/.irssi/modules/ The name of the module and submodule to load.
<install dir, /usr/local or /usr maybe>/lib/irssi/modules/
See plugins page of http://www.irssi.org/ to see if there's any plugins %9Description:%9
you'd want to use.
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

View file

@ -1,41 +1,48 @@
%9Syntax:%9
@SYNTAX:log@ @SYNTAX:log@
-noopen: Create the entry to log list, but don't start logging %9Parameters:%9
-autoopen: Automatically open this log file at startup
-<server tag>: 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.
<filename>: File name where to log, it is parsed with
strftime(), so %%d=day, etc. see "man strftime" for
more info.
<levels>: Defaults to ALL
<id>: ID number of log.
/SET log_create_mode <mode> - Specifies what file mode to use with OPEN: Opens a logfile.
the created log files. Default is 0600. CLOSE: Closes a logfile.
START: Starts logging a log entry.
STOP: Stops logging a log entry.
All of these are parsed with strftime(): -noopen: Saves the entry in the configuration, but doesn't actually
/SET log_timestamp <text> - Specifies the time stamp format. start logging.
Default is "%%H:%%M ". -autoopen: Automatically opens the log at startup.
/SET log_open_string <text> - Text written to log when it's opened -window: Displays the output to the active window, or the window
/SET log_close_string <text> - Text written to log when it's closed specified in the targets parameter.
/SET log_day_changed <text> - Text written to log when day changes -<server tag>: 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 The filename of the log and the levels to match; if no argument is given,
accidentally try to write to the same log file. the list of open logs will be displayed.
Examples: %9Description:%9
/LOG OPEN -targets cras ~/irclogs/cras.log MSGS Opens a logfile and stores the messages of the given targets into it; the
- Logs all messages from/to nick `cras' logfiles will be locked so multiple clients cannot log to the same file.
/LOG OPEN -targets #linux ~/irclogs/linux/linux-%%Y-%%m-%%d You may use any of the date formats to create a logrotation; we strongly
- Logs all messages in channel #linux. Log is rotated daily, so recommend you to enable autolog if you are interested in keeping logs.
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.
See also: SET LOG, WINDOW LOG %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

View file

@ -1,5 +1,24 @@
%9Syntax:%9
@SYNTAX:lusers@ @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

View file

@ -1,22 +1,59 @@
%9Syntax:%9
@SYNTAX:network@ @SYNTAX:network@
-kicks: Maximum number of nicks in one /KICK command %9Parameters:%9
-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 LIST: Displays the list of configured networks.
after connecting to network. This is useful for automatically ADD: Adds a network to your configuration.
identifying yourself to NickServ, for example REMOVE: Removes a network from your configuration.
Shows and changes the settings of defined IRC networks. -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.
See also: CONNECT 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

View file

@ -1,44 +1,69 @@
%9Syntax:%9
@SYNTAX:server@ @SYNTAX:server@
-4, -6: specify explicitly whether to use IPv4 or IPv6 address %9Parameters:%9
-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 <port> argument
/SERVER disconnects the server in active window and connects LIST: Displays the list of servers you are connected to.
to the new one. It will take the same arguments as /CONNECT. CONNECT: Connects to the given server.
If you prefix the address with the + character, Irssi won't ADD: Adds a server to your configuration.
disconnect the active server, and it will create a new window REMOVE: Removes a server from your configuration.
where the server is connected (ie. /window new hide; PURGE: Purges the commands queued to be sent to the server.
/connect address)
/SERVER without any arguments displays the list of connected -!: Doesn't autojoin the channels.
servers. -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 <address> [<port>] [<network>] 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 [<target>] Displays, adds, modifies or removes the network configuration of IRC
servers.
Clears the server send queue. Useful if, for example, you accidentally paste lots of text to a channel. When using the ADD parameter on a server that already exists, the
configuration will be merged with each other.
See also: CONNECT, DISCONNECT, RECONNECT, RMRECONNS 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.
%9Examples:%9
/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

15
docs/help/in/uptime.in Normal file
View file

@ -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

View file

@ -349,7 +349,7 @@
after connecting to the network. This is useful for automatically after connecting to the network. This is useful for automatically
identifying yourself to NickServ, for example identifying yourself to NickServ, for example
/NETWORK ADD -autosendcmd "/msg NickServ identify secret" freenode /NETWORK ADD -autosendcmd "/^msg NickServ identify secret" freenode
/NETWORK REMOVE <name> /NETWORK REMOVE <name>

View file

@ -1,252 +1,358 @@
servers = ( servers = (
{ address = "eu.irc6.net"; chatnet = "IRCnet"; port = "6667"; }, { address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; },
{ address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; }, { address = "irc.efnet.org"; chatnet = "EFNet"; port = "6667"; },
{ address = "chat.freenode.net"; chatnet = "Freenode"; port = "6667"; }, { address = "irc.esper.net"; chatnet = "EsperNet"; port = "6667"; },
{ address = "irc.efnet.org"; chatnet = "EFNet"; port = "6667"; }, { address = "chat.freenode.net"; chatnet = "Freenode"; 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.gamesurge.net"; chatnet = "GameSurge"; port = "6667"; }, { address = "irc.gamesurge.net"; chatnet = "GameSurge"; port = "6667"; },
{ address = "irc.webchat.org"; chatnet = "WebChat"; port = "6667"; }, { address = "eu.irc6.net"; chatnet = "IRCnet"; port = "6667"; },
{ address = "irc.rizon.net"; chatnet = "Rizon"; port = "6667"; }, { address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; },
{ address = "irc.link-net.org"; chatnet = "LinkNet"; port = "6667"; }, { address = "irc.ircsource.net"; chatnet = "IRCSource"; port = "6667"; },
{ address = "silc.silcnet.org"; chatnet = "SILC"; port = "706"; } { 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 = { chatnets = {
IRCnet = { DALnet = {
type = "IRC"; type = "IRC";
max_kicks = "4"; max_kicks = "4";
max_msgs = "5"; max_msgs = "20";
max_whois = "4"; max_whois = "30";
max_query_chans = "5";
}; };
EFNet = { EFNet = {
type = "IRC"; type = "IRC";
max_kicks = "4"; max_kicks = "1";
max_msgs = "3"; max_msgs = "4";
max_whois = "1";
};
EsperNet = {
type = "IRC";
max_kicks = "1";
max_msgs = "4";
max_whois = "1"; max_whois = "1";
}; };
Freenode = { Freenode = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "4"; max_msgs = "4";
max_whois = "1"; max_whois = "1";
}; };
Undernet = { GameSurge = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "3"; max_msgs = "1";
max_whois = "30"; max_whois = "1";
}; };
DALnet = { IRCnet = {
type = "IRC"; type = "IRC";
max_kicks = "4";
max_msgs = "3";
max_whois = "30";
};
QuakeNet = {
type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "3"; max_msgs = "1";
max_whois = "30"; 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 = { OFTC = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "3"; max_msgs = "1";
max_whois = "30"; max_whois = "1";
}; };
GameSurge = { QuakeNet = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "3"; max_msgs = "1";
max_whois = "30"; max_whois = "1";
};
WebChat = {
type = "IRC";
max_kicks = "1";
max_msgs = "3";
max_whois = "30";
}; };
Rizon = { Rizon = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "3"; max_msgs = "1";
max_whois = "30"; max_whois = "1";
}; };
LinkNet = { SILC = {
type = "IRC"; type = "SILC";
};
Undernet = {
type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "3"; max_msgs = "1";
max_whois = "30"; max_whois = "1";
}; };
SILC = { type = "SILC"; };
}; };
channels = ( channels = (
{ name = "#irssi"; chatnet = "ircnet"; autojoin = "No"; }, { name = "#lobby"; chatnet = "EsperNet"; autojoin = "Yes"; },
{ name = "silc"; chatnet = "silc"; autojoin = "No"; } { 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 = { aliases = {
J = "join"; ATAG = "WINDOW SERVER";
WJOIN = "join -window"; ADDALLCHANS = "SCRIPT EXEC foreach my \\$channel (Irssi::channels()) { Irssi::command(\"CHANNEL ADD -auto \\$channel->{name} \\$channel->{server}->{tag} \\$channel->{key}\")\\;}";
WQUERY = "query -window"; B = "BAN";
LEAVE = "part"; BACK = "AWAY";
BYE = "quit"; BANS = "BAN";
EXIT = "quit"; BYE = "QUIT";
SIGNOFF = "quit"; C = "CLEAR";
DESCRIBE = "action"; CALC = "EXEC - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi";
DATE = "time"; CHAT = "DCC CHAT";
HOST = "userhost"; 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) }";
LAST = "lastlog"; DATE = "TIME";
SAY = "msg *"; DEHIGHLIGHT = "DEHILIGHT";
WI = "whois"; DESCRIBE = "ACTION";
WII = "whois $0 $0"; DHL = "DEHILIGHT";
WW = "whowas"; EXEMPTLIST = "MODE $C +e";
W = "who"; EXIT = "QUIT";
N = "names"; GOTO = "SCROLLBACK GOTO";
M = "msg"; HIGHLIGHT = "HILIGHT";
T = "topic"; HL = "HILIGHT";
C = "clear"; HOST = "USERHOST";
CL = "clear"; INVITELIST = "MODE $C +I";
K = "kick"; J = "JOIN";
KB = "kickban"; K = "KICK";
KN = "knockout"; KB = "KICKBAN";
BANS = "ban"; KN = "KNOCKOUT";
B = "ban"; LAST = "LASTLOG";
MUB = "unban *"; LEAVE = "PART";
UB = "unban"; M = "MSG";
IG = "ignore"; MUB = "UNBAN *";
UNIG = "unignore"; N = "NAMES";
SB = "scrollback"; NMSG = "^MSG";
UMODE = "mode $N"; P = "PART";
WC = "window close"; Q = "QUERY";
WN = "window new hide"; RESET = "SET -default";
SV = "say Irssi $J ($V) - http://irssi.org/"; RUN = "SCRIPT LOAD";
GOTO = "sb goto"; SAY = "MSG *";
CHAT = "dcc chat"; SB = "SCROLLBACK";
RUN = "SCRIPT LOAD"; SBAR = "STATUSBAR";
CALC = "exec - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi"; SIGNOFF = "QUIT";
SBAR = "STATUSBAR"; SV = "MSG * Irssi $J ($V) - http://www.irssi.org";
INVITELIST = "mode $C +I"; T = "TOPIC";
Q = "QUERY"; UB = "UNBAN";
"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"; UMODE = "MODE $N";
EXEMPTLIST = "mode $C +e"; UNSET = "SET -clear";
ATAG = "WINDOW SERVER"; W = "WHO";
UNSET = "set -clear"; WC = "WINDOW CLOSE";
RESET = "set -default"; 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 = { 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 = { items = {
# start/end text in statusbars
barstart = "{sbstart}"; barstart = "{sbstart}";
barend = "{sbend}"; barend = "{sbend}";
topicbarstart = "{topicsbstart}"; topicbarstart = "{topicsbstart}";
topicbarend = "{topicsbend}"; topicbarend = "{topicsbend}";
# treated "normally", you could change the time/user name to whatever
time = "{sb $Z}"; time = "{sb $Z}";
user = "{sb {sbnickmode $cumode}$N{sbmode $usermode}{sbaway $A}}"; user = "{sb {sbnickmode $cumode}$N{sbmode $usermode}{sbaway $A}}";
# treated specially .. window is printed with non-empty windows, window = "{sb $winref:$tag/$itemname{sbmode $M}}";
# window_empty is printed with empty windows
window = "{sb $winref:$tag/$itemname{sbmode $M}}";
window_empty = "{sb $winref{sbservertag $tag}}"; window_empty = "{sb $winref{sbservertag $tag}}";
prompt = "{prompt $[.15]itemname}";
prompt = "{prompt $[.15]itemname}";
prompt_empty = "{prompt $winname}"; prompt_empty = "{prompt $winname}";
topic = " $topic";
topic = " $topic";
topic_empty = " Irssi v$J - http://www.irssi.org"; topic_empty = " Irssi v$J - http://www.irssi.org";
# all of these treated specially, they're only displayed when needed lag = "{sb Lag: $0-}";
lag = "{sb Lag: $0-}"; act = "{sb Act: $0-}";
act = "{sb Act: $0-}";
more = "-- more --"; 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 = { default = {
# the "default statusbar" to be displayed at the bottom of the window.
# contains all the normal items.
window = { window = {
disabled = "no";
# window, root disabled = "no";
type = "window"; type = "window";
# top, bottom
placement = "bottom"; placement = "bottom";
# number position = "1";
position = "1"; visible = "active";
# active, inactive, always
visible = "active";
# list of items in statusbar in the display order
items = { items = {
barstart = { priority = "100"; }; barstart = { priority = "100"; };
time = { }; time = { };
user = { }; user = { };
window = { }; window = { };
window_empty = { }; window_empty = { };
lag = { priority = "-1"; }; lag = { priority = "-1"; };
act = { priority = "10"; }; act = { priority = "10"; };
more = { priority = "-1"; alignment = "right"; }; more = { priority = "-1"; alignment = "right"; };
barend = { priority = "100"; alignment = "right"; }; barend = { priority = "100"; alignment = "right"; };
}; };
}; };
# statusbar to use in inactive split windows
window_inact = { window_inact = {
type = "window";
type = "window";
placement = "bottom"; placement = "bottom";
position = "1"; position = "1";
visible = "inactive"; visible = "inactive";
items = { items = {
barstart = { priority = "100"; }; barstart = { priority = "100"; };
window = { }; window = { };
window_empty = { }; window_empty = { };
more = { priority = "-1"; alignment = "right"; }; more = { priority = "-1"; alignment = "right"; };
barend = { priority = "100"; 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 = { prompt = {
type = "root";
type = "root";
placement = "bottom"; placement = "bottom";
# we want to be at the bottom always position = "100";
position = "100"; visible = "always";
visible = "always";
items = { items = {
prompt = { priority = "-1"; }; prompt = { priority = "-1"; };
prompt_empty = { priority = "-1"; }; prompt_empty = { priority = "-1"; };
# treated specially, this is the real input line. input = { priority = "10"; };
input = { priority = "10"; };
}; };
}; };
# topicbar
topic = { topic = {
type = "root";
type = "root";
placement = "top"; placement = "top";
position = "1"; position = "1";
visible = "always"; visible = "always";
items = { items = {
topicbarstart = { priority = "100"; }; topicbarstart = { priority = "100"; };
topic = { }; topic = { };
topic_empty = { }; topic_empty = { };
topicbarend = { priority = "100"; alignment = "right"; }; topicbarend = { priority = "100"; alignment = "right"; };
}; };
}; };
}; };

View file

@ -378,12 +378,35 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
} }
} }
if (target != NULL) { if (target != NULL) {
signal_emit("server sendmsg", 4, server, target, msg, char **splitmsgs;
GINT_TO_POINTER(target_type)); 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); if (free_ret && target != NULL) g_free(target);
cmd_params_free(free_arg); cmd_params_free(free_arg);

View file

@ -968,7 +968,9 @@ static void cmd_cd(const char *data)
if (*data == '\0') return; if (*data == '\0') return;
str = convert_home(data); str = convert_home(data);
chdir(str); if (chdir(str) != 0) {
g_warning("Failed to chdir(): %s", strerror(errno));
}
g_free(str); g_free(str);
} }

View file

@ -58,30 +58,6 @@ static int ignore_check_replies_rec(IGNORE_REC *rec, CHANNEL_REC *channel,
return FALSE; 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) static int ignore_match_pattern(IGNORE_REC *rec, const char *text)
{ {
if (rec->pattern == NULL) if (rec->pattern == NULL)
@ -104,8 +80,15 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text)
stristr(text, rec->pattern) != NULL; 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) \ #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) \ #define ignore_match_nickmask(rec, nick, nickmask) \
((rec)->mask == NULL || \ ((rec)->mask == NULL || \
@ -117,6 +100,31 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text)
((rec)->servertag == NULL || \ ((rec)->servertag == NULL || \
g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0) 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, int ignore_check(SERVER_REC *server, const char *nick, const char *host,
const char *channel, const char *text, int level) 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) if (best_match || (level & MSGLEVEL_PUBLIC) == 0)
return best_match; 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, 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; GSList *tmp;
char **chan; char **chan;
@ -202,6 +217,12 @@ IGNORE_REC *ignore_find(const char *servertag, const char *mask,
continue; 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) || if ((rec->mask == NULL && mask != NULL) ||
(rec->mask != NULL && mask == NULL)) continue; (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) static void ignore_init_rec(IGNORE_REC *rec)
{ {
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H
char *errbuf;
int errcode, errbuf_len;
if (rec->regexp_compiled) regfree(&rec->preg); if (rec->regexp_compiled) regfree(&rec->preg);
rec->regexp_compiled = !rec->regexp || rec->pattern == NULL ? FALSE : rec->regexp_compiled = FALSE;
regcomp(&rec->preg, rec->pattern, if (rec->regexp && rec->pattern != NULL) {
REG_EXTENDED|REG_ICASE|REG_NOSUB) == 0; 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 #endif
} }

View file

@ -32,6 +32,7 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host,
const char *channel, const char *text, int level); const char *channel, const char *text, int level);
IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels); 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_add_rec(IGNORE_REC *rec);
void ignore_update_rec(IGNORE_REC *rec); void ignore_update_rec(IGNORE_REC *rec);

View file

@ -136,19 +136,25 @@ char *bits2level(int bits)
if (bits == 0) if (bits == 0)
return g_strdup(""); return g_strdup("");
if (bits == MSGLEVEL_ALL)
return g_strdup("ALL");
str = g_string_new(NULL); str = g_string_new(NULL);
if (bits & MSGLEVEL_NEVER) if (bits & MSGLEVEL_NEVER) {
g_string_append(str, "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 "); g_string_append(str, "NO_ACT ");
bits &= ~MSGLEVEL_NO_ACT;
}
for (n = 0; levels[n] != NULL; n++) { if (bits == MSGLEVEL_ALL) {
if (bits & (1L << n)) g_string_append(str, "ALL ");
g_string_append_printf(str, "%s ", levels[n]); } else {
for (n = 0; levels[n] != NULL; n++) {
if (bits & (1L << n))
g_string_append_printf(str, "%s ", levels[n]);
}
} }
if (str->len > 0) if (str->len > 0)
g_string_truncate(str, str->len-1); g_string_truncate(str, str->len-1);

View file

@ -183,7 +183,7 @@ int strarray_find(char **array, const char *item)
GSList *gslist_find_string(GSList *list, const char *key) 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; if (strcmp(list->data, key) == 0) return list;
return NULL; 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) 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; if (g_ascii_strcasecmp(list->data, key) == 0) return list;
return NULL; return NULL;
@ -268,7 +268,7 @@ GSList *hashtable_get_keys(GHashTable *hash)
GList *glist_find_string(GList *list, const char *key) 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; if (strcmp(list->data, key) == 0) return list;
return NULL; 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) 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; if (g_ascii_strcasecmp(list->data, key) == 0) return list;
return NULL; return NULL;
@ -966,3 +966,21 @@ char *ascii_strdown(char *str)
*s = g_ascii_tolower (*s); *s = g_ascii_tolower (*s);
return str; 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;
}

View file

@ -115,4 +115,7 @@ uoff_t str_to_uofft(const char *str);
/* find `item' from a space separated `list' */ /* find `item' from a space separated `list' */
int find_substr(const char *list, const char *item); int find_substr(const char *list, const char *item);
/* split `str' into `len' sized substrings */
char **strsplit_len(const char *str, int len);
#endif #endif

View file

@ -60,7 +60,11 @@ GIOChannel *g_io_channel_new(int handle)
IPADDR ip4_any = { IPADDR ip4_any = {
AF_INET, 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) int net_ip_compare(IPADDR *ip1, IPADDR *ip2)

View file

@ -102,10 +102,15 @@ void rawlog_redirect(RAWLOG_REC *rawlog, const char *str)
static void rawlog_dump(RAWLOG_REC *rawlog, int f) static void rawlog_dump(RAWLOG_REC *rawlog, int f)
{ {
GSList *tmp; GSList *tmp;
ssize_t ret = 1;
for (tmp = rawlog->lines; tmp != NULL; tmp = tmp->next) { for (tmp = rawlog->lines; ret && tmp != NULL; tmp = tmp->next) {
write(f, tmp->data, strlen((char *) tmp->data)); ret = write(f, tmp->data, strlen((char *) tmp->data));
write(f, "\n", 1); ret &= write(f, "\n", 1);
}
if (ret <= 0) {
g_warning("rawlog write() failed: %s", strerror(errno));
} }
} }

View file

@ -182,6 +182,86 @@ char *recode_out(const SERVER_REC *server, const char *str, const char *target)
return recoded; 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) void recode_update_charset(void)
{ {
const char *charset = settings_get_str("term_charset"); const char *charset = settings_get_str("term_charset");

View file

@ -3,6 +3,8 @@
char *recode_in (const SERVER_REC *server, const char *str, const char *target); 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_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_valid_charset(const char *charset);
gboolean is_utf8(void); gboolean is_utf8(void);
void recode_update_charset(void); void recode_update_charset(void);

View file

@ -61,6 +61,9 @@ const char *(*get_nick_flags)(SERVER_REC *server);
/* send public or private message to server */ /* send public or private message to server */
void (*send_message)(SERVER_REC *server, const char *target, void (*send_message)(SERVER_REC *server, const char *target,
const char *msg, int target_type); 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 -- */ /* -- Default implementations are used if NULL -- */
CHANNEL_REC *(*channel_find_func)(SERVER_REC *server, const char *name); CHANNEL_REC *(*channel_find_func)(SERVER_REC *server, const char *name);

View file

@ -107,7 +107,9 @@ static int write_buffer_flush_rec(void *handlep, BUFFER_REC *rec)
for (tmp = rec->blocks; tmp != NULL; tmp = tmp->next) { for (tmp = rec->blocks; tmp != NULL; tmp = tmp->next) {
size = tmp->data != rec->active_block ? BUFFER_BLOCK_SIZE : size = tmp->data != rec->active_block ? BUFFER_BLOCK_SIZE :
rec->active_block_pos; 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); empty_blocks = g_slist_concat(empty_blocks, rec->blocks);

View file

@ -463,7 +463,7 @@ void fe_common_core_finish_init(void)
if (setup_changed) if (setup_changed)
signal_emit("setup changed", 0); signal_emit("setup changed", 0);
autorun_startup(); autorun_startup();
autoconnect_servers(); autoconnect_servers();
} }

View file

@ -56,8 +56,10 @@ static void ignore_print(int index, IGNORE_REC *rec)
if (rec->exception) g_string_append(options, "-except "); if (rec->exception) g_string_append(options, "-except ");
if (rec->regexp) { if (rec->regexp) {
g_string_append(options, "-regexp "); g_string_append(options, "-regexp ");
if (rec->pattern == NULL)
g_string_append(options, "[INVALID! -pattern missing] ");
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H
if (!rec->regexp_compiled) else if (!rec->regexp_compiled)
g_string_append(options, "[INVALID!] "); g_string_append(options, "[INVALID!] ");
#endif #endif
} }
@ -118,7 +120,7 @@ static void cmd_ignore(const char *data)
char *patternarg, *chanarg, *mask, *levels, *timestr, *servertag; char *patternarg, *chanarg, *mask, *levels, *timestr, *servertag;
char **channels; char **channels;
void *free_arg; void *free_arg;
int new_ignore, msecs; int new_ignore, msecs, level;
if (*data == '\0') { if (*data == '\0') {
cmd_ignore_show(); 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 (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*levels == '\0') levels = "ALL"; if (*levels == '\0') levels = "ALL";
level = level2bits(levels, NULL);
msecs = 0; msecs = 0;
timestr = g_hash_table_lookup(optlist, "time"); timestr = g_hash_table_lookup(optlist, "time");
@ -154,7 +157,8 @@ static void cmd_ignore(const char *data)
channels = (chanarg == NULL || *chanarg == '\0') ? NULL : channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
g_strsplit(chanarg, ",", -1); 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; new_ignore = rec == NULL;
if (rec == NULL) { if (rec == NULL) {
@ -170,6 +174,12 @@ static void cmd_ignore(const char *data)
rec->level = combine_level(rec->level, levels); 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) { if (new_ignore && rec->level == 0) {
/* tried to unignore levels from nonexisting ignore */ /* tried to unignore levels from nonexisting ignore */
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
@ -226,7 +236,10 @@ static void cmd_unignore(const char *data)
chans[0] = mask; chans[0] = mask;
mask = NULL; 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) { if (rec != NULL) {

View file

@ -45,16 +45,19 @@
GHashTable *printnicks; 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 */ underlining or bolding */
char *expand_emphasis(WI_ITEM_REC *item, const char *text) char *expand_emphasis(WI_ITEM_REC *item, const char *text)
{ {
GString *str; GString *str;
char *ret; char *ret;
int pos; int pos;
int emphasis_italics;
g_return_val_if_fail(text != NULL, NULL); g_return_val_if_fail(text != NULL, NULL);
emphasis_italics = settings_get_bool("emphasis_italics");
str = g_string_new(text); str = g_string_new(text);
for (pos = 0; pos < str->len; pos++) { for (pos = 0; pos < str->len; pos++) {
@ -64,6 +67,8 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
if (*bgn == '*') if (*bgn == '*')
type = 2; /* bold */ type = 2; /* bold */
else if (*bgn == '/' && emphasis_italics)
type = 29; /* italics */
else if (*bgn == '_') else if (*bgn == '_')
type = 31; /* underlined */ type = 31; /* underlined */
else else
@ -190,7 +195,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
if (for_me) if (for_me)
level |= MSGLEVEL_HILIGHT; 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; level |= MSGLEVEL_NO_ACT;
if (settings_get_bool("emphasis")) if (settings_get_bool("emphasis"))
@ -238,13 +243,17 @@ static void sig_message_private(SERVER_REC *server, const char *msg,
{ {
QUERY_REC *query; QUERY_REC *query;
char *freemsg = NULL; char *freemsg = NULL;
int level = MSGLEVEL_MSGS;
query = query_find(server, nick); query = query_find(server, nick);
if (settings_get_bool("emphasis")) if (settings_get_bool("emphasis"))
msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg); 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 : query == NULL ? TXT_MSG_PRIVATE :
TXT_MSG_PRIVATE_QUERY, nick, address, msg); 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; 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; level |= MSGLEVEL_NO_ACT;
printformat(server, channel, level, printformat(server, channel, level,
@ -343,7 +352,7 @@ static void sig_message_part(SERVER_REC *server, const char *channel,
{ {
int level = MSGLEVEL_PARTS; 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; level |= MSGLEVEL_NO_ACT;
printformat(server, channel, level, 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)) if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_QUITS))
return; 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; level |= MSGLEVEL_NO_ACT;
print_channel = NULL; print_channel = NULL;
@ -432,7 +441,7 @@ static void sig_message_kick(SERVER_REC *server, const char *channel,
{ {
int level = MSGLEVEL_KICKS; 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; level |= MSGLEVEL_NO_ACT;
printformat(server, channel, level, printformat(server, channel, level,
@ -453,7 +462,7 @@ static void print_nick_change_channel(SERVER_REC *server, const char *channel,
level = MSGLEVEL_NICKS; level = MSGLEVEL_NICKS;
if (ownnick) level |= MSGLEVEL_NO_ACT; 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; level |= MSGLEVEL_NO_ACT;
printformat(server, channel, level, printformat(server, channel, level,
@ -532,7 +541,7 @@ static void sig_message_topic(SERVER_REC *server, const char *channel,
{ {
int level = MSGLEVEL_TOPICS; 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; level |= MSGLEVEL_NO_ACT;
printformat(server, channel, level, printformat(server, channel, level,
@ -676,6 +685,7 @@ void fe_messages_init(void)
settings_add_bool("lookandfeel", "emphasis", TRUE); settings_add_bool("lookandfeel", "emphasis", TRUE);
settings_add_bool("lookandfeel", "emphasis_replace", FALSE); settings_add_bool("lookandfeel", "emphasis_replace", FALSE);
settings_add_bool("lookandfeel", "emphasis_multiword", 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", TRUE);
settings_add_bool("lookandfeel", "show_nickmode_empty", TRUE); settings_add_bool("lookandfeel", "show_nickmode_empty", TRUE);
settings_add_bool("lookandfeel", "print_active_channel", FALSE); settings_add_bool("lookandfeel", "print_active_channel", FALSE);

View file

@ -387,7 +387,7 @@ void fe_server_init(void)
command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove); command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove);
command_bind_first("server", NULL, (SIGNAL_FUNC) server_command); command_bind_first("server", NULL, (SIGNAL_FUNC) server_command);
command_bind_first("disconnect", 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 looking", (SIGNAL_FUNC) sig_server_looking);
signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting); signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting);

View file

@ -588,6 +588,63 @@ static void window_print_daychange(WINDOW_REC *window, struct tm *tm)
printtext_string_window(window, MSGLEVEL_NEVER, str); 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) static void sig_print_text(void)
{ {
GSList *tmp; GSList *tmp;

View file

@ -97,4 +97,6 @@ void window_bind_remove_unsticky(WINDOW_REC *window);
void windows_init(void); void windows_init(void);
void windows_deinit(void); void windows_deinit(void);
short color_24bit_256(const unsigned char rgb[]);
#endif #endif

View file

@ -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 format_expand_styles(GString *out, const char **format, int *flags)
{ {
int retval = 1;
char *p, fmt; char *p, fmt;
/* storage for numerical parsing code for %x/X formats. */
int tmp;
unsigned int tmp2;
fmt = **format; fmt = **format;
switch (fmt) { switch (fmt) {
case '{': 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, 4);
g_string_append_c(out, FORMAT_STYLE_REVERSE); g_string_append_c(out, FORMAT_STYLE_REVERSE);
break; break;
case 'I':
/* italic */
g_string_append_c(out, 4);
g_string_append_c(out, FORMAT_STYLE_ITALIC);
break;
case ':': case ':':
/* Newline */ /* Newline */
g_string_append_c(out, '\n'); g_string_append_c(out, '\n');
@ -162,6 +245,62 @@ int format_expand_styles(GString *out, const char **format, int *flags)
/* code */ /* code */
format_expand_code(format, out, flags); format_expand_code(format, out, flags);
break; 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: default:
/* check if it's a background color */ /* check if it's a background color */
p = strchr(format_backs, fmt); p = strchr(format_backs, fmt);
@ -195,7 +334,7 @@ int format_expand_styles(GString *out, const char **format, int *flags)
return FALSE; return FALSE;
} }
return TRUE; return retval;
} }
void format_read_arglist(va_list va, FORMAT_REC *format, void format_read_arglist(va_list va, FORMAT_REC *format,
@ -303,6 +442,7 @@ int format_get_length(const char *str)
GString *tmp; GString *tmp;
int len; int len;
gboolean utf8; gboolean utf8;
int adv = 0;
g_return_val_if_fail(str != NULL, 0); g_return_val_if_fail(str != NULL, 0);
@ -313,9 +453,10 @@ int format_get_length(const char *str)
while (*str != '\0') { while (*str != '\0') {
if (*str == '%' && str[1] != '\0') { if (*str == '%' && str[1] != '\0') {
str++; str++;
if (*str != '%' && if (*str != '%') {
format_expand_styles(tmp, &str, NULL)) { adv = format_expand_styles(tmp, &str, NULL);
str++; str += adv;
if (adv)
continue; continue;
} }
@ -340,7 +481,7 @@ int format_real_length(const char *str, int len)
const char *start; const char *start;
const char *oldstr; const char *oldstr;
gboolean utf8; gboolean utf8;
int adv = 0;
g_return_val_if_fail(str != NULL, 0); g_return_val_if_fail(str != NULL, 0);
g_return_val_if_fail(len >= 0, 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) { while (*str != '\0' && len > 0) {
if (*str == '%' && str[1] != '\0') { if (*str == '%' && str[1] != '\0') {
str++; str++;
if (*str != '%' && if (*str != '%') {
format_expand_styles(tmp, &str, NULL)) { adv = format_expand_styles(tmp, &str, NULL);
str++; str += adv;
if (adv)
continue; continue;
} }
@ -378,6 +520,7 @@ char *format_string_expand(const char *text, int *flags)
{ {
GString *out; GString *out;
char code, *ret; char code, *ret;
int adv;
g_return_val_if_fail(text != NULL, NULL); g_return_val_if_fail(text != NULL, NULL);
@ -388,10 +531,13 @@ char *format_string_expand(const char *text, int *flags)
while (*text != '\0') { while (*text != '\0') {
if (code == '%') { if (code == '%') {
/* color 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, '%'); g_string_append_c(out, '%');
g_string_append_c(out, *text); g_string_append_c(out, *text);
} else {
text += adv - 1;
} }
code = 0; code = 0;
} else { } else {
@ -415,6 +561,7 @@ static char *format_get_text_args(TEXT_DEST_REC *dest,
GString *out; GString *out;
char code, *ret; char code, *ret;
int need_free; int need_free;
int adv;
out = g_string_new(NULL); out = g_string_new(NULL);
@ -422,10 +569,13 @@ static char *format_get_text_args(TEXT_DEST_REC *dest,
while (*text != '\0') { while (*text != '\0') {
if (code == '%') { if (code == '%') {
/* color 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, '%'); g_string_append_c(out, '%');
g_string_append_c(out, *text); g_string_append_c(out, *text);
} else {
text += adv - 1;
} }
code = 0; code = 0;
} else if (code == '$') { } else if (code == '$') {
@ -716,13 +866,22 @@ void format_newline(WINDOW_REC *window)
"", NULL); "", 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 */ /* parse ANSI color string */
static const char *get_ansi_color(THEME_REC *theme, const char *str, static const char *get_ansi_color(THEME_REC *theme, const char *str,
int *fg_ret, int *bg_ret, int *flags_ret) int *fg_ret, int *bg_ret, int *flags_ret)
{ {
static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
const char *start; const char *start;
int fg, bg, flags, num; int fg, bg, flags, num, i;
unsigned int num2;
if (*str != '[') if (*str != '[')
return str; return str;
@ -749,28 +908,135 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
/* reset colors back to default */ /* reset colors back to default */
fg = theme->default_color; fg = theme->default_color;
bg = -1; 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; break;
case 1: case 1:
/* hilight */ /* hilight */
flags |= GUI_PRINT_FLAG_BOLD; flags |= GUI_PRINT_FLAG_BOLD;
break; 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: case 5:
/* blink */ /* blink */
flags |= GUI_PRINT_FLAG_BLINK; flags |= GUI_PRINT_FLAG_BLINK;
break; break;
case 25:
/* steady */
flags &= ~GUI_PRINT_FLAG_BLINK;
break;
case 7: case 7:
/* reverse */ /* reverse */
flags |= GUI_PRINT_FLAG_REVERSE; flags |= GUI_PRINT_FLAG_REVERSE;
break; 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: default:
if (num >= 30 && num <= 37) { if (num >= 30 && num <= 37) {
if (fg == -1) fg = 0; flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = (fg & 0xf8) | ansitab[num-30]; fg = ansitab[num-30];
} } else if (num >= 40 && num <= 47) {
if (num >= 40 && num <= 47) { flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
if (bg == -1) bg = 0; bg = ansitab[num-40];
bg = (bg & 0xf8) | 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; break;
} }
@ -832,7 +1098,7 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret)
#define IS_COLOR_CODE(c) \ #define IS_COLOR_CODE(c) \
((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \ ((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' /* Return how many characters in `str' must be skipped before `len'
characters of text is skipped. */ characters of text is skipped. */
@ -858,6 +1124,20 @@ int strip_real_length(const char *str, int len,
*last_color_len = (int) (str-mircstart); *last_color_len = (int) (str-mircstart);
} else if (*str == 4 && str[1] != '\0') { } 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 (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') {
if (last_color_pos != NULL) if (last_color_pos != NULL)
*last_color_pos = (int) (str-start); *last_color_pos = (int) (str-start);
@ -907,6 +1187,14 @@ char *strip_codes(const char *input)
/* irssi color */ /* irssi color */
if (p[2] != '\0') { 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; p += 2;
continue; continue;
} }
@ -1007,6 +1295,9 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
case FORMAT_STYLE_REVERSE: case FORMAT_STYLE_REVERSE:
flags ^= GUI_PRINT_FLAG_REVERSE; flags ^= GUI_PRINT_FLAG_REVERSE;
break; break;
case FORMAT_STYLE_ITALIC:
flags ^= GUI_PRINT_FLAG_ITALIC;
break;
case FORMAT_STYLE_MONOSPACE: case FORMAT_STYLE_MONOSPACE:
flags ^= GUI_PRINT_FLAG_MONOSPACE; flags ^= GUI_PRINT_FLAG_MONOSPACE;
break; break;
@ -1020,16 +1311,47 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
break; break;
case FORMAT_STYLE_CLRTOEOL: case FORMAT_STYLE_CLRTOEOL:
break; 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: default:
if (*ptr != FORMAT_COLOR_NOCHANGE) { 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') if (ptr[1] == '\0')
break; break;
ptr++; ptr++;
if (*ptr != FORMAT_COLOR_NOCHANGE) { if (*ptr != FORMAT_COLOR_NOCHANGE) {
bgcolor = *ptr-'0'; flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bgcolor = *ptr==(char)0xff ? -1 : *ptr-'0';
} }
} }
ptr++; ptr++;
@ -1050,6 +1372,11 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
if (!hide_text_style) if (!hide_text_style)
flags ^= GUI_PRINT_FLAG_REVERSE; flags ^= GUI_PRINT_FLAG_REVERSE;
break; break;
case 29:
/* italic */
if (!hide_text_style)
flags ^= GUI_PRINT_FLAG_ITALIC;
break;
case 31: case 31:
/* underline */ /* underline */
if (!hide_text_style) if (!hide_text_style)

View file

@ -10,9 +10,12 @@
#define GUI_PRINT_FLAG_BLINK 0x0008 #define GUI_PRINT_FLAG_BLINK 0x0008
#define GUI_PRINT_FLAG_MIRC_COLOR 0x0010 #define GUI_PRINT_FLAG_MIRC_COLOR 0x0010
#define GUI_PRINT_FLAG_INDENT 0x0020 #define GUI_PRINT_FLAG_INDENT 0x0020
#define GUI_PRINT_FLAG_ITALIC 0x0040
#define GUI_PRINT_FLAG_NEWLINE 0x0080 #define GUI_PRINT_FLAG_NEWLINE 0x0080
#define GUI_PRINT_FLAG_CLRTOEOL 0x0100 #define GUI_PRINT_FLAG_CLRTOEOL 0x0100
#define GUI_PRINT_FLAG_MONOSPACE 0x0200 #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 MAX_FORMAT_PARAMS 10
#define DEFAULT_FORMAT_ARGLIST_SIZE 200 #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); 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_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_SPECIAL 0x60
#define FORMAT_STYLE_BLINK (0x01 + FORMAT_STYLE_SPECIAL) #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_BOLD (0x03 + FORMAT_STYLE_SPECIAL)
#define FORMAT_STYLE_REVERSE (0x04 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_REVERSE (0x04 + FORMAT_STYLE_SPECIAL)
#define FORMAT_STYLE_INDENT (0x05 + 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_DEFAULTS (0x07 + FORMAT_STYLE_SPECIAL)
#define FORMAT_STYLE_CLRTOEOL (0x08 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_CLRTOEOL (0x08 + FORMAT_STYLE_SPECIAL)
#define FORMAT_STYLE_MONOSPACE (0x09 + FORMAT_STYLE_SPECIAL) #define FORMAT_STYLE_MONOSPACE (0x09 + FORMAT_STYLE_SPECIAL)
int format_expand_styles(GString *out, const char **format, int *flags); 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_init(void);
void formats_deinit(void); void formats_deinit(void);

View file

@ -78,6 +78,7 @@ static void hilight_add_config(HILIGHT_REC *rec)
if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE); if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE);
if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE);
if (rec->regexp) iconfig_node_set_bool(node, "regexp", 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) { if (rec->channels != NULL && *rec->channels != NULL) {
node = config_node_section(node, "channels", NODE_TYPE_LIST); 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) && if (!rec->nickmask && hilight_match_level(rec, level) &&
hilight_match_channel(rec, channel) && 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)) hilight_match_text(rec, str, match_beg, match_end))
return rec; 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)) { if (!nick_match || (dest->level & MSGLEVEL_HILIGHT)) {
/* update the level / hilight info */ /* update the level / hilight info */
hilight_update_text_dest(dest, hilight); 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) if (nick_match)
@ -459,7 +468,7 @@ static void read_hilight_config(void)
rec->nickmask = config_node_get_bool(node, "mask", FALSE); rec->nickmask = config_node_get_bool(node, "mask", FALSE);
rec->fullword = config_node_get_bool(node, "fullword", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE);
rec->regexp = config_node_get_bool(node, "regexp", FALSE); rec->regexp = config_node_get_bool(node, "regexp", FALSE);
rec->servertag = config_node_get_str(node, "servertag", NULL);
hilight_init_rec(rec); hilight_init_rec(rec);
node = config_node_section(node, "channels", -1); node = config_node_section(node, "channels", -1);
@ -492,6 +501,8 @@ static void hilight_print(int index, HILIGHT_REC *rec)
if (rec->priority != 0) if (rec->priority != 0)
g_string_append_printf(options, "-priority %d ", rec->priority); 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) if (rec->color != NULL)
g_string_append_printf(options, "-color %s ", rec->color); g_string_append_printf(options, "-color %s ", rec->color);
if (rec->act_color != NULL) if (rec->act_color != NULL)
@ -530,12 +541,12 @@ static void cmd_hilight_show(void)
/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp] /* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp]
[-color <color>] [-actcolor <color>] [-level <level>] [-color <color>] [-actcolor <color>] [-level <level>]
[-channels <channels>] <text> */ [-network <network>] [-channels <channels>] <text> */
static void cmd_hilight(const char *data) static void cmd_hilight(const char *data)
{ {
GHashTable *optlist; GHashTable *optlist;
HILIGHT_REC *rec; HILIGHT_REC *rec;
char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text; char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text, *servertag;
char **channels; char **channels;
void *free_arg; void *free_arg;
@ -555,6 +566,7 @@ static void cmd_hilight(const char *data)
priorityarg = g_hash_table_lookup(optlist, "priority"); priorityarg = g_hash_table_lookup(optlist, "priority");
colorarg = g_hash_table_lookup(optlist, "color"); colorarg = g_hash_table_lookup(optlist, "color");
actcolorarg = g_hash_table_lookup(optlist, "actcolor"); actcolorarg = g_hash_table_lookup(optlist, "actcolor");
servertag = g_hash_table_lookup(optlist, "network");
if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@ -606,6 +618,11 @@ static void cmd_hilight(const char *data)
if (*actcolorarg != '\0') if (*actcolorarg != '\0')
rec->act_color = g_strdup(actcolorarg); 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); hilight_create(rec);
@ -696,7 +713,7 @@ void hilight_text_init(void)
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); 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) void hilight_text_deinit(void)

View file

@ -29,6 +29,7 @@ struct _HILIGHT_REC {
unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */
regex_t preg; regex_t preg;
#endif #endif
char *servertag;
}; };
extern GSList *hilights; extern GSList *hilights;

View file

@ -206,6 +206,7 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
{ {
GString *out; GString *out;
char *ret; char *ret;
int adv;
out = g_string_new(NULL); out = g_string_new(NULL);
for (; *str != '\0'; str++) { for (; *str != '\0'; str++) {
@ -255,9 +256,12 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
break; break;
} }
default: 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, '%');
g_string_append_c(out, *str); g_string_append_c(out, *str);
} else {
str += adv - 1;
} }
break; break;
} }
@ -272,6 +276,7 @@ static char *printtext_expand_formats(const char *str, int *flags)
{ {
GString *out; GString *out;
char *ret; char *ret;
int adv;
out = g_string_new(NULL); out = g_string_new(NULL);
for (; *str != '\0'; str++) { for (; *str != '\0'; str++) {
@ -283,9 +288,12 @@ static char *printtext_expand_formats(const char *str, int *flags)
if (*++str == '\0') if (*++str == '\0')
break; 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, '%');
g_string_append_c(out, *str); g_string_append_c(out, *str);
} else {
str += adv - 1;
} }
} }

View file

@ -115,8 +115,8 @@ void theme_destroy(THEME_REC *rec)
} }
static char *theme_replace_expand(THEME_REC *theme, int index, static char *theme_replace_expand(THEME_REC *theme, int index,
char default_fg, char default_bg, theme_rm_col default_fg, theme_rm_col default_bg,
char *last_fg, char *last_bg, theme_rm_col *last_fg, theme_rm_col *last_bg,
char chr, int flags) char chr, int flags)
{ {
GSList *rec; GSList *rec;
@ -168,15 +168,44 @@ static void theme_format_append_variable(GString *str, const char **format)
g_free(value); 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 */ /* append next "item", either a character, $variable or %format */
static void theme_format_append_next(THEME_REC *theme, GString *str, static void theme_format_append_next(THEME_REC *theme, GString *str,
const char **format, const char **format,
char default_fg, char default_bg, theme_rm_col default_fg, theme_rm_col default_bg,
char *last_fg, char *last_bg, theme_rm_col *last_fg, theme_rm_col *last_bg,
int flags) int flags)
{ {
int index; int index;
unsigned char chr; unsigned char chr;
char *t;
chr = **format; chr = **format;
if ((chr == '$' || chr == '%') && if ((chr == '$' || chr == '%') &&
@ -203,22 +232,50 @@ static void theme_format_append_next(THEME_REC *theme, GString *str,
/* %n = change to default color */ /* %n = change to default color */
g_string_append(str, "%n"); 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, '%');
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, '%');
g_string_append_c(str, default_fg); g_string_append(str, default_fg.m);
} }
*last_fg = default_fg; *last_fg = default_fg;
*last_bg = default_bg; *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 { } else {
if (IS_FGCOLOR_FORMAT(chr)) if (IS_FGCOLOR_FORMAT(chr)) {
*last_fg = chr; (*last_fg).m[0] = chr;
if (IS_BGCOLOR_FORMAT(chr)) (*last_fg).m[1] = '\0';
*last_bg = chr; }
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, '%');
g_string_append_c(str, chr); 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) char *theme_format_expand_get(THEME_REC *theme, const char **format)
{ {
GString *str; 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 */ int braces = 1; /* we start with one brace opened */
str = g_string_new(NULL); str = g_string_new(NULL);
@ -321,7 +381,7 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
continue; continue;
} else { } else {
theme_format_append_next(theme, str, format, theme_format_append_next(theme, str, format,
'n', 'n', reset, reset,
&dummy, &dummy, 0); &dummy, &dummy, 0);
continue; continue;
} }
@ -343,15 +403,19 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
/* expand a single {abstract ...data... } */ /* expand a single {abstract ...data... } */
static char *theme_format_expand_abstract(THEME_REC *theme, static char *theme_format_expand_abstract(THEME_REC *theme,
const char **formatp, const char **formatp,
char default_fg, char default_bg, theme_rm_col *last_fg,
theme_rm_col *last_bg,
int flags) int flags)
{ {
GString *str; GString *str;
const char *p, *format; const char *p, *format;
char *abstract, *data, *ret; char *abstract, *data, *ret;
theme_rm_col default_fg, default_bg;
int len; int len;
format = *formatp; format = *formatp;
default_fg = *last_fg;
default_bg = *last_bg;
/* get abstract name first */ /* get abstract name first */
p = format; p = format;
@ -425,7 +489,7 @@ static char *theme_format_expand_abstract(THEME_REC *theme,
/* abstract may itself contain abstracts or replaces */ /* abstract may itself contain abstracts or replaces */
p = abstract; p = abstract;
ret = theme_format_expand_data(theme, &p, default_fg, default_bg, ret = theme_format_expand_data(theme, &p, default_fg, default_bg,
&default_fg, &default_bg, last_fg, last_bg,
flags | EXPAND_FLAG_LASTCOLOR_ARG); flags | EXPAND_FLAG_LASTCOLOR_ARG);
g_free(abstract); g_free(abstract);
return ret; return ret;
@ -433,13 +497,13 @@ static char *theme_format_expand_abstract(THEME_REC *theme,
/* expand the data part in {abstract data} */ /* expand the data part in {abstract data} */
char *theme_format_expand_data(THEME_REC *theme, const char **format, char *theme_format_expand_data(THEME_REC *theme, const char **format,
char default_fg, char default_bg, theme_rm_col default_fg, theme_rm_col default_bg,
char *save_last_fg, char *save_last_bg, theme_rm_col *save_last_fg, theme_rm_col *save_last_bg,
int flags) int flags)
{ {
GString *str; GString *str;
char *ret, *abstract; char *ret, *abstract;
char last_fg, last_bg; theme_rm_col last_fg, last_bg;
int recurse_flags; int recurse_flags;
last_fg = default_fg; last_fg = default_fg;
@ -482,7 +546,7 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
/* get a single {...} */ /* get a single {...} */
abstract = theme_format_expand_abstract(theme, format, abstract = theme_format_expand_abstract(theme, format,
last_fg, last_bg, &last_fg, &last_bg,
recurse_flags); recurse_flags);
if (abstract != NULL) { if (abstract != NULL) {
g_string_append(str, abstract); 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 */ /* save the last color */
if (save_last_fg != NULL) if (save_last_fg != NULL)
*save_last_fg = last_fg; *save_last_fg = last_fg;
if (save_last_bg != NULL) if (save_last_bg != NULL)
*save_last_bg = last_bg; *save_last_bg = last_bg;
}
ret = str->str; ret = str->str;
g_string_free(str, FALSE); 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) static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
{ {
GString *str; GString *str;
char *ret, last_fg, last_bg; char *ret;
char last_fg, last_bg;
str = g_string_new(NULL); 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)) if (IS_FGCOLOR_FORMAT(*format))
last_fg = *format; last_fg = *format;
else if (*format == 'Z' || *format == 'X')
last_fg = '\0';
if (IS_BGCOLOR_FORMAT(*format)) if (IS_BGCOLOR_FORMAT(*format))
last_bg = *format; last_bg = *format;
else if (*format == 'z' || *format == 'x')
last_bg = '\0';
} }
format++; 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 *theme_format_expand(THEME_REC *theme, const char *format)
{ {
char *data, *ret; char *data, *ret;
theme_rm_col reset;
strcpy(reset.m, "n");
g_return_val_if_fail(theme != NULL, NULL); g_return_val_if_fail(theme != NULL, NULL);
g_return_val_if_fail(format != 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); EXPAND_FLAG_ROOT);
ret = theme_format_compress_colors(theme, data); ret = theme_format_compress_colors(theme, data);
g_free(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); config_get_int(config, NULL, "default_color", -1);
theme->info_eol = config_get_bool(config, NULL, "info_eol", FALSE); 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); theme_read_replaces(config, theme);
if (path != NULL) if (path != NULL)

View file

@ -57,10 +57,14 @@ void theme_set_default_abstract(const char *key, const char *value);
#define EXPAND_FLAG_ROOT 0x10 #define EXPAND_FLAG_ROOT 0x10
#define EXPAND_FLAG_LASTCOLOR_ARG 0x20 #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(THEME_REC *theme, const char *format);
char *theme_format_expand_data(THEME_REC *theme, const char **format, char *theme_format_expand_data(THEME_REC *theme, const char **format,
char default_fg, char default_bg, theme_rm_col default_fg, theme_rm_col default_bg,
char *save_last_fg, char *save_last_bg, theme_rm_col *save_last_fg, theme_rm_col *save_last_bg,
int flags); int flags);
void themes_reload(void); void themes_reload(void);

View file

@ -25,6 +25,7 @@
#include "irc-servers.h" #include "irc-servers.h"
#include "irc-queries.h" #include "irc-queries.h"
#include "dcc-chat.h" #include "dcc-chat.h"
#include "ignore.h"
#include "module-formats.h" #include "module-formats.h"
#include "printtext.h" #include "printtext.h"
@ -86,12 +87,17 @@ static void sig_message_dcc(CHAT_DCC_REC *dcc, const char *msg)
TEXT_DEST_REC dest; TEXT_DEST_REC dest;
QUERY_REC *query; QUERY_REC *query;
char *tag; char *tag;
int level = MSGLEVEL_DCCMSGS;
tag = g_strconcat("=", dcc->id, NULL); tag = g_strconcat("=", dcc->id, NULL);
query = query_find(NULL, tag); 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, format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag,
MSGLEVEL_DCCMSGS, NULL); level, NULL);
printformat_dest(&dest, query != NULL ? IRCTXT_DCC_MSG_QUERY : printformat_dest(&dest, query != NULL ? IRCTXT_DCC_MSG_QUERY :
IRCTXT_DCC_MSG, dcc->id, msg); 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; TEXT_DEST_REC dest;
QUERY_REC *query; QUERY_REC *query;
char *tag; char *tag;
int level = MSGLEVEL_DCCMSGS | MSGLEVEL_ACTIONS;
tag = g_strconcat("=", dcc->id, NULL); tag = g_strconcat("=", dcc->id, NULL);
query = query_find(NULL, tag); 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, 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 : printformat_dest(&dest, query != NULL ? IRCTXT_ACTION_DCC_QUERY :
IRCTXT_ACTION_DCC, dcc->id, msg); 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; TEXT_DEST_REC dest;
char *tag; char *tag;
int level = MSGLEVEL_DCCMSGS | MSGLEVEL_CTCPS;
tag = g_strconcat("=", dcc->id, NULL); 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, 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); printformat_dest(&dest, IRCTXT_DCC_CTCP, dcc->id, cmd, data);
g_free(tag); g_free(tag);

View file

@ -44,6 +44,9 @@
static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
{ {
const char *target; const char *target;
char *subdata;
char **splitdata;
int n = 0;
CMD_IRC_SERVER(server); CMD_IRC_SERVER(server);
if (!IS_IRC_ITEM(item)) 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); cmd_return_error(CMDERR_NOT_CONNECTED);
target = window_item_get_target(item); target = window_item_get_target(item);
irc_server_send_action(server, target, data); splitdata = irc_server_split_action(server, target, data);
while ((subdata = splitdata[n++])) {
signal_emit("message irc own_action", 3, server, data, irc_server_send_action(server, target, subdata);
item->visible_name); signal_emit("message irc own_action", 3, server, subdata,
item->visible_name);
}
g_strfreev(splitdata);
} }
/* SYNTAX: ACTION [-<server tag>] <target> <message> */ /* SYNTAX: ACTION [-<server tag>] <target> <message> */
@ -64,6 +70,9 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server)
{ {
GHashTable *optlist; GHashTable *optlist;
const char *target, *text; const char *target, *text;
char *subtext;
char **splittexts;
int n = 0;
void *free_arg; void *free_arg;
CMD_IRC_SERVER(server); CMD_IRC_SERVER(server);
@ -79,10 +88,14 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server)
if (server == NULL || !server->connected) if (server == NULL || !server->connected)
cmd_param_error(CMDERR_NOT_CONNECTED); cmd_param_error(CMDERR_NOT_CONNECTED);
irc_server_send_action(server, target, text); splittexts = irc_server_split_action(server, target, text);
while ((subtext = splittexts[n++])) {
signal_emit("message irc own_action", 3, server, text, target); 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); cmd_params_free(free_arg);
} }

View file

@ -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)) if (ignore_check(SERVER(server), nick, address, target, msg, level))
return; return;
if (ignore_check(SERVER(server), nick, address, target, msg,
level | MSGLEVEL_NO_ACT))
level |= MSGLEVEL_NO_ACT;
if (ischannel(*target)) if (ischannel(*target))
item = irc_channel_find(server, target); item = irc_channel_find(server, target);
else else
@ -214,6 +218,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
const char *target) const char *target)
{ {
const char *oldtarget; const char *oldtarget;
int level = MSGLEVEL_NOTICES;
oldtarget = target; oldtarget = target;
target = skip_target(IRC_SERVER(server), 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, if (ignore_check(server, nick, address,
ischannel(*target) ? target : NULL, ischannel(*target) ? target : NULL,
msg, MSGLEVEL_NOTICES)) msg, level))
return; return;
if (ignore_check(server, nick, address,
ischannel(*target) ? target : NULL,
msg, level | MSGLEVEL_NO_ACT))
level |= MSGLEVEL_NO_ACT;
if (ischannel(*target)) { if (ischannel(*target)) {
/* notice in some channel */ /* notice in some channel */
printformat(server, target, MSGLEVEL_NOTICES, printformat(server, target, level,
IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg); IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg);
} else { } else {
/* private notice */ /* private notice */
privmsg_get_query(SERVER(server), nick, FALSE, privmsg_get_query(SERVER(server), nick, FALSE,
MSGLEVEL_NOTICES); MSGLEVEL_NOTICES);
printformat(server, nick, MSGLEVEL_NOTICES, printformat(server, nick, level,
IRCTXT_NOTICE_PRIVATE, nick, address, msg); IRCTXT_NOTICE_PRIVATE, nick, address, msg);
} }
} }

View file

@ -452,7 +452,7 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str)
g_utf8_validate(str, -1, &ptr); g_utf8_validate(str, -1, &ptr);
len = g_utf8_pointer_to_offset(str, ptr); len = g_utf8_pointer_to_offset(str, ptr);
} else if (term_type == TERM_TYPE_BIG5) } else if (term_type == TERM_TYPE_BIG5)
len = strlen_big5(str); len = strlen_big5((const unsigned char *)str);
else else
len = strlen(str); len = strlen(str);
entry_text_grow(entry, len); entry_text_grow(entry, len);

View file

@ -29,7 +29,14 @@
#include "gui-printtext.h" #include "gui-printtext.h"
#include "gui-windows.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 scrollback_lines, scrollback_time, scrollback_burst_remove;
static int next_xpos, next_ypos; 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) static void get_colors(int flags, int *fg, int *bg, int *attr)
{ {
*attr = 0;
if (flags & GUI_PRINT_FLAG_MIRC_COLOR) { if (flags & GUI_PRINT_FLAG_MIRC_COLOR) {
/* mirc colors - real range is 0..15, but after 16 /* mirc colors - extended colours proposal */
colors wrap to 0, 1, ... */ if (*bg >= 0) {
if (*bg >= 0) *bg = mirc_colors[*bg % 16]; *bg = mirc_colors[*bg % 100];
if (*fg >= 0) *fg = mirc_colors[*fg % 16]; flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
if (settings_get_bool("mirc_blink_fix")) if (settings_get_bool("mirc_blink_fix"))
*bg &= ~0x08; *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; *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; *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_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_BOLD) *attr |= ATTR_BOLD;
if (flags & GUI_PRINT_FLAG_UNDERLINE) *attr |= ATTR_UNDERLINE; if (flags & GUI_PRINT_FLAG_UNDERLINE) *attr |= ATTR_UNDERLINE;
if (flags & GUI_PRINT_FLAG_BLINK) *attr |= ATTR_BLINK; 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) { if (window == NULL) {
g_return_if_fail(next_xpos != -1); g_return_if_fail(next_xpos != -1);
attr |= fg >= 0 ? fg : ATTR_RESETFG; term_set_color2(root_window, attr, fg, bg);
attr |= bg >= 0 ? (bg << 4) : ATTR_RESETBG;
term_set_color(root_window, attr);
term_move(root_window, next_xpos, next_ypos); term_move(root_window, next_xpos, next_ypos);
if (flags & GUI_PRINT_FLAG_CLRTOEOL) if (flags & GUI_PRINT_FLAG_CLRTOEOL)

View file

@ -81,14 +81,24 @@ static int dirty, full_redraw, dummy;
static GMainLoop *main_loop; static GMainLoop *main_loop;
int quitting; int quitting;
static const char *banner_text =
" ___ _\n"
"|_ _|_ _ _____(_)\n"
" | || '_(_-<_-< |\n"
"|___|_| /__/__/_|\n"
"Irssi v" PACKAGE_VERSION " - http://www.irssi.org";
static const char *firsttimer_text = static const char *firsttimer_text =
"Looks like this is the first time you've run irssi.\n" "- - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
"This is just a reminder that you really should go read\n" "Hi there! If this is your first time using Irssi, you\n"
"startup-HOWTO if you haven't already. You can find it\n" "might want to go to our website and read the startup\n"
"and more irssi beginner info at http://www.irssi.org\n" "documentation to get you going.\n\n"
"\n" "Our community and staff are available to assist you or\n"
"For the truly impatient people who don't like any automatic\n" "to answer any questions you may have.\n\n"
"window creation or closing, just type: /MANUAL-WINDOWS"; "Use the HELP command to get detailed information about\n"
"the available commands.\n"
"- - - - - - - - - - - - - - - - - - - - - - - - - - - -";
static int display_firsttimer = FALSE; static int display_firsttimer = FALSE;
@ -193,9 +203,13 @@ static void textui_finish_init(void)
fe_common_core_finish_init(); fe_common_core_finish_init();
signal_emit("irssi init finished", 0); signal_emit("irssi init finished", 0);
statusbar_redraw(NULL, TRUE);
printtext_window(active_win, MSGLEVEL_CRAP,
"%s", banner_text);
if (display_firsttimer) { if (display_firsttimer) {
printtext_window(active_win, MSGLEVEL_CLIENTNOTICE, printtext_window(active_win, MSGLEVEL_CRAP,
"%s", firsttimer_text); "%s", firsttimer_text);
} }
} }

View file

@ -670,6 +670,8 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
SERVER_REC *server; SERVER_REC *server;
WI_ITEM_REC *wiitem; WI_ITEM_REC *wiitem;
char *tmpstr, *tmpstr2; char *tmpstr, *tmpstr2;
theme_rm_col reset;
strcpy(reset.m, "n");
int len; int len;
if (str == NULL) if (str == NULL)
@ -690,7 +692,7 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
/* expand templates */ /* expand templates */
tmpstr = theme_format_expand_data(current_theme, &str, tmpstr = theme_format_expand_data(current_theme, &str,
'n', 'n', reset, reset,
NULL, NULL, NULL, NULL,
EXPAND_FLAG_ROOT | EXPAND_FLAG_ROOT |
EXPAND_FLAG_IGNORE_REPLACES | EXPAND_FLAG_IGNORE_REPLACES |

View file

@ -275,25 +275,32 @@ static int get_attr(int color)
{ {
int attr; 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) if (!term_use_colors)
attr = (color & 0x70) ? A_REVERSE : 0; attr = (color & (0x7 << BG_SHIFT)) ? A_REVERSE : 0;
else if ((color & 0xff) == 8 || (color & (0xff | ATTR_RESETFG)) == 0) else if ((color & ((0xf << BG_SHIFT) | 0xf)) == 8 || (color & (FG_MASK | BG_MASK | ATTR_RESETFG)) == 0)
attr = COLOR_PAIR(63); attr = COLOR_PAIR(63);
else if ((color & 0x77) == 0) else if ((color & ((0x7 << BG_SHIFT) | 0x7)) == 0)
attr = A_NORMAL; attr = A_NORMAL;
else { else {
if (color & ATTR_RESETFG) { if (color & ATTR_RESETFG) {
color &= ~0x0f; color &= ~FG_MASK;
color |= settings_get_int("default_color"); color |= settings_get_int("default_color");
} }
attr = COLOR_PAIR((color&7) | ((color&0x70)>>1)); attr = COLOR_PAIR((color&0x7) | ((color&(0x7<<BG_SHIFT))>>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_BLINK) attr |= A_BLINK;
if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE; if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE;
if (color & ATTR_REVERSE) attr |= A_REVERSE; if (color & ATTR_REVERSE) attr |= A_REVERSE;
#ifdef A_ITALIC
if (color & ATTR_ITALIC) attr |= A_ITALIC;
#endif
return attr; return attr;
} }

View file

@ -22,9 +22,12 @@
#include "signals.h" #include "signals.h"
#include "term.h" #include "term.h"
#include "terminfo-core.h" #include "terminfo-core.h"
#include "fe-windows.h"
#include "utf8.h" #include "utf8.h"
#include <signal.h> #include <signal.h>
#include <termios.h>
#include <stdio.h>
/* returns number of characters in the beginning of the buffer being a /* 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 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 crealx, crealy, cforcemove;
static int curs_x, curs_y; 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 GSource *sigcont_source;
static volatile sig_atomic_t got_sigcont; static volatile sig_atomic_t got_sigcont;
@ -136,7 +140,7 @@ int term_init(void)
term_set_input_type(TERM_TYPE_8BIT); term_set_input_type(TERM_TYPE_8BIT);
term_common_init(); term_common_init();
g_atexit(term_deinit); atexit(term_deinit);
return TRUE; return TRUE;
} }
@ -293,49 +297,88 @@ void term_window_scroll(TERM_WINDOW *window, int count)
term_lines_empty[window->y+y] = FALSE; 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 */ /* 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) void term_set_color(TERM_WINDOW *window, int col)
#endif
{ {
int set_normal; int set_normal;
int fg = col & 0x0f;
int bg = (col & 0xf0) >> 4;
set_normal = ((col & ATTR_RESETFG) && last_fg != -1) || unsigned int fg =
((col & ATTR_RESETBG) && last_bg != -1); #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) || 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)) { ((last_attrs & ATTR_BLINK) && (col & ATTR_BLINK) == 0)) {
/* we'll need to get rid of bold/blink - this can only be /* we'll need to get rid of bold/blink/reverse - this
done with setting the default color */ can only be done with setting the default color */
set_normal = TRUE; set_normal = TRUE;
} }
if (set_normal) { if (set_normal) {
last_fg = last_bg = -1; last_fg = last_bg = COLOR_RESET;
last_attrs = 0; last_attrs = 0;
terminfo_set_normal(); 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 */ /* set foreground color */
if (fg != last_fg && if (fg != last_fg &&
(fg != 0 || (col & ATTR_RESETFG) == 0)) { (fg != 0 || (col & ATTR_RESETFG) == 0)) {
if (term_use_colors) { if (term_use_colors) {
last_fg = fg; 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 */ /* 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; col |= ATTR_BLINK;
if (col & ATTR_BLINK) if (col & ATTR_BLINK)
current_term->set_blink(current_term); 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)) { (bg != 0 || (col & ATTR_RESETBG) == 0)) {
if (term_use_colors) { if (term_use_colors) {
last_bg = bg; 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 */ /* bold */
if (col & 0x08 && window->term->TI_colors == 8) if (window && (term_color256map[fg&0xff]&8) == window->term->TI_colors)
col |= ATTR_BOLD; col |= ATTR_BOLD;
if (col & ATTR_BOLD) if (col & ATTR_BOLD)
terminfo_set_bold(); terminfo_set_bold();
@ -361,7 +411,15 @@ void term_set_color(TERM_WINDOW *window, int col)
} else if (last_attrs & ATTR_UNDERLINE) } else if (last_attrs & ATTR_UNDERLINE)
terminfo_set_uline(FALSE); 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) 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 */ /* clrtoeol() doesn't necessarily understand colors */
if (last_fg == -1 && last_bg == -1 && 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 (!term_lines_empty[vcy]) {
if (vcmove) term_move_real(); if (vcmove) term_move_real();
terminfo_clrtoeol(); terminfo_clrtoeol();
@ -522,7 +580,7 @@ void term_stop(void)
static int input_utf8(const unsigned char *buffer, int size, unichar *result) 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) { switch (c) {
case (unichar)-1: case (unichar)-1:

View file

@ -37,6 +37,7 @@
int term_width, term_height; int term_width, term_height;
int term_use_colors; int term_use_colors;
int term_use_colors24;
int term_type; int term_type;
static int force_colors; static int force_colors;
@ -106,10 +107,28 @@ static void cmd_redraw(void)
irssi_redraw(); 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) static void read_settings(void)
{ {
const char *str; const char *str;
int old_colors = term_use_colors; int old_colors = term_use_colors;
int old_colors24 = term_use_colors24;
int old_type = term_type; int old_type = term_type;
/* set terminal type */ /* set terminal type */
@ -133,7 +152,14 @@ static void read_settings(void)
term_use_colors = settings_get_bool("colors") && term_use_colors = settings_get_bool("colors") &&
(force_colors || term_has_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(); irssi_redraw();
} }
@ -149,6 +175,12 @@ void term_common_init(void)
force_colors = FALSE; force_colors = FALSE;
term_use_colors = term_has_colors() && settings_get_bool("colors"); 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(); read_settings();
if (g_get_charset(&dummy)) { if (g_get_charset(&dummy)) {

View file

@ -3,17 +3,24 @@
typedef struct _TERM_WINDOW TERM_WINDOW; typedef struct _TERM_WINDOW TERM_WINDOW;
#define FG_MASK ( 0x00ff )
#define BG_MASK ( 0xff00 )
#define BG_SHIFT 8
/* text attributes */ /* text attributes */
#define ATTR_RESETFG 0x0100 #define ATTR_RESETFG ( 0x010000 )
#define ATTR_RESETBG 0x0200 #define ATTR_RESETBG ( 0x020000 )
#define ATTR_BOLD 0x0400 #define ATTR_BOLD ( 0x040000 )
#define ATTR_BLINK 0x0800 #define ATTR_BLINK ( 0x080000 )
#define ATTR_UNDERLINE 0x1000 #define ATTR_UNDERLINE ( 0x100000 )
#define ATTR_REVERSE 0x2000 #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_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 */ /* terminal types */
#define TERM_TYPE_8BIT 0 /* normal 8bit text */ #define TERM_TYPE_8BIT 0 /* normal 8bit text */
@ -25,6 +32,8 @@ typedef guint32 unichar;
extern TERM_WINDOW *root_window; extern TERM_WINDOW *root_window;
extern int term_width, term_height; extern int term_width, term_height;
extern int term_use_colors, term_type; extern int term_use_colors, term_type;
extern int term_use_colors24;
extern int term_color256map[];
/* Initialize / deinitialize terminal */ /* Initialize / deinitialize terminal */
int term_init(void); int term_init(void);
@ -63,7 +72,13 @@ void term_window_clear(TERM_WINDOW *window);
/* Scroll window up/down */ /* Scroll window up/down */
void term_window_scroll(TERM_WINDOW *window, int count); 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); void term_set_color(TERM_WINDOW *window, int col);
#endif
void term_move(TERM_WINDOW *window, int x, int y); void term_move(TERM_WINDOW *window, int x, int y);
void term_addch(TERM_WINDOW *window, char chr); void term_addch(TERM_WINDOW *window, char chr);

View file

@ -94,8 +94,11 @@ static TERMINFO_REC tcaps[] = {
{ "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) }, { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) },
{ "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) }, { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) },
{ "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) }, { "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) }, { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) },
{ "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) }, { "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) }, { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) },
{ "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) }, { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) },
{ "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) }, { "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)); tput(tparm(term->TI_blink));
} }
/* Reverse on */
static void _set_reverse(TERM_REC *term)
{
tput(tparm(term->TI_rev));
}
/* Bold on */ /* Bold on */
static void _set_bold(TERM_REC *term) 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)); 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 */ /* Change foreground color */
static void _set_fg(TERM_REC *term, int 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 */ /* Change background color */
static void _set_bg(TERM_REC *term, int 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 */ /* Beep */
@ -596,13 +630,17 @@ static int term_setup(TERM_REC *term)
else else
term->repeat = _repeat_manual; term->repeat = _repeat_manual;
/* Bold, underline, standout */ /* Bold, underline, standout, reverse, italics */
term->set_blink = term->TI_blink ? _set_blink : _ignore; term->set_blink = term->TI_blink ? _set_blink : _ignore;
term->set_bold = term->TI_bold ? _set_bold : _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 ? term->set_uline = term->TI_smul && term->TI_rmul ?
_set_uline : _ignore_parm; _set_uline : _ignore_parm;
term->set_standout = term->TI_smso && term->TI_rmso ? term->set_standout = term->TI_smso && term->TI_rmso ?
_set_standout : _ignore_parm; _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 */ /* Create a string to set all attributes off */
str = g_string_new(NULL); str = g_string_new(NULL);
@ -612,6 +650,8 @@ static int term_setup(TERM_REC *term)
g_string_append(str, term->TI_rmul); g_string_append(str, term->TI_rmul);
if (term->TI_rmso && (term->TI_sgr0 == NULL || strcmp(term->TI_rmso, term->TI_sgr0) != 0)) if (term->TI_rmso && (term->TI_sgr0 == NULL || strcmp(term->TI_rmso, term->TI_sgr0) != 0))
g_string_append(str, term->TI_rmso); 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; term->TI_normal = str->str;
g_string_free(str, FALSE); g_string_free(str, FALSE);
term->set_normal = _set_normal; term->set_normal = _set_normal;

Some files were not shown because too many files have changed in this diff Show more