2 /* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009
3 * Free Software Foundation, Inc.
5 * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp
9 * provides the methods necessary to handle indentation and tab
10 * positions using html tables.
14 This file is part of groff.
16 groff is free software; you can redistribute it and/or modify it under
17 the terms of the GNU General Public License as published by the Free
18 Software Foundation, either version 3 of the License, or
19 (at your option) any later version.
21 groff is distributed in the hope that it will be useful, but WITHOUT ANY
22 WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>. */
30 #include "stringclass.h"
32 #include "html-table.h"
35 #include "html-text.h"
44 extern html_dialect dialect;
58 * delete_list - frees the tab list and sets tab to NULL.
61 void tabs::delete_list (void)
63 tab_position *p = tab;
74 void tabs::clear (void)
80 * compatible - returns TRUE if the tab stops in, s, do
81 * not conflict with the current tab stops.
82 * The new tab stops are _not_ placed into
86 int tabs::compatible (const char *s)
90 tab_position *last = tab;
93 return FALSE; // no tab stops defined
96 while ((*s != (char)0) && !isspace(*s))
99 while (*s != (char)0 && last != NULL) {
100 // move over white space
101 while ((*s != (char)0) && isspace(*s))
105 // move over alignment
107 // move over white space
108 while ((*s != (char)0) && isspace(*s))
110 // collect tab position
112 // move over tab position
113 while ((*s != (char)0) && !isspace(*s))
115 if (last->alignment != align || last->position != total)
124 * init - scans the string, s, and initializes the tab stops.
127 void tabs::init (const char *s)
131 tab_position *last = NULL;
133 clear(); // remove any tab stops
135 // move over tag name
136 while ((*s != (char)0) && !isspace(*s))
139 while (*s != (char)0) {
140 // move over white space
141 while ((*s != (char)0) && isspace(*s))
145 // move over alignment
147 // move over white space
148 while ((*s != (char)0) && isspace(*s))
150 // collect tab position
152 // move over tab position
153 while ((*s != (char)0) && !isspace(*s))
156 tab = new tab_position;
159 last->next = new tab_position;
162 last->alignment = align;
163 last->position = total;
169 * check_init - define tab stops using, s, providing none already exist.
172 void tabs::check_init (const char *s)
179 * find_tab - returns the tab number corresponding to the position, pos.
182 int tabs::find_tab (int pos)
187 for (p = tab; p != NULL; p = p->next) {
189 if (p->position == pos)
196 * get_tab_pos - returns the, nth, tab position
199 int tabs::get_tab_pos (int n)
204 for (p = tab; (p != NULL) && (n>0); p = p->next) {
212 char tabs::get_tab_align (int n)
217 for (p = tab; (p != NULL) && (n>0); p = p->next) {
226 * dump_tab - display tab positions
229 void tabs::dump_tabs (void)
234 for (p = tab; p != NULL; p = p->next) {
235 printf("tab %d is %d\n", i, p->position);
241 * html_table - methods
244 html_table::html_table (simple_output *op, int linelen)
245 : out(op), columns(NULL), linelength(linelen), last_col(NULL), start_space(FALSE)
247 tab_stops = new tabs();
250 html_table::~html_table ()
253 if (tab_stops != NULL)
257 while (columns != NULL) {
258 columns = columns->next;
265 * remove_cols - remove a list of columns as defined by, c.
268 void html_table::remove_cols (cols *c)
280 * set_linelength - sets the line length value in this table.
281 * It also adds an extra blank column to the
282 * table should linelen exceed the last column.
285 void html_table::set_linelength (int linelen)
289 linelength = linelen;
291 for (c = columns; c != NULL; c = c->next) {
292 if (c->right > linelength) {
293 c->right = linelength;
294 remove_cols(c->next);
300 if (p != NULL && p->right > 0 && linelength > p->right)
301 add_column(p->no+1, p->right, linelength, 'L');
305 * get_effective_linelength -
308 int html_table::get_effective_linelength (void)
311 return linelength - columns->left;
317 * add_indent - adds the indent to a table.
320 void html_table::add_indent (int indent)
322 if (columns != NULL && columns->left > indent)
323 add_column(0, indent, columns->left, 'L');
327 * emit_table_header - emits the html header for this table.
330 void html_table::emit_table_header (int space)
338 if (linelength > 0) {
342 out->put_string("<table width=\"100%\"")
343 .put_string(" border=\"0\" rules=\"none\" frame=\"void\"\n")
344 .put_string(" cellspacing=\"0\" cellpadding=\"0\"");
347 if (dialect == xhtml)
349 out->put_string("<tr valign=\"top\" align=\"left\"");
351 out->put_string(" style=\"margin-top: ");
352 out->put_string(STYLE_VERTICAL_SPACE);
353 out->put_string("\"");
355 out->put_string(">").nl();
360 * get_right - returns the right most position of this column.
363 int html_table::get_right (cols *c)
365 if (c != NULL && c->right > 0)
373 * set_space - assigns start_space. Used to determine the
374 * vertical alignment when generating the next table row.
377 void html_table::set_space (int space)
383 * emit_colspan - emits a series of colspan entries defining the
387 void html_table::emit_colspan (void)
393 out->put_string("<colgroup>");
395 if (b != NULL && b != c && is_gap(b))
397 * blank column for gap
399 out->put_string("<col width=\"")
400 .put_number(is_gap(b))
401 .put_string("%\" class=\"center\"></col>")
404 width = (get_right(c)*100 + get_effective_linelength()/2)
405 / get_effective_linelength()
406 - (c->left*100 + get_effective_linelength()/2)
407 /get_effective_linelength();
408 switch (c->alignment) {
410 out->put_string("<col width=\"")
412 .put_string("%\" class=\"center\"></col>")
416 out->put_string("<col width=\"")
418 .put_string("%\" class=\"right\"></col>")
422 out->put_string("<col width=\"")
424 .put_string("%\"></col>")
430 out->put_string("</colgroup>").nl();
434 * emit_td - writes out a <td> tag with a corresponding width
435 * if the dialect is html4.
438 void html_table::emit_td (int percentage, const char *s)
441 if (dialect == html4) {
442 out->put_string("<td width=\"")
443 .put_number(percentage)
450 out->put_string("<td");
459 * emit_col - moves onto column, n.
462 void html_table::emit_col (int n)
468 // must be a different row
469 if (last_col != NULL && n <= last_col->no)
472 while (c != NULL && c->no < n)
475 // can we find column, n?
476 if (c != NULL && c->no == n) {
477 // shutdown previous column
478 if (last_col != NULL)
479 out->put_string("</td>").nl();
481 // find previous column
482 if (last_col == NULL)
488 if (last_col != NULL) {
489 emit_td(is_gap(b), "></td>");
493 // move across to column n
495 // we compute the difference after converting positions
496 // to avoid rounding errors
497 width = (get_right(b)*100 + get_effective_linelength()/2)
498 / get_effective_linelength()
499 - (b->left*100 + get_effective_linelength()/2)
500 /get_effective_linelength();
501 emit_td(width, "></td>");
503 emit_td(is_gap(b), "></td>");
506 width = (get_right(b)*100 + get_effective_linelength()/2)
507 / get_effective_linelength()
508 - (b->left*100 + get_effective_linelength()/2)
509 /get_effective_linelength();
510 switch (b->alignment) {
512 emit_td(width, " align=center>");
515 emit_td(width, " align=right>");
520 // remember column, b
529 void html_table::finish_row (void)
534 if (last_col != NULL) {
535 for (c = last_col->next; c != NULL; c = c->next)
541 if (last_col != NULL) {
542 out->put_string("</td>");
546 out->put_string("</tr>").nl();
551 * emit_new_row - move to the next row.
554 void html_table::emit_new_row (void)
558 out->put_string("<tr valign=\"top\" align=\"left\"");
560 out->put_string(" style=\"margin-top: ");
561 out->put_string(STYLE_VERTICAL_SPACE);
562 out->put_string("\"");
564 out->put_string(">").nl();
569 void html_table::emit_finish_table (void)
572 out->put_string("</table>");
576 * add_column - adds a column. It returns FALSE if hstart..hend
577 * crosses into a different columns.
580 int html_table::add_column (int coln, int hstart, int hend, char align)
582 cols *c = get_column(coln);
585 return insert_column(coln, hstart, hend, align);
587 return modify_column(c, hstart, hend, align);
591 * get_column - returns the column, coln.
594 cols *html_table::get_column (int coln)
598 while (c != NULL && coln != c->no)
601 if (c != NULL && coln == c->no)
608 * insert_column - inserts a column, coln.
609 * It returns TRUE if it does not bump into
613 int html_table::insert_column (int coln, int hstart, int hend, char align)
619 while (c != NULL && c->no < coln) {
623 if (l != NULL && l->no>coln && hend > l->left)
624 return FALSE; // new column bumps into previous one
628 while (c != NULL && c->no < coln) {
633 if ((l != NULL) && (hstart < l->right))
634 return FALSE; // new column bumps into previous one
636 if ((l != NULL) && (l->next != NULL) &&
637 (l->next->left < hend))
638 return FALSE; // new column bumps into next one
651 n->alignment = align;
656 * modify_column - given a column, c, modify the width to
657 * contain hstart..hend.
658 * It returns TRUE if it does not clash with
659 * the next or previous column.
662 int html_table::modify_column (cols *c, int hstart, int hend, char align)
666 while (l != NULL && l->next != c)
669 if ((l != NULL) && (hstart < l->right))
670 return FALSE; // new column bumps into previous one
672 if ((c->next != NULL) && (c->next->left < hend))
673 return FALSE; // new column bumps into next one
675 if (c->left > hstart)
681 c->alignment = align;
687 * find_tab_column - finds the column number for position, pos.
688 * It searches through the list tab stops.
691 int html_table::find_tab_column (int pos)
693 // remember the first column is reserved for untabbed glyphs
694 return tab_stops->find_tab(pos)+1;
698 * find_column - find the column number for position, pos.
699 * It searches through the list of columns.
702 int html_table::find_column (int pos)
707 for (c = columns; c != NULL; c = c->next) {
716 * no_columns - returns the number of table columns (rather than tabs)
719 int html_table::no_columns (void)
724 for (c = columns; c != NULL; c = c->next)
730 * is_gap - returns the gap between column, c, and the next column.
733 int html_table::is_gap (cols *c)
735 if (c == NULL || c->right <= 0 || c->next == NULL)
738 // we compute the difference after converting positions
739 // to avoid rounding errors
740 return (c->next->left*100 + get_effective_linelength()/2)
741 / get_effective_linelength()
742 - (c->right*100 + get_effective_linelength()/2)
743 / get_effective_linelength();
747 * no_gaps - returns the number of table gaps between the columns
750 int html_table::no_gaps (void)
755 for (c = columns; c != NULL; c = c->next)
762 * get_tab_pos - returns the, nth, tab position
765 int html_table::get_tab_pos (int n)
767 return tab_stops->get_tab_pos(n);
770 char html_table::get_tab_align (int n)
772 return tab_stops->get_tab_align(n);
776 void html_table::dump_table (void)
778 if (columns != NULL) {
780 for (c = columns; c != NULL; c = c->next) {
781 printf("column %d %d..%d %c\n", c->no, c->left, c->right, c->alignment);
784 tab_stops->dump_tabs();
788 * html_indent - creates an indent with indentation, ind, given
789 * a line length of linelength.
792 html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linelength)
794 table = new html_table(op, linelength);
796 table->add_column(1, ind+pageoffset, linelength, 'L');
797 table->add_indent(pageoffset);
803 html_indent::~html_indent (void)
809 void html_indent::begin (int space)
813 table->out->put_string(" style=\"margin-top: ");
814 table->out->put_string(STYLE_VERTICAL_SPACE);
815 table->out->put_string("\"");
820 // we use exactly the same mechanism for calculating
821 // indentation as html_table::emit_col
823 table->out->put_string(" style=\"margin-left:")
824 .put_number(((in + pg) * 100 + ll/2) / ll -
829 table->out->put_string(" margin-top: ");
830 table->out->put_string(STYLE_VERTICAL_SPACE);
832 table->out->put_string("\"");
836 void html_indent::end (void)
841 * get_reg - collects the registers as supplied during initialization.
844 void html_indent::get_reg (int *ind, int *pageoffset, int *linelength)