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 "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
	switch(m = menuhit(3, mousectl, &menu3, nil)){
132
	case -1:
133
		break;
134
 
135
	case New:
136
		if(!hostlock)
137
			sweeptext(1, 0);
138
		break;
139
 
140
	case Zerox:
141
	case Resize:
142
		if(!hostlock){
143
			setcursor(mousectl, &bullseye);
144
			buttons(Down);
145
			if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && getr(&r))
146
				duplicate(l, r, l->f.font, m==Resize);
147
			else
148
				setcursor(mousectl, cursor);
149
			buttons(Up);
150
		}
151
		break;
152
 
153
	case Close:
154
		if(!hostlock){
155
			setcursor(mousectl, &bullseye);
156
			buttons(Down);
157
			if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && !hostlock){
158
				t=(Text *)l->user1;
159
				if (t->nwin>1)
160
					closeup(l);
161
				else if(t!=&cmd) {
162
					outTs(Tclose, t->tag);
163
					setlock();
164
				}
165
			}
166
			setcursor(mousectl, cursor);
167
			buttons(Up);
168
		}
169
		break;
170
 
171
	case Write:
172
		if(!hostlock){
173
			setcursor(mousectl, &bullseye);
174
			buttons(Down);
175
			if((mousep->buttons&4) && (l = flwhich(mousep->xy))){
176
				outTs(Twrite, ((Text *)l->user1)->tag);
177
				setlock();
178
			}else
179
				setcursor(mousectl, cursor);
180
			buttons(Up);
181
		}
182
		break;
183
 
184
	default:
185
		if(t = text[m-NMENU3]){
186
			i = t->front;
187
			if(t->nwin==0 || t->l[i].textfn==0)
188
				return;	/* not ready yet; try again later */
189
			if(t->nwin>1 && which==&t->l[i])
190
				do
191
					if(++i==NL)
192
						i = 0;
193
				while(i!=t->front && t->l[i].textfn==0);
194
			current(&t->l[i]);
195
		}else if(!hostlock)
196
			sweeptext(0, tag[m-NMENU3]);
197
		break;
198
	}
199
}
200
 
201
 
202
Text *
203
sweeptext(int new, int tag)
204
{
205
	Rectangle r;
206
	Text *t;
207
 
208
	if(getr(&r) && (t = malloc(sizeof(Text)))){
209
		memset((void*)t, 0, sizeof(Text));
210
		current((Flayer *)0);
211
		flnew(&t->l[0], gettext, 0, (char *)t);
212
		flinit(&t->l[0], r, font, maincols);	/*bnl*/
213
		t->nwin = 1;
214
		rinit(&t->rasp);
215
		if(new)
216
			startnewfile(Tstartnewfile, t);
217
		else{
218
			rinit(&t->rasp);
219
			t->tag = tag;
220
			startfile(t);
221
		}
222
		return t;
223
	}
224
	return 0;
225
}
226
 
227
int
228
whichmenu(int tg)
229
{
230
	int i;
231
 
232
	for(i=0; i<nname; i++)
233
		if(tag[i] == tg)
234
			return i;
235
	return -1;
236
}
237
 
238
void
239
menuins(int n, uchar *s, Text *t, int m, int tg)
240
{
241
	int i;
242
 
243
	if(nname == mname){
244
		if(mname == 0)
245
			mname = 32;
246
		else
247
			mname *= 2;
248
		name = realloc(name, sizeof(name[0])*mname);
249
		text = realloc(text, sizeof(text[0])*mname);
250
		tag = realloc(tag, sizeof(tag[0])*mname);
251
		if(name==nil || text==nil || tag==nil)
252
			panic("realloc");
253
	}
254
	for(i=nname; i>n; --i)
255
		name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1];
256
	text[n] = t;
257
	tag[n] = tg;
258
	name[n] = alloc(strlen((char*)s)+2);
259
	name[n][0] = m;
260
	strcpy((char*)name[n]+1, (char*)s);
261
	nname++;
262
	menu3.lasthit = n+NMENU3;
263
}
264
 
