chart: Fix format string issues in chart_write_title callers.
[pspp] / src / language / stats / crosstabs.q
index e296da2d61da1e7307238f76772d8071eb6af2fb..1d35e14e83e0de27b50d451feb2beb62671c8e76 100644 (file)
@@ -161,41 +161,6 @@ struct pivot_table
     double total;              /* Grand total. */
   };
 
-/* A crosstabulation of exactly 2 variables, conditional on zero
-   or more other variables having given values. */
-struct crosstab
-  {
-    /* Case counts. */
-    double missing;
-
-    /* Variables. */
-    int n_vars;                        /* Number of variables (at least 2). */
-    const struct variable **vars;
-    union value *values;       /* Values of variables beyond 2. */
-
-    /* Data. */
-    struct table_entry **entries;
-    size_t n_entries;
-
-    /* Column values, number of columns. */
-    union value *cols;
-    int n_cols;
-
-    /* Row values, number of rows. */
-    union value *rows;
-    int n_rows;
-
-    /* Number of statistically interesting columns/rows
-       (columns/rows with data in them). */
-    int ns_cols, ns_rows;
-
-    /* Matrix contents. */
-    double *mat;               /* Matrix proper. */
-    double *row_tot;           /* Row totals. */
-    double *col_tot;           /* Column totals. */
-    double total;              /* Grand total. */
-  };
-
 /* Integer mode variable info. */
 struct var_range
   {
@@ -235,6 +200,12 @@ struct crosstabs_proc
     unsigned int statistics;    /* Bit k is 1 if statistic k is requested. */
   };
 
+/* Auxiliary data structure for tab_dim. */
+struct crosstabs_dim_aux
+  {
+    enum mv_class exclude;
+  };
+
 static void
 init_proc (struct crosstabs_proc *proc, struct dataset *ds)
 {
@@ -263,8 +234,8 @@ free_proc (struct crosstabs_proc *proc)
 
          The rest of the data was allocated and destroyed at a
          lower level already. */
-      free (pt);
     }
+  free (proc->pivots);
 }
 
 static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds,
@@ -947,8 +918,8 @@ static void display_symmetric (struct crosstabs_proc *, struct pivot_table *,
 static void display_risk (struct pivot_table *, struct tab_table *);
 static void display_directional (struct crosstabs_proc *, struct pivot_table *,
                                  struct tab_table *);
-static void crosstabs_dim (struct tab_table *, struct outp_driver *,
-                           void *proc);
+static void crosstabs_dim (struct tab_rendering *, void *aux);
+static void crosstabs_dim_free (void *aux);
 static void table_value_missing (struct crosstabs_proc *proc,
                                  struct tab_table *table, int c, int r,
                                 unsigned char opt, const union value *v,
@@ -1028,22 +999,22 @@ output_pivot_table (struct crosstabs_proc *proc, struct pivot_table *pt)
       if (chisq)
         {
           display_dimensions (proc, &x, chisq, first_difference);
-          display_chisq (pt, chisq, &showed_fisher);
+          display_chisq (&x, chisq, &showed_fisher);
         }
       if (sym)
         {
           display_dimensions (proc, &x, sym, first_difference);
-          display_symmetric (proc, pt, sym);
+          display_symmetric (proc, &x, sym);
         }
       if (risk)
         {
           display_dimensions (proc, &x, risk, first_difference);
-          display_risk (pt, risk);
+          display_risk (&x, risk);
         }
       if (direct)
         {
           display_dimensions (proc, &x, direct, first_difference);
-          display_directional (proc, pt, direct);
+          display_directional (proc, &x, direct);
         }
 
       /* Free the parts of x that are not owned by pt.  In
@@ -1218,10 +1189,17 @@ create_crosstab_table (struct crosstabs_proc *proc, struct pivot_table *pt)
   for (i = 0; i < pt->n_consts; i++)
     {
       const struct variable *var = pt->const_vars[i];
+      size_t ofs;
+
       ds_put_format (&title, ", %s=", var_get_name (var));
+
+      /* Insert the formatted value of the variable, then trim
+         leading spaces in what was just inserted. */
+      ofs = ds_length (&title);
       data_out (&pt->const_values[i], var_get_print_format (var),
                 ds_put_uninit (&title, var_get_width (var)));
-      /* XXX remove any leading space in what was just inserted.  */
+      ds_remove (&title, ofs, ss_cspan (ds_substr (&title, ofs, SIZE_MAX),
+                                        ss_cstr (" ")));
     }
 
   ds_put_cstr (&title, " [");
@@ -1264,7 +1242,6 @@ create_chisq_table (struct pivot_table *pt)
             _("Exact. Sig. (2-sided)"));
   tab_text (chisq, 5, 0, TAB_RIGHT | TAT_TITLE,
             _("Exact. Sig. (1-sided)"));
