output: Make table dimension functions work in arbitrary contexts.
authorBen Pfaff <blp@gnu.org>
Mon, 15 Jun 2009 04:50:46 +0000 (21:50 -0700)
committerBen Pfaff <blp@gnu.org>
Mon, 15 Jun 2009 04:50:46 +0000 (21:50 -0700)
Until now the function passed to tab_dim has only been called at the
time that the table is passed to tab_submit.  But in upcoming commits
the table will be kept around and rendered possibly much later (by the
GUI), so the function to tab_dim has to be sure to only use data that
will exist at that time.  Thus, this commit makes it possible to free
the auxiliary data passed to that function, so that in the few cases
where it needs to keep around extra data, it can do so without leaking
memory.  At the same time, convert the few functions that do need this
feature to use it.

20 files changed:
src/language/data-io/data-parser.c
src/language/data-io/print.c
src/language/dictionary/split-file.c
src/language/dictionary/sys-file-info.c
src/language/stats/binomial.c
src/language/stats/chisquare.c
src/language/stats/crosstabs.q
src/language/stats/descriptives.c
src/language/stats/examine.q
src/language/stats/frequencies.q
src/language/stats/npar-summary.c
src/language/stats/oneway.q
src/language/stats/regression.q
src/language/stats/reliability.q
src/language/stats/sign.c
src/language/stats/t-test.q
src/language/stats/wilcoxon.c
src/language/utilities/echo.c
src/output/table.c
src/output/table.h

index 2f503423adcbcb5e4066c36736bc6e215d3fdd72..258a42a00153a99ff19313fce9186663adc27bf8 100644 (file)
@@ -647,7 +647,7 @@ dump_fixed_table (const struct data_parser *parser,
   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format"));
   tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, parser->field_cnt);
   tab_hline (t, TAL_2, 0, 3, 1);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   for (i = 0; i < parser->field_cnt; i++)
     {
@@ -686,7 +686,7 @@ dump_delimited_table (const struct data_parser *parser,
   tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Format"));
   tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, parser->field_cnt);
   tab_hline (t, TAL_2, 0, 1, 1);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   for (i = 0; i < parser->field_cnt; i++)
     {
index aae8b38a05f7d126f4ca473a92cf818542a1c6f9..cb06dc64f14fd7d4c8e7c46f55187234168a7fe9 100644 (file)
@@ -404,7 +404,7 @@ dump_table (struct print_trns *trns, const struct file_handle *fh)
   tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record"));
   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Columns"));
   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format"));
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   row = 1;
   ll_for_each (spec, struct prt_out_spec, ll, &trns->specs)
     {
index 155cfa1208c23a035a2f9058eceb3c10de6d241d..62b67762b763303bfc01504f33cc170667b80e99 100644 (file)
@@ -78,7 +78,7 @@ output_split_file_values (const struct dataset *ds, const struct ccase *c)
     return;
 
   t = tab_create (3, split_cnt + 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_vline (t, TAL_GAP, 1, 0, split_cnt);
   tab_vline (t, TAL_GAP, 2, 0, split_cnt);
   tab_text (t, 0, 0, TAB_NONE, _("Variable"));
index 7672a3805183f802a4e706820328ab0143e60e28..1eeb9a3758cd7294c1a88bb8055828f7615d4dea 100644 (file)
@@ -161,11 +161,11 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds UNUSED)
            dict_get_encoding(d) ? dict_get_encoding(d) : _("Unknown"));
 
 
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_submit (t);
 
   t = tab_create (4, 1 + 2 * dict_get_var_cnt (d), 1);
-  tab_dim (t, sysfile_info_dim, NULL);
+  tab_dim (t, sysfile_info_dim, NULL, NULL);
   tab_headers (t, 0, 0, 1, 0);
   tab_text (t, 0, 0, TAB_LEFT | TAT_TITLE, _("Variable"));
   tab_joint_text (t, 1, 0, 2, 0, TAB_LEFT | TAT_TITLE, _("Description"));
@@ -340,35 +340,45 @@ display_documents (const struct dictionary *dict)
     }
 }
 
-static int _flags;
+struct variables_dim_aux
+  {
+    int flags;
+  };
 
 /* Sets the widths of all the columns and heights of all the rows in
    table T for driver D. */
 static void
