kbmap.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <event.h>
  5. typedef struct KbMap KbMap;
  6. struct KbMap {
  7. char *name;
  8. char *file;
  9. Rectangle r;
  10. int current;
  11. };
  12. KbMap *map;
  13. int nmap;
  14. Image *lightblue;
  15. Image *justblue;
  16. enum {
  17. PAD = 3,
  18. MARGIN = 5
  19. };
  20. char *dir = "/sys/lib/kbmap";
  21. void*
  22. erealloc(void *v, ulong n)
  23. {
  24. v = realloc(v, n);
  25. if(v == nil)
  26. sysfatal("out of memory reallocating %lud", n);
  27. return v;
  28. }
  29. void*
  30. emalloc(ulong n)
  31. {
  32. void *v;
  33. v = malloc(n);
  34. if(v == nil)
  35. sysfatal("out of memory allocating %lud", n);
  36. memset(v, 0, n);
  37. return v;
  38. }
  39. char*
  40. estrdup(char *s)
  41. {
  42. int l;
  43. char *t;
  44. if (s == nil)
  45. return nil;
  46. l = strlen(s)+1;
  47. t = emalloc(l);
  48. memcpy(t, s, l);
  49. return t;
  50. }
  51. void
  52. init(void)
  53. {
  54. int i, fd, nr;
  55. Dir *pd;
  56. char buf[128];
  57. if((fd = open(dir, OREAD)) < 0)
  58. return;
  59. nmap = nr = dirreadall(fd, &pd);
  60. map = emalloc(nr * sizeof(KbMap));
  61. for(i=0; i<nr; i++){
  62. sprint(buf, "%s/%s", dir, pd[i].name);
  63. map[i].file = estrdup(buf);
  64. map[i].name = estrdup(pd[i].name);
  65. map[i].current = 0;
  66. }
  67. free(pd);
  68. close(fd);
  69. }
  70. void
  71. drawmap(int i)
  72. {
  73. if(map[i].current)
  74. draw(screen, map[i].r, justblue, nil, ZP);
  75. else
  76. draw(screen, map[i].r, lightblue, nil, ZP);
  77. _string(screen, addpt(map[i].r.min, Pt(2,0)), display->black, ZP,
  78. font, map[i].name, nil, strlen(map[i].name),
  79. map[i].r, nil, ZP, SoverD);
  80. border(screen, map[i].r, 1, display->black, ZP);
  81. }
  82. void
  83. geometry(void)
  84. {
  85. int i, rows;
  86. Rectangle r;
  87. rows = (Dy(screen->r)-2*MARGIN+PAD)/(font->height+PAD);
  88. r = Rect(0,0,(Dx(screen->r)-2*MARGIN), font->height);
  89. for(i=0; i<nmap; i++)
  90. map[i].r = rectaddpt(rectaddpt(r, Pt(MARGIN+(PAD+Dx(r))*(i/rows),
  91. MARGIN+(PAD+Dy(r))*(i%rows))), screen->r.min);
  92. }
  93. void
  94. redraw(Image *screen)
  95. {
  96. int i;
  97. draw(screen, screen->r, lightblue, nil, ZP);
  98. for(i=0; i<nmap; i++)
  99. drawmap(i);
  100. flushimage(display, 1);
  101. }
  102. void
  103. eresized(int new)
  104. {
  105. if(new && getwindow(display, Refmesg) < 0)
  106. fprint(2,"can't reattach to window");
  107. geometry();
  108. redraw(screen);
  109. }
  110. int
  111. writemap(char *file)
  112. {
  113. int i, fd, ofd;
  114. char buf[8192];
  115. if((fd = open(file, OREAD)) < 0){
  116. fprint(2, "cannot open %s: %r", file);
  117. return -1;
  118. }
  119. if((ofd = open("/dev/kbmap", OWRITE)) < 0) {
  120. fprint(2, "cannot open /dev/kbmap: %r");
  121. close(fd);
  122. return -1;
  123. }
  124. while((i = read(fd, buf, sizeof buf)) > 0)
  125. if(write(ofd, buf, i) != i){
  126. fprint(2, "writing /dev/kbmap: %r");
  127. break;
  128. }
  129. close(fd);
  130. close(ofd);
  131. return 0;
  132. }
  133. void
  134. click(Mouse m)
  135. {
  136. int i, j;
  137. char buf[128];
  138. if(m.buttons == 0 || (m.buttons & ~4))
  139. return;
  140. for(i=0; i<nmap; i++)
  141. if(ptinrect(m.xy, map[i].r))
  142. break;
  143. if(i == nmap)
  144. return;
  145. do
  146. m = emouse();
  147. while(m.buttons == 4);
  148. if(m.buttons != 0){
  149. do
  150. m = emouse();
  151. while(m.buttons);
  152. return;
  153. }
  154. for(j=0; j<nmap; j++)
  155. if(ptinrect(m.xy, map[j].r))
  156. break;
  157. if(j != i)
  158. return;
  159. /* since maps are often just a delta of the distributed map... */
  160. snprint(buf, sizeof buf, "%s/ascii", dir);
  161. writemap(buf);
  162. writemap(map[i].file);
  163. /* clean the previous current map */
  164. for(j=0; j<nmap; j++)
  165. map[j].current = 0;
  166. map[i].current = 1;
  167. redraw(screen);
  168. }
  169. void
  170. usage(void)
  171. {
  172. fprint(2, "usage: kbmap [file...]\n");
  173. exits("usage");
  174. }
  175. void
  176. main(int argc, char **argv)
  177. {
  178. Event e;
  179. char *c;
  180. if(argc > 1) {
  181. argv++; argc--;
  182. map = emalloc((argc)*sizeof(KbMap));
  183. while(argc--) {
  184. map[argc].file = estrdup(argv[argc]);
  185. c = strrchr(map[argc].file, '/');
  186. map[argc].name = (c == nil ? map[argc].file : c+1);
  187. map[argc].current = 0;
  188. nmap++;
  189. }
  190. } else
  191. init();
  192. initdraw(0, 0, "kbmap");
  193. lightblue = allocimagemix(display, DPalebluegreen, DWhite);
  194. if(lightblue == nil)
  195. sysfatal("allocimagemix: %r");
  196. justblue = allocimagemix(display, DBlue, DWhite);
  197. if(justblue == nil)
  198. sysfatal("allocimagemix: %r");
  199. eresized(0);
  200. einit(Emouse|Ekeyboard);
  201. for(;;){
  202. switch(eread(Emouse|Ekeyboard, &e)){
  203. case Ekeyboard:
  204. if(e.kbdc==0x7F || e.kbdc=='q')
  205. exits(0);
  206. break;
  207. case Emouse:
  208. if(e.mouse.buttons)
  209. click(e.mouse);
  210. break;
  211. }
  212. }
  213. }