xref: /plan9-contrib/sys/src/cmd/samterm/menu.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <libg.h>
43e12c5d1SDavid du Colombier #include <frame.h>
53e12c5d1SDavid du Colombier #include "flayer.h"
63e12c5d1SDavid du Colombier #include "samterm.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier uchar	*name[MAXFILES];	/* first byte is ' ' or '\'': modified state */
93e12c5d1SDavid du Colombier Text	*text[MAXFILES];	/* pointer to Text associated with file */
103e12c5d1SDavid du Colombier ushort	tag[MAXFILES];		/* text[i].tag, even if text[i] not defined */
113e12c5d1SDavid du Colombier int	nname;
123e12c5d1SDavid du Colombier int	mw;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier char	*genmenu3(int);
153e12c5d1SDavid du Colombier char	*genmenu2(int);
163e12c5d1SDavid du Colombier char	*genmenu2c(int);
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier enum Menu2
193e12c5d1SDavid du Colombier {
203e12c5d1SDavid du Colombier 	Cut,
213e12c5d1SDavid du Colombier 	Paste,
223e12c5d1SDavid du Colombier 	Snarf,
233e12c5d1SDavid du Colombier 	Look,
243e12c5d1SDavid du Colombier 	Exch,
253e12c5d1SDavid du Colombier 	Search,
263e12c5d1SDavid du Colombier 	NMENU2 = Search,
273e12c5d1SDavid du Colombier 	Send = Search,
283e12c5d1SDavid du Colombier 	NMENU2C
293e12c5d1SDavid du Colombier };
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier enum Menu3
323e12c5d1SDavid du Colombier {
333e12c5d1SDavid du Colombier 	New,
34*219b2ee8SDavid du Colombier 	Zerox,
353e12c5d1SDavid du Colombier 	Reshape,
363e12c5d1SDavid du Colombier 	Close,
373e12c5d1SDavid du Colombier 	Write,
383e12c5d1SDavid du Colombier 	NMENU3
393e12c5d1SDavid du Colombier };
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier char	*menu2str[] = {
423e12c5d1SDavid du Colombier 	"cut",
433e12c5d1SDavid du Colombier 	"paste",
443e12c5d1SDavid du Colombier 	"snarf",
453e12c5d1SDavid du Colombier 	"look",
463e12c5d1SDavid du Colombier 	"<8½>",
473e12c5d1SDavid du Colombier 	0,		/* storage for last pattern */
483e12c5d1SDavid du Colombier };
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier char	*menu3str[] = {
513e12c5d1SDavid du Colombier 	"new",
52*219b2ee8SDavid du Colombier 	"zerox",
533e12c5d1SDavid du Colombier 	"reshape",
543e12c5d1SDavid du Colombier 	"close",
553e12c5d1SDavid du Colombier 	"write",
563e12c5d1SDavid du Colombier };
573e12c5d1SDavid du Colombier 
583e12c5d1SDavid du Colombier Menu	menu2 =	{0, genmenu2};
593e12c5d1SDavid du Colombier Menu	menu2c ={0, genmenu2c};
603e12c5d1SDavid du Colombier Menu	menu3 =	{0, genmenu3};
613e12c5d1SDavid du Colombier 
623e12c5d1SDavid du Colombier void
633e12c5d1SDavid du Colombier menu2hit(void)
643e12c5d1SDavid du Colombier {
653e12c5d1SDavid du Colombier 	Text *t=(Text *)which->user1;
663e12c5d1SDavid du Colombier 	int w = which-t->l;
67bd389b36SDavid du Colombier 	int m;
683e12c5d1SDavid du Colombier 
69bd389b36SDavid du Colombier 	m = menuhit(2, &mouse, t==&cmd? &menu2c : &menu2);
70bd389b36SDavid du Colombier 	if(lock || t->lock)
71bd389b36SDavid du Colombier 		return;
72bd389b36SDavid du Colombier 
73bd389b36SDavid du Colombier 	switch(m){
743e12c5d1SDavid du Colombier 	case Cut:
753e12c5d1SDavid du Colombier 		cut(t, w, 1, 1);
763e12c5d1SDavid du Colombier 		break;
773e12c5d1SDavid du Colombier 
783e12c5d1SDavid du Colombier 	case Paste:
793e12c5d1SDavid du Colombier 		paste(t, w);
803e12c5d1SDavid du Colombier 		break;
813e12c5d1SDavid du Colombier 
823e12c5d1SDavid du Colombier 	case Snarf:
833e12c5d1SDavid du Colombier 		snarf(t, w);
843e12c5d1SDavid du Colombier 		break;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	case Exch:
873e12c5d1SDavid du Colombier 		outT0(Tstartsnarf);
883e12c5d1SDavid du Colombier 		setlock();
893e12c5d1SDavid du Colombier 		break;
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 	case Look:
923e12c5d1SDavid du Colombier 		outTsll(Tlook, t->tag, which->p0, which->p1);
933e12c5d1SDavid du Colombier 		setlock();
943e12c5d1SDavid du Colombier 		break;
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier 	case Search:
973e12c5d1SDavid du Colombier 		outcmd();
983e12c5d1SDavid du Colombier 		if(t==&cmd)
993e12c5d1SDavid du Colombier 			outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1);
1003e12c5d1SDavid du Colombier 		else
1013e12c5d1SDavid du Colombier 			outT0(Tsearch);
1023e12c5d1SDavid du Colombier 		setlock();
1033e12c5d1SDavid du Colombier 		break;
1043e12c5d1SDavid du Colombier 	}
1053e12c5d1SDavid du Colombier }
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier void
1083e12c5d1SDavid du Colombier menu3hit(void)
1093e12c5d1SDavid du Colombier {
1103e12c5d1SDavid du Colombier 	Rectangle r;
1113e12c5d1SDavid du Colombier 	Flayer *l;
1123e12c5d1SDavid du Colombier 	int m, i;
1133e12c5d1SDavid du Colombier 	Text *t;
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier 	mw = -1;
1163e12c5d1SDavid du Colombier 	switch(m = menuhit(3, &mouse, &menu3)){
1173e12c5d1SDavid du Colombier 	case -1:
1183e12c5d1SDavid du Colombier 		break;
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier 	case New:
1213e12c5d1SDavid du Colombier 		if(!lock)
1223e12c5d1SDavid du Colombier 			sweeptext(1, 0);
1233e12c5d1SDavid du Colombier 		break;
1243e12c5d1SDavid du Colombier 
125*219b2ee8SDavid du Colombier 	case Zerox:
1263e12c5d1SDavid du Colombier 	case Reshape:
1273e12c5d1SDavid du Colombier 		if(!lock){
1283e12c5d1SDavid du Colombier 			cursorswitch(&bullseye);
1293e12c5d1SDavid du Colombier 			buttons(Down);
1303e12c5d1SDavid du Colombier 			if((mouse.buttons&4) && (l = flwhich(mouse.xy)) && getr(&r))
1313e12c5d1SDavid du Colombier 				duplicate(l, r, l->f.font, m==Reshape);
1323e12c5d1SDavid du Colombier 			else
1333e12c5d1SDavid du Colombier 				cursorswitch(cursor);
1343e12c5d1SDavid du Colombier 			buttons(Up);
1353e12c5d1SDavid du Colombier 		}
1363e12c5d1SDavid du Colombier 		break;
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier 	case Close:
1393e12c5d1SDavid du Colombier 		if(!lock){
1403e12c5d1SDavid du Colombier 			cursorswitch(&bullseye);
1413e12c5d1SDavid du Colombier 			buttons(Down);
1423e12c5d1SDavid du Colombier 			if((mouse.buttons&4) && (l = flwhich(mouse.xy)) && !lock){
1433e12c5d1SDavid du Colombier 				t=(Text *)l->user1;
1443e12c5d1SDavid du Colombier 				if (t->nwin>1)
1453e12c5d1SDavid du Colombier 					closeup(l);
146*219b2ee8SDavid du Colombier 				else if(t!=&cmd) {
1473e12c5d1SDavid du Colombier 					outTs(Tclose, t->tag);
148*219b2ee8SDavid du Colombier 					setlock();
1493e12c5d1SDavid du Colombier 				}
1503e12c5d1SDavid du Colombier 			}
1513e12c5d1SDavid du Colombier 			cursorswitch(cursor);
1523e12c5d1SDavid du Colombier 			buttons(Up);
1533e12c5d1SDavid du Colombier 		}
1543e12c5d1SDavid du Colombier 		break;
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 	case Write:
1573e12c5d1SDavid du Colombier 		if(!lock){
1583e12c5d1SDavid du Colombier 			cursorswitch(&bullseye);
1593e12c5d1SDavid du Colombier 			buttons(Down);
1603e12c5d1SDavid du Colombier 			if((mouse.buttons&4) && (l = flwhich(mouse.xy))){
1613e12c5d1SDavid du Colombier 				outTs(Twrite, ((Text *)l->user1)->tag);
1623e12c5d1SDavid du Colombier 				setlock();
1633e12c5d1SDavid du Colombier 			}else
1643e12c5d1SDavid du Colombier 				cursorswitch(cursor);
1653e12c5d1SDavid du Colombier 			buttons(Up);
1663e12c5d1SDavid du Colombier 		}
1673e12c5d1SDavid du Colombier 		break;
1683e12c5d1SDavid du Colombier 
1693e12c5d1SDavid du Colombier 	default:
1703e12c5d1SDavid du Colombier 		if(t = text[m-NMENU3]){
1713e12c5d1SDavid du Colombier 			i = t->front;
1723e12c5d1SDavid du Colombier 			if(t->nwin==0 || t->l[i].textfn==0)
1733e12c5d1SDavid du Colombier 				return;	/* not ready yet; try again later */
1743e12c5d1SDavid du Colombier 			if(t->nwin>1 && which==&t->l[i])
1753e12c5d1SDavid du Colombier 				do
1763e12c5d1SDavid du Colombier 					if(++i==NL)
1773e12c5d1SDavid du Colombier 						i = 0;
1783e12c5d1SDavid du Colombier 				while(i!=t->front && t->l[i].textfn==0);
1793e12c5d1SDavid du Colombier 			current(&t->l[i]);
180bd389b36SDavid du Colombier 		}else if(!lock)
1813e12c5d1SDavid du Colombier 			sweeptext(0, tag[m-NMENU3]);
1823e12c5d1SDavid du Colombier 		break;
1833e12c5d1SDavid du Colombier 	}
1843e12c5d1SDavid du Colombier }
1853e12c5d1SDavid du Colombier 
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier Text *
1883e12c5d1SDavid du Colombier sweeptext(int new, int tag)
1893e12c5d1SDavid du Colombier {
1903e12c5d1SDavid du Colombier 	Rectangle r;
1913e12c5d1SDavid du Colombier 	Text *t;
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier 	if(getr(&r) && (t = malloc(sizeof(Text)))){
194*219b2ee8SDavid du Colombier 		memset((void*)t, 0, sizeof(Text));
1953e12c5d1SDavid du Colombier 		current((Flayer *)0);
1963e12c5d1SDavid du Colombier 		flnew(&t->l[0], gettext, 0, (char *)t);
1973e12c5d1SDavid du Colombier 		flinit(&t->l[0], r, font);	/*bnl*/
1983e12c5d1SDavid du Colombier 		t->nwin = 1;
1993e12c5d1SDavid du Colombier 		rinit(&t->rasp);
2003e12c5d1SDavid du Colombier 		if(new)
2013e12c5d1SDavid du Colombier 			startnewfile(Tstartnewfile, t);
2023e12c5d1SDavid du Colombier 		else{
2033e12c5d1SDavid du Colombier 			rinit(&t->rasp);
2043e12c5d1SDavid du Colombier 			t->tag = tag;
2053e12c5d1SDavid du Colombier 			startfile(t);
2063e12c5d1SDavid du Colombier 		}
2073e12c5d1SDavid du Colombier 		return t;
2083e12c5d1SDavid du Colombier 	}
2093e12c5d1SDavid du Colombier 	return 0;
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier 
2123e12c5d1SDavid du Colombier int
2133e12c5d1SDavid du Colombier whichmenu(int tg)
2143e12c5d1SDavid du Colombier {
2153e12c5d1SDavid du Colombier 	int i;
2163e12c5d1SDavid du Colombier 
2173e12c5d1SDavid du Colombier 	for(i=0; i<nname; i++)
2183e12c5d1SDavid du Colombier 		if(tag[i] == tg)
2193e12c5d1SDavid du Colombier 			return i;
2203e12c5d1SDavid du Colombier 	return -1;
2213e12c5d1SDavid du Colombier }
2223e12c5d1SDavid du Colombier 
2233e12c5d1SDavid du Colombier void
2243e12c5d1SDavid du Colombier menuins(int n, uchar *s, Text *t, int m, int tg)
2253e12c5d1SDavid du Colombier {
2263e12c5d1SDavid du Colombier 	int i;
2273e12c5d1SDavid du Colombier 
2283e12c5d1SDavid du Colombier 	if(nname == MAXFILES)
2293e12c5d1SDavid du Colombier 		panic("menuins");
2303e12c5d1SDavid du Colombier 	for(i=nname; i>n; --i)
2313e12c5d1SDavid du Colombier 		name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1];
2323e12c5d1SDavid du Colombier 	text[n] = t;
2333e12c5d1SDavid du Colombier 	tag[n] = tg;
2343e12c5d1SDavid du Colombier 	name[n] = alloc(strlen((char*)s)+2);
2353e12c5d1SDavid du Colombier 	name[n][0] = m;
2363e12c5d1SDavid du Colombier 	strcpy((char*)name[n]+1, (char*)s);
2373e12c5d1SDavid du Colombier 	nname++;
238bd389b36SDavid du Colombier 	menu3.lasthit = n+NMENU3;
2393e12c5d1SDavid du Colombier }
2403e12c5d1SDavid du Colombier 
2413e12c5d1SDavid du Colombier void
2423e12c5d1SDavid du Colombier menudel(int n)
2433e12c5d1SDavid du Colombier {
2443e12c5d1SDavid du Colombier 	int i;
2453e12c5d1SDavid du Colombier 
2463e12c5d1SDavid du Colombier 	if(nname==0 || n>=nname || text[n])
2473e12c5d1SDavid du Colombier 		panic("menudel");
2483e12c5d1SDavid du Colombier 	free(name[n]);
2493e12c5d1SDavid du Colombier 	--nname;
2503e12c5d1SDavid du Colombier 	for(i = n; i<nname; i++)
2513e12c5d1SDavid du Colombier 		name[i]=name[i+1], text[i]=text[i+1], tag[i]=tag[i+1];
2523e12c5d1SDavid du Colombier }
2533e12c5d1SDavid du Colombier 
2543e12c5d1SDavid du Colombier void
2553e12c5d1SDavid du Colombier setpat(char *s)
2563e12c5d1SDavid du Colombier {
2573e12c5d1SDavid du Colombier 	static char pat[17];
2583e12c5d1SDavid du Colombier 
2593e12c5d1SDavid du Colombier 	pat[0] = '/';
2603e12c5d1SDavid du Colombier 	strncpy(pat+1, s, 15);
2613e12c5d1SDavid du Colombier 	menu2str[Search] = pat;
2623e12c5d1SDavid du Colombier }
2633e12c5d1SDavid du Colombier 
2643e12c5d1SDavid du Colombier #define	NBUF	64
2653e12c5d1SDavid du Colombier static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier char *
2683e12c5d1SDavid du Colombier paren(char *s)
2693e12c5d1SDavid du Colombier {
2703e12c5d1SDavid du Colombier 	uchar *t = buf;
2713e12c5d1SDavid du Colombier 
2723e12c5d1SDavid du Colombier 	*t++ = '(';
2733e12c5d1SDavid du Colombier 	do; while(*t++ = *s++);
2743e12c5d1SDavid du Colombier 	t[-1] = ')';
2753e12c5d1SDavid du Colombier 	*t = 0;
2763e12c5d1SDavid du Colombier 	return (char *)buf;
2773e12c5d1SDavid du Colombier }
2783e12c5d1SDavid du Colombier char*
2793e12c5d1SDavid du Colombier genmenu2(int n)
2803e12c5d1SDavid du Colombier {
2813e12c5d1SDavid du Colombier 	Text *t=(Text *)which->user1;
2823e12c5d1SDavid du Colombier 	char *p;
2833e12c5d1SDavid du Colombier 	if(n>=NMENU2+(menu2str[Search]!=0))
2843e12c5d1SDavid du Colombier 		return 0;
2853e12c5d1SDavid du Colombier 	p = menu2str[n];
2863e12c5d1SDavid du Colombier 	if(!lock && !t->lock || n==Search || n==Look)
2873e12c5d1SDavid du Colombier 		return p;
2883e12c5d1SDavid du Colombier 	return paren(p);
2893e12c5d1SDavid du Colombier }
2903e12c5d1SDavid du Colombier char*
2913e12c5d1SDavid du Colombier genmenu2c(int n)
2923e12c5d1SDavid du Colombier {
2933e12c5d1SDavid du Colombier 	Text *t=(Text *)which->user1;
2943e12c5d1SDavid du Colombier 	char *p;
2953e12c5d1SDavid du Colombier 	if(n >= NMENU2C)
2963e12c5d1SDavid du Colombier 		return 0;
2973e12c5d1SDavid du Colombier 	if(n == Send)
2983e12c5d1SDavid du Colombier 		p="send";
2993e12c5d1SDavid du Colombier 	else
3003e12c5d1SDavid du Colombier 		p = menu2str[n];
3013e12c5d1SDavid du Colombier 	if(!lock && !t->lock)
3023e12c5d1SDavid du Colombier 		return p;
3033e12c5d1SDavid du Colombier 	return paren(p);
3043e12c5d1SDavid du Colombier }
3053e12c5d1SDavid du Colombier char *
3063e12c5d1SDavid du Colombier genmenu3(int n)
3073e12c5d1SDavid du Colombier {
3083e12c5d1SDavid du Colombier 	Text *t;
3093e12c5d1SDavid du Colombier 	int c, i, k, l, w;
3103e12c5d1SDavid du Colombier 	Rune r;
3113e12c5d1SDavid du Colombier 	char *p;
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier 	if(n >= NMENU3+nname)
3143e12c5d1SDavid du Colombier 		return 0;
3153e12c5d1SDavid du Colombier 	if(n < NMENU3){
3163e12c5d1SDavid du Colombier 		p = menu3str[n];
3173e12c5d1SDavid du Colombier 		if(lock)
3183e12c5d1SDavid du Colombier 			p = paren(p);
3193e12c5d1SDavid du Colombier 		return p;
3203e12c5d1SDavid du Colombier 	}
3213e12c5d1SDavid du Colombier 	n -= NMENU3;
3223e12c5d1SDavid du Colombier 	if(n == 0)	/* unless we've been fooled, this is cmd */
3233e12c5d1SDavid du Colombier 		return (char *)&name[n][1];
3243e12c5d1SDavid du Colombier 	if(mw == -1){
3253e12c5d1SDavid du Colombier 		mw = 7;	/* strlen("~~sam~~"); */
3263e12c5d1SDavid du Colombier 		for(i=1; i<nname; i++){
3273e12c5d1SDavid du Colombier 			w = utflen((char*)name[i]+1)+4;	/* include "'+. " */
3283e12c5d1SDavid du Colombier 			if(w > mw)
3293e12c5d1SDavid du Colombier 				mw = w;
3303e12c5d1SDavid du Colombier 		}
3313e12c5d1SDavid du Colombier 	}
3323e12c5d1SDavid du Colombier 	if(mw > NBUF)
3333e12c5d1SDavid du Colombier 		mw = NBUF;
3343e12c5d1SDavid du Colombier 	t = text[n];
3353e12c5d1SDavid du Colombier 	buf[0] = name[n][0];
3363e12c5d1SDavid du Colombier 	buf[1] = '-';
3373e12c5d1SDavid du Colombier 	buf[2] = ' ';
3383e12c5d1SDavid du Colombier 	buf[3] = ' ';
3393e12c5d1SDavid du Colombier 	if(t){
3403e12c5d1SDavid du Colombier 		if(t->nwin == 1)
3413e12c5d1SDavid du Colombier 			buf[1] = '+';
3423e12c5d1SDavid du Colombier 		else if(t->nwin > 1)
3433e12c5d1SDavid du Colombier 			buf[1] = '*';
3443e12c5d1SDavid du Colombier 		if(work && t==(Text *)work->user1) {
3453e12c5d1SDavid du Colombier 			buf[2]= '.';
3463e12c5d1SDavid du Colombier 			if(modified)
3473e12c5d1SDavid du Colombier 				buf[0] = '\'';
3483e12c5d1SDavid du Colombier 		}
3493e12c5d1SDavid du Colombier 	}
3503e12c5d1SDavid du Colombier 	l = utflen((char*)name[n]+1);
3513e12c5d1SDavid du Colombier 	if(l > NBUF-4-2){
3523e12c5d1SDavid du Colombier 		i = 4;
3533e12c5d1SDavid du Colombier 		k = 1;
3543e12c5d1SDavid du Colombier 		while(i < NBUF/2){
3553e12c5d1SDavid du Colombier 			k += chartorune(&r, (char*)name[n]+k);
3563e12c5d1SDavid du Colombier 			i++;
3573e12c5d1SDavid du Colombier 		}
3583e12c5d1SDavid du Colombier 		c = name[n][k];
3593e12c5d1SDavid du Colombier 		name[n][k] = 0;
3603e12c5d1SDavid du Colombier 		strcpy((char*)buf+4, (char*)name[n]+1);
3613e12c5d1SDavid du Colombier 		name[n][k] = c;
3623e12c5d1SDavid du Colombier 		strcat((char*)buf, "...");
3633e12c5d1SDavid du Colombier 		while((l-i) >= NBUF/2-4){
3643e12c5d1SDavid du Colombier 			k += chartorune(&r, (char*)name[n]+k);
3653e12c5d1SDavid du Colombier 			i++;
3663e12c5d1SDavid du Colombier 		}
3673e12c5d1SDavid du Colombier 		strcat((char*)buf, (char*)name[n]+k);
3683e12c5d1SDavid du Colombier 	}else
3693e12c5d1SDavid du Colombier 		strcpy((char*)buf+4, (char*)name[n]+1);
3703e12c5d1SDavid du Colombier 	i = utflen((char*)buf);
3713e12c5d1SDavid du Colombier 	k = strlen((char*)buf);
3723e12c5d1SDavid du Colombier 	while(i<mw && k<sizeof buf-1){
3733e12c5d1SDavid du Colombier 		buf[k++] = ' ';
3743e12c5d1SDavid du Colombier 		i++;
3753e12c5d1SDavid du Colombier 	}
3763e12c5d1SDavid du Colombier 	buf[k] = 0;
3773e12c5d1SDavid du Colombier 	return (char *)buf;
3783e12c5d1SDavid du Colombier }
379