X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Ftable.c;h=7569c3e46e55adad8bc003502134f66fa473aaf9;hb=1fc57714adfb36009ad22e2a164263b90548bf11;hp=be2c2136f945f0262c0295527856855147c6e613;hpb=8eac4df36306cd357bba29ffbfaddc537fc0be47;p=pspp diff --git a/src/output/table.c b/src/output/table.c index be2c2136f9..7569c3e46e 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -1,49 +1,53 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . +/* PSPP - a program for statistical analysis. + Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include + #include "table.h" + #include #include #include #include -#include + +#include "output.h" +#include "manager.h" + +#include +#include +#include #include #include -#include -#include #include -#include "minmax.h" -#include "output.h" #include -#include "manager.h" -#include + +#include + +#include "error.h" +#include "minmax.h" +#include "xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) const struct som_table_class tab_table_class; -static char *command_name; /* Returns the font to use for a cell with the given OPTIONS. */ static enum outp_font -options_to_font (unsigned options) +options_to_font (unsigned options) { return (options & TAB_FIX ? OUTP_FIXED : options & TAB_EMPH ? OUTP_EMPHASIS @@ -57,8 +61,8 @@ tab_create (int nc, int nr, int reallocable UNUSED) struct tab_table *t; t = pool_create_container (struct tab_table, container); + t->ref_cnt = 1; t->col_style = TAB_COL_NONE; - t->col_group = 0; t->title = NULL; t->flags = SOMF_NONE; t->nr = nr; @@ -76,21 +80,33 @@ tab_create (int nc, int nr, int reallocable UNUSED) memset (t->rv, UCHAR_MAX, nr * (nc + 1)); t->dim = NULL; - t->w = t->h = NULL; t->col_ofs = t->row_ofs = 0; return t; } -/* Destroys table T. */ +/* Increases T's reference count and, if this causes T's + reference count to reach 0, destroys T. */ void tab_destroy (struct tab_table *t) { - assert (t != NULL); + assert (t->ref_cnt > 0); + if (--t->ref_cnt > 0) + return; + if (t->dim_free != NULL) + t->dim_free (t->dim_aux); free (t->title); pool_destroy (t->container); } +/* Increases T's reference count. */ +void +tab_ref (struct tab_table *t) +{ + assert (t->ref_cnt > 0); + t->ref_cnt++; +} + /* Sets the width and height of a table, in columns and rows, respectively. Use only to reduce the size of a table, since it does not change the amount of allocated memory. */ @@ -105,7 +121,7 @@ tab_resize (struct tab_table *t, int nc, int nr) } if (nr != -1) { - assert (nr + t->row_ofs <= t->nr); + assert (nr + t->row_ofs <= tab_nr (t)); t->nr = nr + t->row_ofs; } } @@ -120,7 +136,7 @@ void tab_realloc (struct tab_table *t, int nc, int nr) { int ro, co; - + assert (t != NULL); ro = t->row_ofs; co = t->col_ofs; @@ -128,17 +144,17 @@ tab_realloc (struct tab_table *t, int nc, int nr) tab_offset (t, 0, 0); if (nc == -1) - nc = t->nc; + nc = tab_nc (t); if (nr == -1) - nr = t->nr; - - assert (nc == t->nc); - + nr = tab_nr (t); + + assert (nc == tab_nc (t)); + if (nc > t->cf) { - int mr1 = min (nr, t->nr); - int mc1 = min (nc, t->nc); - + int mr1 = MIN (nr, tab_nr (t)); + int mc1 = MIN (nc, tab_nc (t)); + struct substring *new_cc; unsigned char *new_ct; int r; @@ -147,9 +163,9 @@ tab_realloc (struct tab_table *t, int nc, int nr) new_ct = pool_malloc (t->container, nr * nc); for (r = 0; r < mr1; r++) { - memcpy (&new_cc[r * nc], &t->cc[r * t->nc], mc1 * sizeof *t->cc); - memcpy (&new_ct[r * nc], &t->ct[r * t->nc], mc1); - memset (&new_ct[r * nc + t->nc], TAB_EMPTY, nc - t->nc); + memcpy (&new_cc[r * nc], &t->cc[r * tab_nc (t)], mc1 * sizeof *t->cc); + memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)], mc1); + memset (&new_ct[r * nc + tab_nc (t)], TAB_EMPTY, nc - tab_nc (t)); } pool_free (t->container, t->cc); pool_free (t->container, t->ct); @@ -157,24 +173,24 @@ tab_realloc (struct tab_table *t, int nc, int nr) t->ct = new_ct; t->cf = nc; } - else if (nr != t->nr) + else if (nr != tab_nr (t)) { t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc); t->ct = pool_realloc (t->container, t->ct, nr * nc); t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1); t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1); - - if (nr > t->nr) + + if (nr > tab_nr (t)) { - memset (&t->rh[nc * (t->nr + 1)], TAL_0, (nr - t->nr) * nc); - memset (&t->rv[(nc + 1) * t->nr], UCHAR_MAX, - (nr - t->nr) * (nc + 1)); + memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0, (nr - tab_nr (t)) * nc); + memset (&t->rv[(nc + 1) * tab_nr (t)], UCHAR_MAX, + (nr - tab_nr (t)) * (nc + 1)); } } - memset (&t->ct[nc * t->nr], TAB_EMPTY, nc * (nr - t->nr)); - + memset (&t->ct[nc * tab_nr (t)], TAB_EMPTY, nc * (nr - tab_nr (t))); + t->nr = nr; t->nc = nc; @@ -205,14 +221,12 @@ tab_headers (struct tab_table *table, int l, int r, int t, int b) /* Set up table T so that, when it is an appropriate size, it will be displayed across the page in columns. - STYLE is a TAB_COL_* constant. GROUP is the number of rows to take - as a unit. */ + STYLE is a TAB_COL_* constant. */ void -tab_columns (struct tab_table *t, int style, int group) +tab_columns (struct tab_table *t, int style) { assert (t != NULL); t->col_style = style; - t->col_group = group; } /* Rules. */ @@ -225,16 +239,16 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2) assert (t != NULL); #if DEBUGGING - if (x + t->col_ofs < 0 || x + t->col_ofs > t->nc - || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= t->nr - || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= t->nr) + if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t) + || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t) + || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t)) { printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in " "table size (%d,%d)\n"), x, t->col_ofs, x + t->col_ofs, y1, t->row_ofs, y1 + t->row_ofs, y2, t->row_ofs, y2 + t->row_ofs, - t->nc, t->nr); + tab_nc (t), tab_nr (t)); return; } #endif @@ -244,10 +258,10 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2) y2 += t->row_ofs; assert (x > 0); - assert (x < t->nc); + assert (x < tab_nc (t)); assert (y1 >= 0); assert (y2 >= y1); - assert (y2 <= t->nr); + assert (y2 <= tab_nr (t)); if (style != -1) { @@ -269,10 +283,10 @@ tab_hline (struct tab_table * t, int style, int x1, int x2, int y) y += t->row_ofs; assert (y >= 0); - assert (y < t->nr); + assert (y <= tab_nr (t)); assert (x2 >= x1 ); assert (x1 >= 0 ); - assert (x2 < t->nc); + assert (x2 < tab_nc (t)); if (style != -1) { @@ -295,10 +309,10 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, assert (t != NULL); #if DEBUGGING - if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= t->nc - || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= t->nc - || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= t->nr - || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= t->nr) + if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t) + || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t) + || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t) + || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t)) { printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) " "in table size (%d,%d)\n"), @@ -306,7 +320,7 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, y1, t->row_ofs, y1 + t->row_ofs, x2, t->col_ofs, x2 + t->col_ofs, y2, t->row_ofs, y2 + t->row_ofs, - t->nc, t->nr); + tab_nc (t), tab_nr (t)); NOT_REACHED (); } #endif @@ -320,8 +334,8 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, assert (y2 >= y1); assert (x1 >= 0); assert (y1 >= 0); - assert (x2 < t->nc); - assert (y2 < t->nr); + assert (x2 < tab_nc (t)); + assert (y2 < tab_nr (t)); if (f_h != -1) { @@ -345,7 +359,7 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, if (i_h != -1) { int y; - + for (y = y1 + 1; y <= y2; y++) { int x; @@ -357,11 +371,11 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, if (i_v != -1) { int x; - + for (x = x1 + 1; x <= x2; x++) { int y; - + for (y = y1; y <= y2; y++) t->rv[x + (t->cf + 1) * y] = i_v; } @@ -393,12 +407,23 @@ tab_title (struct tab_table *t, const char *title, ...) va_end (args); } -/* Set DIM_FUNC as the dimension function for table T. */ +/* Set DIM_FUNC, which will be passed auxiliary data AUX, as the + dimension function for table T. + + DIM_FUNC must not assume that it is called from the same + context as tab_dim; for example, table T might be kept in + memory and, thus, DIM_FUNC might be called after the currently + running command completes. If it is non-null, FREE_FUNC is + called when the table is destroyed, to allow any data + allocated for use by DIM_FUNC to be freed. */ void -tab_dim (struct tab_table *t, tab_dim_func *dim_func) +tab_dim (struct tab_table *t, + tab_dim_func *dim_func, tab_dim_free_func *free_func, void *aux) { - assert (t != NULL && t->dim == NULL); + assert (t->dim == NULL); t->dim = dim_func; + t->dim_free = free_func; + t->dim_aux = aux; } /* Returns the natural width of column C in table T for driver D, that @@ -406,86 +431,76 @@ tab_dim (struct tab_table *t, tab_dim_func *dim_func) wrapping. The width will be no larger than the page width minus left and right rule widths. */ int -tab_natural_width (struct tab_table *t, struct outp_driver *d, int c) +tab_natural_width (const struct tab_rendering *r, int col) { - int width; + const struct tab_table *t = r->table; + int width, row, max_width; - assert (t != NULL && c >= 0 && c < t->nc); - { - int r; + assert (col >= 0 && col < tab_nc (t)); - for (width = r = 0; r < t->nr; r++) - { - struct outp_text text; - unsigned char opt = t->ct[c + r * t->cf]; - int w; - - if (opt & (TAB_JOIN | TAB_EMPTY)) - continue; - - text.string = t->cc[c + r * t->cf]; - text.justification = OUTP_LEFT; - text.font = options_to_font (opt); - text.h = text.v = INT_MAX; - - d->class->text_metrics (d, &text, &w, NULL); - if (w > width) - width = w; - } - } + width = 0; + for (row = 0; row < tab_nr (t); row++) + { + struct outp_text text; + unsigned char opt = t->ct[col + row * t->cf]; + int w; + + if (opt & (TAB_JOIN | TAB_EMPTY)) + continue; + + text.string = t->cc[col + row * t->cf]; + text.justification = OUTP_LEFT; + text.font = options_to_font (opt); + text.h = text.v = INT_MAX; + + r->driver->class->text_metrics (r->driver, &text, &w, NULL); + if (w > width) + width = w; + } if (width == 0) { /* FIXME: This is an ugly kluge to compensate for the fact that we don't let joined cells contribute to column widths. */ - width = d->prop_em_width * 8; + width = r->driver->prop_em_width * 8; } - - { - const int clamp = d->width - t->wrv[0] - t->wrv[t->nc]; - - if (width > clamp) - width = clamp; - } - return width; + max_width = r->driver->width - r->wrv[0] - r->wrv[tab_nc (t)]; + return MIN (width, max_width); } /* Returns the natural height of row R in table T for driver D, that is, the minimum height necessary to display the information in the cell at the widths set for each column. */ int -tab_natural_height (struct tab_table *t, struct outp_driver *d, int r) +tab_natural_height (const struct tab_rendering *r, int row) { - int height; + const struct tab_table *t = r->table; + int height, col; - assert (t != NULL && r >= 0 && r < t->nr); - - { - int c; - - for (height = d->font_height, c = 0; c < t->nc; c++) - { - struct outp_text text; - unsigned char opt = t->ct[c + r * t->cf]; - int h; - - assert (t->w[c] != NOT_INT); - if (opt & (TAB_JOIN | TAB_EMPTY)) - continue; - - text.string = t->cc[c + r * t->cf]; - text.justification = OUTP_LEFT; - text.font = options_to_font (opt); - text.h = t->w[c]; - text.v = INT_MAX; - d->class->text_metrics (d, &text, NULL, &h); - - if (h > height) - height = h; - } - } + assert (row >= 0 && row < tab_nr (t)); + + height = r->driver->font_height; + for (col = 0; col < tab_nc (t); col++) + { + struct outp_text text; + unsigned char opt = t->ct[col + row * t->cf]; + int h; + + if (opt & (TAB_JOIN | TAB_EMPTY)) + continue; + + text.string = t->cc[col + row * t->cf]; + text.justification = OUTP_LEFT; + text.font = options_to_font (opt); + text.h = r->w[col]; + text.v = INT_MAX; + r->driver->class->text_metrics (r->driver, &text, NULL, &h); + + if (h > height) + height = h; + } return height; } @@ -493,17 +508,16 @@ tab_natural_height (struct tab_table *t, struct outp_driver *d, int r) /* Callback function to set all columns and rows to their natural dimensions. Not really meant to be called directly. */ void -tab_natural_dimensions (struct tab_table *t, struct outp_driver *d) +tab_natural_dimensions (struct tab_rendering *r, void *aux UNUSED) { + const struct tab_table *t = r->table; int i; - assert (t != NULL); - - for (i = 0; i < t->nc; i++) - t->w[i] = tab_natural_width (t, d, i); - - for (i = 0; i < t->nr; i++) - t->h[i] = tab_natural_height (t, d, i); + for (i = 0; i < tab_nc (t); i++) + r->w[i] = tab_natural_width (r, i); + + for (i = 0; i < tab_nr (t); i++) + r->h[i] = tab_natural_height (r, i); } @@ -520,14 +534,14 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt, assert (table != NULL && v != NULL && f != NULL); #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -535,47 +549,47 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt, contents = pool_alloc (table->container, f->w); table->cc[c + r * table->cf] = ss_buffer (contents, f->w); table->ct[c + r * table->cf] = opt; - - data_out (contents, f, v); + + data_out (v, f, contents); } /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL with NDEC decimal places. */ void -tab_float (struct tab_table *table, int c, int r, unsigned char opt, +tab_fixed (struct tab_table *table, int c, int r, unsigned char opt, double val, int w, int d) { char *contents; char buf[40], *cp; - + struct fmt_spec f; union value double_value; assert (table != NULL && w <= 40); - + assert (c >= 0); - assert (c < table->nc); + assert (c < tab_nc (table)); assert (r >= 0); - assert (r < table->nr); + assert (r < tab_nr (table)); + + f = fmt_for_output (FMT_F, w, d); - f = make_output_format (FMT_F, w, d); - #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { - printf ("tab_float(): bad cell (%d+%d=%d,%d+%d=%d) in table size " + printf ("tab_fixed(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif double_value.f = val; - data_out (buf, &f, &double_value); + data_out (&double_value, &f, buf); cp = buf; while (isspace ((unsigned char) *cp) && cp < &buf[w]) @@ -588,6 +602,61 @@ tab_float (struct tab_table *table, int c, int r, unsigned char opt, memcpy (contents, cp, f.w); } +/* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as + formatted by FMT. + If FMT is null, then the default print format will be used. +*/ +void +tab_double (struct tab_table *table, int c, int r, unsigned char opt, + double val, const struct fmt_spec *fmt) +{ + int w; + char *contents; + char buf[40], *cp; + + union value double_value; + + assert (table != NULL); + + assert (c >= 0); + assert (c < tab_nc (table)); + assert (r >= 0); + assert (r < tab_nr (table)); + + if ( fmt == NULL) + fmt = settings_get_format (); + + fmt_check_output (fmt); + +#if DEBUGGING + if (c + table->col_ofs < 0 || r + table->row_ofs < 0 + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) + { + printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size " + "(%d,%d)\n", + c, table->col_ofs, c + table->col_ofs, + r, table->row_ofs, r + table->row_ofs, + tab_nc (table), tab_nr (table)); + return; + } +#endif + + double_value.f = val; + data_out (&double_value, fmt, buf); + + cp = buf; + while (isspace ((unsigned char) *cp) && cp < &buf[fmt->w]) + cp++; + w = fmt->w - (cp - buf); + + contents = pool_alloc (table->container, w); + table->cc[c + r * table->cf] = ss_buffer (contents, w); + table->ct[c + r * table->cf] = opt; + memcpy (contents, cp, w); +} + + /* Sets cell (C,R) in TABLE, with options OPT, to have text value TEXT. */ void @@ -599,20 +668,20 @@ tab_text (struct tab_table *table, int c, int r, unsigned opt, const char *text, assert (c >= 0 ); assert (r >= 0 ); - assert (c < table->nc); - assert (r < table->nr); - + assert (c < tab_nc (table)); + assert (r < tab_nr (table)); + #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -637,14 +706,14 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, assert (y1 + table->row_ofs >= 0); assert (y2 >= y1); assert (x2 >= x1); - assert (y2 + table->row_ofs < table->nr); - assert (x2 + table->col_ofs < table->nc); + assert (y2 + table->row_ofs < tab_nr (table)); + assert (x2 + table->col_ofs < tab_nc (table)); #if DEBUGGING - if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= table->nc - || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= table->nr - || x2 < x1 || x2 + table->col_ofs >= table->nc - || y2 < y2 || y2 + table->row_ofs >= table->nr) + if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table) + || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table) + || x2 < x1 || x2 + table->col_ofs >= tab_nc (table) + || y2 < y2 || y2 + table->row_ofs >= tab_nr (table)) { printf ("tab_joint_text(): bad cell " "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n", @@ -652,47 +721,46 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, y1, table->row_ofs, y1 + table->row_ofs, x2, table->col_ofs, x2 + table->col_ofs, y2, table->row_ofs, y2 + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2); - + j = pool_alloc (table->container, sizeof *j); - j->hit = 0; j->x1 = x1 + table->col_ofs; j->y1 = y1 + table->row_ofs; j->x2 = ++x2 + table->col_ofs; j->y2 = ++y2 + table->row_ofs; - + { va_list args; - + va_start (args, text); j->contents = text_format (table, opt, text, args); va_end (args); } - + opt |= TAB_JOIN; - + { struct substring *cc = &table->cc[x1 + y1 * table->cf]; unsigned char *ct = &table->ct[x1 + y1 * table->cf]; const int ofs = table->cf - (x2 - x1); int y; - + for (y = y1; y < y2; y++) { int x; - + for (x = x1; x < x2; x++) { *cc++ = ss_buffer ((char *) j, 0); *ct++ = opt; } - + cc += ofs; ct += ofs; } @@ -705,17 +773,17 @@ tab_raw (struct tab_table *table, int c, int r, unsigned opt, struct substring *string) { assert (table != NULL && string != NULL); - + #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { - printf ("tab_float(): bad cell (%d+%d=%d,%d+%d=%d) in table size " + printf ("tab_raw(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -729,19 +797,19 @@ tab_raw (struct tab_table *table, int c, int r, unsigned opt, /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -nowrap_dim (struct tab_table *t, struct outp_driver *d) +nowrap_dim (struct tab_rendering *r, void *aux UNUSED) { - t->w[0] = tab_natural_width (t, d, 0); - t->h[0] = d->font_height; + r->w[0] = tab_natural_width (r, 0); + r->h[0] = r->driver->font_height; } /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -wrap_dim (struct tab_table *t, struct outp_driver *d) +wrap_dim (struct tab_rendering *r, void *aux UNUSED) { - t->w[0] = tab_natural_width (t, d, 0); - t->h[0] = tab_natural_height (t, d, 0); + r->w[0] = tab_natural_width (r, 0); + r->h[0] = tab_natural_height (r, 0); } /* Outputs text BUF as a table with a single cell having cell options @@ -756,17 +824,17 @@ tab_output_text (int options, const char *buf, ...) if (options & TAT_PRINTF) { va_list args; - + va_start (args, buf); buf = tmp_buf = xvasprintf (buf, args); va_end (args); } - + tab_text (t, 0, 0, options & ~TAT_PRINTF, buf); tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING); - tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim); + tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL, NULL); tab_submit (t); - + free (tmp_buf); } @@ -803,14 +871,14 @@ tab_offset (struct tab_table *t, int col, int row) assert (t != NULL); #if DEBUGGING - if (row < -1 || row > t->nr) + if (row < -1 || row > tab_nr (t)) { - printf ("tab_offset(): row=%d in %d-row table\n", row, t->nr); + printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t)); NOT_REACHED (); } - if (col < -1 || col > t->nc) + if (col < -1 || col > tab_nc (t)) { - printf ("tab_offset(): col=%d in %d-column table\n", col, t->nc); + printf ("tab_offset(): col=%d in %d-column table\n", col, tab_nc (t)); NOT_REACHED (); } #endif @@ -832,37 +900,54 @@ tab_next_row (struct tab_table *t) assert (t != NULL); t->cc += t->cf; t->ct += t->cf; - if (++t->row_ofs >= t->nr) - tab_realloc (t, -1, t->nr * 4 / 3); + if (++t->row_ofs >= tab_nr (t)) + tab_realloc (t, -1, tab_nr (t) * 4 / 3); } -static struct tab_table *t; -static struct outp_driver *d; -static int tab_hit; +/* Return the number of columns and rows in the table into N_COLUMNS + and N_ROWS, respectively. */ +static void +tabi_count (struct som_entity *t_, int *n_columns, int *n_rows) +{ + struct tab_table *t = t_->ext; + *n_columns = t->nc; + *n_rows = t->nr; +} -/* Set the current table to TABLE. */ +/* Return the column style for this table into STYLE. */ static void -tabi_table (struct som_entity *table) +tabi_columns (struct som_entity *t_, int *style) { - assert (table != NULL); - assert (table->type == SOM_TABLE); - - t = table->ext; - tab_offset (t, 0, 0); - - assert (t->w == NULL && t->h == NULL); - t->w = pool_nalloc (t->container, t->nc, sizeof *t->w); - t->h = pool_nalloc (t->container, t->nr, sizeof *t->h); - t->hrh = pool_nmalloc (t->container, t->nr + 1, sizeof *t->hrh); - t->wrv = pool_nmalloc (t->container, t->nc + 1, sizeof *t->wrv); + struct tab_table *t = t_->ext; + *style = t->col_style; +} + +/* Return the number of header rows/columns on the left, right, top, + and bottom sides into HL, HR, HT, and HB, respectively. */ +static void +tabi_headers (struct som_entity *t_, int *hl, int *hr, int *ht, int *hb) +{ + struct tab_table *t = t_->ext; + *hl = t->l; + *hr = t->r; + *ht = t->t; + *hb = t->b; +} + +/* Return flags set for the current table into FLAGS. */ +static void +tabi_flags (struct som_entity *t_, unsigned *flags) +{ + struct tab_table *t = t_->ext; + *flags = t->flags; } /* Returns the line style to use for spacing purposes for a rule of the given TYPE. */ static enum outp_line_style -rule_to_spacing_type (unsigned char type) +rule_to_spacing_type (unsigned char type) { - switch (type) + switch (type) { case TAL_0: return OUTP_L_NONE; @@ -876,153 +961,127 @@ rule_to_spacing_type (unsigned char type) } } -/* Set the current output device to DRIVER. */ -static void -tabi_driver (struct outp_driver *driver) +static void * +tabi_render_init (struct som_entity *t_, struct outp_driver *driver, + int hl, int hr, int ht, int hb) { - int c, r; + const struct tab_table *t = t_->ext; + struct tab_rendering *r; + int col, row; int i; - - assert (driver != NULL); - d = driver; - + + tab_offset (t_->ext, 0, 0); + + r = xmalloc (sizeof *r); + r->table = t; + r->driver = driver; + r->w = xnmalloc (tab_nc (t), sizeof *r->w); + r->h = xnmalloc (tab_nr (t), sizeof *r->h); + r->hrh = xnmalloc (tab_nr (t) + 1, sizeof *r->hrh); + r->wrv = xnmalloc (tab_nc (t) + 1, sizeof *r->wrv); + r->l = hl; + r->r = hr; + r->t = ht; + r->b = hb; + /* Figure out sizes of rules. */ - for (r = 0; r <= t->nr; r++) + for (row = 0; row <= tab_nr (t); row++) { int width = 0; - for (c = 0; c < t->nc; c++) + for (col = 0; col < tab_nc (t); col++) { - unsigned char rh = t->rh[c + r * t->cf]; + unsigned char rh = t->rh[col + row * t->cf]; int w = driver->horiz_line_width[rule_to_spacing_type (rh)]; if (w > width) - width = w; + width = w; } - t->hrh[r] = width; + r->hrh[row] = width; } - for (c = 0; c <= t->nc; c++) + for (col = 0; col <= tab_nc (t); col++) { int width = 0; - for (r = 0; r < t->nr; r++) + for (row = 0; row < tab_nr (t); row++) { - unsigned char *rv = &t->rv[c + r * (t->cf + 1)]; + unsigned char *rv = &t->rv[col + row * (t->cf + 1)]; int w; if (*rv == UCHAR_MAX) - *rv = c != 0 && c != t->nc ? TAL_GAP : TAL_0; + *rv = col != 0 && col != tab_nc (t) ? TAL_GAP : TAL_0; w = driver->vert_line_width[rule_to_spacing_type (*rv)]; if (w > width) width = w; } - t->wrv[c] = width; + r->wrv[col] = width; } -#if DEBUGGING - for (i = 0; i < t->nr; i++) - t->h[i] = -1; - for (i = 0; i < t->nc; i++) - t->w[i] = -1; -#endif + /* Determine row heights and columns widths. */ + for (i = 0; i < tab_nr (t); i++) + r->h[i] = -1; + for (i = 0; i < tab_nc (t); i++) + r->w[i] = -1; - assert (t->dim != NULL); - t->dim (t, d); + t->dim (r, t->dim_aux); -#if DEBUGGING - { - int error = 0; + for (i = 0; i < tab_nr (t); i++) + if (r->h[i] < 0) + error (0, 0, "height of table row %d is %d (not initialized?)", + i, r->h[i]); + for (i = 0; i < tab_nc (t); i++) + if (r->w[i] < 0) + error (0, 0, "width of table column %d is %d (not initialized?)", + i, r->w[i]); - for (i = 0; i < t->nr; i++) - { - if (t->h[i] == -1) - { - printf ("Table row %d height not initialized.\n", i); - error = 1; - } - assert (t->h[i] > 0); - } - - for (i = 0; i < t->nc; i++) - { - if (t->w[i] == -1) - { - printf ("Table column %d width not initialized.\n", i); - error = 1; - } - assert (t->w[i] > 0); - } - } -#endif - /* Add up header sizes. */ - for (i = 0, t->wl = t->wrv[0]; i < t->l; i++) - t->wl += t->w[i] + t->wrv[i + 1]; - for (i = 0, t->ht = t->hrh[0]; i < t->t; i++) - t->ht += t->h[i] + t->hrh[i + 1]; - for (i = t->nc - t->r, t->wr = t->wrv[i]; i < t->nc; i++) - t->wr += t->w[i] + t->wrv[i + 1]; - for (i = t->nr - t->b, t->hb = t->hrh[i]; i < t->nr; i++) - t->hb += t->h[i] + t->hrh[i + 1]; - + for (i = 0, r->wl = r->wrv[0]; i < r->l; i++) + r->wl += r->w[i] + r->wrv[i + 1]; + for (i = 0, r->ht = r->hrh[0]; i < r->t; i++) + r->ht += r->h[i] + r->hrh[i + 1]; + for (i = tab_nc (t) - r->r, r->wr = r->wrv[i]; i < tab_nc (t); i++) + r->wr += r->w[i] + r->wrv[i + 1]; + for (i = tab_nr (t) - r->b, r->hb = r->hrh[i]; i < tab_nr (t); i++) + r->hb += r->h[i] + r->hrh[i + 1]; + /* Title. */ if (!(t->flags & SOMF_NO_TITLE)) - t->ht += d->font_height; + r->ht += driver->font_height; + + return r; } -/* Return the number of columns and rows in the table into N_COLUMNS - and N_ROWS, respectively. */ static void -tabi_count (int *n_columns, int *n_rows) +tabi_render_free (void *r_) { - assert (n_columns != NULL && n_rows != NULL); - *n_columns = t->nc; - *n_rows = t->nr; -} + struct tab_rendering *r = r_; -static void tabi_cumulate (int cumtype, int start, int *end, int max, int *actual); + free (r->w); + free (r->h); + free (r->hrh); + free (r->wrv); + free (r); +} /* Return the horizontal and vertical size of the entire table, including headers, for the current output device, into HORIZ and VERT. */ static void -tabi_area (int *horiz, int *vert) -{ - assert (horiz != NULL && vert != NULL); - - { - int w, c; - - for (c = t->l + 1, w = t->wl + t->wr + t->w[t->l]; - c < t->nc - t->r; c++) - w += t->w[c] + t->wrv[c]; - *horiz = w; - } - - { - int h, r; - for (r = t->t + 1, h = t->ht + t->hb + t->h[t->t]; - r < t->nr - t->b; r++) - h += t->h[r] + t->hrh[r]; - *vert = h; - } -} - -/* Return the column style for this table into STYLE. */ -static void -tabi_columns (int *style) -{ - assert (style != NULL); - *style = t->col_style; -} - -/* Return the number of header rows/columns on the left, right, top, - and bottom sides into HL, HR, HT, and HB, respectively. */ -static void -tabi_headers (int *hl, int *hr, int *ht, int *hb) +tabi_area (void *r_, int *horiz, int *vert) { - assert (hl != NULL && hr != NULL && ht != NULL && hb != NULL); - *hl = t->l; - *hr = t->r; - *ht = t->t; - *hb = t->b; + struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + int width, col; + int height, row; + + width = 0; + for (col = r->l + 1, width = r->wl + r->wr + r->w[tab_l (t)]; + col < tab_nc (t) - r->r; col++) + width += r->w[col] + r->wrv[col]; + *horiz = width; + + height = 0; + for (row = r->t + 1, height = r->ht + r->hb + r->h[tab_t (t)]; + row < tab_nr (t) - tab_b (t); row++) + height += r->h[row] + r->hrh[row]; + *vert = height; } /* Determines the number of rows or columns (including appropriate @@ -1033,32 +1092,35 @@ tabi_headers (int *hl, int *hr, int *ht, int *hb) space the selected rows/columns (including appropriate headers) filled. */ static void -tabi_cumulate (int cumtype, int start, int *end, int max, int *actual) +tabi_cumulate (void *r_, int cumtype, int start, int *end, + int max, int *actual) { - int n; - int *d; - int *r; + const struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + int limit; + int *cells, *rules; int total; - + int idx; + assert (end != NULL && (cumtype == SOM_ROWS || cumtype == SOM_COLUMNS)); if (cumtype == SOM_ROWS) { - assert (start >= 0 && start < t->nr); - n = t->nr - t->b; - d = &t->h[start]; - r = &t->hrh[start + 1]; - total = t->ht + t->hb; + assert (start >= 0 && start < tab_nr (t)); + limit = tab_nr (t) - r->b; + cells = &r->h[start]; + rules = &r->hrh[start + 1]; + total = r->ht + r->hb; } else { - assert (start >= 0 && start < t->nc); - n = t->nc - t->r; - d = &t->w[start]; - r = &t->wrv[start + 1]; - total = t->wl + t->wr; + assert (start >= 0 && start < tab_nc (t)); + limit = tab_nc (t) - tab_r (t); + cells = &r->w[start]; + rules = &r->wrv[start + 1]; + total = r->wl + r->wr; } - - total += *d++; + + total += *cells++; if (total > max) { if (end) @@ -1067,181 +1129,140 @@ tabi_cumulate (int cumtype, int start, int *end, int max, int *actual) *actual = 0; return; } - - { - int x; - - for (x = start + 1; x < n; x++) - { - int amt = *d++ + *r++; - - total += amt; - if (total > max) - { - total -= amt; - break; - } - } - - if (end) - *end = x; - - if (actual) - *actual = total; - } -} - -/* Return flags set for the current table into FLAGS. */ -static void -tabi_flags (unsigned *flags) -{ - assert (flags != NULL); - *flags = t->flags; -} - -/* Returns true if the table will fit in the given page WIDTH, - false otherwise. */ -static bool -tabi_fits_width (int width) -{ - int i; - - for (i = t->l; i < t->nc - t->r; i++) - if (t->wl + t->wr + t->w[i] > width) - return false; - return true; -} + for (idx = start + 1; idx < limit; idx++) + { + int amt = *cells++ + *rules++; -/* Returns true if the table will fit in the given page LENGTH, - false otherwise. */ -static bool -tabi_fits_length (int length) -{ - int i; + total += amt; + if (total > max) + { + total -= amt; + break; + } + } - for (i = t->t; i < t->nr - t->b; i++) - if (t->ht + t->hb + t->h[i] > length) - return false; + if (end) + *end = idx; - return true; -} - -/* Sets the number of header rows/columns on the left, right, top, - and bottom sides to HL, HR, HT, and HB, respectively. */ -static void -tabi_set_headers (int hl, int hr, int ht, int hb) -{ - t->l = hl; - t->r = hr; - t->t = ht; - t->b = hb; + if (actual) + *actual = total; } /* Render title for current table, with major index X and minor index Y. Y may be zero, or X and Y may be zero, but X should be nonzero if Y is nonzero. */ static void -tabi_title (int x, int y) +tabi_title (void *r_, int x, int y, int table_num, int subtable_num, + const char *command_name) { - char buf[1024]; - char *cp; + const struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + struct outp_text text; + struct string title; if (t->flags & SOMF_NO_TITLE) return; - - cp = spprintf (buf, "%d.%d", table_num, subtable_num); + + ds_init_empty (&title); + ds_put_format (&title,"%d.%d", table_num, subtable_num); if (x && y) - cp = spprintf (cp, "(%d:%d)", x, y); + ds_put_format (&title, "(%d:%d)", x, y); else if (x) - cp = spprintf (cp, "(%d)", x); + ds_put_format (&title, "(%d)", x); if (command_name != NULL) - cp = spprintf (cp, " %s", command_name); - cp = stpcpy (cp, ". "); + ds_put_format (&title, " %s", command_name); + ds_put_cstr (&title, ". "); if (t->title != NULL) - { - size_t length = strlen (t->title); - memcpy (cp, t->title, length); - cp += length; - } - *cp = 0; - - { - struct outp_text text; - - text.font = OUTP_PROPORTIONAL; - text.justification = OUTP_LEFT; - text.string = ss_buffer (buf, cp - buf); - text.h = d->width; - text.v = d->font_height; - text.x = 0; - text.y = d->cp_y; - d->class->text_draw (d, &text); - } + ds_put_cstr (&title, t->title); + + text.font = OUTP_PROPORTIONAL; + text.justification = OUTP_LEFT; + text.string = ds_ss (&title); + text.h = r->driver->width; + text.v = r->driver->font_height; + text.x = 0; + text.y = r->driver->cp_y; + r->driver->class->text_draw (r->driver, &text); + + ds_destroy (&title); } -static int render_strip (int x, int y, int r, int c1, int c2, int r1, int r2); +static int render_strip (const struct tab_rendering *, + int x, int y, int r, int c1, int c2, int r1, int r2); -/* Renders columns C0...C1, plus headers, of rows R0...R1, - at the given vertical position Y. - C0 and C1 count vertical rules as columns, - but R0 and R1 do not count horizontal rules as rows. - Returns the vertical position after rendering. */ -static int -render_rows (int y, int c0, int c1, int r0, int r1) +static void +add_range (int ranges[][2], int *np, int start, int end) { - int r; - for (r = r0; r < r1; r++) + int n = *np; + if (n == 0 || start > ranges[n - 1][1]) { - int x = d->cp_x; - x = render_strip (x, y, r, 0, t->l * 2 + 1, r0, r1); - x = render_strip (x, y, r, c0 * 2 + 1, c1 * 2, r0, r1); - x = render_strip (x, y, r, (t->nc - t->r) * 2, t->nc * 2 + 1, r0, r1); - y += (r & 1) ? t->h[r / 2] : t->hrh[r / 2]; + ranges[n][0] = start; + ranges[n][1] = end; + ++*np; } - return y; + else + ranges[n - 1][1] = end; } /* Draws table region (C0,R0)-(C1,R1), plus headers, at the current position on the current output device. */ static void -tabi_render (int c0, int r0, int c1, int r1) +tabi_render (void *r_, int c0, int r0, int c1, int r1) { - int y; - - tab_hit++; - - y = d->cp_y; + const struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + int rows[3][2], cols[3][2]; + int n_row_ranges, n_col_ranges; + int y, i; + + /* Rows to render, counting horizontal rules as rows. */ + n_row_ranges = 0; + add_range (rows, &n_row_ranges, 0, tab_t (t) * 2 + 1); + add_range (rows, &n_row_ranges, r0 * 2 + 1, r1 * 2); + add_range (rows, &n_row_ranges, (tab_nr (t) - tab_b (t)) * 2, + tab_nr (t) * 2 + 1); + + /* Columns to render, counting vertical rules as columns. */ + n_col_ranges = 0; + add_range (cols, &n_col_ranges, 0, r->l * 2 + 1); + add_range (cols, &n_col_ranges, c0 * 2 + 1, c1 * 2); + add_range (cols, &n_col_ranges, (tab_nc (t) - r->r) * 2, tab_nc (t) * 2 + 1); + + y = r->driver->cp_y; if (!(t->flags & SOMF_NO_TITLE)) - y += d->font_height; + y += r->driver->font_height; + for (i = 0; i < n_row_ranges; i++) + { + int row; + + for (row = rows[i][0]; row < rows[i][1]; row++) + { + int x, j; - y = render_rows (y, c0, c1, 0, t->t * 2 + 1); - y = render_rows (y, c0, c1, r0 * 2 + 1, r1 * 2); - y = render_rows (y, c0, c1, (t->nr - t->b) * 2, t->nr * 2 + 1); + x = r->driver->cp_x; + for (j = 0; j < n_col_ranges; j++) + x = render_strip (r, x, y, row, + cols[j][0], cols[j][1], + rows[i][0], rows[i][1]); + + y += (row & 1) ? r->h[row / 2] : r->hrh[row / 2]; + } + } } const struct som_table_class tab_table_class = { - tabi_table, - tabi_driver, - tabi_count, - tabi_area, - NULL, - NULL, tabi_columns, - NULL, tabi_headers, - NULL, - tabi_cumulate, tabi_flags, - tabi_fits_width, - tabi_fits_length, - - NULL, - NULL, - tabi_set_headers, + tabi_render_init, + tabi_render_free, + + tabi_area, + tabi_cumulate, tabi_title, tabi_render, }; @@ -1249,7 +1270,7 @@ const struct som_table_class tab_table_class = static enum outp_justification translate_justification (unsigned int opt) { - switch (opt & TAB_ALIGN_MASK) + switch (opt & TAB_ALIGN_MASK) { case TAB_RIGHT: return OUTP_RIGHT; @@ -1265,9 +1286,9 @@ translate_justification (unsigned int opt) /* Returns the line style to use for drawing a rule of the given TYPE. */ static enum outp_line_style -rule_to_draw_type (unsigned char type) +rule_to_draw_type (unsigned char type) { - switch (type) + switch (type) { case TAL_0: case TAL_GAP: @@ -1283,56 +1304,63 @@ rule_to_draw_type (unsigned char type) /* Returns the horizontal rule at the given column and row. */ static int -get_hrule (int c, int r) +get_hrule (const struct tab_table *t, int col, int row) { - return t->rh[c + r * t->cf]; + return t->rh[col + row * t->cf]; } /* Returns the vertical rule at the given column and row. */ static int -get_vrule (int c, int r) +get_vrule (const struct tab_table *t, int col, int row) { - return t->rv[c + r * (t->cf + 1)]; + return t->rv[col + row * (t->cf + 1)]; } /* Renders the horizontal rule at the given column and row at (X,Y) on the page. */ static void -render_horz_rule (int x, int y, int c, int r) +render_horz_rule (const struct tab_rendering *r, + int x, int y, int col, int row) { - enum outp_line_style style = rule_to_draw_type (get_hrule (c, r)); + enum outp_line_style style; + style = rule_to_draw_type (get_hrule (r->table, col, row)); if (style != OUTP_L_NONE) - d->class->line (d, x, y, x + t->w[c], y + t->hrh[r], - OUTP_L_NONE, style, OUTP_L_NONE, style); + r->driver->class->line (r->driver, x, y, x + r->w[col], y + r->hrh[row], + OUTP_L_NONE, style, OUTP_L_NONE, style); } /* Renders the vertical rule at the given column and row at (X,Y) on the page. */ static void -render_vert_rule (int x, int y, int c, int r) +render_vert_rule (const struct tab_rendering *r, + int x, int y, int col, int row) { - enum outp_line_style style = rule_to_draw_type (get_vrule (c, r)); + enum outp_line_style style; + style = rule_to_draw_type (get_vrule (r->table, col, row)); if (style != OUTP_L_NONE) - d->class->line (d, x, y, x + t->wrv[c], y + t->h[r], - style, OUTP_L_NONE, style, OUTP_L_NONE); + r->driver->class->line (r->driver, x, y, x + r->wrv[col], y + r->h[row], + style, OUTP_L_NONE, style, OUTP_L_NONE); } /* Renders the rule intersection at the given column and row at (X,Y) on the page. */ static void -render_rule_intersection (int x, int y, int c, int r) +render_rule_intersection (const struct tab_rendering *r, + int x, int y, int col, int row) { + const struct tab_table *t = r->table; + /* Bounds of intersection. */ int x0 = x; int y0 = y; - int x1 = x + t->wrv[c]; - int y1 = y + t->hrh[r]; + int x1 = x + r->wrv[col]; + int y1 = y + r->hrh[row]; /* Lines on each side of intersection. */ - int top = r > 0 ? get_vrule (c, r - 1) : TAL_0; - int left = c > 0 ? get_hrule (c - 1, r) : TAL_0; - int bottom = r < t->nr ? get_vrule (c, r) : TAL_0; - int right = c < t->nc ? get_hrule (c, r) : TAL_0; + int top = row > 0 ? get_vrule (t, col, row - 1) : TAL_0; + int left = col > 0 ? get_hrule (t, col - 1, row) : TAL_0; + int bottom = row < tab_nr (t) ? get_vrule (t, col, row) : TAL_0; + int right = col < tab_nc (t) ? get_hrule (t, col, row) : TAL_0; /* Output style for each line. */ enum outp_line_style o_top = rule_to_draw_type (top); @@ -1342,36 +1370,37 @@ render_rule_intersection (int x, int y, int c, int r) if (o_top != OUTP_L_NONE || o_left != OUTP_L_NONE || o_bottom != OUTP_L_NONE || o_right != OUTP_L_NONE) - d->class->line (d, x0, y0, x1, y1, o_top, o_left, o_bottom, o_right); + r->driver->class->line (r->driver, x0, y0, x1, y1, + o_top, o_left, o_bottom, o_right); } /* Returns the width of columns C1...C2 exclusive, including interior but not exterior rules. */ static int -strip_width (int c1, int c2) +strip_width (const struct tab_rendering *r, int c1, int c2) { int width = 0; int c; - for (c = c1; c < c2; c++) - width += t->w[c] + t->wrv[c + 1]; + for (c = c1; c < c2; c++) + width += r->w[c] + r->wrv[c + 1]; if (c1 < c2) - width -= t->wrv[c2]; + width -= r->wrv[c2]; return width; } /* Returns the height of rows R1...R2 exclusive, including interior but not exterior rules. */ static int -strip_height (int r1, int r2) +strip_height (const struct tab_rendering *r, int r1, int r2) { int height = 0; - int r; + int row; - for (r = r1; r < r2; r++) - height += t->h[r] + t->hrh[r + 1]; + for (row = r1; row < r2; row++) + height += r->h[row] + r->hrh[row + 1]; if (r1 < r2) - height -= t->hrh[r2]; + height -= r->hrh[r2]; return height; } @@ -1379,12 +1408,14 @@ strip_height (int r1, int r2) page. Also renders joined cells that extend as far to the right as C1 and as far down as R1. */ static void -render_cell (int x, int y, int c, int r, int c1, int r1) +render_cell (const struct tab_rendering *r, + int x, int y, int col, int row, int c1, int r1) { - const int index = c + (r * t->cf); + const struct tab_table *t = r->table; + const int index = col + (row * t->cf); unsigned char type = t->ct[index]; struct substring *content = &t->cc[index]; - + if (!(type & TAB_JOIN)) { if (!(type & TAB_EMPTY)) @@ -1393,11 +1424,11 @@ render_cell (int x, int y, int c, int r, int c1, int r1) text.font = options_to_font (type); text.justification = translate_justification (type); text.string = *content; - text.h = t->w[c]; - text.v = t->h[r]; + text.h = r->w[col]; + text.v = r->h[row]; text.x = x; text.y = y; - d->class->text_draw (d, &text); + r->driver->class->text_draw (r->driver, &text); } } else @@ -1405,63 +1436,50 @@ render_cell (int x, int y, int c, int r, int c1, int r1) struct tab_joined_cell *j = (struct tab_joined_cell *) ss_data (*content); - if (j->hit != tab_hit) + if (j->x1 == col && j->y1 == row) { - j->hit = tab_hit; - - if (j->x1 == c && j->y1 == r) - { - struct outp_text text; - text.font = options_to_font (type); - text.justification = translate_justification (type); - text.string = j->contents; - text.x = x; - text.y = y; - text.h = strip_width (j->x1, MIN (j->x2, c1)); - text.v = strip_height (j->y1, MIN (j->y2, r1)); - d->class->text_draw (d, &text); - } + struct outp_text text; + text.font = options_to_font (type); + text.justification = translate_justification (type); + text.string = j->contents; + text.x = x; + text.y = y; + text.h = strip_width (r, j->x1, MIN (j->x2, c1)); + text.v = strip_height (r, j->y1, MIN (j->y2, r1)); + r->driver->class->text_draw (r->driver, &text); } } } /* Render contiguous strip consisting of columns C0...C1, exclusive, - on row R, at (X,Y). Returns X position after rendering. + on row ROW, at (X,Y). Returns X position after rendering. Also renders joined cells that extend beyond that strip, cropping them to lie within rendering region (C0,R0)-(C1,R1). C0 and C1 count vertical rules as columns. - R counts horizontal rules as rows, but R0 and R1 do not. */ + ROW counts horizontal rules as rows, but R0 and R1 do not. */ static int -render_strip (int x, int y, int r, int c0, int c1, int r0 UNUSED, int r1) +render_strip (const struct tab_rendering *r, + int x, int y, int row, int c0, int c1, int r0 UNUSED, int r1) { - int c; + int col; - for (c = c0; c < c1; c++) - if (c & 1) + for (col = c0; col < c1; col++) + if (col & 1) { - if (r & 1) - render_cell (x, y, c / 2, r / 2, c1 / 2, r1); + if (row & 1) + render_cell (r, x, y, col / 2, row / 2, c1 / 2, r1); else - render_horz_rule (x, y, c / 2, r / 2); - x += t->w[c / 2]; + render_horz_rule (r, x, y, col / 2, row / 2); + x += r->w[col / 2]; } else { - if (r & 1) - render_vert_rule (x, y, c / 2, r / 2); + if (row & 1) + render_vert_rule (r, x, y, col / 2, row / 2); else - render_rule_intersection (x, y, c / 2, r / 2); - x += t->wrv[c / 2]; + render_rule_intersection (r, x, y, col / 2, row / 2); + x += r->wrv[col / 2]; } - - return x; -} -/* Sets COMMAND_NAME as the name of the current command, - for embedding in output. */ -void -tab_set_command_name (const char *command_name_) -{ - free (command_name); - command_name = command_name_ ? xstrdup (command_name_) : NULL; + return x; }