xref: /plan9/sys/src/cmd/samterm/main.c (revision a1216cc64119db675aa140f55fbd73eb2414b763)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
83e12c5d1SDavid du Colombier #include <frame.h>
93e12c5d1SDavid du Colombier #include "flayer.h"
103e12c5d1SDavid du Colombier #include "samterm.h"
113e12c5d1SDavid du Colombier 
12*a1216cc6SDavid du Colombier int	mainstacksize = 16*1024;
13*a1216cc6SDavid du Colombier 
143e12c5d1SDavid du Colombier Text	cmd;
153e12c5d1SDavid du Colombier Rune	*scratch;
163e12c5d1SDavid du Colombier long	nscralloc;
173e12c5d1SDavid du Colombier Cursor	*cursor;
183e12c5d1SDavid du Colombier Flayer	*which = 0;
193e12c5d1SDavid du Colombier Flayer	*work = 0;
203e12c5d1SDavid du Colombier long	snarflen;
213e12c5d1SDavid du Colombier long	typestart = -1;
223e12c5d1SDavid du Colombier long	typeend = -1;
233e12c5d1SDavid du Colombier long	typeesc = -1;
243e12c5d1SDavid du Colombier long	modified = 0;		/* strange lookahead for menus */
257dd7cddfSDavid du Colombier char	hostlock = 1;
263e12c5d1SDavid du Colombier char	hasunlocked = 0;
277dd7cddfSDavid du Colombier int	maxtab = 8;
28e7d29567SDavid du Colombier int	autoindent;
293e12c5d1SDavid du Colombier 
303e12c5d1SDavid du Colombier void
threadmain(int argc,char * argv[])317dd7cddfSDavid du Colombier threadmain(int argc, char *argv[])
323e12c5d1SDavid du Colombier {
33bd389b36SDavid du Colombier 	int i, got, scr;
343e12c5d1SDavid du Colombier 	Text *t;
353e12c5d1SDavid du Colombier 	Rectangle r;
363e12c5d1SDavid du Colombier 	Flayer *nwhich;
373e12c5d1SDavid du Colombier 
383e12c5d1SDavid du Colombier 	getscreen(argc, argv);
393e12c5d1SDavid du Colombier 	iconinit();
403e12c5d1SDavid du Colombier 	initio();
413e12c5d1SDavid du Colombier 	scratch = alloc(100*RUNESIZE);
423e12c5d1SDavid du Colombier 	nscralloc = 100;
437dd7cddfSDavid du Colombier 	r = screen->r;
443e12c5d1SDavid du Colombier 	r.max.y = r.min.y+Dy(r)/5;
457dd7cddfSDavid du Colombier 	flstart(screen->clipr);
463e12c5d1SDavid du Colombier 	rinit(&cmd.rasp);
473e12c5d1SDavid du Colombier 	flnew(&cmd.l[0], gettext, 1, &cmd);
487dd7cddfSDavid du Colombier 	flinit(&cmd.l[0], r, font, cmdcols);
493e12c5d1SDavid du Colombier 	cmd.nwin = 1;
503e12c5d1SDavid du Colombier 	which = &cmd.l[0];
513e12c5d1SDavid du Colombier 	cmd.tag = Untagged;
523e12c5d1SDavid du Colombier 	outTs(Tversion, VERSION);
533e12c5d1SDavid du Colombier 	startnewfile(Tstartcmdfile, &cmd);
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 	got = 0;
563e12c5d1SDavid du Colombier 	for(;;got = waitforio()){
577dd7cddfSDavid du Colombier 		if(hasunlocked && RESIZED())
587dd7cddfSDavid du Colombier 			resize();
597dd7cddfSDavid du Colombier 		if(got&(1<<RHost))
603e12c5d1SDavid du Colombier 			rcv();
617dd7cddfSDavid du Colombier 		if(got&(1<<RPlumb)){
62bd389b36SDavid du Colombier 			for(i=0; cmd.l[i].textfn==0; i++)
63bd389b36SDavid du Colombier 				;
64bd389b36SDavid du Colombier 			current(&cmd.l[i]);
65bd389b36SDavid du Colombier 			flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes);
667dd7cddfSDavid du Colombier 			type(which, RPlumb);
67bd389b36SDavid du Colombier 		}
687dd7cddfSDavid du Colombier 		if(got&(1<<RKeyboard))
693e12c5d1SDavid du Colombier 			if(which)
70bd389b36SDavid du Colombier 				type(which, RKeyboard);
713e12c5d1SDavid du Colombier 			else
723e12c5d1SDavid du Colombier 				kbdblock();
737dd7cddfSDavid du Colombier 		if(got&(1<<RMouse)){
747dd7cddfSDavid du Colombier 			if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){
753e12c5d1SDavid du Colombier 				mouseunblock();
763e12c5d1SDavid du Colombier 				continue;
773e12c5d1SDavid du Colombier 			}
787dd7cddfSDavid du Colombier 			nwhich = flwhich(mousep->xy);
797dd7cddfSDavid du Colombier 			scr = which && ptinrect(mousep->xy, which->scroll);
807dd7cddfSDavid du Colombier 			if(mousep->buttons)
813e12c5d1SDavid du Colombier 				flushtyping(1);
827dd7cddfSDavid du Colombier 			if(mousep->buttons&1){
833e12c5d1SDavid du Colombier 				if(nwhich){
843e12c5d1SDavid du Colombier 					if(nwhich!=which)
853e12c5d1SDavid du Colombier 						current(nwhich);
863e12c5d1SDavid du Colombier 					else if(scr)
873e12c5d1SDavid du Colombier 						scroll(which, 1);
883e12c5d1SDavid du Colombier 					else{
893e12c5d1SDavid du Colombier 						t=(Text *)which->user1;
903e12c5d1SDavid du Colombier 						if(flselect(which)){
913e12c5d1SDavid du Colombier 							outTsl(Tdclick, t->tag, which->p0);
923e12c5d1SDavid du Colombier 							t->lock++;
933e12c5d1SDavid du Colombier 						}else if(t!=&cmd)
943e12c5d1SDavid du Colombier 							outcmd();
953e12c5d1SDavid du Colombier 					}
963e12c5d1SDavid du Colombier 				}
977dd7cddfSDavid du Colombier 			}else if((mousep->buttons&2) && which){
983e12c5d1SDavid du Colombier 				if(scr)
993e12c5d1SDavid du Colombier 					scroll(which, 2);
1003e12c5d1SDavid du Colombier 				else
1013e12c5d1SDavid du Colombier 					menu2hit();
1027dd7cddfSDavid du Colombier 			}else if((mousep->buttons&4)){
1033e12c5d1SDavid du Colombier 				if(scr)
1043e12c5d1SDavid du Colombier 					scroll(which, 3);
1053e12c5d1SDavid du Colombier 				else
1063e12c5d1SDavid du Colombier 					menu3hit();
1073e12c5d1SDavid du Colombier 			}
1083e12c5d1SDavid du Colombier 			mouseunblock();
1093e12c5d1SDavid du Colombier 		}
1103e12c5d1SDavid du Colombier 	}
1113e12c5d1SDavid du Colombier }
1123e12c5d1SDavid du Colombier 
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier void
resize(void)115e7d29567SDavid du Colombier resize(void)
116e7d29567SDavid du Colombier {
1173e12c5d1SDavid du Colombier 	int i;
1183e12c5d1SDavid du Colombier 
1197dd7cddfSDavid du Colombier 	flresize(screen->clipr);
1203e12c5d1SDavid du Colombier 	for(i = 0; i<nname; i++)
1213e12c5d1SDavid du Colombier 		if(text[i])
1223e12c5d1SDavid du Colombier 			hcheck(text[i]->tag);
1233e12c5d1SDavid du Colombier }
1243e12c5d1SDavid du Colombier 
1253e12c5d1SDavid du Colombier void
current(Flayer * nw)1263e12c5d1SDavid du Colombier current(Flayer *nw)
1273e12c5d1SDavid du Colombier {
1283e12c5d1SDavid du Colombier 	Text *t;
1293e12c5d1SDavid du Colombier 
1303e12c5d1SDavid du Colombier 	if(which)
1313e12c5d1SDavid du Colombier 		flborder(which, 0);
1323e12c5d1SDavid du Colombier 	if(nw){
1333e12c5d1SDavid du Colombier 		flushtyping(1);
1343e12c5d1SDavid du Colombier 		flupfront(nw);
1353e12c5d1SDavid du Colombier 		flborder(nw, 1);
1363e12c5d1SDavid du Colombier 		buttons(Up);
1373e12c5d1SDavid du Colombier 		t = (Text *)nw->user1;
1383e12c5d1SDavid du Colombier 		t->front = nw-&t->l[0];
1393e12c5d1SDavid du Colombier 		if(t != &cmd)
1403e12c5d1SDavid du Colombier 			work = nw;
1413e12c5d1SDavid du Colombier 	}
1423e12c5d1SDavid du Colombier 	which = nw;
1433e12c5d1SDavid du Colombier }
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier void
closeup(Flayer * l)1463e12c5d1SDavid du Colombier closeup(Flayer *l)
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier 	Text *t=(Text *)l->user1;
1493e12c5d1SDavid du Colombier 	int m;
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	m = whichmenu(t->tag);
1523e12c5d1SDavid du Colombier 	if(m < 0)
1533e12c5d1SDavid du Colombier 		return;
1543e12c5d1SDavid du Colombier 	flclose(l);
1553e12c5d1SDavid du Colombier 	if(l == which){
1563e12c5d1SDavid du Colombier 		which = 0;
1573e12c5d1SDavid du Colombier 		current(flwhich(Pt(0, 0)));
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 	if(l == work)
1603e12c5d1SDavid du Colombier 		work = 0;
1613e12c5d1SDavid du Colombier 	if(--t->nwin == 0){
1623e12c5d1SDavid du Colombier 		rclear(&t->rasp);
1633e12c5d1SDavid du Colombier 		free((uchar *)t);
1643e12c5d1SDavid du Colombier 		text[m] = 0;
1653e12c5d1SDavid du Colombier 	}else if(l == &t->l[t->front]){
1663e12c5d1SDavid du Colombier 		for(m=0; m<NL; m++)	/* find one; any one will do */
1673e12c5d1SDavid du Colombier 			if(t->l[m].textfn){
1683e12c5d1SDavid du Colombier 				t->front = m;
1693e12c5d1SDavid du Colombier 				return;
1703e12c5d1SDavid du Colombier 			}
1713e12c5d1SDavid du Colombier 		panic("close");
1723e12c5d1SDavid du Colombier 	}
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier 
1753e12c5d1SDavid du Colombier Flayer *
findl(Text * t)1763e12c5d1SDavid du Colombier findl(Text *t)
1773e12c5d1SDavid du Colombier {
1783e12c5d1SDavid du Colombier 	int i;
1793e12c5d1SDavid du Colombier 	for(i = 0; i<NL; i++)
1803e12c5d1SDavid du Colombier 		if(t->l[i].textfn==0)
1813e12c5d1SDavid du Colombier 			return &t->l[i];
1823e12c5d1SDavid du Colombier 	return 0;
1833e12c5d1SDavid du Colombier }
1843e12c5d1SDavid du Colombier 
1853e12c5d1SDavid du Colombier void
duplicate(Flayer * l,Rectangle r,Font * f,int close)1863e12c5d1SDavid du Colombier duplicate(Flayer *l, Rectangle r, Font *f, int close)
1873e12c5d1SDavid du Colombier {
1883e12c5d1SDavid du Colombier 	Text *t=(Text *)l->user1;
1893e12c5d1SDavid du Colombier 	Flayer *nl = findl(t);
1903e12c5d1SDavid du Colombier 	Rune *rp;
1913e12c5d1SDavid du Colombier 	ulong n;
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier 	if(nl){
1943e12c5d1SDavid du Colombier 		flnew(nl, gettext, l->user0, (char *)t);
1957dd7cddfSDavid du Colombier 		flinit(nl, r, f, l->f.cols);
1963e12c5d1SDavid du Colombier 		nl->origin = l->origin;
1973e12c5d1SDavid du Colombier 		rp = (*l->textfn)(l, l->f.nchars, &n);
1983e12c5d1SDavid du Colombier 		flinsert(nl, rp, rp+n, l->origin);
1993e12c5d1SDavid du Colombier 		flsetselect(nl, l->p0, l->p1);
2003e12c5d1SDavid du Colombier 		if(close){
2013e12c5d1SDavid du Colombier 			flclose(l);
2023e12c5d1SDavid du Colombier 			if(l==which)
2033e12c5d1SDavid du Colombier 				which = 0;
2043e12c5d1SDavid du Colombier 		}else
2053e12c5d1SDavid du Colombier 			t->nwin++;
2063e12c5d1SDavid du Colombier 		current(nl);
2073e12c5d1SDavid du Colombier 		hcheck(t->tag);
2083e12c5d1SDavid du Colombier 	}
2097dd7cddfSDavid du Colombier 	setcursor(mousectl, cursor);
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier 
2123e12c5d1SDavid du Colombier void
buttons(int updown)2133e12c5d1SDavid du Colombier buttons(int updown)
2143e12c5d1SDavid du Colombier {
2157dd7cddfSDavid du Colombier 	while(((mousep->buttons&7)!=0) != updown)
2167dd7cddfSDavid du Colombier 		getmouse();
2173e12c5d1SDavid du Colombier }
2183e12c5d1SDavid du Colombier 
2193e12c5d1SDavid du Colombier int
getr(Rectangle * rp)2203e12c5d1SDavid du Colombier getr(Rectangle *rp)
2213e12c5d1SDavid du Colombier {
2223e12c5d1SDavid du Colombier 	Point p;
2233e12c5d1SDavid du Colombier 	Rectangle r;
2243e12c5d1SDavid du Colombier 
2257dd7cddfSDavid du Colombier 	*rp = getrect(3, mousectl);
2263e12c5d1SDavid du Colombier 	if(rp->max.x && rp->max.x-rp->min.x<=5 && rp->max.y-rp->min.y<=5){
2273e12c5d1SDavid du Colombier 		p = rp->min;
2283e12c5d1SDavid du Colombier 		r = cmd.l[cmd.front].entire;
2297dd7cddfSDavid du Colombier 		*rp = screen->r;
2303e12c5d1SDavid du Colombier 		if(cmd.nwin==1){
2313e12c5d1SDavid du Colombier 			if (p.y <= r.min.y)
2323e12c5d1SDavid du Colombier 				rp->max.y = r.min.y;
2333e12c5d1SDavid du Colombier 			else if (p.y >= r.max.y)
2343e12c5d1SDavid du Colombier 				rp->min.y = r.max.y;
2353e12c5d1SDavid du Colombier 			if (p.x <= r.min.x)
2363e12c5d1SDavid du Colombier 				rp->max.x = r.min.x;
2373e12c5d1SDavid du Colombier 			else if (p.x >= r.max.x)
2383e12c5d1SDavid du Colombier 				rp->min.x = r.max.x;
2393e12c5d1SDavid du Colombier 		}
2403e12c5d1SDavid du Colombier 	}
2417dd7cddfSDavid du Colombier 	return rectclip(rp, screen->r) &&
2423e12c5d1SDavid du Colombier 	   rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40;
2433e12c5d1SDavid du Colombier }
2443e12c5d1SDavid du Colombier 
2453e12c5d1SDavid du Colombier void
snarf(Text * t,int w)2463e12c5d1SDavid du Colombier snarf(Text *t, int w)
2473e12c5d1SDavid du Colombier {
2483e12c5d1SDavid du Colombier 	Flayer *l = &t->l[w];
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier 	if(l->p1>l->p0){
2513e12c5d1SDavid du Colombier 		snarflen = l->p1-l->p0;
2523e12c5d1SDavid du Colombier 		outTsll(Tsnarf, t->tag, l->p0, l->p1);
2533e12c5d1SDavid du Colombier 	}
2543e12c5d1SDavid du Colombier }
2553e12c5d1SDavid du Colombier 
2563e12c5d1SDavid du Colombier void
cut(Text * t,int w,int save,int check)2573e12c5d1SDavid du Colombier cut(Text *t, int w, int save, int check)
2583e12c5d1SDavid du Colombier {
2593e12c5d1SDavid du Colombier 	long p0, p1;
260bd389b36SDavid du Colombier 	Flayer *l;
2613e12c5d1SDavid du Colombier 
262bd389b36SDavid du Colombier 	l = &t->l[w];
263bd389b36SDavid du Colombier 	p0 = l->p0;
264bd389b36SDavid du Colombier 	p1 = l->p1;
265bd389b36SDavid du Colombier 	if(p0 == p1)
2663e12c5d1SDavid du Colombier 		return;
2673e12c5d1SDavid du Colombier 	if(p0 < 0)
2683e12c5d1SDavid du Colombier 		panic("cut");
2693e12c5d1SDavid du Colombier 	if(save)
2703e12c5d1SDavid du Colombier 		snarf(t, w);
2713e12c5d1SDavid du Colombier 	outTsll(Tcut, t->tag, p0, p1);
272bd389b36SDavid du Colombier 	flsetselect(l, p0, p0);
2733e12c5d1SDavid du Colombier 	t->lock++;
2743e12c5d1SDavid du Colombier 	hcut(t->tag, p0, p1-p0);
2753e12c5d1SDavid du Colombier 	if(check)
2763e12c5d1SDavid du Colombier 		hcheck(t->tag);
2773e12c5d1SDavid du Colombier }
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier void
paste(Text * t,int w)2803e12c5d1SDavid du Colombier paste(Text *t, int w)
2813e12c5d1SDavid du Colombier {
2823e12c5d1SDavid du Colombier 	if(snarflen){
2833e12c5d1SDavid du Colombier 		cut(t, w, 0, 0);
2843e12c5d1SDavid du Colombier 		t->lock++;
2853e12c5d1SDavid du Colombier 		outTsl(Tpaste, t->tag, t->l[w].p0);
2863e12c5d1SDavid du Colombier 	}
2873e12c5d1SDavid du Colombier }
2883e12c5d1SDavid du Colombier 
2893e12c5d1SDavid du Colombier void
scrorigin(Flayer * l,int but,long p0)2903e12c5d1SDavid du Colombier scrorigin(Flayer *l, int but, long p0)
2913e12c5d1SDavid du Colombier {
2923e12c5d1SDavid du Colombier 	Text *t=(Text *)l->user1;
2933e12c5d1SDavid du Colombier 
2943e12c5d1SDavid du Colombier 	switch(but){
2953e12c5d1SDavid du Colombier 	case 1:
2963e12c5d1SDavid du Colombier 		outTsll(Torigin, t->tag, l->origin, p0);
2973e12c5d1SDavid du Colombier 		break;
2983e12c5d1SDavid du Colombier 	case 2:
2993e12c5d1SDavid du Colombier 		outTsll(Torigin, t->tag, p0, 1L);
3003e12c5d1SDavid du Colombier 		break;
3013e12c5d1SDavid du Colombier 	case 3:
3023e12c5d1SDavid du Colombier 		horigin(t->tag,p0);
3033e12c5d1SDavid du Colombier 	}
3043e12c5d1SDavid du Colombier }
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier int
alnum(int c)3073e12c5d1SDavid du Colombier alnum(int c)
3083e12c5d1SDavid du Colombier {
3093e12c5d1SDavid du Colombier 	/*
3103e12c5d1SDavid du Colombier 	 * Hard to get absolutely right.  Use what we know about ASCII
3113e12c5d1SDavid du Colombier 	 * and assume anything above the Latin control characters is
3123e12c5d1SDavid du Colombier 	 * potentially an alphanumeric.
3133e12c5d1SDavid du Colombier 	 */
3143e12c5d1SDavid du Colombier 	if(c<=' ')
3153e12c5d1SDavid du Colombier 		return 0;
3163e12c5d1SDavid du Colombier 	if(0x7F<=c && c<=0xA0)
3173e12c5d1SDavid du Colombier 		return 0;
3183e12c5d1SDavid du Colombier 	if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
3193e12c5d1SDavid du Colombier 		return 0;
3203e12c5d1SDavid du Colombier 	return 1;
3213e12c5d1SDavid du Colombier }
3223e12c5d1SDavid du Colombier 
3233e12c5d1SDavid du Colombier int
raspc(Rasp * r,long p)3243e12c5d1SDavid du Colombier raspc(Rasp *r, long p)
3253e12c5d1SDavid du Colombier {
3263e12c5d1SDavid du Colombier 	ulong n;
3273e12c5d1SDavid du Colombier 	rload(r, p, p+1, &n);
3283e12c5d1SDavid du Colombier 	if(n)
3293e12c5d1SDavid du Colombier 		return scratch[0];
3303e12c5d1SDavid du Colombier 	return 0;
3313e12c5d1SDavid du Colombier }
3323e12c5d1SDavid du Colombier 
3333e12c5d1SDavid du Colombier long
ctlw(Rasp * r,long o,long p)3343e12c5d1SDavid du Colombier ctlw(Rasp *r, long o, long p)
3353e12c5d1SDavid du Colombier {
3363e12c5d1SDavid du Colombier 	int c;
3373e12c5d1SDavid du Colombier 
3383e12c5d1SDavid du Colombier 	if(--p < o)
3393e12c5d1SDavid du Colombier 		return o;
3403e12c5d1SDavid du Colombier 	if(raspc(r, p)=='\n')
3413e12c5d1SDavid du Colombier 		return p;
3423e12c5d1SDavid du Colombier 	for(; p>=o && !alnum(c=raspc(r, p)); --p)
3433e12c5d1SDavid du Colombier 		if(c=='\n')
3443e12c5d1SDavid du Colombier 			return p+1;
3453e12c5d1SDavid du Colombier 	for(; p>o && alnum(raspc(r, p-1)); --p)
3463e12c5d1SDavid du Colombier 		;
3473e12c5d1SDavid du Colombier 	return p>=o? p : o;
3483e12c5d1SDavid du Colombier }
3493e12c5d1SDavid du Colombier 
3503e12c5d1SDavid du Colombier long
ctlu(Rasp * r,long o,long p)3513e12c5d1SDavid du Colombier ctlu(Rasp *r, long o, long p)
3523e12c5d1SDavid du Colombier {
353f43e6a25SDavid du Colombier 	if(--p < o)
354f43e6a25SDavid du Colombier 		return o;
355f43e6a25SDavid du Colombier 	if(raspc(r, p)=='\n')
356f43e6a25SDavid du Colombier 		return p;
3573e12c5d1SDavid du Colombier 	for(; p-1>=o && raspc(r, p-1)!='\n'; --p)
3583e12c5d1SDavid du Colombier 		;
3593e12c5d1SDavid du Colombier 	return p>=o? p : o;
3603e12c5d1SDavid du Colombier }
3613e12c5d1SDavid du Colombier 
3623e12c5d1SDavid du Colombier int
center(Flayer * l,long a)3633e12c5d1SDavid du Colombier center(Flayer *l, long a)
3643e12c5d1SDavid du Colombier {
3653e12c5d1SDavid du Colombier 	Text *t;
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier 	t = l->user1;
3683e12c5d1SDavid du Colombier 	if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
3693e12c5d1SDavid du Colombier 		if(a > t->rasp.nrunes)
3703e12c5d1SDavid du Colombier 			a = t->rasp.nrunes;
3713e12c5d1SDavid du Colombier 		outTsll(Torigin, t->tag, a, 2L);
3723e12c5d1SDavid du Colombier 		return 1;
3733e12c5d1SDavid du Colombier 	}
3743e12c5d1SDavid du Colombier 	return 0;
3753e12c5d1SDavid du Colombier }
3763e12c5d1SDavid du Colombier 
3773e12c5d1SDavid du Colombier int
onethird(Flayer * l,long a)3783e12c5d1SDavid du Colombier onethird(Flayer *l, long a)
3793e12c5d1SDavid du Colombier {
3803e12c5d1SDavid du Colombier 	Text *t;
3813e12c5d1SDavid du Colombier 	Rectangle s;
3823e12c5d1SDavid du Colombier 	long lines;
3833e12c5d1SDavid du Colombier 
3843e12c5d1SDavid du Colombier 	t = l->user1;
3853e12c5d1SDavid du Colombier 	if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
3863e12c5d1SDavid du Colombier 		if(a > t->rasp.nrunes)
3873e12c5d1SDavid du Colombier 			a = t->rasp.nrunes;
3887dd7cddfSDavid du Colombier 		s = insetrect(l->scroll, 1);
3893e12c5d1SDavid du Colombier 		lines = ((s.max.y-s.min.y)/l->f.font->height+1)/3;
3903e12c5d1SDavid du Colombier 		if (lines < 2)
3913e12c5d1SDavid du Colombier 			lines = 2;
3923e12c5d1SDavid du Colombier 		outTsll(Torigin, t->tag, a, lines);
3933e12c5d1SDavid du Colombier 		return 1;
3943e12c5d1SDavid du Colombier 	}
3953e12c5d1SDavid du Colombier 	return 0;
3963e12c5d1SDavid du Colombier }
3973e12c5d1SDavid du Colombier 
3983e12c5d1SDavid du Colombier void
flushtyping(int clearesc)3993e12c5d1SDavid du Colombier flushtyping(int clearesc)
4003e12c5d1SDavid du Colombier {
4013e12c5d1SDavid du Colombier 	Text *t;
4023e12c5d1SDavid du Colombier 	ulong n;
4033e12c5d1SDavid du Colombier 
4043e12c5d1SDavid du Colombier 	if(clearesc)
4053e12c5d1SDavid du Colombier 		typeesc = -1;
4063e12c5d1SDavid du Colombier 	if(typestart == typeend) {
4073e12c5d1SDavid du Colombier 		modified = 0;
4083e12c5d1SDavid du Colombier 		return;
4093e12c5d1SDavid du Colombier 	}
4103e12c5d1SDavid du Colombier 	t = which->user1;
411219b2ee8SDavid du Colombier 	if(t != &cmd)
412219b2ee8SDavid du Colombier 		modified = 1;
4133e12c5d1SDavid du Colombier 	rload(&t->rasp, typestart, typeend, &n);
4143e12c5d1SDavid du Colombier 	scratch[n] = 0;
4153e12c5d1SDavid du Colombier 	if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=='\n'){
4163e12c5d1SDavid du Colombier 		setlock();
4173e12c5d1SDavid du Colombier 		outcmd();
4183e12c5d1SDavid du Colombier 	}
4193e12c5d1SDavid du Colombier 	outTslS(Ttype, t->tag, typestart, scratch);
4203e12c5d1SDavid du Colombier 	typestart = -1;
4213e12c5d1SDavid du Colombier 	typeend = -1;
4223e12c5d1SDavid du Colombier }
4233e12c5d1SDavid du Colombier 
4247dd7cddfSDavid du Colombier #define	BACKSCROLLKEY	Kup
425e7d29567SDavid du Colombier #define	ENDKEY	Kend
4263e12c5d1SDavid du Colombier #define	ESC		0x1B
427e7d29567SDavid du Colombier #define	HOMEKEY	Khome
428e7d29567SDavid du Colombier #define	LEFTARROW	Kleft
429e7d29567SDavid du Colombier #define	LINEEND	0x05
430e7d29567SDavid du Colombier #define	LINESTART	0x01
431e7d29567SDavid du Colombier #define	PAGEDOWN	Kpgdown
432e7d29567SDavid du Colombier #define	PAGEUP	Kpgup
433e7d29567SDavid du Colombier #define	RIGHTARROW	Kright
434e7d29567SDavid du Colombier #define	SCROLLKEY	Kdown
435e7d29567SDavid du Colombier 
436e7d29567SDavid du Colombier int
nontypingkey(int c)437e7d29567SDavid du Colombier nontypingkey(int c)
438e7d29567SDavid du Colombier {
439e7d29567SDavid du Colombier 	switch(c){
440e7d29567SDavid du Colombier 	case BACKSCROLLKEY:
441e7d29567SDavid du Colombier 	case ENDKEY:
442e7d29567SDavid du Colombier 	case HOMEKEY:
443e7d29567SDavid du Colombier 	case LEFTARROW:
444e7d29567SDavid du Colombier 	case LINEEND:
445e7d29567SDavid du Colombier 	case LINESTART:
446e7d29567SDavid du Colombier 	case PAGEDOWN:
447e7d29567SDavid du Colombier 	case PAGEUP:
448e7d29567SDavid du Colombier 	case RIGHTARROW:
449e7d29567SDavid du Colombier 	case SCROLLKEY:
450e7d29567SDavid du Colombier 		return 1;
451e7d29567SDavid du Colombier 	}
452e7d29567SDavid du Colombier 	return 0;
453e7d29567SDavid du Colombier }
454e7d29567SDavid du Colombier 
4553e12c5d1SDavid du Colombier 
4563e12c5d1SDavid du Colombier void
type(Flayer * l,int res)457bd389b36SDavid du Colombier type(Flayer *l, int res)	/* what a bloody mess this is */
4583e12c5d1SDavid du Colombier {
4593e12c5d1SDavid du Colombier 	Text *t = (Text *)l->user1;
4603e12c5d1SDavid du Colombier 	Rune buf[100];
4613e12c5d1SDavid du Colombier 	Rune *p = buf;
462bd389b36SDavid du Colombier 	int c, backspacing;
4637dd7cddfSDavid du Colombier 	long a, a0;
464bd389b36SDavid du Colombier 	int scrollkey;
465bd389b36SDavid du Colombier 
466bd389b36SDavid du Colombier 	scrollkey = 0;
467bd389b36SDavid du Colombier 	if(res == RKeyboard)
468e7d29567SDavid du Colombier 		scrollkey = nontypingkey(qpeekc());	/* ICK */
4693e12c5d1SDavid du Colombier 
4707dd7cddfSDavid du Colombier 	if(hostlock || t->lock){
4713e12c5d1SDavid du Colombier 		kbdblock();
4723e12c5d1SDavid du Colombier 		return;
4733e12c5d1SDavid du Colombier 	}
4743e12c5d1SDavid du Colombier 	a = l->p0;
4753e12c5d1SDavid du Colombier 	if(a!=l->p1 && !scrollkey){
4763e12c5d1SDavid du Colombier 		flushtyping(1);
4773e12c5d1SDavid du Colombier 		cut(t, t->front, 1, 1);
4783e12c5d1SDavid du Colombier 		return;	/* it may now be locked */
4793e12c5d1SDavid du Colombier 	}
480bd389b36SDavid du Colombier 	backspacing = 0;
481bd389b36SDavid du Colombier 	while((c = kbdchar())>0){
482bd389b36SDavid du Colombier 		if(res == RKeyboard){
483e7d29567SDavid du Colombier 			if(nontypingkey(c) || c==ESC)
484bd389b36SDavid du Colombier 				break;
485bd389b36SDavid du Colombier 			/* backspace, ctrl-u, ctrl-w, del */
486bd389b36SDavid du Colombier 			if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){
4873e12c5d1SDavid du Colombier 				backspacing = 1;
4883e12c5d1SDavid du Colombier 				break;
489bd389b36SDavid du Colombier 			}
490bd389b36SDavid du Colombier 		}
4913e12c5d1SDavid du Colombier 		*p++ = c;
492e7d29567SDavid du Colombier 		if(autoindent)
493e7d29567SDavid du Colombier 		if(c == '\n'){
494e7d29567SDavid du Colombier 			/* autoindent */
495e7d29567SDavid du Colombier 			int cursor, ch;
496e7d29567SDavid du Colombier 			cursor = ctlu(&t->rasp, 0, a+(p-buf)-1);
497e7d29567SDavid du Colombier 			while(p < buf+nelem(buf)){
498e7d29567SDavid du Colombier 				ch = raspc(&t->rasp, cursor++);
499e7d29567SDavid du Colombier 				if(ch == ' ' || ch == '\t')
500e7d29567SDavid du Colombier 					*p++ = ch;
501e7d29567SDavid du Colombier 				else
502e7d29567SDavid du Colombier 					break;
503e7d29567SDavid du Colombier 			}
504e7d29567SDavid du Colombier 		}
505bd389b36SDavid du Colombier 		if(c == '\n' || p >= buf+sizeof(buf)/sizeof(buf[0]))
5063e12c5d1SDavid du Colombier 			break;
5073e12c5d1SDavid du Colombier 	}
5083e12c5d1SDavid du Colombier 	if(p > buf){
5093e12c5d1SDavid du Colombier 		if(typestart < 0)
5103e12c5d1SDavid du Colombier 			typestart = a;
5113e12c5d1SDavid du Colombier 		if(typeesc < 0)
5123e12c5d1SDavid du Colombier 			typeesc = a;
5133e12c5d1SDavid du Colombier 		hgrow(t->tag, a, p-buf, 0);
5143e12c5d1SDavid du Colombier 		t->lock++;	/* pretend we Trequest'ed for hdatarune*/
5153e12c5d1SDavid du Colombier 		hdatarune(t->tag, a, buf, p-buf);
5163e12c5d1SDavid du Colombier 		a += p-buf;
5173e12c5d1SDavid du Colombier 		l->p0 = a;
5183e12c5d1SDavid du Colombier 		l->p1 = a;
5193e12c5d1SDavid du Colombier 		typeend = a;
5203e12c5d1SDavid du Colombier 		if(c=='\n' || typeend-typestart>100)
5213e12c5d1SDavid du Colombier 			flushtyping(0);
5223e12c5d1SDavid du Colombier 		onethird(l, a);
5233e12c5d1SDavid du Colombier 	}
524e7d29567SDavid du Colombier 	if(c==SCROLLKEY || c==PAGEDOWN){
5253e12c5d1SDavid du Colombier 		flushtyping(0);
5263e12c5d1SDavid du Colombier 		center(l, l->origin+l->f.nchars+1);
5273e12c5d1SDavid du Colombier 		/* backspacing immediately after outcmd(): sorry */
528e7d29567SDavid du Colombier 	}else if(c==BACKSCROLLKEY || c==PAGEUP){
5297dd7cddfSDavid du Colombier 		flushtyping(0);
5307dd7cddfSDavid du Colombier 		a0 = l->origin-l->f.nchars;
5317dd7cddfSDavid du Colombier 		if(a0 < 0)
5327dd7cddfSDavid du Colombier 			a0 = 0;
5337dd7cddfSDavid du Colombier 		center(l, a0);
534e7d29567SDavid du Colombier 	}else if(c == RIGHTARROW){
535e7d29567SDavid du Colombier 		flushtyping(0);
536e7d29567SDavid du Colombier 		a0 = l->p0;
537e7d29567SDavid du Colombier 		if(a0 < t->rasp.nrunes)
538e7d29567SDavid du Colombier 			a0++;
539e7d29567SDavid du Colombier 		flsetselect(l, a0, a0);
540e7d29567SDavid du Colombier 		center(l, a0);
541e7d29567SDavid du Colombier 	}else if(c == LEFTARROW){
542e7d29567SDavid du Colombier 		flushtyping(0);
543e7d29567SDavid du Colombier 		a0 = l->p0;
544e7d29567SDavid du Colombier 		if(a0 > 0)
545e7d29567SDavid du Colombier 			a0--;
546e7d29567SDavid du Colombier 		flsetselect(l, a0, a0);
547e7d29567SDavid du Colombier 		center(l, a0);
548e7d29567SDavid du Colombier 	}else if(c == HOMEKEY){
549e7d29567SDavid du Colombier 		flushtyping(0);
550e7d29567SDavid du Colombier 		center(l, 0);
551e7d29567SDavid du Colombier 	}else if(c == ENDKEY){
552e7d29567SDavid du Colombier 		flushtyping(0);
553e7d29567SDavid du Colombier 		center(l, t->rasp.nrunes);
554e7d29567SDavid du Colombier 	}else if(c == LINESTART || c == LINEEND){
555e7d29567SDavid du Colombier 		flushtyping(1);
556e7d29567SDavid du Colombier 		if(c == LINESTART)
557e7d29567SDavid du Colombier 			while(a > 0 && raspc(&t->rasp, a-1)!='\n')
558e7d29567SDavid du Colombier 				a--;
559e7d29567SDavid du Colombier 		else
560e7d29567SDavid du Colombier 			while(a < t->rasp.nrunes && raspc(&t->rasp, a)!='\n')
561e7d29567SDavid du Colombier 				a++;
562e7d29567SDavid du Colombier 		l->p0 = l->p1 = a;
563e7d29567SDavid du Colombier 		for(l=t->l; l<&t->l[NL]; l++)
564e7d29567SDavid du Colombier 			if(l->textfn)
565e7d29567SDavid du Colombier 				flsetselect(l, l->p0, l->p1);
5667dd7cddfSDavid du Colombier 	}else if(backspacing && !hostlock){
567e7d29567SDavid du Colombier 		/* backspacing immediately after outcmd(): sorry */
5683e12c5d1SDavid du Colombier 		if(l->f.p0>0 && a>0){
5693e12c5d1SDavid du Colombier 			switch(c){
5703e12c5d1SDavid du Colombier 			case '\b':
5713e12c5d1SDavid du Colombier 			case 0x7F:	/* del */
5723e12c5d1SDavid du Colombier 				l->p0 = a-1;
5733e12c5d1SDavid du Colombier 				break;
5743e12c5d1SDavid du Colombier 			case 0x15:	/* ctrl-u */
5753e12c5d1SDavid du Colombier 				l->p0 = ctlu(&t->rasp, l->origin, a);
5763e12c5d1SDavid du Colombier 				break;
5773e12c5d1SDavid du Colombier 			case 0x17:	/* ctrl-w */
5783e12c5d1SDavid du Colombier 				l->p0 = ctlw(&t->rasp, l->origin, a);
5793e12c5d1SDavid du Colombier 				break;
5803e12c5d1SDavid du Colombier 			}
5813e12c5d1SDavid du Colombier 			l->p1 = a;
5823e12c5d1SDavid du Colombier 			if(l->p1 != l->p0){
5833e12c5d1SDavid du Colombier 				/* cut locally if possible */
5843e12c5d1SDavid du Colombier 				if(typestart<=l->p0 && l->p1<=typeend){
5853e12c5d1SDavid du Colombier 					t->lock++;	/* to call hcut */
5863e12c5d1SDavid du Colombier 					hcut(t->tag, l->p0, l->p1-l->p0);
5873e12c5d1SDavid du Colombier 					/* hcheck is local because we know rasp is contiguous */
5883e12c5d1SDavid du Colombier 					hcheck(t->tag);
5893e12c5d1SDavid du Colombier 				}else{
5903e12c5d1SDavid du Colombier 					flushtyping(0);
5913e12c5d1SDavid du Colombier 					cut(t, t->front, 0, 1);
5923e12c5d1SDavid du Colombier 				}
5933e12c5d1SDavid du Colombier 			}
5943e12c5d1SDavid du Colombier 			if(typeesc >= l->p0)
5953e12c5d1SDavid du Colombier 				typeesc = l->p0;
5963e12c5d1SDavid du Colombier 			if(typestart >= 0){
5973e12c5d1SDavid du Colombier 				if(typestart >= l->p0)
5983e12c5d1SDavid du Colombier 					typestart = l->p0;
5993e12c5d1SDavid du Colombier 				typeend = l->p0;
6003e12c5d1SDavid du Colombier 				if(typestart == typeend){
6013e12c5d1SDavid du Colombier 					typestart = -1;
6023e12c5d1SDavid du Colombier 					typeend = -1;
6033e12c5d1SDavid du Colombier 					modified = 0;
6043e12c5d1SDavid du Colombier 				}
6053e12c5d1SDavid du Colombier 			}
6063e12c5d1SDavid du Colombier 		}
6073e12c5d1SDavid du Colombier 	}else{
6083e12c5d1SDavid du Colombier 		if(c==ESC && typeesc>=0){
6093e12c5d1SDavid du Colombier 			l->p0 = typeesc;
6103e12c5d1SDavid du Colombier 			l->p1 = a;
6113e12c5d1SDavid du Colombier 			flushtyping(1);
6123e12c5d1SDavid du Colombier 		}
6133e12c5d1SDavid du Colombier 		for(l=t->l; l<&t->l[NL]; l++)
6143e12c5d1SDavid du Colombier 			if(l->textfn)
6153e12c5d1SDavid du Colombier 				flsetselect(l, l->p0, l->p1);
6163e12c5d1SDavid du Colombier 	}
6173e12c5d1SDavid du Colombier }
6183e12c5d1SDavid du Colombier 
6193e12c5d1SDavid du Colombier 
6203e12c5d1SDavid du Colombier void
outcmd(void)6213e12c5d1SDavid du Colombier outcmd(void){
6223e12c5d1SDavid du Colombier 	if(work)
6233e12c5d1SDavid du Colombier 		outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work->p1);
6243e12c5d1SDavid du Colombier }
6253e12c5d1SDavid du Colombier 
6263e12c5d1SDavid du Colombier void
panic(char * s)6273e12c5d1SDavid du Colombier panic(char *s)
6283e12c5d1SDavid du Colombier {
6297dd7cddfSDavid du Colombier 	panic1(display, s);
6307dd7cddfSDavid du Colombier }
6317dd7cddfSDavid du Colombier 
6327dd7cddfSDavid du Colombier void
panic1(Display *,char * s)6337dd7cddfSDavid du Colombier panic1(Display*, char *s)
6347dd7cddfSDavid du Colombier {
6353e12c5d1SDavid du Colombier 	fprint(2, "samterm:panic: ");
6363e12c5d1SDavid du Colombier 	perror(s);
6373e12c5d1SDavid du Colombier 	abort();
6383e12c5d1SDavid du Colombier }
6393e12c5d1SDavid du Colombier 
6403e12c5d1SDavid du Colombier Rune*
gettext(Flayer * l,long n,ulong * np)6413e12c5d1SDavid du Colombier gettext(Flayer *l, long n, ulong *np)
6423e12c5d1SDavid du Colombier {
6433e12c5d1SDavid du Colombier 	Text *t;
6443e12c5d1SDavid du Colombier 
6453e12c5d1SDavid du Colombier 	t = l->user1;
6463e12c5d1SDavid du Colombier 	rload(&t->rasp, l->origin, l->origin+n, np);
6473e12c5d1SDavid du Colombier 	return scratch;
6483e12c5d1SDavid du Colombier }
6493e12c5d1SDavid du Colombier 
6503e12c5d1SDavid du Colombier long
scrtotal(Flayer * l)6513e12c5d1SDavid du Colombier scrtotal(Flayer *l)
6523e12c5d1SDavid du Colombier {
6533e12c5d1SDavid du Colombier 	return ((Text *)l->user1)->rasp.nrunes;
6543e12c5d1SDavid du Colombier }
6553e12c5d1SDavid du Colombier 
6563e12c5d1SDavid du Colombier void*
alloc(ulong n)6573e12c5d1SDavid du Colombier alloc(ulong n)
6583e12c5d1SDavid du Colombier {
6593e12c5d1SDavid du Colombier 	void *p;
6603e12c5d1SDavid du Colombier 
6613e12c5d1SDavid du Colombier 	p = malloc(n);
6623e12c5d1SDavid du Colombier 	if(p == 0)
6633e12c5d1SDavid du Colombier 		panic("alloc");
6643e12c5d1SDavid du Colombier 	memset(p, 0, n);
6653e12c5d1SDavid du Colombier 	return p;
6663e12c5d1SDavid du Colombier }
667