1 /*@ Implementation of html_table.h.
3 * Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
5 * Copyright (C) 2002 - 2005, 2007 Free Software Foundation, Inc.
6 * Written by Gaius Mulley (gaius@glam.ac.uk)
9 * This is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2, or (at your option) any later
14 * This is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * You should have received a copy of the GNU General Public License along
20 * with groff; see the file COPYING. If not, write to the Free Software
21 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "html-config.h"
31 #include "stringclass.h"
34 #include "html-table.h"
35 #include "html-text.h"
37 extern html_dialect dialect
;
50 * delete_list - frees the tab list and sets tab to NULL.
53 void tabs::delete_list (void)
55 tab_position
*p
= tab
;
66 void tabs::clear (void)
72 * compatible - returns true if the tab stops in, s, do
73 * not conflict with the current tab stops.
74 * The new tab stops are _not_ placed into
78 int tabs::compatible (const char *s
)
82 tab_position
*last
= tab
;
85 return false; // no tab stops defined
88 while ((*s
!= (char)0) && !isspace(*s
))
91 while (*s
!= (char)0 && last
!= NULL
) {
92 // move over white space
93 while ((*s
!= (char)0) && isspace(*s
))
97 // move over alignment
99 // move over white space
100 while ((*s
!= (char)0) && isspace(*s
))
102 // collect tab position
104 // move over tab position
105 while ((*s
!= (char)0) && !isspace(*s
))
107 if (last
->alignment
!= align
|| last
->position
!= total
)
116 * init - scans the string, s, and initializes the tab stops.
119 void tabs::init (const char *s
)
123 tab_position
*last
= NULL
;
125 clear(); // remove any tab stops
127 // move over tag name
128 while ((*s
!= (char)0) && !isspace(*s
))
131 while (*s
!= (char)0) {
132 // move over white space
133 while ((*s
!= (char)0) && isspace(*s
))
137 // move over alignment
139 // move over white space
140 while ((*s
!= (char)0) && isspace(*s
))
142 // collect tab position
144 // move over tab position
145 while ((*s
!= (char)0) && !isspace(*s
))
148 tab
= new tab_position
;
151 last
->next
= new tab_position
;
154 last
->alignment
= align
;
155 last
->position
= total
;
161 * check_init - define tab stops using, s, providing none already exist.
164 void tabs::check_init (const char *s
)
171 * find_tab - returns the tab number corresponding to the position, pos.
174 int tabs::find_tab (int pos
)
179 for (p
= tab
; p
!= NULL
; p
= p
->next
) {
181 if (p
->position
== pos
)
188 * get_tab_pos - returns the, nth, tab position
191 int tabs::get_tab_pos (int n
)
196 for (p
= tab
; (p
!= NULL
) && (n
>0); p
= p
->next
) {
204 char tabs::get_tab_align (int n
)
209 for (p
= tab
; (p
!= NULL
) && (n
>0); p
= p
->next
) {
218 * dump_tab - display tab positions
221 void tabs::dump_tabs (void)
226 for (p
= tab
; p
!= NULL
; p
= p
->next
) {
227 printf("tab %d is %d\n", i
, p
->position
);
233 * html_table - methods
236 html_table::html_table (simple_output
*op
, int linelen
)
237 : out(op
), columns(NULL
), linelength(linelen
), last_col(NULL
), start_space(false)
239 tab_stops
= new tabs();
242 html_table::~html_table ()
245 if (tab_stops
!= NULL
)
249 while (columns
!= NULL
) {
250 columns
= columns
->next
;
257 * remove_cols - remove a list of columns as defined by, c.
260 void html_table::remove_cols (cols
*c
)
272 * set_linelength - sets the line length value in this table.
273 * It also adds an extra blank column to the
274 * table should linelen exceed the last column.
277 void html_table::set_linelength (int linelen
)
281 linelength
= linelen
;
283 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
284 if (c
->right
> linelength
) {
285 c
->right
= linelength
;
286 remove_cols(c
->next
);
292 if (p
!= NULL
&& p
->right
> 0 && linelength
> p
->right
)
293 add_column(p
->no
+1, p
->right
, linelength
, 'L');
297 * get_effective_linelength -
300 int html_table::get_effective_linelength (void)
303 return linelength
- columns
->left
;
309 * add_indent - adds the indent to a table.
312 void html_table::add_indent (int indent
)
314 if (columns
!= NULL
&& columns
->left
> indent
)
315 add_column(0, indent
, columns
->left
, 'L');
319 * emit_table_header - emits the html header for this table.
322 void html_table::emit_table_header (int space
)
330 if (linelength
> 0) {
334 out
->put_string("<table width=\"100%\"")
335 .put_string(" border=\"0\" rules=\"none\" frame=\"void\"\n")
336 .put_string(" cellspacing=\"0\" cellpadding=\"0\"");
339 if (dialect
== xhtml
)
341 out
->put_string("<tr valign=\"top\" align=\"left\"");
343 out
->put_string(" style=\"margin-top: ");
344 out
->put_string(STYLE_VERTICAL_SPACE
);
345 out
->put_string("\"");
347 out
->put_string(">").nl();
352 * get_right - returns the right most position of this column.
355 int html_table::get_right (cols
*c
)
357 if (c
!= NULL
&& c
->right
> 0)
365 * set_space - assigns start_space. Used to determine the
366 * vertical alignment when generating the next table row.
369 void html_table::set_space (int space
)
375 * emit_colspan - emits a series of colspan entries defining the
379 void html_table::emit_colspan (void)
385 out
->put_string("<colgroup>");
387 if (b
!= NULL
&& b
!= c
&& is_gap(b
))
389 * blank column for gap
391 out
->put_string("<col width=\"")
392 .put_number(is_gap(b
))
393 .put_string("%\" class=\"center\"></col>")
396 width
= (get_right(c
)*100 + get_effective_linelength()/2)
397 / get_effective_linelength()
398 - (c
->left
*100 + get_effective_linelength()/2)
399 /get_effective_linelength();
400 switch (c
->alignment
) {
402 out
->put_string("<col width=\"")
404 .put_string("%\" class=\"center\"></col>")
408 out
->put_string("<col width=\"")
410 .put_string("%\" class=\"right\"></col>")
414 out
->put_string("<col width=\"")
416 .put_string("%\"></col>")
422 out
->put_string("</colgroup>").nl();
426 * emit_td - writes out a <td> tag with a corresponding width
427 * if the dialect is html4.
430 void html_table::emit_td (int percentage
, const char *s
)
433 if (dialect
== html4
) {
434 out
->put_string("<td width=\"")
435 .put_number(percentage
)
442 out
->put_string("<td");
451 * emit_col - moves onto column, n.
454 void html_table::emit_col (int n
)
460 // must be a different row
461 if (last_col
!= NULL
&& n
<= last_col
->no
)
464 while (c
!= NULL
&& c
->no
< n
)
467 // can we find column, n?
468 if (c
!= NULL
&& c
->no
== n
) {
469 // shutdown previous column
470 if (last_col
!= NULL
)
471 out
->put_string("</td>").nl();
473 // find previous column
474 if (last_col
== NULL
)
480 if (last_col
!= NULL
) {
481 emit_td(is_gap(b
), "></td>");
485 // move across to column n
487 // we compute the difference after converting positions
488 // to avoid rounding errors
489 width
= (get_right(b
)*100 + get_effective_linelength()/2)
490 / get_effective_linelength()
491 - (b
->left
*100 + get_effective_linelength()/2)
492 /get_effective_linelength();
493 emit_td(width
, "></td>");
495 emit_td(is_gap(b
), "></td>");
498 width
= (get_right(b
)*100 + get_effective_linelength()/2)
499 / get_effective_linelength()
500 - (b
->left
*100 + get_effective_linelength()/2)
501 /get_effective_linelength();
502 switch (b
->alignment
) {
504 emit_td(width
, " align=center>");
507 emit_td(width
, " align=right>");
512 // remember column, b
521 void html_table::finish_row (void)
526 if (last_col
!= NULL
) {
527 for (c
= last_col
->next
; c
!= NULL
; c
= c
->next
)
533 if (last_col
!= NULL
) {
534 out
->put_string("</td>");
538 out
->put_string("</tr>").nl();
543 * emit_new_row - move to the next row.
546 void html_table::emit_new_row (void)
550 out
->put_string("<tr valign=\"top\" align=\"left\"");
552 out
->put_string(" style=\"margin-top: ");
553 out
->put_string(STYLE_VERTICAL_SPACE
);
554 out
->put_string("\"");
556 out
->put_string(">").nl();
561 void html_table::emit_finish_table (void)
564 out
->put_string("</table>");
568 * add_column - adds a column. It returns false if hstart..hend
569 * crosses into a different columns.
572 int html_table::add_column (int coln
, int hstart
, int hend
, char align
)
574 cols
*c
= get_column(coln
);
577 return insert_column(coln
, hstart
, hend
, align
);
579 return modify_column(c
, hstart
, hend
, align
);
583 * get_column - returns the column, coln.
586 cols
*html_table::get_column (int coln
)
590 while (c
!= NULL
&& coln
!= c
->no
)
593 if (c
!= NULL
&& coln
== c
->no
)
600 * insert_column - inserts a column, coln.
601 * It returns true if it does not bump into
605 int html_table::insert_column (int coln
, int hstart
, int hend
, char align
)
611 while (c
!= NULL
&& c
->no
< coln
) {
615 if (l
!= NULL
&& l
->no
>coln
&& hend
> l
->left
)
616 return false; // new column bumps into previous one
620 while (c
!= NULL
&& c
->no
< coln
) {
625 if ((l
!= NULL
) && (hstart
< l
->right
))
626 return false; // new column bumps into previous one
628 if ((l
!= NULL
) && (l
->next
!= NULL
) &&
629 (l
->next
->left
< hend
))
630 return false; // new column bumps into next one
643 n
->alignment
= align
;
648 * modify_column - given a column, c, modify the width to
649 * contain hstart..hend.
650 * It returns true if it does not clash with
651 * the next or previous column.
654 int html_table::modify_column (cols
*c
, int hstart
, int hend
, char align
)
658 while (l
!= NULL
&& l
->next
!= c
)
661 if ((l
!= NULL
) && (hstart
< l
->right
))
662 return false; // new column bumps into previous one
664 if ((c
->next
!= NULL
) && (c
->next
->left
< hend
))
665 return false; // new column bumps into next one
667 if (c
->left
> hstart
)
673 c
->alignment
= align
;
679 * find_tab_column - finds the column number for position, pos.
680 * It searches through the list tab stops.
683 int html_table::find_tab_column (int pos
)
685 // remember the first column is reserved for untabbed glyphs
686 return tab_stops
->find_tab(pos
)+1;
690 * find_column - find the column number for position, pos.
691 * It searches through the list of columns.
694 int html_table::find_column (int pos
)
699 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
708 * no_columns - returns the number of table columns (rather than tabs)
711 int html_table::no_columns (void)
716 for (c
= columns
; c
!= NULL
; c
= c
->next
)
722 * is_gap - returns the gap between column, c, and the next column.
725 int html_table::is_gap (cols
*c
)
727 if (c
== NULL
|| c
->right
<= 0 || c
->next
== NULL
)
730 // we compute the difference after converting positions
731 // to avoid rounding errors
732 return (c
->next
->left
*100 + get_effective_linelength()/2)
733 / get_effective_linelength()
734 - (c
->right
*100 + get_effective_linelength()/2)
735 / get_effective_linelength();
739 * no_gaps - returns the number of table gaps between the columns
742 int html_table::no_gaps (void)
747 for (c
= columns
; c
!= NULL
; c
= c
->next
)
754 * get_tab_pos - returns the, nth, tab position
757 int html_table::get_tab_pos (int n
)
759 return tab_stops
->get_tab_pos(n
);
762 char html_table::get_tab_align (int n
)
764 return tab_stops
->get_tab_align(n
);
768 void html_table::dump_table (void)
770 if (columns
!= NULL
) {
772 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
773 printf("column %d %d..%d %c\n", c
->no
, c
->left
, c
->right
, c
->alignment
);
776 tab_stops
->dump_tabs();
780 * html_indent - creates an indent with indentation, ind, given
781 * a line length of linelength.
784 html_indent::html_indent (simple_output
*op
, int ind
, int pageoffset
, int linelength
)
786 table
= new html_table(op
, linelength
);
788 table
->add_column(1, ind
+pageoffset
, linelength
, 'L');
789 table
->add_indent(pageoffset
);
795 html_indent::~html_indent (void)
801 void html_indent::begin (int space
)
805 table
->out
->put_string(" style=\"margin-top: ");
806 table
->out
->put_string(STYLE_VERTICAL_SPACE
);
807 table
->out
->put_string("\"");
812 // we use exactly the same mechanism for calculating
813 // indentation as html_table::emit_col
815 table
->out
->put_string(" style=\"margin-left:")
816 .put_number(((in
+ pg
) * 100 + ll
/2) / ll
-
821 table
->out
->put_string(" margin-top: ");
822 table
->out
->put_string(STYLE_VERTICAL_SPACE
);
824 table
->out
->put_string("\"");
828 void html_indent::end (void)
833 * get_reg - collects the registers as supplied during initialization.
835 void html_indent::get_reg (int *ind
, int *pageoffset
, int *linelength
)