From 3afd76608320f7fb890b166fcb3945e2c377a99f Mon Sep 17 00:00:00 2001 From: John Darrington Date: Sun, 14 Jun 2020 15:30:47 +0200 Subject: [PATCH] PSPPIRE: Add feature to search for text in the syntax window. --- NEWS | 5 +- src/ui/gui/psppire-syntax-window.c | 93 +++++++++++++++++++++++++++++- src/ui/gui/psppire-syntax-window.h | 3 + src/ui/gui/syntax-editor.ui | 6 ++ 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 7cb3c135b4..9e4c345fb2 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,5 @@ PSPP NEWS -- history of user-visible changes. -Copyright (C) 1996-2000, 2008-2016, 2017, 2019 Free Software Foundation, Inc. +Copyright (C) 1996-2000, 2008-2016, 2017, 2019, 2020 Free Software Foundation, Inc. See the end for copying conditions. Please send PSPP bug reports to bug-gnu-pspp@gnu.org. @@ -72,6 +72,9 @@ Changes from 1.2.0 to 1.3.0: sub-category as a percentage of the primary category instead of the total. + * The Syntax Window now has a Find function to perform simple text + searching. + * AUTORECODE: - The PRINT subcommand is now implemented. diff --git a/src/ui/gui/psppire-syntax-window.c b/src/ui/gui/psppire-syntax-window.c index c392fad870..3fecfad26a 100644 --- a/src/ui/gui/psppire-syntax-window.c +++ b/src/ui/gui/psppire-syntax-window.c @@ -1,5 +1,6 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014, 2016 Free Software Foundation + Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014, 2016, + 2020 Free Software Foundation 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 @@ -160,6 +161,8 @@ psppire_syntax_window_dispose (GObject *obj) if (sw->dispose_has_run) return; + g_object_unref (sw->search_text_buffer); + g_free (sw->encoding); sw->encoding = NULL; @@ -265,6 +268,86 @@ on_edit_delete (PsppireSyntaxWindow *sw) gtk_text_buffer_delete (buffer, &begin, &end); } +/* Create and run a dialog to collect the search string. + In future this might be expanded to include options, for example + backward searching, case sensitivity etc. */ +static const char * +get_search_text (PsppireSyntaxWindow *parent) +{ + const char *search_text = NULL; + GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL; + GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Text Search"), + GTK_WINDOW (parent), + flags, + _("_OK"), + GTK_RESPONSE_OK, + _("_Cancel"), + GTK_RESPONSE_CANCEL, + NULL); + + GtkWidget *content_area = + gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + + GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + GtkWidget *label = gtk_label_new (_("Text to search for:")); + GtkWidget *entry = gtk_entry_new_with_buffer (parent->search_text_buffer); + + /* Add the label, and show everything we have added. */ + gtk_container_add (GTK_CONTAINER (content_area), box); + gtk_container_add (GTK_CONTAINER (box), label); + gtk_container_add (GTK_CONTAINER (box), entry); + gtk_widget_show_all (content_area); + + int result = gtk_dialog_run (GTK_DIALOG (dialog)); + switch (result) + { + case GTK_RESPONSE_OK: + search_text = gtk_entry_get_text (GTK_ENTRY (entry)); + break; + default: + search_text = NULL; + }; + + gtk_widget_destroy (dialog); + return search_text; +} + + +/* What to do when the Find menuitem is called. */ +static void +on_edit_find (PsppireSyntaxWindow *sw) +{ + GtkTextBuffer *buffer = GTK_TEXT_BUFFER (sw->buffer); + GtkTextIter begin; + GtkTextIter loc; + const char *target = get_search_text (sw); + + if (target == NULL) + return; + + /* This is a wrap-around search. So start searching one + character after the current char. */ + GtkTextMark *mark = gtk_text_buffer_get_insert (buffer); + gtk_text_buffer_get_iter_at_mark (buffer, &begin, mark); + gtk_text_iter_forward_char (&begin); + if (gtk_text_iter_forward_search (&begin, target, 0, + &loc, 0, 0)) + { + gtk_text_buffer_place_cursor (buffer, &loc); + } + else + { + /* If not found, then continue the search from the top + of the buffer. */ + gtk_text_buffer_get_start_iter (buffer, &begin); + if (gtk_text_iter_forward_search (&begin, target, 0, + &loc, 0, 0)) + { + gtk_text_buffer_place_cursor (buffer, &loc); + } + } +} + /* The syntax editor's clipboard deals only with text */ enum { @@ -729,6 +812,7 @@ psppire_syntax_window_init (PsppireSyntaxWindow *window) window->cliptext = NULL; window->dispose_has_run = FALSE; + window->search_text_buffer = gtk_entry_buffer_new (NULL, -1); window->edit_delete = g_simple_action_new ("delete", NULL); g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (window->edit_delete)); @@ -742,6 +826,8 @@ psppire_syntax_window_init (PsppireSyntaxWindow *window) window->edit_paste = g_simple_action_new ("paste", NULL); g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (window->edit_paste)); + window->edit_find = g_simple_action_new ("find", NULL); + g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (window->edit_find)); window->buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view))); @@ -867,6 +953,11 @@ psppire_syntax_window_init (PsppireSyntaxWindow *window) G_CALLBACK (on_edit_paste), window); + g_signal_connect_swapped (window->edit_find, + "activate", + G_CALLBACK (on_edit_find), + window); + { GSimpleAction *run_all = g_simple_action_new ("run-all", NULL); diff --git a/src/ui/gui/psppire-syntax-window.h b/src/ui/gui/psppire-syntax-window.h index cb125028c9..43dd1b914b 100644 --- a/src/ui/gui/psppire-syntax-window.h +++ b/src/ui/gui/psppire-syntax-window.h @@ -64,6 +64,9 @@ struct _PsppireSyntaxWindow GSimpleAction *edit_copy; GSimpleAction *edit_delete; GSimpleAction *edit_paste; + GSimpleAction *edit_find; + + GtkEntryBuffer *search_text_buffer; gulong ps_handler; gulong sel_handler; diff --git a/src/ui/gui/syntax-editor.ui b/src/ui/gui/syntax-editor.ui index 56423ea70b..7ed0420c15 100644 --- a/src/ui/gui/syntax-editor.ui +++ b/src/ui/gui/syntax-editor.ui @@ -95,6 +95,12 @@ win.redo +
+ + _Find + win.find + +
_Run -- 2.30.2