X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fpivot-table.c;h=30371cae368ad32884f51e675fab8b588e41a07e;hb=bcaaee5f0bd21f443c8dcb5f67114e63d43673af;hp=96821170eff043db82a47e88004d19f2ba84747c;hpb=1abd7f599dd0d773add0a98fa3b612bc15aaf422;p=pspp diff --git a/src/output/pivot-table.c b/src/output/pivot-table.c index 96821170ef..30371cae36 100644 --- a/src/output/pivot-table.c +++ b/src/output/pivot-table.c @@ -61,6 +61,70 @@ pivot_area_to_string (enum pivot_area area) } } +void +pivot_area_get_default_style (enum pivot_area area, struct area_style *style) +{ +#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, \ + }, \ + } + static const struct 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 + + *style = default_area_styles[area]; + style->font_style.typeface = xstrdup ("SansSerif"); +} + +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) @@ -279,7 +343,7 @@ pivot_dimension_create__ (struct pivot_table *table, axis->dimensions, (axis->n_dimensions + 1) * sizeof *axis->dimensions); axis->dimensions[axis->n_dimensions++] = d; - /* XXX extent and label_depth need to be calculated later. */ + /* axis->extent and axis->label_depth will be calculated later. */ return d; } @@ -580,14 +644,6 @@ pivot_result_class_change (const char *s_, const struct fmt_spec *format) return rc != NULL; } -/* One piece of data within a pivot table. */ -struct pivot_cell - { - struct hmap_node hmap_node; /* In struct pivot_table's 'cells' hmap. */ - struct pivot_value *value; - unsigned int idx[]; /* One index per table dimension. */ - }; - /* Pivot tables. */ /* Creates and returns a new pivot table with the given TITLE. TITLE should be @@ -630,36 +686,17 @@ struct pivot_table * pivot_table_create__ (struct pivot_value *title) { struct pivot_table *table = xzalloc (sizeof *table); + table->ref_cnt = 1; table->weight_format = (struct fmt_spec) { FMT_F, 40, 0 }; table->title = title; - /* Set default area styles. */ -#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}, \ - }, \ - } - static const struct 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 + table->sizing[TABLE_HORZ].range[0] = 50; + table->sizing[TABLE_HORZ].range[1] = 72; + table->sizing[TABLE_VERT].range[0] = 36; + table->sizing[TABLE_VERT].range[1] = 120; + for (size_t i = 0; i < PIVOT_N_AREAS; i++) - table->areas[i] = default_area_styles[i]; + pivot_area_get_default_style (i, &table->areas[i]); /* Set default border styles. */ static const enum table_stroke default_strokes[PIVOT_N_BORDERS] = { @@ -713,12 +750,27 @@ pivot_table_create_for_text (struct pivot_value *title, return table; } -/* Destroys TABLE and frees everything it points to. */ +/* Increases TABLE's reference count, indicating that it has an additional + owner. A pivot table that is shared among multiple owners must not be + modified. */ +struct pivot_table * +pivot_table_ref (const struct pivot_table *table_) +{ + struct pivot_table *table = CONST_CAST (struct pivot_table *, table_); + table->ref_cnt++; + return table; +} + +/* Decreases TABLE's reference count, indicating that it has one fewer owner. + If TABLE no longer has any owners, it is freed. */ void -pivot_table_destroy (struct pivot_table *table) +pivot_table_unref (struct pivot_table *table) { if (!table) return; + assert (table->ref_cnt > 0); + if (--table->ref_cnt) + return; free (table->current_layer); free (table->table_look); @@ -771,6 +823,14 @@ pivot_table_destroy (struct pivot_table *table) free (table); } +/* Returns true if TABLE has more than one owner. A pivot table that is shared + among multiple owners must not be modified. */ +bool +pivot_table_is_shared (const struct pivot_table *table) +{ + return table->ref_cnt > 1; +} + /* Sets the format used for PIVOT_RC_COUNT cells to the one used for variable WV, which should be the weight variable for the dictionary whose data or statistics are being put into TABLE. @@ -957,9 +1017,9 @@ pivot_make_default_footnote_marker (int idx, bool show_numeric_markers) return pivot_value_new_user_text (text, -1); } -/* Creates or modifies a footnote in TABLE with 0-based number IDX. If MARKER - is nonnull, sets the footnote's marker; if CONTENT is nonnull, sets the - footnote's content. */ +/* Creates or modifies a footnote in TABLE with 0-based number IDX (and creates + all lower indexes as a side effect). If MARKER is nonnull, sets the + footnote's marker; if CONTENT is nonnull, sets the footnote's content. */ struct pivot_footnote * pivot_table_create_footnote__ (struct pivot_table *table, size_t idx, struct pivot_value *marker, @@ -1344,6 +1404,52 @@ compose_headings (const struct pivot_axis *axis, return headings; } +static void +free_headings (const struct pivot_axis *axis, char ***headings) +{ + for (size_t i = 0; i < axis->label_depth; i++) + { + for (size_t j = 0; j < axis->extent; j++) + free (headings[i][j]); + free (headings[i]); + } + free (headings); +} + +static void +pivot_table_sizing_dump (const char *name, const struct pivot_table_sizing *s, + int indentation) +{ + indent (indentation); + printf ("%ss: min=%d, max=%d\n", name, s->range[0], s->range[1]); + if (s->n_widths) + { + indent (indentation + 1); + printf ("%s widths:", name); + for (size_t i = 0; i < s->n_widths; i++) + printf (" %d", s->widths[i]); + printf ("\n"); + } + if (s->n_breaks) + { + indent (indentation + 1); + printf ("break after %ss:", name); + for (size_t i = 0; i < s->n_breaks; i++) + printf (" %zu", s->breaks[i]); + printf ("\n"); + } + if (s->n_keeps) + { + indent (indentation + 1); + printf ("keep %ss together:", name); + for (size_t i = 0; i < s->n_keeps; i++) + printf (" [%zu,%zu]", + s->keeps[i].ofs, + s->keeps[i].ofs + s->keeps[i].n - 1); + printf ("\n"); + } +} + void pivot_table_dump (const struct pivot_table *table, int indentation) { @@ -1363,9 +1469,17 @@ pivot_table_dump (const struct pivot_table *table, int indentation) if (table->date) { indent (indentation); - printf ("date: %s", ctime (&table->date)); /* XXX thread unsafe */ + char buf[26]; + printf ("date: %s", ctime_r (&table->date, buf)); } + indent (indentation); + printf ("sizing:\n"); + pivot_table_sizing_dump ("column", &table->sizing[TABLE_HORZ], + indentation + 1); + pivot_table_sizing_dump ("row", &table->sizing[TABLE_VERT], + indentation + 1); + indent (indentation); printf ("areas:\n"); for (enum pivot_area area = 0; area < PIVOT_N_AREAS; area++) @@ -1422,7 +1536,7 @@ pivot_table_dump (const struct pivot_table *table, int indentation) fputs (" =", stdout); struct pivot_value **names = xnmalloc (layer_axis->label_depth, - sizeof *names); + sizeof *names); size_t n_names = 0; for (const struct pivot_category *c = d->presentation_leaves[layer_indexes[i]]; @@ -1462,6 +1576,7 @@ pivot_table_dump (const struct pivot_table *table, int indentation) } putchar ('\n'); } + free_headings (&table->axes[PIVOT_AXIS_COLUMN], column_headings); indent (indentation + 1); printf ("-----------------------------------------------\n"); @@ -1510,6 +1625,7 @@ pivot_table_dump (const struct pivot_table *table, int indentation) free (column_enumeration); free (row_enumeration); + free_headings (&table->axes[PIVOT_AXIS_ROW], row_headings); } pivot_table_dump_value (table->caption, "caption", indentation); @@ -1528,6 +1644,7 @@ pivot_table_dump (const struct pivot_table *table, int indentation) putchar ('\n'); } + free (dindexes); settings_set_decimal_char (old_decimal); } @@ -1735,7 +1852,7 @@ pivot_value_format_body (const struct pivot_value *value, break; case PIVOT_VALUE_TEMPLATE: - pivot_format_template (out, value->template.s, value->template.args, + pivot_format_template (out, value->template.local, value->template.args, value->template.n_args, show_values, show_variables); break; @@ -1794,6 +1911,7 @@ pivot_value_destroy (struct pivot_value *value) /* Do not free the elements of footnotes because VALUE does not own them. */ free (value->footnotes); + free (value->subscript); switch (value->type) { @@ -1823,7 +1941,9 @@ pivot_value_destroy (struct pivot_value *value) break; case PIVOT_VALUE_TEMPLATE: - free (value->template.s); + free (value->template.local); + if (value->template.id != value->template.local) + free (value->template.id); for (size_t i = 0; i < value->template.n_args; i++) pivot_argument_uninit (&value->template.args[i]); free (value->template.args); @@ -1837,15 +1957,16 @@ pivot_value_destroy (struct pivot_value *value) DEFAULT_STYLE for the parts of the style that VALUE doesn't override. */ void pivot_value_get_style (struct pivot_value *value, - const struct area_style *default_style, + const struct font_style *base_font_style, + const struct cell_style *base_cell_style, struct area_style *area) { font_style_copy (&area->font_style, (value->font_style ? value->font_style - : &default_style->font_style)); - area->cell_style = (value->cell_style - ? *value->cell_style - : default_style->cell_style); + : base_font_style)); + area->cell_style = *(value->cell_style + ? value->cell_style + : base_cell_style); } /* Copies AREA into VALUE's style. */ @@ -2058,6 +2179,12 @@ void pivot_value_add_footnote (struct pivot_value *v, struct pivot_footnote *footnote) { + /* Some legacy tables include numerous duplicate footnotes. Suppress + them. */ + for (size_t i = 0; i < v->n_footnotes; i++) + if (v->footnotes[i] == footnote) + return; + v->footnotes = xrealloc (v->footnotes, (v->n_footnotes + 1) * sizeof *v->footnotes); v->footnotes[v->n_footnotes++] = footnote;