1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

Highlighting updates. -word renamed to -full. Added new -word option

meaning to highlight only the found word in line. Removed -nonick
option but added -line which means pretty much the same. -actcolor
specifies what color to show in activity list, default is the same as
-color. Also uses the nick cache to match nickmasks faster.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1139 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2001-01-21 04:14:24 +00:00 committed by cras
parent 1bfa0e1ee3
commit 391a7e5710
6 changed files with 441 additions and 162 deletions

View File

@ -142,7 +142,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
for_me = nick_match_msg(chanrec, msg, server->nick); for_me = nick_match_msg(chanrec, msg, server->nick);
color = for_me ? NULL : color = for_me ? NULL :
hilight_match_nick(target, nick, address, MSGLEVEL_PUBLIC, msg); hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
print_channel = chanrec == NULL || print_channel = chanrec == NULL ||
!window_item_is_active((WI_ITEM_REC *) chanrec); !window_item_is_active((WI_ITEM_REC *) chanrec);

View File

@ -592,41 +592,83 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret)
((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \ ((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \
(c) == 15 || (c) == 22 || (c) == 27 || (c) == 31) (c) == 15 || (c) == 22 || (c) == 27 || (c) == 31)
char *strip_codes(const char *input) /* Return how many characters in `str' must be skipped before `len'
characters of text is skipped. */
int strip_real_length(const char *str, int len,
int *last_color_pos, int *last_color_len)
{ {
const char *p; const char *start = str;
char *str, *out;
out = str = g_strdup(input); while (*str != '\0') {
for (p = input; *p != '\0'; p++) { if (*str == 3) {
if (*p == 3) { const char *mircstart = str;
p++;
/* mirc color */ if (last_color_pos != NULL)
get_mirc_color(&p, NULL, NULL); *last_color_pos = (int) (str-start);
p--; str++;
continue; get_mirc_color(&str, NULL, NULL);
} if (last_color_len != NULL)
*last_color_len = (int) (str-mircstart);
if (*p == 4 && p[1] != '\0') { } else if (*str == 4 && str[1] != '\0') {
if (p[1] >= FORMAT_STYLE_SPECIAL) { if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') {
p++; if (last_color_pos != NULL)
continue; *last_color_pos = (int) (str-start);
} if (last_color_len != NULL)
*last_color_len = 3;
/* irssi color */ str++;
if (p[2] != '\0') { } else if (str[1] == FORMAT_STYLE_DEFAULTS) {
p += 2; if (last_color_pos != NULL)
continue; *last_color_pos = (int) (str-start);
if (last_color_len != NULL)
*last_color_len = 2;
} }
str += 2;
} else if (!IS_COLOR_CODE(*str)) {
if (len-- == 0)
break;
str++;
} }
if (!IS_COLOR_CODE(*p))
*out++ = *p;
} }
*out = '\0'; return (int) (str-start);
return str; }
char *strip_codes(const char *input)
{
const char *p;
char *str, *out;
out = str = g_strdup(input);
for (p = input; *p != '\0'; p++) {
if (*p == 3) {
p++;
/* mirc color */
get_mirc_color(&p, NULL, NULL);
p--;
continue;
}
if (*p == 4 && p[1] != '\0') {
if (p[1] >= FORMAT_STYLE_SPECIAL) {
p++;
continue;
}
/* irssi color */
if (p[2] != '\0') {
p += 2;
continue;
}
}
if (!IS_COLOR_CODE(*p))
*out++ = *p;
}
*out = '\0';
return str;
} }
/* send a fully parsed text string for GUI to print */ /* send a fully parsed text string for GUI to print */

View File

@ -78,7 +78,13 @@ void format_create_dest(TEXT_DEST_REC *dest,
void format_newline(WINDOW_REC *window); void format_newline(WINDOW_REC *window);
/* strip all color (etc.) codes from `input'. returns newly allocated string. */ /* Return how many characters in `str' must be skipped before `len'
characters of text is skipped. */
int strip_real_length(const char *str, int len,
int *last_color_pos, int *last_color_len);
/* strip all color (etc.) codes from `input'.
Returns newly allocated string. */
char *strip_codes(const char *input); char *strip_codes(const char *input);
/* send a fully parsed text string for GUI to print */ /* send a fully parsed text string for GUI to print */

View File

@ -22,22 +22,41 @@
#include "module-formats.h" #include "module-formats.h"
#include "signals.h" #include "signals.h"
#include "commands.h" #include "commands.h"
#include "levels.h"
#include "misc.h" #include "misc.h"
#include "lib-config/iconfig.h" #include "lib-config/iconfig.h"
#include "settings.h" #include "settings.h"
#include "levels.h"
#include "servers.h" #include "servers.h"
#include "channels.h"
#include "nicklist.h"
#include "hilight-text.h" #include "hilight-text.h"
#include "nickmatch-cache.h"
#include "printtext.h" #include "printtext.h"
#include "formats.h" #include "formats.h"
static HILIGHT_REC *next_hilight; static NICKMATCH_REC *nickmatch;
static int hilight_stop_next; static HILIGHT_REC *next_nick_hilight, *next_line_hilight;
static int default_hilight_level; static int next_hilight_start, next_hilight_end;
static int never_hilight_level, default_hilight_level;
GSList *hilights; GSList *hilights;
static void reset_cache(void)
{
GSList *tmp;
never_hilight_level = MSGLEVEL_ALL & ~default_hilight_level;
for (tmp = hilights; tmp != NULL; tmp = tmp->next) {
HILIGHT_REC *rec = tmp->data;
if (never_hilight_level & rec->level)
never_hilight_level &= ~rec->level;
}
nickmatch_rebuild(nickmatch);
}
static void hilight_add_config(HILIGHT_REC *rec) static void hilight_add_config(HILIGHT_REC *rec)
{ {
CONFIG_NODE *node; CONFIG_NODE *node;
@ -50,7 +69,10 @@ static void hilight_add_config(HILIGHT_REC *rec)
iconfig_node_set_str(node, "text", rec->text); iconfig_node_set_str(node, "text", rec->text);
if (rec->level > 0) iconfig_node_set_int(node, "level", rec->level); if (rec->level > 0) iconfig_node_set_int(node, "level", rec->level);
if (rec->color) iconfig_node_set_str(node, "color", rec->color); if (rec->color) iconfig_node_set_str(node, "color", rec->color);
if (rec->nick) iconfig_node_set_bool(node, "nick", TRUE); if (rec->act_color) iconfig_node_set_str(node, "act_color", rec->act_color);
if (rec->priority > 0) iconfig_node_set_int(node, "priority", rec->priority);
iconfig_node_set_bool(node, "nick", rec->nick);
iconfig_node_set_bool(node, "word", rec->word);
if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE); if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE);
if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE);
if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE); if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE);
@ -75,8 +97,13 @@ static void hilight_destroy(HILIGHT_REC *rec)
{ {
g_return_if_fail(rec != NULL); g_return_if_fail(rec != NULL);
g_free(rec->text); #ifdef HAVE_REGEX_H
if (rec->regexp_compiled) regfree(&rec->preg);
#endif
if (rec->channels != NULL) g_strfreev(rec->channels);
g_free_not_null(rec->color); g_free_not_null(rec->color);
g_free_not_null(rec->act_color);
g_free(rec->text);
g_free(rec); g_free(rec);
} }
@ -179,57 +206,101 @@ static int mirc_color_name(const char *name)
return -1; return -1;
} }
HILIGHT_REC *hilight_match(const char *channel, const char *nickmask, static int hilight_match_text(HILIGHT_REC *rec, const char *text,
int level, const char *str) int *match_beg, int *match_end)
{ {
GSList *tmp; char *match;
HILIGHT_REC *match;
int len, best_match;
g_return_val_if_fail(str != NULL, NULL); if (rec->regexp) {
#ifdef HAVE_REGEX_H
regmatch_t rmatch[1];
match = NULL; best_match = 0; if (rec->regexp_compiled &&
for (tmp = hilights; tmp != NULL; tmp = tmp->next) { regexec(&rec->preg, text, 1, rmatch, 0) == 0) {
HILIGHT_REC *rec = tmp->data; if (rmatch[0].rm_so > 0 &&
match_beg != NULL && match_end != NULL) {
if ((level & (rec->level > 0 ? rec->level : default_hilight_level)) == 0) *match_beg = rmatch[0].rm_so;
continue; *match_end = rmatch[0].rm_eo;
if (!rec->nick && nickmask != NULL) }
continue; return TRUE;
if (rec->channels != NULL && (channel == NULL || strarray_find(rec->channels, channel) == -1))
continue;
if (rec->nickmask) {
if (nickmask == NULL || !match_wildcards(rec->text, nickmask))
continue;
} else if (rec->regexp) {
if (!regexp_match(str, rec->text))
continue;
} else if (rec->fullword) {
if (stristr_full(str, rec->text) == NULL)
continue;
} else {
if (stristr(str, rec->text) == NULL)
continue;
} }
#endif
len = strlen(rec->text); } else {
if (best_match < len) { match = rec->fullword ?
best_match = len; stristr_full(text, rec->text) :
match = rec; stristr(text, rec->text);
if (match != NULL) {
if (match_beg != NULL && match_end != NULL) {
*match_beg = (int) (match-text);
*match_end = *match_beg + strlen(rec->text);
}
return TRUE;
} }
} }
return match; return FALSE;
} }
char *hilight_get_color(HILIGHT_REC *rec) #define hilight_match_level(rec, level) \
(level & (((rec)->level != 0 ? rec->level : default_hilight_level)))
#define hilight_match_channel(rec, channel) \
((rec)->channels == NULL || ((channel) != NULL && \
strarray_find((rec)->channels, (channel)) != -1))
HILIGHT_REC *hilight_match(SERVER_REC *server, const char *channel,
const char *nick, const char *address,
int level, const char *str,
int *match_beg, int *match_end)
{ {
const char *color = rec->color; GSList *tmp;
CHANNEL_REC *chanrec;
NICK_REC *nickrec;
g_return_val_if_fail(str != NULL, NULL);
if ((never_hilight_level & level) == level)
return NULL;
if (nick != NULL) {
/* check nick mask hilights */
chanrec = channel_find(server, channel);
nickrec = chanrec == NULL ? NULL :
nicklist_find(chanrec, nick);
if (nickrec != NULL) {
HILIGHT_REC *rec;
if (nickrec->host == NULL)
nicklist_set_host(chanrec, nickrec, address);
rec = nickmatch_find(nickmatch, nickrec);
if (rec != NULL && hilight_match_level(rec, level))
return rec;
}
}
for (tmp = hilights; tmp != NULL; tmp = tmp->next) {
HILIGHT_REC *rec = tmp->data;
if (!rec->nickmask && hilight_match_level(rec, level) &&
hilight_match_channel(rec, channel) &&
hilight_match_text(rec, str, match_beg, match_end))
return rec;
}
return NULL;
}
char *hilight_get_color(HILIGHT_REC *rec, int activity)
{
const char *color;
char number[MAX_INT_STRLEN]; char number[MAX_INT_STRLEN];
int colornum; int colornum;
g_return_val_if_fail(rec != NULL, NULL); g_return_val_if_fail(rec != NULL, NULL);
color = activity && rec->act_color != NULL ?
rec->act_color : rec->color;
if (color == NULL) if (color == NULL)
color = settings_get_str("hilight_color"); color = settings_get_str("hilight_color");
@ -245,80 +316,135 @@ char *hilight_get_color(HILIGHT_REC *rec)
return g_strconcat(isdigit(*color) ? "\003" : "", color, NULL); return g_strconcat(isdigit(*color) ? "\003" : "", color, NULL);
} }
static void hilight_update_text_dest(TEXT_DEST_REC *dest, HILIGHT_REC *rec)
{
char *color;
dest->level |= MSGLEVEL_HILIGHT;
if (rec->priority > 0)
dest->hilight_priority = rec->priority;
color = hilight_get_color(rec, TRUE);
if (*color == 3)
dest->hilight_color = atoi(color+1);
g_free(color);
}
static void sig_print_text_stripped(TEXT_DEST_REC *dest, const char *str) static void sig_print_text_stripped(TEXT_DEST_REC *dest, const char *str)
{ {
HILIGHT_REC *hilight; HILIGHT_REC *hilight;
char *newstr, *color;
g_return_if_fail(str != NULL); g_return_if_fail(str != NULL);
if (next_hilight != NULL) { if (next_nick_hilight != NULL) {
dest->hilight_priority = next_hilight->priority; if (!next_nick_hilight->nick) {
color = hilight_get_color(next_hilight); /* non-nick hilight wanted */
dest->hilight_color = (color != NULL && *color == 3) ? hilight = next_nick_hilight;
atoi(color+1) : 0; next_nick_hilight = NULL;
g_free(color); if (!hilight_match_text(hilight, str,
next_hilight = NULL; &next_hilight_start,
return; &next_hilight_end)) {
next_hilight_start = 0;
next_hilight_end = strlen(str);
}
} else {
/* nick is highlighted, just set priority */
hilight_update_text_dest(dest, next_nick_hilight);
next_nick_hilight = NULL;
return;
}
} else {
if (dest->level & (MSGLEVEL_NOHILIGHT|MSGLEVEL_HILIGHT))
return;
hilight = hilight_match(dest->server, dest->target,
NULL, NULL, dest->level, str,
&next_hilight_start,
&next_hilight_end);
} }
if (dest->level & (MSGLEVEL_NOHILIGHT|MSGLEVEL_HILIGHT)) if (hilight != NULL) {
return; /* update the level / hilight info */
hilight_update_text_dest(dest, hilight);
hilight = hilight_match(dest->target, NULL, dest->level, str); next_line_hilight = hilight;
if (hilight == NULL)
return;
/* update the level / hilight info */
dest->level |= MSGLEVEL_HILIGHT;
if (hilight->priority > 0)
dest->hilight_priority = hilight->priority;
color = hilight_get_color(hilight);
if (*color == 3) {
/* colorify */
dest->hilight_color = atoi(color+1);
} }
hilight_stop_next = FALSE;
/* send both signals again. "print text stripped" maybe wouldn't
have to be resent, but it would reverse the signal sending
order which some things may depend on, so maybe it's best we
don't do it. */
signal_emit("print text stripped", 2, dest, str);
newstr = g_strconcat(color, str, NULL);
signal_emit("print text", 2, dest, newstr);
g_free(newstr);
hilight_stop_next = TRUE;
g_free_not_null(color);
signal_stop();
} }
static void sig_print_text(TEXT_DEST_REC *dest, const char *str) static void sig_print_text(TEXT_DEST_REC *dest, const char *str)
{ {
if (hilight_stop_next) { char *color, *newstr;
hilight_stop_next = FALSE; int next_hilight_len;
signal_stop();
if (next_line_hilight == NULL)
return;
color = hilight_get_color(next_line_hilight, FALSE);
next_hilight_len = next_hilight_end-next_hilight_start;
if (!next_line_hilight->word) {
/* hilight whole line */
char *tmp = strip_codes(str);
newstr = g_strconcat(color, tmp, NULL);
g_free(tmp);
} else {
/* hilight part of the line */
GString *tmp;
char *middle, *lastcolor;
int pos, color_pos, color_len;
tmp = g_string_new(NULL);
/* start of the line */
pos = strip_real_length(str, next_hilight_start, NULL, NULL);
g_string_append(tmp, str);
g_string_truncate(tmp, pos);
/* color */
g_string_append(tmp, color);
/* middle of the line, stripped */
middle = strip_codes(str+pos);
pos = tmp->len;
g_string_append(tmp, middle);
g_string_truncate(tmp, pos+next_hilight_len);
g_free(middle);
/* end of the line */
pos = strip_real_length(str, next_hilight_end,
&color_pos, &color_len);
lastcolor = g_strndup(str+color_pos, color_len);
g_string_append(tmp, lastcolor);
g_string_append(tmp, str+pos);
g_free(lastcolor);
newstr = tmp->str;
g_string_free(tmp, FALSE);
} }
next_line_hilight = NULL;
signal_emit("print text", 2, dest, newstr);
g_free(color);
g_free(newstr);
signal_stop();
} }
char *hilight_match_nick(const char *channel, const char *nick, char *hilight_match_nick(SERVER_REC *server, const char *channel,
const char *address, int level, const char *msg) const char *nick, const char *address,
int level, const char *msg)
{ {
HILIGHT_REC *rec; HILIGHT_REC *rec;
char *color, *mask; char *color;
mask = g_strdup_printf("%s!%s", nick, address); rec = hilight_match(server, channel, nick, address,
rec = hilight_match(channel, mask, level, msg); level, msg, NULL, NULL);
g_free(mask); color = rec == NULL || !rec->nick ? NULL :
hilight_get_color(rec, FALSE);
color = rec == NULL ? NULL : hilight_get_color(rec); next_nick_hilight = rec;
next_hilight = rec;
return color; return color;
} }
@ -347,21 +473,36 @@ static void read_hilight_config(void)
rec = g_new0(HILIGHT_REC, 1); rec = g_new0(HILIGHT_REC, 1);
hilights = g_slist_append(hilights, rec); hilights = g_slist_append(hilights, rec);
color = config_node_get_str(node, "color", NULL);
rec->text = g_strdup(text); rec->text = g_strdup(text);
color = config_node_get_str(node, "color", NULL);
rec->color = color == NULL || *color == '\0' ? NULL : rec->color = color == NULL || *color == '\0' ? NULL :
g_strdup(color); g_strdup(color);
color = config_node_get_str(node, "act_color", NULL);
rec->act_color = color == NULL || *color == '\0' ? NULL :
g_strdup(color);
rec->level = config_node_get_int(node, "level", 0); rec->level = config_node_get_int(node, "level", 0);
rec->priority = config_node_get_int(node, "priority", 0); rec->priority = config_node_get_int(node, "priority", 0);
rec->nick = config_node_get_bool(node, "nick", TRUE); rec->nick = config_node_get_bool(node, "nick", TRUE);
rec->word = config_node_get_bool(node, "word", TRUE);
rec->nickmask = config_node_get_bool(node, "mask", FALSE); rec->nickmask = config_node_get_bool(node, "mask", FALSE);
rec->fullword = config_node_get_bool(node, "fullword", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE);
rec->regexp = config_node_get_bool(node, "regexp", FALSE); rec->regexp = config_node_get_bool(node, "regexp", FALSE);
#ifdef HAVE_REGEX_H
rec->regexp_compiled = !rec->regexp ? FALSE :
regcomp(&rec->preg, rec->text,
REG_EXTENDED|REG_ICASE) == 0;
#endif
node = config_node_section(node, "channels", -1); node = config_node_section(node, "channels", -1);
if (node != NULL) rec->channels = config_node_get_list(node); if (node != NULL) rec->channels = config_node_get_list(node);
} }
reset_cache();
} }
static void hilight_print(int index, HILIGHT_REC *rec) static void hilight_print(int index, HILIGHT_REC *rec)
@ -376,7 +517,7 @@ static void hilight_print(int index, HILIGHT_REC *rec)
TXT_HILIGHT_LINE, index, rec->text, TXT_HILIGHT_LINE, index, rec->text,
chans != NULL ? chans : "", chans != NULL ? chans : "",
levelstr != NULL ? levelstr : "", levelstr != NULL ? levelstr : "",
rec->nickmask ? " -nick" : "", rec->nickmask ? " -mask" : "",
rec->fullword ? " -word" : "", rec->fullword ? " -word" : "",
rec->regexp ? " -regexp" : ""); rec->regexp ? " -regexp" : "");
g_free_not_null(chans); g_free_not_null(chans);
@ -398,14 +539,14 @@ static void cmd_hilight_show(void)
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_HILIGHT_FOOTER); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_HILIGHT_FOOTER);
} }
/* SYNTAX: HILIGHT [-nick | -nonick] [-mask | -regexp | -word] /* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp]
[-color <color>] [-level <level>] [-color <color>] [-actcolor <color>] [-level <level>]
[-channels <channels>] <text> */ [-channels <channels>] <text> */
static void cmd_hilight(const char *data) static void cmd_hilight(const char *data)
{ {
GHashTable *optlist; GHashTable *optlist;
HILIGHT_REC *rec; HILIGHT_REC *rec;
char *colorarg, *levelarg, *priorityarg, *chanarg, *text; char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text;
char **channels; char **channels;
void *free_arg; void *free_arg;
@ -424,6 +565,7 @@ static void cmd_hilight(const char *data)
levelarg = g_hash_table_lookup(optlist, "level"); levelarg = g_hash_table_lookup(optlist, "level");
priorityarg = g_hash_table_lookup(optlist, "priority"); priorityarg = g_hash_table_lookup(optlist, "priority");
colorarg = g_hash_table_lookup(optlist, "color"); colorarg = g_hash_table_lookup(optlist, "color");
actcolorarg = g_hash_table_lookup(optlist, "actcolor");
if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@ -434,10 +576,13 @@ static void cmd_hilight(const char *data)
if (rec == NULL) { if (rec == NULL) {
rec = g_new0(HILIGHT_REC, 1); rec = g_new0(HILIGHT_REC, 1);
/* default to nick/word hilighting */
rec->nick = TRUE;
rec->word = TRUE;
rec->text = g_strdup(text); rec->text = g_strdup(text);
rec->channels = channels; rec->channels = channels;
} else { } else {
g_free_and_null(rec->color);
g_strfreev(channels); g_strfreev(channels);
hilight_remove_config(rec); hilight_remove_config(rec);
@ -447,22 +592,51 @@ static void cmd_hilight(const char *data)
rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 : rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 :
level2bits(replace_chars(levelarg, ',', ' ')); level2bits(replace_chars(levelarg, ',', ' '));
rec->priority = priorityarg == NULL ? 0 : atoi(priorityarg); rec->priority = priorityarg == NULL ? 0 : atoi(priorityarg);
rec->nick = settings_get_bool("hilight_only_nick") &&
(rec->level == 0 || (rec->level & default_hilight_level) == rec->level) ? if (g_hash_table_lookup(optlist, "line") != NULL) {
g_hash_table_lookup(optlist, "nonick") == NULL : rec->word = FALSE;
g_hash_table_lookup(optlist, "nick") != NULL; rec->nick = FALSE;
}
if (g_hash_table_lookup(optlist, "word") != NULL) {
rec->word = TRUE;
rec->nick = FALSE;
}
if (g_hash_table_lookup(optlist, "nick") != NULL)
rec->nick = TRUE;
rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL; rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL;
rec->fullword = g_hash_table_lookup(optlist, "word") != NULL; rec->fullword = g_hash_table_lookup(optlist, "word") != NULL;
rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL;
if (colorarg != NULL && *colorarg != '\0') if (colorarg != NULL) {
rec->color = g_strdup(colorarg); if (*colorarg != '\0')
rec->color = g_strdup(colorarg);
else
g_free_and_null(rec->color);
}
if (actcolorarg != NULL) {
if (*actcolorarg != '\0')
rec->act_color = g_strdup(actcolorarg);
else
g_free_and_null(rec->act_color);
}
#ifdef HAVE_REGEX_H
if (rec->regexp_compiled)
regfree(&rec->preg);
rec->regexp_compiled = !rec->regexp ? FALSE :
regcomp(&rec->preg, rec->text, REG_EXTENDED|REG_ICASE) == 0;
#endif
hilights = g_slist_append(hilights, rec); hilights = g_slist_append(hilights, rec);
hilight_add_config(rec); hilight_add_config(rec);
hilight_print(g_slist_index(hilights, rec)+1, rec); hilight_print(g_slist_index(hilights, rec)+1, rec);
cmd_params_free(free_arg); cmd_params_free(free_arg);
reset_cache();
} }
/* SYNTAX: DEHILIGHT <id>|<mask> */ /* SYNTAX: DEHILIGHT <id>|<mask> */
@ -486,9 +660,43 @@ static void cmd_dehilight(const char *data)
else { else {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_HILIGHT_REMOVED, rec->text); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_HILIGHT_REMOVED, rec->text);
hilight_remove(rec); hilight_remove(rec);
reset_cache();
} }
} }
static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel,
NICK_REC *nick)
{
GSList *tmp;
HILIGHT_REC *match;
char *nickmask;
int len, best_match;
if (nick->host == NULL)
return; /* don't check until host is known */
nickmask = g_strconcat(nick->nick, "!", nick->host, NULL);
best_match = 0; match = NULL;
for (tmp = hilights; tmp != NULL; tmp = tmp->next) {
HILIGHT_REC *rec = tmp->data;
if (rec->nickmask &&
hilight_match_channel(rec, channel->name) &&
match_wildcards(rec->text, nickmask)) {
len = strlen(rec->text);
if (best_match < len) {
best_match = len;
match = rec;
}
}
}
g_free_not_null(nickmask);
if (match != NULL)
g_hash_table_insert(list, nick, match);
}
static void read_settings(void) static void read_settings(void)
{ {
default_hilight_level = level2bits(settings_get_str("hilight_levels")); default_hilight_level = level2bits(settings_get_str("hilight_levels"));
@ -496,14 +704,17 @@ static void read_settings(void)
void hilight_text_init(void) void hilight_text_init(void)
{ {
next_hilight = NULL;
hilight_stop_next = FALSE;
read_hilight_config();
settings_add_str("lookandfeel", "hilight_color", "8"); settings_add_str("lookandfeel", "hilight_color", "8");
settings_add_bool("lookandfeel", "hilight_only_nick", TRUE);
settings_add_str("lookandfeel", "hilight_levels", "PUBLIC MSGS DCCMSGS"); settings_add_str("lookandfeel", "hilight_levels", "PUBLIC MSGS DCCMSGS");
next_nick_hilight = NULL;
next_line_hilight = NULL;
read_settings();
nickmatch = nickmatch_init(hilight_nick_cache);
read_hilight_config();
signal_add_first("print text stripped", (SIGNAL_FUNC) sig_print_text_stripped); signal_add_first("print text stripped", (SIGNAL_FUNC) sig_print_text_stripped);
signal_add_first("print text", (SIGNAL_FUNC) sig_print_text); signal_add_first("print text", (SIGNAL_FUNC) sig_print_text);
signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config); signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config);
@ -511,12 +722,13 @@ void hilight_text_init(void)
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight);
command_set_options("hilight", "-color -level -priority -channels nick nonick mask word regexp"); command_set_options("hilight", "-color -actcolor -level -priority -channels nick word line mask full regexp");
} }
void hilight_text_deinit(void) void hilight_text_deinit(void)
{ {
hilights_destroy_all(); hilights_destroy_all();
nickmatch_deinit(nickmatch);
signal_remove("print text stripped", (SIGNAL_FUNC) sig_print_text_stripped); signal_remove("print text stripped", (SIGNAL_FUNC) sig_print_text_stripped);
signal_remove("print text", (SIGNAL_FUNC) sig_print_text); signal_remove("print text", (SIGNAL_FUNC) sig_print_text);

View File

@ -1,6 +1,10 @@
#ifndef __HILIGHT_TEXT_H #ifndef __HILIGHT_TEXT_H
#define __HILIGHT_TEXT_H #define __HILIGHT_TEXT_H
#ifdef HAVE_REGEX_H
# include <regex.h>
#endif
typedef struct { typedef struct {
char *text; char *text;
@ -8,22 +12,33 @@ typedef struct {
int level; /* match only messages with this level, 0=default */ int level; /* match only messages with this level, 0=default */
char *color; /* if starts with number, \003 is automatically char *color; /* if starts with number, \003 is automatically
inserted before it. */ inserted before it. */
char *act_color; /* color for window activity */
int priority; int priority;
unsigned int nick:1; /* hilight only the nick, not a full line - works only with msgs. */ unsigned int nick:1; /* hilight only nick if possible */
unsigned int nickmask:1; /* `text 'is a nick mask - colorify the nick */ unsigned int word:1; /* hilight only word, not full line */
unsigned int nickmask:1; /* `text' is a nick mask */
unsigned int fullword:1; /* match `text' only for full words */ unsigned int fullword:1; /* match `text' only for full words */
unsigned int regexp:1; /* `text' is a regular expression */ unsigned int regexp:1; /* `text' is a regular expression */
#ifdef HAVE_REGEX_H
unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */
regex_t preg;
#endif
} HILIGHT_REC; } HILIGHT_REC;
extern GSList *hilights; extern GSList *hilights;
HILIGHT_REC *hilight_match(const char *channel, const char *nickmask, HILIGHT_REC *hilight_match(SERVER_REC *server, const char *channel,
int level, const char *str); const char *nick, const char *address,
char *hilight_get_color(HILIGHT_REC *rec); int level, const char *str,
int *match_beg, int *match_end);
char *hilight_match_nick(const char *channel, const char *nick, char *hilight_get_color(HILIGHT_REC *rec, int activity);
const char *address, int level, const char *msg);
char *hilight_match_nick(SERVER_REC *server, const char *channel,
const char *nick, const char *address,
int level, const char *msg);
void hilight_text_init(void); void hilight_text_init(void);
void hilight_text_deinit(void); void hilight_text_deinit(void);

View File

@ -33,7 +33,7 @@
#include "formats.h" #include "formats.h"
static char **hide_targets; static char **hide_targets;
static int hilight_levels, msg_levels; static int hide_level, msg_level, hilight_level;
static void window_activity(WINDOW_REC *window, static void window_activity(WINDOW_REC *window,
int data_level, int hilight_color) int data_level, int hilight_color)
@ -76,14 +76,15 @@ static void sig_hilight_text(TEXT_DEST_REC *dest, const char *msg)
WI_ITEM_REC *item; WI_ITEM_REC *item;
int data_level; int data_level;
if (dest->window == active_win || if (dest->window == active_win || (dest->level & hide_level))
(dest->level & (MSGLEVEL_NEVER|MSGLEVEL_NO_ACT)))
return; return;
data_level = (dest->level & hilight_levels) ? if (dest->level & hilight_level)
DATA_LEVEL_HILIGHT+dest->hilight_priority : data_level = DATA_LEVEL_HILIGHT+dest->hilight_priority;
((dest->level & msg_levels) ? else {
DATA_LEVEL_MSG : DATA_LEVEL_TEXT); data_level = (dest->level & msg_level) ?
DATA_LEVEL_MSG : DATA_LEVEL_TEXT;
}
if (hide_target_activity(data_level, dest->target)) if (hide_target_activity(data_level, dest->target))
return; return;
@ -122,16 +123,19 @@ static void read_settings(void)
hide_targets = *targets == '\0' ? NULL : hide_targets = *targets == '\0' ? NULL :
g_strsplit(targets, " ", -1); g_strsplit(targets, " ", -1);
msg_levels = level2bits(settings_get_str("activity_msg_levels")); hide_level = MSGLEVEL_NEVER | MSGLEVEL_NO_ACT |
hilight_levels = MSGLEVEL_HILIGHT | level2bits(settings_get_str("activity_hide_level"));
level2bits(settings_get_str("activity_hilight_levels")); msg_level = level2bits(settings_get_str("activity_msg_level"));
hilight_level = MSGLEVEL_HILIGHT |
level2bits(settings_get_str("activity_hilight_level"));
} }
void window_activity_init(void) void window_activity_init(void)
{ {
settings_add_str("lookandfeel", "activity_hide_targets", ""); settings_add_str("lookandfeel", "activity_hide_targets", "");
settings_add_str("lookandfeel", "activity_msg_levels", "PUBLIC"); settings_add_str("lookandfeel", "activity_hide_level", "");
settings_add_str("lookandfeel", "activity_hilight_levels", "MSGS DCCMSGS"); settings_add_str("lookandfeel", "activity_msg_level", "PUBLIC");
settings_add_str("lookandfeel", "activity_hilight_level", "MSGS DCCMSGS");
read_settings(); read_settings();
signal_add("print text", (SIGNAL_FUNC) sig_hilight_text); signal_add("print text", (SIGNAL_FUNC) sig_hilight_text);