vlabels works a little
[pspp] / src / language / stats / ctables.c
index dc761ade728e85235f89953dcd6d093303cdffec..333b8f8c5413008adb2ee56195f212141a3d7741 100644 (file)
 
 enum ctables_vlabel
   {
-    CTVL_DEFAULT = SETTINGS_VALUE_SHOW_DEFAULT,
+    CTVL_NONE = SETTINGS_VALUE_SHOW_DEFAULT,
     CTVL_NAME = SETTINGS_VALUE_SHOW_VALUE,
     CTVL_LABEL = SETTINGS_VALUE_SHOW_LABEL,
     CTVL_BOTH = SETTINGS_VALUE_SHOW_BOTH,
-    CTVL_NONE,
   };
-static void UNUSED
-ctables_vlabel_unique (enum ctables_vlabel vlabel)
-{
-  /* This ensures that all of the values are unique. */
-  switch (vlabel)
-    {
-    case CTVL_DEFAULT:
-    case CTVL_NAME:
-    case CTVL_LABEL:
-    case CTVL_BOTH:
-    case CTVL_NONE:
-      abort ();
-    }
-}
 
 /* XXX:
    - unweighted summaries (U*)
@@ -1435,8 +1420,22 @@ ctables_execute (struct dataset *ds, struct ctables *ct)
             {
               struct ctables_freqtab *ft = t->fts[j];
 
+              for (size_t k = 0; k < ft->vars.n; k++)
+                {
+                  const struct variable *var = ft->vars.vars[k];
+                  switch (var_is_value_missing (var, case_data (c, var)))
+                    {
+                    case MV_SYSTEM:
+                      goto next_ft;
+
+                    case MV_USER:
+                      if (!t->categories[var_get_dict_index (var)]
+                          || !t->categories[var_get_dict_index (var)]->include_missing)
+                        goto next_ft;
+                      break;
+                    }
+                }
               size_t hash = 0;
-
               for (size_t k = 0; k < ft->vars.n; k++)
                 {
                   const struct variable *var = ft->vars.vars[k];
@@ -1480,6 +1479,9 @@ ctables_execute (struct dataset *ds, struct ctables *ct)
     {
       struct ctables_table *t = &ct->tables[i];
 
+      struct pivot_table *pt = pivot_table_create (N_("Custom Tables"));
+      struct pivot_dimension *d = pivot_dimension_create (
+        pt, PIVOT_AXIS_ROW, N_("Rows"));
       for (size_t j = 0; j < t->n_fts; j++)
         {
           struct ctables_freqtab *ft = t->fts[j];
@@ -1489,9 +1491,54 @@ ctables_execute (struct dataset *ds, struct ctables *ct)
           size_t n = 0;
           HMAP_FOR_EACH (f, struct freq, node, &ft->data)
             ft->sorted[n++] = f;
-          sort (ft->sorted, ft->data.count, sizeof *ft->sorted,
+          assert (n == ft->data.count);
+          sort (ft->sorted, n, sizeof *ft->sorted,
                 compare_freq_3way, &ft->vars);
+
+          struct pivot_category **groups = xnmalloc (ft->vars.n,
+                                                     sizeof *groups);
+          for (size_t k = 0; k < n; k++)
+            {
+              struct freq *prev = k > 0 ? ft->sorted[k - 1] : NULL;
+              struct freq *f = ft->sorted[k];
+
+              size_t n_common = 0;
+              if (prev)
+                for (; n_common + 1 < ft->vars.n; n_common++)
+                  if (!value_equal (&prev->values[n_common],
+                                    &f->values[n_common],
+                                    var_get_type (ft->vars.vars[n_common])))
+                    break;
+
+              for (size_t m = n_common; m < ft->vars.n; m++)
+                {
+                  struct pivot_category *parent = m > 0 ? groups[m - 1] : d->root;
+                  const struct variable *var = ft->vars.vars[m];
+                  enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (var)];
+
+                  if (vlabel != CTVL_NONE)
+                    parent = pivot_category_create_group__ (
+                      parent, pivot_value_new_variable (ft->vars.vars[m]));
+
+                  if (m + 1 < ft->vars.n)
+                    parent = pivot_category_create_group__ (
+                      parent,
+                      pivot_value_new_var_value (ft->vars.vars[m], &f->values[m]));
+                  groups[m] = parent;
+
+                  if (m == ft->vars.n - 1)
+                    {
+                      int leaf = pivot_category_create_leaf (
+                        parent,
+                        pivot_value_new_var_value (ft->vars.vars[ft->vars.n - 1],
+                                                   &f->values[ft->vars.n - 1]));
+                      pivot_table_put1 (pt, leaf, pivot_value_new_number (f->count));
+                    }
+                }
+            }
+          free (groups);
         }
+      pivot_table_submit (pt);
     }
 
   for (size_t i = 0; i < ct->n_tables; i++)
@@ -1528,8 +1575,9 @@ cmd_ctables (struct lexer *lexer, struct dataset *ds)
 {
   size_t n_vars = dict_get_n_vars (dataset_dict (ds));
   enum ctables_vlabel *vlabels = xnmalloc (n_vars, sizeof *vlabels);
+  enum settings_value_show tvars = settings_get_show_variables ();
   for (size_t i = 0; i < n_vars; i++)
-    vlabels[i] = CTVL_DEFAULT;
+    vlabels[i] = (enum ctables_vlabel) tvars;
 
   struct ctables *ct = xmalloc (sizeof *ct);
   *ct = (struct ctables) {
@@ -1653,7 +1701,7 @@ cmd_ctables (struct lexer *lexer, struct dataset *ds)
 
           enum ctables_vlabel vlabel;
           if (lex_match_id (lexer, "DEFAULT"))
-            vlabel = CTVL_DEFAULT;
+            vlabel = (enum ctables_vlabel) settings_get_show_variables ();
           else if (lex_match_id (lexer, "NAME"))
             vlabel = CTVL_NAME;
           else if (lex_match_id (lexer, "LABEL"))