prompter.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include <draw.h>
  5. #include <mouse.h>
  6. #include <keyboard.h>
  7. #include <control.h>
  8. int Nline;
  9. enum{
  10. Back,
  11. Shade,
  12. Light,
  13. Mask,
  14. Ncol
  15. };
  16. enum {
  17. Keyback = 0xeeee9eff,
  18. Keyshade = 0xaaaa55ff,
  19. Keylight = DWhite,
  20. Keymask = 0x0C0C0C0C,
  21. };
  22. Image *cols[Ncol];
  23. int nline;
  24. char *lines[24]; /* plus one so last line gets terminated by getfields */
  25. Control *entry[24];
  26. Control *kbd;
  27. Control *scrib;
  28. Controlset *keyboard;
  29. Controlset *text;
  30. int kbdy;
  31. int resizeready;
  32. int ctldeletequits = 1;
  33. Channel *eventchan;
  34. void
  35. resizecontrolset(Controlset *cs)
  36. {
  37. int i;
  38. Rectangle r, r1;
  39. if(cs != keyboard)
  40. return;
  41. if (!resizeready)
  42. return;
  43. if(getwindow(display, Refnone) < 0)
  44. ctlerror("resize failed: %r");
  45. draw(screen, screen->r, cols[Back], nil, ZP);
  46. r = insetrect(screen->r, 4);
  47. for(i=0; i<Nline; i++){
  48. r.max.y = r.min.y + font->height;
  49. ctlprint(entry[i], "rect %R", r);
  50. ctlprint(entry[i], "show");
  51. r.min.y = r.max.y;
  52. }
  53. kbdy = r.min.y;
  54. r = screen->r;
  55. r.min.y = kbdy;
  56. r.max.y = screen->r.max.y;
  57. r.min.y = r.max.y - 2*2 - 5*13;
  58. if(r.min.y >= r.max.y)
  59. r.min.y = r.max.y;
  60. r1 = r;
  61. if(scrib)
  62. r.max.x = (3*r.max.x + r.min.x)/4;
  63. ctlprint(kbd, "rect %R", r);
  64. ctlprint(kbd, "show");
  65. if(scrib){
  66. r1.min.x = (3*r1.max.x + r1.min.x)/4;
  67. ctlprint(scrib, "rect %R", r1);
  68. ctlprint(scrib, "show");
  69. }
  70. }
  71. void
  72. readall(char *s)
  73. {
  74. char *buf;
  75. int fd;
  76. Dir *d;
  77. fd = open(s, OREAD);
  78. if(fd < 0){
  79. fprint(2, "prompter: can't open %s: %r\n", s);
  80. exits("open");
  81. }
  82. d = dirfstat(fd);
  83. if(d == nil){
  84. fprint(2, "prompter: can't stat %s: %r\n", s);
  85. exits("stat");
  86. }
  87. buf = ctlmalloc(d->length+1); /* +1 for NUL on end */
  88. if(read(fd, buf, d->length) != d->length){
  89. fprint(2, "prompter: can't read %s: %r\n", s);
  90. exits("stat");
  91. }
  92. nline = getfields(buf, lines, nelem(lines), 0, "\n");
  93. free(d);
  94. close(fd);
  95. }
  96. void
  97. mousemux(void *v)
  98. {
  99. Mouse m;
  100. Channel *c;
  101. c = v;
  102. for(;;){
  103. if(recv(c, &m) < 0)
  104. break;
  105. if(m.buttons & 0x20) {
  106. sendp(eventchan, "mouse: exit");
  107. break;
  108. }
  109. if(m.xy.y >= kbdy)
  110. send(keyboard->mousec, &m);
  111. else
  112. send(text->mousec, &m);
  113. }
  114. }
  115. void
  116. resizemux(void *v)
  117. {
  118. Channel *c;
  119. c = v;
  120. for(;;){
  121. if(recv(c, nil) < 0)
  122. break;
  123. send(keyboard->resizec, nil);
  124. send(text->resizec, nil);
  125. }
  126. }
  127. void
  128. writeall(char *s)
  129. {
  130. int fd;
  131. int i, n;
  132. fd = create(s, OWRITE, 0666);
  133. if(fd < 0){
  134. fprint(2, "prompter: can't create %s: %r\n", s);
  135. exits("open");
  136. }
  137. for(n=Nline; --n>=0; )
  138. if(lines[n][0] != '\0')
  139. break;
  140. for(i=0; i<=n; i++)
  141. fprint(fd, "%s\n", lines[i]);
  142. close(fd);
  143. }
  144. void
  145. usage(void)
  146. {
  147. fprint(2, "usage: prompter file\n");
  148. threadexitsall("usage");
  149. }
  150. void
  151. threadmain(int argc, char *argv[])
  152. {
  153. char *s;
  154. Font *f;
  155. int i, n;
  156. char buf[32], *args[3];
  157. Keyboardctl *kbdctl;
  158. Mousectl *mousectl;
  159. Rune r;
  160. Channel *mtok, *mtot, *ktok, *rtok, *rtot;
  161. int noscrib;
  162. noscrib = 0;
  163. ARGBEGIN{
  164. case 'n':
  165. noscrib++;
  166. break;
  167. default:
  168. usage();
  169. }ARGEND
  170. if(argc != 1)
  171. usage();
  172. readall(argv[0]);
  173. initdraw(0, 0, "prompter");
  174. mousectl = initmouse(nil, screen);
  175. kbdctl = initkeyboard(nil);
  176. mtok = chancreate(sizeof(Mouse), 0);
  177. mtot = chancreate(sizeof(Mouse), 0);
  178. ktok = chancreate(sizeof(Rune), 20);
  179. rtok = chancreate(sizeof(int), 2);
  180. rtot = chancreate(sizeof(int), 2);
  181. initcontrols();
  182. keyboard = newcontrolset(screen, ktok, mtok, rtok);
  183. text = newcontrolset(screen, kbdctl->c, mtot, rtot);
  184. text->clicktotype = 1;
  185. threadcreate(mousemux, mousectl->c, 4096);
  186. threadcreate(resizemux, mousectl->resizec, 4096);
  187. eventchan = chancreate(sizeof(char*), 0);
  188. cols[Back] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyback);
  189. namectlimage(cols[Back], "keyback");
  190. cols[Light] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keylight);
  191. namectlimage(cols[Light], "keylight");
  192. cols[Shade] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyshade);
  193. namectlimage(cols[Shade], "keyshade");
  194. cols[Mask] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, Keymask);
  195. namectlimage(cols[Shade], "keymask");
  196. f = openfont(display, "/lib/font/bit/lucidasans/boldlatin1.6.font");
  197. namectlfont(f, "bold");
  198. f = openfont(display, "/lib/font/bit/lucidasans/unicode.6.font");
  199. namectlfont(f, "roman");
  200. font = f;
  201. Nline = (screen->r.max.y - 2*2 - 5*13 - 8)/font->height;
  202. if (Nline > nelem(entry)) Nline = nelem(entry);
  203. for(i=0; i<Nline; i++){
  204. snprint(buf, sizeof buf, "line.%.2d", i);
  205. entry[i] = createentry(text, buf);
  206. ctlprint(entry[i], "font roman");
  207. ctlprint(entry[i], "image keyback");
  208. if(i < nline)
  209. ctlprint(entry[i], "value %q", lines[i]);
  210. controlwire(entry[i], "event", eventchan);
  211. activate(entry[i]);
  212. }
  213. kbd = createkeyboard(keyboard, "keyboard");
  214. ctlprint(kbd, "font bold roman");
  215. ctlprint(kbd, "image keyback");
  216. ctlprint(kbd, "light keylight");
  217. ctlprint(kbd, "mask keymask");
  218. ctlprint(kbd, "border 1");
  219. controlwire(kbd, "event", eventchan);
  220. scrib = nil;
  221. if(!noscrib){
  222. scrib = createscribble(keyboard, "scribble");
  223. ctlprint(scrib, "font bold");
  224. ctlprint(scrib, "image keyback");
  225. ctlprint(scrib, "border 1");
  226. controlwire(scrib, "event", eventchan);
  227. activate(scrib);
  228. }
  229. activate(kbd);
  230. resizeready = 1;
  231. resizecontrolset(keyboard);
  232. for(;;){
  233. s = recvp(eventchan);
  234. n = tokenize(s, args, nelem(args));
  235. if(n == 2 && strcmp(args[0], "mouse:")==0 && strcmp(args[1], "exit")==0)
  236. break;
  237. if(n == 3)
  238. if(strcmp(args[0], "keyboard:")==0 || strcmp(args[0], "scribble:")==0)
  239. if(strcmp(args[1], "value") == 0){
  240. n = atoi(args[2]);
  241. if(n == '\033') /* Escape exits */
  242. break;
  243. if(n <= 0xFFFF){
  244. r = n;
  245. send(kbdctl->c, &r);
  246. }
  247. }
  248. }
  249. for(i=0; i<Nline; i++){
  250. ctlprint(entry[i], "data");
  251. lines[i] = ctlstrdup(recvp(entry[i]->data));
  252. }
  253. writeall(argv[0]);
  254. draw(screen, screen->r, display->white, nil, ZP);
  255. flushimage(display, 1);
  256. threadexitsall(nil);
  257. }