Added SILC Thread Queue API
[runtime.git] / apps / irssi / src / fe-common / core / fe-messages.c
index 4b4e4db4f758776a561bdc1cd9324b8354f604b8..3080b99caa16b4ffb4b9e2f28e51990028e106b1 100644 (file)
@@ -31,6 +31,7 @@
 #include "channels.h"
 #include "nicklist.h"
 #include "ignore.h"
+#include "recode.h"
 
 #include "window-items.h"
 #include "fe-queries.h"
 #include "printtext.h"
 
 #define ishighalnum(c) ((unsigned char) (c) >= 128 || i_isalnum(c))
+#define isnickchar(a) \
+       (i_isalnum(a) || (a) == '`' || (a) == '-' || (a) == '_' || \
+       (a) == '[' || (a) == ']' || (a) == '{' || (a) == '}' || \
+       (a) == '|' || (a) == '\\' || (a) == '^')
 
-static GHashTable *printnicks;
+GHashTable *printnicks;
 
 /* convert _underlined_ and *bold* words (and phrases) to use real
    underlining or bolding */
@@ -67,7 +72,7 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
 
                /* check that the beginning marker starts a word, and
                   that the matching end marker ends a word */
-               if ((pos > 0 && !i_isspace(bgn[-1])) || !ishighalnum(bgn[1]))
+               if ((pos > 0 && bgn[-1] != ' ') || !ishighalnum(bgn[1]))
                        continue;
                if ((end = strchr(bgn+1, *bgn)) == NULL)
                        continue;
@@ -80,12 +85,25 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
                           use emphasis on them. */
                        int found;
                         char c;
+                       char *end2; 
 
+                       /* check if _foo_ is a nick */
                        c = end[1];
                         end[1] = '\0';
                         found = nicklist_find(CHANNEL(item), bgn) != NULL;
                        end[1] = c;
                        if (found) continue;
+                       
+                       /* check if the whole 'word' (e.g. "_foo_^") is a nick
+                          in "_foo_^ ", end will be the second _, end2 the ^ */
+                       end2 = end;
+                       while (isnickchar(end2[1]))
+                               end2++;
+                       c = end2[1];
+                       end2[1] = '\0';
+                       found = nicklist_find(CHANNEL(item), bgn) != NULL;
+                       end2[1] = c;
+                       if (found) continue;
                }
 
                /* allow only *word* emphasis, not *multiple words* */
