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