/contrib/groff/src/devices/grohtml/html-text.cpp

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 1047 lines · 662 code · 160 blank · 225 comment · 195 complexity · f89a23d631b8fb8033801b6f84b3cb05 MD5 · raw file

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