static void oput(int ch) /* int ch; / * next output character */ { /* * * Responsible for adding all printing characters from the input file to the * open string on top of the stack. The only other characters that end up in * that string are the quotes required for special characters. Reverse printing * mode hasn't been tested but it should be close. hpos and lastx should disagree * each time (except after startline() does something), and that should force a * call to endstring() for every character. * */ if ( stringcount > 100 ) /* don't put too much on the stack */ endline(); if ( vpos != lasty ) endline(); if ( advance == -1 ) /* for reverse printing - move first */ hmot(hmi); startline(); if ( lastc != ch || hpos != prevx ) { if ( lastx != hpos ) endstring(); if ( isascii(ch) && isprint(ch) ) { if ( ch == '\\' || ch == '(' || ch == ')' ) putc('\\', fp_out); putc(ch, fp_out); } else fprintf(fp_out, "\\%.3o", ch & 0377); lastc = ch; prevx = hpos; lastx += lasthmi; } /* End if */ if ( advance != -1 ) hmot(hmi); markedpage = TRUE; } /* End of oput */
static void backspace(void) { /* * * Moves backwards a distance equal to the current value of hmi, but don't go * past the left margin. * */ endline(); if ( hpos - leftmargin >= hmi ) hmot(-hmi); else hgoto(leftmargin); /* maybe just ignore the backspace?? */ lastx = hpos; } /* End of backspace */
Tchar getch(void) { int k; Tchar i, j; g0: if (ch) { i = ch; if (cbits(i) == '\n') nlflg++; ch = 0; return(i); } if (nlflg) return('\n'); i = getch0(); if (ismot(i)) return(i); k = cbits(i); if (k >= sizeof(gchtab)/sizeof(gchtab[0]) || gchtab[k] == 0) /* nothing special */ return(i); if (k != ESC) { if (k == '\n') { nlflg++; if (ip == 0) numtabp[CD].val++; /* line number */ return(k); } if (k == FLSS) { copyf++; raw++; i = getch0(); if (!fi) flss = i; copyf--; raw--; goto g0; } if (k == RPT) { setrpt(); goto g0; } if (!copyf) { if (k == 'f' && lg && !lgf) { i = getlg(i); return(i); } if (k == fc || k == tabch || k == ldrch) { if ((i = setfield(k)) == 0) goto g0; else return(i); } if (k == '\b') { i = makem(-width(' ' | chbits)); return(i); } } return(i); } k = cbits(j = getch0()); if (ismot(j)) return(j); switch (k) { case 'n': /* number register */ setn(); goto g0; case '$': /* argument indicator */ seta(); goto g0; case '*': /* string indicator */ setstr(); goto g0; case '{': /* LEFT */ i = LEFT; goto gx; case '}': /* RIGHT */ i = RIGHT; goto gx; case '"': /* comment */ while (cbits(i = getch0()) != '\n') ; if (ip == 0) numtabp[CD].val++; /* line number */ nlflg++; return(i); /* experiment: put it here instead of copy mode */ case '(': /* special char name \(xx */ case 'C': /* \C'...' */ if ((i = setch(k)) == 0) goto g0; goto gx; case ESC: /* double backslash */ i = eschar; goto gx; case 'e': /* printable version of current eschar */ i = PRESC; goto gx; case '\n': /* concealed newline */ numtabp[CD].val++; goto g0; case ' ': /* unpaddable space */ i = UNPAD; goto gx; case '\'': /* \(aa */ i = ACUTE; goto gx; case '`': /* \(ga */ i = GRAVE; goto gx; case '_': /* \(ul */ i = UNDERLINE; goto gx; case '-': /* current font minus */ i = MINUS; goto gx; case '&': /* filler */ i = FILLER; goto gx; case 'c': /* to be continued */ i = CONT; goto gx; case '!': /* transparent indicator */ i = XPAR; goto gx; case 't': /* tab */ i = '\t'; return(i); case 'a': /* leader (SOH) */ /* old: *pbp++ = LEADER; goto g0; */ i = LEADER; return i; case '%': /* ohc */ i = OHC; return(i); case 'g': /* return format of a number register */ setaf(); /* should this really be in copy mode??? */ goto g0; case '.': /* . */ i = '.'; gx: setsfbits(i, sfbits(j)); return(i); } if (copyf) { *pbp++ = j; return(eschar); } switch (k) { case 'f': /* font indicator */ setfont(0); goto g0; case 's': /* size indicator */ setps(); goto g0; case 'v': /* vert mot */ numerr.type = numerr.escarg = 0; numerr.esc = k; if (i = vmot()) { return(i); } goto g0; case 'h': /* horiz mot */ numerr.type = numerr.escarg = 0; numerr.esc = k; if (i = hmot()) return(i); goto g0; case '|': /* narrow space */ if (NROFF) goto g0; return(makem((int)(EM)/6)); case '^': /* half narrow space */ if (NROFF) goto g0; return(makem((int)(EM)/12)); case 'w': /* width function */ setwd(); goto g0; case 'p': /* spread */ spread++; goto g0; case 'N': /* absolute character number */ numerr.type = numerr.escarg = 0; numerr.esc = k; if ((i = setabs()) == 0) goto g0; return i; case 'H': /* character height */ numerr.type = numerr.escarg = 0; numerr.esc = k; return(setht()); case 'S': /* slant */ numerr.type = numerr.escarg = 0; numerr.esc = k; return(setslant()); case 'z': /* zero with char */ return(setz()); case 'l': /* hor line */ numerr.type = numerr.escarg = 0; numerr.esc = k; setline(); goto g0; case 'L': /* vert line */ numerr.type = numerr.escarg = 0; numerr.esc = k; setvline(); goto g0; case 'D': /* drawing function */ numerr.type = numerr.escarg = 0; numerr.esc = k; setdraw(); goto g0; case 'X': /* \X'...' for copy through */ setxon(); goto g0; case 'b': /* bracket */ setbra(); goto g0; case 'o': /* overstrike */ setov(); goto g0; case 'k': /* mark hor place */ if ((k = findr(getsn())) != -1) { numtabp[k].val = numtabp[HP].val; } goto g0; case '0': /* number space */ return(makem(width('0' | chbits))); case 'x': /* extra line space */ numerr.type = numerr.escarg = 0; numerr.esc = k; if (i = xlss()) return(i); goto g0; case 'u': /* half em up */ case 'r': /* full em up */ case 'd': /* half em down */ return(sethl(k)); default: return(j); } /* NOTREACHED */ }
void drawline(int dx, int dy, char *s) /* draw line from here to dx, dy using s */ { int xd, yd; float val, slope; int i, numdots; int dirmot, perp; int motincr, perpincr; int ohpos, ovpos, osize; float incrway; int itemp; /*temp. storage for value returned byint function sgn*/ osize = size; setsize(t_size(pstab[osize-1] / drawsize)); ohpos = hpos; ovpos = vpos; xd = dx / DX; yd = dy / DX; if (xd == 0) { numdots = abs (yd); numdots = min(numdots, maxdots); motincr = DX * sgn (yd); for (i = 0; i < numdots; i++) { vmot(motincr); put1(drawdot); } vgoto(ovpos + dy); setsize(osize); return; } if (yd == 0) { numdots = abs (xd); motincr = DX * sgn (xd); for (i = 0; i < numdots; i++) { hmot(motincr); put1(drawdot); } hgoto(ohpos + dx); setsize(osize); return; } if (abs (xd) > abs (yd)) { val = slope = (float) xd/yd; numdots = abs (xd); numdots = min(numdots, maxdots); dirmot = 'h'; perp = 'v'; motincr = DX * sgn (xd); perpincr = DX * sgn (yd); } else { val = slope = (float) yd/xd; numdots = abs (yd); numdots = min(numdots, maxdots); dirmot = 'v'; perp = 'h'; motincr = DX * sgn (yd); perpincr = DX * sgn (xd); } incrway = itemp = sgn ((int) slope); for (i = 0; i < numdots; i++) { val -= incrway; if (dirmot == 'h') hmot(motincr); else vmot(motincr); if (val * slope < 0) { if (perp == 'h') hmot(perpincr); else vmot(perpincr); val += slope; } put1(drawdot); } hgoto(ohpos + dx); vgoto(ovpos + dy); setsize(osize); }
void conv(Biobuf *Bp) { long n; int r; char special[10]; int save; inputlineno = 1; if (debug) Bprint(Bstderr, "conv(Biobufhdr *Bp=0x%x)\n", Bp); while ((r = Bgetrune(Bp)) >= 0) { /* Bprint(Bstderr, "r=<%c>,0x%x\n", r, r); */ /* Bflush(Bstderr); */ switch (r) { case 's': /* set point size */ Bgetfield(Bp, 'd', &fontsize, 0); break; case 'f': /* set font to postion */ Bgetfield(Bp, 'd', &fontpos, 0); save = inputlineno; settrfont(); inputlineno = save; /* ugh */ break; case 'c': /* print rune */ r = Bgetrune(Bp); runeout(r); break; case 'C': /* print special character */ Bgetfield(Bp, 's', special, 10); specialout(special); break; case 'N': /* print character with numeric value from current font */ Bgetfield(Bp, 'd', &n, 0); break; case 'H': /* go to absolute horizontal position */ Bgetfield(Bp, 'd', &n, 0); hgoto(n); break; case 'V': /* go to absolute vertical position */ Bgetfield(Bp, 'd', &n, 0); vgoto(n); break; case 'h': /* go to relative horizontal position */ Bgetfield(Bp, 'd', &n, 0); hmot(n); break; case 'v': /* go to relative vertical position */ Bgetfield(Bp, 'd', &n, 0); vmot(n); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* move right nn units, then print character c */ n = (r - '0') * 10; r = Bgetrune(Bp); if (r < 0) error(FATAL, "EOF or error reading input\n"); else if (r < '0' || r > '9') error(FATAL, "integer expected\n"); n += r - '0'; r = Bgetrune(Bp); hmot(n); runeout(r); break; case 'p': /* begin page */ Bgetfield(Bp, 'd', &n, 0); endpage(); startpage(); break; case 'n': /* end of line (information only 'b a' follows) */ Brdline(Bp, '\n'); /* toss rest of line */ inputlineno++; break; case 'w': /* paddable word space (information only) */ break; case 'D': /* graphics function */ draw(Bp); break; case 'x': /* device control functions */ devcntl(Bp); break; case '#': /* comment */ Brdline(Bp, '\n'); /* toss rest of line */ case '\n': inputlineno++; break; default: error(WARNING, "unknown troff function <%c>\n", r); break; } } endpage(); if (debug) Bprint(Bstderr, "r=0x%x\n", r); if (debug) Bprint(Bstderr, "leaving conv\n"); }
void main(void) { int c, n; char str[100], *args[10]; int jfont, curfont; if(initdraw(0, fontfile, 0) < 0){ fprint(2, "mnihongo: can't initialize display: %r\n"); exits("open"); } Binit(&bin, 0, OREAD); Binit(&bout, 1, OWRITE); jfont = -1; curfont = 1; while ((c = Bgetc(&bin)) >= 0) { switch (c) { case '\n': /* when input is text */ case ' ': case '\0': /* occasional noise creeps in */ putchar(c); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* two motion digits plus a character */ putchar(c); /* digit 1 */ n = (c-'0')*10; c = Bgetc(&bin); putchar(c); /* digit 2 */ n += c - '0'; hmot(n); putchar(Bgetc(&bin)); /* char itself */ break; case 'c': /* single character */ c = Bgetrune(&bin); if(c==' ') /* why does this happen? it's troff - bwk */ break; else if(jfont == curfont){ Bungetrune(&bin); Bgetstr(&bin, str); kanji(str); }else{ putchar('c'); putchar(c); } break; case 'C': Bgetstr(&bin, str); Bprint(&bout, "C%s", str); break; case 'f': Bgetstr(&bin, str); curfont = atoi(str); if(curfont < 0 || curfont > 20) curfont = 1; /* sanity */ Bprint(&bout, "%c%s", c, str); break; case 'N': /* absolute character number */ case 's': case 'p': /* new page */ Bgetint(&bin, &n); Bprint(&bout, "%c%d", c, n); break; case 'H': /* absolute horizontal motion */ Bgetint(&bin, &n); Bprint(&bout, "%c%d", c, n); hgoto(n); break; case 'h': /* relative horizontal motion */ Bgetint(&bin, &n); Bprint(&bout, "%c%d", c, n); hmot(n); break; case 'V': Bgetint(&bin, &n); Bprint(&bout, "%c%d", c, n); vgoto(n); break; case 'v': Bgetint(&bin, &n); Bprint(&bout, "%c%d", c, n); vmot(n); break; case 'w': /* word space */ putchar(c); break; case 'x': /* device control */ Bgetline(&bin, str); Bprint(&bout, "%c%s", c, str); if(tokenize(str, args, 10)>2 && args[0][0]=='f' && ('0'<=args[1][0] && args[1][0]<='9')){ if(strncmp(args[2], "Jp", 2) == 0) jfont = atoi(args[1]); else if(atoi(args[1]) == jfont) jfont = -1; } break; case 'D': /* draw function */ case 'n': /* end of line */ case '#': /* comment */ Bgetline(&bin, str); Bprint(&bout, "%c%s", c, str); break; default: fprint(2, "mnihongo: unknown input character %o %c\n", c, c); exits("error"); } } }
/* output glyph. Use first rune to look up character (hash) * then use stoken UTF string to find correct glyph in linked * list of glyphs in bucket. */ void glyphout(Rune rune, char *stoken, BOOLEAN specialflag) { struct charent **cp; struct troffont *tfp; struct psfent *psfp; int i, t, mi, wid; int fontid; /* this is the troff font table index, not the mounted font table index */ Rune r; mi = 0; settrfont(); /* check current font for the character, special or not */ fontid = curtrofffontid; if (debug) fprint(2, "\tlooking through current font: trying %s\n", troffontab[fontid].trfontid); cp = findglyph(fontid, rune, stoken); if (*cp != 0) goto foundit; if (specialflag) { if (expecthmot) hmot(0); /* check special fonts for the special character */ /* cycle through the (troff) mounted fonts starting at the next font */ for (mi=0; mi<fontmnt; mi++) { if (troffontab[fontid].trfontid==0) error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n", fontid, troffontab[fontid].trfontid); if (fontmtab[mi]==0) { if (debug) fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n", mi, fontmtab[mi], fontmnt); continue; } if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0) break; } if (mi==fontmnt) error(FATAL, "current troff font is not mounted, botch!\n"); for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) { if (fontmtab[i]==0) { if (debug) fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n", i, fontmtab[i], fontmnt); continue; } fontid = findtfn(fontmtab[i], TRUE); if (debug) fprint(2, " looking through special fonts: trying %s\n", troffontab[fontid].trfontid); if (troffontab[fontid].special) { cp = findglyph(fontid, rune, stoken); if (*cp != 0) goto foundit; } } /* check font 1 (if current font is not font 1) for the special character */ if (mi != 1) { fontid = findtfn(fontmtab[1], TRUE);; if (debug) fprint(2, " looking through font at position 1: trying %s\n", troffontab[fontid].trfontid); cp = findglyph(fontid, rune, stoken); if (*cp != 0) goto foundit; } } if (*cp == 0) { error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken, troffontab[curtrofffontid].trfontid); expecthmot = 0; } /* use the peter face in lieu of the character that we couldn't find */ rune = 'p'; stoken = "pw"; for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) { if (fontmtab[i]==0) { if (debug) fprint(2, "fontmtab[%d]=%#p\n", i, fontmtab[i]); continue; } fontid = findtfn(fontmtab[i], TRUE); if (debug) fprint(2, " looking through special fonts: trying %s\n", troffontab[fontid].trfontid); if (troffontab[fontid].special) { cp = findglyph(fontid, rune, stoken); if (*cp != 0) goto foundit; } } if (*cp == 0) { error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken, troffontab[curtrofffontid].trfontid); expecthmot = 0; return; } foundit: t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff); if (debug) fprint(2, "runeout(0x%x)<%C> postfontid=0x%x postcharid=0x%x troffcharwidth=%d\n", rune, rune, (*cp)->postfontid, (*cp)->postcharid, (*cp)->troffcharwidth); tfp = &troffontab[fontid]; psfp = nil; for (i=0; i<tfp->psfmapsize; i++) { psfp = &(tfp->psfmap[i]); if(t>=psfp->start && t<=psfp->end) break; } if (i >= tfp->psfmapsize) error(FATAL, "character <0x%x> does not have a Postscript font defined.\n", rune); setpsfont(psfp->psftid, fontsize); if (t == 0x0001) { /* character is in charlib */ endstring(); if (pageon()) { Bprint(Bstdout, "%d %d m ", hpos, vpos); /* if char is unicode character rather than name, clean up for postscript */ wid = chartorune(&r, (*cp)->name); if(' '<r && r<0x7F) Bprint(Bstdout, "%d build_%s\n", (*cp)->troffcharwidth, (*cp)->name); else{ if((*cp)->name[wid] != 0) error(FATAL, "character <%s> badly named\n", (*cp)->name); Bprint(Bstdout, "%d build_X%.4x\n", (*cp)->troffcharwidth, r); } /* * stash charent pointer in a list so that we can * print these character definitions in the prologue. */ for (i=0; i<build_char_cnt; i++) if (*cp == build_char_list[i]) break; if (i == build_char_cnt) { build_char_list = galloc(build_char_list, sizeof(struct charent *)*++build_char_cnt, "build_char_list"); build_char_list[build_char_cnt-1] = *cp; } } expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth; } else if (isinstring() || rune != ' ') { startstring(); if (pageon()) if (rune == ' ') Bprint(Bstdout, " "); else Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)].str); expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth; } }
void conv(register FILE *fp) { register int c, k; int m, n, n1, m1; char str[4096], buf[4096]; while ((c = getc(fp)) != EOF) { switch (c) { case '\n': /* when input is text */ case ' ': case 0: /* occasional noise creeps in */ break; case '{': /* push down current environment */ t_push(); break; case '}': t_pop(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* two motion digits plus a character */ hmot((c-'0')*10 + getc(fp)-'0'); put1(getc(fp)); break; case 'c': /* single ascii character */ put1(getc(fp)); break; case 'C': sget(str, sizeof str, fp); put1s(str); break; case 't': /* straight text */ fgets(buf, sizeof(buf), fp); t_text(buf); break; case 'D': /* draw function */ fgets(buf, sizeof(buf), fp); switch (buf[0]) { case 'l': /* draw a line */ sscanf(buf+1, "%d %d", &n, &m); drawline(n, m, "."); break; case 'c': /* circle */ sscanf(buf+1, "%d", &n); drawcirc(n); break; case 'e': /* ellipse */ sscanf(buf+1, "%d %d", &m, &n); drawellip(m, n); break; case 'a': /* arc */ sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); drawarc(n, m, n1, m1); break; case '~': /* wiggly line */ drawwig(buf+1); break; default: error(FATAL, "unknown drawing function %s\n", buf); break; } break; case 's': fscanf(fp, "%d", &n); if (n == -23) { float f; fscanf(fp, "%f", &f); setsize(f); } else setsize(t_size(n));/* ignore fractional sizes */ break; case 'f': sget(str, sizeof str, fp); setfont(t_font(str)); break; case 'H': /* absolute horizontal motion */ /* fscanf(fp, "%d", &n); */ while ((c = getc(fp)) == ' ') ; k = 0; do { k = 10 * k + c - '0'; } while (isdigit(c = getc(fp))); ungetc(c, fp); hgoto(k); break; case 'h': /* relative horizontal motion */ /* fscanf(fp, "%d", &n); */ while ((c = getc(fp)) == ' ') ; k = 0; do { k = 10 * k + c - '0'; } while (isdigit(c = getc(fp))); ungetc(c, fp); hmot(k); break; case 'w': /* word space */ putc(' ', stdout); break; case 'V': fscanf(fp, "%d", &n); vgoto(n); break; case 'v': fscanf(fp, "%d", &n); vmot(n); break; case 'p': /* new page */ fscanf(fp, "%d", &n); t_page(n); break; case 'n': /* end of line */ while (getc(fp) != '\n') ; t_newline(); break; case '#': /* comment */ while (getc(fp) != '\n') ; break; case 'x': /* device control */ devcntrl(fp); break; default: error(!FATAL, "unknown input character %o %c\n", c, c); done(); } } }