Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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