home *** CD-ROM | disk | FTP | other *** search
/ Mega A/V / mega_av.zip / mega_av / GRAPHUTL / FRPOR172.ZIP / HELPCOM.H < prev    next >
C/C++ Source or Header  |  1992-03-15  |  16KB  |  806 lines

  1.  
  2. /*
  3.  * helpcom.h
  4.  *
  5.  *
  6.  * Common #defines, structures and code for HC.C and HELP.C
  7.  *
  8.  */
  9.  
  10. #include "port.h"
  11.  
  12. /*
  13.  * help file signature
  14.  */
  15.  
  16. #define HELP_SIG       (0xAFBC1823LU)
  17.  
  18.  
  19. /*
  20.  * commands imbedded in the help text
  21.  */
  22.  
  23. #define CMD_LITERAL      1   /* next char taken literally */
  24. #define CMD_PARA      2   /* paragraph start code */
  25. #define CMD_LINK      3   /* hot-link start/end code */
  26. #define CMD_FF          4   /* force a form-feed */
  27. #define CMD_XONLINE      5   /* exclude from online help on/off */
  28. #define CMD_XDOC      6   /* exclude from printed document on/off */
  29. #define CMD_CENTER      7   /* center this line */
  30. #define CMD_SPACE      8   /* next byte is count of spaces */
  31.  
  32. #define MAX_CMD       8
  33.  
  34.  
  35. /*
  36.  * on-line help dimensions
  37.  */
  38.  
  39. #define SCREEN_WIDTH      (78)
  40. #define SCREEN_DEPTH      (22)
  41. #define SCREEN_INDENT      (1)
  42.  
  43.  
  44. /*
  45.  * printed document dimensions
  46.  */
  47.  
  48. #define PAGE_WIDTH       (72)  /* width of printed text */
  49. #define PAGE_INDENT       (2)     /* indent all text by this much */
  50. #define TITLE_INDENT       (1)     /* indent titles by this much */
  51.  
  52. #define PAGE_RDEPTH       (59)  /* the total depth (inc. heading) */
  53. #define PAGE_HEADING_DEPTH (3)     /* depth of the heading */
  54. #define PAGE_DEPTH       (PAGE_RDEPTH-PAGE_HEADING_DEPTH) /* depth of text */
  55.  
  56.  
  57. /*
  58.  * Document page-break macros.    Goto to next page if this close (or closer)
  59.  * to end of page when starting a CONTENT, TOPIC, or at a BLANK line.
  60.  */
  61.  
  62. #define CONTENT_BREAK (7)  /* start of a "DocContent" entry */
  63. #define TOPIC_BREAK   (4)  /* start of each topic under a DocContent entry */
  64. #define BLANK_BREAK   (2)  /* a blank line */
  65.  
  66.  
  67. /*
  68.  * tokens returned by find_token_length
  69.  */
  70.  
  71. #define TOK_DONE    (0)   /* len == 0          */
  72. #define TOK_SPACE   (1)   /* a run of spaces      */
  73. #define TOK_LINK    (2)   /* an entire link      */
  74. #define TOK_PARA    (3)   /* a CMD_PARA       */
  75. #define TOK_NL        (4)   /* a new-line ('\n')    */
  76. #define TOK_FF        (5)   /* a form-feed (CMD_FF) */
  77. #define TOK_WORD    (6)   /* a word          */
  78. #define TOK_XONLINE (7)   /* a CMD_XONLINE      */
  79. #define TOK_XDOC    (8)   /* a CMD_XDOC       */
  80. #define TOK_CENTER  (9)   /* a CMD_CENTER      */
  81.  
  82.  
  83. /*
  84.  * modes for find_token_length() and find_line_width()
  85.  */
  86.  
  87. #define ONLINE 1
  88. #define DOC    2
  89.  
  90.  
  91. /*
  92.  * struct PD_INFO used by process_document()
  93.  */
  94.  
  95. typedef struct
  96.    {
  97.  
  98.    /* used by process_document -- look but don't touch! */
  99.  
  100.    int         pnum,
  101.          lnum;
  102.  
  103.    /* PD_GET_TOPIC is allowed to change these */
  104.  
  105.    char far *curr;
  106.    unsigned  len;
  107.  
  108.    /* PD_GET_CONTENT is allowed to change these */
  109.  
  110.    char far *id;
  111.    char far *title;
  112.    int         new_page;
  113.  
  114.    /* general parameters */
  115.  
  116.    char far *s;
  117.    int         i;
  118.  
  119.  
  120.    } PD_INFO;
  121.  
  122.  
  123. /*
  124.  * Commands passed to (*get_info)() and (*output)() by process_document()
  125.  */
  126.  
  127. enum  PD_COMMANDS
  128.    {
  129.  
  130. /* commands sent to pd_output */
  131.  
  132.    PD_HEADING,           /* call at the top of each page */
  133.    PD_FOOTING,        /* called at the end of each page */
  134.    PD_PRINT,        /* called to send text to the printer */
  135.    PD_PRINTN,        /* called to print a char n times */
  136.    PD_PRINT_SEC,    /* called to print the section title line */
  137.    PD_START_SECTION,    /* called at the start of each section */
  138.    PD_START_TOPIC,    /* called at the start of each topic */
  139.    PD_SET_SECTION_PAGE, /* set the current sections page number */
  140.    PD_SET_TOPIC_PAGE,    /* set the current topics page number */
  141.    PD_PERIODIC,     /* called just before curr is incremented to next token */
  142.  
  143. /* commands sent to pd_get_info */
  144.  
  145.    PD_GET_CONTENT,
  146.    PD_GET_TOPIC,
  147.    PD_RELEASE_TOPIC,
  148.    PD_GET_LINK_PAGE
  149.  
  150.    } ;
  151.  
  152.  
  153. typedef int (*PD_FUNC)(int cmd, PD_INFO *pd, VOIDPTR info);
  154.  
  155.  
  156. int _find_token_length(char far *curr, unsigned len, int *size, int *width);
  157. int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width);
  158. int find_line_width(int mode, char far *curr, unsigned len);
  159. int process_document(PD_FUNC get_info, PD_FUNC output, VOIDPTR info);
  160.  
  161.  
  162. /*
  163.  * Code common to both HC.C and HELP.C (in Fractint).
  164.  * #include INCLUDE_COMMON once for each program
  165.  */
  166.  
  167.  
  168. #ifdef INCLUDE_COMMON
  169.  
  170.  
  171. #ifndef XFRACT
  172. #define getint(ptr) (*(int far *)(ptr))
  173. #define setint(ptr,n) (*(int far *)(ptr)) = n
  174. #else
  175. /* Get an int from an unaligned pointer
  176.  * This routine is needed because this program uses unaligned 2 byte
  177.  * pointers all over the place.
  178.  */
  179. getint(ptr)
  180. char *ptr;
  181. {
  182.     int s;
  183.     bcopy(ptr,&s,sizeof(int));
  184.     return s;
  185. }
  186.  
  187. /* Set an int to an unaligned pointer */
  188. void setint(ptr, n)
  189. int n;
  190. char *ptr;
  191. {
  192.     bcopy(&n,ptr,sizeof(int));
  193. }
  194. #endif
  195.  
  196.  
  197. static int is_hyphen(char far *ptr)   /* true if ptr points to a real hyphen */
  198.    {                   /* checkes for "--" and " -" */
  199.    if ( *ptr != '-' )
  200.       return (0);    /* that was easy! */
  201.  
  202.    --ptr;
  203.  
  204.    return ( *ptr!=' ' && *ptr!='-' );
  205.    }
  206.  
  207.  
  208. int _find_token_length(register char far *curr, unsigned len, int *size, int *width)
  209.    {
  210.    register int _size  = 0;
  211.    register int _width = 0;
  212.    int tok;
  213.  
  214.    if (len == 0)
  215.       tok = TOK_DONE;
  216.  
  217.    else
  218.       {
  219.       switch ( *curr )
  220.      {
  221.      case ' ':    /* it's a run of spaces */
  222.         tok = TOK_SPACE;
  223.         while ( *curr == ' ' && _size < len )
  224.            {
  225.            ++curr;
  226.            ++_size;
  227.            ++_width;
  228.            }
  229.         break;
  230.  
  231.      case CMD_SPACE:
  232.         tok = TOK_SPACE;
  233.         ++curr;
  234.         ++_size;
  235.         _width = *curr;
  236.         ++curr;
  237.         ++_size;
  238.         break;
  239.  
  240.      case CMD_LINK:
  241.         tok = TOK_LINK;
  242.             _size += 1+3*sizeof(int); /* skip CMD_LINK + topic_num + topic_off + page_num */
  243.             curr += 1+3*sizeof(int);
  244.  
  245.         while ( *curr != CMD_LINK )
  246.            {
  247.            if ( *curr == CMD_LITERAL )
  248.           {
  249.           ++curr;
  250.           ++_size;
  251.           }
  252.            ++curr;
  253.            ++_size;
  254.            ++_width;
  255.            assert(_size < len);
  256.            }
  257.  
  258.         ++_size;   /* skip ending CMD_LINK */
  259.         break;
  260.  
  261.      case CMD_PARA:
  262.         tok = TOK_PARA;
  263.         _size += 3;     /* skip CMD_PARA + indent + margin */
  264.         break;
  265.  
  266.      case CMD_XONLINE:
  267.         tok = TOK_XONLINE;
  268.         ++_size;
  269.         break;
  270.  
  271.      case CMD_XDOC:
  272.         tok = TOK_XDOC;
  273.         ++_size;
  274.         break;
  275.  
  276.      case CMD_CENTER:
  277.         tok = TOK_CENTER;
  278.         ++_size;
  279.         break;
  280.  
  281.      case '\n':
  282.         tok = TOK_NL;
  283.         ++_size;
  284.         break;
  285.  
  286.      case CMD_FF:
  287.         tok = TOK_FF;
  288.         ++_size;
  289.         break;
  290.  
  291.      default:   /* it must be a word */
  292.         tok = TOK_WORD;
  293.         while (1)
  294.            {
  295.            if ( _size >= len )
  296.           break;
  297.  
  298.            else if ( *curr == CMD_LITERAL )
  299.           {
  300.           curr += 2;
  301.           _size += 2;
  302.           _width += 1;
  303.           }
  304.  
  305.            else if ( *curr == '\0' )
  306.           {
  307.           assert(0);
  308.           }
  309.  
  310.            else if ((unsigned)*curr <= MAX_CMD || *curr == ' ' ||
  311.             *curr == '\n')
  312.           break;
  313.  
  314.            else if ( *curr == '-' )
  315.           {
  316.           ++curr;
  317.           ++_size;
  318.           ++_width;
  319.           if ( is_hyphen(curr-1) )
  320.              break;
  321.           }
  322.  
  323.            else
  324.           {
  325.           ++curr;
  326.           ++_size;
  327.           ++_width;
  328.           }
  329.            }
  330.         break;
  331.      } /* switch */
  332.       }
  333.  
  334.    if (size  != NULL)    *size  = _size;
  335.    if (width != NULL)    *width = _width;
  336.  
  337.    return (tok);
  338.    }
  339.  
  340.  
  341. int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width)
  342.    {
  343.    int tok;
  344.    int t;
  345.    int _size;
  346.  
  347.    tok = _find_token_length(curr, len, &t, width);
  348.  
  349.    if ( (tok == TOK_XONLINE && mode == ONLINE) ||
  350.     (tok == TOK_XDOC    && mode == DOC)     )
  351.       {
  352.       _size = 0;
  353.  
  354.       while (1)
  355.      {
  356.      curr  += t;
  357.      len   -= t;
  358.      _size += t;
  359.  
  360.      tok = _find_token_length(curr, len, &t, NULL);
  361.  
  362.      if ( (tok == TOK_XONLINE && mode == ONLINE) ||
  363.           (tok == TOK_XDOC      && mode == DOC)    ||
  364.           (tok == TOK_DONE)                )
  365.         break;
  366.      }
  367.  
  368.       _size += t;
  369.       }
  370.    else
  371.       _size = t;
  372.  
  373.    if (size != NULL )
  374.       *size = _size;
  375.  
  376.    return (tok);
  377.    }
  378.  
  379.  
  380. int find_line_width(int mode, char far *curr, unsigned len)
  381.    {
  382.    int size   = 0,
  383.        width  = 0,
  384.        lwidth = 0,
  385.        done   = 0,
  386.        tok;
  387.  
  388.    do
  389.       {
  390.       tok = find_token_length(mode, curr, len, &size, &width);
  391.  
  392.       switch(tok)
  393.      {
  394.      case TOK_DONE:
  395.      case TOK_PARA:
  396.      case TOK_NL:
  397.      case TOK_FF:
  398.         done = 1;
  399.         break;
  400.  
  401.      case TOK_XONLINE:
  402.      case TOK_XDOC:
  403.      case TOK_CENTER:
  404.         curr += size;
  405.         len -= size;
  406.         break;
  407.  
  408.      default:   /* TOK_SPACE, TOK_LINK or TOK_WORD */
  409.         lwidth += width;
  410.         curr += size;
  411.         len -= size;
  412.         break;
  413.      }
  414.       }
  415.    while ( !done );
  416.  
  417.    return (lwidth);
  418.    }
  419.  
  420.  
  421. #define DO_PRINTN(ch,n)  ( pd.s = &(ch), pd.i = (n), output(PD_PRINTN, &pd, info) )
  422. #define DO_PRINT(str,n)  ( pd.s = (str), pd.i = (n), output(PD_PRINT, &pd, info) )
  423.  
  424.  
  425. int process_document(PD_FUNC get_info, PD_FUNC output, VOIDPTR info)
  426.    {
  427.    int         skip_blanks;
  428.    int         tok;
  429.    int         size,
  430.          width;
  431.    int         col;
  432.    char      page_text[10];
  433.    PD_INFO   pd;
  434.    char      nl = '\n',
  435.          sp = ' ';
  436.    int         first_section,
  437.          first_topic;
  438.  
  439.    pd.pnum = 1;
  440.    pd.lnum = 0;
  441.  
  442.    col = 0;
  443.  
  444.    output(PD_HEADING, &pd, info);
  445.  
  446.    first_section = 1;
  447.  
  448.    while ( get_info(PD_GET_CONTENT, &pd, info) )
  449.       {
  450.       if ( !output(PD_START_SECTION, &pd, info) )
  451.      return (0);
  452.  
  453.       if ( pd.new_page && pd.lnum != 0 )
  454.      {
  455.      if ( !output(PD_FOOTING, &pd, info) )
  456.         return (0);
  457.      ++pd.pnum;
  458.      pd.lnum = 0;
  459.      if ( !output(PD_HEADING, &pd, info) )
  460.         return (0);
  461.      }
  462.  
  463.       else
  464.      {
  465.      if ( pd.lnum+2 > PAGE_DEPTH-CONTENT_BREAK )
  466.         {
  467.         if ( !output(PD_FOOTING, &pd, info) )
  468.            return (0);
  469.         ++pd.pnum;
  470.         pd.lnum = 0;
  471.         if ( !output(PD_HEADING, &pd, info) )
  472.            return (0);
  473.         }
  474.      else if (pd.lnum > 0)
  475.         {
  476.         if ( !DO_PRINTN(nl, 2) )
  477.            return (0);
  478.         pd.lnum += 2;
  479.         }
  480.      }
  481.  
  482.       if ( !output(PD_SET_SECTION_PAGE, &pd, info) )
  483.      return (0);
  484.  
  485.       if ( !first_section )
  486.      {
  487.      if ( !output(PD_PRINT_SEC, &pd, info) )
  488.         return (0);
  489.      ++pd.lnum;
  490.      }
  491.  
  492.       col = 0;
  493.  
  494.       first_topic = 1;
  495.  
  496.       while ( get_info(PD_GET_TOPIC, &pd, info) )
  497.      {
  498.      if ( !output(PD_START_TOPIC, &pd, info) )
  499.         return (0);
  500.  
  501.      skip_blanks = 0;
  502.      col = 0;
  503.  
  504.      if ( !first_section )     /* do not skip blanks for DocContents */
  505.         {
  506.         while (pd.len > 0)
  507.            {
  508.            tok = find_token_length(DOC, pd.curr, pd.len, &size, NULL);
  509.            if (tok != TOK_XDOC && tok != TOK_XONLINE &&
  510.            tok != TOK_NL   && tok != TOK_DONE )
  511.           break;
  512.            pd.curr += size;
  513.            pd.len  -= size;
  514.            }
  515.         if ( first_topic && pd.len != 0 )
  516.            {
  517.            if ( !DO_PRINTN(nl, 1) )
  518.           return (0);
  519.            ++pd.lnum;
  520.            }
  521.         }
  522.  
  523.      if ( pd.lnum > PAGE_DEPTH-TOPIC_BREAK )
  524.         {
  525.         if ( !output(PD_FOOTING, &pd, info) )
  526.            return (0);
  527.         ++pd.pnum;
  528.         pd.lnum = 0;
  529.         if ( !output(PD_HEADING, &pd, info) )
  530.            return (0);
  531.         }
  532.      else if ( !first_topic )
  533.         {
  534.         if ( !DO_PRINTN(nl, 1) )
  535.            return (0);
  536.         pd.lnum++;
  537.         }
  538.  
  539.      if ( !output(PD_SET_TOPIC_PAGE, &pd, info) )
  540.         return (0);
  541.  
  542.      do
  543.         {
  544.         if ( !output(PD_PERIODIC, &pd, info) )
  545.            return (0);
  546.  
  547.         tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
  548.  
  549.         switch ( tok )
  550.            {
  551.            case TOK_PARA:
  552.           {
  553.           int        indent,
  554.                 margin;
  555.           unsigned  holdlen = 0;
  556.           char far *holdcurr = 0;
  557.           int        in_link = 0;
  558.  
  559.           ++pd.curr;
  560.  
  561.           indent = *pd.curr++;
  562.           margin = *pd.curr++;
  563.  
  564.           pd.len -= 3;
  565.  
  566.           if ( !DO_PRINTN(sp, indent) )
  567.              return (0);
  568.  
  569.           col = indent;
  570.  
  571.           while (1)
  572.              {
  573.              if ( !output(PD_PERIODIC, &pd, info) )
  574.             return (0);
  575.  
  576.              tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
  577.  
  578.              if ( tok == TOK_NL || tok == TOK_FF )
  579.             break;
  580.  
  581.              if ( tok == TOK_DONE )
  582.             {
  583.             if (in_link == 0)
  584.                {
  585.                col = 0;
  586.                ++pd.lnum;
  587.                if ( !DO_PRINTN(nl, 1) )
  588.                   return (0);
  589.                break;
  590.                }
  591.  
  592.             else if (in_link == 1)
  593.                {
  594.                tok = TOK_SPACE;
  595.                width = 1;
  596.                size = 0;
  597.                ++in_link;
  598.                }
  599.  
  600.             else if (in_link == 2)
  601.                {
  602.                tok = TOK_WORD;
  603.                width = strlen(page_text);
  604.                col += 8 - width;
  605.                size = 0;
  606.                pd.curr = page_text;
  607.                ++in_link;
  608.                }
  609.  
  610.             else if (in_link == 3)
  611.                {
  612.                pd.curr = holdcurr;
  613.                pd.len = holdlen;
  614.                in_link = 0;
  615.                continue;
  616.                }
  617.             }
  618.  
  619.              if ( tok == TOK_PARA )
  620.             {
  621.             col = 0;   /* fake a nl */
  622.             ++pd.lnum;
  623.             if ( !DO_PRINTN(nl, 1) )
  624.                return (0);
  625.             break;
  626.             }
  627.  
  628.              if (tok == TOK_XONLINE || tok == TOK_XDOC )
  629.             {
  630.             pd.curr += size;
  631.             pd.len -= size;
  632.             continue;
  633.             }
  634.  
  635.              if ( tok == TOK_LINK )
  636.             {
  637.             pd.s = pd.curr+1;
  638.             if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
  639.                {
  640.                in_link = 1;
  641.                sprintf(page_text, "(p. %d)", pd.i);
  642.                }
  643.             else
  644.                in_link = 3;
  645.             holdcurr = pd.curr + size;
  646.             holdlen = pd.len - size;
  647.                         pd.len = size - 2 - 3*sizeof(int);
  648.                         pd.curr += 1 + 3*sizeof(int);
  649.             continue;
  650.             }
  651.  
  652.              /* now tok is TOK_SPACE or TOK_WORD */
  653.  
  654.              if (col+width > PAGE_WIDTH)
  655.             {       /* go to next line... */
  656.             if ( !DO_PRINTN(nl, 1) )
  657.                return (0);
  658.             if ( ++pd.lnum >= PAGE_DEPTH )
  659.                {
  660.                if ( !output(PD_FOOTING, &pd, info) )
  661.                   return (0);
  662.                ++pd.pnum;
  663.                pd.lnum = 0;
  664.                if ( !output(PD_HEADING, &pd, info) )
  665.                   return (0);
  666.                }
  667.  
  668.             if ( tok == TOK_SPACE )
  669.                width = 0;    /* skip spaces at start of a line */
  670.  
  671.             if ( !DO_PRINTN(sp, margin) )
  672.                return (0);
  673.             col = margin;
  674.             }
  675.  
  676.              if (width > 0)
  677.             {
  678.             if (tok == TOK_SPACE)
  679.                {
  680.                if ( !DO_PRINTN(sp, width) )
  681.                   return (0);
  682.                }
  683.             else
  684.                {
  685.                if ( !DO_PRINT(pd.curr, (size==0) ? width : size) )
  686.                   return (0);
  687.                }
  688.             }
  689.  
  690.              col += width;
  691.              pd.curr += size;
  692.              pd.len -= size;
  693.              }
  694.  
  695.           skip_blanks = 0;
  696.           width = size = 0;
  697.           break;
  698.           }
  699.  
  700.            case TOK_NL:
  701.           if (skip_blanks && col == 0)
  702.              break;
  703.  
  704.           ++pd.lnum;
  705.  
  706.           if ( pd.lnum >= PAGE_DEPTH || (col == 0 && pd.lnum >= PAGE_DEPTH-BLANK_BREAK) )
  707.              {
  708.              if ( col != 0 )    /* if last wasn't a blank line... */
  709.             {
  710.             if ( !DO_PRINTN(nl, 1) )
  711.                return (0);
  712.             }
  713.              if ( !output(PD_FOOTING, &pd, info) )
  714.             return (0);
  715.              ++pd.pnum;
  716.              pd.lnum = 0;
  717.              skip_blanks = 1;
  718.              if ( !output(PD_HEADING, &pd, info) )
  719.             return (0);
  720.              }
  721.           else
  722.              {
  723.              if ( !DO_PRINTN(nl, 1) )
  724.             return (0);
  725.              }
  726.  
  727.           col = 0;
  728.           break;
  729.  
  730.            case TOK_FF:
  731.           if (skip_blanks)
  732.              break;
  733.           if ( !output(PD_FOOTING, &pd, info) )
  734.              return (0);
  735.           col = 0;
  736.           pd.lnum = 0;
  737.           ++pd.pnum;
  738.           if ( !output(PD_HEADING, &pd, info) )
  739.              return (0);
  740.           break;
  741.  
  742.            case TOK_CENTER:
  743.           width = (PAGE_WIDTH - find_line_width(DOC,pd.curr,pd.len)) / 2;
  744.           if ( !DO_PRINTN(sp, width) )
  745.              return (0);
  746.           break;
  747.  
  748.            case TOK_LINK:
  749.           skip_blanks = 0;
  750.           if ( !DO_PRINT(pd.curr+7, size-8) )
  751.              return (0);
  752.           pd.s = pd.curr+1;
  753.           if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
  754.              {
  755.              width += 9;
  756.              sprintf(page_text, " (p. %d)", pd.i);
  757.              if ( !DO_PRINT(page_text, strlen(page_text)) )
  758.             return (0);
  759.              }
  760.           break;
  761.  
  762.            case TOK_WORD:
  763.           skip_blanks = 0;
  764.           if ( !DO_PRINT(pd.curr, size) )
  765.              return (0);
  766.           break;
  767.  
  768.            case TOK_SPACE:
  769.           skip_blanks = 0;
  770.           if ( !DO_PRINTN(sp, width) )
  771.              return (0);
  772.           break;
  773.  
  774.            case TOK_DONE:
  775.            case TOK_XONLINE:   /* skip */
  776.            case TOK_XDOC:       /* ignore */
  777.           break;
  778.  
  779.            } /* switch */
  780.  
  781.         pd.curr += size;
  782.         pd.len  -= size;
  783.         col     += width;
  784.         }
  785.      while (pd.len > 0);
  786.  
  787.      get_info(PD_RELEASE_TOPIC, &pd, info);
  788.  
  789.      first_topic = 0;
  790.      } /* while */
  791.  
  792.       first_section = 0;
  793.       } /* while */
  794.  
  795.    if ( !output(PD_FOOTING, &pd, info) )
  796.       return (0);
  797.  
  798.    return (1);
  799.    }
  800.  
  801. #undef DO_PRINT
  802. #undef DO_PRINTN
  803.  
  804.  
  805. #endif     /* #ifdef INCLUDE_COMMON */
  806.