plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

mnihongo.c (6406B)


      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
     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 
    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 
    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 
    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 
    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 
    253 void	Bgetint(Biobuf *bp, int *n)	/* get an integer */
    254 {
    255 	double d;
    256 
    257 	Bgetd(bp, &d);
    258 	*n = d;
    259 }