Blob


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"
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;
19 char *genmenu3(int);
20 char *genmenu2(int);
21 char *genmenu2c(int);
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 };
37 enum Menu3
38 {
39 New,
40 Zerox,
41 Resize,
42 Close,
43 Write,
44 NMENU3
45 };
47 char *menu2str[] = {
48 "cut",
49 "paste",
50 "snarf",
51 "plumb",
52 "look",
53 "<rio>",
54 0, /* storage for last pattern */
55 };
57 char *menu3str[] = {
58 "new",
59 "zerox",
60 "resize",
61 "close",
62 "write"
63 };
65 Menu menu2 = {0, genmenu2};
66 Menu menu2c ={0, genmenu2c};
67 Menu menu3 = {0, genmenu3};
69 void
70 menu2hit(void)
71 {
72 Text *t=(Text *)which->user1;
73 int w = which-t->l;
74 int m;
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;
82 switch(m){
83 case Cut:
84 cut(t, w, 1, 1);
85 break;
87 case Paste:
88 paste(t, w);
89 break;
91 case Snarf:
92 snarf(t, w);
93 break;
95 case Plumb:
96 if(hversion > 0)
97 outTsll(Tplumb, t->tag, which->p0, which->p1);
98 break;
100 case Exch:
101 snarf(t, w);
102 outT0(Tstartsnarf);
103 setlock();
104 break;
106 case Look:
107 outTsll(Tlook, t->tag, which->p0, which->p1);
108 setlock();
109 break;
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;
122 void
123 menu3hit(void)
125 Rectangle r;
126 Flayer *l;
127 int m, i;
128 Text *t;
130 mw = -1;
131 m = menuhit(3, mousectl, &menu3, nil);
132 switch(m){
133 case -1:
134 break;
136 case New:
137 if(!hostlock)
138 sweeptext(1, 0);
139 break;
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);
152 break;
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();
167 setcursor(mousectl, cursor);
168 buttons(Up);
170 break;
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);
183 break;
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;
203 Text *
204 sweeptext(int new, int tag)
206 Rectangle r;
207 Text *t;
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);
223 return t;
225 return 0;
228 int
229 whichmenu(int tg)
231 int i;
233 for(i=0; i<nname; i++)
234 if(tag[i] == tg)
235 return i;
236 return -1;
239 void
240 menuins(int n, uchar *s, Text *t, int m, int tg)
242 int i;
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");
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;
266 void
267 menudel(int n)
269 int i;
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];
279 void
280 setpat(char *s)
282 static char pat[17];
284 pat[0] = '/';
285 strncpy(pat+1, s, 15);
286 menu2str[Search] = pat;
289 #define NBUF 64
290 static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};
292 char *
293 paren(char *s)
295 uchar *t = buf;
297 *t++ = '(';
298 do; while(*t++ = *s++);
299 t[-1] = ')';
300 *t = 0;
301 return (char *)buf;
303 char*
304 genmenu2(int n)
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);
315 char*
316 genmenu2c(int n)
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);
330 char *
331 genmenu3(int n)
333 Text *t;
334 int c, i, k, l, w;
335 Rune r;
336 char *p;
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;
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;
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] = '\'';
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++;
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++;
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++;
401 buf[k] = 0;
402 return (char *)buf;