home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d197 / nro.lha / Nro / nrotxt.c < prev    next >
C/C++ Source or Header  |  1989-03-28  |  23KB  |  950 lines

  1. /*
  2.  *      Text processing portion of NRO word processor
  3.  *
  4.  *      Originally by Stephen L. Browning, 5723 North Parker Avenue
  5.  *      Indianapolis, Indiana 46220
  6.  *
  7.  *      Transformed beyond immediate recognition, and
  8.  *      adapted for Amiga by Olaf Seibert, KosmoSoft
  9.  *
  10.  *      Vossendijk 149-1 (study)   Beek 5 (home)
  11.  *      5634 TN  Nijmegen          5815 CS  Merselo
  12.  *      The Netherlands            The Netherlands
  13.  *      Phone:
  14.  *             (...-31)80561045     (...-31)4786205
  15.  *          or 080-561045           04786-205
  16.  *
  17.  *      This program is NOT in the public domain. It may, however
  18.  *      be distributed only at no charge, and this notice must be
  19.  *      included unaltered.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include "nro.h"
  24. #include "nroxtrn.h"
  25.  
  26. text(from, infile)
  27. register uchar *from;
  28. register FILE *infile;
  29. {
  30.         register short more;
  31.  
  32.         /*
  33.          * text() Is being called with the first letter of an input line
  34.          * already in the buffer.
  35.          */
  36.  
  37.         if (*from == ' ' || iseol(*from))
  38.                 leadbl(from, infile);
  39.         else
  40.                 putbak(*from);
  41.  
  42.         if (iseol(*from)) put(from); /* All blank line */
  43.         else if (env.fill == NO)        unfilled(infile);
  44.         else {
  45.                 more = getwrd(from, infile);
  46.                 while (more > 0) {
  47.                         putwrd(from);
  48.                         more = getwrd(from, infile);
  49.                 }
  50.                 if (more != EOF) putwrd(from);
  51.         }
  52.  
  53.         /* Reached end of input line */
  54.  
  55.         if (env.ceval > 0)      --env.ceval;
  56.         if (env.ulval > 0)      if (--env.ulval == 0)   env.reqmode &= ~FXUL;
  57.         if (env.cuval > 0)      if (--env.cuval == 0)   env.reqmode &= ~FXUL;
  58.         if (env.boval > 0)      if (--env.boval == 0)   env.reqmode &= ~FXBO;
  59.         if (env.itval > 0)      if (--env.itval == 0)   env.reqmode &= ~FXIT;
  60. }
  61.  
  62.  
  63.  
  64. /*
  65.  *      delete leading blanks, set tival
  66.  */
  67.  
  68. leadbl(p, infile)
  69. uchar *p;
  70. FILE *infile;
  71. {
  72.         int i = 0;
  73.         register uchar chr = *p;
  74.  
  75.         dobrk();
  76.  
  77.         while (chr == ' ') {
  78.                 chr = ngetc(infile);
  79.                 i++;
  80.         }
  81.         *p = chr;
  82.  
  83.         if (isnteol(chr)) {
  84.                 env.tival += i;
  85.                 putbak(chr);
  86.         } else p[1] = EOS;
  87. }
  88.  
  89.  
  90. /*
  91.  *      Get non-blank word from the input file.
  92.  *      Returns 1 if there is propably more text on the line,
  93.  *      EOF on end of file, and 0 otherwise.
  94.  */
  95.  
  96. getwrd(to, infile)
  97. register uchar *to;
  98. register FILE *infile;
  99. {
  100.         register int length;
  101.         register short chr;
  102.         uchar firstchr;
  103.         int more;
  104.  
  105.         chr = ngetc(infile);
  106.         if (chr == EOF) {
  107.                 *to = EOS;
  108.                 return EOF;
  109.         }
  110.         length = 0;
  111.  
  112.         /* Skip spaces, include tabs, but only at begin of word */
  113.  
  114.         while (chr == ' ')      chr = ngetc(infile);
  115.         firstchr = chr;
  116.  
  117.         more = TRUE; /* May I still accept more TABs ? */
  118.         while (chr != ' ' && isnteol(chr) && chr != EOF && length < MAXWORD-3) {
  119.                 if (chr != '\t') more = FALSE;
  120.                 else if (!more) break;
  121.                 *to++ = chr;
  122.                 length++;
  123.                 chr = ngetc(infile);
  124.         }
  125.  
  126.         if (iseol(chr)) more = FALSE;
  127.         else {
  128.                 more = TRUE;
  129.                 if (chr == '\t') putbak(chr);
  130.         }
  131.  
  132.         if (length > 0) {
  133.                 chr = *(to-1);
  134.                 if (chr == '"') chr = *(to-2);
  135.                 if (chr == '?' || chr == '!') {
  136.                         *to++ = ' ';
  137.                         ++length;
  138.                 }
  139.                 if (chr == '.' && (!more || islower(firstchr))) {
  140.                         *to++ = ' ';
  141.                         ++length;
  142.                 }
  143.         }
  144.         *to = EOS;
  145.         if (length >= MAXWORD-1) error("nro: word buffer overflow\n");
  146.  
  147.         return more;
  148. }
  149.  
  150.  
  151.  
  152. /*
  153.  *      Put word in output buffer
  154.  */
  155.  
  156. putwrd(wrdbuf)
  157. uchar *wrdbuf;
  158. {
  159.         uchar *from, *to;
  160.         int w, last, llval, nextra;
  161.         uchar temp[MAXWORD];
  162.  
  163.  
  164.         if ((w = strlen(wrdbuf)) == 0) return;
  165.         last = w + env.outp;
  166.         w = width(wrdbuf);
  167.  
  168.         llval = env.tmval - env.tival;
  169.         if ((env.outp > 0 && env.outw + w > llval) || last > MAXLINE-20) {
  170.  
  171.                 if (env.ceval != 0)     /* Centering overrides justification */
  172.                         /* Can't be done here since buffer not terminated */
  173.                         /* center(env.outbuf) */ ;
  174.                 else if (env.juval == YES) {
  175.                         nextra = llval - env.outw + 1;
  176.                         /*
  177.                          *      Delete trailing spaces and
  178.                          *      modify counts so that it is right justified.
  179.                          */
  180.                         if (env.outbuf[env.outp-2] == ' ') {
  181.                                 --env.outp;
  182.                                 ++nextra;
  183.                         }
  184.                         spread(env.outbuf, env.outp-1, nextra, env.outwds);
  185.                         if (env.outwds > 1)
  186.                                 env.outp += (nextra - 1);
  187.                 }
  188.                 env.dontbrk = FALSE;
  189.                 dobrk();        /* This also does a put() and may change modes */
  190.         }
  191.  
  192.         /* Do bold underline italics here */
  193.         env.curmode = doboitul(wrdbuf, temp, MAXWORD, env.curmode);
  194.         from = wrdbuf;
  195.         to = env.outbuf + env.outp;
  196.  
  197.         /* Append given word to the output buffer */
  198.         nextra = FALSE;
  199.         while (*from != EOS) {
  200.                 if (*from == '\t') {
  201.                         llval = 0;      /* Ouch, but we need pointer to INT */
  202.                         to = tabexp(env.outw, &llval, to);
  203.                         env.outw += llval;
  204.                         w--;
  205.                         from++;
  206.                         nextra = TRUE;  /* We have just expanded a tab */
  207.                 } else {
  208.                         *to++ = *from++;
  209.                 }
  210.         }
  211.         *to++ = ' ';
  212.         env.outw += w + 1;
  213.         env.outp = to - env.outbuf;
  214.         env.outwds++;
  215.  
  216.         if (nextra) {   /* Eliminate all preceding spaces */
  217.                 to--;           /* Don't touch the last appended space */
  218.                 while (to > env.outbuf) {
  219.                         if (*--to == ' ') *to = NBSP;
  220.                 }
  221.                 env.outwds = 1;
  222.         }
  223. }
  224.  
  225. /*
  226.  *      doboitul - Do bold, italics and underline
  227.  */
  228.  
  229. doboitul(from, via, size, curmode)
  230. uchar *from, *via;
  231. int size;
  232. short curmode;
  233. {
  234.         if (dc.bsflg == BSAMIGA) {
  235.                 return processfx(from, via, size, curmode);
  236.         } else {
  237.                 if (env.reqmode & FXBO)        bold(from, via, size);
  238.                 else if (env.reqmode & FXUL) underl(from, via, size);
  239.  
  240.                 return curmode;
  241.         }
  242. }
  243.  
  244.  
  245. /*
  246.  *      Insert bold face text in from using via
  247.  */
  248.  
  249. bold(from, via, size)
  250. register uchar *from, *via;
  251. register int size;
  252. {
  253.         register int i, j;
  254.         register uchar c;
  255.  
  256.         j = 0;
  257.         for (i=0; (c=from[i]) && c != '\n' && (j < size-1); i++) {
  258.                 if (isalnum(c)) {
  259.                         via[j++] = c;
  260.                         via[j++] = '\b';
  261.                 }
  262.                 via[j++] = c;
  263.         }
  264.         via[j++] = c;
  265.         via[j] = EOS;
  266.         while (*via != EOS) *from++ = *via++;
  267.         *from = EOS;
  268. }
  269.  
  270.  
  271.  
  272. /*
  273.  *      Underline a line from using buffer via
  274.  */
  275.  
  276. underl(from, via, size)
  277. register uchar *from, *via;
  278. register int size;
  279. {
  280.         register int i, j;
  281.         register uchar c;
  282.  
  283.         j = 0;
  284.         for (i=0; (c=from[i]) && c != '\n' && (j < size-1); i++) {
  285.                 /* if (c >= ' ' && c <= '~') */ /* Test superfluous */
  286.                 if (isalnum(c) || env.cuval > 0 && c!= ' ') {
  287.                         via[j++] = '_';
  288.                         via[j++] = '\b';
  289.                 }
  290.                 via[j++] = c;
  291.         }
  292.         via[j++] = c;
  293.         via[j] = EOS;
  294.         while (*via != EOS) *from++ = *via++;
  295.         *from = EOS;
  296. }
  297.  
  298.  
  299.  
  300. #define movecodes(index)\
  301.         for (cp=commseq[index]; commbyte = *cp++; ) from[j++] = commbyte;
  302.  
  303. /*
  304.  *      Do bold, underline and italics the Amiga way
  305.  */
  306.  
  307. short processfx(from, via, size, curmode)
  308. uchar *from, *via;
  309. int size;
  310. register short curmode;
  311. {
  312.         register short reqmode = env.reqmode;
  313.         register short tmpmode;
  314.         register int j;
  315.         register uchar c;
  316.         short cu = TRUE;
  317.         uchar *cp, commbyte;
  318.  
  319.         if (reqmode == FXPLAIN && curmode == FXPLAIN)
  320.                 return FXPLAIN;
  321.  
  322.         if (env.ulval > 0) {    /* Need we underline non-continuously? */
  323.                 cu = FALSE;
  324.         }
  325.  
  326.         strcpy(via, from);      /* Minimize amount to move */
  327.         j = 0;
  328.  
  329.         if (curmode & ~reqmode) {       /* Something too much active? */
  330.                 movecodes(FXPLAIN);     /* Cancel it! */
  331.                 curmode = FXPLAIN;
  332.         }
  333.  
  334.         while ( (c = *via++) && c != '\n' && (j < size-6) ) {
  335.                 if (isspace(c)) {       /* Spaces cancel underline */
  336.                         if (curmode & FXUL) {
  337.                                 movecodes(FXPLAIN);
  338.                                 curmode = FXPLAIN;
  339.                         }
  340.                 } else if (isalnum(c)) {/* Letgits set everything */
  341.                         if (curmode != reqmode) {
  342.                                 movecodes(reqmode & ~curmode);
  343.                                 curmode = reqmode;
  344.                         }
  345.                 } else {                /* Rest of characters are mixed */
  346.                         tmpmode = reqmode & ~FXBO;
  347.                         if (! cu) tmpmode = tmpmode & ~FXUL;
  348.  
  349.                         if (curmode & ~tmpmode) {
  350.                                 movecodes(FXPLAIN);
  351.                                 curmode = FXPLAIN;
  352.                         }
  353.                         if (curmode != tmpmode) {
  354.                                 movecodes(tmpmode & ~curmode);
  355.                                 curmode = tmpmode;
  356.                         }
  357.                 }
  358.                 from[j++] = c;
  359.         }
  360.         if (curmode & FXUL) {           /* Leave bold and italics on */
  361.                 movecodes(FXPLAIN);
  362.                 curmode = FXPLAIN;
  363.         }
  364.  
  365.         from[j++] = c;                  /* Append terminator */
  366.         from[j++] = EOS;                /* This may sometimes not be necessary */
  367.  
  368.         return curmode;
  369. }
  370.  
  371.  
  372. /*
  373.  *      tabexp - Expand a tab
  374.  *
  375.  *      Returns the pointer to the next free byte
  376.  */
  377.  
  378. uchar *tabexp(inwidth, outwidth, buffer)
  379. int inwidth;
  380. register int *outwidth;
  381. register uchar *buffer;
  382. {
  383.         int i, extra;
  384.  
  385.         /* Find the tab we need to go to */
  386.         inwidth += env.tival;
  387.         for (i=0; i<MAXTAB && env.tabstop[i] <= inwidth; i++) ;
  388.  
  389.         extra = env.tabstop[i];
  390.         if (extra >= env.tmval || i >= MAXTAB)
  391.                 extra = 0;
  392.         else
  393.                 extra -= inwidth;
  394.  
  395.         while (extra-- > 0) {
  396.                 *(buffer++) = NBSP;
  397.                 ++*outwidth;
  398.         }
  399.  
  400.         return buffer;
  401. }
  402.  
  403. /*
  404.  *      swmodes - switch printer modes
  405.  */
  406.  
  407. swmodes(modefrom, modeto)
  408. int modefrom, modeto;
  409. {
  410.         uchar commbyte;
  411.         uchar from[16];
  412.         uchar *cp;
  413.         int j = 0;
  414.  
  415.         if (modefrom & ~modeto) {
  416.                 movecodes(FXPLAIN);
  417.                 modefrom = FXPLAIN;
  418.         }
  419.         if (modefrom != modeto) {
  420.                 movecodes(modeto & ~modefrom);
  421.         }
  422.         from[j] = EOS;
  423.  
  424.         putlin(from, pout);
  425. }
  426.  
  427. #undef movecodes
  428.  
  429.  
  430. /*
  431.  *      unfilled - Copy input line without fill
  432.  */
  433.  
  434. unfilled(infile)
  435. register FILE *infile;
  436. {
  437.         uchar line[MAXLINE];
  438.         uchar temp[MAXLINE];
  439.         register uchar *linep = line;
  440.         register int chr;
  441.         int width = 0;
  442.  
  443.         while (width < MAXLINE-2 && (chr = ngetc(infile), isnteol(chr))) {
  444.                 if (chr == '\t') {
  445.                         linep = tabexp(width, &width, linep);
  446.                 } else if (chr == EOF) {
  447.                         break;
  448.                 } else {
  449.                         *linep++ = chr;
  450.                         width++;
  451.                 }
  452.         }
  453. #ifdef CPM
  454.         *linep++ = '\r';
  455. #endif
  456.         *linep++ = '\n';
  457.         *linep = EOS;
  458.  
  459.         if (env.ceval != 0)     /* Centering */
  460.                 center(line);
  461.         env.curmode = doboitul(line, temp, MAXLINE, env.expmode = dc.curmode);
  462.         put(line);
  463. }
  464.  
  465.  
  466.  
  467. /*
  468.  *      Center a line by incrementing tival
  469.  */
  470.  
  471. center(p)
  472. uchar *p;
  473. {
  474.         env.tival += max((env.tmval - env.tival - width(p) + 1) >> 1, 0);
  475. }
  476.  
  477.  
  478.  
  479. /*
  480.  *      Expand title buffer to include character string
  481.  */
  482.  
  483. expand(buffer, pgchr, string)
  484. uchar *buffer;
  485. uchar pgchr;
  486. uchar *string;
  487. {
  488.         uchar tmp[MAXLINE];
  489.         register uchar *from, *to, *tmpstr;
  490.  
  491.         from = buffer;
  492.         to = tmp;
  493.         while (*from != EOS) {
  494.                 if (*from == pgchr) {
  495.                         tmpstr = string;
  496.                         while (*tmpstr != EOS) *to++ = *tmpstr++;
  497.                 } else *to++ = *from;
  498.                 from++;
  499.         }
  500.         *to = EOS;
  501.         strcpy(buffer, tmp);    /* Copy it back */
  502. }
  503.  
  504.  
  505. /*
  506.  *      Get field from title
  507.  */
  508.  
  509. uchar *getfield(p, q, delim)
  510. uchar *p, *q;
  511. uchar delim;
  512. {
  513.         while (*p != delim && isnteol(*p) && *p != EOS) {
  514.                 *q++ = *p++;
  515.         }
  516.         *q = EOS;
  517.         if (*p == delim) p++;
  518.         return p;
  519. }
  520.  
  521.  
  522. /*
  523.  *      Convert integer to decimal ascii string
  524.  */
  525.  
  526. itoda(value, buffer)
  527. int value;
  528. uchar *buffer;
  529. {
  530.         if (env.pnflg == PNARABIC)
  531.                 sprintf(buffer, "%d", value);
  532.         else {
  533.                 buffer[0] = EOS;
  534.                 while (value >= 1000) { strcat(buffer, "m" ); value -= 1000; }
  535.                 if    (value >= 400 ) { strcat(buffer, "cd"); value -= 400;  }
  536.                 while (value >= 100 ) { strcat(buffer, "c" ); value -= 100;  }
  537.                 if    (value >= 90  ) { strcat(buffer, "xc"); value -= 90;   }
  538.                 if    (value >= 50  ) { strcat(buffer, "l" ); value -= 50;   }
  539.                 if    (value >= 40  ) { strcat(buffer, "xl"); value -= 40;   }
  540.                 while (value >= 10  ) { strcat(buffer, "x" ); value -= 10;   }
  541.                 if    (value >= 9   ) { strcat(buffer, "ix"); value -= 9;    }
  542.                 if    (value >= 5   ) { strcat(buffer, "v" ); value -= 5;    }
  543.                 if    (value >= 4   ) { strcat(buffer, "iv"); value -= 4;    }
  544.                 while (value--)         strcat(buffer, "i");
  545.  
  546.                 if (env.pnflg == PNUROMAN)      strupper (buffer);
  547.         }
  548. }
  549.  
  550. /*
  551.  *      strupper - Convert string to upper case
  552.  */
  553.  
  554. strupper(string)
  555. register uchar *string;
  556. {
  557.         for ( ; *string != EOS; string++) {
  558.                 if (islower(*string))
  559.                         *string = toupper(*string);
  560.         }
  561. }
  562.  
  563.  
  564. /*
  565.  *      Center title text into print buffer
  566.  */
  567.  
  568. justcntr(p, q, limit)
  569. uchar *p, *q;
  570. int limit[];
  571. {
  572.         int len;
  573.  
  574.         len = width(p);
  575.         q = &q[(limit[RIGHT] + limit[LEFT] - len) >> 1];
  576.         while (*p != EOS) *q++ = *p++;
  577. }
  578.  
  579.  
  580.  
  581. /*
  582.  *      Left justify title text into print buffer
  583.  */
  584.  
  585. justleft(from, to, limit)
  586. uchar *from, *to;
  587. int limit;
  588. {
  589.         to = &to[limit];
  590.         while (*from != EOS) *to++ = *from++;
  591. }
  592.  
  593.  
  594. /*
  595.  *      Right justify title text into print buffer
  596.  */
  597.  
  598. justrite(from, to, limit)
  599. uchar *from, *to;
  600. int limit;
  601. {
  602.         int len;
  603.  
  604.         len = width(from);
  605.         to = &to[limit - len];
  606.         while (*from != EOS) *to++ = *from++;
  607. }
  608.  
  609.  
  610.  
  611.  
  612. /*
  613.  *      Find minimum of two integers
  614.  */
  615.  
  616. int min(v1, v2)
  617. int v1, v2;
  618. {
  619.         return (v1 < v2) ? v1 : v2;
  620. }
  621.  
  622.  
  623.  
  624. /*
  625.  *      Find maximum of two integers
  626.  */
  627.  
  628. int max(v1, v2)
  629. int v1, v2;
  630. {
  631.         return (v1 > v2) ? v1 : v2;
  632. }
  633.  
  634.  
  635.  
  636. /*
  637.  *      Find absolute of a value
  638.  */
  639.  
  640. abs(foo)
  641. int foo;
  642. {
  643.         return (foo >= 0) ? foo : -foo;
  644. }
  645.  
  646.  
  647.  
  648. /*
  649.  *      Put out page footer
  650.  */
  651.  
  652. pfoot()
  653. {
  654.         if (pg.prflg) {
  655.                 skip(pg.m3val);
  656.                 if (pg.m4val > 0) {
  657.                         if ((pg.curpag % 2) == 0) {
  658.                                 puttl(pg.efoot, pg.eflim, pg.curpag);
  659.                         } else {
  660.                                 puttl(pg.ofoot, pg.oflim, pg.curpag);
  661.                         }
  662.                         skip(pg.m4val - 1);
  663.                 }
  664.         }
  665. }
  666.  
  667.  
  668.  
  669. /*
  670.  *      Put out page header
  671.  */
  672.  
  673. phead()
  674. {
  675.         pg.curpag = pg.newpag;
  676.         if (pg.curpag >= pg.frstpg && pg.curpag <= pg.lastpg) {
  677.                 pg.prflg = TRUE;
  678.         } else {
  679.                 pg.prflg = FALSE;
  680.         }
  681.         ++pg.newpag;
  682.         if (pg.prflg) {
  683.                 if (pg.m1val > 0) {
  684.                         skip(pg.m1val - 1);
  685.                         if ((pg.curpag % 2) == 0) {
  686.                                 puttl(pg.ehead, pg.ehlim, pg.curpag);
  687.                         } else {
  688.                                 puttl(pg.ohead, pg.ohlim, pg.curpag);
  689.                         }
  690.                 }
  691.                 skip(pg.m2val);
  692.         }
  693.         /*
  694.          *              Initialize lineno for the next page
  695.          */
  696.         pg.lineno = pg.m1val + pg.m2val + 1;
  697. }
  698.  
  699.  
  700. /*
  701.  *      Print character with test for printer
  702.  */
  703.  
  704. #ifdef CPM
  705. prchar(c, fp)
  706. uchar c;
  707. FILE *fp;
  708. {
  709.         if (dc.lpr) {
  710.                 bdos(5, c);
  711.         } else {
  712.                 putc(c, fp);
  713.         }
  714. }
  715. #endif
  716.  
  717.  
  718.  
  719.  
  720. /*
  721.  *      Put out line with proper spacing and indenting
  722.  */
  723.  
  724. put(p)
  725. uchar *p;
  726. {
  727.         int j;
  728.         uchar os[MAXLINE];
  729.  
  730.         if (pg.lineno == 0 || pg.lineno > pg.bottom) {
  731.                 phead();
  732.         }
  733.         if (pg.prflg) {
  734.                 if (dc.bsflg == BSNO && strkovr(p, os)) {
  735.                         if (isnteol(os[0]))
  736.                                 for (j = pg.offset + env.tival; j; j--)
  737.                                         prchar(' ', pout);
  738.                         putlin(os, pout);
  739.                 }
  740.                 if (isnteol(*p))
  741.                         for (j = pg.offset + env.tival; j; j--)
  742.                                 prchar(' ', pout);
  743.  
  744.                 /* Is the expected mode at the beginning of the line */
  745.                 /* also the real current printer mode ?              */
  746.  
  747.                 if (env.expmode != dc.curmode)
  748.                         swmodes(dc.curmode, env.expmode);
  749.                 putlin(p, pout);
  750.  
  751.                 /* Update the mode at the end of the line */
  752.                 env.expmode = dc.curmode = env.curmode;
  753.         }
  754.  
  755.         env.tival = env.inval;
  756.         env.tmval = env.rmval;
  757.         skip(min(env.lsval-1, pg.bottom-pg.lineno));
  758.         pg.lineno = pg.lineno + env.lsval;
  759.  
  760.         if (pg.lineno > pg.bottom) pfoot();
  761. }
  762.  
  763.  
  764. /*
  765.  *      Output a null terminated string to the file
  766.  *      specified by pbuf.
  767.  */
  768.  
  769. #ifndef putlin
  770.  
  771. putlin(p, prfile)
  772. register uchar *p;
  773. register FILE *prfile;
  774. {
  775.         register uchar chr;
  776.  
  777.         while ((chr = *p++) != EOS) prchar(chr, prfile);
  778. }
  779.  
  780. #endif
  781.  
  782.  
  783. /*
  784.  *      Put out title or footer
  785.  */
  786.  
  787. puttl(p, lim, pgno)
  788. uchar *p;
  789. int lim[];
  790. int pgno;
  791. {
  792.         int i;
  793.         uchar pn[8];
  794.         uchar delim;
  795.         uchar t[MAXLINE];
  796.         uchar h[MAXLINE];
  797.  
  798.         itoda(pgno, pn);
  799.  
  800.         for (i=0; i<MAXLINE; i++) h[i] = ' ';
  801.  
  802.         delim = *p++;
  803.         p = getfield(p, t, delim);
  804.         expand(t, env.pgchr, pn);
  805.         justleft(t, h, lim[LEFT]);
  806.  
  807.         p = getfield(p, t, delim);
  808.         expand(t, env.pgchr, pn);
  809.         justcntr(t, h, lim);
  810.  
  811.         p = getfield(p, t, delim);
  812.         expand(t, env.pgchr, pn);
  813.         justrite(t, h, lim[RIGHT]);
  814.  
  815.         for (i=MAXLINE-4; h[i] == ' '; --i) h[i] = EOS;
  816.         h[++i] = '\n';
  817. #ifdef CPM
  818.         h[++i] = '\r';
  819. #endif
  820.         h[++i] = EOS;
  821.         if (i > 1) {    /* strlen(h) */
  822.                 for (i=0; i<pg.offset; i++) prchar(' ', pout);
  823.         }
  824.         if (dc.curmode != FXPLAIN) {    /* Cancel special effx */
  825.                 putlin(commseq[FXPLAIN], pout);
  826.                 dc.curmode = /* env.curmode = */ FXPLAIN;
  827.         }
  828.         putlin(h, pout);
  829. }
  830.  
  831.  
  832. /*
  833.  *      Skips the number of lines specified by n.
  834.  */
  835.  
  836. skip(n)
  837. register int n;
  838. {
  839.         register int i;
  840.  
  841.         if (n > 0 && pg.prflg) {
  842.                 for (i=0; i<n; i++) {
  843.                         prchar('\n', pout);
  844.                 }
  845.         }
  846. }
  847.  
  848.  
  849.  
  850. /*
  851.  *      Spread words to justify right margin
  852.  */
  853.  
  854. spread(p, outp, nextra, outwds)
  855. uchar p[];
  856. int outp, nextra, outwds;
  857. {
  858.         register int from, to;
  859.         register int nblanks, needed, nholes;
  860.  
  861.         if ((nextra <= 0) || (outwds <= 1)) return;
  862.         env.sprdir = !env.sprdir;
  863.         needed = nextra;
  864.         nholes = outwds - 1;            /* Holes between words */
  865.         from = outp - 1;                /* Last non-blank character */
  866.         to = min(MAXLINE-2, from+needed); /* Leave room for LF, EOS  */
  867.  
  868.         /* Walk over the line from right to left */
  869.         while (from < to) { /* as long as we need insert more spaces */
  870.                 p[to] = p[from];
  871.                 if (p[from] == ' ') {   /* Aha. Need to insert spaces here */
  872.                         if (env.sprdir == 0) nblanks = (needed - 1)/ nholes + 1;
  873.                         else                nblanks =  needed     / nholes;
  874.                         needed -= nblanks;
  875.                         --nholes;
  876.                         for (; nblanks>0; --nblanks) {
  877.                                 /* --to; */
  878.                                 p[--to] = ' ';
  879.                         }
  880.                 }
  881.                 --from;
  882.                 --to;
  883.         }
  884. }
  885.  
  886.  
  887.  
  888. /*
  889.  *      Split overstrikes (backspaces) into seperate buffer
  890.  */
  891.  
  892. strkovr(from, aux)
  893. register uchar *from, *aux;
  894. {
  895.         register uchar *to;             /* Pointer back in original buffer      */
  896.         uchar *beginaux = aux;
  897.         int bsflg;
  898.  
  899.         bsflg = FALSE;
  900.         to = from;
  901.  
  902.         while (*from != EOS) {
  903.                 *aux = ' ';             /* First, assume no action necessary */
  904.                 *to = *from;            /* Copy current character */
  905.                 from++;
  906.                 if (*from == '\b') {    /* Oh, we need to do some work */
  907.                         if (*to >= ' ' && *to <= '~') {
  908.                                 bsflg = TRUE;
  909.                                 *aux = *to;     /* Put overstruck 1st character in aux */
  910.                                 from++;
  911.                                 *to = *from;/* Put second character in orig. buffer */
  912.                                 from++;
  913.                         }
  914.                 }
  915.                 aux++;
  916.                 to++;
  917.         }
  918.  
  919.         if (bsflg) {                    /* Eliminate trailing spaces */
  920.                 while (aux[-1] == ' ' && aux > beginaux) aux--;
  921.                 *aux++ = '\r';
  922.                 if (aux <= beginaux+1)
  923.                         bsflg = FALSE;  /* Maybe nothing is left in the buffer! */
  924.         }
  925.         *aux = *to = EOS;
  926.  
  927.         return bsflg;
  928. }
  929.  
  930.  
  931. /*
  932.  *      Compute width of character string
  933.  */
  934.  
  935. width(s)
  936. register uchar *s;
  937. {
  938.         int w;
  939.  
  940.         w = 0;
  941.         while (*s != EOS) {
  942.                 if (*s == '\b') --w;
  943.                 else if ((*s & 0x7F) == ESC) {  /* Eat escape sequences */
  944.                         while (*++s <= '@');
  945.                 } else if (isnteol(*s)) w++;
  946.                 ++s;
  947.         }
  948.         return w;
  949. }
  950.