diff options
Diffstat (limited to 'sediff/find_dialog.c')
-rw-r--r-- | sediff/find_dialog.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/sediff/find_dialog.c b/sediff/find_dialog.c new file mode 100644 index 0000000..7bc3c07 --- /dev/null +++ b/sediff/find_dialog.c @@ -0,0 +1,184 @@ +/** + * @file + * Display a dialog to let the user search through results. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * @author Brandon Whalen bwhalen@tresys.com + * @author Randy Wicks rwicks@tresys.com + * + * Copyright (C) 2005-2007 Tresys Technology, LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> + +#include "find_dialog.h" +#include "utilgui.h" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <gdk/gdkkeysyms.h> +#include <glade/glade.h> + +struct find_dialog +{ + toplevel_t *top; + GladeXML *xml; + /** offset to start searching from if searching up and the + * start of the offset to select from */ + gint start_offset; + /** the offset to start searching from if searching down and + * the offset to end selecting from */ + gint end_offset; + /** the main window */ + GtkDialog *w; + GtkEntry *entry; + GtkRadioButton *forward, *reverse; +}; + +static void find_dialog_search(find_dialog_t * f) +{ + GtkTextView *view = toplevel_get_text_view(f->top); + GtkTextBuffer *tb = gtk_text_view_get_buffer(view); + GtkTextMark *mark = gtk_text_buffer_get_insert(tb); + GtkTextIter iter, start, end; + const gchar *search_text = gtk_entry_get_text(f->entry); + gboolean text_found; + /* if nothing is selected then start the search from the + * cursor. otherwise, if searching forward then start search + * at the end of the selection, else set start to beginning of + * selection */ + if (!gtk_text_buffer_get_selection_bounds(tb, &start, &end)) { + gtk_text_buffer_get_iter_at_mark(tb, &iter, mark); + } else { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->forward))) { + iter = end; + } else { + iter = start; + } + } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->forward))) { + text_found = gtk_text_iter_forward_search(&iter, search_text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start, &end, NULL); + if (!text_found) { + /* wrap search */ + gtk_text_buffer_get_start_iter(tb, &iter); + text_found = + gtk_text_iter_forward_search(&iter, search_text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start, &end, NULL); + } + } else { + text_found = gtk_text_iter_backward_search(&iter, search_text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start, &end, NULL); + if (!text_found) { + /* wrap search */ + gtk_text_buffer_get_end_iter(tb, &iter); + text_found = + gtk_text_iter_backward_search(&iter, search_text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start, &end, NULL); + } + } + if (!text_found) { + GString *string = g_string_new(""); + g_string_printf(string, "Text \"%s\" not found.", search_text); + util_message(GTK_WINDOW(f->w), GTK_MESSAGE_INFO, string->str); + g_string_free(string, TRUE); + } else { + gtk_text_view_scroll_to_iter(view, &start, 0.0, FALSE, 0.0, 0.5); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->forward))) { + gtk_text_buffer_select_range(tb, &end, &start); + } else { + gtk_text_buffer_select_range(tb, &start, &end); + } + } +} + +static void find_dialog_on_response(GtkDialog * dialog __attribute__ ((unused)), gint response, gpointer user_data) +{ + find_dialog_t *f = (find_dialog_t *) user_data; + if (response == GTK_RESPONSE_CLOSE) { + gtk_widget_hide(GTK_WIDGET(f->w)); + } else if (response == GTK_RESPONSE_OK) { + find_dialog_search(f); + } +} + +static gboolean find_dialog_on_key_press_event(GtkWidget * widget __attribute__ ((unused)), GdkEventKey * event, gpointer user_data) +{ + find_dialog_t *f = (find_dialog_t *) user_data; + if (event->keyval == GDK_Escape) { + gtk_widget_hide(GTK_WIDGET(f->w)); + return TRUE; + } + return FALSE; +} + +static void find_dialog_on_entry_activate(GtkEntry * entry __attribute__ ((unused)), gpointer user_data) +{ + find_dialog_t *f = (find_dialog_t *) user_data; + find_dialog_search(f); +} + +find_dialog_t *find_dialog_create(toplevel_t * top) +{ + find_dialog_t *f; + int error = 0; + + if ((f = calloc(1, sizeof(*f))) == NULL) { + error = errno; + goto cleanup; + } + f->top = top; + f->xml = glade_xml_new(toplevel_get_glade_xml(f->top), "find_dialog", NULL); + + f->w = GTK_DIALOG(glade_xml_get_widget(f->xml, "find_dialog")); + assert(f->w != NULL); + gtk_window_set_transient_for(GTK_WINDOW(f->w), toplevel_get_window(f->top)); + g_signal_connect_swapped(G_OBJECT(f->w), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), f->w); + g_signal_connect(G_OBJECT(f->w), "response", G_CALLBACK(find_dialog_on_response), f); + g_signal_connect(G_OBJECT(f->w), "key-press-event", G_CALLBACK(find_dialog_on_key_press_event), f); + + f->entry = GTK_ENTRY(glade_xml_get_widget(f->xml, "find entry")); + f->forward = GTK_RADIO_BUTTON(glade_xml_get_widget(f->xml, "find forward radio")); + f->reverse = GTK_RADIO_BUTTON(glade_xml_get_widget(f->xml, "find reverse radio")); + assert(f->entry != NULL && f->forward != NULL && f->reverse != NULL); + + /* connect the text entry callback events */ + g_signal_connect(G_OBJECT(f->entry), "activate", G_CALLBACK(find_dialog_on_entry_activate), f); + + cleanup: + if (error != 0) { + find_dialog_destroy(&f); + errno = error; + return NULL; + } + return f; +} + +void find_dialog_destroy(find_dialog_t ** f) +{ + if (f != NULL && *f != NULL) { + free(*f); + *f = NULL; + } +} + +void find_dialog_show(find_dialog_t * f) +{ + gtk_widget_show(GTK_WIDGET(f->w)); + gtk_widget_grab_focus(GTK_WIDGET(f->entry)); + gtk_editable_set_position(GTK_EDITABLE(f->entry), -1); + gtk_editable_select_region(GTK_EDITABLE(f->entry), 0, -1); + gtk_window_present(GTK_WINDOW(f->w)); +} |