@@ -116,12 +134,19 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
 static char *channel_get_nickmode_rec(NICK_REC *nickrec)
 {
         char *emptystr;
+       static char nickmode[2]; /* FIXME: bad */
 
        if (!settings_get_bool("show_nickmode"))
                 return "";
 
         emptystr = settings_get_bool("show_nickmode_empty") ? " " : "";
 
+       if (nickrec != NULL && nickrec->other) {
+               nickmode[0] = nickrec->other;
+               nickmode[1] = '\0';
+               return nickmode;
+       }
+
        return nickrec == NULL ? emptystr :
                nickrec->op ? "@" :
                nickrec->halfop ? "%" :
@@ -145,6 +170,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
        const char *nickmode, *printnick;
        int for_me, print_channel, level;
        char *color, *freemsg = NULL;
+       HILIGHT_REC *hilight;
 
        /* NOTE: this may return NULL if some channel is just closed with
           /WINDOW CLOSE and server still sends the few last messages */
@@ -152,9 +178,11 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
        if (nickrec == NULL && chanrec != NULL)
                 nickrec = nicklist_find(chanrec, nick);
 
-       for_me = nick_match_msg(chanrec, msg, server->nick);
-       color = for_me ? NULL :
+       for_me = !settings_get_bool("hilight_nick_matches") ? FALSE :
+               nick_match_msg(chanrec, msg, server->nick);
+       hilight = for_me ? NULL :
                hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
+       color = (hilight == NULL) ? NULL : hilight_get_color(hilight);
 
        print_channel = chanrec == NULL ||
                !window_item_is_active((WI_ITEM_REC *) chanrec);
@@ -163,7 +191,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
                print_channel = TRUE;
 
        level = MSGLEVEL_PUBLIC;
-       if (for_me || color != NULL)
+       if (for_me)
                level |= MSGLEVEL_HILIGHT;
 
        if (settings_get_bool("emphasis"))
@@ -177,34 +205,31 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
        if (printnick == NULL)
                printnick = nick;
 
-       if (!print_channel) {
-               /* message to active channel in window */
-               if (color != NULL) {
-                       /* highlighted nick */
-                       printformat(server, target, level,
-                                   TXT_PUBMSG_HILIGHT,
-                                   color, printnick, msg, nickmode);
-               } else {
+       if (color != NULL) {
+               /* highlighted nick */
+               TEXT_DEST_REC dest;
+               format_create_dest(&dest, server, target, level, NULL);
+               hilight_update_text_dest(&dest,hilight);
+               if (!print_channel) /* message to active channel in window */
+                       printformat_dest(&dest, TXT_PUBMSG_HILIGHT, color,
+                                        printnick, msg, nickmode);
+               else /* message to not existing/active channel */
+                       printformat_dest(&dest, TXT_PUBMSG_HILIGHT_CHANNEL,
+                                        color, printnick, target, msg,
+                                        nickmode);
+       } else {
+               if (!print_channel)
                        printformat(server, target, level,
                                    for_me ? TXT_PUBMSG_ME : TXT_PUBMSG,
                                    printnick, msg, nickmode);
-               }
-       } else {
-               /* message to not existing/active channel */
-               if (color != NULL) {
-                       /* highlighted nick */
-                       printformat(server, target, level,
-                                   TXT_PUBMSG_HILIGHT_CHANNEL,
-                                   color, printnick, target, msg, nickmode);
-               } else {
+               else
                        printformat(server, target, level,
                                    for_me ? TXT_PUBMSG_ME_CHANNEL :
                                    TXT_PUBMSG_CHANNEL,
                                    printnick, target, msg, nickmode);
-               }
-       }
+       }                                               
 
-        g_free_not_null(freemsg);
+       g_free_not_null(freemsg);
        g_free_not_null(color);
 }
 
@@ -226,13 +251,17 @@ static void sig_message_private(SERVER_REC *server, const char *msg,
        g_free_not_null(freemsg);
 }
 
-static void print_own_channel_message(SERVER_REC *server, CHANNEL_REC *channel,
-                                     const char *target, const char *msg)
+static void sig_message_own_public(SERVER_REC *server, const char *msg,
+                                  const char *target)
 {
        WINDOW_REC *window;
+       CHANNEL_REC *channel;
        const char *nickmode;
-        char *freemsg = NULL;
+        char *freemsg = NULL, *recoded;
        int print_channel;
+       channel = channel_find(server, target);
+       if (channel != NULL)
+               target = channel->visible_name;
 
        nickmode = channel_get_nickmode(channel, server->nick);
 
@@ -249,38 +278,29 @@ static void print_own_channel_message(SERVER_REC *server, CHANNEL_REC *channel,
        if (settings_get_bool("emphasis"))
                msg = freemsg = expand_emphasis((WI_ITEM_REC *) channel, msg);
 
+       /* ugly: recode the sent message back for printing */ 
+       recoded = recode_in(server, msg, target);
+       
        if (!print_channel) {
                printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
-                           TXT_OWN_MSG, server->nick, msg, nickmode);
+                           TXT_OWN_MSG, server->nick, recoded, nickmode);
        } else {
                printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
-                           TXT_OWN_MSG_CHANNEL, server->nick, target, msg, nickmode);
+                           TXT_OWN_MSG_CHANNEL, server->nick, target, recoded, nickmode);
        }
 
