Merged Irssi 0.8.2 from irssi.org cvs. silc.client.0.8.1
authorPekka Riikonen <priikone@silcnet.org>
Mon, 11 Mar 2002 21:33:32 +0000 (21:33 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 11 Mar 2002 21:33:32 +0000 (21:33 +0000)
41 files changed:
CHANGES
TODO
apps/irssi/docs/help/in/bind.in
apps/irssi/docs/help/in/connect.in
apps/irssi/docs/help/in/ignore.in
apps/irssi/docs/help/in/server.in
apps/irssi/docs/perl.txt
apps/irssi/docs/startup-HOWTO.html
apps/irssi/src/core/chatnets.c
apps/irssi/src/core/core.c
apps/irssi/src/core/core.h
apps/irssi/src/core/network.c
apps/irssi/src/core/queries.c
apps/irssi/src/core/query-rec.h
apps/irssi/src/core/servers.c
apps/irssi/src/core/session.c
apps/irssi/src/fe-common/core/fe-channels.c
apps/irssi/src/fe-common/core/fe-core-commands.c
apps/irssi/src/fe-common/core/fe-ignore-messages.c
apps/irssi/src/fe-common/core/fe-queries.c
apps/irssi/src/fe-common/core/fe-windows.c
apps/irssi/src/fe-common/core/formats.c
apps/irssi/src/fe-common/core/formats.h
apps/irssi/src/fe-common/core/keyboard.c
apps/irssi/src/fe-common/core/printtext.c
apps/irssi/src/fe-common/core/themes.c
apps/irssi/src/fe-common/core/themes.h
apps/irssi/src/fe-text/gui-entry.c
apps/irssi/src/fe-text/gui-entry.h
apps/irssi/src/fe-text/gui-printtext.c
apps/irssi/src/fe-text/gui-readline.c
apps/irssi/src/fe-text/mainwindows.c
apps/irssi/src/fe-text/module-formats.c
apps/irssi/src/fe-text/module-formats.h
apps/irssi/src/fe-text/statusbar-items.c
apps/irssi/src/fe-text/statusbar.c
apps/irssi/src/fe-text/term-terminfo.c
apps/irssi/src/fe-text/term.c
apps/irssi/src/perl/common/Irssi.pm
apps/irssi/src/perl/perl-common.c
lib/silccore/silcidcache.h

diff --git a/CHANGES b/CHANGES
index fb664a36c83306be6adf476cf180b3bfeed87c1d..f3d99036d65d2bb4a92c512e84d16b7a9d97a252 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+Mon Mar 11 23:37:38 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Merged Irssi 0.8.2 from irssi.org CVS.
+
 Sun Mar 10 23:34:48 CET 2002  Johnny Mnemonic <johnny@themnemonic.org>
 
        * If silc_debug is TRUE, also output standard logging messages
diff --git a/TODO b/TODO
index 322e71f0792fc5dee65317a83331b397127010e0..d32f8bf141803cbe57d0ccbd530f13139a37fd1f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -37,6 +37,10 @@ TODO/bugs In SILC Server
 
  o Configuration file additions:
 
+       o Add support for multipe PublicKey params in connections 
+         sections.  For now, add this support only in Client and not
+         in ServerConnection nor RouterConnection.
+
        o Add version handling, to allow, disallow certain versions to
          connect.
 
index 152ac34d114e8acfbd88292f045f237a3b27b662..89cfbdda34861517e027f25602ddf9f7c830eb87 100644 (file)
@@ -92,6 +92,7 @@ Command can be one of:
   refresh_screen
   yank_from_cutbuffer - "Undelete" line
   transpose_characters - Swap current and previous character
+  escape_char - Insert the next character exactly as-is to input line
   insert_text - Insert data to entry line, data may contain $variables.
   stop_irc - Send SIGSTOP to client (^Z)
 
index 98c91680a6bb591ab07de650db2b8d7a55ebd880..aa6ce5b10c0df6db673b900276325100e1b1f1cc 100644 (file)
@@ -2,8 +2,9 @@
 @SYNTAX:connect@
 
      -4, -6: specify explicitly whether to use IPv4 or IPv6 address
-     -silcnet: the specified network
+     -silcnet: the SILCNet
      -host: the host
+     -!: don't autojoin channels
 
 This command makes irssi to connect to specified server.
 Current connections are kept and a new one is created.
index 34a49dece3b99ed139d95e2b215a6bd5950dd53d..c5b5c342e1c3ab271b0e93a03dd7d63914db2c1c 100644 (file)
@@ -2,25 +2,41 @@
 @SYNTAX:ignore@
 
     -regexp: <pattern> is a regular expression
-    -word: <pattern> must match to full words
+    -full: <pattern> must match to full words
     -pattern: <pattern> must match to the message's text
     -replies: Ignore replies to nick in channels. For example
-             "/IGNORE -replies *!*@*.fi PUBLIC" ignores everyone
-             from Finland, but also anyone sending message
-             "tofinnishnick: blahblah".
-    -except: *DON'T* ignore
+              "/IGNORE -replies *!*@*.fi PUBLIC" ignores everyone
+              from Finland, but also anyone sending message
+              "tofinnishnick: blahblah".
+    -except: *DON'T* ignore - overrides an existing ignore.
     -channels: Ignore only in channels
     <mask>: Either a nick mask or list of channels
-    <levels>: List of levels to ignore
+    <levels>: List of levels to ignore. You can use -<level> to remove levels
+              from ignore.
     <^levels>: List of levels to NOT ignore
-            (/ignore -except nick notices = /ignore nick ^notices)
+               (/ignore -except nick notices = /ignore nick ^notices)
 
 
-/IGNORE without any arguments displays list of ignores.
+/IGNORE without any arguments displays list of ignores. If you want to remove
+some levels of the ignore, use /IGNORE <mask> -<level> -<level2> etc
 
 The best match always wins, so you can have:
     /IGNORE * CTCPS
     /IGNORE -except *!*@host.org CTCPS
 
+Examples:
+
+    /IGNORE #channel ALL -PUBLIC -ACTIONS   - ignore all but public/actions
+    /IGNORE #channel -JOINS                 - don't ignore joins anymore
+    /IGNORE -replies *!user@*.host.org ALL  - ignore user and all replies
+
+Some suggestions for ignoring annoying public aways:
+    /IGNORE -regexp -pattern "is (away|gone|back)" * ACTIONS
+    /IGNORE *zzz* NICKS
+    /IGNORE *afk* NICKS
+    /IGNORE *away* NICKS
+
+For regular expressions, see `man 7 regex`.
+
 See also: UNIGNORE
 
index 75170f1273f015b170a70c724e2b7342704c5eac..ac514f73f7cf5d12d1f5bf8588b1cd42b44d875f 100644 (file)
@@ -6,6 +6,7 @@
      -noauto: Don't connect to server at startup
      -silcnet: Specify what network this server belongs to
      -host: Specify what host name to use, if you have multiple
+     -!: don't autojoin channels
      -cmdspeed: Same as /SET cmd_queue_speed, see section 3.1
      -cmdmax: Same as /SET cmd_max_at_once, see section 3.1
      -port: This is pretty much like the port argument later, 
index 0d779a8e5346a326836a70337c91cd58d8c0176b..23ecfbed1f520ce193f9aeab56e8d2570b0e3424 100644 (file)
@@ -200,11 +200,7 @@ command(cmd)
 Server::command(cmd)
 Window::command(cmd)
 Windowitem::command(cmd)
-  Send a command `cmd' (in current channel). This will work just as if you
-  had typed `cmd' in command line, so you'll need to use /COMMANDS or the
-  text will be sent to the channel.
-
-  Just like above, except different calling method.
+  Send a command `cmd' (in current channel). The '/' char isn't needed.
 
 
  *** Themes
@@ -723,9 +719,13 @@ Channel::nick_remove(nick)
   Remove nick from nicklist.
 
 Nick
-Channel::nick_find(mask)
+Channel::nick_find(nick)
   Find nick from nicklist.
 
+Nick
+Channel::nick_find_mask(mask)
+  Find nick mask from nicklist, wildcards allowed.
+
 Channel::nicks(channel)
   Return a list of all nicks in channel.
 
index ddd5d025ba1de271fbf93d4d1e467fc23dfdc411..af92b83e4a30660951d0371a03acb8ef4ad99c82 100644 (file)
@@ -9,6 +9,9 @@
 
 <ol>
 <li><a href="#c1">For all the lazy people</a></li>
+    <ul>
+    <li>This window management is just weird, I want it exactly like ircII</li>
+    </ul>
 <li><a href="#c2">Basic user interface usage</a>
     <ul>
     <li>Split windows work in weird way</li>
     </ul></li>
 <li><a href="#c10">Proxies and IRC bouncers</a></li>
 <li><a href="#c11">Irssi's settings</a></li>
+<li><a href="#c12">Statusbar</a>
+    <ul>
+    <li>I loaded a statusbar script but it's not visible anywhere!</li>
+    </ul></li>
 </ol>
 
 <h3><a id="c1">1. For all the lazy people</a></h3>
 
 <p>These settings should give you pretty good defaults (the ones I use):</p>
 
+<p>If colors don't work, and you know you're not going to use some
+weird non-VT compatible terminal (you most probably aren't), just
+say:</p>
+
+<pre>
+     /SET term_force_colors ON
+</pre>
+
 <p>I don't like automatic query windows, I don't like status window, I do
 like msgs window where all messages go:</p>
 
@@ -67,6 +82,22 @@ query:</p>
      /SET reuse_unused_windows ON
 </pre>
 
+<p>Here's the settings that make irssi work exactly like ircII in window
+management (send me a note if you can think of more):</p>
+
+<pre>
+     /SET autocreate_own_query OFF
+     /SET autocreate_query_level NONE
+     /SET use_status_window OFF
+     /SET use_msgs_window OFF
+     /SET reuse_unused_windows ON
+     /SET windows_auto_renumber OFF
+
+     /SET autostick_split_windows OFF
+     /SET autoclose_windows OFF
+     /SET print_active_channel ON
+</pre>
+
 <p>And example how to add servers:</p>
 
 <p>(openprojects network, identify with nickserv and wait for 2 seconds before
@@ -202,6 +233,13 @@ automatic creating of them with</p>
      /SET autocreate_windows OFF
 </pre>
 
+<p>And if you keep all channels in one window, you most probably want
+the channel name printed in each line:</p>
+
+<pre>
+     /SET print_active_channel ON
+</pre>
+
 <p>If you want to group only some channels or queries in one window,
 use</p>
 
@@ -539,8 +577,44 @@ be better to use eg.:</p>
 
 <h3><a id="c10">10. Proxies and IRC bouncers</a></h3>
 
-<p>Irssi supports connecting to IRC servers via a proxy. All proxies have
-these settings in common:</p>
+<p>Irssi supports connecting to IRC servers via a proxy. All server
+connections are then made through it, and if you've set up everything
+properly, you don't need to do any /QUOTE SERVER commands manually.</p>
+
+<p>Here's an example: You have your bouncer (lets say, BNC or BNC-like)
+listening in irc.bouncer.org port 5000. You want to use it to connect
+to servers irc.dalnet and irc.efnet.org. First you'd need to setup the
+bouncer:</p>
+
+<pre>
+     /SET use_proxy ON
+     /SET proxy_address irc.bouncer.org
+     /SET proxy_port 5000
+
+     /SET proxy_password YOUR_BNC_PASSWORD_HERE
+     /SET -clear proxy_string
+     /SET proxy_string_after conn %s %d
+</pre>
+
+<p>Then you'll need to add the server connections. These are done
+exactly as if you'd want to connect directly to them. Nothing special
+about them:</p>
+
+<pre>
+     /SERVER ADD -auto -ircnet dalnet irc.dal.net
+     /SERVER ADD -auto -ircnet efnet irc.efnet.org
+</pre>
+
+<p>With the proxy /SETs however, irssi now connects to those servers
+through your BNC. All server connections are made through them so you
+can just forget that your bouncer even exists.</p>
+
+<p>If you don't want to use the proxy for some reason, there's -noproxy
+option which you can give to /SERVER and /SERVER ADD commands.</p>
+
+<p><strong>Proxy specific settings:</strong></p>
+
+<p>All proxies have these settings in common:</p>
 
 <pre>
      /SET use_proxy ON
@@ -562,7 +636,7 @@ these settings in common:</p>
 <pre>
      /SET proxy_password your_pass
      /SET -clear proxy_string
-     /SET proxy_string conn %s %d
+     /SET proxy_string_after conn %s %d
 </pre>
 
 <p><strong>dircproxy</strong></p>
@@ -583,6 +657,26 @@ this:</p>
 <p>The server name and port you give isn't used anywhere, so you can
 put anything you want in there.</p>
 
+<p><strong>psyBNC</strong></p>
+
+<p>psyBNC has internal support for multiple servers. However, it could
+be a bit annoying to use, and some people just use different users for
+connecting to different servers. You can manage this in a bit same way
+as with dircproxy, by creating fake connections:</p>
+
+<pre>
+    /SET -clear proxy_password
+    /SET -clear proxy_string
+
+    /IRCNET ADD -user ircnetuser ircnet
+    /SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
+    /IRCNET ADD -user opnuser opn
+    /SERVER ADD -auto -ircnet opn fake.opn 6667 opnpass
+</pre>
+
+<p>So, you'll specify the usernames with /IRCNET ADD command, and the
+user's password with /SERVER ADD.</p>
+
 <p><strong>Irssi proxy</strong></p>
 
 <p>Irssi contains it's own proxy which you can build giving
@@ -796,6 +890,7 @@ of them you might want to change (the default value is shown):</p>
   or queries, list them here. For example "#boringchannel =bot1 =bot2".
   If any highlighted text or message for you appears in that window, this
   setting is ignored and the activity is shown.</dd>
+</dl>
 
 <p><strong>Nick completion</strong></p>
 
@@ -808,3 +903,50 @@ of them you might want to change (the default value is shown):</p>
 <dt>/SET completion_char :</dt>
   <dd>Completion character to use.</dd>
 </dl>
+
+<h3><a id="c12">12. Statusbar</a></h3>
+
+<p><strong>/STATUSBAR</strong> displays a list of statusbars:</p>
+
+<pre>
+Name                           Type   Placement Position Visible
+window                         window bottom    0        always
+window_inact                   window bottom    1        inactive
+prompt                         root   bottom    100      always
+topic                          root   top       1        always
+</pre>
+
+<p><strong>/STATUSBAR &lt;name&gt;</strong> prints the statusbar
+settings and it's items. <strong>/STATUSBAR &lt;name&gt;
+ENABLE|DISABLE</strong> enables/disables the statusbar.
+<strong>/STATUSBAR &lt;name&gt; RESET</strong> resets the statusbar to
+it's default settings, or if the statusbar was created by you, it will be
+removed.</p>
+
+<p>Type can be window or root, meaning if the statusbar should be
+created for each split window, or just once. Placement can be top or
+bottom. Position is a number, the higher the value the lower in screen
+it is. Visible can be always, active or inactive. Active/inactive is
+useful only with split windows, one split window is active and the rest
+are inactive. These settings can be changed with:</p>
+
+<ul>
+<li>STATUSBAR &lt;name&gt; TYPE window|root</li>
+<li>STATUSBAR &lt;name&gt; PLACEMENT top|bottom</li>
+<li>STATUSBAR &lt;name&gt; POSITION &lt;num&gt;</li>
+<li>STATUSBAR &lt;name&gt; VISIBLE always|active|inactive</li>
+</ul>
+
+<p>When loading a new statusbar scripts, you'll need to also specify
+where you want to show it. Statusbar items can be modified with:</p>
+
+<ul>
+<li>10:52 STATUSBAR &lt;name&gt; ADD [-before | -after &lt;item&gt;] [-priority #] [-alignment left|right] &lt;item&gt;</li>
+<li>10:52 STATUSBAR &lt;name&gt; REMOVE &lt;item&gt;</li>
+</ul>
+
+<p>The item name with statusbar scripts is usually same as the script's
+name. Script's documentation should tell if this isn't the case. So, to
+add mail.pl before the window activity item (see the list with
+/STATUSBAR window), use: <strong>/STATUSBAR window ADD -before act
+mail</strong>.</p>
index 8739ff7d4cbf7f6f2b154f6d6641ef246fdb7a57..502d11d7fbc1f1dde72c203eed90552aef4e202d 100644 (file)
@@ -118,7 +118,8 @@ static void sig_connected(SERVER_REC *server)
 
        g_return_if_fail(IS_SERVER(server));
 
-       if (server->connrec->chatnet == NULL)
+       if (server->connrec->chatnet == NULL ||
+           server->session_reconnect)
                return;
 
        rec = chatnet_find(server->connrec->chatnet);
index 041d75a46b7707aeedbbee4dbdbdcb31ded6313b..b11064cb6b9c7b1dcd5f718ad492de665cfc1c2e 100644 (file)
@@ -59,6 +59,7 @@ void log_away_deinit(void);
 
 int irssi_gui;
 int irssi_init_finished;
+int reload_config;
 
 static char *irssi_dir, *irssi_config_file;
 static GSList *dialog_type_queue, *dialog_text_queue;
@@ -74,15 +75,20 @@ const char *get_irssi_config(void)
         return irssi_config_file;
 }
 
+static void sig_reload_config(int signo)
+{
+        reload_config = TRUE;
+}
+
 static void read_settings(void)
 {
 #ifndef WIN32
        static int signals[] = {
-               SIGHUP, SIGINT, SIGQUIT, SIGTERM,
+               SIGINT, SIGQUIT, SIGTERM,
                SIGALRM, SIGUSR1, SIGUSR2
        };
        static char *signames[] = {
-               "hup", "int", "quit", "term",
+               "int", "quit", "term",
                "alrm", "usr1", "usr2"
        };
 
@@ -95,6 +101,10 @@ static void read_settings(void)
        sigemptyset (&act.sa_mask);
        act.sa_flags = 0;
 
+       /* reload config on SIGHUP */
+        act.sa_handler = sig_reload_config;
+       sigaction(SIGHUP, &act, NULL);
+
        for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) {
                act.sa_handler = find_substr(ignores, signames[n]) ?
                        SIG_IGN : SIG_DFL;
index 6b7ec6218f25616d118377e8d5e567b04094b32e..74317166a13eede62a1714bc0a80d79620400eb7 100644 (file)
@@ -11,6 +11,7 @@
 
 extern int irssi_gui;
 extern int irssi_init_finished; /* TRUE after "irssi init finished" signal is sent */
+extern int reload_config; /* TRUE after received SIGHUP. */
 
 void core_init_paths(int argc, char *argv[]);
 
index 6be871132df4e3695416c166f15a5bf689345b9c..e53b01897b4938ddfe1ea3e092165160a26e9428 100644 (file)
@@ -415,8 +415,7 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
 #else
        hp = gethostbyname(addr);
        if (hp == NULL)
-                return -1;
-               //return h_errno;
+               return h_errno;
 
        ip4->family = AF_INET;
        memcpy(&ip4->ip, hp->h_addr, 4);
@@ -590,7 +589,7 @@ int is_ipv4_address(const char *host)
 int is_ipv6_address(const char *host)
 {
        while (*host != '\0') {
-               if (*host != ':' && !isxdigit(*host))
+               if (*host != ':' && !i_isxdigit(*host))
                        return 0;
                 host++;
        }
index 21bb6db49de7af40e3b9dc5cb045c6a4544a97de..f4aae6e7f219392a4774909ebd104bd890c003bc 100644 (file)
@@ -37,6 +37,8 @@ void query_init(QUERY_REC *query, int automatic)
         MODULE_DATA_INIT(query);
        query->type = module_get_uniq_id_str("WINDOW ITEM TYPE", "QUERY");
         query->destroy = (void (*) (WI_ITEM_REC *)) query_destroy;
+       query->last_unread_msg = time(NULL);
+
        if (query->server_tag != NULL) {
                query->server = server_find_tag(query->server_tag);
                if (query->server != NULL) {
index 12ef491cd1f72aa93d9324d2422e6fecd937fec6..fc08d2effe3851aece47ec3c50ee328702df7e2c 100644 (file)
@@ -4,6 +4,8 @@
 
 char *address;
 char *server_tag;
+time_t last_unread_msg;
+
 unsigned int unwanted:1; /* TRUE if the other side closed or
                            some error occured (DCC chats!) */
 unsigned int destroying:1;
index 499f1f919f1165f5ea358f800d13e4be4c60279f..2f3d15d1d22cb20ee6cfe0b0197dee932ba4ddd9 100644 (file)
@@ -186,12 +186,22 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
        server->connect_pipe[1] = NULL;
 
        /* figure out if we should use IPv4 or v6 address */
-       ip = iprec.error != 0 ? NULL : iprec.ip6.family == 0 ||
-               (server->connrec->family == AF_INET && iprec.ip4.family != 0) ?
-               &iprec.ip4 : &iprec.ip6;
-       if (iprec.ip4.family != 0 && server->connrec->family == 0 &&
-           !settings_get_bool("resolve_prefer_ipv6"))
-                ip = &iprec.ip4;
+       if (iprec.error != 0) {
+                /* error */
+               ip = NULL;
+       } else if (server->connrec->family == AF_INET) {
+               /* force IPv4 connection */
+               ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4;
+       } else if (server->connrec->family == AF_INET6) {
+               /* force IPv6 connection */
+               ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6;
+       } else {
+               /* pick the one that was found, or if both do it like
+                  /SET resolve_prefer_ipv6 says. */
+               ip = iprec.ip6.family != 0 &&
+                       settings_get_bool("resolve_prefer_ipv6") ?
+                       &iprec.ip6 : &iprec.ip4;
+       }
 
         conn = server->connrec;
        port = conn->proxy != NULL ? conn->proxy_port : conn->port;
@@ -209,15 +219,21 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
 
        if (handle == NULL) {
                /* failed */
-               if (iprec.error != 0 && net_hosterror_notfound(iprec.error)) {
+               if (ip == NULL && (iprec.error == 0 ||
+                                  net_hosterror_notfound(iprec.error))) {
                        /* IP wasn't found for the host, don't try to reconnect
                           back to this server */
                        server->dns_error = TRUE;
                }
 
-               if (iprec.error == 0) {
+               if (ip != NULL) {
                        /* connect() failed */
                        errormsg = g_strerror(errno);
+               } else if (iprec.error == 0) {
+                       /* forced IPv4 or IPv6 address but it wasn't found */
+                       errormsg = server->connrec->family == AF_INET ?
+                               "IPv4 address not found for host" :
+                               "IPv6 address not found for host";
                } else {
                        /* gethostbyname() failed */
                        errormsg = iprec.errorstr != NULL ? iprec.errorstr :
index 0248f13e07b6ed2dc8fc02bcfa03662042d27647..7e7b0afa1cf21567fa2868de2f454c88d251aefb 100644 (file)
@@ -146,6 +146,8 @@ static void session_save_channel(CHANNEL_REC *channel, CONFIG_REC *config,
 
        config_node_set_str(config, node, "name", channel->name);
        config_node_set_str(config, node, "topic", channel->topic);
+       config_node_set_str(config, node, "topic_by", channel->topic_by);
+       config_node_set_int(config, node, "topic_time", channel->topic_time);
        config_node_set_str(config, node, "key", channel->key);
 
        signal_emit("session save channel", 3, channel, config, node);
@@ -220,6 +222,8 @@ static void session_restore_channel(SERVER_REC *server, CONFIG_NODE *node)
 
        channel = CHAT_PROTOCOL(server)->channel_create(server, name, TRUE);
        channel->topic = g_strdup(config_node_get_str(node, "topic", NULL));
+       channel->topic_by = g_strdup(config_node_get_str(node, "topic_by", NULL));
+       channel->topic_time = config_node_get_int(node, "topic_time", 0);
         channel->key = g_strdup(config_node_get_str(node, "key", NULL));
         channel->session_rejoin = TRUE;
 
index 64c5214c74d77f7b5447f51153647151c47e80a3..01b8aced0781f368e5691d0531d9f63b929a426b 100644 (file)
@@ -585,7 +585,12 @@ static void cmd_cycle(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
        joindata = chanrec->get_join_data(chanrec);
        window_bind_add(window_item_window(chanrec),
                        chanrec->server->tag, chanrec->name);
-        channel_destroy(chanrec);
+
+       /* FIXME: kludgy kludgy... and it relies on channel not
+          being destroyed immediately.. */
+       signal_emit("command part", 3, data, server, item);
+        chanrec->left = TRUE;
+       channel_destroy(chanrec);
 
        server->channels_join(server, joindata, FALSE);
        g_free(joindata);
index cf7938eaf0ec533d0efb381e0e88dad483f7ef48..d50b23e501bb5d54194bcf64945b43a5d6363d10 100644 (file)
@@ -136,8 +136,10 @@ static void cmd_cat(const char *data)
                recvlen = read(f, tmpbuf, sizeof(tmpbuf));
 
                ret = line_split(tmpbuf, recvlen, &str, &buffer);
-               if (ret > 0)
-                       printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s", str);
+               if (ret > 0) {
+                       printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP |
+                                 MSGLEVEL_NEVER, "%s", str);
+               }
        } while (ret > 0);
        line_split_free(buffer);
 
index 770f4a4e2848c1ea41003cb0856e76a46bb907b3..c1fb979d3402b9060a46f797ed7d728f7a33f185 100644 (file)
@@ -22,6 +22,7 @@
 #include "signals.h"
 #include "levels.h"
 #include "ignore.h"
+#include "servers.h"
 
 static void sig_message_public(SERVER_REC *server, const char *msg,
                               const char *nick, const char *address,
@@ -64,7 +65,9 @@ static void sig_message_kick(SERVER_REC *server, const char *channel,
                             const char *nick, const char *kicker,
                             const char *address, const char *reason)
 {
-       if (ignore_check(server, kicker, address,
+        /* never ignore if you were kicked */
+       if (g_strcasecmp(nick, server->nick) != 0 &&
+           ignore_check(server, kicker, address,
                         channel, reason, MSGLEVEL_KICKS))
                signal_stop();
 }
index 44d7ef012bdea1da61cdea9539287f4961491e74..40df4ec99af671fcf0665ae566834878feafec7f 100644 (file)
@@ -275,32 +275,28 @@ static void cmd_query(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
        cmd_params_free(free_arg);
 }
 
-static int window_has_query(WINDOW_REC *window)
+static void window_reset_query_timestamps(WINDOW_REC *window)
 {
        GSList *tmp;
 
-       g_return_val_if_fail(window != NULL, FALSE);
+       if (window == NULL)
+                return;
 
        for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
-               if (IS_QUERY(tmp->data))
-                       return TRUE;
-       }
+               QUERY_REC *query = QUERY(tmp->data);
 
-       return FALSE;
+               if (query != NULL)
+                        query->last_unread_msg = time(NULL);
+       }
 }
 
 static void sig_window_changed(WINDOW_REC *window, WINDOW_REC *old_window)
 {
-       if (query_auto_close <= 0)
-               return;
-
-       /* reset the window's last_line timestamp so that query doesn't get
-          closed immediately after switched to the window, or after changed
-          to some other window from it */
-       if (window != NULL && window_has_query(window))
-               window->last_line = time(NULL);
-       if (old_window != NULL && window_has_query(old_window))
-               old_window->last_line = time(NULL);
+       /* reset the queries last_unread_msg so query doesn't get closed
+          immediately after switched to the window, or after changed to
+          some other window from it */
+        window_reset_query_timestamps(window);
+        window_reset_query_timestamps(old_window);
 }
 
 static int sig_query_autoclose(void)
@@ -315,8 +311,8 @@ static int sig_query_autoclose(void)
 
                next = tmp->next;
                window = window_item_window((WI_ITEM_REC *) rec);
-               if (window != active_win && rec->data_level == 0 &&
-                   now-window->last_line > query_auto_close)
+               if (window != active_win && rec->data_level < DATA_LEVEL_MSG &&
+                   now-rec->last_unread_msg > query_auto_close)
                        query_destroy(rec);
        }
         return 1;
@@ -325,8 +321,14 @@ static int sig_query_autoclose(void)
 static void sig_message_private(SERVER_REC *server, const char *msg,
                                const char *nick, const char *address)
 {
+       QUERY_REC *query;
+
        /* create query window if needed */
-       privmsg_get_query(server, nick, FALSE, MSGLEVEL_MSGS);
+       query = privmsg_get_query(server, nick, FALSE, MSGLEVEL_MSGS);
+
+       /* reset the query's last_unread_msg timestamp */
+        if (query != NULL)
+               query->last_unread_msg = time(NULL);
 }
 
 static void read_settings(void)
index 985d05c4895ae7f191aa7fc78ca91aa2421599d4..fe76427b466e42d12ca455ba51be5e52b20ad294 100644 (file)
@@ -238,24 +238,26 @@ char *window_get_active_name(WINDOW_REC *window)
        return window->name;
 }
 
+#define WINDOW_LEVEL_MATCH(window, server, level) \
+       (((window)->level & level) && \
+        (server == NULL || (window)->active_server == server))
+
 WINDOW_REC *window_find_level(void *server, int level)
 {
-       WINDOW_REC *match;
        GSList *tmp;
 
-       match = NULL;
+        /* prefer active window if possible */
+       if (WINDOW_LEVEL_MATCH(active_win, server, level))
+                return active_win;
+
        for (tmp = windows; tmp != NULL; tmp = tmp->next) {
                WINDOW_REC *rec = tmp->data;
 
-               if ((server == NULL || rec->active_server == server) &&
-                   (rec->level & level)) {
-                       if (server == NULL || rec->active_server == server)
-                               return rec;
-                       match = rec;
-               }
+               if (WINDOW_LEVEL_MATCH(rec, server, level))
+                        return rec;
        }
 
-       return match;
+       return NULL;
 }
 
 WINDOW_REC *window_find_closest(void *server, const char *name, int level)
index 8991164a8597c9177f2b2af11defa112fbabf078..e014583c617e61ebbf0fc775cdc86db2c292b215 100644 (file)
@@ -549,6 +549,31 @@ char *format_add_linestart(const char *text, const char *linestart)
         return ret;
 }
 
+char *format_add_lineend(const char *text, const char *linestart)
+{
+       GString *str;
+       char *ret;
+
+       if (linestart == NULL)
+               return g_strdup(text);
+
+       if (strchr(text, '\n') == NULL)
+               return g_strconcat(text, linestart, NULL);
+
+       str = g_string_new(NULL);
+       while (*text != '\0') {
+               if (*text == '\n')
+                       g_string_append(str, linestart);
+               g_string_append_c(str, *text);
+               text++;
+       }
+       g_string_append(str, linestart);
+
+       ret = str->str;
+       g_string_free(str, FALSE);
+        return ret;
+}
+
 #define LINE_START_IRSSI_LEVEL \
        (MSGLEVEL_CLIENTERROR | MSGLEVEL_CLIENTNOTICE)
 
@@ -729,8 +754,10 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
                        flags |= GUI_PRINT_FLAG_REVERSE;
                        break;
                default:
-                       if (num >= 30 && num <= 37)
+                       if (num >= 30 && num <= 37) {
+                               if (fg == -1) fg = 0;
                                fg = (fg & 0xf8) | ansitab[num-30];
+                       }
                        if (num >= 40 && num <= 47) {
                                if (bg == -1) bg = 0;
                                bg = (bg & 0xf8) | ansitab[num-40];
@@ -875,8 +902,10 @@ char *strip_codes(const char *input)
                         }
                }
 
-               if (*p == 27 && p[1] != '\0')
+               if (*p == 27 && p[1] != '\0') {
+                        p++;
                        p = get_ansi_color(current_theme, p, NULL, NULL, NULL);
+               }
 
                 if (!IS_COLOR_CODE(*p))
                         *out++ = *p;   
@@ -889,13 +918,17 @@ char *strip_codes(const char *input)
 /* send a fully parsed text string for GUI to print */
 void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
 {
+        THEME_REC *theme;
        char *dup, *str, *ptr, type;
        int fgcolor, bgcolor;
        int flags;
 
+        theme = dest->window != NULL && dest->window->theme != NULL ?
+               dest->window->theme : current_theme;
+
        dup = str = g_strdup(text);
 
-       flags = 0; fgcolor = -1; bgcolor = -1;
+       flags = 0; fgcolor = theme->default_color; bgcolor = -1;
        while (*str != '\0') {
                 type = '\0';
                for (ptr = str; *ptr != '\0'; ptr++) {
@@ -980,7 +1013,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
                                break;
                        }
                        case FORMAT_STYLE_DEFAULTS:
-                               fgcolor = bgcolor = -1;
+                                fgcolor = theme->default_color;
+                               bgcolor = -1;
                                flags &= GUI_PRINT_FLAG_INDENT;
                                break;
                        case FORMAT_STYLE_CLRTOEOL:
@@ -1020,7 +1054,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
                        break;
                case 15:
                        /* remove all styling */
-                       fgcolor = bgcolor = -1;
+                       fgcolor = theme->default_color;
+                       bgcolor = -1;
                        flags &= GUI_PRINT_FLAG_INDENT;
                        break;
                case 22:
@@ -1036,9 +1071,7 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
                case 27:
                        /* ansi color code */
                        ptr = (char *)
-                               get_ansi_color(dest->window == NULL || dest->window->theme == NULL ?
-                                              current_theme : dest->window->theme,
-                                              ptr,
+                               get_ansi_color(theme, ptr,
                                               hide_text_style ? NULL : &fgcolor,
                                               hide_text_style ? NULL : &bgcolor,
                                               hide_text_style ? NULL : &flags);
index b98d7be75787e927fa573c58e74df9ae42e4695f..4d459c1cf89c526506d9844745a317f0a2474c7c 100644 (file)
@@ -86,9 +86,10 @@ char *format_get_text_theme_charargs(THEME_REC *theme, const char *module,
                                     TEXT_DEST_REC *dest, int formatnum,
                                     char **args);
 
-/* add `linestart' to start of each line in `text'. `text' may contain
+/* add `linestart' to start/end of each line in `text'. `text' may contain
    multiple lines separated with \n. */
 char *format_add_linestart(const char *text, const char *linestart);
+char *format_add_lineend(const char *text, const char *linestart);
 
 /* return the "-!- " text at the start of the line */
 char *format_get_level_tag(THEME_REC *theme, TEXT_DEST_REC *dest);
index ac68200196baec1863f5a8dd99f239613724a528..e622f973ce769b8809f052e1f804c3d091215676 100644 (file)
@@ -683,7 +683,7 @@ static void cmd_bind(const char *data)
        command_id = strchr(settings_get_str("cmdchars"), *id) != NULL;
        if (command_id) {
                /* using shortcut to command id */
-               keydata = g_strconcat(id, " ", keydata, NULL);
+               keydata = g_strconcat(id+1, " ", keydata, NULL);
                id = "command";
        }
 
index 2f6c19ea80b6c601f1c260ce303050e4805eec62..369842196f1199b749248fce168bb9e211069f46 100644 (file)
@@ -158,13 +158,16 @@ void printformat_module_gui(const char *module, int formatnum, ...)
 
 static void print_line(TEXT_DEST_REC *dest, const char *text)
 {
+        THEME_REC *theme;
        char *str, *tmp, *stripped;
 
        g_return_if_fail(dest != NULL);
        g_return_if_fail(text != NULL);
 
-       tmp = format_get_level_tag(window_get_theme(dest->window), dest);
-       str = format_add_linestart(text, tmp);
+        theme = window_get_theme(dest->window);
+       tmp = format_get_level_tag(theme, dest);
+       str = !theme->info_eol ? format_add_linestart(text, tmp) :
+               format_add_lineend(text, tmp);
        g_free_not_null(tmp);
 
        /* send both the formatted + stripped (for logging etc.) */
@@ -408,6 +411,7 @@ static void msg_beep_check(TEXT_DEST_REC *dest)
 
 static void sig_print_text(TEXT_DEST_REC *dest, const char *text)
 {
+        THEME_REC *theme;
        char *str, *tmp;
 
        g_return_if_fail(dest != NULL);
@@ -421,9 +425,11 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text)
 
        /* add timestamp/server tag here - if it's done in print_line()
           it would be written to log files too */
-       tmp = format_get_line_start(window_get_theme(dest->window),
-                                   dest, time(NULL));
-       str = format_add_linestart(text, tmp);
+        theme = window_get_theme(dest->window);
+       tmp = format_get_line_start(theme, dest, time(NULL));
+       str = !theme->info_eol ? format_add_linestart(text, tmp) :
+               format_add_lineend(text, tmp);
+
        g_free_not_null(tmp);
 
        format_send_to_gui(dest, str);
index 514dd377ba78a0e2c4ec171622efef087345bf0d..ec4a994af44a1f450b6df1822c22d0625098b2d1 100644 (file)
@@ -221,7 +221,7 @@ static void theme_format_append_next(THEME_REC *theme, GString *str,
        }
 
        index = (flags & EXPAND_FLAG_IGNORE_REPLACES) ? -1 :
-               theme->replace_keys[(int) chr];
+               theme->replace_keys[(int) (unsigned char) chr];
        if (index == -1)
                g_string_append_c(str, chr);
        else {
@@ -542,7 +542,7 @@ static void theme_read_replaces(CONFIG_REC *config, THEME_REC *theme)
 
                if (node->key != NULL && node->value != NULL) {
                        for (p = node->key; *p != '\0'; p++)
-                                theme->replace_keys[(int) *p] = index;
+                                theme->replace_keys[(int) (unsigned char) *p] = index;
 
                        theme->replace_values =
                                g_slist_append(theme->replace_values,
@@ -844,6 +844,8 @@ static int theme_read(THEME_REC *theme, const char *path, const char *data)
 
        theme->default_color =
                config_get_int(config, NULL, "default_color", -1);
+       theme->info_eol = config_get_bool(config, NULL, "info_eol", FALSE);
+
        /* FIXME: remove after 0.7.99 */
        if (theme->default_color == 0 &&
            config_get_int(config, NULL, "default_real_color", -1) != -1)
@@ -1157,6 +1159,8 @@ static void sig_complete_format(GList **list, WINDOW_REC *window,
 
        words = 0;
        do {
+                ptr++;
+
                words++;
                 ptr = strchr(ptr, ' ');
        } while (ptr != NULL);
index 59d2810ad6550be38e377c6369dbae8bcfc60a26..3ef7cb924348a8a32be64477845a1d172dfb4afe 100644 (file)
@@ -18,6 +18,9 @@ typedef struct {
        int default_color; /* default color to use with text with default
                              background. default is -1 which means the
                              default color set by terminal */
+       unsigned int info_eol:1; /* show the timestamp/servertag at the
+                                   end of the line, not at beginning */
+
        GHashTable *modules;
 
         int replace_keys[256]; /* index to replace_values for each char */
index 1148d076607f7e3c9b739522097a6d65d0d3701a..e7e5fcc5f12ba92e003902aa57b4bd92244b0f29 100644 (file)
@@ -37,7 +37,8 @@ static void entry_text_grow(GUI_ENTRY_REC *entry, int grow_size)
                return;
 
        entry->text_alloc = nearest_power(entry->text_alloc+grow_size);
-       entry->text = g_realloc(entry->text, entry->text_alloc);
+       entry->text = g_realloc(entry->text,
+                               sizeof(unichar) * entry->text_alloc);
 }
 
 GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
@@ -323,6 +324,9 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
 
        g_return_val_if_fail(entry != NULL, NULL);
 
+       if (entry->cutbuffer == NULL)
+                return NULL;
+
        buf = g_malloc(entry->cutbuffer_len*6 + 1);
        if (entry->utf8)
                utf16_to_utf8(entry->cutbuffer, buf);
@@ -333,23 +337,25 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
        return buf;
 }
 
-void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
+void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer)
 {
         g_return_if_fail(entry != NULL);
 
        if (entry->pos < size)
                return;
 
-        /* put erased text to cutbuffer */
-       if (entry->cutbuffer == NULL || entry->cutbuffer_len < size) {
-               g_free(entry->cutbuffer);
-               entry->cutbuffer = g_new(unichar, size+1);
-       }
+       if (update_cutbuffer) {
+               /* 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));
+               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 */
@@ -390,7 +396,7 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
        }
        if (to > 0) to++;
 
-        gui_entry_erase(entry, entry->pos-to);
+        gui_entry_erase(entry, entry->pos-to, TRUE);
 }
 
 void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
@@ -416,7 +422,7 @@ void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
 
         size = to-entry->pos;
        entry->pos = to;
-        gui_entry_erase(entry, size);
+        gui_entry_erase(entry, size, TRUE);
 }
 
 void gui_entry_transpose_chars(GUI_ENTRY_REC *entry)
index b54ed0759ec346677052d1b711b34feb42e103d4..2ad38041fe719d34a8d14520c3ab366ff4a532aa 100644 (file)
@@ -39,7 +39,7 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str);
 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(GUI_ENTRY_REC *entry, int size, int update_cutbuffer);
 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);
 
index 5aa8dddcaa886e76168e0df6775fc5c3d73b7c20..429937a52c1bc79a6b73306267e9967816df7b0d 100644 (file)
@@ -145,10 +145,12 @@ static void get_colors(int flags, int *fg, int *bg, int *attr)
                   colors wrap to 0, 1, ... */
                 if (*bg >= 0) *bg = mirc_colors[*bg % 16];
                if (*fg >= 0) *fg = mirc_colors[*fg % 16];
+               if (settings_get_bool("mirc_blink_fix"))
+                       *bg &= ~0x08;
        }
 
        if (*fg < 0 || *fg > 15)
-               *fg = current_theme->default_color;
+               *fg = -1;
        if (*bg < 0 || *bg > 15)
                 *bg = -1;
 
index 96e7e074b4d58db8dbe1991fc8c1907e8bb30cc2..145273b724e1f83f7df522b4a79873df0e2c29df 100644 (file)
@@ -48,6 +48,7 @@ typedef struct {
 
 static KEYBOARD_REC *keyboard;
 static ENTRY_REDIRECT_REC *redir;
+static int escape_next_key;
 
 static int readtag;
 static time_t idle_time;
@@ -161,8 +162,9 @@ void handle_key(unichar key)
                str[utf16_char_to_utf8(key, str)] = '\0';
        }
 
-       if (!key_pressed(keyboard, str)) {
-                /* key wasn't used for anything, print it */
+       if (escape_next_key || !key_pressed(keyboard, str)) {
+               /* key wasn't used for anything, print it */
+                escape_next_key = FALSE;
                gui_entry_insert_char(active_entry, key);
        }
 }
@@ -173,7 +175,7 @@ static void key_send_line(void)
         char *str, *add_history;
 
        str = gui_entry_get_text(active_entry);
-       if (str == NULL || *str == '\0') {
+       if (str == NULL || (*str == '\0' && redir == NULL)) {
                 g_free(str);
                return;
        }
@@ -278,7 +280,7 @@ static void key_forward_to_space(void)
 static void key_erase_line(void)
 {
        gui_entry_set_pos(active_entry, active_entry->text_len);
-       gui_entry_erase(active_entry, active_entry->text_len);
+       gui_entry_erase(active_entry, active_entry->text_len, TRUE);
 }
 
 static void key_erase_to_beg_of_line(void)
@@ -286,7 +288,7 @@ static void key_erase_to_beg_of_line(void)
        int pos;
 
        pos = gui_entry_get_pos(active_entry);
-       gui_entry_erase(active_entry, pos);
+       gui_entry_erase(active_entry, pos, TRUE);
 }
 
 static void key_erase_to_end_of_line(void)
@@ -295,7 +297,7 @@ static void key_erase_to_end_of_line(void)
 
        pos = gui_entry_get_pos(active_entry);
        gui_entry_set_pos(active_entry, active_entry->text_len);
-       gui_entry_erase(active_entry, active_entry->text_len - pos);
+       gui_entry_erase(active_entry, active_entry->text_len - pos, TRUE);
 }
 
 static void key_yank_from_cutbuffer(void)
@@ -303,8 +305,10 @@ static void key_yank_from_cutbuffer(void)
        char *cutbuffer;
 
         cutbuffer = gui_entry_get_cutbuffer(active_entry);
-       if (cutbuffer != NULL)
+       if (cutbuffer != NULL) {
                gui_entry_insert_text(active_entry, cutbuffer);
+                g_free(cutbuffer);
+       }
 }
 
 static void key_transpose_characters(void)
@@ -316,13 +320,13 @@ static void key_delete_character(void)
 {
        if (gui_entry_get_pos(active_entry) < active_entry->text_len) {
                gui_entry_move_pos(active_entry, 1);
-               gui_entry_erase(active_entry, 1);
+               gui_entry_erase(active_entry, 1, FALSE);
        }
 }
 
 static void key_backspace(void)
 {
-       gui_entry_erase(active_entry, 1);
+       gui_entry_erase(active_entry, 1, FALSE);
 }
 
 static void key_delete_previous_word(void)
@@ -519,6 +523,11 @@ static void key_next_window_item(void)
        }
 }
 
+static void key_escape(void)
+{
+        escape_next_key = TRUE;
+}
+
 static void key_insert_text(const char *data)
 {
        char *str;
@@ -566,6 +575,7 @@ void gui_readline_init(void)
        char *key, data[MAX_INT_STRLEN];
        int n;
 
+        escape_next_key = FALSE;
        redir = NULL;
        idle_time = time(NULL);
         input_listen_init(STDIN_FILENO);
@@ -673,6 +683,7 @@ void gui_readline_init(void)
        key_bind("scroll_end", "End of the window", "", NULL, (SIGNAL_FUNC) key_scroll_end);
 
         /* inserting special input characters to line.. */
+       key_bind("escape_char", "Escape the next keypress", NULL, NULL, (SIGNAL_FUNC) key_escape);
        key_bind("insert_text", "Append text to line", NULL, NULL, (SIGNAL_FUNC) key_insert_text);
 
         /* autoreplaces */
@@ -743,6 +754,7 @@ void gui_readline_deinit(void)
        key_unbind("scroll_start", (SIGNAL_FUNC) key_scroll_start);
        key_unbind("scroll_end", (SIGNAL_FUNC) key_scroll_end);
 
+       key_unbind("escape_char", (SIGNAL_FUNC) key_escape);
        key_unbind("insert_text", (SIGNAL_FUNC) key_insert_text);
        key_unbind("change_window", (SIGNAL_FUNC) key_change_window);
        key_unbind("stop_irc", (SIGNAL_FUNC) key_sig_stop);
index 7fcd910333b3ad0beb6cf69f00e91c63c88a9ab4..03a8270512a0f2070a356c9b4a10e69e52b3c846 100644 (file)
@@ -1035,14 +1035,17 @@ static void cmd_window_move_down(void)
                window_reparent(active_win, rec);
 }
 
-static void windows_print_sticky(MAIN_WINDOW_REC *win)
+static void windows_print_sticky(WINDOW_REC *win)
 {
+        MAIN_WINDOW_REC *mainwin;
         GSList *tmp, *list;
        GString *str;
 
+        mainwin = WINDOW_MAIN(win);
+
         /* convert to string */
        str = g_string_new(NULL);
-       list = get_sticky_windows_sorted(win);
+       list = get_sticky_windows_sorted(mainwin);
        for (tmp = list; tmp != NULL; tmp = tmp->next) {
                WINDOW_REC *rec = tmp->data;
 
@@ -1051,15 +1054,24 @@ static void windows_print_sticky(MAIN_WINDOW_REC *win)
         g_string_truncate(str, str->len-2);
         g_slist_free(list);
 
-       printformat_window(win->active, MSGLEVEL_CLIENTCRAP,
+       printformat_window(win, MSGLEVEL_CLIENTCRAP,
                           TXT_WINDOW_INFO_STICKY, str->str);
         g_string_free(str, TRUE);
 }
 
 static void sig_window_print_info(WINDOW_REC *win)
 {
+       GUI_WINDOW_REC *gui;
+
+       gui = WINDOW_GUI(win);
+       if (gui->use_scroll) {
+               printformat_window(win, MSGLEVEL_CLIENTCRAP,
+                                  TXT_WINDOW_INFO_SCROLL,
+                                  gui->scroll ? "yes" : "no");
+       }
+
        if (WINDOW_MAIN(win)->sticky_windows)
-                windows_print_sticky(WINDOW_MAIN(win));
+                windows_print_sticky(win);
 }
 
 void mainwindows_init(void)
index 7584a8c03c13ea544a28bc68b67c9a10e99f7e71..f236d900018ccab5e66bc257b8e3ce1b97ce2330 100644 (file)
@@ -46,6 +46,7 @@ FORMAT_REC gui_text_formats[] =
        { "window_set_sticky", "Window set sticky", 0 },
        { "window_unset_sticky", "Window is not sticky anymore", 0 },
        { "window_info_sticky", "Sticky  : $0", 1, { 0 } },
+       { "window_info_scroll", "Scroll  : $0", 1, { 0 } },
        { "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 } },
 
index 88c670001c0bed6f6765b127beb783b650f080fe..c3607311dd3f3c9bcdffeba1c8c0688dc6ecc2b2 100644 (file)
@@ -21,7 +21,8 @@ enum {
         TXT_WINDOW_NOT_STICKY,
         TXT_WINDOW_SET_STICKY,
        TXT_WINDOW_UNSET_STICKY,
-        TXT_WINDOW_INFO_STICKY,
+       TXT_WINDOW_INFO_STICKY,
+        TXT_WINDOW_INFO_SCROLL,
         TXT_WINDOW_SCROLL,
         TXT_WINDOW_SCROLL_UNKNOWN,
 
index f8042c5c3eab3718b12f0c0ede4ed90e196358c0..fc1d526fb820130e4a4f79c6a11737c67ca2a7d2 100644 (file)
@@ -389,6 +389,8 @@ void statusbar_items_init(void)
        statusbar_item_register("window_empty", NULL, item_window_empty);
        statusbar_item_register("prompt", NULL, item_window_active);
        statusbar_item_register("prompt_empty", NULL, item_window_empty);
+       statusbar_item_register("topic", NULL, item_window_active);
+       statusbar_item_register("topic_empty", NULL, item_window_empty);
        statusbar_item_register("lag", NULL, item_lag);
        statusbar_item_register("act", NULL, item_act);
        statusbar_item_register("more", NULL, item_more);
index 7f3bbe3c258fb04b9682171d708236904198c4a6..9d39ede790e8c68bbe83a94df7d975d33e2ba364 100644 (file)
@@ -653,6 +653,32 @@ const char *statusbar_item_get_value(SBAR_ITEM_REC *item)
         return value;
 }
 
+static char *reverse_controls(const char *str)
+{
+       GString *out;
+        char *ret;
+
+       out = g_string_new(NULL);
+
+       while (*str != '\0') {
+               if ((unsigned char) *str < 32 ||
+                   (term_type == TERM_TYPE_8BIT &&
+                    (unsigned char) (*str & 0x7f) < 32)) {
+                       /* control char */
+                       g_string_sprintfa(out, "%%8%c%%8",
+                                         'A'-1 + (*str & 0x7f));
+               } else {
+                       g_string_append_c(out, *str);
+               }
+
+               str++;
+       }
+
+       ret = out->str;
+        g_string_free(out, FALSE);
+       return ret;
+}
+
 void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
                                    const char *str, const char *data,
                                    int escape_vars)
@@ -693,6 +719,11 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
        tmpstr = strip_codes(tmpstr2);
         g_free(tmpstr2);
 
+       /* show all control chars reversed */
+       tmpstr2 = reverse_controls(tmpstr);
+       g_free(tmpstr);
+
+       tmpstr = tmpstr2;
        if (get_size_only) {
                item->min_size = item->max_size = format_get_length(tmpstr);
        } else {
index e09e9c20481fafd7bdd7ebff330e89ab17aa6402..4e9781fe744f405efd4c786d97a74029086d7a91 100644 (file)
@@ -379,14 +379,21 @@ void term_addch(TERM_WINDOW *window, int chr)
        if (term_detached) return;
 
        if (vcmove) term_move_real();
-        term_printed_text(1);
+
+       /* With UTF-8, move cursor only if this char is either single-byte
+          (8. bit on) or beginning of multibyte (7+8 bits on) */
+       if (term_type != TERM_TYPE_UTF8 ||
+           (chr & 0x80) == 0 || (chr & 0x40) == 0) {
+               term_printed_text(1);
+       }
+
        if (vcy != term_height || vcx != 0)
                putc(chr, window->term->out);
 }
 
 static void term_addch_utf8(TERM_WINDOW *window, unichar chr)
 {
-       unsigned char buf[10];
+       char buf[10];
        int i, len;
 
        len = utf16_char_to_utf8(chr, buf);
@@ -630,9 +637,9 @@ int term_gets(unichar *buffer, int size)
 
                if (i >= term_inbuf_pos)
                        term_inbuf_pos = 0;
-               else {
+               else if (i > 0) {
                        memmove(term_inbuf+i, term_inbuf, term_inbuf_pos-i);
-                        term_inbuf_pos = i;
+                        term_inbuf_pos -= i;
                }
        }
 
index cc49103f16a8240a124f2faa72a57e9de794dee0..a50fc8a31a46f08272d4e646984e0113964e01aa 100644 (file)
@@ -138,6 +138,7 @@ 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", "mirc_blink_fix", FALSE);
         settings_add_str("lookandfeel", "term_type", "8bit");
 
        force_colors = FALSE;
index ce35c52e9bfb3b214514cfb16f197f6d349e21c9..14d3f4dca3a559a65b3c1a864de815a414b27710 100644 (file)
@@ -5,7 +5,7 @@
 package Irssi;
 
 use strict;
-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+use vars qw($VERSION $in_irssi @ISA @EXPORT @EXPORT_OK);
 
 sub VERSION {
   my $version = $_[1];
@@ -18,6 +18,10 @@ sub EXPORT_ALL () {
   @EXPORT_OK = grep { /[a-z]/ && defined *{$_}{CODE} } keys %Irssi::;
 }
 
+sub in_irssi {
+  return $in_irssi;
+}
+
 $VERSION = "0.9";
 
 require Exporter;
@@ -35,14 +39,25 @@ require DynaLoader;
 );
 @EXPORT_OK = qw();
 
-bootstrap Irssi $VERSION if (!Irssi::Core::is_static());
+my $static = 0;
+
+eval {
+  $static = Irssi::Core::is_static();
+};
+$in_irssi = $@ ? 0 : 1;
 
-@Irssi::Channel::ISA = qw(Irssi::Windowitem);
-@Irssi::Query::ISA = qw(Irssi::Windowitem);
+if (!in_irssi()) {
+  print "Warning: This script should be run inside irssi\n";
+} else {
+  bootstrap Irssi $VERSION if (!$static);
 
-Irssi::init();
+  @Irssi::Channel::ISA = qw(Irssi::Windowitem);
+  @Irssi::Query::ISA = qw(Irssi::Windowitem);
 
-Irssi::EXPORT_ALL();
+  Irssi::init();
+
+  Irssi::EXPORT_ALL();
+}
 
 1;
 
index 76fa3f3fbe1b4792dfd5d7e302d7a1bd77ef424c..cb5f09877adde79a217e4c6bab4c1daeafc85cbd 100644 (file)
@@ -340,6 +340,9 @@ void perl_channel_fill_hash(HV *hv, CHANNEL_REC *channel)
 
        perl_window_item_fill_hash(hv, (WI_ITEM_REC *) channel);
 
+        if (channel->ownnick != NULL)
+               hv_store(hv, "ownnick", 7, iobject_bless(channel->ownnick), 0);
+
        hv_store(hv, "topic", 5, new_pv(channel->topic), 0);
        hv_store(hv, "topic_by", 8, new_pv(channel->topic_by), 0);
        hv_store(hv, "topic_time", 10, newSViv(channel->topic_time), 0);
index 8d2170a01be89e981e3c08e2fd9b75eea72ecec8..ccdbb345619c414f13f0bc521f617163bf90aea7 100644 (file)
@@ -165,7 +165,7 @@ void silc_idcache_free(SilcIDCache cache);
  * SYNOPSIS
  *
  *    bool silc_idcache_add(SilcIDCache cache, char *name, void *id, 
- *                          void *context, int expire);
+ *                          void *context, int expire, SilcIDCacheEntry *ret);
  *
  * DESCRIPTION
  *