diff options
author | Ruslan Ermilov <ru@FreeBSD.org> | 2001-04-17 12:23:50 +0000 |
---|---|---|
committer | Ruslan Ermilov <ru@FreeBSD.org> | 2001-04-17 12:23:50 +0000 |
commit | d0bf30505c50ee6b6f217d5e2bd1a67938ce81e4 (patch) | |
tree | d0ecc32b66c84ba03b40de7da66350fc02b90d02 /contrib/groff/tbl | |
parent | af2786323e797d59708a2ca7929031c965bc2dde (diff) |
This commit was generated by cvs2svn to compensate for changes in r75587,
which included commits to RCS files with non-trunk default branches.
Notes
Notes:
svn path=/head/; revision=75588
Diffstat (limited to 'contrib/groff/tbl')
-rw-r--r-- | contrib/groff/tbl/Makefile.sub | 12 | ||||
-rw-r--r-- | contrib/groff/tbl/main.cc | 1514 | ||||
-rw-r--r-- | contrib/groff/tbl/table.cc | 2778 | ||||
-rw-r--r-- | contrib/groff/tbl/table.h | 152 | ||||
-rw-r--r-- | contrib/groff/tbl/tbl.man | 178 |
5 files changed, 0 insertions, 4634 deletions
diff --git a/contrib/groff/tbl/Makefile.sub b/contrib/groff/tbl/Makefile.sub deleted file mode 100644 index 224baffcf329..000000000000 --- a/contrib/groff/tbl/Makefile.sub +++ /dev/null @@ -1,12 +0,0 @@ -PROG=tbl -MAN1=tbl.n -XLIBS=$(LIBGROFF) -OBJS=\ - main.o \ - table.o -CCSRCS=\ - $(srcdir)/main.cc \ - $(srcdir)/table.cc -HDRS=\ - $(srcdir)/table.h -NAMEPREFIX=$(g) diff --git a/contrib/groff/tbl/main.cc b/contrib/groff/tbl/main.cc deleted file mode 100644 index 5ff69e8914ff..000000000000 --- a/contrib/groff/tbl/main.cc +++ /dev/null @@ -1,1514 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff 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, or (at your option) any later -version. - -groff 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 groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "table.h" - -#define MAX_POINT_SIZE 99 -#define MAX_VERTICAL_SPACING 72 - -static int compatible_flag = 0; - -class table_input { - FILE *fp; - enum { START, MIDDLE, REREAD_T, REREAD_TE, REREAD_E, END, ERROR } state; - string unget_stack; -public: - table_input(FILE *); - int get(); - int ended() { return unget_stack.empty() && state == END; } - void unget(char); -}; - -table_input::table_input(FILE *p) -: fp(p), state(START) -{ -} - -void table_input::unget(char c) -{ - assert(c != '\0'); - unget_stack += c; - if (c == '\n') - current_lineno--; -} - -int table_input::get() -{ - int len = unget_stack.length(); - if (len != 0) { - unsigned char c = unget_stack[len - 1]; - unget_stack.set_length(len - 1); - if (c == '\n') - current_lineno++; - return c; - } - int c; - for (;;) { - switch (state) { - case START: - if ((c = getc(fp)) == '.') { - if ((c = getc(fp)) == 'T') { - if ((c = getc(fp)) == 'E') { - if (compatible_flag) { - state = END; - return EOF; - } - else { - c = getc(fp); - if (c != EOF) - ungetc(c, fp); - if (c == EOF || c == ' ' || c == '\n') { - state = END; - return EOF; - } - state = REREAD_TE; - return '.'; - } - } - else { - if (c != EOF) - ungetc(c, fp); - state = REREAD_T; - return '.'; - } - } - else { - if (c != EOF) - ungetc(c, fp); - state = MIDDLE; - return '.'; - } - } - else if (c == EOF) { - state = ERROR; - return EOF; - } - else { - if (c == '\n') - current_lineno++; - else { - state = MIDDLE; - if (c == '\0') { - error("illegal input character code 0"); - break; - } - } - return c; - } - break; - case MIDDLE: - // handle line continuation - if ((c = getc(fp)) == '\\') { - c = getc(fp); - if (c == '\n') - c = getc(fp); // perhaps state ought to be START now - else { - if (c != EOF) - ungetc(c, fp); - c = '\\'; - } - } - if (c == EOF) { - state = ERROR; - return EOF; - } - else { - if (c == '\n') { - state = START; - current_lineno++; - } - else if (c == '\0') { - error("illegal input character code 0"); - break; - } - return c; - } - case REREAD_T: - state = MIDDLE; - return 'T'; - case REREAD_TE: - state = REREAD_E; - return 'T'; - case REREAD_E: - state = MIDDLE; - return 'E'; - case END: - case ERROR: - return EOF; - } - } -} - -void process_input_file(FILE *); -void process_table(table_input &in); - -void process_input_file(FILE *fp) -{ - enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state; - state = START; - int c; - while ((c = getc(fp)) != EOF) - switch (state) { - case START: - if (c == '.') - state = HAD_DOT; - else { - if (c == '\n') - current_lineno++; - else - state = MIDDLE; - putchar(c); - } - break; - case MIDDLE: - if (c == '\n') { - current_lineno++; - state = START; - } - putchar(c); - break; - case HAD_DOT: - if (c == 'T') - state = HAD_T; - else if (c == 'l') - state = HAD_l; - else { - putchar('.'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_T: - if (c == 'S') - state = HAD_TS; - else { - putchar('.'); - putchar('T'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_TS: - if (c == ' ' || c == '\n' || compatible_flag) { - putchar('.'); - putchar('T'); - putchar('S'); - while (c != '\n') { - if (c == EOF) { - error("end of file at beginning of table"); - return; - } - putchar(c); - c = getc(fp); - } - putchar('\n'); - printf(".if '\\*(.T'html' \\X(table-start(\n"); - current_lineno++; - { - table_input input(fp); - process_table(input); - if (input.ended()) - printf(".if '\\*(.T'html' \\X(table-end(\n"); - set_troff_location(current_filename, current_lineno); - if (input.ended()) { - fputs(".TE", stdout); - while ((c = getc(fp)) != '\n') { - if (c == EOF) { - putchar('\n'); - return; - } - putchar(c); - } - putchar('\n'); - current_lineno++; - } - } - state = START; - } - else { - fputs(".TS", stdout); - putchar(c); - state = MIDDLE; - } - break; - case HAD_l: - if (c == 'f') - state = HAD_lf; - else { - putchar('.'); - putchar('l'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_lf: - if (c == ' ' || c == '\n' || compatible_flag) { - string line; - while (c != EOF) { - line += c; - if (c == '\n') { - current_lineno++; - break; - } - c = getc(fp); - } - line += '\0'; - interpret_lf_args(line.contents()); - printf(".lf%s", line.contents()); - state = START; - } - else { - fputs(".lf", stdout); - putchar(c); - state = MIDDLE; - } - break; - default: - assert(0); - } - switch(state) { - case START: - break; - case MIDDLE: - putchar('\n'); - break; - case HAD_DOT: - fputs(".\n", stdout); - break; - case HAD_l: - fputs(".l\n", stdout); - break; - case HAD_T: - fputs(".T\n", stdout); - break; - case HAD_lf: - fputs(".lf\n", stdout); - break; - case HAD_TS: - fputs(".TS\n", stdout); - break; - } - if (fp != stdin) - fclose(fp); -} - -struct options { - unsigned flags; - int linesize; - char delim[2]; - char tab_char; - char decimal_point_char; - - options(); -}; - -options::options() -: flags(0), linesize(0), tab_char('\t'), decimal_point_char('.') -{ - delim[0] = delim[1] = '\0'; -} - -// Return non-zero if p and q are the same ignoring case. - -int strieq(const char *p, const char *q) -{ - for (; cmlower(*p) == cmlower(*q); p++, q++) - if (*p == '\0') - return 1; - return 0; -} - -// return 0 if we should give up in this table - -options *process_options(table_input &in) -{ - options *opt = new options; - string line; - int level = 0; - for (;;) { - int c = in.get(); - if (c == EOF) { - int i = line.length(); - while (--i >= 0) - in.unget(line[i]); - return opt; - } - if (c == '\n') { - in.unget(c); - int i = line.length(); - while (--i >= 0) - in.unget(line[i]); - return opt; - } - else if (c == '(') - level++; - else if (c == ')') - level--; - else if (c == ';' && level == 0) { - line += '\0'; - break; - } - line += c; - } - if (line.empty()) - return opt; - char *p = &line[0]; - for (;;) { - while (!csalpha(*p) && *p != '\0') - p++; - if (*p == '\0') - break; - char *q = p; - while (csalpha(*q)) - q++; - char *arg = 0; - if (*q != '(' && *q != '\0') - *q++ = '\0'; - while (csspace(*q)) - q++; - if (*q == '(') { - *q++ = '\0'; - arg = q; - while (*q != ')' && *q != '\0') - q++; - if (*q == '\0') - error("missing `)'"); - else - *q++ = '\0'; - } - if (*p == '\0') { - if (arg) - error("argument without option"); - } - else if (strieq(p, "tab")) { - if (!arg) - error("`tab' option requires argument in parentheses"); - else { - if (arg[0] == '\0' || arg[1] != '\0') - error("argument to `tab' option must be a single character"); - else - opt->tab_char = arg[0]; - } - } - else if (strieq(p, "linesize")) { - if (!arg) - error("`linesize' option requires argument in parentheses"); - else { - if (sscanf(arg, "%d", &opt->linesize) != 1) - error("bad linesize `%s'", arg); - else if (opt->linesize <= 0) { - error("linesize must be positive"); - opt->linesize = 0; - } - } - } - else if (strieq(p, "delim")) { - if (!arg) - error("`delim' option requires argument in parentheses"); - else if (arg[0] == '\0' || arg[1] == '\0' || arg[2] != '\0') - error("argument to `delim' option must be two characters"); - else { - opt->delim[0] = arg[0]; - opt->delim[1] = arg[1]; - } - } - else if (strieq(p, "center") || strieq(p, "centre")) { - if (arg) - error("`center' option does not take a argument"); - opt->flags |= table::CENTER; - } - else if (strieq(p, "expand")) { - if (arg) - error("`expand' option does not take a argument"); - opt->flags |= table::EXPAND; - } - else if (strieq(p, "box") || strieq(p, "frame")) { - if (arg) - error("`box' option does not take a argument"); - opt->flags |= table::BOX; - } - else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) { - if (arg) - error("`doublebox' option does not take a argument"); - opt->flags |= table::DOUBLEBOX; - } - else if (strieq(p, "allbox")) { - if (arg) - error("`allbox' option does not take a argument"); - opt->flags |= table::ALLBOX; - } - else if (strieq(p, "nokeep")) { - if (arg) - error("`nokeep' option does not take a argument"); - opt->flags |= table::NOKEEP; - } - else if (strieq(p, "decimalpoint")) { - if (!arg) - error("`decimalpoint' option requires argument in parentheses"); - else { - if (arg[0] == '\0' || arg[1] != '\0') - error("argument to `decimalpoint' option must be a single character"); - else - opt->decimal_point_char = arg[0]; - } - } - else { - error("unrecognised global option `%1'", p); - // delete opt; - // return 0; - } - p = q; - } - return opt; -} - -entry_modifier::entry_modifier() -: vertical_alignment(CENTER), zero_width(0), stagger(0) -{ - vertical_spacing.inc = vertical_spacing.val = 0; - point_size.inc = point_size.val = 0; -} - -entry_modifier::~entry_modifier() -{ -} - -entry_format::entry_format() : type(FORMAT_LEFT) -{ -} - -entry_format::entry_format(format_type t) : type(t) -{ -} - -void entry_format::debug_print() const -{ - switch (type) { - case FORMAT_LEFT: - putc('l', stderr); - break; - case FORMAT_CENTER: - putc('c', stderr); - break; - case FORMAT_RIGHT: - putc('r', stderr); - break; - case FORMAT_NUMERIC: - putc('n', stderr); - break; - case FORMAT_ALPHABETIC: - putc('a', stderr); - break; - case FORMAT_SPAN: - putc('s', stderr); - break; - case FORMAT_VSPAN: - putc('^', stderr); - break; - case FORMAT_HLINE: - putc('_', stderr); - break; - case FORMAT_DOUBLE_HLINE: - putc('=', stderr); - break; - default: - assert(0); - break; - } - if (point_size.val != 0) { - putc('p', stderr); - if (point_size.inc > 0) - putc('+', stderr); - else if (point_size.inc < 0) - putc('-', stderr); - fprintf(stderr, "%d ", point_size.val); - } - if (vertical_spacing.val != 0) { - putc('v', stderr); - if (vertical_spacing.inc > 0) - putc('+', stderr); - else if (vertical_spacing.inc < 0) - putc('-', stderr); - fprintf(stderr, "%d ", vertical_spacing.val); - } - if (!font.empty()) { - putc('f', stderr); - put_string(font, stderr); - putc(' ', stderr); - } - switch (vertical_alignment) { - case entry_modifier::CENTER: - break; - case entry_modifier::TOP: - putc('t', stderr); - break; - case entry_modifier::BOTTOM: - putc('d', stderr); - break; - } - if (zero_width) - putc('z', stderr); - if (stagger) - putc('u', stderr); -} - -struct format { - int nrows; - int ncolumns; - int *separation; - string *width; - char *equal; - entry_format **entry; - char **vline; - - format(int nr, int nc); - ~format(); - void add_rows(int n); -}; - -format::format(int nr, int nc) : nrows(nr), ncolumns(nc) -{ - int i; - separation = ncolumns > 1 ? new int[ncolumns - 1] : 0; - for (i = 0; i < ncolumns-1; i++) - separation[i] = -1; - width = new string[ncolumns]; - equal = new char[ncolumns]; - for (i = 0; i < ncolumns; i++) - equal[i] = 0; - entry = new entry_format *[nrows]; - for (i = 0; i < nrows; i++) - entry[i] = new entry_format[ncolumns]; - vline = new char*[nrows]; - for (i = 0; i < nrows; i++) { - vline[i] = new char[ncolumns+1]; - for (int j = 0; j < ncolumns+1; j++) - vline[i][j] = 0; - } -} - -void format::add_rows(int n) -{ - int i; - char **old_vline = vline; - vline = new char*[nrows + n]; - for (i = 0; i < nrows; i++) - vline[i] = old_vline[i]; - a_delete old_vline; - for (i = 0; i < n; i++) { - vline[nrows + i] = new char[ncolumns + 1]; - for (int j = 0; j < ncolumns + 1; j++) - vline[nrows + i][j] = 0; - } - entry_format **old_entry = entry; - entry = new entry_format *[nrows + n]; - for (i = 0; i < nrows; i++) - entry[i] = old_entry[i]; - a_delete old_entry; - for (i = 0; i < n; i++) - entry[nrows + i] = new entry_format[ncolumns]; - nrows += n; -} - -format::~format() -{ - a_delete separation; - ad_delete(ncolumns) width; - a_delete equal; - for (int i = 0; i < nrows; i++) { - a_delete vline[i]; - ad_delete(ncolumns) entry[i]; - } - a_delete vline; - a_delete entry; -} - -struct input_entry_format : public entry_format { - input_entry_format *next; - string width; - int separation; - int vline; - int pre_vline; - int last_column; - int equal; - input_entry_format(format_type, input_entry_format * = 0); - ~input_entry_format(); - void debug_print(); -}; - -input_entry_format::input_entry_format(format_type t, input_entry_format *p) -: entry_format(t), next(p) -{ - separation = -1; - last_column = 0; - vline = 0; - pre_vline = 0; - equal = 0; -} - -input_entry_format::~input_entry_format() -{ -} - -void free_input_entry_format_list(input_entry_format *list) -{ - while (list) { - input_entry_format *tem = list; - list = list->next; - delete tem; - } -} - -void input_entry_format::debug_print() -{ - int i; - for (i = 0; i < pre_vline; i++) - putc('|', stderr); - entry_format::debug_print(); - if (!width.empty()) { - putc('w', stderr); - putc('(', stderr); - put_string(width, stderr); - putc(')', stderr); - } - if (equal) - putc('e', stderr); - if (separation >= 0) - fprintf(stderr, "%d", separation); - for (i = 0; i < vline; i++) - putc('|', stderr); - if (last_column) - putc(',', stderr); -} - -// Return zero if we should give up on this table. -// If this is a continuation format line, current_format will be the current -// format line. - -format *process_format(table_input &in, options *opt, - format *current_format = 0) -{ - input_entry_format *list = 0; - int c = in.get(); - for (;;) { - int pre_vline = 0; - int got_format = 0; - int got_period = 0; - format_type t; - for (;;) { - if (c == EOF) { - error("end of input while processing format"); - free_input_entry_format_list(list); - return 0; - } - switch (c) { - case 'n': - case 'N': - t = FORMAT_NUMERIC; - got_format = 1; - break; - case 'a': - case 'A': - got_format = 1; - t = FORMAT_ALPHABETIC; - break; - case 'c': - case 'C': - got_format = 1; - t = FORMAT_CENTER; - break; - case 'l': - case 'L': - got_format = 1; - t = FORMAT_LEFT; - break; - case 'r': - case 'R': - got_format = 1; - t = FORMAT_RIGHT; - break; - case 's': - case 'S': - got_format = 1; - t = FORMAT_SPAN; - break; - case '^': - got_format = 1; - t = FORMAT_VSPAN; - break; - case '_': - case '-': // tbl also accepts this - got_format = 1; - t = FORMAT_HLINE; - break; - case '=': - got_format = 1; - t = FORMAT_DOUBLE_HLINE; - break; - case '.': - got_period = 1; - break; - case '|': - pre_vline++; - break; - case ' ': - case '\t': - case '\n': - break; - default: - if (c == opt->tab_char) - break; - error("unrecognised format `%1'", char(c)); - free_input_entry_format_list(list); - return 0; - } - if (got_period) - break; - c = in.get(); - if (got_format) - break; - } - if (got_period) - break; - list = new input_entry_format(t, list); - if (pre_vline) - list->pre_vline = pre_vline; - int success = 1; - do { - switch (c) { - case 't': - case 'T': - c = in.get(); - list->vertical_alignment = entry_modifier::TOP; - break; - case 'd': - case 'D': - c = in.get(); - list->vertical_alignment = entry_modifier::BOTTOM; - break; - case 'u': - case 'U': - c = in.get(); - list->stagger = 1; - break; - case 'z': - case 'Z': - c = in.get(); - list->zero_width = 1; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int w = 0; - do { - w = w*10 + (c - '0'); - c = in.get(); - } while (c != EOF && csdigit(c)); - list->separation = w; - } - break; - case 'f': - case 'F': - do { - c = in.get(); - } while (c == ' ' || c == '\t'); - if (c == EOF) { - error("missing font name"); - break; - } - if (c == '(') { - for (;;) { - c = in.get(); - if (c == EOF || c == ' ' || c == '\t') { - error("missing `)'"); - break; - } - if (c == ')') { - c = in.get(); - break; - } - list->font += char(c); - } - } - else { - list->font = c; - char cc = c; - c = in.get(); - if (!csdigit(cc) - && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') { - list->font += char(c); - c = in.get(); - } - } - break; - case 'v': - case 'V': - c = in.get(); - list->vertical_spacing.val = 0; - list->vertical_spacing.inc = 0; - if (c == '+' || c == '-') { - list->vertical_spacing.inc = (c == '+' ? 1 : -1); - c = in.get(); - } - if (c == EOF || !csdigit(c)) { - error("`v' modifier must be followed by number"); - list->vertical_spacing.inc = 0; - } - else { - do { - list->vertical_spacing.val *= 10; - list->vertical_spacing.val += c - '0'; - c = in.get(); - } while (c != EOF && csdigit(c)); - } - if (list->vertical_spacing.val > MAX_VERTICAL_SPACING - || list->vertical_spacing.val < -MAX_VERTICAL_SPACING) { - error("unreasonable point size"); - list->vertical_spacing.val = 0; - list->vertical_spacing.inc = 0; - } - break; - case 'p': - case 'P': - c = in.get(); - list->point_size.val = 0; - list->point_size.inc = 0; - if (c == '+' || c == '-') { - list->point_size.inc = (c == '+' ? 1 : -1); - c = in.get(); - } - if (c == EOF || !csdigit(c)) { - error("`p' modifier must be followed by number"); - list->point_size.inc = 0; - } - else { - do { - list->point_size.val *= 10; - list->point_size.val += c - '0'; - c = in.get(); - } while (c != EOF && csdigit(c)); - } - if (list->point_size.val > MAX_POINT_SIZE - || list->point_size.val < -MAX_POINT_SIZE) { - error("unreasonable point size"); - list->point_size.val = 0; - list->point_size.inc = 0; - } - break; - case 'w': - case 'W': - c = in.get(); - while (c == ' ' || c == '\t') - c = in.get(); - if (c == '(') { - list->width = ""; - c = in.get(); - while (c != ')') { - if (c == EOF || c == '\n') { - error("missing `)'"); - free_input_entry_format_list(list); - return 0; - } - list->width += c; - c = in.get(); - } - c = in.get(); - } - else { - if (c == '+' || c == '-') { - list->width = char(c); - c = in.get(); - } - else - list->width = ""; - if (c == EOF || !csdigit(c)) - error("bad argument for `w' modifier"); - else { - do { - list->width += char(c); - c = in.get(); - } while (c != EOF && csdigit(c)); - } - } - break; - case 'e': - case 'E': - c = in.get(); - list->equal++; - break; - case '|': - c = in.get(); - list->vline++; - break; - case 'B': - case 'b': - c = in.get(); - list->font = "B"; - break; - case 'I': - case 'i': - c = in.get(); - list->font = "I"; - break; - case ' ': - case '\t': - c = in.get(); - break; - default: - if (c == opt->tab_char) - c = in.get(); - else - success = 0; - break; - } - } while (success); - if (list->vline > 2) { - list->vline = 2; - error("more than 2 vertical bars between key letters"); - } - if (c == '\n' || c == ',') { - c = in.get(); - list->last_column = 1; - } - } - if (c == '.') { - do { - c = in.get(); - } while (c == ' ' || c == '\t'); - if (c != '\n') { - error("`.' not last character on line"); - free_input_entry_format_list(list); - return 0; - } - } - if (!list) { - error("no format"); - free_input_entry_format_list(list); - return 0; - } - list->last_column = 1; - // now reverse the list so that the first row is at the beginning - input_entry_format *rev = 0; - while (list != 0) { - input_entry_format *tem = list->next; - list->next = rev; - rev = list; - list = tem; - } - list = rev; - input_entry_format *tem; - -#if 0 - for (tem = list; tem; tem = tem->next) - tem->debug_print(); - putc('\n', stderr); -#endif - // compute number of columns and rows - int ncolumns = 0; - int nrows = 0; - int col = 0; - for (tem = list; tem; tem = tem->next) { - if (tem->last_column) { - if (col >= ncolumns) - ncolumns = col + 1; - col = 0; - nrows++; - } - else - col++; - } - int row; - format *f; - if (current_format) { - if (ncolumns > current_format->ncolumns) { - error("cannot increase the number of columns in a continued format"); - free_input_entry_format_list(list); - return 0; - } - f = current_format; - row = f->nrows; - f->add_rows(nrows); - } - else { - f = new format(nrows, ncolumns); - row = 0; - } - col = 0; - for (tem = list; tem; tem = tem->next) { - f->entry[row][col] = *tem; - if (col < ncolumns-1) { - // use the greatest separation - if (tem->separation > f->separation[col]) { - if (current_format) - error("cannot change column separation in continued format"); - else - f->separation[col] = tem->separation; - } - } - else if (tem->separation >= 0) - error("column separation specified for last column"); - if (tem->equal && !f->equal[col]) { - if (current_format) - error("cannot change which columns are equal in continued format"); - else - f->equal[col] = 1; - } - if (!tem->width.empty()) { - // use the last width - if (!f->width[col].empty() && f->width[col] != tem->width) - error("multiple widths for column %1", col+1); - f->width[col] = tem->width; - } - if (tem->pre_vline) { - assert(col == 0); - f->vline[row][col] = tem->pre_vline; - } - f->vline[row][col+1] = tem->vline; - if (tem->last_column) { - row++; - col = 0; - } - else - col++; - } - free_input_entry_format_list(list); - for (col = 0; col < ncolumns; col++) { - entry_format *e = f->entry[f->nrows-1] + col; - if (e->type != FORMAT_HLINE - && e->type != FORMAT_DOUBLE_HLINE - && e->type != FORMAT_SPAN) - break; - } - if (col >= ncolumns) { - error("last row of format is all lines"); - delete f; - return 0; - } - return f; -} - -table *process_data(table_input &in, format *f, options *opt) -{ - char tab_char = opt->tab_char; - int ncolumns = f->ncolumns; - int current_row = 0; - int format_index = 0; - int give_up = 0; - enum { DATA_INPUT_LINE, TROFF_INPUT_LINE, SINGLE_HLINE, DOUBLE_HLINE } type; - table *tbl = new table(ncolumns, opt->flags, opt->linesize, - opt->decimal_point_char); - if (opt->delim[0] != '\0') - tbl->set_delim(opt->delim[0], opt->delim[1]); - for (;;) { - // first determine what type of line this is - int c = in.get(); - if (c == EOF) - break; - if (c == '.') { - int d = in.get(); - if (d != EOF && csdigit(d)) { - in.unget(d); - type = DATA_INPUT_LINE; - } - else { - in.unget(d); - type = TROFF_INPUT_LINE; - } - } - else if (c == '_' || c == '=') { - int d = in.get(); - if (d == '\n') { - if (c == '_') - type = SINGLE_HLINE; - else - type = DOUBLE_HLINE; - } - else { - in.unget(d); - type = DATA_INPUT_LINE; - } - } - else { - type = DATA_INPUT_LINE; - } - switch (type) { - case DATA_INPUT_LINE: - { - string input_entry; - if (format_index >= f->nrows) - format_index = f->nrows - 1; - // A format row that is all lines doesn't use up a data line. - while (format_index < f->nrows - 1) { - int c; - for (c = 0; c < ncolumns; c++) { - entry_format *e = f->entry[format_index] + c; - if (e->type != FORMAT_HLINE - && e->type != FORMAT_DOUBLE_HLINE - // Unfortunately tbl treats a span as needing data. - // && e->type != FORMAT_SPAN - ) - break; - } - if (c < ncolumns) - break; - for (c = 0; c < ncolumns; c++) - tbl->add_entry(current_row, c, input_entry, - f->entry[format_index] + c, current_filename, - current_lineno); - tbl->add_vlines(current_row, f->vline[format_index]); - format_index++; - current_row++; - } - entry_format *line_format = f->entry[format_index]; - int col = 0; - int row_comment = 0; - for (;;) { - if (c == tab_char || c == '\n') { - int ln = current_lineno; - if (c == '\n') - --ln; - while (col < ncolumns - && line_format[col].type == FORMAT_SPAN) { - tbl->add_entry(current_row, col, "", &line_format[col], - current_filename, ln); - col++; - } - if (c == '\n' && input_entry.length() == 2 - && input_entry[0] == 'T' && input_entry[1] == '{') { - input_entry = ""; - ln++; - enum { - START, MIDDLE, GOT_T, GOT_RIGHT_BRACE, GOT_DOT, - GOT_l, GOT_lf, END - } state = START; - while (state != END) { - c = in.get(); - if (c == EOF) - break; - switch (state) { - case START: - if (c == 'T') - state = GOT_T; - else if (c == '.') - state = GOT_DOT; - else { - input_entry += c; - if (c != '\n') - state = MIDDLE; - } - break; - case GOT_T: - if (c == '}') - state = GOT_RIGHT_BRACE; - else { - input_entry += 'T'; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case GOT_DOT: - if (c == 'l') - state = GOT_l; - else { - input_entry += '.'; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case GOT_l: - if (c == 'f') - state = GOT_lf; - else { - input_entry += ".l"; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case GOT_lf: - if (c == ' ' || c == '\n' || compatible_flag) { - string args; - input_entry += ".lf"; - while (c != EOF) { - args += c; - if (c == '\n') - break; - c = in.get(); - } - args += '\0'; - interpret_lf_args(args.contents()); - // remove the '\0' - args.set_length(args.length() - 1); - input_entry += args; - state = START; - } - else { - input_entry += ".lf"; - input_entry += c; - state = MIDDLE; - } - break; - case GOT_RIGHT_BRACE: - if (c == '\n' || c == tab_char) - state = END; - else { - input_entry += 'T'; - input_entry += '}'; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case MIDDLE: - if (c == '\n') - state = START; - input_entry += c; - break; - case END: - default: - assert(0); - } - } - if (c == EOF) { - error("end of data in middle of text block"); - give_up = 1; - break; - } - } - if (col >= ncolumns) { - if (!input_entry.empty()) { - if (input_entry.length() >= 2 - && input_entry[0] == '\\' - && input_entry[1] == '"') - row_comment = 1; - else if (!row_comment) { - if (c == '\n') - in.unget(c); - input_entry += '\0'; - error("excess data entry `%1' discarded", - input_entry.contents()); - if (c == '\n') - (void)in.get(); - } - } - } - else - tbl->add_entry(current_row, col, input_entry, - &line_format[col], current_filename, ln); - col++; - if (c == '\n') - break; - input_entry = ""; - } - else - input_entry += c; - c = in.get(); - if (c == EOF) - break; - } - if (give_up) - break; - input_entry = ""; - for (; col < ncolumns; col++) - tbl->add_entry(current_row, col, input_entry, &line_format[col], - current_filename, current_lineno - 1); - tbl->add_vlines(current_row, f->vline[format_index]); - current_row++; - format_index++; - } - break; - case TROFF_INPUT_LINE: - { - string line; - int ln = current_lineno; - for (;;) { - line += c; - if (c == '\n') - break; - c = in.get(); - if (c == EOF) { - break; - } - } - tbl->add_text_line(current_row, line, current_filename, ln); - if (line.length() >= 4 - && line[0] == '.' && line[1] == 'T' && line[2] == '&') { - format *newf = process_format(in, opt, f); - if (newf == 0) - give_up = 1; - else - f = newf; - } - if (line.length() >= 3 - && line[0] == '.' && line[1] == 'f' && line[2] == 'f') { - line += '\0'; - interpret_lf_args(line.contents() + 3); - } - } - break; - case SINGLE_HLINE: - tbl->add_single_hline(current_row); - break; - case DOUBLE_HLINE: - tbl->add_double_hline(current_row); - break; - default: - assert(0); - } - if (give_up) - break; - } - if (!give_up && current_row == 0) { - error("no real data"); - give_up = 1; - } - if (give_up) { - delete tbl; - return 0; - } - // Do this here rather than at the beginning in case continued formats - // change it. - int i; - for (i = 0; i < ncolumns - 1; i++) - if (f->separation[i] >= 0) - tbl->set_column_separation(i, f->separation[i]); - for (i = 0; i < ncolumns; i++) - if (!f->width[i].empty()) - tbl->set_minimum_width(i, f->width[i]); - for (i = 0; i < ncolumns; i++) - if (f->equal[i]) - tbl->set_equal_column(i); - return tbl; -} - -void process_table(table_input &in) -{ - int c; - options *opt = 0; - format *form = 0; - table *tbl = 0; - if ((opt = process_options(in)) != 0 - && (form = process_format(in, opt)) != 0 - && (tbl = process_data(in, form, opt)) != 0) { - tbl->print(); - delete tbl; - } - else { - error("giving up on this table"); - while ((c = in.get()) != EOF) - ; - } - delete opt; - delete form; - if (!in.ended()) - error("premature end of file"); -} - -static void usage() -{ - fprintf(stderr, "usage: %s [ -vC ] [ files... ]\n", program_name); - exit(1); -} - -int main(int argc, char **argv) -{ - program_name = argv[0]; - static char stderr_buf[BUFSIZ]; - setbuf(stderr, stderr_buf); - int opt; - while ((opt = getopt(argc, argv, "vCT:")) != EOF) - switch (opt) { - case 'C': - compatible_flag = 1; - break; - case 'v': - { - extern const char *Version_string; - fprintf(stderr, "GNU tbl version %s\n", Version_string); - fflush(stderr); - break; - } - case 'T': - // I'm sick of getting bug reports from IRIX users - break; - case '?': - usage(); - break; - default: - assert(0); - } - printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n" - ".if !dTS .ds TS\n" - ".if !dTE .ds TE\n"); - if (argc > optind) { - for (int i = optind; i < argc; i++) - if (argv[i][0] == '-' && argv[i][1] == '\0') { - current_filename = "-"; - current_lineno = 1; - printf(".lf 1 -\n"); - process_input_file(stdin); - } - else { - errno = 0; - FILE *fp = fopen(argv[i], "r"); - if (fp == 0) { - current_lineno = -1; - error("can't open `%1': %2", argv[i], strerror(errno)); - } - else { - current_lineno = 1; - current_filename = argv[i]; - printf(".lf 1 %s\n", current_filename); - process_input_file(fp); - } - } - } - else { - current_filename = "-"; - current_lineno = 1; - printf(".lf 1 -\n"); - process_input_file(stdin); - } - if (ferror(stdout) || fflush(stdout) < 0) - fatal("output error"); - return 0; -} - diff --git a/contrib/groff/tbl/table.cc b/contrib/groff/tbl/table.cc deleted file mode 100644 index 354c7d885089..000000000000 --- a/contrib/groff/tbl/table.cc +++ /dev/null @@ -1,2778 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff 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, or (at your option) any later -version. - -groff 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 groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "table.h" - -#define BAR_HEIGHT ".25m" -#define DOUBLE_LINE_SEP "2p" -#define HALF_DOUBLE_LINE_SEP "1p" -#define LINE_SEP "2p" -#define BODY_DEPTH ".25m" - -const int DEFAULT_COLUMN_SEPARATION = 3; - -#define DELIMITER_CHAR "\\[tbl]" -#define PREFIX "3" -#define SEPARATION_FACTOR_REG PREFIX "sep" -#define BOTTOM_REG PREFIX "bot" -#define RESET_MACRO_NAME PREFIX "init" -#define LINESIZE_REG PREFIX "lps" -#define TOP_REG PREFIX "top" -#define CURRENT_ROW_REG PREFIX "crow" -#define LAST_PASSED_ROW_REG PREFIX "passed" -#define TRANSPARENT_STRING_NAME PREFIX "trans" -#define QUOTE_STRING_NAME PREFIX "quote" -#define SECTION_DIVERSION_NAME PREFIX "section" -#define SECTION_DIVERSION_FLAG_REG PREFIX "sflag" -#define SAVED_VERTICAL_POS_REG PREFIX "vert" -#define NEED_BOTTOM_RULE_REG PREFIX "brule" -#define KEEP_MACRO_NAME PREFIX "keep" -#define RELEASE_MACRO_NAME PREFIX "release" -#define SAVED_FONT_REG PREFIX "fnt" -#define SAVED_SIZE_REG PREFIX "sz" -#define SAVED_FILL_REG PREFIX "fll" -#define SAVED_INDENT_REG PREFIX "ind" -#define SAVED_CENTER_REG PREFIX "cent" -#define TABLE_DIVERSION_NAME PREFIX "table" -#define TABLE_DIVERSION_FLAG_REG PREFIX "tflag" -#define TABLE_KEEP_MACRO_NAME PREFIX "tkeep" -#define TABLE_RELEASE_MACRO_NAME PREFIX "trelease" -#define NEEDED_REG PREFIX "needed" -#define REPEATED_MARK_MACRO PREFIX "rmk" -#define REPEATED_VPT_MACRO PREFIX "rvpt" -#define SUPPRESS_BOTTOM_REG PREFIX "supbot" -#define SAVED_DN_REG PREFIX "dn" - -// this must be one character -#define COMPATIBLE_REG PREFIX "c" - -#define BLOCK_WIDTH_PREFIX PREFIX "tbw" -#define BLOCK_DIVERSION_PREFIX PREFIX "tbd" -#define BLOCK_HEIGHT_PREFIX PREFIX "tbh" -#define SPAN_WIDTH_PREFIX PREFIX "w" -#define SPAN_LEFT_NUMERIC_WIDTH_PREFIX PREFIX "lnw" -#define SPAN_RIGHT_NUMERIC_WIDTH_PREFIX PREFIX "rnw" -#define SPAN_ALPHABETIC_WIDTH_PREFIX PREFIX "aw" -#define COLUMN_SEPARATION_PREFIX PREFIX "cs" -#define ROW_START_PREFIX PREFIX "rs" -#define COLUMN_START_PREFIX PREFIX "cl" -#define COLUMN_END_PREFIX PREFIX "ce" -#define COLUMN_DIVIDE_PREFIX PREFIX "cd" -#define ROW_TOP_PREFIX PREFIX "rt" - -string block_width_reg(int r, int c); -string block_diversion_name(int r, int c); -string block_height_reg(int r, int c); -string span_width_reg(int start_col, int end_col); -string span_left_numeric_width_reg(int start_col, int end_col); -string span_right_numeric_width_reg(int start_col, int end_col); -string span_alphabetic_width_reg(int start_col, int end_col); -string column_separation_reg(int col); -string row_start_reg(int r); -string column_start_reg(int c); -string column_end_reg(int c); -string column_divide_reg(int c); -string row_top_reg(int r); - -void set_inline_modifier(const entry_modifier *); -void restore_inline_modifier(const entry_modifier *m); -void set_modifier(const entry_modifier *); -int find_decimal_point(const char *s, char decimal_point_char, - const char *delim); - -string an_empty_string; -int location_force_filename = 0; - -void printfs(const char *, - const string &arg1 = an_empty_string, - const string &arg2 = an_empty_string, - const string &arg3 = an_empty_string, - const string &arg4 = an_empty_string, - const string &arg5 = an_empty_string); - -void prints(const string &); - -inline void prints(char c) -{ - putchar(c); -} - -inline void prints(const char *s) -{ - fputs(s, stdout); -} - -void prints(const string &s) -{ - if (!s.empty()) - fwrite(s.contents(), 1, s.length(), stdout); -} - -struct horizontal_span { - horizontal_span *next; - short start_col; - short end_col; - horizontal_span(int, int, horizontal_span *); -}; - -struct single_line_entry; -struct double_line_entry; -struct simple_entry; - -class table_entry { -friend class table; - table_entry *next; - int input_lineno; - const char *input_filename; -protected: - int start_row; - int end_row; - short start_col; - short end_col; - const entry_modifier *mod; -public: - void set_location(); - table_entry(const entry_modifier *); - virtual ~table_entry(); - virtual int divert(int ncols, const string *mw, int *sep); - virtual void do_width(); - virtual void do_depth(); - virtual void print() = 0; - virtual void position_vertically() = 0; - virtual single_line_entry *to_single_line_entry(); - virtual double_line_entry *to_double_line_entry(); - virtual simple_entry *to_simple_entry(); - virtual int line_type(); - virtual void note_double_vrule_on_right(int); - virtual void note_double_vrule_on_left(int); -}; - -class simple_entry : public table_entry { -public: - simple_entry(const entry_modifier *); - void print(); - void position_vertically(); - simple_entry *to_simple_entry(); - virtual void add_tab(); - virtual void simple_print(int); -}; - -class empty_entry : public simple_entry { -public: - empty_entry(const entry_modifier *); - int line_type(); -}; - -class text_entry : public simple_entry { -protected: - char *contents; - void print_contents(); -public: - text_entry(char *, const entry_modifier *); - ~text_entry(); -}; - -void text_entry::print_contents() -{ - set_inline_modifier(mod); - prints(contents); - restore_inline_modifier(mod); -} - -class repeated_char_entry : public text_entry { -public: - repeated_char_entry(char *s, const entry_modifier *m); - void simple_print(int); -}; - -class simple_text_entry : public text_entry { -public: - simple_text_entry(char *s, const entry_modifier *m); - void do_width(); -}; - -class left_text_entry : public simple_text_entry { -public: - left_text_entry(char *s, const entry_modifier *m); - void simple_print(int); - void add_tab(); -}; - -class right_text_entry : public simple_text_entry { -public: - right_text_entry(char *s, const entry_modifier *m); - void simple_print(int); - void add_tab(); -}; - -class center_text_entry : public simple_text_entry { -public: - center_text_entry(char *s, const entry_modifier *m); - void simple_print(int); - void add_tab(); -}; - -class numeric_text_entry : public text_entry { - int dot_pos; -public: - numeric_text_entry(char *s, const entry_modifier *m, int pos); - void do_width(); - void simple_print(int); -}; - -class alphabetic_text_entry : public text_entry { -public: - alphabetic_text_entry(char *s, const entry_modifier *m); - void do_width(); - void simple_print(int); - void add_tab(); -}; - -class line_entry : public simple_entry { -protected: - char double_vrule_on_right; - char double_vrule_on_left; -public: - line_entry(const entry_modifier *); - void note_double_vrule_on_right(int); - void note_double_vrule_on_left(int); - void simple_print(int) = 0; -}; - -class single_line_entry : public line_entry { -public: - single_line_entry(const entry_modifier *m); - void simple_print(int); - single_line_entry *to_single_line_entry(); - int line_type(); -}; - -class double_line_entry : public line_entry { -public: - double_line_entry(const entry_modifier *m); - void simple_print(int); - double_line_entry *to_double_line_entry(); - int line_type(); -}; - -class short_line_entry : public simple_entry { -public: - short_line_entry(const entry_modifier *m); - void simple_print(int); - int line_type(); -}; - -class short_double_line_entry : public simple_entry { -public: - short_double_line_entry(const entry_modifier *m); - void simple_print(int); - int line_type(); -}; - -class block_entry : public table_entry { - char *contents; -protected: - void do_divert(int alphabetic, int ncols, const string *mw, int *sep); -public: - block_entry(char *s, const entry_modifier *m); - ~block_entry(); - int divert(int ncols, const string *mw, int *sep); - void do_width(); - void do_depth(); - void position_vertically(); - void print() = 0; -}; - -class left_block_entry : public block_entry { -public: - left_block_entry(char *s, const entry_modifier *m); - void print(); -}; - -class right_block_entry : public block_entry { -public: - right_block_entry(char *s, const entry_modifier *m); - void print(); -}; - -class center_block_entry : public block_entry { -public: - center_block_entry(char *s, const entry_modifier *m); - void print(); -}; - -class alphabetic_block_entry : public block_entry { -public: - alphabetic_block_entry(char *s, const entry_modifier *m); - void print(); - int divert(int ncols, const string *mw, int *sep); -}; - -table_entry::table_entry(const entry_modifier *m) -: next(0), input_lineno(-1), input_filename(0), - start_row(-1), end_row(-1), start_col(-1), end_col(-1), mod(m) -{ -} - -table_entry::~table_entry() -{ -} - -int table_entry::divert(int, const string *, int *) -{ - return 0; -} - -void table_entry::do_width() -{ -} - -single_line_entry *table_entry::to_single_line_entry() -{ - return 0; -} - -double_line_entry *table_entry::to_double_line_entry() -{ - return 0; -} - -simple_entry *table_entry::to_simple_entry() -{ - return 0; -} - -void table_entry::do_depth() -{ -} - -void table_entry::set_location() -{ - set_troff_location(input_filename, input_lineno); -} - -int table_entry::line_type() -{ - return -1; -} - -void table_entry::note_double_vrule_on_right(int) -{ -} - -void table_entry::note_double_vrule_on_left(int) -{ -} - -simple_entry::simple_entry(const entry_modifier *m) : table_entry(m) -{ -} - -void simple_entry::add_tab() -{ - // do nothing -} - -void simple_entry::simple_print(int) -{ - // do nothing -} - -void simple_entry::position_vertically() -{ - if (start_row != end_row) - switch (mod->vertical_alignment) { - case entry_modifier::TOP: - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - break; - case entry_modifier::CENTER: - // Peform the motion in two stages so that the center is rounded - // vertically upwards even if net vertical motion is upwards. - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-1v/2u\n", - row_start_reg(start_row)); - break; - case entry_modifier::BOTTOM: - printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-1v\n", - row_start_reg(start_row)); - break; - default: - assert(0); - } -} - -void simple_entry::print() -{ - prints(".ta"); - add_tab(); - prints('\n'); - set_location(); - prints("\\&"); - simple_print(0); - prints('\n'); -} - -simple_entry *simple_entry::to_simple_entry() -{ - return this; -} - -empty_entry::empty_entry(const entry_modifier *m) -: simple_entry(m) -{ -} - -int empty_entry::line_type() -{ - return 0; -} - -text_entry::text_entry(char *s, const entry_modifier *m) -: simple_entry(m), contents(s) -{ -} - -text_entry::~text_entry() -{ - a_delete contents; -} - - -repeated_char_entry::repeated_char_entry(char *s, const entry_modifier *m) -: text_entry(s, m) -{ -} - -void repeated_char_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - set_inline_modifier(mod); - printfs("\\l" DELIMITER_CHAR "\\n[%1]u\\&", - span_width_reg(start_col, end_col)); - prints(contents); - prints(DELIMITER_CHAR); - restore_inline_modifier(mod); -} - -simple_text_entry::simple_text_entry(char *s, const entry_modifier *m) -: text_entry(s, m) -{ -} - -void simple_text_entry::do_width() -{ - set_location(); - printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, - span_width_reg(start_col, end_col)); - print_contents(); - prints(DELIMITER_CHAR "\n"); -} - -left_text_entry::left_text_entry(char *s, const entry_modifier *m) -: simple_text_entry(s, m) -{ -} - -void left_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - print_contents(); -} - -// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr. - -void left_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -right_text_entry::right_text_entry(char *s, const entry_modifier *m) -: simple_text_entry(s, m) -{ -} - -void right_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - prints("\002\003"); - print_contents(); - prints("\002"); -} - -void right_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -center_text_entry::center_text_entry(char *s, const entry_modifier *m) -: simple_text_entry(s, m) -{ -} - -void center_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - prints("\002\003"); - print_contents(); - prints("\003\002"); -} - -void center_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -numeric_text_entry::numeric_text_entry(char *s, const entry_modifier *m, int pos) -: text_entry(s, m), dot_pos(pos) -{ -} - -void numeric_text_entry::do_width() -{ - if (dot_pos != 0) { - set_location(); - printfs(".nr %1 0\\w" DELIMITER_CHAR, - block_width_reg(start_row, start_col)); - set_inline_modifier(mod); - for (int i = 0; i < dot_pos; i++) - prints(contents[i]); - restore_inline_modifier(mod); - prints(DELIMITER_CHAR "\n"); - printfs(".nr %1 \\n[%1]>?\\n[%2]\n", - span_left_numeric_width_reg(start_col, end_col), - block_width_reg(start_row, start_col)); - } - else - printfs(".nr %1 0\n", block_width_reg(start_row, start_col)); - if (contents[dot_pos] != '\0') { - set_location(); - printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, - span_right_numeric_width_reg(start_col, end_col)); - set_inline_modifier(mod); - prints(contents + dot_pos); - restore_inline_modifier(mod); - prints(DELIMITER_CHAR "\n"); - } -} - -void numeric_text_entry::simple_print(int) -{ - printfs("\\h'|(\\n[%1]u-\\n[%2]u-\\n[%3]u/2u+\\n[%2]u+\\n[%4]u-\\n[%5]u)'", - span_width_reg(start_col, end_col), - span_left_numeric_width_reg(start_col, end_col), - span_right_numeric_width_reg(start_col, end_col), - column_start_reg(start_col), - block_width_reg(start_row, start_col)); - print_contents(); -} - -alphabetic_text_entry::alphabetic_text_entry(char *s, const entry_modifier *m) -: text_entry(s, m) -{ -} - -void alphabetic_text_entry::do_width() -{ - set_location(); - printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, - span_alphabetic_width_reg(start_col, end_col)); - print_contents(); - prints(DELIMITER_CHAR "\n"); -} - -void alphabetic_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - printfs("\\h'\\n[%1]u-\\n[%2]u/2u'", - span_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col)); - print_contents(); -} - -// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr. - -void alphabetic_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -block_entry::block_entry(char *s, const entry_modifier *m) -: table_entry(m), contents(s) -{ -} - -block_entry::~block_entry() -{ - a_delete contents; -} - -void block_entry::position_vertically() -{ - if (start_row != end_row) - switch(mod->vertical_alignment) { - case entry_modifier::TOP: - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - break; - case entry_modifier::CENTER: - // Peform the motion in two stages so that the center is rounded - // vertically upwards even if net vertical motion is upwards. - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u/2u\n", - row_start_reg(start_row), - block_height_reg(start_row, start_col)); - break; - case entry_modifier::BOTTOM: - printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u\n", - row_start_reg(start_row), - block_height_reg(start_row, start_col)); - break; - default: - assert(0); - } - if (mod->stagger) - prints(".sp -.5v\n"); -} - -int block_entry::divert(int ncols, const string *mw, int *sep) -{ - do_divert(0, ncols, mw, sep); - return 1; -} - -void block_entry::do_divert(int alphabetic, int ncols, const string *mw, - int *sep) -{ - printfs(".di %1\n", block_diversion_name(start_row, start_col)); - prints(".if \\n[" SAVED_FILL_REG "] .fi\n" - ".in 0\n"); - prints(".ll "); - int i; - for (i = start_col; i <= end_col; i++) - if (mw[i].empty()) - break; - if (i > end_col) { - // Every column spanned by this entry has a minimum width. - for (int j = start_col; j <= end_col; j++) { - if (j > start_col) { - if (sep) - printfs("+%1n", as_string(sep[j - 1])); - prints('+'); - } - printfs("(n;%1)", mw[j]); - } - printfs(">?\\n[%1]u", span_width_reg(start_col, end_col)); - } - else - printfs("(u;\\n[%1]>?(\\n[.l]*%2/%3))", - span_width_reg(start_col, end_col), - as_string(end_col - start_col + 1), - as_string(ncols + 1)); - if (alphabetic) - prints("-2n"); - prints("\n"); - set_modifier(mod); - prints(".cp \\n(" COMPATIBLE_REG "\n"); - set_location(); - prints(contents); - prints(".br\n.di\n.cp 0\n"); - if (!mod->zero_width) { - if (alphabetic) { - printfs(".nr %1 \\n[%1]>?(\\n[dl]+2n)\n", - span_width_reg(start_col, end_col)); - printfs(".nr %1 \\n[%1]>?\\n[dl]\n", - span_alphabetic_width_reg(start_col, end_col)); - } - else - printfs(".nr %1 \\n[%1]>?\\n[dl]\n", span_width_reg(start_col, end_col)); - } - printfs(".nr %1 \\n[dn]\n", block_height_reg(start_row, start_col)); - printfs(".nr %1 \\n[dl]\n", block_width_reg(start_row, start_col)); - prints("." RESET_MACRO_NAME "\n" - ".in \\n[" SAVED_INDENT_REG "]u\n" - ".nf\n"); - // the block might have contained .lf commands - location_force_filename = 1; -} - -void block_entry::do_width() -{ - // do nothing; the action happens in divert -} - -void block_entry::do_depth() -{ - printfs(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?(\\n[%1]+\\n[%2])\n", - row_start_reg(start_row), - block_height_reg(start_row, start_col)); -} - -left_block_entry::left_block_entry(char *s, const entry_modifier *m) -: block_entry(s, m) -{ -} - -void left_block_entry::print() -{ - printfs(".in +\\n[%1]u\n", column_start_reg(start_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - - - -right_block_entry::right_block_entry(char *s, const entry_modifier *m) -: block_entry(s, m) -{ -} - -void right_block_entry::print() -{ - printfs(".in +\\n[%1]u+\\n[%2]u-\\n[%3]u\n", - column_start_reg(start_col), - span_width_reg(start_col, end_col), - block_width_reg(start_row, start_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -center_block_entry::center_block_entry(char *s, const entry_modifier *m) -: block_entry(s, m) -{ -} - -void center_block_entry::print() -{ - printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n", - column_start_reg(start_col), - span_width_reg(start_col, end_col), - block_width_reg(start_row, start_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -alphabetic_block_entry::alphabetic_block_entry(char *s, - const entry_modifier *m) -: block_entry(s, m) -{ -} - -int alphabetic_block_entry::divert(int ncols, const string *mw, int *sep) -{ - do_divert(1, ncols, mw, sep); - return 1; -} - -void alphabetic_block_entry::print() -{ - printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n", - column_start_reg(start_col), - span_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -line_entry::line_entry(const entry_modifier *m) -: simple_entry(m), double_vrule_on_right(0), double_vrule_on_left(0) -{ -} - -void line_entry::note_double_vrule_on_right(int is_corner) -{ - double_vrule_on_right = is_corner ? 1 : 2; -} - -void line_entry::note_double_vrule_on_left(int is_corner) -{ - double_vrule_on_left = is_corner ? 1 : 2; -} - - -single_line_entry::single_line_entry(const entry_modifier *m) -: line_entry(m) -{ -} - -int single_line_entry::line_type() -{ - return 1; -} - -void single_line_entry::simple_print(int dont_move) -{ - printfs("\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (double_vrule_on_left) { - prints(double_vrule_on_left == 1 ? "-" : "+"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints("'"); - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\s[\\n[" LINESIZE_REG "]]" "\\D'l |\\n[%1]u", - column_divide_reg(end_col+1)); - if (double_vrule_on_right) { - prints(double_vrule_on_left == 1 ? "+" : "-"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints("0'\\s0"); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); -} - -single_line_entry *single_line_entry::to_single_line_entry() -{ - return this; -} - -double_line_entry::double_line_entry(const entry_modifier *m) -: line_entry(m) -{ -} - -int double_line_entry::line_type() -{ - return 2; -} - -void double_line_entry::simple_print(int dont_move) -{ - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (double_vrule_on_left) { - prints(double_vrule_on_left == 1 ? "-" : "+"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints("'"); - printfs("\\v'-" HALF_DOUBLE_LINE_SEP "'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\D'l |\\n[%1]u", - column_divide_reg(end_col+1)); - if (double_vrule_on_right) - prints("-" HALF_DOUBLE_LINE_SEP); - prints(" 0'"); - printfs("\\v'" DOUBLE_LINE_SEP "'" - "\\D'l |\\n[%1]u", - column_divide_reg(start_col)); - if (double_vrule_on_right) { - prints(double_vrule_on_left == 1 ? "+" : "-"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints(" 0'"); - prints("\\s0" - "\\v'-" HALF_DOUBLE_LINE_SEP "'"); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); -} - -double_line_entry *double_line_entry::to_double_line_entry() -{ - return this; -} - -short_line_entry::short_line_entry(const entry_modifier *m) -: simple_entry(m) -{ -} - -int short_line_entry::line_type() -{ - return 1; -} - -void short_line_entry::simple_print(int dont_move) -{ - if (mod->stagger) - prints("\\v'-.5v'"); - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - printfs("\\s[\\n[" LINESIZE_REG "]]" - "\\D'l \\n[%1]u 0'" - "\\s0", - span_width_reg(start_col, end_col)); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); - if (mod->stagger) - prints("\\v'.5v'"); -} - -short_double_line_entry::short_double_line_entry(const entry_modifier *m) -: simple_entry(m) -{ -} - -int short_double_line_entry::line_type() -{ - return 2; -} - -void short_double_line_entry::simple_print(int dont_move) -{ - if (mod->stagger) - prints("\\v'-.5v'"); - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\h'|\\n[%2]u'" - "\\v'-" HALF_DOUBLE_LINE_SEP "'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\D'l \\n[%1]u 0'" - "\\v'" DOUBLE_LINE_SEP "'" - "\\D'l |\\n[%2]u 0'" - "\\s0" - "\\v'-" HALF_DOUBLE_LINE_SEP "'", - span_width_reg(start_col, end_col), - column_start_reg(start_col)); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); - if (mod->stagger) - prints("\\v'.5v'"); -} - -void set_modifier(const entry_modifier *m) -{ - if (!m->font.empty()) - printfs(".ft %1\n", m->font); - if (m->point_size.val != 0) { - prints(".ps "); - if (m->point_size.inc > 0) - prints('+'); - else if (m->point_size.inc < 0) - prints('-'); - printfs("%1\n", as_string(m->point_size.val)); - } - if (m->vertical_spacing.val != 0) { - prints(".vs "); - if (m->vertical_spacing.inc > 0) - prints('+'); - else if (m->vertical_spacing.inc < 0) - prints('-'); - printfs("%1\n", as_string(m->vertical_spacing.val)); - } -} - -void set_inline_modifier(const entry_modifier *m) -{ - if (!m->font.empty()) - printfs("\\f[%1]", m->font); - if (m->point_size.val != 0) { - prints("\\s["); - if (m->point_size.inc > 0) - prints('+'); - else if (m->point_size.inc < 0) - prints('-'); - printfs("%1]", as_string(m->point_size.val)); - } - if (m->stagger) - prints("\\v'-.5v'"); -} - -void restore_inline_modifier(const entry_modifier *m) -{ - if (!m->font.empty()) - prints("\\f[\\n[" SAVED_FONT_REG "]]"); - if (m->point_size.val != 0) - prints("\\s[\\n[" SAVED_SIZE_REG "]]"); - if (m->stagger) - prints("\\v'.5v'"); -} - - -struct stuff { - stuff *next; - int row; // occurs before row `row' - char printed; // has it been printed? - - stuff(int); - virtual void print(table *) = 0; - virtual ~stuff(); - virtual int is_single_line() { return 0; }; - virtual int is_double_line() { return 0; }; -}; - -stuff::stuff(int r) : next(0), row(r), printed(0) -{ -} - -stuff::~stuff() -{ -} - -struct text_stuff : public stuff { - string contents; - const char *filename; - int lineno; - - text_stuff(const string &, int r, const char *fn, int ln); - ~text_stuff(); - void print(table *); -}; - - -text_stuff::text_stuff(const string &s, int r, const char *fn, int ln) -: stuff(r), contents(s), filename(fn), lineno(ln) -{ -} - -text_stuff::~text_stuff() -{ -} - -void text_stuff::print(table *) -{ - printed = 1; - prints(".cp \\n(" COMPATIBLE_REG "\n"); - set_troff_location(filename, lineno); - prints(contents); - prints(".cp 0\n"); - location_force_filename = 1; // it might have been a .lf command -} - -struct single_hline_stuff : public stuff { - single_hline_stuff(int r); - void print(table *); - int is_single_line(); -}; - -single_hline_stuff::single_hline_stuff(int r) : stuff(r) -{ -} - -void single_hline_stuff::print(table *tbl) -{ - printed = 1; - tbl->print_single_hline(row); -} - -int single_hline_stuff::is_single_line() -{ - return 1; -} - -struct double_hline_stuff : stuff { - double_hline_stuff(int r); - void print(table *); - int is_double_line(); -}; - -double_hline_stuff::double_hline_stuff(int r) : stuff(r) -{ -} - -void double_hline_stuff::print(table *tbl) -{ - printed = 1; - tbl->print_double_hline(row); -} - -int double_hline_stuff::is_double_line() -{ - return 1; -} - -struct vertical_rule { - vertical_rule *next; - int start_row; - int end_row; - short col; - char is_double; - string top_adjust; - string bot_adjust; - - vertical_rule(int sr, int er, int c, int dbl, vertical_rule *); - ~vertical_rule(); - void contribute_to_bottom_macro(table *); - void print(); -}; - -vertical_rule::vertical_rule(int sr, int er, int c, int dbl, vertical_rule *p) -: next(p), start_row(sr), end_row(er), col(c), is_double(dbl) -{ -} - -vertical_rule::~vertical_rule() -{ -} - -void vertical_rule::contribute_to_bottom_macro(table *tbl) -{ - printfs(".if \\n[" CURRENT_ROW_REG "]>=%1", - as_string(start_row)); - if (end_row != tbl->get_nrows() - 1) - printfs("&(\\n[" CURRENT_ROW_REG "]<%1)", - as_string(end_row)); - prints(" \\{"); - printfs(".if %1<=\\n[" LAST_PASSED_ROW_REG "] .nr %2 \\n[#T]\n", - as_string(start_row), - row_top_reg(start_row)); - const char *offset_table[3]; - if (is_double) { - offset_table[0] = "-" HALF_DOUBLE_LINE_SEP; - offset_table[1] = "+" HALF_DOUBLE_LINE_SEP; - offset_table[2] = 0; - } - else { - offset_table[0] = ""; - offset_table[1] = 0; - } - for (const char **offsetp = offset_table; *offsetp; offsetp++) { - prints(".sp -1\n" - "\\v'" BODY_DEPTH); - if (!bot_adjust.empty()) - printfs("+%1", bot_adjust); - prints("'"); - printfs("\\h'\\n[%1]u%3'\\s[\\n[" LINESIZE_REG "]]\\D'l 0 |\\n[%2]u-1v", - column_divide_reg(col), - row_top_reg(start_row), - *offsetp); - if (!bot_adjust.empty()) - printfs("-(%1)", bot_adjust); - // don't perform the top adjustment if the top is actually #T - if (!top_adjust.empty()) - printfs("+((%1)*(%2>\\n[" LAST_PASSED_ROW_REG "]))", - top_adjust, - as_string(start_row)); - prints("'\\s0\n"); - } - prints(".\\}\n"); -} - -void vertical_rule::print() -{ - printfs("\\*[" TRANSPARENT_STRING_NAME "]" - ".if %1<=\\*[" QUOTE_STRING_NAME "]\\n[" LAST_PASSED_ROW_REG "] " - ".nr %2 \\*[" QUOTE_STRING_NAME "]\\n[#T]\n", - as_string(start_row), - row_top_reg(start_row)); - const char *offset_table[3]; - if (is_double) { - offset_table[0] = "-" HALF_DOUBLE_LINE_SEP; - offset_table[1] = "+" HALF_DOUBLE_LINE_SEP; - offset_table[2] = 0; - } - else { - offset_table[0] = ""; - offset_table[1] = 0; - } - for (const char **offsetp = offset_table; *offsetp; offsetp++) { - prints("\\*[" TRANSPARENT_STRING_NAME "].sp -1\n" - "\\*[" TRANSPARENT_STRING_NAME "]\\v'" BODY_DEPTH); - if (!bot_adjust.empty()) - printfs("+%1", bot_adjust); - prints("'"); - printfs("\\h'\\n[%1]u%3'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\D'l 0 |\\*[" QUOTE_STRING_NAME "]\\n[%2]u-1v", - column_divide_reg(col), - row_top_reg(start_row), - *offsetp); - if (!bot_adjust.empty()) - printfs("-(%1)", bot_adjust); - // don't perform the top adjustment if the top is actually #T - if (!top_adjust.empty()) - printfs("+((%1)*(%2>\\*[" QUOTE_STRING_NAME "]\\n[" - LAST_PASSED_ROW_REG "]))", - top_adjust, - as_string(start_row)); - prints("'" - "\\s0\n"); - } -} - -table::table(int nc, unsigned f, int ls, char dpc) -: flags(f), nrows(0), ncolumns(nc), linesize(ls), decimal_point_char(dpc), - vrule_list(0), stuff_list(0), span_list(0), - entry_list(0), entry_list_tailp(&entry_list), entry(0), - vline(0), row_is_all_lines(0), left_separation(0), right_separation(0), - allocated_rows(0) -{ - minimum_width = new string[ncolumns]; - column_separation = ncolumns > 1 ? new int[ncolumns - 1] : 0; - equal = new char[ncolumns]; - int i; - for (i = 0; i < ncolumns; i++) - equal[i] = 0; - for (i = 0; i < ncolumns-1; i++) - column_separation[i] = DEFAULT_COLUMN_SEPARATION; - delim[0] = delim[1] = '\0'; -} - -table::~table() -{ - for (int i = 0; i < nrows; i++) { - a_delete entry[i]; - a_delete vline[i]; - } - a_delete entry; - a_delete vline; - while (entry_list) { - table_entry *tem = entry_list; - entry_list = entry_list->next; - delete tem; - } - ad_delete(ncolumns) minimum_width; - a_delete column_separation; - a_delete equal; - while (stuff_list) { - stuff *tem = stuff_list; - stuff_list = stuff_list->next; - delete tem; - } - while (vrule_list) { - vertical_rule *tem = vrule_list; - vrule_list = vrule_list->next; - delete tem; - } - a_delete row_is_all_lines; - while (span_list) { - horizontal_span *tem = span_list; - span_list = span_list->next; - delete tem; - } -} - -void table::set_delim(char c1, char c2) -{ - delim[0] = c1; - delim[1] = c2; -} - -void table::set_minimum_width(int c, const string &w) -{ - assert(c >= 0 && c < ncolumns); - minimum_width[c] = w; -} - -void table::set_column_separation(int c, int n) -{ - assert(c >= 0 && c < ncolumns - 1); - column_separation[c] = n; -} - -void table::set_equal_column(int c) -{ - assert(c >= 0 && c < ncolumns); - equal[c] = 1; -} - -void table::add_stuff(stuff *p) -{ - stuff **pp; - for (pp = &stuff_list; *pp; pp = &(*pp)->next) - ; - *pp = p; -} - -void table::add_text_line(int r, const string &s, const char *filename, int lineno) -{ - add_stuff(new text_stuff(s, r, filename, lineno)); -} - -void table::add_single_hline(int r) -{ - add_stuff(new single_hline_stuff(r)); -} - -void table::add_double_hline(int r) -{ - add_stuff(new double_hline_stuff(r)); -} - -void table::allocate(int r) -{ - if (r >= nrows) { - typedef table_entry **PPtable_entry; // work around g++ 1.36.1 bug - if (r >= allocated_rows) { - if (allocated_rows == 0) { - allocated_rows = 16; - if (allocated_rows <= r) - allocated_rows = r + 1; - entry = new PPtable_entry[allocated_rows]; - vline = new char*[allocated_rows]; - } - else { - table_entry ***old_entry = entry; - int old_allocated_rows = allocated_rows; - allocated_rows *= 2; - if (allocated_rows <= r) - allocated_rows = r + 1; - entry = new PPtable_entry[allocated_rows]; - memcpy(entry, old_entry, sizeof(table_entry**)*old_allocated_rows); - a_delete old_entry; - char **old_vline = vline; - vline = new char*[allocated_rows]; - memcpy(vline, old_vline, sizeof(char*)*old_allocated_rows); - a_delete old_vline; - } - } - assert(allocated_rows > r); - while (nrows <= r) { - entry[nrows] = new table_entry*[ncolumns]; - int i; - for (i = 0; i < ncolumns; i++) - entry[nrows][i] = 0; - vline[nrows] = new char[ncolumns+1]; - for (i = 0; i < ncolumns+1; i++) - vline[nrows][i] = 0; - nrows++; - } - } -} - -void table::do_hspan(int r, int c) -{ - assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns); - if (c == 0) { - error("first column cannot be horizontally spanned"); - return; - } - table_entry *e = entry[r][c]; - if (e) { - assert(e->start_row <= r && r <= e->end_row - && e->start_col <= c && c <= e->end_col - && e->end_row - e->start_row > 0 - && e->end_col - e->start_col > 0); - return; - } - e = entry[r][c-1]; - // e can be 0 if we had an empty entry or an error - if (e == 0) - return; - if (e->start_row != r) { - /* - l l - ^ s */ - error("impossible horizontal span at row %1, column %2", r + 1, c + 1); - } - else { - e->end_col = c; - entry[r][c] = e; - } -} - -void table::do_vspan(int r, int c) -{ - assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns); - if (r == 0) { - error("first row cannot be vertically spanned"); - return; - } - table_entry *e = entry[r][c]; - if (e) { - assert(e->start_row <= r && r <= e->end_row - && e->start_col <= c && c <= e->end_col - && e->end_row - e->start_row > 0 - && e->end_col - e->start_col > 0); - return; - } - e = entry[r-1][c]; - // e can be 0 if we had an empty entry or an error - if (e == 0) - return; - if (e->start_col != c) { - /* l s - l ^ */ - error("impossible vertical span at row %1, column %2", r + 1, c + 1); - } - else { - for (int i = c; i <= e->end_col; i++) { - assert(entry[r][i] == 0); - entry[r][i] = e; - } - e->end_row = r; - } -} - -int find_decimal_point(const char *s, char decimal_point_char, - const char *delim) -{ - if (s == 0 || *s == '\0') - return -1; - const char *p; - int in_delim = 0; // is p within eqn delimiters? - // tbl recognises \& even within eqn delimiters; I don't - for (p = s; *p; p++) - if (in_delim) { - if (*p == delim[1]) - in_delim = 0; - } - else if (*p == delim[0]) - in_delim = 1; - else if (p[0] == '\\' && p[1] == '&') - return p - s; - int possible_pos = -1; - in_delim = 0; - for (p = s; *p; p++) - if (in_delim) { - if (*p == delim[1]) - in_delim = 0; - } - else if (*p == delim[0]) - in_delim = 1; - else if (p[0] == decimal_point_char && csdigit(p[1])) - possible_pos = p - s; - if (possible_pos >= 0) - return possible_pos; - in_delim = 0; - for (p = s; *p; p++) - if (in_delim) { - if (*p == delim[1]) - in_delim = 0; - } - else if (*p == delim[0]) - in_delim = 1; - else if (csdigit(*p)) - possible_pos = p + 1 - s; - return possible_pos; -} - -void table::add_entry(int r, int c, const string &str, const entry_format *f, - const char *fn, int ln) -{ - allocate(r); - table_entry *e = 0; - if (str == "\\_") { - e = new short_line_entry(f); - } - else if (str == "\\=") { - e = new short_double_line_entry(f); - } - else if (str == "_") { - single_line_entry *lefte; - if (c > 0 && entry[r][c-1] != 0 && - (lefte = entry[r][c-1]->to_single_line_entry()) != 0 - && lefte->start_row == r - && lefte->mod->stagger == f->stagger) { - lefte->end_col = c; - entry[r][c] = lefte; - } - else - e = new single_line_entry(f); - } - else if (str == "=") { - double_line_entry *lefte; - if (c > 0 && entry[r][c-1] != 0 && - (lefte = entry[r][c-1]->to_double_line_entry()) != 0 - && lefte->start_row == r - && lefte->mod->stagger == f->stagger) { - lefte->end_col = c; - entry[r][c] = lefte; - } - else - e = new double_line_entry(f); - } - else if (str == "\\^") { - do_vspan(r, c); - } - else if (str.length() > 2 && str[0] == '\\' && str[1] == 'R') { - if (str.search('\n') >= 0) - error_with_file_and_line(fn, ln, "bad repeated character"); - else { - char *s = str.substring(2, str.length() - 2).extract(); - e = new repeated_char_entry(s, f); - } - } - else { - int is_block = str.search('\n') >= 0; - char *s; - switch (f->type) { - case FORMAT_SPAN: - assert(str.empty()); - do_hspan(r, c); - break; - case FORMAT_LEFT: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new left_block_entry(s, f); - else - e = new left_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_CENTER: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new center_block_entry(s, f); - else - e = new center_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_RIGHT: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new right_block_entry(s, f); - else - e = new right_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_NUMERIC: - if (!str.empty()) { - s = str.extract(); - if (is_block) { - error_with_file_and_line(fn, ln, "can't have numeric text block"); - e = new left_block_entry(s, f); - } - else { - int pos = find_decimal_point(s, decimal_point_char, delim); - if (pos < 0) - e = new center_text_entry(s, f); - else - e = new numeric_text_entry(s, f, pos); - } - } - else - e = new empty_entry(f); - break; - case FORMAT_ALPHABETIC: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new alphabetic_block_entry(s, f); - else - e = new alphabetic_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_VSPAN: - do_vspan(r, c); - break; - case FORMAT_HLINE: - if (str.length() != 0) - error_with_file_and_line(fn, ln, - "non-empty data entry for `_' format ignored"); - e = new single_line_entry(f); - break; - case FORMAT_DOUBLE_HLINE: - if (str.length() != 0) - error_with_file_and_line(fn, ln, - "non-empty data entry for `=' format ignored"); - e = new double_line_entry(f); - break; - default: - assert(0); - } - } - if (e) { - table_entry *preve = entry[r][c]; - if (preve) { - /* c s - ^ l */ - error_with_file_and_line(fn, ln, "row %1, column %2 already spanned", - r + 1, c + 1); - delete e; - } - else { - e->input_lineno = ln; - e->input_filename = fn; - e->start_row = e->end_row = r; - e->start_col = e->end_col = c; - *entry_list_tailp = e; - entry_list_tailp = &e->next; - entry[r][c] = e; - } - } -} - -// add vertical lines for row r - -void table::add_vlines(int r, const char *v) -{ - allocate(r); - for (int i = 0; i < ncolumns+1; i++) - vline[r][i] = v[i]; -} - -void table::check() -{ - table_entry *p = entry_list; - int i, j; - while (p) { - for (i = p->start_row; i <= p->end_row; i++) - for (j = p->start_col; j <= p->end_col; j++) - assert(entry[i][j] == p); - p = p->next; - } -} - -void table::print() -{ - location_force_filename = 1; - check(); - init_output(); - determine_row_type(); - compute_widths(); - if (!(flags & CENTER)) - prints(".if \\n[" SAVED_CENTER_REG "] \\{"); - prints(".in +(u;\\n[.l]-\\n[.i]-\\n[TW]/2)\n" - ".nr " SAVED_INDENT_REG " \\n[.i]\n"); - if (!(flags & CENTER)) - prints(".\\}\n"); - build_vrule_list(); - define_bottom_macro(); - do_top(); - for (int i = 0; i < nrows; i++) - do_row(i); - do_bottom(); -} - -void table::determine_row_type() -{ - row_is_all_lines = new char[nrows]; - for (int i = 0; i < nrows; i++) { - int had_single = 0; - int had_double = 0; - int had_non_line = 0; - for (int c = 0; c < ncolumns; c++) { - table_entry *e = entry[i][c]; - if (e != 0) { - if (e->start_row == e->end_row) { - int t = e->line_type(); - switch (t) { - case -1: - had_non_line = 1; - break; - case 0: - // empty - break; - case 1: - had_single = 1; - break; - case 2: - had_double = 1; - break; - default: - assert(0); - } - if (had_non_line) - break; - } - c = e->end_col; - } - } - if (had_non_line) - row_is_all_lines[i] = 0; - else if (had_double) - row_is_all_lines[i] = 2; - else if (had_single) - row_is_all_lines[i] = 1; - else - row_is_all_lines[i] = 0; - } -} - - -void table::init_output() -{ - prints(".nr " COMPATIBLE_REG " \\n(.C\n" - ".cp 0\n"); - if (linesize > 0) - printfs(".nr " LINESIZE_REG " %1\n", as_string(linesize)); - else - prints(".nr " LINESIZE_REG " \\n[.s]\n"); - if (!(flags & CENTER)) - prints(".nr " SAVED_CENTER_REG " \\n[.ce]\n"); - prints(".de " RESET_MACRO_NAME "\n" - ".ft \\n[.f]\n" - ".ps \\n[.s]\n" - ".vs \\n[.v]u\n" - ".in \\n[.i]u\n" - ".ll \\n[.l]u\n" - ".ls \\n[.L]\n" - ".ad \\n[.j]\n" - ".ie \\n[.u] .fi\n" - ".el .nf\n" - ".ce \\n[.ce]\n" - "..\n" - ".nr " SAVED_INDENT_REG " \\n[.i]\n" - ".nr " SAVED_FONT_REG " \\n[.f]\n" - ".nr " SAVED_SIZE_REG " \\n[.s]\n" - ".nr " SAVED_FILL_REG " \\n[.u]\n" - ".nr T. 0\n" - ".nr " CURRENT_ROW_REG " 0-1\n" - ".nr " LAST_PASSED_ROW_REG " 0-1\n" - ".nr " SECTION_DIVERSION_FLAG_REG " 0\n" - ".ds " TRANSPARENT_STRING_NAME "\n" - ".ds " QUOTE_STRING_NAME "\n" - ".nr " NEED_BOTTOM_RULE_REG " 1\n" - ".nr " SUPPRESS_BOTTOM_REG " 0\n" - ".eo\n" - ".de " REPEATED_MARK_MACRO "\n" - ".mk \\$1\n" - ".if !'\\n(.z'' \\!." REPEATED_MARK_MACRO " \"\\$1\"\n" - "..\n" - ".de " REPEATED_VPT_MACRO "\n" - ".vpt \\$1\n" - ".if !'\\n(.z'' \\!." REPEATED_VPT_MACRO " \"\\$1\"\n" - "..\n"); - if (!(flags & NOKEEP)) - prints(".de " KEEP_MACRO_NAME "\n" - ".if '\\n[.z]'' \\{.ds " QUOTE_STRING_NAME " \\\\\n" - ".ds " TRANSPARENT_STRING_NAME " \\!\n" - ".di " SECTION_DIVERSION_NAME "\n" - ".nr " SECTION_DIVERSION_FLAG_REG " 1\n" - ".in 0\n" - ".\\}\n" - "..\n" - ".de " RELEASE_MACRO_NAME "\n" - ".if \\n[" SECTION_DIVERSION_FLAG_REG "] \\{" - ".di\n" - ".in \\n[" SAVED_INDENT_REG "]u\n" - ".nr " SAVED_DN_REG " \\n[dn]\n" - ".ds " QUOTE_STRING_NAME "\n" - ".ds " TRANSPARENT_STRING_NAME "\n" - ".nr " SECTION_DIVERSION_FLAG_REG " 0\n" - ".if \\n[.t]<=\\n[dn] \\{" - ".nr T. 1\n" - ".T#\n" - ".nr " SUPPRESS_BOTTOM_REG " 1\n" - ".sp \\n[.t]u\n" - ".nr " SUPPRESS_BOTTOM_REG " 0\n" - ".mk #T\n" - ".\\}\n" - ".if \\n[.t]<=\\n[" SAVED_DN_REG "] " - /* Since we turn off traps, it won't get into an infinite loop - when we try and print it; it will just go off the bottom of the - page. */ - ".tm warning: page \\n%: table text block will not fit on one page\n" - ".nf\n" - ".ls 1\n" - "." SECTION_DIVERSION_NAME "\n" - ".ls\n" - ".rm " SECTION_DIVERSION_NAME "\n" - ".\\}\n" - "..\n" - ".nr " TABLE_DIVERSION_FLAG_REG " 0\n" - ".de " TABLE_KEEP_MACRO_NAME "\n" - ".if '\\n[.z]'' \\{" - ".di " TABLE_DIVERSION_NAME "\n" - ".nr " TABLE_DIVERSION_FLAG_REG " 1\n" - ".\\}\n" - "..\n" - ".de " TABLE_RELEASE_MACRO_NAME "\n" - ".if \\n[" TABLE_DIVERSION_FLAG_REG "] \\{.br\n" - ".di\n" - ".nr " SAVED_DN_REG " \\n[dn]\n" - ".ne \\n[dn]u+\\n[.V]u\n" - ".ie \\n[.t]<=\\n[" SAVED_DN_REG "] " - ".tm error: page \\n%: table will not fit on one page; use .TS H/.TH with a supporting macro package\n" - ".el \\{" - ".in 0\n" - ".ls 1\n" - ".nf\n" - "." TABLE_DIVERSION_NAME "\n" - ".\\}\n" - ".rm " TABLE_DIVERSION_NAME "\n" - ".\\}\n" - "..\n"); - prints(".ec\n" - ".ce 0\n" - ".nf\n"); -} - -string block_width_reg(int r, int c) -{ - static char name[sizeof(BLOCK_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, BLOCK_WIDTH_PREFIX "%d,%d", r, c); - return string(name); -} - -string block_diversion_name(int r, int c) -{ - static char name[sizeof(BLOCK_DIVERSION_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, BLOCK_DIVERSION_PREFIX "%d,%d", r, c); - return string(name); -} - -string block_height_reg(int r, int c) -{ - static char name[sizeof(BLOCK_HEIGHT_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, BLOCK_HEIGHT_PREFIX "%d,%d", r, c); - return string(name); -} - -string span_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string span_left_numeric_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_LEFT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_LEFT_NUMERIC_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string span_right_numeric_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_RIGHT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_RIGHT_NUMERIC_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string span_alphabetic_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_ALPHABETIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_ALPHABETIC_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - - -string column_separation_reg(int col) -{ - static char name[sizeof(COLUMN_SEPARATION_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_SEPARATION_PREFIX "%d", col); - return string(name); -} - -string row_start_reg(int row) -{ - static char name[sizeof(ROW_START_PREFIX)+INT_DIGITS]; - sprintf(name, ROW_START_PREFIX "%d", row); - return string(name); -} - -string column_start_reg(int col) -{ - static char name[sizeof(COLUMN_START_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_START_PREFIX "%d", col); - return string(name); -} - -string column_end_reg(int col) -{ - static char name[sizeof(COLUMN_END_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_END_PREFIX "%d", col); - return string(name); -} - -string column_divide_reg(int col) -{ - static char name[sizeof(COLUMN_DIVIDE_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_DIVIDE_PREFIX "%d", col); - return string(name); -} - -string row_top_reg(int row) -{ - static char name[sizeof(ROW_TOP_PREFIX)+INT_DIGITS]; - sprintf(name, ROW_TOP_PREFIX "%d", row); - return string(name); -} - -void init_span_reg(int start_col, int end_col) -{ - printfs(".nr %1 \\n(.H\n.nr %2 0\n.nr %3 0\n.nr %4 0\n", - span_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col), - span_left_numeric_width_reg(start_col, end_col), - span_right_numeric_width_reg(start_col, end_col)); -} - -void compute_span_width(int start_col, int end_col) -{ - printfs(".nr %1 \\n[%1]>?(\\n[%2]+\\n[%3])\n" - ".if \\n[%4] .nr %1 \\n[%1]>?(\\n[%4]+2n)\n", - span_width_reg(start_col, end_col), - span_left_numeric_width_reg(start_col, end_col), - span_right_numeric_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col)); - -} - -// Increase the widths of columns so that the width of any spanning entry -// is no greater than the sum of the widths of the columns that it spans. -// Ensure that the widths of columns remain equal. - -void table::divide_span(int start_col, int end_col) -{ - assert(end_col > start_col); - printfs(".nr " NEEDED_REG " \\n[%1]-(\\n[%2]", - span_width_reg(start_col, end_col), - span_width_reg(start_col, start_col)); - int i; - for (i = start_col + 1; i <= end_col; i++) { - // The column separation may shrink with the expand option. - if (!(flags & EXPAND)) - printfs("+%1n", as_string(column_separation[i - 1])); - printfs("+\\n[%1]", span_width_reg(i, i)); - } - prints(")\n"); - printfs(".nr " NEEDED_REG " \\n[" NEEDED_REG "]/%1\n", - as_string(end_col - start_col + 1)); - prints(".if \\n[" NEEDED_REG "] \\{"); - for (i = start_col; i <= end_col; i++) - printfs(".nr %1 +\\n[" NEEDED_REG "]\n", - span_width_reg(i, i)); - int equal_flag = 0; - for (i = start_col; i <= end_col && !equal_flag; i++) - if (equal[i]) - equal_flag = 1; - if (equal_flag) { - for (i = 0; i < ncolumns; i++) - if (i < start_col || i > end_col) - printfs(".nr %1 +\\n[" NEEDED_REG "]\n", - span_width_reg(i, i)); - } - prints(".\\}\n"); -} - - -void table::sum_columns(int start_col, int end_col) -{ - assert(end_col > start_col); - printfs(".nr %1 \\n[%2]", - span_width_reg(start_col, end_col), - span_width_reg(start_col, start_col)); - for (int i = start_col + 1; i <= end_col; i++) - printfs("+(%1*\\n[" SEPARATION_FACTOR_REG "])+\\n[%2]", - as_string(column_separation[i - 1]), - span_width_reg(i, i)); - prints('\n'); -} - -horizontal_span::horizontal_span(int sc, int ec, horizontal_span *p) -: next(p), start_col(sc), end_col(ec) -{ -} - -void table::build_span_list() -{ - span_list = 0; - table_entry *p = entry_list; - while (p) { - if (p->end_col != p->start_col) { - horizontal_span *q; - for (q = span_list; q; q = q->next) - if (q->start_col == p->start_col - && q->end_col == p->end_col) - break; - if (!q) - span_list = new horizontal_span(p->start_col, p->end_col, span_list); - } - p = p->next; - } - // Now sort span_list primarily by order of end_row, and secondarily - // by reverse order of start_row. This ensures that if we divide - // spans using the order in span_list, we will get reasonable results. - horizontal_span *unsorted = span_list; - span_list = 0; - while (unsorted) { - horizontal_span **pp; - for (pp = &span_list; *pp; pp = &(*pp)->next) - if (unsorted->end_col < (*pp)->end_col - || (unsorted->end_col == (*pp)->end_col - && (unsorted->start_col > (*pp)->start_col))) - break; - horizontal_span *tem = unsorted->next; - unsorted->next = *pp; - *pp = unsorted; - unsorted = tem; - } -} - - -void table::compute_separation_factor() -{ - if (flags & (ALLBOX|BOX|DOUBLEBOX)) - left_separation = right_separation = 1; - else { - for (int i = 0; i < nrows; i++) { - if (vline[i][0] > 0) - left_separation = 1; - if (vline[i][ncolumns] > 0) - right_separation = 1; - } - } - if (flags & EXPAND) { - int total_sep = left_separation + right_separation; - int i; - for (i = 0; i < ncolumns - 1; i++) - total_sep += column_separation[i]; - if (total_sep != 0) { - // Don't let the separation factor be negative. - prints(".nr " SEPARATION_FACTOR_REG " \\n[.l]-\\n[.i]"); - for (i = 0; i < ncolumns; i++) - printfs("-\\n[%1]", span_width_reg(i, i)); - printfs("/%1>?0\n", as_string(total_sep)); - } - } -} - -void table::compute_column_positions() -{ - printfs(".nr %1 0\n", column_divide_reg(0)); - printfs(".nr %1 %2*\\n[" SEPARATION_FACTOR_REG "]\n", - column_start_reg(0), - as_string(left_separation)); - int i; - for (i = 1;; i++) { - printfs(".nr %1 \\n[%2]+\\n[%3]\n", - column_end_reg(i-1), - column_start_reg(i-1), - span_width_reg(i-1, i-1)); - if (i >= ncolumns) - break; - printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n", - column_start_reg(i), - column_end_reg(i-1), - as_string(column_separation[i-1])); - printfs(".nr %1 \\n[%2]+\\n[%3]/2\n", - column_divide_reg(i), - column_end_reg(i-1), - column_start_reg(i)); - } - printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n", - column_divide_reg(ncolumns), - column_end_reg(i-1), - as_string(right_separation)); - printfs(".nr TW \\n[%1]\n", - column_divide_reg(ncolumns)); - if (flags & DOUBLEBOX) { - printfs(".nr %1 +" DOUBLE_LINE_SEP "\n", column_divide_reg(0)); - printfs(".nr %1 -" DOUBLE_LINE_SEP "\n", column_divide_reg(ncolumns)); - } -} - -void table::make_columns_equal() -{ - int first = -1; // index of first equal column - int i; - for (i = 0; i < ncolumns; i++) - if (equal[i]) { - if (first < 0) { - printfs(".nr %1 \\n[%1]", span_width_reg(i, i)); - first = i; - } - else - printfs(">?\\n[%1]", span_width_reg(i, i)); - } - if (first >= 0) { - prints('\n'); - for (i = first + 1; i < ncolumns; i++) - if (equal[i]) - printfs(".nr %1 \\n[%2]\n", - span_width_reg(i, i), - span_width_reg(first, first)); - } -} - -void table::compute_widths() -{ - build_span_list(); - int i; - horizontal_span *p; - prints(".nr " SEPARATION_FACTOR_REG " 1n\n"); - for (i = 0; i < ncolumns; i++) { - init_span_reg(i, i); - if (!minimum_width[i].empty()) - printfs(".nr %1 %2\n", span_width_reg(i, i), minimum_width[i]); - } - for (p = span_list; p; p = p->next) - init_span_reg(p->start_col, p->end_col); - table_entry *q; - for (q = entry_list; q; q = q->next) - if (!q->mod->zero_width) - q->do_width(); - for (i = 0; i < ncolumns; i++) - compute_span_width(i, i); - for (p = span_list; p; p = p->next) - compute_span_width(p->start_col, p->end_col); - make_columns_equal(); - // Note that divide_span keeps equal width columns equal. - for (p = span_list; p; p = p->next) - divide_span(p->start_col, p->end_col); - for (p = span_list; p; p = p->next) - sum_columns(p->start_col, p->end_col); - int had_spanning_block = 0; - int had_equal_block = 0; - for (q = entry_list; q; q = q->next) - if (q->divert(ncolumns, minimum_width, - (flags & EXPAND) ? column_separation : 0)) { - if (q->end_col > q->start_col) - had_spanning_block = 1; - for (i = q->start_col; i <= q->end_col && !had_equal_block; i++) - if (equal[i]) - had_equal_block = 1; - } - if (had_equal_block) - make_columns_equal(); - if (had_spanning_block) - for (p = span_list; p; p = p->next) - divide_span(p->start_col, p->end_col); - compute_separation_factor(); - for (p = span_list; p; p = p->next) - sum_columns(p->start_col, p->end_col); - compute_column_positions(); -} - -void table::print_single_hline(int r) -{ - prints(".vs " LINE_SEP ">?\\n[.V]u\n" - ".ls 1\n" - "\\v'" BODY_DEPTH "'" - "\\s[\\n[" LINESIZE_REG "]]"); - if (r > nrows - 1) - prints("\\D'l |\\n[TW]u 0'"); - else { - int start_col = 0; - for (;;) { - while (start_col < ncolumns - && entry[r][start_col] != 0 - && entry[r][start_col]->start_row != r) - start_col++; - int end_col; - for (end_col = start_col; - end_col < ncolumns - && (entry[r][end_col] == 0 - || entry[r][end_col]->start_row == r); - end_col++) - ; - if (end_col <= start_col) - break; - printfs("\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if ((r > 0 && vline[r-1][start_col] == 2) - || (r < nrows && vline[r][start_col] == 2)) - prints("-" HALF_DOUBLE_LINE_SEP); - prints("'"); - printfs("\\D'l |\\n[%1]u", - column_divide_reg(end_col)); - if ((r > 0 && vline[r-1][end_col] == 2) - || (r < nrows && vline[r][end_col] == 2)) - prints("+" HALF_DOUBLE_LINE_SEP); - prints(" 0'"); - start_col = end_col; - } - } - prints("\\s0\n"); - prints(".ls\n" - ".vs\n"); -} - -void table::print_double_hline(int r) -{ - prints(".vs " LINE_SEP "+" DOUBLE_LINE_SEP - ">?\\n[.V]u\n" - ".ls 1\n" - "\\v'" BODY_DEPTH "'" - "\\s[\\n[" LINESIZE_REG "]]"); - if (r > nrows - 1) - prints("\\v'-" DOUBLE_LINE_SEP "'" - "\\D'l |\\n[TW]u 0'" - "\\v'" DOUBLE_LINE_SEP "'" - "\\h'|0'" - "\\D'l |\\n[TW]u 0'"); - else { - int start_col = 0; - for (;;) { - while (start_col < ncolumns - && entry[r][start_col] != 0 - && entry[r][start_col]->start_row != r) - start_col++; - int end_col; - for (end_col = start_col; - end_col < ncolumns - && (entry[r][end_col] == 0 - || entry[r][end_col]->start_row == r); - end_col++) - ; - if (end_col <= start_col) - break; - const char *left_adjust = 0; - if ((r > 0 && vline[r-1][start_col] == 2) - || (r < nrows && vline[r][start_col] == 2)) - left_adjust = "-" HALF_DOUBLE_LINE_SEP; - const char *right_adjust = 0; - if ((r > 0 && vline[r-1][end_col] == 2) - || (r < nrows && vline[r][end_col] == 2)) - right_adjust = "+" HALF_DOUBLE_LINE_SEP; - printfs("\\v'-" DOUBLE_LINE_SEP "'" - "\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (left_adjust) - prints(left_adjust); - prints("'"); - printfs("\\D'l |\\n[%1]u", - column_divide_reg(end_col)); - if (right_adjust) - prints(right_adjust); - prints(" 0'"); - printfs("\\v'" DOUBLE_LINE_SEP "'" - "\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (left_adjust) - prints(left_adjust); - prints("'"); - printfs("\\D'l |\\n[%1]u", - column_divide_reg(end_col)); - if (right_adjust) - prints(right_adjust); - prints(" 0'"); - start_col = end_col; - } - } - prints("\\s0\n" - ".ls\n" - ".vs\n"); -} - -void table::compute_vrule_top_adjust(int start_row, int col, string &result) -{ - if (row_is_all_lines[start_row] && start_row < nrows - 1) { - if (row_is_all_lines[start_row] == 2) - result = LINE_SEP ">?\\n[.V]u" "+" DOUBLE_LINE_SEP; - else - result = LINE_SEP ">?\\n[.V]u"; - start_row++; - } - else { - result = ""; - if (start_row == 0) - return; - for (stuff *p = stuff_list; p && p->row <= start_row; p = p->next) - if (p->row == start_row - && (p->is_single_line() || p->is_double_line())) - return; - } - int left = 0; - if (col > 0) { - table_entry *e = entry[start_row-1][col-1]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - left = 2; - else if (e->to_single_line_entry() != 0) - left = 1; - } - } - int right = 0; - if (col < ncolumns) { - table_entry *e = entry[start_row-1][col]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - right = 2; - else if (e->to_single_line_entry() != 0) - right = 1; - } - } - if (row_is_all_lines[start_row-1] == 0) { - if (left > 0 || right > 0) { - result += "-" BODY_DEPTH "-" BAR_HEIGHT; - if ((left == 2 && right != 2) || (right == 2 && left != 2)) - result += "-" HALF_DOUBLE_LINE_SEP; - else if (left == 2 && right == 2) - result += "+" HALF_DOUBLE_LINE_SEP; - } - } - else if (row_is_all_lines[start_row-1] == 2) { - if ((left == 2 && right != 2) || (right == 2 && left != 2)) - result += "-" DOUBLE_LINE_SEP; - else if (left == 1 || right == 1) - result += "-" HALF_DOUBLE_LINE_SEP; - } -} - -void table::compute_vrule_bot_adjust(int end_row, int col, string &result) -{ - if (row_is_all_lines[end_row] && end_row > 0) { - end_row--; - result = ""; - } - else { - stuff *p; - for (p = stuff_list; p && p->row < end_row + 1; p = p->next) - ; - if (p && p->row == end_row + 1 && p->is_double_line()) { - result = "-" DOUBLE_LINE_SEP; - return; - } - if ((p != 0 && p->row == end_row + 1) - || end_row == nrows - 1) { - result = ""; - return; - } - if (row_is_all_lines[end_row+1] == 1) - result = LINE_SEP; - else if (row_is_all_lines[end_row+1] == 2) - result = LINE_SEP "+" DOUBLE_LINE_SEP; - else - result = ""; - } - int left = 0; - if (col > 0) { - table_entry *e = entry[end_row+1][col-1]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - left = 2; - else if (e->to_single_line_entry() != 0) - left = 1; - } - } - int right = 0; - if (col < ncolumns) { - table_entry *e = entry[end_row+1][col]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - right = 2; - else if (e->to_single_line_entry() != 0) - right = 1; - } - } - if (row_is_all_lines[end_row+1] == 0) { - if (left > 0 || right > 0) { - result = "1v-" BODY_DEPTH "-" BAR_HEIGHT; - if ((left == 2 && right != 2) || (right == 2 && left != 2)) - result += "+" HALF_DOUBLE_LINE_SEP; - else if (left == 2 && right == 2) - result += "-" HALF_DOUBLE_LINE_SEP; - } - } - else if (row_is_all_lines[end_row+1] == 2) { - if (left == 2 && right == 2) - result += "-" DOUBLE_LINE_SEP; - else if (left != 2 && right != 2 && (left == 1 || right == 1)) - result += "-" HALF_DOUBLE_LINE_SEP; - } -} - -void table::add_vertical_rule(int start_row, int end_row, int col, int is_double) -{ - vrule_list = new vertical_rule(start_row, end_row, col, is_double, - vrule_list); - compute_vrule_top_adjust(start_row, col, vrule_list->top_adjust); - compute_vrule_bot_adjust(end_row, col, vrule_list->bot_adjust); -} - -void table::build_vrule_list() -{ - int col; - if (flags & ALLBOX) { - for (col = 1; col < ncolumns; col++) { - int start_row = 0; - for (;;) { - while (start_row < nrows && vline_spanned(start_row, col)) - start_row++; - if (start_row >= nrows) - break; - int end_row = start_row; - while (end_row < nrows && !vline_spanned(end_row, col)) - end_row++; - end_row--; - add_vertical_rule(start_row, end_row, col, 0); - start_row = end_row + 1; - } - } - } - if (flags & (BOX|ALLBOX|DOUBLEBOX)) { - add_vertical_rule(0, nrows - 1, 0, 0); - add_vertical_rule(0, nrows - 1, ncolumns, 0); - } - for (int end_row = 0; end_row < nrows; end_row++) - for (col = 0; col < ncolumns+1; col++) - if (vline[end_row][col] > 0 - && !vline_spanned(end_row, col) - && (end_row == nrows - 1 - || vline[end_row+1][col] != vline[end_row][col] - || vline_spanned(end_row+1, col))) { - int start_row; - for (start_row = end_row - 1; - start_row >= 0 - && vline[start_row][col] == vline[end_row][col] - && !vline_spanned(start_row, col); - start_row--) - ; - start_row++; - add_vertical_rule(start_row, end_row, col, vline[end_row][col] > 1); - } - for (vertical_rule *p = vrule_list; p; p = p->next) - if (p->is_double) - for (int r = p->start_row; r <= p->end_row; r++) { - if (p->col > 0 && entry[r][p->col-1] != 0 - && entry[r][p->col-1]->end_col == p->col-1) { - int is_corner = r == p->start_row || r == p->end_row; - entry[r][p->col-1]->note_double_vrule_on_right(is_corner); - } - if (p->col < ncolumns && entry[r][p->col] != 0 - && entry[r][p->col]->start_col == p->col) { - int is_corner = r == p->start_row || r == p->end_row; - entry[r][p->col]->note_double_vrule_on_left(is_corner); - } - } -} - -void table::define_bottom_macro() -{ - prints(".eo\n" - ".de T#\n" - ".if !\\n[" SUPPRESS_BOTTOM_REG "] \\{" - "." REPEATED_VPT_MACRO " 0\n" - ".mk " SAVED_VERTICAL_POS_REG "\n"); - if (flags & (BOX|ALLBOX|DOUBLEBOX)) { - prints(".if \\n[T.]&\\n[" NEED_BOTTOM_RULE_REG "] \\{"); - print_single_hline(0); - prints(".\\}\n"); - } - prints(".ls 1\n"); - for (vertical_rule *p = vrule_list; p; p = p->next) - p->contribute_to_bottom_macro(this); - if (flags & DOUBLEBOX) - prints(".if \\n[T.] \\{.vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n" - "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]" - "\\D'l \\n[TW]u 0'\\s0\n" - ".vs\n" - ".\\}\n" - ".if \\n[" LAST_PASSED_ROW_REG "]>=0 " - ".nr " TOP_REG " \\n[#T]-" DOUBLE_LINE_SEP "\n" - ".sp -1\n" - "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]" - "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n" - ".sp -1\n" - "\\v'" BODY_DEPTH "'\\h'|\\n[TW]u'\\s[\\n[" LINESIZE_REG "]]" - "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n"); - prints(".ls\n"); - prints(".nr " LAST_PASSED_ROW_REG " \\n[" CURRENT_ROW_REG "]\n" - ".sp |\\n[" SAVED_VERTICAL_POS_REG "]u\n" - "." REPEATED_VPT_MACRO " 1\n" - ".\\}\n" - "..\n" - ".ec\n"); -} - - -// is the vertical line before column c in row r horizontally spanned? - -int table::vline_spanned(int r, int c) -{ - assert(r >= 0 && r < nrows && c >= 0 && c < ncolumns + 1); - return (c != 0 && c != ncolumns && entry[r][c] != 0 - && entry[r][c]->start_col != c - // horizontally spanning lines don't count - && entry[r][c]->to_double_line_entry() == 0 - && entry[r][c]->to_single_line_entry() == 0); -} - -int table::row_begins_section(int r) -{ - assert(r >= 0 && r < nrows); - for (int i = 0; i < ncolumns; i++) - if (entry[r][i] && entry[r][i]->start_row != r) - return 0; - return 1; -} - -int table::row_ends_section(int r) -{ - assert(r >= 0 && r < nrows); - for (int i = 0; i < ncolumns; i++) - if (entry[r][i] && entry[r][i]->end_row != r) - return 0; - return 1; -} - -void table::do_row(int r) -{ - if (!(flags & NOKEEP) && row_begins_section(r)) - prints("." KEEP_MACRO_NAME "\n"); - int had_line = 0; - stuff *p; - for (p = stuff_list; p && p->row < r; p = p->next) - ; - for (stuff *p1 = p; p1 && p1->row == r; p1 = p1->next) - if (!p1->printed && (p1->is_single_line() || p1->is_double_line())) { - had_line = 1; - break; - } - if (!had_line && !row_is_all_lines[r]) - printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); - had_line = 0; - for (; p && p->row == r; p = p->next) - if (!p->printed) { - p->print(this); - if (!had_line && (p->is_single_line() || p->is_double_line())) { - printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); - had_line = 1; - } - } - // Change the row *after* printing the stuff list (which might contain .TH). - printfs("\\*[" TRANSPARENT_STRING_NAME "].nr " CURRENT_ROW_REG " %1\n", - as_string(r)); - if (!had_line && row_is_all_lines[r]) - printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); - // we might have had a .TH, for example, since we last tried - if (!(flags & NOKEEP) && row_begins_section(r)) - prints("." KEEP_MACRO_NAME "\n"); - printfs(".mk %1\n", row_start_reg(r)); - prints(".mk " BOTTOM_REG "\n" - "." REPEATED_VPT_MACRO " 0\n"); - int c; - int row_is_blank = 1; - int first_start_row = r; - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r) { - e->do_depth(); - if (e->start_row < first_start_row) - first_start_row = e->start_row; - row_is_blank = 0; - } - c = e->end_col; - } - } - if (row_is_blank) - prints(".nr " BOTTOM_REG " +1v\n"); - if (row_is_all_lines[r]) { - prints(".vs " LINE_SEP); - if (row_is_all_lines[r] == 2) - prints("+" DOUBLE_LINE_SEP); - prints(">?\\n[.V]u\n.ls 1\n"); - prints("\\&"); - prints("\\v'" BODY_DEPTH); - if (row_is_all_lines[r] == 2) - prints("-" HALF_DOUBLE_LINE_SEP); - prints("'"); - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == e->start_row) - e->to_simple_entry()->simple_print(1); - c = e->end_col; - } - } - prints("\n"); - prints(".ls\n" - ".vs\n"); - prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n"); - printfs(".sp |\\n[%1]u\n", row_start_reg(r)); - } - for (int i = row_is_all_lines[r] ? r - 1 : r; - i >= first_start_row; - i--) { - simple_entry *first = 0; - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r && e->start_row == i) { - simple_entry *simple = e->to_simple_entry(); - if (simple) { - if (!first) { - prints(".ta"); - first = simple; - } - simple->add_tab(); - } - } - c = e->end_col; - } - } - if (first) { - prints('\n'); - first->position_vertically(); - first->set_location(); - prints("\\&"); - first->simple_print(0); - for (c = first->end_col + 1; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r && e->start_row == i) { - simple_entry *simple = e->to_simple_entry(); - if (simple) - simple->simple_print(0); - } - c = e->end_col; - } - } - prints('\n'); - prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n"); - printfs(".sp |\\n[%1]u\n", row_start_reg(r)); - } - } - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r && e->to_simple_entry() == 0) { - e->position_vertically(); - e->print(); - prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n"); - printfs(".sp |\\n[%1]u\n", row_start_reg(r)); - } - c = e->end_col; - } - } - prints("." REPEATED_VPT_MACRO " 1\n" - ".sp |\\n[" BOTTOM_REG "]u\n" - "\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 1\n"); - if (r != nrows - 1 && (flags & ALLBOX)) { - print_single_hline(r + 1); - prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 0\n"); - } - if (r != nrows - 1) { - if (p && p->row == r + 1 - && (p->is_single_line() || p->is_double_line())) { - p->print(this); - prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG - " 0\n"); - } - int printed_one = 0; - for (vertical_rule *vr = vrule_list; vr; vr = vr->next) - if (vr->end_row == r) { - if (!printed_one) { - prints("." REPEATED_VPT_MACRO " 0\n"); - printed_one = 1; - } - vr->print(); - } - if (printed_one) - prints("." REPEATED_VPT_MACRO " 1\n"); - if (!(flags & NOKEEP) && row_ends_section(r)) - prints("." RELEASE_MACRO_NAME "\n"); - } -} - -void table::do_top() -{ - prints(".fc \002\003\n"); - if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX))) - prints("." TABLE_KEEP_MACRO_NAME "\n"); - if (flags & DOUBLEBOX) { - prints(".ls 1\n" - ".vs " LINE_SEP ">?\\n[.V]u\n" - "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]\\D'l \\n[TW]u 0'\\s0\n" - ".vs\n" - "." REPEATED_MARK_MACRO " " TOP_REG "\n" - ".vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n"); - printfs("\\v'" BODY_DEPTH "'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\h'\\n[%1]u'" - "\\D'l |\\n[%2]u 0'" - "\\s0" - "\n", - column_divide_reg(0), - column_divide_reg(ncolumns)); - prints(".ls\n" - ".vs\n"); - } - else if (flags & (ALLBOX|BOX)) { - print_single_hline(0); - } - //printfs(".mk %1\n", row_top_reg(0)); -} - -void table::do_bottom() -{ - // print stuff after last row - for (stuff *p = stuff_list; p; p = p->next) - if (p->row > nrows - 1) - p->print(this); - if (!(flags & NOKEEP)) - prints("." RELEASE_MACRO_NAME "\n"); - printfs(".mk %1\n", row_top_reg(nrows)); - prints(".nr " NEED_BOTTOM_RULE_REG " 1\n" - ".nr T. 1\n" - ".T#\n"); - if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX))) - prints("." TABLE_RELEASE_MACRO_NAME "\n"); - if (flags & DOUBLEBOX) - prints(".sp " DOUBLE_LINE_SEP "\n"); - prints("." RESET_MACRO_NAME "\n" - ".fc\n" - ".cp \\n(" COMPATIBLE_REG "\n"); -} - -int table::get_nrows() -{ - return nrows; -} - -const char *last_filename = 0; - -void set_troff_location(const char *fn, int ln) -{ - if (!location_force_filename && last_filename != 0 - && strcmp(fn, last_filename) == 0) - printfs(".lf %1\n", as_string(ln)); - else { - printfs(".lf %1 %2\n", as_string(ln), fn); - last_filename = fn; - location_force_filename = 0; - } -} - -void printfs(const char *s, const string &arg1, const string &arg2, - const string &arg3, const string &arg4, const string &arg5) -{ - if (s) { - char c; - while ((c = *s++) != '\0') { - if (c == '%') { - switch (*s++) { - case '1': - prints(arg1); - break; - case '2': - prints(arg2); - break; - case '3': - prints(arg3); - break; - case '4': - prints(arg4); - break; - case '5': - prints(arg5); - break; - case '6': - case '7': - case '8': - case '9': - break; - case '%': - prints('%'); - break; - default: - assert(0); - } - } - else - prints(c); - } - } -} - diff --git a/contrib/groff/tbl/table.h b/contrib/groff/tbl/table.h deleted file mode 100644 index ca55b8026c22..000000000000 --- a/contrib/groff/tbl/table.h +++ /dev/null @@ -1,152 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff 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, or (at your option) any later -version. - -groff 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 groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <ctype.h> -#include <errno.h> - -#include "cset.h" -#include "cmap.h" -#include "stringclass.h" -#include "errarg.h" -#include "error.h" -#include "lib.h" - -struct inc_number { - short inc; - short val; -}; - -struct entry_modifier { - inc_number point_size; - inc_number vertical_spacing; - string font; - enum { CENTER, TOP, BOTTOM } vertical_alignment; - char zero_width; - char stagger; - - entry_modifier(); - ~entry_modifier(); -}; - -enum format_type { - FORMAT_LEFT, - FORMAT_CENTER, - FORMAT_RIGHT, - FORMAT_NUMERIC, - FORMAT_ALPHABETIC, - FORMAT_SPAN, - FORMAT_VSPAN, - FORMAT_HLINE, - FORMAT_DOUBLE_HLINE -}; - -struct entry_format : public entry_modifier { - format_type type; - - entry_format(format_type); - entry_format(); - void debug_print() const; -}; - -struct table_entry; -struct horizontal_span; -struct stuff; -struct vertical_rule; - -class table { - unsigned flags; - int nrows; - int ncolumns; - int linesize; - char delim[2]; - char decimal_point_char; - vertical_rule *vrule_list; - stuff *stuff_list; - horizontal_span *span_list; - table_entry *entry_list; - table_entry **entry_list_tailp; - table_entry ***entry; - char **vline; - char *row_is_all_lines; - string *minimum_width; - int *column_separation; - char *equal; - int left_separation; - int right_separation; - int allocated_rows; - void build_span_list(); - void do_hspan(int r, int c); - void do_vspan(int r, int c); - void allocate(int r); - void compute_widths(); - void divide_span(int, int); - void sum_columns(int, int); - void compute_separation_factor(); - void compute_column_positions(); - void do_row(int); - void init_output(); - void add_stuff(stuff *); - void do_top(); - void do_bottom(); - void do_vertical_rules(); - void build_vrule_list(); - void add_vertical_rule(int, int, int, int); - void define_bottom_macro(); - int vline_spanned(int r, int c); - int row_begins_section(int); - int row_ends_section(int); - void make_columns_equal(); - void compute_vrule_top_adjust(int, int, string &); - void compute_vrule_bot_adjust(int, int, string &); - void determine_row_type(); -public: - /* used by flags */ - enum { - CENTER = 01, - EXPAND = 02, - BOX = 04, - ALLBOX = 010, - DOUBLEBOX = 020, - NOKEEP = 040 - }; - table(int nc, unsigned flags, int linesize, char decimal_point_char); - ~table(); - - void add_text_line(int r, const string &, const char *, int); - void add_single_hline(int r); - void add_double_hline(int r); - void add_entry(int r, int c, const string &, const entry_format *, - const char *, int lineno); - void add_vlines(int r, const char *); - void check(); - void print(); - void set_minimum_width(int c, const string &w); - void set_column_separation(int c, int n); - void set_equal_column(int c); - void set_delim(char c1, char c2); - void print_single_hline(int r); - void print_double_hline(int r); - int get_nrows(); -}; - -void set_troff_location(const char *, int); diff --git a/contrib/groff/tbl/tbl.man b/contrib/groff/tbl/tbl.man deleted file mode 100644 index 6016ddf35f8f..000000000000 --- a/contrib/groff/tbl/tbl.man +++ /dev/null @@ -1,178 +0,0 @@ -.ig \"-*- nroff -*- -Copyright (C) 1989-1995 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -.TH @G@TBL @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -.SH NAME -@g@tbl \- format tables for troff -.SH SYNOPSIS -.B @g@tbl -[ -.B \-Cv -] -[ -.IR files \|.\|.\|. -] -.SH DESCRIPTION -This manual page describes the GNU version of -.BR tbl , -which is part of the groff document formatting system. -.B tbl -compiles descriptions of tables embedded within -.B troff -input files into commands that are understood by -.BR troff . -Normally, it should be invoked using the -.B \-t -option of -.B groff. -It is highly compatible with Unix -.BR tbl . -The output generated by GNU -.B tbl -cannot be processed with Unix -.BR troff ; -it must be processed with GNU -.BR troff . -If no files are given on the command line, the standard input -will be read. -A filename of -.B \- -will cause the standard input to be read. -.SH OPTIONS -.TP -.B \-C -Recognize -.B .TS -and -.B .TE -even when followed by a character other than space or newline. -.TP -.B \-v -Print the version number. -.SH USAGE -Only the differences between GNU -.B tbl -and Unix -.B tbl -are described here. -.LP -Normally -.B tbl -attempts to prevent undesirable breaks in the table by using diversions. -This can sometimes interact badly with macro packages' own use of diversions, -when footnotes, for example, are used. -The -.B nokeep -option tells -.B tbl -not to try and prevent breaks in this way. -.LP -The -.B decimalpoint -option specifies the character to be recognized as the decimal -point character in place of the default period. -It takes an argument in parentheses, which must be a single -character, as for the -.B tab -option. -.LP -The -.B f -format modifier can be followed by an arbitrary length -font name in parentheses. -.LP -There is a -.B d -format modifier which means that a vertically spanning entry -should be aligned at the bottom of its range. -.LP -There is no limit on the number of columns in a table, nor any limit -on the number of text blocks. -All the lines of a table are considered in deciding column -widths, not just the first 200. -Table continuation -.RB ( .T& ) -lines are not restricted to the first 200 lines. -.LP -Numeric and alphabetic items may appear in the same column. -.LP -Numeric and alphabetic items may span horizontally. -.LP -.B tbl -uses register, string, macro and diversion names beginning with -.BR 3 . -When using -.B tbl -you should avoid using any names beginning with a -.BR 3 . -.SH BUGS -You should use -.BR .TS\ H / .TH -in conjunction with a supporting macro package for -.I all -multi-page boxed tables. -If there is no header that you wish to appear at the top of each page -of the table, place the -.B .TH -line immediately after the format section. -Do not enclose a multi-page table within keep/release macros, -or divert it in any other way. -.LP -A text block within a table must be able to fit on one page. -.LP -The -.B bp -request cannot be used to force a page-break in a multi-page table. -Instead, define -.B BP -as follows -.IP -.B .de BP -.br -.B .ie '\e\en(.z'' .bp \e\e$1 -.br -.B .el \e!.BP \e\e$1 -.br -.B .. -.br -.LP -and use -.B BP -instead of -.BR bp . -.LP -Using \ea directly in a table to get leaders will not work. -This is correct behaviour: \ea is a -.B uninterpreted -leader. -To get leaders use a real leader, either by using a control A or like -this: -.IP -.nf -.ft B -\&.ds a \ea -\&.TS -tab(;); -lw(1i) l. -A\e*a;B -\&.TE -.ft -.fi -.SH "SEE ALSO" -.BR groff (@MAN1EXT@), -.BR @g@troff (@MAN1EXT@) |