123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*
- output language from troff:
- all numbers are character strings
- sn size in points
- fn font as number from 1-n
- cx ascii character x
- Cxyz funny char xyz. terminated by white space
- Nn absolute character number n on this font. ditto
- Hn go to absolute horizontal position n
- Vn go to absolute vertical position n (down is positive)
- hn go n units horizontally (relative)
- vn ditto vertically
- nnc move right nn, then print c (exactly 2 digits!)
- (this wart is an optimization that shrinks output file size
- about 35% and run-time about 15% while preserving ascii-ness)
- Dt ...\n draw operation 't':
- Dl x y line from here by x,y
- Dc d circle of diameter d with left side here
- De x y ellipse of axes x,y with left side here
- Da dx dy dx dy arc counter-clockwise, center at dx,dx, end at dx,dy
- D~ x y x y ... wiggly line by x,y then x,y ...
- nb a end of line (information only -- no action needed)
- w paddable word space -- no action needed
- b = space before line, a = after
- p new page begins -- set v to 0
- #...\n comment
- x ...\n device control functions:
- x i init
- x T s name of device is s
- x r n h v resolution is n/inch
- h = min horizontal motion, v = min vert
- x p pause (can restart)
- x s stop -- done for ever
- x t generate trailer
- x f n s font position n contains font s
- x H n set character height to n
- x S n set slant to N
- Subcommands like "i" are often spelled out like "init".
- */
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <bio.h>
- #define hmot(n) hpos += n
- #define hgoto(n) hpos = n
- #define vmot(n) vgoto(vpos + n)
- #define vgoto(n) vpos = n
- #define putchar(x) Bprint(&bout, "%C", x)
- int hpos; /* horizontal position where we are supposed to be next (left = 0) */
- int vpos; /* current vertical position (down positive) */
- char *fontfile = "/lib/font/bit/pelm/unicode.9x24.font";
- char *pschar(char *, char *hex, int *wid, int *ht);
- int kanji(char *);
- void Bgetstr(Biobuf *bp, char *s);
- void Bgetline(Biobuf *bp, char *s);
- void Bgetint(Biobuf *bp, int *n);
- Biobuf bin, bout;
- 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");
- }
- }
- }
- int kanji(char *s) /* very special pleading */
- { /* dump as kanji char if looks like one */
- Rune r;
- char hex[500];
- int size = 10, ht, wid;
- chartorune(&r, s);
- pschar(s, hex, &wid, &ht);
- Bprint(&bout, "x X PS save %d %d m\n", hpos, vpos);
- Bprint(&bout, "x X PS currentpoint translate %d %d scale ptsize dup scale\n", size, size);
- Bprint(&bout, "x X PS %d %d true [%d 0 0 -%d 0 %d]\n",
- wid, ht, wid, wid, ht-2); /* kludge; ought to use ->ascent */
- Bprint(&bout, "x X PS {<%s>}\n", hex);
- Bprint(&bout, "x X PS imagemask restore\n");
- return 1;
- }
- char *pschar(char *s, char *hex, int *wid, int *ht)
- {
- Point chpt, spt;
- Image *b;
- uchar rowdata[100];
- char *hp = hex;
- int y, i;
- chpt = stringsize(font, s); /* bounding box of char */
- *wid = ((chpt.x+7) / 8) * 8;
- *ht = chpt.y;
- /* postscript is backwards to video, so draw white (ones) on black (zeros) */
- b = allocimage(display, Rpt(ZP, chpt), GREY1, 0, DBlack); /* place to put it */
- spt = string(b, Pt(0,0), display->white, ZP, font, s); /* put it there */
- /* Bprint(&bout, "chpt %P, spt %P, wid,ht %d,%d\n", chpt, spt, *wid, *ht);
- /* Bflush(&bout); */
- for (y = 0; y < chpt.y; y++) { /* read bits a row at a time */
- memset(rowdata, 0, sizeof rowdata);
- unloadimage(b, Rect(0, y, chpt.x, y+1), rowdata, sizeof rowdata);
- for (i = 0; i < spt.x; i += 8) { /* 8 == byte */
- sprint(hp, "%2.2x", rowdata[i/8]);
- hp += 2;
- }
- }
- *hp = 0;
- freeimage(b);
- return hex;
- }
- void Bgetstr(Biobuf *bp, char *s) /* get a string */
- {
- int c;
- while ((c = Bgetc(bp)) >= 0) {
- if (c == ' ' || c == '\t' || c == '\n') {
- Bungetc(bp);
- break;
- }
- *s++ = c;
- }
- *s = 0;
- }
- void Bgetline(Biobuf *bp, char *s) /* get a line, including newline */
- {
- int c;
- while ((c = Bgetc(bp)) >= 0) {
- *s++ = c;
- if (c == '\n')
- break;
- }
- *s = 0;
- }
- void Bgetint(Biobuf *bp, int *n) /* get an integer */
- {
- double d;
- Bgetd(bp, &d);
- *n = d;
- }
|