-static void *
-tabi_render_init (struct som_entity *t_, struct outp_driver *driver,
- int hl, int hr, int ht, int hb)
-{
- const struct tab_table *t = t_->ext;
- struct tab_rendering *r;
- int col, row;
- int i;
-
- 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 (row = 0; row <= tab_nr (t); row++)
- {
- int width = 0;
- for (col = 0; col < tab_nc (t); col++)
- {
- 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;
- }
- r->hrh[row] = width;
- }
-
- for (col = 0; col <= tab_nc (t); col++)
- {
- int width = 0;
- for (row = 0; row < tab_nr (t); row++)
- {
- unsigned char *rv = &t->rv[col + row * (t->cf + 1)];
- int w;
- if (*rv == UCHAR_MAX)
- *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;
- }
- r->wrv[col] = width;
- }
-
- /* 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;
-
- t->dim (r, t->dim_aux);
-
- 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]);
-
- /* Add up header sizes. */
- 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))
- r->ht += driver->font_height;
-
- return r;
-}
-
-static void
-tabi_render_free (void *r_)
-{
- struct tab_rendering *r = r_;
-
- 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 (void *r_, int *horiz, int *vert)
-{
- 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
- 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 (void *r_, int cumtype, int start, int *end,
- int max, int *actual)
-{
- 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 < 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 < 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 += *cells++;
- if (total > max)
- {
- if (end)
- *end = start;
- if (actual)
- *actual = 0;
- return;
- }
-
- for (idx = start + 1; idx < limit; idx++)
- {
- int amt = *cells++ + *rules++;
-
- total += amt;
- if (total > max)
- {
- total -= amt;
- break;
- }
- }
-
- if (end)
- *end = idx;
-
- 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 (void *r_, int x, int y, int table_num, int subtable_num,
- const char *command_name)
-{
- 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;
-
- ds_init_empty (&title);
- ds_put_format (&title,"%d.%d", table_num, subtable_num);
- if (x && y)
- ds_put_format (&title, "(%d:%d)", x, y);
- else if (x)
- ds_put_format (&title, "(%d)", x);
- if (command_name != NULL)
- ds_put_format (&title, " %s", command_name);
- ds_put_cstr (&title, ". ");
- if (t->title != NULL)
- 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 (const struct tab_rendering *,
- int x, int y, int r, int c1, int c2, int r1, int r2);
-
-static void
-add_range (int ranges[][2], int *np, int start, int end)