X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fpivot-table.c;h=ad95d71fdb04d1c7f6d3950be6145cb374105a2b;hb=7fceea6249f2a570ecc44b5cb35f94711da957c1;hp=272ccc9e34849dca95a9d133712d219b2a3e0b75;hpb=24e84c14af8ac6dc897344104e756c8820f9a031;p=pspp diff --git a/src/output/pivot-table.c b/src/output/pivot-table.c index 272ccc9e34..ad95d71fdb 100644 --- a/src/output/pivot-table.c +++ b/src/output/pivot-table.c @@ -24,13 +24,17 @@ #include "data/settings.h" #include "data/value.h" #include "data/variable.h" +#include "data/file-name.h" #include "libpspp/hash-functions.h" #include "libpspp/i18n.h" #include "output/driver.h" +#include "output/spv/spv-table-look.h" #include "gl/c-ctype.h" +#include "gl/configmake.h" #include "gl/intprops.h" #include "gl/minmax.h" +#include "gl/relocatable.h" #include "gl/xalloc.h" #include "gl/xmemdup0.h" #include "gl/xsize.h" @@ -62,70 +66,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 +135,157 @@ pivot_table_sizing_uninit (struct pivot_table_sizing *sizing) /* Pivot table looks. */ +static const struct pivot_table_look * +default_look (const struct pivot_table_look *new) +{ + static struct pivot_table_look *look; + if (new) + { + pivot_table_look_unref (look); + look = pivot_table_look_ref (new); + } + else if (!look) + { + char *error = pivot_table_look_read ("default.stt", &look); + if (error) + { + free (error); + look = pivot_table_look_ref (pivot_table_look_builtin_default ()); + } + } + return look; +} + +const struct pivot_table_look * +pivot_table_look_get_default (void) +{ + return default_look (NULL); +} + void -pivot_table_look_init (struct pivot_table_look *look) +pivot_table_look_set_default (const struct pivot_table_look *look) +{ + default_look (look); +} + +char * WARN_UNUSED_RESULT +pivot_table_look_read (const char *name, struct pivot_table_look **lookp) { - memset (look, 0, sizeof *look); + *lookp = NULL; - look->omit_empty = false; - 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; + /* Construct search path. */ + const char *path[4]; + size_t n = 0; + path[n++] = "."; + const char *home = getenv ("HOME"); + char *allocated = NULL; + if (home != NULL) + path[n++] = allocated = xasprintf ("%s/.pspp/looks", home); + char *allocated2; + path[n++] = relocate2 (PKGDATADIR "/looks", &allocated2); + path[n++] = NULL; - 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, + /* Search path. */ + char *file = fn_search_path (name, (char **) path); + if (!file) + { + char *name2 = xasprintf ("%s.stt", name); + file = fn_search_path (name2, (char **) path); + free (name2); + } + free (allocated); + free (allocated2); + if (!file) + return xasprintf ("%s: not found", name); + + /* Read file. */ + char *error = spv_table_look_read (file, lookp); + free (file); + return error; +} + +const struct pivot_table_look * +pivot_table_look_builtin_default (void) +{ + static struct pivot_table_look look = { + .ref_cnt = 1, + + .omit_empty = true, + .row_labels_in_corner = true, + .width_ranges = { + [TABLE_HORZ] = { 36, 72 }, + [TABLE_VERT] = { 36, 120 }, + }, + + .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 +294,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 +843,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_get_default ()); hmap_init (&table->cells); @@ -831,7 +893,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 +949,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 +1165,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; @@ -1216,6 +1278,14 @@ pivot_table_enumerate_axis (const struct pivot_table *table, memcpy (p, axis_indexes, axis->n_dimensions * sizeof *p); p += axis->n_dimensions; } + if (omit_empty && p == enumeration) + { + PIVOT_AXIS_FOR_EACH (axis_indexes, axis) + { + memcpy (p, axis_indexes, axis->n_dimensions * sizeof *p); + p += axis->n_dimensions; + } + } *p = SIZE_MAX; if (n) *n = (p - enumeration) / axis->n_dimensions; @@ -1322,7 +1392,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; @@ -1533,7 +1603,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); @@ -1546,20 +1616,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++) @@ -1629,9 +1699,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,