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