mnihongo.c 6.3 KB

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