Search window improvements (Richard Hitt)

This commit is contained in:
Berke Viktor 2012-05-28 23:17:09 +02:00
parent 1f62507fc0
commit a6cc734b38
7 changed files with 861 additions and 168 deletions

View File

@ -451,6 +451,7 @@ const struct prefs vars[] = {
#endif #endif
{"gui_pane_left_size", P_OFFINT (gui_pane_left_size), TYPE_INT}, {"gui_pane_left_size", P_OFFINT (gui_pane_left_size), TYPE_INT},
{"gui_pane_right_size", P_OFFINT (gui_pane_right_size), TYPE_INT}, {"gui_pane_right_size", P_OFFINT (gui_pane_right_size), TYPE_INT},
{"gui_pane_right_size_min", P_OFFINT (gui_pane_right_size_min), TYPE_INT},
{"gui_quit_dialog", P_OFFINT (gui_quit_dialog), TYPE_BOOL}, {"gui_quit_dialog", P_OFFINT (gui_quit_dialog), TYPE_BOOL},
{"gui_slist_fav", P_OFFINT (slist_fav), TYPE_INT}, {"gui_slist_fav", P_OFFINT (slist_fav), TYPE_INT},
{"gui_slist_select", P_OFFINT (slist_select), TYPE_INT}, {"gui_slist_select", P_OFFINT (slist_select), TYPE_INT},
@ -589,6 +590,11 @@ const struct prefs vars[] = {
{"text_max_indent", P_OFFINT (max_auto_indent), TYPE_INT}, {"text_max_indent", P_OFFINT (max_auto_indent), TYPE_INT},
{"text_max_lines", P_OFFINT (max_lines), TYPE_INT}, {"text_max_lines", P_OFFINT (max_lines), TYPE_INT},
{"text_replay", P_OFFINT (text_replay), TYPE_BOOL}, {"text_replay", P_OFFINT (text_replay), TYPE_BOOL},
{"text_search_case_match", P_OFFINT (text_search_case_match), TYPE_BOOL},
{"text_search_backward", P_OFFINT (text_search_backward), TYPE_BOOL},
{"text_search_highlight_all", P_OFFINT (text_search_highlight_all), TYPE_BOOL},
{"text_search_follow", P_OFFINT (text_search_follow), TYPE_BOOL},
{"text_search_regexp", P_OFFINT (text_search_regexp), TYPE_BOOL},
{"text_show_marker", P_OFFINT (show_marker), TYPE_BOOL}, {"text_show_marker", P_OFFINT (show_marker), TYPE_BOOL},
{"text_show_sep", P_OFFINT (show_separator), TYPE_BOOL}, {"text_show_sep", P_OFFINT (show_separator), TYPE_BOOL},
{"text_spell_langs", P_OFFSET (spell_langs), TYPE_STR}, {"text_spell_langs", P_OFFSET (spell_langs), TYPE_STR},
@ -715,6 +721,7 @@ load_config (void)
prefs.gui_tray = 1; prefs.gui_tray = 1;
prefs.gui_pane_left_size = 100; prefs.gui_pane_left_size = 100;
prefs.gui_pane_right_size = 100; prefs.gui_pane_right_size = 100;
prefs.gui_pane_right_size_min = 80;
prefs.mainwindow_save = 1; prefs.mainwindow_save = 1;
prefs.bantype = 2; prefs.bantype = 2;
prefs.input_balloon_time = 20; prefs.input_balloon_time = 20;
@ -723,6 +730,7 @@ load_config (void)
prefs.autodccsend = 2; /* browse mode */ prefs.autodccsend = 2; /* browse mode */
prefs.url_grabber = 1; prefs.url_grabber = 1;
prefs.url_grabber_limit = 0; /* 0 means unlimited for backcompat */ prefs.url_grabber_limit = 0; /* 0 means unlimited for backcompat */
prefs.text_search_follow = 1;
#ifdef WIN32 #ifdef WIN32
prefs.identd = 1; prefs.identd = 1;
#endif #endif

View File

@ -162,6 +162,7 @@ struct xchatprefs
int gui_pane_left_size; int gui_pane_left_size;
int gui_pane_right_size; int gui_pane_right_size;
int gui_pane_right_size_min;
int gui_ulist_pos; int gui_ulist_pos;
int tab_pos; int tab_pos;
@ -327,6 +328,11 @@ struct xchatprefs
This is so that we continue using internal defaults (which can This is so that we continue using internal defaults (which can
change in the next release) until the user edits them. */ change in the next release) until the user edits them. */
unsigned int save_pevents:1; unsigned int save_pevents:1;
unsigned int text_search_case_match;
unsigned int text_search_backward;
unsigned int text_search_highlight_all;
unsigned int text_search_follow;
unsigned int text_search_regexp;
}; };
/* Session types */ /* Session types */

