#include <regex.h>
#include <stdlib.h>
#include <sys/types.h>
+#include <math.h>
#include "data/data-in.h"
#include "data/datasheet.h"
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 = -1;
+ gint unused;
+ gint row = 0;
+ ssw_sheet_get_active_cell (sheet, &unused, &row);
find_value (fd, row, &x, &column);
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);
static casenumber
cm1 (casenumber current, struct datasheet *data)
{
- if (current == -1)
- return datasheet_get_n_rows (data);
+ if (current == 0)
+ return datasheet_get_n_rows (data) - 1;
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;
}
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}
};
if (wrap)
{
if (reverse)
- return &ip[REVERSE_WRAP];
+ return &case_iterator[REVERSE_WRAP];
else
- return &ip[FORWARD_WRAP];
+ return &case_iterator[FORWARD_WRAP];
}
else
{
if (reverse)
- return &ip[REVERSE];
+ return &case_iterator[REVERSE];
else
- return &ip[FORWARD];
+ return &case_iterator[FORWARD];
}
}
};
-/* 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 */
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;
}
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 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->compare = value_compare;
+ const struct fmt_spec *fs = var_get_write_format (var);
- text_to_value (target, 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;
}
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;
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;
if (flags & (STR_CMP_SUBSTR | STR_CMP_LABELS))
return string_comparator_create (var, str, flags);
- return value_comparator_create (var, str);
+ return numeric_comparator_create (var, str);
}