-variables_dim (struct tab_rendering *r, void *aux UNUSED)
+variables_dim (struct tab_rendering *r, void *aux_)
 {
   const struct outp_driver *d = r->driver;
+  struct variables_dim_aux *aux = aux_;
 
   tab_natural_dimensions (r, NULL);
-  if (_flags & (DF_VALUE_LABELS | DF_VARIABLE_LABELS | DF_MISSING_VALUES
-                | DF_AT_ATTRIBUTES | DF_ATTRIBUTES))
+  if (aux->flags & (DF_VALUE_LABELS | DF_VARIABLE_LABELS | DF_MISSING_VALUES
+                    | DF_AT_ATTRIBUTES | DF_ATTRIBUTES))
     {
       r->w[1] = MAX (r->w[1], d->prop_em_width * 5);
       r->w[2] = MAX (r->w[2], d->prop_em_width * 35);
     }
 }
 
+static void
+variables_dim_free (void *aux_)
+{
+  struct variables_dim_aux *aux = aux_;
+  free (aux);
+}
+
 static void
 display_variables (const struct variable **vl, size_t n, int flags)
 {
   struct tab_table *t;
+  struct variables_dim_aux *aux;
   int nc;                      /* Number of columns. */
   int pc;                      /* `Position column' */
   int r;                       /* Current row. */
   size_t i;
 
-  _flags = flags;
-
   /* One column for the name,
      two columns for general description,
      one column for dictionary index. */
@@ -389,7 +399,10 @@ display_variables (const struct variable **vl, size_t n, int flags)
                      ? _("Description") : _("Label")));
   if (flags & DF_DICT_INDEX)
     tab_text (t, pc, 0, TAB_LEFT | TAT_TITLE, _("Position"));
-  tab_dim (t, variables_dim, NULL);
+
+  aux = xmalloc (sizeof *aux);
+  aux->flags = flags;
+  tab_dim (t, variables_dim, variables_dim_free, aux);
 
   r = 1;
   for (i = 0; i < n; i++)
@@ -479,7 +492,7 @@ display_data_file_attributes (struct attrset *set, int flags)
   tab_text (t, 1, 0, TAB_LEFT | TAT_TITLE, _("Value"));
   display_attributes (t, set, flags, 0, 1);
   tab_columns (t, TAB_COL_DOWN, 1);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_title (t, "Custom data file attributes.");
   tab_submit (t);
 }
@@ -706,7 +719,7 @@ display_vectors (const struct dictionary *dict, int sorted)
   t = tab_create (4, nrow + 1, 0);
   tab_headers (t, 0, 0, 1, 0);
   tab_columns (t, TAB_COL_DOWN, 1);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_box (t, TAL_1, TAL_1, -1, -1, 0, 0, 3, nrow);
   tab_box (t, -1, -1, -1, TAL_1, 0, 0, 3, nrow);
   tab_hline (t, TAL_2, 0, 3, 1);
index b44c5a6f165ea38160430bfedb3012630169afc2..672bdbf3b7e4362ab498d89fcf8a989c7b865067 100644 (file)
@@ -189,7 +189,7 @@ binomial_execute (const struct dataset *ds,
 
       struct tab_table *table = tab_create (7, ost->n_vars * 3 + 1, 0);
 
-      tab_dim (table, tab_natural_dimensions, NULL);
+      tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
       tab_title (table, _("Binomial Test"));
 
index 4593df4116eda81be5230a64ee2eee6c5f9fa15f..10ea0959517095da322687055d46ba8a730ed3b1 100644 (file)
@@ -180,7 +180,7 @@ create_variable_frequency_table (const struct dictionary *dict,
     }
 
   table = tab_create(4, n_cells + 2, 0);
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, var_to_string(var));
   tab_text (table, 1, 0, TAB_LEFT, _("Observed N"));
@@ -216,7 +216,7 @@ create_combo_frequency_table (const struct chisquare_test *test)
   int n_cells = test->hi - test->lo + 1;
 
   table = tab_create(1 + ost->n_vars * 4, n_cells + 3, 0);
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, _("Frequencies"));
   for ( i = 0 ; i < ost->n_vars ; ++i )
