From c8d4730341536ea6120a273100b0333327bf880a Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 20 Dec 2020 23:10:59 -0800 Subject: [PATCH 1/1] pivot-table: Make pivot_table_look a refcounted object. This is a first step toward adding a default pivot_table_look as a user setting. --- src/output/pivot-output.c | 48 +++--- src/output/pivot-table.c | 249 +++++++++++++--------------- src/output/pivot-table.h | 20 ++- src/output/spv/spv-legacy-decoder.c | 36 ++-- src/output/spv/spv-light-decoder.c | 39 ++--- src/output/spv/spv-table-look.c | 22 ++- src/output/spv/spv-writer.c | 38 ++--- src/output/spv/spv.c | 6 +- utilities/pspp-output.c | 14 +- 9 files changed, 227 insertions(+), 245 deletions(-) diff --git a/src/output/pivot-output.c b/src/output/pivot-output.c index e469afb081..31d68c8d37 100644 --- a/src/output/pivot-output.c +++ b/src/output/pivot-output.c @@ -313,9 +313,9 @@ pivot_table_submit_layer (const struct pivot_table *pt, size_t body[TABLE_N_AXES]; size_t *column_enumeration = pivot_table_enumerate_axis ( - pt, PIVOT_AXIS_COLUMN, layer_indexes, pt->look.omit_empty, &body[H]); + pt, PIVOT_AXIS_COLUMN, layer_indexes, pt->look->omit_empty, &body[H]); size_t *row_enumeration = pivot_table_enumerate_axis ( - pt, PIVOT_AXIS_ROW, layer_indexes, pt->look.omit_empty, &body[V]); + pt, PIVOT_AXIS_ROW, layer_indexes, pt->look->omit_empty, &body[V]); int stub[TABLE_N_AXES] = { [H] = pt->axes[PIVOT_AXIS_ROW].label_depth, @@ -327,11 +327,11 @@ pivot_table_submit_layer (const struct pivot_table *pt, for (size_t i = 0; i < PIVOT_N_AREAS; i++) table->styles[i] = table_area_style_override ( - table->container, &pt->look.areas[i], NULL, NULL); + table->container, &pt->look->areas[i], NULL, NULL); for (size_t i = 0; i < PIVOT_N_BORDERS; i++) { - const struct table_border_style *in = &pt->look.borders[i]; + const struct table_border_style *in = &pt->look->borders[i]; table->rule_colors[i] = pool_alloc (table->container, sizeof *table->rule_colors[i]); struct cell_color *out = table->rule_colors[i]; @@ -356,7 +356,7 @@ pivot_table_submit_layer (const struct pivot_table *pt, footnotes[i] = table_create_footnote ( table, i, content, marker, table_area_style_override (table->container, - &pt->look.areas[PIVOT_AREA_FOOTER], + &pt->look->areas[PIVOT_AREA_FOOTER], pf->content->cell_style, pf->content->font_style)); free (marker); @@ -365,29 +365,29 @@ pivot_table_submit_layer (const struct pivot_table *pt, compose_headings (table, &pt->axes[PIVOT_AXIS_COLUMN], H, &pt->axes[PIVOT_AXIS_ROW], - pt->look.borders, + pt->look->borders, PIVOT_BORDER_DIM_COL_HORZ, PIVOT_BORDER_DIM_COL_VERT, PIVOT_BORDER_CAT_COL_HORZ, PIVOT_BORDER_CAT_COL_VERT, column_enumeration, body[H], - &pt->look.areas[PIVOT_AREA_COLUMN_LABELS], + &pt->look->areas[PIVOT_AREA_COLUMN_LABELS], PIVOT_AREA_COLUMN_LABELS, - &pt->look.areas[PIVOT_AREA_CORNER], footnotes, + &pt->look->areas[PIVOT_AREA_CORNER], footnotes, pt->show_values, pt->show_variables, pt->rotate_inner_column_labels, false); compose_headings (table, &pt->axes[PIVOT_AXIS_ROW], V, &pt->axes[PIVOT_AXIS_COLUMN], - pt->look.borders, + pt->look->borders, PIVOT_BORDER_DIM_ROW_VERT, PIVOT_BORDER_DIM_ROW_HORZ, PIVOT_BORDER_CAT_ROW_VERT, PIVOT_BORDER_CAT_ROW_HORZ, row_enumeration, body[V], - &pt->look.areas[PIVOT_AREA_ROW_LABELS], + &pt->look->areas[PIVOT_AREA_ROW_LABELS], PIVOT_AREA_ROW_LABELS, - &pt->look.areas[PIVOT_AREA_CORNER], footnotes, + &pt->look->areas[PIVOT_AREA_CORNER], footnotes, pt->show_values, pt->show_variables, false, pt->rotate_outer_row_labels); @@ -406,7 +406,7 @@ pivot_table_submit_layer (const struct pivot_table *pt, fill_cell (table, x + stub[H], y + stub[V], x + stub[H], y + stub[V], - &pt->look.areas[PIVOT_AREA_DATA], PIVOT_AREA_DATA, + &pt->look->areas[PIVOT_AREA_DATA], PIVOT_AREA_DATA, value, footnotes, pt->show_values, pt->show_variables, false); @@ -419,32 +419,32 @@ pivot_table_submit_layer (const struct pivot_table *pt, if (pt->corner_text && stub[H] && stub[V]) fill_cell (table, 0, 0, stub[H] - 1, stub[V] - 1, - &pt->look.areas[PIVOT_AREA_CORNER], PIVOT_AREA_CORNER, + &pt->look->areas[PIVOT_AREA_CORNER], PIVOT_AREA_CORNER, pt->corner_text, footnotes, pt->show_values, pt->show_variables, false); if (table_nc (table) && table_nr (table)) { table_hline ( - table, get_table_rule (pt->look.borders, PIVOT_BORDER_INNER_TOP), + table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_TOP), 0, table_nc (table) - 1, 0); table_hline ( - table, get_table_rule (pt->look.borders, PIVOT_BORDER_INNER_BOTTOM), + table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_BOTTOM), 0, table_nc (table) - 1, table_nr (table)); table_vline ( - table, get_table_rule (pt->look.borders, PIVOT_BORDER_INNER_LEFT), + table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_LEFT), 0, 0, table_nr (table) - 1); table_vline ( - table, get_table_rule (pt->look.borders, PIVOT_BORDER_INNER_RIGHT), + table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_RIGHT), table_nc (table), 0, table_nr (table) - 1); if (stub[V]) table_hline ( - table, get_table_rule (pt->look.borders, PIVOT_BORDER_DATA_TOP), + table, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_TOP), 0, table_nc (table) - 1, stub[V]); if (stub[H]) table_vline ( - table, get_table_rule (pt->look.borders, PIVOT_BORDER_DATA_LEFT), + table, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_LEFT), stub[H], 0, table_nr (table) - 1); } @@ -456,7 +456,7 @@ pivot_table_submit_layer (const struct pivot_table *pt, if (pt->title) { struct table_item_text *title = pivot_value_to_table_item_text ( - pt->title, &pt->look.areas[PIVOT_AREA_TITLE], footnotes, + pt->title, &pt->look->areas[PIVOT_AREA_TITLE], footnotes, pt->show_values, pt->show_variables); table_item_set_title (ti, title); table_item_text_destroy (title); @@ -473,7 +473,7 @@ pivot_table_submit_layer (const struct pivot_table *pt, { layers = xzalloc (sizeof *layers); layers->style = table_area_style_override ( - NULL, &pt->look.areas[PIVOT_AREA_LAYERS], NULL, NULL); + NULL, &pt->look->areas[PIVOT_AREA_LAYERS], NULL, NULL); layers->layers = xnmalloc (layer_axis->n_dimensions, sizeof *layers->layers); } @@ -505,7 +505,7 @@ pivot_table_submit_layer (const struct pivot_table *pt, if (pt->caption && pt->show_caption) { struct table_item_text *caption = pivot_value_to_table_item_text ( - pt->caption, &pt->look.areas[PIVOT_AREA_CAPTION], footnotes, + pt->caption, &pt->look->areas[PIVOT_AREA_CAPTION], footnotes, pt->show_values, pt->show_variables); table_item_set_caption (ti, caption); table_item_text_destroy (caption); @@ -526,13 +526,13 @@ pivot_table_submit (struct pivot_table *pt) if (pt->decimal == '.' || pt->decimal == ',') settings_set_decimal_char (pt->decimal); - if (pt->look.print_all_layers) + if (pt->look->print_all_layers) { size_t *layer_indexes; PIVOT_AXIS_FOR_EACH (layer_indexes, &pt->axes[PIVOT_AXIS_LAYER]) { - if (pt->look.paginate_layers) + if (pt->look->paginate_layers) page_eject_item_submit (page_eject_item_create ()); pivot_table_submit_layer (pt, layer_indexes); } diff --git a/src/output/pivot-table.c b/src/output/pivot-table.c index 45704a7a1e..7eeee46ce6 100644 --- a/src/output/pivot-table.c +++ b/src/output/pivot-table.c @@ -62,70 +62,6 @@ pivot_area_to_string (enum pivot_area area) } } -const struct table_area_style * -pivot_area_get_default_style (enum pivot_area area) -{ -#define STYLE(BOLD, H, V, L, R, T, B) { \ - .cell_style = { \ - .halign = TABLE_HALIGN_##H, \ - .valign = TABLE_VALIGN_##V, \ - .margin = { [TABLE_HORZ][0] = L, [TABLE_HORZ][1] = R, \ - [TABLE_VERT][0] = T, [TABLE_VERT][1] = B }, \ - }, \ - .font_style = { \ - .bold = BOLD, \ - .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK}, \ - .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE}, \ - .size = 9, \ - .typeface = (char *) "Sans Serif", \ - }, \ - } - static const struct table_area_style default_area_styles[PIVOT_N_AREAS] = { - [PIVOT_AREA_TITLE] = STYLE(true, CENTER, CENTER, 8,11,1,8), - [PIVOT_AREA_CAPTION] = STYLE(false, LEFT, TOP, 8,11,1,1), - [PIVOT_AREA_FOOTER] = STYLE(false, LEFT, TOP, 11, 8,2,3), - [PIVOT_AREA_CORNER] = STYLE(false, LEFT, BOTTOM, 8,11,1,1), - [PIVOT_AREA_COLUMN_LABELS] = STYLE(false, CENTER, BOTTOM, 8,11,1,3), - [PIVOT_AREA_ROW_LABELS] = STYLE(false, LEFT, TOP, 8,11,1,3), - [PIVOT_AREA_DATA] = STYLE(false, MIXED, TOP, 8,11,1,1), - [PIVOT_AREA_LAYERS] = STYLE(false, LEFT, BOTTOM, 8,11,1,3), - }; -#undef STYLE - - return &default_area_styles[area]; -} - -void -pivot_border_get_default_style (enum pivot_border border, - struct table_border_style *style) -{ - static const enum table_stroke default_strokes[PIVOT_N_BORDERS] = { - [PIVOT_BORDER_TITLE] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_LEFT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_TOP] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_RIGHT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_BOTTOM] = TABLE_STROKE_NONE, - [PIVOT_BORDER_INNER_LEFT] = TABLE_STROKE_THICK, - [PIVOT_BORDER_INNER_TOP] = TABLE_STROKE_THICK, - [PIVOT_BORDER_INNER_RIGHT] = TABLE_STROKE_THICK, - [PIVOT_BORDER_INNER_BOTTOM] = TABLE_STROKE_THICK, - [PIVOT_BORDER_DATA_LEFT] = TABLE_STROKE_THICK, - [PIVOT_BORDER_DATA_TOP] = TABLE_STROKE_THICK, - [PIVOT_BORDER_DIM_ROW_HORZ] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_DIM_ROW_VERT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_DIM_COL_HORZ] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_DIM_COL_VERT] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_CAT_ROW_HORZ] = TABLE_STROKE_NONE, - [PIVOT_BORDER_CAT_ROW_VERT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_CAT_COL_HORZ] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_CAT_COL_VERT] = TABLE_STROKE_SOLID, - }; - *style = (struct table_border_style) { - .stroke = default_strokes[border], - .color = CELL_COLOR_BLACK, - }; -} - /* Returns the name of BORDER. */ const char * pivot_border_to_string (enum pivot_border border) @@ -195,59 +131,88 @@ pivot_table_sizing_uninit (struct pivot_table_sizing *sizing) /* Pivot table looks. */ -void -pivot_table_look_init (struct pivot_table_look *look) +const struct pivot_table_look * +pivot_table_look_builtin_default (void) { - memset (look, 0, sizeof *look); + static struct pivot_table_look look = { + .ref_cnt = 1, - look->omit_empty = true; - look->row_labels_in_corner = true; - look->width_ranges[TABLE_HORZ][0] = 36; - look->width_ranges[TABLE_HORZ][1] = 72; - look->width_ranges[TABLE_VERT][0] = 36; - look->width_ranges[TABLE_VERT][1] = 120; + .omit_empty = true, + .row_labels_in_corner = true, + .width_ranges = { + [TABLE_HORZ] = { 36, 72 }, + [TABLE_VERT] = { 36, 120 }, + }, - for (size_t i = 0; i < PIVOT_N_AREAS; i++) - table_area_style_copy (NULL, &look->areas[i], - pivot_area_get_default_style (i)); - - static const enum table_stroke default_strokes[PIVOT_N_BORDERS] = { - [PIVOT_BORDER_TITLE] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_LEFT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_TOP] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_RIGHT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_OUTER_BOTTOM] = TABLE_STROKE_NONE, - [PIVOT_BORDER_INNER_LEFT] = TABLE_STROKE_THICK, - [PIVOT_BORDER_INNER_TOP] = TABLE_STROKE_THICK, - [PIVOT_BORDER_INNER_RIGHT] = TABLE_STROKE_THICK, - [PIVOT_BORDER_INNER_BOTTOM] = TABLE_STROKE_THICK, - [PIVOT_BORDER_DATA_LEFT] = TABLE_STROKE_THICK, - [PIVOT_BORDER_DATA_TOP] = TABLE_STROKE_THICK, - [PIVOT_BORDER_DIM_ROW_HORZ] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_DIM_ROW_VERT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_DIM_COL_HORZ] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_DIM_COL_VERT] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_CAT_ROW_HORZ] = TABLE_STROKE_NONE, - [PIVOT_BORDER_CAT_ROW_VERT] = TABLE_STROKE_NONE, - [PIVOT_BORDER_CAT_COL_HORZ] = TABLE_STROKE_SOLID, - [PIVOT_BORDER_CAT_COL_VERT] = TABLE_STROKE_SOLID, + .areas = { +#define AREA(BOLD, H, V, L, R, T, B) { \ + .cell_style = { \ + .halign = TABLE_HALIGN_##H, \ + .valign = TABLE_VALIGN_##V, \ + .margin = { [TABLE_HORZ][0] = L, [TABLE_HORZ][1] = R, \ + [TABLE_VERT][0] = T, [TABLE_VERT][1] = B }, \ + }, \ + .font_style = { \ + .bold = BOLD, \ + .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK}, \ + .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE}, \ + .size = 9, \ + .typeface = (char *) "Sans Serif", \ + }, \ + } + [PIVOT_AREA_TITLE] = AREA(true, CENTER, CENTER, 8,11,1,8), + [PIVOT_AREA_CAPTION] = AREA(false, LEFT, TOP, 8,11,1,1), + [PIVOT_AREA_FOOTER] = AREA(false, LEFT, TOP, 11, 8,2,3), + [PIVOT_AREA_CORNER] = AREA(false, LEFT, BOTTOM, 8,11,1,1), + [PIVOT_AREA_COLUMN_LABELS] = AREA(false, CENTER, BOTTOM, 8,11,1,3), + [PIVOT_AREA_ROW_LABELS] = AREA(false, LEFT, TOP, 8,11,1,3), + [PIVOT_AREA_DATA] = AREA(false, MIXED, TOP, 8,11,1,1), + [PIVOT_AREA_LAYERS] = AREA(false, LEFT, BOTTOM, 8,11,1,3), +#undef AREA + }, + + .borders = { +#define BORDER(STROKE) { .stroke = STROKE, .color = CELL_COLOR_BLACK } + [PIVOT_BORDER_TITLE] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_OUTER_LEFT] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_OUTER_TOP] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_OUTER_RIGHT] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_OUTER_BOTTOM] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_INNER_LEFT] = BORDER(TABLE_STROKE_THICK), + [PIVOT_BORDER_INNER_TOP] = BORDER(TABLE_STROKE_THICK), + [PIVOT_BORDER_INNER_RIGHT] = BORDER(TABLE_STROKE_THICK), + [PIVOT_BORDER_INNER_BOTTOM] = BORDER(TABLE_STROKE_THICK), + [PIVOT_BORDER_DATA_LEFT] = BORDER(TABLE_STROKE_THICK), + [PIVOT_BORDER_DATA_TOP] = BORDER(TABLE_STROKE_THICK), + [PIVOT_BORDER_DIM_ROW_HORZ] = BORDER(TABLE_STROKE_SOLID), + [PIVOT_BORDER_DIM_ROW_VERT] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_DIM_COL_HORZ] = BORDER(TABLE_STROKE_SOLID), + [PIVOT_BORDER_DIM_COL_VERT] = BORDER(TABLE_STROKE_SOLID), + [PIVOT_BORDER_CAT_ROW_HORZ] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_CAT_ROW_VERT] = BORDER(TABLE_STROKE_NONE), + [PIVOT_BORDER_CAT_COL_HORZ] = BORDER(TABLE_STROKE_SOLID), + [PIVOT_BORDER_CAT_COL_VERT] = BORDER(TABLE_STROKE_SOLID), + }, }; - for (size_t i = 0; i < PIVOT_N_BORDERS; i++) - look->borders[i] = (struct table_border_style) { - .stroke = default_strokes[i], - .color = CELL_COLOR_BLACK, - }; + + return &look; } -void -pivot_table_look_uninit (struct pivot_table_look *look) +struct pivot_table_look * +pivot_table_look_new_builtin_default (void) { - free (look->name); + return pivot_table_look_unshare ( + pivot_table_look_ref (pivot_table_look_builtin_default ())); +} - for (size_t i = 0; i < PIVOT_N_AREAS; i++) - table_area_style_uninit (&look->areas[i]); +struct pivot_table_look * +pivot_table_look_ref (const struct pivot_table_look *look_) +{ + assert (look_->ref_cnt > 0); - free (look->continuation); + struct pivot_table_look *look = CONST_CAST (struct pivot_table_look *, look_); + look->ref_cnt++; + return look; } static char * @@ -256,15 +221,40 @@ xstrdup_if_nonempty (const char *s) return s && s[0] ? xstrdup (s) : NULL; } -void -pivot_table_look_copy (struct pivot_table_look *dst, - const struct pivot_table_look *src) +struct pivot_table_look * +pivot_table_look_unshare (struct pivot_table_look *old) { - *dst = *src; - dst->name = xstrdup_if_nonempty (src->name); + assert (old->ref_cnt > 0); + if (old->ref_cnt == 1) + return old; + + pivot_table_look_unref (old); + + struct pivot_table_look *new = xmemdup (old, sizeof *old); + new->ref_cnt = 1; + new->name = xstrdup_if_nonempty (old->name); for (size_t i = 0; i < PIVOT_N_AREAS; i++) - table_area_style_copy (NULL, &dst->areas[i], &src->areas[i]); - dst->continuation = xstrdup_if_nonempty (src->continuation); + table_area_style_copy (NULL, &new->areas[i], &old->areas[i]); + new->continuation = xstrdup_if_nonempty (old->continuation); + + return new; +} + +void +pivot_table_look_unref (struct pivot_table_look *look) +{ + if (look) + { + assert (look->ref_cnt > 0); + if (!--look->ref_cnt) + { + free (look->name); + for (size_t i = 0; i < PIVOT_N_AREAS; i++) + table_area_style_uninit (&look->areas[i]); + free (look->continuation); + free (look); + } + } } /* Axes. */ @@ -780,8 +770,7 @@ pivot_table_create__ (struct pivot_value *title, const char *subtype) table->title = title; table->subtype = subtype ? pivot_value_new_text (subtype) : NULL; table->command_c = output_get_command_name (); - - pivot_table_look_init (&table->look); + table->look = pivot_table_look_ref (pivot_table_look_builtin_default ()); hmap_init (&table->cells); @@ -831,7 +820,7 @@ pivot_table_unref (struct pivot_table *table) return; free (table->current_layer); - pivot_table_look_uninit (&table->look); + pivot_table_look_unref (table->look); for (int i = 0; i < TABLE_N_AXES; i++) pivot_table_sizing_uninit (&table->sizing[i]); @@ -887,15 +876,15 @@ pivot_table_is_shared (const struct pivot_table *table) const struct pivot_table_look * pivot_table_get_look (const struct pivot_table *table) { - return &table->look; + return table->look; } void pivot_table_set_look (struct pivot_table *table, const struct pivot_table_look *look) { - pivot_table_look_uninit (&table->look); - pivot_table_look_copy (&table->look, look); + pivot_table_look_unref (table->look); + table->look = pivot_table_look_ref (look); } /* Sets the format used for PIVOT_RC_COUNT cells to the one used for variable @@ -1103,7 +1092,7 @@ pivot_table_create_footnote__ (struct pivot_table *table, size_t idx, struct pivot_footnote *f = xmalloc (sizeof *f); f->idx = table->n_footnotes; f->marker = pivot_make_default_footnote_marker ( - f->idx, table->look.show_numeric_markers); + f->idx, table->look->show_numeric_markers); f->content = NULL; f->show = true; @@ -1330,7 +1319,7 @@ pivot_table_assign_label_depth (struct pivot_table *table) { pivot_axis_assign_label_depth (table, PIVOT_AXIS_COLUMN, false); if (pivot_axis_assign_label_depth ( - table, PIVOT_AXIS_ROW, (table->look.row_labels_in_corner + table, PIVOT_AXIS_ROW, (table->look->row_labels_in_corner && !table->corner_text)) && table->axes[PIVOT_AXIS_COLUMN].label_depth == 0) table->axes[PIVOT_AXIS_COLUMN].label_depth = 1; @@ -1541,7 +1530,7 @@ pivot_table_dump (const struct pivot_table *table, int indentation) pivot_table_dump_string (table->dataset, "dataset", indentation); pivot_table_dump_string (table->datafile, "datafile", indentation); pivot_table_dump_string (table->notes, "notes", indentation); - pivot_table_dump_string (table->look.name, "table-look", indentation); + pivot_table_dump_string (table->look->name, "table-look", indentation); if (table->date) { indent (indentation); @@ -1554,20 +1543,20 @@ pivot_table_dump (const struct pivot_table *table, int indentation) indent (indentation); printf ("sizing:\n"); - pivot_table_sizing_dump ("column", table->look.width_ranges[TABLE_HORZ], + pivot_table_sizing_dump ("column", table->look->width_ranges[TABLE_HORZ], &table->sizing[TABLE_HORZ], indentation + 1); - pivot_table_sizing_dump ("row", table->look.width_ranges[TABLE_VERT], + pivot_table_sizing_dump ("row", table->look->width_ranges[TABLE_VERT], &table->sizing[TABLE_VERT], indentation + 1); indent (indentation); printf ("areas:\n"); for (enum pivot_area area = 0; area < PIVOT_N_AREAS; area++) - table_area_style_dump (area, &table->look.areas[area], indentation + 1); + table_area_style_dump (area, &table->look->areas[area], indentation + 1); indent (indentation); printf ("borders:\n"); for (enum pivot_border border = 0; border < PIVOT_N_BORDERS; border++) - table_border_style_dump (border, &table->look.borders[border], + table_border_style_dump (border, &table->look->borders[border], indentation + 1); for (size_t i = 0; i < table->n_dimensions; i++) @@ -1637,9 +1626,9 @@ pivot_table_dump (const struct pivot_table *table, int indentation) putchar ('\n'); size_t *column_enumeration = pivot_table_enumerate_axis ( - table, PIVOT_AXIS_COLUMN, layer_indexes, table->look.omit_empty, NULL); + table, PIVOT_AXIS_COLUMN, layer_indexes, table->look->omit_empty, NULL); size_t *row_enumeration = pivot_table_enumerate_axis ( - table, PIVOT_AXIS_ROW, layer_indexes, table->look.omit_empty, NULL); + table, PIVOT_AXIS_ROW, layer_indexes, table->look->omit_empty, NULL); char ***column_headings = compose_headings ( &table->axes[PIVOT_AXIS_COLUMN], column_enumeration, diff --git a/src/output/pivot-table.h b/src/output/pivot-table.h index 99fbdb295d..94adcca73e 100644 --- a/src/output/pivot-table.h +++ b/src/output/pivot-table.h @@ -107,7 +107,6 @@ enum pivot_area }; const char *pivot_area_to_string (enum pivot_area); -const struct table_area_style *pivot_area_get_default_style (enum pivot_area); /* Table borders for styling purposes. */ enum pivot_border @@ -146,8 +145,6 @@ enum pivot_border }; const char *pivot_border_to_string (enum pivot_border); -void pivot_border_get_default_style (enum pivot_border, - struct table_border_style *); /* Sizing for rows or columns of a rendered table. The comments below talk about columns and their widths but they apply equally to rows and their @@ -376,6 +373,11 @@ bool pivot_result_class_change (const char *, const struct fmt_spec *); because that's how SPSS documentation and file formats do it. */ struct pivot_table_look { + /* Reference count. A pivot_table_look may be shared between multiple + owners, indicated by a reference count greater than 1. When this is the + case, the pivot_table must not be modified. */ + int ref_cnt; + char *name; /* May be null. */ /* General properties. */ @@ -400,10 +402,12 @@ struct pivot_table_look size_t n_orphan_lines; }; -void pivot_table_look_init (struct pivot_table_look *); -void pivot_table_look_uninit (struct pivot_table_look *); -void pivot_table_look_copy (struct pivot_table_look *, - const struct pivot_table_look *); +const struct pivot_table_look *pivot_table_look_builtin_default (void); +struct pivot_table_look *pivot_table_look_new_builtin_default (void); +struct pivot_table_look *pivot_table_look_ref ( + const struct pivot_table_look *); +void pivot_table_look_unref (struct pivot_table_look *); +struct pivot_table_look *pivot_table_look_unshare (struct pivot_table_look *); /* A pivot table. See the top of this file for more information. */ struct pivot_table @@ -414,7 +418,7 @@ struct pivot_table int ref_cnt; /* Styling. */ - struct pivot_table_look look; + struct pivot_table_look *look; /* Display settings. */ bool rotate_inner_column_labels; diff --git a/src/output/spv/spv-legacy-decoder.c b/src/output/spv/spv-legacy-decoder.c index 09924cf8e0..1894092a14 100644 --- a/src/output/spv/spv-legacy-decoder.c +++ b/src/output/spv/spv-legacy-decoder.c @@ -671,12 +671,12 @@ decode_label_frame (struct pivot_table *table, if (lf->label->purpose == SPVDX_PURPOSE_TITLE) { target = &table->title; - area = &table->look.areas[PIVOT_AREA_TITLE]; + area = &table->look->areas[PIVOT_AREA_TITLE]; } else if (lf->label->purpose == SPVDX_PURPOSE_SUB_TITLE) { target = &table->caption; - area = &table->look.areas[PIVOT_AREA_CAPTION]; + area = &table->look->areas[PIVOT_AREA_CAPTION]; } else if (lf->label->purpose == SPVDX_PURPOSE_FOOTNOTE) { @@ -684,7 +684,7 @@ decode_label_frame (struct pivot_table *table, && lf->label->text[0]->uses_reference != INT_MIN) { target = NULL; - area = &table->look.areas[PIVOT_AREA_FOOTER]; + area = &table->look->areas[PIVOT_AREA_FOOTER]; } else return NULL; @@ -692,7 +692,7 @@ decode_label_frame (struct pivot_table *table, else if (lf->label->purpose == SPVDX_PURPOSE_LAYER) { target = NULL; - area = &table->look.areas[PIVOT_AREA_LAYERS]; + area = &table->look->areas[PIVOT_AREA_LAYERS]; } else return NULL; @@ -1081,9 +1081,9 @@ add_dimension (struct spv_series **series, size_t n, { struct table_area_style *area = (axis_type == PIVOT_AXIS_COLUMN - ? &table->look.areas[PIVOT_AREA_COLUMN_LABELS] + ? &table->look->areas[PIVOT_AREA_COLUMN_LABELS] : axis_type == PIVOT_AXIS_ROW - ? &table->look.areas[PIVOT_AREA_ROW_LABELS] + ? &table->look->areas[PIVOT_AREA_ROW_LABELS] : NULL); if (area && fl->axis->label) { @@ -1101,7 +1101,7 @@ add_dimension (struct spv_series **series, size_t n, decode_spvdx_style_incremental ( fl2->axis->major_ticks->style, fl2->axis->major_ticks->tick_frame_style, - &table->look.areas[PIVOT_AREA_ROW_LABELS]); + &table->look->areas[PIVOT_AREA_ROW_LABELS]); } const struct spvdx_facet_level *fl3 = find_facet_level (v, base_facet_level); @@ -1494,9 +1494,9 @@ decode_set_cell_properties__ (struct pivot_table *table, /* Sets alt_fg_color and alt_bg_color. */ struct table_area_style area; decode_spvdx_style (labeling, graph, &area); - table->look.areas[PIVOT_AREA_DATA].font_style.fg[1] + table->look->areas[PIVOT_AREA_DATA].font_style.fg[1] = area.font_style.fg[0]; - table->look.areas[PIVOT_AREA_DATA].font_style.bg[1] + table->look->areas[PIVOT_AREA_DATA].font_style.bg[1] = area.font_style.bg[0]; table_area_style_uninit (&area); } @@ -1532,8 +1532,8 @@ decode_set_cell_properties__ (struct pivot_table *table, { const struct table_area_style *base_area_style = (c->dimension->axis_type == PIVOT_AXIS_ROW - ? &table->look.areas[PIVOT_AREA_ROW_LABELS] - : &table->look.areas[PIVOT_AREA_COLUMN_LABELS]); + ? &table->look->areas[PIVOT_AREA_ROW_LABELS] + : &table->look->areas[PIVOT_AREA_COLUMN_LABELS]); apply_styles_to_value (table, c->name, set_format, base_area_style, major_ticks, frame); } @@ -1626,7 +1626,7 @@ decode_set_cell_properties__ (struct pivot_table *table, goto skip; } apply_styles_to_value (table, cell->value, set_format, - &table->look.areas[PIVOT_AREA_DATA], + &table->look->areas[PIVOT_AREA_DATA], labeling, interval); skip: ; @@ -1697,7 +1697,7 @@ decode_set_cell_properties (struct pivot_table *table, struct hmap *series_map, struct pivot_cell *cell; HMAP_FOR_EACH (cell, struct pivot_cell, hmap_node, &table->cells) apply_styles_to_value (table, cell->value, set_format, - &table->look.areas[PIVOT_AREA_DATA], + &table->look->areas[PIVOT_AREA_DATA], NULL, NULL); } } @@ -1760,7 +1760,9 @@ decode_spvdx_table (const struct spvdx_visualization *v, const char *subtype, struct spv_data *data, struct pivot_table **outp) { struct pivot_table *table = pivot_table_create__ (NULL, subtype); + pivot_table_set_look (table, look); + table->look = pivot_table_look_unshare (table->look); struct hmap series_map = HMAP_INITIALIZER (series_map); struct hmap format_map = HMAP_INITIALIZER (format_map); @@ -1778,8 +1780,8 @@ decode_spvdx_table (const struct spvdx_visualization *v, const char *subtype, &min_width, &max_width, &n) && v->graph->cell_style->width[n] == '\0') { - table->look.width_ranges[TABLE_HORZ][0] = min_width; - table->look.width_ranges[TABLE_HORZ][1] = max_width; + table->look->width_ranges[TABLE_HORZ][0] = min_width; + table->look->width_ranges[TABLE_HORZ][1] = max_width; } } @@ -1845,10 +1847,10 @@ decode_spvdx_table (const struct spvdx_visualization *v, const char *subtype, } if (v->graph->interval->labeling->style) { - table_area_style_uninit (&table->look.areas[PIVOT_AREA_DATA]); + table_area_style_uninit (&table->look->areas[PIVOT_AREA_DATA]); decode_spvdx_style (v->graph->interval->labeling->style, v->graph->cell_style, - &table->look.areas[PIVOT_AREA_DATA]); + &table->look->areas[PIVOT_AREA_DATA]); } /* Decode all of the sourceVariable and derivedVariable */ diff --git a/src/output/spv/spv-light-decoder.c b/src/output/spv/spv-light-decoder.c index a352106434..990a847b85 100644 --- a/src/output/spv/spv-light-decoder.c +++ b/src/output/spv/spv-light-decoder.c @@ -679,7 +679,7 @@ decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table) if (in->border_type >= PIVOT_N_BORDERS) return xasprintf ("bad border type %"PRIu32, in->border_type); - struct table_border_style *out = &table->look.borders[in->border_type]; + struct table_border_style *out = &table->look->borders[in->border_type]; out->color = decode_spvlb_color_u32 (in->color); return decode_spvlb_stroke (in->stroke_type, &out->stroke); } @@ -825,6 +825,7 @@ decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp) struct pivot_table *out = xzalloc (sizeof *out); out->ref_cnt = 1; hmap_init (&out->cells); + out->look = pivot_table_look_new_builtin_default (); const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1 : in->formats->x3 ? in->formats->x3->y1 @@ -839,14 +840,14 @@ decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp) } /* Display settings. */ - out->look.show_numeric_markers = !in->ts->show_alphabetic_markers; + out->look->show_numeric_markers = !in->ts->show_alphabetic_markers; out->rotate_inner_column_labels = in->header->rotate_inner_column_labels; out->rotate_outer_row_labels = in->header->rotate_outer_row_labels; - out->look.row_labels_in_corner = in->ts->show_row_labels_in_corner; + out->look->row_labels_in_corner = in->ts->show_row_labels_in_corner; out->show_grid_lines = in->borders->show_grid_lines; out->show_caption = true; - out->look.footnote_marker_superscripts = in->ts->footnote_marker_superscripts; - out->look.omit_empty = in->ts->omit_empty; + out->look->footnote_marker_superscripts = in->ts->footnote_marker_superscripts; + out->look->omit_empty = in->ts->omit_empty; const struct spvlb_x1 *x1 = in->formats->x1; if (x1) @@ -862,10 +863,10 @@ decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp) } /* Column and row display settings. */ - out->look.width_ranges[TABLE_VERT][0] = in->header->min_row_height; - out->look.width_ranges[TABLE_VERT][1] = in->header->max_row_height; - out->look.width_ranges[TABLE_HORZ][0] = in->header->min_col_width; - out->look.width_ranges[TABLE_HORZ][1] = in->header->max_col_width; + out->look->width_ranges[TABLE_VERT][0] = in->header->min_row_height; + out->look->width_ranges[TABLE_VERT][1] = in->header->max_row_height; + out->look->width_ranges[TABLE_HORZ][0] = in->header->min_col_width; + out->look->width_ranges[TABLE_HORZ][1] = in->header->max_col_width; convert_widths (in->formats->widths, in->formats->n_widths, &out->sizing[TABLE_HORZ].widths, @@ -892,17 +893,17 @@ decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp) &out->sizing[TABLE_HORZ].n_keeps); out->notes = to_utf8_if_nonempty (in->ts->notes, encoding); - out->look.name = to_utf8_if_nonempty (in->ts->table_look, encoding); + out->look->name = to_utf8_if_nonempty (in->ts->table_look, encoding); /* Print settings. */ - out->look.print_all_layers = in->ps->all_layers; - out->look.paginate_layers = in->ps->paginate_layers; - out->look.shrink_to_fit[TABLE_HORZ] = in->ps->fit_width; - out->look.shrink_to_fit[TABLE_VERT] = in->ps->fit_length; - out->look.top_continuation = in->ps->top_continuation; - out->look.bottom_continuation = in->ps->bottom_continuation; - out->look.continuation = xstrdup (in->ps->continuation_string); - out->look.n_orphan_lines = in->ps->n_orphan_lines; + out->look->print_all_layers = in->ps->all_layers; + out->look->paginate_layers = in->ps->paginate_layers; + out->look->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width; + out->look->shrink_to_fit[TABLE_VERT] = in->ps->fit_length; + out->look->top_continuation = in->ps->top_continuation; + out->look->bottom_continuation = in->ps->bottom_continuation; + out->look->continuation = xstrdup (in->ps->continuation_string); + out->look->n_orphan_lines = in->ps->n_orphan_lines; /* Format settings. */ out->epoch = in->formats->y0->epoch; @@ -990,7 +991,7 @@ decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp) /* Styles. */ for (size_t i = 0; i < PIVOT_N_AREAS; i++) { - error = decode_spvlb_area (in->areas->areas[i], &out->look.areas[i], + error = decode_spvlb_area (in->areas->areas[i], &out->look->areas[i], encoding); if (error) goto error; diff --git a/src/output/spv/spv-table-look.c b/src/output/spv/spv-table-look.c index d229af2c0c..3e5f962bd3 100644 --- a/src/output/spv/spv-table-look.c +++ b/src/output/spv/spv-table-look.c @@ -128,7 +128,7 @@ char * WARN_UNUSED_RESULT spv_table_look_decode (const struct spvsx_table_properties *in, struct pivot_table_look **outp) { - struct pivot_table_look *out = xzalloc (sizeof *out); + struct pivot_table_look *out = pivot_table_look_new_builtin_default (); char *error = NULL; out->name = in->name ? xstrdup (in->name) : NULL; @@ -148,10 +148,6 @@ spv_table_look_decode (const struct spvsx_table_properties *in, out->show_numeric_markers = (f->number_format == SPVSX_NUMBER_FORMAT_NUMERIC); - for (int i = 0; i < PIVOT_N_AREAS; i++) - table_area_style_copy (NULL, &out->areas[i], - pivot_area_get_default_style (i)); - const struct spvsx_cell_format_properties *cfp = in->cell_format_properties; for (size_t i = 0; i < cfp->n_cell_style; i++) { @@ -229,9 +225,6 @@ spv_table_look_decode (const struct spvsx_table_properties *in, 1); } - for (int i = 0; i < PIVOT_N_BORDERS; i++) - pivot_border_get_default_style (i, &out->borders[i]); - const struct spvsx_border_properties *bp = in->border_properties; for (size_t i = 0; i < bp->n_border_style; i++) { @@ -269,6 +262,7 @@ spv_table_look_decode (const struct spvsx_table_properties *in, out->shrink_to_fit[TABLE_VERT] = pp->rescale_long_table_to_fit_page > 0; out->top_continuation = pp->continuation_text_at_top > 0; out->bottom_continuation = pp->continuation_text_at_bottom > 0; + free (out->continuation); out->continuation = xstrdup (pp->continuation_text ? pp->continuation_text : "(cont.)"); out->n_orphan_lines = optional_int (pp->window_orphan_lines, 2); @@ -277,8 +271,7 @@ spv_table_look_decode (const struct spvsx_table_properties *in, return NULL; error: - pivot_table_look_uninit (out); - free (out); + pivot_table_look_unref (out); *outp = NULL; return error; } @@ -380,8 +373,7 @@ tlo_decode_area (const struct tlo_area_color *color, static struct pivot_table_look * tlo_decode (const struct tlo_table_look *in) { - struct pivot_table_look *out = xmalloc (sizeof *out); - pivot_table_look_init (out); + struct pivot_table_look *out = pivot_table_look_new_builtin_default (); const uint16_t flags = in->tl->flags; @@ -487,6 +479,12 @@ tlo_decode (const struct tlo_table_look *in) out->shrink_to_fit[TABLE_VERT] = flags & 0x20; out->top_continuation = flags & 0x80; out->bottom_continuation = flags & 0x100; + if (in->v2_styles) + { + free (out->continuation); + out->continuation = xmemdup0 (in->v2_styles->continuation, + in->v2_styles->continuation_len); + } /* n_orphan_lines isn't in .tlo files AFAICT. */ return out; diff --git a/src/output/spv/spv-writer.c b/src/output/spv/spv-writer.c index 12f3ec70df..f1aa798dc0 100644 --- a/src/output/spv/spv-writer.c +++ b/src/output/spv/spv-writer.c @@ -773,10 +773,10 @@ put_light_table (struct buf *buf, uint64_t table_id, put_bool (buf, table->rotate_outer_row_labels); put_bool (buf, true); put_u32 (buf, 0x15); - put_u32 (buf, table->look.width_ranges[H][0]); - put_u32 (buf, table->look.width_ranges[H][1]); - put_u32 (buf, table->look.width_ranges[V][0]); - put_u32 (buf, table->look.width_ranges[V][1]); + put_u32 (buf, table->look->width_ranges[H][0]); + put_u32 (buf, table->look->width_ranges[H][1]); + put_u32 (buf, table->look->width_ranges[V][0]); + put_u32 (buf, table->look->width_ranges[V][1]); put_u64 (buf, table_id); /* Titles. */ @@ -798,7 +798,7 @@ put_light_table (struct buf *buf, uint64_t table_id, /* Areas. */ for (size_t i = 0; i < PIVOT_N_AREAS; i++) { - const struct table_area_style *a = &table->look.areas[i]; + const struct table_area_style *a = &table->look->areas[i]; put_byte (buf, i + 1); put_byte (buf, 0x31); put_string (buf, (a->font_style.typeface @@ -841,7 +841,7 @@ put_light_table (struct buf *buf, uint64_t table_id, put_be32 (buf, PIVOT_N_BORDERS); for (size_t i = 0; i < PIVOT_N_BORDERS; i++) { - const struct table_border_style *b = &table->look.borders[i]; + const struct table_border_style *b = &table->look->borders[i]; put_be32 (buf, i); put_be32 (buf, (b->stroke == TABLE_STROKE_NONE ? 0 : b->stroke == TABLE_STROKE_SOLID ? 1 @@ -861,14 +861,14 @@ put_light_table (struct buf *buf, uint64_t table_id, /* Print Settings. */ uint32_t ps_start = start_count (buf); put_be32 (buf, 1); - put_bool (buf, table->look.print_all_layers); - put_bool (buf, table->look.paginate_layers); - put_bool (buf, table->look.shrink_to_fit[H]); - put_bool (buf, table->look.shrink_to_fit[V]); - put_bool (buf, table->look.top_continuation); - put_bool (buf, table->look.bottom_continuation); - put_be32 (buf, table->look.n_orphan_lines); - put_bestring (buf, table->look.continuation); + put_bool (buf, table->look->print_all_layers); + put_bool (buf, table->look->paginate_layers); + put_bool (buf, table->look->shrink_to_fit[H]); + put_bool (buf, table->look->shrink_to_fit[V]); + put_bool (buf, table->look->top_continuation); + put_bool (buf, table->look->bottom_continuation); + put_be32 (buf, table->look->n_orphan_lines); + put_bestring (buf, table->look->continuation); end_count_u32 (buf, ps_start); /* Table Settings. */ @@ -876,10 +876,10 @@ put_light_table (struct buf *buf, uint64_t table_id, put_be32 (buf, 1); put_be32 (buf, 4); put_be32 (buf, 0); /* XXX current_layer */ - put_bool (buf, table->look.omit_empty); - put_bool (buf, table->look.row_labels_in_corner); - put_bool (buf, !table->look.show_numeric_markers); - put_bool (buf, table->look.footnote_marker_superscripts); + put_bool (buf, table->look->omit_empty); + put_bool (buf, table->look->row_labels_in_corner); + put_bool (buf, !table->look->show_numeric_markers); + put_bool (buf, table->look->footnote_marker_superscripts); put_byte (buf, 0); uint32_t keep_start = start_count (buf); put_be32 (buf, 0); /* n-row-breaks */ @@ -890,7 +890,7 @@ put_light_table (struct buf *buf, uint64_t table_id, put_be32 (buf, 0); /* n-column-point-keeps */ end_count_be32 (buf, keep_start); put_bestring (buf, table->notes); - put_bestring (buf, table->look.name); + put_bestring (buf, table->look->name); for (size_t i = 0; i < 82; i++) put_byte (buf, 0); end_count_u32 (buf, ts_start); diff --git a/src/output/spv/spv.c b/src/output/spv/spv.c index 5f537edfc8..cbdf10fcdf 100644 --- a/src/output/spv/spv.c +++ b/src/output/spv/spv.c @@ -260,11 +260,7 @@ spv_item_destroy (struct spv_item *item) free (item->children); pivot_table_unref (item->table); - if (item->table_look) - { - pivot_table_look_uninit (item->table_look); - free (item->table_look); - } + pivot_table_look_unref (item->table_look); free (item->bin_member); free (item->xml_member); free (item->subtype); diff --git a/utilities/pspp-output.c b/utilities/pspp-output.c index b3b4b57fa0..f9f149bd63 100644 --- a/utilities/pspp-output.c +++ b/utilities/pspp-output.c @@ -374,7 +374,7 @@ run_convert_table_look (int argc UNUSED, char **argv) if (err) error (1, 0, "%s", err); - pivot_table_look_uninit (look); + pivot_table_look_unref (look); free (look); } @@ -808,11 +808,7 @@ main (int argc, char **argv) c->run (argc, argv); - if (table_look) - { - pivot_table_look_uninit (table_look); - free (table_look); - } + pivot_table_look_unref (table_look); i18n_done (); return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS; @@ -942,11 +938,7 @@ parse_members (const char *arg) static void parse_table_look (const char *arg) { - if (table_look) - { - pivot_table_look_uninit (table_look); - free (table_look); - } + pivot_table_look_unref (table_look); char *error_s = spv_table_look_read (arg, &table_look); if (error_s) -- 2.30.2