+       g_free(recoded);
        g_free_not_null(freemsg);
 }
 
-static void sig_message_own_public(SERVER_REC *server, const char *msg,
-                                  const char *target)
-{
-       CHANNEL_REC *channel;
-
-       g_return_if_fail(server != NULL);
-       g_return_if_fail(msg != NULL);
-
-       channel = channel_find(server, target);
-       print_own_channel_message(server, channel, target, msg);
-}
-
 static void sig_message_own_private(SERVER_REC *server, const char *msg,
                                    const char *target, const char *origtarget)
 {
        QUERY_REC *query;
-        char *freemsg = NULL;
+        char *freemsg = NULL, *recoded;
 
        g_return_if_fail(server != NULL);
        g_return_if_fail(msg != NULL);
-
        if (target == NULL) {
                /* this should only happen if some special target failed and
                   we should display some error message. currently the special
@@ -300,11 +320,15 @@ static void sig_message_own_private(SERVER_REC *server, const char *msg,
        if (settings_get_bool("emphasis"))
                msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
 
+       /* ugly: recode the sent message back for printing */
+       recoded = recode_in(server, msg, target);
+
        printformat(server, target,
                    MSGLEVEL_MSGS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
                    query == NULL ? TXT_OWN_MSG_PRIVATE :
-                   TXT_OWN_MSG_PRIVATE_QUERY, target, msg, server->nick);
+                   TXT_OWN_MSG_PRIVATE_QUERY, target, recoded, server->nick);
 
+       g_free(recoded);
        g_free_not_null(freemsg);
 }
 
@@ -329,7 +353,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick,
        WINDOW_REC *window;
        GString *chans;
        GSList *tmp, *windows;
-       char *print_channel;
+       char *print_channel, *recoded;
        int once, count;
 
        if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_QUITS))
@@ -346,7 +370,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick,
                if (!nicklist_find(rec, nick))
                        continue;
 
