home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / txict100.zip / texicvt1.00 / source / util.cc < prev    next >
C/C++ Source or Header  |  1997-03-31  |  20KB  |  838 lines

  1. /*
  2. ================================================================================
  3.                         Texinfo converting Tools
  4.                          Release 1.00 28.03.97
  5.                        (c) 1996 by Andreas Kaiser
  6.                     (c) 1997 by Karl Heinz Marbaise
  7. ================================================================================
  8.  
  9. Discription:
  10.     Utilities to support conversion to IPF
  11.  
  12. Authors:
  13.    Andreas Kaiser
  14.    Karl Heinz Marbaise
  15.  
  16. e-mail:
  17.    Internet: KHMarbaise@p69.ks.fido.de
  18.    Fido-net: 2:2452/117.69
  19.  
  20. Bugs, question:
  21.    to above e-mail adress.
  22.  
  23. Register:
  24.    Please send a e-mail to above adress to register.
  25.    (include the release you want to register)
  26.    This registration should be done to let me
  27.    know how many people using these tools and
  28.    if it is worth to invest more time in continuing
  29.    development these tools or let the first release
  30.    of them be the last.
  31.    That is the only reason to make a registration.
  32.    I think a e-mail is not to much, isn't it?
  33.  
  34. License:
  35.    The "Texinfo converting tools" are free software;
  36.    you can redistribute it and/or modify it under the terms of
  37.    the GNU General Public License as published by the Free
  38.    Software Foundation; either version 2, or (at your option)
  39.    any later version.
  40.  
  41.    The "Texinfo converting tools" are distributed in the hope that
  42.    they will be useful, but WITHOUT ANY WARRANTY; without even the
  43.    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  44.    PURPOSE.  See the GNU General Public License for more details.
  45.  
  46.    You should have received a copy of the GNU General Public License
  47.    along with the "Texinfo converting tools" ; see the file COPYING.
  48.    If not, write to the:
  49.    Free Software Foundation,
  50.    59 Temple Place - Suite 330,
  51.    Boston, MA 02111-1307, USA.
  52.  
  53.    See \texicvt1.00\COPYING for details.
  54.  
  55. ================================================================================
  56. */
  57. static char *rcsid = "$Id: UTIL.CC 1.5 1997/03/30 15:08:23 KHM Exp $";
  58.  
  59. #include "info.h"
  60. #include <ctype.h>
  61. #include <alloca.h>
  62. #include <limits.h>
  63. #include <minmax.h>
  64.  
  65. static char *    old_font = "default";
  66. static int    preface  = 1;
  67.  
  68. ////////////////////////////////////////////////////////////////////////
  69.  
  70. static const char *fstack[10] = {"default"};
  71. static int       fstackx    = 0;
  72.  
  73. void
  74. font(const char *name, const char *size)
  75. {
  76.     if (!name)
  77.         name = fstack[fstackx];
  78.     if (strcmp(name, "default") == 0) {
  79.         PUTA(":font facename=default size=0x0.");
  80.     } else
  81.         PUTA(":font facename=" << name << " size=" << size << '.');
  82. }
  83.  
  84. void
  85. beg_example(const char *fontname)
  86. {
  87.     newpara = 0;
  88.     ++nofill;
  89.     *out << ":lines align=left.";
  90.     margin(+10);
  91.     fstack[++fstackx] = fontname;
  92.     font(0);
  93.     PUTL();
  94.     newpara = 0;
  95. }
  96.  
  97. void
  98. end_example()
  99. {
  100.     newpara = 0;
  101.     --nofill;
  102.     --fstackx;
  103.     font(0);
  104.     margin(-10);
  105.     *out << ":elines.";
  106.     PUTL();
  107.     newpara = 0;
  108. }
  109.  
  110. ////////////////////////////////////////////////////////////////////////
  111.  
  112. void
  113. words(String& line)
  114. {
  115.     int i = 0;
  116.     String tmp;
  117.     int pos;
  118.     
  119.     for (const char *p1 = line.chars(), *end = p1 + line.length();;) {
  120.         while (p1 < end && isspace(*p1))
  121.             ++p1;
  122.         if (p1 == end)
  123.             break;
  124.         const char *p2 = p1;
  125.         while (p2 < end && *p2 != ',')
  126.             ++p2;
  127.         if (i < MaxW)
  128.         {
  129.             tmp = String (p1, p2 - p1);
  130.             if (tmp.length ())
  131.             {
  132.             pos = tmp.length ()-1;
  133.             
  134.                 while (tmp.length () && (isspace(tmp[pos]) || tmp[pos] == '\t'))
  135.                 tmp.del (pos--,1);
  136.             }
  137.             w[i++] = tmp;
  138.         }
  139.         if (p2 == end)
  140.             break;
  141.         p1 = p2 + 1;
  142.     }
  143.     while (i < MaxW)
  144.         w[i++] = null;
  145. }
  146.  
  147. void
  148. spaced(String& line)
  149. {
  150.     int i = 0;
  151.     for (const char *p1 = line.chars(), *end = p1 + line.length();;) {
  152.         while (p1 < end && isspace(*p1))
  153.             ++p1;
  154.         if (p1 == end)
  155.             break;
  156.         const char *p2 = p1;
  157.         while (p2 < end && !isspace(*p2))
  158.             ++p2;
  159.         if (i < MaxW)
  160.             w[i++] = String(p1, p2 - p1);
  161.         if (p2 == end)
  162.             break;
  163.         p1 = p2 + 1;
  164.     }
  165.     while (i < MaxW)
  166.         w[i++] = null;
  167. }
  168.  
  169. ////////////////////////////////////////////////////////////////////////
  170.  
  171. static int    hstack[6];
  172. static int    hlevel = 0;
  173.  
  174. void
  175. heading(int level, const char *s)
  176. {
  177.     if (istackp != istack)
  178.         return;
  179.     if (f_node) {
  180.         if (preface)
  181.             PUT(":h2." << s << endl << ":lm margin=1.");
  182.     } else {
  183.         if (debug)
  184.             cerr << "Heading, logical level=" << level
  185.                  << " stack level=" << hlevel
  186.                  << " stacked=" << hstack[hlevel];
  187.         if (level > hstack[hlevel])
  188.             hstack[++hlevel] = level;
  189.         else while (level < hstack[hlevel])
  190.             --hlevel;
  191.         if (debug)
  192.             cerr << " panel level=" << hlevel << endl;
  193.         if (node_id) {
  194.             panel_id = node_id;
  195.             node_id = 0;
  196.         } else
  197.             panel_id = ++hdid;
  198.         panel_name = s;
  199.         PUT(":h" << hlevel << " id=hd" << panel_id << '.' << s
  200.              << endl << ":lm margin=1.");
  201.     }
  202. }
  203.  
  204.  
  205. void
  206. Menu::flush()
  207. {
  208.     int x1;
  209.     int x2;
  210.     String name;
  211.     String Node;
  212.     String Filename;
  213.     String Text;
  214.  
  215.     if (!line.length())
  216.         return;
  217.  
  218.     x1 = line.index("&colon.");
  219.     if (debug)
  220.         cerr << "Menu::flush ()" << endl
  221.              << "    line=\"" << line << "\"" << endl;
  222.  
  223.  
  224.     if (x1>=0)
  225.     {
  226.         x2 = line.index ("&colon.", x1+7);
  227.         /* Is this a menu entry like:
  228.            * Node::   discription
  229.          */
  230.         if (x2 > 0)
  231.         {
  232.             /* Yes it is. */
  233.         if ((x2-x1) == 7)
  234.         {
  235.         name = line.before (x1);
  236.         if (debug)
  237.             cerr << "Menu::flush ()" << endl
  238.              << "    name1=\"" << name << "\"" << endl;
  239.         }
  240.             else
  241.                 cerr << "Menu::flush ()" << endl
  242.                      << "    the second colon is not positioned after the first!" << endl;
  243.  
  244.             if (!table.contains(name))
  245.                 table[name] = Name(++hdid);
  246.  
  247.             for (x2 += 7; x2 < line.length() && isspace(line[x2]); ++x2)
  248.                 ;
  249.  
  250.             Node = line.before (x1);
  251.             Text = line.from (x2);
  252.             if (!Text.length ())
  253.                 Text = Node;
  254.  
  255.         *out << ":pt.:link reftype=hd refid=hd" << table[Node].id
  256.          << '.' <<  Node << ":elink.:pd."
  257.          << Text << endl;
  258.  
  259.             /* *out << "<LI><A HREF=\"#"
  260.                  << Node << "\">"
  261.                  << Text << "</A>"
  262.                  << endl; */
  263.  
  264.         }
  265.         else
  266.         {
  267.             /* If we came here it might be an
  268.              * entry like this:
  269.              * Entry: node-name.   Discription
  270.              * Entry&colon. node-name.  Discription
  271.              */
  272.             /* search the positition of the dot */
  273.             x2 = line.index (".", x1+7);
  274.  
  275.             for (x1 += 7; x1 < line.length() && isspace(line[x1]); ++x1)
  276.                 ;
  277.             name = line.at (x1, x2-x1);
  278.  
  279.             for (x2 += 1; x2 < line.length() && isspace(line[x2]); ++x2)
  280.                 ;
  281.  
  282.             /* check if a file name is part of the node */
  283.             if (name.index("(", 1) == 1)
  284.             {
  285.                 /* extract the file name */
  286.                 Filename = name.at (name.index("(",1), name.index (")", 2));
  287.                 while (name[0]!=')' && name.length ())
  288.                     name.del(0,1);
  289.             }
  290.             else
  291.                 Filename = "";
  292.  
  293.             if (Filename.length())
  294.             {
  295.                 /* Node out of another file */
  296.                 cerr << "Menu::line ()" << endl
  297.                      << "  actualy we don't support this" << endl;
  298.             }
  299.             else
  300.             {
  301.             }
  302.  
  303.                 Text =  line.from (x2);
  304.                 if (!Text.length ())
  305.                     Text = name;
  306.  
  307.                 if (!table.contains(name))
  308.                     table[name] = Name(++hdid);
  309.         *out << ":pt.:link reftype=hd refid=hd" << table[name].id
  310.              << '.' << name << ":elink.:pd."
  311.              << Text << endl;
  312.  
  313.                 /* *out << "<LI><A HREF=\"#" << name << "\">"
  314.                      << Text << "</A>"
  315.                      << endl; */
  316.  
  317.             if (debug)
  318.                 cerr << "*** Node=\"" << name << "\"" << endl
  319.                      << "    Text=\"" << Text << "\"" << endl
  320.                      << "    File=\"" << Filename << "\"" << endl;
  321.         }
  322.     } /* if (x1>=0)... */
  323.  
  324. /*************************************
  325.     if (line.length() == 0)
  326.         return;
  327.     int x1 = line.index("&colon.");
  328.         cerr << "Menu::flush ()" << endl
  329.              << "    line=\"" << line << "\"" << endl;
  330.  
  331.     if (x1 >= 0) {
  332.         int x2 = line.index("&colon.", x1+7);
  333.         if (x2 >= 0) {
  334.             String name = line.at(x1+7, x2-x1-7);
  335.             if (name.length() == 0)
  336.                 name = line.before(x1);
  337.             if (!table.contains(name))
  338.                 table[name] = Name(++hdid);
  339.             for (x2 += 7; x2 < line.length() && isspace(line[x2]); ++x2)
  340.                 ;
  341.             *out << ":pt.:link reftype=hd refid=hd" << table[name].id
  342.                  << '.' << line.before(x1) << ":elink.:pd."
  343.                  << line.from(x2) << endl;
  344.         }
  345.     } **********************************/
  346.     line = "";
  347. }
  348.  
  349. void
  350. node(String name, String next, String prev, String up)
  351. {
  352.     if (table.contains(up)) {
  353.         if (f_node)
  354.             hlevel = table[up].level + 1;
  355.     } else if (name == "Top" || up.length() == 0) {
  356.         if (f_node)
  357.             hlevel = 0;
  358.     } else {
  359.         cerr << "<up> node undefined in '" << name << "', '" << next
  360.             << "', '" << prev << "', '" << up << '\'' << endl;
  361.         cerr.flush();
  362. #if 0
  363.         exit(1);
  364. #endif
  365.     }
  366.     if (debug)
  367.         cerr << "Define name='" << name << "' next='" << next
  368.              << "' prev='" << prev << "' up='" << up << "'";
  369.     Name& entry = table[name];
  370.     if (entry.id) {
  371.         if (entry.defined) {
  372.             cerr << "Node '" << name << "' redefined " << endl;
  373.             cerr.flush();
  374. #if 0
  375.             exit(1);
  376. #endif
  377.         }
  378.         entry.defined = 1;
  379.         if (debug)
  380.             cerr << ", known id=" << entry.id << endl;
  381.     } else {
  382.         table[name] = Name(++hdid, 1, hlevel);
  383.         if (debug)
  384.             cerr << ", new id=" << hdid << endl;
  385.     }
  386.     if (f_node && hlevel >= 1 && hlevel <= 6 && istackp == istack) {
  387.         preface = 0;
  388.         PUT(":h" << hlevel << " id=hd" << entry.id << '.' << name
  389.              << endl << ":lm margin=1.");
  390.     }
  391.     node_name = name;
  392.     node_id = entry.id;
  393. }
  394.  
  395. void
  396. xref(char *see, String name, String entry, String topic, String file, String manual)
  397. {
  398.     if (debug)
  399.         cerr << "Refer to name='" << name << "' entry='" << entry
  400.              << "' topic='" << topic << "' file='" << file
  401.              << "' manual='" << manual << "'";
  402.     if (see)
  403.         PUTS(see);
  404.     if (file.empty()) {
  405.         if (!table.contains(name)) {
  406.             table[name] = Name(++hdid);
  407.             if (debug)
  408.                 cerr << " new id=" << hdid << endl;
  409.         } else
  410.             if (debug)
  411.                 cerr << " known id=" << table[name].id << endl;
  412.         PUTS(":link reftype=hd refid=hd" << table[name].id << '.');
  413.         if (topic.length()) {
  414.             PUT(topic);
  415.         } else
  416.             PUT(name);
  417.         if (entry.length())
  418.             PUT(": " << entry);
  419.         PUT(":elink.");
  420.     } else
  421.         PUTS("Section " << topic << " of :hp1." << manual << ":ehp1.");
  422. }
  423.  
  424. ////////////////////////////////////////////////////////////////////////
  425.  
  426. static int current_margin = 0;
  427.  
  428. static void
  429. set_margin(int indent)
  430. {
  431.     current_margin = indent;
  432.     PUTA(":lm margin=" << (1 + current_margin) << '.');
  433. }
  434.  
  435.     // > 0: indent
  436.     // < 0: extend
  437.     // = 0: reset
  438. int
  439. margin(int delta)
  440. {
  441.     int old = current_margin;
  442.     if (delta) {
  443.         current_margin += delta;
  444.         if (current_margin < 0)
  445.             current_margin = 0;
  446.     } else
  447.         current_margin = 0;
  448.     PUTA(":lm margin=" << (1 + current_margin) << '.');
  449.     return old;
  450. }
  451.  
  452. void
  453. item_begin(const char *text, int it, char *ic)
  454. {
  455.     if (istackp == istack) {
  456.         istackp->indent = current_margin;
  457.         istackp->nested = 1;
  458.     }
  459.     ++istackp;
  460.     istackp->type = it;
  461.     istackp->cat = ic;
  462.     istackp->beg = Item();
  463.     istackp->end = Item();
  464.     istackp->indent = current_margin;
  465.     switch (it) {
  466.     case 'o':
  467.         istackp->indent += 3;
  468.         break;
  469.     case 'u':
  470.         istackp->indent += 5;
  471.         break;
  472.     case 'p':
  473.         istackp->indent += 12;
  474.         break;
  475.     }
  476.     istackp->nested = 0;
  477.     istackp->count = 0;
  478.     for (ItemType *p = istack; p < istackp; ++p)
  479.         if (p->type == 'p')
  480.             ++istackp->nested;
  481.     PUTL();
  482.     if (!istackp->nested)
  483.         PUT(text);
  484.     newpara = 0;
  485. }
  486.  
  487. void
  488. ItemType::item(const char *text)
  489. {
  490.         newpara = 0;
  491.     if (nested) {
  492.         set_margin((istackp-1)->indent);
  493.         *out << ":p.";
  494.         switch (type) {
  495.         case 'o':
  496.             margin(+1);
  497.             *out << ".&larrow.";
  498.             margin(+2);
  499.             break;
  500.         case 'u':
  501.             margin(+2);
  502.             *out << ++count << '.';
  503.             margin(+3);
  504.             break;
  505.         }
  506.     } else if (type == 'p')
  507.         *out << ":pt.";
  508.     else
  509.         *out << ":li.";
  510.  
  511.     if (text && *text) {
  512.         if (beg.fontname)
  513.             *out << ":font facename=" << beg.fontname
  514.                  << " size=" FontSize ".";
  515.         if (beg.hpnumber == 100)
  516.             *out << "&sqbul.";
  517.         else if (beg.hpnumber)
  518.             *out << ":hp" << beg.hpnumber << '.';
  519.         if (beg.delimiter)
  520.             *out << beg.delimiter;
  521.  
  522.         //*out << text << " ";
  523.         *out << text;
  524.  
  525.         if (end.delimiter)
  526.             *out << end.delimiter;
  527.         if (end.hpnumber)
  528.             *out << ":ehp" << end.hpnumber << '.';
  529.         if (end.fontname)
  530.             *out << ":font facename=" << end.fontname
  531.                 << " size=" FontSize ".";
  532.         *out << endl << ".br" << endl; // new khm
  533.     }
  534.  
  535.     if (type == 'p') {
  536.         if (nested)
  537.             margin(+12);
  538.         else
  539.             *out << ":pd.";
  540.     }
  541. }
  542.  
  543. void
  544. item_end(const char *text)
  545. {
  546.     PUTL();
  547.     if (istackp->nested)
  548.         newpara = 1;
  549.     else {
  550.         PUT(text);
  551.         newpara = 0;
  552.     }
  553.     --istackp;
  554.     set_margin(istackp->indent);
  555. }
  556.  
  557. ////////////////////////////////////////////////////////////////////////
  558.  
  559. /*
  560.  * @defcv category class name
  561.  * @deffn category name arguments...
  562.  * @defivar class instance-var-name
  563.  * @defmac macro-name arguments...
  564.  * @defmethod class method-name arguemtns...
  565.  * @defop category classs name arguments...
  566.  *
  567.  */
  568. void define
  569.          (
  570.              String& s,
  571.              int xflag,  /* handle def...x situation */
  572.              const char *index,
  573.              int typeflag,  /* 1 */
  574.              int argflag,   /* 1 */
  575.              const char *category
  576.          )
  577. {
  578.     int i = 0, len = s.length();
  579.     String cat = category, type, name;
  580.  
  581.     if (!cat.length()) {
  582.         while (i < len && isspace(s[i]))
  583.             i++;
  584.         while (i < len && !isspace(s[i]))
  585.             cat += s[i++];
  586.     }
  587.     if (typeflag) {
  588.         while (i < len && isspace(s[i]))
  589.             i++;
  590.         while (i < len && !isspace(s[i]))
  591.             type += s[i++];
  592.     }
  593.     while (i < len && isspace(s[i]))
  594.         i++;
  595.     while (i < len && !isspace(s[i]) && s[i] != '(')
  596.         name += s[i++];
  597.     while (i < len && isspace(s[i]))
  598.         i++;
  599.  
  600.     if (xflag)
  601.         margin(-10);
  602.     else if (newpara)
  603.         para();
  604.     font("Courier", FontSize);
  605.     if (type.length())
  606.         *out << type << " ";
  607.     *out << ":hp2." << name << ":ehp2. ";
  608.     if (i < len)
  609.         if (argflag)
  610.             *out << ":hp1." << s.from(i) << ":ehp1.";
  611.         else
  612.             *out << s.from(i);
  613.     font(0, 0);
  614.     *out << "    :hp9.(" << cat << "):ehp9.";
  615.     *out << "\n.br\n";
  616.     lastnl = 1;
  617.         margin(10);
  618.     indexref(index, name);
  619. }
  620.  
  621. ////////////////////////////////////////////////////////////////////////
  622.  
  623. static void
  624. xentry(String& xk, XEntry& xe)
  625. {
  626.     PUT(":pt." << xk << endl << ":pd.");
  627.     int ne = 0;
  628.     for (Pix item = xe.first(); item; xe.next(item)) {
  629.         if (ne++)
  630.             PUT(".br" << endl);
  631.         XItem& xi = xe(item);
  632.         PUT(":link reftype=hd refid=hd" << xi.id << '.'
  633.          << xi.title << ":elink." << endl);
  634.     }
  635. }
  636.  
  637. void
  638. indexref(const char *classname, const String& text)
  639. {
  640.     indexes[classname].entries[text].add(XItem(panel_name, panel_id));
  641.     if (f_index) {
  642.         static int id = 0;
  643.         PUT(":i1 id=i" << ++id << '.' << text);
  644.         PUTL();
  645.     }
  646. }
  647.  
  648. void
  649. printindex(String& classname)
  650. {
  651.     XClassT& xc = indexes[classname].entries;
  652.     int ckeys[UCHAR_MAX+1], digit = 0, other = 0;
  653.     enum { Small, CType, Medium, Huge } mode;
  654.  
  655.     const Limit = 1000;
  656.  
  657.     if (xc.length() >= Limit) {
  658.         memset(ckeys, 0, sizeof ckeys);
  659.         for (Pix entry = xc.first(); entry; xc.next(entry)) {
  660.             unsigned char c = xc.key(entry)[0];
  661.             if (isalpha(c))
  662.                 ++ckeys[toupper(c)];
  663.             else
  664.                 ++ckeys[c];
  665.         }
  666.         mode = Medium;
  667.         for (int i = 0; i <= UCHAR_MAX; ++i) {
  668.             if (ckeys[i] >= Limit) {
  669.                 mode = Huge;
  670.                 break;
  671.             }
  672.             if (isdigit(i))
  673.                 digit += ckeys[i];
  674.             else if (!isalpha(i))
  675.                 other += ckeys[i];
  676.         }
  677.         if (mode == Medium && digit < Limit && other < Limit)
  678.             mode = CType;
  679.     } else
  680.         mode = Small;
  681.  
  682.     switch (mode) {
  683.  
  684.     case Huge: {
  685.         int count = xc.length();
  686.         int chunk = count / 50;
  687.         int i = 0;
  688.         String *keys = new String [count];
  689.         Pix entry;
  690.         for (entry = xc.first(); entry; xc.next(entry))
  691.             keys[i++] = xc.key(entry).before(' ');
  692.         i = 0;
  693.         for (entry = xc.first(); entry; xc.next(entry)) {
  694.             if (i % chunk == 0) {
  695.                 if (i)
  696.                     PUT(":eparml." << endl)
  697.                 PUT(":h" << hlevel+1 << '.'
  698.                      << keys[i]
  699.                      << "  &dot.&dot.&dot.  "
  700.                      << keys[min(i+chunk-1, count-1)]
  701.                      << endl);
  702.                 PUT(":parml tsize=50 break=none compact." << endl);
  703.             }
  704.             xentry(xc.key(entry), xc.contents(entry));
  705.             ++i;
  706.         }
  707.         delete [] keys;
  708.         }
  709.         break;
  710.  
  711.     case Medium: {
  712.         unsigned char c0 = 0;
  713.         for (Pix entry = xc.first(); entry; xc.next(entry)) {
  714.             unsigned char c = toupper(xc.key(entry)[0]);
  715.             if (c != c0) {
  716.                 if (c0)
  717.                     PUT(":eparml.");
  718.                 c0 = c;
  719.                 PUT(":h" << hlevel+1 << '.' << c << endl);
  720.                 PUT(":parml tsize=50 break=none compact." << endl);
  721.             }
  722.             xentry(xc.key(entry), xc.contents(entry));
  723.         }
  724.         }
  725.         break;
  726.  
  727.     case CType: {
  728.         unsigned char c1, c2 = 0;
  729.         for (Pix entry = xc.first(); entry; xc.next(entry)) {
  730.             unsigned char c = toupper(xc.key(entry)[0]);
  731.             if (!isalpha(c))
  732.                 continue;
  733.             if (c > c2) {
  734.                 if (c2)
  735.                     PUT(":eparml." << endl);
  736.                 c1 = c;
  737.                 int n = ckeys[c1];
  738.                 for (c2 = c1; isalpha(c2+1); ++c2) {
  739.                     n += ckeys[c2+1];
  740.                     if (n > 100)
  741.                         break;
  742.                 }
  743.                 PUT(":h" << hlevel+1 << '.');
  744.                 if (c1 != c2)
  745.                     PUT(c1 << "&dot.&dot.&dot." << c2)
  746.                 else
  747.                     PUT(c1);
  748.                 PUT(endl);
  749.                 PUT(":parml tsize=50 break=none compact." << endl);
  750.             }
  751.             xentry(xc.key(entry), xc.contents(entry));
  752.         }
  753.         if (digit) {
  754.             PUT(":eparml." << endl);
  755.             PUT(":h" << hlevel+1 << ".0&dot.&dot.&dot.9" << endl);
  756.             PUT(":parml tsize=50 break=none compact." << endl);
  757.             for (Pix entry = xc.first(); entry; xc.next(entry)) {
  758.                 unsigned char c = toupper(xc.key(entry)[0]);
  759.                 if (isdigit(c))
  760.                     xentry(xc.key(entry), xc.contents(entry));
  761.             }
  762.         }
  763.         if (other) {
  764.             PUT(":eparml." << endl);
  765.             PUT(":h" << hlevel+1 << ".&dot.&dot.&dot." << endl);
  766.             PUT(":parml tsize=50 break=none compact." << endl);
  767.             for (Pix entry = xc.first(); entry; xc.next(entry)) {
  768.                 unsigned char c = toupper(xc.key(entry)[0]);
  769.                 if (!isalpha(c) && !isdigit(c))
  770.                     xentry(xc.key(entry), xc.contents(entry));
  771.             }
  772.         }
  773.         }
  774.         break;
  775.  
  776.     case Small:
  777.         PUT(":parml tsize=50 break=none compact." << endl);
  778.         for (Pix entry = xc.first(); entry; xc.next(entry))
  779.             xentry(xc.key(entry), xc.contents(entry));
  780.     }
  781.     PUT(":eparml.");
  782.     PUTL();
  783. }
  784.  
  785. ////////////////////////////////////////////////////////////////////////
  786.  
  787. void
  788. single_word(const char *text)
  789. {
  790.     int ipf = 0;
  791.     while (*text) {
  792.         char c = *text++;
  793.         switch (c) {
  794.         case ' ':
  795.             if (ipf)
  796.                 break;
  797.             PUTS("&rbl.");
  798.             continue;
  799.         case ':':
  800.         case '&':
  801.             ipf = 1;
  802.             break;
  803.         }
  804.         PUTS(c);
  805.     }
  806. }
  807.  
  808. ////////////////////////////////////////////////////////////////////////
  809.  
  810. void
  811. para()
  812. {
  813.     if (!plevel) {
  814.         *out << ":p.";
  815.         newpara = 0;
  816.     }
  817. }
  818.  
  819. ////////////////////////////////////////////////////////////////////////
  820.  
  821. void
  822. setflag(String& line)
  823. {
  824.     int x = line.index(' ');
  825.     if (x < 0)
  826.         x = line.index('=');
  827.     if (x >= 0)
  828.         flags[line.before(x)] = line.after(x);
  829.     else
  830.         flags[line] = "";
  831. }
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.