home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / wroff / part01 / source / format.c
Encoding:
C/C++ Source or Header  |  1991-12-11  |  11.9 KB  |  564 lines

  1. /* this file contains the line formatting stuff */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include "defs.h"
  6. #include "externs.c"
  7.  
  8. format(s,ifile,f)
  9. char s[];
  10. FILE *ifile,*f;
  11. {
  12.     /* The idea is to collect output into a buffer (outbuf)
  13.        and when the buffer is complete, write it. 
  14.        The variable s contains the text of the last line
  15.        read from the input file.  The output buffer is
  16.        in variable "outbuf".  */
  17.     
  18.     int i;
  19.  
  20.     char word[MAXSTR],tstring[MAXSTR];
  21.     int wordlength;
  22.     int diff;
  23.     int chcnt;
  24.  
  25.     /* first "doctor" the line if boldcount or italicscount > 0 */
  26.     if (BOLDCNT > 0) {
  27.         addstr(s,"\\fB","\\fP");
  28.         BOLDCNT--;
  29.     }
  30.     if (ITALCNT > 0) {
  31.         addstr(s,"\\fI","\\fP");
  32.         ITALCNT--;
  33.     }
  34.     if (ULCOUNT > 0) {
  35.         addstr(s,"\\fU","\\fU");
  36.         ULCOUNT--;
  37.     }
  38.  
  39.     /* now if the line should be centered, do it, otherwise just
  40.       format it */
  41.     if (!FILLMODE || CNTRCNT > 0) {
  42.         /* just parse the line to get the length */
  43.         i = 0;
  44.         while (s[i] != '\0') {
  45.             getword(word,s,&i);
  46.             parseword(tstring,word,&wordlength,&chcnt,ifile,f);
  47.             append(tstring,chcnt);
  48.             CURRX = CURRX + wordlength;
  49.         }
  50.         endln();
  51.  
  52.         TEMPINDENT = 0;
  53.         if (CNTRCNT > 0) {
  54.             TEMPINDENT = (RMARGIN - LMARGIN - CURRX)/2;
  55.             CNTRCNT--;
  56.         }
  57.  
  58.         output (ifile,f,0);
  59.     }
  60.     else { /* don't center it */
  61.  
  62.     /* get a word from s */
  63.     i = 0;
  64.     while ( s[i] != '\0') {
  65.         getword(word,s,&i);
  66.         /* now add the word to the buffer */
  67.         /* we have to parse the word to find any
  68.            embedded font changes, and to determine its printable
  69.            length */
  70.         parseword(tstring,word,&wordlength,&chcnt,ifile,f);
  71.  
  72.         diff = RMARGIN - LMARGIN - TEMPINDENT;
  73.         if (( length(' ') + CURRX + wordlength) >= diff) { 
  74.             endln();
  75.             output(ifile,f,diff);
  76.         }
  77.         append(tstring,chcnt);
  78.         CURRX = CURRX + wordlength ;
  79.         /* note CURRX is current printable position on line */
  80.  
  81.     }
  82.     } /* of don't center it */
  83. }
  84.  
  85.  
  86. /* getword looks inside string s, starts at position i, and returns
  87.    the next word in t */
  88. VOID getword(t,s,i)
  89. char t[];
  90. char s[];
  91. int *i;
  92. {
  93.     int j;
  94.     /* first skip any white space */
  95.     while ( s[*i] != '\0' && isspace(s[*i]) ) (*i)++;
  96.     
  97.     /* now copy into string t */
  98.     j = 0;
  99.     while ( s[*i] != '\0' && !isspace(s[*i]) ) {
  100.         t[j] = s[*i];
  101.         (*i)++;
  102.         j++;
  103.     }
  104.     t[j] = '\0';
  105.     /* note that s[*i] is either '\0' or it is white space */
  106.  
  107. }
  108.  
  109.  
  110. /* append adds the string to the existing output buffer.  Note that
  111.    the buffer does NOT have a NULL at its end.  */
  112. VOID append(s,chcnt)
  113. char s[];
  114. int chcnt;
  115. {
  116.     int j;
  117.     if (shadd &&  obufpos != 0 && s[0] != '\0') {
  118.         outbuf[obufpos] = ' ';
  119.         obufpos++;
  120.         outbuf[obufpos] = SHIFTOUT;
  121.         obufpos++;
  122.         CHARCNT = CHARCNT + 1;
  123.         CURRX = CURRX + length(' ');
  124.     }
  125.     else
  126.         shadd = TRUE;
  127.  
  128.     j = 0;
  129.     while (s[j] != '\0') {
  130.         outbuf[obufpos] = s[j];
  131.         j++;
  132.         obufpos++;
  133.     }
  134.     if (LASTPERIOD) {
  135.         outbuf[obufpos] = ' ';
  136.         obufpos++;
  137.         outbuf[obufpos] = SHIFTOUT;
  138.         obufpos++;
  139.         CHARCNT = CHARCNT + 1;
  140.         CURRX = CURRX + length(' ');
  141.         LASTPERIOD = FALSE;
  142.     }
  143.     /* WARNING --- outbuf does NOT have a NULL at its end */
  144.     CHARCNT = CHARCNT + chcnt ;
  145.  
  146.  
  147. }
  148.  
  149.  
  150. /* we have to parse the word to find any
  151.    embedded font changes, and to determine its printable
  152.    length.  The word is copied into tstring with any control characters
  153.    expanded and embedded.  This needs to be a FSM. */
  154.  
  155. VOID parseword(tstring,word,wordlength,chcnt,ifile,f)
  156. char tstring[],word[];
  157. int *wordlength;
  158. int *chcnt;
  159. FILE *ifile, *f;
  160. {
  161.     int nextstate;
  162.     int i; /* for counter of subscript in word */
  163.     int j;  /* subscript in tstring */
  164.     int k; /* subscript for copying */
  165.     int m;  /* general counter */
  166.  
  167.     char tstr[MAXSTR], tempstr[MAXSTR];    /* a temporary string */
  168.     char ch,regname;
  169.  
  170.     *chcnt = 0;
  171.     *wordlength = 0;
  172.     i = 0;
  173.     j = 0;
  174.  
  175.     nextstate = 0;
  176.     if (InExpression)
  177.         nextstate = 4;
  178.     
  179.     if (InMacro)
  180.         nextstate = 17;
  181.  
  182.     while (nextstate != 999) {
  183.         ch = word[i];
  184.         switch(nextstate) {
  185.             case 0: /* start state */
  186.                 if (ch == '\\')
  187.                     nextstate = 1;
  188.                 else if (ch == '\0' || ch == EOF)
  189.                     nextstate = 999;
  190.                 else  /* copy state */
  191.                     nextstate = 1000;
  192.                 break;
  193.             
  194.             case 1 : /* it's a '\' */
  195.                 i++;
  196.                 ch = word[i];
  197.                 if (ch == '\\')
  198.                     nextstate = 2;
  199.                 else if (ch == '(')
  200.                     nextstate = 3;
  201.                 else if (ch == '{')
  202.                     nextstate = 17;
  203.                 else if (ch == '[')
  204.                     nextstate = 4;
  205.                 else if (ch == 'f')
  206.                     nextstate = 8;
  207.                 else 
  208.                     /* not a state -- must be an escaped
  209.                     character, so just copy it */
  210.                     nextstate = 1000;
  211.                 break;
  212.             
  213.             case 2:  /* it is an escaped '\' */
  214.                 tstring[j] = ch;
  215.                 j++;
  216.                 tstring[j] = SHIFTOUT;
  217.                 j++;
  218.                 *wordlength = *wordlength + length('\\');
  219.                 *chcnt = *chcnt + 1;
  220.                 i++;
  221.                 nextstate = 0; /* start it over */
  222.                 break;
  223.  
  224.             case 3:  /* it is an in-line register */
  225.                 /* first get the name of the register -- it should
  226.                 be a single character */
  227.                 i++;
  228.                 regname = word[i];
  229.                 i++; /* advance to after the register name */
  230.                 if (word[i] == 'C') {
  231.                     /* interpolate as a character */
  232.                     sprintf(tempstr,"%c",REG(regname));
  233.                     i++;
  234.                 }
  235.                 else  /* interpolate as a number */
  236.                     sprintf(tempstr,"%d",REG(regname));
  237.                 if (word[i]!= ')') {
  238.                     fprintf(stderr,"error in register name -- one letter only!\n");
  239.                     exit(1);
  240.                 }
  241.                 i++; /* to skip the ')' */
  242.                 /* now append tempstr to the output string */
  243.                 k = 0;
  244.                 while (tempstr[k] != '\0') {
  245.                   tstring[j] = tempstr[k];
  246.                   j++;
  247.                   tstring[j] = SHIFTOUT;
  248.                   *wordlength = *wordlength + length(tempstr[k]);
  249.                   *chcnt = *chcnt + 1;
  250.                   j++;
  251.                   k++;
  252.                 }
  253.                 nextstate = 0;
  254.  
  255.                 break;
  256.  
  257.             case 4: /* it is an expression */
  258.                 /* don't forget to advance i to end of expression */
  259.                 /* the end of the expression is signified by ']' */
  260.                 InExpression = TRUE;
  261.                 tstr[0] = '\0';
  262.                 if (word[i] == '[') i++; /* skip the '[' */
  263.                 k = 0;
  264.                 while (word[i] != '\0' && word[i] != ']') {
  265.                     tstr[k] = word[i];
  266.                     i++;
  267.                     k++;
  268.                 }
  269.                 tstr[k] = ' ';
  270.                 tstr[k + 1] = '\0';
  271.                 strcat(expstr,tstr);
  272.                 if (word[i] == ']') {
  273.                     InExpression = FALSE;
  274.                     eval(expstr);
  275.                     expstr[0] = '\0';
  276.                 }
  277.  
  278.                 if (word[i] == ']') i++; /* skip the whatever */
  279.                 nextstate = 0;
  280.  
  281.                 break;
  282.  
  283.             case 8:  /* it is a font change, I guess.  find out which one */
  284.                 i++;
  285.                 ch = word[i];
  286.                 switch (ch) {
  287.                   case '0' : /* return to default font */
  288.                     pushf(cfont,&fstk);
  289.                     pushi(clen,&ipstk);
  290.                     clen = defl;
  291.                     strcpy(cfont,prinit);
  292.                     k = 0;
  293.                     if (!FONTCHANGE)
  294.                         cfont[0] = '\0';
  295.                     while (cfont[k] != '\0') {
  296.                         tstring[j] = cfont[k];
  297.                         k++;
  298.                         j++;
  299.                     }
  300.                     break;
  301.                   case 'M': /* mountable font */
  302.                   case '1' : /* Presentation 18 point */
  303.                     pushf(cfont,&fstk);
  304.                     pushi(clen,&ipstk);
  305.                     strcpy(cfont,Pres);
  306.                     clen = &P18bl[0];
  307.                     k = 0;
  308.                     if (!FONTCHANGE ) cfont[0] = '\0';
  309.                     while (cfont[k] != '\0') {
  310.                         tstring[j] = cfont[k];
  311.                         k++;
  312.                         j++;
  313.                     }
  314.                     break;
  315.                   case '2' : /* Helv. 6 point font */
  316.                     pushf(cfont,&fstk);
  317.                     pushi(clen,&ipstk);
  318.  
  319.                     sprintf(cfont,"%c&10O%c(0U%c(s1p6vsb4T",ESC,ESC,ESC);
  320.                     clen = &H6nl[0];
  321.                     k = 0;
  322.                     if (!FONTCHANGE ) cfont[0] = '\0';
  323.                     while (cfont[k] != '\0') {
  324.                         tstring[j] = cfont[k];
  325.                         k++;
  326.                         j++;
  327.                     }
  328.                     break;
  329.                   case 'B' : /* Times Roman bold face */
  330.                     pushf(cfont,&fstk);
  331.                     pushi(clen,&ipstk);
  332.                     clen = &H12bl[0];
  333.                     sprintf(cfont,"%c&l0O%c(0U%c(s1p12vs3b5T",ESC,ESC,ESC);
  334.                     if (!FONTCHANGE ) cfont[0] = '\0';
  335.                     k = 0;
  336.                     while (cfont[k] != '\0') {
  337.                         tstring[j] = cfont[k];
  338.                         k++;
  339.                         j++;
  340.                     }
  341.                     break;
  342.                   case 'I' : /* Times Roman 12 point italics */
  343.                     pushf(cfont,&fstk);
  344.                     pushi(clen,&ipstk);
  345.                     sprintf(cfont,"%c&l0O%c(0U%c(s1p12v1sb5T",ESC,ESC,ESC);
  346.                     clen = &H12il[0];
  347.                     if (!FONTCHANGE ) cfont[0] = '\0';
  348.                     k = 0;
  349.                     while (cfont[k] != '\0') {
  350.                         tstring[j] = cfont[k];
  351.                         k++;
  352.                         j++;
  353.                     }
  354.                     break;
  355.                   case 'T' : /* Courier */
  356.                     pushf(cfont,&fstk);
  357.                     pushi(clen,&ipstk);
  358.                     sprintf(cfont,"%c&10O%c(0U%c(sp10h12vsb3T",ESC,ESC,ESC);
  359.                     clen = &C12nl[0];
  360.                     if (!FONTCHANGE ) cfont[0] = '\0';
  361.                     k = 0;
  362.                     while (cfont[k] != '\0') {
  363.                         tstring[j] = cfont[k];
  364.                         k++;
  365.                         j++;
  366.                     }
  367.                     break;
  368.                   case 'U' : /* underline toggle */
  369.                     if (ULSTATE == FALSE) {
  370.                         sprintf(tempstr,"%c&dD",ESC);
  371.                         ULSTATE = TRUE;
  372.                     }
  373.                     else {
  374.                         sprintf(tempstr,"%c&d@",ESC);
  375.                         ULSTATE = FALSE;
  376.                     }
  377.                     if (!FONTCHANGE ) tempstr[0] = '\0';
  378.                     k = 0;
  379.                     while (tempstr[k] != '\0') {
  380.                         tstring[j] = tempstr[k];
  381.                         k++;
  382.                         j++;
  383.                     }
  384.                     break;
  385.                   case 'P' : /* pop font stack */
  386.                     popf(cfont,&fstk);
  387.                     popi(&clen,&ipstk);
  388.                     k = 0;
  389.                     if (!FONTCHANGE ) cfont[0] = '\0';
  390.                     while (cfont[k] != '\0') {
  391.                         tstring[j] = cfont[k];
  392.                         k++;
  393.                         j++;
  394.                     }
  395.                     break;
  396.  
  397.                   case '|' : /* it's an anchor */
  398.                     m = 0;
  399.                     while (m <= j) {
  400.                         if (tstring[m] == SHIFTOUT) {
  401.                             tstring[m] = ANCHOR;
  402.                             *chcnt = *chcnt - 1;
  403.                         }
  404.                         m++;
  405.                     }
  406.                     sprintf(tempstr,"%c*p%dX",ESC,TEMPINDENT + LMARGIN + i*length('w') );
  407.                     k = 0;
  408.                     if (!FONTCHANGE ) tempstr[0] = '\0';
  409.                     while (tempstr[k] != '\0') {
  410.                         tstring[j] = tempstr[k];
  411.                         k++;
  412.                         j++;
  413.                     }
  414.                     break;
  415.  
  416.                 } /* of switch */
  417.                 i++;
  418.                 nextstate = 0; /* start over */
  419.                 break;
  420.  
  421.             case 17: /* expand in-line string macro */
  422.                 /* don't forget to advance i */
  423.                 InMacro = TRUE;
  424.                 if (word[i] == '{') i++; /* skip the '{' */
  425.                 k = 0;
  426.                 while (word[i] != '\0' && word[i] != '}') {
  427.                     tstr[k] = word[i];
  428.                     i++;
  429.                     k++;
  430.                 }
  431.                 tstr[k] = ' ';
  432.                 tstr[k + 1] = '\0';
  433.                 strcat(macline,tstr);
  434.                 if (word[i] == '}') {
  435.                     /* skip the '}' */
  436.                     i++;
  437.                     /* end the macline and process the
  438.                        macro */
  439.                     InMacro = FALSE;
  440.                     procmacro (macline,ifile,f);
  441.                     macline[0] = '\0';
  442.                     tstr[0] = '\0';
  443.                     
  444.                 }
  445.  
  446.                 nextstate = 0;
  447.  
  448.                 break;
  449.  
  450.  
  451.             case 999 : /* at the end state */
  452.                 break;
  453.  
  454.             case 1000 : /* copy state */
  455.             default:
  456.                 tstring[j] = ch;
  457.                 j++;
  458.                 tstring[j] = SHIFTOUT;
  459.                 nextstate = 0; /* start it over */
  460.                 *wordlength = *wordlength + length(ch);
  461.                 *chcnt = *chcnt + 1;
  462.                 j++;
  463.                 i++;
  464.                 break;
  465.             
  466.         }  /* of switch */
  467.     }  /* of while nextstate */
  468.     tstring[j] = '\0';
  469.     k = j - 1;
  470.     while (k > 0 && (isspace(tstring[k]) || tstring[k] == SHIFTOUT) ) k--;
  471.     if (k > 0 && ispunct(tstring[k]) )
  472.         LASTPERIOD = TRUE;
  473.     else
  474.         LASTPERIOD = FALSE;
  475.  
  476. }  /* of parseword */
  477.  
  478.  
  479.  
  480. /* length returns the length of a character, measured in dots */
  481. int length(c)
  482. char c;
  483. {
  484.     /* temporarily */
  485.     return *(clen + (c & 0xff));
  486. }
  487.  
  488. /* clean out the buffers, print anything collected, and reset counters */
  489. VOID brek(ifile,ofile)
  490. FILE *ifile,*ofile;
  491. {
  492.     /* be sure to empty the buffer again */
  493.     outbuf[obufpos] = '\0';
  494.     if (outbuf[0] != '\0') 
  495.         output(ifile,ofile,0);
  496.     outbuf[0] = '\0';
  497.     obufpos = 0;
  498.     CURRX = 0;
  499.     CHARCNT = 0;
  500. }
  501.  
  502.  
  503. /* process a line, but do not justify it, and preserve the spaces */
  504. nonfill(s,ifile,f)
  505. char s[];
  506. FILE *ifile,*f;
  507. {
  508.     /* The idea is to collect output into a buffer (outbuf)
  509.        and when the buffer is complete, write it. 
  510.        The variable s contains the text of the last line
  511.        read from the input file.  The output buffer is
  512.        in variable "outbuf".  */
  513.     
  514.     int i;
  515.  
  516.     char word[MAXSTR],tstring[MAXSTR];
  517.     int wordlength;
  518.     int chcnt;
  519.  
  520.     /* first "doctor" the line if boldcount or italicscount > 0 */
  521.     if (BOLDCNT > 0) {
  522.         addstr(s,"\\fB","\\fP");
  523.         BOLDCNT--;
  524.     }
  525.     if (ITALCNT > 0) {
  526.         addstr(s,"\\fI","\\fP");
  527.         ITALCNT--;
  528.     }
  529.     if (ULCOUNT > 0) {
  530.         addstr(s,"\\fU","\\fU");
  531.         ULCOUNT--;
  532.     }
  533.  
  534.     /* now if the line should be centered, do it, otherwise just
  535.       format it */
  536.     if ( CNTRCNT > 0) {
  537.         /* just parse the line to get the length */
  538.         i = 0;
  539.         while (s[i] != '\0') {
  540.             getword(word,s,&i);
  541.             parseword(tstring,word,&wordlength,&chcnt,ifile,f);
  542.             append(tstring,chcnt);
  543.             CURRX = CURRX + wordlength;
  544.         }
  545.         endln();
  546.  
  547.         TEMPINDENT = (RMARGIN - LMARGIN - CURRX)/2;
  548.         CNTRCNT--;
  549.  
  550.         output (ifile,f,0);
  551.     }
  552.     else { /* don't center it */
  553.  
  554.     /* expand s to include any font changes */
  555.     parseword(tstring,s,&wordlength,&chcnt,ifile,f);
  556.     strcpy(outbuf,tstring);
  557.     CURRX = CURRX + wordlength ;
  558.     TEMPINDENT = 0;
  559.     output(ifile,f,0);
  560.  
  561.     } /* of don't center it */
  562. }
  563.  
  564.