Blob


1 /*
2 output language from troff:
3 all numbers are character strings
5 sn size in points
6 fn font as number from 1-n
7 cx ascii character x
8 Cxyz funny char xyz. terminated by white space
9 Nn absolute character number n on this font. ditto
10 Hn go to absolute horizontal position n
11 Vn go to absolute vertical position n (down is positive)
12 hn go n units horizontally (relative)
13 vn ditto vertically
14 nnc move right nn, then print c (exactly 2 digits!)
15 (this wart is an optimization that shrinks output file size
16 about 35% and run-time about 15% while preserving ascii-ness)
17 Dt ...\n draw operation 't':
18 Dl x y line from here by x,y
19 Dc d circle of diameter d with left side here
20 De x y ellipse of axes x,y with left side here
21 Da dx dy dx dy arc counter-clockwise, center at dx,dx, end at dx,dy
22 D~ x y x y ... wiggly line by x,y then x,y ...
23 nb a end of line (information only -- no action needed)
24 w paddable word space -- no action needed
25 b = space before line, a = after
26 p new page begins -- set v to 0
27 #...\n comment
28 x ...\n device control functions:
29 x i init
30 x T s name of device is s
31 x r n h v resolution is n/inch
32 h = min horizontal motion, v = min vert
33 x p pause (can restart)
34 x s stop -- done for ever
35 x t generate trailer
36 x f n s font position n contains font s
37 x H n set character height to n
38 x S n set slant to N
40 Subcommands like "i" are often spelled out like "init".
41 */
43 #include <u.h>
44 #include <libc.h>
45 #include <draw.h>
46 #include <bio.h>
48 #define hmot(n) hpos += n
49 #define hgoto(n) hpos = n
50 #define vmot(n) vgoto(vpos + n)
51 #define vgoto(n) vpos = n
53 #define putchar(x) Bprint(&bout, "%C", x)
55 int hpos; /* horizontal position where we are supposed to be next (left = 0) */
56 int vpos; /* current vertical position (down positive) */
57 char *fontfile = "/lib/font/bit/pelm/unicode.9x24.font";
59 char *pschar(char *, char *hex, int *wid, int *ht);
60 int kanji(char *);
61 void Bgetstr(Biobuf *bp, char *s);
62 void Bgetline(Biobuf *bp, char *s);
63 void Bgetint(Biobuf *bp, int *n);
65 Biobuf bin, bout;
67 void
68 main(void)
69 {
70 int c, n;
71 char str[100], *args[10];
72 int jfont, curfont;
74 if(initdraw(0, fontfile, 0) < 0){
75 fprint(2, "mnihongo: can't initialize display: %r\n");
76 exits("open");
77 }
78 Binit(&bin, 0, OREAD);
79 Binit(&bout, 1, OWRITE);
81 jfont = -1;
82 curfont = 1;
83 while ((c = Bgetc(&bin)) >= 0) {
84 switch (c) {
85 case '\n': /* when input is text */
86 case ' ':
87 case '\0': /* occasional noise creeps in */
88 putchar(c);
89 break;
90 case '0': case '1': case '2': case '3': case '4':
91 case '5': case '6': case '7': case '8': case '9':
92 /* two motion digits plus a character */
93 putchar(c); /* digit 1 */
94 n = (c-'0')*10;
95 c = Bgetc(&bin);
96 putchar(c); /* digit 2 */
97 n += c - '0';
98 hmot(n);
99 putchar(Bgetc(&bin)); /* char itself */
100 break;
101 case 'c': /* single character */
102 c = Bgetrune(&bin);
103 if(c==' ') /* why does this happen? it's troff - bwk */
104 break;
105 else if(jfont == curfont){
106 Bungetrune(&bin);
107 Bgetstr(&bin, str);
108 kanji(str);
109 }else{
110 putchar('c');
111 putchar(c);
113 break;
114 case 'C':
115 Bgetstr(&bin, str);
116 Bprint(&bout, "C%s", str);
117 break;
118 case 'f':
119 Bgetstr(&bin, str);
120 curfont = atoi(str);
121 if(curfont < 0 || curfont > 20)
122 curfont = 1; /* sanity */
123 Bprint(&bout, "%c%s", c, str);
124 break;
125 case 'N': /* absolute character number */
126 case 's':
127 case 'p': /* new page */
128 Bgetint(&bin, &n);
129 Bprint(&bout, "%c%d", c, n);
130 break;
131 case 'H': /* absolute horizontal motion */
132 Bgetint(&bin, &n);
133 Bprint(&bout, "%c%d", c, n);
134 hgoto(n);
135 break;
136 case 'h': /* relative horizontal motion */
137 Bgetint(&bin, &n);
138 Bprint(&bout, "%c%d", c, n);
139 hmot(n);
140 break;
141 case 'V':
142 Bgetint(&bin, &n);
143 Bprint(&bout, "%c%d", c, n);
144 vgoto(n);
145 break;
146 case 'v':
147 Bgetint(&bin, &n);
148 Bprint(&bout, "%c%d", c, n);
149 vmot(n);
150 break;
152 case 'w': /* word space */
153 putchar(c);
154 break;
156 case 'x': /* device control */
157 Bgetline(&bin, str);
158 Bprint(&bout, "%c%s", c, str);
159 if(tokenize(str, args, 10)>2 && args[0][0]=='f' && ('0'<=args[1][0] && args[1][0]<='9')){
160 if(strncmp(args[2], "Jp", 2) == 0)
161 jfont = atoi(args[1]);
162 else if(atoi(args[1]) == jfont)
163 jfont = -1;
165 break;
167 case 'D': /* draw function */
168 case 'n': /* end of line */
169 case '#': /* comment */
170 Bgetline(&bin, str);
171 Bprint(&bout, "%c%s", c, str);
172 break;
173 default:
174 fprint(2, "mnihongo: unknown input character %o %c\n", c, c);
175 exits("error");
180 int kanji(char *s) /* very special pleading */
181 { /* dump as kanji char if looks like one */
182 Rune r;
183 char hex[500];
184 int size = 10, ht, wid;
186 chartorune(&r, s);
187 pschar(s, hex, &wid, &ht);
188 Bprint(&bout, "x X PS save %d %d m\n", hpos, vpos);
189 Bprint(&bout, "x X PS currentpoint translate %d %d scale ptsize dup scale\n", size, size);
190 Bprint(&bout, "x X PS %d %d true [%d 0 0 -%d 0 %d]\n",
191 wid, ht, wid, wid, ht-2); /* kludge; ought to use ->ascent */
192 Bprint(&bout, "x X PS {<%s>}\n", hex);
193 Bprint(&bout, "x X PS imagemask restore\n");
194 return 1;
197 char *pschar(char *s, char *hex, int *wid, int *ht)
199 Point chpt, spt;
200 Image *b;
201 uchar rowdata[100];
202 char *hp = hex;
203 int y, i;
205 chpt = stringsize(font, s); /* bounding box of char */
206 *wid = ((chpt.x+7) / 8) * 8;
207 *ht = chpt.y;
208 /* postscript is backwards to video, so draw white (ones) on black (zeros) */
209 b = allocimage(display, Rpt(ZP, chpt), GREY1, 0, DBlack); /* place to put it */
210 spt = string(b, Pt(0,0), display->white, ZP, font, s); /* put it there */
211 /* Bprint(&bout, "chpt %P, spt %P, wid,ht %d,%d\n", chpt, spt, *wid, *ht);
212 /* Bflush(&bout); */
213 for (y = 0; y < chpt.y; y++) { /* read bits a row at a time */
214 memset(rowdata, 0, sizeof rowdata);
215 unloadimage(b, Rect(0, y, chpt.x, y+1), rowdata, sizeof rowdata);
216 for (i = 0; i < spt.x; i += 8) { /* 8 == byte */
217 sprint(hp, "%2.2x", rowdata[i/8]);
218 hp += 2;
221 *hp = 0;
222 freeimage(b);
223 return hex;
227 void Bgetstr(Biobuf *bp, char *s) /* get a string */
229 int c;
231 while ((c = Bgetc(bp)) >= 0) {
232 if (c == ' ' || c == '\t' || c == '\n') {
233 Bungetc(bp);
234 break;
236 *s++ = c;
238 *s = 0;
241 void Bgetline(Biobuf *bp, char *s) /* get a line, including newline */
243 int c;
245 while ((c = Bgetc(bp)) >= 0) {
246 *s++ = c;
247 if (c == '\n')
248 break;
250 *s = 0;
253 void Bgetint(Biobuf *bp, int *n) /* get an integer */
255 double d;
257 Bgetd(bp, &d);
258 *n = d;