xref: /plan9/sys/src/cmd/aux/mnihongo/mnihongo.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 /*
2 output language from troff:
3 all numbers are character strings
4 
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
39 
40 	Subcommands like "i" are often spelled out like "init".
41 */
42 
43 #include <u.h>
44 #include <libc.h>
45 #include <draw.h>
46 #include <bio.h>
47 
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
52 
53 #define	putchar(x)	Bprint(&bout, "%C", x)
54 
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";
58 
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);
64 
65 Biobuf bin, bout;
66 
67 void
main(void)68 main(void)
69 {
70 	int c, n;
71 	char str[100], *args[10];
72 	int jfont, curfont;
73 
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);
80 
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);
112 			}
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;
151 
152 		case 'w':	/* word space */
153 			putchar(c);
154 			break;
155 
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;
164 			}
165 			break;
166 
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");
176 		}
177 	}
178 }
179 
kanji(char * s)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;
185 
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;
195 }
196 
pschar(char * s,char * hex,int * wid,int * ht)197 char *pschar(char *s, char *hex, int *wid, int *ht)
198 {
199 	Point chpt, spt;
200 	Image *b;
201 	uchar rowdata[100];
202 	char *hp = hex;
203 	int y, i;
204 
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;
219 		}
220 	}
221 	*hp = 0;
222 	freeimage(b);
223 	return hex;
224 }
225 
226 
Bgetstr(Biobuf * bp,char * s)227 void	Bgetstr(Biobuf *bp, char *s)	/* get a string */
228 {
229 	int c;
230 
231 	while ((c = Bgetc(bp)) >= 0) {
232 		if (c == ' ' || c == '\t' || c == '\n') {
233 			Bungetc(bp);
234 			break;
235 		}
236 		*s++ = c;
237 	}
238 	*s = 0;
239 }
240 
Bgetline(Biobuf * bp,char * s)241 void	Bgetline(Biobuf *bp, char *s)	/* get a line, including newline */
242 {
243 	int c;
244 
245 	while ((c = Bgetc(bp)) >= 0) {
246 		*s++ = c;
247 		if (c == '\n')
248 			break;
249 	}
250 	*s = 0;
251 }
252 
Bgetint(Biobuf * bp,int * n)253 void	Bgetint(Biobuf *bp, int *n)	/* get an integer */
254 {
255 	double d;
256 
257 	Bgetd(bp, &d);
258 	*n = d;
259 }
260