summary refs log tree commit diff stats
path: root/src/fe-gtk/maingui.c
diff options
context:
space:
mode:
authorTingPing <tingping@tingping.se>2013-07-24 20:47:01 -0400
committerTingPing <tingping@tingping.se>2013-09-15 02:51:35 -0400
commitb0b8f40791de39eb6a7ee301d2edada80ad32338 (patch)
treebe583b2313d19eba71cd8582dab664e2c4da4736 /src/fe-gtk/maingui.c
parentaa37686bbd69a6fab9dea6492a2f6a8b818845f0 (diff)
Replace search window with a searchbar
Diffstat (limited to 'src/fe-gtk/maingui.c')
-rw-r--r--src/fe-gtk/maingui.c198
1 files changed, 197 insertions, 1 deletions
diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c
index 2a486b17..91bc9d6f 100644
--- a/src/fe-gtk/maingui.c
+++ b/src/fe-gtk/maingui.c
@@ -21,6 +21,8 @@
 #include <stdio.h>
 #include <ctype.h>
 
+#include <gdk/gdkkeysyms.h>
+
 #include "../common/hexchat.h"
 #include "../common/fe.h"
 #include "../common/server.h"
@@ -33,6 +35,7 @@
 #include "../common/util.h"
 #include "../common/text.h"
 #include "../common/chanopt.h"
+#include "../common/cfgfiles.h"
 
 #include "fe-gtk.h"
 #include "banlist.h"
@@ -77,6 +80,7 @@ enum
 #define TAG_UTIL 1	/* dcc, notify, chanlist */
 
 static void mg_create_entry (session *sess, GtkWidget *box);
+static void mg_create_search (session *sess, GtkWidget *box);
 static void mg_link_irctab (session *sess, int focus);
 
 static session_gui static_mg_gui;
@@ -2619,7 +2623,18 @@ mg_create_center (session *sess, session_gui *gui, GtkWidget *box)
 	vbox = gtk_vbox_new (FALSE, 3);
 	gtk_notebook_append_page (GTK_NOTEBOOK (book), vbox, NULL);
 	mg_create_topicbar (sess, vbox);
-	mg_create_textarea (sess, vbox);
+
+	if (prefs.hex_gui_search_pos)
+	{
+		mg_create_search (sess, vbox);
+		mg_create_textarea (sess, vbox);
+	}
+	else
+	{
+		mg_create_textarea (sess, vbox);
+		mg_create_search (sess, vbox);
+	}
+
 	mg_create_entry (sess, vbox);
 
 	mg_add_pane_signals (gui);
@@ -2814,6 +2829,183 @@ mg_inputbox_rightclick (GtkEntry *entry, GtkWidget *menu)
 	mg_create_color_menu (menu, NULL);
 }
 
