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/?p=silc.git;a=commitdiff_plain;h=35013080aabb8ec82609c07c43c5444cbf6568e4 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:

  1. For all the lazy people
  2. -
  3. Basic user interface usage
  4. +
  5. Basic user interface usage +
      +
    • Split windows work in weird way
    • +
  6. 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?
  7. Setting up windows and automatically restoring them at startup
  8. @@ -34,8 +37,12 @@
  9. How can I save all texts in a window to file?
  10. Logging
  11. -
  12. Proxies and IRC bouncers
  13. -
  14. Irssi's settings
  15. +
  16. Changing keyboard bindings +
      +
    • How do I make F1 key do something?
    • +
  17. +
  18. Proxies and IRC bouncers
  19. +
  20. Irssi's settings

1. For all the lazy people

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

-

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:

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

-

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 @@ -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); }