home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / UTILITY / CAWF2.ZIP / PASS3.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-04  |  12.4 KB  |  579 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.                 Charput('\f');
  129.             for (i = (Topmarg - 1)/2; i > 0; i--) {
  130.                 Charput('\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.                     Charput(' ');
  144.                 if (Hdl)
  145.                     LenprtHF(Hdl, Thispg, 1);
  146.                 while (j--)
  147.                     Charput(' ');
  148.                 if (Hdc)
  149.                     LenprtHF(Hdc, Thispg, 1);
  150.                 while (n--)
  151.                     Charput(' ');
  152.                 if (Hdr)
  153.                     LenprtHF(Hdr, Thispg, 1);
  154.                 Charput('\n');
  155.             } else
  156.                 Charput('\n');
  157.             Nxtln++;
  158.             while(Nxtln <= Topmarg) {
  159.                 Charput('\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.             Charput('\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.                 Charput(' ');
  197.             Stringput(Outln);
  198.             Charput('\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.                 Charput(' ');
  207.             Stringput(Outln);
  208.             Charput('\n');
  209.         } else if (Adj == BOTHADJ) {
  210.             /*
  211.              * Adjust right margin.
  212.              */
  213.             for (i = 0; i < (Pgoff + Ind + Tind); i++)
  214.                 Charput(' ');
  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.                     Charput(*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.                     Charput(' ');
  232.             }
  233.             while (*s1)
  234.                 Charput(*s1++);
  235.             Charput('\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.                 Charput('\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.                 Charput('\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.                 Charput(' ');
  270.             if (Ftl)
  271.                 LenprtHF(Ftl, Thispg, 1);
  272.             while (j--)
  273.                 Charput(' ');
  274.             if (Ftc)
  275.                 LenprtHF(Ftc, Thispg, 1);
  276.             while (n--)
  277.                 Charput(' ');
  278.             if (Ftr)
  279.                 LenprtHF(Ftr, Thispg, 1);
  280.             Charput('\n');
  281.             Nxtln++;
  282.         /*
  283.          * The last blank line on the page is suppressed to assist
  284.          * printers that can't look ahead to the following FF.
  285.          */
  286.             while (Nxtln < Pglen) {
  287.                 Charput('\n');
  288.                 Nxtln++;
  289.             }
  290.             Nxtln = 1;
  291.             Thispg++;
  292.             Nospmode = 1;
  293.             Padfrom = PADRIGHT;
  294.         }
  295.         /*
  296.          * Initiate any extra vertical spacing.
  297.          */
  298.         if (++vsp < Vspace)
  299.             goto print_line;
  300.         /*
  301.          * Save any input word that might have forced output.
  302.          */
  303.         if (len >= 0) {
  304.             (void) strcpy(Outln, word);
  305.             Outll = len;
  306.             Outlx = wl;
  307.             Padx = 0;
  308.         }
  309.     }
  310.     /*
  311.      * A break causes padding reversal.
  312.      */
  313.     if (len == DOBREAK)
  314.         Padfrom = PADRIGHT;
  315.     if (len >= 0 || strcmp(word, "nohyphen") == 0) {
  316.     /*
  317.      * Reset continuation and hyphenation.
  318.      */
  319.         if (Contlen != 1 || Cont[0] != ' ') {
  320.             Free(&Cont);
  321.             Cont = Newstr(" ");
  322.             Contlen = 1;
  323.         }
  324.         if (Eollen > 0) {
  325.             Free(&Eol);
  326.             Eollen = 0;
  327.         }
  328.         return;
  329.     }
  330.     /*
  331.      * Now post-process any special commands.
  332.      */
  333.     if (len == MESSAGE) {
  334.         Error3(len, word, sarg, narg, NULL);
  335.         return;
  336.     }
  337.  
  338.     switch (*word) {
  339.  
  340.     case 'b':                /* both */
  341.         /*
  342.          * Adjust on both margins.
  343.          */
  344.         Adj = BOTHADJ;
  345.         return;
  346.  
  347.     case 'c':                /* center */
  348.         return;
  349.  
  350.     case 'e':                /* errsto */
  351.         /*
  352.          * "errsto" comes from awf.
  353.          */
  354.         return;
  355.  
  356.     case 'f':                /* flush and fph */
  357.         if (word[1] == 'l')
  358.             return;
  359.         else if (word[1] == 'p') {
  360.         /*
  361.          * First page header status
  362.          */
  363.             Fph = narg;
  364.             return;
  365.         }
  366.         break;
  367.  
  368.     case 'g':                /* gap */
  369.         /*
  370.          * Increase word gap.  (Space is not paddable.)
  371.          */
  372.         if (Outll >= 0) {
  373.             if ((Outlx + narg - 1) >= MAXOLL)
  374.                 goto line_too_big;
  375.             for (i = 0; i < (narg - 1); i++) {
  376.                 Outln[Outlx++] = ' ';
  377.                 Outll++;
  378.             }
  379.         }
  380.         return;
  381.  
  382.     case 'h':                /* hyphen */
  383.         /*
  384.          * Set discretionary hyphen.
  385.          */
  386.         Free(&Cont);
  387.         Contlen = 0;
  388.         Free(&Eol);
  389.         Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
  390.         Eollen = narg;
  391.         return;
  392.  
  393.     case 'i':                /* indent */
  394.         /*
  395.          * Set indentation.
  396.          */
  397.         Ind = narg;
  398.         return;
  399.  
  400.     case 'l':                /* left or linelen */
  401.         if (word[1] == 'e') {
  402.         /*
  403.          * Adjust on left margin.
  404.          */
  405.             Adj = LEFTADJ;
  406.             return;
  407.         } else if (word[1] == 'i') {
  408.         /*
  409.          * Set line length.
  410.          */
  411.             LL = narg;
  412.             return;
  413.         }
  414.         break;
  415.  
  416.     case 'n':                /* need or nospace */
  417.         if (word[1] == 'e')
  418.             return;            /* need */
  419.         else if (word[1] == 'o') {
  420.         /*
  421.          * Set no space mode.
  422.          */
  423.             Nospmode = 1;
  424.             return;
  425.         }
  426.         break;
  427.  
  428.     case 'p':                /* pagelen or pageoffset */
  429.         if (strncmp(&word[1], "age", 3) != 0)
  430.             break;
  431.         if (word[4] == 'l') {
  432.         /*
  433.          * Set page length.
  434.          */
  435.             Pglen = narg;
  436.             return;
  437.         } else if (word[4] == 'o') {
  438.         /*
  439.          * Set page offset.
  440.          */
  441.             Pgoff = narg;
  442.             return;
  443.         }
  444.         break;
  445.  
  446.     case 's':                /* space */
  447.         /*
  448.          * Generate an empty line.
  449.          */
  450.         if (Nospmode == 0) {
  451.             Outlx = 0;
  452.             Outln[0] = '\0';
  453.             Padx = 0;
  454.             Outll = LL - 1;
  455.         }
  456.         return;
  457.  
  458.     case 't':                /* tabto, tempindent, or
  459.                          * toindent */
  460.         if (word[1] == 'a') {
  461.         /*
  462.          * Move to TAB stop.
  463.          */
  464.             if (Outll < 0)
  465.                 Outll = 0;
  466.             if ((n = narg - Outll) > 0) {
  467.                 if ((Outlx + n) >= MAXOLL)
  468.                     goto line_too_big;
  469.                 Outll += n;
  470.                 for (i = n; i > 0; i--)
  471.                     Outln[Outlx++] = ' ';
  472.                 Free(&Cont);
  473.                 Contlen = 0;
  474.                 Padx = 0;
  475.             }
  476.             return;
  477.         } else if (word[1] == 'e') {
  478.         /*
  479.          * Set temporary indentation.
  480.          */
  481.             if (*sarg == '\0' && narg >= 0)
  482.                 Tind = narg - Ind;
  483.             else
  484.                 Tind = ((Ind + narg) >= 0) ? narg : -Ind;
  485.             return;
  486.         } else if (word[1] == 'o')
  487.             return;                /* toindent */
  488.         break;
  489.  
  490.     case 'u':                    /* userhyphen */
  491.         /*
  492.          * Set line length.
  493.          */
  494.         Free(&Cont);
  495.         Free(&Eol);
  496.         Contlen = Eollen = narg;
  497.         Cont = (sarg == NULL) ? NULL : Newstr(sarg);
  498.         Eol = (sarg == NULL) ? NULL : Newstr(sarg);
  499.         return;
  500.  
  501.     case 'v':                    /* vspace */
  502.         /*
  503.          * Set vertical spacing.
  504.          */
  505.         Vspace = (narg == 0) ? 1 : narg;
  506.         return;
  507.  
  508.     case 'y':                    /* yesspace */
  509.         /*
  510.          * Set space mode.
  511.          */
  512.         Nospmode = 0;
  513.         return;
  514.     }                /* end of switch(*word) */
  515.     /*
  516.      * Locate header and footer defintions.
  517.      */
  518.     if (regexec(Pat[14].pat, word)) {
  519.         if (strcmp(word, "LH") == 0) {
  520.             /*
  521.              * Left header
  522.              */
  523.             Free(&Hdl);
  524.             if (sarg != NULL)
  525.                 Hdl = Newstr(sarg);
  526.             return;
  527.         }
  528.         if (strcmp(word, "CH") == 0) {
  529.             /*
  530.              * Center header
  531.              */
  532.             Free(&Hdc);
  533.             if (sarg != NULL)
  534.                 Hdc = Newstr(sarg);
  535.             return;
  536.         }
  537.         if (strcmp(word, "RH") == 0) {
  538.             /*
  539.              * Right header
  540.              */
  541.             Free(&Hdr);
  542.             if (sarg != NULL)
  543.                 Hdr = Newstr(sarg);
  544.             return;
  545.         }
  546.         if (strcmp(word, "LF") == 0) {
  547.             /*
  548.              * Left footer
  549.              */
  550.             Free(&Ftl);
  551.             if (sarg != NULL)
  552.                 Ftl = Newstr(sarg);
  553.             return;
  554.         }
  555.         if (strcmp(word, "CF") == 0) {
  556.             /*
  557.              * Center footer
  558.              */
  559.             Free(&Ftc);
  560.             if (sarg != NULL)
  561.                 Ftc = Newstr(sarg);
  562.             return;
  563.         }
  564.         if (strcmp(word, "RF") == 0) {
  565.             /*
  566.              * Right footer
  567.              */
  568.             Free(&Ftr);
  569.             if (sarg != NULL)
  570.                 Ftr = Newstr(sarg);
  571.             return;
  572.         }
  573.     }
  574.     /*
  575.      * Error on unknown arguments
  576.      */
  577.     Error3(len, word, sarg, narg, "unknown request");
  578. }
  579.