2 /* Copyright (C) 2002, 2003, 2004, 2005 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 2, or (at your option) any later
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 along
26 with groff; see the file COPYING. If not, write to the Free Software
27 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
30 #include "stringclass.h"
32 #include "html-table.h"
35 #include "html-text.h"
55 * delete_list - frees the tab list and sets tab to NULL.
58 void tabs::delete_list (void)
60 tab_position
*p
= tab
;
71 void tabs::clear (void)
77 * compatible - returns TRUE if the tab stops in, s, do
78 * not conflict with the current tab stops.
79 * The new tab stops are _not_ placed into
83 int tabs::compatible (const char *s
)
87 tab_position
*last
= tab
;
90 return FALSE
; // no tab stops defined
93 while ((*s
!= (char)0) && !isspace(*s
))
96 while (*s
!= (char)0 && last
!= NULL
) {
97 // move over white space
98 while ((*s
!= (char)0) && isspace(*s
))
102 // move over alignment
104 // move over white space
105 while ((*s
!= (char)0) && isspace(*s
))
107 // collect tab position
109 // move over tab position
110 while ((*s
!= (char)0) && !isspace(*s
))
112 if (last
->alignment
!= align
|| last
->position
!= total
)
121 * init - scans the string, s, and initializes the tab stops.
124 void tabs::init (const char *s
)
128 tab_position
*last
= NULL
;
130 clear(); // remove any tab stops
132 // move over tag name
133 while ((*s
!= (char)0) && !isspace(*s
))
136 while (*s
!= (char)0) {
137 // move over white space
138 while ((*s
!= (char)0) && isspace(*s
))
142 // move over alignment
144 // move over white space
145 while ((*s
!= (char)0) && isspace(*s
))
147 // collect tab position
149 // move over tab position
150 while ((*s
!= (char)0) && !isspace(*s
))
153 tab
= new tab_position
;
156 last
->next
= new tab_position
;
159 last
->alignment
= align
;
160 last
->position
= total
;
166 * check_init - define tab stops using, s, providing none already exist.
169 void tabs::check_init (const char *s
)
176 * find_tab - returns the tab number corresponding to the position, pos.
179 int tabs::find_tab (int pos
)
184 for (p
= tab
; p
!= NULL
; p
= p
->next
) {
186 if (p
->position
== pos
)
193 * get_tab_pos - returns the, nth, tab position
196 int tabs::get_tab_pos (int n
)
201 for (p
= tab
; (p
!= NULL
) && (n
>0); p
= p
->next
) {
209 char tabs::get_tab_align (int n
)
214 for (p
= tab
; (p
!= NULL
) && (n
>0); p
= p
->next
) {
223 * dump_tab - display tab positions
226 void tabs::dump_tabs (void)
231 for (p
= tab
; p
!= NULL
; p
= p
->next
) {
232 printf("tab %d is %d\n", i
, p
->position
);
238 * html_table - methods
241 html_table::html_table (simple_output
*op
, int linelen
)
242 : out(op
), columns(NULL
), linelength(linelen
), last_col(NULL
), start_space(FALSE
)
244 tab_stops
= new tabs();
247 html_table::~html_table ()
250 if (tab_stops
!= NULL
)
254 while (columns
!= NULL
) {
255 columns
= columns
->next
;
262 * remove_cols - remove a list of columns as defined by, c.
265 void html_table::remove_cols (cols
*c
)
277 * set_linelength - sets the line length value in this table.
278 * It also adds an extra blank column to the
279 * table should linelen exceed the last column.
282 void html_table::set_linelength (int linelen
)
286 linelength
= linelen
;
288 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
289 if (c
->right
> linelength
) {
290 c
->right
= linelength
;
291 remove_cols(c
->next
);
297 if (p
!= NULL
&& p
->right
> 0)
298 add_column(p
->no
+1, p
->right
, linelength
, 'L');
302 * get_effective_linelength -
305 int html_table::get_effective_linelength (void)
308 return linelength
- columns
->left
;
314 * add_indent - adds the indent to a table.
317 void html_table::add_indent (int indent
)
319 if (columns
!= NULL
&& columns
->left
> indent
)
320 add_column(0, indent
, columns
->left
, 'L');
324 * emit_table_header - emits the html header for this table.
327 void html_table::emit_table_header (int space
)
335 if (linelength
> 0) {
339 out
->put_string("<table width=\"100%\"")
340 .put_string(" border=0 rules=\"none\" frame=\"void\"\n")
341 .put_string(" cellspacing=\"0\" cellpadding=\"0\"");
344 out
->put_string("<tr valign=\"top\" align=\"left\"");
346 out
->put_string(" style=\"margin-top: ");
347 out
->put_string(STYLE_VERTICAL_SPACE
);
348 out
->put_string("\"");
350 out
->put_string(">").nl();
355 * get_right - returns the right most position of this column.
358 int html_table::get_right (cols
*c
)
360 if (c
!= NULL
&& c
->right
> 0)
368 * set_space - assigns start_space. Used to determine the
369 * vertical alignment when generating the next table row.
372 void html_table::set_space (int space
)
378 * emit_col - moves onto column, n.
381 void html_table::emit_col (int n
)
387 // must be a different row
388 if (last_col
!= NULL
&& n
<= last_col
->no
)
391 while (c
!= NULL
&& c
->no
< n
)
394 // can we find column, n?
395 if (c
!= NULL
&& c
->no
== n
) {
396 // shutdown previous column
397 if (last_col
!= NULL
)
398 out
->put_string("</td>").nl();
400 // find previous column
401 if (last_col
== NULL
)
407 if (last_col
!= NULL
) {
409 out
->put_string("<td width=\"")
410 .put_number(is_gap(b
))
411 .put_string("%\"></td>")
416 // move across to column n
418 // we compute the difference after converting positions
419 // to avoid rounding errors
420 width
= (get_right(b
)*100 + get_effective_linelength()/2)
421 / get_effective_linelength()
422 - (b
->left
*100 + get_effective_linelength()/2)
423 /get_effective_linelength();
425 out
->put_string("<td width=\"")
427 .put_string("%\"></td>")
431 out
->put_string("<td width=\"")
432 .put_number(is_gap(b
))
433 .put_string("%\"></td>")
437 width
= (get_right(b
)*100 + get_effective_linelength()/2)
438 / get_effective_linelength()
439 - (b
->left
*100 + get_effective_linelength()/2)
440 /get_effective_linelength();
441 switch (b
->alignment
) {
443 out
->put_string("<td width=\"")
445 .put_string("%\" align=center>")
449 out
->put_string("<td width=\"")
451 .put_string("%\" align=right>")
455 out
->put_string("<td width=\"")
460 // remember column, b
469 void html_table::finish_row (void)
474 if (last_col
!= NULL
) {
475 for (c
= last_col
->next
; c
!= NULL
; c
= c
->next
)
480 out
->put_string("</td>").nl();
485 * emit_new_row - move to the next row.
488 void html_table::emit_new_row (void)
492 out
->put_string("<tr valign=\"top\" align=\"left\"");
494 out
->put_string(" style=\"margin-top: ");
495 out
->put_string(STYLE_VERTICAL_SPACE
);
496 out
->put_string("\"");
498 out
->put_string(">").nl();
503 void html_table::emit_finish_table (void)
506 out
->put_string("</table>");
510 * add_column - adds a column. It returns FALSE if hstart..hend
511 * crosses into a different columns.
514 int html_table::add_column (int coln
, int hstart
, int hend
, char align
)
516 cols
*c
= get_column(coln
);
519 return insert_column(coln
, hstart
, hend
, align
);
521 return modify_column(c
, hstart
, hend
, align
);
525 * get_column - returns the column, coln.
528 cols
*html_table::get_column (int coln
)
532 while (c
!= NULL
&& coln
!= c
->no
)
535 if (c
!= NULL
&& coln
== c
->no
)
542 * insert_column - inserts a column, coln.
543 * It returns TRUE if it does not bump into
547 int html_table::insert_column (int coln
, int hstart
, int hend
, char align
)
553 while (c
!= NULL
&& c
->no
< coln
) {
557 if (l
!= NULL
&& l
->no
>coln
&& hend
> l
->left
)
558 return FALSE
; // new column bumps into previous one
562 while (c
!= NULL
&& c
->no
< coln
) {
567 if ((l
!= NULL
) && (hstart
< l
->right
))
568 return FALSE
; // new column bumps into previous one
570 if ((l
!= NULL
) && (l
->next
!= NULL
) &&
571 (l
->next
->left
< hend
))
572 return FALSE
; // new column bumps into next one
585 n
->alignment
= align
;
590 * modify_column - given a column, c, modify the width to
591 * contain hstart..hend.
592 * It returns TRUE if it does not clash with
593 * the next or previous column.
596 int html_table::modify_column (cols
*c
, int hstart
, int hend
, char align
)
600 while (l
!= NULL
&& l
->next
!= c
)
603 if ((l
!= NULL
) && (hstart
< l
->right
))
604 return FALSE
; // new column bumps into previous one
606 if ((c
->next
!= NULL
) && (c
->next
->left
< hend
))
607 return FALSE
; // new column bumps into next one
609 if (c
->left
> hstart
)
615 c
->alignment
= align
;
621 * find_tab_column - finds the column number for position, pos.
622 * It searches through the list tab stops.
625 int html_table::find_tab_column (int pos
)
627 // remember the first column is reserved for untabbed glyphs
628 return tab_stops
->find_tab(pos
)+1;
632 * find_column - find the column number for position, pos.
633 * It searches through the list of columns.
636 int html_table::find_column (int pos
)
641 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
650 * no_columns - returns the number of table columns (rather than tabs)
653 int html_table::no_columns (void)
658 for (c
= columns
; c
!= NULL
; c
= c
->next
)
664 * is_gap - returns the gap between column, c, and the next column.
667 int html_table::is_gap (cols
*c
)
669 if (c
== NULL
|| c
->right
<= 0 || c
->next
== NULL
)
672 // we compute the difference after converting positions
673 // to avoid rounding errors
674 return (c
->next
->left
*100 + get_effective_linelength()/2)
675 / get_effective_linelength()
676 - (c
->right
*100 + get_effective_linelength()/2)
677 / get_effective_linelength();
681 * no_gaps - returns the number of table gaps between the columns
684 int html_table::no_gaps (void)
689 for (c
= columns
; c
!= NULL
; c
= c
->next
)
696 * get_tab_pos - returns the, nth, tab position
699 int html_table::get_tab_pos (int n
)
701 return tab_stops
->get_tab_pos(n
);
704 char html_table::get_tab_align (int n
)
706 return tab_stops
->get_tab_align(n
);
710 void html_table::dump_table (void)
712 if (columns
!= NULL
) {
714 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
715 printf("column %d %d..%d %c\n", c
->no
, c
->left
, c
->right
, c
->alignment
);
718 tab_stops
->dump_tabs();
722 * html_indent - creates an indent with indentation, ind, given
723 * a line length of linelength.
726 html_indent::html_indent (simple_output
*op
, int ind
, int pageoffset
, int linelength
)
728 table
= new html_table(op
, linelength
);
730 table
->add_column(1, ind
+pageoffset
, linelength
, 'L');
731 table
->add_indent(pageoffset
);
737 html_indent::~html_indent (void)
743 void html_indent::begin (int space
)
747 table
->out
->put_string(" style=\"margin-top: ");
748 table
->out
->put_string(STYLE_VERTICAL_SPACE
);
749 table
->out
->put_string("\"");
754 // we use exactly the same mechanism for calculating
755 // indentation as html_table::emit_col
757 table
->out
->put_string(" style=\"margin-left:")
758 .put_number(((in
+ pg
) * 100 + ll
/2) / ll
-
763 table
->out
->put_string(" margin-top: ");
764 table
->out
->put_string(STYLE_VERTICAL_SPACE
);
766 table
->out
->put_string("\"");
770 void html_indent::end (void)
775 * get_reg - collects the registers as supplied during initialization.
778 void html_indent::get_reg (int *ind
, int *pageoffset
, int *linelength
)