2 /* Copyright (C) 2002-2018 Free Software Foundation, Inc.
4 * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp
8 * provides the methods necessary to handle indentation and tab
9 * positions using html tables.
13 This file is part of groff.
15 groff is free software; you can redistribute it and/or modify it under
16 the terms of the GNU General Public License as published by the Free
17 Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
20 groff is distributed in the hope that it will be useful, but WITHOUT ANY
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>. */
29 #include "stringclass.h"
31 #include "html-table.h"
34 #include "html-text.h"
43 extern html_dialect dialect;
57 * delete_list - frees the tab list and sets tab to NULL.
60 void tabs::delete_list (void)
62 tab_position *p = tab;
73 void tabs::clear (void)
79 * compatible - returns TRUE if the tab stops in, s, do
80 * not conflict with the current tab stops.
81 * The new tab stops are _not_ placed into
85 int tabs::compatible (const char *s)
89 tab_position *last = tab;
92 return FALSE; // no tab stops defined
95 while ((*s != (char)0) && !isspace(*s))
98 while (*s != (char)0 && last != NULL) {
99 // move over white space
100 while ((*s != (char)0) && isspace(*s))
104 // move over alignment
106 // move over white space
107 while ((*s != (char)0) && isspace(*s))
109 // collect tab position
111 // move over tab position
112 while ((*s != (char)0) && !isspace(*s))
114 if (last->alignment != align || last->position != total)
123 * init - scans the string, s, and initializes the tab stops.
126 void tabs::init (const char *s)
130 tab_position *last = NULL;
132 clear(); // remove any tab stops
134 // move over tag name
135 while ((*s != (char)0) && !isspace(*s))
138 while (*s != (char)0) {
139 // move over white space
140 while ((*s != (char)0) && isspace(*s))
144 // move over alignment
146 // move over white space
147 while ((*s != (char)0) && isspace(*s))
149 // collect tab position
151 // move over tab position
152 while ((*s != (char)0) && !isspace(*s))
155 tab = new tab_position;
158 last->next = new tab_position;
161 last->alignment = align;
162 last->position = total;
168 * check_init - define tab stops using, s, providing none already exist.
171 void tabs::check_init (const char *s)
178 * find_tab - returns the tab number corresponding to the position, pos.
181 int tabs::find_tab (int pos)
186 for (p = tab; p != NULL; p = p->next) {
188 if (p->position == pos)
195 * get_tab_pos - returns the, nth, tab position
198 int tabs::get_tab_pos (int n)
203 for (p = tab; (p != NULL) && (n>0); p = p->next) {
211 char tabs::get_tab_align (int n)
216 for (p = tab; (p != NULL) && (n>0); p = p->next) {
225 * dump_tab - display tab positions
228 void tabs::dump_tabs (void)
233 for (p = tab; p != NULL; p = p->next) {
234 printf("tab %d is %d\n", i, p->position);
240 * html_table - methods
243 html_table::html_table (simple_output *op, int linelen)
244 : out(op), columns(NULL), linelength(linelen), last_col(NULL), start_space(FALSE)
246 tab_stops = new tabs();
249 html_table::~html_table ()
252 if (tab_stops != NULL)
256 while (columns != NULL) {
257 columns = columns->next;
264 * remove_cols - remove a list of columns as defined by, c.
267 void html_table::remove_cols (cols *c)
279 * set_linelength - sets the line length value in this table.
280 * It also adds an extra blank column to the
281 * table should linelen exceed the last column.
284 void html_table::set_linelength (int linelen)
288 linelength = linelen;
290 for (c = columns; c != NULL; c = c->next) {
291 if (c->right > linelength) {
292 c->right = linelength;
293 remove_cols(c->next);
299 if (p != NULL && p->right > 0 && linelength > p->right)
300 add_column(p->no+1, p->right, linelength, 'L');
304 * get_effective_linelength -
307 int html_table::get_effective_linelength (void)
310 return linelength - columns->left;
316 * add_indent - adds the indent to a table.
319 void html_table::add_indent (int indent)
321 if (columns != NULL && columns->left > indent)
322 add_column(0, indent, columns->left, 'L');
326 * emit_table_header - emits the html header for this table.
329 void html_table::emit_table_header (int space)
337 if (linelength > 0) {
341 out->put_string("<table width=\"100%\"")
342 .put_string(" border=\"0\" rules=\"none\" frame=\"void\"\n")
343 .put_string(" cellspacing=\"0\" cellpadding=\"0\"");
346 if (dialect == xhtml)
348 out->put_string("<tr valign=\"top\" align=\"left\"");
350 out->put_string(" style=\"margin-top: ");
351 out->put_string(STYLE_VERTICAL_SPACE);
352 out->put_string("\"");
354 out->put_string(">").nl();
359 * get_right - returns the right most position of this column.
362 int html_table::get_right (cols *c)
364 if (c != NULL && c->right > 0)
372 * set_space - assigns start_space. Used to determine the
373 * vertical alignment when generating the next table row.
376 void html_table::set_space (int space)
382 * emit_colspan - emits a series of colspan entries defining the
386 void html_table::emit_colspan (void)
392 out->put_string("<colgroup>");
394 if (b != NULL && b != c && is_gap(b))
396 * blank column for gap
398 out->put_string("<col width=\"")
399 .put_number(is_gap(b))
400 .put_string("%\" class=\"center\"></col>")
403 width = (get_right(c)*100 + get_effective_linelength()/2)
404 / get_effective_linelength()
405 - (c->left*100 + get_effective_linelength()/2)
406 /get_effective_linelength();
407 switch (c->alignment) {
409 out->put_string("<col width=\"")
411 .put_string("%\" class=\"center\"></col>")
415 out->put_string("<col width=\"")
417 .put_string("%\" class=\"right\"></col>")
421 out->put_string("<col width=\"")
423 .put_string("%\"></col>")
429 out->put_string("</colgroup>").nl();
433 * emit_td - writes out a <td> tag with a corresponding width
434 * if the dialect is html4.
437 void html_table::emit_td (int percentage, const char *s)
440 if (dialect == html4) {
441 out->put_string("<td width=\"")
442 .put_number(percentage)
449 out->put_string("<td");
458 * emit_col - moves onto column, n.
461 void html_table::emit_col (int n)
467 // must be a different row
468 if (last_col != NULL && n <= last_col->no)
471 while (c != NULL && c->no < n)
474 // can we find column, n?
475 if (c != NULL && c->no == n) {
476 // shutdown previous column
477 if (last_col != NULL)
478 out->put_string("</td>").nl();
480 // find previous column
481 if (last_col == NULL)
487 if (last_col != NULL) {
488 emit_td(is_gap(b), "></td>");
492 // move across to column n
494 // we compute the difference after converting positions
495 // to avoid rounding errors
496 width = (get_right(b)*100 + get_effective_linelength()/2)
497 / get_effective_linelength()
498 - (b->left*100 + get_effective_linelength()/2)
499 /get_effective_linelength();
500 emit_td(width, "></td>");
502 emit_td(is_gap(b), "></td>");
505 width = (get_right(b)*100 + get_effective_linelength()/2)
506 / get_effective_linelength()
507 - (b->left*100 + get_effective_linelength()/2)
508 /get_effective_linelength();
509 switch (b->alignment) {
511 emit_td(width, " align=center>");
514 emit_td(width, " align=right>");
519 // remember column, b
528 void html_table::finish_row (void)
533 if (last_col != NULL) {
534 for (c = last_col->next; c != NULL; c = c->next)
540 if (last_col != NULL) {
541 out->put_string("</td>");
545 out->put_string("</tr>").nl();
550 * emit_new_row - move to the next row.
553 void html_table::emit_new_row (void)
557 out->put_string("<tr valign=\"top\" align=\"left\"");
559 out->put_string(" style=\"margin-top: ");
560 out->put_string(STYLE_VERTICAL_SPACE);
561 out->put_string("\"");
563 out->put_string(">").nl();
568 void html_table::emit_finish_table (void)
571 out->put_string("</table>");
575 * add_column - adds a column. It returns FALSE if hstart..hend
576 * crosses into a different columns.
579 int html_table::add_column (int coln, int hstart, int hend, char align)
581 cols *c = get_column(coln);
584 return insert_column(coln, hstart, hend, align);
586 return modify_column(c, hstart, hend, align);
590 * get_column - returns the column, coln.
593 cols *html_table::get_column (int coln)
597 while (c != NULL && coln != c->no)
600 if (c != NULL && coln == c->no)
607 * insert_column - inserts a column, coln.
608 * It returns TRUE if it does not bump into
612 int html_table::insert_column (int coln, int hstart, int hend, char align)
618 while (c != NULL && c->no < coln) {
622 if (l != NULL && l->no>coln && hend > l->left)
623 return FALSE; // new column bumps into previous one
627 while (c != NULL && c->no < coln) {
632 if ((l != NULL) && (hstart < l->right))
633 return FALSE; // new column bumps into previous one
635 if ((l != NULL) && (l->next != NULL) &&
636 (l->next->left < hend))
637 return FALSE; // new column bumps into next one
650 n->alignment = align;
655 * modify_column - given a column, c, modify the width to
656 * contain hstart..hend.
657 * It returns TRUE if it does not clash with
658 * the next or previous column.
661 int html_table::modify_column (cols *c, int hstart, int hend, char align)
665 while (l != NULL && l->next != c)
668 if ((l != NULL) && (hstart < l->right))
669 return FALSE; // new column bumps into previous one
671 if ((c->next != NULL) && (c->next->left < hend))
672 return FALSE; // new column bumps into next one
674 if (c->left > hstart)
680 c->alignment = align;
686 * find_tab_column - finds the column number for position, pos.
687 * It searches through the list tab stops.
690 int html_table::find_tab_column (int pos)
692 // remember the first column is reserved for untabbed glyphs
693 return tab_stops->find_tab(pos)+1;
697 * find_column - find the column number for position, pos.
698 * It searches through the list of columns.
701 int html_table::find_column (int pos)
706 for (c = columns; c != NULL; c = c->next) {
715 * no_columns - returns the number of table columns (rather than tabs)
718 int html_table::no_columns (void)
723 for (c = columns; c != NULL; c = c->next)
729 * is_gap - returns the gap between column, c, and the next column.
732 int html_table::is_gap (cols *c)
734 if (c == NULL || c->right <= 0 || c->next == NULL)
737 // we compute the difference after converting positions
738 // to avoid rounding errors
739 return (c->next->left*100 + get_effective_linelength()/2)
740 / get_effective_linelength()
741 - (c->right*100 + get_effective_linelength()/2)
742 / get_effective_linelength();
746 * no_gaps - returns the number of table gaps between the columns
749 int html_table::no_gaps (void)
754 for (c = columns; c != NULL; c = c->next)
761 * get_tab_pos - returns the, nth, tab position
764 int html_table::get_tab_pos (int n)
766 return tab_stops->get_tab_pos(n);
769 char html_table::get_tab_align (int n)
771 return tab_stops->get_tab_align(n);
775 void html_table::dump_table (void)
777 if (columns != NULL) {
779 for (c = columns; c != NULL; c = c->next) {
780 printf("column %d %d..%d %c\n", c->no, c->left, c->right, c->alignment);
783 tab_stops->dump_tabs();
787 * html_indent - creates an indent with indentation, ind, given
788 * a line length of linelength.
791 html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linelength)
793 table = new html_table(op, linelength);
795 table->add_column(1, ind+pageoffset, linelength, 'L');
796 table->add_indent(pageoffset);
802 html_indent::~html_indent (void)
808 void html_indent::begin (int space)
812 table->out->put_string(" style=\"margin-top: ");
813 table->out->put_string(STYLE_VERTICAL_SPACE);
814 table->out->put_string("\"");
819 // we use exactly the same mechanism for calculating
820 // indentation as html_table::emit_col
822 table->out->put_string(" style=\"margin-left:")
823 .put_number(((in + pg) * 100 + ll/2) / ll -
828 table->out->put_string(" margin-top: ");
829 table->out->put_string(STYLE_VERTICAL_SPACE);
831 table->out->put_string("\"");
835 void html_indent::end (void)
840 * get_reg - collects the registers as supplied during initialization.
843 void html_indent::get_reg (int *ind, int *pageoffset, int *linelength)