Replace numerous instances of xzalloc with XZALLOC
[pspp] / src / ui / gui / find-dialog.c
index 52f26d4a695c64df49a4658d6be6d0b3e64caa37..16f5e365761a12ab3b13cec78ea4d91e42da3bce 100644 (file)
@@ -25,6 +25,7 @@ which match particular strings */
 #include <regex.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <math.h>
 
 #include "data/data-in.h"
 #include "data/datasheet.h"
@@ -100,15 +101,17 @@ 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 = -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);
 
@@ -310,8 +313,8 @@ cp1c (casenumber current, struct datasheet *data)
 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;
 }
@@ -322,9 +325,6 @@ cm1c (casenumber current, struct datasheet *data)
 {
   casenumber next = current;
 
-  if (current == -1)
-    return datasheet_get_n_rows (data);
-
   backward_wrap (&next, data);
 
   return next;
@@ -340,9 +340,6 @@ last (casenumber current, struct datasheet *data)
 static casenumber
 minus1 (casenumber current, struct datasheet *data)
 {
-  if (current == -1)
-    return 0;
-
   return -1;
 }
 
@@ -367,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}
   };
 
@@ -390,16 +394,16 @@ get_iteration_params (const struct find_dialog *fd)
   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];
     }
 }
 
@@ -428,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 */
@@ -449,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;
 }
 
 
@@ -572,27 +594,21 @@ 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 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;
 }
@@ -601,7 +617,7 @@ static struct comparator *
 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;
@@ -623,7 +639,7 @@ 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;
@@ -686,7 +702,7 @@ comparator_factory (const struct variable *var, const char *str,
   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);
 }