1 /* $NetBSD: html-text.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */
2
3 // -*- C++ -*-
4 /* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
5 * Free Software Foundation, Inc.
6 *
7 * Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cpp
8 *
9 * html-text.cpp
10 *
11 * provide a troff like state machine interface which
12 * generates html text.
13 */
14
15 /*
16 This file is part of groff.
17
18 groff is free software; you can redistribute it and/or modify it under
19 the terms of the GNU General Public License as published by the Free
20 Software Foundation; either version 2, or (at your option) any later
21 version.
22
23 groff is distributed in the hope that it will be useful, but WITHOUT ANY
24 WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 for more details.
27
28 You should have received a copy of the GNU General Public License along
29 with groff; see the file COPYING. If not, write to the Free Software
30 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
31
32 #include "driver.h"
33 #include "stringclass.h"
34 #include "cset.h"
35
36 #if !defined(TRUE)
37 # define TRUE (1==1)
38 #endif
39 #if !defined(FALSE)
40 # define FALSE (1==0)
41 #endif
42
43
44 #include "html-text.h"
45
46 #undef DEBUGGING
47 // #define DEBUGGING
48
html_text(simple_output * op)49 html_text::html_text (simple_output *op) :
50 stackptr(NULL), lastptr(NULL), out(op), space_emitted(TRUE),
51 current_indentation(-1), pageoffset(-1), linelength(-1),
52 blank_para(TRUE), start_space(FALSE)
53 {
54 }
55
~html_text()56 html_text::~html_text ()
57 {
58 flush_text();
59 }
60
61
62 #if defined(DEBUGGING)
63 static int debugStack = FALSE;
64
65
66 /*
67 * turnDebug - flip the debugStack boolean and return the new value.
68 */
69
turnDebug(void)70 static int turnDebug (void)
71 {
72 debugStack = 1-debugStack;
73 return debugStack;
74 }
75
76 /*
77 * dump_stack_element - display an element of the html stack, p.
78 */
79
dump_stack_element(tag_definition * p)80 void html_text::dump_stack_element (tag_definition *p)
81 {
82 fprintf(stderr, " | ");
83 switch (p->type) {
84
85 case P_TAG: if (p->indent == NULL) {
86 fprintf(stderr, "<P %s>", (char *)p->arg1); break;
87 } else {
88 fprintf(stderr, "<P %s [TABLE]>", (char *)p->arg1); break;
89 }
90 case I_TAG: fprintf(stderr, "<I>"); break;
91 case B_TAG: fprintf(stderr, "<B>"); break;
92 case SUB_TAG: fprintf(stderr, "<SUB>"); break;
93 case SUP_TAG: fprintf(stderr, "<SUP>"); break;
94 case TT_TAG: fprintf(stderr, "<TT>"); break;
95 case PRE_TAG: if (p->indent == NULL) {
96 fprintf(stderr, "<PRE>"); break;
97 } else {
98 fprintf(stderr, "<PRE [TABLE]>"); break;
99 }
100 case SMALL_TAG: fprintf(stderr, "<SMALL>"); break;
101 case BIG_TAG: fprintf(stderr, "<BIG>"); break;
102 case BREAK_TAG: fprintf(stderr, "<BREAK>"); break;
103 case COLOR_TAG: {
104 if (p->col.is_default())
105 fprintf(stderr, "<COLOR (default)>");
106 else {
107 unsigned int r, g, b;
108
109 p->col.get_rgb(&r, &g, &b);
110 fprintf(stderr, "<COLOR %x %x %x>", r/0x101, g/0x101, b/0x101);
111 }
112 break;
113 }
114 default: fprintf(stderr, "unknown tag");
115 }
116 if (p->text_emitted)
117 fprintf(stderr, "[t] ");
118 }
119
120 /*
121 * dump_stack - debugging function only.
122 */
123
dump_stack(void)124 void html_text::dump_stack (void)
125 {
126 if (debugStack) {
127 tag_definition *p = stackptr;
128
129 while (p != NULL) {
130 dump_stack_element(p);
131 p = p->next;
132 }
133 }
134 fprintf(stderr, "\n");
135 fflush(stderr);
136 }
137 #else
dump_stack(void)138 void html_text::dump_stack (void) {}
139 #endif
140
141
142 /*
143 * end_tag - shuts down the tag.
144 */
145
end_tag(tag_definition * t)146 void html_text::end_tag (tag_definition *t)
147 {
148 switch (t->type) {
149
150 case I_TAG: out->put_string("</i>"); break;
151 case B_TAG: out->put_string("</b>"); break;
152 case P_TAG: if (t->indent == NULL) {
153 out->put_string("</p>");
154 } else {
155 delete t->indent;
156 t->indent = NULL;
157 out->put_string("</p>");
158 }
159 out->enable_newlines(FALSE);
160 blank_para = TRUE; break;
161 case SUB_TAG: out->put_string("</sub>"); break;
162 case SUP_TAG: out->put_string("</sup>"); break;
163 case TT_TAG: out->put_string("</tt>"); break;
164 case PRE_TAG: out->put_string("</pre>"); out->enable_newlines(TRUE);
165 blank_para = TRUE;
166 if (t->indent != NULL)
167 delete t->indent;
168 t->indent = NULL;
169 break;
170 case SMALL_TAG: out->put_string("</small>"); break;
171 case BIG_TAG: out->put_string("</big>"); break;
172 case COLOR_TAG: out->put_string("</font>"); break;
173
174 default:
175 error("unrecognised tag");
176 }
177 }
178
179 /*
180 * issue_tag - writes out an html tag with argument.
181 * space == 0 if no space is requested
182 * space == 1 if a space is requested
183 * space == 2 if tag should not have a space style
184 */
185
issue_tag(const char * tagname,const char * arg,int space)186 void html_text::issue_tag (const char *tagname, const char *arg,
187 int space)
188 {
189 if ((arg == 0) || (strlen(arg) == 0))
190 out->put_string(tagname);
191 else {
192 out->put_string(tagname);
193 out->put_string(" ");
194 out->put_string(arg);
195 }
196 if (space == TRUE) {
197 out->put_string(" style=\"margin-top: ");
198 out->put_string(STYLE_VERTICAL_SPACE);
199 out->put_string("\"");
200 }
201 if (space == TRUE || space == FALSE)
202 out->put_string(" valign=\"top\"");
203 out->put_string(">");
204 }
205
206 /*
207 * issue_color_begin - writes out an html color tag.
208 */
209
issue_color_begin(color * c)210 void html_text::issue_color_begin (color *c)
211 {
212 unsigned int r, g, b;
213 char buf[6+1];
214
215 out->put_string("<font color=\"#");
216 if (c->is_default())
217 sprintf(buf, "000000");
218 else {
219 c->get_rgb(&r, &g, &b);
220 // we have to scale 0..0xFFFF to 0..0xFF
221 sprintf(buf, "%.2X%.2X%.2X", r/0x101, g/0x101, b/0x101);
222 }
223 out->put_string(buf);
224 out->put_string("\">");
225 }
226
227 /*
228 * start_tag - starts a tag.
229 */
230
start_tag(tag_definition * t)231 void html_text::start_tag (tag_definition *t)
232 {
233 switch (t->type) {
234
235 case I_TAG: issue_tag("<i", (char *)t->arg1); break;
236 case B_TAG: issue_tag("<b", (char *)t->arg1); break;
237 case P_TAG: if (t->indent != NULL) {
238 out->nl();
239 #if defined(DEBUGGING)
240 out->simple_comment("INDENTATION");
241 #endif
242 out->put_string("\n<p");
243 t->indent->begin(start_space);
244 issue_tag("", (char *)t->arg1);
245 } else {
246 out->nl();
247 issue_tag("\n<p", (char *)t->arg1, start_space);
248 }
249
250 out->enable_newlines(TRUE); break;
251 case SUB_TAG: issue_tag("<sub", (char *)t->arg1); break;
252 case SUP_TAG: issue_tag("<sup", (char *)t->arg1); break;
253 case TT_TAG: issue_tag("<tt", (char *)t->arg1); break;
254 case PRE_TAG: out->enable_newlines(TRUE);
255 out->nl(); out->put_string("<pre");
256 if (t->indent == NULL)
257 issue_tag("", (char *)t->arg1, start_space);
258 else {
259 t->indent->begin(start_space);
260 issue_tag("", (char *)t->arg1);
261 }
262 out->enable_newlines(FALSE); break;
263 case SMALL_TAG: issue_tag("<small", (char *)t->arg1); break;
264 case BIG_TAG: issue_tag("<big", (char *)t->arg1); break;
265 case BREAK_TAG: break;
266 case COLOR_TAG: issue_color_begin(&t->col); break;
267
268 default:
269 error("unrecognised tag");
270 }
271 }
272
273 /*
274 * flush_text - flushes html tags which are outstanding on the html stack.
275 */
276
flush_text(void)277 void html_text::flush_text (void)
278 {
279 int notext=TRUE;
280 tag_definition *p=stackptr;
281
282 while (stackptr != 0) {
283 notext = (notext && (! stackptr->text_emitted));
284 if (! notext) {
285 end_tag(stackptr);
286 }
287 p = stackptr;
288 stackptr = stackptr->next;
289 delete p;
290 }
291 lastptr = NULL;
292 }
293
294 /*
295 * is_present - returns TRUE if tag is already present on the stack.
296 */
297
is_present(HTML_TAG t)298 int html_text::is_present (HTML_TAG t)
299 {
300 tag_definition *p=stackptr;
301
302 while (p != NULL) {
303 if (t == p->type)
304 return TRUE;
305 p = p->next;
306 }
307 return FALSE;
308 }
309
310 /*
311 * uses_indent - returns TRUE if the current paragraph is using a
312 * html table to effect an indent.
313 */
314
uses_indent(void)315 int html_text::uses_indent (void)
316 {
317 tag_definition *p = stackptr;
318
319 while (p != NULL) {
320 if (p->indent != NULL)
321 return TRUE;
322 p = p->next;
323 }
324 return FALSE;
325 }
326
327 extern void stop();
328
329 /*
330 * do_push - places, tag_definition, p, onto the stack
331 */
332
do_push(tag_definition * p)333 void html_text::do_push (tag_definition *p)
334 {
335 HTML_TAG t = p->type;
336
337 #if defined(DEBUGGING)
338 if (t == PRE_TAG)
339 stop();
340 debugStack = TRUE;
341 fprintf(stderr, "\nentering do_push (");
342 dump_stack_element(p);
343 fprintf(stderr, ")\n");
344 dump_stack();
345 fprintf(stderr, ")\n");
346 fflush(stderr);
347 #endif
348
349 /*
350 * if t is a P_TAG or PRE_TAG make sure it goes on the end of the stack.
351 */
352
353 if (((t == P_TAG) || (t == PRE_TAG)) && (lastptr != NULL)) {
354 /*
355 * store, p, at the end
356 */
357 lastptr->next = p;
358 lastptr = p;
359 p->next = NULL;
360 } else {
361 p->next = stackptr;
362 if (stackptr == NULL)
363 lastptr = p;
364 stackptr = p;
365 }
366
367 #if defined(DEBUGGING)
368 dump_stack();
369 fprintf(stderr, "exiting do_push\n");
370 #endif
371 }
372
373 /*
374 * push_para - adds a new entry onto the html paragraph stack.
375 */
376
push_para(HTML_TAG t,void * arg,html_indent * in)377 void html_text::push_para (HTML_TAG t, void *arg, html_indent *in)
378 {
379 tag_definition *p= new tag_definition;
380
381 p->type = t;
382 p->arg1 = arg;
383 p->text_emitted = FALSE;
384 p->indent = in;
385
386 if (t == PRE_TAG && is_present(PRE_TAG))
387 fatal("cannot have multiple PRE_TAGs");
388
389 do_push(p);
390 }
391
push_para(HTML_TAG t)392 void html_text::push_para (HTML_TAG t)
393 {
394 push_para(t, (void *)"", NULL);
395 }
396
push_para(color * c)397 void html_text::push_para (color *c)
398 {
399 tag_definition *p = new tag_definition;
400
401 p->type = COLOR_TAG;
402 p->arg1 = NULL;
403 p->col = *c;
404 p->text_emitted = FALSE;
405 p->indent = NULL;
406
407 do_push(p);
408 }
409
410 /*
411 * do_italic - changes to italic
412 */
413
do_italic(void)414 void html_text::do_italic (void)
415 {
416 if (! is_present(I_TAG))
417 push_para(I_TAG);
418 }
419
420 /*
421 * do_bold - changes to bold.
422 */
423
do_bold(void)424 void html_text::do_bold (void)
425 {
426 if (! is_present(B_TAG))
427 push_para(B_TAG);
428 }
429
430 /*
431 * do_tt - changes to teletype.
432 */
433
do_tt(void)434 void html_text::do_tt (void)
435 {
436 if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG)))
437 push_para(TT_TAG);
438 }
439
440 /*
441 * do_pre - changes to preformated text.
442 */
443
do_pre(void)444 void html_text::do_pre (void)
445 {
446 done_tt();
447 if (is_present(P_TAG)) {
448 html_indent *i = remove_indent(P_TAG);
449 int space = retrieve_para_space();
450 (void)done_para();
451 if (! is_present(PRE_TAG))
452 push_para(PRE_TAG, NULL, i);
453 start_space = space;
454 } else if (! is_present(PRE_TAG))
455 push_para(PRE_TAG, NULL, NULL);
456 dump_stack();
457 }
458
459 /*
460 * is_in_pre - returns TRUE if we are currently within a preformatted
461 * <pre> block.
462 */
463
is_in_pre(void)464 int html_text::is_in_pre (void)
465 {
466 return is_present(PRE_TAG);
467 }
468
469 /*
470 * do_color - initiates a new color tag.
471 */
472
do_color(color * c)473 void html_text::do_color (color *c)
474 {
475 shutdown(COLOR_TAG); // shutdown a previous color tag, if present
476 push_para(c);
477 }
478
479 /*
480 * done_color - shutdown an outstanding color tag, if it exists.
481 */
482
done_color(void)483 void html_text::done_color (void)
484 {
485 shutdown(COLOR_TAG);
486 }
487
488 /*
489 * shutdown - shuts down an html tag.
490 */
491
shutdown(HTML_TAG t)492 char *html_text::shutdown (HTML_TAG t)
493 {
494 char *arg=NULL;
495
496 if (is_present(t)) {
497 tag_definition *p =stackptr;
498 tag_definition *temp =NULL;
499 int notext =TRUE;
500
501 dump_stack();
502 while ((stackptr != NULL) && (stackptr->type != t)) {
503 notext = (notext && (! stackptr->text_emitted));
504 if (! notext) {
505 end_tag(stackptr);
506 }
507
508 /*
509 * pop tag
510 */
511 p = stackptr;
512 stackptr = stackptr->next;
513 if (stackptr == NULL)
514 lastptr = NULL;
515
516 /*
517 * push tag onto temp stack
518 */
519 p->next = temp;
520 temp = p;
521 }
522
523 /*
524 * and examine stackptr
525 */
526 if ((stackptr != NULL) && (stackptr->type == t)) {
527 if (stackptr->text_emitted) {
528 end_tag(stackptr);
529 }
530 if (t == P_TAG) {
531 arg = (char *)stackptr->arg1;
532 }
533 p = stackptr;
534 stackptr = stackptr->next;
535 if (stackptr == NULL)
536 lastptr = NULL;
537 if (p->indent != NULL)
538 delete p->indent;
539 delete p;
540 }
541
542 /*
543 * and restore unaffected tags
544 */
545 while (temp != NULL) {
546 if (temp->type == COLOR_TAG)
547 push_para(&temp->col);
548 else
549 push_para(temp->type, temp->arg1, temp->indent);
550 p = temp;
551 temp = temp->next;
552 delete p;
553 }
554 }
555 return arg;
556 }
557
558 /*
559 * done_bold - shuts downs a bold tag.
560 */
561
done_bold(void)562 void html_text::done_bold (void)
563 {
564 shutdown(B_TAG);
565 }
566
567 /*
568 * done_italic - shuts downs an italic tag.
569 */
570
done_italic(void)571 void html_text::done_italic (void)
572 {
573 shutdown(I_TAG);
574 }
575
576 /*
577 * done_sup - shuts downs a sup tag.
578 */
579
done_sup(void)580 void html_text::done_sup (void)
581 {
582 shutdown(SUP_TAG);
583 }
584
585 /*
586 * done_sub - shuts downs a sub tag.
587 */
588
done_sub(void)589 void html_text::done_sub (void)
590 {
591 shutdown(SUB_TAG);
592 }
593
594 /*
595 * done_tt - shuts downs a tt tag.
596 */
597
done_tt(void)598 void html_text::done_tt (void)
599 {
600 shutdown(TT_TAG);
601 }
602
603 /*
604 * done_pre - shuts downs a pre tag.
605 */
606
done_pre(void)607 void html_text::done_pre (void)
608 {
609 shutdown(PRE_TAG);
610 }
611
612 /*
613 * done_small - shuts downs a small tag.
614 */
615
done_small(void)616 void html_text::done_small (void)
617 {
618 shutdown(SMALL_TAG);
619 }
620
621 /*
622 * done_big - shuts downs a big tag.
623 */
624
done_big(void)625 void html_text::done_big (void)
626 {
627 shutdown(BIG_TAG);
628 }
629
630 /*
631 * check_emit_text - ensures that all previous tags have been emitted (in order)
632 * before the text is written.
633 */
634
check_emit_text(tag_definition * t)635 void html_text::check_emit_text (tag_definition *t)
636 {
637 if ((t != NULL) && (! t->text_emitted)) {
638 check_emit_text(t->next);
639 t->text_emitted = TRUE;
640 start_tag(t);
641 }
642 }
643
644 /*
645 * do_emittext - tells the class that text was written during the current tag.
646 */
647
do_emittext(const char * s,int length)648 void html_text::do_emittext (const char *s, int length)
649 {
650 if ((! is_present(P_TAG)) && (! is_present(PRE_TAG)))
651 do_para("", FALSE);
652
653 if (is_present(BREAK_TAG)) {
654 int text = remove_break();
655 check_emit_text(stackptr);
656 if (text) {
657 if (is_present(PRE_TAG)) {
658 out->nl();
659 } else
660 out->put_string("<br>").nl();
661 }
662 } else
663 check_emit_text(stackptr);
664
665 out->put_string(s, length);
666 space_emitted = FALSE;
667 blank_para = FALSE;
668 }
669
670 /*
671 * do_para - starts a new paragraph
672 */
673
do_para(const char * arg,html_indent * in,int space)674 void html_text::do_para (const char *arg, html_indent *in, int space)
675 {
676 if (! is_present(P_TAG)) {
677 if (is_present(PRE_TAG)) {
678 html_indent *i = remove_indent(PRE_TAG);
679 done_pre();
680 if ((arg == NULL || (strcmp(arg, "") == 0)) &&
681 (i == in || in == NULL))
682 in = i;
683 else
684 delete i;
685 }
686 remove_sub_sup();
687 push_para(P_TAG, (void *)arg, in);
688 start_space = space;
689 }
690 }
691
do_para(const char * arg,int space)692 void html_text::do_para (const char *arg, int space)
693 {
694 do_para(arg, NULL, space);
695 }
696
do_para(simple_output * op,const char * arg1,int indentation_value,int page_offset,int line_length,int space)697 void html_text::do_para (simple_output *op, const char *arg1,
698 int indentation_value, int page_offset,
699 int line_length, int space)
700 {
701 html_indent *ind;
702
703 if (indentation_value == 0)
704 ind = NULL;
705 else
706 ind = new html_indent(op, indentation_value, page_offset, line_length);
707 do_para(arg1, ind, space);
708 }
709
710 /*
711 * done_para - shuts down a paragraph tag.
712 */
713
done_para(void)714 char *html_text::done_para (void)
715 {
716 char *result;
717 space_emitted = TRUE;
718 result = shutdown(P_TAG);
719 start_space = FALSE;
720 return result;
721 }
722
723 /*
724 * remove_indent - returns the indent associated with, tag.
725 * The indent associated with tag is set to NULL.
726 */
727
remove_indent(HTML_TAG tag)728 html_indent *html_text::remove_indent (HTML_TAG tag)
729 {
730 tag_definition *p=stackptr;
731
732 while (p != NULL) {
733 if (tag == p->type) {
734 html_indent *i = p->indent;
735 p->indent = NULL;
736 return i;
737 }
738 p = p->next;
739 }
740 return NULL;
741 }
742
743 /*
744 * remove_para_space - removes the leading space to a paragraph
745 * (effectively this trims off a leading `.sp' tag).
746 */
747
remove_para_space(void)748 void html_text::remove_para_space (void)
749 {
750 start_space = FALSE;
751 }
752
753 /*
754 * do_space - issues an end of paragraph
755 */
756
do_space(void)757 void html_text::do_space (void)
758 {
759 if (is_in_pre()) {
760 do_emittext("", 0);
761 out->force_nl();
762 space_emitted = TRUE;
763 } else {
764 html_indent *i = remove_indent(P_TAG);
765
766 do_para(done_para(), i, TRUE);
767 space_emitted = TRUE;
768 }
769 }
770
771 /*
772 * do_break - issue a break tag.
773 */
774
do_break(void)775 void html_text::do_break (void)
776 {
777 if (! is_present(PRE_TAG))
778 if (emitted_text())
779 if (! is_present(BREAK_TAG))
780 push_para(BREAK_TAG);
781
782 space_emitted = TRUE;
783 }
784
785 /*
786 * do_newline - issue a newline providing that we are inside a <pre> tag.
787 */
788
do_newline(void)789 void html_text::do_newline (void)
790 {
791 if (is_present(PRE_TAG)) {
792 do_emittext("\n", 1);
793 space_emitted = TRUE;
794 }
795 }
796
797 /*
798 * emitted_text - returns FALSE if white space has just been written.
799 */
800
emitted_text(void)801 int html_text::emitted_text (void)
802 {
803 return !space_emitted;
804 }
805
806 /*
807 * ever_emitted_text - returns TRUE if we have ever emitted text in this
808 * paragraph.
809 */
810
ever_emitted_text(void)811 int html_text::ever_emitted_text (void)
812 {
813 return !blank_para;
814 }
815
816 /*
817 * starts_with_space - returns TRUE if we started this paragraph with a .sp
818 */
819
starts_with_space(void)820 int html_text::starts_with_space (void)
821 {
822 return start_space;
823 }
824
825 /*
826 * retrieve_para_space - returns TRUE, if the paragraph starts with
827 * a space and text has not yet been emitted.
828 * If TRUE is returned, then the, start_space,
829 * variable is set to FALSE.
830 */
831
retrieve_para_space(void)832 int html_text::retrieve_para_space (void)
833 {
834 if (start_space && blank_para) {
835 start_space = FALSE;
836 return TRUE;
837 }
838 else
839 return FALSE;
840 }
841
842 /*
843 * emit_space - writes a space providing that text was written beforehand.
844 */
845
emit_space(void)846 void html_text::emit_space (void)
847 {
848 if (is_present(PRE_TAG))
849 do_emittext(" ", 1);
850 else
851 out->space_or_newline();
852
853 space_emitted = TRUE;
854 }
855
856 /*
857 * remove_def - removes a definition, t, from the stack.
858 */
859
remove_def(tag_definition * t)860 void html_text::remove_def (tag_definition *t)
861 {
862 tag_definition *p = stackptr;
863 tag_definition *l = 0;
864 tag_definition *q = 0;
865
866 while ((p != 0) && (p != t)) {
867 l = p;
868 p = p->next;
869 }
870 if ((p != 0) && (p == t)) {
871 if (p == stackptr) {
872 stackptr = stackptr->next;
873 if (stackptr == NULL)
874 lastptr = NULL;
875 q = stackptr;
876 } else if (l == 0) {
877 error("stack list pointers are wrong");
878 } else {
879 l->next = p->next;
880 q = p->next;
881 if (l->next == NULL)
882 lastptr = l;
883 }
884 delete p;
885 }
886 }
887
888 /*
889 * remove_tag - removes a tag from the stack.
890 */
891
remove_tag(HTML_TAG tag)892 void html_text::remove_tag (HTML_TAG tag)
893 {
894 tag_definition *p = stackptr;
895
896 while ((p != 0) && (p->type != tag)) {
897 p = p->next;
898 }
899 if ((p != 0) && (p->type == tag))
900 remove_def(p);
901 }
902
903 /*
904 * remove_sub_sup - removes a sub or sup tag, should either exist
905 * on the stack.
906 */
907
remove_sub_sup(void)908 void html_text::remove_sub_sup (void)
909 {
910 if (is_present(SUB_TAG)) {
911 remove_tag(SUB_TAG);
912 }
913 if (is_present(SUP_TAG)) {
914 remove_tag(SUP_TAG);
915 }
916 if (is_present(PRE_TAG)) {
917 remove_tag(PRE_TAG);
918 }
919 }
920
921 /*
922 * remove_break - break tags are not balanced thus remove it once it has been emitted.
923 * It returns TRUE if text was emitted before the <br> was issued.
924 */
925
remove_break(void)926 int html_text::remove_break (void)
927 {
928 tag_definition *p = stackptr;
929 tag_definition *l = 0;
930 tag_definition *q = 0;
931
932 while ((p != 0) && (p->type != BREAK_TAG)) {
933 l = p;
934 p = p->next;
935 }
936 if ((p != 0) && (p->type == BREAK_TAG)) {
937 if (p == stackptr) {
938 stackptr = stackptr->next;
939 if (stackptr == NULL)
940 lastptr = NULL;
941 q = stackptr;
942 } else if (l == 0)
943 error("stack list pointers are wrong");
944 else {
945 l->next = p->next;
946 q = p->next;
947 if (l->next == NULL)
948 lastptr = l;
949 }
950 delete p;
951 }
952 /*
953 * now determine whether text was issued before <br>
954 */
955 while (q != 0) {
956 if (q->text_emitted)
957 return TRUE;
958 else
959 q = q->next;
960 }
961 return FALSE;
962 }
963
964 /*
965 * remove_para_align - removes a paragraph which has a text
966 * argument. If the paragraph has no text
967 * argument then it is left alone.
968 */
969
remove_para_align(void)970 void html_text::remove_para_align (void)
971 {
972 if (is_present(P_TAG)) {
973 tag_definition *p=stackptr;
974
975 while (p != NULL) {
976 if (p->type == P_TAG && p->arg1 != NULL) {
977 html_indent *i = remove_indent(P_TAG);
978 int space = retrieve_para_space();
979 done_para();
980 do_para("", i, space);
981 return;
982 }
983 p = p->next;
984 }
985 }
986 }
987
988 /*
989 * get_alignment - returns the alignment for the paragraph.
990 * If no alignment was given then we return "".
991 */
992
get_alignment(void)993 char *html_text::get_alignment (void)
994 {
995 if (is_present(P_TAG)) {
996 tag_definition *p=stackptr;
997
998 while (p != NULL) {
999 if (p->type == P_TAG && p->arg1 != NULL)
1000 return (char *)p->arg1;
1001 p = p->next;
1002 }
1003 }
1004 return (char *)"";
1005 }
1006
1007 /*
1008 * do_small - potentially inserts a <small> tag into the html stream.
1009 * However we check for a <big> tag, if present then we terminate it.
1010 * Otherwise a <small> tag is inserted.
1011 */
1012
do_small(void)1013 void html_text::do_small (void)
1014 {
1015 if (is_present(BIG_TAG))
1016 done_big();
1017 else
1018 push_para(SMALL_TAG);
1019 }
1020
1021 /*
1022 * do_big - is the mirror image of do_small.
1023 */
1024
do_big(void)1025 void html_text::do_big (void)
1026 {
1027 if (is_present(SMALL_TAG))
1028 done_small();
1029 else
1030 push_para(BIG_TAG);
1031 }
1032
1033 /*
1034 * do_sup - save a superscript tag on the stack of tags.
1035 */
1036
do_sup(void)1037 void html_text::do_sup (void)
1038 {
1039 push_para(SUP_TAG);
1040 }
1041
1042 /*
1043 * do_sub - save a subscript tag on the stack of tags.
1044 */
1045
do_sub(void)1046 void html_text::do_sub (void)
1047 {
1048 push_para(SUB_TAG);
1049 }
1050