4 /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
6 * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp
10 * provides the methods necessary to handle indentation and tab
11 * positions using html tables.
15 This file is part of groff.
17 groff is free software; you can redistribute it and/or modify it under
18 the terms of the GNU General Public License as published by the Free
19 Software Foundation; either version 2, or (at your option) any later
22 groff is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 You should have received a copy of the GNU General Public License along
28 with groff; see the file COPYING. If not, write to the Free Software
29 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
32 #include "stringclass.h"
34 #include "html-table.h"
37 #include "html-text.h"
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)
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 out
->put_string("<tr valign=\"top\" align=\"left\"");
348 out
->put_string(" style=\"margin-top: ");
349 out
->put_string(STYLE_VERTICAL_SPACE
);
350 out
->put_string("\"");
352 out
->put_string(">").nl();
357 * get_right - returns the right most position of this column.
360 int html_table::get_right (cols
*c
)
362 if (c
!= NULL
&& c
->right
> 0)
370 * set_space - assigns start_space. Used to determine the
371 * vertical alignment when generating the next table row.
374 void html_table::set_space (int space
)
380 * emit_col - moves onto column, n.
383 void html_table::emit_col (int n
)
389 // must be a different row
390 if (last_col
!= NULL
&& n
<= last_col
->no
)
393 while (c
!= NULL
&& c
->no
< n
)
396 // can we find column, n?
397 if (c
!= NULL
&& c
->no
== n
) {
398 // shutdown previous column
399 if (last_col
!= NULL
)
400 out
->put_string("</td>").nl();
402 // find previous column
403 if (last_col
== NULL
)
409 if (last_col
!= NULL
) {
411 out
->put_string("<td width=\"")
412 .put_number(is_gap(b
))
413 .put_string("%\"></td>")
418 // move across to column n
420 // we compute the difference after converting positions
421 // to avoid rounding errors
422 width
= (get_right(b
)*100 + get_effective_linelength()/2)
423 / get_effective_linelength()
424 - (b
->left
*100 + get_effective_linelength()/2)
425 /get_effective_linelength();
427 out
->put_string("<td width=\"")
429 .put_string("%\"></td>")
433 out
->put_string("<td width=\"")
434 .put_number(is_gap(b
))
435 .put_string("%\"></td>")
439 width
= (get_right(b
)*100 + get_effective_linelength()/2)
440 / get_effective_linelength()
441 - (b
->left
*100 + get_effective_linelength()/2)
442 /get_effective_linelength();
443 switch (b
->alignment
) {
445 out
->put_string("<td width=\"")
447 .put_string("%\" align=center>")
451 out
->put_string("<td width=\"")
453 .put_string("%\" align=right>")
457 out
->put_string("<td width=\"")
462 // remember column, b
471 void html_table::finish_row (void)
476 if (last_col
!= NULL
) {
477 for (c
= last_col
->next
; c
!= NULL
; c
= c
->next
)
482 out
->put_string("</td>").nl();
487 * emit_new_row - move to the next row.
490 void html_table::emit_new_row (void)
494 out
->put_string("<tr valign=\"top\" align=\"left\"");
496 out
->put_string(" style=\"margin-top: ");
497 out
->put_string(STYLE_VERTICAL_SPACE
);
498 out
->put_string("\"");
500 out
->put_string(">").nl();
505 void html_table::emit_finish_table (void)
508 out
->put_string("</table>");
512 * add_column - adds a column. It returns FALSE if hstart..hend
513 * crosses into a different columns.
516 int html_table::add_column (int coln
, int hstart
, int hend
, char align
)
518 cols
*c
= get_column(coln
);
521 return insert_column(coln
, hstart
, hend
, align
);
523 return modify_column(c
, hstart
, hend
, align
);
527 * get_column - returns the column, coln.
530 cols
*html_table::get_column (int coln
)
534 while (c
!= NULL
&& coln
!= c
->no
)
537 if (c
!= NULL
&& coln
== c
->no
)
544 * insert_column - inserts a column, coln.
545 * It returns TRUE if it does not bump into
549 int html_table::insert_column (int coln
, int hstart
, int hend
, char align
)
555 while (c
!= NULL
&& c
->no
< coln
) {
559 if (l
!= NULL
&& l
->no
>coln
&& hend
> l
->left
)
560 return FALSE
; // new column bumps into previous one
564 while (c
!= NULL
&& c
->no
< coln
) {
569 if ((l
!= NULL
) && (hstart
< l
->right
))
570 return FALSE
; // new column bumps into previous one
572 if ((l
!= NULL
) && (l
->next
!= NULL
) &&
573 (l
->next
->left
< hend
))
574 return FALSE
; // new column bumps into next one
587 n
->alignment
= align
;
592 * modify_column - given a column, c, modify the width to
593 * contain hstart..hend.
594 * It returns TRUE if it does not clash with
595 * the next or previous column.
598 int html_table::modify_column (cols
*c
, int hstart
, int hend
, char align
)
602 while (l
!= NULL
&& l
->next
!= c
)
605 if ((l
!= NULL
) && (hstart
< l
->right
))
606 return FALSE
; // new column bumps into previous one
608 if ((c
->next
!= NULL
) && (c
->next
->left
< hend
))
609 return FALSE
; // new column bumps into next one
611 if (c
->left
> hstart
)
617 c
->alignment
= align
;
623 * find_tab_column - finds the column number for position, pos.
624 * It searches through the list tab stops.
627 int html_table::find_tab_column (int pos
)
629 // remember the first column is reserved for untabbed glyphs
630 return tab_stops
->find_tab(pos
)+1;
634 * find_column - find the column number for position, pos.
635 * It searches through the list of columns.
638 int html_table::find_column (int pos
)
643 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
652 * no_columns - returns the number of table columns (rather than tabs)
655 int html_table::no_columns (void)
660 for (c
= columns
; c
!= NULL
; c
= c
->next
)
666 * is_gap - returns the gap between column, c, and the next column.
669 int html_table::is_gap (cols
*c
)
671 if (c
== NULL
|| c
->right
<= 0 || c
->next
== NULL
)
674 // we compute the difference after converting positions
675 // to avoid rounding errors
676 return (c
->next
->left
*100 + get_effective_linelength()/2)
677 / get_effective_linelength()
678 - (c
->right
*100 + get_effective_linelength()/2)
679 / get_effective_linelength();
683 * no_gaps - returns the number of table gaps between the columns
686 int html_table::no_gaps (void)
691 for (c
= columns
; c
!= NULL
; c
= c
->next
)
698 * get_tab_pos - returns the, nth, tab position
701 int html_table::get_tab_pos (int n
)
703 return tab_stops
->get_tab_pos(n
);
706 char html_table::get_tab_align (int n
)
708 return tab_stops
->get_tab_align(n
);
712 void html_table::dump_table (void)
714 if (columns
!= NULL
) {
716 for (c
= columns
; c
!= NULL
; c
= c
->next
) {
717 printf("column %d %d..%d %c\n", c
->no
, c
->left
, c
->right
, c
->alignment
);
720 tab_stops
->dump_tabs();
724 * html_indent - creates an indent with indentation, ind, given
725 * a line length of linelength.
728 html_indent::html_indent (simple_output
*op
, int ind
, int pageoffset
, int linelength
)
730 table
= new html_table(op
, linelength
);
732 table
->add_column(1, ind
+pageoffset
, linelength
, 'L');
733 table
->add_indent(pageoffset
);
739 html_indent::~html_indent (void)
745 void html_indent::begin (int space
)
749 table
->out
->put_string(" style=\"margin-top: ");
750 table
->out
->put_string(STYLE_VERTICAL_SPACE
);
751 table
->out
->put_string("\"");
756 // we use exactly the same mechanism for calculating
757 // indentation as html_table::emit_col
759 table
->out
->put_string(" style=\"margin-left:")
760 .put_number(((in
+ pg
) * 100 + ll
/2) / ll
-
765 table
->out
->put_string(" margin-top: ");
766 table
->out
->put_string(STYLE_VERTICAL_SPACE
);
768 table
->out
->put_string("\"");
772 void html_indent::end (void)
777 * get_reg - collects the registers as supplied during initialization.
780 void html_indent::get_reg (int *ind
, int *pageoffset
, int *linelength
)