diff --git a/src/core/ignore.c b/src/core/ignore.c index 6d432a4c..81df32ba 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -46,7 +46,7 @@ static int ignore_check_replies(IGNORE_REC *rec, CHANNEL_REC *channel, for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *nick = tmp->data; - if (nick_match_msg(channel->server, text, nick->nick)) + if (nick_match_msg(channel, text, nick->nick)) return TRUE; } g_slist_free(nicks); diff --git a/src/core/nicklist.c b/src/core/nicklist.c index a54b005b..50623dcf 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -262,46 +262,93 @@ static void sig_channel_destroyed(CHANNEL_REC *channel) g_hash_table_destroy(channel->nicks); } -/* Check is `msg' is meant for `nick'. */ -int nick_match_msg(SERVER_REC *server, const char *msg, const char *nick) +static NICK_REC *nick_nfind(CHANNEL_REC *channel, const char *nick, int len) { - int len; + NICK_REC *rec; + char *tmpnick; + + tmpnick = g_strndup(nick, len); + rec = g_hash_table_lookup(channel->nicks, tmpnick); + g_free(tmpnick); + return rec; +} + +/* Check is `msg' is meant for `nick'. */ +int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick) +{ + const char *msgstart, *orignick; + int len, fullmatch; g_return_val_if_fail(nick != NULL, FALSE); g_return_val_if_fail(msg != NULL, FALSE); - if (server != NULL && server->nick_match_msg != NULL) - return server->nick_match_msg(msg, nick); + if (channel != NULL && channel->server->nick_match_msg != NULL) + return channel->server->nick_match_msg(msg, nick); /* first check for identical match */ len = strlen(nick); if (g_strncasecmp(msg, nick, len) == 0 && !isalnumhigh((int) msg[len])) return TRUE; - /* check if it matches for alphanumeric parts of nick */ - while (*nick != '\0' && *msg != '\0') { - if (*nick == *msg) { - /* total match */ - msg++; - } else if (isalnum(*msg) && !isalnum(*nick)) { - /* some strange char in your nick, pass it */ - } else + orignick = nick; + for (;;) { + nick = orignick; + msgstart = msg; + fullmatch = TRUE; + + /* check if it matches for alphanumeric parts of nick */ + while (*nick != '\0' && *msg != '\0') { + if (*nick == *msg) { + /* total match */ + msg++; + } else if (isalnum(*msg) && !isalnum(*nick)) { + /* some strange char in your nick, pass it */ + fullmatch = FALSE; + } else + break; + + nick++; + } + + if (msg != msgstart && !isalnumhigh(*msg)) { + /* at least some of the chars in line matched the + nick, and msg continue with non-alphanum character, + this might be for us.. */ + if (*nick != '\0') { + /* remove the rest of the non-alphanum chars + from nick and check if it then matches. */ + fullmatch = FALSE; + while (*nick != '\0' && !isalnum(*nick)) + nick++; + } + + if (*nick == '\0') { + /* yes, match! */ + break; + } + } + + /* no match. check if this is a message to multiple people + (like nick1,nick2: text) */ + while (*msg != '\0' && *msg != ' ' && *msg != ',') msg++; + + if (*msg != ',') { + nick = orignick; break; + } - nick++; + msg++; } - if (isalnumhigh(*msg)) { - /* message continues with another alphanumeric character, - it isn't for us. */ - return FALSE; - } + if (*nick != '\0') + return FALSE; /* didn't match */ - /* remove all the non-alphanumeric characters at the end of - the nick and check if message matched that far. */ - while (*nick != '\0' && !isalnum(*nick)) nick++; + if (fullmatch) + return TRUE; /* matched without fuzzyness */ - return *nick == '\0'; + /* matched with some fuzzyness .. check if there's an exact match + for some other nick in the same channel. */ + return nick_nfind(channel, msgstart, (int) (msg-msgstart)) == NULL; } void nicklist_init(void) diff --git a/src/core/nicklist.h b/src/core/nicklist.h index 90cdece6..5f857e60 100644 --- a/src/core/nicklist.h +++ b/src/core/nicklist.h @@ -37,7 +37,7 @@ void nicklist_update_flags(SERVER_REC *server, const char *nick, int nicklist_compare(NICK_REC *p1, NICK_REC *p2); /* Check is `msg' is meant for `nick'. */ -int nick_match_msg(SERVER_REC *server, const char *msg, const char *nick); +int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick); void nicklist_init(void); void nicklist_deinit(void); diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index a29c1cc8..544a6043 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -148,7 +148,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg, channel = channel_find(server, target); if (channel != NULL) { - list = nick_match_msg(server, msg, server->nick) ? + list = nick_match_msg(channel, msg, server->nick) ? &channel->lastownmsgs : &channel->lastmsgs; last_msg_add(list, nick); diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index c574085d..c1446517 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -63,7 +63,9 @@ static void sig_message_public(SERVER_REC *server, const char *msg, char *color; chanrec = channel_find(server, target); - for_me = nick_match_msg(server, msg, server->nick); + g_return_if_fail(chanrec != NULL); + + for_me = nick_match_msg(chanrec, msg, server->nick); color = for_me ? NULL : hilight_find_nick(target, nick, address, MSGLEVEL_PUBLIC, msg); diff --git a/src/fe-common/core/window-activity.c b/src/fe-common/core/window-activity.c index 7c90ec52..8cb11dd1 100644 --- a/src/fe-common/core/window-activity.c +++ b/src/fe-common/core/window-activity.c @@ -145,8 +145,7 @@ static void sig_message(SERVER_REC *server, const char *msg, /* hilight */ if (item != NULL) item->last_color = hilight_last_nick_color(); level = (item != NULL && item->last_color > 0) || - (level & hilight_level) || - nick_match_msg(SERVER(server), msg, server->nick) ? + (level & hilight_level) ? NEWDATA_HILIGHT : NEWDATA_MSG; if (item != NULL && item->new_data < level) { item->new_data = level; @@ -169,7 +168,12 @@ static void sig_message_public(SERVER_REC *server, const char *msg, const char *nick, const char *addr, const char *target) { - sig_message(server, msg, nick, addr, target, MSGLEVEL_PUBLIC); + int level = MSGLEVEL_PUBLIC; + + if (nick_match_msg(channel_find(server, target), msg, server->nick)) + level |= MSGLEVEL_HILIGHT; + + sig_message(server, msg, nick, addr, target, level); } static void sig_message_private(SERVER_REC *server, const char *msg,