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/* 16This file is part of groff. 17 18groff is free software; you can redistribute it and/or modify it under 19the terms of the GNU General Public License as published by the Free 20Software Foundation; either version 2, or (at your option) any later 21version. 22 23groff is distributed in the hope that it will be useful, but WITHOUT ANY 24WARRANTY; without even the implied warranty of MERCHANTABILITY or 25FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26for more details. 27 28You should have received a copy of the GNU General Public License along 29with groff; see the file COPYING. If not, write to the Free Software 30Foundation, 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 49html_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 56html_text::~html_text () 57{ 58 flush_text(); 59} 60 61 62#if defined(DEBUGGING) 63static int debugStack = FALSE; 64 65 66/* 67 * turnDebug - flip the debugStack boolean and return the new value. 68 */ 69 70static 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 80void 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 124void 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 138void html_text::dump_stack (void) {} 139#endif 140 141 142/* 143 * end_tag - shuts down the tag. 144 */ 145 146void 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 186void 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 210void 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 231void 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 277void 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 298int 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 315int 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 327extern void stop(); 328 329/* 330 * do_push - places, tag_definition, p, onto the stack 331 */ 332 333void 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 377void 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 392void html_text::push_para (HTML_TAG t) 393{ 394 push_para(t, (void *)"", NULL); 395} 396 397void 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 414void 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 424void 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 434void 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 444void 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 464int 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 473void 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 483void html_text::done_color (void) 484{ 485 shutdown(COLOR_TAG); 486} 487 488/* 489 * shutdown - shuts down an html tag. 490 */ 491 492char *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 562void html_text::done_bold (void) 563{ 564 shutdown(B_TAG); 565} 566 567/* 568 * done_italic - shuts downs an italic tag. 569 */ 570 571void html_text::done_italic (void) 572{ 573 shutdown(I_TAG); 574} 575 576/* 577 * done_sup - shuts downs a sup tag. 578 */ 579 580void html_text::done_sup (void) 581{ 582 shutdown(SUP_TAG); 583} 584 585/* 586 * done_sub - shuts downs a sub tag. 587 */ 588 589void html_text::done_sub (void) 590{ 591 shutdown(SUB_TAG); 592} 593 594/* 595 * done_tt - shuts downs a tt tag. 596 */ 597 598void html_text::done_tt (void) 599{ 600 shutdown(TT_TAG); 601} 602 603/* 604 * done_pre - shuts downs a pre tag. 605 */ 606 607void html_text::done_pre (void) 608{ 609 shutdown(PRE_TAG); 610} 611 612/* 613 * done_small - shuts downs a small tag. 614 */ 615 616void html_text::done_small (void) 617{ 618 shutdown(SMALL_TAG); 619} 620 621/* 622 * done_big - shuts downs a big tag. 623 */ 624 625void 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 635void 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 648void 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 674void 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 692void html_text::do_para (const char *arg, int space) 693{ 694 do_para(arg, NULL, space); 695} 696 697void 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 714char *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 728html_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 748void html_text::remove_para_space (void) 749{ 750 start_space = FALSE; 751} 752 753/* 754 * do_space - issues an end of paragraph 755 */ 756 757void 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 775void 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 789void 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 801int 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 811int 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 820int 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 832int 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 846void 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 860void 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 892void 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 908void 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 926int 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 970void 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 993char *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 1013void 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 1025void 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 1037void 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 1046void html_text::do_sub (void) 1047{ 1048 push_para(SUB_TAG); 1049} 1050