plan9port

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

menu.c (6531B)


      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 "flayer.h"
     10 #include "samterm.h"
     11 
     12 uchar	**name;	/* first byte is ' ' or '\'': modified state */
     13 Text	**text;	/* pointer to Text associated with file */
     14 ushort	*tag;		/* text[i].tag, even if text[i] not defined */
     15 int	nname;
     16 int	mname;
     17 int	mw;
     18 
     19 char	*genmenu3(int);
     20 char	*genmenu2(int);
     21 char	*genmenu2c(int);
     22 
     23 enum Menu2
     24 {
     25 	Cut,
     26 	Paste,
     27 	Snarf,
     28 	Plumb,
     29 	Look,
     30 	Exch,
     31 	Search,
     32 	NMENU2 = Search,
     33 	Send = Search,
     34 	NMENU2C
     35 };
     36 
     37 enum Menu3
     38 {
     39 	New,
     40 	Zerox,
     41 	Resize,
     42 	Close,
     43 	Write,
     44 	NMENU3
     45 };
     46 
     47 char	*menu2str[] = {
     48 	"cut",
     49 	"paste",
     50 	"snarf",
     51 	"plumb",
     52 	"look",
     53 	"<rio>",
     54 	0,		/* storage for last pattern */
     55 };
     56 
     57 char	*menu3str[] = {
     58 	"new",
     59 	"zerox",
     60 	"resize",
     61 	"close",
     62 	"write"
     63 };
     64 
     65 Menu	menu2 =	{0, genmenu2};
     66 Menu	menu2c ={0, genmenu2c};
     67 Menu	menu3 =	{0, genmenu3};
     68 
     69 void
     70 menu2hit(void)
     71 {
     72 	Text *t=(Text *)which->user1;
     73 	int w = which-t->l;
     74 	int m;
     75 
     76 	if(hversion==0 || plumbfd<0)
     77 		menu2str[Plumb] = "(plumb)";
     78 	m = menuhit(2, mousectl, t==&cmd? &menu2c : &menu2, nil);
     79 	if(hostlock || t->lock)
     80 		return;
     81 
     82 	switch(m){
     83 	case Cut:
     84 		cut(t, w, 1, 1);
     85 		break;
     86 
     87 	case Paste:
     88 		paste(t, w);
     89 		break;
     90 
     91 	case Snarf:
     92 		snarf(t, w);
     93 		break;
     94 
     95 	case Plumb:
     96 		if(hversion > 0)
     97 			outTsll(Tplumb, t->tag, which->p0, which->p1);
     98 		break;
     99 
    100 	case Exch:
    101 		snarf(t, w);
    102 		outT0(Tstartsnarf);
    103 		setlock();
    104 		break;
    105 
    106 	case Look:
    107 		outTsll(Tlook, t->tag, which->p0, which->p1);
    108 		setlock();
    109 		break;
    110 
    111 	case Search:
    112 		outcmd();
    113 		if(t==&cmd)
    114 			outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1);
    115 		else
    116 			outT0(Tsearch);
    117 		setlock();
    118 		break;
    119 	}
    120 }
    121 
    122 void
    123 menu3hit(void)
    124 {
    125 	Rectangle r;
    126 	Flayer *l;
    127 	int m, i;
    128 	Text *t;
    129 
    130 	mw = -1;
    131 	m = menuhit(3, mousectl, &menu3, nil);
    132 	switch(m){
    133 	case -1:
    134 		break;
    135 
    136 	case New:
    137 		if(!hostlock)
    138 			sweeptext(1, 0);
    139 		break;
    140 
    141 	case Zerox:
    142 	case Resize:
    143 		if(!hostlock){
    144 			setcursor(mousectl, &bullseye);
    145 			buttons(Down);
    146 			if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && getr(&r))
    147 				duplicate(l, r, l->f.font, m==Resize);
    148 			else
    149 				setcursor(mousectl, cursor);
    150 			buttons(Up);
    151 		}
    152 		break;
    153 
    154 	case Close:
    155 		if(!hostlock){
    156 			setcursor(mousectl, &bullseye);
    157 			buttons(Down);
    158 			if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && !hostlock){
    159 				t=(Text *)l->user1;
    160 				if (t->nwin>1)
    161 					closeup(l);
    162 				else if(t!=&cmd) {
    163 					outTs(Tclose, t->tag);
    164 					setlock();
    165 				}
    166 			}
    167 			setcursor(mousectl, cursor);
    168 			buttons(Up);
    169 		}
    170 		break;
    171 
    172 	case Write:
    173 		if(!hostlock){
    174 			setcursor(mousectl, &bullseye);
    175 			buttons(Down);
    176 			if((mousep->buttons&4) && (l = flwhich(mousep->xy))){
    177 				outTs(Twrite, ((Text *)l->user1)->tag);
    178 				setlock();
    179 			}else
    180 				setcursor(mousectl, cursor);
    181 			buttons(Up);
    182 		}
    183 		break;
    184 
    185 	default:
    186 		if(t = text[m-NMENU3]){
    187 			i = t->front;
    188 			if(t->nwin==0 || t->l[i].textfn==0)
    189 				return;	/* not ready yet; try again later */
    190 			if(t->nwin>1 && which==&t->l[i])
    191 				do
    192 					if(++i==NL)
    193 						i = 0;
    194 				while(i!=t->front && t->l[i].textfn==0);
    195 			current(&t->l[i]);
    196 		}else if(!hostlock)
    197 			sweeptext(0, tag[m-NMENU3]);
    198 		break;
    199 	}
    200 }
    201 
    202 
    203 Text *
    204 sweeptext(int new, int tag)
    205 {
    206 	Rectangle r;
    207 	Text *t;
    208 
    209 	if(getr(&r) && (t = malloc(sizeof(Text)))){
    210 		memset((void*)t, 0, sizeof(Text));
    211 		current((Flayer *)0);
    212 		flnew(&t->l[0], gettext, 0, (char *)t);
    213 		flinit(&t->l[0], r, font, maincols);	/*bnl*/
    214 		t->nwin = 1;
    215 		rinit(&t->rasp);
    216 		if(new)
    217 			startnewfile(Tstartnewfile, t);
    218 		else{
    219 			rinit(&t->rasp);
    220 			t->tag = tag;
    221 			startfile(t);
    222 		}
    223 		return t;
    224 	}
    225 	return 0;
    226 }
    227 
    228 int
    229 whichmenu(int tg)
    230 {
    231 	int i;
    232 
    233 	for(i=0; i<nname; i++)
    234 		if(tag[i] == tg)
    235 			return i;
    236 	return -1;
    237 }
    238 
    239 void
    240 menuins(int n, uchar *s, Text *t, int m, int tg)
    241 {
    242 	int i;
    243 
    244 	if(nname == mname){
    245 		if(mname == 0)
    246 			mname = 32;
    247 		else
    248 			mname *= 2;
    249 		name = realloc(name, sizeof(name[0])*mname);
    250 		text = realloc(text, sizeof(text[0])*mname);
    251 		tag = realloc(tag, sizeof(tag[0])*mname);
    252 		if(name==nil || text==nil || tag==nil)
    253 			panic("realloc");
    254 	}
    255 	for(i=nname; i>n; --i)
    256 		name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1];
    257 	text[n] = t;
    258 	tag[n] = tg;
    259 	name[n] = alloc(strlen((char*)s)+2);
    260 	name[n][0] = m;
    261 	strcpy((char*)name[n]+1, (char*)s);
    262 	nname++;
    263 	menu3.lasthit = n+NMENU3;
    264 }
    265 
    266 void
    267 menudel(int n)
    268 {
    269 	int i;
    270 
    271 	if(nname==0 || n>=nname || text[n])
    272 		panic("menudel");
    273 	free(name[n]);
    274 	--nname;
    275 	for(i = n; i<nname; i++)
    276 		name[i]=name[i+1], text[i]=text[i+1], tag[i]=tag[i+1];
    277 }
    278 
    279 void
    280 setpat(char *s)
    281 {
    282 	static char pat[17];
    283 
    284 	pat[0] = '/';
    285 	strncpy(pat+1, s, 15);
    286 	menu2str[Search] = pat;
    287 }
    288 
    289 #define	NBUF	64
    290 static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};
    291 
    292 char *
    293 paren(char *s)
    294 {
    295 	uchar *t = buf;
    296 
    297 	*t++ = '(';
    298 	do; while(*t++ = *s++);
    299 	t[-1] = ')';
    300 	*t = 0;
    301 	return (char *)buf;
    302 }
    303 char*
    304 genmenu2(int n)
    305 {
    306 	Text *t=(Text *)which->user1;
    307 	char *p;
    308 	if(n>=NMENU2+(menu2str[Search]!=0))
    309 		return 0;
    310 	p = menu2str[n];
    311 	if(!hostlock && !t->lock || n==Search || n==Look)
    312 		return p;
    313 	return paren(p);
    314 }
    315 char*
    316 genmenu2c(int n)
    317 {
    318 	Text *t=(Text *)which->user1;
    319 	char *p;
    320 	if(n >= NMENU2C)
    321 		return 0;
    322 	if(n == Send)
    323 		p="send";
    324 	else
    325 		p = menu2str[n];
    326 	if(!hostlock && !t->lock)
    327 		return p;
    328 	return paren(p);
    329 }
    330 char *
    331 genmenu3(int n)
    332 {
    333 	Text *t;
    334 	int c, i, k, l, w;
    335 	Rune r;
    336 	char *p;
    337 
    338 	if(n >= NMENU3+nname)
    339 		return 0;
    340 	if(n < NMENU3){
    341 		p = menu3str[n];
    342 		if(hostlock)
    343 			p = paren(p);
    344 		return p;
    345 	}
    346 	n -= NMENU3;
    347 	if(n == 0)	/* unless we've been fooled, this is cmd */
    348 		return (char *)&name[n][1];
    349 	if(mw == -1){
    350 		mw = 7;	/* strlen("~~sam~~"); */
    351 		for(i=1; i<nname; i++){
    352 			w = utflen((char*)name[i]+1)+4;	/* include "'+. " */
    353 			if(w > mw)
    354 				mw = w;
    355 		}
    356 	}
    357 	if(mw > NBUF)
    358 		mw = NBUF;
    359 	t = text[n];
    360 	buf[0] = name[n][0];
    361 	buf[1] = '-';
    362 	buf[2] = ' ';
    363 	buf[3] = ' ';
    364 	if(t){
    365 		if(t->nwin == 1)
    366 			buf[1] = '+';
    367 		else if(t->nwin > 1)
    368 			buf[1] = '*';
    369 		if(work && t==(Text *)work->user1) {
    370 			buf[2]= '.';
    371 			if(modified)
    372 				buf[0] = '\'';
    373 		}
    374 	}
    375 	l = utflen((char*)name[n]+1);
    376 	if(l > NBUF-4-2){
    377 		i = 4;
    378 		k = 1;
    379 		while(i < NBUF/2){
    380 			k += chartorune(&r, (char*)name[n]+k);
    381 			i++;
    382 		}
    383 		c = name[n][k];
    384 		name[n][k] = 0;
    385 		strcpy((char*)buf+4, (char*)name[n]+1);
    386 		name[n][k] = c;
    387 		strcat((char*)buf, "...");
    388 		while((l-i) >= NBUF/2-4){
    389 			k += chartorune(&r, (char*)name[n]+k);
    390 			i++;
    391 		}
    392 		strcat((char*)buf, (char*)name[n]+k);
    393 	}else
    394 		strcpy((char*)buf+4, (char*)name[n]+1);
    395 	i = utflen((char*)buf);
    396 	k = strlen((char*)buf);
    397 	while(i<mw && k<sizeof buf-1){
    398 		buf[k++] = ' ';
    399 		i++;
    400 	}
    401 	buf[k] = 0;
    402 	return (char *)buf;
    403 }