/* 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
#include <config.h>
-#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 <data/value.h>
-#include <data/format.h>
-#include <data/datasheet.h>
-#include <data/data-in.h>
-#include "psppire-data-store.h"
#include <ctype.h>
-#include <sys/types.h>
-#include <regex.h>
-#include <libpspp/message.h>
-
#include <gtk/gtk.h>
+#include <regex.h>
#include <stdlib.h>
-
-#include "xalloc.h"
+#include <sys/types.h>
+#include <math.h>
+
+#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 <ssw-sheet.h>
+
+#include "gl/xalloc.h"
#include <gettext.h>
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-/* FIXME: These shouldn't be here */
-#include "psppire-var-store.h"
-
struct find_dialog
{
GtkBuilder *xml;
{
casenumber x = -1;
gint column = -1;
- glong row;
-
- g_object_get (fd->de->data_editor, "current-case", &row, NULL);
-
- if ( row < 0 )
- row = 0;
+ glong row = -1;
find_value (fd, row, &x, &column);
-
- if ( x != -1)
+ if (x != -1)
{
+ SswSheet *sheet = SSW_SHEET (fd->de->data_editor->data_sheet);
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.
/* Pops up the Find dialog box
*/
void
-find_dialog (GObject *o, gpointer data)
+find_dialog (PsppireDataWindow *de)
{
- PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
-
struct find_dialog fd;
GtkWidget *dialog ;
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");
- gtk_box_pack_start_defaults (GTK_BOX (buttonbox), find_button);
+ psppire_box_pack_start_defaults (GTK_BOX (buttonbox), find_button);
gtk_box_reorder_child (GTK_BOX (buttonbox), find_button, 0);
dialog = get_widget_assert (fd.xml, "find-dialog");
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");
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
- g_object_set (source, "dictionary", fd.dict,
+ g_object_set (source, "model", fd.dict,
"selection-mode", GTK_SELECTION_SINGLE,
NULL);
- psppire_selector_set_subjects (PSPPIRE_SELECTOR (selector),
- insert_source_row_into_entry,
- is_currently_in_entry,
- NULL
- );
+
+ psppire_selector_set_filter_func (PSPPIRE_SELECTOR (selector),
+ is_currently_in_entry);
g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), &fd);
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
static void
backward_wrap (casenumber *i, struct datasheet *data)
{
- if ( --*i < 0 )
+ if (--*i < 0)
*i = datasheet_get_n_rows (data) - 1;
}
static casenumber
cm1 (casenumber current, struct datasheet *data)
{
+ if (current == -1)
+ return datasheet_get_n_rows (data);
+
return current - 1;
}
{
casenumber next = current;
+ if (current == -1)
+ return datasheet_get_n_rows (data);
+
backward_wrap (&next, data);
return next;
static casenumber
minus1 (casenumber current, struct datasheet *data)
{
+ if (current == -1)
+ return 0;
+
return -1;
}
gboolean reverse = gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON (get_widget_assert (fd->xml, "find-backwards")));
- if ( wrap )
+ if (wrap)
{
- if ( reverse )
+ if (reverse)
return &ip[REVERSE_WRAP];
else
return &ip[FORWARD_WRAP];
}
else
{
- if ( reverse )
+ if (reverse)
return &ip[REVERSE];
else
return &ip[FORWARD];
{
const struct variable *var;
enum string_cmp_flags flags;
- const PsppireDict *dict;
bool (*compare) (const struct comparator *,
const union value *);
};
-/* 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 */
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 * exp10 (fs->d));
+
+ return c == nc->rounded_ref;
}
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));
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));
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);
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);
static void
regexp_destroy (struct comparator *cmptr)
{
- struct regexp_comparator *rec = (struct regexp_comparator *) cmptr;
+ struct regexp_comparator *rec
+ = UP_CAST (cmptr, struct regexp_comparator, parent);
regfree (&rec->re);
}
-static void
-cmptr_value_destroy (struct comparator *cmptr)
-{
- struct value_comparator *vc = (struct value_comparator *) cmptr;
- 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 = (struct comparator *) vc;
+ struct numeric_comparator *nc = xzalloc (sizeof (*nc));
+ 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 * exp10 (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 comparator *cmptr = (struct comparator *) ssc;
+ 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;
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 comparator *cmptr = (struct comparator *) rec;
+ 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);
msg (ME, _("Bad regular expression: %s"), errbuf);
- free ( cmptr);
+ free (cmptr);
free (errbuf);
return NULL;
}
static void
comparator_destroy (struct comparator *cmptr)
{
- if ( ! cmptr )
+ if (! cmptr)
return ;
- if ( cmptr->destroy )
+ if (cmptr->destroy)
cmptr->destroy (cmptr);
free (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);
}
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);
*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;
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);
{
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;