-  chisq = 0;
   tab_offset (chisq, 0, 1);
 
   return chisq;
@@ -1373,6 +1350,7 @@ static void
 submit (struct crosstabs_proc *proc, struct pivot_table *pt,
         struct tab_table *t)
 {
+  struct crosstabs_dim_aux *aux;
   int i;
 
   if (t == NULL)
@@ -1395,21 +1373,27 @@ submit (struct crosstabs_proc *proc, struct pivot_table *pt,
   tab_box (t, -1, -1, -1, TAL_GAP, 0, tab_t (t), tab_l (t) - 1,
           tab_nr (t) - 1);
   tab_vline (t, TAL_2, tab_l (t), 0, tab_nr (t) - 1);
-  tab_dim (t, crosstabs_dim, proc);
+
+  aux = xmalloc (sizeof *aux);
+  aux->exclude = proc->exclude;
+  tab_dim (t, crosstabs_dim, crosstabs_dim_free, aux);
+
   tab_submit (t);
 }
 
 /* Sets the widths of all the columns and heights of all the rows in
    table T for driver D. */
 static void
-crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *proc_)
+crosstabs_dim (struct tab_rendering *r, void *aux_)
 {
-  struct crosstabs_proc *proc = proc_;
+  const struct tab_table *t = r->table;
+  struct outp_driver *d = r->driver;
+  struct crosstabs_dim_aux *aux = aux_;
   int i;
 
   /* Width of a numerical column. */
   int c = outp_string_width (d, "0.000000", OUTP_PROPORTIONAL);
-  if (proc->exclude == MV_NEVER)
+  if (aux->exclude == MV_NEVER)
     c += outp_string_width (d, "M", OUTP_PROPORTIONAL);
 
   /* Set width for header columns. */
@@ -1420,7 +1404,7 @@ crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *proc_)
 
       w = d->width - c * (t->nc - t->l);
       for (i = 0; i <= t->nc; i++)
-        w -= t->wrv[i];
+        w -= r->wrv[i];
       w /= t->l;
 
       if (w < d->prop_em_width * 8)
@@ -1430,14 +1414,21 @@ crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *proc_)
        w = d->prop_em_width * 15;
 
       for (i = 0; i < t->l; i++)
-       t->w[i] = w;
+       r->w[i] = w;
     }
 
   for (i = t->l; i < t->nc; i++)
-    t->w[i] = c;
+    r->w[i] = c;
 
   for (i = 0; i < t->nr; i++)
-    t->h[i] = tab_natural_height (t, d, i);
+    r->h[i] = tab_natural_height (r, i);
+}
+
+static void
+crosstabs_dim_free (void *aux_)
+{
+  struct crosstabs_dim_aux *aux = aux_;
+  free (aux);
 }
 
 static bool
@@ -1809,7 +1800,6 @@ display_chisq (struct pivot_table *pt, struct tab_table *chisq,
   double chisq_v[N_CHISQ];
   double fisher1, fisher2;
   int df[N_CHISQ];
-  int s = 0;
 
   int i;
 
@@ -1822,7 +1812,6 @@ display_chisq (struct pivot_table *pt, struct tab_table *chisq,
       if ((i != 2 && chisq_v[i] == SYSMIS)
          || (i == 2 && fisher1 == SYSMIS))
        continue;
-      s = 1;
 
       tab_text (chisq, 0, 0, TAB_LEFT, gettext (chisq_stats[i]));
       if (i != 2)