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