-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);
-}
-\f
-static struct tab_table *t;
-static struct outp_driver *d;
-static int tab_hit;
-
-/* Set the current table to TABLE. */
-static void
-tabi_table (struct som_entity *table)
-{
- 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);
-}
-
-/* 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)
-{
- switch (type)
- {
- case TAL_0:
- return OUTP_L_NONE;
- case TAL_GAP:
- case TAL_1:
- return OUTP_L_SINGLE;
- case TAL_2:
- return OUTP_L_DOUBLE;
- default:
- NOT_REACHED ();
- }
-}
-
-/* Set the current output device to DRIVER. */
-static void
-tabi_driver (struct outp_driver *driver)
-{
- int c, r;
- int i;
-
- assert (driver != NULL);
- d = driver;
-
- /* Figure out sizes of rules. */
- for (r = 0; r <= t->nr; r++)
- {
- int width = 0;
- for (c = 0; c < t->nc; c++)
- {
- unsigned char rh = t->rh[c + r * t->cf];
- int w = driver->horiz_line_width[rule_to_spacing_type (rh)];
- if (w > width)
- width = w;
- }
- t->hrh[r] = width;
- }
-
- for (c = 0; c <= t->nc; c++)
- {
- int width = 0;
- for (r = 0; r < t->nr; r++)
- {
- unsigned char *rv = &t->rv[c + r * (t->cf + 1)];
- int w;
- if (*rv == UCHAR_MAX)
- *rv = c != 0 && c != t->nc ? TAL_GAP : TAL_0;
- w = driver->vert_line_width[rule_to_spacing_type (*rv)];
- if (w > width)
- width = w;
- }
- t->wrv[c] = 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
-
- assert (t->dim != NULL);
- t->dim (t, d);
-
-#if DEBUGGING
- {
- int error = 0;
-
- 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];
-
- /* Title. */
- if (!(t->flags & SOMF_NO_TITLE))
- t->ht += d->font_height;
-}
-
-/* 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)
-{
- assert (n_columns != NULL && n_rows != NULL);
- *n_columns = t->nc;
- *n_rows = t->nr;
-}
-
-static void tabi_cumulate (int cumtype, int start, int *end, int max, int *actual);
-
-/* 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)
-{
- assert (hl != NULL && hr != NULL && ht != NULL && hb != NULL);
- *hl = t->l;
- *hr = t->r;
- *ht = t->t;
- *hb = t->b;
-}
-
-/* Determines the number of rows or columns (including appropriate
- headers), depending on CUMTYPE, that will fit into the space
- specified. Takes rows/columns starting at index START and attempts
- to fill up available space MAX. Returns in END the index of the
- last row/column plus one; returns in ACTUAL the actual amount of
- space the selected rows/columns (including appropriate headers)
- filled. */
-static void
-tabi_cumulate (int cumtype, int start, int *end, int max, int *actual)
-{
- int n;
- int *d;
- int *r;
- int total;
-
- 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;
- }
- 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;
- }
-
- total += *d++;
- if (total > max)
- {
- if (end)
- *end = start;
- if (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;
-}
-
-/* Returns true if the table will fit in the given page LENGTH,
- false otherwise. */
-static bool
-tabi_fits_length (int length)
-{
- int i;
-
- for (i = t->t; i < t->nr - t->b; i++)
- if (t->ht + t->hb + t->h[i] > length)
- return false;
-
- 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;
-}
-
-/* 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)
-{
- char buf[1024];
- char *cp;
-
- if (t->flags & SOMF_NO_TITLE)
- return;
-
- cp = spprintf (buf, "%d.%d", table_num, subtable_num);
- if (x && y)
- cp = spprintf (cp, "(%d:%d)", x, y);
- else if (x)
- cp = spprintf (cp, "(%d)", x);
- if (command_name != NULL)
- cp = spprintf (cp, " %s", command_name);
- cp = stpcpy (cp, ". ");
- 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);
- }
-}
-
-static int render_strip (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)
-{
- int r;
- for (r = r0; r < r1; r++)
- {
- 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];
- }
- return y;
-}
-
-/* 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)
-{
- int y;
-
- tab_hit++;
-
- y = d->cp_y;
- if (!(t->flags & SOMF_NO_TITLE))
- y += d->font_height;
-
- 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);
-}
-
-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_title,
- tabi_render,