]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/samterm/menu.c
merge
[plan9front.git] / sys / src / cmd / samterm / menu.c
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 }