Merge Irssi 0.8.16-rc1
[silc.git] / apps / irssi / src / fe-common / core / fe-messages.c
index e210c2a2d156101e53adc30dee660797419e33f5..846272fdcf1b6453a463c5dafd92d4be23e46446 100644 (file)
@@ -13,9 +13,9 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
 #include "module.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 +71,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 +84,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,17 +133,21 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
 static char *channel_get_nickmode_rec(NICK_REC *nickrec)
 {
         char *emptystr;
+       char *nickmode;
 
        if (!settings_get_bool("show_nickmode"))
-                return "";
+                return g_strdup("");
 
         emptystr = settings_get_bool("show_nickmode_empty") ? " " : "";
 
-       return nickrec == NULL ? emptystr :
-               nickrec->op ? "@" :
-               nickrec->halfop ? "%" :
-               nickrec->voice ? "+" :
-               emptystr;
+       if (nickrec == NULL || nickrec->prefixes[0] == '\0')
+               nickmode = g_strdup(emptystr);
+       else {
+               nickmode = g_malloc(2);
+               nickmode[0] = nickrec->prefixes[0];
+               nickmode[1] = '\0';
+       }
+       return nickmode;
 }
 
 char *channel_get_nickmode(CHANNEL_REC *channel, const char *nick)
@@ -142,9 +163,10 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
                               const char *target, NICK_REC *nickrec)
 {
        CHANNEL_REC *chanrec;
-       const char *nickmode, *printnick;
+       const char *printnick;
        int for_me, print_channel, level;
-       char *color, *freemsg = NULL;
+       char *nickmode, *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 */
@@ -154,8 +176,9 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
 
        for_me = !settings_get_bool("hilight_nick_matches") ? FALSE :
                nick_match_msg(chanrec, msg, server->nick);
-       color = for_me ? NULL :
+       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);
@@ -164,7 +187,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"))
@@ -178,34 +201,32 @@ 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(nickmode);
+       g_free_not_null(freemsg);
        g_free_not_null(color);
 }
 
@@ -232,10 +253,9 @@ static void sig_message_own_public(SERVER_REC *server, const char *msg,
 {
        WINDOW_REC *window;
        CHANNEL_REC *channel;
-       const char *nickmode;
+       char *nickmode;
         char *freemsg = NULL;
        int print_channel;
-
        channel = channel_find(server, target);
        if (channel != NULL)
                target = channel->visible_name;
@@ -263,6 +283,7 @@ static void sig_message_own_public(SERVER_REC *server, const char *msg,
                            TXT_OWN_MSG_CHANNEL, server->nick, target, msg, nickmode);
        }
 
+       g_free_not_null(nickmode);
        g_free_not_null(freemsg);
 }
 
@@ -274,7 +295,6 @@ static void sig_message_own_private(SERVER_REC *server, const char *msg,
 
        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
@@ -351,7 +371,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick,
                        print_channel = rec->visible_name;
 
                if (once)
-                       g_string_sprintfa(chans, "%s,", rec->visible_name);
+                       g_string_append_printf(chans, "%s,", rec->visible_name);
                else {
                        window = window_item_window((WI_ITEM_REC *) rec);
                        if (g_slist_find(windows, window) == NULL) {
@@ -422,7 +442,7 @@ static void print_nick_change(SERVER_REC *server, const char *newnick,
 
        msgprint = FALSE;
 
-       /* Print to each channel/query where the nick is.
+       /* Print to each channel where the nick is.
           Don't print more than once to the same window. */
        windows = NULL;
        for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
@@ -556,7 +576,7 @@ static void sig_nicklist_new(CHANNEL_REC *channel, NICK_REC *nick)
        newnick = g_string_new(NULL);
         n = 2;
        do {
-               g_string_sprintf(newnick, "%s%d", nickhost, n);
+               g_string_printf(newnick, "%s%d", nickhost, n);
                 n++;
        } while (printnick_exists(firstnick, nick, newnick->str));