-               if (ignore_check(server, nick, address, rec->name,
+               if (ignore_check(server, nick, address, rec->visible_name,
                                 reason, MSGLEVEL_QUITS)) {
                        count++;
                        continue;
@@ -354,17 +378,20 @@ static void sig_message_quit(SERVER_REC *server, const char *nick,
 
                if (print_channel == NULL ||
                    active_win->active == (WI_ITEM_REC *) rec)
-                       print_channel = rec->name;
+                       print_channel = rec->visible_name;
 
                if (once)
-                       g_string_sprintfa(chans, "%s,", rec->name);
+                       g_string_sprintfa(chans, "%s,", rec->visible_name);
                else {
                        window = window_item_window((WI_ITEM_REC *) rec);
                        if (g_slist_find(windows, window) == NULL) {
                                windows = g_slist_append(windows, window);
-                               printformat(server, rec->name, MSGLEVEL_QUITS,
-                                           TXT_QUIT, nick, address, reason,
-                                           rec->name);
+                               recoded = recode_in(server, reason, rec->visible_name);
+                               printformat(server, rec->visible_name,
+                                           MSGLEVEL_QUITS,
+                                           TXT_QUIT, nick, address, recoded,
+                                           rec->visible_name);
+                               g_free(recoded);
                        }
                }
                count++;
@@ -376,17 +403,22 @@ static void sig_message_quit(SERVER_REC *server, const char *nick,
                   display the quit there too */
                QUERY_REC *query = query_find(server, nick);
                if (query != NULL) {
+                       recoded = recode_in(server, reason, nick);
                        printformat(server, nick, MSGLEVEL_QUITS,
-                                   TXT_QUIT, nick, address, reason, "");
+                                   TXT_QUIT, nick, address, recoded, "");
+                       g_free(recoded);
                }
        }
 
        if (once || count == 0) {
                if (chans->len > 0)
                        g_string_truncate(chans, chans->len-1);
+               /* at least recode_fallback will be used */
+               recoded = recode_in(server, reason, nick);
                printformat(server, print_channel, MSGLEVEL_QUITS,
                            count <= 1 ? TXT_QUIT : TXT_QUIT_ONCE,
-                           nick, address, reason, chans->str);
+                           nick, address, recoded, chans->str);
+               g_free(recoded);
        }
        g_string_free(chans, TRUE);
 }
@@ -396,7 +428,7 @@ static void sig_message_kick(SERVER_REC *server, const char *channel,
                             const char *address, const char *reason)
 {
        printformat(server, channel, MSGLEVEL_KICKS,
-                   TXT_KICK, nick, channel, kicker, reason);
+                   TXT_KICK, nick, channel, kicker, reason, address);
 }
 
 static void print_nick_change_channel(SERVER_REC *server, const char *channel,
@@ -415,7 +447,7 @@ static void print_nick_change_channel(SERVER_REC *server, const char *channel,
 
        printformat(server, channel, level,
                    ownnick ? TXT_YOUR_NICK_CHANGED : TXT_NICK_CHANGED,
-                   oldnick, newnick, channel);
+                   oldnick, newnick, channel, address);
 }
 
 static void print_nick_change(SERVER_REC *server, const char *newnick,
@@ -440,8 +472,8 @@ static void print_nick_change(SERVER_REC *server, const char *newnick,
                        continue;
 
                windows = g_slist_append(windows, window);
-               print_nick_change_channel(server, channel->name, newnick,
-                                         oldnick, address, ownnick);
+               print_nick_change_channel(server, channel->visible_name,
+                                         newnick, oldnick, address, ownnick);
                msgprint = TRUE;
        }
 
@@ -449,7 +481,8 @@ static void print_nick_change(SERVER_REC *server, const char *newnick,
 
        if (!msgprint && ownnick) {
                printformat(server, NULL, MSGLEVEL_NICKS,
-                           TXT_YOUR_NICK_CHANGED, oldnick, newnick, "");
+                           TXT_YOUR_NICK_CHANGED, oldnick, newnick, "",
+                           address);
        }
 }
 
@@ -466,7 +499,8 @@ static void sig_message_own_nick(SERVER_REC *server, const char *newnick,
                print_nick_change(server, newnick, oldnick, address, TRUE);
        else {
                printformat(server, NULL, MSGLEVEL_NICKS,
-                           TXT_YOUR_NICK_CHANGED, oldnick, newnick, "");
+                           TXT_YOUR_NICK_CHANGED, oldnick, newnick, "",
+                           address);
        }
 }
 
@@ -477,7 +511,7 @@ static void sig_message_invite(SERVER_REC *server, const char *channel,
 
        str = show_lowascii(channel);
        printformat(server, NULL, MSGLEVEL_INVITES,
-                   TXT_INVITE, nick, str);
+                   TXT_INVITE, nick, str, address);
        g_free(str);
 }
 
@@ -487,7 +521,7 @@ static void sig_message_topic(SERVER_REC *server, const char *channel,
 {
        printformat(server, channel, MSGLEVEL_TOPICS,
                    *topic != '\0' ? TXT_NEW_TOPIC : TXT_TOPIC_UNSET,
-                   nick, channel, topic);
+                   nick, channel, topic, address);
 }
 
 static int printnick_exists(NICK_REC *first, NICK_REC *ignore,
@@ -622,6 +656,7 @@ void fe_messages_init(void)
        printnicks = g_hash_table_new((GHashFunc) g_direct_hash,
                                      (GCompareFunc) g_direct_equal);
 
+       settings_add_bool("lookandfeel", "hilight_nick_matches", TRUE);
        settings_add_bool("lookandfeel", "emphasis", TRUE);
        settings_add_bool("lookandfeel", "emphasis_replace", FALSE);
        settings_add_bool("lookandfeel", "emphasis_multiword", FALSE);