+/* Search bar adapted from Conspire's by William Pitcock */
+
+#define SEARCH_CHANGE		1
+#define SEARCH_NEXT			2
+#define SEARCH_PREVIOUS		3
+#define SEARCH_REFRESH		4
+
+static void
+search_handle_event(int search_type, session *sess)
+{
+	textentry *last;
+	const gchar *text = NULL;
+	gtk_xtext_search_flags flags;
+	GError *err = NULL;
+	gboolean backwards = FALSE;
+
+	/* When just typing show most recent first */
+	if (search_type == SEARCH_PREVIOUS || search_type == SEARCH_CHANGE)
+		backwards = TRUE;
+
+	flags = ((prefs.hex_text_search_case_match == 1? case_match: 0) |
+				(backwards? backward: 0) |
+				(prefs.hex_text_search_highlight_all == 1? highlight: 0) |
+				(prefs.hex_text_search_follow == 1? follow: 0) |
+				(prefs.hex_text_search_regexp == 1? regexp: 0));
+
+	if (search_type != SEARCH_REFRESH)
+		text = gtk_entry_get_text (GTK_ENTRY(sess->gui->shentry));
+	last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text, flags, &err);
+
+	if (err)
+	{
+		gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
+		gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _(err->message));
+		g_error_free (err);
+	}
+	else if (!last)
+	{
+		/* Either end of search or not found, try again to wrap if only end */
+		last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text, flags, &err);
+		if (!last) /* Not found error */
+		{
+			gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
+			gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _("No results found."));
+		}
+	}
+	else
+	{
+		gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);	
+	}
+}
+
+static void
+search_handle_change(GtkWidget *wid, session *sess)
+{
+	search_handle_event(SEARCH_CHANGE, sess);
+}
+
+static void
+search_handle_refresh(GtkWidget *wid, session *sess)
+{
+	search_handle_event(SEARCH_REFRESH, sess);
+}
+
+void
+mg_search_handle_previous(GtkWidget *wid, session *sess)
+{
+	search_handle_event(SEARCH_PREVIOUS, sess);
+}
+
+void
+mg_search_handle_next(GtkWidget *wid, session *sess)
+{
+	search_handle_event(SEARCH_NEXT, sess);
+}
+
+static void
+search_set_option (GtkToggleButton *but, guint *pref)
+{
+	*pref = gtk_toggle_button_get_active(but);
+	save_config();
+}
+
+void
+mg_search_toggle(session *sess)
+{
+	if (gtk_widget_get_visible(sess->gui->shbox))
+	{
+		gtk_widget_hide(sess->gui->shbox);
+		gtk_widget_grab_focus(sess->gui->input_box);
+		gtk_entry_set_text(GTK_ENTRY(sess->gui->shentry), "");
+	}
+	else
+	{
+		/* Reset search state */
+		gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
+
+		/* Show and focus */
+		gtk_widget_show(sess->gui->shbox);
+		gtk_widget_grab_focus(sess->gui->shentry);
+	}
+}
+
+static gboolean
+search_handle_esc (GtkWidget *win, GdkEventKey *key, session *sess)
+{
+	if (key->keyval == GDK_KEY_Escape)
+		mg_search_toggle(sess);
+			
+	return FALSE;
+}
+
+static void
+mg_create_search(session *sess, GtkWidget *box)
+{
+	GtkWidget *entry, *label, *next, *previous, *highlight, *matchcase, *regex, *close;
+	session_gui *gui = sess->gui;
+
+	gui->shbox = gtk_hbox_new(FALSE, 5);
+	gtk_box_pack_start(GTK_BOX(box), gui->shbox, FALSE, FALSE, 0);
+
+	close = gtk_button_new ();
+	gtk_button_set_image (GTK_BUTTON (close), gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
+	gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE);
+	gtk_widget_set_can_focus (close, FALSE);
+	gtk_box_pack_start(GTK_BOX(gui->shbox), close, FALSE, FALSE, 0);
+	g_signal_connect_swapped(G_OBJECT(close), "clicked", G_CALLBACK(mg_search_toggle), sess);
+
+	label = gtk_label_new(_("Find:"));
+	gtk_box_pack_start(GTK_BOX(gui->shbox), label, FALSE, FALSE, 0);
+
+	gui->shentry = entry = gtk_entry_new();
+	gtk_box_pack_start(GTK_BOX(gui->shbox), entry, FALSE, FALSE, 0);
+	gtk_widget_set_size_request (gui->shentry, 180, -1);
+	gui->search_changed_signal = g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(search_handle_change), sess);
+	g_signal_connect (G_OBJECT (entry), "key_press_event", G_CALLBACK (search_handle_esc), sess);
+	g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(mg_search_handle_next), sess);
+	gtk_entry_set_icon_activatable (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, FALSE);
+	gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _("Search hit end or not found."));
+
+	previous = gtk_button_new ();
+	gtk_button_set_image (GTK_BUTTON (previous), gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU));
+	gtk_button_set_relief(GTK_BUTTON(previous), GTK_RELIEF_NONE);
+	gtk_widget_set_can_focus (previous, FALSE);
+	gtk_box_pack_start(GTK_BOX(gui->shbox), previous, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(previous), "clicked", G_CALLBACK(mg_search_handle_previous), sess);
+
+	next = gtk_button_new ();
+	gtk_button_set_image (GTK_BUTTON (next), gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU));
+	gtk_button_set_relief(GTK_BUTTON(next), GTK_RELIEF_NONE);
+	gtk_widget_set_can_focus (next, FALSE);
+	gtk_box_pack_start(GTK_BOX(gui->shbox), next, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(next), "clicked", G_CALLBACK(mg_search_handle_next), sess);
+
+	highlight = gtk_check_button_new_with_mnemonic (_("Highlight _all"));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(highlight), prefs.hex_text_search_case_match);
+	gtk_widget_set_can_focus (highlight, FALSE);
+	g_signal_connect (G_OBJECT (highlight), "toggled", G_CALLBACK (search_set_option), &prefs.hex_text_search_highlight_all);
+	g_signal_connect (G_OBJECT (highlight), "toggled", G_CALLBACK (search_handle_refresh), sess);
+	gtk_box_pack_start(GTK_BOX(gui->shbox), highlight, FALSE, FALSE, 0);
+	add_tip (highlight, _("Highlight all occurrences, and underline the current occurrence."));
+
+	matchcase = gtk_check_button_new_with_mnemonic (_("Mat_ch case"));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(matchcase), prefs.hex_text_search_case_match);
+	gtk_widget_set_can_focus (matchcase, FALSE);
+	g_signal_connect (G_OBJECT (matchcase), "toggled", G_CALLBACK (search_set_option), &prefs.hex_text_search_case_match);
+	gtk_box_pack_start(GTK_BOX(gui->shbox), matchcase, FALSE, FALSE, 0);
+	add_tip (matchcase, _("Perform a case-sensitive search."));
+
+	regex = gtk_check_button_new_with_mnemonic (_("_Regex"));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(regex), prefs.hex_text_search_regexp);
+	gtk_widget_set_can_focus (regex, FALSE);
+	g_signal_connect (G_OBJECT (regex), "toggled", G_CALLBACK (search_set_option), &prefs.hex_text_search_regexp);
+	gtk_box_pack_start(GTK_BOX(gui->shbox), regex, FALSE, FALSE, 0);
+	add_tip (regex, _("Regard search string as a regular expression."));
+}
+
 static void
 mg_create_entry (session *sess, GtkWidget *box)
 {
@@ -3055,6 +3247,8 @@ mg_create_topwindow (session *sess)
 	if (!prefs.hex_gui_input_nick)
 		gtk_widget_hide (sess->gui->nick_box);
 
+	gtk_widget_hide(sess->gui->shbox);
+
 	mg_decide_userlist (sess, FALSE);
 
 	if (sess->type == SESS_DIALOG)
@@ -3158,6 +3352,8 @@ mg_create_tabwindow (session *sess)
 	if (!prefs.hex_gui_input_nick)
 		gtk_widget_hide (sess->gui->nick_box);
 
+	gtk_widget_hide (sess->gui->shbox);
+
 	mg_place_userlist_and_chanview (sess->gui);
 
 	gtk_widget_show (win);