1*89a07cf8Schristos /* $NetBSD: html-table.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */
2*89a07cf8Schristos
3*89a07cf8Schristos // -*- C++ -*-
4*89a07cf8Schristos /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5*89a07cf8Schristos *
6*89a07cf8Schristos * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp
7*89a07cf8Schristos *
8*89a07cf8Schristos * html-table.h
9*89a07cf8Schristos *
10*89a07cf8Schristos * provides the methods necessary to handle indentation and tab
11*89a07cf8Schristos * positions using html tables.
12*89a07cf8Schristos */
13*89a07cf8Schristos
14*89a07cf8Schristos /*
15*89a07cf8Schristos This file is part of groff.
16*89a07cf8Schristos
17*89a07cf8Schristos groff is free software; you can redistribute it and/or modify it under
18*89a07cf8Schristos the terms of the GNU General Public License as published by the Free
19*89a07cf8Schristos Software Foundation; either version 2, or (at your option) any later
20*89a07cf8Schristos version.
21*89a07cf8Schristos
22*89a07cf8Schristos groff is distributed in the hope that it will be useful, but WITHOUT ANY
23*89a07cf8Schristos WARRANTY; without even the implied warranty of MERCHANTABILITY or
24*89a07cf8Schristos FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25*89a07cf8Schristos for more details.
26*89a07cf8Schristos
27*89a07cf8Schristos You should have received a copy of the GNU General Public License along
28*89a07cf8Schristos with groff; see the file COPYING. If not, write to the Free Software
29*89a07cf8Schristos Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
30*89a07cf8Schristos
31*89a07cf8Schristos #include "driver.h"
32*89a07cf8Schristos #include "stringclass.h"
33*89a07cf8Schristos #include "cset.h"
34*89a07cf8Schristos #include "html-table.h"
35*89a07cf8Schristos #include "ctype.h"
36*89a07cf8Schristos #include "html.h"
37*89a07cf8Schristos #include "html-text.h"
38*89a07cf8Schristos
39*89a07cf8Schristos #if !defined(TRUE)
40*89a07cf8Schristos # define TRUE (1==1)
41*89a07cf8Schristos #endif
42*89a07cf8Schristos #if !defined(FALSE)
43*89a07cf8Schristos # define FALSE (1==0)
44*89a07cf8Schristos #endif
45*89a07cf8Schristos
tabs()46*89a07cf8Schristos tabs::tabs ()
47*89a07cf8Schristos : tab(NULL)
48*89a07cf8Schristos {
49*89a07cf8Schristos }
50*89a07cf8Schristos
~tabs()51*89a07cf8Schristos tabs::~tabs ()
52*89a07cf8Schristos {
53*89a07cf8Schristos delete_list();
54*89a07cf8Schristos }
55*89a07cf8Schristos
56*89a07cf8Schristos /*
57*89a07cf8Schristos * delete_list - frees the tab list and sets tab to NULL.
58*89a07cf8Schristos */
59*89a07cf8Schristos
delete_list(void)60*89a07cf8Schristos void tabs::delete_list (void)
61*89a07cf8Schristos {
62*89a07cf8Schristos tab_position *p = tab;
63*89a07cf8Schristos tab_position *q;
64*89a07cf8Schristos
65*89a07cf8Schristos while (p != NULL) {
66*89a07cf8Schristos q = p;
67*89a07cf8Schristos p = p->next;
68*89a07cf8Schristos delete q;
69*89a07cf8Schristos }
70*89a07cf8Schristos tab = NULL;
71*89a07cf8Schristos }
72*89a07cf8Schristos
clear(void)73*89a07cf8Schristos void tabs::clear (void)
74*89a07cf8Schristos {
75*89a07cf8Schristos delete_list();
76*89a07cf8Schristos }
77*89a07cf8Schristos
78*89a07cf8Schristos /*
79*89a07cf8Schristos * compatible - returns TRUE if the tab stops in, s, do
80*89a07cf8Schristos * not conflict with the current tab stops.
81*89a07cf8Schristos * The new tab stops are _not_ placed into
82*89a07cf8Schristos * this class.
83*89a07cf8Schristos */
84*89a07cf8Schristos
compatible(const char * s)85*89a07cf8Schristos int tabs::compatible (const char *s)
86*89a07cf8Schristos {
87*89a07cf8Schristos char align;
88*89a07cf8Schristos int total=0;
89*89a07cf8Schristos tab_position *last = tab;
90*89a07cf8Schristos
91*89a07cf8Schristos if (last == NULL)
92*89a07cf8Schristos return FALSE; // no tab stops defined
93*89a07cf8Schristos
94*89a07cf8Schristos // move over tag name
95*89a07cf8Schristos while ((*s != (char)0) && !isspace(*s))
96*89a07cf8Schristos s++;
97*89a07cf8Schristos
98*89a07cf8Schristos while (*s != (char)0 && last != NULL) {
99*89a07cf8Schristos // move over white space
100*89a07cf8Schristos while ((*s != (char)0) && isspace(*s))
101*89a07cf8Schristos s++;
102*89a07cf8Schristos // collect alignment
103*89a07cf8Schristos align = *s;
104*89a07cf8Schristos // move over alignment
105*89a07cf8Schristos s++;
106*89a07cf8Schristos // move over white space
107*89a07cf8Schristos while ((*s != (char)0) && isspace(*s))
108*89a07cf8Schristos s++;
109*89a07cf8Schristos // collect tab position
110*89a07cf8Schristos total = atoi(s);
111*89a07cf8Schristos // move over tab position
112*89a07cf8Schristos while ((*s != (char)0) && !isspace(*s))
113*89a07cf8Schristos s++;
114*89a07cf8Schristos if (last->alignment != align || last->position != total)
115*89a07cf8Schristos return FALSE;
116*89a07cf8Schristos
117*89a07cf8Schristos last = last->next;
118*89a07cf8Schristos }
119*89a07cf8Schristos return TRUE;
120*89a07cf8Schristos }
121*89a07cf8Schristos
122*89a07cf8Schristos /*
123*89a07cf8Schristos * init - scans the string, s, and initializes the tab stops.
124*89a07cf8Schristos */
125*89a07cf8Schristos
init(const char * s)126*89a07cf8Schristos void tabs::init (const char *s)
127*89a07cf8Schristos {
128*89a07cf8Schristos char align;
129*89a07cf8Schristos int total=0;
130*89a07cf8Schristos tab_position *last = NULL;
131*89a07cf8Schristos
132*89a07cf8Schristos clear(); // remove any tab stops
133*89a07cf8Schristos
134*89a07cf8Schristos // move over tag name
135*89a07cf8Schristos while ((*s != (char)0) && !isspace(*s))
136*89a07cf8Schristos s++;
137*89a07cf8Schristos
138*89a07cf8Schristos while (*s != (char)0) {
139*89a07cf8Schristos // move over white space
140*89a07cf8Schristos while ((*s != (char)0) && isspace(*s))
141*89a07cf8Schristos s++;
142*89a07cf8Schristos // collect alignment
143*89a07cf8Schristos align = *s;
144*89a07cf8Schristos // move over alignment
145*89a07cf8Schristos s++;
146*89a07cf8Schristos // move over white space
147*89a07cf8Schristos while ((*s != (char)0) && isspace(*s))
148*89a07cf8Schristos s++;
149*89a07cf8Schristos // collect tab position
150*89a07cf8Schristos total = atoi(s);
151*89a07cf8Schristos // move over tab position
152*89a07cf8Schristos while ((*s != (char)0) && !isspace(*s))
153*89a07cf8Schristos s++;
154*89a07cf8Schristos if (last == NULL) {
155*89a07cf8Schristos tab = new tab_position;
156*89a07cf8Schristos last = tab;
157*89a07cf8Schristos } else {
158*89a07cf8Schristos last->next = new tab_position;
159*89a07cf8Schristos last = last->next;
160*89a07cf8Schristos }
161*89a07cf8Schristos last->alignment = align;
162*89a07cf8Schristos last->position = total;
163*89a07cf8Schristos last->next = NULL;
164*89a07cf8Schristos }
165*89a07cf8Schristos }
166*89a07cf8Schristos
167*89a07cf8Schristos /*
168*89a07cf8Schristos * check_init - define tab stops using, s, providing none already exist.
169*89a07cf8Schristos */
170*89a07cf8Schristos
check_init(const char * s)171*89a07cf8Schristos void tabs::check_init (const char *s)
172*89a07cf8Schristos {
173*89a07cf8Schristos if (tab == NULL)
174*89a07cf8Schristos init(s);
175*89a07cf8Schristos }
176*89a07cf8Schristos
177*89a07cf8Schristos /*
178*89a07cf8Schristos * find_tab - returns the tab number corresponding to the position, pos.
179*89a07cf8Schristos */
180*89a07cf8Schristos
find_tab(int pos)181*89a07cf8Schristos int tabs::find_tab (int pos)
182*89a07cf8Schristos {
183*89a07cf8Schristos tab_position *p;
184*89a07cf8Schristos int i=0;
185*89a07cf8Schristos
186*89a07cf8Schristos for (p = tab; p != NULL; p = p->next) {
187*89a07cf8Schristos i++;
188*89a07cf8Schristos if (p->position == pos)
189*89a07cf8Schristos return i;
190*89a07cf8Schristos }
191*89a07cf8Schristos return 0;
192*89a07cf8Schristos }
193*89a07cf8Schristos
194*89a07cf8Schristos /*
195*89a07cf8Schristos * get_tab_pos - returns the, nth, tab position
196*89a07cf8Schristos */
197*89a07cf8Schristos
get_tab_pos(int n)198*89a07cf8Schristos int tabs::get_tab_pos (int n)
199*89a07cf8Schristos {
200*89a07cf8Schristos tab_position *p;
201*89a07cf8Schristos
202*89a07cf8Schristos n--;
203*89a07cf8Schristos for (p = tab; (p != NULL) && (n>0); p = p->next) {
204*89a07cf8Schristos n--;
205*89a07cf8Schristos if (n == 0)
206*89a07cf8Schristos return p->position;
207*89a07cf8Schristos }
208*89a07cf8Schristos return 0;
209*89a07cf8Schristos }
210*89a07cf8Schristos
get_tab_align(int n)211*89a07cf8Schristos char tabs::get_tab_align (int n)
212*89a07cf8Schristos {
213*89a07cf8Schristos tab_position *p;
214*89a07cf8Schristos
215*89a07cf8Schristos n--;
216*89a07cf8Schristos for (p = tab; (p != NULL) && (n>0); p = p->next) {
217*89a07cf8Schristos n--;
218*89a07cf8Schristos if (n == 0)
219*89a07cf8Schristos return p->alignment;
220*89a07cf8Schristos }
221*89a07cf8Schristos return 'L';
222*89a07cf8Schristos }
223*89a07cf8Schristos
224*89a07cf8Schristos /*
225*89a07cf8Schristos * dump_tab - display tab positions
226*89a07cf8Schristos */
227*89a07cf8Schristos
dump_tabs(void)228*89a07cf8Schristos void tabs::dump_tabs (void)
229*89a07cf8Schristos {
230*89a07cf8Schristos int i=1;
231*89a07cf8Schristos tab_position *p;
232*89a07cf8Schristos
233*89a07cf8Schristos for (p = tab; p != NULL; p = p->next) {
234*89a07cf8Schristos printf("tab %d is %d\n", i, p->position);
235*89a07cf8Schristos i++;
236*89a07cf8Schristos }
237*89a07cf8Schristos }
238*89a07cf8Schristos
239*89a07cf8Schristos /*
240*89a07cf8Schristos * html_table - methods
241*89a07cf8Schristos */
242*89a07cf8Schristos
html_table(simple_output * op,int linelen)243*89a07cf8Schristos html_table::html_table (simple_output *op, int linelen)
244*89a07cf8Schristos : out(op), columns(NULL), linelength(linelen), last_col(NULL), start_space(FALSE)
245*89a07cf8Schristos {
246*89a07cf8Schristos tab_stops = new tabs();
247*89a07cf8Schristos }
248*89a07cf8Schristos
~html_table()249*89a07cf8Schristos html_table::~html_table ()
250*89a07cf8Schristos {
251*89a07cf8Schristos cols *c;
252*89a07cf8Schristos if (tab_stops != NULL)
253*89a07cf8Schristos delete tab_stops;
254*89a07cf8Schristos
255*89a07cf8Schristos c = columns;
256*89a07cf8Schristos while (columns != NULL) {
257*89a07cf8Schristos columns = columns->next;
258*89a07cf8Schristos delete c;
259*89a07cf8Schristos c = columns;
260*89a07cf8Schristos }
261*89a07cf8Schristos }
262*89a07cf8Schristos
263*89a07cf8Schristos /*
264*89a07cf8Schristos * remove_cols - remove a list of columns as defined by, c.
265*89a07cf8Schristos */
266*89a07cf8Schristos
remove_cols(cols * c)267*89a07cf8Schristos void html_table::remove_cols (cols *c)
268*89a07cf8Schristos {
269*89a07cf8Schristos cols *p;
270*89a07cf8Schristos
271*89a07cf8Schristos while (c != NULL) {
272*89a07cf8Schristos p = c;
273*89a07cf8Schristos c = c->next;
274*89a07cf8Schristos delete p;
275*89a07cf8Schristos }
276*89a07cf8Schristos }
277*89a07cf8Schristos
278*89a07cf8Schristos /*
279*89a07cf8Schristos * set_linelength - sets the line length value in this table.
280*89a07cf8Schristos * It also adds an extra blank column to the
281*89a07cf8Schristos * table should linelen exceed the last column.
282*89a07cf8Schristos */
283*89a07cf8Schristos
set_linelength(int linelen)284*89a07cf8Schristos void html_table::set_linelength (int linelen)
285*89a07cf8Schristos {
286*89a07cf8Schristos cols *p = NULL;
287*89a07cf8Schristos cols *c;
288*89a07cf8Schristos linelength = linelen;
289*89a07cf8Schristos
290*89a07cf8Schristos for (c = columns; c != NULL; c = c->next) {
291*89a07cf8Schristos if (c->right > linelength) {
292*89a07cf8Schristos c->right = linelength;
293*89a07cf8Schristos remove_cols(c->next);
294*89a07cf8Schristos c->next = NULL;
295*89a07cf8Schristos return;
296*89a07cf8Schristos }
297*89a07cf8Schristos p = c;
298*89a07cf8Schristos }
299*89a07cf8Schristos if (p != NULL && p->right > 0)
300*89a07cf8Schristos add_column(p->no+1, p->right, linelength, 'L');
301*89a07cf8Schristos }
302*89a07cf8Schristos
303*89a07cf8Schristos /*
304*89a07cf8Schristos * get_effective_linelength -
305*89a07cf8Schristos */
306*89a07cf8Schristos
get_effective_linelength(void)307*89a07cf8Schristos int html_table::get_effective_linelength (void)
308*89a07cf8Schristos {
309*89a07cf8Schristos if (columns != NULL)
310*89a07cf8Schristos return linelength - columns->left;
311*89a07cf8Schristos else
312*89a07cf8Schristos return linelength;
313*89a07cf8Schristos }
314*89a07cf8Schristos
315*89a07cf8Schristos /*
316*89a07cf8Schristos * add_indent - adds the indent to a table.
317*89a07cf8Schristos */
318*89a07cf8Schristos
add_indent(int indent)319*89a07cf8Schristos void html_table::add_indent (int indent)
320*89a07cf8Schristos {
321*89a07cf8Schristos if (columns != NULL && columns->left > indent)
322*89a07cf8Schristos add_column(0, indent, columns->left, 'L');
323*89a07cf8Schristos }
324*89a07cf8Schristos
325*89a07cf8Schristos /*
326*89a07cf8Schristos * emit_table_header - emits the html header for this table.
327*89a07cf8Schristos */
328*89a07cf8Schristos
emit_table_header(int space)329*89a07cf8Schristos void html_table::emit_table_header (int space)
330*89a07cf8Schristos {
331*89a07cf8Schristos if (columns == NULL)
332*89a07cf8Schristos return;
333*89a07cf8Schristos
334*89a07cf8Schristos // dump_table();
335*89a07cf8Schristos
336*89a07cf8Schristos last_col = NULL;
337*89a07cf8Schristos if (linelength > 0) {
338*89a07cf8Schristos out->nl();
339*89a07cf8Schristos out->nl();
340*89a07cf8Schristos
341*89a07cf8Schristos out->put_string("<table width=\"100%\"")
342*89a07cf8Schristos .put_string(" border=0 rules=\"none\" frame=\"void\"\n")
343*89a07cf8Schristos .put_string(" cellspacing=\"0\" cellpadding=\"0\"");
344*89a07cf8Schristos out->put_string(">")
345*89a07cf8Schristos .nl();
346*89a07cf8Schristos out->put_string("<tr valign=\"top\" align=\"left\"");
347*89a07cf8Schristos if (space) {
348*89a07cf8Schristos out->put_string(" style=\"margin-top: ");
349*89a07cf8Schristos out->put_string(STYLE_VERTICAL_SPACE);
350*89a07cf8Schristos out->put_string("\"");
351*89a07cf8Schristos }
352*89a07cf8Schristos out->put_string(">").nl();
353*89a07cf8Schristos }
354*89a07cf8Schristos }
355*89a07cf8Schristos
356*89a07cf8Schristos /*
357*89a07cf8Schristos * get_right - returns the right most position of this column.
358*89a07cf8Schristos */
359*89a07cf8Schristos
get_right(cols * c)360*89a07cf8Schristos int html_table::get_right (cols *c)
361*89a07cf8Schristos {
362*89a07cf8Schristos if (c != NULL && c->right > 0)
363*89a07cf8Schristos return c->right;
364*89a07cf8Schristos if (c->next != NULL)
365*89a07cf8Schristos return c->left;
366*89a07cf8Schristos return linelength;
367*89a07cf8Schristos }
368*89a07cf8Schristos
369*89a07cf8Schristos /*
370*89a07cf8Schristos * set_space - assigns start_space. Used to determine the
371*89a07cf8Schristos * vertical alignment when generating the next table row.
372*89a07cf8Schristos */
373*89a07cf8Schristos
set_space(int space)374*89a07cf8Schristos void html_table::set_space (int space)
375*89a07cf8Schristos {
376*89a07cf8Schristos start_space = space;
377*89a07cf8Schristos }
378*89a07cf8Schristos
379*89a07cf8Schristos /*
380*89a07cf8Schristos * emit_col - moves onto column, n.
381*89a07cf8Schristos */
382*89a07cf8Schristos
emit_col(int n)383*89a07cf8Schristos void html_table::emit_col (int n)
384*89a07cf8Schristos {
385*89a07cf8Schristos cols *c = columns;
386*89a07cf8Schristos cols *b = columns;
387*89a07cf8Schristos int width = 0;
388*89a07cf8Schristos
389*89a07cf8Schristos // must be a different row
390*89a07cf8Schristos if (last_col != NULL && n <= last_col->no)
391*89a07cf8Schristos emit_new_row();
392*89a07cf8Schristos
393*89a07cf8Schristos while (c != NULL && c->no < n)
394*89a07cf8Schristos c = c->next;
395*89a07cf8Schristos
396*89a07cf8Schristos // can we find column, n?
397*89a07cf8Schristos if (c != NULL && c->no == n) {
398*89a07cf8Schristos // shutdown previous column
399*89a07cf8Schristos if (last_col != NULL)
400*89a07cf8Schristos out->put_string("</td>").nl();
401*89a07cf8Schristos
402*89a07cf8Schristos // find previous column
403*89a07cf8Schristos if (last_col == NULL)
404*89a07cf8Schristos b = columns;
405*89a07cf8Schristos else
406*89a07cf8Schristos b = last_col;
407*89a07cf8Schristos
408*89a07cf8Schristos // have we a gap?
409*89a07cf8Schristos if (last_col != NULL) {
410*89a07cf8Schristos if (is_gap(b))
411*89a07cf8Schristos out->put_string("<td width=\"")
412*89a07cf8Schristos .put_number(is_gap(b))
413*89a07cf8Schristos .put_string("%\"></td>")
414*89a07cf8Schristos .nl();
415*89a07cf8Schristos b = b->next;
416*89a07cf8Schristos }
417*89a07cf8Schristos
418*89a07cf8Schristos // move across to column n
419*89a07cf8Schristos while (b != c) {
420*89a07cf8Schristos // we compute the difference after converting positions
421*89a07cf8Schristos // to avoid rounding errors
422*89a07cf8Schristos width = (get_right(b)*100 + get_effective_linelength()/2)
423*89a07cf8Schristos / get_effective_linelength()
424*89a07cf8Schristos - (b->left*100 + get_effective_linelength()/2)
425*89a07cf8Schristos /get_effective_linelength();
426*89a07cf8Schristos if (width)
427*89a07cf8Schristos out->put_string("<td width=\"")
428*89a07cf8Schristos .put_number(width)
429*89a07cf8Schristos .put_string("%\"></td>")
430*89a07cf8Schristos .nl();
431*89a07cf8Schristos // have we a gap?
432*89a07cf8Schristos if (is_gap(b))
433*89a07cf8Schristos out->put_string("<td width=\"")
434*89a07cf8Schristos .put_number(is_gap(b))
435*89a07cf8Schristos .put_string("%\"></td>")
436*89a07cf8Schristos .nl();
437*89a07cf8Schristos b = b->next;
438*89a07cf8Schristos }
439*89a07cf8Schristos width = (get_right(b)*100 + get_effective_linelength()/2)
440*89a07cf8Schristos / get_effective_linelength()
441*89a07cf8Schristos - (b->left*100 + get_effective_linelength()/2)
442*89a07cf8Schristos /get_effective_linelength();
443*89a07cf8Schristos switch (b->alignment) {
444*89a07cf8Schristos case 'C':
445*89a07cf8Schristos out->put_string("<td width=\"")
446*89a07cf8Schristos .put_number(width)
447*89a07cf8Schristos .put_string("%\" align=center>")
448*89a07cf8Schristos .nl();
449*89a07cf8Schristos break;
450*89a07cf8Schristos case 'R':
451*89a07cf8Schristos out->put_string("<td width=\"")
452*89a07cf8Schristos .put_number(width)
453*89a07cf8Schristos .put_string("%\" align=right>")
454*89a07cf8Schristos .nl();
455*89a07cf8Schristos break;
456*89a07cf8Schristos default:
457*89a07cf8Schristos out->put_string("<td width=\"")
458*89a07cf8Schristos .put_number(width)
459*89a07cf8Schristos .put_string("%\">")
460*89a07cf8Schristos .nl();
461*89a07cf8Schristos }
462*89a07cf8Schristos // remember column, b
463*89a07cf8Schristos last_col = b;
464*89a07cf8Schristos }
465*89a07cf8Schristos }
466*89a07cf8Schristos
467*89a07cf8Schristos /*
468*89a07cf8Schristos * finish_row -
469*89a07cf8Schristos */
470*89a07cf8Schristos
finish_row(void)471*89a07cf8Schristos void html_table::finish_row (void)
472*89a07cf8Schristos {
473*89a07cf8Schristos int n = 0;
474*89a07cf8Schristos cols *c;
475*89a07cf8Schristos
476*89a07cf8Schristos if (last_col != NULL) {
477*89a07cf8Schristos for (c = last_col->next; c != NULL; c = c->next)
478*89a07cf8Schristos n = c->no;
479*89a07cf8Schristos
480*89a07cf8Schristos if (n > 0)
481*89a07cf8Schristos emit_col(n);
482*89a07cf8Schristos out->put_string("</td>").nl();
483*89a07cf8Schristos }
484*89a07cf8Schristos }
485*89a07cf8Schristos
486*89a07cf8Schristos /*
487*89a07cf8Schristos * emit_new_row - move to the next row.
488*89a07cf8Schristos */
489*89a07cf8Schristos
emit_new_row(void)490*89a07cf8Schristos void html_table::emit_new_row (void)
491*89a07cf8Schristos {
492*89a07cf8Schristos finish_row();
493*89a07cf8Schristos
494*89a07cf8Schristos out->put_string("<tr valign=\"top\" align=\"left\"");
495*89a07cf8Schristos if (start_space) {
496*89a07cf8Schristos out->put_string(" style=\"margin-top: ");
497*89a07cf8Schristos out->put_string(STYLE_VERTICAL_SPACE);
498*89a07cf8Schristos out->put_string("\"");
499*89a07cf8Schristos }
500*89a07cf8Schristos out->put_string(">").nl();
501*89a07cf8Schristos start_space = FALSE;
502*89a07cf8Schristos last_col = NULL;
503*89a07cf8Schristos }
504*89a07cf8Schristos
emit_finish_table(void)505*89a07cf8Schristos void html_table::emit_finish_table (void)
506*89a07cf8Schristos {
507*89a07cf8Schristos finish_row();
508*89a07cf8Schristos out->put_string("</table>");
509*89a07cf8Schristos }
510*89a07cf8Schristos
511*89a07cf8Schristos /*
512*89a07cf8Schristos * add_column - adds a column. It returns FALSE if hstart..hend
513*89a07cf8Schristos * crosses into a different columns.
514*89a07cf8Schristos */
515*89a07cf8Schristos
add_column(int coln,int hstart,int hend,char align)516*89a07cf8Schristos int html_table::add_column (int coln, int hstart, int hend, char align)
517*89a07cf8Schristos {
518*89a07cf8Schristos cols *c = get_column(coln);
519*89a07cf8Schristos
520*89a07cf8Schristos if (c == NULL)
521*89a07cf8Schristos return insert_column(coln, hstart, hend, align);
522*89a07cf8Schristos else
523*89a07cf8Schristos return modify_column(c, hstart, hend, align);
524*89a07cf8Schristos }
525*89a07cf8Schristos
526*89a07cf8Schristos /*
527*89a07cf8Schristos * get_column - returns the column, coln.
528*89a07cf8Schristos */
529*89a07cf8Schristos
get_column(int coln)530*89a07cf8Schristos cols *html_table::get_column (int coln)
531*89a07cf8Schristos {
532*89a07cf8Schristos cols *c = columns;
533*89a07cf8Schristos
534*89a07cf8Schristos while (c != NULL && coln != c->no)
535*89a07cf8Schristos c = c->next;
536*89a07cf8Schristos
537*89a07cf8Schristos if (c != NULL && coln == c->no)
538*89a07cf8Schristos return c;
539*89a07cf8Schristos else
540*89a07cf8Schristos return NULL;
541*89a07cf8Schristos }
542*89a07cf8Schristos
543*89a07cf8Schristos /*
544*89a07cf8Schristos * insert_column - inserts a column, coln.
545*89a07cf8Schristos * It returns TRUE if it does not bump into
546*89a07cf8Schristos * another column.
547*89a07cf8Schristos */
548*89a07cf8Schristos
insert_column(int coln,int hstart,int hend,char align)549*89a07cf8Schristos int html_table::insert_column (int coln, int hstart, int hend, char align)
550*89a07cf8Schristos {
551*89a07cf8Schristos cols *c = columns;
552*89a07cf8Schristos cols *l = columns;
553*89a07cf8Schristos cols *n = NULL;
554*89a07cf8Schristos
555*89a07cf8Schristos while (c != NULL && c->no < coln) {
556*89a07cf8Schristos l = c;
557*89a07cf8Schristos c = c->next;
558*89a07cf8Schristos }
559*89a07cf8Schristos if (l != NULL && l->no>coln && hend > l->left)
560*89a07cf8Schristos return FALSE; // new column bumps into previous one
561*89a07cf8Schristos
562*89a07cf8Schristos l = NULL;
563*89a07cf8Schristos c = columns;
564*89a07cf8Schristos while (c != NULL && c->no < coln) {
565*89a07cf8Schristos l = c;
566*89a07cf8Schristos c = c->next;
567*89a07cf8Schristos }
568*89a07cf8Schristos
569*89a07cf8Schristos if ((l != NULL) && (hstart < l->right))
570*89a07cf8Schristos return FALSE; // new column bumps into previous one
571*89a07cf8Schristos
572*89a07cf8Schristos if ((l != NULL) && (l->next != NULL) &&
573*89a07cf8Schristos (l->next->left < hend))
574*89a07cf8Schristos return FALSE; // new column bumps into next one
575*89a07cf8Schristos
576*89a07cf8Schristos n = new cols;
577*89a07cf8Schristos if (l == NULL) {
578*89a07cf8Schristos n->next = columns;
579*89a07cf8Schristos columns = n;
580*89a07cf8Schristos } else {
581*89a07cf8Schristos n->next = l->next;
582*89a07cf8Schristos l->next = n;
583*89a07cf8Schristos }
584*89a07cf8Schristos n->left = hstart;
585*89a07cf8Schristos n->right = hend;
586*89a07cf8Schristos n->no = coln;
587*89a07cf8Schristos n->alignment = align;
588*89a07cf8Schristos return TRUE;
589*89a07cf8Schristos }
590*89a07cf8Schristos
591*89a07cf8Schristos /*
592*89a07cf8Schristos * modify_column - given a column, c, modify the width to
593*89a07cf8Schristos * contain hstart..hend.
594*89a07cf8Schristos * It returns TRUE if it does not clash with
595*89a07cf8Schristos * the next or previous column.
596*89a07cf8Schristos */
597*89a07cf8Schristos
modify_column(cols * c,int hstart,int hend,char align)598*89a07cf8Schristos int html_table::modify_column (cols *c, int hstart, int hend, char align)
599*89a07cf8Schristos {
600*89a07cf8Schristos cols *l = columns;
601*89a07cf8Schristos
602*89a07cf8Schristos while (l != NULL && l->next != c)
603*89a07cf8Schristos l = l->next;
604*89a07cf8Schristos
605*89a07cf8Schristos if ((l != NULL) && (hstart < l->right))
606*89a07cf8Schristos return FALSE; // new column bumps into previous one
607*89a07cf8Schristos
608*89a07cf8Schristos if ((c->next != NULL) && (c->next->left < hend))
609*89a07cf8Schristos return FALSE; // new column bumps into next one
610*89a07cf8Schristos
611*89a07cf8Schristos if (c->left > hstart)
612*89a07cf8Schristos c->left = hstart;
613*89a07cf8Schristos
614*89a07cf8Schristos if (c->right < hend)
615*89a07cf8Schristos c->right = hend;
616*89a07cf8Schristos
617*89a07cf8Schristos c->alignment = align;
618*89a07cf8Schristos
619*89a07cf8Schristos return TRUE;
620*89a07cf8Schristos }
621*89a07cf8Schristos
622*89a07cf8Schristos /*
623*89a07cf8Schristos * find_tab_column - finds the column number for position, pos.
624*89a07cf8Schristos * It searches through the list tab stops.
625*89a07cf8Schristos */
626*89a07cf8Schristos
find_tab_column(int pos)627*89a07cf8Schristos int html_table::find_tab_column (int pos)
628*89a07cf8Schristos {
629*89a07cf8Schristos // remember the first column is reserved for untabbed glyphs
630*89a07cf8Schristos return tab_stops->find_tab(pos)+1;
631*89a07cf8Schristos }
632*89a07cf8Schristos
633*89a07cf8Schristos /*
634*89a07cf8Schristos * find_column - find the column number for position, pos.
635*89a07cf8Schristos * It searches through the list of columns.
636*89a07cf8Schristos */
637*89a07cf8Schristos
find_column(int pos)638*89a07cf8Schristos int html_table::find_column (int pos)
639*89a07cf8Schristos {
640*89a07cf8Schristos int p=0;
641*89a07cf8Schristos cols *c;
642*89a07cf8Schristos
643*89a07cf8Schristos for (c = columns; c != NULL; c = c->next) {
644*89a07cf8Schristos if (c->left > pos)
645*89a07cf8Schristos return p;
646*89a07cf8Schristos p = c->no;
647*89a07cf8Schristos }
648*89a07cf8Schristos return p;
649*89a07cf8Schristos }
650*89a07cf8Schristos
651*89a07cf8Schristos /*
652*89a07cf8Schristos * no_columns - returns the number of table columns (rather than tabs)
653*89a07cf8Schristos */
654*89a07cf8Schristos
no_columns(void)655*89a07cf8Schristos int html_table::no_columns (void)
656*89a07cf8Schristos {
657*89a07cf8Schristos int n=0;
658*89a07cf8Schristos cols *c;
659*89a07cf8Schristos
660*89a07cf8Schristos for (c = columns; c != NULL; c = c->next)
661*89a07cf8Schristos n++;
662*89a07cf8Schristos return n;
663*89a07cf8Schristos }
664*89a07cf8Schristos
665*89a07cf8Schristos /*
666*89a07cf8Schristos * is_gap - returns the gap between column, c, and the next column.
667*89a07cf8Schristos */
668*89a07cf8Schristos
is_gap(cols * c)669*89a07cf8Schristos int html_table::is_gap (cols *c)
670*89a07cf8Schristos {
671*89a07cf8Schristos if (c == NULL || c->right <= 0 || c->next == NULL)
672*89a07cf8Schristos return 0;
673*89a07cf8Schristos else
674*89a07cf8Schristos // we compute the difference after converting positions
675*89a07cf8Schristos // to avoid rounding errors
676*89a07cf8Schristos return (c->next->left*100 + get_effective_linelength()/2)
677*89a07cf8Schristos / get_effective_linelength()
678*89a07cf8Schristos - (c->right*100 + get_effective_linelength()/2)
679*89a07cf8Schristos / get_effective_linelength();
680*89a07cf8Schristos }
681*89a07cf8Schristos
682*89a07cf8Schristos /*
683*89a07cf8Schristos * no_gaps - returns the number of table gaps between the columns
684*89a07cf8Schristos */
685*89a07cf8Schristos
no_gaps(void)686*89a07cf8Schristos int html_table::no_gaps (void)
687*89a07cf8Schristos {
688*89a07cf8Schristos int n=0;
689*89a07cf8Schristos cols *c;
690*89a07cf8Schristos
691*89a07cf8Schristos for (c = columns; c != NULL; c = c->next)
692*89a07cf8Schristos if (is_gap(c))
693*89a07cf8Schristos n++;
694*89a07cf8Schristos return n;
695*89a07cf8Schristos }
696*89a07cf8Schristos
697*89a07cf8Schristos /*
698*89a07cf8Schristos * get_tab_pos - returns the, nth, tab position
699*89a07cf8Schristos */
700*89a07cf8Schristos
get_tab_pos(int n)701*89a07cf8Schristos int html_table::get_tab_pos (int n)
702*89a07cf8Schristos {
703*89a07cf8Schristos return tab_stops->get_tab_pos(n);
704*89a07cf8Schristos }
705*89a07cf8Schristos
get_tab_align(int n)706*89a07cf8Schristos char html_table::get_tab_align (int n)
707*89a07cf8Schristos {
708*89a07cf8Schristos return tab_stops->get_tab_align(n);
709*89a07cf8Schristos }
710*89a07cf8Schristos
711*89a07cf8Schristos
dump_table(void)712*89a07cf8Schristos void html_table::dump_table (void)
713*89a07cf8Schristos {
714*89a07cf8Schristos if (columns != NULL) {
715*89a07cf8Schristos cols *c;
716*89a07cf8Schristos for (c = columns; c != NULL; c = c->next) {
717*89a07cf8Schristos printf("column %d %d..%d %c\n", c->no, c->left, c->right, c->alignment);
718*89a07cf8Schristos }
719*89a07cf8Schristos } else
720*89a07cf8Schristos tab_stops->dump_tabs();
721*89a07cf8Schristos }
722*89a07cf8Schristos
723*89a07cf8Schristos /*
724*89a07cf8Schristos * html_indent - creates an indent with indentation, ind, given
725*89a07cf8Schristos * a line length of linelength.
726*89a07cf8Schristos */
727*89a07cf8Schristos
html_indent(simple_output * op,int ind,int pageoffset,int linelength)728*89a07cf8Schristos html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linelength)
729*89a07cf8Schristos {
730*89a07cf8Schristos table = new html_table(op, linelength);
731*89a07cf8Schristos
732*89a07cf8Schristos table->add_column(1, ind+pageoffset, linelength, 'L');
733*89a07cf8Schristos table->add_indent(pageoffset);
734*89a07cf8Schristos in = ind;
735*89a07cf8Schristos pg = pageoffset;
736*89a07cf8Schristos ll = linelength;
737*89a07cf8Schristos }
738*89a07cf8Schristos
~html_indent(void)739*89a07cf8Schristos html_indent::~html_indent (void)
740*89a07cf8Schristos {
741*89a07cf8Schristos end();
742*89a07cf8Schristos delete table;
743*89a07cf8Schristos }
744*89a07cf8Schristos
begin(int space)745*89a07cf8Schristos void html_indent::begin (int space)
746*89a07cf8Schristos {
747*89a07cf8Schristos if (in + pg == 0) {
748*89a07cf8Schristos if (space) {
749*89a07cf8Schristos table->out->put_string(" style=\"margin-top: ");
750*89a07cf8Schristos table->out->put_string(STYLE_VERTICAL_SPACE);
751*89a07cf8Schristos table->out->put_string("\"");
752*89a07cf8Schristos }
753*89a07cf8Schristos }
754*89a07cf8Schristos else {
755*89a07cf8Schristos //
756*89a07cf8Schristos // we use exactly the same mechanism for calculating
757*89a07cf8Schristos // indentation as html_table::emit_col
758*89a07cf8Schristos //
759*89a07cf8Schristos table->out->put_string(" style=\"margin-left:")
760*89a07cf8Schristos .put_number(((in + pg) * 100 + ll/2) / ll -
761*89a07cf8Schristos (ll/2)/ll)
762*89a07cf8Schristos .put_string("%;");
763*89a07cf8Schristos
764*89a07cf8Schristos if (space) {
765*89a07cf8Schristos table->out->put_string(" margin-top: ");
766*89a07cf8Schristos table->out->put_string(STYLE_VERTICAL_SPACE);
767*89a07cf8Schristos }
768*89a07cf8Schristos table->out->put_string("\"");
769*89a07cf8Schristos }
770*89a07cf8Schristos }
771*89a07cf8Schristos
end(void)772*89a07cf8Schristos void html_indent::end (void)
773*89a07cf8Schristos {
774*89a07cf8Schristos }
775*89a07cf8Schristos
776*89a07cf8Schristos /*
777*89a07cf8Schristos * get_reg - collects the registers as supplied during initialization.
778*89a07cf8Schristos */
779*89a07cf8Schristos
get_reg(int * ind,int * pageoffset,int * linelength)780*89a07cf8Schristos void html_indent::get_reg (int *ind, int *pageoffset, int *linelength)
781*89a07cf8Schristos {
782*89a07cf8Schristos *ind = in;
783*89a07cf8Schristos *pageoffset = pg;
784*89a07cf8Schristos *linelength = ll;
785*89a07cf8Schristos }
786