X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Ftable.c;h=31348a46a70d53b32aa6c3e7fdd8cd9bb2c5eea4;hb=08959981d167390d9c9ba0ac5a8a2558de9175af;hp=1e3c53d256d29b5c0a9c9900ad6a70fc131f958d;hpb=5c177572411cf2a48c8a9b8aa620bb8ea0ce7bf2;p=pspp diff --git a/src/output/table.c b/src/output/table.c index 1e3c53d256..31348a46a7 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -30,7 +30,7 @@ #include "libpspp/pool.h" #include "libpspp/str.h" #include "output/table-item.h" -#include "output/tab.h" +#include "output/table.h" #include "output/text-item.h" #include "gl/xalloc.h" @@ -175,8 +175,14 @@ table_collect_footnotes (const struct table_item *item, struct table * table_from_string (const char *text) { - struct table *t = tab_create (1, 1, 0, 0, 0, 0); - tab_text (t, 0, 0, TAB_LEFT, text); + struct table *t = table_create (1, 1, 0, 0, 0, 0); + t->styles[0] = pool_alloc (t->container, sizeof *t->styles[0]); + *t->styles[0] = (struct area_style) { + AREA_STYLE_INITIALIZER__, + .cell_style.halign = TABLE_HALIGN_LEFT, + .cell_style.valign = TABLE_VALIGN_TOP + }; + table_text (t, 0, 0, 0 << TAB_STYLE_SHIFT, text); return t; } @@ -228,11 +234,12 @@ table_halign_interpret (enum table_halign halign, bool numeric) } void -font_style_copy (struct font_style *dst, const struct font_style *src) +font_style_copy (struct pool *container, + struct font_style *dst, const struct font_style *src) { *dst = *src; if (dst->typeface) - dst->typeface = xstrdup (dst->typeface); + dst->typeface = pool_strdup (container, dst->typeface); } void @@ -243,9 +250,10 @@ font_style_uninit (struct font_style *font) } void -area_style_copy (struct area_style *dst, const struct area_style *src) +area_style_copy (struct pool *container, + struct area_style *dst, const struct area_style *src) { - font_style_copy (&dst->font_style, &src->font_style); + font_style_copy (container, &dst->font_style, &src->font_style); dst->cell_style = src->cell_style; } @@ -319,18 +327,6 @@ cell_style_dump (const struct cell_style *c) static const bool debugging = true; -/* Joined cell. */ -struct tab_joined_cell -{ - int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */ - char *text; - - size_t n_footnotes; - const struct footnote **footnotes; - - const struct area_style *style; -}; - /* Creates and returns a new table with NC columns and NR rows and initially no header rows or columns. @@ -341,7 +337,7 @@ struct tab_joined_cell The table's cells are initially empty. */ struct table * -tab_create (int nc, int nr, int hl, int hr, int ht, int hb) +table_create (int nc, int nr, int hl, int hr, int ht, int hb) { struct table *t; @@ -358,10 +354,10 @@ tab_create (int nc, int nr, int hl, int hr, int ht, int hb) t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct); t->rh = pool_nmalloc (t->container, nc, nr + 1); - memset (t->rh, TAL_0, nc * (nr + 1)); + memset (t->rh, TABLE_STROKE_NONE, nc * (nr + 1)); t->rv = pool_nmalloc (t->container, nr, nc + 1); - memset (t->rv, TAL_0, nr * (nc + 1)); + memset (t->rv, TABLE_STROKE_NONE, nr * (nc + 1)); memset (t->styles, 0, sizeof t->styles); memset (t->rule_colors, 0, sizeof t->rule_colors); @@ -374,7 +370,7 @@ tab_create (int nc, int nr, int hl, int hr, int ht, int hb) /* Draws a vertical line to the left of cells at horizontal position X from Y1 to Y2 inclusive in style STYLE, if style is not -1. */ void -tab_vline (struct table *t, int style, int x, int y1, int y2) +table_vline (struct table *t, int style, int x, int y1, int y2) { if (debugging) { @@ -405,7 +401,7 @@ tab_vline (struct table *t, int style, int x, int y1, int y2) /* Draws a horizontal line above cells at vertical position Y from X1 to X2 inclusive in style STYLE, if style is not -1. */ void -tab_hline (struct table *t, int style, int x1, int x2, int y) +table_hline (struct table *t, int style, int x1, int x2, int y) { if (debugging) { @@ -440,8 +436,8 @@ tab_hline (struct table *t, int style, int x1, int x2, int y) drawing those lines. This is distinct from 0, which draws a null line. */ void -tab_box (struct table *t, int f_h, int f_v, int i_h, int i_v, - int x1, int y1, int x2, int y2) +table_box (struct table *t, int f_h, int f_v, int i_h, int i_v, + int x1, int y1, int x2, int y2) { if (debugging) { @@ -511,7 +507,7 @@ tab_box (struct table *t, int f_h, int f_v, int i_h, int i_v, /* Cells. */ static void -do_tab_text (struct table *table, int c, int r, unsigned opt, char *text) +do_table_text (struct table *table, int c, int r, unsigned opt, char *text) { assert (c >= 0); assert (r >= 0); @@ -522,7 +518,7 @@ do_tab_text (struct table *table, int c, int r, unsigned opt, char *text) { if (c < 0 || r < 0 || c >= table_nc (table) || r >= table_nr (table)) { - printf ("tab_text(): bad cell (%d,%d) in table size (%d,%d)\n", + printf ("table_text(): bad cell (%d,%d) in table size (%d,%d)\n", c, r, table_nc (table), table_nr (table)); return; } @@ -535,32 +531,30 @@ do_tab_text (struct table *table, int c, int r, unsigned opt, char *text) /* Sets cell (C,R) in TABLE, with options OPT, to have text value TEXT. */ void -tab_text (struct table *table, int c, int r, unsigned opt, +table_text (struct table *table, int c, int r, unsigned opt, const char *text) { - do_tab_text (table, c, r, opt, pool_strdup (table->container, text)); + do_table_text (table, c, r, opt, pool_strdup (table->container, text)); } /* Sets cell (C,R) in TABLE, with options OPT, to have text value FORMAT, which is formatted as if passed to printf. */ void -tab_text_format (struct table *table, int c, int r, unsigned opt, - const char *format, ...) +table_text_format (struct table *table, int c, int r, unsigned opt, + const char *format, ...) { va_list args; va_start (args, format); - do_tab_text (table, c, r, opt, - pool_vasprintf (table->container, format, args)); + do_table_text (table, c, r, opt, + pool_vasprintf (table->container, format, args)); va_end (args); } -static struct tab_joined_cell * +static struct table_cell * add_joined_cell (struct table *table, int x1, int y1, int x2, int y2, unsigned opt) { - struct tab_joined_cell *j; - assert (x1 >= 0); assert (y1 >= 0); assert (y2 >= y1); @@ -575,121 +569,146 @@ add_joined_cell (struct table *table, int x1, int y1, int x2, int y2, || x2 < x1 || x2 >= table_nc (table) || y2 < y1 || y2 >= table_nr (table)) { - printf ("tab_joint_text(): bad cell " + printf ("table_joint_text(): bad cell " "(%d,%d)-(%d,%d) in table size (%d,%d)\n", x1, y1, x2, y2, table_nc (table), table_nr (table)); return NULL; } } - tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2); - - j = pool_alloc (table->container, sizeof *j); - j->d[TABLE_HORZ][0] = x1; - j->d[TABLE_VERT][0] = y1; - j->d[TABLE_HORZ][1] = ++x2; - j->d[TABLE_VERT][1] = ++y2; - j->n_footnotes = 0; - j->footnotes = NULL; - j->style = NULL; - - { - void **cc = &table->cc[x1 + y1 * table_nc (table)]; - unsigned short *ct = &table->ct[x1 + y1 * table_nc (table)]; - const int ofs = table_nc (table) - (x2 - x1); + table_box (table, -1, -1, TABLE_STROKE_NONE, TABLE_STROKE_NONE, + x1, y1, x2, y2); - int y; + struct table_cell *cell = pool_alloc (table->container, sizeof *cell); + *cell = (struct table_cell) { + .d = { [TABLE_HORZ] = { x1, ++x2 }, + [TABLE_VERT] = { y1, ++y2 } }, + .options = opt, + }; - for (y = y1; y < y2; y++) - { - int x; - - for (x = x1; x < x2; x++) - { - *cc++ = j; - *ct++ = opt | TAB_JOIN; - } + void **cc = &table->cc[x1 + y1 * table_nc (table)]; + unsigned short *ct = &table->ct[x1 + y1 * table_nc (table)]; + const int ofs = table_nc (table) - (x2 - x1); + for (int y = y1; y < y2; y++) + { + for (int x = x1; x < x2; x++) + { + *cc++ = cell; + *ct++ = opt | TAB_JOIN; + } - cc += ofs; - ct += ofs; - } - } + cc += ofs; + ct += ofs; + } - return j; + return cell; } /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with options OPT to have text value TEXT. */ void -tab_joint_text (struct table *table, int x1, int y1, int x2, int y2, - unsigned opt, const char *text) +table_joint_text (struct table *table, int x1, int y1, int x2, int y2, + unsigned opt, const char *text) { char *s = pool_strdup (table->container, text); if (x1 == x2 && y1 == y2) - do_tab_text (table, x1, y1, opt, s); + do_table_text (table, x1, y1, opt, s); else add_joined_cell (table, x1, y1, x2, y2, opt)->text = s; } -struct footnote * -tab_create_footnote (struct table *table, size_t idx, const char *content, - const char *marker, struct area_style *style) -{ - struct footnote *f = pool_alloc (table->container, sizeof *f); - f->idx = idx; - f->content = pool_strdup (table->container, content); - f->marker = pool_strdup (table->container, marker); - f->style = style; - return f; -} - -void -tab_add_footnote (struct table *table, int x, int y, - const struct footnote *f) +static struct table_cell * +get_joined_cell (struct table *table, int x, int y) { int index = x + y * table_nc (table); unsigned short opt = table->ct[index]; - struct tab_joined_cell *j; + struct table_cell *cell; if (opt & TAB_JOIN) - j = table->cc[index]; + cell = table->cc[index]; else { char *text = table->cc[index]; - j = add_joined_cell (table, x, y, x, y, table->ct[index]); - j->text = text ? text : xstrdup (""); + cell = add_joined_cell (table, x, y, x, y, table->ct[index]); + cell->text = text ? text : pool_strdup (table->container, ""); } + return cell; +} - j->footnotes = pool_realloc (table->container, j->footnotes, - (j->n_footnotes + 1) * sizeof *j->footnotes); +/* Sets the subscripts for column X, row Y in TABLE. */ +void +table_add_subscripts (struct table *table, int x, int y, + char **subscripts, size_t n_subscripts) +{ + struct table_cell *cell = get_joined_cell (table, x, y); - j->footnotes[j->n_footnotes++] = f; + cell->n_subscripts = n_subscripts; + cell->subscripts = pool_nalloc (table->container, n_subscripts, + sizeof *cell->subscripts); + for (size_t i = 0; i < n_subscripts; i++) + cell->subscripts[i] = pool_strdup (table->container, subscripts[i]); } +/* Sets the superscript for column X, row Y in TABLE. */ void -tab_add_style (struct table *table, int x, int y, - const struct area_style *style) +table_add_superscript (struct table *table, int x, int y, + const char *superscript) { - int index = x + y * table_nc (table); - unsigned short opt = table->ct[index]; - struct tab_joined_cell *j; + get_joined_cell (table, x, y)->superscript + = pool_strdup (table->container, superscript); +} - if (opt & TAB_JOIN) - j = table->cc[index]; - else - { - char *text = table->cc[index]; +/* Create a footnote in TABLE with MARKER (e.g. "a") as its marker and CONTENT + as its content. The footnote will be styled as STYLE, which is mandatory. + IDX must uniquely identify the footnote within TABLE. - j = add_joined_cell (table, x, y, x, y, table->ct[index]); - j->text = text ? text : xstrdup (""); - } + Returns the new footnote. The return value is the only way to get to the + footnote later, so it is important for the caller to remember it. */ +struct footnote * +table_create_footnote (struct table *table, size_t idx, const char *content, + const char *marker, struct area_style *style) +{ + assert (style); - j->style = style; + struct footnote *f = pool_alloc (table->container, sizeof *f); + f->idx = idx; + f->content = pool_strdup (table->container, content); + f->marker = pool_strdup (table->container, marker); + f->style = style; + return f; } +/* Attaches a reference to footnote F to the cell at column X, row Y in + TABLE. */ +void +table_add_footnote (struct table *table, int x, int y, + const struct footnote *f) +{ + assert (f->style); + + struct table_cell *cell = get_joined_cell (table, x, y); + + cell->footnotes = pool_realloc ( + table->container, cell->footnotes, + (cell->n_footnotes + 1) * sizeof *cell->footnotes); + + cell->footnotes[cell->n_footnotes++] = f; +} + +/* Overrides the style for column X, row Y in TABLE with STYLE. + Does not make a copy of STYLE, so it should either be allocated from + TABLE->container or have a lifetime that will outlive TABLE. */ +void +table_add_style (struct table *table, int x, int y, + const struct area_style *style) +{ + get_joined_cell (table, x, y)->style = style; +} + +/* Returns true if column C, row R has no contents, otherwise false. */ bool -tab_cell_is_empty (const struct table *table, int c, int r) +table_cell_is_empty (const struct table *table, int c, int r) { return table->cc[c + r * table_nc (table)] == NULL; } @@ -702,15 +721,15 @@ tab_cell_is_empty (const struct table *table, int c, int r) This function is obsolete. Please do not add new uses of it. Instead, use a text_item (see output/text-item.h). */ void -tab_output_text (int options UNUSED, const char *string) +table_output_text (int options UNUSED, const char *string) { text_item_submit (text_item_create (TEXT_ITEM_LOG, string)); } -/* Same as tab_output_text(), but FORMAT is passed through printf-like +/* Same as table_output_text(), but FORMAT is passed through printf-like formatting before output. */ void -tab_output_text_format (int options, const char *format, ...) +table_output_text_format (int options, const char *format, ...) { va_list args; char *text; @@ -719,7 +738,7 @@ tab_output_text_format (int options, const char *format, ...) text = xvasprintf (format, args); va_end (args); - tab_output_text (options, text); + table_output_text (options, text); free (text); } @@ -739,66 +758,25 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell) unsigned short opt = t->ct[index]; const void *cc = t->cc[index]; - cell->options = opt; - cell->n_footnotes = 0; - - int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT; - const struct area_style *style = t->styles[style_idx]; - if (style) - cell->style = style; - else - { - static const struct area_style styles[3][3] = { -#define S(H,V) [H][V] = { AREA_STYLE_INITIALIZER__, \ - .cell_style.halign = H, \ - .cell_style.valign = V } - S(TABLE_HALIGN_LEFT, TABLE_VALIGN_TOP), - S(TABLE_HALIGN_LEFT, TABLE_VALIGN_CENTER), - S(TABLE_HALIGN_LEFT, TABLE_VALIGN_BOTTOM), - S(TABLE_HALIGN_CENTER, TABLE_VALIGN_TOP), - S(TABLE_HALIGN_CENTER, TABLE_VALIGN_CENTER), - S(TABLE_HALIGN_CENTER, TABLE_VALIGN_BOTTOM), - S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_TOP), - S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_CENTER), - S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_BOTTOM), - }; - - enum table_halign halign - = ((opt & TAB_HALIGN) == TAB_LEFT ? TABLE_HALIGN_LEFT - : (opt & TAB_HALIGN) == TAB_CENTER ? TABLE_HALIGN_CENTER - : TABLE_HALIGN_RIGHT); - enum table_valign valign - = ((opt & TAB_VALIGN) == TAB_TOP ? TABLE_VALIGN_TOP - : (opt & TAB_VALIGN) == TAB_MIDDLE ? TABLE_VALIGN_CENTER - : TABLE_VALIGN_BOTTOM); - - cell->style = &styles[halign][valign]; - } - + const struct area_style *style + = t->styles[(opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT]; if (opt & TAB_JOIN) { - const struct tab_joined_cell *jc = cc; - cell->text = jc->text; - - cell->footnotes = jc->footnotes; - cell->n_footnotes = jc->n_footnotes; - - cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0]; - cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1]; - cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0]; - cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1]; - - if (jc->style) - cell->style = jc->style; + const struct table_cell *jc = cc; + *cell = *jc; + if (!cell->style) + cell->style = style; } else - { - cell->d[TABLE_HORZ][0] = x; - cell->d[TABLE_HORZ][1] = x + 1; - cell->d[TABLE_VERT][0] = y; - cell->d[TABLE_VERT][1] = y + 1; - cell->text = CONST_CAST (char *, cc ? cc : ""); - } + *cell = (struct table_cell) { + .d = { [TABLE_HORZ] = { x, x + 1 }, + [TABLE_VERT] = { y, y + 1 } }, + .options = opt, + .text = CONST_CAST (char *, cc ? cc : ""), + .style = style, + }; + + assert (cell->style); } /* Returns one of the TAL_* enumeration constants (declared in output/table.h)