mesg.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  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 <cursor.h>
  14. #include <mouse.h>
  15. #include <keyboard.h>
  16. #include <frame.h>
  17. #include <plumb.h>
  18. #include "flayer.h"
  19. #include "samterm.h"
  20. #define HSIZE 3 /* Type + short count */
  21. Header h;
  22. uchar indata[DATASIZE+1]; /* room for NUL */
  23. uchar outdata[DATASIZE];
  24. short outcount;
  25. int hversion;
  26. int exiting;
  27. void inmesg(Hmesg, int);
  28. int inshort(int);
  29. long inlong(int);
  30. vlong invlong(int);
  31. void hsetdot(int, long, long);
  32. void hmoveto(int, long);
  33. void hsetsnarf(int);
  34. void hplumb(int);
  35. void clrlock(void);
  36. int snarfswap(char*, int, char**);
  37. void
  38. rcv(void)
  39. {
  40. int c;
  41. static int count = 0, errs = 0, i = 0, state = 0;
  42. while((c=rcvchar()) != -1)
  43. switch(state){
  44. case 0:
  45. h.type = c;
  46. state++;
  47. break;
  48. case 1:
  49. h.count0 = c;
  50. state++;
  51. break;
  52. case 2:
  53. h.count1 = c;
  54. count = h.count0|(h.count1<<8);
  55. i = 0;
  56. if(count > DATASIZE){
  57. if(++errs < 5){
  58. dumperrmsg(count, h.type, h.count0, c);
  59. state = 0;
  60. continue;
  61. }
  62. fprint(2, "type %d count %d\n", h.type, count);
  63. panic("count>DATASIZE");
  64. }
  65. if(count == 0)
  66. goto zerocount;
  67. state++;
  68. break;
  69. case 3:
  70. indata[i++] = c;
  71. if(i == count){
  72. zerocount:
  73. indata[i] = 0;
  74. inmesg(h.type, count);
  75. state = count = 0;
  76. continue;
  77. }
  78. break;
  79. }
  80. }
  81. Text *
  82. whichtext(int tg)
  83. {
  84. int i;
  85. for(i=0; i<nname; i++)
  86. if(tag[i] == tg)
  87. return text[i];
  88. panic("whichtext");
  89. return 0;
  90. }
  91. void
  92. inmesg(Hmesg type, int count)
  93. {
  94. Text *t;
  95. int i, m;
  96. long l;
  97. Flayer *lp;
  98. m = inshort(0);
  99. l = inlong(2);
  100. switch(type){
  101. default:
  102. fprint(2, "type %d\n", type);
  103. panic("rcv unknown");
  104. case Hversion:
  105. hversion = m;
  106. break;
  107. case Hbindname:
  108. l = invlong(2); /* for 64-bit pointers */
  109. if((i=whichmenu(m)) < 0)
  110. break;
  111. /* in case of a race, a bindname may already have occurred */
  112. if((t=whichtext(m)) == 0)
  113. t=(Text *)l;
  114. else /* let the old one win; clean up the new one */
  115. while(((Text *)l)->nwin>0)
  116. closeup(&((Text *)l)->l[((Text *)l)->front]);
  117. text[i] = t;
  118. text[i]->tag = m;
  119. break;
  120. case Hcurrent:
  121. if(whichmenu(m)<0)
  122. break;
  123. t = whichtext(m);
  124. i = which && ((Text *)which->user1)==&cmd && m!=cmd.tag;
  125. if(t==0 && (t = sweeptext(0, m))==0)
  126. break;
  127. if(t->l[t->front].textfn==0)
  128. panic("Hcurrent");
  129. lp = &t->l[t->front];
  130. if(i){
  131. flupfront(lp);
  132. flborder(lp, 0);
  133. work = lp;
  134. }else
  135. current(lp);
  136. break;
  137. case Hmovname:
  138. if((m=whichmenu(m)) < 0)
  139. break;
  140. t = text[m];
  141. l = tag[m];
  142. i = name[m][0];
  143. text[m] = 0; /* suppress panic in menudel */
  144. menudel(m);
  145. if(t == &cmd)
  146. m = 0;
  147. else{
  148. if (nname>0 && text[0]==&cmd)
  149. m = 1;
  150. else m = 0;
  151. for(; m<nname; m++)
  152. if(strcmp((char*)indata+2, (char*)name[m]+1)<0)
  153. break;
  154. }
  155. menuins(m, indata+2, t, i, (int)l);
  156. break;
  157. case Hgrow:
  158. if(whichmenu(m) >= 0)
  159. hgrow(m, l, inlong(6), 1);
  160. break;
  161. case Hnewname:
  162. menuins(0, (uchar *)"", (Text *)0, ' ', m);
  163. break;
  164. case Hcheck0:
  165. i = whichmenu(m);
  166. if(i>=0) {
  167. t = text[i];
  168. if(t)
  169. t->lock++;
  170. outTs(Tcheck, m);
  171. }
  172. break;
  173. case Hcheck:
  174. i = whichmenu(m);
  175. if(i>=0) {
  176. t = text[i];
  177. if(t && t->lock)
  178. t->lock--;
  179. hcheck(m);
  180. }
  181. break;
  182. case Hunlock:
  183. clrlock();
  184. break;
  185. case Hdata:
  186. if(whichmenu(m) >= 0)
  187. l += hdata(m, l, indata+6, count-6);
  188. Checkscroll:
  189. if(m == cmd.tag){
  190. for(i=0; i<NL; i++){
  191. lp = &cmd.l[i];
  192. if(lp->textfn)
  193. center(lp, l>=0? l : lp->p1);
  194. }
  195. }
  196. break;
  197. case Horigin:
  198. if(whichmenu(m) >= 0)
  199. horigin(m, l);
  200. break;
  201. case Hunlockfile:
  202. if(whichmenu(m)>=0 && (t = whichtext(m))->lock){
  203. --t->lock;
  204. l = -1;
  205. goto Checkscroll;
  206. }
  207. break;
  208. case Hsetdot:
  209. if(whichmenu(m) >= 0)
  210. hsetdot(m, l, inlong(6));
  211. break;
  212. case Hgrowdata:
  213. if(whichmenu(m)<0)
  214. break;
  215. hgrow(m, l, inlong(6), 0);
  216. whichtext(m)->lock++; /* fake the request */
  217. l += hdata(m, l, indata+10, count-10);
  218. goto Checkscroll;
  219. case Hmoveto:
  220. if(whichmenu(m)>=0)
  221. hmoveto(m, l);
  222. break;
  223. case Hclean:
  224. if((m = whichmenu(m)) >= 0)
  225. name[m][0] = ' ';
  226. break;
  227. case Hdirty:
  228. if((m = whichmenu(m))>=0)
  229. name[m][0] = '\'';
  230. break;
  231. case Hdelname:
  232. if((m=whichmenu(m)) >= 0)
  233. menudel(m);
  234. break;
  235. case Hcut:
  236. if(whichmenu(m) >= 0)
  237. hcut(m, l, inlong(6));
  238. break;
  239. case Hclose:
  240. if(whichmenu(m)<0 || (t = whichtext(m))==0)
  241. break;
  242. l = t->nwin;
  243. for(i = 0,lp = t->l; l>0 && i<NL; i++,lp++)
  244. if(lp->textfn){
  245. closeup(lp);
  246. --l;
  247. }
  248. break;
  249. case Hsetpat:
  250. setpat((char *)indata);
  251. break;
  252. case Hsetsnarf:
  253. hsetsnarf(m);
  254. break;
  255. case Hsnarflen:
  256. snarflen = inlong(0);
  257. break;
  258. case Hack:
  259. outT0(Tack);
  260. break;
  261. case Hexit:
  262. exiting = 1;
  263. outT0(Texit);
  264. threadexitsall(nil);
  265. break;
  266. case Hplumb:
  267. hplumb(m);
  268. break;
  269. }
  270. }
  271. void
  272. setlock(void)
  273. {
  274. hostlock++;
  275. setcursor(mousectl, cursor = &lockarrow);
  276. }
  277. void
  278. clrlock(void)
  279. {
  280. hasunlocked = 1;
  281. if(hostlock > 0)
  282. hostlock--;
  283. if(hostlock == 0)
  284. setcursor(mousectl, cursor=(Cursor *)0);
  285. }
  286. void
  287. startfile(Text *t)
  288. {
  289. outTsv(Tstartfile, t->tag, (vlong)t); /* for 64-bit pointers */
  290. setlock();
  291. }
  292. void
  293. startnewfile(int type, Text *t)
  294. {
  295. t->tag = Untagged;
  296. outTv(type, (vlong)t); /* for 64-bit pointers */
  297. }
  298. int
  299. inshort(int n)
  300. {
  301. return indata[n]|(indata[n+1]<<8);
  302. }
  303. long
  304. inlong(int n)
  305. {
  306. return indata[n]|(indata[n+1]<<8)|
  307. ((long)indata[n+2]<<16)|((long)indata[n+3]<<24);
  308. }
  309. vlong
  310. invlong(int n)
  311. {
  312. vlong v;
  313. v = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[n+4];
  314. v = (v<<16) | (indata[n+3]<<8) | indata[n+2];
  315. v = (v<<16) | (indata[n+1]<<8) | indata[n];
  316. return v;
  317. }
  318. void
  319. outT0(Tmesg type)
  320. {
  321. outstart(type);
  322. outsend();
  323. }
  324. void
  325. outTl(Tmesg type, long l)
  326. {
  327. outstart(type);
  328. outlong(l);
  329. outsend();
  330. }
  331. void
  332. outTs(Tmesg type, int s)
  333. {
  334. outstart(type);
  335. outshort(s);
  336. outsend();
  337. }
  338. void
  339. outTss(Tmesg type, int s1, int s2)
  340. {
  341. outstart(type);
  342. outshort(s1);
  343. outshort(s2);
  344. outsend();
  345. }
  346. void
  347. outTsll(Tmesg type, int s1, long l1, long l2)
  348. {
  349. outstart(type);
  350. outshort(s1);
  351. outlong(l1);
  352. outlong(l2);
  353. outsend();
  354. }
  355. void
  356. outTsl(Tmesg type, int s1, long l1)
  357. {
  358. outstart(type);
  359. outshort(s1);
  360. outlong(l1);
  361. outsend();
  362. }
  363. void
  364. outTsv(Tmesg type, int s1, vlong v1)
  365. {
  366. outstart(type);
  367. outshort(s1);
  368. outvlong(v1);
  369. outsend();
  370. }
  371. void
  372. outTv(Tmesg type, vlong v1)
  373. {
  374. outstart(type);
  375. outvlong(v1);
  376. outsend();
  377. }
  378. void
  379. outTslS(Tmesg type, int s1, long l1, Rune *s)
  380. {
  381. char buf[DATASIZE*3+1];
  382. char *c;
  383. outstart(type);
  384. outshort(s1);
  385. outlong(l1);
  386. c = buf;
  387. while(*s)
  388. c += runetochar(c, s++);
  389. *c++ = 0;
  390. outcopy(c-buf, (uchar *)buf);
  391. outsend();
  392. }
  393. void
  394. outTsls(Tmesg type, int s1, long l1, int s2)
  395. {
  396. outstart(type);
  397. outshort(s1);
  398. outlong(l1);
  399. outshort(s2);
  400. outsend();
  401. }
  402. void
  403. outstart(Tmesg type)
  404. {
  405. outdata[0] = type;
  406. outcount = 0;
  407. }
  408. void
  409. outcopy(int count, uchar *data)
  410. {
  411. while(count--)
  412. outdata[HSIZE+outcount++] = *data++;
  413. }
  414. void
  415. outshort(int s)
  416. {
  417. uchar buf[2];
  418. buf[0]=s;
  419. buf[1]=s>>8;
  420. outcopy(2, buf);
  421. }
  422. void
  423. outlong(long l)
  424. {
  425. uchar buf[4];
  426. buf[0]=l;
  427. buf[1]=l>>8;
  428. buf[2]=l>>16;
  429. buf[3]=l>>24;
  430. outcopy(4, buf);
  431. }
  432. void
  433. outvlong(vlong v)
  434. {
  435. int i;
  436. uchar buf[8];
  437. for(i = 0; i < sizeof(buf); i++){
  438. buf[i] = v;
  439. v >>= 8;
  440. }
  441. outcopy(8, buf);
  442. }
  443. void
  444. outsend(void)
  445. {
  446. if(outcount>DATASIZE-HSIZE)
  447. panic("outcount>sizeof outdata");
  448. outdata[1]=outcount;
  449. outdata[2]=outcount>>8;
  450. if(write(1, (char *)outdata, outcount+HSIZE)!=outcount+HSIZE)
  451. panic("write error");
  452. }
  453. void
  454. hsetdot(int m, long p0, long p1)
  455. {
  456. Text *t = whichtext(m);
  457. Flayer *l = &t->l[t->front];
  458. flushtyping(1);
  459. flsetselect(l, p0, p1);
  460. }
  461. void
  462. horigin(int m, long p0)
  463. {
  464. Text *t = whichtext(m);
  465. Flayer *l = &t->l[t->front];
  466. long a;
  467. ulong n;
  468. Rune *r;
  469. if(!flprepare(l)){
  470. l->origin = p0;
  471. return;
  472. }
  473. a = p0-l->origin;
  474. if(a>=0 && a<l->f.nchars)
  475. frdelete(&l->f, 0, a);
  476. else if(a<0 && -a<l->f.nchars){
  477. r = rload(&t->rasp, p0, l->origin, &n);
  478. frinsert(&l->f, r, r+n, 0);
  479. }else
  480. frdelete(&l->f, 0, l->f.nchars);
  481. l->origin = p0;
  482. scrdraw(l, t->rasp.nrunes);
  483. if(l->visible==Some)
  484. flrefresh(l, l->entire, 0);
  485. hcheck(m);
  486. }
  487. void
  488. hmoveto(int m, long p0)
  489. {
  490. Text *t = whichtext(m);
  491. Flayer *l = &t->l[t->front];
  492. if(p0<l->origin || p0-l->origin>l->f.nchars*9/10)
  493. outTsll(Torigin, m, p0, 2L);
  494. }
  495. void
  496. hcheck(int m)
  497. {
  498. Flayer *l;
  499. Text *t;
  500. int reqd = 0, i;
  501. long n, nl, a;
  502. Rune *r;
  503. if(m == Untagged)
  504. return;
  505. t = whichtext(m);
  506. if(t == 0) /* possible in a half-built window */
  507. return;
  508. for(l = &t->l[0], i = 0; i<NL; i++, l++){
  509. if(l->textfn==0 || !flprepare(l)) /* BUG: don't
  510. need this if BUG below
  511. is fixed */
  512. continue;
  513. a = t->l[i].origin;
  514. n = rcontig(&t->rasp, a, a+l->f.nchars, 1);
  515. if(n<l->f.nchars) /* text missing in middle of screen */
  516. a+=n;
  517. else{ /* text missing at end of screen? */
  518. Again:
  519. if(l->f.lastlinefull)
  520. goto Checksel; /* all's well */
  521. a = t->l[i].origin+l->f.nchars;
  522. n = t->rasp.nrunes-a;
  523. if(n==0)
  524. goto Checksel;
  525. if(n>TBLOCKSIZE)
  526. n = TBLOCKSIZE;
  527. n = rcontig(&t->rasp, a, a+n, 1);
  528. if(n>0){
  529. rload(&t->rasp, a, a+n, 0);
  530. nl = l->f.nchars;
  531. r = scratch;
  532. flinsert(l, r, r+n, l->origin+nl);
  533. if(nl == l->f.nchars) /* made no progress */
  534. goto Checksel;
  535. goto Again;
  536. }
  537. }
  538. if(!reqd){
  539. n = rcontig(&t->rasp, a, a+TBLOCKSIZE, 0);
  540. if(n <= 0)
  541. panic("hcheck request==0");
  542. outTsls(Trequest, m, a, (int)n);
  543. outTs(Tcheck, m);
  544. t->lock++; /* for the Trequest */
  545. t->lock++; /* for the Tcheck */
  546. reqd++;
  547. }
  548. Checksel:
  549. flsetselect(l, l->p0, l->p1);
  550. }
  551. }
  552. void
  553. flnewlyvisible(Flayer *l)
  554. {
  555. hcheck(((Text *)l->user1)->tag);
  556. }
  557. void
  558. hsetsnarf(int nc)
  559. {
  560. char *s2;
  561. char *s1;
  562. int i;
  563. int n;
  564. setcursor(mousectl, &deadmouse);
  565. s2 = alloc(nc+1);
  566. for(i=0; i<nc; i++)
  567. s2[i] = getch();
  568. s2[nc] = 0;
  569. n = snarfswap(s2, nc, &s1);
  570. if(n >= 0){
  571. if(!s1)
  572. n = 0;
  573. if(n > SNARFSIZE){
  574. s1 = strdup("<snarf too long>");
  575. if (!s1)
  576. panic("strdup");
  577. n = strlen(s1);
  578. }else{
  579. s1 = realloc(s1, n+1);
  580. if (!s1)
  581. panic("realloc");
  582. s1[n] = 0;
  583. }
  584. snarflen = n;
  585. outTs(Tsetsnarf, n);
  586. if(n>0 && write(1, s1, n)!=n)
  587. panic("snarf write error");
  588. free(s1);
  589. }else
  590. outTs(Tsetsnarf, 0);
  591. free(s2);
  592. setcursor(mousectl, cursor);
  593. }
  594. void
  595. hplumb(int nc)
  596. {
  597. int i;
  598. char *s;
  599. Plumbmsg *m;
  600. s = alloc(nc);
  601. for(i=0; i<nc; i++)
  602. s[i] = getch();
  603. if(plumbfd > 0){
  604. m = plumbunpack(s, nc);
  605. if(m != 0)
  606. plumbsend(plumbfd, m);
  607. plumbfree(m);
  608. }
  609. free(s);
  610. }
  611. void
  612. hgrow(int m, long a, long new, int req)
  613. {
  614. int i;
  615. Flayer *l;
  616. Text *t = whichtext(m);
  617. long o, b;
  618. if(new <= 0)
  619. panic("hgrow");
  620. rresize(&t->rasp, a, 0L, new);
  621. for(l = &t->l[0], i = 0; i<NL; i++, l++){
  622. if(l->textfn == 0)
  623. continue;
  624. o = l->origin;
  625. b = a-o-rmissing(&t->rasp, o, a);
  626. if(a < o)
  627. l->origin+=new;
  628. if(a < l->p0)
  629. l->p0+=new;
  630. if(a < l->p1)
  631. l->p1+=new;
  632. /* must prevent b temporarily becoming unsigned */
  633. if(!req || a<o || (b>0 && b>l->f.nchars) ||
  634. (l->f.nchars==0 && a-o>0))
  635. continue;
  636. if(new>TBLOCKSIZE)
  637. new = TBLOCKSIZE;
  638. outTsls(Trequest, m, a, (int)new);
  639. t->lock++;
  640. req = 0;
  641. }
  642. }
  643. int
  644. hdata1(Text *t, long a, Rune *r, int len)
  645. {
  646. int i;
  647. Flayer *l;
  648. long o, b;
  649. for(l = &t->l[0], i=0; i<NL; i++, l++){
  650. if(l->textfn==0)
  651. continue;
  652. o = l->origin;
  653. b = a-o-rmissing(&t->rasp, o, a);
  654. /* must prevent b temporarily becoming unsigned */
  655. if(a<o || (b>0 && b>l->f.nchars))
  656. continue;
  657. flinsert(l, r, r+len, o+b);
  658. }
  659. rdata(&t->rasp, a, a+len, r);
  660. rclean(&t->rasp);
  661. return len;
  662. }
  663. int
  664. hdata(int m, long a, uchar *s, int len)
  665. {
  666. int i, w;
  667. Text *t = whichtext(m);
  668. Rune buf[DATASIZE], *r;
  669. if(t->lock)
  670. --t->lock;
  671. if(len == 0)
  672. return 0;
  673. r = buf;
  674. for(i=0; i<len; i+=w,s+=w)
  675. w = chartorune(r++, (char*)s);
  676. return hdata1(t, a, buf, r-buf);
  677. }
  678. int
  679. hdatarune(int m, long a, Rune *r, int len)
  680. {
  681. Text *t = whichtext(m);
  682. if(t->lock)
  683. --t->lock;
  684. if(len == 0)
  685. return 0;
  686. return hdata1(t, a, r, len);
  687. }
  688. void
  689. hcut(int m, long a, long old)
  690. {
  691. Flayer *l;
  692. Text *t = whichtext(m);
  693. int i;
  694. long o, b;
  695. if(t->lock)
  696. --t->lock;
  697. for(l = &t->l[0], i = 0; i<NL; i++, l++){
  698. if(l->textfn == 0)
  699. continue;
  700. o = l->origin;
  701. b = a-o-rmissing(&t->rasp, o, a);
  702. /* must prevent b temporarily becoming unsigned */
  703. if((b<0 || b<l->f.nchars) && a+old>=o){
  704. fldelete(l, b<0? o : o+b,
  705. a+old-rmissing(&t->rasp, o, a+old));
  706. }
  707. if(a+old<o)
  708. l->origin-=old;
  709. else if(a<=o)
  710. l->origin = a;
  711. if(a+old<l->p0)
  712. l->p0-=old;
  713. else if(a<=l->p0)
  714. l->p0 = a;
  715. if(a+old<l->p1)
  716. l->p1-=old;
  717. else if(a<=l->p1)
  718. l->p1 = a;
  719. }
  720. rresize(&t->rasp, a, old, 0L);
  721. rclean(&t->rasp);
  722. }