diff --git a/src/common/fe.h b/src/common/fe.h index e330ef3e..3fa4e2bc 100644 --- a/src/common/fe.h +++ b/src/common/fe.h @@ -98,7 +98,7 @@ void fe_set_nonchannel (struct session *sess, int state); void fe_set_nick (struct server *serv, char *newnick); void fe_ignore_update (int level); void fe_beep (void); -void fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gboolean regexp); +void fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gtk_xtext_search_flags flags); void fe_set_lag (server *serv, int lag); void fe_set_throttle (server *serv); void fe_set_away (server *serv); diff --git a/src/common/outbound.c b/src/common/outbound.c index 060c6742..2e79d59e 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -2362,7 +2362,7 @@ cmd_lagcheck (struct session *sess, char *tbuf, char *word[], char *word_eol[]) } static void -lastlog (session *sess, char *search, gboolean regexp) +lastlog (session *sess, char *search, gtk_xtext_search_flags flags) { session *lastlog_sess; @@ -2374,29 +2374,50 @@ lastlog (session *sess, char *search, gboolean regexp) lastlog_sess = new_ircwindow (sess->server, "(lastlog)", SESS_DIALOG, 0); lastlog_sess->lastlog_sess = sess; - lastlog_sess->lastlog_regexp = regexp; /* remember the search type */ + lastlog_sess->lastlog_flags = flags; fe_text_clear (lastlog_sess, 0); - fe_lastlog (sess, lastlog_sess, search, regexp); + fe_lastlog (sess, lastlog_sess, search, flags); } static int cmd_lastlog (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { - if (*word_eol[2]) + int j = 2; + gtk_xtext_search_flags flags = 0; + gboolean doublehyphen = FALSE; + + while (word_eol[j] != NULL && word_eol [j][0] == '-' && !doublehyphen) { - if (!strcmp (word[2], "-r")) + switch (word_eol [j][1]) { - lastlog (sess, word_eol[3], TRUE); - } - else - { - lastlog (sess, word_eol[2], FALSE); + case 'r': + flags |= regexp; + break; + case 'm': + flags |= case_match; + break; + case 'h': + flags |= highlight; + break; + case '-': + doublehyphen = TRUE; + break; + default: + break; + /* O dear whatever shall we do here? */ } + j++; + } + if (*word_eol[j]) + { + lastlog (sess, word_eol[j], flags); return TRUE; } - - return FALSE; + else + { + return FALSE; + } } static int @@ -3602,7 +3623,11 @@ const struct commands xc_cmds[] = { {"LAGCHECK", cmd_lagcheck, 0, 0, 1, N_("LAGCHECK, forces a new lag check")}, {"LASTLOG", cmd_lastlog, 0, 0, 1, - N_("LASTLOG [-r] , searches for a string in the buffer")}, + N_("LASTLOG [-h] [-m] [-r] [--] , searches for a string in the buffer\n" + " Use -h to highlight the found string(s)\n" + " Use -m to match case\n" + " Use -r when string is a Regular Expression\n" + " Use -- (double hyphen) to end options when searching for, say, the string '-r'")}, {"LIST", cmd_list, 1, 0, 1, 0}, {"LOAD", cmd_load, 0, 0, 1, N_("LOAD [-e] , loads a plugin or script")}, @@ -4099,7 +4124,7 @@ handle_say (session *sess, char *text, int check_spch) if (strcmp (sess->channel, "(lastlog)") == 0) { - lastlog (sess->lastlog_sess, text, sess->lastlog_regexp); + lastlog (sess->lastlog_sess, text, sess->lastlog_flags); return; } diff --git a/src/common/xchat.c b/src/common/xchat.c index f90a6291..21e2bd9e 100644 --- a/src/common/xchat.c +++ b/src/common/xchat.c @@ -591,7 +591,7 @@ static char defaultconf_commands[] = "NAME DIALOG\n" "CMD query %2\n\n"\ "NAME DMSG\n" "CMD msg =%2 &3\n\n"\ "NAME EXIT\n" "CMD quit\n\n"\ - "NAME GREP\n" "CMD lastlog -r &2\n\n"\ + "NAME GREP\n" "CMD lastlog -r -- &2\n\n"\ "NAME IGNALL\n" "CMD ignore %2!*@* ALL\n\n"\ "NAME J\n" "CMD join &2\n\n"\ "NAME KILL\n" "CMD quote KILL %2 :&3\n\n"\ diff --git a/src/common/xchat.h b/src/common/xchat.h index a5b854af..d9a64d68 100644 --- a/src/common/xchat.h +++ b/src/common/xchat.h @@ -347,6 +347,15 @@ struct xchatprefs #define SET_ON 1 #define SET_DEFAULT 2 /* use global setting */ +/* Moved from fe-gtk for use in outbound.c as well -- */ +typedef enum gtk_xtext_search_flags_e { + case_match = 1, + backward = 2, + highlight = 4, + follow = 8, + regexp = 16 +} gtk_xtext_search_flags; + typedef struct session { /* Per-Channel Alerts */ @@ -406,7 +415,7 @@ typedef struct session int end_of_names:1; int doing_who:1; /* /who sent on this channel */ int done_away_check:1; /* done checking for away status changes */ - unsigned int lastlog_regexp:1; /* this is a lastlog and using regexp */ + gtk_xtext_search_flags lastlog_flags; } session; struct msproxy_state_t diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c index cb9c0376..ad401bca 100644 --- a/src/fe-gtk/fe-gtk.c +++ b/src/fe-gtk/fe-gtk.c @@ -718,50 +718,48 @@ fe_beep (void) gdk_beep (); } -static int -lastlog_regex_cmp (char *a, GRegex *reg) -{ - GMatchInfo *gmi; - int ret; - - g_regex_match (reg, a, 0, &gmi); - ret = (g_match_info_matches (gmi))? TRUE: FALSE; - g_match_info_free (gmi); - return ret; -} - void -fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gboolean regexp) +fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gtk_xtext_search_flags flags) { - GRegex *search_re = NULL; GError *err = NULL; + xtext_buffer *buf, *lbuf; - if (gtk_xtext_is_empty (sess->res->buffer)) + buf = sess->res->buffer; + + if (gtk_xtext_is_empty (buf)) { PrintText (lastlog_sess, _("Search buffer is empty.\n")); return; } - if (!regexp) + lbuf = lastlog_sess->res->buffer; + if (flags & regexp) { - gtk_xtext_lastlog (lastlog_sess->res->buffer, sess->res->buffer, - (void *) nocasestrstr, sstr); - return; - } + GRegexCompileFlags gcf = (flags & case_match)? 0: G_REGEX_CASELESS; - /* TODO: add arg 'match' and if it's TRUE don't use G_REGEX_CASELESS - * and for that matter don't use nocasesetrstr() above either */ - search_re = g_regex_new (sstr, G_REGEX_CASELESS, 0, &err); - if (err) + lbuf->search_re = g_regex_new (sstr, gcf, 0, &err); + if (err) + { + PrintText (lastlog_sess, _(err->message)); + g_error_free (err); + return; + } + } + else { - PrintText (lastlog_sess, _(err->message)); - g_error_free (err); - return; + if (flags & case_match) + { + lbuf->search_nee = g_strdup (sstr); + } + else + { + lbuf->search_nee = g_utf8_casefold (sstr, strlen (sstr)); + } + lbuf->search_lnee = strlen (lbuf->search_nee); } - - gtk_xtext_lastlog (lastlog_sess->res->buffer, sess->res->buffer, - (void *) lastlog_regex_cmp, search_re); - g_regex_unref (search_re); + lbuf->search_flags = flags; + lbuf->search_text = strdup (sstr); + gtk_xtext_lastlog (lbuf, buf); } void diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c index 2bca63c8..a02ec284 100644 --- a/src/fe-gtk/menu.c +++ b/src/fe-gtk/menu.c @@ -1235,7 +1235,7 @@ menu_search_prev () xtext_buffer *buf = xtext->buffer; if (!gtk_xtext_search(xtext, buf->search_text, - (buf->search_flags & (case_match | follow | regexp) | backward), NULL)) + (buf->search_flags & (case_match | follow | regexp)) | backward, NULL)) { fe_message (_("Search hit end, not found."), FE_MSG_ERROR); } diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c index 38ae2a89..585555b1 100644 --- a/src/fe-gtk/xtext.c +++ b/src/fe-gtk/xtext.c @@ -183,7 +183,8 @@ gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf, static gboolean gtk_xtext_check_ent_visibility (GtkXText * xtext, textentry *find_ent, int add); static int gtk_xtext_render_page_timeout (GtkXText * xtext); static int gtk_xtext_search_offset (xtext_buffer *buf, textentry *ent, unsigned int off); -static void gtk_xtext_search_textentry (xtext_buffer *, textentry *, int); +static GList * gtk_xtext_search_textentry (xtext_buffer *, textentry *); +static void gtk_xtext_search_textentry_add (xtext_buffer *, textentry *, GList *, gboolean); static void gtk_xtext_search_textentry_del (xtext_buffer *, textentry *); static void gtk_xtext_search_textentry_fini (gpointer, gpointer); static void gtk_xtext_search_fini (xtext_buffer *); @@ -5226,8 +5227,8 @@ gtk_xtext_unstrip_color (gint start, gint end, GSList *slp, GList **gl, gint max } /* Search a single textentry for occurrence(s) of search arg string */ -static void -gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent, int pre) +static GList * +gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent) { gchar *str; /* text string to be searched */ GList *gl = NULL; @@ -5236,7 +5237,7 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent, int pre) if (buf->search_text == NULL) { - return; + return gl; } str = gtk_xtext_strip_color (ent->str, ent->str_len, buf->xtext->scratch_buffer, @@ -5250,7 +5251,7 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent, int pre) if (buf->search_re == NULL) { - return; + return gl; } g_regex_match (buf->search_re, str, 0, &gmi); while (g_match_info_matches (gmi)) @@ -5289,6 +5290,13 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent, int pre) /* Common processing --- */ g_slist_free (slp); + return gl; +} + +/* Add a list of found search results to an entry, maybe NULL */ +static void +gtk_xtext_search_textentry_add (xtext_buffer *buf, textentry *ent, GList *gl, gboolean pre) +{ ent->marks = gl; if (gl) { @@ -5298,7 +5306,6 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent, int pre) buf->hintsearch = ent; } } - return; } /* Free all search information for a textentry */ @@ -5424,7 +5431,10 @@ gtk_xtext_search (GtkXText * xtext, const gchar *text, gtk_xtext_search_flags fl ent = gl? gl->data: buf->text_first; for (; ent; ent = ent->next) { - gtk_xtext_search_textentry (buf, ent, FALSE); + GList *gl; + + gl = gtk_xtext_search_textentry (buf, ent); + gtk_xtext_search_textentry_add (buf, ent, gl, FALSE); } } buf->search_flags = flags; @@ -5448,7 +5458,10 @@ gtk_xtext_search (GtkXText * xtext, const gchar *text, gtk_xtext_search_flags fl } for (ent = buf->text_first; ent; ent = ent->next) { - gtk_xtext_search_textentry (buf, ent, TRUE); + GList *gl; + + gl = gtk_xtext_search_textentry (buf, ent); + gtk_xtext_search_textentry_add (buf, ent, gl, TRUE); } buf->search_found = g_list_reverse (buf->search_found); } @@ -5661,7 +5674,10 @@ gtk_xtext_append_entry (xtext_buffer *buf, textentry * ent, time_t stamp) } if (buf->search_flags & follow) { - gtk_xtext_search_textentry (buf, ent, FALSE); + GList *gl; + + gl = gtk_xtext_search_textentry (buf, ent); + gtk_xtext_search_textentry_add (buf, ent, gl, FALSE); } } @@ -5764,30 +5780,41 @@ gtk_xtext_is_empty (xtext_buffer *buf) return buf->text_first == NULL; } + int -gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area, - int (*cmp_func) (char *, void *), void *userdata) +gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area) { - textentry *ent = search_area->text_first; - int matches = 0; + textentry *ent; + int matches; + GList *gl; + + ent = search_area->text_first; + matches = 0; while (ent) { - if (cmp_func (ent->str, userdata)) + gl = gtk_xtext_search_textentry (out, ent); + if (gl) { matches++; /* copy the text over */ if (search_area->xtext->auto_indent) + { gtk_xtext_append_indent (out, ent->str, ent->left_len, ent->str + ent->left_len + 1, ent->str_len - ent->left_len - 1, 0); + } else + { gtk_xtext_append (out, ent->str, ent->str_len); - /* copy the timestamp over */ + } + out->text_last->stamp = ent->stamp; + gtk_xtext_search_textentry_add (out, out->text_last, gl, TRUE); } ent = ent->next; } + out->search_found = g_list_reverse (out->search_found); return matches; } diff --git a/src/fe-gtk/xtext.h b/src/fe-gtk/xtext.h index 6c126346..48c71d0c 100644 --- a/src/fe-gtk/xtext.h +++ b/src/fe-gtk/xtext.h @@ -43,13 +43,6 @@ typedef struct _GtkXText GtkXText; typedef struct _GtkXTextClass GtkXTextClass; typedef struct textentry textentry; -typedef enum gtk_xtext_search_flags_e { - case_match = 1, - backward = 2, - highlight = 4, - follow = 8, - regexp = 16 -} gtk_xtext_search_flags; typedef struct { GtkXText *xtext; /* attached to this widget */ @@ -263,7 +256,7 @@ void gtk_xtext_set_palette (GtkXText * xtext, GdkColor palette[]); void gtk_xtext_clear (xtext_buffer *buf, int lines); void gtk_xtext_save (GtkXText * xtext, int fh); void gtk_xtext_refresh (GtkXText * xtext, int do_trans); -int gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area, int (*cmp_func) (char *, void *userdata), void *userdata); +int gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area); textentry *gtk_xtext_search (GtkXText * xtext, const gchar *text, gtk_xtext_search_flags flags, GError **err); void gtk_xtext_reset_marker_pos (GtkXText *xtext); void gtk_xtext_check_marker_visibility(GtkXText *xtext);