home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / emxtutor.zip / emxsrcd1.zip / emx / src / emxdoc / ipf.c < prev    next >
C/C++ Source or Header  |  1998-07-04  |  15KB  |  721 lines

  1. /* ipf.c -- IPF output
  2.    Copyright (c) 1993-1998 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 <ctype.h>
  26. #include "emxdoc.h"
  27. #include "ipf.h"
  28. #include "xref.h"
  29.  
  30. #define HBAR   0xc4
  31. #define VBAR   0xb3
  32.  
  33. void ipf_hilite (int new)
  34. {
  35.   int diff, font_changed;
  36.  
  37.   if (new & HL_EM)
  38.     new = (new & ~HL_EM) | HL_SL;
  39.   if (hl_ipf == new)
  40.     return;
  41.   font_changed = FALSE;
  42.   diff = new & ~hl_ipf;
  43.   if (diff & HL_TT)
  44.     {
  45.       write_string (":font");
  46.       write_space ();
  47.       write_string ("facename=Courier");
  48.       write_space ();
  49.       write_string ("size=16x9.");
  50.       font_changed = TRUE;
  51.     }
  52.   diff = hl_ipf & ~new;
  53.   if (diff & HL_TT)
  54.     {
  55.       write_string (":font");
  56.       write_space ();
  57.       write_string ("facename=default");
  58.       write_space ();
  59.       write_string ("size=0x0.");
  60.       font_changed = TRUE;
  61.     }
  62.  
  63.   if ((hl_ipf & (HL_BF|HL_SL|HL_UL))
  64.       != (new & (HL_BF|HL_SL|HL_UL)) || font_changed)
  65.     {
  66.       if (hl_ipf_no != 0)
  67.         write_fmt (":ehp%d.", hl_ipf_no);
  68.       if (opt_c && (new & HL_SL))
  69.         hl_ipf_no = 4;
  70.       else
  71.         switch (new & (HL_BF|HL_SL|HL_UL))
  72.           {
  73.           case 0:
  74.             hl_ipf_no = 0;
  75.             break;
  76.           case HL_SL:
  77.             hl_ipf_no = 1;
  78.             break;
  79.           case HL_SL|HL_BF:
  80.             hl_ipf_no = 3;
  81.             break;
  82.           case HL_SL|HL_UL:
  83.           case HL_SL|HL_BF|HL_UL:
  84.             hl_ipf_no = 6;
  85.             break;
  86.           case HL_BF:
  87.             hl_ipf_no = 2;
  88.             break;
  89.           case HL_BF|HL_UL:
  90.             hl_ipf_no = 7;
  91.             break;
  92.           case HL_UL:
  93.             hl_ipf_no = 5;
  94.             break;
  95.           default:
  96.             abort ();
  97.           }
  98.       if (hl_ipf_no != 0)
  99.         write_fmt (":hp%d.", hl_ipf_no);
  100.     }
  101.  
  102.   hl_ipf = new;
  103. }
  104.  
  105.  
  106. static void ipf_string (const uchar *p, int may_break)
  107. {
  108.   const uchar *q;
  109.  
  110.   if (*p == ' ' && output_x >= 60 && may_break)
  111.     {
  112.       write_nl ();
  113.       ++p;
  114.     }
  115.   if (*p == '.' && output_x == 0)
  116.     {
  117.       write_string ("&per.");
  118.       ++p;
  119.     }
  120.   while ((q = strpbrk (p, ":&")) != NULL)
  121.     {
  122.       write_nstring (p, q - p);
  123.       switch (*q)
  124.         {
  125.         case ':':
  126.           write_string ("&colon.");
  127.           break;
  128.         case '&':
  129.           write_string ("&.");
  130.           break;
  131.         default:
  132.           abort ();
  133.         }
  134.       p = q + 1;
  135.     }
  136.   write_string (p);
  137. }
  138.  
  139.  
  140. void ipf_output (const uchar *p, int may_break)
  141. {
  142.   ipf_hilite (hl_stack[hl_sp]);
  143.   ipf_string (p, may_break);
  144. }
  145.  
  146.  
  147. void ipf_para (void)
  148. {
  149.   write_break ();
  150.   write_line (":p.");
  151. }
  152.  
  153.  
  154. void ipf_margin (int margin)
  155. {
  156.   if (out && mode == 'i')
  157.     {
  158.       write_fmt (":lm margin=%d.", margin);
  159.       write_nl ();
  160.     }
  161. }
  162.  
  163.  
  164. void ipf_env_margin (int sp)
  165. {
  166.   ipf_margin (env_stack[sp].imargin);
  167. }
  168.  
  169.  
  170. void ipf_elements (enum style style)
  171. {
  172.   const struct element *ep;
  173.   enum style style_stack[STYLE_STACK_SIZE];
  174.   int style_sp;
  175.  
  176.   style_sp = 0;
  177.   style_stack[style_sp] = style;
  178.   for (ep = elements; ep->el != EL_END; ++ep)
  179.     switch (ep->el)
  180.       {
  181.       case EL_WORD:
  182.       case EL_PUNCT:
  183.         if (ep->n != 0)
  184.           {
  185.             if (ep->wp->database == NULL)
  186.               ipf_begin_link (NULL, ep->wp->ref);
  187.             else
  188.               ipf_begin_link (ep->wp->database->str, ep->wp->ref);
  189.             format_output (ep->wp->str, FALSE);
  190.             ipf_end_link ();
  191.           }
  192.         else if (ep->wp->special != NULL && ep->wp->special->ipf != NULL)
  193.           write_string (ep->wp->special->ipf);
  194.         else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
  195.           format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
  196.                                        ? ep->wp->style : style), FALSE);
  197.         else
  198.           format_string (ep->wp->str, style_stack[style_sp], FALSE);
  199.         break;
  200.       case EL_SPACE:
  201.         format_spaces (ep->n, style_stack[style_sp]);
  202.         break;
  203.       case EL_BREAK:
  204.         write_break ();
  205.         write_line (".br");
  206.         break;
  207.       case EL_STYLE:
  208.         if (style_sp + 1 >= STYLE_STACK_SIZE)
  209.           fatal ("%s:%d: Style stack overflow", input_fname, line_no);
  210.         style_stack[++style_sp] = ep->n;
  211.         break;
  212.       case EL_ENDSTYLE:
  213.         if (style_sp == 0)
  214.           fatal ("%s:%d: Style stack underflow", input_fname, line_no);
  215.         --style_sp;
  216.         break;
  217.       default:
  218.         abort ();
  219.       }
  220. }
  221.  
  222.  
  223. void ipf_begin_link (const uchar *database, int ref)
  224. {
  225.   ipf_hilite (hl_stack[hl_sp]);
  226.   write_string (":link");
  227.   write_space ();
  228.   write_string ("reftype=hd");
  229.   write_space ();
  230.   if (database != NULL && !opt_a)
  231.     {
  232.       write_space ();
  233.       write_fmt ("refid=%d database='%s'", ref, database);
  234.     }
  235.   else
  236.     write_fmt ("res=%d", ref);
  237.   write_string (".");
  238. }
  239.  
  240.  
  241. void ipf_end_link (void)
  242. {
  243.   write_string (":elink.");
  244. }
  245.  
  246.  
  247. void ipf_end_env (void)
  248. {
  249.   switch (env_stack[env_sp].env)
  250.     {
  251.     case ENV_DESCRIPTION:
  252.       write_break ();
  253.       write_line (":edl.");
  254.       break;
  255.     case ENV_ENUMERATE:
  256.       write_break ();
  257.       write_line (":eol.");
  258.       break;
  259.     case ENV_ITEMIZE:
  260.       write_break ();
  261.       write_line (":eul.");
  262.       break;
  263.     case ENV_LIST:
  264.     case ENV_INDENT:
  265.     case ENV_TYPEWRITER:
  266.       write_break ();
  267.       ipf_env_margin (env_sp-1);
  268.       break;
  269.     default:
  270.       abort ();
  271.     }
  272. }
  273.  
  274.  
  275. void ipf_toc_start (void)
  276. {
  277.   write_line (":lines align=left.");
  278. }
  279.  
  280.  
  281. void ipf_toc_line (const uchar *s, const struct toc *tp)
  282. {
  283.   format_string (s, STYLE_NORMAL, FALSE);
  284.   ipf_begin_link (NULL, tp->ref);
  285.   format_output (tp->title, FALSE);
  286.   ipf_end_link ();
  287.   write_nl ();
  288. }
  289.  
  290.  
  291. void ipf_toc_end (void)
  292. {
  293.   write_line (":elines.");
  294. }
  295.  
  296.  
  297. void ipf_heading1 (int level, int ref, int global, unsigned flags)
  298. {
  299.   if (hl_sp != 0)
  300.     fatal ("%s:%d: Hilighting must be off at section heading",
  301.            input_fname, line_no);
  302.   ipf_hilite (hl_stack[hl_sp]);
  303.   write_break ();
  304.   write_fmt (":h%d res=%d", level, ref);
  305.   if (global && !opt_a)
  306.     write_fmt (" id=%d global", ref);
  307.   if (flags & HF_HIDE)
  308.     write_string (" hide");
  309.   write_string (".");
  310. }
  311.  
  312.  
  313. void ipf_heading2 (const uchar *s)
  314. {
  315.   if (tg_level == 0)
  316.     {
  317.       if (para_flag)
  318.         ipf_para ();
  319.       ipf_para ();
  320.       start_hilite (HL_BF);
  321.       format_output (s, FALSE);
  322.       end_hilite ();
  323.     }
  324.   else
  325.     format_output (s, FALSE);
  326.   write_nl ();
  327.   ipf_env_margin (0);
  328. }
  329.  
  330.  
  331. void ipf_description (void)
  332. {
  333.   write_fmt (":dl break=fit tsize=%d.", IPF_DESCRIPTION_INDENT);
  334.   write_nl ();
  335. }
  336.  
  337.  
  338. void ipf_enumerate (void)
  339. {
  340.   write_line (":ol.");
  341. }
  342.  
  343.  
  344. void ipf_itemize (void)
  345. {
  346.   write_line (":ul.");
  347. }
  348.  
  349.  
  350. void ipf_verbatim_start (enum tag tag_end)
  351. {
  352.   switch (tag_end)
  353.     {
  354.     case TAG_ENDHEADERS:
  355.       format_string ("Headers:", STYLE_BOLD, FALSE);
  356.       break;
  357.     case TAG_ENDSAMPLECODE:
  358.       ipf_para ();
  359.       format_string ("Example:", STYLE_BOLD, FALSE);
  360.       break;
  361.     case TAG_ENDEXAMPLE:
  362.       ipf_margin (env_stack[env_sp].imargin + 4);
  363.       break;
  364.     default:
  365.       break;
  366.     }
  367.   write_break ();
  368.   ipf_hilite (hl_stack[hl_sp]); /* Don't switch font after :cgraphic */
  369.   write_line (":cgraphic.");
  370. }
  371.  
  372.  
  373. void ipf_verbatim_line (void)
  374. {
  375.   format_output (input, FALSE);
  376.   write_nl ();
  377. }
  378.  
  379.  
  380. void ipf_verbatim_end (enum tag tag_end)
  381. {
  382.   write_line (":ecgraphic.");
  383.   switch (tag_end)
  384.     {
  385.     case TAG_ENDEXAMPLE:
  386.       ipf_env_margin (env_sp);
  387.       write_line (".br");
  388.       para_flag = FALSE;
  389.       break;
  390.     default:
  391.       para_flag = TRUE;
  392.       break;
  393.     }
  394. }
  395.  
  396.  
  397. void ipf_description_item (const uchar *s)
  398. {
  399.   write_break ();
  400.   write_string (":dt.");
  401.   make_elements (s);
  402.   ipf_elements (STYLE_NORMAL);
  403.   write_break ();
  404.   write_string (":dd.");
  405. }
  406.  
  407.  
  408. void ipf_enumerate_item (void)
  409. {
  410.   write_break ();
  411.   ipf_hilite (hl_stack[hl_sp]); /* Use correct font for number */
  412.   write_string (":li.");
  413. }
  414.  
  415.  
  416. void ipf_itemize_item (void)
  417. {
  418.   write_break ();
  419.   ipf_hilite (hl_stack[hl_sp]); /* Use correct font for mark */
  420.   write_string (":li.");
  421. }
  422.  
  423.  
  424. void ipf_list_item (const uchar *s)
  425. {
  426.   ipf_env_margin (env_sp-1);
  427.   ipf_para ();
  428.   make_elements (s);
  429.   ipf_elements (STYLE_NORMAL);
  430.   ipf_para ();
  431.   ipf_env_margin (env_sp);
  432. }
  433.  
  434.  
  435. void ipf_prototype_start (void)
  436. {
  437.   if (para_flag)
  438.     ipf_para ();
  439.   format_string (function_count == 1 ? "Prototype:" : "Prototypes:",
  440.                  STYLE_BOLD, FALSE);
  441.   write_break ();
  442.   ipf_para ();
  443. }
  444.  
  445.  
  446. void ipf_prototype_end (uchar *compat)
  447. {
  448.   ipf_elements (STYLE_TTY);
  449.   ipf_para ();
  450.   if (compat[0] != 0)
  451.     {
  452.       format_string ("Compatibility:", STYLE_BOLD, FALSE);
  453.       ipf_para ();
  454.       format_string (compat, STYLE_NORMAL, FALSE);
  455.       ipf_para ();
  456.       compat[0] = 0;
  457.     }
  458.   format_string ("Description:", STYLE_BOLD, FALSE);
  459. }
  460.  
  461.  
  462. void ipf_start (void)
  463. {
  464.   write_line (":userdoc.");
  465.   write_line (":prolog.");
  466.   write_line (":docprof toc=123.");
  467.   if (title != NULL)
  468.     {
  469.       write_string (":title.");
  470.       format_string (title, STYLE_NORMAL, FALSE);
  471.       write_nl ();
  472.     }
  473.   write_line (":eprolog.");
  474.   write_line (":body.");
  475. }
  476.  
  477.  
  478. void ipf_table_start (int do_indent, int *widths, int wn)
  479. {
  480.   int wi;
  481.  
  482.   if (do_indent)
  483.     ipf_margin (env_stack[env_sp].imargin + 4);
  484.   write_break ();
  485.   write_string (":table");
  486.   if (wn != 0)
  487.     {
  488.       write_string (" cols='");
  489.       for (wi = 0; wi < wn; ++wi)
  490.         {
  491.           if (wi != 0)
  492.             write_string (" ");
  493.           write_fmt ("%d", widths[wi]);
  494.         }
  495.       write_string ("'");
  496.     }
  497.   write_line (".");
  498. }
  499.  
  500.  
  501. void ipf_table_line (const uchar *s, int wn)
  502. {
  503.   int wi;
  504.   uchar word[512], *d;
  505.  
  506.   if (*s != HBAR)
  507.     {
  508.       write_line (":row.");
  509.       wi = 0;
  510.       while (*s != 0)
  511.         {
  512.           ++wi;
  513.           write_string (":c.");
  514.           d = word;
  515.           while (*s != VBAR && *s != 0)
  516.             *d++ = *s++;
  517.           while (d != word && isspace (d[-1]))
  518.             --d;
  519.           *d = 0;
  520.           make_elements (word);
  521.           ipf_elements (STYLE_NORMAL);
  522.           write_break ();
  523.           if (*s != 0)
  524.             {
  525.               ++s;
  526.               while (isspace (*s))
  527.                 ++s;
  528.             }
  529.         }
  530.       if (wi != wn)
  531.         fatal ("%s:%d: Wrong number of columns", input_fname, line_no);
  532.     }
  533. }
  534.  
  535.  
  536. void ipf_table_end (int do_indent)
  537. {
  538.   write_line (":etable.");
  539.   if (do_indent)
  540.     {
  541.       ipf_env_margin (env_sp);
  542.       write_line (".br");
  543.       para_flag = FALSE;
  544.     }
  545.   else
  546.     para_flag = TRUE;
  547. }
  548.  
  549.  
  550. void ipf_index (const uchar *s)
  551. {
  552.   struct word *wp;
  553.  
  554.   switch (tg_level)
  555.     {
  556.     case 0:
  557.       write_string (":i1.");
  558.       ipf_string (s, FALSE);
  559.       write_nl ();
  560.       break;
  561.     case 1:
  562.       if (*s == 0)
  563.         idx_refid = 0;
  564.       else
  565.         {
  566.           wp = word_add (s);
  567.           if (wp->idx == 0)
  568.             {
  569.               idx_refid = wp->idx = ++idx_no;
  570.               write_fmt (":i1 id=%d.", idx_refid);
  571.               ipf_string (s, FALSE);
  572.               write_nl ();
  573.             }
  574.           else
  575.             idx_refid = wp->idx;
  576.         }
  577.       break;
  578.     case 2:
  579.       if (idx_refid == 0)
  580.         fatal ("%s:%d: %ci2 without %ci1", input_fname, line_no,
  581.                escape, escape);
  582.       write_fmt (":i2 refid=%d.", idx_refid);
  583.       ipf_string (s, FALSE);
  584.       write_nl ();
  585.       break;
  586.     default:
  587.       abort ();
  588.     }
  589. }
  590.  
  591.  
  592. void ipf_see_also_start (void)
  593. {
  594.   if (para_flag)
  595.     ipf_para ();
  596.   format_string ("See also: ", STYLE_BOLD, FALSE);
  597. }
  598.  
  599.  
  600. void ipf_see_also_word (const uchar *word, const uchar *s)
  601. {
  602.   struct word *wp;
  603.  
  604.   wp = use_reference (word);
  605.   if (wp != NULL)
  606.     {
  607.       if (wp->database == NULL)
  608.         ipf_begin_link (NULL, wp->ref);
  609.       else
  610.         ipf_begin_link (wp->database->str, wp->ref);
  611.       write_string (word);
  612.       ipf_end_link ();
  613.     }
  614.   if (*s != 0)
  615.     {
  616.       write_string (",");
  617.       if (output_x >= 60)
  618.         write_nl ();
  619.       else
  620.         write_string (" ");
  621.     }
  622. }
  623.  
  624.  
  625. void ipf_sample_file (const uchar *s)
  626. {
  627.   if (para_flag)
  628.     ipf_para ();
  629.   format_string ("Example: ", STYLE_BOLD, FALSE);
  630.   format_string ("See ", STYLE_NORMAL, FALSE);
  631.   format_string (s, STYLE_TTY, FALSE);
  632.   para_flag = TRUE;
  633. }
  634.  
  635.  
  636. void ipf_libref_section (const uchar *s)
  637. {
  638.   if (para_flag)
  639.     ipf_para ();
  640.   format_string (s, STYLE_BOLD, FALSE);
  641.   para_flag = TRUE;
  642. }
  643.  
  644.  
  645. void ipf_function_start (const struct toc *tp)
  646. {
  647.   ipf_heading1 (2, tp->ref, tp->global, 0);
  648.   write_line (tp->title);
  649.   if (idx_refid == 0)
  650.     fatal ("%s:%d: %cfunction without %ci1",
  651.            input_fname, line_no, escape, escape);
  652.   ipf_margin (1);
  653. }
  654.  
  655.  
  656. void ipf_function_function (const uchar *s)
  657. {
  658.   write_break ();
  659.   write_fmt (":i2 refid=%d.", idx_refid);
  660.   write_line (s);
  661. }
  662.  
  663.  
  664. void ipf_copy (void)
  665. {
  666.   if (para_flag)
  667.     ipf_para ();
  668.   switch (env_stack[env_sp].env)
  669.     {
  670.     case ENV_TYPEWRITER:
  671.       ipf_elements (STYLE_TTY);
  672.       break;
  673.     default:
  674.       ipf_elements (STYLE_NORMAL);
  675.       break;
  676.     }
  677. }
  678.  
  679.  
  680. void ipf_minitoc (const struct toc *tp)
  681. {
  682.   int level, any;
  683.  
  684.   if (tp == NULL)
  685.     fatal ("%s:%d: Cannot build minitoc before the first heading",
  686.            input_fname, line_no);
  687.   if (para_flag)
  688.     ipf_para ();
  689.   level = tp->level;
  690.   tp = tp->next;
  691.   any = FALSE;
  692.   while (tp != NULL && tp->level >= level + 1)
  693.     {
  694.       if (tp->level == level + 1)
  695.         {
  696.           if (!any)
  697.             {
  698.               write_line (":lines align=left.");
  699.               any = TRUE;
  700.             }
  701.           ipf_begin_link (NULL, tp->ref);
  702.           format_output (tp->title, FALSE);
  703.           ipf_end_link ();
  704.           write_nl ();
  705.         }
  706.       tp = tp->next;
  707.     }
  708.   if (any)
  709.     {
  710.       write_line (":elines.");
  711.       para_flag = TRUE;
  712.     }
  713. }
  714.  
  715.  
  716. void ipf_end (void)
  717. {
  718.   ipf_hilite (0);
  719.   write_line (":euserdoc.");
  720. }
  721.