1 /* $Id: menu.c,v 1.46 2007/05/23 12:34:20 inu Exp $ */
2 /*
3 * w3m menu.c
4 */
5 #include <stdio.h>
6
7 #include "fm.h"
8 #include "menu.h"
9 #include "func.h"
10 #include "myctype.h"
11 #include "regex.h"
12
13 #ifdef USE_MOUSE
14 #ifdef USE_GPM
15 #include <gpm.h>
16 static int gpm_process_menu_mouse(Gpm_Event * event, void *data);
17 extern int gpm_process_mouse(Gpm_Event *, void *);
18 #endif /* USE_GPM */
19 #ifdef USE_SYSMOUSE
20 extern int (*sysm_handler) (int x, int y, int nbs, int obs);
21 static int sysm_process_menu_mouse(int, int, int, int);
22 extern int sysm_process_mouse(int, int, int, int);
23 #endif /* USE_SYSMOUSE */
24 #if defined(USE_GPM) || defined(USE_SYSMOUSE)
25 #define X_MOUSE_SELECTED (char)0xff
26 static int X_Mouse_Selection;
27 extern int do_getch();
28 #define getch() do_getch()
29 #endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */
30 #endif /* USE_MOUSE */
31
32 #ifdef USE_MENU
33
34 static char **FRAME;
35 static int FRAME_WIDTH;
36 static int graph_mode = FALSE;
37 #define G_start {if (graph_mode) graphstart();}
38 #define G_end {if (graph_mode) graphend();}
39
40 static int mEsc(char c);
41 static int mEscB(char c);
42 static int mEscD(char c);
43 static int mNull(char c);
44 static int mSelect(char c);
45 static int mDown(char c);
46 static int mUp(char c);
47 static int mLast(char c);
48 static int mTop(char c);
49 static int mNext(char c);
50 static int mPrev(char c);
51 static int mFore(char c);
52 static int mBack(char c);
53 static int mLineU(char c);
54 static int mLineD(char c);
55 static int mOk(char c);
56 static int mCancel(char c);
57 static int mClose(char c);
58 static int mSusp(char c);
59 static int mMouse(char c);
60 static int mSgrMouse(char c);
61 static int mSrchF(char c);
62 static int mSrchB(char c);
63 static int mSrchN(char c);
64 static int mSrchP(char c);
65 #ifdef __EMX__
66 static int mPc(char c);
67 #endif
68
69 /* *INDENT-OFF* */
70 static int (*MenuKeymap[128]) (char c) = {
71 /* C-@ C-a C-b C-c C-d C-e C-f C-g */
72 #ifdef __EMX__
73 mPc, mTop, mPrev, mClose, mNull, mLast, mNext, mNull,
74 #else
75 mNull, mTop, mPrev, mClose, mNull, mLast, mNext, mNull,
76 #endif
77 /* C-h C-i C-j C-k C-l C-m C-n C-o */
78 mCancel,mNull, mOk, mNull, mNull, mOk, mDown, mNull,
79 /* C-p C-q C-r C-s C-t C-u C-v C-w */
80 mUp, mNull, mSrchB, mSrchF, mNull, mNull, mNext, mNull,
81 /* C-x C-y C-z C-[ C-\ C-] C-^ C-_ */
82 mNull, mNull, mSusp, mEsc, mNull, mNull, mNull, mNull,
83 /* SPC ! " # $ % & ' */
84 mOk, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
85 /* ( ) * + , - . / */
86 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mSrchF,
87 /* 0 1 2 3 4 5 6 7 */
88 mNull, mNull, mNull, mNull, mNull, mNull , mNull, mNull,
89 /* 8 9 : ; < = > ? */
90 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mSrchB,
91 /* @ A B C D E F G */
92 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
93 /* H I J K L M N O */
94 mNull, mNull, mLineU, mLineD, mNull, mNull, mSrchP, mNull,
95 /* P Q R S T U V W */
96 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
97 /* X Y Z [ \ ] ^ _ */
98 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
99 /* ` a b c d e f g */
100 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
101 /* h i j k l m n o */
102 mCancel,mNull, mDown, mUp, mOk, mNull, mSrchN, mNull,
103 /* p q r s t u v w */
104 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
105 /* x y z { | } ~ DEL */
106 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mCancel,
107 };
108 static int (*MenuEscKeymap[128]) (char c) = {
109 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
110 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
111 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
112 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
113
114 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
115 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
116 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
117 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
118
119 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
120 /* O */
121 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mEscB,
122 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
123 /* [ */
124 mNull, mNull, mNull, mEscB, mNull, mNull, mNull, mNull,
125
126 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
127 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
128 /* v */
129 mNull, mNull, mNull, mNull, mNull, mNull, mPrev, mNull,
130 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
131 };
132 static int (*MenuEscBKeymap[128]) (char c) = {
133 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
134 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
135 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
136 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
137
138 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
139 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
140 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
141 /* 8 9 : ; < = > ? */
142 mNull, mNull, mNull, mNull, mSgrMouse,mNull,mNull, mNull,
143 /* A B C D E */
144 mNull, mUp, mDown, mOk, mCancel,mClose, mNull, mNull,
145 /* L M */
146 mNull, mNull, mNull, mNull, mClose, mMouse, mNull, mNull,
147 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
148 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
149
150 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
151 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
152 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
153 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
154 };
155 static int (*MenuEscDKeymap[128]) (char c) = {
156 /* 0 1 INS 3 4 PgUp, PgDn 7 */
157 mNull, mNull, mClose, mNull, mNull, mBack, mFore, mNull,
158 /* 8 9 10 F1 F2 F3 F4 F5 */
159 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
160 /* 16 F6 F7 F8 F9 F10 22 23 */
161 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
162 /* 24 25 26 27 HELP 29 30 31 */
163 mNull, mNull, mNull, mNull, mClose, mNull, mNull, mNull,
164
165 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
166 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
167 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
168 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
169
170 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
171 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
172 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
173 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
174
175 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
176 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
177 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
178 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
179 };
180
181 #ifdef __EMX__
182 static int (*MenuPcKeymap[256])(char c)={
183 // Null
184 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
185 // S-Tab
186 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
187 // A-q A-w A-E A-r A-t A-y A-u A-i
188 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
189 // A-o A-p A-[ A-] A-a A-s
190 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
191 // A-d A-f A-g A-h A-j A-k A-l A-;
192 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
193 // A-' A-' A-\ A-x A-c A-v
194 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mPrev,
195 // A-b A-n A-m A-, A-. A-/ A-+
196 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
197 // F1 F2 F3 F4 F5
198 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
199 // F6 F7 F8 F9 F10 Home
200 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mTop,
201 // Up PgUp A-/ Left 5 Right C-* End
202 mUp, mUp, mNull, mCancel,mNull, mOk, mNull, mLast,
203 // Down PgDn Ins Del S-F1 S-F2 S-F3 S-F4
204 mDown, mDown, mClose, mCancel,mNull, mNull, mNull, mNull,
205 // S-F5 S-F6 S-F7 S-F8 S-F9 S-F10 C-F1 C-F2
206 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
207 // C-F3 C-F4 C-F5 C-F6 C-F7 C-F8 C-F9 C-F10
208 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
209 // A-F1 A-F2 A-F3 A-F4 A-F5 A-F6 A-F7 A-F8
210 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
211 // A-F9 A-F10 PrtSc C-Left C-Right C-End C-PgDn C-Home
212 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
213 // A-1 A-2 A-3 A-4 A-5 A-6 A-7/8 A-9
214 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
215 // A-0 A - A-= C-PgUp F11 F12 S-F11
216 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
217 // S-F12 C-F11 C-F12 A-F11 A-F12 C-Up C-/ C-5
218 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
219 // S-* C-Down C-Ins C-Del C-Tab C - C-+
220 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
221 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
222 // A - A-Tab A-Enter
223 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 160
224 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 168
225 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 176
226 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 184
227 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 192
228 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 200
229 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 208
230 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 216
231 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 224
232 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 232
233 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 240
234 mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull // 248
235 };
236 #endif
237 /* *INDENT-ON* */
238 /* --- SelectMenu --- */
239
240 static Menu SelectMenu;
241 static int SelectV = 0;
242 static void initSelectMenu(void);
243 static void smChBuf(void);
244 static int smDelBuf(char c);
245
246 /* --- SelectMenu (END) --- */
247
248 /* --- SelTabMenu --- */
249
250 static Menu SelTabMenu;
251 static int SelTabV = 0;
252 static void initSelTabMenu(void);
253 static void smChTab(void);
254 static int smDelTab(char c);
255
256 /* --- SelTabMenu (END) --- */
257
258 /* --- MainMenu --- */
259
260 static Menu MainMenu;
261 #ifdef USE_M17N
262 /* FIXME: gettextize here */
263 static wc_ces MainMenuCharset = WC_CES_US_ASCII; /* FIXME: charset of source code */
264 static int MainMenuEncode = FALSE;
265 #endif
266
267 static MenuItem MainMenuItem[] = {
268 /* type label variable value func popup keys data */
269 {MENU_FUNC, N_(" Back (b) "), NULL, 0, backBf, NULL, "b", NULL},
270 {MENU_POPUP, N_(" Select Buffer(s) "), NULL, 0, NULL, &SelectMenu, "s",
271 NULL},
272 {MENU_POPUP, N_(" Select Tab (t) "), NULL, 0, NULL, &SelTabMenu, "tT",
273 NULL},
274 {MENU_FUNC, N_(" View Source (v) "), NULL, 0, vwSrc, NULL, "vV", NULL},
275 {MENU_FUNC, N_(" Edit Source (e) "), NULL, 0, editBf, NULL, "eE", NULL},
276 {MENU_FUNC, N_(" Save Source (S) "), NULL, 0, svSrc, NULL, "S", NULL},
277 {MENU_FUNC, N_(" Reload (r) "), NULL, 0, reload, NULL, "rR", NULL},
278 {MENU_NOP, N_(" ---------------- "), NULL, 0, nulcmd, NULL, "", NULL},
279 {MENU_FUNC, N_(" Go Link (a) "), NULL, 0, followA, NULL, "a", NULL},
280 {MENU_FUNC, N_(" on New Tab (n) "), NULL, 0, tabA, NULL, "nN", NULL},
281 {MENU_FUNC, N_(" Save Link (A) "), NULL, 0, svA, NULL, "A", NULL},
282 {MENU_FUNC, N_(" View Image (i) "), NULL, 0, followI, NULL, "i", NULL},
283 {MENU_FUNC, N_(" Save Image (I) "), NULL, 0, svI, NULL, "I", NULL},
284 {MENU_FUNC, N_(" View Frame (f) "), NULL, 0, rFrame, NULL, "fF", NULL},
285 {MENU_NOP, N_(" ---------------- "), NULL, 0, nulcmd, NULL, "", NULL},
286 {MENU_FUNC, N_(" Bookmark (B) "), NULL, 0, ldBmark, NULL, "B", NULL},
287 {MENU_FUNC, N_(" Help (h) "), NULL, 0, ldhelp, NULL, "hH", NULL},
288 {MENU_FUNC, N_(" Option (o) "), NULL, 0, ldOpt, NULL, "oO", NULL},
289 {MENU_NOP, N_(" ---------------- "), NULL, 0, nulcmd, NULL, "", NULL},
290 {MENU_FUNC, N_(" Quit (q) "), NULL, 0, qquitfm, NULL, "qQ", NULL},
291 {MENU_END, "", NULL, 0, nulcmd, NULL, "", NULL},
292 };
293
294 /* --- MainMenu (END) --- */
295
296 static MenuList *w3mMenuList;
297
298 static Menu *CurrentMenu = NULL;
299
300 #define mvaddch(y, x, c) (move(y, x), addch(c))
301 #define mvaddstr(y, x, str) (move(y, x), addstr(str))
302 #define mvaddnstr(y, x, str, n) (move(y, x), addnstr_sup(str, n))
303
304 void
new_menu(Menu * menu,MenuItem * item)305 new_menu(Menu *menu, MenuItem *item)
306 {
307 int i, l;
308 char *p;
309
310 menu->cursorX = 0;
311 menu->cursorY = 0;
312 menu->x = 0;
313 menu->y = 0;
314 menu->nitem = 0;
315 menu->item = item;
316 menu->initial = 0;
317 menu->select = 0;
318 menu->offset = 0;
319 menu->active = 0;
320
321 if (item == NULL)
322 return;
323
324 for (i = 0; item[i].type != MENU_END; i++) ;
325 menu->nitem = i;
326 menu->height = menu->nitem;
327 for (i = 0; i < 128; i++)
328 menu->keymap[i] = MenuKeymap[i];
329 menu->width = 0;
330 for (i = 0; i < menu->nitem; i++) {
331 if ((p = item[i].keys) != NULL) {
332 while (*p) {
333 if (IS_ASCII(*p)) {
334 menu->keymap[(int)*p] = mSelect;
335 menu->keyselect[(int)*p] = i;
336 }
337 p++;
338 }
339 }
340 l = get_strwidth(item[i].label);
341 if (l > menu->width)
342 menu->width = l;
343 }
344 }
345
346 void
geom_menu(Menu * menu,int x,int y,int mselect)347 geom_menu(Menu *menu, int x, int y, int mselect)
348 {
349 int win_x, win_y, win_w, win_h;
350
351 menu->select = mselect;
352
353 if (menu->width % FRAME_WIDTH)
354 menu->width = (menu->width / FRAME_WIDTH + 1) * FRAME_WIDTH;
355 win_x = menu->x - FRAME_WIDTH;
356 win_w = menu->width + 2 * FRAME_WIDTH;
357 if (win_x + win_w > COLS)
358 win_x = COLS - win_w;
359 if (win_x < 0) {
360 win_x = 0;
361 if (win_w > COLS) {
362 menu->width = COLS - 2 * FRAME_WIDTH;
363 menu->width -= menu->width % FRAME_WIDTH;
364 }
365 }
366 menu->x = win_x + FRAME_WIDTH;
367
368 win_y = menu->y - mselect - 1;
369 win_h = menu->height + 2;
370 if (win_y + win_h > LASTLINE)
371 win_y = LASTLINE - win_h;
372 if (win_y < 0) {
373 win_y = 0;
374 if (win_y + win_h > LASTLINE) {
375 win_h = LASTLINE - win_y;
376 menu->height = win_h - 2;
377 if (menu->height <= mselect)
378 menu->offset = mselect - menu->height + 1;
379 }
380 }
381 menu->y = win_y + 1;
382 }
383
384 void
draw_all_menu(Menu * menu)385 draw_all_menu(Menu *menu)
386 {
387 if (menu->parent != NULL)
388 draw_all_menu(menu->parent);
389 draw_menu(menu);
390 }
391
392 void
draw_menu(Menu * menu)393 draw_menu(Menu *menu)
394 {
395 int x, y, w;
396 int i, j;
397
398 x = menu->x - FRAME_WIDTH;
399 w = menu->width + 2 * FRAME_WIDTH;
400 y = menu->y - 1;
401
402 if (menu->offset == 0) {
403 G_start;
404 mvaddstr(y, x, FRAME[3]);
405 for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
406 mvaddstr(y, x + i, FRAME[10]);
407 mvaddstr(y, x + i, FRAME[6]);
408 G_end;
409 }
410 else {
411 G_start;
412 mvaddstr(y, x, FRAME[5]);
413 G_end;
414 for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i++)
415 mvaddstr(y, x + i, " ");
416 G_start;
417 mvaddstr(y, x + i, FRAME[5]);
418 G_end;
419 i = (w / 2 - 1) / FRAME_WIDTH * FRAME_WIDTH;
420 mvaddstr(y, x + i, ":");
421 }
422
423 for (j = 0; j < menu->height; j++) {
424 y++;
425 G_start;
426 mvaddstr(y, x, FRAME[5]);
427 G_end;
428 draw_menu_item(menu, menu->offset + j);
429 G_start;
430 mvaddstr(y, x + w - FRAME_WIDTH, FRAME[5]);
431 G_end;
432 }
433 y++;
434 if (menu->offset + menu->height == menu->nitem) {
435 G_start;
436 mvaddstr(y, x, FRAME[9]);
437 for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
438 mvaddstr(y, x + i, FRAME[10]);
439 mvaddstr(y, x + i, FRAME[12]);
440 G_end;
441 }
442 else {
443 G_start;
444 mvaddstr(y, x, FRAME[5]);
445 G_end;
446 for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i++)
447 mvaddstr(y, x + i, " ");
448 G_start;
449 mvaddstr(y, x + i, FRAME[5]);
450 G_end;
451 i = (w / 2 - 1) / FRAME_WIDTH * FRAME_WIDTH;
452 mvaddstr(y, x + i, ":");
453 }
454 }
455
456 void
draw_menu_item(Menu * menu,int mselect)457 draw_menu_item(Menu *menu, int mselect)
458 {
459 mvaddnstr(menu->y + mselect - menu->offset, menu->x,
460 menu->item[mselect].label, menu->width);
461 }
462
463 int
select_menu(Menu * menu,int mselect)464 select_menu(Menu *menu, int mselect)
465 {
466 if (mselect < 0 || mselect >= menu->nitem)
467 return (MENU_NOTHING);
468 if (mselect < menu->offset)
469 up_menu(menu, menu->offset - mselect);
470 else if (mselect >= menu->offset + menu->height)
471 down_menu(menu, mselect - menu->offset - menu->height + 1);
472
473 if (menu->select >= menu->offset &&
474 menu->select < menu->offset + menu->height)
475 draw_menu_item(menu, menu->select);
476 menu->select = mselect;
477 standout();
478 draw_menu_item(menu, menu->select);
479 standend();
480 /*
481 * move(menu->cursorY, menu->cursorX); */
482 move(menu->y + mselect - menu->offset, menu->x);
483 toggle_stand();
484 refresh();
485
486 return (menu->select);
487 }
488
489 void
goto_menu(Menu * menu,int mselect,int down)490 goto_menu(Menu *menu, int mselect, int down)
491 {
492 int select_in;
493 if (mselect >= menu->nitem)
494 mselect = menu->nitem - 1;
495 else if (mselect < 0)
496 mselect = 0;
497 select_in = mselect;
498 while (menu->item[mselect].type == MENU_NOP) {
499 if (down > 0) {
500 if (++mselect >= menu->nitem) {
501 down_menu(menu, select_in - menu->select);
502 mselect = menu->select;
503 break;
504 }
505 }
506 else if (down < 0) {
507 if (--mselect < 0) {
508 up_menu(menu, menu->select - select_in);
509 mselect = menu->select;
510 break;
511 }
512 }
513 else {
514 return;
515 }
516 }
517 select_menu(menu, mselect);
518 }
519
520 void
up_menu(Menu * menu,int n)521 up_menu(Menu *menu, int n)
522 {
523 if (n < 0 || menu->offset == 0)
524 return;
525 menu->offset -= n;
526 if (menu->offset < 0)
527 menu->offset = 0;
528
529 draw_menu(menu);
530 }
531
532 void
down_menu(Menu * menu,int n)533 down_menu(Menu *menu, int n)
534 {
535 if (n < 0 || menu->offset + menu->height == menu->nitem)
536 return;
537 menu->offset += n;
538 if (menu->offset + menu->height > menu->nitem)
539 menu->offset = menu->nitem - menu->height;
540
541 draw_menu(menu);
542 }
543
544 int
action_menu(Menu * menu)545 action_menu(Menu *menu)
546 {
547 char c;
548 int mselect;
549 MenuItem item;
550
551 if (menu->active == 0) {
552 if (menu->parent != NULL)
553 menu->parent->active = 0;
554 return (0);
555 }
556 draw_all_menu(menu);
557 select_menu(menu, menu->select);
558
559 while (1) {
560 #ifdef USE_MOUSE
561 if (use_mouse)
562 mouse_active();
563 #endif /* USE_MOUSE */
564 c = getch();
565 #ifdef USE_MOUSE
566 if (use_mouse)
567 mouse_inactive();
568 #if defined(USE_GPM) || defined(USE_SYSMOUSE)
569 if (c == X_MOUSE_SELECTED) {
570 mselect = X_Mouse_Selection;
571 if (mselect != MENU_NOTHING)
572 break;
573 }
574 #endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */
575 #endif /* USE_MOUSE */
576 if (IS_ASCII(c)) { /* Ascii */
577 mselect = (*menu->keymap[(int)c]) (c);
578 if (mselect != MENU_NOTHING)
579 break;
580 }
581 }
582 if (mselect >= 0 && mselect < menu->nitem) {
583 item = menu->item[mselect];
584 if (item.type & MENU_POPUP) {
585 popup_menu(menu, item.popup);
586 return (1);
587 }
588 if (menu->parent != NULL)
589 menu->parent->active = 0;
590 if (item.type & MENU_VALUE)
591 *item.variable = item.value;
592 if (item.type & MENU_FUNC) {
593 CurrentKey = -1;
594 CurrentKeyData = NULL;
595 CurrentCmdData = item.data;
596 (*item.func) ();
597 CurrentCmdData = NULL;
598 }
599 }
600 else if (mselect == MENU_CLOSE) {
601 if (menu->parent != NULL)
602 menu->parent->active = 0;
603 }
604 return (0);
605 }
606
607 void
popup_menu(Menu * parent,Menu * menu)608 popup_menu(Menu *parent, Menu *menu)
609 {
610 int active = 1;
611
612 if (menu->item == NULL || menu->nitem == 0)
613 return;
614 if (menu->active)
615 return;
616
617 #ifdef USE_MOUSE
618 #ifdef USE_GPM
619 gpm_handler = gpm_process_menu_mouse;
620 #endif /* USE_GPM */
621 #ifdef USE_SYSMOUSE
622 sysm_handler = sysm_process_menu_mouse;
623 #endif /* USE_SYSMOUSE */
624 #endif /* USE_MOUSE */
625 menu->parent = parent;
626 menu->select = menu->initial;
627 menu->offset = 0;
628 menu->active = 1;
629 if (parent != NULL) {
630 menu->cursorX = parent->cursorX;
631 menu->cursorY = parent->cursorY;
632 guess_menu_xy(parent, menu->width, &menu->x, &menu->y);
633 }
634 geom_menu(menu, menu->x, menu->y, menu->select);
635
636 CurrentMenu = menu;
637 while (active) {
638 active = action_menu(CurrentMenu);
639 displayBuffer(Currentbuf, B_FORCE_REDRAW);
640 }
641 menu->active = 0;
642 CurrentMenu = parent;
643 #ifdef USE_MOUSE
644 #ifdef USE_GPM
645 if (CurrentMenu == NULL)
646 gpm_handler = gpm_process_mouse;
647 #endif /* USE_GPM */
648 #ifdef USE_SYSMOUSE
649 if (CurrentMenu == NULL)
650 sysm_handler = sysm_process_mouse;
651 #endif /* USE_SYSMOUSE */
652 #endif /* USE_MOUSE */
653 }
654
655 void
guess_menu_xy(Menu * parent,int width,int * x,int * y)656 guess_menu_xy(Menu *parent, int width, int *x, int *y)
657 {
658 *x = parent->x + parent->width + FRAME_WIDTH - 1;
659 if (*x + width + FRAME_WIDTH > COLS) {
660 *x = COLS - width - FRAME_WIDTH;
661 if ((parent->x + parent->width / 2 > *x) &&
662 (parent->x + parent->width / 2 > COLS / 2))
663 *x = parent->x - width - FRAME_WIDTH + 1;
664 }
665 *y = parent->y + parent->select - parent->offset;
666 }
667
668 void
new_option_menu(Menu * menu,char ** label,int * variable,void (* func)())669 new_option_menu(Menu *menu, char **label, int *variable, void (*func) ())
670 {
671 int i, nitem;
672 char **p;
673 MenuItem *item;
674
675 if (label == NULL || *label == NULL)
676 return;
677
678 for (i = 0, p = label; *p != NULL; i++, p++) ;
679 nitem = i;
680
681 item = New_N(MenuItem, nitem + 1);
682
683 for (i = 0, p = label; i < nitem; i++, p++) {
684 if (func != NULL)
685 item[i].type = MENU_VALUE | MENU_FUNC;
686 else
687 item[i].type = MENU_VALUE;
688 item[i].label = *p;
689 item[i].variable = variable;
690 item[i].value = i;
691 item[i].func = func;
692 item[i].popup = NULL;
693 item[i].keys = "";
694 }
695 item[nitem].type = MENU_END;
696
697 new_menu(menu, item);
698 }
699
700 static void
set_menu_frame(void)701 set_menu_frame(void)
702 {
703 if (graph_ok()) {
704 graph_mode = TRUE;
705 FRAME_WIDTH = 1;
706 FRAME = graph_symbol;
707 }
708 else {
709 graph_mode = FALSE;
710 #ifdef USE_M17N
711 FRAME_WIDTH = 0;
712 FRAME = get_symbol(DisplayCharset, &FRAME_WIDTH);
713 if (!WcOption.use_wide)
714 FRAME_WIDTH = 1;
715 #else
716 FRAME_WIDTH = 1;
717 FRAME = get_symbol();
718 #endif
719 }
720 }
721
722 /* --- MenuFunctions --- */
723
724 #ifdef __EMX__
725 static int
mPc(char c)726 mPc(char c)
727 {
728 c = getch();
729 return (MenuPcKeymap[(int)c] (c));
730 }
731 #endif
732
733 static int
mEsc(char c)734 mEsc(char c)
735 {
736 c = getch();
737 return (MenuEscKeymap[(int)c] (c));
738 }
739
740 static int
mEscB(char c)741 mEscB(char c)
742 {
743 c = getch();
744 if (IS_DIGIT(c))
745 return (mEscD(c));
746 else
747 return (MenuEscBKeymap[(int)c] (c));
748 }
749
750 static int
mEscD(char c)751 mEscD(char c)
752 {
753 int d;
754
755 d = (int)c - (int)'0';
756 c = getch();
757 if (IS_DIGIT(c)) {
758 d = d * 10 + (int)c - (int)'0';
759 c = getch();
760 }
761 if (c == '~')
762 return (MenuEscDKeymap[d] (c));
763 else
764 return (MENU_NOTHING);
765 }
766
767 static int
mNull(char c)768 mNull(char c)
769 {
770 return (MENU_NOTHING);
771 }
772
773 static int
mSelect(char c)774 mSelect(char c)
775 {
776 if (IS_ASCII(c))
777 return (select_menu(CurrentMenu, CurrentMenu->keyselect[(int)c]));
778 else
779 return (MENU_NOTHING);
780 }
781
782 static int
mDown(char c)783 mDown(char c)
784 {
785 if (CurrentMenu->select >= CurrentMenu->nitem - 1)
786 return (MENU_NOTHING);
787 goto_menu(CurrentMenu, CurrentMenu->select + 1, 1);
788 return (MENU_NOTHING);
789 }
790
791 static int
mUp(char c)792 mUp(char c)
793 {
794 if (CurrentMenu->select <= 0)
795 return (MENU_NOTHING);
796 goto_menu(CurrentMenu, CurrentMenu->select - 1, -1);
797 return (MENU_NOTHING);
798 }
799
800 static int
mLast(char c)801 mLast(char c)
802 {
803 goto_menu(CurrentMenu, CurrentMenu->nitem - 1, -1);
804 return (MENU_NOTHING);
805 }
806
807 static int
mTop(char c)808 mTop(char c)
809 {
810 goto_menu(CurrentMenu, 0, 1);
811 return (MENU_NOTHING);
812 }
813
814 static int
mNext(char c)815 mNext(char c)
816 {
817 int mselect = CurrentMenu->select + CurrentMenu->height;
818
819 if (mselect >= CurrentMenu->nitem)
820 return mLast(c);
821 down_menu(CurrentMenu, CurrentMenu->height);
822 goto_menu(CurrentMenu, mselect, -1);
823 return (MENU_NOTHING);
824 }
825
826 static int
mPrev(char c)827 mPrev(char c)
828 {
829 int mselect = CurrentMenu->select - CurrentMenu->height;
830
831 if (mselect < 0)
832 return mTop(c);
833 up_menu(CurrentMenu, CurrentMenu->height);
834 goto_menu(CurrentMenu, mselect, 1);
835 return (MENU_NOTHING);
836 }
837
838 static int
mFore(char c)839 mFore(char c)
840 {
841 if (CurrentMenu->select >= CurrentMenu->nitem - 1)
842 return (MENU_NOTHING);
843 goto_menu(CurrentMenu, (CurrentMenu->select + CurrentMenu->height - 1),
844 (CurrentMenu->height + 1));
845 return (MENU_NOTHING);
846 }
847
848 static int
mBack(char c)849 mBack(char c)
850 {
851 if (CurrentMenu->select <= 0)
852 return (MENU_NOTHING);
853 goto_menu(CurrentMenu, (CurrentMenu->select - CurrentMenu->height + 1),
854 (-1 - CurrentMenu->height));
855 return (MENU_NOTHING);
856 }
857
858 static int
mLineU(char c)859 mLineU(char c)
860 {
861 int mselect = CurrentMenu->select;
862
863 if (mselect >= CurrentMenu->nitem)
864 return mLast(c);
865 if (CurrentMenu->offset + CurrentMenu->height >= CurrentMenu->nitem)
866 mselect++;
867 else {
868 down_menu(CurrentMenu, 1);
869 if (mselect < CurrentMenu->offset)
870 mselect++;
871 }
872 goto_menu(CurrentMenu, mselect, 1);
873 return (MENU_NOTHING);
874 }
875
876 static int
mLineD(char c)877 mLineD(char c)
878 {
879 int mselect = CurrentMenu->select;
880
881 if (mselect <= 0)
882 return mTop(c);
883 if (CurrentMenu->offset <= 0)
884 mselect--;
885 else {
886 up_menu(CurrentMenu, 1);
887 if (mselect >= CurrentMenu->offset + CurrentMenu->height)
888 mselect--;
889 }
890 goto_menu(CurrentMenu, mselect, -1);
891 return (MENU_NOTHING);
892 }
893
894 static int
mOk(char c)895 mOk(char c)
896 {
897 int mselect = CurrentMenu->select;
898
899 if (CurrentMenu->item[mselect].type == MENU_NOP)
900 return (MENU_NOTHING);
901 return (mselect);
902 }
903
904 static int
mCancel(char c)905 mCancel(char c)
906 {
907 return (MENU_CANCEL);
908 }
909
910 static int
mClose(char c)911 mClose(char c)
912 {
913 return (MENU_CLOSE);
914 }
915
916 static int
mSusp(char c)917 mSusp(char c)
918 {
919 susp();
920 draw_all_menu(CurrentMenu);
921 select_menu(CurrentMenu, CurrentMenu->select);
922 return (MENU_NOTHING);
923 }
924
925 static char *SearchString = NULL;
926
927 int (*menuSearchRoutine) (Menu *, char *, int);
928
929 static int
menuForwardSearch(Menu * menu,char * str,int from)930 menuForwardSearch(Menu *menu, char *str, int from)
931 {
932 int i;
933 char *p;
934 if ((p = regexCompile(str, IgnoreCase)) != NULL) {
935 message(p, 0, 0);
936 return -1;
937 }
938 if (from < 0)
939 from = 0;
940 for (i = from; i < menu->nitem; i++)
941 if (menu->item[i].type != MENU_NOP &&
942 regexMatch(menu->item[i].label, -1, 1) == 1)
943 return i;
944 return -1;
945 }
946
947 static int
menu_search_forward(Menu * menu,int from)948 menu_search_forward(Menu *menu, int from)
949 {
950 char *str;
951 int found;
952 str = inputStrHist("Forward: ", NULL, TextHist);
953 if (str != NULL && *str == '\0')
954 str = SearchString;
955 if (str == NULL || *str == '\0')
956 return -1;
957 SearchString = str;
958 str = conv_search_string(str, DisplayCharset);
959 menuSearchRoutine = menuForwardSearch;
960 found = menuForwardSearch(menu, str, from + 1);
961 if (WrapSearch && found == -1)
962 found = menuForwardSearch(menu, str, 0);
963 if (found >= 0)
964 return found;
965 disp_message("Not found", TRUE);
966 return -1;
967 }
968
969 static int
mSrchF(char c)970 mSrchF(char c)
971 {
972 int mselect;
973 mselect = menu_search_forward(CurrentMenu, CurrentMenu->select);
974 if (mselect >= 0)
975 goto_menu(CurrentMenu, mselect, 1);
976 return (MENU_NOTHING);
977 }
978
979 static int
menuBackwardSearch(Menu * menu,char * str,int from)980 menuBackwardSearch(Menu *menu, char *str, int from)
981 {
982 int i;
983 char *p;
984 if ((p = regexCompile(str, IgnoreCase)) != NULL) {
985 message(p, 0, 0);
986 return -1;
987 }
988 if (from >= menu->nitem)
989 from = menu->nitem - 1;
990 for (i = from; i >= 0; i--)
991 if (menu->item[i].type != MENU_NOP &&
992 regexMatch(menu->item[i].label, -1, 1) == 1)
993 return i;
994 return -1;
995 }
996
997 static int
menu_search_backward(Menu * menu,int from)998 menu_search_backward(Menu *menu, int from)
999 {
1000 char *str;
1001 int found;
1002 str = inputStrHist("Backward: ", NULL, TextHist);
1003 if (str != NULL && *str == '\0')
1004 str = SearchString;
1005 if (str == NULL || *str == '\0')
1006 return -1;
1007 SearchString = str;
1008 str = conv_search_string(str, DisplayCharset);
1009 menuSearchRoutine = menuBackwardSearch;
1010 found = menuBackwardSearch(menu, str, from - 1);
1011 if (WrapSearch && found == -1)
1012 found = menuBackwardSearch(menu, str, menu->nitem);
1013 if (found >= 0)
1014 return found;
1015 disp_message("Not found", TRUE);
1016 return -1;
1017 }
1018
1019 static int
mSrchB(char c)1020 mSrchB(char c)
1021 {
1022 int mselect;
1023 mselect = menu_search_backward(CurrentMenu, CurrentMenu->select);
1024 if (mselect >= 0)
1025 goto_menu(CurrentMenu, mselect, -1);
1026 return (MENU_NOTHING);
1027 }
1028
1029 static int
menu_search_next_previous(Menu * menu,int from,int reverse)1030 menu_search_next_previous(Menu *menu, int from, int reverse)
1031 {
1032 int found;
1033 static int (*routine[2]) (Menu *, char *, int) = {
1034 menuForwardSearch, menuBackwardSearch};
1035 char *str;
1036
1037 if (menuSearchRoutine == NULL) {
1038 disp_message("No previous regular expression", TRUE);
1039 return -1;
1040 }
1041 str = conv_search_string(SearchString, DisplayCharset);
1042 if (reverse != 0)
1043 reverse = 1;
1044 if (menuSearchRoutine == menuBackwardSearch)
1045 reverse ^= 1;
1046 from += reverse ? -1 : 1;
1047 found = (*routine[reverse]) (menu, str, from);
1048 if (WrapSearch && found == -1)
1049 found = (*routine[reverse]) (menu, str, reverse * menu->nitem);
1050 if (found >= 0)
1051 return found;
1052 disp_message("Not found", TRUE);
1053 return -1;
1054 }
1055
1056 static int
mSrchN(char c)1057 mSrchN(char c)
1058 {
1059 int mselect;
1060 mselect = menu_search_next_previous(CurrentMenu, CurrentMenu->select, 0);
1061 if (mselect >= 0)
1062 goto_menu(CurrentMenu, mselect, 1);
1063 return (MENU_NOTHING);
1064 }
1065
1066 static int
mSrchP(char c)1067 mSrchP(char c)
1068 {
1069 int mselect;
1070 mselect = menu_search_next_previous(CurrentMenu, CurrentMenu->select, 1);
1071 if (mselect >= 0)
1072 goto_menu(CurrentMenu, mselect, -1);
1073 return (MENU_NOTHING);
1074 }
1075
1076 #ifdef USE_MOUSE
1077 #define MOUSE_BTN1_DOWN 0
1078 #define MOUSE_BTN2_DOWN 1
1079 #define MOUSE_BTN3_DOWN 2
1080 #define MOUSE_BTN4_DOWN_RXVT 3
1081 #define MOUSE_BTN5_DOWN_RXVT 4
1082 #define MOUSE_BTN4_DOWN_XTERM 64
1083 #define MOUSE_BTN5_DOWN_XTERM 65
1084 #define MOUSE_BTN_UP 3
1085 #define MOUSE_BTN_RESET -1
1086
1087 static int
mMouse_scroll_line(void)1088 mMouse_scroll_line(void)
1089 {
1090 int i = 0;
1091 if (relative_wheel_scroll)
1092 i = (relative_wheel_scroll_ratio * CurrentMenu->height + 99) / 100;
1093 else
1094 i = fixed_wheel_scroll_count;
1095 return i ? i : 1;
1096 }
1097
1098 static int
process_mMouse(int btn,int x,int y)1099 process_mMouse(int btn, int x, int y)
1100 {
1101 Menu *menu;
1102 int mselect, i;
1103 static int press_btn = MOUSE_BTN_RESET, press_x, press_y;
1104 char c = ' ';
1105
1106 menu = CurrentMenu;
1107
1108 if (x < 0 || x >= COLS || y < 0 || y > LASTLINE)
1109 return (MENU_NOTHING);
1110
1111 if (btn == MOUSE_BTN_UP) {
1112 switch (press_btn) {
1113 case MOUSE_BTN1_DOWN:
1114 case MOUSE_BTN3_DOWN:
1115 if (x < menu->x - FRAME_WIDTH ||
1116 x >= menu->x + menu->width + FRAME_WIDTH ||
1117 y < menu->y - 1 || y >= menu->y + menu->height + 1) {
1118 return (MENU_CANCEL);
1119 }
1120 else if ((x >= menu->x - FRAME_WIDTH &&
1121 x < menu->x) ||
1122 (x >= menu->x + menu->width &&
1123 x < menu->x + menu->width + FRAME_WIDTH)) {
1124 return (MENU_NOTHING);
1125 }
1126 else if (press_y > y) {
1127 for (i = 0; i < press_y - y; i++)
1128 mLineU(c);
1129 return (MENU_NOTHING);
1130 }
1131 else if (press_y < y) {
1132 for (i = 0; i < y - press_y; i++)
1133 mLineD(c);
1134 return (MENU_NOTHING);
1135 }
1136 else if (y == menu->y - 1) {
1137 mPrev(c);
1138 return (MENU_NOTHING);
1139 }
1140 else if (y == menu->y + menu->height) {
1141 mNext(c);
1142 return (MENU_NOTHING);
1143 }
1144 else {
1145 mselect = y - menu->y + menu->offset;
1146 if (menu->item[mselect].type == MENU_NOP)
1147 return (MENU_NOTHING);
1148 return (select_menu(menu, mselect));
1149 }
1150 break;
1151 case MOUSE_BTN4_DOWN_RXVT:
1152 for (i = 0; i < mMouse_scroll_line(); i++)
1153 mLineD(c);
1154 break;
1155 case MOUSE_BTN5_DOWN_RXVT:
1156 for (i = 0; i < mMouse_scroll_line(); i++)
1157 mLineU(c);
1158 break;
1159 }
1160 }
1161 else if (btn == MOUSE_BTN4_DOWN_XTERM) {
1162 for (i = 0; i < mMouse_scroll_line(); i++)
1163 mLineD(c);
1164 }
1165 else if (btn == MOUSE_BTN5_DOWN_XTERM) {
1166 for (i = 0; i < mMouse_scroll_line(); i++)
1167 mLineU(c);
1168 }
1169
1170 if (btn != MOUSE_BTN4_DOWN_RXVT || press_btn == MOUSE_BTN_RESET) {
1171 press_btn = btn;
1172 press_x = x;
1173 press_y = y;
1174 }
1175 else {
1176 press_btn = MOUSE_BTN_RESET;
1177 }
1178 return (MENU_NOTHING);
1179 }
1180
1181 static int
mMouse(char c)1182 mMouse(char c)
1183 {
1184 int btn, x, y;
1185
1186 btn = (unsigned char)getch() - 32;
1187 #if defined(__CYGWIN__) && CYGWIN_VERSION_DLL_MAJOR < 1005
1188 if (cygwin_mouse_btn_swapped) {
1189 if (btn == MOUSE_BTN2_DOWN)
1190 btn = MOUSE_BTN3_DOWN;
1191 else if (btn == MOUSE_BTN3_DOWN)
1192 btn = MOUSE_BTN2_DOWN;
1193 }
1194 #endif
1195 x = (unsigned char)getch() - 33;
1196 if (x < 0)
1197 x += 0x100;
1198 y = (unsigned char)getch() - 33;
1199 if (y < 0)
1200 y += 0x100;
1201
1202 /*
1203 * if (x < 0 || x >= COLS || y < 0 || y > LASTLINE) return; */
1204 return process_mMouse(btn, x, y);
1205 }
1206
1207 static int
mSgrMouse(char c)1208 mSgrMouse(char c)
1209 {
1210 int btn = 0, x = 0, y = 0;
1211 unsigned char ch;
1212
1213 for (ch = getch(); IS_DIGIT(ch); ch = getch())
1214 btn = btn * 10 + ch - '0';
1215 if (ch != ';')
1216 return MENU_NOTHING;
1217
1218 #if defined (__CYGWIN__) && CYGWIN_VERSION_DLL_MAJOR < 1005
1219 if (cygwin_mouse_btn_swapped) {
1220 if (btn == MOUSE_BTN2_DOWN)
1221 btn = MOUSE_BTN3_DOWN;
1222 else if (btn == MOUSE_BTN3_DOWN)
1223 btn = MOUSE_BTN2_DOWN;
1224 }
1225 #endif
1226
1227 for (ch = getch(); IS_DIGIT(ch); ch = getch())
1228 x = x * 10 + ch - '0';
1229 if (ch != ';')
1230 return MENU_NOTHING;
1231 if (x > 0)
1232 x--;
1233
1234 for (ch = getch(); IS_DIGIT(ch); ch = getch())
1235 y = y * 10 + ch - '0';
1236 if (ch == 'm')
1237 btn |= 3;
1238 else if (ch != 'M' && ch != ';')
1239 return MENU_NOTHING;
1240 if (y > 0)
1241 y--;
1242
1243 if (x < 0 || x >= COLS || y < 0 || y > LASTLINE)
1244 return MENU_NOTHING;
1245
1246 return process_mMouse(btn, x, y);
1247 }
1248
1249 #ifdef USE_GPM
1250 static int
gpm_process_menu_mouse(Gpm_Event * event,void * data)1251 gpm_process_menu_mouse(Gpm_Event * event, void *data)
1252 {
1253 int btn = MOUSE_BTN_RESET, x, y;
1254 if (event->type & GPM_UP)
1255 btn = MOUSE_BTN_UP;
1256 else if (event->type & GPM_DOWN) {
1257 switch (event->buttons) {
1258 case GPM_B_LEFT:
1259 btn = MOUSE_BTN1_DOWN;
1260 break;
1261 case GPM_B_MIDDLE:
1262 btn = MOUSE_BTN2_DOWN;
1263 break;
1264 case GPM_B_RIGHT:
1265 btn = MOUSE_BTN3_DOWN;
1266 break;
1267 }
1268 }
1269 else {
1270 GPM_DRAWPOINTER(event);
1271 return 0;
1272 }
1273 x = event->x;
1274 y = event->y;
1275 X_Mouse_Selection = process_mMouse(btn, x - 1, y - 1);
1276 return X_MOUSE_SELECTED;
1277 }
1278 #endif /* USE_GPM */
1279
1280 #ifdef USE_SYSMOUSE
1281 static int
sysm_process_menu_mouse(int x,int y,int nbs,int obs)1282 sysm_process_menu_mouse(int x, int y, int nbs, int obs)
1283 {
1284 int btn;
1285 int bits;
1286
1287 if (obs & ~nbs)
1288 btn = MOUSE_BTN_UP;
1289 else if (nbs & ~obs) {
1290 bits = nbs & ~obs;
1291 btn = bits & 0x1 ? MOUSE_BTN1_DOWN :
1292 (bits & 0x2 ? MOUSE_BTN2_DOWN :
1293 (bits & 0x4 ? MOUSE_BTN3_DOWN : 0));
1294 }
1295 else /* nbs == obs */
1296 return 0;
1297 X_Mouse_Selection = process_mMouse(btn, x, y);
1298 return X_MOUSE_SELECTED;
1299 }
1300 #endif /* USE_SYSMOUSE */
1301 #else /* not USE_MOUSE */
1302 static int
mMouse(char c)1303 mMouse(char c)
1304 {
1305 return (MENU_NOTHING);
1306 }
1307
1308 static int
mSgrMouse(char c)1309 mSgrMouse(char c)
1310 {
1311 return (MENU_NOTHING);
1312 }
1313 #endif /* not USE_MOUSE */
1314
1315 /* --- MenuFunctions (END) --- */
1316
1317 /* --- MainMenu --- */
1318
1319 void
popupMenu(int x,int y,Menu * menu)1320 popupMenu(int x, int y, Menu *menu)
1321 {
1322 set_menu_frame();
1323
1324 initSelectMenu();
1325 initSelTabMenu();
1326
1327 menu->cursorX = Currentbuf->cursorX + Currentbuf->rootX;
1328 menu->cursorY = Currentbuf->cursorY + Currentbuf->rootY;
1329 menu->x = x + FRAME_WIDTH + 1;
1330 menu->y = y + 2;
1331
1332 popup_menu(NULL, menu);
1333 }
1334
1335 void
mainMenu(int x,int y)1336 mainMenu(int x, int y)
1337 {
1338 popupMenu(x, y, &MainMenu);
1339 }
1340
1341 DEFUN(mainMn, MAIN_MENU MENU, "Pop up menu")
1342 {
1343 Menu *menu = &MainMenu;
1344 char *data;
1345 int n;
1346 int x = Currentbuf->cursorX + Currentbuf->rootX,
1347 y = Currentbuf->cursorY + Currentbuf->rootY;
1348
1349 data = searchKeyData();
1350 if (data != NULL) {
1351 n = getMenuN(w3mMenuList, data);
1352 if (n < 0)
1353 return;
1354 menu = w3mMenuList[n].menu;
1355 }
1356 #ifdef USE_MOUSE
1357 if (mouse_action.in_action) {
1358 x = mouse_action.cursorX;
1359 y = mouse_action.cursorY;
1360 }
1361 #endif
1362 popupMenu(x, y, menu);
1363 }
1364
1365 /* --- MainMenu (END) --- */
1366
1367 /* --- SelectMenu --- */
1368
1369 DEFUN(selMn, SELECT_MENU, "Pop up buffer-stack menu")
1370 {
1371 int x = Currentbuf->cursorX + Currentbuf->rootX,
1372 y = Currentbuf->cursorY + Currentbuf->rootY;
1373
1374 #ifdef USE_MOUSE
1375 if (mouse_action.in_action) {
1376 x = mouse_action.cursorX;
1377 y = mouse_action.cursorY;
1378 }
1379 #endif
1380 popupMenu(x, y, &SelectMenu);
1381 }
1382
1383 static void
initSelectMenu(void)1384 initSelectMenu(void)
1385 {
1386 int i, nitem, len = 0, l;
1387 Buffer *buf;
1388 Str str;
1389 char **label;
1390 char *p;
1391 static char *comment = " SPC for select / D for delete buffer ";
1392
1393 SelectV = -1;
1394 for (i = 0, buf = Firstbuf; buf != NULL; i++, buf = buf->nextBuffer) {
1395 if (buf == Currentbuf)
1396 SelectV = i;
1397 }
1398 nitem = i;
1399
1400 label = New_N(char *, nitem + 2);
1401 for (i = 0, buf = Firstbuf; i < nitem; i++, buf = buf->nextBuffer) {
1402 str = Sprintf("<%s>", buf->buffername);
1403 if (buf->filename != NULL) {
1404 switch (buf->currentURL.scheme) {
1405 case SCM_LOCAL:
1406 if (strcmp(buf->currentURL.file, "-")) {
1407 Strcat_char(str, ' ');
1408 Strcat_charp(str,
1409 conv_from_system(buf->currentURL.real_file));
1410 }
1411 break;
1412 /* case SCM_UNKNOWN: */
1413 case SCM_MISSING:
1414 break;
1415 default:
1416 Strcat_char(str, ' ');
1417 p = url_decode2(parsedURL2Str(&buf->currentURL)->ptr, NULL);
1418 Strcat_charp(str, p);
1419 break;
1420 }
1421 }
1422 label[i] = str->ptr;
1423 if (len < str->length)
1424 len = str->length;
1425 }
1426 l = get_strwidth(comment);
1427 if (len < l + 4)
1428 len = l + 4;
1429 if (len > COLS - 2 * FRAME_WIDTH)
1430 len = COLS - 2 * FRAME_WIDTH;
1431 len = (len > 1) ? ((len - l + 1) / 2) : 0;
1432 str = Strnew();
1433 for (i = 0; i < len; i++)
1434 Strcat_char(str, '-');
1435 Strcat_charp(str, comment);
1436 for (i = 0; i < len; i++)
1437 Strcat_char(str, '-');
1438 label[nitem] = str->ptr;
1439 label[nitem + 1] = NULL;
1440
1441 new_option_menu(&SelectMenu, label, &SelectV, smChBuf);
1442 SelectMenu.initial = SelectV;
1443 SelectMenu.cursorX = Currentbuf->cursorX + Currentbuf->rootX;
1444 SelectMenu.cursorY = Currentbuf->cursorY + Currentbuf->rootY;
1445 SelectMenu.keymap['D'] = smDelBuf;
1446 SelectMenu.item[nitem].type = MENU_NOP;
1447 }
1448
1449 static void
smChBuf(void)1450 smChBuf(void)
1451 {
1452 int i;
1453 Buffer *buf;
1454
1455 if (SelectV < 0 || SelectV >= SelectMenu.nitem)
1456 return;
1457 for (i = 0, buf = Firstbuf; i < SelectV; i++, buf = buf->nextBuffer) ;
1458 Currentbuf = buf;
1459 for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) {
1460 if (buf == Currentbuf)
1461 continue;
1462 #ifdef USE_IMAGE
1463 deleteImage(buf);
1464 #endif
1465 if (clear_buffer)
1466 tmpClearBuffer(buf);
1467 }
1468 }
1469
1470 static int
smDelBuf(char c)1471 smDelBuf(char c)
1472 {
1473 int i, x, y, mselect;
1474 Buffer *buf;
1475
1476 if (CurrentMenu->select < 0 || CurrentMenu->select >= SelectMenu.nitem)
1477 return (MENU_NOTHING);
1478 for (i = 0, buf = Firstbuf; i < CurrentMenu->select;
1479 i++, buf = buf->nextBuffer) ;
1480 if (Currentbuf == buf)
1481 Currentbuf = buf->nextBuffer;
1482 Firstbuf = deleteBuffer(Firstbuf, buf);
1483 if (!Currentbuf)
1484 Currentbuf = nthBuffer(Firstbuf, i - 1);;
1485 if (Firstbuf == NULL) {
1486 Firstbuf = nullBuffer();
1487 Currentbuf = Firstbuf;
1488 }
1489
1490 x = CurrentMenu->x;
1491 y = CurrentMenu->y;
1492 mselect = CurrentMenu->select;
1493
1494 initSelectMenu();
1495
1496 CurrentMenu->x = x;
1497 CurrentMenu->y = y;
1498
1499 geom_menu(CurrentMenu, x, y, 0);
1500
1501 CurrentMenu->select = (mselect <= CurrentMenu->nitem - 2) ? mselect
1502 : (CurrentMenu->nitem - 2);
1503
1504 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1505 draw_all_menu(CurrentMenu);
1506 select_menu(CurrentMenu, CurrentMenu->select);
1507 return (MENU_NOTHING);
1508 }
1509
1510 /* --- SelectMenu (END) --- */
1511
1512 /* --- SelTabMenu --- */
1513
1514 DEFUN(tabMn, TAB_MENU, "Pop up tab selection menu")
1515 {
1516 int x = Currentbuf->cursorX + Currentbuf->rootX,
1517 y = Currentbuf->cursorY + Currentbuf->rootY;
1518
1519 #ifdef USE_MOUSE
1520 if (mouse_action.in_action) {
1521 x = mouse_action.cursorX;
1522 y = mouse_action.cursorY;
1523 }
1524 #endif
1525 popupMenu(x, y, &SelTabMenu);
1526 }
1527
1528 static void
initSelTabMenu(void)1529 initSelTabMenu(void)
1530 {
1531 int i, nitem, len = 0, l;
1532 TabBuffer *tab;
1533 Buffer *buf;
1534 Str str;
1535 char **label;
1536 char *p;
1537 static char *comment = " SPC for select / D for delete tab ";
1538
1539 SelTabV = -1;
1540 for (i = 0, tab = LastTab; tab != NULL; i++, tab = tab->prevTab) {
1541 if (tab == CurrentTab)
1542 SelTabV = i;
1543 }
1544 nitem = i;
1545
1546 label = New_N(char *, nitem + 2);
1547 for (i = 0, tab = LastTab; i < nitem; i++, tab = tab->prevTab) {
1548 buf = tab->currentBuffer;
1549 str = Sprintf("<%s>", buf->buffername);
1550 if (buf->filename != NULL) {
1551 switch (buf->currentURL.scheme) {
1552 case SCM_LOCAL:
1553 if (strcmp(buf->currentURL.file, "-")) {
1554 Strcat_char(str, ' ');
1555 Strcat_charp(str,
1556 conv_from_system(buf->currentURL.real_file));
1557 }
1558 break;
1559 /* case SCM_UNKNOWN: */
1560 case SCM_MISSING:
1561 break;
1562 default:
1563 p = url_decode2(parsedURL2Str(&buf->currentURL)->ptr, NULL);
1564 Strcat_charp(str, p);
1565 break;
1566 }
1567 }
1568 label[i] = str->ptr;
1569 if (len < str->length)
1570 len = str->length;
1571 }
1572 l = strlen(comment);
1573 if (len < l + 4)
1574 len = l + 4;
1575 if (len > COLS - 2 * FRAME_WIDTH)
1576 len = COLS - 2 * FRAME_WIDTH;
1577 len = (len > 1) ? ((len - l + 1) / 2) : 0;
1578 str = Strnew();
1579 for (i = 0; i < len; i++)
1580 Strcat_char(str, '-');
1581 Strcat_charp(str, comment);
1582 for (i = 0; i < len; i++)
1583 Strcat_char(str, '-');
1584 label[nitem] = str->ptr;
1585 label[nitem + 1] = NULL;
1586
1587 new_option_menu(&SelTabMenu, label, &SelTabV, smChTab);
1588 SelTabMenu.initial = SelTabV;
1589 SelTabMenu.cursorX = Currentbuf->cursorX + Currentbuf->rootX;
1590 SelTabMenu.cursorY = Currentbuf->cursorY + Currentbuf->rootY;
1591 SelTabMenu.keymap['D'] = smDelTab;
1592 SelTabMenu.item[nitem].type = MENU_NOP;
1593 }
1594
1595 static void
smChTab(void)1596 smChTab(void)
1597 {
1598 int i;
1599 TabBuffer *tab;
1600 Buffer *buf;
1601
1602 if (SelTabV < 0 || SelTabV >= SelTabMenu.nitem)
1603 return;
1604 for (i = 0, tab = LastTab; i < SelTabV && tab != NULL;
1605 i++, tab = tab->prevTab) ;
1606 CurrentTab = tab;
1607 for (tab = LastTab; tab != NULL; tab = tab->prevTab) {
1608 if (tab == CurrentTab)
1609 continue;
1610 buf = tab->currentBuffer;
1611 #ifdef USE_IMAGE
1612 deleteImage(buf);
1613 #endif
1614 if (clear_buffer)
1615 tmpClearBuffer(buf);
1616 }
1617 }
1618
1619 static int
smDelTab(char c)1620 smDelTab(char c)
1621 {
1622 int i, x, y, mselect;
1623 TabBuffer *tab;
1624
1625 if (CurrentMenu->select < 0 || CurrentMenu->select >= SelTabMenu.nitem)
1626 return (MENU_NOTHING);
1627 for (i = 0, tab = LastTab; i < CurrentMenu->select && tab != NULL;
1628 i++, tab = tab->prevTab) ;
1629 deleteTab(tab);
1630
1631 x = CurrentMenu->x;
1632 y = CurrentMenu->y;
1633 mselect = CurrentMenu->select;
1634
1635 initSelTabMenu();
1636
1637 CurrentMenu->x = x;
1638 CurrentMenu->y = y;
1639
1640 geom_menu(CurrentMenu, x, y, 0);
1641
1642 CurrentMenu->select = (mselect <= CurrentMenu->nitem - 2) ? mselect
1643 : (CurrentMenu->nitem - 2);
1644
1645 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1646 draw_all_menu(CurrentMenu);
1647 select_menu(CurrentMenu, CurrentMenu->select);
1648 return (MENU_NOTHING);
1649 }
1650
1651 /* --- SelectMenu (END) --- */
1652
1653 /* --- OptionMenu --- */
1654
1655 void
optionMenu(int x,int y,char ** label,int * variable,int initial,void (* func)())1656 optionMenu(int x, int y, char **label, int *variable, int initial,
1657 void (*func) ())
1658 {
1659 Menu menu;
1660
1661 set_menu_frame();
1662
1663 new_option_menu(&menu, label, variable, func);
1664 menu.cursorX = COLS - 1;
1665 menu.cursorY = LASTLINE;
1666 menu.x = x;
1667 menu.y = y;
1668 menu.initial = initial;
1669
1670 popup_menu(NULL, &menu);
1671 }
1672
1673 /* --- OptionMenu (END) --- */
1674
1675 /* --- InitMenu --- */
1676
1677 static void
interpret_menu(FILE * mf)1678 interpret_menu(FILE * mf)
1679 {
1680 Str line;
1681 char *p, *s;
1682 int in_menu = 0, nmenu = 0, nitem = 0, type;
1683 MenuItem *item = NULL;
1684 #ifdef USE_M17N
1685 wc_ces charset = SystemCharset;
1686 #endif
1687
1688 while (!feof(mf)) {
1689 line = Strfgets(mf);
1690 Strchop(line);
1691 Strremovefirstspaces(line);
1692 if (line->length == 0)
1693 continue;
1694 #ifdef USE_M17N
1695 line = wc_Str_conv(line, charset, InnerCharset);
1696 #endif
1697 p = line->ptr;
1698 s = getWord(&p);
1699 if (*s == '#') /* comment */
1700 continue;
1701 if (in_menu) {
1702 type = setMenuItem(&item[nitem], s, p);
1703 if (type == -1)
1704 continue; /* error */
1705 if (type == MENU_END)
1706 in_menu = 0;
1707 else {
1708 nitem++;
1709 item = New_Reuse(MenuItem, item, (nitem + 1));
1710 w3mMenuList[nmenu].item = item;
1711 item[nitem].type = MENU_END;
1712 }
1713 }
1714 else if (!strcmp(s, "menu")) {
1715 s = getQWord(&p);
1716 if (*s == '\0') /* error */
1717 continue;
1718 in_menu = 1;
1719 if ((nmenu = getMenuN(w3mMenuList, s)) != -1)
1720 w3mMenuList[nmenu].item = New(MenuItem);
1721 else
1722 nmenu = addMenuList(&w3mMenuList, s);
1723 item = w3mMenuList[nmenu].item;
1724 nitem = 0;
1725 item[nitem].type = MENU_END;
1726 }
1727 #ifdef USE_M17N
1728 else if (!strcmp(s, "charset") || !strcmp(s, "encoding")) {
1729 s = getQWord(&p);
1730 if (*s == '\0') /* error */
1731 continue;
1732 charset = wc_guess_charset(s, charset);
1733 }
1734 #endif
1735 }
1736 }
1737
1738 void
initMenu(void)1739 initMenu(void)
1740 {
1741 FILE *mf;
1742 MenuList *list;
1743
1744 w3mMenuList = New_N(MenuList, 4);
1745 w3mMenuList[0].id = "Main";
1746 w3mMenuList[0].menu = &MainMenu;
1747 w3mMenuList[0].item = MainMenuItem;
1748 w3mMenuList[1].id = "Select";
1749 w3mMenuList[1].menu = &SelectMenu;
1750 w3mMenuList[1].item = NULL;
1751 w3mMenuList[2].id = "SelectTab";
1752 w3mMenuList[2].menu = &SelTabMenu;
1753 w3mMenuList[2].item = NULL;
1754 w3mMenuList[3].id = NULL;
1755
1756 #ifdef USE_M17N
1757 if (!MainMenuEncode) {
1758 MenuItem *item;
1759 #ifdef ENABLE_NLS
1760 /* FIXME: charset that gettext(3) returns */
1761 MainMenuCharset = SystemCharset;
1762 #endif
1763 for (item = MainMenuItem; item->type != MENU_END; item++)
1764 item->label =
1765 wc_conv(_(item->label), MainMenuCharset,
1766 InnerCharset)->ptr;
1767 MainMenuEncode = TRUE;
1768 }
1769 #endif
1770 if ((mf = fopen(confFile(MENU_FILE), "rt")) != NULL) {
1771 interpret_menu(mf);
1772 fclose(mf);
1773 }
1774 if ((mf = fopen(rcFile(MENU_FILE), "rt")) != NULL) {
1775 interpret_menu(mf);
1776 fclose(mf);
1777 }
1778
1779 for (list = w3mMenuList; list->id != NULL; list++) {
1780 if (list->item == NULL)
1781 continue;
1782 new_menu(list->menu, list->item);
1783 }
1784 }
1785
1786 int
setMenuItem(MenuItem * item,char * type,char * line)1787 setMenuItem(MenuItem *item, char *type, char *line)
1788 {
1789 char *label, *func, *popup, *keys, *data;
1790 int f;
1791 int n;
1792
1793 if (type == NULL || *type == '\0') /* error */
1794 return -1;
1795 if (strcmp(type, "end") == 0) {
1796 item->type = MENU_END;
1797 return MENU_END;
1798 }
1799 else if (strcmp(type, "nop") == 0) {
1800 item->type = MENU_NOP;
1801 item->label = getQWord(&line);
1802 return MENU_NOP;
1803 }
1804 else if (strcmp(type, "func") == 0) {
1805 label = getQWord(&line);
1806 func = getWord(&line);
1807 keys = getQWord(&line);
1808 data = getQWord(&line);
1809 if (*func == '\0') /* error */
1810 return -1;
1811 item->type = MENU_FUNC;
1812 item->label = label;
1813 f = getFuncList(func);
1814 item->func = w3mFuncList[(f >= 0) ? f : FUNCNAME_nulcmd].func;
1815 item->keys = keys;
1816 item->data = data;
1817 return MENU_FUNC;
1818 }
1819 else if (strcmp(type, "popup") == 0) {
1820 label = getQWord(&line);
1821 popup = getQWord(&line);
1822 keys = getQWord(&line);
1823 if (*popup == '\0') /* error */
1824 return -1;
1825 item->type = MENU_POPUP;
1826 item->label = label;
1827 if ((n = getMenuN(w3mMenuList, popup)) == -1)
1828 n = addMenuList(&w3mMenuList, popup);
1829 item->popup = w3mMenuList[n].menu;
1830 item->keys = keys;
1831 return MENU_POPUP;
1832 }
1833 return -1; /* error */
1834 }
1835
1836 int
addMenuList(MenuList ** mlist,char * id)1837 addMenuList(MenuList **mlist, char *id)
1838 {
1839 int n;
1840 MenuList *list = *mlist;
1841
1842 for (n = 0; list->id != NULL; list++, n++) ;
1843 *mlist = New_Reuse(MenuList, *mlist, (n + 2));
1844 list = *mlist + n;
1845 list->id = id;
1846 list->menu = New(Menu);
1847 list->item = New(MenuItem);
1848 (list + 1)->id = NULL;
1849 return n;
1850 }
1851
1852 int
getMenuN(MenuList * list,char * id)1853 getMenuN(MenuList *list, char *id)
1854 {
1855 int n;
1856
1857 for (n = 0; list->id != NULL; list++, n++) {
1858 if (strcmp(id, list->id) == 0)
1859 return n;
1860 }
1861 return -1;
1862 }
1863
1864 /* --- InitMenu (END) --- */
1865
1866 LinkList *
link_menu(Buffer * buf)1867 link_menu(Buffer *buf)
1868 {
1869 Menu menu;
1870 LinkList *l;
1871 int i, nitem, len = 0, linkV = -1;
1872 char **label;
1873 Str str;
1874 char *p;
1875
1876 if (!buf->linklist)
1877 return NULL;
1878
1879 for (i = 0, l = buf->linklist; l; i++, l = l->next) ;
1880 nitem = i;
1881
1882 label = New_N(char *, nitem + 1);
1883 for (i = 0, l = buf->linklist; l; i++, l = l->next) {
1884 str = Strnew_charp(l->title ? l->title : "(empty)");
1885 if (l->type == LINK_TYPE_REL)
1886 Strcat_charp(str, " [Rel] ");
1887 else if (l->type == LINK_TYPE_REV)
1888 Strcat_charp(str, " [Rev] ");
1889 else
1890 Strcat_charp(str, " ");
1891 if (!l->url)
1892 p = "";
1893 else
1894 p = url_decode2(l->url, buf);
1895 Strcat_charp(str, p);
1896 label[i] = str->ptr;
1897 if (len < str->length)
1898 len = str->length;
1899 }
1900 label[nitem] = NULL;
1901
1902 set_menu_frame();
1903 new_option_menu(&menu, label, &linkV, NULL);
1904
1905 menu.initial = 0;
1906 menu.cursorX = buf->cursorX + buf->rootX;
1907 menu.cursorY = buf->cursorY + buf->rootY;
1908 menu.x = menu.cursorX + FRAME_WIDTH + 1;
1909 menu.y = menu.cursorY + 2;
1910
1911 popup_menu(NULL, &menu);
1912
1913 if (linkV < 0)
1914 return NULL;
1915 for (i = 0, l = buf->linklist; l; i++, l = l->next) {
1916 if (i == linkV)
1917 return l;
1918 }
1919 return NULL;
1920 }
1921
1922 /* --- LinkMenu (END) --- */
1923
1924 Anchor *
accesskey_menu(Buffer * buf)1925 accesskey_menu(Buffer *buf)
1926 {
1927 Menu menu;
1928 AnchorList *al = buf->href;
1929 Anchor *a;
1930 Anchor **ap;
1931 int i, n, nitem = 0, key = -1;
1932 char **label;
1933 char *t;
1934 unsigned char c;
1935
1936 if (!al)
1937 return NULL;
1938 for (i = 0; i < al->nanchor; i++) {
1939 a = &al->anchors[i];
1940 if (!a->slave && a->accesskey && IS_ASCII(a->accesskey))
1941 nitem++;
1942 }
1943 if (!nitem)
1944 return NULL;
1945
1946 label = New_N(char *, nitem + 1);
1947 ap = New_N(Anchor *, nitem);
1948 for (i = 0, n = 0; i < al->nanchor; i++) {
1949 a = &al->anchors[i];
1950 if (!a->slave && a->accesskey && IS_ASCII(a->accesskey)) {
1951 t = getAnchorText(buf, al, a);
1952 label[n] = Sprintf("%c: %s", a->accesskey, t ? t : "")->ptr;
1953 ap[n] = a;
1954 n++;
1955 }
1956 }
1957 label[nitem] = NULL;
1958
1959 set_menu_frame();
1960 new_option_menu(&menu, label, &key, NULL);
1961
1962 menu.initial = 0;
1963 menu.cursorX = buf->cursorX + buf->rootX;
1964 menu.cursorY = buf->cursorY + buf->rootY;
1965 menu.x = menu.cursorX + FRAME_WIDTH + 1;
1966 menu.y = menu.cursorY + 2;
1967 for (i = 0; i < 128; i++)
1968 menu.keyselect[i] = -1;
1969 for (i = 0; i < nitem; i++) {
1970 c = ap[i]->accesskey;
1971 menu.keymap[(int)c] = mSelect;
1972 menu.keyselect[(int)c] = i;
1973 }
1974 for (i = 0; i < nitem; i++) {
1975 c = ap[i]->accesskey;
1976 if (!IS_ALPHA(c) || menu.keyselect[n] >= 0)
1977 continue;
1978 c = TOLOWER(c);
1979 menu.keymap[(int)c] = mSelect;
1980 menu.keyselect[(int)c] = i;
1981 c = TOUPPER(c);
1982 menu.keymap[(int)c] = mSelect;
1983 menu.keyselect[(int)c] = i;
1984 }
1985
1986 a = retrieveCurrentAnchor(buf);
1987 if (a && a->accesskey && IS_ASCII(a->accesskey)) {
1988 for (i = 0; i < nitem; i++) {
1989 if (a->hseq == ap[i]->hseq) {
1990 menu.initial = i;
1991 break;
1992 }
1993 }
1994 }
1995
1996 popup_menu(NULL, &menu);
1997
1998 return (key >= 0) ? ap[key] : NULL;
1999 }
2000
2001 static char lmKeys[] = "abcdefgimopqrstuvwxyz";
2002 static char lmKeys2[] = "1234567890ABCDEFGHILMOPQRSTUVWXYZ";
2003 #define nlmKeys (sizeof(lmKeys) - 1)
2004 #define nlmKeys2 (sizeof(lmKeys2) - 1)
2005
2006 static int
lmGoto(char c)2007 lmGoto(char c)
2008 {
2009 if (IS_ASCII(c) && CurrentMenu->keyselect[(int)c] >= 0) {
2010 goto_menu(CurrentMenu, CurrentMenu->nitem - 1, -1);
2011 goto_menu(CurrentMenu, CurrentMenu->keyselect[(int)c] * nlmKeys, 1);
2012 }
2013 return (MENU_NOTHING);
2014 }
2015
2016 static int
lmSelect(char c)2017 lmSelect(char c)
2018 {
2019 if (IS_ASCII(c))
2020 return select_menu(CurrentMenu, (CurrentMenu->select / nlmKeys) *
2021 nlmKeys + CurrentMenu->keyselect[(int)c]);
2022 else
2023 return (MENU_NOTHING);
2024 }
2025
2026 Anchor *
list_menu(Buffer * buf)2027 list_menu(Buffer *buf)
2028 {
2029 Menu menu;
2030 AnchorList *al = buf->href;
2031 Anchor *a;
2032 Anchor **ap;
2033 int i, n, nitem = 0, key = -1, two = FALSE;
2034 char **label;
2035 char *t;
2036 unsigned char c;
2037
2038 if (!al)
2039 return NULL;
2040 for (i = 0; i < al->nanchor; i++) {
2041 a = &al->anchors[i];
2042 if (!a->slave)
2043 nitem++;
2044 }
2045 if (!nitem)
2046 return NULL;
2047
2048 if (nitem >= nlmKeys)
2049 two = TRUE;
2050 label = New_N(char *, nitem + 1);
2051 ap = New_N(Anchor *, nitem);
2052 for (i = 0, n = 0; i < al->nanchor; i++) {
2053 a = &al->anchors[i];
2054 if (!a->slave) {
2055 t = getAnchorText(buf, al, a);
2056 if (!t)
2057 t = "";
2058 if (two && n >= nlmKeys2 * nlmKeys)
2059 label[n] = Sprintf(" : %s", t)->ptr;
2060 else if (two)
2061 label[n] = Sprintf("%c%c: %s", lmKeys2[n / nlmKeys],
2062 lmKeys[n % nlmKeys], t)->ptr;
2063 else
2064 label[n] = Sprintf("%c: %s", lmKeys[n], t)->ptr;
2065 ap[n] = a;
2066 n++;
2067 }
2068 }
2069 label[nitem] = NULL;
2070
2071 set_menu_frame();
2072 new_option_menu(&menu, label, &key, NULL);
2073
2074 menu.initial = 0;
2075 menu.cursorX = buf->cursorX + buf->rootX;
2076 menu.cursorY = buf->cursorY + buf->rootY;
2077 menu.x = menu.cursorX + FRAME_WIDTH + 1;
2078 menu.y = menu.cursorY + 2;
2079 for (i = 0; i < 128; i++)
2080 menu.keyselect[i] = -1;
2081 if (two) {
2082 for (i = 0; i < nlmKeys2; i++) {
2083 c = lmKeys2[i];
2084 menu.keymap[(int)c] = lmGoto;
2085 menu.keyselect[(int)c] = i;
2086 }
2087 for (i = 0; i < nlmKeys; i++) {
2088 c = lmKeys[i];
2089 menu.keymap[(int)c] = lmSelect;
2090 menu.keyselect[(int)c] = i;
2091 }
2092 }
2093 else {
2094 for (i = 0; i < nitem; i++) {
2095 c = lmKeys[i];
2096 menu.keymap[(int)c] = mSelect;
2097 menu.keyselect[(int)c] = i;
2098 }
2099 }
2100
2101 a = retrieveCurrentAnchor(buf);
2102 if (a) {
2103 for (i = 0; i < nitem; i++) {
2104 if (a->hseq == ap[i]->hseq) {
2105 menu.initial = i;
2106 break;
2107 }
2108 }
2109 }
2110
2111 popup_menu(NULL, &menu);
2112
2113 return (key >= 0) ? ap[key] : NULL;
2114 }
2115
2116 #endif /* USE_MENU */
2117