265
void
266
menudel(int n)
267
{
268
	int i;
269
 
270
	if(nname==0 || n>=nname || text[n])
271
		panic("menudel");
272
	free(name[n]);
273
	--nname;
274
	for(i = n; i<nname; i++)
275
		name[i]=name[i+1], text[i]=text[i+1], tag[i]=tag[i+1];
276
}
277
 
278
void
279
setpat(char *s)
280
{
281
	static char pat[17];
282
 
283
	pat[0] = '/';
284
	strncpy(pat+1, s, 15);
285
	menu2str[Search] = pat;
286
}
287
 
288
#define	NBUF	64
289
static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};
290
 
291
char *
292
paren(char *s)
293
{
294
	uchar *t = buf;
295
 
296
	*t++ = '(';
297
	do; while(*t++ = *s++);
298
	t[-1] = ')';
299
	*t = 0;
300
	return (char *)buf;
301
}
302
char*
303
genmenu2(int n)
304
{
305
	Text *t=(Text *)which->user1;
306
	char *p;
307
	if(n>=NMENU2+(menu2str[Search]!=0))
308
		return 0;
309
	p = menu2str[n];
310
	if(!hostlock && !t->lock || n==Search || n==Look)
311
		return p;
312
	return paren(p);
313
}
314
char*
315
genmenu2c(int n)
316
{
317
	Text *t=(Text *)which->user1;
318
	char *p;
319
	if(n >= NMENU2C)
320
		return 0;
321
	if(n == Send)
322
		p="send";
323
	else
324
		p = menu2str[n];
325
	if(!hostlock && !t->lock)
326
		return p;
327
	return paren(p);
328
}
329
char *
330
genmenu3(int n)
331
{
332
	Text *t;
333
	int c, i, k, l, w;
334
	Rune r;
335
	char *p;
336
 
337
	if(n >= NMENU3+nname)
338
		return 0;
339
	if(n < NMENU3){
340
		p = menu3str[n];
341
		if(hostlock)
342
			p = paren(p);
343
		return p;
344
	}
345
	n -= NMENU3;
346
	if(n == 0)	/* unless we've been fooled, this is cmd */
347
		return (char *)&name[n][1];
348
	if(mw == -1){
349
		mw = 7;	/* strlen("~~sam~~"); */
350
		for(i=1; i<nname; i++){
351
			w = utflen((char*)name[i]+1)+4;	/* include "'+. " */
352
			if(w > mw)
353
				mw = w;
354
		}
355
	}
356
	if(mw > NBUF)
357
		mw = NBUF;
358
	t = text[n];
359
	buf[0] = name[n][0];
360
	buf[1] = '-';
361
	buf[2] = ' ';
362
	buf[3] = ' ';
363
	if(t){
364
		if(t->nwin == 1)
365
			buf[1] = '+';
366
		else if(t->nwin > 1)
367
			buf[1] = '*';
368
		if(work && t==(Text *)work->user1) {
369
			buf[2]= '.';
370
			if(modified)
371
				buf[0] = '\'';
372
		}
373
	}
374
	l = utflen((char*)name[n]+1);
375
	if(l > NBUF-4-2){
376
		i = 4;
377
		k = 1;
378
		while(i < NBUF/2){
379
			k += chartorune(&r, (char*)name[n]+k);
380
			i++;
381
		}
382
		c = name[n][k];
383
		name[n][k] = 0;
384
		strcpy((char*)buf+4, (char*)name[n]+1);
385
		name[n][k] = c;
386
		strcat((char*)buf, "...");
387
		while((l-i) >= NBUF/2-4){
388
			k += chartorune(&r, (char*)name[n]+k);
389
			i++;
390
		}
391
		strcat((char*)buf, (char*)name[n]+k);
392
	}else
393
		strcpy((char*)buf+4, (char*)name[n]+1);
394
	i = utflen((char*)buf);
395
	k = strlen((char*)buf);
396
	while(i<mw && k<sizeof buf-1){
397
		buf[k++] = ' ';
398
		i++;
399
	}
400
	buf[k] = 0;
401
	return (char *)buf;
402
}