X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Ftab.c;h=db384bdfc93408b434b08211ac774c03f60251a4;hb=refs%2Fheads%2Fpivot-table2;hp=d9872c7214e5d3d9015a92b1101eca3702e83f99;hpb=d2b769f76cbbadede9bd68da7caecabd69235bfa;p=pspp diff --git a/src/output/tab.c b/src/output/tab.c index d9872c7214..db384bdfc9 100644 --- a/src/output/tab.c +++ b/src/output/tab.c @@ -44,14 +44,24 @@ #include "gettext.h" #define _(msgid) gettext (msgid) -/* Set in the options field of cells that */ -#define TAB_JOIN (1u << TAB_FIRST_AVAILABLE) +/* Cell options. */ +#define TAB_JOIN (1u << TAB_FIRST_AVAILABLE) +#define TAB_SUBTABLE (1u << (TAB_FIRST_AVAILABLE + 1)) +#define TAB_BARE (1u << (TAB_FIRST_AVAILABLE + 2)) /* Joined cell. */ struct tab_joined_cell { int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */ - char *contents; + union + { + char *text; + struct table_item *subtable; + } + u; + + size_t n_footnotes; + char **footnotes; }; static const struct table_class tab_table_class; @@ -78,6 +88,7 @@ tab_create (int nc, int nr) table_set_nr (&t->table, nr); t->title = NULL; + t->caption = NULL; t->cf = nc; t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc); t->ct = pool_malloc (t->container, nr * nc); @@ -500,9 +511,9 @@ tab_text_format (struct tab_table *table, int c, int r, unsigned opt, va_end (args); } -static void -do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, - unsigned opt, char *text) +static struct tab_joined_cell * +add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2, + unsigned opt) { struct tab_joined_cell *j; @@ -537,9 +548,8 @@ do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, j->d[TABLE_VERT][0] = y1 + table->row_ofs; j->d[TABLE_HORZ][1] = ++x2 + table->col_ofs; j->d[TABLE_VERT][1] = ++y2 + table->row_ofs; - j->contents = text; - - opt |= TAB_JOIN; + j->n_footnotes = 0; + j->footnotes = NULL; { void **cc = &table->cc[x1 + y1 * table->cf]; @@ -555,13 +565,15 @@ do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, for (x = x1; x < x2; x++) { *cc++ = j; - *ct++ = opt; + *ct++ = opt | TAB_JOIN; } cc += ofs; ct += ofs; } } + + return j; } /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with @@ -570,8 +582,8 @@ void tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, unsigned opt, const char *text) { - do_tab_joint_text (table, x1, y1, x2, y2, opt, - pool_strdup (table->container, text)); + char *s = pool_strdup (table->container, text); + add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s; } /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them @@ -582,13 +594,74 @@ tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2, unsigned opt, const char *format, ...) { va_list args; + char *s; + + va_start (args, format); + s = pool_vasprintf (table->container, format, args); + va_end (args); + + add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s; +} + +void +tab_footnote (struct tab_table *table, int x, int y, const char *format, ...) +{ + int index = x + y * table->cf; + unsigned char opt = table->ct[index]; + struct tab_joined_cell *j; + va_list args; + + if (opt & TAB_JOIN) + j = table->cc[index]; + else + { + char *text = table->cc[index]; + + j = add_joined_cell (table, x, y, x, y, table->ct[index]); + j->u.text = text ? text : xstrdup (""); + } + + j->footnotes = xrealloc (j->footnotes, + (j->n_footnotes + 1) * sizeof *j->footnotes); va_start (args, format); - do_tab_joint_text (table, x1, y1, x2, y2, opt, - pool_vasprintf (table->container, format, args)); + j->footnotes[j->n_footnotes++] = pool_vasprintf (table->container, format, args); va_end (args); } +static void +subtable_unref (void *subtable) +{ + table_item_unref (subtable); +} + +/* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE + with options OPT. */ +void +tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2, + unsigned opt, struct table_item *subtable) +{ + add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable + = subtable; + pool_register (table->container, subtable_unref, subtable); +} + +/* Places the contents of SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) + inclusive in TABLE with options OPT. + + SUBTABLE must have exactly one row and column. The contents of its single + cell are used as the contents of TABLE's cell; that is, SUBTABLE is not used + as a nested table but its contents become part of TABLE. */ +void +tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2, + unsigned opt, struct table_item *subtable) +{ + const struct table *t UNUSED = table_item_get_table (subtable); + assert (table_nc (t) == 1); + assert (table_nr (t) == 1); + tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable); +} + bool tab_cell_is_empty (const struct tab_table *table, int c, int r) { @@ -610,11 +683,24 @@ tab_title (struct tab_table *t, const char *title, ...) va_end (args); } +/* Set the caption of table T to CAPTION, which is formatted as if + passed to printf(). */ +void +tab_caption (struct tab_table *t, const char *caption, ...) +{ + va_list args; + + free (t->caption); + va_start (args, caption); + t->caption = xvasprintf (caption, args); + va_end (args); +} + /* Easy, type-safe way to submit a tab table to som. */ void tab_submit (struct tab_table *t) { - table_item_submit (table_item_create (&t->table, t->title)); + table_item_submit (table_item_create (&t->table, t->title, t->caption)); } /* Editing. */ @@ -698,6 +784,8 @@ tab_destroy (struct table *table) struct tab_table *t = tab_cast (table); free (t->title); t->title = NULL; + free (t->caption); + t->caption = NULL; pool_destroy (t->container); } @@ -707,17 +795,43 @@ tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell) const struct tab_table *t = tab_cast (table); int index = x + y * t->cf; unsigned char opt = t->ct[index]; - const void *content = t->cc[index]; + const void *cc = t->cc[index]; + + cell->inline_contents.options = opt; + cell->inline_contents.table = NULL; + cell->inline_contents.n_footnotes = 0; + cell->destructor = NULL; - cell->options = opt; if (opt & TAB_JOIN) { - const struct tab_joined_cell *jc = content; + const struct tab_joined_cell *jc = cc; + if (opt & TAB_BARE) + { + assert (opt & TAB_SUBTABLE); + + /* This overwrites all of the members of CELL. */ + table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell); + } + else + { + cell->contents = &cell->inline_contents; + cell->n_contents = 1; + if (opt & TAB_SUBTABLE) + { + cell->inline_contents.table = jc->u.subtable; + cell->inline_contents.text = NULL; + } + else + cell->inline_contents.text = jc->u.text; + } + + cell->inline_contents.footnotes = jc->footnotes; + cell->inline_contents.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]; - cell->contents = jc->contents; } else { @@ -725,9 +839,18 @@ tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell) cell->d[TABLE_HORZ][1] = x + 1; cell->d[TABLE_VERT][0] = y; cell->d[TABLE_VERT][1] = y + 1; - cell->contents = content != NULL ? content : ""; + if (cc != NULL) + { + cell->contents = &cell->inline_contents; + cell->n_contents = 1; + cell->inline_contents.text = CONST_CAST (char *, cc); + } + else + { + cell->contents = NULL; + cell->n_contents = 0; + } } - cell->destructor = NULL; } static int