diff --git a/src/config/theme.c b/src/config/theme.c index c8e466d5..d221bd3f 100644 --- a/src/config/theme.c +++ b/src/config/theme.c @@ -107,7 +107,9 @@ theme_init(const char *const theme_name) g_hash_table_insert(defaults, strdup("receipt.sent"), strdup("red")); g_hash_table_insert(defaults, strdup("roominfo"), strdup("yellow")); g_hash_table_insert(defaults, strdup("roommention"), strdup("yellow")); + g_hash_table_insert(defaults, strdup("roommention.term"), strdup("yellow")); g_hash_table_insert(defaults, strdup("roomtrigger"), strdup("yellow")); + g_hash_table_insert(defaults, strdup("roomtrigger.term"), strdup("yellow")); g_hash_table_insert(defaults, strdup("online"), strdup("green")); g_hash_table_insert(defaults, strdup("offline"), strdup("red")); g_hash_table_insert(defaults, strdup("away"), strdup("cyan")); @@ -751,7 +753,9 @@ theme_attrs(theme_item_t attrs) case THEME_RECEIPT_SENT: _theme_prep_fgnd("receipt.sent", lookup_str, &bold); break; case THEME_ROOMINFO: _theme_prep_fgnd("roominfo", lookup_str, &bold); break; case THEME_ROOMMENTION: _theme_prep_fgnd("roommention", lookup_str, &bold); break; + case THEME_ROOMMENTION_TERM: _theme_prep_fgnd("roommention.term", lookup_str, &bold); break; case THEME_ROOMTRIGGER: _theme_prep_fgnd("roomtrigger", lookup_str, &bold); break; + case THEME_ROOMTRIGGER_TERM: _theme_prep_fgnd("roomtrigger.term", lookup_str, &bold); break; case THEME_ONLINE: _theme_prep_fgnd("online", lookup_str, &bold); break; case THEME_OFFLINE: _theme_prep_fgnd("offline", lookup_str, &bold); break; case THEME_AWAY: _theme_prep_fgnd("away", lookup_str, &bold); break; diff --git a/src/config/theme.h b/src/config/theme.h index 4ec74510..6ea369d9 100644 --- a/src/config/theme.h +++ b/src/config/theme.h @@ -70,7 +70,9 @@ typedef enum { THEME_THEM, THEME_ROOMINFO, THEME_ROOMMENTION, + THEME_ROOMMENTION_TERM, THEME_ROOMTRIGGER, + THEME_ROOMTRIGGER_TERM, THEME_ONLINE, THEME_OFFLINE, THEME_AWAY, diff --git a/src/event/server_events.c b/src/event/server_events.c index 0b11fbfa..a21b27c0 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -256,7 +256,7 @@ sv_ev_room_message(const char *const room_jid, const char *const nick, const cha GList *triggers = prefs_message_get_triggers(message); - mucwin_message(mucwin, nick, message, mention, triggers != NULL); + mucwin_message(mucwin, nick, message, mention, triggers); ProfWin *window = (ProfWin*)mucwin; int num = wins_get_num(window); diff --git a/src/ui/console.c b/src/ui/console.c index 8d8542a4..8164ccf1 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -2215,7 +2215,9 @@ cons_theme_properties(void) _cons_theme_prop(THEME_ROOMINFO, "roominfo"); _cons_theme_prop(THEME_ROOMMENTION, "roommention"); + _cons_theme_prop(THEME_ROOMMENTION_TERM, "roommention.term"); _cons_theme_prop(THEME_ROOMTRIGGER, "roomtrigger"); + _cons_theme_prop(THEME_ROOMTRIGGER_TERM, "roomtrigger.term"); _cons_theme_prop(THEME_ROSTER_HEADER, "roster.header"); _cons_theme_prop(THEME_ROSTER_CHAT, "roster.chat"); diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index a24daa59..cc744ba6 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -355,9 +355,121 @@ mucwin_history(ProfMucWin *mucwin, const char *const nick, GDateTime *timestamp, g_string_free(line, TRUE); } +static void +_mucwin_print_mention(ProfWin *window, const char *const message, const char *const my_nick) +{ + char *mynick_lower = g_utf8_strdown(my_nick, -1); + char *message_lower = g_utf8_strdown(message, -1); + char message_section[strlen(message) + 1]; + + int i = 0; + while(!g_str_has_prefix(&message_lower[i], mynick_lower) && i < strlen(message)) { + message_section[i] = message[i]; + i++; + } + message_section[i] = '\0'; + + char *mention_section = strndup(&message[i], strlen(my_nick)); + int used = strlen(message_section) + strlen(mention_section); + + win_print(window, '-', 0, NULL, NO_DATE | NO_ME | NO_EOL, THEME_ROOMMENTION, "", message_section); + if (strlen(message) > used) { + win_print(window, '-', 0, NULL, NO_DATE | NO_ME | NO_EOL, THEME_ROOMMENTION_TERM, "", mention_section); + _mucwin_print_mention(window, &message[used], my_nick); + } else { + win_print(window, '-', 0, NULL, NO_DATE | NO_ME, THEME_ROOMMENTION_TERM, "", mention_section); + } + + free(mention_section); + g_free(mynick_lower); + g_free(message_lower); +} + +gint +_cmp_trigger_weight(gconstpointer a, gconstpointer b) +{ + int alen = strlen((char*)a); + int blen = strlen((char*)b); + + if (alen > blen) return -1; + if (alen < blen) return 1; + + return 0; +} + +static void +_mucwin_print_triggers(ProfWin *window, const char *const message, GList *triggers) +{ + GList *weighted_triggers = NULL; + GList *curr = triggers; + while (curr) { + weighted_triggers = g_list_insert_sorted(weighted_triggers, curr->data, (GCompareFunc)_cmp_trigger_weight); + curr = g_list_next(curr); + } + + char *message_lower = g_utf8_strdown(message, -1); + + // find earliest trigger in message + int first_trigger_pos = -1; + int first_trigger_len = -1; + curr = weighted_triggers; + while (curr) { + char *trigger_lower = g_utf8_strdown(curr->data, -1); + char *trigger_ptr = g_strstr_len(message_lower, -1, trigger_lower); + + // not found, try next + if (trigger_ptr == NULL) { + curr = g_list_next(curr); + continue; + } + + // found, repace vars if earlier than previous + int trigger_pos = trigger_ptr - message_lower; + if (first_trigger_pos == -1 || trigger_pos < first_trigger_pos) { + first_trigger_pos = trigger_pos; + first_trigger_len = strlen(trigger_lower); + } + + g_free(trigger_lower); + curr = g_list_next(curr); + } + + g_free(message_lower); + g_list_free(weighted_triggers); + + // no triggers found + if (first_trigger_pos == -1) { + win_print(window, '-', 0, NULL, NO_DATE | NO_ME, THEME_ROOMTRIGGER, "", message); + } else { + if (first_trigger_pos > 0) { + char message_section[strlen(message) + 1]; + int i = 0; + while (i < first_trigger_pos) { + message_section[i] = message[i]; + i++; + } + message_section[i] = '\0'; + win_print(window, '-', 0, NULL, NO_DATE | NO_ME | NO_EOL, THEME_ROOMTRIGGER, "", message_section); + } + char trigger_section[first_trigger_len + 1]; + int i = 0; + while (i < first_trigger_len) { + trigger_section[i] = message[first_trigger_pos + i]; + i++; + } + trigger_section[i] = '\0'; + + if (first_trigger_pos + first_trigger_len < strlen(message)) { + win_print(window, '-', 0, NULL, NO_DATE | NO_ME | NO_EOL, THEME_ROOMTRIGGER_TERM, "", trigger_section); + _mucwin_print_triggers(window, &message[first_trigger_pos + first_trigger_len], triggers); + } else { + win_print(window, '-', 0, NULL, NO_DATE | NO_ME, THEME_ROOMTRIGGER_TERM, "", trigger_section); + } + } +} + void -mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const message, gboolean mention, - gboolean trigger_found) +mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const message, gboolean mention, GList *triggers) { assert(mucwin != NULL); @@ -366,9 +478,11 @@ mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const mes if (g_strcmp0(nick, my_nick) != 0) { if (mention) { - win_print(window, '-', 0, NULL, NO_ME, THEME_ROOMMENTION, nick, message); - } else if (trigger_found) { - win_print(window, '-', 0, NULL, NO_ME, THEME_ROOMTRIGGER, nick, message); + win_print(window, '-', 0, NULL, NO_ME | NO_EOL, THEME_ROOMMENTION, nick, ""); + _mucwin_print_mention(window, message, my_nick); + } else if (triggers) { + win_print(window, '-', 0, NULL, NO_ME | NO_EOL, THEME_ROOMTRIGGER, nick, ""); + _mucwin_print_triggers(window, message, triggers); } else { win_print(window, '-', 0, NULL, NO_ME, THEME_TEXT_THEM, nick, message); } diff --git a/src/ui/ui.h b/src/ui/ui.h index 70b01df3..8376cb90 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -158,7 +158,7 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char const char *const role, const char *const affiliation, const char *const actor, const char *const reason); void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char *const presence); void mucwin_history(ProfMucWin *mucwin, const char *const nick, GDateTime *timestamp, const char *const message); -void mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const message, gboolean mention, gboolean trigger_found); +void mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const message, gboolean mention, GList *triggers); void mucwin_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject); void mucwin_requires_config(ProfMucWin *mucwin); void mucwin_info(ProfMucWin *mucwin); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index 40467c6e..79c9a6cf 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -193,7 +193,7 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char const char * const affiliation, const char * const actor, const char * const reason) {} void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char * const presence) {} void mucwin_history(ProfMucWin *mucwin, const char * const nick, GDateTime *timestamp, const char * const message) {} -void mucwin_message(ProfMucWin *mucwin, const char * const nick, const char * const message, gboolean mention, gboolean trigger_found) {} +void mucwin_message(ProfMucWin *mucwin, const char * const nick, const char * const message, gboolean mention, GList *triggers) {} void mucwin_subject(ProfMucWin *mucwin, const char * const nick, const char * const subject) {} void mucwin_requires_config(ProfMucWin *mucwin) {} void ui_room_destroy(const char * const roomjid) {} diff --git a/theme_template b/theme_template index 926008b6..20393bab 100644 --- a/theme_template +++ b/theme_template @@ -45,7 +45,9 @@ gone= error= roominfo= roommention= +roommention.term= roomtrigger= +roomtrigger.term= me= them= roster.header= diff --git a/themes/aqua b/themes/aqua index 6ea11e2c..a0f7fb91 100644 --- a/themes/aqua +++ b/themes/aqua @@ -45,7 +45,9 @@ gone=blue error=bold_white roominfo=white roommention=bold_blue +roommention.term=bold_blue roomtrigger=bold_blue +roomtrigger.term=bold_blue me=cyan them=white roster.header=bold_white diff --git a/themes/batman b/themes/batman index b90fdc23..e982b182 100644 --- a/themes/batman +++ b/themes/batman @@ -47,7 +47,9 @@ main.text.them=white subscribed=magenta unsubscribed=black_bold roommention=cyan +roommention.term=cyan roomtrigger=cyan +roomtrigger.term=cyan roster.header=yellow roster.chat=green roster.online=green diff --git a/themes/bios b/themes/bios index 262ea9e6..ad582d7e 100644 --- a/themes/bios +++ b/themes/bios @@ -45,7 +45,9 @@ gone=bold_red error=bold_red roominfo=bold_yellow roommention=bold_green +roommention.term=bold_green roomtrigger=bold_green +roomtrigger.term=bold_green me=bold_cyan them=bold_magenta roster.header=bold_magenta diff --git a/themes/boothj5 b/themes/boothj5 index 179e154b..bb1f8d27 100644 --- a/themes/boothj5 +++ b/themes/boothj5 @@ -44,8 +44,10 @@ typing=yellow gone=red error=red roominfo=yellow -roommention=bold_cyan -roomtrigger=bold_blue +roommention=bold_white +roommention.term=bold_cyan +roomtrigger=bold_white +roomtrigger.term=bold_blue me=blue them=bold_green roster.header=bold_yellow diff --git a/themes/boothj5_slack b/themes/boothj5_slack index 8fa88497..e7f1a571 100644 --- a/themes/boothj5_slack +++ b/themes/boothj5_slack @@ -44,8 +44,10 @@ typing=yellow gone=red error=red roominfo=yellow -roommention=bold_cyan -roomtrigger=bold_blue +roommention=bold_white +roommention.term=bold_cyan +roomtrigger=bold_white +roomtrigger.term=bold_blue me=blue them=bold_green roster.header=bold_yellow diff --git a/themes/forest b/themes/forest index 32344439..d466eda1 100644 --- a/themes/forest +++ b/themes/forest @@ -45,7 +45,9 @@ gone=bold_black error=bold_black roominfo=yellow roommention=bold_cyan +roommention.term=bold_cyan roomtrigger=bold_cyan +roomtrigger.term=bold_cyan me=blue them=bold_blue roster.header=bold_green diff --git a/themes/hacker b/themes/hacker index 70f65b7a..a6516baa 100644 --- a/themes/hacker +++ b/themes/hacker @@ -45,7 +45,9 @@ gone=green error=bold_green roominfo=green roommention=bold_green +roommention.term=bold_green roomtrigger=bold_green +roomtrigger.term=bold_green me=green them=bold_green roster.header=bold_green diff --git a/themes/headache b/themes/headache index 3c47e4c2..d53a1286 100644 --- a/themes/headache +++ b/themes/headache @@ -45,7 +45,9 @@ gone=yellow error=red roominfo=white roommention=bold_green +roommention.term=bold_green roomtrigger=bold_green +roomtrigger.term=bold_green me=white them=white roster.header=bold_cyan diff --git a/themes/joker b/themes/joker index 49a387ec..db5e6d54 100644 --- a/themes/joker +++ b/themes/joker @@ -45,7 +45,9 @@ gone=red error=red roominfo=green roommention=green +roommention.term=green roomtrigger=green +roomtrigger.term=green me=magenta them=green roster.header=magenta diff --git a/themes/mono b/themes/mono index c6743ab6..fcb16230 100644 --- a/themes/mono +++ b/themes/mono @@ -45,7 +45,9 @@ gone=white error=white roominfo=white roommention=white +roommention.term=white roomtrigger=white +roomtrigger.term=white me=white them=white roster.header=white diff --git a/themes/orange b/themes/orange index de988435..729ea5d4 100644 --- a/themes/orange +++ b/themes/orange @@ -45,7 +45,9 @@ gone=green error=red roominfo=blue roommention=blue +roommention.term=blue roomtrigger=blue +roomtrigger.term=blue me=black them=black roster.header=black diff --git a/themes/original b/themes/original index 85df4c48..33e54fb3 100644 --- a/themes/original +++ b/themes/original @@ -45,7 +45,9 @@ gone=yellow error=red roominfo=yellow roommention=yellow +roommention.term=yellow roomtrigger=yellow +roomtrigger.term=yellow me=yellow them=green roster.header=yellow diff --git a/themes/original_bright b/themes/original_bright index 49c9d336..92f139e3 100644 --- a/themes/original_bright +++ b/themes/original_bright @@ -45,7 +45,9 @@ gone=bold_yellow error=bold_red roominfo=bold_yellow roommention=bold_yellow +roommention.term=bold_yellow roomtrigger=bold_yellow +roomtrigger.term=bold_yellow me=bold_yellow them=bold_green roster.header=bold_yellow diff --git a/themes/shade b/themes/shade index 6a2f5729..7672ea32 100644 --- a/themes/shade +++ b/themes/shade @@ -45,7 +45,9 @@ gone=red error=red roominfo=green roommention=green +roommention.term=green roomtrigger=green +roomtrigger.term=green me=bold_black them=magenta roster.header=magenta diff --git a/themes/spawn b/themes/spawn index 7b267948..82c63e9d 100644 --- a/themes/spawn +++ b/themes/spawn @@ -45,7 +45,9 @@ gone=red error=red roominfo=green roommention=red +roommention.term=red roomtrigger=red +roomtrigger.term=red me=green them=yellow roster.header=white diff --git a/themes/whiteness b/themes/whiteness index 9799877e..5bf83850 100644 --- a/themes/whiteness +++ b/themes/whiteness @@ -45,7 +45,9 @@ gone=red error=red roominfo=yellow roommention=yellow +roommention.term=yellow roomtrigger=yellow +roomtrigger.term=yellow me=black them=black roster.header=black