io.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <thread.h>
  13. #include <mouse.h>
  14. #include <keyboard.h>
  15. #include <frame.h>
  16. #include "flayer.h"
  17. #include "samterm.h"
  18. int cursorfd;
  19. int plumbfd = -1;
  20. int input;
  21. int got;
  22. int block;
  23. int kbdc;
  24. int resized;
  25. uchar* hostp;
  26. uchar* hoststop;
  27. uchar* plumbbase;
  28. uchar* plumbp;
  29. uchar* plumbstop;
  30. Channel* plumbc;
  31. Channel* hostc;
  32. Mousectl* mousectl;
  33. Mouse* mousep;
  34. Keyboardctl* keyboardctl;
  35. void panic(char*);
  36. void
  37. closeio(void)
  38. {
  39. closekeyboard(keyboardctl);
  40. closemouse(mousectl);
  41. }
  42. void
  43. initio(void)
  44. {
  45. threadsetname("main");
  46. mousectl = initmouse(nil, display->image);
  47. if(mousectl == nil) {
  48. fprint(2, "samterm: mouse init failed: %r\n");
  49. threadexitsall("mouse");
  50. }
  51. mousep = (Mouse*)mousectl;
  52. keyboardctl = initkeyboard(nil);
  53. if(keyboardctl == nil) {
  54. fprint(2, "samterm: keyboard init failed: %r\n");
  55. threadexitsall("kbd");
  56. }
  57. atexit(closeio);
  58. hoststart();
  59. if(plumbstart() < 0)
  60. extstart();
  61. }
  62. void
  63. getmouse(void)
  64. {
  65. if(readmouse(mousectl) < 0)
  66. panic("mouse");
  67. }
  68. void
  69. mouseunblock(void)
  70. {
  71. got &= ~(1 << RMouse);
  72. }
  73. void
  74. kbdblock(void)
  75. { /* ca suffit */
  76. block = (1 << RKeyboard) | (1 << RPlumb);
  77. }
  78. int
  79. button(int but)
  80. {
  81. getmouse();
  82. return mousep->buttons & (1 << (but - 1));
  83. }
  84. void
  85. externload(int i)
  86. {
  87. plumbbase = malloc(plumbbuf[i].n);
  88. if(plumbbase == 0)
  89. return;
  90. memmove(plumbbase, plumbbuf[i].data, plumbbuf[i].n);
  91. plumbp = plumbbase;
  92. plumbstop = plumbbase + plumbbuf[i].n;
  93. got |= 1 << RPlumb;
  94. }
  95. int
  96. waitforio(void)
  97. {
  98. Alt alts[NRes + 1];
  99. Rune r;
  100. int i;
  101. ulong type;
  102. again:
  103. alts[RPlumb].c = plumbc;
  104. alts[RPlumb].v = &i;
  105. alts[RPlumb].op = CHANRCV;
  106. if((block & (1 << RPlumb)) || plumbc == nil)
  107. alts[RPlumb].op = CHANNOP;
  108. alts[RHost].c = hostc;
  109. alts[RHost].v = &i;
  110. alts[RHost].op = CHANRCV;
  111. if(block & (1 << RHost))
  112. alts[RHost].op = CHANNOP;
  113. alts[RKeyboard].c = keyboardctl->c;
  114. alts[RKeyboard].v = &r;
  115. alts[RKeyboard].op = CHANRCV;
  116. if(block & (1 << RKeyboard))
  117. alts[RKeyboard].op = CHANNOP;
  118. alts[RMouse].c = mousectl->c;
  119. alts[RMouse].v = (Mouse*)mousectl;
  120. alts[RMouse].op = CHANRCV;
  121. if(block & (1 << RMouse))
  122. alts[RMouse].op = CHANNOP;
  123. alts[RResize].c = mousectl->resizec;
  124. alts[RResize].v = nil;
  125. alts[RResize].op = CHANRCV;
  126. if(block & (1 << RResize))
  127. alts[RResize].op = CHANNOP;
  128. alts[NRes].op = CHANEND;
  129. if(got & ~block)
  130. return got & ~block;
  131. flushimage(display, 1);
  132. type = alt(alts);
  133. if(!(type < NRes)) {
  134. /* coverity wants to make sure type cant do an INT_MAX shift when we return */
  135. fprint(2, "samterm: waited wrong: %lx\n", type);
  136. panic("wait");
  137. }
  138. switch(type) {
  139. case RHost:
  140. hostp = hostbuf[i].data;
  141. hoststop = hostbuf[i].data + hostbuf[i].n;
  142. block = 0;
  143. break;
  144. case RPlumb:
  145. externload(i);
  146. break;
  147. case RKeyboard:
  148. kbdc = r;
  149. break;
  150. case RMouse:
  151. break;
  152. case RResize:
  153. resized = 1;
  154. /* do the resize in line if we've finished initializing and we're not in a blocking state */
  155. if(hasunlocked && block == 0 && RESIZED())
  156. resize();
  157. goto again;
  158. }
  159. got |= 1 << type;
  160. return got;
  161. }
  162. int
  163. rcvchar(void)
  164. {
  165. int c;
  166. if(!(got & (1 << RHost)))
  167. return -1;
  168. c = *hostp++;
  169. if(hostp == hoststop)
  170. got &= ~(1 << RHost);
  171. return c;
  172. }
  173. char*
  174. rcvstring(void)
  175. {
  176. *hoststop = 0;
  177. got &= ~(1 << RHost);
  178. return (char*)hostp;
  179. }
  180. int
  181. getch(void)
  182. {
  183. int c;
  184. while((c = rcvchar()) == -1) {
  185. block = ~(1 << RHost);
  186. waitforio();
  187. block = 0;
  188. }
  189. return c;
  190. }
  191. int
  192. externchar(void)
  193. {
  194. Rune r;
  195. loop:
  196. if(got & ((1 << RPlumb) & ~block)) {
  197. plumbp += chartorune(&r, (char*)plumbp);
  198. if(plumbp >= plumbstop) {
  199. got &= ~(1 << RPlumb);
  200. free(plumbbase);
  201. }
  202. if(r == 0)
  203. goto loop;
  204. return r;
  205. }
  206. return -1;
  207. }
  208. int kpeekc = -1;
  209. int
  210. ecankbd(void)
  211. {
  212. Rune r;
  213. if(kpeekc >= 0)
  214. return 1;
  215. if(nbrecv(keyboardctl->c, &r) > 0) {
  216. kpeekc = r;
  217. return 1;
  218. }
  219. return 0;
  220. }
  221. int
  222. ekbd(void)
  223. {
  224. int c;
  225. Rune r;
  226. if(kpeekc >= 0) {
  227. c = kpeekc;
  228. kpeekc = -1;
  229. return c;
  230. }
  231. if(recv(keyboardctl->c, &r) < 0) {
  232. fprint(2, "samterm: keybard recv error: %r\n");
  233. panic("kbd");
  234. }
  235. return r;
  236. }
  237. int
  238. kbdchar(void)
  239. {
  240. int c, i;
  241. c = externchar();
  242. if(c > 0)
  243. return c;
  244. if(got & (1 << RKeyboard)) {
  245. c = kbdc;
  246. kbdc = -1;
  247. got &= ~(1 << RKeyboard);
  248. return c;
  249. }
  250. while(plumbc != nil && nbrecv(plumbc, &i) > 0) {
  251. externload(i);
  252. c = externchar();
  253. if(c > 0)
  254. return c;
  255. }
  256. if(!ecankbd())
  257. return -1;
  258. return ekbd();
  259. }
  260. int
  261. qpeekc(void)
  262. {
  263. return kbdc;
  264. }
  265. int
  266. RESIZED(void)
  267. {
  268. if(resized) {
  269. if(getwindow(display, Refnone) < 0)
  270. panic("can't reattach to window");
  271. resized = 0;
  272. return 1;
  273. }
  274. return 0;
  275. }