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;
20 void inmesg(Hmesg, int);
21 int inshort(int);
22 long inlong(int);
23 long invlong(int);
24 void hsetdot(int, long, long);
25 void hmoveto(int, long);
26 void hsetsnarf(int);
27 /* void hplumb(int); */
28 void clrlock(void);
29 int snarfswap(char*, int, char**);
31 void
32 rcv(void)
33 {
34 int c;
35 static int state = 0;
36 static int count = 0;
37 static int i = 0;
38 static int errs = 0;
40 while((c=rcvchar()) != -1)
41 switch(state){
42 case 0:
43 h.type = c;
44 state++;
45 break;
47 case 1:
48 h.count0 = c;
49 state++;
50 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;
70 case 3:
71 indata[i++] = c;
72 if(i == count){
73 zerocount:
74 indata[i] = 0;
75 inmesg(h.type, count);
76 state = count = 0;
77 continue;
78 }
79 break;
80 }
81 }
83 Text *
84 whichtext(int tg)
85 {
86 int i;
88 for(i=0; i<nname; i++)
89 if(tag[i] == tg)
90 return text[i];
91 panic("whichtext");
92 return 0;
93 }
95 void
96 inmesg(Hmesg type, int count)
97 {
98 Text *t;
99 int i, m;
100 long l;
101 Flayer *lp;
103 m = inshort(0);
104 l = inlong(2);
105 switch(type){
106 case -1:
107 panic("rcv error");
108 default:
109 fprint(2, "type %d\n", type);
110 panic("rcv unknown");
112 case Hversion:
113 hversion = m;
114 break;
116 case Hbindname:
117 l = invlong(2); /* for 64-bit pointers */
118 if((i=whichmenu(m)) < 0)
119 break;
120 /* in case of a race, a bindname may already have occurred */
121 if((t=whichtext(m)) == 0)
122 t=(Text *)l;
123 else /* let the old one win; clean up the new one */
124 while(((Text *)l)->nwin>0)
125 closeup(&((Text *)l)->l[((Text *)l)->front]);
126 text[i] = t;
127 text[i]->tag = m;
128 break;
130 case Hcurrent:
131 if(whichmenu(m)<0)
132 break;
133 t = whichtext(m);
134 i = which && ((Text *)which->user1)==&cmd && m!=cmd.tag;
135 if(t==0 && (t = sweeptext(0, m))==0)
136 break;
137 if(t->l[t->front].textfn==0)
138 panic("Hcurrent");
139 lp = &t->l[t->front];
140 if(i){
141 flupfront(lp);
142 flborder(lp, 0);
143 work = lp;
144 }else
145 current(lp);
146 break;
148 case Hmovname:
149 if((m=whichmenu(m)) < 0)
150 break;
151 t = text[m];
152 l = tag[m];
153 i = name[m][0];
154 text[m] = 0; /* suppress panic in menudel */
155 menudel(m);
156 if(t == &cmd)
157 m = 0;
158 else{
159 if (nname>0 && text[0]==&cmd)
160 m = 1;
161 else m = 0;
162 for(; m<nname; m++)
163 if(strcmp((char*)indata+2, (char*)name[m]+1)<0)
164 break;
166 menuins(m, indata+2, t, i, (int)l);
167 break;
169 case Hgrow:
170 if(whichmenu(m) >= 0)
171 hgrow(m, l, inlong(6), 1);
172 break;
174 case Hnewname:
175 menuins(0, (uchar *)"", (Text *)0, ' ', m);
176 break;
178 case Hcheck0:
179 i = whichmenu(m);
180 if(i>=0) {
181 t = text[i];
182 if(t)
183 t->lock++;
184 outTs(Tcheck, m);
186 break;
188 case Hcheck:
189 i = whichmenu(m);
190 if(i>=0) {
191 t = text[i];
192 if(t && t->lock)
193 t->lock--;
194 hcheck(m);
196 break;
198 case Hunlock:
199 clrlock();
200 break;
202 case Hdata:
203 if(whichmenu(m) >= 0)
204 l += hdata(m, l, indata+6, count-6);
205 Checkscroll:
206 if(m == cmd.tag){
207 for(i=0; i<NL; i++){
208 lp = &cmd.l[i];
209 if(lp->textfn)
210 center(lp, l>=0? l : lp->p1);
213 break;
215 case Horigin:
216 if(whichmenu(m) >= 0)
217 horigin(m, l);
218 break;
220 case Hunlockfile:
221 if(whichmenu(m)>=0 && (t = whichtext(m))->lock){
222 --t->lock;
223 l = -1;
224 goto Checkscroll;
226 break;
228 case Hsetdot:
229 if(whichmenu(m) >= 0)
230 hsetdot(m, l, inlong(6));
231 break;
233 case Hgrowdata:
234 if(whichmenu(m)<0)
235 break;
236 hgrow(m, l, inlong(6), 0);
237 whichtext(m)->lock++; /* fake the request */
238 l += hdata(m, l, indata+10, count-10);
239 goto Checkscroll;
241 case Hmoveto:
242 if(whichmenu(m)>=0)
243 hmoveto(m, l);
244 break;
246 case Hclean:
247 if((m = whichmenu(m)) >= 0)
248 name[m][0] = ' ';
249 break;
251 case Hdirty:
252 if((m = whichmenu(m))>=0)
253 name[m][0] = '\'';
254 break;
256 case Hdelname:
257 if((m=whichmenu(m)) >= 0)
258 menudel(m);
259 break;
261 case Hcut:
262 if(whichmenu(m) >= 0)
263 hcut(m, l, inlong(6));
264 break;
266 case Hclose:
267 if(whichmenu(m)<0 || (t = whichtext(m))==0)
268 break;
269 l = t->nwin;
270 for(i = 0,lp = t->l; l>0 && i<NL; i++,lp++)
271 if(lp->textfn){
272 closeup(lp);
273 --l;
275 break;
277 case Hsetpat:
278 setpat((char *)indata);
279 break;
281 case Hsetsnarf:
282 hsetsnarf(m);
283 break;
285 case Hsnarflen:
286 snarflen = inlong(0);
287 break;
289 case Hack:
290 outT0(Tack);
291 break;
293 case Hexit:
294 outT0(Texit);
295 threadexitsall(nil);
296 break;
298 /*
299 case Hplumb:
300 hplumb(m);
301 break;
302 */
306 void
307 setlock(void)
309 hostlock++;
310 setcursor(mousectl, cursor = &lockarrow);
313 void
314 clrlock(void)
316 hasunlocked = 1;
317 if(hostlock > 0)
318 hostlock--;
319 if(hostlock == 0)
320 setcursor(mousectl, cursor=(Cursor *)0);
323 void
324 startfile(Text *t)
326 outTsv(Tstartfile, t->tag, t); /* for 64-bit pointers */
327 setlock();
330 void
331 startnewfile(int type, Text *t)
333 t->tag = Untagged;
334 outTv(type, t); /* for 64-bit pointers */
337 int
338 inshort(int n)
340 return indata[n]|(indata[n+1]<<8);
343 long
344 inlong(int n)
346 return indata[n]|(indata[n+1]<<8)|
347 ((long)indata[n+2]<<16)|((long)indata[n+3]<<24);
350 long
351 invlong(int n)
353 long l;
355 l = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[n+4];
356 l = (l<<16) | (indata[n+3]<<8) | indata[n+2];
357 l = (l<<16) | (indata[n+1]<<8) | indata[n];
358 return l;
361 void
362 outT0(Tmesg type)
364 outstart(type);
365 outsend();
368 void
369 outTl(Tmesg type, long l)
371 outstart(type);
372 outlong(l);
373 outsend();
376 void
377 outTs(Tmesg type, int s)
379 outstart(type);
380 outshort(s);
381 outsend();
384 void
385 outTss(Tmesg type, int s1, int s2)
387 outstart(type);
388 outshort(s1);
389 outshort(s2);
390 outsend();
393 void
394 outTsll(Tmesg type, int s1, long l1, long l2)
396 outstart(type);
397 outshort(s1);
398 outlong(l1);
399 outlong(l2);
400 outsend();
403 void
404 outTsl(Tmesg type, int s1, long l1)
406 outstart(type);
407 outshort(s1);
408 outlong(l1);
409 outsend();
412 void
413 outTsv(Tmesg type, int s1, void *l1)
415 outstart(type);
416 outshort(s1);
417 outvlong(l1);
418 outsend();
421 void
422 outTv(Tmesg type, void *l1)
424 outstart(type);
425 outvlong(l1);
426 outsend();
429 void
430 outTslS(Tmesg type, int s1, long l1, Rune *s)
432 char buf[DATASIZE*3+1];
433 char *c;
435 outstart(type);
436 outshort(s1);
437 outlong(l1);
438 c = buf;
439 while(*s)
440 c += runetochar(c, s++);
441 *c++ = 0;
442 outcopy(c-buf, (uchar *)buf);
443 outsend();
446 void
447 outTsls(Tmesg type, int s1, long l1, int s2)
449 outstart(type);
450 outshort(s1);
451 outlong(l1);
452 outshort(s2);
453 outsend();
456 void
457 outstart(Tmesg type)
459 outdata[0] = type;
460 outcount = 0;
463 void
464 outcopy(int count, uchar *data)
466 while(count--)
467 outdata[HSIZE+outcount++] = *data++;
470 void
471 outshort(int s)
473 uchar buf[2];
475 buf[0]=s;
476 buf[1]=s>>8;
477 outcopy(2, buf);
480 void
481 outlong(long l)
483 uchar buf[4];
485 buf[0]=l;
486 buf[1]=l>>8;
487 buf[2]=l>>16;
488 buf[3]=l>>24;
489 outcopy(4, buf);
492 void
493 outvlong(void *v)
495 int i;
496 ulong l;
497 uchar buf[8];
499 l = (ulong) v;
500 for(i = 0; i < sizeof(buf); i++, l >>= 8)
501 buf[i] = l;
503 outcopy(8, buf);
506 void
507 outsend(void)
509 if(outcount>DATASIZE-HSIZE)
510 panic("outcount>sizeof outdata");
511 outdata[1]=outcount;
512 outdata[2]=outcount>>8;
513 if(write(1, (char *)outdata, outcount+HSIZE)!=outcount+HSIZE)
514 panic("write error");
518 void
519 hsetdot(int m, long p0, long p1)
521 Text *t = whichtext(m);
522 Flayer *l = &t->l[t->front];
524 flushtyping(1);
525 flsetselect(l, p0, p1);
528 void
529 horigin(int m, long p0)
531 Text *t = whichtext(m);
532 Flayer *l = &t->l[t->front];
533 long a;
534 ulong n;
535 Rune *r;
537 if(!flprepare(l)){
538 l->origin = p0;
539 return;
541 a = p0-l->origin;
542 if(a>=0 && a<l->f.nchars)
543 frdelete(&l->f, 0, a);
544 else if(a<0 && -a<l->f.nchars){
545 r = rload(&t->rasp, p0, l->origin, &n);
546 frinsert(&l->f, r, r+n, 0);
547 }else
548 frdelete(&l->f, 0, l->f.nchars);
549 l->origin = p0;
550 scrdraw(l, t->rasp.nrunes);
551 if(l->visible==Some)
552 flrefresh(l, l->entire, 0);
553 hcheck(m);
556 void
557 hmoveto(int m, long p0)
559 Text *t = whichtext(m);
560 Flayer *l = &t->l[t->front];
562 if(p0<l->origin || p0-l->origin>l->f.nchars*9/10)
563 outTsll(Torigin, m, p0, 2L);
566 void
567 hcheck(int m)
569 Flayer *l;
570 Text *t;
571 int reqd = 0, i;
572 long n, nl, a;
573 Rune *r;
575 if(m == Untagged)
576 return;
577 t = whichtext(m);
578 if(t == 0) /* possible in a half-built window */
579 return;
580 for(l = &t->l[0], i = 0; i<NL; i++, l++){
581 if(l->textfn==0 || !flprepare(l)) /* BUG: don't
582 need this if BUG below
583 is fixed */
584 continue;
585 a = t->l[i].origin;
586 n = rcontig(&t->rasp, a, a+l->f.nchars, 1);
587 if(n<l->f.nchars) /* text missing in middle of screen */
588 a+=n;
589 else{ /* text missing at end of screen? */
590 Again:
591 if(l->f.lastlinefull)
592 goto Checksel; /* all's well */
593 a = t->l[i].origin+l->f.nchars;
594 n = t->rasp.nrunes-a;
595 if(n==0)
596 goto Checksel;
597 if(n>TBLOCKSIZE)
598 n = TBLOCKSIZE;
599 n = rcontig(&t->rasp, a, a+n, 1);
600 if(n>0){
601 rload(&t->rasp, a, a+n, 0);
602 nl = l->f.nchars;
603 r = scratch;
604 flinsert(l, r, r+n, l->origin+nl);
605 if(nl == l->f.nchars) /* made no progress */
606 goto Checksel;
607 goto Again;
610 if(!reqd){
611 n = rcontig(&t->rasp, a, a+TBLOCKSIZE, 0);
612 if(n <= 0)
613 panic("hcheck request==0");
614 outTsls(Trequest, m, a, (int)n);
615 outTs(Tcheck, m);
616 t->lock++; /* for the Trequest */
617 t->lock++; /* for the Tcheck */
618 reqd++;
620 Checksel:
621 flsetselect(l, l->p0, l->p1);
625 void
626 flnewlyvisible(Flayer *l)
628 hcheck(((Text *)l->user1)->tag);
631 void
632 hsetsnarf(int nc)
634 char *s2;
635 char *s1;
636 int i;
637 int n;
639 setcursor(mousectl, &deadmouse);
640 s2 = alloc(nc+1);
641 for(i=0; i<nc; i++)
642 s2[i] = getch();
643 s2[nc] = 0;
644 n = snarfswap(s2, nc, &s1);
645 if(n >= 0){
646 if(!s1)
647 n = 0;
648 s1 = realloc(s1, n+1);
649 if (!s1)
650 panic("realloc");
651 s1[n] = 0;
652 snarflen = n;
653 outTs(Tsetsnarf, n);
654 if(n>0 && write(1, s1, n)!=n)
655 panic("snarf write error");
656 free(s1);
657 }else
658 outTs(Tsetsnarf, 0);
659 free(s2);
660 setcursor(mousectl, cursor);
663 /*
664 void
665 hplumb(int nc)
667 int i;
668 char *s;
669 Plumbmsg *m;
671 s = alloc(nc);
672 for(i=0; i<nc; i++)
673 s[i] = getch();
674 if(plumbfd > 0){
675 m = plumbunpack(s, nc);
676 if(m != 0)
677 plumbsend(plumbfd, m);
678 plumbfree(m);
680 free(s);
682 */
684 void
685 hgrow(int m, long a, long new, int req)
687 int i;
688 Flayer *l;
689 Text *t = whichtext(m);
690 long o, b;
692 if(new <= 0)
693 panic("hgrow");
694 rresize(&t->rasp, a, 0L, new);
695 for(l = &t->l[0], i = 0; i<NL; i++, l++){
696 if(l->textfn == 0)
697 continue;
698 o = l->origin;
699 b = a-o-rmissing(&t->rasp, o, a);
700 if(a < o)
701 l->origin+=new;
702 if(a < l->p0)
703 l->p0+=new;
704 if(a < l->p1)
705 l->p1+=new;
706 /* must prevent b temporarily becoming unsigned */
707 if(!req || a<o || (b>0 && b>l->f.nchars) ||
708 (l->f.nchars==0 && a-o>0))
709 continue;
710 if(new>TBLOCKSIZE)
711 new = TBLOCKSIZE;
712 outTsls(Trequest, m, a, (int)new);
713 t->lock++;
714 req = 0;
718 int
719 hdata1(Text *t, long a, Rune *r, int len)
721 int i;
722 Flayer *l;
723 long o, b;
725 for(l = &t->l[0], i=0; i<NL; i++, l++){
726 if(l->textfn==0)
727 continue;
728 o = l->origin;
729 b = a-o-rmissing(&t->rasp, o, a);
730 /* must prevent b temporarily becoming unsigned */
731 if(a<o || (b>0 && b>l->f.nchars))
732 continue;
733 flinsert(l, r, r+len, o+b);
735 rdata(&t->rasp, a, a+len, r);
736 rclean(&t->rasp);
737 return len;
740 int
741 hdata(int m, long a, uchar *s, int len)
743 int i, w;
744 Text *t = whichtext(m);
745 Rune buf[DATASIZE], *r;
747 if(t->lock)
748 --t->lock;
749 if(len == 0)
750 return 0;
751 r = buf;
752 for(i=0; i<len; i+=w,s+=w)
753 w = chartorune(r++, (char*)s);
754 return hdata1(t, a, buf, r-buf);
757 int
758 hdatarune(int m, long a, Rune *r, int len)
760 Text *t = whichtext(m);
762 if(t->lock)
763 --t->lock;
764 if(len == 0)
765 return 0;
766 return hdata1(t, a, r, len);
769 void
770 hcut(int m, long a, long old)
772 Flayer *l;
773 Text *t = whichtext(m);
774 int i;
775 long o, b;
777 if(t->lock)
778 --t->lock;
779 for(l = &t->l[0], i = 0; i<NL; i++, l++){
780 if(l->textfn == 0)
781 continue;
782 o = l->origin;
783 b = a-o-rmissing(&t->rasp, o, a);
784 /* must prevent b temporarily becoming unsigned */
785 if((b<0 || b<l->f.nchars) && a+old>=o){
786 fldelete(l, b<0? o : o+b,
787 a+old-rmissing(&t->rasp, o, a+old));
789 if(a+old<o)
790 l->origin-=old;
791 else if(a<=o)
792 l->origin = a;
793 if(a+old<l->p0)
794 l->p0-=old;
795 else if(a<=l->p0)
796 l->p0 = a;
797 if(a+old<l->p1)
798 l->p1-=old;
799 else if(a<=l->p1)
800 l->p1 = a;
802 rresize(&t->rasp, a, old, 0L);
803 rclean(&t->rasp);