Blob


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"
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;
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**);
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;
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;
52 case 1:
53 h.count0 = c;
54 state++;
55 break;
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;
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 }
89 if(protodebug) print("rcv out\n");
90 }
92 Text *
93 whichtext(int tg)
94 {
95 int i;
97 for(i=0; i<nname; i++)
98 if(tag[i] == tg)
99 return text[i];
100 panic("whichtext");
101 return 0;
104 void
105 inmesg(Hmesg type, int count)
107 Text *t;
108 int i, m;
109 long l;
110 Flayer *lp;
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");
121 case Hversion:
122 hversion = m;
123 break;
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;
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;
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;
175 menuins(m, indata+2, t, i, (int)l);
176 break;
178 case Hgrow:
179 if(whichmenu(m) >= 0)
180 hgrow(m, l, inlong(6), 1);
181 break;
183 case Hnewname:
184 menuins(0, (uchar *)"", (Text *)0, ' ', m);
185 break;
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);
195 break;
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);
205 break;
207 case Hunlock:
208 clrlock();
209 break;
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);
222 break;
224 case Horigin:
225 if(whichmenu(m) >= 0)
226 horigin(m, l);
227 break;
229 case Hunlockfile:
230 if(whichmenu(m)>=0 && (t = whichtext(m))->lock){
231 --t->lock;
232 l = -1;
233 goto Checkscroll;
235 break;
237 case Hsetdot:
238 if(whichmenu(m) >= 0)
239 hsetdot(m, l, inlong(6));
240 break;
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;
250 case Hmoveto:
251 if(whichmenu(m)>=0)
252 hmoveto(m, l);
253 break;
255 case Hclean:
256 if((m = whichmenu(m)) >= 0)
257 name[m][0] = ' ';
258 break;
260 case Hdirty:
261 if((m = whichmenu(m))>=0)
262 name[m][0] = '\'';
263 break;
265 case Hdelname:
266 if((m=whichmenu(m)) >= 0)
267 menudel(m);
268 break;
270 case Hcut:
271 if(whichmenu(m) >= 0)
272 hcut(m, l, inlong(6));
273 break;
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;
284 break;
286 case Hsetpat:
287 setpat((char *)indata);
288 break;
290 case Hsetsnarf:
291 hsetsnarf(m);
292 break;
294 case Hsnarflen:
295 snarflen = inlong(0);
296 break;
298 case Hack:
299 outT0(Tack);
300 break;
302 case Hexit:
303 exiting = 1;
304 outT0(Texit);
305 threadexitsall(nil);
306 break;
308 case Hplumb:
309 hplumb(m);
310 break;
314 void
315 setlock(void)
317 hostlock++;
318 setcursor(mousectl, cursor = &lockarrow);
321 void
322 clrlock(void)
324 hasunlocked = 1;
325 if(hostlock > 0)
326 hostlock--;
327 if(hostlock == 0)
328 setcursor(mousectl, cursor=(Cursor *)0);
331 void
332 startfile(Text *t)
334 outTsv(Tstartfile, t->tag, (vlong)(uintptr)t); /* for 64-bit pointers */
335 setlock();
338 void
339 startnewfile(int type, Text *t)
341 t->tag = Untagged;
342 outTv(type, (vlong)(uintptr)t); /* for 64-bit pointers */
345 int
346 inshort(int n)
348 return indata[n]|(indata[n+1]<<8);
351 long
352 inlong(int n)
354 return indata[n]|(indata[n+1]<<8)|
355 ((long)indata[n+2]<<16)|((long)indata[n+3]<<24);
358 vlong
359 invlong(int n)
361 vlong v;
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;
369 void
370 outT0(Tmesg type)
372 outstart(type);
373 outsend();
376 void
377 outTl(Tmesg type, long l)
379 outstart(type);
380 outlong(l);
381 outsend();
384 void
385 outTs(Tmesg type, int s)
387 outstart(type);
388 outshort(s);
389 outsend();
392 void
393 outTss(Tmesg type, int s1, int s2)
395 outstart(type);
396 outshort(s1);
397 outshort(s2);
398 outsend();
401 void
402 outTsll(Tmesg type, int s1, long l1, long l2)
404 outstart(type);
405 outshort(s1);
406 outlong(l1);
407 outlong(l2);
408 outsend();
411 void
412 outTsl(Tmesg type, int s1, long l1)
414 outstart(type);
415 outshort(s1);
416 outlong(l1);
417 outsend();
420 void
421 outTsv(Tmesg type, int s1, vlong v1)
423 outstart(type);
424 outshort(s1);
425 outvlong(v1);
426 outsend();
429 void
430 outTv(Tmesg type, vlong v1)
432 outstart(type);
433 outvlong(v1);
434 outsend();
437 void
438 outTslS(Tmesg type, int s1, long l1, Rune *s)
440 char buf[DATASIZE*3+1];
441 char *c;
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();
454 void
455 outTsls(Tmesg type, int s1, long l1, int s2)
457 outstart(type);
458 outshort(s1);
459 outlong(l1);
460 outshort(s2);
461 outsend();
464 void
465 outstart(Tmesg type)
467 outdata[0] = type;
468 outcount = 0;
471 void
472 outcopy(int count, uchar *data)
474 while(count--)
475 outdata[HSIZE+outcount++] = *data++;
478 void
479 outshort(int s)
481 uchar buf[2];
483 buf[0]=s;
484 buf[1]=s>>8;
485 outcopy(2, buf);
488 void
489 outlong(long l)
491 uchar buf[4];
493 buf[0]=l;
494 buf[1]=l>>8;
495 buf[2]=l>>16;
496 buf[3]=l>>24;
497 outcopy(4, buf);
500 void
501 outvlong(vlong v)
503 int i;
504 uchar buf[8];
506 for(i = 0; i < sizeof(buf); i++){
507 buf[i] = v;
508 v >>= 8;
511 outcopy(8, buf);
514 void
515 outsend(void)
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");
526 void
527 hsetdot(int m, long p0, long p1)
529 Text *t = whichtext(m);
530 Flayer *l = &t->l[t->front];
532 flushtyping(1);
533 flsetselect(l, p0, p1);
536 void
537 horigin(int m, long p0)
539 Text *t = whichtext(m);
540 Flayer *l = &t->l[t->front];
541 long a;
542 ulong n;
543 Rune *r;
545 if(!flprepare(l)){
546 l->origin = p0;
547 return;
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);
564 void
565 hmoveto(int m, long p0)
567 Text *t = whichtext(m);
568 Flayer *l = &t->l[t->front];
570 if(p0<l->origin || p0-l->origin>l->f.nchars*9/10)
571 outTsll(Torigin, m, p0, 2L);
574 void
575 hcheck(int m)
577 Flayer *l;
578 Text *t;
579 int reqd = 0, i;
580 long n, nl, a;
581 Rune *r;
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;
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++;
628 Checksel:
629 flsetselect(l, l->p0, l->p1);
633 void
634 flnewlyvisible(Flayer *l)
636 hcheck(((Text *)l->user1)->tag);
639 void
640 hsetsnarf(int nc)
642 char *s2;
643 char *s1;
644 int i;
645 int n;
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 > 65535){
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;
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);
678 void
679 hplumb(int nc)
681 int i;
682 char *s;
683 Plumbmsg *m;
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);
694 free(s);
697 void
698 hgrow(int m, long a, long new, int req)
700 int i;
701 Flayer *l;
702 Text *t = whichtext(m);
703 long o, b;
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;
731 int
732 hdata1(Text *t, long a, Rune *r, int len)
734 int i;
735 Flayer *l;
736 long o, b;
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);
748 rdata(&t->rasp, a, a+len, r);
749 rclean(&t->rasp);
750 return len;
753 int
754 hdata(int m, long a, uchar *s, int len)
756 int i, w;
757 Text *t = whichtext(m);
758 Rune buf[DATASIZE], *r;
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);
770 int
771 hdatarune(int m, long a, Rune *r, int len)
773 Text *t = whichtext(m);
775 if(t->lock)
776 --t->lock;
777 if(len == 0)
778 return 0;
779 return hdata1(t, a, r, len);
782 void
783 hcut(int m, long a, long old)
785 Flayer *l;
786 Text *t = whichtext(m);
787 int i;
788 long o, b;
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));
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;
815 rresize(&t->rasp, a, old, 0L);
816 rclean(&t->rasp);