home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / fileutil / cawf / pass3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-21  |  12.2 KB  |  572 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, sarg, narg)
  35.     int len;            /* length (negative is special) */
  36.     char *word;            /* word */
  37.     char *sarg;            /* string argument */
  38.     int narg;            /* numeric argument */
  39. {
  40.     int addto;            /* spaces to add to all words */
  41.     int i, j, k;            /* temporary index */
  42.     char msg[MAXLINE];        /* message buffer */
  43.     int n;                /* temporary number */
  44.     char *s1;            /* temporary string pointer */
  45.     int wl;                /* real word length */
  46.     int xsp;            /* extra spaces to add */
  47.     int vsp;            /* vertical spacing status */
  48.  
  49.     vsp = 0;
  50.     if (word != NULL)
  51.         wl = strlen(word);
  52.     /*
  53.      * If not a special command, process a word.
  54.      */
  55.     if (len >= 0 && Outll < 0) {
  56.     /*
  57.      * Enter first word.
  58.      */
  59.         (void) strcpy(Outln, word);
  60.         Outll = len;
  61.         Outlx = wl;
  62.         Padx = 0;
  63.     } else if (len >= 0
  64.            && (Outll+Contlen+len+narg) <= (LL-Pgoff-Ind-Tind)) {
  65.     /*
  66.      * The word fits, so enter it.
  67.      */
  68.         if ((Contlen + len) > 0) {
  69. line_too_big:
  70.             if ((Outlx + Contlen + wl) >= MAXOLL) {
  71.                 Error3(len, word, sarg, narg,
  72.                     "output line too big");
  73.                 return;
  74.             } else {
  75.                 if (Contlen > 0 && Cont != NULL) {
  76.                     if (Contlen == 1 && *Cont == ' ') {
  77.                         Padchar[Padx++] = Outlx;
  78.                         Outln[Outlx++] = ' ';
  79.                     } else {
  80.                         (void) strcpy(&Outln[Outlx],
  81.                             Cont);
  82.                         Outlx += Contlen;
  83.                     }
  84.                 }
  85.                 if (len > 0) {
  86.                     (void) strcpy(&Outln[Outlx], word);
  87.                     Outlx += wl;
  88.                 }
  89.             }
  90.         }
  91.         Outll += Contlen + len;
  92.     } else if (len == NOBREAK || len == MESSAGE) {
  93.         /*
  94.          * Do nothing (equivalent to break)
  95.          */
  96.     } else if (len == DOBREAK && strcmp(word, "need") == 0
  97.            &&  (Nxtln + narg) < (Pglen + 1 - Botmarg)) {
  98.         /*
  99.          * Do nothing, because there is room on the page.
  100.          */
  101.     } else if (len == DOBREAK && strcmp(word, "toindent") == 0
  102.            &&  (Ind + Tind + Outll) < Ind) {
  103.     /*
  104.      * Move to indent position with line - there is room.
  105.      */
  106.         n = Ind - (Ind + Tind +Outll);
  107.         Outll += n;
  108.         if ((Outlx + n) >= MAXOLL)
  109.             goto line_too_big;
  110.         for (i = n; i; i--)
  111.             Outln[Outlx++] = ' ';
  112.         Padx = 0;
  113.         Free(&Cont);
  114.         Contlen = 0;
  115.     } else if (Outll >= 0
  116.            || (len == DOBREAK && strcmp(word, "need") == 0)) {
  117.     /*
  118.      * A non-empty line or a "need" forces output.
  119.      */
  120.         vsp = 0;
  121.  
  122. print_line:
  123.         if (Nxtln == 1) {
  124.         /*
  125.          * We're at the top of the page, so issue the header.
  126.          */
  127.             if (Thispg > 1)
  128.                 putchar('\f');
  129.             for (i = (Topmarg - 1)/2; i > 0; i--) {
  130.                 putchar('\n');
  131.                 Nxtln++;
  132.             }
  133.             /*
  134.              * Print the page header, as required.
  135.              */
  136.             if (Fph || Thispg > 1) {
  137.                 i = LenprtHF(Hdc, Thispg, 0)
  138.                   + LenprtHF(Hdl, Thispg, 0)
  139.                   + LenprtHF(Hdr, Thispg, 0) + 2;
  140.                 j = (LL - i - Pgoff) / 2 + 1;
  141.                 n = LL - Pgoff - i - j + 2;
  142.                 for (k = 0; k < Pgoff; k++)
  143.                     putchar(' ');
  144.                 if (Hdl)
  145.                     LenprtHF(Hdl, Thispg, 1);
  146.                 while (j--)
  147.                     putchar(' ');
  148.                 if (Hdc)
  149.                     LenprtHF(Hdc, Thispg, 1);
  150.                 while (n--)
  151.                     putchar(' ');
  152.                 if (Hdr)
  153.                     LenprtHF(Hdr, Thispg, 1);
  154.                 putchar('\n');
  155.             } else
  156.                 putchar('\n');
  157.             Nxtln++;
  158.             while(Nxtln <= Topmarg) {
  159.                 putchar('\n');
  160.                 Nxtln++;
  161.             }
  162.         }
  163.         /*
  164.          *  Add a trailing hyphen, if mecessary.
  165.          */
  166.              if (vsp == 0 && Eollen > 0 && Eol != NULL) {
  167.             i = strlen(Eol);
  168.             if ((Outlx + i) >= MAXOLL)
  169.                 goto line_too_big;
  170.             (void) strcpy(&Outln[Outlx], Eol);
  171.             Outlx += i;
  172.             Outll += Eollen;
  173.         }
  174.         /*
  175.          * Trim trailing spaces from the output line.
  176.          */
  177.              while (Outlx > 0) {
  178.             if (Outln[Outlx - 1] != ' ')
  179.                 break;
  180.             if (Padx > 0 && (Outlx - 1) == Padchar[Padx - 1])
  181.                 Padx--;
  182.             Outlx--;
  183.             Outln[Outlx] = '\0';
  184.             Outll--;
  185.         }
  186.         if (Outlx == 0)
  187.             putchar('\n');
  188.         else if (len == DOBREAK && strcmp(word, "center") == 0) {
  189.             /*
  190.              * Center the output line.
  191.              */
  192.             i = (LL - Pgoff - Outll) / 2;
  193.             if (i < 0)
  194.                 i = 0;
  195.             for (j = (Pgoff + Ind + Tind + i); j; j--)
  196.                 putchar(' ');
  197.             fputs(Outln, stdout);
  198.             putchar('\n');
  199.         } else if (Adj == LEFTADJ || Adj == BOTHADJ
  200.              &&  (len < 0 || Padx == 0)) {
  201.             /*
  202.              * No right margin adjustment - disabled, inappropriate
  203.              * (line ended by break) or impossible.
  204.              */
  205.             for (i = 0; i < (Pgoff + Ind + Tind); i++)
  206.                 putchar(' ');
  207.             fputs(Outln, stdout);
  208.             putchar('\n');
  209.         } else if (Adj == BOTHADJ) {
  210.             /*
  211.              * Adjust right margin.
  212.              */
  213.             for (i = 0; i < (Pgoff + Ind + Tind); i++)
  214.                 putchar(' ');
  215.             i = LL - (Pgoff + Ind + Tind);
  216.             j = i - Outll;
  217.             addto = Padx ? (j / Padx) : 0;
  218.             xsp = j - (Padx * addto);
  219.             for (i = 0, s1 = Outln; i < Padx; i++) {
  220.                 while (*s1 && (s1 - Outln) <= Padchar[i])
  221.                     putchar(*s1++);
  222.                 if (*s1 == '\0')
  223.                     break;
  224.                 j = addto;
  225.                 if (Padfrom == PADLEFT) {
  226.                     if (i < xsp)
  227.                         j++;
  228.                 } else if (i >= (Padx - xsp))
  229.                     j++;
  230.                 while (j--)
  231.                     putchar(' ');
  232.             }
  233.             while (*s1)
  234.                 putchar(*s1++);
  235.             putchar('\n');
  236.             Padfrom = (Padfrom == PADLEFT) ? PADRIGHT : PADLEFT;
  237.         }
  238.         /*
  239.          * End of line housekeeping
  240.          */
  241.         Nxtln++;
  242.         Outll = -1;
  243.         Outlx = 0;
  244.         Padx = 0;
  245.         Tind = 0;
  246.         Nospmode = 0;
  247.         if (vsp == 0 && len == DOBREAK && strcmp(word, "need") == 0) {
  248.         /*
  249.          * Break caused by "need" - satisfy it.
  250.          */
  251.             while (Nxtln < (Pglen + 1 - Botmarg)) {
  252.                 putchar('\n');
  253.                 Nxtln++;
  254.             }
  255.         }
  256.         if (Nxtln >= (Pglen + 1 - Botmarg)) {
  257.         /*
  258.          * Footer required
  259.          */
  260.             for (i = (Botmarg - 1)/2; i > 0; i--) {
  261.                 putchar('\n');
  262.                 Nxtln++;
  263.             }
  264.             i = LenprtHF(Ftl, Thispg, 0) + LenprtHF(Ftc, Thispg, 0)
  265.               + LenprtHF(Ftr, Thispg, 0) + 2;
  266.             j = (LL - i - Pgoff) / 2 + 1;
  267.             n = LL - Pgoff - i - j + 2;
  268.             for (k = 0; k < Pgoff; k++)
  269.                 putchar(' ');
  270.             if (Ftl)
  271.                 LenprtHF(Ftl, Thispg, 1);
  272.             while (j--)
  273.                 putchar(' ');
  274.             if (Ftc)
  275.                 LenprtHF(Ftc, Thispg, 1);
  276.             while (n--)
  277.                 putchar(' ');
  278.             if (Ftr)
  279.                 LenprtHF(Ftr, Thispg, 1);
  280.             putchar('\n');
  281.             Nxtln++;
  282.             while (Nxtln <= Pglen) {
  283.                 putchar('\n');
  284.                 Nxtln++;
  285.             }
  286.             Nxtln = 1;
  287.             Thispg++;
  288.             Nospmode = 1;
  289.             Padfrom = PADRIGHT;
  290.         }
  291.         /*
  292.          * Initiate any extra vertical spacing.
  293.          */
  294.         if (++vsp < Vspace)
  295.             goto print_line;
  296.         /*
  297.          * Save any input word that might have forced output.
  298.          */
  299.         if (len >= 0) {
  300.             (void) strcpy(Outln, word);
  301.             Outll = len;
  302.             Outlx = wl;
  303.             Padx = 0;
  304.         }
  305.     }
  306.     /*
  307.      * A break causes padding reversal.
  308.      */
  309.     if (len == DOBREAK)
  310.         Padfrom = PADRIGHT;
  311.     if (len >= 0 || strcmp(word, "nohyphen") == 0) {
  312.     /*
  313.      * Reset continuation and hyphenation.
  314.      */
  315.         if (Contlen != 1 || Cont[0] != ' ') {
  316.             Free(&Cont);
  317.             Cont = Newstr(" ");
  318.             Contlen = 1;
  319.         }
  320.         if (Eollen > 0) {
  321.             Free(&Eol);
  322.             Eollen = 0;
  323.         }
  324.         return;
  325.     }
  326.     /*
  327.      * Now post-process any special commands.
  328.      */
  329.     if (len == MESSAGE) {
  330.         Error3(len, word, sarg, narg, NULL);
  331.         return;
  332.     }
  333.  
  334.     switch (*word) {
  335.  
  336.     case 'b':                /* both */
  337.         /*
  338.          * Adjust on both margins.
  339.          */
  340.         Adj = BOTHADJ;
  341.         return;
  342.  
  343.     case 'c':                /* center */
  344.         return;
  345.  
  346.     case 'e':                /* errsto */
  347.         /*
  348.          * "errsto" comes from awf.
  349.          */
  350.         return;
  351.  
  352.     case 'f':                /* flush and fph */
  353.         if (word[1] == 'l')
  354.             return;
  355.         else if (word[1] == 'p') {
  356.         /*
  357.          * First page header status
  358.          */
  359.             Fph = narg;
  360.             return;
  361.         }
  362.         break;
  363.  
  364.     case 'g':                /* gap */
  365.         /*
  366.          * Increase word gap.  (Space is not paddable.)
  367.          */
  368.         if (Outll >= 0) {
  369.             if ((Outlx + narg - 1) >= MAXOLL)
  370.                 goto line_too_big;
  371.             for (i = 0; i < (narg - 1); i++) {
  372.                 Outln[Outlx++] = ' ';
  373.                 Outll++;
  374.             }
  375.         }
  376.         return;
  377.  
  378.     case 'h':                /* hyphen */
  379.         /*
  380.          * Set discretionary hyphen.
  381.          */
  382.         Free(&Cont);
  383.         Contlen = 0;
  384.         Free(&Eol);
  385.         Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
  386.         Eollen = narg;
  387.         return;
  388.  
  389.     case 'i':                /* indent */
  390.         /*
  391.          * Set indentation.
  392.          */
  393.         Ind = narg;
  394.         return;
  395.  
  396.     case 'l':                /* left or linelen */
  397.         if (word[1] == 'e') {
  398.         /*
  399.          * Adjust on left margin.
  400.          */
  401.             Adj = LEFTADJ;
  402.             return;
  403.         } else if (word[1] == 'i') {
  404.         /*
  405.          * Set line length.
  406.          */
  407.             LL = narg;
  408.             return;
  409.         }
  410.         break;
  411.  
  412.     case 'n':                /* need or nospace */
  413.         if (word[1] == 'e')
  414.             return;            /* need */
  415.         else if (word[1] == 'o') {
  416.         /*
  417.          * Set no space mode.
  418.          */
  419.             Nospmode = 1;
  420.             return;
  421.         }
  422.         break;
  423.  
  424.     case 'p':                /* pagelen or pageoffset */
  425.         if (strncmp(&word[1], "age", 3) != 0)
  426.             break;
  427.         if (word[4] == 'l') {
  428.         /*
  429.          * Set page length.
  430.          */
  431.             Pglen = narg;
  432.             return;
  433.         } else if (word[4] == 'o') {
  434.         /*
  435.          * Set page offset.
  436.          */
  437.             Pgoff = narg;
  438.             return;
  439.         }
  440.         break;
  441.  
  442.     case 's':                /* space */
  443.         /*
  444.          * Generate an empty line.
  445.          */
  446.         if (Nospmode == 0) {
  447.             Outlx = 0;
  448.             Outln[0] = '\0';
  449.             Padx = 0;
  450.             Outll = LL - 1;
  451.         }
  452.         return;
  453.  
  454.     case 't':                /* tabto, tempindent, or
  455.                          * toindent */
  456.         if (word[1] == 'a') {
  457.         /*
  458.          * Move to TAB stop.
  459.          */
  460.             if (Outll < 0)
  461.                 Outll = 0;
  462.             if ((n = narg - Outll) > 0) {
  463.                 if ((Outlx + n) >= MAXOLL)
  464.                     goto line_too_big;
  465.                 Outll += n;
  466.                 for (i = n; i > 0; i--)
  467.                     Outln[Outlx++] = ' ';
  468.                 Free(&Cont);
  469.                 Contlen = 0;
  470.                 Padx = 0;
  471.             }
  472.             return;
  473.         } else if (word[1] == 'e') {
  474.         /*
  475.          * Set temporary indentation.
  476.          */
  477.             Tind = narg;
  478.             return;
  479.         } else if (word[1] == 'o')
  480.             return;                /* toindent */
  481.         break;
  482.  
  483.     case 'u':                    /* userhyphen */
  484.         /*
  485.          * Set line length.
  486.          */
  487.         Free(&Cont);
  488.         Free(&Eol);
  489.         Contlen = Eollen = narg;
  490.         Cont = (sarg == NULL) ? NULL : Newstr(sarg);
  491.         Eol = (sarg == NULL) ? NULL : Newstr(sarg);
  492.         return;
  493.  
  494.     case 'v':                    /* vspace */
  495.         /*
  496.          * Set vertical spacing.
  497.          */
  498.         Vspace = (narg == 0) ? 1 : narg;
  499.         return;
  500.  
  501.     case 'y':                    /* yesspace */
  502.         /*
  503.          * Set space mode.
  504.          */
  505.         Nospmode = 0;
  506.         return;
  507.     }                /* end of switch(*word) */
  508.     /*
  509.      * Locate header and footer defintions.
  510.      */
  511.     if (regexec(Pat[14].pat, word)) {
  512.         if (strcmp(word, "LH") == 0) {
  513.             /*
  514.              * Left header
  515.              */
  516.             Free(&Hdl);
  517.             if (sarg != NULL)
  518.                 Hdl = Newstr(sarg);
  519.             return;
  520.         }
  521.         if (strcmp(word, "CH") == 0) {
  522.             /*
  523.              * Center header
  524.              */
  525.             Free(&Hdc);
  526.             if (sarg != NULL)
  527.                 Hdc = Newstr(sarg);
  528.             return;
  529.         }
  530.         if (strcmp(word, "RH") == 0) {
  531.             /*
  532.              * Right header
  533.              */
  534.             Free(&Hdr);
  535.             if (sarg != NULL)
  536.                 Hdr = Newstr(sarg);
  537.             return;
  538.         }
  539.         if (strcmp(word, "LF") == 0) {
  540.             /*
  541.              * Left footer
  542.              */
  543.             Free(&Ftl);
  544.             if (sarg != NULL)
  545.                 Ftl = Newstr(sarg);
  546.             return;
  547.         }
  548.         if (strcmp(word, "CF") == 0) {
  549.             /*
  550.              * Center footer
  551.              */
  552.             Free(&Ftc);
  553.             if (sarg != NULL)
  554.                 Ftc = Newstr(sarg);
  555.             return;
  556.         }
  557.         if (strcmp(word, "RF") == 0) {
  558.             /*
  559.              * Right footer
  560.              */
  561.             Free(&Ftr);
  562.             if (sarg != NULL)
  563.                 Ftr = Newstr(sarg);
  564.             return;
  565.         }
  566.     }
  567.     /*
  568.      * Error on unknown arguments
  569.      */
  570.     Error3(len, word, sarg, narg, "unknown request");
  571. }
  572.