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 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 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 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 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 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 138 void html_text::dump_stack (void) {} 139 #endif 140 141 142 /* 143 * end_tag - shuts down the tag. 144 */ 145 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 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 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 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 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 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 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 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 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 392 void html_text::push_para (HTML_TAG t) 393 { 394 push_para(t, (void *)"", NULL); 395 } 396 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 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 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 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 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 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 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 483 void html_text::done_color (void) 484 { 485 shutdown(COLOR_TAG); 486 } 487 488 /* 489 * shutdown - shuts down an html tag. 490 */ 491 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 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 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 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 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 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 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 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 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 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 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 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 692 void html_text::do_para (const char *arg, int space) 693 { 694 do_para(arg, NULL, space); 695 } 696 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1046 void html_text::do_sub (void) 1047 { 1048 push_para(SUB_TAG); 1049 } 1050