X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Ffind-dialog.c;h=16f5e365761a12ab3b13cec78ea4d91e42da3bce;hb=339f1956cc72;hp=faaa8d6b348991a40274ed7168d154182810d8f6;hpb=319711ff80e76a730ec26c86d67c0107143d8747;p=pspp diff --git a/src/ui/gui/find-dialog.c b/src/ui/gui/find-dialog.c index faaa8d6b34..16f5e36576 100644 --- a/src/ui/gui/find-dialog.c +++ b/src/ui/gui/find-dialog.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2009 Free Software Foundation + Copyright (C) 2007, 2009, 2011, 2012, 2015, 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 @@ -20,36 +20,36 @@ which match particular strings */ #include -#include "find-dialog.h" -#include "psppire-selector.h" -#include "psppire-dialog.h" -#include "helper.h" -#include "psppire-data-window.h" -#include "dict-display.h" -#include -#include -#include -#include -#include "psppire-data-store.h" #include -#include -#include -#include -#include - #include +#include #include - -#include "xalloc.h" +#include +#include + +#include "data/data-in.h" +#include "data/datasheet.h" +#include "data/format.h" +#include "data/value.h" +#include "libpspp/cast.h" +#include "libpspp/message.h" +#include "ui/gui/builder-wrapper.h" +#include "ui/gui/dict-display.h" +#include "ui/gui/find-dialog.h" +#include "ui/gui/helper.h" +#include "ui/gui/psppire-data-store.h" +#include "ui/gui/psppire-data-window.h" +#include "ui/gui/psppire-dialog.h" +#include "ui/gui/psppire-selector.h" +#include + +#include "gl/xalloc.h" #include #define _(msgid) gettext (msgid) #define N_(msgid) msgid -/* FIXME: These shouldn't be here */ -#include "psppire-var-store.h" - struct find_dialog { GtkBuilder *xml; @@ -101,29 +101,23 @@ refresh (GObject *obj, const struct find_dialog *fd) static void do_find (GObject *obj, const struct find_dialog *fd) { + SswSheet *sheet = SSW_SHEET (fd->de->data_editor->data_sheet); casenumber x = -1; gint column = -1; - glong row; - - g_object_get (fd->de->data_editor, "current-case", &row, NULL); - - if ( row < 0 ) - row = 0; + gint unused; + gint row = 0; + ssw_sheet_get_active_cell (sheet, &unused, &row); find_value (fd, row, &x, &column); - - if ( x != -1) + if (x != -1) { gtk_notebook_set_current_page (GTK_NOTEBOOK (fd->de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW); - g_object_set (fd->de->data_editor, - "current-case", x, - "current-variable", column, - NULL); + ssw_sheet_scroll_to (sheet, column, x); + ssw_sheet_set_active_cell (sheet, column, x, NULL); } - } /* Callback on the selector. @@ -184,10 +178,8 @@ value_labels_toggled (GtkToggleButton *tb, gpointer data) /* Pops up the Find dialog box */ void -find_dialog (gpointer data) +find_dialog (PsppireDataWindow *de) { - PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data); - struct find_dialog fd; GtkWidget *dialog ; @@ -197,13 +189,12 @@ find_dialog (gpointer data) GtkWidget *buttonbox; - PsppireVarStore *vs ; PsppireDataStore *ds ; fd.xml = builder_new ("find.ui"); fd.de = de; - find_button = gtk_button_new_from_stock (GTK_STOCK_FIND); + find_button = gtk_button_new_with_label (_("Find")); gtk_widget_show (find_button); buttonbox = get_widget_assert (fd.xml, "find-buttonbox"); @@ -216,12 +207,10 @@ find_dialog (gpointer data) selector = get_widget_assert (fd.xml, "find-selector"); g_object_get (de->data_editor, - "var-store", &vs, + "dictionary", &fd.dict, "data-store", &ds, NULL); - g_object_get (vs, "dictionary", &fd.dict, NULL); - fd.data = ds->datasheet; fd.variable_entry = get_widget_assert (fd.xml, "find-variable-entry"); @@ -283,7 +272,7 @@ forward (casenumber *i, struct datasheet *data UNUSED) static void forward_wrap (casenumber *i, struct datasheet *data) { - if ( ++*i >= datasheet_get_n_rows (data) ) *i = 0; + if (++*i >= datasheet_get_n_rows (data)) *i = 0; } static void @@ -296,7 +285,7 @@ backward (casenumber *i, struct datasheet *data UNUSED) static void backward_wrap (casenumber *i, struct datasheet *data) { - if ( --*i < 0 ) + if (--*i < 0) *i = datasheet_get_n_rows (data) - 1; } @@ -324,6 +313,9 @@ cp1c (casenumber current, struct datasheet *data) static casenumber cm1 (casenumber current, struct datasheet *data) { + if (current == 0) + return datasheet_get_n_rows (data) - 1; + return current - 1; } @@ -372,11 +364,18 @@ enum iteration_type{ n_iterators }; -static const struct casenum_iterator ip[n_iterators] = +static const struct casenum_iterator case_iterator[n_iterators] = { + /* Forward iterator (linear) */ {cp1, last, forward}, + + /* Forward iterator (circular) */ {cp1c, cm1, forward_wrap}, + + /* Reverse iterator (linear) */ {cm1, minus1, backward}, + + /* Reverse iterator (circular */ {cm1c, cp1, backward_wrap} }; @@ -392,19 +391,19 @@ get_iteration_params (const struct find_dialog *fd) gboolean reverse = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (get_widget_assert (fd->xml, "find-backwards"))); - if ( wrap ) + if (wrap) { - if ( reverse ) - return &ip[REVERSE_WRAP]; + if (reverse) + return &case_iterator[REVERSE_WRAP]; else - return &ip[FORWARD_WRAP]; + return &case_iterator[FORWARD_WRAP]; } else { - if ( reverse ) - return &ip[REVERSE]; + if (reverse) + return &case_iterator[REVERSE]; else - return &ip[FORWARD]; + return &case_iterator[FORWARD]; } } @@ -425,7 +424,6 @@ struct comparator { const struct variable *var; enum string_cmp_flags flags; - const PsppireDict *dict; bool (*compare) (const struct comparator *, const union value *); @@ -434,11 +432,13 @@ struct comparator }; -/* A comparator which operates on the unadulterated union values */ -struct value_comparator +/* A comparator which operates on the numerical values, + rounded to the number of decimal places indicated by + the variable's format. */ +struct numeric_comparator { struct comparator parent; - union value pattern; + double rounded_ref; }; /* A comparator which matches string values or parts thereof */ @@ -455,13 +455,29 @@ struct regexp_comparator regex_t re; }; +/* Returns 10 raised to the power of X. + X must be a non-negative integer. */ +static inline int +int_pow10 (int x) +{ + int ret = 1; + assert (x >= 0); + while (x--) + ret *= 10; + + return ret; +} static bool value_compare (const struct comparator *cmptr, const union value *v) { - const struct value_comparator *vc = (const struct value_comparator *) cmptr; - return 0 == value_compare_3way (v, &vc->pattern, var_get_width (cmptr->var)); + const struct numeric_comparator *nc = (const struct numeric_comparator *) cmptr; + const struct fmt_spec *fs = var_get_print_format (cmptr->var); + + double c = nearbyint (v->f * int_pow10 (fs->d)); + + return c == nc->rounded_ref; } @@ -473,14 +489,19 @@ string_label_compare (const struct comparator *cmptr, const struct string_comparator *ssc = (const struct string_comparator *) cmptr; + int width; + const char *text = var_lookup_value_label (cmptr->var, val); - int width = strlen (text); + if (text == NULL) + return false; - assert ( cmptr->flags & STR_CMP_LABELS); + width = strlen (text); + + assert (cmptr->flags & STR_CMP_LABELS); g_return_val_if_fail (width > 0, false); - if ( cmptr->flags & STR_CMP_SUBSTR) + if (cmptr->flags & STR_CMP_SUBSTR) return (NULL != g_strstr_len (text, width, ssc->pattern)); else return (0 == strncmp (text, ssc->pattern, width)); @@ -498,11 +519,11 @@ string_value_compare (const struct comparator *cmptr, int width = var_get_width (cmptr->var); g_return_val_if_fail (width > 0, false); - assert ( ! (cmptr->flags & STR_CMP_LABELS)); + assert (! (cmptr->flags & STR_CMP_LABELS)); - text = value_to_text (*val, cmptr->dict, *var_get_write_format (cmptr->var)); + text = value_to_text (*val, cmptr->var); - if ( cmptr->flags & STR_CMP_SUBSTR) + if (cmptr->flags & STR_CMP_SUBSTR) found = (NULL != g_strstr_len (text, width, ssc->pattern)); else found = (0 == strncmp (text, ssc->pattern, width)); @@ -525,11 +546,11 @@ regexp_value_compare (const struct comparator *cmptr, int width = var_get_width (cmptr->var); - assert ( ! (cmptr->flags & STR_CMP_LABELS) ); + assert (! (cmptr->flags & STR_CMP_LABELS)); g_return_val_if_fail (width > 0, false); - text = value_to_text (*val, cmptr->dict, *var_get_write_format (cmptr->var)); + text = value_to_text (*val, cmptr->var); /* We must remove trailing whitespace, otherwise $ will not match where one would expect */ g_strchomp (text); @@ -552,7 +573,7 @@ regexp_label_compare (const struct comparator *cmptr, int width ; - assert ( cmptr->flags & STR_CMP_LABELS); + assert (cmptr->flags & STR_CMP_LABELS); text = var_lookup_value_label (cmptr->var, val); width = strlen (text); @@ -573,45 +594,36 @@ regexp_destroy (struct comparator *cmptr) regfree (&rec->re); } -static void -cmptr_value_destroy (struct comparator *cmptr) -{ - struct value_comparator *vc - = UP_CAST (cmptr, struct value_comparator, parent); - value_destroy (&vc->pattern, var_get_width (cmptr->var)); -} - - static struct comparator * -value_comparator_create (const struct variable *var, const PsppireDict *dict, const char *target) +numeric_comparator_create (const struct variable *var, const char *target) { - struct value_comparator *vc = xzalloc (sizeof (*vc)); - struct comparator *cmptr = &vc->parent; + struct numeric_comparator *nc = XZALLOC (struct numeric_comparator); + struct comparator *cmptr = &nc->parent; cmptr->flags = 0; cmptr->var = var; - cmptr->compare = value_compare ; - cmptr->destroy = cmptr_value_destroy; - cmptr->dict = dict; + cmptr->compare = value_compare; + const struct fmt_spec *fs = var_get_write_format (var); - text_to_value (target, dict, var, &vc->pattern); + union value val; + text_to_value (target, var, &val); + nc->rounded_ref = nearbyint (val.f * int_pow10 (fs->d)); + value_destroy (&val, var_get_width (var)); return cmptr; } static struct comparator * -string_comparator_create (const struct variable *var, const PsppireDict *dict, - const char *target, +string_comparator_create (const struct variable *var, const char *target, enum string_cmp_flags flags) { - struct string_comparator *ssc = xzalloc (sizeof (*ssc)); + struct string_comparator *ssc = XZALLOC (struct string_comparator); struct comparator *cmptr = &ssc->parent; cmptr->flags = flags; cmptr->var = var; - cmptr->dict = dict; - if ( flags & STR_CMP_LABELS) + if (flags & STR_CMP_LABELS) cmptr->compare = string_label_compare; else cmptr->compare = string_value_compare; @@ -623,23 +635,22 @@ string_comparator_create (const struct variable *var, const PsppireDict *dict, static struct comparator * -regexp_comparator_create (const struct variable *var, const PsppireDict *dict, const char *target, +regexp_comparator_create (const struct variable *var, const char *target, enum string_cmp_flags flags) { int code; - struct regexp_comparator *rec = xzalloc (sizeof (*rec)); + struct regexp_comparator *rec = XZALLOC (struct regexp_comparator); struct comparator *cmptr = &rec->parent; cmptr->flags = flags; cmptr->var = var; - cmptr->dict = dict; cmptr->compare = (flags & STR_CMP_LABELS) ? regexp_label_compare : regexp_value_compare ; cmptr->destroy = regexp_destroy; code = regcomp (&rec->re, target, 0); - if ( code != 0 ) + if (code != 0) { char *errbuf = NULL; size_t errbuf_size = regerror (code, &rec->re, errbuf, 0); @@ -650,7 +661,7 @@ regexp_comparator_create (const struct variable *var, const PsppireDict *dict, c msg (ME, _("Bad regular expression: %s"), errbuf); - free ( cmptr); + free (cmptr); free (errbuf); return NULL; } @@ -671,10 +682,10 @@ comparator_compare (const struct comparator *cmptr, static void comparator_destroy (struct comparator *cmptr) { - if ( ! cmptr ) + if (! cmptr) return ; - if ( cmptr->destroy ) + if (cmptr->destroy) cmptr->destroy (cmptr); free (cmptr); @@ -682,16 +693,16 @@ comparator_destroy (struct comparator *cmptr) static struct comparator * -comparator_factory (const struct variable *var, const PsppireDict *dict, const char *str, +comparator_factory (const struct variable *var, const char *str, enum string_cmp_flags flags) { - if ( flags & STR_CMP_REGEXP ) - return regexp_comparator_create (var, dict, str, flags); + if (flags & STR_CMP_REGEXP) + return regexp_comparator_create (var, str, flags); - if ( flags & (STR_CMP_SUBSTR | STR_CMP_LABELS) ) - return string_comparator_create (var, dict, str, flags); + if (flags & (STR_CMP_SUBSTR | STR_CMP_LABELS)) + return string_comparator_create (var, str, flags); - return value_comparator_create (var, dict, str); + return numeric_comparator_create (var, str); } @@ -709,10 +720,9 @@ find_value (const struct find_dialog *fd, casenumber current_row, const char *target_string = gtk_entry_get_text (GTK_ENTRY (fd->value_entry)); enum string_cmp_flags flags = 0; - g_assert (current_row >= 0); var = dict_lookup_var (fd->dict->dict, var_name); - if ( ! var ) + if (! var) return ; width = var_get_width (var); @@ -720,15 +730,15 @@ find_value (const struct find_dialog *fd, casenumber current_row, *column = var_get_dict_index (var); *row = -1; - if ( gtk_toggle_button_get_active + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->match_substring_checkbox))) flags |= STR_CMP_SUBSTR; - if ( gtk_toggle_button_get_active + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->match_regexp_checkbox))) flags |= STR_CMP_REGEXP; - if ( gtk_toggle_button_get_active + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->value_labels_checkbox))) flags |= STR_CMP_LABELS; @@ -737,10 +747,10 @@ find_value (const struct find_dialog *fd, casenumber current_row, casenumber i; const struct casenum_iterator *ip = get_iteration_params (fd); struct comparator *cmptr = - comparator_factory (var, fd->dict, target_string, flags); + comparator_factory (var, target_string, flags); value_init (&val, width); - if ( ! cmptr) + if (! cmptr) goto finish; for (i = ip->start (current_row, fd->data); @@ -749,7 +759,7 @@ find_value (const struct find_dialog *fd, casenumber current_row, { datasheet_get_value (fd->data, i, var_get_case_index (var), &val); - if ( comparator_compare (cmptr, &val)) + if (comparator_compare (cmptr, &val)) { *row = i; break;