home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 195_01 / format.c < prev    next >
Text File  |  1987-10-05  |  10KB  |  556 lines

  1. /* [FORMAT.C of JUGPDS Vol.18]
  2. *****************************************************************
  3. *                                *
  4. *    Written by  Hakuo Katayose (JUG-CP/M No.179)        *
  5. *            49-114 Kawauchi-Sanjuunin-machi        *
  6. *            Sendai, Miyagi 980                          *
  7. *            Phone: 0222-61-3219                *
  8. *                                *
  9. *    Edited & tested by Y. Monma (JUG-C/M Disk Editor)       * 
  10. *                                *
  11. *****************************************************************
  12. */
  13.  
  14. /*    format - text formatter 
  15.  
  16. ---------------------------------------------------------------------
  17.  #  dot command  break?  default     function
  18. ---------------------------------------------------------------------
  19.  1  .fi          yes          stat filling
  20.  2  .nf          yes              stop filling
  21.  3  .br n        yes              cause break
  22.  4  .ls n        no       n=1     line spacing is n
  23.  5  .bp n        yes      n=+1    begin page numbered n
  24.  6  .sp n        yes      n=1     space down n lines
  25.  7  .in n        no       n=0     indent n spaces
  26.  8  .rm n        no       n=60    set right margin to n
  27.  9  .ti n        yes      n=0     temporary indent of n
  28. 10  .ce n        yes      n=1     center nextn lines
  29. 11  .ul n        no       n=1     underline words from next n lines
  30. 12  .he          no      empty    header title
  31. 13  .fo          no      empty    footer title
  32. 14  .pl n        no       n=66    set page length to n
  33. ---------------------------------------------------------------------
  34.  
  35. .bp 1
  36. .in 8
  37. .rm 76
  38. .he :        program     format.c                                       #
  39. */
  40.  
  41. #include <stdio.h>
  42. #include <dio.h>
  43.  
  44. #define UNKNOWN 0
  45. #define FI 1
  46. #define NF 2
  47. #define BR 3
  48. #define LS 4
  49. #define BP 5
  50. #define SP 6
  51. #define IN 7
  52. #define RM 8
  53. #define TI 9
  54. #define CE 10
  55. #define UL 11
  56. #define HE 12    /* Header enable */
  57. #define FO 13
  58. #define PL 14
  59.  
  60. #define SQUOTE '\''
  61. #define DQUOTE '"'
  62. #define PLUS '+'
  63. #define MINUS '-'
  64. #define COMMAND '.'
  65. #define PAGENUM '#'
  66. #define PAGELEN 66
  67. #define PAGEWIDTH 60
  68. #define MAXOUT 256
  69. #define HUGE 1000
  70. #define INSIZE 256
  71. #define MAXLINE 256
  72.  
  73. #define YES 1
  74. #define NO 0
  75.  
  76. int    fill,    /* fill if YES; init = YES            */
  77.     lsval,    /* current line spacing; init = 1        */
  78.     inval,    /* current indent; >= 0; init = 0        */
  79.     rmval,    /* current right margin; init = PAGEWIDTH = 60    */
  80.     tival,    /* current temporary indent; init = 0        */
  81.     ceval,    /* # of lines to center; init = 0        */
  82.     ulval,    /* # of lines to underline; init = 0        */
  83.     curpag,
  84.     newpag,
  85.     lineno,
  86.     plval;
  87.  
  88. int    m1val, m2val, m3val, m4val, bottom;
  89.  
  90. char    __header[MAXLINE], __footer[MAXLINE], *header, *footer;
  91.  
  92. int    outp, outw, outwds, dir;
  93. char    outbuf[(MAXOUT+1)];
  94. /*
  95. .bp
  96. */
  97.  
  98. main(argc, argv)
  99. int    argc;
  100. char     **argv;
  101.  
  102. {
  103.     char inbuf[MAXLINE], *line;
  104.  
  105.     dioinit(&argc, argv);
  106.     if (argc < 2) {
  107.         error("Usage: format <infile >outfile ^Z");
  108.         exit();
  109.         }
  110.     init();
  111.     line = inbuf;
  112.     while (getlin(line, MAXLINE) > 0)
  113.         if (*line == COMMAND)
  114.             Comand(line);
  115.         else
  116.             Text(line);
  117.     if (lineno > 0)
  118.         LineSpace(HUGE);
  119.     dioflush();
  120. }
  121.  
  122.  
  123. /*    comand - perform formatting command
  124. .bp
  125. */
  126. Comand(line)
  127. char *line;
  128.  
  129. {
  130.     int ctyp, argtyp, val, spval;
  131.  
  132.     if ((ctyp = ComandTyp(line)) == UNKNOWN)
  133.         return;
  134.     val = GetArgVal(line, &argtyp);
  135.     switch (ctyp) {
  136.     case FI :
  137.         brk();
  138.         fill = YES;
  139.         break;
  140.     case NF :
  141.         brk();
  142.         fill = NO;
  143.         break;
  144.     case BR :
  145.         brk();
  146.         break;
  147.     case LS :
  148.         lsval = set(lsval, val, argtyp, 1, 1, HUGE);
  149.         break;
  150.     case BP :
  151.         if (lineno > 0)
  152.             LineSpace(HUGE);
  153.         curpag = set(curpag, val, argtyp, curpag+1, -HUGE, HUGE);
  154.         newpag = curpag;
  155.         break;
  156.     case SP :
  157.         spval = set(spval, val, argtyp, 1, 0, HUGE);
  158.         LineSpace(spval);
  159.         break;
  160.     case IN :
  161.         inval = set(inval, val, argtyp, 0, 0, rmval-1);
  162.         tival = inval;
  163.         break;
  164.     case RM :
  165.         rmval = set(rmval, val, argtyp, PAGEWIDTH, tival+1, HUGE);
  166.         break;
  167.     case TI :
  168.         brk();
  169.         tival = set(tival, val, argtyp, 0, 0, rmval);
  170.         break;
  171.     case CE :
  172.         brk();
  173.         ceval = set(ceval, val, argtyp, 1, 0, HUGE);
  174.         break;
  175.     case UL :
  176.         ulval = set(ulval, val, argtyp, 0, 1, HUGE);
  177.         break;
  178.     case HE :
  179.         GetTitle(line, header);
  180.         break;
  181.     case FO :
  182.         GetTitle(line, footer);
  183.         break;
  184.     case PL :
  185.         plval = set(plval, val, argtyp, PAGELEN,
  186.             m1val + m2val + m3val + m4val + 1, HUGE);
  187.         bottom = plval - m3val - m4val;
  188.         break;
  189.     }
  190. }
  191.  
  192.  
  193. ComandTyp(line)
  194. char *line;
  195.  
  196. {
  197.     char cmd[3];
  198.  
  199.     ++line;    cmd[0] = toupper(*line);
  200.     ++line;    cmd[1] = toupper(*line);
  201.     cmd[2] = '\0';
  202.     if (!strcmp(cmd, "FI"))
  203.         return(FI);
  204.     else if (!strcmp(cmd, "NF"))
  205.         return(NF);
  206.     else if (!strcmp(cmd, "BR"))
  207.         return(BR);
  208.     else if (!strcmp(cmd, "LS"))
  209.         return(LS);
  210.     else if (!strcmp(cmd, "BP"))
  211.         return(BP);
  212.     else if (!strcmp(cmd, "IN"))
  213.         return(IN);
  214.     else if (!strcmp(cmd, "RM"))
  215.         return(RM);
  216.     else if (!strcmp(cmd, "TI"))
  217.         return(TI);
  218.     else if (!strcmp(cmd, "CE"))
  219.         return(CE);
  220.     else if (!strcmp(cmd, "UL"))
  221.         return(UL);
  222.     else if (!strcmp(cmd, "HE"))
  223.         return(HE);
  224.     else if (!strcmp(cmd, "FO"))
  225.         return(FO);
  226.     else if (!strcmp(cmd, "PL"))
  227.         return(PL);
  228.     return(UNKNOWN);
  229. }
  230.  
  231.  
  232. /* GetAgVal - get argument value */
  233. GetArgVal(line, argtyp)
  234. char *line;
  235. int  *argtyp;
  236.  
  237. {
  238.     while (!isspace(*line))
  239.         line++;
  240.     while (*line == ' ' || *line == '\t')
  241.         line++;
  242.     *argtyp = *line;
  243.     if (*line == PLUS || *line == MINUS)
  244.         line++;
  245.     return(atoi(line));
  246. }
  247.  
  248. /* set - set parameter and check range */
  249. set(param, val, argtyp, defval, minval, maxval)
  250.  
  251. {
  252.     if (argtyp == '\n')
  253.         param = defval;
  254.     else if (argtyp == PLUS)
  255.         param += val;
  256.     else if (argtyp == MINUS)
  257.         param -= val;
  258.     else
  259.         param = val;
  260.     param = min(param, maxval);
  261.     return max(param, minval);
  262. }
  263.  
  264.  
  265. /* Text - process text lines */
  266. Text(line)
  267. char *line;
  268.  
  269. {
  270.     char wrdbuf[INSIZE];
  271.     int  i, len;
  272.     
  273.     i = 0;
  274.     if (isspace(*line))
  275.         LeadBlank(line);
  276.     if (ceval > 0) {
  277.         tival = max((rmval + tival - width(line))/2, 0);
  278.         put(line);
  279.         ceval--;
  280.         }
  281.     else if (*line == '\n')
  282.         put(line);
  283.     else if (fill == NO)    
  284.         put(line);
  285.     else
  286.         while (GetWord(line, &i, wrdbuf) > 0)
  287.             PutWord(wrdbuf);
  288. }
  289.  
  290. /* put - put out line with proper spacing andindenting */
  291. put(line)
  292. char *line;
  293.  
  294. {
  295.     int    i;
  296.  
  297.     if (lineno == 0 || lineno > bottom)
  298.         phead();
  299.     for (i = 0; i < tival; i++)
  300.         putchar(' ');
  301.     tival = inval;
  302.     puts(line);
  303.     skip(min(lsval-1, bottom - lineno));
  304.     lineno += lsval;
  305.     if (lineno > bottom)
  306.         pfoot();
  307. }
  308.  
  309.  
  310. LineSpace(i)
  311.  
  312. {
  313.     brk();
  314.     if (lineno > bottom)
  315.         return;
  316.     if (lineno == 0)
  317.         phead();
  318.     skip(min(i,bottom + 1 - lineno));
  319.     lineno += i;
  320.     if (lineno > bottom)
  321.         pfoot();
  322. }
  323.  
  324.  
  325. /* phead - put out line with proper spacing and indenting */
  326. phead()
  327.  
  328. {
  329.     curpag = newpag++;
  330.     if (m1val > 0) {
  331.         skip(m1val-1);
  332.         PutTitle(header, curpag);
  333.         }
  334.     skip(m2val);
  335.     lineno = m1val + m2val + 1;
  336. }
  337.  
  338.  
  339. /* pfoot - put out page footer */
  340. pfoot()
  341.  
  342. {
  343.     skip(m3val);
  344.     if (m4val > 0) {
  345.         PutTitle(footer, curpag);
  346.         skip(m4val-1);
  347.         }
  348. }
  349.  
  350.  
  351. /* PutTitle - put out title line with optional pagenumber */
  352. PutTitle(line, pageno)
  353. char *line;
  354.  
  355. {
  356.     *line--;
  357.     while (*++line)
  358.         if (*line == PAGENUM)
  359.             printf("%3d", pageno);
  360.         else
  361.             putchar(*line);
  362. }
  363.  
  364.  
  365. /* skip - output n blank lines */
  366. skip(i)
  367.  
  368. {
  369.     while (i--)
  370.         putchar('\n');
  371. }
  372.  
  373.  
  374. LeadBlank(buf)
  375. char *buf;
  376.  
  377. {
  378.     char *temp;
  379.     int  i;
  380.  
  381.     temp = buf;
  382.     i = 0;
  383. /*
  384.     brk();
  385. */
  386.     while (*buf == ' ' || *buf == '\t') {
  387.         if (*buf++ == '\t')
  388.             i = (i & ~0x07) + 8;
  389.         else
  390.             i++;
  391.         }
  392.     if (*buf != '\n' && fill == NO)
  393.         tival = i;
  394.     while (*buf)
  395.         *temp++ = *buf++;
  396.     *temp = '\0';
  397. }
  398.  
  399.  
  400. GetWord(in, ii, out)
  401. char in[], *out;
  402. int  *ii;
  403.  
  404. {
  405.     int i;
  406.     char *p;
  407.  
  408.  
  409.     p = out;
  410.     i = *ii;
  411.     while (in[i] == ' ' || in[i] == '\t')
  412.         i++;
  413.     while (in[i] && !isspace(in[i]))
  414.         *out++ = in[i++];
  415.     *out = '\0';
  416.     *ii = i;
  417.     return(out - p);
  418. }
  419.  
  420.  
  421. PutWord(wrdbuf)
  422. char *wrdbuf;
  423.  
  424. {
  425.     int last, llval, nextra, w;
  426.  
  427.     w = width(wrdbuf);
  428.     last = strlen(wrdbuf) + outp + 1;
  429.     llval = rmval - tival;
  430.     if (outp > 0 && (outw + w > llval || last >= MAXOUT)) {
  431.         last -= outp;
  432.         nextra = llval - outp + 1;
  433.         spread(outbuf, outp, nextra, outwds);
  434.         if (nextra > 0 && outwds > 1)
  435.             outp += nextra;
  436.         brk();
  437.         }
  438.     strcpy(outbuf+outp+1, wrdbuf);
  439.     outp = last;
  440.     outbuf[outp] = BLANK;
  441.     outw += w + 1;
  442.     outwds++;
  443. }
  444.  
  445.  
  446. /* brk - end current filled line */
  447. brk()
  448.  
  449. {
  450.     if (outp > 0) {
  451.         outbuf[outp] = '\n';
  452.         outbuf[outp+1] = '\0';
  453.         put(outbuf+1);
  454.         }
  455.     outp = 0;
  456.     outw = 0;
  457.     outwds = 0;
  458. }
  459.  
  460.  
  461. /* width - compute width of character string */
  462. width(buf)
  463. char *buf;
  464.  
  465. {
  466.     int w;
  467.  
  468.     w = 0;
  469.     for ( ;*buf != EOS; *buf++)
  470.         if (*buf == BACKSPACE)
  471.             w--;
  472.         else if (*buf != '\n')
  473.             w++;
  474.     return(w);
  475. }
  476.  
  477.  
  478. /* spread - spread words to justify  right margin */
  479. spread(buf, outp, nextra, outwds)
  480. char *buf;
  481.  
  482. {
  483.     int i, j, nb, ne, nholes;
  484.  
  485.     if (nextra <= 0 || outwds <= 1)
  486.         return;
  487.     dir = 1 - dir;
  488.     ne = nextra;
  489.     nholes = outwds - 1;
  490.     i = outp - 1;
  491.     j = min(MAXOUT-2, i + ne);
  492.     while (i < j) {
  493.         buf[j] = buf[i];
  494.         if (buf[i] == ' ') {
  495.             if (dir == 0)
  496.                 nb = (ne - 1) / nholes + 1;
  497.             else
  498.                 nb = ne / nholes;
  499.             ne = ne - nb;
  500.             nholes = nholes - 1;
  501.             for (; nb > 0; nb--) {
  502.                 j--;
  503.                 buf[j] = ' ';
  504.                 }
  505.             }
  506.         i--;
  507.         j--;
  508.         }
  509.     return;
  510. }
  511.  
  512.  
  513. GetTitle(line, title)
  514. char *line, *title;
  515.  
  516. {
  517.     while (!isspace(*line)) line++;
  518.     while (*line == ' ' || *line == '\t') line++;
  519.     if (*line == SQUOTE || *line == DQUOTE)
  520.         line++;
  521.     strcpy(title, line);
  522. }
  523.  
  524.  
  525. init()
  526.  
  527. {
  528.     fill  = YES;    /* fill if YES; init = YES            */
  529.     lsval = 1;    /* current line spacing; init = 1        */
  530.     inval = 0;    /* current indent; >= 0; init = 0        */
  531.     rmval = 60;    /* current right margin; init = PAGEWIDTH = 60    */
  532.     tival = 0;    /* current temporary indent; init = 0        */
  533.     ceval = 0;    /* # of lines to center; init = 0        */
  534.     ulval = 0;    /* # of lines to underline; init = 0        */
  535.     curpag = 0;
  536.     newpag = 1;
  537.     lineno = 0;
  538.     plval  = 66;
  539.  
  540.     m1val  = 2;
  541.     m2val  = 1;
  542.     m3val  = 1;
  543.     m4val  = 2;
  544.     bottom = plval - m3val - m4val;
  545.     header = __header;
  546.     *header++ = '\n';  *header-- = '\0';
  547.     footer = __footer;
  548.     *footer++ = '\n';  *footer-- = '\0';
  549.  
  550.     outp = 0;
  551.     outw = 0;
  552.     outwds = 0;
  553.     dir = 0;
  554. }
  555.  
  556.