From: Pekka Riikonen
Date: Sun, 17 Feb 2002 17:26:24 +0000 (+0000)
Subject: updates.
X-Git-Tag: silc.client.0.8.1~48
X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=35013080aabb8ec82609c07c43c5444cbf6568e4;p=silc.git
updates.
---
diff --git a/CHANGES b/CHANGES
index 0faf7a25..2dede966 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Sun Feb 17 19:02:56 EET 2002 Pekka Riikonen
+
+ * Merged latest Irssi (0.8.1) from the irssi.org's CVS into
+ the SILC tree.
+
Sun Feb 17 15:52:30 EET 2002 Pekka Riikonen
* Added `user_count' to the SilcChannelEntry which now tells the
diff --git a/apps/irssi/.cvsignore b/apps/irssi/.cvsignore
new file mode 100644
index 00000000..bbb8ef8f
--- /dev/null
+++ b/apps/irssi/.cvsignore
@@ -0,0 +1,36 @@
+Makefile
+Makefile.in
+aclocal.m4
+config.cache
+config.guess
+config.h
+config.log
+config.status
+config.sub
+configure
+configure.scan
+libtool
+libtool-shared
+ltconfig
+ltmain.sh
+stamp-h
+stamp-h.in
+stamp.h
+version.h
+config.h.in
+.exrc
+install-sh
+missing
+mkinstalldirs
+INSTALL
+intl
+ABOUT-NLS
+COPYING
+irssi.spec
+default-config.h
+default-theme.h
+irssi-version.h
+irssi-config
+colorless.theme
+build-stamp
+configure-stamp
diff --git a/apps/irssi/Makefile.am b/apps/irssi/Makefile.am
index 5d3888cf..4f79ed20 100644
--- a/apps/irssi/Makefile.am
+++ b/apps/irssi/Makefile.am
@@ -38,6 +38,7 @@ EXTRA_DIST = \
$(theme_DATA) \
irssi-config.in \
irssi-icon.png \
+ syntax.pl \
Makefile.defines.in \
Makefile.defines_int.in
diff --git a/apps/irssi/README b/apps/irssi/README
index 7f8fdc77..fd05732b 100644
--- a/apps/irssi/README
+++ b/apps/irssi/README
@@ -3,11 +3,16 @@
irssi, http://irssi.org
+ * INSTALLATION
+
+See INSTALL file.
+
+
* FILES
- docs/ directory contains several documents:
- startup-HOWTO.txt - new users should read this
- - manual.txt - manual I started writing but didn't get it finished :)
+ - manual.txt - manual I started writing but didn't get it very far :)
- perl.txt - Perl scripting help
- formats.txt - How to use colors, etc. with irssi
- faq.txt - Frequently Asked Questions
@@ -107,5 +112,5 @@ See TODO file if it is already listed in there - if not send me email..
- Timo Sirainen
- tss@iki.fi
- - cras@ircnet/efnet/opn/silc
- - #irssi@ircnet/opn
+ - cras at ircnet/opn/silc
+ - #irssi at ircnet/opn, #irssi.fi at ircnet
diff --git a/apps/irssi/configure.in b/apps/irssi/configure.in
index dfa63c84..79e9eeec 100644
--- a/apps/irssi/configure.in
+++ b/apps/irssi/configure.in
@@ -7,7 +7,7 @@ if test -n "`grep '^#undef VERSION' config.h.in`"; then
fi
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(Irssi-SILC, 0.7.99)
+AM_INIT_AUTOMAKE(Irssi-SILC, 0.8.1)
AM_MAINTAINER_MODE
@@ -30,19 +30,6 @@ AC_CHECK_HEADERS(string.h stdlib.h unistd.h dirent.h sys/ioctl.h sys/resource.h)
# check posix headers..
AC_CHECK_HEADERS(sys/time.h sys/utsname.h regex.h)
-AC_ARG_WITH(big5,
-[ --with-big5 Build with tr-Chinese Big5 support],
- if test x$withval = xyes; then
- want_big5=yes
- else
- if test "x$withval" = xno; then
- want_big5=no
- else
- want_big5=yes
- fi
- fi,
- want_big5=no)
-
AC_ARG_WITH(socks,
[ --with-socks Build with socks support],
if test x$withval = xyes; then
@@ -217,7 +204,7 @@ case "$host_os" in
esac
-AC_CHECK_FUNCS(mkfifo fcntl)
+AC_CHECK_FUNCS(mkfifo fcntl nl_langinfo)
AC_CHECK_FUNC(socket, [], [
AC_CHECK_LIB(socket, socket, [
@@ -304,12 +291,14 @@ AC_DEFUN(AC_CHECK_GLIBDIR,[
if test -f $full_glib_dir/gmodule/.libs/libgmodule.a; then
GLIB_LIBS="$GLIB_LIBS $full_glib_dir/gmodule/.libs/libgmodule.a"
AC_DEFINE(HAVE_GMODULE)
+ have_gmodule=yes
fi
else
GLIB_LIBS="$full_glib_dir/libglib.a $GLIB_LDEXTRA"
if test -f $full_glib_dir/gmodule/libgmodule.a; then
GLIB_LIBS="$GLIB_LIBS $full_glib_dir/gmodule/libgmodule.a"
AC_DEFINE(HAVE_GMODULE)
+ have_gmodule=yes
fi
fi
AC_SUBST(GLIB_CFLAGS)
@@ -329,6 +318,7 @@ if test -z "$GLIB_DIR"; then
AM_PATH_GLIB(1.2.0)
else
AC_DEFINE(HAVE_GMODULE)
+ have_gmodule=yes
fi
if test -z "$GLIB_LIBS"; then
@@ -444,11 +434,9 @@ if test "x$want_textui" = "xyes"; then
AC_CHECK_FUNC(idcok, AC_DEFINE(HAVE_CURSES_IDCOK))
AC_CHECK_FUNC(resizeterm, AC_DEFINE(HAVE_CURSES_RESIZETERM))
AC_CHECK_FUNC(wresize, AC_DEFINE(HAVE_CURSES_WRESIZE))
- if test "x$want_terminfo" = "xyes"; then
- AC_CHECK_LIB(curses, setupterm,, [
- want_termcap=yes
- ])
- fi
+ AC_CHECK_FUNC(setupterm,, [
+ want_termcap=yes
+ ])
else
AC_CHECK_LIB(tinfo, setupterm, [
LIBS="$LIBS -ltinfo"
@@ -728,14 +716,6 @@ COMMON_LIBS="$FE_COMMON_LIBS $COMMON_NOUI_LIBS"
AC_SUBST(COMMON_NOUI_LIBS)
AC_SUBST(COMMON_LIBS)
-dnl **
-dnl ** tr-Chinese Big5 support
-dnl **
-
-if test "x$want_big5" = "xyes"; then
- AC_DEFINE(WANT_BIG5)
-fi
-
dnl **
dnl ** IPv6 support
dnl **
@@ -838,6 +818,13 @@ fi
echo "Building irssi bot ......... : $want_irssibot"
echo "Building irssi proxy ....... : $want_irssiproxy"
echo "Building with IPv6 support . : $want_ipv6"
+if test "x$have_gmodule" = "xyes"; then
+ echo "Building with module support : yes"
+else
+ echo "Building with module support : NO!! /LOAD will not work!"
+ echo " - You're missing gmodule (comes with glib) for some reason,"
+ echo " or it doesn't work in your system."
+fi
if test "x$want_perl" = "xstatic"; then
echo "Building with Perl support . : static (in irssi binary)"
@@ -873,5 +860,6 @@ if test "x$want_perl" != "xno"; then
echo " Anyway, installing perl to this directory should work just as well."
fi
fi
+
echo "Install prefix ............. : $prefix"
diff --git a/apps/irssi/docs/faq.txt b/apps/irssi/docs/faq.txt
index 6f603e8d..d8825106 100644
--- a/apps/irssi/docs/faq.txt
+++ b/apps/irssi/docs/faq.txt
@@ -1,21 +1,18 @@
Q: Why doesn't irssi display colors even when ircii etc. displays them?
-A: Irssi uses curses, ircii and others don't (no, not even if ldd says they
- use it). Curses decides if terminal supports colors based on the TERM
- variable, so changing it should help. Some values to try when running
- in xterm are: xterm, xterm-color and color_xterm.
-
-Q: Why does irssi crash when pressing Ctrl-4?
-A: Most unices are usually configured to send SIGQUIT to active process when
- Ctrl-\ is pressed. Some terminals also treat Ctrl-4 and Ctrl-\ equally, so
- Irssi will die to SIGQUIT. Two ways to fix this: change it to something
- else with stty (stty quit undef) or in irssi /SET ignore_signals quit
-
-Q: Where's the GUI version?
-A: Read http://irssi.org/?page=about
+A: They force ANSI colors even if terminal doesn't support them. By default,
+ irssi uses colors only if terminfo/termcap so says. The correct way to
+ fix this would be to change your TERM environment to a value where colors
+ work, like xterm-color or color_xterm. If this doesn't help, then use the
+ evil way of /SET term_force_colors ON.
Q: How do I easily write text to channel that starts with '/' character?
A: / /text
+Q: Why doesn't irssi update my realname (or whatever) after I change it
+ with /SET realname and reconnect with /RECONNECT or /SERVER?
+A: Irssi is trying to be too smart. This will be fixed in future, but for
+ now you should use /DISCONNECT + /CONNECT.
+
Q: I connected to some server which isn't responding but now irssi tries
to connect back to it all the time! How can I stop it?
A: Two ways. The "good way" to do it is with /DISCONNECT. Check the server
@@ -25,12 +22,49 @@ A: Two ways. The "good way" to do it is with /DISCONNECT. Check the server
reconnections with /RMRECONNS, easier but may remove some connections
you actually wanted to reconnect (if you used multiple servers..).
+Q: How do I add seconds to timestamp?
+A: "/FORMAT timestamp {timestamp %%H:%%M:%%S} " - and remember to add the
+ trailing space :)
+
Q: Why does irssi say "Irssi: Channel not fully synchronized yet, try again
after a while" when I try to use /BAN etc?
-A: IRC server you use is coded badly, do something like this:
- /IRCNET ADD -querychans 1 quakenet
- /SERVER ADD -ircnet quakenet irc.quakenet.org
- /SAVE
- After that /CONNECT quakenet should work properly (NOTE: when you do this
- the first time you'll have to /DISCONNECT and /CONNECT again, /SERVER
- doesn't work correctly).
+A: Possibly a bug in irssi, or ircd you're using does something that irssi
+ didn't really notice. The new code should make this happen far less often
+ than before, but one known reason for this is when irssi doesn't notice
+ that you were unable to join some channel. Currently however I don't know
+ of any such events irssi doesn't know about.
+
+ Anyway, if this does happen, do "/RAWLOG SAVE ~/rawlog" soon after joining
+ to channel, and either try to figure out yourself why irssi didn't get
+ reply to WHO request, or send the whole log to tss@iki.fi. Note that the
+ rawlog is by default only 200 lines and it may not be enough to show all
+ needed information, so you might want to do /SET rawlog_lines 1000 or so.
+
+Q: Where's the GUI version?
+A: Read http://irssi.org/?page=about
+
+Q: How do I autorejoin channels after being kicked?
+A: That's evil and you shouldn't do it. If you get kicked, you should
+ stay out, at least until the channel forgot you existed :) Most channels
+ I've joined just ban you if you autorejoin after kick. If you're joined
+ to channels who kick people for fun, try changing channels or something.
+
+ Anyway, if you REALLY want to do that, and you understand that you're
+ doing evilness, you can use the autorejoin.pl script that comes with
+ irssi. You'll still need to specify the channels you wish to rejoin with
+ /SET autorejoin_channels #chan1 #chan2 ...
+
+Q: How do I announce that I'm away/back in all channels I've joined?
+ Or how do I change my nick when setting myself away/back?
+A: That's even worse than autorejoin. Who could possibly care every time you
+ come and go? Many channels will kick you for using this, and I for example
+ have added several ignores so I'd never need to see these messages. Learn
+ to use /AWAY command properly and tell it's existence to people who don't
+ know about it. /WII yournick shows your away reason much better for people
+ who actually want to know if you're there or not.
+
+ You can script these behaviours if you really wish to of course. But
+ currently there's no public scripts for either of these, and the only way
+ I'm going to add such to irssi.org is if the script contains a setting to
+ specify which specific channels the announcement is sent.
+
diff --git a/apps/irssi/docs/help/in/bind.in b/apps/irssi/docs/help/in/bind.in
index 0d0d2ab1..152ac34d 100644
--- a/apps/irssi/docs/help/in/bind.in
+++ b/apps/irssi/docs/help/in/bind.in
@@ -13,7 +13,9 @@ Most most commonly used keystrokes are:
Irssi has by default also defined several other keys which you can use:
return - The return/enter key
+ space, backspace - Space / backspace
up, down, left, right - Arrow keys
+ cleft, cright - Ctrl-left/right
home, end, prior, next - prior = Page Up, next = Page Down
insert, delete
@@ -75,6 +77,7 @@ Command can be one of:
delete_character
delete_next_word
delete_previous_word
+ delete_to_next_space
delete_to_previous_space
erase_line
erase_to_beg_of_line
@@ -82,6 +85,7 @@ Command can be one of:
(Word completion)
word_completion
+ erase_completion
check_replaces - Check word replaces
(Misc)
@@ -89,6 +93,7 @@ Command can be one of:
yank_from_cutbuffer - "Undelete" line
transpose_characters - Swap current and previous character
insert_text - Insert data to entry line, data may contain $variables.
+ stop_irc - Send SIGSTOP to client (^Z)
Examples:
diff --git a/apps/irssi/docs/help/in/levels.in b/apps/irssi/docs/help/in/levels.in
index 937ec1dd..e48a79fd 100644
--- a/apps/irssi/docs/help/in/levels.in
+++ b/apps/irssi/docs/help/in/levels.in
@@ -11,7 +11,7 @@ list of them all:
ACTIONS - Actions (/me) - usually ORed with PUBLIC or MSGS
JOINS - Someone joins a channel
PARTS - Someone parts a channel
- QUITS - Someone quits IRC
+ QUITS - Someone quits network
KICKS - Someone gets kicked from channel
MODES - Channel mode is changed
TOPICS - Channel topic is changed
diff --git a/apps/irssi/docs/help/in/statusbar.in b/apps/irssi/docs/help/in/statusbar.in
new file mode 100644
index 00000000..5b47bc86
--- /dev/null
+++ b/apps/irssi/docs/help/in/statusbar.in
@@ -0,0 +1,4 @@
+
+@SYNTAX:statusbar@
+
+Commands for modifying statusbar.
diff --git a/apps/irssi/docs/help/in/upgrade.in b/apps/irssi/docs/help/in/upgrade.in
new file mode 100644
index 00000000..f7c5cfa1
--- /dev/null
+++ b/apps/irssi/docs/help/in/upgrade.in
@@ -0,0 +1,7 @@
+
+@SYNTAX:upgrade@
+
+Upgrade irssi to new version on-the-fly without disconnecting from
+server, so other people won't even notice you quit from network. This ONLY
+executes the new binary, it does NOT download/compile/whatever irssi.
+
diff --git a/apps/irssi/docs/perl.txt b/apps/irssi/docs/perl.txt
index b04e0cb9..0d779a8e 100644
--- a/apps/irssi/docs/perl.txt
+++ b/apps/irssi/docs/perl.txt
@@ -1,23 +1,22 @@
- Running Perl scripts
- --------------------
+ Installation problems
+ ---------------------
-First you'll need to have Perl support on. By default irssi compiles
-Perl as a module, so /LOAD perl probably helps. If you want to do this
-automatically at startup put the "/LOAD perl" to ~/.irssi/startup file.
-After that you can run scripts with /RUN script (you don't need to give
-the .pl extension). If /RUN complains about "unknown command", you
-don't have Perl module loaded, or maybe Perl support wasn't compiled at
-all.
+You'll need to have perl support compiled with irssi. If "/LOAD"
+doesn't show perl in list of loaded modules, you have a problem. See
+INSTALL file for information about perl problems.
-Place new scripts to ~/.irssi/scripts/ or /usr/local/lib/irssi/scripts/
-directory. Scripts in ~/.irssi/scripts/autorun/ directory are
-automatically run at startup.
-Using /PERLFLUSH closes and reopens the perl interpreter removing all
-Perl scripts from memory. There's currently no way to unload a single
-Perl script (/SCRIPT REMOVE will probably work soon). You can however
-run same script multiple times, and irssi will remove the old version
-from memory before running the new version.
+ Running scripts
+ ---------------
+
+Scripts are run with /SCRIPT LOAD command, or the default /RUN alias.
+"/SCRIPT" shows list of running script, and /SCRIPT UNLOAD can unload
+scripts.
+
+Scripts should be placed to ~/.irssi/scripts/ or
+/usr/local/lib/irssi/scripts/ (or depending on where irssi was
+installed) directories. After that /RUN script_name should work, you
+don't need to add the .pl prefix.
Irssi's signals
@@ -522,8 +521,8 @@ Server::ischannel(data)
Server::get_nick_flags()
Returns nick flag characters in order: op, voice, halfop ("@+%" in IRC).
-Server::send_message(target, msg)
- Sends a message to nick/channel.
+Server::send_message(target, msg, target_type)
+ Sends a message to nick/channel. target_type 0 = channel, 1 = nick
*** Server reconnections
diff --git a/apps/irssi/docs/signals.txt b/apps/irssi/docs/signals.txt
index f32789fc..f009a4de 100644
--- a/apps/irssi/docs/signals.txt
+++ b/apps/irssi/docs/signals.txt
@@ -302,7 +302,7 @@ fe-irc-messages.c:
"message irc own_notice", SERVER_REC, char *msg, char *target
"message irc notice", SERVER_REC, char *msg, char *nick, char *address, char *target
"message irc own_ctcp", SERVER_REC, char *cmd, char *data, char *target
- "message irc ctcp", SERVER_REC, char *msg, char *nick, char *address, char *target
+ "message irc ctcp", SERVER_REC, char *cmd, char *data, char *nick, char *address, char *target
dcc/fe-dcc-chat-messages.c:
"message dcc own", DCC_REC *dcc, char *msg
diff --git a/apps/irssi/docs/startup-HOWTO.html b/apps/irssi/docs/startup-HOWTO.html
index dd8f2148..ddd5d025 100644
--- a/apps/irssi/docs/startup-HOWTO.html
+++ b/apps/irssi/docs/startup-HOWTO.html
@@ -2,18 +2,21 @@
To new Irssi users (not to new IRC users ..)
- Copyright (c) 2000-2001 by Timo Sirainen
+ Copyright (c) 2000-2002 by Timo Sirainen
Index with some FAQ questions that are answered in the chapter:
- For all the lazy people
-- Basic user interface usage
+- Basic user interface usage
+
+ - Split windows work in weird way
+
- Server and channel automation
- - how do I automatically connect to servers at startup?
- - how do I automatically join to channels at startup?
+ - How do I automatically connect to servers at startup?
+ - How do I automatically join to channels at startup?
- Setting up windows and automatically restoring them
at startup
@@ -34,8 +37,12 @@
- How can I save all texts in a window to file?
- Logging
-- Proxies and IRC bouncers
-- Irssi's settings
+- Changing keyboard bindings
+
+ - How do I make F1 key do something?
+
+- Proxies and IRC bouncers
+- Irssi's settings
@@ -342,7 +349,7 @@ see list of all active connections, use /SERVER without any parameters.
You should see a list of something like:
- -!- IRCNet: irc.telia.fi:6667 (IRCNet)
+ -!- IRCNet: irc.song.fi:6667 (IRCNet)
-!- OPN: tolkien.openprojects.net:6667 (OPN)
-!- RECON-1: 192.168.0.1:6667 () (02:59 left before reconnecting)
@@ -436,9 +443,9 @@ buffer. Simplest usages are
/LASTLOG -topics - print all topic changes
-If there's more lines to be printed than 1000, irssi doesn't thinks
-that you probably made some mistake and won't print them without -force
-option. If you want to save the full lastlog to file, use
+If there's more than 1000 lines to be printed, irssi thinks that you
+probably made some mistake and won't print them without -force option.
+If you want to save the full lastlog to file, use
/LASTLOG -file ~/irc.log
@@ -501,7 +508,36 @@ logs by adding date/time formats to the file name. The formats are in
For logging only some specific channels or nicks, see /HELP log
-
+
+
+You can change any keyboard binding that terminal lets irssi know
+about. It doesn't let irssi know everything, so for example
+shift-backspace can't be bound unless you modify xterm resources
+somehow.
+
+/HELP bind tells pretty much everything there is to know about
+keyboard bindings. However, there's the problem of how to bind some
+non-standard keys. They might differ a bit with each terminal, so
+you'll need to find out what exactly the keypress produces. Easiest
+way to check that would be to see what it prints in "cat". Here's
+an example for pressing F1 key:
+
+
+[cras@hurina] ~% cat
+^[OP
+
+
+So in irssi you would use /BIND ^[OP /ECHO F1 pressed. If you use
+multiple terminals which have different bindings for the key, it would
+be better to use eg.:
+
+
+/BIND ^[OP key F1
+/BIND ^[11~ key F1
+/BIND F1 /ECHO F1 pressed.
+
+
+
Irssi supports connecting to IRC servers via a proxy. All proxies have
these settings in common:
@@ -521,6 +557,32 @@ these settings in common:
/EVAL SET proxy_string CONNECT %s:%d\n\n
+BNC
+
+
+ /SET proxy_password your_pass
+ /SET -clear proxy_string
+ /SET proxy_string conn %s %d
+
+
+dircproxy
+
+dircproxy separates the server connections by passwords. So, if you
+for example have ircnet connection with password ircpass and
+openprojects connection with opnpass, you would do something like
+this:
+
+
+ /SET -clear proxy_password
+ /SET -clear proxy_string
+
+ /SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
+ /SERVER ADD -auto -ircnet opn fake.opn 6667 opnpass
+
+
+The server name and port you give isn't used anywhere, so you can
+put anything you want in there.
+
Irssi proxy
Irssi contains it's own proxy which you can build giving
@@ -538,7 +600,7 @@ ports, like you can share ircnet in port 2777 and efnet in port 2778.
Usage in proxy side:
- /LOAD irc_proxy (/LOAD proxy in irssi 0.7.98.3 and older)
+ /LOAD proxy
/SET irssiproxy_password <password>
/SET irssiproxy_ports <ircnet>=<port> ... (eg. ircnet=2777 efnet=2778)
@@ -549,7 +611,7 @@ are using to server and ircnet lists with /SERVER ADD and /IRCNET ADD.
one server connection, you may simply set:
- /SET irssiproxy_ports *=2777 (irssi 0.7.99 and later only)
+ /SET irssiproxy_ports *=2777
Usage in client side:
@@ -579,15 +641,18 @@ give it with:
/SET proxy_password <password>
-Irssi's default for connect string is
+Irssi's defaults for connect strings are
/SET proxy_string CONNECT %s %d
+ /SET proxy_string_after
-which you can modify according to your bouncer's needs.
+The proxy_string is sent before NICK/USER commands, the
+proxy_string_after is sent after them. %s and %d can be used with both
+of them.
-
+
You probably don't like Irssi's default settings. I don't like them.
But I'm still convinced that they're pretty good defaults. Here's some
@@ -716,9 +781,6 @@ of them you might want to change (the default value is shown):
Show quit message only once in some of the channel windows the
nick was in instead of in all windows.
-/SET topicbar ON
- Show the channel's topic in top of screen.
-
/SET lag_min_show 100
Show the server lag in status bar if it's bigger than this, the
unit is 1/100 of seconds (ie. the default value of 100 = 1 second).
@@ -735,12 +797,6 @@ of them you might want to change (the default value is shown):
If any highlighted text or message for you appears in that window, this
setting is ignored and the activity is shown.
-/SET mail_counter ON
- Show the number of mails in your mbox in status
- bar. The mbox file is taken from $MAIL environment setting. Only mbox
- format works for now.
-
-
Nick completion
diff --git a/apps/irssi/docs/startup-HOWTO.txt b/apps/irssi/docs/startup-HOWTO.txt
index cf989546..611965bc 100644
--- a/apps/irssi/docs/startup-HOWTO.txt
+++ b/apps/irssi/docs/startup-HOWTO.txt
@@ -2,14 +2,15 @@ Startup HOWTO
To new Irssi users (not to new IRC users ..)
- Copyright (c) 2000-2001 by Timo Sirainen
+ Copyright (c) 2000-2002 by Timo Sirainen
Index with some FAQ questions that are answered in the chapter:
1. For all the lazy people
2. Basic user interface usage
+ + Split windows work in weird way
3. Server and channel automation
- + how do I automatically connect to servers at startup?
- + how do I automatically join to channels at startup?
+ + How do I automatically connect to servers at startup?
+ + How do I automatically join to channels at startup?
4. Setting up windows and automatically restoring them at startup
5. Status and msgs windows & message levels
+ I want /WHOIS to print reply to current window
@@ -23,8 +24,10 @@ Startup HOWTO
7. /LASTLOG and jumping around in scrollback
+ How can I save all texts in a window to file?
8. Logging
- 9. Proxies and IRC bouncers
- 10. Irssi's settings
+ 9. Changing keyboard bindings
+ + How do I make F1 key do something?
+ 10. Proxies and IRC bouncers
+ 11. Irssi's settings
1. For all the lazy people
@@ -257,7 +260,7 @@ Startup HOWTO
Instead of the /SERVER which disconnects the existing connection. To
see list of all active connections, use /SERVER without any
parameters. You should see a list of something like:
- -!- IRCNet: irc.telia.fi:6667 (IRCNet)
+ -!- IRCNet: irc.song.fi:6667 (IRCNet)
-!- OPN: tolkien.openprojects.net:6667 (OPN)
-!- RECON-1: 192.168.0.1:6667 () (02:59 left before reconnecting)
@@ -331,9 +334,9 @@ Startup HOWTO
/LASTLOG word 10 - print last 10 occurances of "word"
/LASTLOG -topics - print all topic changes
- If there's more lines to be printed than 1000, irssi doesn't thinks
- that you probably made some mistake and won't print them without
- -force option. If you want to save the full lastlog to file, use
+ If there's more than 1000 lines to be printed, irssi thinks that you
+ probably made some mistake and won't print them without -force option.
+ If you want to save the full lastlog to file, use
/LASTLOG -file ~/irc.log
With -file option you don't need -force even if there's more than 1000
@@ -377,7 +380,30 @@ Startup HOWTO
For logging only some specific channels or nicks, see /HELP log
- 9. Proxies and IRC bouncers
+ 9. Changing keyboard bindings
+
+ You can change any keyboard binding that terminal lets irssi know
+ about. It doesn't let irssi know everything, so for example
+ shift-backspace can't be bound unless you modify xterm resources
+ somehow.
+
+ /HELP bind tells pretty much everything there is to know about
+ keyboard bindings. However, there's the problem of how to bind some
+ non-standard keys. They might differ a bit with each terminal, so
+ you'll need to find out what exactly the keypress produces. Easiest
+ way to check that would be to see what it prints in "cat". Here's an
+ example for pressing F1 key:
+[cras@hurina] ~% cat
+^[OP
+
+ So in irssi you would use /BIND ^[OP /ECHO F1 pressed. If you use
+ multiple terminals which have different bindings for the key, it would
+ be better to use eg.:
+/BIND ^[OP key F1
+/BIND ^[11~ key F1
+/BIND F1 /ECHO F1 pressed.
+
+ 10. Proxies and IRC bouncers
Irssi supports connecting to IRC servers via a proxy. All proxies have
these settings in common:
@@ -391,6 +417,26 @@ Startup HOWTO
/SET -clear proxy_password
/EVAL SET proxy_string CONNECT %s:%d\n\n
+ BNC
+ /SET proxy_password your_pass
+ /SET -clear proxy_string
+ /SET proxy_string conn %s %d
+
+ dircproxy
+
+ dircproxy separates the server connections by passwords. So, if you
+ for example have ircnet connection with password ircpass and
+ openprojects connection with opnpass, you would do something like
+ this:
+ /SET -clear proxy_password
+ /SET -clear proxy_string
+
+ /SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
+ /SERVER ADD -auto -ircnet opn fake.opn 6667 opnpass
+
+ The server name and port you give isn't used anywhere, so you can put
+ anything you want in there.
+
Irssi proxy
Irssi contains it's own proxy which you can build giving --with-proxy
@@ -406,7 +452,7 @@ Startup HOWTO
ports, like you can share ircnet in port 2777 and efnet in port 2778.
Usage in proxy side:
- /LOAD irc_proxy (/LOAD proxy in irssi 0.7.98.3 and older)
+ /LOAD proxy
/SET irssiproxy_password
/SET irssiproxy_ports = ... (eg. ircnet=2777 efnet=2778)
@@ -414,7 +460,7 @@ Startup HOWTO
lists with /SERVER ADD and /IRCNET ADD. ..Except if you really don't
want to for some reason, and you only use one server connection, you
may simply set:
- /SET irssiproxy_ports *=2777 (irssi 0.7.99 and later only)
+ /SET irssiproxy_ports *=2777
Usage in client side:
@@ -436,12 +482,15 @@ Startup HOWTO
can give it with:
/SET proxy_password
- Irssi's default for connect string is
+ Irssi's defaults for connect strings are
/SET proxy_string CONNECT %s %d
+ /SET proxy_string_after
- which you can modify according to your bouncer's needs.
+ The proxy_string is sent before NICK/USER commands, the
+ proxy_string_after is sent after them. %s and %d can be used with both
+ of them.
- 10. Irssi's settings
+ 11. Irssi's settings
You probably don't like Irssi's default settings. I don't like them.
But I'm still convinced that they're pretty good defaults. Here's some
@@ -561,9 +610,6 @@ Startup HOWTO
Show quit message only once in some of the channel windows the
nick was in instead of in all windows.
- /SET topicbar ON
- Show the channel's topic in top of screen.
-
/SET lag_min_show 100
Show the server lag in status bar if it's bigger than this, the
unit is 1/100 of seconds (ie. the default value of 100 = 1
@@ -582,17 +628,12 @@ Startup HOWTO
message for you appears in that window, this setting is ignored
and the activity is shown.
- /SET mail_counter ON
- Show the number of mails in your mbox in status bar. The mbox
- file is taken from $MAIL environment setting. Only mbox format
- works for now.
-
- Nick completion
+ Nick completion
- /SET completion_auto OFF
- Automatically complete the nick if line begins with start of
- nick and the completion character. Learn to use the
- tab-completion instead, it's a lot better ;)
+ /SET completion_auto OFF
+ Automatically complete the nick if line begins with start
+ of nick and the completion character. Learn to use the
+ tab-completion instead, it's a lot better ;)
- /SET completion_char :
- Completion character to use.
+ /SET completion_char :
+ Completion character to use.
diff --git a/apps/irssi/scripts/autorejoin.pl b/apps/irssi/scripts/autorejoin.pl
index bbbb0ed8..3738f5fc 100644
--- a/apps/irssi/scripts/autorejoin.pl
+++ b/apps/irssi/scripts/autorejoin.pl
@@ -1,26 +1,41 @@
# automatically rejoin to channel after kicked
+# /SET autorejoin_channels #channel1 #channel2 ...
+
# NOTE: I personally don't like this feature, in most channels I'm in it
# will just result as ban. You've probably misunderstood the idea of /KICK
# if you kick/get kicked all the time "just for fun" ...
-use Irssi;
-use Irssi::Irc;
use strict;
+use Irssi::Irc;
-sub event_rejoin_kick {
- my ($server, $data) = @_;
- my ($channel, $nick) = split(/ +/, $data);
+sub channel_rejoin {
+ my ($server, $channel) = @_;
- return if ($server->{nick} ne $nick);
+ # check if channel has password
+ my $chanrec = $server->channel_find($channel);
+ my $password = $chanrec->{key} if ($chanrec);
+
+ # We have to use send_raw() because the channel record still
+ # exists and irssi won't even try to join to it with command()
+ $server->send_raw("JOIN $channel $password");
+}
+
+sub event_rejoin_kick {
+ my ($server, $data) = @_;
+ my ($channel, $nick) = split(/ +/, $data);
- # check if channel has password
- my $chanrec = $server->channel_find($channel);
- my $password = $chanrec->{key} if ($chanrec);
+ return if ($server->{nick} ne $nick);
- # We have to use send_raw() because the channel record still
- # exists and irssi won't even try to join to it with command()
- $server->send_raw("JOIN $channel $password");
+ # check if we want to autorejoin this channel
+ my @chans = split(/ ,/, Irssi::settings_get_str('autorejoin_channels'));
+ foreach my $chan (@chans) {
+ if (lc($chan) eq lc($channel)) {
+ channel_rejoin($server, $channel);
+ last;
+ }
+ }
}
+Irssi::settings_add_str('misc', 'autorejoin_channels', '');
Irssi::signal_add('event kick', 'event_rejoin_kick');
diff --git a/apps/irssi/silc.conf b/apps/irssi/silc.conf
index 3439e3c9..e95502c0 100644
--- a/apps/irssi/silc.conf
+++ b/apps/irssi/silc.conf
@@ -64,6 +64,7 @@ aliases = {
RUN = "SCRIPT LOAD";
UPTIME = "eval exec - expr `date +%s` - \\$F | awk '{print \"Irssi uptime: \"int(\\\\\\$1/3600/24)\"d \"int(\\\\\\$1/3600%24)\"h \"int(\\\\\\$1/60%60)\"m \"int(\\\\\\$1%60)\"s\" }'";
CALC = "exec - if which bc &>/dev/null\\; then echo '$*' | bc | awk '{print \"$*=\"$$1}'\\; else echo bc was not found\\; fi";
+ SBAR = "STATUSBAR";
};
#
@@ -105,13 +106,15 @@ statusbar = {
# the "default statusbar" to be displayed at the bottom of the window.
# contains all the normal items.
window = {
+ disabled = "no";
+
# window, root
type = "window";
# top, bottom
placement = "bottom";
# number
position = "1";
- # active, inactive, always, never (disables the statusbar)
+ # active, inactive, always
visible = "active";
# list of items in statusbar in the display order
@@ -164,7 +167,8 @@ statusbar = {
type = "root";
placement = "top";
position = "1";
- visible = "never";
+ visible = "always";
+ disabled = "yes";
items = {
barstart = { priority = "100"; };
topic = { };
diff --git a/apps/irssi/src/.cvsignore b/apps/irssi/src/.cvsignore
new file mode 100644
index 00000000..282522db
--- /dev/null
+++ b/apps/irssi/src/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/apps/irssi/src/core/channels-setup.c b/apps/irssi/src/core/channels-setup.c
index ac9b1c23..62d43b2c 100644
--- a/apps/irssi/src/core/channels-setup.c
+++ b/apps/irssi/src/core/channels-setup.c
@@ -38,7 +38,7 @@ static void channel_setup_save(CHANNEL_SETUP_REC *channel)
index = g_slist_index(setupchannels, channel);
parentnode = iconfig_node_traverse("(channels", TRUE);
- node = config_node_index(parentnode, index);
+ node = config_node_nth(parentnode, index);
if (node == NULL)
node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
diff --git a/apps/irssi/src/core/channels.c b/apps/irssi/src/core/channels.c
index 57288f7e..06bf0c41 100644
--- a/apps/irssi/src/core/channels.c
+++ b/apps/irssi/src/core/channels.c
@@ -249,5 +249,4 @@ void channels_deinit(void)
channels_setup_deinit();
signal_remove("event connected", (SIGNAL_FUNC) event_connected);
- module_uniq_destroy("CHANNEL");
}
diff --git a/apps/irssi/src/core/chat-commands.c b/apps/irssi/src/core/chat-commands.c
index 8b1b3738..933cc3f5 100644
--- a/apps/irssi/src/core/chat-commands.c
+++ b/apps/irssi/src/core/chat-commands.c
@@ -324,7 +324,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
return;
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- server = cmd_options_get_server("msg", optlist, SERVER(server));
+ server = cmd_options_get_server("msg", optlist, server);
if (server == NULL || !server->connected)
cmd_param_error(CMDERR_NOT_CONNECTED);
diff --git a/apps/irssi/src/core/commands.c b/apps/irssi/src/core/commands.c
index a96b5fa0..0899c9fa 100644
--- a/apps/irssi/src/core/commands.c
+++ b/apps/irssi/src/core/commands.c
@@ -717,7 +717,8 @@ int cmd_get_params(const char *data, gpointer *free_me, int count, ...)
cnt = PARAM_WITHOUT_FLAGS(count);
if (count & PARAM_FLAG_OPTCHAN) {
/* optional channel as first parameter */
- require_name = (count & PARAM_FLAG_OPTCHAN_NAME);
+ require_name = (count & PARAM_FLAG_OPTCHAN_NAME) ==
+ PARAM_FLAG_OPTCHAN_NAME;
arg = get_optional_channel(item, &datad, require_name);
str = (char **) va_arg(args, char **);
diff --git a/apps/irssi/src/core/commands.h b/apps/irssi/src/core/commands.h
index 3e55a2ad..e3bf4374 100644
--- a/apps/irssi/src/core/commands.h
+++ b/apps/irssi/src/core/commands.h
@@ -136,7 +136,7 @@ int command_have_option(const char *cmd, const char *option);
/* optional channel in first argument */
#define PARAM_FLAG_OPTCHAN 0x00010000
/* optional channel in first argument, but don't treat "*" as current channel */
-#define PARAM_FLAG_OPTCHAN_NAME 0x00030000
+#define PARAM_FLAG_OPTCHAN_NAME (0x00020000|PARAM_FLAG_OPTCHAN)
char *cmd_get_param(char **data);
/* get parameters from command - you should point free_me somewhere and
diff --git a/apps/irssi/src/core/core.c b/apps/irssi/src/core/core.c
index f39c50d3..041d75a4 100644
--- a/apps/irssi/src/core/core.c
+++ b/apps/irssi/src/core/core.c
@@ -249,6 +249,8 @@ void core_init(int argc, char *argv[])
void core_deinit(void)
{
+ module_uniq_destroy("WINDOW ITEM TYPE");
+
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished);
diff --git a/apps/irssi/src/core/log.c b/apps/irssi/src/core/log.c
index e843ffe7..9a131f96 100644
--- a/apps/irssi/src/core/log.c
+++ b/apps/irssi/src/core/log.c
@@ -290,7 +290,7 @@ void log_file_write(const char *server_tag, const char *item, int level,
if (!found && !no_fallbacks && fallbacks != NULL) {
/* not found from any items, so write it to all main logs */
- tmpstr = (level & MSGLEVEL_PUBLIC) ?
+ tmpstr = (level & MSGLEVEL_PUBLIC) && item != NULL ?
g_strconcat(item, ": ", str, NULL) :
g_strdup(str);
diff --git a/apps/irssi/src/core/misc.c b/apps/irssi/src/core/misc.c
index d57c7f66..6bf87177 100644
--- a/apps/irssi/src/core/misc.c
+++ b/apps/irssi/src/core/misc.c
@@ -745,7 +745,7 @@ int expand_escape(const char **data)
case 'x':
/* hex digit */
- if (!isxdigit((*data)[1]) || !isxdigit((*data)[2]))
+ if (!i_isxdigit((*data)[1]) || !i_isxdigit((*data)[2]))
return -1;
digit[0] = (*data)[1];
diff --git a/apps/irssi/src/core/queries.c b/apps/irssi/src/core/queries.c
index cc16ad1e..21bb6db4 100644
--- a/apps/irssi/src/core/queries.c
+++ b/apps/irssi/src/core/queries.c
@@ -155,5 +155,4 @@ void queries_init(void)
void queries_deinit(void)
{
- module_uniq_destroy("QUERY");
}
diff --git a/apps/irssi/src/core/servers-setup.c b/apps/irssi/src/core/servers-setup.c
index 99f9f579..992f4e00 100644
--- a/apps/irssi/src/core/servers-setup.c
+++ b/apps/irssi/src/core/servers-setup.c
@@ -410,7 +410,7 @@ static void server_setup_save(SERVER_SETUP_REC *rec)
index = g_slist_index(setupservers, rec);
parentnode = iconfig_node_traverse("(servers", TRUE);
- node = config_node_index(parentnode, index);
+ node = config_node_nth(parentnode, index);
if (node == NULL)
node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
diff --git a/apps/irssi/src/core/special-vars.c b/apps/irssi/src/core/special-vars.c
index 4b1f535b..2556cd63 100644
--- a/apps/irssi/src/core/special-vars.c
+++ b/apps/irssi/src/core/special-vars.c
@@ -362,6 +362,8 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item,
int brackets, nest_free;
*free_ret = FALSE;
+ if (**cmd == '\0')
+ return NULL;
command = **cmd; (*cmd)++;
switch (command) {
diff --git a/apps/irssi/src/fe-common/core/Makefile.am b/apps/irssi/src/fe-common/core/Makefile.am
index 43bb1cd1..d97433a3 100644
--- a/apps/irssi/src/fe-common/core/Makefile.am
+++ b/apps/irssi/src/fe-common/core/Makefile.am
@@ -58,6 +58,7 @@ noinst_HEADERS = \
printtext.h \
themes.h \
translation.h \
+ window-activity.h \
window-items.h \
windows-layout.h \
fe-windows.h
diff --git a/apps/irssi/src/fe-common/core/chat-completion.c b/apps/irssi/src/fe-common/core/chat-completion.c
index a3d92ccd..2c23a6ab 100644
--- a/apps/irssi/src/fe-common/core/chat-completion.c
+++ b/apps/irssi/src/fe-common/core/chat-completion.c
@@ -22,6 +22,7 @@
#include "signals.h"
#include "commands.h"
#include "misc.h"
+#include "levels.h"
#include "settings.h"
#include "chatnets.h"
@@ -603,6 +604,9 @@ static void sig_complete_word(GList **list, WINDOW_REC *window,
/* nick completion .. we could also be completing a nick
after /MSG from nicks in channel */
complete_window_nicks(list, window, word, linestart);
+ } else if (window->level & MSGLEVEL_MSGS) {
+ /* msgs window, complete /MSG nicks */
+ *list = g_list_concat(completion_msg(server, NULL, word, NULL), *list);
}
if (*list != NULL) signal_stop();
@@ -910,8 +914,10 @@ void chat_completion_init(void)
signal_add("complete word", (SIGNAL_FUNC) sig_complete_word);
signal_add("complete command msg", (SIGNAL_FUNC) sig_complete_msg);
signal_add("complete command query", (SIGNAL_FUNC) sig_complete_msg);
+ signal_add("complete command action", (SIGNAL_FUNC) sig_complete_msg);
signal_add("complete erase command msg", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_add("complete erase command query", (SIGNAL_FUNC) sig_erase_complete_msg);
+ signal_add("complete erase command action", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_add("complete command connect", (SIGNAL_FUNC) sig_complete_connect);
signal_add("complete command server", (SIGNAL_FUNC) sig_complete_connect);
signal_add("complete command topic", (SIGNAL_FUNC) sig_complete_topic);
@@ -936,8 +942,10 @@ void chat_completion_deinit(void)
signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word);
signal_remove("complete command msg", (SIGNAL_FUNC) sig_complete_msg);
signal_remove("complete command query", (SIGNAL_FUNC) sig_complete_msg);
+ signal_remove("complete command action", (SIGNAL_FUNC) sig_complete_msg);
signal_remove("complete erase command msg", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_remove("complete erase command query", (SIGNAL_FUNC) sig_erase_complete_msg);
+ signal_remove("complete erase command action", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_remove("complete command connect", (SIGNAL_FUNC) sig_complete_connect);
signal_remove("complete command server", (SIGNAL_FUNC) sig_complete_connect);
signal_remove("complete command topic", (SIGNAL_FUNC) sig_complete_topic);
diff --git a/apps/irssi/src/fe-common/core/fe-channels.c b/apps/irssi/src/fe-common/core/fe-channels.c
index fe41ea30..64c5214c 100644
--- a/apps/irssi/src/fe-common/core/fe-channels.c
+++ b/apps/irssi/src/fe-common/core/fe-channels.c
@@ -437,7 +437,7 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
}
}
- if (str->len != 0) {
+ if (str->len > strlen(prefix_format)) {
printtext(channel->server, channel->name,
MSGLEVEL_CLIENTCRAP, "%s", str->str);
}
@@ -490,13 +490,13 @@ void fe_channels_nicklist(CHANNEL_REC *channel, int flags)
/* display the nicks */
if ((flags & CHANNEL_NICKLIST_FLAG_COUNT) == 0) {
printformat(channel->server, channel->name,
- MSGLEVEL_CRAP, TXT_NAMES, channel->name, "");
+ MSGLEVEL_CLIENTCRAP, TXT_NAMES, channel->name, nicks, ops, halfops, voices, normal);
display_sorted_nicks(channel, sorted);
}
g_slist_free(sorted);
printformat(channel->server, channel->name,
- MSGLEVEL_CRAP, TXT_ENDOFNAMES,
+ MSGLEVEL_CLIENTNOTICE, TXT_ENDOFNAMES,
channel->name, nicks, ops, halfops, voices, normal);
}
diff --git a/apps/irssi/src/fe-common/core/fe-common-core.c b/apps/irssi/src/fe-common/core/fe-common-core.c
index fb0e0fec..89c17c7f 100644
--- a/apps/irssi/src/fe-common/core/fe-common-core.c
+++ b/apps/irssi/src/fe-common/core/fe-common-core.c
@@ -42,6 +42,7 @@
#include "translation.h"
#include "fe-channels.h"
#include "fe-windows.h"
+#include "window-activity.h"
#include "window-items.h"
#include "windows-layout.h"
@@ -87,9 +88,6 @@ void fe_server_deinit(void);
void fe_settings_init(void);
void fe_settings_deinit(void);
-void window_activity_init(void);
-void window_activity_deinit(void);
-
void window_commands_init(void);
void window_commands_deinit(void);
diff --git a/apps/irssi/src/fe-common/core/fe-windows.c b/apps/irssi/src/fe-common/core/fe-windows.c
index d3f068e5..985d05c4 100644
--- a/apps/irssi/src/fe-common/core/fe-windows.c
+++ b/apps/irssi/src/fe-common/core/fe-windows.c
@@ -70,6 +70,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic)
rec = g_new0(WINDOW_REC, 1);
rec->refnum = window_get_new_refnum();
+ rec->level = level2bits(settings_get_str("window_default_level"));
windows = g_slist_prepend(windows, rec);
signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic));
@@ -259,14 +260,18 @@ WINDOW_REC *window_find_level(void *server, int level)
WINDOW_REC *window_find_closest(void *server, const char *name, int level)
{
- WINDOW_REC *window;
+ WINDOW_REC *window,*namewindow=NULL;
WI_ITEM_REC *item;
/* match by name */
item = name == NULL ? NULL :
window_item_find(server, name);
- if (item != NULL)
- return window_item_window(item);
+ if (item != NULL) {
+ namewindow = window_item_window(item);
+ if (namewindow != NULL && ((namewindow->level & level) != 0 ||
+ !settings_get_bool("window_check_level_first")))
+ return namewindow;
+ }
/* match by level */
if (level != MSGLEVEL_HILIGHT)
@@ -278,6 +283,9 @@ WINDOW_REC *window_find_closest(void *server, const char *name, int level)
window = window_find_level(NULL, level);
if (window != NULL) return window;
+ /* still return item's window if we didnt find anything */
+ if (namewindow != NULL) return namewindow;
+
/* fallback to active */
return active_win;
}
@@ -602,6 +610,8 @@ void windows_init(void)
daycheck = 0; daytag = -1;
settings_add_bool("lookandfeel", "window_auto_change", FALSE);
settings_add_bool("lookandfeel", "windows_auto_renumber", TRUE);
+ settings_add_bool("lookandfeel", "window_check_level_first", FALSE);
+ settings_add_str("lookandfeel", "window_default_level", "NONE");
read_settings();
signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
diff --git a/apps/irssi/src/fe-common/core/formats.c b/apps/irssi/src/fe-common/core/formats.c
index b4d2e7ed..8991164a 100644
--- a/apps/irssi/src/fe-common/core/formats.c
+++ b/apps/irssi/src/fe-common/core/formats.c
@@ -972,6 +972,7 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
while (*ptr != ',' && *ptr != '\0')
ptr++;
if (*ptr != '\0') *ptr++ = '\0';
+ ptr--;
signal_emit_id(signal_gui_print_text, 6,
dest->window, NULL, NULL,
GINT_TO_POINTER(GUI_PRINT_FLAG_INDENT_FUNC),
@@ -995,6 +996,9 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
flags |= GUI_PRINT_FLAG_BOLD;
}
}
+ if (ptr[1] == '\0')
+ break;
+
ptr++;
if (*ptr != FORMAT_COLOR_NOCHANGE) {
bgcolor = *ptr-'0';
diff --git a/apps/irssi/src/fe-common/core/hilight-text.c b/apps/irssi/src/fe-common/core/hilight-text.c
index 0bdda55f..4d5466e2 100644
--- a/apps/irssi/src/fe-common/core/hilight-text.c
+++ b/apps/irssi/src/fe-common/core/hilight-text.c
@@ -272,8 +272,11 @@ static void hilight_update_text_dest(TEXT_DEST_REC *dest, HILIGHT_REC *rec)
if (rec->priority > 0)
dest->hilight_priority = rec->priority;
- g_free_not_null(dest->hilight_color);
- dest->hilight_color = hilight_get_act_color(rec);
+ g_free_and_null(dest->hilight_color);
+ if (rec->act_color != NULL && strcmp(rec->act_color, "%n") == 0)
+ dest->level |= MSGLEVEL_NO_ACT;
+ else
+ dest->hilight_color = hilight_get_act_color(rec);
}
static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
diff --git a/apps/irssi/src/fe-common/core/module-formats.c b/apps/irssi/src/fe-common/core/module-formats.c
index 3972ea8b..b3b4c8d6 100644
--- a/apps/irssi/src/fe-common/core/module-formats.c
+++ b/apps/irssi/src/fe-common/core/module-formats.c
@@ -107,7 +107,7 @@ FORMAT_REC fecommon_core_formats[] = {
{ "talking_in", "You are now talking in {channel $0}", 1, { 0 } },
{ "not_in_channels", "You are not on any channels", 0 },
{ "current_channel", "Current channel {channel $0}", 1, { 0 } },
- { "names", "{names_users Users {names_channel $0}} $1", 2, { 0, 0 } },
+ { "names", "{names_users Users {names_channel $0}}", 6, { 0, 1, 1, 1, 1, 1 } },
{ "names_prefix", "{names_prefix $0}", 1, { 0 } },
{ "names_nick_op", "{names_nick_op $0 $1}", 2, { 0, 0 } },
{ "names_nick_halfop", "{names_nick_halfop $0 $1}", 2, { 0, 0 } },
diff --git a/apps/irssi/src/fe-common/core/printtext.c b/apps/irssi/src/fe-common/core/printtext.c
index 1900adec..2f6c19ea 100644
--- a/apps/irssi/src/fe-common/core/printtext.c
+++ b/apps/irssi/src/fe-common/core/printtext.c
@@ -416,7 +416,8 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text)
msg_beep_check(dest);
- dest->window->last_line = time(NULL);
+ if ((dest->level & MSGLEVEL_NEVER) == 0)
+ dest->window->last_line = time(NULL);
/* add timestamp/server tag here - if it's done in print_line()
it would be written to log files too */
diff --git a/apps/irssi/src/fe-common/core/themes.c b/apps/irssi/src/fe-common/core/themes.c
index c80c9e2d..514dd377 100644
--- a/apps/irssi/src/fe-common/core/themes.c
+++ b/apps/irssi/src/fe-common/core/themes.c
@@ -146,7 +146,9 @@ static void theme_format_append_variable(GString *str, const char **format)
value = parse_special((char **) format, NULL, NULL,
args, &free_ret, NULL, PARSE_FLAG_ONLY_ARGS);
if (free_ret) g_free(value);
- (*format)++;
+
+ if (**format != '\0')
+ (*format)++;
/* append the variable name */
value = g_strndup(orig, (int) (*format-orig));
@@ -1173,6 +1175,8 @@ static void change_theme(const char *name, int verbose)
rec = theme_load(name);
if (rec != NULL) {
current_theme = rec;
+ signal_emit("theme changed", 1, rec);
+
if (verbose) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
TXT_THEME_CHANGED,
diff --git a/apps/irssi/src/fe-common/core/window-activity.c b/apps/irssi/src/fe-common/core/window-activity.c
index 3e4cd80c..7238e50b 100644
--- a/apps/irssi/src/fe-common/core/window-activity.c
+++ b/apps/irssi/src/fe-common/core/window-activity.c
@@ -35,8 +35,8 @@
static char **hide_targets;
static int hide_level, msg_level, hilight_level;
-static void window_activity(WINDOW_REC *window, int data_level,
- const char *hilight_color)
+void window_activity(WINDOW_REC *window, int data_level,
+ const char *hilight_color)
{
int old_data_level;
@@ -52,8 +52,8 @@ static void window_activity(WINDOW_REC *window, int data_level,
GINT_TO_POINTER(old_data_level));
}
-static void window_item_activity(WI_ITEM_REC *item, int data_level,
- const char *hilight_color)
+void window_item_activity(WI_ITEM_REC *item, int data_level,
+ const char *hilight_color)
{
int old_data_level;
diff --git a/apps/irssi/src/fe-common/core/window-activity.h b/apps/irssi/src/fe-common/core/window-activity.h
new file mode 100644
index 00000000..b904872f
--- /dev/null
+++ b/apps/irssi/src/fe-common/core/window-activity.h
@@ -0,0 +1,13 @@
+#ifndef __WINDOW_ACTIVITY_H
+#define __WINDOW_ACTIVITY_H
+
+void window_activity(WINDOW_REC *window, int data_level,
+ const char *hilight_color);
+
+void window_item_activity(WI_ITEM_REC *item, int data_level,
+ const char *hilight_color);
+
+void window_activity_init(void);
+void window_activity_deinit(void);
+
+#endif
diff --git a/apps/irssi/src/fe-common/core/window-commands.c b/apps/irssi/src/fe-common/core/window-commands.c
index e54478d7..2accad9d 100644
--- a/apps/irssi/src/fe-common/core/window-commands.c
+++ b/apps/irssi/src/fe-common/core/window-commands.c
@@ -346,14 +346,17 @@ static void cmd_window_immortal(const char *data)
{
int set;
- if (g_strcasecmp(data, "ON") == 0)
+ if (*data == '\0')
+ set = active_win->immortal;
+ else if (g_strcasecmp(data, "ON") == 0)
set = TRUE;
else if (g_strcasecmp(data, "OFF") == 0)
set = FALSE;
else if (g_strcasecmp(data, "TOGGLE") == 0)
set = !active_win->immortal;
else {
- printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_NOT_TOGGLE);
+ printformat_window(active_win, MSGLEVEL_CLIENTERROR,
+ TXT_NOT_TOGGLE);
return;
}
diff --git a/apps/irssi/src/fe-text/gui-entry.c b/apps/irssi/src/fe-text/gui-entry.c
index f70bf0df..1148d076 100644
--- a/apps/irssi/src/fe-text/gui-entry.c
+++ b/apps/irssi/src/fe-text/gui-entry.c
@@ -19,6 +19,7 @@
*/
#include "module.h"
+#include "misc.h"
#include "utf8.h"
#include "formats.h"
@@ -26,8 +27,19 @@
#include "gui-printtext.h"
#include "term.h"
+const unichar empty_str[] = { 0 };
+
GUI_ENTRY_REC *active_entry;
+static void entry_text_grow(GUI_ENTRY_REC *entry, int grow_size)
+{
+ if (entry->text_len+grow_size < entry->text_alloc)
+ return;
+
+ entry->text_alloc = nearest_power(entry->text_alloc+grow_size);
+ entry->text = g_realloc(entry->text, entry->text_alloc);
+}
+
GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
{
GUI_ENTRY_REC *rec;
@@ -36,7 +48,9 @@ GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
rec->xpos = xpos;
rec->ypos = ypos;
rec->width = width;
- rec->text = g_string_new(NULL);
+ rec->text_alloc = 1024;
+ rec->text = g_new(unichar, rec->text_alloc);
+ rec->text[0] = '\0';
rec->utf8 = utf8;
return rec;
}
@@ -48,8 +62,8 @@ void gui_entry_destroy(GUI_ENTRY_REC *entry)
if (active_entry == entry)
gui_entry_set_active(NULL);
- g_free_not_null(entry->prompt);
- g_string_free(entry->text, TRUE);
+ g_free(entry->text);
+ g_free(entry->prompt);
g_free(entry);
}
@@ -76,14 +90,9 @@ static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry)
static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
{
- const unsigned char *p, *end;
+ const unichar *p;
int xpos, end_xpos;
- if (entry->utf8) {
- /* FIXME: a stupid kludge to make the chars output correctly */
- pos = 0;
- }
-
xpos = entry->xpos + entry->promptlen + pos;
end_xpos = entry->xpos + entry->width;
if (xpos > end_xpos)
@@ -92,20 +101,14 @@ static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
term_set_color(root_window, ATTR_RESET);
term_move(root_window, xpos, entry->ypos);
- p = (unsigned char *) (entry->scrstart + pos >= entry->text->len ? "" :
- entry->text->str + entry->scrstart + pos);
+ p = entry->scrstart + pos < entry->text_len ?
+ entry->text + entry->scrstart + pos : empty_str;
for (; *p != '\0' && xpos < end_xpos; p++, xpos++) {
- end = p;
- if (entry->utf8)
- get_utf8_char(&end);
-
if (entry->hidden)
term_addch(root_window, ' ');
- else if (*p >= 32 && (end != p || (*p & 127) >= 32)) {
- for (; p < end; p++)
- term_addch(root_window, *p);
- term_addch(root_window, *p);
- } else {
+ else if (*p >= 32 && (entry->utf8 || (*p & 127) >= 32))
+ term_add_unichar(root_window, *p);
+ else {
term_set_color(root_window, ATTR_RESET|ATTR_REVERSE);
term_addch(root_window, *p+'A'-1);
term_set_color(root_window, ATTR_RESET);
@@ -230,38 +233,67 @@ void gui_entry_set_utf8(GUI_ENTRY_REC *entry, int utf8)
void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str)
{
- g_return_if_fail(entry != NULL);
+ g_return_if_fail(entry != NULL);
g_return_if_fail(str != NULL);
- g_string_assign(entry->text, str);
- entry->pos = entry->text->len;
+ entry->text_len = 0;
+ entry->pos = 0;
+ entry->text[0] = '\0';
- gui_entry_redraw_from(entry, 0);
- gui_entry_fix_cursor(entry);
- gui_entry_draw(entry);
+ gui_entry_insert_text(entry, str);
}
char *gui_entry_get_text(GUI_ENTRY_REC *entry)
{
+ char *buf;
+ int i;
+
g_return_val_if_fail(entry != NULL, NULL);
- return entry->text->str;
+ buf = g_malloc(entry->text_len*6 + 1);
+ if (entry->utf8)
+ utf16_to_utf8(entry->text, buf);
+ else {
+ for (i = 0; i <= entry->text_len; i++)
+ buf[i] = entry->text[i];
+ }
+ return buf;
}
void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str)
{
+ unichar chr;
+ int i, len;
+
g_return_if_fail(entry != NULL);
g_return_if_fail(str != NULL);
gui_entry_redraw_from(entry, entry->pos);
- g_string_insert(entry->text, entry->pos, str);
- entry->pos += strlen(str);
+
+ len = !entry->utf8 ? strlen(str) : strlen_utf8(str);
+ entry_text_grow(entry, len);
+
+ /* make space for the string */
+ g_memmove(entry->text + entry->pos + len, entry->text + entry->pos,
+ (entry->text_len-entry->pos + 1) * sizeof(unichar));
+
+ if (!entry->utf8) {
+ for (i = 0; i < len; i++)
+ entry->text[entry->pos+i] = str[i];
+ } else {
+ chr = entry->text[entry->pos+len];
+ utf8_to_utf16(str, entry->text+entry->pos);
+ entry->text[entry->pos+len] = chr;
+ }
+
+ entry->text_len += len;
+ entry->pos += len;
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
}
-void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr)
+void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr)
{
g_return_if_fail(entry != NULL);
@@ -269,13 +301,38 @@ void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr)
return; /* never insert NUL, CR or LF characters */
gui_entry_redraw_from(entry, entry->pos);
- g_string_insert_c(entry->text, entry->pos, chr);
- entry->pos++;
+
+ entry_text_grow(entry, 1);
+
+ /* make space for the string */
+ g_memmove(entry->text + entry->pos + 1, entry->text + entry->pos,
+ (entry->text_len-entry->pos + 1) * sizeof(unichar));
+
+ entry->text[entry->pos] = chr;
+ entry->text_len++;
+ entry->pos++;
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
}
+char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
+{
+ char *buf;
+ int i;
+
+ g_return_val_if_fail(entry != NULL, NULL);
+
+ buf = g_malloc(entry->cutbuffer_len*6 + 1);
+ if (entry->utf8)
+ utf16_to_utf8(entry->cutbuffer, buf);
+ else {
+ for (i = 0; i <= entry->cutbuffer_len; i++)
+ buf[i] = entry->cutbuffer[i];
+ }
+ return buf;
+}
+
void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
{
g_return_if_fail(entry != NULL);
@@ -283,14 +340,27 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
if (entry->pos < size)
return;
-#ifdef WANT_BIG5
- if (is_big5(entry->text->str[entry->pos-2],
- entry->text->str[entry->pos-1]))
- size++;
-#endif
+ /* put erased text to cutbuffer */
+ if (entry->cutbuffer == NULL || entry->cutbuffer_len < size) {
+ g_free(entry->cutbuffer);
+ entry->cutbuffer = g_new(unichar, size+1);
+ }
+
+ entry->cutbuffer_len = size;
+ entry->cutbuffer[size] = '\0';
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+
+ if (size == 0) {
+ /* we just wanted to clear the cutbuffer */
+ return;
+ }
+
+ g_memmove(entry->text + entry->pos - size, entry->text + entry->pos,
+ (entry->text_len-entry->pos+1) * sizeof(unichar));
entry->pos -= size;
- g_string_erase(entry->text, entry->pos, size);
+ entry->text_len -= size;
gui_entry_redraw_from(entry, entry->pos);
gui_entry_fix_cursor(entry);
@@ -308,50 +378,65 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
to = entry->pos - 1;
if (to_space) {
- while (entry->text->str[to] == ' ' && to > 0)
+ while (entry->text[to] == ' ' && to > 0)
to--;
- while (entry->text->str[to] != ' ' && to > 0)
+ while (entry->text[to] != ' ' && to > 0)
to--;
} else {
- while (!i_isalnum(entry->text->str[to]) && to > 0)
+ while (!i_isalnum(entry->text[to]) && to > 0)
to--;
- while (i_isalnum(entry->text->str[to]) && to > 0)
+ while (i_isalnum(entry->text[to]) && to > 0)
to--;
}
if (to > 0) to++;
- g_string_erase(entry->text, to, entry->pos - to);
- entry->pos = to;
-
- gui_entry_redraw_from(entry, entry->pos);
- gui_entry_fix_cursor(entry);
- gui_entry_draw(entry);
+ gui_entry_erase(entry, entry->pos-to);
}
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
{
- int to;
+ int to, size;
g_return_if_fail(entry != NULL);
- if (entry->pos == entry->text->len)
+ if (entry->pos == entry->text_len)
return;
to = entry->pos;
if (to_space) {
- while (entry->text->str[to] == ' ' && to < entry->text->len)
+ while (entry->text[to] == ' ' && to < entry->text_len)
to++;
- while (entry->text->str[to] != ' ' && to < entry->text->len)
+ while (entry->text[to] != ' ' && to < entry->text_len)
to++;
} else {
- while (!i_isalnum(entry->text->str[to]) && to < entry->text->len)
+ while (!i_isalnum(entry->text[to]) && to < entry->text_len)
to++;
- while (i_isalnum(entry->text->str[to]) && to < entry->text->len)
+ while (i_isalnum(entry->text[to]) && to < entry->text_len)
to++;
}
- g_string_erase(entry->text, entry->pos, to - entry->pos);
+ size = to-entry->pos;
+ entry->pos = to;
+ gui_entry_erase(entry, size);
+}
- gui_entry_redraw_from(entry, entry->pos);
+void gui_entry_transpose_chars(GUI_ENTRY_REC *entry)
+{
+ unichar chr;
+
+ if (entry->pos == 0 || entry->text_len < 2)
+ return;
+
+ if (entry->pos == entry->text_len)
+ entry->pos--;
+
+ /* swap chars */
+ chr = entry->text[entry->pos];
+ entry->text[entry->pos] = entry->text[entry->pos-1];
+ entry->text[entry->pos-1] = chr;
+
+ entry->pos++;
+
+ gui_entry_redraw_from(entry, entry->pos-2);
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
}
@@ -367,7 +452,7 @@ void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos)
{
g_return_if_fail(entry != NULL);
- if (pos >= 0 && pos <= entry->text->len)
+ if (pos >= 0 && pos <= entry->text_len)
entry->pos = pos;
gui_entry_fix_cursor(entry);
@@ -378,16 +463,7 @@ void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos)
{
g_return_if_fail(entry != NULL);
-#ifdef WANT_BIG5
- if (pos > 0 && is_big5(entry->text->str[entry->pos],
- entry->text->str[entry->pos+1]))
- pos++;
- else if (pos < 0 && is_big5(entry->text->str[entry->pos-1],
- entry->text->str[entry->pos]))
- pos--;
-#endif
-
- if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text->len)
+ if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text_len)
entry->pos += pos;
gui_entry_fix_cursor(entry);
@@ -401,14 +477,14 @@ static void gui_entry_move_words_left(GUI_ENTRY_REC *entry, int count, int to_sp
pos = entry->pos;
while (count > 0 && pos > 0) {
if (to_space) {
- while (pos > 0 && entry->text->str[pos-1] == ' ')
+ while (pos > 0 && entry->text[pos-1] == ' ')
pos--;
- while (pos > 0 && entry->text->str[pos-1] != ' ')
+ while (pos > 0 && entry->text[pos-1] != ' ')
pos--;
} else {
- while (pos > 0 && !i_isalnum(entry->text->str[pos-1]))
+ while (pos > 0 && !i_isalnum(entry->text[pos-1]))
pos--;
- while (pos > 0 && i_isalnum(entry->text->str[pos-1]))
+ while (pos > 0 && i_isalnum(entry->text[pos-1]))
pos--;
}
count--;
@@ -422,16 +498,16 @@ static void gui_entry_move_words_right(GUI_ENTRY_REC *entry, int count, int to_s
int pos;
pos = entry->pos;
- while (count > 0 && pos < entry->text->len) {
+ while (count > 0 && pos < entry->text_len) {
if (to_space) {
- while (pos < entry->text->len && entry->text->str[pos] == ' ')
+ while (pos < entry->text_len && entry->text[pos] == ' ')
pos++;
- while (pos < entry->text->len && entry->text->str[pos] != ' ')
+ while (pos < entry->text_len && entry->text[pos] != ' ')
pos++;
} else {
- while (pos < entry->text->len && !i_isalnum(entry->text->str[pos]))
+ while (pos < entry->text_len && !i_isalnum(entry->text[pos]))
pos++;
- while (pos < entry->text->len && i_isalnum(entry->text->str[pos]))
+ while (pos < entry->text_len && i_isalnum(entry->text[pos]))
pos++;
}
count--;
diff --git a/apps/irssi/src/fe-text/gui-entry.h b/apps/irssi/src/fe-text/gui-entry.h
index 364f92da..b54ed075 100644
--- a/apps/irssi/src/fe-text/gui-entry.h
+++ b/apps/irssi/src/fe-text/gui-entry.h
@@ -2,7 +2,13 @@
#define __GUI_ENTRY_H
typedef struct {
- GString *text;
+ int text_len, text_alloc; /* as shorts, not chars */
+ unichar *text;
+
+ int cutbuffer_len;
+ unichar *cutbuffer;
+
+ /* all as shorts, not chars */
int xpos, ypos, width; /* entry position in screen */
int pos, scrstart, scrpos; /* cursor position */
int hidden; /* print the chars as spaces in input line (useful for passwords) */
@@ -30,12 +36,15 @@ void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str);
char *gui_entry_get_text(GUI_ENTRY_REC *entry);
void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str);
-void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr);
+void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr);
+char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry);
void gui_entry_erase(GUI_ENTRY_REC *entry, int size);
void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space);
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space);
+void gui_entry_transpose_chars(GUI_ENTRY_REC *entry);
+
int gui_entry_get_pos(GUI_ENTRY_REC *entry);
void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos);
void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos);
diff --git a/apps/irssi/src/fe-text/gui-expandos.c b/apps/irssi/src/fe-text/gui-expandos.c
index b07bf129..74d6b34d 100644
--- a/apps/irssi/src/fe-text/gui-expandos.c
+++ b/apps/irssi/src/fe-text/gui-expandos.c
@@ -43,7 +43,8 @@ static char *expando_inputline(SERVER_REC *server, void *item, int *free_ret)
/* value of cutbuffer */
static char *expando_cutbuffer(SERVER_REC *server, void *item, int *free_ret)
{
- return cutbuffer;
+ *free_ret = TRUE;
+ return gui_entry_get_cutbuffer(active_entry);
}
void gui_expandos_init(void)
diff --git a/apps/irssi/src/fe-text/gui-printtext.c b/apps/irssi/src/fe-text/gui-printtext.c
index affd2b9f..5aa8dddc 100644
--- a/apps/irssi/src/fe-text/gui-printtext.c
+++ b/apps/irssi/src/fe-text/gui-printtext.c
@@ -83,7 +83,8 @@ void gui_set_default_indent(const char *name)
list = name == NULL ? NULL :
g_hash_table_lookup(indent_functions, name);
- default_indent_func = list == NULL ? NULL : list->data;
+ default_indent_func = list == NULL ? NULL :
+ (INDENT_FUNC) list->data;
gui_windows_reset_settings();
}
diff --git a/apps/irssi/src/fe-text/gui-readline.c b/apps/irssi/src/fe-text/gui-readline.c
index 8fe17410..96e7e074 100644
--- a/apps/irssi/src/fe-text/gui-readline.c
+++ b/apps/irssi/src/fe-text/gui-readline.c
@@ -33,6 +33,7 @@
#include "term.h"
#include "gui-entry.h"
#include "gui-windows.h"
+#include "utf8.h"
#include
@@ -48,7 +49,6 @@ typedef struct {
static KEYBOARD_REC *keyboard;
static ENTRY_REDIRECT_REC *redir;
-char *cutbuffer;
static int readtag;
static time_t idle_time;
@@ -133,9 +133,9 @@ static void window_next_page(void)
gui_window_scroll(active_win, get_scroll_count());
}
-void handle_key(int key)
+void handle_key(unichar key)
{
- char str[3];
+ char str[20];
idle_time = time(NULL);
@@ -144,23 +144,26 @@ void handle_key(int key)
return;
}
- if (key >= 0 && key < 32) {
+ if (key < 32) {
/* control key */
str[0] = '^';
- str[1] = key+'@';
+ str[1] = (char)key+'@';
str[2] = '\0';
} else if (key == 127) {
str[0] = '^';
str[1] = '?';
str[2] = '\0';
- } else {
- str[0] = key;
+ } else if (!active_entry->utf8) {
+ str[0] = (char)key;
str[1] = '\0';
+ } else {
+ /* need to convert to utf8 */
+ str[utf16_char_to_utf8(key, str)] = '\0';
}
if (!key_pressed(keyboard, str)) {
/* key wasn't used for anything, print it */
- gui_entry_insert_char(active_entry, (char) key);
+ gui_entry_insert_char(active_entry, key);
}
}
@@ -170,7 +173,10 @@ static void key_send_line(void)
char *str, *add_history;
str = gui_entry_get_text(active_entry);
- if (*str == '\0') return;
+ if (str == NULL || *str == '\0') {
+ g_free(str);
+ return;
+ }
/* we can't use gui_entry_get_text() later, since the entry might
have been destroyed after we get back */
@@ -199,6 +205,8 @@ static void key_send_line(void)
if (active_entry != NULL)
gui_entry_set_text(active_entry, "");
command_history_clear_pos(active_win);
+
+ g_free(str);
}
static void key_combo(void)
@@ -208,17 +216,23 @@ static void key_combo(void)
static void key_backward_history(void)
{
const char *text;
+ char *line;
- text = command_history_prev(active_win, gui_entry_get_text(active_entry));
+ line = gui_entry_get_text(active_entry);
+ text = command_history_prev(active_win, line);
gui_entry_set_text(active_entry, text);
+ g_free(line);
}
static void key_forward_history(void)
{
const char *text;
+ char *line;
- text = command_history_next(active_win, gui_entry_get_text(active_entry));
+ line = gui_entry_get_text(active_entry);
+ text = command_history_next(active_win, line);
gui_entry_set_text(active_entry, text);
+ g_free(line);
}
static void key_beginning_of_line(void)
@@ -228,7 +242,7 @@ static void key_beginning_of_line(void)
static void key_end_of_line(void)
{
- gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry)));
+ gui_entry_set_pos(active_entry, active_entry->text_len);
}
static void key_backward_character(void)
@@ -263,10 +277,8 @@ static void key_forward_to_space(void)
static void key_erase_line(void)
{
- g_free_not_null(cutbuffer);
- cutbuffer = g_strdup(gui_entry_get_text(active_entry));
-
- gui_entry_set_text(active_entry, "");
+ gui_entry_set_pos(active_entry, active_entry->text_len);
+ gui_entry_erase(active_entry, active_entry->text_len);
}
static void key_erase_to_beg_of_line(void)
@@ -274,9 +286,6 @@ static void key_erase_to_beg_of_line(void)
int pos;
pos = gui_entry_get_pos(active_entry);
- g_free_not_null(cutbuffer);
- cutbuffer = g_strndup(gui_entry_get_text(active_entry), pos);
-
gui_entry_erase(active_entry, pos);
}
@@ -285,42 +294,27 @@ static void key_erase_to_end_of_line(void)
int pos;
pos = gui_entry_get_pos(active_entry);
- g_free_not_null(cutbuffer);
- cutbuffer = g_strdup(gui_entry_get_text(active_entry)+pos);
-
- gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry)));
- gui_entry_erase(active_entry, strlen(gui_entry_get_text(active_entry)) - pos);
+ gui_entry_set_pos(active_entry, active_entry->text_len);
+ gui_entry_erase(active_entry, active_entry->text_len - pos);
}
static void key_yank_from_cutbuffer(void)
{
+ char *cutbuffer;
+
+ cutbuffer = gui_entry_get_cutbuffer(active_entry);
if (cutbuffer != NULL)
gui_entry_insert_text(active_entry, cutbuffer);
}
static void key_transpose_characters(void)
{
- char *line, c;
- int pos;
-
- pos = gui_entry_get_pos(active_entry);
- line = gui_entry_get_text(active_entry);
- if (pos == 0 || strlen(line) < 2)
- return;
-
- if (line[pos] != '\0')
- gui_entry_move_pos(active_entry, 1);
- c = line[gui_entry_get_pos(active_entry)-1];
- gui_entry_erase(active_entry, 1);
- gui_entry_move_pos(active_entry, -1);
- gui_entry_insert_char(active_entry, c);
- gui_entry_set_pos(active_entry, pos);
- gui_entry_move_pos(active_entry, 1);
+ gui_entry_transpose_chars(active_entry);
}
static void key_delete_character(void)
{
- if (gui_entry_get_pos(active_entry) < (int)strlen(gui_entry_get_text(active_entry))) {
+ if (gui_entry_get_pos(active_entry) < active_entry->text_len) {
gui_entry_move_pos(active_entry, 1);
gui_entry_erase(active_entry, 1);
}
@@ -353,7 +347,7 @@ static void key_delete_to_next_space(void)
static void sig_input(void)
{
- unsigned char buffer[128];
+ unichar buffer[128];
int ret, i;
if (!active_entry) {
@@ -361,7 +355,7 @@ static void sig_input(void)
return;
}
- ret = term_gets(buffer, sizeof(buffer));
+ ret = term_gets(buffer, sizeof(buffer)/sizeof(buffer[0]));
if (ret == -1) {
/* lost terminal */
if (!term_detached)
@@ -404,13 +398,15 @@ static void key_change_window(const char *data)
static void key_completion(int erase)
{
- char *line;
+ char *text, *line;
int pos;
pos = gui_entry_get_pos(active_entry);
- line = word_complete(active_win, gui_entry_get_text(active_entry),
- &pos, erase);
+ text = gui_entry_get_text(active_entry);
+ line = word_complete(active_win, text, &pos, erase);
+ g_free(text);
+
if (line != NULL) {
gui_entry_set_text(active_entry, line);
gui_entry_set_pos(active_entry, pos);
@@ -430,12 +426,15 @@ static void key_erase_completion(void)
static void key_check_replaces(void)
{
- char *line;
+ char *text, *line;
int pos;
pos = gui_entry_get_pos(active_entry);
- line = auto_word_complete(gui_entry_get_text(active_entry), &pos);
+ text = gui_entry_get_text(active_entry);
+ line = auto_word_complete(text, &pos);
+ g_free(text);
+
if (line != NULL) {
gui_entry_set_text(active_entry, line);
gui_entry_set_pos(active_entry, pos);
@@ -537,11 +536,15 @@ static void key_sig_stop(void)
static void sig_window_auto_changed(void)
{
+ char *text;
+
if (active_entry == NULL)
return;
- command_history_next(active_win, gui_entry_get_text(active_entry));
+ text = gui_entry_get_text(active_entry);
+ command_history_next(active_win, text);
gui_entry_set_text(active_entry, "");
+ g_free(text);
}
static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry,
@@ -563,7 +566,6 @@ void gui_readline_init(void)
char *key, data[MAX_INT_STRLEN];
int n;
- cutbuffer = NULL;
redir = NULL;
idle_time = time(NULL);
input_listen_init(STDIN_FILENO);
@@ -578,6 +580,7 @@ void gui_readline_init(void)
key_bind("key", NULL, "^J", "return", (SIGNAL_FUNC) key_combo);
key_bind("key", NULL, "^H", "backspace", (SIGNAL_FUNC) key_combo);
key_bind("key", NULL, "^?", "backspace", (SIGNAL_FUNC) key_combo);
+ key_bind("key", NULL, "^I", "tab", (SIGNAL_FUNC) key_combo);
/* meta */
key_bind("key", NULL, "^[", "meta", (SIGNAL_FUNC) key_combo);
@@ -616,7 +619,9 @@ void gui_readline_init(void)
key_bind("backward_character", "", "left", NULL, (SIGNAL_FUNC) key_backward_character);
key_bind("forward_character", "", "right", NULL, (SIGNAL_FUNC) key_forward_character);
key_bind("backward_word", "", "cleft", NULL, (SIGNAL_FUNC) key_backward_word);
+ key_bind("backward_word", NULL, "meta-b", NULL, (SIGNAL_FUNC) key_backward_word);
key_bind("forward_word", "", "cright", NULL, (SIGNAL_FUNC) key_forward_word);
+ key_bind("forward_word", NULL, "meta-f", NULL, (SIGNAL_FUNC) key_forward_word);
key_bind("backward_to_space", "", NULL, NULL, (SIGNAL_FUNC) key_backward_to_space);
key_bind("forward_to_space", "", NULL, NULL, (SIGNAL_FUNC) key_forward_to_space);
key_bind("beginning_of_line", "", "home", NULL, (SIGNAL_FUNC) key_beginning_of_line);
@@ -644,7 +649,7 @@ void gui_readline_init(void)
/* line transmitting */
key_bind("send_line", "Execute the input line", "return", NULL, (SIGNAL_FUNC) key_send_line);
- key_bind("word_completion", "", "^I", NULL, (SIGNAL_FUNC) key_word_completion);
+ key_bind("word_completion", "", "tab", NULL, (SIGNAL_FUNC) key_word_completion);
key_bind("erase_completion", "", "meta-k", NULL, (SIGNAL_FUNC) key_erase_completion);
key_bind("check_replaces", "Check word replaces", NULL, NULL, (SIGNAL_FUNC) key_check_replaces);
@@ -693,7 +698,6 @@ void gui_readline_init(void)
void gui_readline_deinit(void)
{
- g_free_not_null(cutbuffer);
input_listen_deinit();
key_configure_freeze();
diff --git a/apps/irssi/src/fe-text/gui-windows.c b/apps/irssi/src/fe-text/gui-windows.c
index cd834ee4..1e7316f4 100644
--- a/apps/irssi/src/fe-text/gui-windows.c
+++ b/apps/irssi/src/fe-text/gui-windows.c
@@ -44,7 +44,7 @@ static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window,
gui->view = textbuffer_view_create(textbuffer_create(),
window->width, window->height,
settings_get_bool("scroll"),
- settings_get_bool("term_utf8"));
+ term_type == TERM_TYPE_UTF8);
textbuffer_view_set_default_indent(gui->view,
settings_get_int("indent"),
!settings_get_bool("indent_always"),
diff --git a/apps/irssi/src/fe-text/module-formats.c b/apps/irssi/src/fe-text/module-formats.c
index 4a37db25..7584a8c0 100644
--- a/apps/irssi/src/fe-text/module-formats.c
+++ b/apps/irssi/src/fe-text/module-formats.c
@@ -25,12 +25,18 @@ FORMAT_REC gui_text_formats[] =
{
{ MODULE_NAME, "Text user interface", 0 },
+ /* ---- */
+ { NULL, "Lastlog", 0 },
+
{ "lastlog_too_long", "/LASTLOG would print $0 lines. If you really want to print all these lines use -force option.", 1, { 1 } },
{ "lastlog_count", "{hilight Lastlog}: $0 lines", 1, { 1 } },
{ "lastlog_start", "{hilight Lastlog}:", 0 },
{ "lastlog_end", "{hilight End of Lastlog}", 0 },
{ "lastlog_separator", "--", 0 },
+ /* ---- */
+ { NULL, "Windows", 0 },
+
{ "refnum_not_found", "Window number $0 not found", 1, { 0 } },
{ "window_too_small", "Not enough room to resize this window", 0 },
{ "cant_hide_last", "You can't hide the last window", 0 },
@@ -43,5 +49,27 @@ FORMAT_REC gui_text_formats[] =
{ "window_scroll", "Window scroll mode is now $0", 1, { 0 } },
{ "window_scroll_unknown", "Unknown scroll mode $0, must be ON, OFF or DEFAULT", 1, { 0 } },
+ /* ---- */
+ { NULL, "Statusbars", 0 },
+
+ { "statusbar_list_header", "Name Type Placement Position Visible", 0 },
+ { "statusbar_list_footer", "", 0 },
+ { "statusbar_list", "$[30]0 $[6]1 $[9]2 $[8]3 $4", 5, { 0, 0, 0, 1, 0 } },
+ { "statusbar_info_name", "Statusbar: {hilight $0}", 1, { 0 } },
+ { "statusbar_info_type", "Type : $0", 1, { 0 } },
+ { "statusbar_info_placement", "Placement: $0", 1, { 0 } },
+ { "statusbar_info_position", "Position : $0", 1, { 1 } },
+ { "statusbar_info_visible", "Visible : $0", 1, { 0 } },
+ { "statusbar_info_item_header", "Items : Name Priority Alignment", 0 },
+ { "statusbar_info_item_footer", "", 0 },
+ { "statusbar_info_item_name", " : $[35]0 $[9]1 $2", 3, { 0, 1, 0 } },
+ { "statusbar_not_found", "Statusbar doesn't exist: $0", 1, { 0 } },
+ { "statusbar_not_found", "Statusbar doesn't exist: $0", 1, { 0 } },
+ { "statusbar_item_not_found", "Statusbar item doesn't exist: $0", 1, { 0 } },
+ { "statusbar_unknown_command", "Unknown statusbar command: $0", 1, { 0 } },
+ { "statusbar_unknown_type", "Statusbar type must be 'window' or 'root'", 1, { 0 } },
+ { "statusbar_unknown_placement", "Statusbar placement must be 'top' or 'bottom'", 1, { 0 } },
+ { "statusbar_unknown_visibility", "Statusbar visibility must be 'always', 'active' or 'inactive'", 1, { 0 } },
+
{ NULL, NULL, 0 }
};
diff --git a/apps/irssi/src/fe-text/module-formats.h b/apps/irssi/src/fe-text/module-formats.h
index 2bbf4007..88c67000 100644
--- a/apps/irssi/src/fe-text/module-formats.h
+++ b/apps/irssi/src/fe-text/module-formats.h
@@ -3,12 +3,16 @@
enum {
TXT_MODULE_NAME,
+ TXT_FILL_1,
+
TXT_LASTLOG_TOO_LONG,
TXT_LASTLOG_COUNT,
TXT_LASTLOG_START,
TXT_LASTLOG_END,
TXT_LASTLOG_SEPARATOR,
+ TXT_FILL_2,
+
TXT_REFNUM_NOT_FOUND,
TXT_WINDOW_TOO_SMALL,
TXT_CANT_HIDE_LAST,
@@ -19,7 +23,27 @@ enum {
TXT_WINDOW_UNSET_STICKY,
TXT_WINDOW_INFO_STICKY,
TXT_WINDOW_SCROLL,
- TXT_WINDOW_SCROLL_UNKNOWN
+ TXT_WINDOW_SCROLL_UNKNOWN,
+
+ TXT_FILL_3,
+
+ TXT_STATUSBAR_LIST_HEADER,
+ TXT_STATUSBAR_LIST_FOOTER,
+ TXT_STATUSBAR_LIST,
+ TXT_STATUSBAR_INFO_NAME,
+ TXT_STATUSBAR_INFO_TYPE,
+ TXT_STATUSBAR_INFO_PLACEMENT,
+ TXT_STATUSBAR_INFO_POSITION,
+ TXT_STATUSBAR_INFO_VISIBLE,
+ TXT_STATUSBAR_INFO_ITEM_HEADER,
+ TXT_STATUSBAR_INFO_ITEM_FOOTER,
+ TXT_STATUSBAR_INFO_ITEM_NAME,
+ TXT_STATUSBAR_NOT_FOUND,
+ TXT_STATUSBAR_ITEM_NOT_FOUND,
+ TXT_STATUSBAR_UNKNOWN_COMMAND,
+ TXT_STATUSBAR_UNKNOWN_TYPE,
+ TXT_STATUSBAR_UNKNOWN_PLACEMENT,
+ TXT_STATUSBAR_UNKNOWN_VISIBILITY
};
extern FORMAT_REC gui_text_formats[];
diff --git a/apps/irssi/src/fe-text/module.h b/apps/irssi/src/fe-text/module.h
index c6643545..0ca9f703 100644
--- a/apps/irssi/src/fe-text/module.h
+++ b/apps/irssi/src/fe-text/module.h
@@ -1,4 +1,5 @@
#include "common.h"
+#include "term.h"
#define MODULE_NAME "fe-text"
diff --git a/apps/irssi/src/fe-text/statusbar-config.c b/apps/irssi/src/fe-text/statusbar-config.c
index f9ea05f2..81638d99 100644
--- a/apps/irssi/src/fe-text/statusbar-config.c
+++ b/apps/irssi/src/fe-text/statusbar-config.c
@@ -19,11 +19,15 @@
*/
#include "module.h"
+#include "module-formats.h"
#include "signals.h"
+#include "commands.h"
#include "settings.h"
+#include "levels.h"
#include "lib-config/iconfig.h"
#include "statusbar.h"
+#include "printtext.h"
static void read_statusbar_config_from_node(CONFIG_NODE *node);
@@ -141,21 +145,11 @@ static void statusbar_read(STATUSBAR_GROUP_REC *group, CONFIG_NODE *node)
{
STATUSBAR_CONFIG_REC *bar;
GSList *tmp;
- int visible;
const char *visible_str;
bar = statusbar_config_find(group, node->key);
- visible = bar == NULL ? STATUSBAR_VISIBLE_ALWAYS : bar->visible;
-
- /* first make sure we want to see this statusbar */
- visible_str = config_node_get_str(node, "visible", "");
- if (strcmp(visible_str, "active") == 0)
- visible = STATUSBAR_VISIBLE_ACTIVE;
- else if (strcmp(visible_str, "inactive") == 0)
- visible = STATUSBAR_VISIBLE_INACTIVE;
- else if (strcmp(visible_str, "never") == 0) {
- /* we don't want this statusbar -
- destroy it if it already exists */
+ if (config_node_get_bool(node, "disabled", FALSE)) {
+ /* disabled, destroy it if it already exists */
if (bar != NULL)
statusbar_config_destroy(group, bar);
return;
@@ -167,11 +161,18 @@ static void statusbar_read(STATUSBAR_GROUP_REC *group, CONFIG_NODE *node)
bar->placement = STATUSBAR_BOTTOM;
bar->position = 0;
}
- bar->visible = visible;
- if (strcmp(config_node_get_str(node, "type", ""), "window") == 0)
+ visible_str = config_node_get_str(node, "visible", "");
+ if (g_strcasecmp(visible_str, "active") == 0)
+ bar->visible = STATUSBAR_VISIBLE_ACTIVE;
+ else if (g_strcasecmp(visible_str, "inactive") == 0)
+ bar->visible = STATUSBAR_VISIBLE_INACTIVE;
+ else
+ bar->visible = STATUSBAR_VISIBLE_ALWAYS;
+
+ if (g_strcasecmp(config_node_get_str(node, "type", ""), "window") == 0)
bar->type = STATUSBAR_TYPE_WINDOW;
- if (strcmp(config_node_get_str(node, "placement", ""), "top") == 0)
+ if (g_strcasecmp(config_node_get_str(node, "placement", ""), "top") == 0)
bar->placement = STATUSBAR_TOP;
bar->position = config_node_get_int(node, "position", 0);
@@ -247,15 +248,353 @@ static void read_statusbar_config(void)
read_statusbar_config_from_node(node);
create_root_statusbars();
+ statusbars_create_window_bars();
+}
+
+static const char *sbar_get_type(STATUSBAR_CONFIG_REC *rec)
+{
+ return rec->type == STATUSBAR_TYPE_ROOT ? "root" :
+ rec->type == STATUSBAR_TYPE_WINDOW ? "window" : "??";
+}
+
+static const char *sbar_get_placement(STATUSBAR_CONFIG_REC *rec)
+{
+ return rec->placement == STATUSBAR_TOP ? "top" :
+ rec->placement == STATUSBAR_BOTTOM ? "bottom" : "??";
+}
+
+static const char *sbar_get_visibility(STATUSBAR_CONFIG_REC *rec)
+{
+ return rec->visible == STATUSBAR_VISIBLE_ALWAYS ? "always" :
+ rec->visible == STATUSBAR_VISIBLE_ACTIVE ? "active" :
+ rec->visible == STATUSBAR_VISIBLE_INACTIVE ? "inactive" : "??";
+}
+
+static void statusbar_list_items(STATUSBAR_CONFIG_REC *bar)
+{
+ GSList *tmp;
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_ITEM_HEADER);
+
+ for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
+ SBAR_ITEM_CONFIG_REC *rec = tmp->data;
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_ITEM_NAME,
+ rec->name, rec->priority,
+ rec->right_alignment ? "right" : "left");
+ }
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_ITEM_FOOTER);
+}
+
+static void statusbar_print(STATUSBAR_CONFIG_REC *rec)
+{
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_NAME, rec->name);
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_TYPE, sbar_get_type(rec));
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_PLACEMENT,
+ sbar_get_placement(rec));
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_POSITION, rec->position);
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_INFO_VISIBLE,
+ sbar_get_visibility(rec));
+
+ if (rec->items != NULL)
+ statusbar_list_items(rec);
+}
+
+static void cmd_statusbar_list(void)
+{
+ GSList *tmp;
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_STATUSBAR_LIST_HEADER);
+
+ tmp = active_statusbar_group->config_bars;
+ for (; tmp != NULL; tmp = tmp->next) {
+ STATUSBAR_CONFIG_REC *rec = tmp->data;
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+ TXT_STATUSBAR_LIST, rec->name, sbar_get_type(rec),
+ sbar_get_placement(rec), rec->position,
+ sbar_get_visibility(rec));
+ }
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_STATUSBAR_LIST_FOOTER);
+}
+
+static void cmd_statusbar_print_info(const char *name)
+{
+ GSList *tmp;
+
+ tmp = active_statusbar_group->config_bars;
+ for (; tmp != NULL; tmp = tmp->next) {
+ STATUSBAR_CONFIG_REC *rec = tmp->data;
+
+ if (g_strcasecmp(rec->name, name) == 0) {
+ statusbar_print(rec);
+ return;
+ }
+ }
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_NOT_FOUND, name);
+}
+
+/* SYNTAX: STATUSBAR ENABLE */
+static void cmd_statusbar_enable(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ iconfig_node_set_str(node, "disabled", NULL);
+}
+
+/* SYNTAX: STATUSBAR DISABLE */
+static void cmd_statusbar_disable(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ iconfig_node_set_bool(node, "disabled", TRUE);
+}
+
+/* SYNTAX: STATUSBAR RESET */
+static void cmd_statusbar_reset(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ CONFIG_NODE *parent;
+
+ parent = iconfig_node_traverse("statusbar", TRUE);
+ parent = config_node_section(parent, active_statusbar_group->name,
+ NODE_TYPE_BLOCK);
+
+ iconfig_node_set_str(parent, node->key, NULL);
+}
+
+/* SYNTAX: STATUSBAR TYPE window|root */
+static void cmd_statusbar_type(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ if (g_strcasecmp(data, "window") == 0)
+ iconfig_node_set_str(node, "type", "window");
+ else if (g_strcasecmp(data, "root") == 0)
+ iconfig_node_set_str(node, "type", "root");
+ else {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_UNKNOWN_TYPE, data);
+ }
+}
+
+/* SYNTAX: STATUSBAR PLACEMENT top|bottom */
+static void cmd_statusbar_placement(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ if (g_strcasecmp(data, "top") == 0)
+ iconfig_node_set_str(node, "placement", "top");
+ else if (g_strcasecmp(data, "bottom") == 0)
+ iconfig_node_set_str(node, "placement", "bottom");
+ else {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_UNKNOWN_PLACEMENT, data);
+ }
+}
+
+/* SYNTAX: STATUSBAR POSITION */
+static void cmd_statusbar_position(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ iconfig_node_set_int(node, "position", atoi(data));
+}
+
+/* SYNTAX: STATUSBAR VISIBLE always|active|inactive */
+static void cmd_statusbar_visible(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ if (g_strcasecmp(data, "always") == 0)
+ iconfig_node_set_str(node, "visible", "always");
+ else if (g_strcasecmp(data, "active") == 0)
+ iconfig_node_set_str(node, "visible", "active");
+ else if (g_strcasecmp(data, "inactive") == 0)
+ iconfig_node_set_str(node, "visible", "inactive");
+ else {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_UNKNOWN_VISIBILITY, data);
+ }
+}
+
+static CONFIG_NODE *statusbar_items_section(CONFIG_NODE *parent)
+{
+ STATUSBAR_CONFIG_REC *bar;
+ CONFIG_NODE *node;
+ GSList *tmp;
+
+ node = config_node_section(parent, "items", -1);
+ if (node != NULL)
+ return node;
+
+ /* find the statusbar configuration from memory */
+ bar = statusbar_config_find(active_statusbar_group, parent->key);
+ if (bar == NULL) {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_NOT_FOUND, parent->key);
+ return NULL;
+ }
+
+ /* since items list in config file overrides defaults,
+ we'll need to copy the whole list. */
+ parent = config_node_section(parent, "items", NODE_TYPE_BLOCK);
+ for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
+ SBAR_ITEM_CONFIG_REC *rec = tmp->data;
+
+ node = config_node_section(parent, rec->name,
+ NODE_TYPE_BLOCK);
+ if (rec->priority != 0)
+ iconfig_node_set_int(node, "priority", rec->priority);
+ if (rec->right_alignment)
+ iconfig_node_set_str(node, "alignment", "right");
+ }
+
+ return parent;
+}
+
+/* SYNTAX: STATUSBAR ADD [-before | -after - ]
+ [-priority #] [-alignment left|right]
- */
+static void cmd_statusbar_add(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ GHashTable *optlist;
+ char *name, *value;
+ void *free_arg;
+ int index;
+
+ node = statusbar_items_section(node);
+ if (node == NULL)
+ return;
+
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+ "statusbar add", &optlist, &name))
+ return;
+
+ /* get the index */
+ index = -1;
+ value = g_hash_table_lookup(optlist, "before");
+ if (value != NULL) index = config_node_index(node, value);
+ value = g_hash_table_lookup(optlist, "after");
+ if (value != NULL) index = config_node_index(node, value)+1;
+
+ /* create/move item */
+ node = config_node_section_index(node, name, index, NODE_TYPE_BLOCK);
+
+ /* set the options */
+ value = g_hash_table_lookup(optlist, "priority");
+ if (value != NULL) iconfig_node_set_int(node, "priority", atoi(value));
+
+ value = g_hash_table_lookup(optlist, "alignment");
+ if (value != NULL) {
+ iconfig_node_set_str(node, "alignment",
+ g_strcasecmp(value, "right") == 0 ?
+ "right" : NULL);
+ }
+
+ cmd_params_free(free_arg);
+}
+
+/* SYNTAX: STATUSBAR REMOVE
- */
+static void cmd_statusbar_remove(const char *data, void *server,
+ void *item, CONFIG_NODE *node)
+{
+ node = statusbar_items_section(node);
+ if (node == NULL)
+ return;
+
+ if (config_node_section(node, data, -1) != NULL)
+ iconfig_node_set_str(node, data, NULL);
+ else {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_ITEM_NOT_FOUND, data);
+ }
+}
+
+static void cmd_statusbar(const char *data)
+{
+ CONFIG_NODE *node;
+ char *name, *cmd, *params, *signal;
+ void *free_arg;
+
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
+ &name, &cmd, ¶ms))
+ return;
+
+ if (*name == '\0') {
+ /* list all statusbars */
+ cmd_statusbar_list();
+ cmd_params_free(free_arg);
+ return;
+ }
+
+ if (*cmd == '\0') {
+ /* print statusbar info */
+ cmd_statusbar_print_info(name);
+ cmd_params_free(free_arg);
+ return;
+ }
+
+ /* lookup/create the statusbar node */
+ node = iconfig_node_traverse("statusbar", TRUE);
+ node = config_node_section(node, active_statusbar_group->name,
+ NODE_TYPE_BLOCK);
+ node = config_node_section(node, name, NODE_TYPE_BLOCK);
+
+ /* call the subcommand */
+ signal = g_strconcat("command statusbar ", cmd, NULL);
+ g_strdown(signal);
+ if (!signal_emit(signal, 4, params, NULL, NULL, node)) {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ TXT_STATUSBAR_UNKNOWN_COMMAND, cmd);
+ } else {
+ read_statusbar_config();
+ }
+ g_free(signal);
+
+ cmd_params_free(free_arg);
}
void statusbar_config_init(void)
{
read_statusbar_config();
- signal_add("setup reread", (SIGNAL_FUNC) read_statusbar_config);
+ signal_add_last("setup reread", (SIGNAL_FUNC) read_statusbar_config);
+ signal_add("theme changed", (SIGNAL_FUNC) read_statusbar_config);
+
+ command_bind("statusbar", NULL, (SIGNAL_FUNC) cmd_statusbar);
+ command_bind("statusbar enable", NULL, (SIGNAL_FUNC) cmd_statusbar_enable);
+ command_bind("statusbar disable", NULL, (SIGNAL_FUNC) cmd_statusbar_disable);
+ command_bind("statusbar reset", NULL, (SIGNAL_FUNC) cmd_statusbar_reset);
+ command_bind("statusbar add", NULL, (SIGNAL_FUNC) cmd_statusbar_add);
+ command_bind("statusbar remove", NULL, (SIGNAL_FUNC) cmd_statusbar_remove);
+ command_bind("statusbar type", NULL, (SIGNAL_FUNC) cmd_statusbar_type);
+ command_bind("statusbar placement", NULL, (SIGNAL_FUNC) cmd_statusbar_placement);
+ command_bind("statusbar position", NULL, (SIGNAL_FUNC) cmd_statusbar_position);
+ command_bind("statusbar visible", NULL, (SIGNAL_FUNC) cmd_statusbar_visible);
+
+ command_set_options("statusbar add", "+before +after +priority +alignment");
}
void statusbar_config_deinit(void)
{
signal_remove("setup reread", (SIGNAL_FUNC) read_statusbar_config);
+ signal_remove("theme changed", (SIGNAL_FUNC) read_statusbar_config);
+
+ command_unbind("statusbar", (SIGNAL_FUNC) cmd_statusbar);
+ command_unbind("statusbar enable", (SIGNAL_FUNC) cmd_statusbar_enable);
+ command_unbind("statusbar disable", (SIGNAL_FUNC) cmd_statusbar_disable);
+ command_unbind("statusbar reset", (SIGNAL_FUNC) cmd_statusbar_reset);
+ command_unbind("statusbar add", (SIGNAL_FUNC) cmd_statusbar_add);
+ command_unbind("statusbar remove", (SIGNAL_FUNC) cmd_statusbar_remove);
+ command_unbind("statusbar type", (SIGNAL_FUNC) cmd_statusbar_type);
+ command_unbind("statusbar placement", (SIGNAL_FUNC) cmd_statusbar_placement);
+ command_unbind("statusbar position", (SIGNAL_FUNC) cmd_statusbar_position);
+ command_unbind("statusbar visible", (SIGNAL_FUNC) cmd_statusbar_visible);
}
diff --git a/apps/irssi/src/fe-text/statusbar-items.c b/apps/irssi/src/fe-text/statusbar-items.c
index ac98c77a..f8042c5c 100644
--- a/apps/irssi/src/fe-text/statusbar-items.c
+++ b/apps/irssi/src/fe-text/statusbar-items.c
@@ -344,13 +344,12 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
{
GUI_ENTRY_REC *rec;
- rec = g_hash_table_lookup(input_entries, item);
+ rec = g_hash_table_lookup(input_entries, item->bar);
if (rec == NULL) {
rec = gui_entry_create(item->xpos, item->bar->real_ypos,
- item->size,
- settings_get_bool("term_utf8"));
+ item->size, term_type == TERM_TYPE_UTF8);
gui_entry_set_active(rec);
- g_hash_table_insert(input_entries, item, rec);
+ g_hash_table_insert(input_entries, item->bar, rec);
}
if (get_size_only) {
@@ -364,23 +363,21 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
}
-static void sig_statusbar_item_destroyed(SBAR_ITEM_REC *item)
+static void sig_statusbar_destroyed(STATUSBAR_REC *bar)
{
GUI_ENTRY_REC *rec;
- rec = g_hash_table_lookup(input_entries, item);
+ rec = g_hash_table_lookup(input_entries, bar);
if (rec != NULL) {
gui_entry_destroy(rec);
- g_hash_table_remove(input_entries, item);
+ g_hash_table_remove(input_entries, bar);
}
}
static void read_settings(void)
{
- if (active_entry != NULL) {
- gui_entry_set_utf8(active_entry,
- settings_get_bool("term_utf8"));
- }
+ if (active_entry != NULL)
+ gui_entry_set_utf8(active_entry, term_type == TERM_TYPE_UTF8);
}
void statusbar_items_init(void)
@@ -421,10 +418,10 @@ void statusbar_items_init(void)
/* input */
input_entries = g_hash_table_new((GHashFunc) g_direct_hash,
(GCompareFunc) g_direct_equal);
- signal_add("statusbar item destroyed", (SIGNAL_FUNC) sig_statusbar_item_destroyed);
+ signal_add("statusbar destroyed", (SIGNAL_FUNC) sig_statusbar_destroyed);
read_settings();
- signal_add("setup changed", (SIGNAL_FUNC) read_settings);
+ signal_add_last("setup changed", (SIGNAL_FUNC) read_settings);
}
void statusbar_items_deinit(void)
@@ -451,7 +448,7 @@ void statusbar_items_deinit(void)
g_source_remove(lag_timeout_tag);
/* input */
- signal_remove("statusbar item destroyed", (SIGNAL_FUNC) sig_statusbar_item_destroyed);
+ signal_remove("statusbar destroyed", (SIGNAL_FUNC) sig_statusbar_destroyed);
g_hash_table_destroy(input_entries);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
diff --git a/apps/irssi/src/fe-text/statusbar.c b/apps/irssi/src/fe-text/statusbar.c
index a9271b3c..7f3bbe3c 100644
--- a/apps/irssi/src/fe-text/statusbar.c
+++ b/apps/irssi/src/fe-text/statusbar.c
@@ -231,8 +231,7 @@ static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
}
#define SBAR_ITEM_REDRAW_NEEDED(_bar, _item, _xpos) \
- (((_bar)->dirty_xpos != -1 && \
- (_xpos) >= (_bar)->dirty_xpos) || \
+ (((_bar)->dirty_xpos != -1 && (_xpos) >= (_bar)->dirty_xpos) || \
(_item)->xpos != (_xpos) || (_item)->current_size != (_item)->size)
static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
@@ -279,7 +278,9 @@ static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
if (rec->config->right_alignment) {
if (rec->size > 0)
right_items = g_slist_prepend(right_items, rec);
- else if (rec->current_size > 0) {
+ else if (rec->current_size > 0 &&
+ (bar->dirty_xpos == -1 ||
+ rec->xpos < bar->dirty_xpos)) {
/* item was hidden - set the dirty position
to begin from the item's old xpos */
irssi_set_dirty();
@@ -1069,10 +1070,8 @@ static void statusbar_item_signal_destroy(void *key, GSList *value)
g_slist_free(value);
}
-static void sig_setup_reload(void)
+void statusbars_create_window_bars(void)
{
- /* statusbar-config.c recreates root statusbars,
- we need to create window-statusbars */
g_slist_foreach(mainwindows, (GFunc) statusbars_add_visible, NULL);
}
@@ -1098,7 +1097,6 @@ void statusbar_init(void)
signal_add("gui window created", (SIGNAL_FUNC) sig_gui_window_created);
signal_add("window changed", (SIGNAL_FUNC) sig_window_changed);
signal_add("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed);
- signal_add_last("setup reread", (SIGNAL_FUNC) sig_setup_reload);
statusbar_items_init();
statusbar_config_init(); /* signals need to be before this call */
@@ -1130,7 +1128,6 @@ void statusbar_deinit(void)
signal_remove("gui window created", (SIGNAL_FUNC) sig_gui_window_created);
signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed);
signal_remove("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed);
- signal_remove("setup reread", (SIGNAL_FUNC) sig_setup_reload);
statusbar_items_deinit();
statusbar_config_deinit();
diff --git a/apps/irssi/src/fe-text/statusbar.h b/apps/irssi/src/fe-text/statusbar.h
index 0d61c059..2e411fd2 100644
--- a/apps/irssi/src/fe-text/statusbar.h
+++ b/apps/irssi/src/fe-text/statusbar.h
@@ -110,6 +110,7 @@ void statusbar_items_redraw(const char *name);
void statusbar_recreate_items(STATUSBAR_REC *bar);
void statusbars_recreate_items(void);
+void statusbars_create_window_bars(void);
void statusbar_redraw_dirty(void);
diff --git a/apps/irssi/src/fe-text/term-curses.c b/apps/irssi/src/fe-text/term-curses.c
index 69e2b922..63db46e5 100644
--- a/apps/irssi/src/fe-text/term-curses.c
+++ b/apps/irssi/src/fe-text/term-curses.c
@@ -51,7 +51,6 @@ struct _TERM_WINDOW {
};
TERM_WINDOW *root_window;
-int term_width, term_height;
static int curs_x, curs_y;
static int freeze_refresh;
@@ -314,6 +313,11 @@ void term_addch(TERM_WINDOW *window, int chr)
waddch(window->win, chr);
}
+void term_add_unichar(TERM_WINDOW *window, unichar chr)
+{
+ waddch(window->win, chr);
+}
+
void term_addstr(TERM_WINDOW *window, const char *str)
{
waddstr(window->win, (const char *) str);
@@ -363,7 +367,15 @@ void term_stop(void)
irssi_redraw();
}
-int term_gets(unsigned char *buffer, int size)
+void term_auto_detach(int set)
+{
+}
+
+void term_set_input_type(int type)
+{
+}
+
+int term_gets(unichar *buffer, int size)
{
int key, count;
diff --git a/apps/irssi/src/fe-text/term-terminfo.c b/apps/irssi/src/fe-text/term-terminfo.c
index a1b106a7..e09e9c20 100644
--- a/apps/irssi/src/fe-text/term-terminfo.c
+++ b/apps/irssi/src/fe-text/term-terminfo.c
@@ -22,9 +22,16 @@
#include "signals.h"
#include "term.h"
#include "terminfo-core.h"
+#include "utf8.h"
#include
+/* returns number of characters in the beginning of the buffer being a
+ a single character, or -1 if more input is needed. The character will be
+ saved in result */
+typedef int (*TERM_INPUT_FUNC)(const unsigned char *buffer, int size,
+ unichar *result);
+
struct _TERM_WINDOW {
/* Terminal to use for window */
TERM_REC *term;
@@ -35,7 +42,6 @@ struct _TERM_WINDOW {
};
TERM_WINDOW *root_window;
-int term_width, term_height, term_detached;
static char *term_lines_empty; /* 1 if line is entirely empty */
static int vcmove, vcx, vcy, curs_visible;
@@ -48,6 +54,10 @@ static int last_fg, last_bg, last_attrs;
static int redraw_needed, redraw_tag;
static int freeze_counter;
+static TERM_INPUT_FUNC input_func;
+static unsigned char term_inbuf[256];
+static int term_inbuf_pos;
+
/* SIGCONT handler */
static void sig_cont(int p)
{
@@ -94,6 +104,7 @@ int term_init(void)
term_lines_empty = g_new0(char, term_height);
+ term_set_input_type(TERM_TYPE_8BIT);
term_common_init();
g_atexit(term_deinit);
return TRUE;
@@ -373,6 +384,39 @@ void term_addch(TERM_WINDOW *window, int chr)
putc(chr, window->term->out);
}
+static void term_addch_utf8(TERM_WINDOW *window, unichar chr)
+{
+ unsigned char buf[10];
+ int i, len;
+
+ len = utf16_char_to_utf8(chr, buf);
+ for (i = 0; i < len; i++)
+ putc(buf[i], window->term->out);
+}
+
+void term_add_unichar(TERM_WINDOW *window, unichar chr)
+{
+ if (term_detached) return;
+
+ if (vcmove) term_move_real();
+ term_printed_text(1);
+ if (vcy == term_height && vcx == 0)
+ return; /* last char in screen */
+
+ switch (term_type) {
+ case TERM_TYPE_UTF8:
+ term_addch_utf8(window, chr);
+ break;
+ case TERM_TYPE_BIG5:
+ putc((chr >> 8) & 0xff, window->term->out);
+ putc((chr & 0xff), window->term->out);
+ break;
+ default:
+ putc(chr, window->term->out);
+ break;
+ }
+}
+
void term_addstr(TERM_WINDOW *window, const char *str)
{
int len;
@@ -487,15 +531,80 @@ void term_stop(void)
}
}
-int term_gets(unsigned char *buffer, int size)
+static int input_utf8(const unsigned char *buffer, int size, unichar *result)
+{
+ const unsigned char *end = buffer;
+
+ *result = get_utf8_char(&end, size);
+ switch (*result) {
+ case (unichar) -2:
+ /* not UTF8 - fallback to 8bit ascii */
+ *result = *buffer;
+ return 1;
+ case (unichar) -1:
+ /* need more data */
+ return -1;
+ default:
+ return (int) (end-buffer)+1;
+ }
+}
+
+/* XXX I didn't check the encoding range of big5+. This is standard big5. */
+#define is_big5_los(lo) (0x40 <= (lo) && (lo) <= 0x7E) /* standard */
+#define is_big5_lox(lo) (0x80 <= (lo) && (lo) <= 0xFE) /* extended */
+#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE)
+#define is_big5(hi,lo) (is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo)))
+
+static int input_big5(const unsigned char *buffer, int size, unichar *result)
+{
+ if (is_big5_hi(*buffer)) {
+ /* could be */
+ if (size == 1)
+ return -1;
+
+ if (is_big5_los(buffer[1]) || is_big5_lox(buffer[1])) {
+ *result = buffer[1] + ((int) *buffer << 8);
+ return 2;
+ }
+ }
+
+ *result = *buffer;
+ return 1;
+}
+
+static int input_8bit(const unsigned char *buffer, int size, unichar *result)
{
- int ret;
+ *result = *buffer;
+ return 1;
+}
+
+void term_set_input_type(int type)
+{
+ switch (type) {
+ case TERM_TYPE_UTF8:
+ input_func = input_utf8;
+ break;
+ case TERM_TYPE_BIG5:
+ input_func = input_big5;
+ break;
+ default:
+ input_func = input_8bit;
+ }
+}
+
+int term_gets(unichar *buffer, int size)
+{
+ int ret, i, char_len;
if (term_detached)
return 0;
/* fread() doesn't work */
- ret = read(fileno(current_term->in), buffer, size);
+ if (size > sizeof(term_inbuf)-term_inbuf_pos)
+ size = sizeof(term_inbuf)-term_inbuf_pos;
+
+ ret = read(fileno(current_term->in),
+ term_inbuf + term_inbuf_pos, size);
if (ret == 0) {
/* EOF - terminal got lost */
if (auto_detach)
@@ -504,5 +613,28 @@ int term_gets(unsigned char *buffer, int size)
} else if (ret == -1 && (errno == EINTR || errno == EAGAIN))
ret = 0;
+ if (ret > 0) {
+ /* convert input to unichars. */
+ term_inbuf_pos += ret;
+ ret = 0;
+ for (i = 0; i < term_inbuf_pos; ) {
+ char_len = input_func(term_inbuf+i, term_inbuf_pos-i,
+ buffer);
+ if (char_len < 0)
+ break;
+
+ i += char_len;
+ buffer++;
+ ret++;
+ }
+
+ if (i >= term_inbuf_pos)
+ term_inbuf_pos = 0;
+ else {
+ memmove(term_inbuf+i, term_inbuf, term_inbuf_pos-i);
+ term_inbuf_pos = i;
+ }
+ }
+
return ret;
}
diff --git a/apps/irssi/src/fe-text/term.c b/apps/irssi/src/fe-text/term.c
index c32b2491..cc49103f 100644
--- a/apps/irssi/src/fe-text/term.c
+++ b/apps/irssi/src/fe-text/term.c
@@ -26,6 +26,11 @@
#include "term.h"
#include "mainwindows.h"
+#ifdef HAVE_NL_LANGINFO
+# include
+# include
+#endif
+
#ifdef HAVE_SYS_IOCTL_H
# include
#endif
@@ -34,7 +39,10 @@
#define MIN_SCREEN_WIDTH 20
+int term_width, term_height, term_detached;
+
int term_use_colors;
+int term_type;
static int force_colors;
static int resize_dirty;
@@ -91,10 +99,25 @@ static void cmd_resize(void)
static void read_settings(void)
{
+ const char *str;
int old_colors = term_use_colors;
+ int old_type = term_type;
term_auto_detach(settings_get_bool("term_auto_detach"));
+ /* set terminal type */
+ str = settings_get_str("term_type");
+ if (g_strcasecmp(str, "utf-8") == 0)
+ term_type = TERM_TYPE_UTF8;
+ else if (g_strcasecmp(str, "big5") == 0)
+ term_type = TERM_TYPE_BIG5;
+ else
+ term_type = TERM_TYPE_8BIT;
+
+ if (old_type != term_type)
+ term_set_input_type(term_type);
+
+ /* change color stuff */
if (force_colors != settings_get_bool("term_force_colors")) {
force_colors = settings_get_bool("term_force_colors");
term_force_colors(force_colors);
@@ -115,12 +138,20 @@ void term_common_init(void)
settings_add_bool("lookandfeel", "colors", TRUE);
settings_add_bool("lookandfeel", "term_force_colors", FALSE);
settings_add_bool("lookandfeel", "term_auto_detach", FALSE);
- settings_add_bool("lookandfeel", "term_utf8", FALSE);
+ settings_add_str("lookandfeel", "term_type", "8bit");
force_colors = FALSE;
term_use_colors = term_has_colors() && settings_get_bool("colors");
read_settings();
+#if defined (HAVE_NL_LANGINFO) && defined(CODESET)
+ setlocale(LC_CTYPE, "");
+ if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
+ term_type = TERM_TYPE_UTF8;
+ term_set_input_type(TERM_TYPE_UTF8);
+ }
+#endif
+
signal_add("beep", (SIGNAL_FUNC) term_beep);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
command_bind("resize", NULL, (SIGNAL_FUNC) cmd_resize);
diff --git a/apps/irssi/src/fe-text/term.h b/apps/irssi/src/fe-text/term.h
index 9cd1b153..3607fad5 100644
--- a/apps/irssi/src/fe-text/term.h
+++ b/apps/irssi/src/fe-text/term.h
@@ -3,6 +3,7 @@
typedef struct _TERM_WINDOW TERM_WINDOW;
+/* text attributes */
#define ATTR_RESETFG 0x0100
#define ATTR_RESETBG 0x0200
#define ATTR_BOLD 0x0400
@@ -14,16 +15,16 @@ typedef struct _TERM_WINDOW TERM_WINDOW;
#define ATTR_NOCOLORS (ATTR_UNDERLINE|ATTR_REVERSE)
-#ifdef WANT_BIG5
-/* XXX I didn't check the encoding range of big5+. This is standard big5. */
-# define is_big5_los(lo) (((char)0x40<=lo)&&(lo<=(char)0x7E)) /* standard */
-# define is_big5_lox(lo) (((char)0x80<=lo)&&(lo<=(char)0xFE)) /* extended */
-# define is_big5_hi(hi) (((char)0x81<=hi)&&(hi<=(char)0xFE))
-# define is_big5(hi,lo) is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo))
-#endif
+/* terminal types */
+#define TERM_TYPE_8BIT 0 /* normal 8bit text */
+#define TERM_TYPE_UTF8 1
+#define TERM_TYPE_BIG5 2
+
+typedef guint32 unichar;
extern TERM_WINDOW *root_window;
-extern int term_width, term_height, term_use_colors, term_detached;
+extern int term_width, term_height;
+extern int term_use_colors, term_type, term_detached;
/* Initialize / deinitialize terminal */
int term_init(void);
@@ -63,6 +64,7 @@ void term_set_color(TERM_WINDOW *window, int col);
void term_move(TERM_WINDOW *window, int x, int y);
void term_addch(TERM_WINDOW *window, int chr);
+void term_add_unichar(TERM_WINDOW *window, unichar chr);
void term_addstr(TERM_WINDOW *window, const char *str);
void term_clrtoeol(TERM_WINDOW *window);
@@ -78,7 +80,10 @@ void term_detach(void);
void term_attach(FILE *in, FILE *out);
void term_stop(void);
-int term_gets(unsigned char *buffer, int size);
+
+/* keyboard input handling */
+void term_set_input_type(int type);
+int term_gets(unichar *buffer, int size);
/* internal */
void term_common_init(void);
diff --git a/apps/irssi/src/fe-text/textbuffer-view.c b/apps/irssi/src/fe-text/textbuffer-view.c
index d98fc85c..dc21aae6 100644
--- a/apps/irssi/src/fe-text/textbuffer-view.c
+++ b/apps/irssi/src/fe-text/textbuffer-view.c
@@ -231,7 +231,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
}
if (view->utf8)
- get_utf8_char(&ptr);
+ get_utf8_char(&ptr, 6);
xpos++;
if (*ptr++ == ' ') {
@@ -398,7 +398,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
if (xpos < term_width) {
const unsigned char *end = text;
if (view->utf8)
- get_utf8_char(&end);
+ get_utf8_char(&end, 6);
if (*text >= 32 &&
(end != text || (*text & 127) >= 32)) {
diff --git a/apps/irssi/src/fe-text/textbuffer.c b/apps/irssi/src/fe-text/textbuffer.c
index 8ac8bf00..ee11aa67 100644
--- a/apps/irssi/src/fe-text/textbuffer.c
+++ b/apps/irssi/src/fe-text/textbuffer.c
@@ -518,7 +518,8 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
textbuffer_line_ref(line);
matches = g_list_append(matches, line);
- if (!line_matched && --match_after == 0)
+ if ((!line_matched && --match_after == 0) ||
+ (line_matched && match_after == 0 && before > 0))
matches = g_list_append(matches, NULL);
}
}
diff --git a/apps/irssi/src/fe-text/utf8.c b/apps/irssi/src/fe-text/utf8.c
index 63a834c8..2d72fe2b 100644
--- a/apps/irssi/src/fe-text/utf8.c
+++ b/apps/irssi/src/fe-text/utf8.c
@@ -1,3 +1,29 @@
+/* utf8.c - Operations on UTF-8 strings.
+ *
+ * Copyright (C) 2002 Timo Sirainen
+ *
+ * Based on GLib code by
+ *
+ * Copyright (C) 1999 Tom Tromey
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "module.h"
#define UTF8_COMPUTE(Char, Mask, Len) \
if (Char < 128) \
@@ -46,19 +72,106 @@
(Result) |= ((Chars)[(Count)] & 0x3f); \
}
-void get_utf8_char(const unsigned char **ptr)
+unichar get_utf8_char(const unsigned char **ptr, int len)
{
- int i, mask = 0, len;
- unsigned int result;
- unsigned char c = (unsigned char) **ptr;
+ int i, result, mask, chrlen;
+
+ mask = 0;
+ UTF8_COMPUTE(**ptr, mask, chrlen);
+ if (chrlen == -1)
+ return (unichar) -2;
- UTF8_COMPUTE(c, mask, len);
- if (len == -1)
- return;
+ if (chrlen > len)
+ return (unichar) -1;
- UTF8_GET(result, *ptr, i, mask, len);
+ UTF8_GET(result, *ptr, i, mask, chrlen);
if (result == -1)
- return;
+ return (unichar) -2;
+
+ *ptr += chrlen-1;
+ return result;
+}
+
+int strlen_utf8(const char *str)
+{
+ const unsigned char *p = (const unsigned char *) str;
+ int len;
+
+ len = 0;
+ while (*p != '\0' && get_utf8_char(&p, 6) > 0) {
+ len++;
+ p++;
+ }
+ return len;
+}
+
+int utf16_char_to_utf8(unichar c, char *outbuf)
+{
+ int len, i, first;
+
+ len = 0;
+ if (c < 0x80) {
+ first = 0;
+ len = 1;
+ } else if (c < 0x800) {
+ first = 0xc0;
+ len = 2;
+ } else if (c < 0x10000) {
+ first = 0xe0;
+ len = 3;
+ } else if (c < 0x200000) {
+ first = 0xf0;
+ len = 4;
+ } else if (c < 0x4000000) {
+ first = 0xf8;
+ len = 5;
+ } else {
+ first = 0xfc;
+ len = 6;
+ }
+
+ if (outbuf) {
+ for (i = len - 1; i > 0; --i) {
+ outbuf[i] = (c & 0x3f) | 0x80;
+ c >>= 6;
+ }
+ outbuf[0] = c | first;
+ }
+
+ return len;
+}
+
+void utf8_to_utf16(const char *str, unichar *out)
+{
+ const unsigned char *p = (const unsigned char *) str;
+ int i, result, mask, len;
+
+ while (*p != '\0') {
+ mask = 0;
+ UTF8_COMPUTE(*p, mask, len);
+ if (len == -1)
+ break;
+
+ UTF8_GET(result, p, i, mask, len);
+ if (result == -1)
+ break;
+
+ p += len;
+ *out++ = result;
+ }
+
+ *out = '\0';
+}
+
+void utf16_to_utf8(const unichar *str, char *out)
+{
+ int len;
+
+ while (*str != '\0') {
+ len = utf16_char_to_utf8(*str, out);
+ out += len;
- *ptr += len-1;
+ str++;
+ }
+ *out = '\0';
}
diff --git a/apps/irssi/src/fe-text/utf8.h b/apps/irssi/src/fe-text/utf8.h
index 3d8f3783..efc6af08 100644
--- a/apps/irssi/src/fe-text/utf8.h
+++ b/apps/irssi/src/fe-text/utf8.h
@@ -1,6 +1,21 @@
#ifndef __UTF8_H
#define __UTF8_H
-void get_utf8_char(const unsigned char **ptr);
+/* Returns -2 = invalid, -1 = need more data, otherwise unichar. */
+unichar get_utf8_char(const unsigned char **ptr, int len);
+
+/* Returns length of UTF8 string */
+int strlen_utf8(const char *str);
+
+/* UTF-8 -> unichar string. The NUL is copied as well. */
+void utf8_to_utf16(const char *str, unichar *out);
+
+/* unichar -> UTF-8 string. outbuf must be at least 6 chars long.
+ Returns outbuf string length. */
+int utf16_char_to_utf8(unichar c, char *outbuf);
+
+/* unichar -> UTF-8 string. The NUL is copied as well.
+ Make sure out is at least 6 x length of str. */
+void utf16_to_utf8(const unichar *str, char *out);
#endif
diff --git a/apps/irssi/src/lib-config/get.c b/apps/irssi/src/lib-config/get.c
index 124d7101..e4c5cf07 100644
--- a/apps/irssi/src/lib-config/get.c
+++ b/apps/irssi/src/lib-config/get.c
@@ -41,8 +41,15 @@ CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key)
/* find the section from node - if not found create it unless new_type is -1.
you can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */
CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type)
+{
+ return config_node_section_index(parent, key, -1, new_type);
+}
+
+CONFIG_NODE *config_node_section_index(CONFIG_NODE *parent, const char *key,
+ int index, int new_type)
{
CONFIG_NODE *node;
+ int nindex;
g_return_val_if_fail(parent != NULL, NULL);
g_return_val_if_fail(is_node_list(parent), NULL);
@@ -50,14 +57,22 @@ CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_t
node = key == NULL ? NULL : config_node_find(parent, key);
if (node != NULL) {
g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL);
- return node;
+ nindex = g_slist_index(parent->value, node);
+ if (index >= 0 && nindex != index &&
+ nindex <= g_slist_length(parent->value)) {
+ /* move it to wanted position */
+ parent->value = g_slist_remove(parent->value, node);
+ parent->value = g_slist_insert(parent->value, node, index);
+ }
+ return node;
}
if (new_type == -1)
return NULL;
node = g_new0(CONFIG_NODE, 1);
- parent->value = g_slist_append(parent->value, node);
+ parent->value = index < 0 ? g_slist_append(parent->value, node) :
+ g_slist_insert(parent->value, node, index);
node->type = new_type;
node->key = key == NULL ? NULL : g_strdup(key);
@@ -294,7 +309,7 @@ char **config_node_get_list(CONFIG_NODE *node)
}
/* Returns n'th node from list. */
-CONFIG_NODE *config_node_index(CONFIG_NODE *node, int index)
+CONFIG_NODE *config_node_nth(CONFIG_NODE *node, int index)
{
GSList *tmp;
@@ -309,6 +324,21 @@ CONFIG_NODE *config_node_index(CONFIG_NODE *node, int index)
return NULL;
}
+/* Returns index for given key */
+int config_node_index(CONFIG_NODE *parent, const char *key)
+{
+ CONFIG_NODE *node;
+
+ g_return_val_if_fail(parent != NULL, -1);
+ g_return_val_if_fail(key != NULL, -1);
+
+ node = config_node_find(parent, key);
+ if (node == NULL)
+ return -1;
+
+ return g_slist_index(parent->value, node);
+}
+
/* Returns the first non-comment node in list */
GSList *config_node_first(GSList *list)
{
diff --git a/apps/irssi/src/lib-config/iconfig.h b/apps/irssi/src/lib-config/iconfig.h
index fc475f4e..7ef8d791 100644
--- a/apps/irssi/src/lib-config/iconfig.h
+++ b/apps/irssi/src/lib-config/iconfig.h
@@ -98,7 +98,9 @@ const char *config_list_find(CONFIG_REC *rec, const char *section, const char *k
/* Like config_list_find(), but return node instead of it's value */
CONFIG_NODE *config_list_find_node(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key);
/* Returns n'th node from list. */
-CONFIG_NODE *config_node_index(CONFIG_NODE *node, int index);
+CONFIG_NODE *config_node_nth(CONFIG_NODE *node, int index);
+/* Returns index for given key */
+int config_node_index(CONFIG_NODE *parent, const char *key);
/* Returns the first non-comment node in list */
GSList *config_node_first(GSList *list);
@@ -116,6 +118,8 @@ CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key);
/* Find the section from node - if not found create it unless new_type is -1.
You can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */
CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type);
+CONFIG_NODE *config_node_section_index(CONFIG_NODE *parent, const char *key,
+ int index, int new_type);
/* Find the section with the whole path.
Create the path if necessary `create' is TRUE. */
CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int create);
diff --git a/apps/irssi/src/lib-config/set.c b/apps/irssi/src/lib-config/set.c
index fdb358f9..6cfaa483 100644
--- a/apps/irssi/src/lib-config/set.c
+++ b/apps/irssi/src/lib-config/set.c
@@ -67,7 +67,7 @@ void config_node_list_remove(CONFIG_REC *rec, CONFIG_NODE *node, int index)
g_return_if_fail(node != NULL);
g_return_if_fail(is_node_list(node));
- child = config_node_index(node, index);
+ child = config_node_nth(node, index);
if (child != NULL) config_node_remove(rec, node, child);
}
diff --git a/apps/irssi/src/lib-popt/popthelp.c b/apps/irssi/src/lib-popt/popthelp.c
index 243f868e..15ed2d95 100644
--- a/apps/irssi/src/lib-popt/popthelp.c
+++ b/apps/irssi/src/lib-popt/popthelp.c
@@ -175,7 +175,7 @@ static int showHelpIntro(poptContext con, FILE * f) {
fprintf(f, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
fn = con->optionStack->argv[0];
- if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
+ if (strrchr(fn, '/')) fn = strrchr(fn, '/') + 1;
fprintf(f, " %s", fn);
len += strlen(fn) + 1;
}
diff --git a/apps/irssi/src/perl/perl-signals-list.h b/apps/irssi/src/perl/perl-signals-list.h
index 4c1c9ad6..fc888cf2 100644
--- a/apps/irssi/src/perl/perl-signals-list.h
+++ b/apps/irssi/src/perl/perl-signals-list.h
@@ -166,7 +166,7 @@ static PERL_SIGNAL_ARGS_REC perl_signal_args[] =
{ "message irc own_notice", { "iobject", "string", "string", NULL } },
{ "message irc notice", { "iobject", "string", "string", "string", "string", NULL } },
{ "message irc own_ctcp", { "iobject", "string", "string", "string", NULL } },
- { "message irc ctcp", { "iobject", "string", "string", "string", "string", NULL } },
+ { "message irc ctcp", { "iobject", "string", "string", "string", "string", "string", NULL } },
{ "message dcc own", { "siobject", "string", NULL } },
{ "message dcc own_action", { "siobject", "string", NULL } },
{ "message dcc own_ctcp", { "siobject", "string", "string", NULL } },
diff --git a/apps/irssi/src/perl/ui/Window.xs b/apps/irssi/src/perl/ui/Window.xs
index d6183789..ac65480e 100644
--- a/apps/irssi/src/perl/ui/Window.xs
+++ b/apps/irssi/src/perl/ui/Window.xs
@@ -215,6 +215,12 @@ window_set_level(window, level)
Irssi::UI::Window window
int level
+void
+window_activity(window, data_level, hilight_color=NULL)
+ Irssi::UI::Window window
+ int data_level
+ char *hilight_color
+
char *
window_get_active_name(window)
Irssi::UI::Window window
@@ -268,3 +274,10 @@ window_item_set_active(item)
Irssi::Windowitem item
CODE:
window_item_set_active(window_item_window(item), item);
+
+void
+window_item_activity(item, data_level, hilight_color=NULL)
+ Irssi::Windowitem item
+ int data_level
+ char *hilight_color
+
diff --git a/lib/silccore/DIRECTORY b/lib/silccore/DIRECTORY
index bc335255..c1fc2bed 100644
--- a/lib/silccore/DIRECTORY
+++ b/lib/silccore/DIRECTORY
@@ -1,16 +1,16 @@
SILC Core Library
diff --git a/lib/silccore/silcargument.h b/lib/silccore/silcargument.h
index f5de0d99..687c1998 100644
--- a/lib/silccore/silcargument.h
+++ b/lib/silccore/silcargument.h
@@ -21,7 +21,7 @@
*
* DESCRIPTION
*
- * Implementation of the Arugment Payload, that is used to include
+ * Implementation of the Argument Payload, that is used to include
* argument to other payload that needs arguments.
*
***/
diff --git a/lib/silccore/silcauth.h b/lib/silccore/silcauth.h
index c280dab3..538de11b 100644
--- a/lib/silccore/silcauth.h
+++ b/lib/silccore/silcauth.h
@@ -22,7 +22,7 @@
*
* DESCRIPTION
*
- * Implementations of the Silc Authentication Payload and authentication
+ * Implementations of the SILC Authentication Payload and authentication
* routines. The SILC Authentication Payload is used to deliver
* authentication data usually from client to server in purpose of
* gaining access to some service. The Payload and the authentication
diff --git a/lib/silccrypt/DIRECTORY b/lib/silccrypt/DIRECTORY
index 58101e8b..7b950634 100644
--- a/lib/silccrypt/DIRECTORY
+++ b/lib/silccrypt/DIRECTORY
@@ -1,7 +1,7 @@
SILC Math Library
diff --git a/lib/silcsftp/DIRECTORY b/lib/silcsftp/DIRECTORY
index 87c2b2f0..088a6975 100644
--- a/lib/silcsftp/DIRECTORY
+++ b/lib/silcsftp/DIRECTORY
@@ -1,8 +1,8 @@
SILC SFTP Library
diff --git a/lib/silcutil/DIRECTORY b/lib/silcutil/DIRECTORY
index 9fce1564..1caefbf3 100644
--- a/lib/silcutil/DIRECTORY
+++ b/lib/silcutil/DIRECTORY
@@ -1,23 +1,24 @@
SILC Utility Library
diff --git a/scripts/silcdoc/gen_index.php b/scripts/silcdoc/gen_index.php
index 4ee117cc..01e9d9c7 100644
--- a/scripts/silcdoc/gen_index.php
+++ b/scripts/silcdoc/gen_index.php
@@ -102,9 +102,9 @@ require "$page";
diff --git a/scripts/silcdoc/silcdoc b/scripts/silcdoc/silcdoc
index 41c56643..0405a7fa 100755
--- a/scripts/silcdoc/silcdoc
+++ b/scripts/silcdoc/silcdoc
@@ -110,13 +110,13 @@ echo $f
sh gen.sh $DST gen_index.php 1 $DST/$i.html $DST/$i.html
# Generate the details and the layout
- files=`find $DST -name ""$i"__*.html"`
+ files=`find $DST -name ""$i"-*.html"`
for k in $files
do
sh gen.sh $DST gen_index.php 0 $k $k
done
- rm -f $DST/$i__index.tmpl
+ rm -f $DST/$i-index.tmpl
done
# Generate the index and TOC files from the DIRECTORY files
diff --git a/util/robodoc/Source/generator.c b/util/robodoc/Source/generator.c
index f93b00b3..c1d90780 100644
--- a/util/robodoc/Source/generator.c
+++ b/util/robodoc/Source/generator.c
@@ -64,7 +64,7 @@ RB_Generate_Documentation (
if (output_mode == HTML)
{
- sprintf(fname, "%s__%s.html", doc_base, cur_header->function_name);
+ sprintf(fname, "%s-%s.html", doc_base, cur_header->function_name);
dest_doc = fopen(fname, "w");
if (!dest_doc)
{
@@ -272,7 +272,7 @@ RB_Generate_Doc_Start (
#endif
/* Generate quick index file, for fast referencing */
- sprintf(iname, "%s__index.tmpl", doc_base);
+ sprintf(iname, "%s-index.tmpl", doc_base);
index = fopen(iname, "w");
if (!index)
{
@@ -286,7 +286,7 @@ RB_Generate_Doc_Start (
{
char fname[256];
- sprintf(fname, "%s__%s.html", RB_FilePart(doc_base),
+ sprintf(fname, "%s-%s.html", RB_FilePart(doc_base),
cur_header->function_name);
if (cur_header->name && cur_header->function_name)
@@ -1284,7 +1284,7 @@ RB_Generate_Item_Body (FILE * dest_doc, char *dest_name,
fprintf (dest_doc, "%s",
label_name, label_name);
#endif
- fprintf (dest_doc, "%s",
+ fprintf (dest_doc, "%s",
RB_FilePart(doc_base), label_name,
label_name);
}