/* * NROFF clone for the PC. * * This program was taken from the SIMTEL archive. To reduce the number * of files in my collection, I have removed files which were either * irrevalent or easily recreatable. I also combined several smaller * separate files into single larger ones. I have left the individual * file headings intact should you wish to recreate the originals, * however the program will compile "as is". - Dave Dunfield * * Compile command: cc nro -fop * --- The original READ.ME file follows --- This is nro, an implementation of nroff for the PC. A man page is included, which contains the instructions for use of nro. To produce the manual page from the file nro.nro, the command is: nro -man nro.nro >nro.man where the files "an." and "nro.nro" are in the current directory. I have used it to process man pages for various unix-like packages on the pc. Sometimes it won't handle certain commands used in more sophisticated documents, particularly if they were formatted for troff. Also, the use of .. to indicate end-of-macro is not supported. (It uses .en). This version was originally written for Computer Innovations C88 (I think) under DOS 1.x. The sources were obtained from wuarchive.wustl.edu. I have ported it to MS C 5.1. It is compiled under the small model. I have included a makefile for ndmake. I have not tested it very well, assuming that the original version worked as expected. Apparently it was taken from the Software Tools book by Kernighan and Plaugher and is supposed to implement the Unix V7 nroff capabilities. Files: NRO NRO Unformatted man page SKELETON NRO "Standard" man page skeleton AN Standard macro file for formatting man pages NRO H Source for main header file NRO C Source for main program ;DD These files have been deleted from the original distribution :MAKEFILE Make file for ndmake :NRO MAN Formatted man page :NRO EXE Executable nro program ;DD These files were combined into the others ;NROXTRN H Source header file for externals ;NROCMD C Source for routines to handle formatting commands ;NROTXT C Source for routines to format text John Dudeck jdudeck@polyslo.calpoly.edu December 7, 1990 */ /* * NRO.C: Word Processor * similar to Unix NROFF or RSX-11M RNO - adaptation of text processor * given in "Software Tools", Kernighan and Plauger. * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * Ported to MS C 5.1 by John Dudeck (jdudeck@polyslo.calpoly.edu) 11/25/90. */ #include #define EXTERN #include "nro.h" main(argc,argv) int argc; char *argv[]; { int i; int swflg; swflg = FALSE; setbuf(pout = stdout, 512); /* Increase output efficency */ init(); for (i=1; ioutfile]\n"); exit(-1); } } /* * retrieve one line of input text */ getlin(p,in_buf) char *p; FILE *in_buf; { int i; int c; char *q; q = p; for (i=0; i= &mac.pbb[0]) { c = *mac.ppb--; } else { c = getc(infp); } return(c); } /* * process input files from command line */ profile() { char ibuf[MAXLINE]; for (dc.flevel=0; dc.flevel>=0; --dc.flevel) { while (getlin(ibuf,sofile[dc.flevel]) != EOF) { if (ibuf[0] == dc.cmdchr) comand(ibuf); else text(ibuf); } if (dc.flevel > 0) fclose(sofile[dc.flevel]); } if (pg.lineno > 0) space(HUGE); } /* * process switch values from command line */ pswitch(p,q) char *p; int *q; { int swgood; swgood = TRUE; if (*p == '-') { p++; switch (tolower(*p)) { case 'b': dc.bsflg = TRUE; break; case 'm': p++; if ((sofile[0] = fopen(p,"r")) == NULL) { printf("***nro: unable to open file %s\n",p); exit(-1); } profile(); fclose(sofile[0]); break; case 'p': p++; set(&pg.offset,ctod(p),'1',0,0,HUGE); break; case 'u': dc.buflg = TRUE; break; case 'v': printf("NRO version 1.01 JRD 11/25/90\n"); *q = TRUE; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pg.lastpg = ctod(p); break; default: swgood = FALSE; break; } } else if (*p == '+') { p++; pg.frstpg = ctod(p); } else { swgood = FALSE; } if (swgood == FALSE) { printf("nro: illegal switch %s\n",p); return(ERR); } return(OK); } /* * NROCMD.C: Command processor for NRO text processor * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * Ported to MS C 5.1 by John Dudeck (jdudeck@polyslo.calpoly.edu) 11/25/90. */ /* #include #include "nro.h" */ char *skipbl(); char *skipwd(); comand(p) char *p; { int ct, val; int spval; int index; char argtyp; char name[MAXLINE]; char macexp[MXMLEN]; ct = comtyp(p,macexp); if (ct == UNKNOWN) { printf("*** nro: unrecognized command %s\n",p); return; } expesc(p,name); val = getval(p,&argtyp); switch (ct) { case BO: /* bold face */ set(&dc.boval,val,argtyp,1,0,HUGE); dc.cuval = dc.ulval = 0; break; case BP: /* begin page */ if(pg.lineno > 0) space(HUGE); set(&pg.curpag,val,argtyp,pg.curpag+1,-HUGE,HUGE); pg.newpag = pg.curpag; break; case BR: /* break */ brk(); break; case BS: /* backspaces in output */ set(&dc.bsflg,val,argtyp,1,0,1); break; case CC: /* command character */ if (argtyp == '\r' || argtyp == '\n') dc.cmdchr = '.'; else dc.cmdchr = argtyp; break; case CE: /* center */ brk(); set(&dc.ceval,val,argtyp,1,0,HUGE); break; case CU: /* continuous underline */ set(&dc.cuval,val,argtyp,1,0,HUGE); dc.ulval = dc.boval = 0; break; case DE: /* define macro */ defmac(p,sofile[dc.flevel]); break; case EF: /* even footer */ gettl(p,pg.efoot,&pg.eflim[0]); break; case EH: /* even header */ gettl(p,pg.ehead,&pg.ehlim[0]); break; case EN: /* end macro definition */ puts("***nro: missing .de command\n"); break; case FI: /* fill */ brk(); dc.fill = YES; break; case FO: /* footer */ gettl(p,pg.efoot,&pg.eflim[0]); gettl(p,pg.ofoot,&pg.oflim[0]); break; case HE: /* header */ gettl(p,pg.ehead,&pg.ehlim[0]); gettl(p,pg.ohead,&pg.ohlim[0]); break; case IN: /* indenting */ set(&dc.inval,val,argtyp,0,0,dc.rmval-1); dc.tival = dc.inval; break; case JU: /* justify */ dc.juval = YES; break; case LS: /* line spacing */ set(&dc.lsval,val,argtyp,1,1,HUGE); break; case M1: /* set topmost margin */ set(&pg.m1val,val,argtyp,2,0,HUGE); break; case M2: /* set second top margin */ set(&pg.m2val,val,argtyp,2,0,HUGE); break; case M3: /* set first bottom margin */ set(&pg.m3val,val,argtyp,2,0,HUGE); pg.bottom = pg.plval - pg.m4val - pg.m3val; break; case M4: /* set bottom-most margin */ set(&pg.m4val,val,argtyp,2,0,HUGE); pg.bottom = pg.plval - pg.m4val - pg.m3val; break; case MACRO: /* macro expansion */ maceval(p,macexp); break; case NE: /* need n lines */ brk(); if ((pg.bottom-pg.lineno+1) < (val*dc.lsval)) { space(HUGE); } break; case NF: /* no fill */ brk(); dc.fill = NO; break; case NJ: /* no justify */ dc.juval = NO; break; case NR: /* set number register */ p = skipwd(p); p = skipbl(p); if (!isalpha(*p)) { puts("***nro: invalid or missing number register name\n"); } else { index = tolower(*p) - 'a'; p = skipwd(p); val = getval(p,&argtyp); set(&dc.nr[index],val,argtyp,0,-HUGE,HUGE); } break; case OF: /* odd footer */ gettl(p,pg.ofoot,&pg.oflim[0]); break; case OH: /* odd header */ gettl(p,pg.ohead,&pg.ohlim[0]); break; case PC: /* page number character */ if (argtyp == '\r' || argtyp == '\n') dc.pgchr = EOS; else dc.pgchr = argtyp; break; case PL: /* page length */ set(&pg.plval,val,argtyp,PAGELEN, pg.m1val+pg.m2val+pg.m3val+pg.m4val+1,HUGE); pg.bottom = pg.plval - pg.m3val - pg.m4val; break; case PO: /* page offset */ set(&pg.offset,val,argtyp,0,0,HUGE); break; case RM: /* right margin */ set(&dc.rmval,val,argtyp,PAGEWIDTH,dc.tival+1,HUGE); break; case SO: /* source file */ p = skipwd(p); p = skipbl(p); if (getwrd(p,name) == 0) break; if (dc.flevel+1 >= NFILES) { puts("***nro: .so commands nested too deeply\n"); exit(-1); } if ((sofile[dc.flevel+1] = fopen(name,"r")) == NULL) { printf("***nro: unable to open %s\n",name); exit(-1); } ++dc.flevel; break; case SP: /* space */ set(&spval,val,argtyp,1,0,HUGE); space(spval); break; case TI: /* temporary indent */ brk(); set(&dc.tival,val,argtyp,0,0,dc.rmval); break; case UL: /* underline */ set(&dc.ulval,val,argtyp,0,1,HUGE); dc.cuval = dc.boval = 0; break; } } /* * convert ascii character to decimal. */ atod(c) char c; { return(((c < '0') || (c > '9')) ? -1 : c-'0'); } /* * end current filled line */ brk() { if(co.outp > 0) { /* co.outbuf[co.outp] = '\r'; co.outbuf[co.outp + 1] = '\n'; co.outbuf[co.outp + 2] = EOS; */ co.outbuf[co.outp] = '\n'; co.outbuf[co.outp + 1] = EOS; put(co.outbuf); } co.outp = 0; co.outw = 0; co.outwds = 0; } /* * Collect macro definition from input stream */ colmac(p,d,i) char *p, d[]; int i; { while (*p != EOS) { if (i >= MXMLEN-1) { d[i-1] = EOS; return(ERR); } d[i++] = *p++; } d[i] = EOS; return(i); } /* * decodes nro command and returns its associated * value. */ comtyp(p,m) char *p; char *m; { char c1, c2; char macnam[MNLEN]; char *s; p++; /* * First check to see if the command is a macro. * If it is, truncate to two characters and return * expansion in m. Note that upper and lower case * characters are handled differently for macro names, * but not for normal command names. */ getwrd(p,macnam); macnam[2] = EOS; if ((s = getmac(macnam)) != NULL) { strcpy(m,s); return(MACRO); } c1 = tolower(*p); p++; c2 = tolower(*p); if (c1 == 'b' && c2 == 'o') return(BO); if (c1 == 'b' && c2 == 'p') return(BP); if (c1 == 'b' && c2 == 'r') return(BR); if (c1 == 'b' && c2 == 's') return(BS); if (c1 == 'c' && c2 == 'c') return(CC); if (c1 == 'c' && c2 == 'e') return(CE); if (c1 == 'c' && c2 == 'u') return(CU); if (c1 == 'd' && c2 == 'e') return(DE); if (c1 == 'e' && c2 == 'f') return(EF); if (c1 == 'e' && c2 == 'h') return(EH); if (c1 == 'e' && c2 == 'n') return(EN); if (c1 == 'f' && c2 == 'i') return(FI); if (c1 == 'f' && c2 == 'o') return(FO); if (c1 == 'h' && c2 == 'e') return(HE); if (c1 == 'i' && c2 == 'n') return(IN); if (c1 == 'j' && c2 == 'u') return(JU); if (c1 == 'l' && c2 == 's') return(LS); if (c1 == 'm' && c2 == '1') return(M1); if (c1 == 'm' && c2 == '2') return(M2); if (c1 == 'm' && c2 == '3') return(M3); if (c1 == 'm' && c2 == '4') return(M4); if (c1 == 'n' && c2 == 'e') return(NE); if (c1 == 'n' && c2 == 'f') return(NF); if (c1 == 'n' && c2 == 'j') return(NJ); if (c1 == 'n' && c2 == 'r') return(NR); if (c1 == 'o' && c2 == 'f') return(OF); if (c1 == 'o' && c2 == 'h') return(OH); if (c1 == 'p' && c2 == 'c') return(PC); if (c1 == 'p' && c2 == 'l') return(PL); if (c1 == 'p' && c2 == 'o') return(PO); if (c1 == 'r' && c2 == 'm') return(RM); if (c1 == 's' && c2 == 'o') return(SO); if (c1 == 's' && c2 == 'p') return(SP); if (c1 == 't' && c2 == 'i') return(TI); if (c1 == 'u' && c2 == 'l') return(UL); return(UNKNOWN); } /* * convert string to decimal. * processes only positive values. */ ctod(p) char *p; { int val, d; val = 0; while(*p != EOS) { d = atod(*p); p++; if(d == -1) return(val); val = 10 * val + d; } return(val); } /* * Define a macro */ defmac(p,infp) char *p; FILE *infp; { int i; char name[MNLEN]; char defn[MXMLEN]; char *q; q = skipwd(p); q = skipbl(q); i = getwrd(q,name); if (!isalpha(*name)) { puts("***nro: missing or illegal macro definition name\n"); exit(-1); } if (i > 2) name[2] = EOS; i = 0; while (getlin(p,infp) != EOF) { if (p[0] == dc.cmdchr && tolower(p[1]) == 'e' && tolower(p[2]) == 'n') { break; } if ((i = colmac(p,defn,i)) == ERR) { puts("***nro: macro definition too long\n"); exit(-1); } } if (putmac(name,defn) == ERR) { puts("***nro: macro definition table full\n"); exit(-1); } } /* * Expand escape sequences */ expesc(p,q) char *p; char *q; { char *s, *t; s = p; t = q; while (*s != EOS) { if (*s != '@') { *t++ = *s++; } else if (*(s+1) == '@') { *t++ = *s++; ++s; } else if (tolower(*(s+1)) == 'n' && isalpha(*(s+2))) { s += 2; t += itoda(dc.nr[tolower(*s)-'a'],t,6) - 1; ++s; } else { *t++ = *s++; } } *t = EOS; strcpy(p,q); } /* * Get macro definition from table */ char *getmac(name) char *name; { int i; for (i = mac.lastp; i >= 0; --i) { if (!strcmp(name,mac.mnames[i])) { return(mac.mnames[i] + 3); } } return(NULL); } /* * get header or footer title */ gettl(p,q,limit) char *p; char *q; int limit[]; { p = skipwd(p); p = skipbl(p); strcpy(q,p); limit[LEFT] = dc.inval; limit[RIGHT] = dc.rmval; } /* * retrieves optional argument following nro command. * returns positive integer value with sign (if any) * saved in character addressed by p_argt. */ getval(p,p_argt) char *p; char *p_argt; { p = skipwd(p); p = skipbl(p); *p_argt = *p; if((*p == '+') || (*p == '-')) ++p; return(ctod(p)); } /* * Evaluate macro expansion */ maceval(p,m) char *p; char m[]; { int i; char *argp[10]; char c; *p++ = EOS; /* replace command char with EOS */ /* * initialize argp array to substitute command * string for any undefined argument */ for (i=0; i<10; ++i) argp[i] = p; p = skipwd(p); *p++ = EOS; for (i=0; i<10; ++i) { p = skipbl(p); if (*p == '\r' || *p == '\n' || *p == EOS) break; if (*p == '\'' || *p == '"') { c = *p++; argp[i] = p; while (*p != c && *p != '\r' && *p != '\n' && *p != EOS) ++p; *p++ = EOS; } else { argp[i] = p; p = skipwd(p); *p++ = EOS; } } for (i=strlen(m)-1; i>=0; --i) { if (i > 0 && m[i-1] == '$') { if (!isdigit(m[i])) { putbak(m[i]); } else { pbstr(argp[m[i]-'0']); --i; } } else { putbak(m[i]); } } } /* * Push back string into input stream */ pbstr(p) char p[]; { int i; for (i=strlen(p)-1; i>=0; --i) { putbak(p[i]); } } /* * Push character back into input stream */ putbak(c) char c; { if (mac.ppb < &mac.pbb[0]) { mac.ppb = &mac.pbb[0]; *mac.ppb = c; } else { if (mac.ppb >= &mac.pbb[MAXLINE-1]) { puts("***nro: push back buffer overflow\n"); exit(-1); } *++mac.ppb = c; } } /* * Put macro definition into table */ putmac(name,p) char *name; char *p; { if (mac.lastp >= MXMDEF) return(ERR); if (mac.emb + strlen(name) + strlen(p) + 1 > &mac.mb[MACBUF]) { return(ERR); } ++mac.lastp; mac.mnames[mac.lastp] = mac.emb; strcpy(mac.emb,name); strcpy(mac.emb + strlen(name) + 1,p); mac.emb += strlen(name) + strlen(p) + 2; return(OK); } /* * set parameter and check range */ set(param,val,type,defval,minval,maxval) int *param; int val; char type; int defval,minval,maxval; { switch(type) { case '\r': case '\n': *param = defval; break; case '+': *param += val; break; case '-': *param -= val; break; default: *param = val; break; } *param = min(*param,maxval); *param = max(*param,minval); } /* * skip blanks and tabs in character buffer. * return number of characters skipped. */ char *skipbl(p) char *p; { while (*p == ' ' || *p == '\t') ++p; return(p); } /* * skip over word and punctuation */ char *skipwd(p) char *p; { while (*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != EOS) ++p; return(p); } /* * space vertically n lines */ space(n) int n; { brk(); if (pg.lineno > pg.bottom) return; if (pg.lineno == 0) phead(); skip(min(n,pg.bottom+1-pg.lineno)); pg.lineno += n; if (pg.lineno > pg.bottom) pfoot(); } /* * NROTXT.C: Text processing portion of NRO word processor * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * Ported to MS C 5.1 by John Dudeck (jdudeck@polyslo.calpoly.edu) 11/25/90. */ /* #include #include "nro.h" */ text(p) char *p; { int i; char wrdbuf[MAXLINE]; if (*p == ' ' || *p == '\n' || *p == '\r') leadbl(p); expesc(p,wrdbuf); if (dc.ulval > 0) { /* * Because of the way underlining is handled, * MAXLINE should be declared to be three times * larger than the longest expected input line * for underlining. Since many of the character * buffers use this parameter, a lot of memory * can be allocated when it may not really be * needed. A MAXLINE of 180 would allow about * 60 characters in the output line to be * underlined (remember that only alphanumerics * get underlined - no spaces or punctuation). */ if (dc.buflg) underl(p,wrdbuf,MAXLINE); --dc.ulval; } if (dc.cuval > 0) { if (dc.buflg) underl(p,wrdbuf,MAXLINE); --dc.cuval; } if (dc.boval > 0) { if (dc.buflg) bold(p,wrdbuf,MAXLINE); --dc.boval; } if (dc.ceval > 0) { center(p); put(p); --dc.ceval; } else if (*p == '\r' || *p == '\n') put(p); /* all blank line */ else if (dc.fill == NO) put(p); /* unfilled */ else { while ((i = getwrd(p,wrdbuf)) > 0) { putwrd(wrdbuf); p += i; } } } /* * insert bold face text */ bold(p0,p1,size) char *p0, *p1; int size; { int i, j; j = 0; for (i=0; (p0[i] != '\n') && (j < size-1); ++i) { if (isalpha(p0[i]) || isdigit(p0[i])) { p1[j++] = p0[i]; p1[j++] = '\b'; } p1[j++] = p0[i]; } p1[j++] = '\n'; p1[j] = EOS; while (*p1 != EOS) *p0++ = *p1++; *p0 = EOS; } /* * center a line by setting tival */ center(p) char *p; { dc.tival = max((dc.rmval + dc.tival - width(p)) >> 1,0); } /* * expand title buffer to include character string */ expand(p0,c,s) char *p0; char c; char *s; { char tmp[MAXLINE]; char *p, *q, *r; p = p0; q = tmp; while (*p != EOS) { if (*p == c) { r = s; while (*r != EOS) *q++ = *r++; } else *q++ = *p; ++p; } *q = EOS; strcpy(p0,tmp); /* copy it back */ } /* * get field from title */ char *getfield(p,q,delim) char *p, *q; char delim; { while (*p != delim && *p != '\r' && *p != '\n' && *p != EOS) { *q++ = *p++; } *q = EOS; if (*p == delim) ++p; return(p); } /* * get non-blank word from p0 into p1. * return number of characters processed. */ getwrd(p0,p1) char *p0,*p1; { int i; char *p, c; i = 0; while (*p0 == ' ' || *p0 == '\t') { ++i; ++p0; } p = p0; while (*p0 != ' ' && *p0 != EOS && *p0 != '\t') { if (*p0 == '\n' || *p0 == '\r') break; *p1 = *p0++; ++p1; ++i; } c = *(p1-1); if (c == '"') c = *(p1-2); if (c == '?' || c == '!') { *p1++ = ' '; ++i; } if (c == '.' && (*p0 == '\n' || *p0 == '\r' || islower(*p))) { *p1++ = ' '; ++i; } *p1 = EOS; return(i); } /* * convert integer to decimal ascii string */ itoda(value,p,size) int value; char *p; int size; { char c[7]; int i, j; int aval; aval = abs(value); c[0] = EOS; i = 1; do { c[i++] = (aval % 10) + '0'; aval /= 10; } while (aval > 0 && i <= size); if (value < 0 && i <= size) c[i++] = '-'; for (j=0; j> 1]; while (*p != EOS) *q++ = *p++; } /* * left justify title text into print buffer */ justleft(p,q,limit) char *p, *q; int limit; { q = &q[limit]; while (*p != EOS) *q++ = *p++; } /* * right justify title text into print buffer */ justrite(p,q,limit) char *p, *q; int limit; { int len; len = width(p); q = &q[limit - len]; while (*p != EOS) *q++ = *p++; } /* * delete leading blanks, set tival */ leadbl(p) char *p; { int i,j; brk(); for (i=0; p[i] == ' '; ++i) ; if (p[i] != '\n' && p[i] != '\r') dc.tival = i; for (j=0; p[i] != EOS; ++j) p[j] = p[i++]; p[j] = EOS; } /* * find minimum of two integer */ min(v1,v2) int v1,v2; { return((v1 < v2) ? v1 : v2); } /* * find maximum of two integers */ max(v1,v2) int v1,v2; { return((v1 > v2) ? v1 : v2); } /* * put out page footer */ pfoot() { if (dc.prflg == TRUE) { skip(pg.m3val); if (pg.m4val > 0) { if ((pg.curpag % 2) == 0) { puttl(pg.efoot,pg.eflim,pg.curpag); } else { puttl(pg.ofoot,pg.oflim,pg.curpag); } skip(pg.m4val - 1); } } } /* * put out page header */ phead() { pg.curpag = pg.newpag; if (pg.curpag >= pg.frstpg && pg.curpag <= pg.lastpg) { dc.prflg = TRUE; } else { dc.prflg = FALSE; } ++pg.newpag; if (dc.prflg == TRUE) { if (pg.m1val > 0) { skip(pg.m1val - 1); if ((pg.curpag % 2) == 0) { puttl(pg.ehead,pg.ehlim,pg.curpag); } else { puttl(pg.ohead,pg.ohlim,pg.curpag); } } skip(pg.m2val); } /* * initialize lineno for the next page */ pg.lineno = pg.m1val + pg.m2val + 1; } /* * print character with test for printer */ prchar(c,fp) char c; FILE *fp; { putc(c,fp); } /* * put out line with proper spacing and indenting */ put(p) char *p; { char os[MAXLINE]; int j; if (pg.lineno == 0 || pg.lineno > pg.bottom) { phead(); } if (dc.prflg == TRUE) { if (!dc.bsflg) { if (strkovr(p,os) == TRUE) { for (j=0; j pg.bottom) pfoot(); } /* * output a null terminated string to the file * specified by pbuf. */ putlin(p,pbuf) char *p; FILE *pbuf; { while (*p != EOS) prchar(*p++,pbuf); } /* * put out title or footer */ puttl(p,lim,pgno) char *p; int lim[]; int pgno; { int i; char pn[8]; char t[MAXLINE]; char h[MAXLINE]; char delim; itoda(pgno,pn,6); for (i=0; i 2) { for (i=0; i 0) && ((co.outw + w) > llval)) || (last > MAXLINE)) { last -= co.outp; if(dc.juval == YES) { nextra = llval - co.outw + 1; /* * Check whether last word was end of * sentence and modify counts so that * it is right justified. */ if (co.outbuf[co.outp-2] == ' ') { --co.outp; ++nextra; } spread(co.outbuf,co.outp-1,nextra,co.outwds); if((nextra > 0) && (co.outwds > 1)) { co.outp += (nextra - 1); } } brk(); } p0 = wrdbuf; p1 = co.outbuf + co.outp; while(*p0 != EOS) *p1++ = *p0++; co.outp = last; co.outbuf[co.outp++] = ' '; co.outw += w + 1; ++co.outwds; } /* * skips the number of lines specified by n. */ skip(n) int n; { int i; if (dc.prflg == TRUE && n > 0) { for(i=0; i0; --nb) { --j; p[j] = ' '; } } --i; --j; } } /* * split overstrikes (backspaces) into seperate buffer */ strkovr(p,q) char *p, *q; { char *pp; int bsflg; bsflg = FALSE; pp = p; while (*p != EOS) { *q = ' '; *pp = *p; ++p; if (*p == '\b') { if (*pp >= ' ' && *pp <= '~') { bsflg = TRUE; *q = *pp; ++p; *pp = *p; ++p; } } ++q; ++pp; } *q++ = '\r'; *q = *pp = EOS; return(bsflg); } /* * underline a line */ underl(p0,p1,size) char *p0,*p1; int size; { int i,j; j = 0; for (i=0; (p0[i] != '\n') && (j < size-1); ++i) { if (p0[i] >= ' ' && p0[i] <= '~') { if (isalpha(p0[i]) || isdigit(p0[i]) || dc.cuval > 0) { p1[j++] = '_'; p1[j++] = '\b'; } } p1[j++] = p0[i]; } p1[j++] = '\n'; p1[j] = EOS; while (*p1 != EOS) *p0++ = *p1++; *p0 = EOS; } /* * compute width of character string */ width(s) char *s; { int w; w = 0; while (*s != EOS) { if (*s == '\b') --w; else if (*s != '\n' && *s != '\r') ++w; ++s; } return(w); }