home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / emxtutor.zip / emxsrcd1.zip / emx / src / emxdoc / text.c < prev    next >
C/C++ Source or Header  |  1995-10-19  |  10KB  |  466 lines

  1. /* text.c -- Text output
  2.    Copyright (c) 1993-1995 Eberhard Mattes
  3.  
  4. This file is part of emxdoc.
  5.  
  6. emxdoc is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. emxdoc is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with emxdoc; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "emxdoc.h"
  26. #include "text.h"
  27. #include "lb.h"
  28.  
  29. static int text_width = 70;
  30. static int format_width;
  31. static int format_margin;
  32. static struct lb *lb;
  33. static struct lbh *lbh = NULL;
  34.  
  35. static void text_indent (int margin)
  36. {
  37.   uchar *s;
  38.   int i;
  39.  
  40.   i = margin - output_x;
  41.   if (i > 0)
  42.     {
  43.       s = alloca (i);
  44.       memset (s, ' ', i);
  45.       write_nstring (s, i);
  46.     }
  47. }
  48.  
  49.  
  50. static void text_para (void)
  51. {
  52.   if (para_flag)
  53.     {
  54.       para_flag = FALSE;
  55.       write_nl ();
  56.     }
  57. }
  58.  
  59.  
  60. static int isblank (const uchar *p)
  61. {
  62.   while (*p != 0)
  63.     if (*p++ != ' ')
  64.       return FALSE;
  65.   return TRUE;
  66. }
  67.  
  68.  
  69. void text_output (const uchar *p, int may_break)
  70. {
  71.   if (opt_b == 0)
  72.     {
  73.       if (may_break && output_x + strlen (p) > format_width)
  74.         write_nl ();
  75.       text_indent (format_margin);
  76.       write_string (p);
  77.     }
  78.   else
  79.     {
  80.       int rc;
  81.  
  82.       if (may_break && isblank (p))
  83.         rc = lb_glue (lb, strlen (p), NULL);
  84.       else
  85.         rc = lb_word (lb, strlen (p), p, NULL);
  86.       if (rc != 0)
  87.         fatal ("lb_glue or lb_word failed, rc=%d", rc);
  88.     }
  89. }
  90.  
  91.  
  92. static int text_elements (int margin, int width, int newline)
  93. {
  94.   const struct element *ep, *ep2;
  95.   int i, spaces, line, rc;
  96.   enum style style_stack[STYLE_STACK_SIZE];
  97.   int style_sp;
  98.   enum style style = STYLE_NORMAL;
  99.  
  100.   style_sp = 0;
  101.   style_stack[style_sp] = style;
  102.   line = output_line_no; spaces = 0;
  103.   format_width = width; format_margin = margin;
  104.   if (opt_b != 0)
  105.     {
  106.       rc = lb_init (&lb, margin, width);
  107.       if (rc != 0)
  108.         fatal ("lb_init failed, rc=%d", rc);
  109.       if (output_x > margin)
  110.         lb_first_lmargin (lb, output_x);
  111.     }
  112.  
  113.   for (ep = elements; ep->el != EL_END; ++ep)
  114.     switch (ep->el)
  115.       {
  116.       case EL_WORD:
  117.       case EL_PUNCT:
  118.         if (spaces != 0)
  119.           {
  120.             format_spaces (spaces, STYLE_NORMAL); spaces = 0;
  121.           }
  122.         if (ep->wp->special != NULL && ep->wp->special->text != NULL)
  123.           format_output (ep->wp->special->text, FALSE);
  124.         else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
  125.           format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
  126.                                        ? ep->wp->style : style), FALSE);
  127.         else
  128.           format_string (ep->wp->str, style_stack[style_sp], FALSE);
  129.         break;
  130.       case EL_SPACE:
  131.         if (opt_b == 0)
  132.           {
  133.             spaces += ep->n;
  134.             i = 0;
  135.             ep2 = ep + 1;
  136.             while (ep2->el != EL_END && ep2->el != EL_SPACE)
  137.               {
  138.                 if (ep2->el == EL_WORD || ep2->el == EL_PUNCT)
  139.                   i += strlen (ep2->wp->str);
  140.                 ++ep2;
  141.               }
  142.             if (output_x + spaces + i > format_width)
  143.               {
  144.                 write_nl ();
  145.                 spaces = 0;
  146.               }
  147.           }
  148.         else
  149.           format_spaces (ep->n, STYLE_NORMAL);
  150.         break;
  151.       case EL_BREAK:
  152.         if (opt_b == 0)
  153.           {
  154.             if (output_x != 0 || ep->n)
  155.               {
  156.                 write_nl (); spaces = 0;
  157.               }
  158.           }
  159.         else
  160.           lb_penalty (lb, -10000);
  161.         break;
  162.       case EL_STYLE:
  163.         if (style_sp + 1 >= STYLE_STACK_SIZE)
  164.           fatal ("%s:%d: Style stack overflow", input_fname, line_no);
  165.         style_stack[++style_sp] = ep->n;
  166.         break;
  167.       case EL_ENDSTYLE:
  168.         if (style_sp == 0)
  169.           fatal ("%s:%d: Style stack underflow", input_fname, line_no);
  170.         --style_sp;
  171.         break;
  172.       default:
  173.         abort ();
  174.       }
  175.  
  176.   if (opt_b != 0)
  177.     {
  178.       struct lb_node lbn;
  179.  
  180.       if (lbh != NULL)
  181.         lb_use_hyphenation (lb, lbh);
  182.       rc = lb_format (lb);
  183.       if (rc != 0)
  184.         fatal ("lb_format failed, rc=%d", rc);
  185.       for (;;)
  186.         {
  187.           rc = lb_next (lb, &lbn);
  188.           if (rc != 0)
  189.             fatal ("lb_next failed, rc=%d", rc);
  190.           if (lbn.type == LBN_END)
  191.             break;
  192.           switch (lbn.type)
  193.             {
  194.             case LBN_WORD:
  195.             case LBN_PRE:
  196.             case LBN_POST:
  197.               text_indent (margin);
  198.               write_string (lbn.word);
  199.               break;
  200.             case LBN_GLUE:
  201.               text_indent (margin);
  202.               write_fmt ("%*s", lbn.value, "");
  203.               break;
  204.             case LBN_NEWLINE:
  205.               write_nl ();
  206.               break;
  207.             default:
  208.               abort ();
  209.             }
  210.         }
  211.       lb_exit (&lb);
  212.     }
  213.  
  214.   if (newline && output_x > margin)
  215.     write_nl ();
  216.   return output_line_no - line;
  217. }
  218.  
  219.  
  220. void text_heading1 (void)
  221. {
  222.   env_stack[0].tmargin = 0;
  223.   write_nl ();
  224.   write_nl ();
  225. }
  226.  
  227.  
  228. void text_heading2 (uchar *s)
  229. {
  230.   if (tg_level == 0)
  231.     {
  232.       if (para_flag)
  233.         write_nl ();
  234.       write_nl ();
  235.     }
  236.   write_line (s);
  237.   strset (s, tg_underline);
  238.   write_line (s);
  239. }
  240.  
  241.  
  242. void text_see_also_start (void)
  243. {
  244.   if (para_flag)
  245.     write_nl ();
  246. }
  247.  
  248.  
  249. void text_see_also_end (const uchar *s)
  250. {
  251.   write_string ("  See also: ");
  252.   make_elements (s);
  253.   text_elements (output_x, text_width, TRUE);
  254. }
  255.  
  256.  
  257. void text_description_item (const uchar *s)
  258. {
  259.   write_nl ();
  260.   text_para ();
  261.   make_elements (s);
  262.   text_elements (env_stack[env_sp-1].tmargin, text_width, FALSE);
  263.   if (output_x + 2 <= env_stack[env_sp].tmargin)
  264.     write_string ("  ");
  265.   else
  266.     write_nl ();
  267. }
  268.  
  269.  
  270. void text_enumerate_item (void)
  271. {
  272.   write_nl ();
  273.   text_para ();
  274.   text_indent (env_stack[env_sp-1].tmargin);
  275.   write_fmt ("%d.", ++env_stack[env_sp].counter);
  276. }
  277.  
  278.  
  279. void text_itemize_item (void)
  280. {
  281.   write_nl ();
  282.   text_para ();
  283.   text_indent (env_stack[env_sp-1].tmargin);
  284.   write_string ("- ");
  285. }
  286.  
  287.  
  288. void text_list_item (const uchar *s)
  289. {
  290.   write_nl ();
  291.   text_para ();
  292.   make_elements (s);
  293.   text_elements (env_stack[env_sp-1].tmargin, text_width, TRUE);
  294.   write_nl ();
  295. }
  296.  
  297.  
  298. void text_copy (void)
  299. {
  300.   if (para_flag)
  301.     write_nl ();
  302.   text_elements (env_stack[env_sp].tmargin, text_width, TRUE);
  303. }
  304.  
  305.  
  306. void text_verbatim_start (enum tag tag_end, int *ptmargin)
  307. {
  308.   switch (tag_end)
  309.     {
  310.     case TAG_ENDHEADERS:
  311.       break;
  312.     case TAG_ENDSAMPLECODE:
  313.       write_nl ();
  314.       write_line ("  Example:");
  315.       write_nl ();
  316.       break;
  317.     case TAG_ENDEXAMPLE:
  318.       *ptmargin += 4;
  319.       write_nl ();
  320.       break;
  321.     default:
  322.       write_nl ();
  323.       break;
  324.     }
  325. }
  326.  
  327.  
  328. static void add_compat (uchar *dst, uchar *compat)
  329. {
  330.   int i, len;
  331.  
  332.   len = strlen (dst);
  333.   i = 78 - len - strlen (compat) - 2;
  334.   if (i > 0)
  335.     {
  336.       memset (dst + len, ' ', i);
  337.       len += i;
  338.     }
  339.   dst[len++] = '[';
  340.   strcpy (dst+len, compat);
  341.   strcat (dst+len, "]");
  342.   compat[0] = 0;
  343. }
  344.  
  345.  
  346. void text_verbatim_line (enum tag tag_end, int tmargin, uchar *compat)
  347. {
  348.   uchar buf[512];
  349.  
  350.   memset (buf, ' ', tmargin);
  351.   strcpy (buf + tmargin, input);
  352.   if (tag_end == TAG_ENDHEADERS && compat[0] != 0)
  353.     add_compat (buf, compat);
  354.   write_line (buf);
  355. }
  356.  
  357.  
  358. void text_function (void)
  359. {
  360.   env_stack[0].tmargin = 0;
  361.   write_nl ();
  362.   write_line("---------------------------------------"
  363.              "---------------------------------------");
  364. }
  365.  
  366.  
  367. void text_prototype_start (uchar *compat)
  368. {
  369.   uchar buf[512];
  370.  
  371.   if (compat[0] != 0)
  372.     {
  373.       buf[0] = 0;
  374.       add_compat (buf, compat);
  375.       write_string (buf);
  376.     }
  377.   write_nl ();
  378. }
  379.  
  380.  
  381. void text_prototype_end (void)
  382. {
  383.   text_elements (0, 78, TRUE);
  384.   env_stack[0].tmargin = 4;
  385. }
  386.  
  387.  
  388. void text_toc_line (const uchar *s, const struct toc *tp)
  389. {
  390.   write_string (s);
  391.   write_line (tp->title);
  392. }
  393.  
  394.  
  395. void text_table_start (int do_indent, int *ptmargin)
  396. {
  397.   if (do_indent)
  398.     *ptmargin += 4;
  399.   write_nl ();
  400. }
  401.  
  402.  
  403. void text_table_line (const uchar *s, int tmargin)
  404. {
  405.   make_elements (s);
  406.   if (text_elements (tmargin, 78, TRUE) > 1)
  407.     fatal ("%s:%d: Table entry too long", input_fname, line_no);
  408. }
  409.  
  410.  
  411. void text_sample_file (const uchar *s)
  412. {
  413.   if (para_flag)
  414.     write_nl ();
  415.   write_string ("  Example: See ");
  416.   write_line (s);
  417. }
  418.  
  419.  
  420. void text_libref_section (const uchar *s)
  421. {
  422.   if (para_flag)
  423.     write_nl ();
  424.   write_fmt ("  %s", s);
  425.   write_nl ();
  426.   para_flag = TRUE;
  427. }
  428.  
  429.  
  430. void text_hyphenation (const char *name)
  431. {
  432.   FILE *f;
  433.   char line[128], *p;
  434.   int line_no, rc;
  435.  
  436.   if (opt_b == 0)
  437.     return;
  438.   rc = lbh_init (&lbh);
  439.   if (rc != 0)
  440.     fatal ("lb_init failed, rc=%d", rc);
  441.   f = fopen (name, "rt");
  442.   if (f == NULL)
  443.     {
  444.       perror (name);
  445.       exit (1);
  446.     }
  447.   line_no = 0;
  448.   while (fgets (line, sizeof (line), f) != NULL)
  449.     {
  450.       ++line_no;
  451.       p = strchr (line, '\n');
  452.       if (p == NULL)
  453.         fatal ("%s:%d: Line too long", name, line_no);
  454.       *p = 0;
  455.       rc = lbh_word (lbh, line);
  456.       if (rc != 0)
  457.         fatal ("lbh_word failed, rc=%d", rc);
  458.     }
  459.   if (ferror (f))
  460.     {
  461.       perror (name);
  462.       exit (1);
  463.     }
  464.   fclose (f);
  465. }
  466.