blob: 18070a8fcfa4a6f559de14ca31d1bf00715f9212 [file] [log] [blame]
rsc84b1cb72003-09-30 17:47:44 +00001#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
12uchar **name; /* first byte is ' ' or '\'': modified state */
13Text **text; /* pointer to Text associated with file */
14ushort *tag; /* text[i].tag, even if text[i] not defined */
15int nname;
16int mname;
17int mw;
18
19char *genmenu3(int);
20char *genmenu2(int);
21char *genmenu2c(int);
22
23enum 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
37enum Menu3
38{
39 New,
40 Zerox,
41 Resize,
42 Close,
43 Write,
44 NMENU3
45};
46
47char *menu2str[] = {
48 "cut",
49 "paste",
50 "snarf",
51 "plumb",
52 "look",
53 "<rio>",
54 0, /* storage for last pattern */
55};
56
57char *menu3str[] = {
58 "new",
59 "zerox",
60 "resize",
61 "close",
62 "write",
63};
64
65Menu menu2 = {0, genmenu2};
66Menu menu2c ={0, genmenu2c};
67Menu menu3 = {0, genmenu3};
68
69void
70menu2hit(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
122void
123menu3hit(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
203Text *
204sweeptext(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
228int
229whichmenu(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
239void
240menuins(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
266void
267menudel(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
279void
280setpat(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
290static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};
291
292char *
293paren(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}
303char*
304genmenu2(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}
315char*
316genmenu2c(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}
330char *
331genmenu3(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}