View File

@ -800,6 +800,9 @@ mg_userlist_showhide (session *sess, int show)
{ {
session_gui *gui = sess->gui; session_gui *gui = sess->gui;
int handle_size; int handle_size;
int right_size;
right_size = MAX (prefs.gui_pane_right_size, prefs.gui_pane_right_size_min);
if (show) if (show)
{ {
@ -807,7 +810,7 @@ mg_userlist_showhide (session *sess, int show)
gui->ul_hidden = 0; gui->ul_hidden = 0;
gtk_widget_style_get (GTK_WIDGET (gui->hpane_right), "handle-size", &handle_size, NULL); gtk_widget_style_get (GTK_WIDGET (gui->hpane_right), "handle-size", &handle_size, NULL);
gtk_paned_set_position (GTK_PANED (gui->hpane_right), GTK_WIDGET (gui->hpane_right)->allocation.width - (prefs.gui_pane_right_size + handle_size)); gtk_paned_set_position (GTK_PANED (gui->hpane_right), GTK_WIDGET (gui->hpane_right)->allocation.width - (right_size + handle_size));
} }
else else
{ {
@ -2848,7 +2851,7 @@ mg_create_entry (session *sess, GtkWidget *box)
#else #else
gui->input_box = entry = gtk_entry_new (); gui->input_box = entry = gtk_entry_new ();
#endif #endif
gtk_entry_set_max_length (GTK_ENTRY (gui->input_box), 2048); gtk_entry_set_max_length (GTK_ENTRY (gui->input_box), 0);
g_signal_connect (G_OBJECT (entry), "activate", g_signal_connect (G_OBJECT (entry), "activate",
G_CALLBACK (mg_inputbox_cb), gui); G_CALLBACK (mg_inputbox_cb), gui);
gtk_container_add (GTK_CONTAINER (hbox), entry); gtk_container_add (GTK_CONTAINER (hbox), entry);

View File

@ -1215,6 +1215,41 @@ menu_search ()
search_open (current_sess); search_open (current_sess);
} }
static void
menu_search_next ()
{
GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
xtext_buffer *buf = xtext->buffer;
if (!gtk_xtext_search (xtext, buf->search_text,
(buf->search_flags & (case_match | follow | regexp)), NULL))
{
fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
}
}
static void
menu_search_prev ()
{
GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
xtext_buffer *buf = xtext->buffer;
if (!gtk_xtext_search(xtext, buf->search_text,
(buf->search_flags & (case_match | follow | regexp) | backward), NULL))
{
fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
}
}
static void
menu_search_reset ()
{
GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
xtext_buffer *buf = xtext->buffer;
gtk_xtext_search (xtext, "", 0, NULL);
}
static void static void
menu_resetmarker (GtkWidget * wid, gpointer none) menu_resetmarker (GtkWidget * wid, gpointer none)
{ {
@ -1675,11 +1710,17 @@ static struct mymenu mymenu[] = {
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m}, {N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m},
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_C}, {N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_C},
{N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l}, {N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l},
#define SEARCH_OFFSET 68
{N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
{N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1}, {N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1},
#define SEARCH_OFFSET 70
{N_("Search"), 0, GTK_STOCK_JUSTIFY_LEFT, M_MENUSUB, 0, 0, 1},
{N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
{N_("Reset Search"), menu_search_reset, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_F},
{N_("Search Next" ), menu_search_next, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_g},
{N_("Search Previous" ), menu_search_prev, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_G},
{0, 0, 0, M_END, 0, 0, 0},
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 70 */
{N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1}, {N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1},
#if 0 #if 0
{N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1}, {N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1},

View File

@ -42,15 +42,20 @@
#include "xtext.h" #include "xtext.h"
#include "maingui.h" #include "maingui.h"
GtkWidget *searchwin;
static textentry *last; /* our last search pos */
static int case_match = 0;
static int search_backward = 0;
static void static void
search_search (session * sess, const gchar *text) search_search (session * sess, const gchar *text)
{ {
gtk_xtext_search_flags flags;
textentry *last;
GError *err = NULL;
flags = ((prefs.text_search_case_match == 1? case_match: 0) |
(prefs.text_search_backward == 1? backward: 0) |
(prefs.text_search_highlight_all == 1? highlight: 0) |
(prefs.text_search_follow == 1? follow: 0) |
(prefs.text_search_regexp == 1? regexp: 0));
if (!is_session (sess)) if (!is_session (sess))
{ {
fe_message (_("The window you opened this Search " fe_message (_("The window you opened this Search "
@ -58,10 +63,20 @@ search_search (session * sess, const gchar *text)
return; return;
} }
last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text, last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text, flags, &err);
last, case_match, search_backward); if (text == NULL || text[0] == 0)
if (!last) {
return;
}
if (err)
{
fe_message (_(err->message), FE_MSG_ERROR);
g_error_free (err);
}
else if (!last)
{
fe_message (_("Search hit end, not found."), FE_MSG_ERROR); fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
}
} }
static void static void
@ -79,6 +94,23 @@ static void
search_close_cb (GtkWidget * button, GtkWidget * win) search_close_cb (GtkWidget * button, GtkWidget * win)
{ {
gtk_widget_destroy (win); gtk_widget_destroy (win);
searchwin = NULL;
}
static void
search_reset_cb (GtkWidget * button, session * sess)
{
search_search (sess, "");
if (searchwin)
{
search_close_cb (button, searchwin);
}
}
static void
search_cleanup_cb (GtkWidget * button, GtkWidget * win)
{
searchwin = NULL;
} }
static void static void
@ -98,13 +130,26 @@ search_key_cb (GtkWidget * window, GdkEventKey * key, gpointer userdata)
static void static void
search_caseign_cb (GtkToggleButton * but, session * sess) search_caseign_cb (GtkToggleButton * but, session * sess)
{ {
case_match = (but->active)? 1: 0; prefs.text_search_case_match = (but->active)? 1: 0;
} }
static void static void
search_dirbwd_cb (GtkToggleButton * but, session * sess) search_dirbwd_cb (GtkToggleButton * but, session * sess)
{ {
search_backward = (but->active)? 1: 0; prefs.text_search_backward = (but->active)? 1: 0;
}
static void
search_regexp_cb (GtkToggleButton * but, session * sess)
{
prefs.text_search_regexp = (but->active)? 1: 0;
}
static void
search_highlight_cb (GtkToggleButton * but, session * sess)
{
prefs.text_search_highlight_all = (but->active)? 1: 0;
search_search (sess, NULL);
} }
void void
@ -112,18 +157,21 @@ search_open (session * sess)
{ {
GtkWidget *win, *hbox, *vbox, *entry, *wid; GtkWidget *win, *hbox, *vbox, *entry, *wid;
last = NULL; if (searchwin)
{
gtk_widget_destroy (searchwin);
searchwin = NULL;
}
win = mg_create_generic_tab ("search", _("XChat: Search"), TRUE, FALSE, win = mg_create_generic_tab ("search", _("XChat: Search"), TRUE, FALSE,
NULL, NULL, 0, 0, &vbox, 0); search_cleanup_cb, NULL, 0, 0, &vbox, 0);
gtk_container_set_border_width (GTK_CONTAINER (win), 12); gtk_container_set_border_width (GTK_CONTAINER (win), 12);
gtk_box_set_spacing (GTK_BOX (vbox), 4); gtk_box_set_spacing (GTK_BOX (vbox), 4);
/* First line: _____________________ _Find */
hbox = gtk_hbox_new (0, 10); hbox = gtk_hbox_new (0, 10);
gtk_container_add (GTK_CONTAINER (vbox), hbox); gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_widget_show (hbox); gtk_widget_show (hbox);
gtkutil_label_new (_("Find:"), hbox);
entry = gtk_entry_new (); entry = gtk_entry_new ();
g_signal_connect (G_OBJECT (entry), "activate", g_signal_connect (G_OBJECT (entry), "activate",
G_CALLBACK (search_entry_cb), sess); G_CALLBACK (search_entry_cb), sess);
@ -131,29 +179,61 @@ search_open (session * sess)
gtk_widget_show (entry); gtk_widget_show (entry);
gtk_widget_grab_focus (entry); gtk_widget_grab_focus (entry);
wid = gtk_hbutton_box_new ();
gtk_container_add (GTK_CONTAINER (hbox), wid);
gtk_widget_show (wid);
wid = gtkutil_button (wid, GTK_STOCK_FIND, 0, search_find_cb, sess,
_("_Find"));
g_object_set_data (G_OBJECT (wid), "e", entry);
/* Second line: X Match case */
wid = gtk_check_button_new_with_mnemonic (_("_Match case")); wid = gtk_check_button_new_with_mnemonic (_("_Match case"));
GTK_TOGGLE_BUTTON (wid)->active = case_match; GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_case_match;
g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_caseign_cb), sess); g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_caseign_cb), sess);
gtk_container_add (GTK_CONTAINER (vbox), wid); gtk_container_add (GTK_CONTAINER (vbox), wid);
add_tip (wid, "Perform a case-sensitive search.");
gtk_widget_show (wid); gtk_widget_show (wid);
/* Third line: X Search backwards */
wid = gtk_check_button_new_with_mnemonic (_("Search _backwards")); wid = gtk_check_button_new_with_mnemonic (_("Search _backwards"));
GTK_TOGGLE_BUTTON (wid)->active = search_backward; GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_backward;
g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_dirbwd_cb), sess); g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_dirbwd_cb), sess);
gtk_container_add (GTK_CONTAINER (vbox), wid); gtk_container_add (GTK_CONTAINER (vbox), wid);
add_tip (wid, "Search from the newest text line to the oldest.");
gtk_widget_show (wid); gtk_widget_show (wid);
/* Fourth line: X Highlight all */
wid = gtk_check_button_new_with_mnemonic (_("_Highlight all"));
GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_highlight_all;
g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_highlight_cb), sess);
gtk_container_add (GTK_CONTAINER (vbox), wid);
add_tip (wid, "Highlight all occurrences, and underline the current occurrence.");
gtk_widget_show (wid);
/* Fifth line: X Regular expression */
wid = gtk_check_button_new_with_mnemonic (_("R_egular expression"));
GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_regexp;
g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_regexp_cb), sess);
gtk_container_add (GTK_CONTAINER (vbox), wid);
add_tip (wid, "Regard search string as a regular expression.");
gtk_widget_show (wid);
/* Sixth line: _Close Close and _Reset */
hbox = gtk_hbutton_box_new (); hbox = gtk_hbutton_box_new ();
gtk_box_pack_start (GTK_BOX (vbox), hbox, 0, 0, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, 0, 0, 4);
gtk_widget_show (hbox); gtk_widget_show (hbox);
gtkutil_button (hbox, GTK_STOCK_CLOSE, 0, search_close_cb, win, wid = gtkutil_button (hbox, GTK_STOCK_CLOSE, 0, search_close_cb, win,
_("_Close")); _("_Close"));
wid = gtkutil_button (hbox, GTK_STOCK_FIND, 0, search_find_cb, sess, add_tip (wid, "Close this box, but continue searching new lines.");
_("_Find")); wid = gtkutil_button (hbox, "gtk-reset", 0, search_reset_cb, sess,
g_object_set_data (G_OBJECT (wid), "e", entry); _("Close and _Reset"));
add_tip (wid, "Close this box, reset highlighted search items, and stop searching new lines.");
/* Add recognition of the ESC key to close the box */
g_signal_connect (G_OBJECT (win), "key_press_event", G_CALLBACK (search_key_cb), win); g_signal_connect (G_OBJECT (win), "key_press_event", G_CALLBACK (search_key_cb), win);
/* That's all, folks */
searchwin = win;
gtk_widget_show (win); gtk_widget_show (win);
} }

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,13 @@
typedef struct _GtkXText GtkXText; typedef struct _GtkXText GtkXText;
typedef struct _GtkXTextClass GtkXTextClass; typedef struct _GtkXTextClass GtkXTextClass;
typedef struct textentry textentry; 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 { typedef struct {
GtkXText *xtext; /* attached to this widget */ GtkXText *xtext; /* attached to this widget */
@ -77,6 +84,16 @@ typedef struct {
unsigned int grid_dirty:1; unsigned int grid_dirty:1;
unsigned int marker_seen:1; unsigned int marker_seen:1;
unsigned int reset_marker_pos:1; unsigned int reset_marker_pos:1;
GList *search_found; /* list of textentries where search found strings */
gchar *search_text; /* desired text to search for */
gchar *search_nee; /* prepared needle to look in haystack for */
gint search_lnee; /* its length */
gtk_xtext_search_flags search_flags; /* match, bwd, highlight */
GList *cursearch; /* GList whose 'data' pts to current textentry */
GList *curmark; /* current item in ent->marks */
GRegex *search_re; /* Compiled regular expression */
textentry *hintsearch; /* textentry found for last search */
} xtext_buffer; } xtext_buffer;
struct _GtkXText struct _GtkXText
@ -247,7 +264,7 @@ void gtk_xtext_clear (xtext_buffer *buf, int lines);
void gtk_xtext_save (GtkXText * xtext, int fh); void gtk_xtext_save (GtkXText * xtext, int fh);
void gtk_xtext_refresh (GtkXText * xtext, int do_trans); 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, int (*cmp_func) (char *, void *userdata), void *userdata);
textentry *gtk_xtext_search (GtkXText * xtext, const gchar *text, textentry *start, gboolean case_match, gboolean backward); 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_reset_marker_pos (GtkXText *xtext);
void gtk_xtext_check_marker_visibility(GtkXText *xtext); void gtk_xtext_check_marker_visibility(GtkXText *xtext);