diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-09-26 23:06:02 +0000 |
---|---|---|
committer | <> | 2015-02-03 11:56:22 +0000 |
commit | e0b511b834f3529395df67126a7314097c2cf97e (patch) | |
tree | 89945ae53183ab2acdc61659c8b0b3e57e4a1f3a /makeinfo/multi.c | |
parent | 2d8ae7b161658c4a589172db0072fc99f76fa979 (diff) | |
download | texinfo-tarball-texinfo-5.2.tar.gz |
Imported from /home/lorry/working-area/delta_texinfo-tarball/texinfo-5.2.tar.xz.HEADtexinfo-5.2master
Diffstat (limited to 'makeinfo/multi.c')
-rw-r--r-- | makeinfo/multi.c | 646 |
1 files changed, 0 insertions, 646 deletions
diff --git a/makeinfo/multi.c b/makeinfo/multi.c deleted file mode 100644 index 43033a2..0000000 --- a/makeinfo/multi.c +++ /dev/null @@ -1,646 +0,0 @@ -/* multi.c -- multiple-column tables (@multitable) for makeinfo. - $Id: multi.c,v 1.18 2007/07/01 21:20:33 karl Exp $ - - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007 - Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - Originally written by phr@gnu.org (Paul Rubin). */ - -#include "system.h" -#include "mbswidth.h" -#include "cmds.h" -#include "insertion.h" -#include "makeinfo.h" -#include "multi.h" -#include "xml.h" - -#define MAXCOLS 100 /* remove this limit later @@ */ - - -/* - * Output environments. This is a hack grafted onto existing - * structure. The "output environment" used to consist of the - * global variables `output_paragraph', `fill_column', etc. - * Routines like add_char would manipulate these variables. - * - * Now, when formatting a multitable, we maintain separate environments - * for each column. That way we can build up the columns separately - * and write them all out at once. The "current" output environment" - * is still kept in those global variables, so that the old output - * routines don't have to change. But we provide routines to save - * and restore these variables in an "environment table". The - * `select_output_environment' function switches from one output - * environment to another. - * - * Environment #0 (i.e., element #0 of the table) is the regular - * environment that is used when we're not formatting a multitable. - * - * Environment #N (where N = 1,2,3,...) is the env. for column #N of - * the table, when a multitable is active. - */ - -/* contents of an output environment */ -/* some more vars may end up being needed here later @@ */ -static struct env -{ - unsigned char *output_paragraph; - int output_paragraph_offset; - int paragraph_buffer_len; - int paragraph_is_open; - int meta_char_pos; - int current_indent; - int fill_column; -} envs[MAXCOLS]; /* the environment table */ - -/* index in environment table of currently selected environment */ -static int current_env_no; - -/* current column number */ -static int current_column_no; - -/* We need to make a difference between template based widths and - @columnfractions for HTML tables' sake. Sigh. */ -static int seen_column_fractions; - -/* column number of last column in current multitable */ -static int last_column; - -/* flags indicating whether horizontal and vertical separators need - to be drawn, separating rows and columns in the current multitable. */ -static int hsep, vsep; - -/* whether this is the first row. */ -static int first_row; - -/* Called to handle a {...} template on the @multitable line. - We're at the { and our first job is to find the matching }; as a side - effect, we change *PARAMS to point to after it. Our other job is to - expand the template text and return the width of that string. */ -static unsigned -find_template_width (char **params) -{ - char *template, *xtemplate; - unsigned len; - char *start = *params; - int brace_level = 0; - - /* The first character should be a {. */ - if (!params || !*params || **params != '{') - { - line_error ("find_template width internal error: passed %s", - params ? *params : "null"); - return 0; - } - - do - { - if (**params == '{' && (*params == start || (*params)[-1] != '@')) - brace_level++; - else if (**params == '}' && (*params)[-1] != '@') - brace_level--; - else if (**params == 0) - { - line_error (_("Missing } in @multitable template")); - return 0; - } - (*params)++; - } - while (brace_level > 0); - - template = substring (start + 1, *params - 1); /* omit braces */ - xtemplate = expansion (template, 0); - len = strlen (xtemplate); - - free (template); - free (xtemplate); - - return len; -} - -/* Direct current output to environment number N. Used when - switching work from one column of a multitable to the next. - Returns previous environment number. */ -static int -select_output_environment (int n) -{ - struct env *e = &envs[current_env_no]; - int old_env_no = current_env_no; - - /* stash current env info from global vars into the old environment */ - e->output_paragraph = output_paragraph; - e->output_paragraph_offset = output_paragraph_offset; - e->paragraph_buffer_len = paragraph_buffer_len; - e->paragraph_is_open = paragraph_is_open; - e->meta_char_pos = meta_char_pos; - e->current_indent = current_indent; - e->fill_column = fill_column; - - /* now copy new environment into global vars */ - current_env_no = n; - e = &envs[current_env_no]; - output_paragraph = e->output_paragraph; - output_paragraph_offset = e->output_paragraph_offset; - /* All the elements in the output environment structures start out as - zeros from the static declaration. However, we don't want to try - to malloc zero bytes when init_paragraph is called just below, - after we return. */ - paragraph_buffer_len = e->paragraph_buffer_len ? e->paragraph_buffer_len - : INITIAL_PARAGRAPH_BUFFER_LEN; - paragraph_is_open = e->paragraph_is_open; - meta_char_pos = e->meta_char_pos; - current_indent = e->current_indent; - fill_column = e->fill_column; - - return old_env_no; -} - -/* Initialize environment number ENV_NO, of width WIDTH. - The idea is that we're going to use one environment for each column of - a multitable, so we can build them up separately and print them - all out at the end. */ -static int -setup_output_environment (int env_no, int width) -{ - int old_env = select_output_environment (env_no); - - /* clobber old environment and set width of new one */ - init_paragraph (); - - /* make our change */ - fill_column = width; - - /* Save new environment and restore previous one. */ - select_output_environment (old_env); - - return env_no; -} - -/* Read the parameters for a multitable from the current command - line, save the parameters away, and return the - number of columns. */ -static int -setup_multitable_parameters (void) -{ - char *params = insertion_stack->item_function; - int nchars; - float columnfrac; - char command[200]; /* xx no fixed limits */ - int i = 1; - - /* We implement @hsep and @vsep even though TeX doesn't. - We don't get mixing of @columnfractions and templates right, - but TeX doesn't either. */ - hsep = vsep = 0; - - /* Assume no @columnfractions per default. */ - seen_column_fractions = 0; - - while (*params) { - while (whitespace (*params)) - params++; - - if (*params == '@') { - sscanf (params, "%200s", command); - nchars = strlen (command); - params += nchars; - if (strcmp (command, "@hsep") == 0) - hsep++; - else if (strcmp (command, "@vsep") == 0) - vsep++; - else if (strcmp (command, "@columnfractions") == 0) { - seen_column_fractions = 1; - /* Clobber old environments and create new ones, starting at #1. - Environment #0 is the normal output, so don't mess with it. */ - for ( ; i <= MAXCOLS; i++) { - if (sscanf (params, "%f", &columnfrac) < 1) - goto done; - /* Unfortunately, can't use %n since m68k-hp-bsd libc (at least) - doesn't support it. So skip whitespace (preceding the - number) and then non-whitespace (the number). */ - while (*params && (*params == ' ' || *params == '\t')) - params++; - /* Hmm, but what about @columnfractions 3foo. Oh well, - it's invalid input anyway. */ - while (*params && *params != ' ' && *params != '\t' - && *params != '\n' && *params != '@') - params++; - - { - /* For html/xml/docbook, translate fractions into integer - percentages, adding .005 to avoid rounding problems. For - info, we want the character width. */ - int width = xml || html ? (columnfrac + .005) * 100 - : (columnfrac * (fill_column - current_indent) + .5); - setup_output_environment (i, width); - } - } - } - - } else if (*params == '{') { - unsigned template_width = find_template_width (¶ms); - - /* This gives us two spaces between columns. Seems reasonable. - How to take into account current_indent here? */ - setup_output_environment (i++, template_width + 2); - - } else { - warning (_("ignoring stray text `%s' after @multitable"), params); - break; - } - } - -done: - flush_output (); - inhibit_output_flushing (); - - last_column = i - 1; - return last_column; -} - -/* Output a row. Calls insert, but also flushes the buffered output - when we see a newline, since in multitable every line is a separate - paragraph. */ -static void -out_char (int ch) -{ - if (html || xml) - add_char (ch); - else - { - int env = select_output_environment (0); - insert (ch); - if (ch == '\n') - { - uninhibit_output_flushing (); - flush_output (); - inhibit_output_flushing (); - } - select_output_environment (env); - } -} - - -static void -draw_horizontal_separator (void) -{ - int i, j, s; - - if (html) - { - add_word ("<hr>"); - return; - } - if (xml) - return; - - for (s = 0; s < envs[0].current_indent; s++) - out_char (' '); - if (vsep) - out_char ('+'); - for (i = 1; i <= last_column; i++) { - for (j = 0; j <= envs[i].fill_column; j++) - out_char ('-'); - if (vsep) - out_char ('+'); - } - out_char (' '); - out_char ('\n'); -} - - -/* multitable strategy: - for each item { - for each column in an item { - initialize a new paragraph - do ordinary formatting into the new paragraph - save the paragraph away - repeat if there are more paragraphs in the column - } - dump out the saved paragraphs and free the storage - } - - For HTML we construct a simple HTML 3.2 table with <br>s inserted - to help non-tables browsers. `@item' inserts a <tr> and `@tab' - inserts <td>; we also try to close <tr>. The only real - alternative is to rely on the info formatting engine and present - preformatted text. */ - -void -do_multitable (void) -{ - int ncolumns; - - if (multitable_active) - { - line_error ("Multitables cannot be nested"); - return; - } - - close_single_paragraph (); - - if (xml) - { - xml_no_para = 1; - if (output_paragraph_offset > 0 - && output_paragraph[output_paragraph_offset-1] == '\n') - output_paragraph_offset--; - } - - /* scan the current item function to get the field widths - and number of columns, and set up the output environment list - accordingly. */ - ncolumns = setup_multitable_parameters (); - first_row = 1; - - /* <p> for non-tables browsers. @multitable implicitly ends the - current paragraph, so this is ok. */ - if (html) - add_html_block_elt ("<p><table summary=\"\">"); - /* else if (docbook)*/ /* 05-08 */ - else if (xml) - { - int *widths = xmalloc (ncolumns * sizeof (int)); - int i; - for (i=0; i<ncolumns; i++) - widths[i] = envs[i+1].fill_column; - xml_begin_multitable (ncolumns, widths); - free (widths); - } - - if (hsep) - draw_horizontal_separator (); - - /* The next @item command will direct stdout into the first column - and start processing. @tab will then switch to the next column, - and @item will flush out the saved output and return to the first - column. Environment #1 is the first column. (Environment #0 is - the normal output) */ - - ++multitable_active; -} - -/* advance to the next environment number */ -static void -nselect_next_environment (void) -{ - if (current_env_no >= last_column) { - line_error (_("Too many columns in multitable item (max %d)"), last_column); - return; - } - select_output_environment (current_env_no + 1); -} - - -/* do anything needed at the beginning of processing a - multitable column. */ -static void -init_column (void) -{ - /* don't indent 1st paragraph in the item */ - cm_noindent (); - - /* throw away possible whitespace after @item or @tab command */ - skip_whitespace (); -} - -static void -output_multitable_row (void) -{ - /* offset in the output paragraph of the next char needing - to be output for that column. */ - int offset[MAXCOLS]; - int i, j, s, remaining; - int had_newline = 0; - - for (i = 0; i <= last_column; i++) - offset[i] = 0; - - /* select the current environment, to make sure the env variables - get updated */ - select_output_environment (current_env_no); - -#define CHAR_ADDR(n) (offset[i] + (n)) -#define CHAR_AT(n) (envs[i].output_paragraph[CHAR_ADDR(n)]) - - /* remove trailing whitespace from each column */ - for (i = 1; i <= last_column; i++) { - while (envs[i].output_paragraph_offset - && cr_or_whitespace (CHAR_AT (envs[i].output_paragraph_offset - 1))) - envs[i].output_paragraph_offset--; - - if (i == current_env_no) - output_paragraph_offset = envs[i].output_paragraph_offset; - } - - /* read the current line from each column, outputting them all - pasted together. Do this til all lines are output from all - columns. */ - for (;;) { - remaining = 0; - /* first, see if there is any work to do */ - for (i = 1; i <= last_column; i++) { - if (CHAR_ADDR (0) < envs[i].output_paragraph_offset) { - remaining = 1; - break; - } - } - if (!remaining) - break; - - for (s = 0; s < envs[0].current_indent; s++) - out_char (' '); - - if (vsep) - out_char ('|'); - - for (i = 1; i <= last_column; i++) { - for (s = 0; s < envs[i].current_indent; s++) - out_char (' '); - for (j = 0; CHAR_ADDR (j) < envs[i].output_paragraph_offset; j++) { - if (CHAR_AT (j) == '\n') - break; - out_char (CHAR_AT (j)); - } - /* Do not output trailing blanks if we're in the last column and - there will be no trailing |. */ - if (i < last_column && !vsep) - for (s = mbsnwidth ((char *)&CHAR_AT (0), j, 0); - s <= envs[i].fill_column; s++) - out_char (' '); - if (vsep) - out_char ('|'); /* draw column separator */ - - offset[i] += j + 1; /* skip last text plus skip the newline */ - } - out_char ('\n'); /* end of line */ - had_newline = 1; - } - - /* If completely blank item, get blank line despite no other output. */ - if (!had_newline) - out_char ('\n'); /* end of line */ - - if (hsep) - draw_horizontal_separator (); - - /* Now dispose of the buffered output. */ - for (i = 1; i <= last_column; i++) { - select_output_environment (i); - init_paragraph (); - } -} - -int after_headitem = 0; -int headitem_row = 0; - -/* start a new item (row) of a multitable */ -int -multitable_item (void) -{ - if (!multitable_active) { - line_error ("multitable_item internal error: no active multitable"); - xexit (1); - } - - current_column_no = 1; - - if (html) - { - if (!first_row) - /* <br> for non-tables browsers. */ - add_word_args ("<br></%s></tr>", after_headitem ? "th" : "td"); - - if (seen_column_fractions) - add_word_args ("<tr align=\"left\"><%s valign=\"top\" width=\"%d%%\">", - headitem_flag ? "th" : "td", - envs[current_column_no].fill_column); - else - add_word_args ("<tr align=\"left\"><%s valign=\"top\">", - headitem_flag ? "th" : "td"); - - if (headitem_flag) - after_headitem = 1; - else - after_headitem = 0; - first_row = 0; - headitem_row = headitem_flag; - headitem_flag = 0; - return 0; - } - /* else if (docbook)*/ /* 05-08 */ - else if (xml) - { - xml_end_multitable_row (first_row); - if (headitem_flag) - after_headitem = 1; - else - after_headitem = 0; - first_row = 0; - headitem_flag = 0; - return 0; - } - first_row = 0; - - if (current_env_no > 0) { - output_multitable_row (); - } - /* start at column 1 */ - select_output_environment (1); - if (!output_paragraph) { - line_error (_("[unexpected] cannot select column #%d in multitable"), - current_env_no); - xexit (1); - } - - init_column (); - - if (headitem_flag) - hsep = 1; - else - hsep = 0; - - if (headitem_flag) - after_headitem = 1; - else - after_headitem = 0; - headitem_flag = 0; - - return 0; -} - -#undef CHAR_AT -#undef CHAR_ADDR - -/* select a new column in current row of multitable */ -void -cm_tab (void) -{ - if (!multitable_active) - error (_("ignoring @tab outside of multitable")); - - current_column_no++; - - if (html) - { - if (seen_column_fractions) - add_word_args ("</%s><%s valign=\"top\" width=\"%d%%\">", - headitem_row ? "th" : "td", - headitem_row ? "th" : "td", - envs[current_column_no].fill_column); - else - add_word_args ("</%s><%s valign=\"top\">", - headitem_row ? "th" : "td", - headitem_row ? "th" : "td"); - } - /* else if (docbook)*/ /* 05-08 */ - else if (xml) - xml_end_multitable_column (); - else - nselect_next_environment (); - - init_column (); -} - -/* close a multitable, flushing its output and resetting - whatever needs resetting */ -void -end_multitable (void) -{ - if (!html && !docbook) - output_multitable_row (); - - /* Multitables cannot be nested. Otherwise, we'd have to save the - previous output environment number on a stack somewhere, and then - restore to that environment. */ - select_output_environment (0); - multitable_active = 0; - uninhibit_output_flushing (); - close_insertion_paragraph (); - - if (html) - add_word_args ("<br></%s></tr></table>\n", headitem_row ? "th" : "td"); - /* else if (docbook)*/ /* 05-08 */ - else if (xml) - xml_end_multitable (); - -#if 0 - printf (_("** Multicolumn output from last row:\n")); - for (i = 1; i <= last_column; i++) { - select_output_environment (i); - printf (_("* column #%d: output = %s\n"), i, output_paragraph); - } -#endif -} |