mesg.c 12 KB

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