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 }