|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 12633 (0x3159) Types: TextFile Notes: UNIX file Names: »process.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/nroff/process.c«
/* * Nroff/Troff. * Formatting. */ #include <stdio.h> #include <ctype.h> #include "roff.h" #include "char.h" #include "code.h" #include "div.h" #include "env.h" #include "esc.h" #include "hyphen.h" #include "reg.h" /* * Process input, formatting text. */ process() { REG *rp; int lastc, n; register int c, f, w; char charbuf[CBFSIZE], name[2]; c = '\n'; for (;;) { lastc = c; c = getf(1); next: switch (c) { case EOF: /* End of file */ return; case EESC: /* Printable version of escape */ f = asctab[esc]; goto character; case EACA: /* Acute accent */ f = CACUTE; goto character; case EGRA: /* Grave accent */ f = CGRAVE; goto character; case EMIN: /* Minus sign */ f = CMINUS; goto character; case EUNP: /* Unpaddable space */ n = mws; goto hormove; case EDWS: /* Digit width space */ n = unit(SMDIGW, SDDIGW); goto hormove; case EM06: /* 1/6 em (narrow space) */ n = unit(SMNARS, SDNARS); goto hormove; case EM12: /* 1/12 em (half narrow space) */ n = unit(SMNARS, SDNARS*2); goto hormove; case ENOP: /* Zero width character */ continue; case ETLI: /* Transparent line indicator */ /* Not implemented yet */ continue; case EHYP: /* Potential hyphenation break */ addidir(DHYPH, 0); continue; case ECHR: /* Special character indicator */ /* Not implemented yet */ getf(); getf(); continue; case EBRA: /* Bracket building function */ /* Not implemented yet */ continue; case EINT: /* Interrupt text processing */ if ((c=getf(0)) != '\n') goto next; continue; case EVNF: /* 1/2 em vertical motion */ n = unit(SMVEMS, SDVEMS*2); goto vermove; case EFON: /* Change font */ if ((c=getf(0)) != '(') { name[0] = c; name[1] = '\0'; } else { name[0] = getf(0); name[1] = getf(0); } setfont(name, 1); continue; case EHMT: /* Local horizontal motion */ n = 0; if (scandel(charbuf, CBFSIZE)) n = number(charbuf, SMUNIT, SDUNIT, 0, 0, 0); hormove: addidir(DHMOV, n); nlinsiz += n; continue; case EMAR: /* Mark horizontal input place */ name[0] = c = getf(0); name[1] = '\0'; rp = getnreg(name); rp->r_nval = nlinsiz; continue; case EHLF: /* Horizontal line drawing function */ /* Not implemented yet */ n = 0; if (scandel(charbuf, CBFSIZE)) n = number(charbuf, 1, 1, 0, 0, 0); n /= 12; f = asctab['_']; w = defwidt[f]; if (n < 0) { addidir(DHMOV, n); nlinsiz += n; n = -n; } while (n--) { addchar(f, w); nlinsiz += w; nlindir++; } continue; case EVLF: /* Vertical line drawing function */ /* Not implemented yet */ continue; case EOVS: /* Overstrike */ /* Not implemented yet */ continue; case ESPR: /* Break and spread output line */ wordbreak(DNULL); linebreak(); continue; case EVRM: /* Reverse 1 em vertically */ n = -unit(SMVEMS, SDVEMS); goto vermove; case EPSZ: /* Change pointsize */ /* Not implemented yet */ continue; case EVRN: /* Reverse 1 en vertically */ n = -unit(SMVEMS, SDVEMS*2); goto vermove; case EVMT: /* Local vertical motion */ n = 0; if (scandel(charbuf, CBFSIZE)) n = number(charbuf, SMUNIT, SDUNIT, 0, 1, 0); vermove: basline += n; addidir(DVMOV, n); continue; case EXLS: /* Extra line spacing */ n = 0; if (scandel(charbuf, CBFSIZE)) n = number(charbuf, SMUNIT, SDUNIT, 0, 1, 0); if (n < 0) { if (-n > preexls) preexls = -n; } else { if (n > posexls) posexls = n; } continue; case EZWD: /* Print character with zero width */ /* Not implemented yet */ continue; case ECOD: /* Processed text */ c = diverse(); lastc = '\n'; goto next; case SOH: wordbreak(DHMOV); movetab(ldc); continue; case '\t': wordbreak(DHMOV); movetab(tbc); continue; case '\n': wordbreak(DPADC); switch (lastc) { case '\n': setbreak(); nlindir++; setbreak(); break; case '.': case '!': case '?': llinptr->c_iarg += 2*mws; nlinsiz += 2*mws; break; default: llinptr->c_iarg += mws; nlinsiz += mws; } if (fil==0 || cec) linebreak(); if (cec) --cec; if (ulc) { if (--ulc == 0) setfont(ufp, 1); } if (inpltrc) if (--inpltrc == 0) execute(inptrap); continue; case ' ': if (lastc == '\n') setbreak(); else wordbreak(DPADC); llinptr->c_iarg += mws; nlinsiz += mws; continue; default: if (lastc == '\n') { if (c == ccc) { request(); c = '\n'; continue; } else if (c == nbc) { nbrflag = 1; request(); nbrflag = 0; c = '\n'; continue; } } if (!isascii(c)) continue; f = asctab[trantab[c]]; character: if (f == CNULL) continue; if (bolmode != newbold || bolmode != curbold || itlmode != newital || itlmode != curital) { curbold = bolmode = newbold; curital = itlmode = newital; addcdir(DTYPE, curbold, curital); } if (fontype != newfont || fontype != curfont) addidir(DFONT, curfont = fontype = newfont); if (psz != newpsz || psz != curpsz) addidir(DPSZE, curpsz = psz = newpsz); if ((w=fonwidt[f]) < 0) w = defwidt[f]; w = unit(w*psz*swdmul, swddiv); if (csz!=0 && csz!=w) { w = (csz-w) / 2; addidir(DHMOV, w); w = csz - w; } addchar(f, w); nlindir++; nlinsiz += w; } } } /* * Whoever thought up the way diversions work in NROFF/TROFF * should have done something else. */ int diverse() { int c, lastcode; for (c = ECOD; c == ECOD; c = getf(1)) { switch (codeval.c_code) { case DSPAR: if (codeval.c_iarg==0) { break; /* discard empty newline codes */ } else if (fil) { wordbreak(DPADC); padspace(lastcode); } else { register int cvls, clsp; wordbreak(DNULL); cvls = vls, clsp = lsp; vls = 0, lsp = 1; linebreak(); vls = cvls, lsp = clsp; sspace(codeval.c_iarg); } if (inpltrc && --inpltrc == 0) execute(inptrap); break; case DPADC: wordbreak(DPADC); if (fil) { padspace(lastcode); } else { llinptr->c_iarg += codeval.c_iarg; nlinsiz += codeval.c_iarg; } break; case DHYPC: if (fil) { register int c; addidir(DHYPH, 0); while ((c=getf(0))==ECOD && codeval.c_code==DSPAR && codeval.c_iarg==0 ) ; if (c!=ECOD || codeval.c_code!=DSPAR) panic("Cannot dehyphenate"); } else { nlindir++; nlinsiz += codeval.c_iarg; addidir(codeval.c_code, codeval.c_iarg); } break; case DHMOV: nlinsiz += codeval.c_iarg; case DNULL: case DVMOV: case DHYPH: addidir(codeval.c_code, codeval.c_iarg); break; case DTYPE: curbold = codeval.c_car1; curital = codeval.c_car2; addcdir(codeval.c_code, curbold, curital); break; case DFONT: addidir(codeval.c_code, curfont = codeval.c_iarg); break; case DPSZE: addidir(codeval.c_code, curpsz = codeval.c_iarg); break; default: nlindir++; nlinsiz += codeval.c_move; addchar(codeval.c_code, codeval.c_move); break; } lastcode = codeval.c_code; } return (c); } padspace(lastcode) int lastcode; { switch (lastcode) { case CEXCLAM: case CQUEST: case CDOT: llinptr->c_iarg += 2*mws; nlinsiz += 2*mws; break; default: llinptr->c_iarg += mws; nlinsiz += mws; } } /* * End the current line and left justify it. */ setbreak() { register int cfil; if (nbrflag) return; wordbreak(DNULL); cfil = fil; fil = 0; linebreak(); fil = cfil; } /* * End the current word. The given directive type is added onto * the end of the line. */ wordbreak(dir) { int n, s, d; if (nlindir == llindir) return; if (llinptr == linebuf) setwork(); else { if (fil!=0 && nlinsiz>lln) { n = nlinptr - (llinptr+1); s = nlinsiz - llinsiz - llinptr->c_iarg; d = nlindir - llindir; if (hyp==0 || fitword(&n, &s, &d)==0) copystr(wordbuf, llinptr+1, sizeof (CODE), n); if (n > WORSIZE) panic("Word buffer overflow"); linebreak(); copystr(nlinptr, wordbuf, sizeof (CODE), n); nlinptr += n; nlinsiz += s; nlindir += d; setwork(); } } llinptr = nlinptr; llinsiz = nlinsiz; llindir = nlindir; addidir(dir, 0); } /* * Set up working parameters for the line. */ setwork() { if (tif) tif = 0; else tin = ind; linebuf[0].c_iarg += tin; llinsiz += tin; nlinsiz += tin; tlinsiz += tin; } /* * Try to hyphenate and fit the last word in a line. * This routine is really part of the routine `wordbreak'. * The arguments are pointers to variables in `wordbreak'. */ fitword(np, sp, dp) int *dp; int *sp; int *np; { CODE *wp; int hflag, b1, b2, h, d, s, n; register CODE *cp; register int c; register char *hp; hyphen(wp=llinptr+1, nlinptr); if ((h=fonwidt[CHYPHEN]) < 0) h = defwidt[CHYPHEN]; h = unit(h*psz*swdmul, swddiv); b1 = nlinsiz - lln; b2 = b1 + h; d = 0; s = 0; n = 0; cp = nlinptr; hp = &hyphbuf[nlinptr-wp]; for (;;) { if (--cp < wp) return (0); c = cp->c_code; if (cp>wp && c==CHYPHEN && s>=b1) { hflag = 0; break; } if (*--hp) { if (s >= b2) { hflag = 1; break; } } if (ifcchar(c)) { d++; s += cp->c_move; continue; } if (c==DHMOV || c==DPADC) { s += cp->c_iarg; continue; } } n = nlinptr - ++cp; copystr(wordbuf, cp, sizeof (CODE), n); llinptr = cp; llinsiz = nlinsiz - s; llindir = nlindir - d; if (hflag) { nlinptr = llinptr; addchar(CHYPHEN, h); llinptr = nlinptr; llinsiz += h; llindir++; } *dp = d; *sp = s; *np = n; return (1); } /* * End the current line. * This must be called after calling wordbreak. */ linebreak() { if (llindir == 0) return; movetab(EOF); justify(); if (llinsiz > cdivp->d_maxw) cdivp->d_maxw = llinsiz; sspace(preexls); if (cdivp == mdivp) { nrorval = llinsiz - linebuf[0].c_iarg; linebuf[0].c_iarg += pof; flushl(linebuf, llinptr); nsm = 0; } else flushd(linebuf, llinptr); arorval = posexls; setline(); lspace(vls+posexls); nrnlreg->r_nval = mdivp->d_rpos; sspace((lsp-1)*vls); } /* * Justify the current line. */ justify() { register CODE *cp; int t; register int n, r; n = cec ? CJUS : (fil==0||adm==0) ? LJUS : adj; switch (n) { case LJUS: n = 0; break; case CJUS: n = (lln-llinsiz) / 2; break; case RJUS: n = lln - llinsiz; break; case FJUS: r = 0; for (cp=linebuf; cp<llinptr; cp++) if (cp->c_code == DPADC) r++; n = lln - llinsiz; t = n%r; n = 1 + n/r; r = t; for (cp=linebuf; cp<llinptr; cp++) { if (cp->c_code != DPADC) continue; if (r-- == 0) --n; cp->c_iarg += n; } return; } linebuf[0].c_iarg += n; } /* * Tab to the next tab stop. The intermediate space is filled * with the character c. If the character passed is an EOF, * then it is being called at the end of a line to finish up * the final tab stop. This must be called right after calling * wordbreak. */ movetab(c) { register TAB *tp; int n, f, w, d2; register int d, d1; register int pos; tp = ctabptr; pos = tp->t_pos + tin; /* relative to indent */ switch (tp->t_jus) { case LJUS: d = pos - tlinsiz; /* tlinptr->c_iarg -= d; nlinsiz = llinsiz -= d; */ break; case CJUS: d = pos - (llinsiz+tlinsiz)/2; break; case RJUS: d = pos - llinsiz; break; case NJUS: llinptr->c_iarg += mws; return; } if ((f=asctab[ltabchr]) == 0) tlinptr->c_iarg += d; else { if ((w=fonwidt[f]) < 0) w = defwidt[f]; if ((n=nlinptr-(tlinptr+1)) > WORSIZE) panic("Word buffer overflow"); copystr(wordbuf, tlinptr+1, sizeof (CODE), n); nlinptr = tlinptr + 1; if ((d2=(d1=tlinsiz)%w) != 0) { d1 += w-d2; tlinptr->c_iarg += w-d2; } d2 = tlinsiz + d; while ((d1+=w) <= d2) addchar(f, w); addidir(DHMOV, d2-(d1-w)); if (nlinptr+n >= &linebuf[LINSIZE]) panic("Line buffer overflow"); copystr(nlinptr, wordbuf, sizeof (CODE), n); llinptr = nlinptr += n; --llinptr; } tlinsiz = nlinsiz = llinsiz += d; tlinptr = llinptr; if (c == EOF) return; while ((++tp)->t_jus!=NJUS && tp->t_pos+tin <= llinsiz) ; /* if (tp->t_jus == LJUS) { tlinptr->c_iarg += d = tp->t_pos+tin - tlinsiz; nlinsiz = llinsiz += d; } */ ctabptr = tp; ltabchr = c; } /* * Initialise line data for a new line. */ setline() { llinptr = nlinptr = tlinptr = linebuf; llinsiz = nlinsiz = tlinsiz = 0; llindir = nlindir = 0; ctabptr = tab; ltabchr = '\0'; basline = 0; preexls = 0; posexls = 0; addidir(DHMOV, 0); }