plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }