home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / cawf407.zip / src / pass3.c < prev    next >
C/C++ Source or Header  |  1993-12-28  |  14KB  |  657 lines

  1. /*
  2.  *    pass3.c - cawf(1) pass 3 function
  3.  */
  4.  
  5. /*
  6.  *    Copyright (c) 1991 Purdue University Research Foundation,
  7.  *    West Lafayette, Indiana 47907.  All rights reserved.
  8.  *
  9.  *    Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
  10.  *    University Computing Center.  Not derived from licensed software;
  11.  *    derived from awf(1) by Henry Spencer of the University of Toronto.
  12.  *
  13.  *    Permission is granted to anyone to use this software for any
  14.  *    purpose on any computer system, and to alter it and redistribute
  15.  *    it freely, subject to the following restrictions:
  16.  *
  17.  *    1. The author is not responsible for any consequences of use of
  18.  *       this software, even if they arise from flaws in it.
  19.  *
  20.  *    2. The origin of this software must not be misrepresented, either
  21.  *       by explicit claim or by omission.  Credits must appear in the
  22.  *       documentation.
  23.  *
  24.  *    3. Altered versions must be plainly marked as such, and must not
  25.  *       be misrepresented as being the original software.  Credits must
  26.  *       appear in the documentation.
  27.  *
  28.  *    4. This notice may not be removed or altered.
  29.  */
  30.  
  31. #include "cawf.h"
  32.  
  33. void
  34. Pass3(len, word, wl, sarg, narg)
  35.     int len;            /* output length -- negative is
  36.                      * special */
  37.     unsigned char *word;        /* word */
  38.     int wl;                /* real word length */
  39.     unsigned char *sarg;        /* string argument */
  40.     int narg;            /* numeric argument */
  41. {
  42.     int addto;            /* spaces to add to all words */
  43.     static int fp = 1;        /* first page print status */
  44.     int i, j, k;            /* temporary index */
  45.     int n;                /* temporary number */
  46.     int sp = 0;            /* no-break spacing switch */
  47.     int sp_Outll;            /* sp-saved Outll */
  48.     char sp_Outln;            /* sp-saved Outln[0] */
  49.     int sp_Outlx;            /* sp-saved Outlx */
  50.     int sp_Padx;            /* sp-saved Padx */
  51.     int sp_Tind;            /* sp-saved Tind */
  52.     int xsp;            /* extra spaces to add */
  53.     int vsp;            /* vertical spacing status */
  54.  
  55.     vsp = 0;
  56.     /*
  57.      * If not a special command, process a word.
  58.      */
  59.     if (len >= 0 && Outll < 0) {
  60.     /*
  61.      * Enter first word.
  62.      */
  63.         (void) memcpy((void *)Outln, (void *)word, (size_t)wl);
  64.         Outlx = wl;
  65.         Outll = len;
  66.         Padx = 0;
  67.     } else if (len >= 0
  68.            && (Outll+Contlen+len+narg) <= (LL-Pgoff-Ind-Tind)) {
  69.     /*
  70.      * The word fits, so enter it.
  71.      */
  72.         if ((Contlen + len) > 0) {
  73. line_too_big:
  74.             if ((Outlx + Contlen + wl) >= MAXOLL) {
  75.                 Error3(len, (char *)word, (char *)sarg, narg,
  76.                     "output line too big");
  77.                 return;
  78.             } else {
  79.                 if (Contlen > 0 && Cont != NULL) {
  80.                     if (Contlen == 1 && *Cont == ' ') {
  81.                         Padchar[Padx++] = Outlx;
  82.                         Outln[Outlx++] = ' ';
  83.                     } else {
  84.                         (void) strcpy((char *)&Outln[Outlx],
  85.                         (char *)Cont);
  86.                         Outlx += Contlen;
  87.                     }
  88.                 }
  89.                 if (len > 0) {
  90.                     (void) memcpy((void *)&Outln[Outlx],
  91.                     (void *)word, (size_t)wl);
  92.                     Outlx += wl;
  93.                 }
  94.             }
  95.         }
  96.         Outll += Contlen + len;
  97.     } else if (len == NOBREAK || len == MESSAGE) {
  98.         /*
  99.          * Do nothing (equivalent to break)
  100.          */
  101.     } else if (len == DOBREAK && strcmp((char *)word, "need") == 0
  102.            &&  (Nxtln + narg) < (Pglen + 1 - Botmarg)) {
  103.         /*
  104.          * Do nothing, because there is room on the page.
  105.          */
  106.     } else if (len == DOBREAK && strcmp((char *)word, "toindent") == 0
  107.            &&  (Ind + Tind + Outll) < Ind) {
  108.     /*
  109.      * Move to indent position with line - there is room.
  110.      */
  111.         n = Ind - (Ind + Tind + Outll);
  112.         Outll += n;
  113.         if ((Outlx + n) >= MAXOLL)
  114.             goto line_too_big;
  115.         for (i = n; i; i--)
  116.             Outln[Outlx++] = ' ';
  117.         Padx = 0;
  118.         Free(&Cont);
  119.         Contlen = 0;
  120.     } else if (Outll >= 0
  121.            || (len == DOBREAK && strcmp((char *)word, "need") == 0)
  122.            || (len == RAWLINE)) {
  123.     /*
  124.      * A non-empty line or a "need" or a RAWLINE forces output.
  125.      */
  126.         vsp = 0;
  127.  
  128. print_line:
  129.         if (Nxtln == 1) {
  130.         /*
  131.          * We're at the top of the page.
  132.          *
  133.          * Determine if the page is in the printing range.
  134.          *
  135.          * Issue the header.
  136.          */
  137.             j = fp;
  138.             if ((Pageprt = PageInRange(Thispg)) == 1) {
  139.                 if (!fp)
  140.                     Charput("\f");
  141.                 fp = 0;
  142.             }
  143.             for (i = (Topmarg - 1)/2; i > 0; i--) {
  144.                 Charput("\n");
  145.                 Nxtln++;
  146.             }
  147.             /*
  148.              * Print the page header, as required.
  149.              */
  150.             if (Fph || !j) {
  151.                 i = LenprtHF(Hdc, Thispg, 0, NULL, 0)
  152.                   + LenprtHF(Hdl, Thispg, 0, NULL, 0)
  153.                   + LenprtHF(Hdr, Thispg, 0, NULL, 0) + 2;
  154.                 j = (LL - i - Pgoff) / 2 + 1;
  155.                 n = LL - Pgoff - i - j + 2;
  156.                 for (k = 0; k < Pgoff; k++)
  157.                     Charput(" ");
  158.                 if (Hdl)
  159.                     (void) LenprtHF(Hdl, Thispg, 1, NULL, 0);
  160.                 while (j--)
  161.                     Charput(" ");
  162.                 if (Hdc)
  163.                     (void) LenprtHF(Hdc, Thispg, 1, NULL, 0);
  164.                 while (n--)
  165.                     Charput(" ");
  166.                 if (Hdr)
  167.                     (void) LenprtHF(Hdr, Thispg, 1, NULL, 0);
  168.                 Charput("\n");
  169.             } else
  170.                 Charput("\n");
  171.             Nxtln++;
  172.             while(Nxtln <= Topmarg) {
  173.                 Charput("\n");
  174.                 Nxtln++;
  175.             }
  176.         }
  177.         /*
  178.          * If this is a raw line, simply output the string argument.
  179.          */
  180.         if (len == RAWLINE) {
  181.             Stringput(sarg, strlen((char *)sarg));
  182.             Charput("\n");
  183.             Nxtln++;
  184.         } else {
  185.  
  186.         /*
  187.          * Print a normal output line.
  188.          */
  189.         /*
  190.          *  Add a trailing hyphen, if mecessary.
  191.          */
  192.             if (vsp == 0 && Eollen > 0 && Eol != NULL) {
  193.             i = strlen((char *)Eol);
  194.             if ((Outlx + i) >= MAXOLL)
  195.                 goto line_too_big;
  196.             (void) memcpy((void *)&Outln[Outlx], (void *)Eol, i);
  197.             Outlx += i;
  198.             Outll += Eollen;
  199.             }
  200.         /*
  201.          * Trim trailing spaces from the output line.
  202.          */
  203.                  while (Outlx > 0) {
  204.             if (Outln[Outlx - 1] != ' ')
  205.                 break;
  206.             if (Padx > 0 && (Outlx - 1) == Padchar[Padx - 1])
  207.                 Padx--;
  208.             Outlx--;
  209.             Outll--;
  210.             }
  211.             if (Outlx == 0) {
  212.             Charput("\n");
  213.             } else if (len == DOBREAK
  214.              && strcmp((char *)word, "center") == 0) {
  215.             /*
  216.              * Center the output line.
  217.              */
  218.             i = (LL - Pgoff - Outll) / 2;
  219.             if (i < 0)
  220.                 i = 0;
  221.             for (j = (Pgoff + Ind + Tind + i); j; j--)
  222.                 Charput(" ");
  223.             Stringput(Outln, Outlx);
  224.             Charput("\n");
  225.             } else if (Adj == LEFTADJ
  226.                    || (Adj == BOTHADJ && (len < 0 || Padx == 0))) {
  227.             /*
  228.              * No right margin adjustment - disabled, inappropriate
  229.              * (line ended by break) or impossible.
  230.              */
  231.             for (i = 0; i < (Pgoff + Ind + Tind); i++)
  232.                 Charput(" ");
  233.             Stringput(Outln, Outlx);
  234.             Charput("\n");
  235.             } else if (Adj == BOTHADJ) {
  236.             /*
  237.              * Adjust right margin.
  238.              */
  239.             for (i = 0; i < (Pgoff + Ind + Tind); i++)
  240.                 Charput(" ");
  241.             i = LL - (Pgoff + Ind + Tind);
  242.             j = i - Outll;
  243.             addto = Padx ? (j / Padx) : 0;
  244.             xsp = j - (Padx * addto);
  245.             for (i = k = 0; i < Padx; i++) {
  246.                 while (k < Outlx && k <= Padchar[i]) {
  247.                 Charput(&Outln[k]);
  248.                 k++;
  249.                 }
  250.                 if (k >= Outlx)
  251.                 break;
  252.                 j = addto;
  253.                 if (Padfrom == PADLEFT) {
  254.                 if (i < xsp)
  255.                     j++;
  256.                 } else if (i >= (Padx - xsp))
  257.                 j++;
  258.                 while (j--)
  259.                 Charput(" ");
  260.             }
  261.             if ((Outlx - k) > 0)
  262.                 Stringput(&Outln[k], Outlx - k);
  263.             Charput("\n");
  264.             Padfrom = (Padfrom == PADLEFT) ? PADRIGHT : PADLEFT;
  265.             }
  266.         /*
  267.          * End of line housekeeping
  268.          */
  269.             Nxtln++;
  270.             Outll = -1;
  271.             Outlx = 0;
  272.             Padx = 0;
  273.             Tind = 0;
  274.             Nospmode = 0;
  275.             if (vsp == 0 && len == DOBREAK
  276.             &&  strcmp((char *)word, "need") == 0) {
  277.             /*
  278.              * Break caused by "need" - satisfy it.
  279.              */
  280.             while (Nxtln < (Pglen + 1 - Botmarg)) {
  281.                 Charput("\n");
  282.                 Nxtln++;
  283.             }
  284.             }
  285.         }
  286.         if (Nxtln >= (Pglen + 1 - Botmarg)) {
  287.         /*
  288.          * Footer required
  289.          */
  290.             for (i = (Botmarg - 1)/2; i > 0; i--) {
  291.                 Charput("\n");
  292.                 Nxtln++;
  293.             }
  294.             i = LenprtHF(Ftl, Thispg, 0, NULL, 0)
  295.               + LenprtHF(Ftc, Thispg, 0, NULL, 0)
  296.               + LenprtHF(Ftr, Thispg, 0, NULL, 0) + 2;
  297.             j = (LL - i - Pgoff) / 2 + 1;
  298.             n = LL - Pgoff - i - j + 2;
  299.             for (k = 0; k < Pgoff; k++)
  300.                 Charput(" ");
  301.             if (Ftl)
  302.                 (void) LenprtHF(Ftl, Thispg, 1, NULL, 0);
  303.             while (j--)
  304.                 Charput(" ");
  305.             if (Ftc)
  306.                 (void) LenprtHF(Ftc, Thispg, 1, NULL, 0);
  307.             while (n--)
  308.                 Charput(" ");
  309.             if (Ftr)
  310.                 (void) LenprtHF(Ftr, Thispg, 1, NULL, 0);
  311.             Charput("\n");
  312.             Nxtln++;
  313.         /*
  314.          * The last blank line on the page is suppressed to assist
  315.          * printers that can't look ahead to the following FF.
  316.          */
  317.             while (Nxtln < Pglen) {
  318.                 Charput("\n");
  319.                 Nxtln++;
  320.             }
  321.             Nxtln = 1;
  322.             Thispg++;
  323.             Nospmode = 1;
  324.             Padfrom = PADRIGHT;
  325.         }
  326.         /*
  327.          * Initiate any extra vertical spacing.
  328.          */
  329.         if (++vsp < Vspace)
  330.             goto print_line;
  331.         /*
  332.          * Save any input word that might have forced output.
  333.          */
  334.         if (len >= 0) {
  335.             (void) memcpy((void *)Outln, (void *)word, (size_t)wl);
  336.             Outlx = wl;
  337.             Outll = len;
  338.             Padx = 0;
  339.         } else if (len == RAWLINE)
  340.             return;
  341.     }
  342.     /*
  343.      * A break causes padding reversal.
  344.      */
  345.     if (len == DOBREAK)
  346.         Padfrom = PADRIGHT;
  347.     if (len >= 0 || strcmp((char *)word, "nohyphen") == 0) {
  348.     /*
  349.      * Reset continuation and hyphenation.
  350.      */
  351.         if (Contlen != 1 || Cont[0] != ' ') {
  352.             Free(&Cont);
  353.             Cont = Newstr((unsigned char *)" ");
  354.             Contlen = 1;
  355.         }
  356.         if (Eollen > 0) {
  357.             Free(&Eol);
  358.             Eollen = 0;
  359.         }
  360.         return;
  361.     }
  362.     /*
  363.      * Now post-process any special commands.
  364.      */
  365.     if (len == MESSAGE) {
  366.         Error3(len, (char *)word, (char *)sarg, narg, NULL);
  367.         return;
  368.     }
  369.  
  370.     switch (*word) {
  371.  
  372.     case 'b':                /* both */
  373.         /*
  374.          * Adjust on both margins.
  375.          */
  376.         Adj = BOTHADJ;
  377.         return;
  378.  
  379.     case 'c':                /* center */
  380.         return;
  381.  
  382.     case 'e':                /* errsto */
  383.         /*
  384.          * "errsto" comes from awf.
  385.          */
  386.         return;
  387.  
  388.     case 'f':                /* flush and fph */
  389.         if (word[1] == 'l')
  390.             return;
  391.         else if (word[1] == 'p') {
  392.         /*
  393.          * First page header status
  394.          */
  395.             Fph = narg;
  396.             return;
  397.         }
  398.         break;
  399.  
  400.     case 'g':                /* gap */
  401.         /*
  402.          * Increase word gap.  (Space is not paddable.)
  403.          */
  404.         if (Outll >= 0) {
  405.             if ((Outlx + narg - 1) >= MAXOLL)
  406.                 goto line_too_big;
  407.             for (i = 0; i < (narg - 1); i++) {
  408.                 Outln[Outlx++] = ' ';
  409.                 Outll++;
  410.             }
  411.         }
  412.         return;
  413.  
  414.     case 'h':                /* hyphen */
  415.         /*
  416.          * Set discretionary hyphen.
  417.          */
  418.         Free(&Cont);
  419.         Contlen = 0;
  420.         Free(&Eol);
  421.         Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
  422.         Eollen = narg;
  423.         return;
  424.  
  425.     case 'i':                /* indent */
  426.         /*
  427.          * Set indentation.
  428.          */
  429.         Ind = narg;
  430.         return;
  431.  
  432.     case 'l':                /* left or linelen */
  433.         if (word[1] == 'e') {
  434.         /*
  435.          * Adjust on left margin.
  436.          */
  437.             Adj = LEFTADJ;
  438.             return;
  439.         } else if (word[1] == 'i') {
  440.         /*
  441.          * Set line length.
  442.          */
  443.             LL = narg;
  444.             return;
  445.         }
  446.         break;
  447.  
  448.     case 'n':                /* need or nospace */
  449.         if (word[1] == 'e')
  450.             return;            /* need */
  451.         else if (word[1] == 'o') {
  452.         /*
  453.          * Set no space mode.
  454.          */
  455.             Nospmode = 1;
  456.             return;
  457.         }
  458.         break;
  459.  
  460.     case 'p':                /* pagelen or pageoffset */
  461.         if (strncmp((char *)&word[1], "age", 3) != 0)
  462.             break;
  463.         if (word[4] == 'l') {
  464.         /*
  465.          * Set page length.
  466.          */
  467.             Pglen = narg;
  468.             return;
  469.         } else if (word[4] == 'o') {
  470.         /*
  471.          * Set page offset.
  472.          */
  473.             Pgoff = narg;
  474.             return;
  475.         }
  476.         break;
  477.  
  478.     case 's':                /* space */
  479.         if (sp) {
  480.  
  481.         /*
  482.          * Restore values after NOBREAK spacing ("^'sp").
  483.          */
  484.  
  485. #ifdef    _BCC
  486. #pragma warn -def
  487. #endif
  488.             Outlx = sp_Outlx;
  489.             Outln[0] = sp_Outln;
  490.             Padx = sp_Padx;
  491.             Outll = sp_Outll;
  492.             Tind = sp_Tind;
  493.  
  494. #ifdef    _BCC
  495. #pragma warn +def
  496. #endif
  497.  
  498.             return;
  499.         }
  500.         if (Nospmode == 0) {
  501.             if (len == NOBREAK) {
  502.         
  503.             /*
  504.              * Set up for NOBREAK spacing.
  505.              */
  506.                 sp_Outlx = Outlx;
  507.                 sp_Outln = Outln[0];
  508.                 sp_Padx = Padx;
  509.                 sp_Outll = Outll;
  510.                 sp_Tind = Tind;
  511.                 vsp = Vspace + 1;
  512.                 sp = 1;
  513.             }
  514.         /*
  515.          * Generate a blank line.
  516.          */
  517.             Outlx = 0;
  518.             Padx = 0;
  519.             Outll = LL - 1;
  520.             if (sp)
  521.                 goto print_line;
  522.         }
  523.         return;
  524.  
  525.     case 't':                /* tabto, tempindent, toindent,
  526.                          * or ttllen */
  527.         if (word[1] == 'a') {
  528.         /*
  529.          * Move to TAB stop.
  530.          */
  531.             if (Outll < 0)
  532.                 Outll = 0;
  533.             for (i = 0; i < Ntabs; i++) {
  534.                 if ((n = Tabs[i] - Outll) > 0) {
  535.                     if ((Outlx + n) >= MAXOLL)
  536.                         goto line_too_big;
  537.                     Outll += n;
  538.                     for (i = n; i > 0; i--)
  539.                         Outln[Outlx++] = ' ';
  540.                     Free(&Cont);
  541.                     Contlen = 0;
  542.                     Padx = 0;
  543.                     break;
  544.                 }
  545.             }
  546.             return;
  547.         } else if (word[1] == 'e') {
  548.         /*
  549.          * Set temporary indentation.
  550.          */
  551.             if (*sarg == '\0' && narg >= 0)
  552.                 Tind = narg - Ind;
  553.             else
  554.                 Tind = ((Ind + narg) >= 0) ? narg : -Ind;
  555.             return;
  556.         } else if (word[1] == 'o') {
  557.             return;                /* toindent */
  558.  
  559.         /*
  560.          * Set 3-part title line length.
  561.          */
  562.         } else if (word[1] == 't') {
  563.             LT = narg;
  564.             return;
  565.         }
  566.         break;
  567.  
  568.     case 'u':                    /* userhyphen */
  569.         /*
  570.          * Set continuation and end-of-line values for hyphenation.
  571.          */
  572.         Free(&Cont);
  573.         Free(&Eol);
  574.         Contlen = Eollen = narg;
  575.         Cont = (sarg == NULL) ? NULL : Newstr(sarg);
  576.         Eol = (sarg == NULL) ? NULL : Newstr(sarg);
  577.         return;
  578.  
  579.     case 'v':                    /* vspace */
  580.         /*
  581.          * Set vertical spacing.
  582.          */
  583.         Vspace = (narg == 0) ? 1 : narg;
  584.         return;
  585.  
  586.     case 'y':                    /* yesspace */
  587.         /*
  588.          * Set space mode.
  589.          */
  590.         Nospmode = 0;
  591.         return;
  592.     }                /* end of switch(*word) */
  593.     /*
  594.      * Locate header and footer defintions.
  595.      */
  596.     if (regexec(Pat[14].pat, word)) {
  597.         if (strcmp((char *)word, "LH") == 0) {
  598.             /*
  599.              * Left header
  600.              */
  601.             Free(&Hdl);
  602.             if (sarg != NULL)
  603.                 Hdl = Newstr(sarg);
  604.             return;
  605.         }
  606.         if (strcmp((char *)word, "CH") == 0) {
  607.             /*
  608.              * Center header
  609.              */
  610.             Free(&Hdc);
  611.             if (sarg != NULL)
  612.                 Hdc = Newstr(sarg);
  613.             return;
  614.         }
  615.         if (strcmp((char *)word, "RH") == 0) {
  616.             /*
  617.              * Right header
  618.              */
  619.             Free(&Hdr);
  620.             if (sarg != NULL)
  621.                 Hdr = Newstr(sarg);
  622.             return;
  623.         }
  624.         if (strcmp((char *)word, "LF") == 0) {
  625.             /*
  626.              * Left footer
  627.              */
  628.             Free(&Ftl);
  629.             if (sarg != NULL)
  630.                 Ftl = Newstr(sarg);
  631.             return;
  632.         }
  633.         if (strcmp((char *)word, "CF") == 0) {
  634.             /*
  635.              * Center footer
  636.              */
  637.             Free(&Ftc);
  638.             if (sarg != NULL)
  639.                 Ftc = Newstr(sarg);
  640.             return;
  641.         }
  642.         if (strcmp((char *)word, "RF") == 0) {
  643.             /*
  644.              * Right footer
  645.              */
  646.             Free(&Ftr);
  647.             if (sarg != NULL)
  648.                 Ftr = Newstr(sarg);
  649.             return;
  650.         }
  651.     }
  652.     /*
  653.      * Error on unknown arguments
  654.      */
  655.     Error3(len, (char *)word, (char *)sarg, narg, "unknown request");
  656. }
  657.