@@ -272,7 +272,7 @@ create_stats_table (const struct chisquare_test *test)
 
   struct tab_table *table;
   table = tab_create (1 + ost->n_vars, 4, 0);
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
   tab_title (table, _("Test Statistics"));
   tab_headers (table, 1, 0, 1, 0);
 
index 29ed67e4f18673bcd525f904aa446cfaaa81eaa3..76cae1b30e1f334a3f9a19a7b8a1ab1d2a2bda87 100644 (file)
@@ -200,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)
 {
@@ -912,7 +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_rendering *, 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,
@@ -1343,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)
@@ -1365,23 +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_rendering *r, void *proc_)
+crosstabs_dim (struct tab_rendering *r, void *aux_)
 {
   const struct tab_table *t = r->table;
   struct outp_driver *d = r->driver;
-  struct crosstabs_proc *proc = proc_;
+  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. */
@@ -1412,6 +1424,13 @@ crosstabs_dim (struct tab_rendering *r, void *proc_)
     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
 find_crosstab (struct pivot_table *pt, size_t *row0p, size_t *row1p)
 {
index 58144ceb908fc063b062435bf66abd314d130f43..16869a1829651136b4ccde671849bc4f3b4ce27d 100644 (file)
@@ -560,7 +560,7 @@ dump_z_table (struct dsc_proc *dsc)
   tab_hline (t, TAL_2, 0, 1, 1);
   tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Source"));
   tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Target"));
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   {
     size_t i, y;
@@ -879,7 +879,7 @@ display (struct dsc_proc *dsc)
   tab_box (t, -1, -1, -1, TAL_1, 1, 0, nc - 1, dsc->var_cnt);
   tab_hline (t, TAL_2, 0, nc - 1, 1);
   tab_vline (t, TAL_2, 1, 0, dsc->var_cnt);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   nc = 0;
   tab_text (t, nc++, 0, TAB_LEFT | TAT_TITLE, _("Variable"));
index a829112ef2e45366034dc93da16b0cedb4b5372c..c0facb0b84437774c51861a3f243a20d6b2386a3 100644 (file)
@@ -1245,7 +1245,7 @@ show_summary (const struct variable **dependent_var, int n_dep_var,
   tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   /* Outline the box */
   tab_box (tbl,
@@ -1482,7 +1482,7 @@ show_descriptives (const struct variable **dependent_var,
   tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   /* Outline the box */
   tab_box (tbl,
@@ -1795,7 +1795,7 @@ show_extremes (const struct variable **dependent_var,
   tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   /* Outline the box */
   tab_box (tbl,
@@ -2000,7 +2000,7 @@ show_percentiles (const struct variable **dependent_var,
   tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   /* Outline the box */
   tab_box (tbl,
index 5a57ffa877a033dfa023162b485b75303a954c37..1fd98a306e37be512e859863a7f2821c36a13b60 100644 (file)
@@ -997,19 +997,25 @@ compare_freq_alpha_d (const void *a_, const void *b_, const void *v_)
 \f
 /* Frequency table display. */
 
+struct full_dim_aux
+  {
+    bool show_labels;
+  };
+
 /* Sets the widths of all the columns and heights of all the rows in
    table T for driver D. */
 static void
-full_dim (struct tab_rendering *r, void *aux UNUSED)
+full_dim (struct tab_rendering *r, void *aux_)
 {
   const struct outp_driver *d = r->driver;
   const struct tab_table *t = r->table;
+  const struct full_dim_aux *aux = aux_;
   int i;
 
   for (i = 0; i < t->nc; i++)
     {
       r->w[i] = tab_natural_width (r, i);
-      if (cmd.labels == FRQ_LABELS && i == 0)
+      if (aux->show_labels && i == 0)
         r->w[i] = MIN (r->w[i], d->prop_em_width * 15);
       else
         r->w[i] = MAX (r->w[i], d->prop_em_width * 8);
@@ -1019,6 +1025,13 @@ full_dim (struct tab_rendering *r, void *aux UNUSED)
     r->h[i] = d->font_height;
 }
 
+static void
+full_dim_free (void *aux_)
+{
+  struct full_dim_aux *aux = aux_;
+  free (aux);
+}
+
 /* Displays a full frequency table for variable V. */
 static void
 dump_full (const struct variable *v, const struct variable *wv)
@@ -1059,12 +1072,17 @@ dump_full (const struct variable *v, const struct variable *wv)
 
   const bool lab = (cmd.labels == FRQ_LABELS);
 
+  struct full_dim_aux *aux;
+
   vf = get_var_freqs (v);
   ft = &vf->tab;
   n_categories = ft->n_valid + ft->n_missing;
   t = tab_create (5 + lab, n_categories + 3, 0);
   tab_headers (t, 0, 0, 2, 0);
-  tab_dim (t, full_dim, NULL);
+
+  aux = xmalloc (sizeof *aux);
+  aux->show_labels = lab;
+  tab_dim (t, full_dim, full_dim_free, aux);
 
   if (lab)
     tab_text (t, 0, 1, TAB_CENTER | TAT_TITLE, _("Value Label"));
@@ -1181,7 +1199,7 @@ dump_condensed (const struct variable *v, const struct variable *wv)
   tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("Pct"));
   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Cum"));
   tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Pct"));
-  tab_dim (t, condensed_dim, NULL);
+  tab_dim (t, condensed_dim, NULL, NULL);
 
   r = 2;
   for (f = ft->valid; f < ft->missing; f++)
@@ -1380,7 +1398,7 @@ dump_statistics (const struct variable *v, bool show_varname,
   calc_stats (v, stat_value);
 
   t = tab_create (3, n_stats + n_percentiles + 2, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ;
 
index d626dffac5f72075a582c370cb5940ec3845e2d1..90a1b656106d8544ac77ceacb9cb4d972ea5a824 100644 (file)
@@ -104,7 +104,7 @@ do_summary_box (const struct descriptives *desc,
 
   table = tab_create (columns, 2 + n_vars, 0);
 
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, _("Descriptive Statistics"));
 
index 2c1c19e8d8d77a19b8c1827143207053b90ca069..e1d5b79fdc1aa8ff8a5e36e131e155931744ed32 100644 (file)
@@ -261,7 +261,7 @@ show_anova_table (void)
 
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
 
   tab_box (t,
@@ -372,7 +372,7 @@ show_descriptives (const struct dictionary *dict)
 
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 2, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
 
   /* Put a frame around the entire box, and vertical lines inside */
@@ -518,7 +518,7 @@ show_homogeneity (void)
 
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 1, 0, 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   /* Put a frame around the entire box, and vertical lines inside */
   tab_box (t,
@@ -578,7 +578,7 @@ show_contrast_coeffs (short *bad_contrast)
 
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 2, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   /* Put a frame around the entire box, and vertical lines inside */
   tab_box (t,
@@ -663,7 +663,7 @@ show_contrast_tests (short *bad_contrast)
 
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 3, 0, 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   /* Put a frame around the entire box, and vertical lines inside */
   tab_box (t,
index 05c08dfad145eeb6c0c9d0f38a74f2b357525741..155ac3fd3285c99e6a4b11443478b7eec5ed535d 100644 (file)
@@ -150,7 +150,7 @@ reg_stats_r (pspp_linreg_cache * c)
   adjrsq = 1.0 - (1.0 - rsq) * (c->n_obs - 1.0) / (c->n_obs - c->n_indeps);
   std_error = sqrt (pspp_linreg_mse (c));
   t = tab_create (n_cols, n_rows, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
   tab_hline (t, TAL_2, 0, n_cols - 1, 1);
   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
@@ -193,7 +193,7 @@ reg_stats_coeff (pspp_linreg_cache * c)
 
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
   tab_hline (t, TAL_2, 0, n_cols - 1, 1);
   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
@@ -290,7 +290,7 @@ reg_stats_anova (pspp_linreg_cache * c)
   assert (c != NULL);
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
 
   tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
 
@@ -381,7 +381,7 @@ reg_stats_bcov (pspp_linreg_cache * c)
   n_rows = 2 * (c->n_indeps + 1);
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 1, 0);
-  tab_dim (t, tab_natural_dimensions, NULL);
+  tab_dim (t, tab_natural_dimensions, NULL, NULL);
   tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
   tab_hline (t, TAL_2, 0, n_cols - 1, 1);
   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
index 166a4dfae129fd2b59f3bb31b494be5a47d31882..52d8e3cbf625129439fe383b3efbfa26b434abc7 100644 (file)
@@ -383,7 +383,7 @@ run_reliability (struct casereader *input, struct dataset *ds,
   {
     struct tab_table *tab = tab_create(1, 1, 0);
 
-    tab_dim (tab, tab_natural_dimensions, NULL);
+    tab_dim (tab, tab_natural_dimensions, NULL, NULL);
     tab_flags (tab, SOMF_NO_TITLE );
 
     tab_text(tab, 0, 0, TAT_PRINTF, "Scale: %s", ds_cstr (&rel->scale_name));
@@ -428,7 +428,7 @@ reliability_statistics (const struct reliability *rel)
   struct tab_table *tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   tab_title (tbl, _("Reliability Statistics"));
 
@@ -471,7 +471,7 @@ reliability_summary_total (const struct reliability *rel)
   struct tab_table *tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   tab_title (tbl, _("Item-Total Statistics"));
 
@@ -681,7 +681,7 @@ case_processing_summary (casenumber n_valid, casenumber n_missing,
   tbl = tab_create (n_cols, n_rows, 0);
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
-  tab_dim (tbl, tab_natural_dimensions, NULL);
+  tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
 
   tab_title (tbl, _("Case Processing Summary"));
 
index a5a272126007c557a2c006b652d73cf7e9fe4436..82b126595f8a8b87986467c4b64e81b2501141d8 100644 (file)
@@ -57,7 +57,7 @@ output_frequency_table (const struct two_sample_test *t2s,
   const struct variable *wv = dict_get_weight (dict);
   const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
 
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, _("Frequencies"));
 
@@ -110,7 +110,7 @@ output_statistics_table (const struct two_sample_test *t2s,
   int i;
   struct tab_table *table = tab_create (1 + t2s->n_pairs, 4, 0);
 
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, _("Test Statistics"));
 
index c0a6f47715acf6d6b69aba0a820f37905572f376..500e18ffb422dfa1b5f22076f5b21160d86dbc37 100644 (file)
@@ -481,7 +481,7 @@ ssbox_base_init (struct ssbox *this, int cols, int rows)
   tab_headers (this->t, 0, 0, 1, 0);
   tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
   tab_hline (this->t, TAL_2, 0, cols- 1, 1);
-  tab_dim (this->t, tab_natural_dimensions, NULL);
+  tab_dim (this->t, tab_natural_dimensions, NULL, NULL);
 }
 \f
 /* ssbox implementations. */
@@ -1071,7 +1071,7 @@ trbox_base_init (struct trbox *self, size_t data_rows, int cols)
   tab_headers (self->t, 0, 0, 3, 0);
   tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1);
   tab_hline (self->t, TAL_2, 0, cols- 1, 3);
-  tab_dim (self->t, tab_natural_dimensions, NULL);
+  tab_dim (self->t, tab_natural_dimensions, NULL, NULL);
 }
 
 /* Base finalizer for the trbox */
@@ -1098,7 +1098,7 @@ pscbox (struct t_test_proc *proc)
   tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
   tab_hline (table, TAL_2, 0, cols - 1, 1);
   tab_vline (table, TAL_2, 2, 0, rows - 1);
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
   tab_title (table, _("Paired Samples Correlations"));
 
   /* column headings */
index 37d2b191ccfe323804733d69d0d7c7a98f9260af..ee14f7e6842a380b5e9ffa7f7f1499e832a08e5d 100644 (file)
@@ -227,7 +227,7 @@ show_ranks_box (const struct wilcoxon_state *ws,
 
   struct tab_table *table = tab_create (5, 1 + 4 * t2s->n_pairs, 0);
 
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, _("Ranks"));
 
@@ -308,7 +308,7 @@ show_tests_box (const struct wilcoxon_state *ws,
   size_t i;
   struct tab_table *table = tab_create (1 + t2s->n_pairs, exact ? 5 : 3, 0);
 
-  tab_dim (table, tab_natural_dimensions, NULL);
+  tab_dim (table, tab_natural_dimensions, NULL, NULL);
 
   tab_title (table, _("Test Statistics"));
 
index 19e9f9e54bf36b860b46f8d4681ce61660931b10..05353f81e6ad0e885c33c55fb7fa26a006613ad7 100644 (file)
@@ -35,7 +35,7 @@ cmd_echo (struct lexer *lexer, struct dataset *ds UNUSED)
 
   tab = tab_create(1, 1, 0);
 
-  tab_dim (tab, tab_natural_dimensions, NULL);
+  tab_dim (tab, tab_natural_dimensions, NULL, NULL);
   tab_flags (tab, SOMF_NO_TITLE );
 
   tab_text(tab, 0, 0, 0, ds_cstr (lex_tokstr (lexer)));
index 480534e1de4c3de8dbd02a3bc282a96172219144..3cf6a3ae03e698c218aba24fef3f31d6195c3986 100644 (file)
@@ -91,6 +91,8 @@ void
 tab_destroy (struct tab_table *t)
 {
   assert (t != NULL);
+  if (t->dim_free != NULL)
+    t->dim_free (t->dim_aux);
   free (t->title);
   pool_destroy (t->container);
 }
@@ -397,12 +399,22 @@ tab_title (struct tab_table *t, const char *title, ...)
   va_end (args);
 }
 
-/* Set DIM_FUNC as the dimension function for table T. */
+/* Set DIM_FUNC, which will be passed auxiliary data AUX, as the
+   dimension function for table T.
+
+   DIM_FUNC must not assume that it is called from the same
+   context as tab_dim; for example, table T might be kept in
+   memory and, thus, DIM_FUNC might be called after the currently
+   running command completes.  If it is non-null, FREE_FUNC is
+   called when the table is destroyed, to allow any data
+   allocated for use by DIM_FUNC to be freed.  */
 void
-tab_dim (struct tab_table *t, tab_dim_func *dim_func, void *aux)
+tab_dim (struct tab_table *t,
+         tab_dim_func *dim_func, tab_dim_free_func *free_func, void *aux)
 {
-  assert (t != NULL && t->dim == NULL);
+  assert (t->dim == NULL);
   t->dim = dim_func;
+  t->dim_free = free_func;
   t->dim_aux = aux;
 }
 
@@ -813,7 +825,7 @@ tab_output_text (int options, const char *buf, ...)
 
   tab_text (t, 0, 0, options & ~TAT_PRINTF, buf);
   tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING);
-  tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL);
+  tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL, NULL);
   tab_submit (t);
 
   free (tmp_buf);
index 1ce69ab4dd5bebf53676df8b8b4fb5073b6f6b95..516db6a52a7f44e5fe9e6a853aaf1fb63294587b 100644 (file)
@@ -70,6 +70,7 @@ struct tab_table;
 struct tab_rendering;
 
 typedef void tab_dim_func (struct tab_rendering *, void *aux);
+typedef void tab_dim_free_func (void *aux);
 
 /* A table. */
 struct tab_table
@@ -88,7 +89,10 @@ struct tab_table
     unsigned char *ct;         /* Cell types; unsigned char[nr][nc]. */
     unsigned char *rh;         /* Horiz rules; unsigned char[nr+1][nc]. */
     unsigned char *rv;         /* Vert rules; unsigned char[nr][nc+1]. */
+
+    /* Calculating row and column dimensions. */
     tab_dim_func *dim;         /* Calculates cell widths and heights. */
+    tab_dim_free_func *dim_free; /* Frees space allocated for dim function. */
     void *dim_aux;              /* Auxiliary data for dim function. */
 
     /* Editing info. */
@@ -138,7 +142,8 @@ void tab_submit (struct tab_table *);
 tab_dim_func tab_natural_dimensions;
 int tab_natural_width (const struct tab_rendering *, int c);
 int tab_natural_height (const struct tab_rendering *, int r);
-void tab_dim (struct tab_table *, tab_dim_func *, void *aux);
+void tab_dim (struct tab_table *,
+              tab_dim_func *, tab_dim_free_func *, void *aux);
 
 /* Rules. */
 void tab_hline (struct tab_table *, int style, int x1, int x2, int y);