ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/menubar.C
(Generate patch)

Comparing rxvt-unicode/src/menubar.C (file contents):
Revision 1.5 by pcg, Sat Jan 31 03:27:45 2004 UTC vs.
Revision 1.29 by root, Tue Jan 3 02:43:33 2006 UTC

1/*--------------------------------*-C-*---------------------------------* 1/*--------------------------------*-C-*---------------------------------*
2 * File: menubar.c 2 * File: menubar.C
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * 4 *
5 * Copyright (c) 1997,1998 mj olesen <olesen@me.QueensU.CA> 5 * Copyright (c) 1997,1998 mj olesen <olesen@me.QueensU.CA>
6 * Copyright (c) 2004 Marc Lehmann <pcg@goof.com>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 11 * (at your option) any later version.
21 * refer.html (or refer.txt) contains up-to-date documentation. The 22 * refer.html (or refer.txt) contains up-to-date documentation. The
22 * summary that appears at the end of this file was taken from there. 23 * summary that appears at the end of this file was taken from there.
23 *----------------------------------------------------------------------*/ 24 *----------------------------------------------------------------------*/
24 25
25#include "../config.h" /* NECESSARY */ 26#include "../config.h" /* NECESSARY */
27
28#include <cstdlib>
29
26#include "rxvt.h" /* NECESSARY */ 30#include "rxvt.h" /* NECESSARY */
27#ifdef MENUBAR 31#ifdef MENUBAR
28#include "version.h" 32#include "version.h"
29#include "menubar.h" 33#include "menubar.h"
30#include "menubar.intpro" /* PROTOS for internal routines */
31 34
32#define Menu_PixelWidth(menu) \ 35#define Menu_PixelWidth(menu) \
33 (2 * SHADOW + Width2Pixel ((menu)->width + 3 * HSPACE)) 36 (2 * MENU_SHADOW + Width2Pixel ((menu)->width + 3 * HSPACE))
34 37
35static const struct { 38static const struct
39 {
36 const char name; /* (l)eft, (u)p, (d)own, (r)ight */ 40 const char name; /* (l)eft, (u)p, (d)own, (r)ight */
37 const unsigned char str[5]; /* str[0] = STRLEN (str+1) */ 41 const unsigned char str[5]; /* str[0] = strlen (str+1) */
42 }
38} Arrows[NARROWS] = { 43Arrows[NARROWS] = {
39 { 'l', "\003\033[D" }, 44 { 'l', "\003\033[D" },
40 { 'u', "\003\033[A" }, 45 { 'u', "\003\033[A" },
41 { 'd', "\003\033[B" }, 46 { 'd', "\003\033[B" },
42 { 'r', "\003\033[C" } 47 { 'r', "\003\033[C" }
43}; 48 };
44 49
45/*}}} */ 50/*}}} */
51
52static void
53draw_string (rxvt_drawable &d, GC gc, rxvt_fontset *fs, int x, int y, char *str, int len)
54{
55 mbstate mbs;
56
57 while (len)
58 {
59 wchar_t w;
60 int l = mbrtowc (&w, str, len, mbs);
61
62 if (l <= 0)
63 break;
64
65 len -= l;
66 str += l;
67
68 rxvt_font *font = (*fs)[fs->find_font (w)];
69 text_t ch = w;
70 font->draw (d, x, y, &ch, 1, Color_bg, Color_scroll);
71
72 x += font->width * wcwidth (w);
73 }
74}
46 75
47/* 76/*
48 * find an item called NAME in MENU 77 * find an item called NAME in MENU
49 */ 78 */
50menuitem_t * 79menuitem_t *
51rxvt_menuitem_find(const menu_t *menu, const char *name) 80rxvt_menuitem_find (const menu_t *menu, const char *name)
52{ 81{
53 menuitem_t *item; 82 menuitem_t *item;
54 83
55#ifdef DEBUG_STRICT 84#ifdef DEBUG_STRICT
56 assert(name != NULL); 85 assert (name != NULL);
57 assert(menu != NULL); 86 assert (menu != NULL);
58#endif 87#endif
59 88
60/* find the last item in the menu, this is good for separators */ 89 /* find the last item in the menu, this is good for separators */
61 for (item = menu->tail; item != NULL; item = item->prev) { 90 for (item = menu->tail; item != NULL; item = item->prev)
91 {
62 if (item->entry.type == MenuSubMenu) { 92 if (item->entry.type == MenuSubMenu)
93 {
63 if (!STRCMP(name, (item->entry.submenu.menu)->name)) 94 if (!strcmp (name, (item->entry.submenu.menu)->name))
64 break; 95 break;
96 }
65 } else if ((isSeparator(name) && isSeparator(item->name)) 97 else if ((isSeparator (name) && isSeparator (item->name))
66 || !STRCMP(name, item->name)) 98 || !strcmp (name, item->name))
67 break; 99 break;
68 } 100 }
69 return item; 101 return item;
70} 102}
71 103
72/* 104/*
73 * unlink ITEM from its MENU and free its memory 105 * unlink ITEM from its MENU and free its memory
74 */ 106 */
75void 107void
76rxvt_term::menuitem_free (menu_t *menu, menuitem_t *item) 108rxvt_term::menuitem_free (menu_t *menu, menuitem_t *item)
77{ 109{
78/* disconnect */ 110 /* disconnect */
79 menuitem_t *prev, *next; 111 menuitem_t *prev, *next;
80 112
81#ifdef DEBUG_STRICT 113#ifdef DEBUG_STRICT
82 assert(menu != NULL); 114 assert (menu != NULL);
83#endif 115#endif
84 116
85 prev = item->prev; 117 prev = item->prev;
86 next = item->next; 118 next = item->next;
87 if (prev != NULL) 119 if (prev != NULL)
88 prev->next = next; 120 prev->next = next;
89 if (next != NULL) 121 if (next != NULL)
90 next->prev = prev; 122 next->prev = prev;
91 123
92/* new head, tail */ 124 /* new head, tail */
93 if (menu->tail == item) 125 if (menu->tail == item)
94 menu->tail = prev; 126 menu->tail = prev;
95 if (menu->head == item) 127 if (menu->head == item)
96 menu->head = next; 128 menu->head = next;
97 129
98 switch (item->entry.type) { 130 switch (item->entry.type)
131 {
99 case MenuAction: 132 case MenuAction:
100 case MenuTerminalAction: 133 case MenuTerminalAction:
101 free(item->entry.action.str); 134 free (item->entry.action.str);
102 break; 135 break;
103 case MenuSubMenu: 136 case MenuSubMenu:
104 menu_delete (item->entry.submenu.menu); 137 menu_delete (item->entry.submenu.menu);
105 break; 138 break;
106 } 139 }
107 if (item->name != NULL) 140 if (item->name != NULL)
108 free(item->name); 141 free (item->name);
109 if (item->name2 != NULL) 142 if (item->name2 != NULL)
110 free(item->name2); 143 free (item->name2);
111 free(item); 144 free (item);
112} 145}
113 146
114/* 147/*
115 * sort command vs. terminal actions and 148 * sort command vs. terminal actions and
116 * remove the first character of STR if it's '\0' 149 * remove the first character of STR if it's '\0'
117 */ 150 */
118int 151int
119rxvt_action_type(action_t *action, unsigned char *str) 152rxvt_action_type (action_t *action, unsigned char *str)
120{ 153{
121 unsigned int len; 154 unsigned int len;
122 155
123#if defined (DEBUG_MENU) || defined (DEBUG_MENUARROWS) 156#if defined (DEBUG_MENU) || defined (DEBUG_MENUARROWS)
124 len = STRLEN(str); 157 len = strlen (str);
125 fprintf(stderr, "(len %d) = %s\n", len, str); 158 fprintf (stderr, " (len %d) = %s\n", len, str);
126#else 159#else
127 len = rxvt_Str_escaped((char *)str); 160 len = rxvt_Str_escaped ((char *)str);
128#endif 161#endif
129 162
130 if (!len) 163 if (!len)
131 return -1; 164 return -1;
132 165
133/* sort command vs. terminal actions */ 166 /* sort command vs. terminal actions */
134 action->type = MenuAction; 167 action->type = MenuAction;
135 if (str[0] == '\0') { 168 if (str[0] == '\0')
169 {
136 /* the functional equivalent: memmove (str, str+1, len); */ 170 /* the functional equivalent: memmove (str, str+1, len); */
137 unsigned char *dst = (str); 171 unsigned char *dst = (str);
138 unsigned char *src = (str + 1); 172 unsigned char *src = (str + 1);
139 unsigned char *end = (str + len); 173 unsigned char *end = (str + len);
140 174
141 while (src <= end) 175 while (src <= end)
142 *dst++ = *src++; 176 *dst++ = *src++;
143 177
144 len--; /* decrement length */ 178 len--; /* decrement length */
145 if (str[0] != '\0') 179 if (str[0] != '\0')
146 action->type = MenuTerminalAction; 180 action->type = MenuTerminalAction;
147 } 181 }
148 action->str = str; 182 action->str = str;
149 action->len = len; 183 action->len = len;
150 184
151 return 0; 185 return 0;
152} 186}
153 187
154int 188int
155rxvt_term::action_dispatch (action_t *action) 189rxvt_term::action_dispatch (action_t *action)
156{ 190{
157 switch (action->type) { 191 switch (action->type)
192 {
158 case MenuTerminalAction: 193 case MenuTerminalAction:
159 cmd_write (action->str, action->len); 194 cmd_write (action->str, action->len);
160 break; 195 break;
161 196
162 case MenuAction: 197 case MenuAction:
163 tt_write (action->str, action->len); 198 tt_write (action->str, action->len);
164 break; 199 break;
165 200
166 default: 201 default:
167 return -1; 202 return -1;
168 break; 203 break;
169 } 204 }
170 return 0; 205 return 0;
171} 206}
172 207
173/* return the arrow index corresponding to NAME */ 208/* return the arrow index corresponding to NAME */
174int 209int
175rxvt_menuarrow_find(char name) 210rxvt_menuarrow_find (char name)
176{ 211{
177 int i; 212 int i;
178 213
179 for (i = 0; i < NARROWS; i++) 214 for (i = 0; i < NARROWS; i++)
180 if (name == Arrows[i].name) 215 if (name == Arrows[i].name)
181 return i; 216 return i;
182 return -1; 217 return -1;
183} 218}
184 219
185/* free the memory associated with arrow NAME of the current menubar */ 220/* free the memory associated with arrow NAME of the current menubar */
186void 221void
187rxvt_term::menuarrow_free (char name) 222rxvt_term::menuarrow_free (char name)
188{ 223{
189 int i; 224 int i;
190 225
191 if (name) { 226 if (name)
227 {
192 i = rxvt_menuarrow_find(name); 228 i = rxvt_menuarrow_find (name);
193 if (i >= 0) { 229 if (i >= 0)
230 {
194 action_t *act = &(CurrentBar->arrows[i]); 231 action_t *act = & (CurrentBar->arrows[i]);
195 232
196 switch (act->type) { 233 switch (act->type)
234 {
197 case MenuAction: 235 case MenuAction:
198 case MenuTerminalAction: 236 case MenuTerminalAction:
199 free(act->str); 237 free (act->str);
200 act->str = NULL; 238 act->str = NULL;
201 act->len = 0; 239 act->len = 0;
202 break; 240 break;
241 }
242 act->type = MenuLabel;
243 }
203 } 244 }
204 act->type = MenuLabel; 245 else
205 } 246 {
206 } else {
207 for (i = 0; i < NARROWS; i++) 247 for (i = 0; i < NARROWS; i++)
208 menuarrow_free (Arrows[i].name); 248 menuarrow_free (Arrows[i].name);
209 } 249 }
210} 250}
211 251
212void 252void
213rxvt_term::menuarrow_add (char *string) 253rxvt_term::menuarrow_add (char *string)
214{ 254{
215 int i; 255 int i;
216 unsigned xtra_len; 256 unsigned xtra_len;
217 char *p; 257 char *p;
218 struct { 258 struct
259 {
219 char *str; 260 char *str;
220 int len; 261 int len;
221 } 262 }
222 beg = { NULL, 0 }, 263 beg = { NULL, 0 },
223 end = { NULL, 0 }, 264 end = { NULL, 0 },
224 *cur, 265 *cur,
225 parse[NARROWS]; 266 parse[NARROWS];
226 267
227 MEMSET(parse, 0, sizeof(parse)); 268 memset (parse, 0, sizeof (parse));
228 269
229/* fprintf(stderr, "add arrows = `%s'\n", string); */ 270 /* fprintf (stderr, "add arrows = `%s'\n", string); */
230 for (p = string; p != NULL && *p; string = p) { 271 for (p = string; p != NULL && *p; string = p)
272 {
231 p = (string + 3); 273 p = (string + 3);
232 /* fprintf(stderr, "parsing at %s\n", string); */ 274 /* fprintf (stderr, "parsing at %s\n", string); */
233 switch (string[1]) { 275 switch (string[1])
234 case 'b': 276 {
277 case 'b':
235 cur = &beg; 278 cur = &beg;
236 break; 279 break;
237 case 'e': 280 case 'e':
238 cur = &end; 281 cur = &end;
239 break; 282 break;
240 283
241 default: 284 default:
242 i = rxvt_menuarrow_find(string[1]); 285 i = rxvt_menuarrow_find (string[1]);
243 if (i >= 0) 286 if (i >= 0)
244 cur = &(parse[i]); 287 cur = & (parse[i]);
288 else
289 continue; /* not found */
290 break;
291 }
292
293 string = p;
294 cur->str = string;
295 cur->len = 0;
296
297 if (cur == &end)
298 {
299 p = strchr (string, '\0');
300 }
245 else 301 else
246 continue; /* not found */ 302 {
247 break;
248 }
249
250 string = p;
251 cur->str = string;
252 cur->len = 0;
253
254 if (cur == &end) {
255 p = STRCHR(string, '\0');
256 } else {
257 char *next = string; 303 char *next = string;
258 304
259 while (1) { 305 while (1)
260 p = STRCHR(next, '<'); 306 {
261 if (p != NULL) { 307 p = strchr (next, '<');
308 if (p != NULL)
309 {
262 if (p[1] && p[2] == '>') 310 if (p[1] && p[2] == '>')
263 break; 311 break;
264 /* parsed */ 312 /* parsed */
265 } else { 313 }
314 else
315 {
266 if (beg.str == NULL) /* no end needed */ 316 if (beg.str == NULL) /* no end needed */
267 p = STRCHR(next, '\0'); 317 p = strchr (next, '\0');
268 break; 318 break;
269 } 319 }
270 next = (p + 1); 320 next = (p + 1);
271 } 321 }
272 } 322 }
273 323
274 if (p == NULL) 324 if (p == NULL)
275 return; 325 return;
276 cur->len = (p - string); 326 cur->len = (p - string);
277 } 327 }
278 328
279#ifdef DEBUG_MENUARROWS 329#ifdef DEBUG_MENUARROWS
280 cur = &beg; 330 cur = &beg;
281 fprintf(stderr, "<b>(len %d) = %.*s\n", 331 fprintf (stderr, "<b> (len %d) = %.*s\n",
282 cur->len, cur->len, (cur->str ? cur->str : "")); 332 cur->len, cur->len, (cur->str ? cur->str : ""));
283 for (i = 0; i < NARROWS; i++) { 333 for (i = 0; i < NARROWS; i++)
334 {
284 cur = &(parse[i]); 335 cur = & (parse[i]);
285 fprintf(stderr, "<%c>(len %d) = %.*s\n", 336 fprintf (stderr, "<%c> (len %d) = %.*s\n",
286 Arrows[i].name, 337 Arrows[i].name,
287 cur->len, cur->len, (cur->str ? cur->str : "")); 338 cur->len, cur->len, (cur->str ? cur->str : ""));
288 } 339 }
289 cur = &end; 340 cur = &end;
290 fprintf(stderr, "<e>(len %d) = %.*s\n", 341 fprintf (stderr, "<e> (len %d) = %.*s\n",
291 cur->len, cur->len, (cur->str ? cur->str : "")); 342 cur->len, cur->len, (cur->str ? cur->str : ""));
292#endif 343#endif
293 344
294 xtra_len = (beg.len + end.len); 345 xtra_len = (beg.len + end.len);
295 for (i = 0; i < NARROWS; i++) { 346 for (i = 0; i < NARROWS; i++)
347 {
296 if (xtra_len || parse[i].len) 348 if (xtra_len || parse[i].len)
297 menuarrow_free (Arrows[i].name); 349 menuarrow_free (Arrows[i].name);
298 } 350 }
299 351
300 for (i = 0; i < NARROWS; i++) { 352 for (i = 0; i < NARROWS; i++)
353 {
301 unsigned char *str; 354 unsigned char *str;
302 unsigned int len; 355 unsigned int len;
303 356
304 if (!parse[i].len) 357 if (!parse[i].len)
305 continue; 358 continue;
306 359
307 str = rxvt_malloc(parse[i].len + xtra_len + 1); 360 str = (unsigned char *) rxvt_malloc (parse[i].len + xtra_len + 1);
308 361
309 len = 0; 362 len = 0;
310 if (beg.len) { 363 if (beg.len)
311 STRNCPY(str + len, beg.str, beg.len); 364 {
365 strncpy (str + len, beg.str, beg.len);
312 len += beg.len; 366 len += beg.len;
313 } 367 }
314 STRNCPY(str + len, parse[i].str, parse[i].len); 368 strncpy (str + len, parse[i].str, parse[i].len);
315 len += parse[i].len; 369 len += parse[i].len;
316 370
317 if (end.len) { 371 if (end.len)
318 STRNCPY(str + len, end.str, end.len); 372 {
373 strncpy (str + len, end.str, end.len);
319 len += end.len; 374 len += end.len;
320 } 375 }
321 str[len] = '\0'; 376 str[len] = '\0';
322 377
323#ifdef DEBUG_MENUARROWS 378#ifdef DEBUG_MENUARROWS
324 fprintf(stderr, "<%c>(len %d) = %s\n", Arrows[i].name, len, str); 379 fprintf (stderr, "<%c> (len %d) = %s\n", Arrows[i].name, len, str);
325#endif 380#endif
326 if (rxvt_action_type(&(CurrentBar->arrows[i]), str) < 0) 381 if (rxvt_action_type (& (CurrentBar->arrows[i]), str) < 0)
327 free(str); 382 free (str);
328 } 383 }
329} 384}
330 385
331menuitem_t * 386menuitem_t *
332rxvt_menuitem_add(menu_t *menu, const char *name, const char *name2, const char *action) 387rxvt_menuitem_add (menu_t *menu, const char *name, const char *name2, const char *action)
333{ 388{
334 menuitem_t *item; 389 menuitem_t *item;
335 unsigned int len; 390 unsigned int len;
336 391
337#ifdef DEBUG_STRICT 392#ifdef DEBUG_STRICT
338 assert(name != NULL); 393 assert (name != NULL);
339 assert(action != NULL); 394 assert (action != NULL);
340#endif 395#endif
341 396
342 if (menu == NULL) 397 if (menu == NULL)
343 return NULL; 398 return NULL;
344 399
345 if (isSeparator(name)) { 400 if (isSeparator (name))
401 {
346 /* add separator, no action */ 402 /* add separator, no action */
347 name = ""; 403 name = "";
348 action = ""; 404 action = "";
349 } else {
350 /*
351 * add/replace existing menu item
352 */
353 item = rxvt_menuitem_find(menu, name);
354 if (item != NULL) {
355 if (item->name2 != NULL && name2 != NULL) {
356 free(item->name2);
357 item->len2 = 0;
358 item->name2 = NULL;
359 } 405 }
406 else
407 {
408 /*
409 * add/replace existing menu item
410 */
411 item = rxvt_menuitem_find (menu, name);
412 if (item != NULL)
413 {
414 if (item->name2 != NULL && name2 != NULL)
415 {
416 free (item->name2);
417 item->len2 = 0;
418 item->name2 = NULL;
419 }
360 switch (item->entry.type) { 420 switch (item->entry.type)
421 {
361 case MenuAction: 422 case MenuAction:
362 case MenuTerminalAction: 423 case MenuTerminalAction:
363 free(item->entry.action.str); 424 free (item->entry.action.str);
364 item->entry.action.str = NULL; 425 item->entry.action.str = NULL;
365 break; 426 break;
427 }
428 goto Item_Found;
429 }
366 } 430 }
367 goto Item_Found;
368 }
369 }
370/* allocate a new itemect */ 431 /* allocate a new itemect */
371 item = (menuitem_t *) rxvt_malloc(sizeof(menuitem_t)); 432 item = (menuitem_t *) rxvt_malloc (sizeof (menuitem_t));
372 433
373 item->len2 = 0; 434 item->len2 = 0;
374 item->name2 = NULL; 435 item->name2 = NULL;
375 436
376 len = STRLEN(name); 437 len = strlen (name);
377 item->name = rxvt_malloc(len + 1); 438 item->name = (char *)rxvt_malloc (len + 1);
378 STRCPY(item->name, name); 439 strcpy (item->name, name);
379 if (name[0] == '.' && name[1] != '.') 440 if (name[0] == '.' && name[1] != '.')
380 len = 0; /* hidden menu name */ 441 len = 0; /* hidden menu name */
381 item->len = len; 442 item->len = len;
382 443
383/* add to tail of list */ 444 /* add to tail of list */
384 item->prev = menu->tail; 445 item->prev = menu->tail;
385 item->next = NULL; 446 item->next = NULL;
386 447
387 if (menu->tail != NULL) 448 if (menu->tail != NULL)
388 (menu->tail)->next = item; 449 (menu->tail)->next = item;
389 menu->tail = item; 450 menu->tail = item;
390/* fix head */ 451 /* fix head */
391 if (menu->head == NULL) 452 if (menu->head == NULL)
392 menu->head = item; 453 menu->head = item;
393 454
394/* 455 /*
395 * add action 456 * add action
396 */ 457 */
397 Item_Found: 458Item_Found:
398 if (name2 != NULL && item->name2 == NULL) { 459 if (name2 != NULL && item->name2 == NULL)
399 len = STRLEN(name2); 460 {
461 len = strlen (name2);
400 if (len == 0) 462 if (len == 0)
401 item->name2 = NULL; 463 item->name2 = NULL;
402 else { 464 else
465 {
403 item->name2 = rxvt_malloc(len + 1); 466 item->name2 = (char *)rxvt_malloc (len + 1);
404 STRCPY(item->name2, name2); 467 strcpy (item->name2, name2);
405 } 468 }
406 item->len2 = len; 469 item->len2 = len;
407 } 470 }
408 item->entry.type = MenuLabel; 471 item->entry.type = MenuLabel;
409 len = STRLEN(action); 472 len = strlen (action);
410 473
411 if (len == 0 && item->name2 != NULL) { 474 if (len == 0 && item->name2 != NULL)
475 {
412 action = item->name2; 476 action = item->name2;
413 len = item->len2; 477 len = item->len2;
414 } 478 }
415 if (len) { 479 if (len)
480 {
416 unsigned char *str = rxvt_malloc(len + 1); 481 unsigned char *str = (unsigned char *)rxvt_malloc (len + 1);
417 482
418 STRCPY(str, action); 483 strcpy (str, action);
419 484
420 if (rxvt_action_type(&(item->entry.action), str) < 0) 485 if (rxvt_action_type (& (item->entry.action), str) < 0)
421 free(str); 486 free (str);
422 } 487 }
423/* new item and a possible increase in width */ 488 /* new item and a possible increase in width */
424 if (menu->width < (item->len + item->len2)) 489 if (menu->width < (item->len + item->len2))
425 menu->width = (item->len + item->len2); 490 menu->width = (item->len + item->len2);
426 491
427 return item; 492 return item;
428} 493}
429 494
430/* 495/*
431 * search for the base starting menu for NAME. 496 * search for the base starting menu for NAME.
432 * return a pointer to the portion of NAME that remains 497 * return a pointer to the portion of NAME that remains
433 */ 498 */
434char * 499char *
435rxvt_term::menu_find_base (menu_t **menu, char *path) 500rxvt_term::menu_find_base (menu_t **menu, char *path)
436{ 501{
437 menu_t *m = NULL; 502 menu_t *m = NULL;
438 menuitem_t *item; 503 menuitem_t *item;
439 504
440#ifdef DEBUG_STRICT 505#ifdef DEBUG_STRICT
441 assert(menu != NULL); 506 assert (menu != NULL);
442 assert(CurrentBar != NULL); 507 assert (CurrentBar != NULL);
443#endif 508#endif
444 509
445 if (path[0] == '\0') 510 if (path[0] == '\0')
446 return path;
447
448 if (STRCHR(path, '/') != NULL) {
449 char *p = path;
450
451 while ((p = STRCHR(p, '/')) != NULL) {
452 p++;
453 if (*p == '/')
454 path = p;
455 }
456 if (path[0] == '/') {
457 path++;
458 *menu = NULL;
459 }
460 while ((p = STRCHR(path, '/')) != NULL) {
461 p[0] = '\0';
462 if (path[0] == '\0')
463 return NULL;
464 if (!STRCMP(path, DOT)) {
465 /* nothing to do */
466 } else if (!STRCMP(path, DOTS)) {
467 if (*menu != NULL)
468 *menu = (*menu)->parent;
469 } else {
470 path = menu_find_base (menu, path);
471 if (path[0] != '\0') { /* not found */
472 p[0] = '/'; /* fix-up name again */
473 return path;
474 }
475 }
476
477 path = (p + 1);
478 }
479 }
480 if (!STRCMP(path, DOTS)) {
481 path += STRLEN(DOTS);
482 if (*menu != NULL)
483 *menu = (*menu)->parent;
484 return path;
485 }
486/* find this menu */
487 if (*menu == NULL) {
488 for (m = CurrentBar->tail; m != NULL; m = m->prev) {
489 if (!STRCMP(path, m->name))
490 break;
491 }
492 } else {
493 /* find this menu */
494 for (item = (*menu)->tail; item != NULL; item = item->prev) {
495 if (item->entry.type == MenuSubMenu
496 && !STRCMP(path, (item->entry.submenu.menu)->name)) {
497 m = (item->entry.submenu.menu);
498 break;
499 }
500 }
501 }
502 if (m != NULL) {
503 *menu = m;
504 path += STRLEN(path);
505 }
506 return path; 511 return path;
512
513 if (strchr (path, '/') != NULL)
514 {
515 char *p = path;
516
517 while ((p = strchr (p, '/')) != NULL)
518 {
519 p++;
520 if (*p == '/')
521 path = p;
522 }
523
524 if (path[0] == '/')
525 {
526 path++;
527 *menu = NULL;
528 }
529
530 while ((p = strchr (path, '/')) != NULL)
531 {
532 p[0] = '\0';
533 if (path[0] == '\0')
534 return NULL;
535
536 if (!strcmp (path, DOT))
537 {
538 /* nothing to do */
539 }
540 else if (!strcmp (path, DOTS))
541 {
542 if (*menu != NULL)
543 *menu = (*menu)->parent;
544 }
545 else
546 {
547 path = menu_find_base (menu, path);
548 if (path[0] != '\0')
549 { /* not found */
550 p[0] = '/'; /* fix-up name again */
551 return path;
552 }
553 }
554
555 path = (p + 1);
556 }
557 }
558
559 if (!strcmp (path, DOTS))
560 {
561 path += strlen (DOTS);
562 if (*menu != NULL)
563 *menu = (*menu)->parent;
564 return path;
565 }
566
567 /* find this menu */
568 if (*menu == NULL)
569 {
570 for (m = CurrentBar->tail; m != NULL; m = m->prev)
571 if (!strcmp (path, m->name))
572 break;
573 }
574 else
575 {
576 /* find this menu */
577 for (item = (*menu)->tail; item != NULL; item = item->prev)
578 {
579 if (item->entry.type == MenuSubMenu
580 && !strcmp (path, (item->entry.submenu.menu)->name))
581 {
582 m = (item->entry.submenu.menu);
583 break;
584 }
585 }
586 }
587
588 if (m != NULL)
589 {
590 *menu = m;
591 path += strlen (path);
592 }
593
594 return path;
507} 595}
508 596
509/* 597/*
510 * delete this entire menu 598 * delete this entire menu
511 */ 599 */
512menu_t * 600menu_t *
513rxvt_term::menu_delete (menu_t *menu) 601rxvt_term::menu_delete (menu_t *menu)
514{ 602{
515 menu_t *parent = NULL, *prev, *next; 603 menu_t *parent = NULL, *prev, *next;
516 menuitem_t *item; 604 menuitem_t *item;
517 bar_t *CurrentBar = CurrentBar;
518 605
519#ifdef DEBUG_STRICT 606#ifdef DEBUG_STRICT
520 assert(CurrentBar != NULL); 607 assert (CurrentBar != NULL);
521#endif 608#endif
522 609
523/* delete the entire menu */ 610 /* delete the entire menu */
524 if (menu == NULL) 611 if (menu == NULL)
525 return NULL; 612 return NULL;
526 613
527 parent = menu->parent; 614 parent = menu->parent;
528 615
529/* unlink MENU */ 616 /* unlink MENU */
530 prev = menu->prev; 617 prev = menu->prev;
531 next = menu->next; 618 next = menu->next;
532 if (prev != NULL) 619 if (prev != NULL)
533 prev->next = next; 620 prev->next = next;
534 if (next != NULL) 621 if (next != NULL)
535 next->prev = prev; 622 next->prev = prev;
536 623
537/* fix the index */ 624 /* fix the index */
538 if (parent == NULL) { 625 if (parent == NULL)
626 {
539 const int len = (menu->len + HSPACE); 627 const int len = (menu->len + HSPACE);
540 628
541 if (CurrentBar->tail == menu) 629 if (CurrentBar->tail == menu)
542 CurrentBar->tail = prev; 630 CurrentBar->tail = prev;
543 if (CurrentBar->head == menu) 631 if (CurrentBar->head == menu)
544 CurrentBar->head = next; 632 CurrentBar->head = next;
545 633
546 for (next = menu->next; next != NULL; next = next->next) 634 for (next = menu->next; next != NULL; next = next->next)
547 next->x -= len; 635 next->x -= len;
548 } else { 636 }
637 else
638 {
549 for (item = parent->tail; item != NULL; item = item->prev) { 639 for (item = parent->tail; item != NULL; item = item->prev)
640 {
550 if (item->entry.type == MenuSubMenu 641 if (item->entry.type == MenuSubMenu
551 && item->entry.submenu.menu == menu) { 642 && item->entry.submenu.menu == menu)
643 {
552 item->entry.submenu.menu = NULL; 644 item->entry.submenu.menu = NULL;
553 menuitem_free (menu->parent, item); 645 menuitem_free (menu->parent, item);
554 break; 646 break;
647 }
648 }
555 } 649 }
556 }
557 }
558 650
559 item = menu->tail; 651 item = menu->tail;
560 while (item != NULL) { 652 while (item != NULL)
653 {
561 menuitem_t *p = item->prev; 654 menuitem_t *p = item->prev;
562 655
563 menuitem_free (menu, item); 656 menuitem_free (menu, item);
564 item = p; 657 item = p;
565 } 658 }
566 659
567 if (menu->name != NULL)
568 free(menu->name); 660 free (menu->name);
569 free(menu); 661 free (menu);
570 662
571 return parent; 663 return parent;
572} 664}
573 665
574menu_t * 666menu_t *
575rxvt_term::menu_add (menu_t *parent, char *path) 667rxvt_term::menu_add (menu_t *parent, char *path)
576{ 668{
577 menu_t *menu; 669 menu_t *menu;
578 bar_t *CurrentBar = CurrentBar;
579 670
580#ifdef DEBUG_STRICT 671#ifdef DEBUG_STRICT
581 assert(CurrentBar != NULL); 672 assert (CurrentBar != NULL);
582#endif 673#endif
583 674
584 if (STRCHR(path, '/') != NULL) { 675 if (strchr (path, '/') != NULL)
585 char *p; 676 {
677 char *p;
586 678
587 if (path[0] == '/') { 679 if (path[0] == '/')
680 {
588 /* shouldn't happen */ 681 /* shouldn't happen */
589 path++; 682 path++;
590 parent = NULL; 683 parent = NULL;
591 } 684 }
592 while ((p = STRCHR(path, '/')) != NULL) { 685 while ((p = strchr (path, '/')) != NULL)
686 {
593 p[0] = '\0'; 687 p[0] = '\0';
594 if (path[0] == '\0') 688 if (path[0] == '\0')
595 return NULL; 689 return NULL;
596 690
597 parent = menu_add (parent, path); 691 parent = menu_add (parent, path);
598 path = (p + 1); 692 path = (p + 1);
599 } 693 }
600 } 694 }
601 if (!STRCMP(path, DOTS)) 695 if (!strcmp (path, DOTS))
602 return (parent != NULL ? parent->parent : parent); 696 return (parent != NULL ? parent->parent : parent);
603 697
604 if (!STRCMP(path, DOT) || path[0] == '\0') 698 if (!strcmp (path, DOT) || path[0] == '\0')
605 return parent; 699 return parent;
606 700
607/* allocate a new menu */ 701 /* allocate a new menu */
608 menu = (menu_t *) rxvt_malloc(sizeof(menu_t)); 702 menu = (menu_t *) rxvt_malloc (sizeof (menu_t));
609 703
610 menu->width = 0; 704 menu->width = 0;
611 menu->parent = parent; 705 menu->parent = parent;
612 menu->len = STRLEN(path); 706 menu->len = strlen (path);
613 menu->name = rxvt_malloc((menu->len + 1)); 707 menu->name = (char *)rxvt_malloc ((menu->len + 1));
614 STRCPY(menu->name, path); 708 strcpy (menu->name, path);
615 709
616/* initialize head/tail */ 710 /* initialize head/tail */
617 menu->head = menu->tail = NULL; 711 menu->head = menu->tail = NULL;
618 menu->prev = menu->next = NULL; 712 menu->prev = menu->next = NULL;
619 713
620 menu->win = None; 714 menu->win = None;
715 menu->drawable = 0;
621 menu->x = menu->y = menu->w = menu->h = 0; 716 menu->x = menu->y = menu->w = menu->h = 0;
622 menu->item = NULL; 717 menu->item = NULL;
623 718
624/* add to tail of list */ 719 /* add to tail of list */
625 if (parent == NULL) { 720 if (parent == NULL)
721 {
626 menu->prev = CurrentBar->tail; 722 menu->prev = CurrentBar->tail;
627 if (CurrentBar->tail != NULL) 723 if (CurrentBar->tail != NULL)
628 CurrentBar->tail->next = menu; 724 CurrentBar->tail->next = menu;
629 CurrentBar->tail = menu; 725 CurrentBar->tail = menu;
630 if (CurrentBar->head == NULL) 726 if (CurrentBar->head == NULL)
631 CurrentBar->head = menu; /* fix head */ 727 CurrentBar->head = menu; /* fix head */
632 if (menu->prev) 728 if (menu->prev)
633 menu->x = (menu->prev->x + menu->prev->len + HSPACE); 729 menu->x = (menu->prev->x + menu->prev->len + HSPACE);
634 } else { 730 }
731 else
732 {
635 menuitem_t *item; 733 menuitem_t *item;
636 734
637 item = rxvt_menuitem_add(parent, path, "", ""); 735 item = rxvt_menuitem_add (parent, path, "", "");
638 if (item == NULL) { 736 if (item == NULL)
737 {
639 free(menu); 738 free (menu);
640 return parent; 739 return parent;
641 } 740 }
642#ifdef DEBUG_STRICT 741#ifdef DEBUG_STRICT
643 assert(item->entry.type == MenuLabel); 742 assert (item->entry.type == MenuLabel);
644#endif 743#endif
645 item->entry.type = MenuSubMenu; 744 item->entry.type = MenuSubMenu;
646 item->entry.submenu.menu = menu; 745 item->entry.submenu.menu = menu;
647 } 746 }
648 747
649 return menu; 748 return menu;
650} 749}
651 750
652void 751void
653rxvt_term::drawbox_menubar (int x, int len, int state) 752rxvt_term::drawbox_menubar (int x, int len, int state)
654{ 753{
655 GC top, bot; 754 GC top, bot;
656 755
657 x = Width2Pixel(x); 756 x = Width2Pixel (x);
658 len = Width2Pixel(len + HSPACE); 757 len = Width2Pixel (len + HSPACE);
659 if (x >= TermWin.width) 758 if (x >= width)
660 return; 759 return;
661 else if (x + len >= TermWin.width) 760 else if (x + len >= width)
662 len = (TermWin_TotalWidth() - x); 761 len = (TermWin_TotalWidth () - x);
663 762
664#ifdef MENUBAR_SHADOW_IN 763#ifdef MENUBAR_SHADOW_IN
665 state = -state; 764 state = -state;
666#endif 765#endif
667 switch (state) { 766 switch (state)
767 {
668 case +1: 768 case +1:
669 top = topShadowGC; 769 top = topShadowGC;
670 bot = botShadowGC; 770 bot = botShadowGC;
671 break; /* SHADOW_OUT */ 771 break; /* SHADOW_OUT */
672 case -1: 772 case -1:
673 top = botShadowGC; 773 top = botShadowGC;
674 bot = topShadowGC; 774 bot = topShadowGC;
675 break; /* SHADOW_IN */ 775 break; /* SHADOW_IN */
676 default: 776 default:
677 top = bot = scrollbarGC; 777 top = bot = scrollbarGC;
678 break; /* neutral */ 778 break; /* neutral */
679 } 779 }
680 780
681 rxvt_Draw_Shadow(Xdisplay, menuBar.win, top, bot, 781 rxvt_Draw_Shadow (display->display, menuBar.win, top, bot,
682 x, 0, len, menuBar_TotalHeight()); 782 x, 0, len, menuBar_TotalHeight ());
683} 783}
684 784
685void 785void
686rxvt_term::drawtriangle (int x, int y, int state) 786rxvt_term::drawtriangle (int x, int y, int state)
687{ 787{
688 GC top, bot; 788 GC top, bot;
689 int w; 789 int w;
690 790
691#ifdef MENU_SHADOW_IN 791#ifdef MENU_SHADOW_IN
692 state = -state; 792 state = -state;
693#endif 793#endif
694 switch (state) { 794 switch (state)
795 {
695 case +1: 796 case +1:
696 top = topShadowGC; 797 top = topShadowGC;
697 bot = botShadowGC; 798 bot = botShadowGC;
698 break; /* SHADOW_OUT */ 799 break; /* SHADOW_OUT */
699 case -1: 800 case -1:
700 top = botShadowGC; 801 top = botShadowGC;
701 bot = topShadowGC; 802 bot = topShadowGC;
702 break; /* SHADOW_IN */ 803 break; /* SHADOW_IN */
703 default: 804 default:
704 top = bot = scrollbarGC; 805 top = bot = scrollbarGC;
705 break; /* neutral */ 806 break; /* neutral */
706 } 807 }
707 808
708 w = Height2Pixel(1) - 2 * SHADOW; 809 w = Height2Pixel (1) - 2 * MENU_SHADOW;
709 810
710 x -= SHADOW + (3 * w / 2); 811 x -= MENU_SHADOW + (3 * w / 2);
711 y += SHADOW * 3; 812 y += MENU_SHADOW * 3;
712 813
713 rxvt_Draw_Triangle(Xdisplay, ActiveMenu->win, top, bot, x, y, w, 814 rxvt_Draw_Triangle (display->display, ActiveMenu->win, top, bot, x, y, w, 'r');
714 'r');
715} 815}
716 816
717void 817void
718rxvt_term::drawbox_menuitem (int y, int state) 818rxvt_term::drawbox_menuitem (int y, int state)
719{ 819{
720 GC top, bot; 820 GC top, bot;
721 821
722#ifdef MENU_SHADOW_IN 822#ifdef MENU_SHADOW_IN
723 state = -state; 823 state = -state;
724#endif 824#endif
725 switch (state) { 825 switch (state)
826 {
726 case +1: 827 case +1:
727 top = topShadowGC; 828 top = topShadowGC;
728 bot = botShadowGC; 829 bot = botShadowGC;
729 break; /* SHADOW_OUT */ 830 break; /* SHADOW_OUT */
730 case -1: 831 case -1:
731 top = botShadowGC; 832 top = botShadowGC;
732 bot = topShadowGC; 833 bot = topShadowGC;
733 break; /* SHADOW_IN */ 834 break; /* SHADOW_IN */
734 default: 835 default:
735 top = bot = scrollbarGC; 836 top = bot = scrollbarGC;
736 break; /* neutral */ 837 break; /* neutral */
737 } 838 }
738 839
739 rxvt_Draw_Shadow(Xdisplay, ActiveMenu->win, top, bot, 840 rxvt_Draw_Shadow (display->display, ActiveMenu->win, top, bot,
740 SHADOW + 0, SHADOW + y, 841 MENU_SHADOW + 0, MENU_SHADOW + y,
741 ActiveMenu->w - 2 * (SHADOW), 842 ActiveMenu->w - 2 * (MENU_SHADOW),
742 HEIGHT_TEXT + 2 * SHADOW); 843 HEIGHT_TEXT + 2 * MENU_SHADOW);
743 XFlush(Xdisplay); 844 XFlush (display->display);
744} 845}
745 846
746#ifdef DEBUG_MENU_LAYOUT 847#ifdef DEBUG_MENU_LAYOUT
747void 848void
748rxvt_print_menu_ancestors(menu_t *menu) 849rxvt_print_menu_ancestors (menu_t *menu)
749{ 850{
750 if (menu == NULL) { 851 if (menu == NULL)
852 {
751 fprintf(stderr, "Top Level menu\n"); 853 fprintf (stderr, "Top Level menu\n");
752 return; 854 return;
753 } 855 }
856
754 fprintf(stderr, "menu %s ", menu->name); 857 fprintf (stderr, "menu %s ", menu->name);
755 if (menu->parent != NULL) { 858 if (menu->parent != NULL)
859 {
756 menuitem_t *item; 860 menuitem_t *item;
757 861
758 for (item = menu->parent->head; item != NULL; item = item->next) { 862 for (item = menu->parent->head; item != NULL; item = item->next)
863 {
759 if (item->entry.type == MenuSubMenu 864 if (item->entry.type == MenuSubMenu
760 && item->entry.submenu.menu == menu) { 865 && item->entry.submenu.menu == menu)
761 break; 866 {
867 break;
868 }
869 }
870
871 if (item == NULL)
872 {
873 fprintf (stderr, "is an orphan!\n");
874 return;
875 }
762 } 876 }
763 } 877
764 if (item == NULL) {
765 fprintf(stderr, "is an orphan!\n");
766 return;
767 }
768 }
769 fprintf(stderr, "\n"); 878 fprintf (stderr, "\n");
770 rxvt_print_menu_ancestors(menu->parent); 879 rxvt_print_menu_ancestors (menu->parent);
771} 880}
772 881
773void 882void
774rxvt_print_menu_descendants(menu_t *menu) 883rxvt_print_menu_descendants (menu_t *menu)
775{ 884{
776 menuitem_t *item; 885 menuitem_t *item;
777 menu_t *parent; 886 menu_t *parent;
778 int i, level = 0; 887 int i, level = 0;
779 888
780 parent = menu; 889 parent = menu;
890 do
781 do { 891 {
782 level++; 892 level++;
783 parent = parent->parent; 893 parent = parent->parent;
784 } 894 }
785 while (parent != NULL); 895 while (parent != NULL);
786 896
787 for (i = 0; i < level; i++) 897 for (i = 0; i < level; i++)
788 fprintf(stderr, ">"); 898 fprintf (stderr, ">");
789 fprintf(stderr, "%s\n", menu->name); 899 fprintf (stderr, "%s\n", menu->name);
790 900
791 for (item = menu->head; item != NULL; item = item->next) { 901 for (item = menu->head; item != NULL; item = item->next)
902 {
792 if (item->entry.type == MenuSubMenu) { 903 if (item->entry.type == MenuSubMenu)
904 {
793 if (item->entry.submenu.menu == NULL) 905 if (item->entry.submenu.menu == NULL)
794 fprintf(stderr, "> %s == NULL\n", item->name); 906 fprintf (stderr, "> %s == NULL\n", item->name);
795 else 907 else
796 rxvt_print_menu_descendants(item->entry.submenu.menu); 908 rxvt_print_menu_descendants (item->entry.submenu.menu);
797 } else { 909 }
910 else
911 {
798 for (i = 0; i < level; i++) 912 for (i = 0; i < level; i++)
799 fprintf(stderr, "+"); 913 fprintf (stderr, "+");
800 if (item->entry.type == MenuLabel) 914 if (item->entry.type == MenuLabel)
801 fprintf(stderr, "label: "); 915 fprintf (stderr, "label: ");
802 fprintf(stderr, "%s\n", item->name); 916 fprintf (stderr, "%s\n", item->name);
803 } 917 }
804 } 918 }
805 919
806 for (i = 0; i < level; i++) 920 for (i = 0; i < level; i++)
807 fprintf(stderr, "<"); 921 fprintf (stderr, "<");
808 fprintf(stderr, "\n"); 922 fprintf (stderr, "\n");
809} 923}
810#endif 924#endif
811 925
812/* pop up/down the current menu and redraw the menuBar button */ 926/* pop up/down the current menu and redraw the menuBar button */
813void 927void
814rxvt_term::menu_show () 928rxvt_term::menu_show ()
815{ 929{
816 int x, y, xright; 930 int x, y, xright;
817 menu_t *ActiveMenu = ActiveMenu;
818 menuitem_t *item; 931 menuitem_t *item;
819 932
820 if (ActiveMenu == NULL) 933 if (ActiveMenu == NULL)
821 return; 934 return;
822 935
823 x = ActiveMenu->x; 936 x = ActiveMenu->x;
824 if (ActiveMenu->parent == NULL) { 937 if (ActiveMenu->parent == NULL)
938 {
825 register int h; 939 register int h;
826 940
827 drawbox_menubar (x, ActiveMenu->len, -1); 941 drawbox_menubar (x, ActiveMenu->len, -1);
828 x = Width2Pixel(x); 942 x = Width2Pixel (x);
829 943
830 ActiveMenu->y = 1; 944 ActiveMenu->y = 1;
831 ActiveMenu->w = Menu_PixelWidth(ActiveMenu); 945 ActiveMenu->w = Menu_PixelWidth (ActiveMenu);
832 946
833 if ((x + ActiveMenu->w) >= TermWin.width) 947 if ((x + ActiveMenu->w) >= width)
834 x = (TermWin_TotalWidth() - ActiveMenu->w); 948 x = (TermWin_TotalWidth () - ActiveMenu->w);
835 949
836 /* find the height */ 950 /* find the height */
837 for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next) 951 for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next)
838 h += isSeparator(item->name) ? HEIGHT_SEPARATOR 952 h += isSeparator (item->name) ? HEIGHT_SEPARATOR
839 : HEIGHT_TEXT + 2 * SHADOW; 953 : HEIGHT_TEXT + 2 * MENU_SHADOW;
840 ActiveMenu->h = h + 2 * SHADOW; 954 ActiveMenu->h = h + 2 * MENU_SHADOW;
841 } 955 }
956
842 if (ActiveMenu->win == None) { 957 if (ActiveMenu->win == None)
958 {
843 ActiveMenu->win = XCreateSimpleWindow(Xdisplay, TermWin.vt, 959 ActiveMenu->win = XCreateSimpleWindow (display->display, vt,
844 x, ActiveMenu->y, 960 x, ActiveMenu->y,
845 ActiveMenu->w, ActiveMenu->h, 961 ActiveMenu->w, ActiveMenu->h,
846 0, 962 0,
847 PixColors[Color_fg], 963 pix_colors[Color_fg],
848 PixColors[Color_scroll]); 964 pix_colors[Color_scroll]);
965 ActiveMenu->drawable = new rxvt_drawable (display, ActiveMenu->win);
849 XMapWindow(Xdisplay, ActiveMenu->win); 966 XMapWindow (display->display, ActiveMenu->win);
850 } 967 }
968
851 rxvt_Draw_Shadow(Xdisplay, ActiveMenu->win, 969 rxvt_Draw_Shadow (display->display, ActiveMenu->win,
852 topShadowGC, botShadowGC, 970 topShadowGC, botShadowGC,
853 0, 0, ActiveMenu->w, ActiveMenu->h); 971 0, 0, ActiveMenu->w, ActiveMenu->h);
854 972
855/* determine the correct right-alignment */ 973 /* determine the correct right-alignment */
856 for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next) 974 for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next)
857 if (item->len2 > xright) 975 if (item->len2 > xright)
858 xright = item->len2; 976 xright = item->len2;
859 977
860 for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { 978 for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next)
979 {
861 const int xoff = (SHADOW + Width2Pixel(HSPACE) / 2); 980 const int xoff = (MENU_SHADOW + Width2Pixel (HSPACE) / 2);
862 register int h; 981 register int h;
863 GC gc = menubarGC; 982 GC gc = menubarGC;
864 983
865 if (isSeparator(item->name)) { 984 if (isSeparator (item->name))
985 {
866 rxvt_Draw_Shadow(Xdisplay, ActiveMenu->win, 986 rxvt_Draw_Shadow (display->display, ActiveMenu->win,
867 topShadowGC, botShadowGC, 987 topShadowGC, botShadowGC,
868 SHADOW, y + SHADOW + 1, 988 MENU_SHADOW, y + MENU_SHADOW + 1,
869 ActiveMenu->w - 2 * SHADOW, 0); 989 ActiveMenu->w - 2 * MENU_SHADOW, 0);
870 h = HEIGHT_SEPARATOR; 990 h = HEIGHT_SEPARATOR;
871 } else { 991 }
992 else
993 {
872 char *name = item->name; 994 char *name = item->name;
873 int len = item->len; 995 int len = item->len;
874 996
875 if (item->entry.type == MenuLabel) { 997 if (item->entry.type == MenuLabel)
876 gc = botShadowGC; 998 gc = botShadowGC;
877 } else if (item->entry.type == MenuSubMenu) { 999 else if (item->entry.type == MenuSubMenu)
878 int x1, y1; 1000 {
879 menuitem_t *it; 1001 int x1, y1;
1002 menuitem_t *it;
880 menu_t *menu = item->entry.submenu.menu; 1003 menu_t *menu = item->entry.submenu.menu;
881 1004
882 drawtriangle (ActiveMenu->w, y, +1); 1005 drawtriangle (ActiveMenu->w, y, +1);
883 1006
884 name = menu->name; 1007 name = menu->name;
885 len = menu->len; 1008 len = menu->len;
886 1009
887 y1 = ActiveMenu->y + y; 1010 y1 = ActiveMenu->y + y;
888 1011
889 menu->w = Menu_PixelWidth(menu); 1012 menu->w = Menu_PixelWidth (menu);
890 1013
891 /* place sub-menu at midpoint of parent menu */ 1014 /* place sub-menu at midpoint of parent menu */
892 x1 = ActiveMenu->w / 2; 1015 x1 = ActiveMenu->w / 2;
893 if (x1 > menu->w) /* right-flush menu if too small */ 1016 if (x1 > menu->w) /* right-flush menu if too small */
894 x1 += (x1 - menu->w); 1017 x1 += (x1 - menu->w);
895 x1 += x; 1018 x1 += x;
896 1019
897 /* find the height of this submenu */ 1020 /* find the height of this submenu */
898 for (h = 0, it = menu->head; it != NULL; it = it->next) 1021 for (h = 0, it = menu->head; it != NULL; it = it->next)
899 h += isSeparator(it->name) ? HEIGHT_SEPARATOR 1022 h += isSeparator (it->name) ? HEIGHT_SEPARATOR
900 : HEIGHT_TEXT + 2 * SHADOW; 1023 : HEIGHT_TEXT + 2 * MENU_SHADOW;
901 menu->h = h + 2 * SHADOW; 1024 menu->h = h + 2 * MENU_SHADOW;
902 1025
903 /* ensure menu is in window limits */ 1026 /* ensure menu is in window limits */
904 if ((x1 + menu->w) >= TermWin.width) 1027 if ((x1 + menu->w) >= width)
905 x1 = (TermWin_TotalWidth() - menu->w); 1028 x1 = (TermWin_TotalWidth () - menu->w);
906 1029
907 if ((y1 + menu->h) >= TermWin.height) 1030 if ((y1 + menu->h) >= height)
908 y1 = (TermWin_TotalHeight() - menu->h); 1031 y1 = (TermWin_TotalHeight () - menu->h);
909 1032
910 menu->x = (x1 < 0 ? 0 : x1); 1033 menu->x = (x1 < 0 ? 0 : x1);
911 menu->y = (y1 < 0 ? 0 : y1); 1034 menu->y = (y1 < 0 ? 0 : y1);
1035 }
912 } else if (item->name2 && !STRCMP(name, item->name2)) 1036 else if (item->name2 && !strcmp (name, item->name2))
913 name = NULL; 1037 name = NULL;
914 1038
915 if (len && name) { 1039 if (len && name)
916#ifdef USE_XIM 1040 draw_string (*ActiveMenu->drawable, gc, fontset[0],
917 if (TermWin.fontset) 1041 xoff, 2 * MENU_SHADOW + y, name, len);
918 XmbDrawString(Xdisplay,
919 ActiveMenu->win, TermWin.fontset,
920 gc, xoff,
921 2 * SHADOW + y + TermWin.font->ascent + 1,
922 name, len);
923 else
924#endif
925 XDrawString(Xdisplay, ActiveMenu->win, gc, xoff,
926 2 * SHADOW + y + TermWin.font->ascent + 1,
927 name, len);
928 }
929 1042
930 len = item->len2; 1043 len = item->len2;
931 name = item->name2; 1044 name = item->name2;
1045
932 if (len && name) { 1046 if (len && name)
933#ifdef USE_XIM 1047 draw_string (*ActiveMenu->drawable, gc, fontset[0],
934 if (TermWin.fontset) 1048 ActiveMenu->w - (xoff + Width2Pixel (xright)), 2 * MENU_SHADOW + y, name, len);
935 XmbDrawString(Xdisplay, 1049
936 ActiveMenu->win, TermWin.fontset,
937 gc,
938 ActiveMenu->w - (xoff + Width2Pixel(xright)),
939 2 * SHADOW + y + TermWin.font->ascent + 1,
940 name, len);
941 else
942#endif
943 XDrawString(Xdisplay, ActiveMenu->win, gc,
944 ActiveMenu->w - (xoff + Width2Pixel(xright)),
945 2 * SHADOW + y + TermWin.font->ascent + 1,
946 name, len);
947 }
948 h = HEIGHT_TEXT + 2 * SHADOW; 1050 h = HEIGHT_TEXT + 2 * MENU_SHADOW;
949 } 1051 }
950 y += h; 1052 y += h;
951 } 1053 }
952} 1054}
953 1055
954void 1056void
955rxvt_term::menu_display (void (*update)(rxvt_t *)) 1057rxvt_term::menu_display (void (rxvt_term::*update) ())
956{ 1058{
957 menu_t *ActiveMenu = ActiveMenu;
958
959 if (ActiveMenu == NULL) 1059 if (ActiveMenu == NULL)
960 return; 1060 return;
1061
1062 delete ActiveMenu->drawable;
961 if (ActiveMenu->win != None) 1063 if (ActiveMenu->win != None)
962 XDestroyWindow(Xdisplay, ActiveMenu->win); 1064 XDestroyWindow (display->display, ActiveMenu->win);
963 ActiveMenu->win = None; 1065 ActiveMenu->win = None;
964 ActiveMenu->item = NULL; 1066 ActiveMenu->item = NULL;
965 1067
966 if (ActiveMenu->parent == NULL) 1068 if (ActiveMenu->parent == NULL)
967 drawbox_menubar (ActiveMenu->x, ActiveMenu->len, +1); 1069 drawbox_menubar (ActiveMenu->x, ActiveMenu->len, +1);
1070
968 ActiveMenu = ActiveMenu->parent; 1071 ActiveMenu = ActiveMenu->parent;
969 update(r); 1072 (this->*update) ();
970} 1073}
971 1074
972void 1075void
973rxvt_term::menu_hide_all () 1076rxvt_term::menu_hide_all ()
974{ 1077{
975 menu_display (rxvt_menu_hide_all); 1078 menu_display (&rxvt_term::menu_hide_all);
976} 1079}
977 1080
978void 1081void
979rxvt_term::menu_hide () 1082rxvt_term::menu_hide ()
980{ 1083{
981 menu_display (rxvt_menu_show); 1084 menu_display (&rxvt_term::menu_show);
982} 1085}
983 1086
984void 1087void
985rxvt_term::menu_clear (menu_t *menu) 1088rxvt_term::menu_clear (menu_t *menu)
986{ 1089{
987 if (menu != NULL) { 1090 if (menu != NULL)
1091 {
988 menuitem_t *item = menu->tail; 1092 menuitem_t *item = menu->tail;
989 1093
990 while (item != NULL) { 1094 while (item != NULL)
1095 {
991 menuitem_free (menu, item); 1096 menuitem_free (menu, item);
992 /* it didn't get freed ... why? */ 1097 /* it didn't get freed ... why? */
993 if (item == menu->tail) 1098 if (item == menu->tail)
994 return; 1099 return;
995 item = menu->tail; 1100 item = menu->tail;
996 } 1101 }
997 menu->width = 0; 1102 menu->width = 0;
998 } 1103 }
999} 1104}
1000 1105
1001void 1106void
1002rxvt_term::menubar_clear () 1107rxvt_term::menubar_clear ()
1003{ 1108{
1004 bar_t *CurrentBar = CurrentBar;
1005
1006 if (CurrentBar != NULL) { 1109 if (CurrentBar != NULL)
1110 {
1007 menu_t *menu = CurrentBar->tail; 1111 menu_t *menu = CurrentBar->tail;
1008 1112
1009 while (menu != NULL) { 1113 while (menu != NULL)
1114 {
1010 menu_t *prev = menu->prev; 1115 menu_t *prev = menu->prev;
1011 1116
1012 menu_delete (menu); 1117 menu_delete (menu);
1013 menu = prev; 1118 menu = prev;
1014 } 1119 }
1015 CurrentBar->head = CurrentBar->tail = NULL; 1120 CurrentBar->head = CurrentBar->tail = NULL;
1016 1121
1017 if (CurrentBar->title) { 1122 if (CurrentBar->title)
1123 {
1018 free(CurrentBar->title); 1124 free (CurrentBar->title);
1019 CurrentBar->title = NULL; 1125 CurrentBar->title = NULL;
1020 } 1126 }
1127
1021 menuarrow_free (0); /* remove all arrow functions */ 1128 menuarrow_free (0); /* remove all arrow functions */
1022 } 1129 }
1130
1023 ActiveMenu = NULL; 1131 ActiveMenu = NULL;
1024} 1132}
1025 1133
1026#if (MENUBAR_MAX > 1) 1134#if (MENUBAR_MAX > 1)
1027/* find if menu already exists */ 1135/* find if menu already exists */
1028bar_t * 1136bar_t *
1029rxvt_term::menubar_find (const char *name) 1137rxvt_term::menubar_find (const char *name)
1030{ 1138{
1031 bar_t *bar = CurrentBar; 1139 bar_t *bar = CurrentBar;
1032 1140
1033#ifdef DEBUG_MENUBAR_STACKING 1141#ifdef DEBUG_MENUBAR_STACKING
1034 fprintf(stderr, "looking for [menu:%s] ...", name ? name : "(nil)"); 1142 fprintf (stderr, "looking for [menu:%s] ...", name ? name : " (nil)");
1035#endif 1143#endif
1036 if (bar == NULL || name == NULL) 1144 if (bar == NULL || name == NULL)
1037 return NULL; 1145 return NULL;
1038 1146
1039 if (STRLEN(name) && STRCMP(name, "*")) { 1147 if (strlen (name) && strcmp (name, "*"))
1040 do { 1148 {
1041 if (!STRCMP(bar->name, name)) { 1149 do
1150 {
1151 if (!strcmp (bar->name, name))
1152 {
1042#ifdef DEBUG_MENUBAR_STACKING 1153#ifdef DEBUG_MENUBAR_STACKING
1043 fprintf(stderr, " found!\n"); 1154 fprintf (stderr, " found!\n");
1044#endif 1155#endif
1045 return bar; 1156 return bar;
1046 } 1157 }
1047 bar = bar->next; 1158 bar = bar->next;
1048 } 1159 }
1049 while (bar != CurrentBar); 1160 while (bar != CurrentBar);
1050 bar = NULL; 1161 bar = NULL;
1051 } 1162 }
1052#ifdef DEBUG_MENUBAR_STACKING 1163#ifdef DEBUG_MENUBAR_STACKING
1053 fprintf(stderr, "%s found!\n", (bar ? "" : " NOT")); 1164 fprintf (stderr, "%s found!\n", (bar ? "" : " NOT"));
1054#endif 1165#endif
1055 1166
1056 return bar; 1167 return bar;
1057} 1168}
1058 1169
1059int 1170int
1060rxvt_term::menubar_push (const char *name) 1171rxvt_term::menubar_push (const char *name)
1061{ 1172{
1062 int ret = 1; 1173 int ret = 1;
1063 bar_t *bar; 1174 bar_t *bar;
1064 1175
1065 if (CurrentBar == NULL) { 1176 if (CurrentBar == NULL)
1177 {
1066 /* allocate first one */ 1178 /* allocate first one */
1067 bar = (bar_t *) rxvt_malloc(sizeof(bar_t)); 1179 bar = (bar_t *) rxvt_malloc (sizeof (bar_t));
1068 1180
1069 MEMSET(bar, 0, sizeof(bar_t)); 1181 memset (bar, 0, sizeof (bar_t));
1070 /* circular linked-list */ 1182 /* circular linked-list */
1071 bar->next = bar->prev = bar; 1183 bar->next = bar->prev = bar;
1072 bar->head = bar->tail = NULL; 1184 bar->head = bar->tail = NULL;
1073 bar->title = NULL; 1185 bar->title = NULL;
1074 CurrentBar = bar;
1075 Nbars++;
1076
1077 menubar_clear ();
1078 } else {
1079 /* find if menu already exists */
1080 bar = menubar_find (name);
1081 if (bar != NULL) {
1082 /* found it, use it */
1083 CurrentBar = bar; 1186 CurrentBar = bar;
1084 } else { 1187 Nbars++;
1188
1189 menubar_clear ();
1190 }
1191 else
1192 {
1193 /* find if menu already exists */
1194 bar = menubar_find (name);
1195 if (bar != NULL)
1196 {
1197 /* found it, use it */
1198 CurrentBar = bar;
1199 }
1200 else
1201 {
1085 /* create if needed, or reuse the existing empty menubar */ 1202 /* create if needed, or reuse the existing empty menubar */
1086 if (CurrentBar->head != NULL) { 1203 if (CurrentBar->head != NULL)
1204 {
1087 /* need to malloc another one */ 1205 /* need to malloc another one */
1088 if (Nbars < MENUBAR_MAX) 1206 if (Nbars < MENUBAR_MAX)
1089 bar = (bar_t *) rxvt_malloc(sizeof(bar_t)); 1207 bar = (bar_t *) rxvt_malloc (sizeof (bar_t));
1090 else 1208 else
1091 bar = NULL; 1209 bar = NULL;
1092 1210
1093 /* malloc failed or too many menubars, reuse another */ 1211 /* malloc failed or too many menubars, reuse another */
1094 if (bar == NULL) { 1212 if (bar == NULL)
1213 {
1095 bar = CurrentBar->next; 1214 bar = CurrentBar->next;
1096 ret = -1; 1215 ret = -1;
1097 } else { 1216 }
1217 else
1218 {
1098 bar->head = bar->tail = NULL; 1219 bar->head = bar->tail = NULL;
1099 bar->title = NULL; 1220 bar->title = NULL;
1100 1221
1101 bar->next = CurrentBar->next; 1222 bar->next = CurrentBar->next;
1102 CurrentBar->next = bar; 1223 CurrentBar->next = bar;
1103 bar->prev = CurrentBar; 1224 bar->prev = CurrentBar;
1104 bar->next->prev = bar; 1225 bar->next->prev = bar;
1105 1226
1106 Nbars++; 1227 Nbars++;
1107 } 1228 }
1108 CurrentBar = bar; 1229 CurrentBar = bar;
1109 1230
1231 }
1232
1233 menubar_clear ();
1234 }
1110 } 1235 }
1111 menubar_clear ();
1112 }
1113 }
1114 1236
1115/* give menubar this name */ 1237 /* give menubar this name */
1116 STRNCPY(CurrentBar->name, name, MAXNAME); 1238 strncpy (CurrentBar->name, name, MAXNAME);
1117 CurrentBar->name[MAXNAME - 1] = '\0'; 1239 CurrentBar->name[MAXNAME - 1] = '\0';
1118 1240
1119 return ret; 1241 return ret;
1120} 1242}
1121 1243
1122/* switch to a menu called NAME and remove it */ 1244/* switch to a menu called NAME and remove it */
1123void 1245void
1124rxvt_term::menubar_remove (const char *name) 1246rxvt_term::menubar_remove (const char *name)
1125{ 1247{
1126 bar_t *bar; 1248 bar_t *bar;
1127 1249
1128 if ((bar = menubar_find (name)) == NULL) 1250 if ((bar = menubar_find (name)) == NULL)
1129 return; 1251 return;
1130 CurrentBar = bar; 1252 CurrentBar = bar;
1131 1253
1254 do
1132 do { 1255 {
1133 menubar_clear (); 1256 menubar_clear ();
1134 /* 1257 /*
1135 * pop a menubar, clean it up first 1258 * pop a menubar, clean it up first
1136 */ 1259 */
1137 if (CurrentBar != NULL) { 1260 if (CurrentBar != NULL)
1261 {
1138 bar_t *prev = CurrentBar->prev; 1262 bar_t *prev = CurrentBar->prev;
1139 bar_t *next = CurrentBar->next; 1263 bar_t *next = CurrentBar->next;
1140 1264
1141 if (prev == next && prev == CurrentBar) { /* only 1 left */ 1265 if (prev == next && prev == CurrentBar)
1142 prev = NULL; 1266 { /* only 1 left */
1143 Nbars = 0; /* safety */ 1267 prev = NULL;
1144 } else { 1268 Nbars = 0; /* safety */
1145 next->prev = prev; 1269 }
1146 prev->next = next; 1270 else
1147 Nbars--; 1271 {
1272 next->prev = prev;
1273 prev->next = next;
1274 Nbars--;
1275 }
1276
1277 free (CurrentBar);
1278 CurrentBar = prev;
1279 }
1148 } 1280 }
1149
1150 free(CurrentBar);
1151 CurrentBar = prev;
1152 }
1153 }
1154 while (CurrentBar && !STRCMP(name, "*")); 1281 while (CurrentBar && !strcmp (name, "*"));
1155} 1282}
1156 1283
1157void 1284void
1158rxvt_action_decode(FILE *fp, action_t *act) 1285rxvt_action_decode (FILE *fp, action_t *act)
1159{ 1286{
1160 unsigned char *str; 1287 unsigned char *str;
1161 short len; 1288 short len;
1162 1289
1163 if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL) 1290 if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL)
1164 return; 1291 return;
1165 1292
1166 if (act->type == MenuTerminalAction) { 1293 if (act->type == MenuTerminalAction)
1294 {
1167 fprintf(fp, "^@"); 1295 fprintf (fp, "^@");
1168 /* can strip trailing ^G from XTerm sequence */ 1296 /* can strip trailing ^G from XTerm sequence */
1169 if (str[0] == C0_ESC && str[1] == ']' && str[len - 1] == C0_BEL) 1297 if (str[0] == C0_ESC && str[1] == ']' && str[len - 1] == C0_BEL)
1170 len--; 1298 len--;
1299 }
1171 } else if (str[0] == C0_ESC) { 1300 else if (str[0] == C0_ESC)
1301 {
1172 switch (str[1]) { 1302 switch (str[1])
1173 case '[': 1303 {
1174 case ']': 1304 case '[':
1175 break; 1305 case ']':
1306 break;
1176 1307
1177 case 'x': 1308 case 'x':
1178 /* can strip trailing '\r' from M-x sequence */ 1309 /* can strip trailing '\r' from M-x sequence */
1179 if (str[len - 1] == '\r') 1310 if (str[len - 1] == '\r')
1180 len--; 1311 len--;
1181 /* FALLTHROUGH */ 1312 /* FALLTHROUGH */
1182 1313
1183 default: 1314 default:
1184 fprintf(fp, "M-"); /* meta prefix */ 1315 fprintf (fp, "M-"); /* meta prefix */
1185 str++; 1316 str++;
1186 len--; 1317 len--;
1187 break; 1318 break;
1188 } 1319 }
1189 } 1320 }
1190/* 1321
1322 /*
1191 * control character form is preferred, since backslash-escaping 1323 * control character form is preferred, since backslash-escaping
1192 * can be really ugly looking when the backslashes themselves also 1324 * can be really ugly looking when the backslashes themselves also
1193 * have to be escaped to avoid Shell (or whatever scripting 1325 * have to be escaped to avoid Shell (or whatever scripting
1194 * language) interpretation 1326 * language) interpretation
1195 */ 1327 */
1196 while (len > 0) { 1328 while (len > 0)
1329 {
1197 unsigned char ch = *str++; 1330 unsigned char ch = *str++;
1198 1331
1199 switch (ch) { 1332 switch (ch)
1200 case C0_ESC: 1333 {
1334 case C0_ESC:
1201 fprintf(fp, "\\E"); 1335 fprintf (fp, "\\E");
1202 break; /* escape */ 1336 break; /* escape */
1203 case '\r': 1337 case '\r':
1204 fprintf(fp, "\\r"); 1338 fprintf (fp, "\\r");
1205 break; /* carriage-return */ 1339 break; /* carriage-return */
1206 case '\\': 1340 case '\\':
1207 fprintf(fp, "\\\\"); 1341 fprintf (fp, "\\\\");
1208 break; /* backslash */ 1342 break; /* backslash */
1209 case '^': 1343 case '^':
1210 fprintf(fp, "\\^"); 1344 fprintf (fp, "\\^");
1211 break; /* caret */ 1345 break; /* caret */
1212 case 127: 1346 case 127:
1213 fprintf(fp, "^?"); 1347 fprintf (fp, "^?");
1214 default: 1348 default:
1215 if (ch <= 31) 1349 if (ch <= 31)
1216 fprintf(fp, "^%c", ('@' + ch)); 1350 fprintf (fp, "^%c", ('@' + ch));
1217 else if (ch > 127) 1351 else if (ch > 127)
1218 fprintf(fp, "\\%o", ch); 1352 fprintf (fp, "\\%o", ch);
1219 else 1353 else
1220 fprintf(fp, "%c", ch); 1354 fprintf (fp, "%c", ch);
1221 break; 1355 break;
1222 } 1356 }
1223 len--; 1357
1358 len--;
1224 } 1359 }
1360
1225 fprintf(fp, "\n"); 1361 fprintf (fp, "\n");
1226} 1362}
1227 1363
1228void 1364void
1229rxvt_menu_dump(FILE *fp, menu_t *menu) 1365rxvt_menu_dump (FILE *fp, menu_t *menu)
1230{ 1366{
1231 menuitem_t *item; 1367 menuitem_t *item;
1232 1368
1233/* create a new menu and clear it */ 1369 /* create a new menu and clear it */
1234 fprintf(fp, (menu->parent ? "./%s/*\n" : "/%s/*\n"), menu->name); 1370 fprintf (fp, (menu->parent ? "./%s/*\n" : "/%s/*\n"), menu->name);
1235 1371
1236 for (item = menu->head; item != NULL; item = item->next) { 1372 for (item = menu->head; item != NULL; item = item->next)
1373 {
1237 switch (item->entry.type) { 1374 switch (item->entry.type)
1375 {
1238 case MenuSubMenu: 1376 case MenuSubMenu:
1239 if (item->entry.submenu.menu == NULL) 1377 if (item->entry.submenu.menu == NULL)
1240 fprintf(fp, "> %s == NULL\n", item->name); 1378 fprintf (fp, "> %s == NULL\n", item->name);
1241 else 1379 else
1242 rxvt_menu_dump(fp, item->entry.submenu.menu); 1380 rxvt_menu_dump (fp, item->entry.submenu.menu);
1243 break; 1381 break;
1244 1382
1245 case MenuLabel: 1383 case MenuLabel:
1246 fprintf(fp, "{%s}\n", (STRLEN(item->name) ? item->name : "-")); 1384 fprintf (fp, "{%s}\n", (strlen (item->name) ? item->name : "-"));
1247 break; 1385 break;
1248 1386
1249 case MenuTerminalAction: 1387 case MenuTerminalAction:
1250 case MenuAction: 1388 case MenuAction:
1251 fprintf(fp, "{%s}", item->name); 1389 fprintf (fp, "{%s}", item->name);
1252 if (item->name2 != NULL && STRLEN(item->name2)) 1390 if (item->name2 != NULL && strlen (item->name2))
1253 fprintf(fp, "{%s}", item->name2); 1391 fprintf (fp, "{%s}", item->name2);
1254 fprintf(fp, "\t"); 1392 fprintf (fp, "\t");
1255 rxvt_action_decode(fp, &(item->entry.action)); 1393 rxvt_action_decode (fp, & (item->entry.action));
1256 break; 1394 break;
1257 } 1395 }
1258 } 1396 }
1259 1397
1260 fprintf(fp, (menu->parent ? "../\n" : "/\n\n")); 1398 fprintf (fp, (menu->parent ? "../\n" : "/\n\n"));
1261} 1399}
1262 1400
1263void 1401void
1264rxvt_term::menubar_dump (FILE *fp) 1402rxvt_term::menubar_dump (FILE *fp)
1265{ 1403{
1266 bar_t *bar = CurrentBar; 1404 bar_t *bar = CurrentBar;
1267 time_t t; 1405 time_t t;
1268 1406
1269 if (bar == NULL || fp == NULL) 1407 if (bar == NULL || fp == NULL)
1270 return; 1408 return;
1271 time(&t); 1409 time (&t);
1272 1410
1273 fprintf(fp, 1411 fprintf (fp,
1274 "# " APL_SUBCLASS " (%s) Pid: %u\n# Date: %s\n\n", 1412 "# " RESCLASS " (%s) Pid: %u\n# Date: %s\n\n",
1275 rs[Rs_name], (unsigned int)getpid(), ctime(&t)); 1413 rs[Rs_name], (unsigned int)getpid (), ctime (&t));
1276 1414
1277/* dump in reverse order */ 1415 /* dump in reverse order */
1278 bar = CurrentBar->prev; 1416 bar = CurrentBar->prev;
1417 do
1279 do { 1418 {
1280 menu_t *menu; 1419 menu_t *menu;
1281 int i; 1420 int i;
1282 1421
1283 fprintf(fp, "[menu:%s]\n", bar->name); 1422 fprintf (fp, "[menu:%s]\n", bar->name);
1284 1423
1285 if (bar->title != NULL) 1424 if (bar->title != NULL)
1286 fprintf(fp, "[title:%s]\n", bar->title); 1425 fprintf (fp, "[title:%s]\n", bar->title);
1287 1426
1288 for (i = 0; i < NARROWS; i++) { 1427 for (i = 0; i < NARROWS; i++)
1428 {
1289 switch (bar->arrows[i].type) { 1429 switch (bar->arrows[i].type)
1430 {
1290 case MenuTerminalAction: 1431 case MenuTerminalAction:
1291 case MenuAction: 1432 case MenuAction:
1292 fprintf(fp, "<%c>", Arrows[i].name); 1433 fprintf (fp, "<%c>", Arrows[i].name);
1293 rxvt_action_decode(fp, &(bar->arrows[i])); 1434 rxvt_action_decode (fp, & (bar->arrows[i]));
1294 break; 1435 break;
1295 } 1436 }
1296 } 1437 }
1297 fprintf(fp, "\n"); 1438 fprintf (fp, "\n");
1298 1439
1299 for (menu = bar->head; menu != NULL; menu = menu->next) 1440 for (menu = bar->head; menu != NULL; menu = menu->next)
1300 rxvt_menu_dump(fp, menu); 1441 rxvt_menu_dump (fp, menu);
1301 1442
1302 fprintf(fp, "\n[done:%s]\n\n", bar->name); 1443 fprintf (fp, "\n[done:%s]\n\n", bar->name);
1303 bar = bar->prev; 1444 bar = bar->prev;
1304 } 1445 }
1305 while (bar != CurrentBar->prev); 1446 while (bar != CurrentBar->prev);
1306} 1447}
1307#endif /* (MENUBAR_MAX > 1) */ 1448#endif /* (MENUBAR_MAX > 1) */
1308 1449
1309/* 1450/*
1310 * read in menubar commands from FILENAME 1451 * read in menubar commands from FILENAME
1322 * read `file' starting with [menu:tag] 1463 * read `file' starting with [menu:tag]
1323 */ 1464 */
1324void 1465void
1325rxvt_term::menubar_read (const char *filename) 1466rxvt_term::menubar_read (const char *filename)
1326{ 1467{
1327/* read in a menu from a file */ 1468 /* read in a menu from a file */
1328 FILE *fp; 1469 FILE *fp;
1329 char buffer[256]; 1470 char buffer[256];
1330 char *p, *file, *tag = NULL; 1471 char *p, *file, *tag = NULL;
1331 1472
1332 file = (char *)rxvt_File_find(filename, ".menu", rs[Rs_path]); 1473 file = (char *)rxvt_File_find (filename, ".menu", rs[Rs_path]);
1333 if (file == NULL) 1474 if (file == NULL)
1334 return; 1475 return;
1476
1335 fp = fopen(file, "rb"); 1477 fp = fopen (file, "rb");
1336 free(file); 1478 free (file);
1337 if (fp == NULL) 1479 if (fp == NULL)
1338 return; 1480 return;
1339 1481
1340#if (MENUBAR_MAX > 1) 1482#if (MENUBAR_MAX > 1)
1341/* semi-colon delimited */ 1483 /* semi-colon delimited */
1342 if ((tag = STRCHR(filename, ';')) != NULL) { 1484 if ((tag = strchr (filename, ';')) != NULL)
1343 tag++; 1485 {
1486 tag++;
1344 if (*tag == '\0') 1487 if (*tag == '\0')
1345 tag = NULL; 1488 tag = NULL;
1346 } 1489 }
1347#endif /* (MENUBAR_MAX > 1) */ 1490#endif /* (MENUBAR_MAX > 1) */
1348#ifdef DEBUG_MENU 1491#ifdef DEBUG_MENU
1349 fprintf(stderr, "[read:%s]\n", p); 1492 fprintf (stderr, "[read:%s]\n", p);
1350 if (tag) 1493 if (tag)
1351 fprintf(stderr, "looking for [menu:%s]\n", tag); 1494 fprintf (stderr, "looking for [menu:%s]\n", tag);
1352#endif 1495#endif
1353 1496
1354 while ((p = fgets(buffer, sizeof(buffer), fp)) != NULL) { 1497 while ((p = fgets (buffer, sizeof (buffer), fp)) != NULL)
1498 {
1355 int n; 1499 int n;
1356 1500
1357 if ((n = rxvt_Str_match(p, "[menu")) != 0) { 1501 if ((n = rxvt_Str_match (p, "[menu")) != 0)
1358 if (tag) { 1502 {
1503 if (tag)
1504 {
1359 /* looking for [menu:tag] */ 1505 /* looking for [menu:tag] */
1360 if (p[n] == ':' && p[n + 1] != ']') { 1506 if (p[n] == ':' && p[n + 1] != ']')
1361 n++; 1507 {
1508 n++;
1362 n += rxvt_Str_match(p + n, tag); 1509 n += rxvt_Str_match (p + n, tag);
1363 if (p[n] == ']') { 1510 if (p[n] == ']')
1511 {
1364#ifdef DEBUG_MENU 1512#ifdef DEBUG_MENU
1365 fprintf(stderr, "[menu:%s]\n", tag); 1513 fprintf (stderr, "[menu:%s]\n", tag);
1366#endif 1514#endif
1367 break; 1515 break;
1516 }
1517 }
1518 }
1519 else if (p[n] == ':' || p[n] == ']')
1520 break;
1521 }
1368 } 1522 }
1369 }
1370 } else if (p[n] == ':' || p[n] == ']')
1371 break;
1372 }
1373 }
1374 1523
1375/* found [menu], [menu:???] tag */ 1524 /* found [menu], [menu:???] tag */
1376 while (p != NULL) { 1525 while (p != NULL)
1526 {
1377 int n; 1527 int n;
1378 1528
1379#ifdef DEBUG_MENU 1529#ifdef DEBUG_MENU
1380 fprintf(stderr, "read line = %s\n", p); 1530 fprintf (stderr, "read line = %s\n", p);
1381#endif 1531#endif
1382 1532
1383 /* looking for [done:tag] or [done:] */ 1533 /* looking for [done:tag] or [done:] */
1384 if ((n = rxvt_Str_match(p, "[done")) != 0) { 1534 if ((n = rxvt_Str_match (p, "[done")) != 0)
1535 {
1385 if (p[n] == ']') { 1536 if (p[n] == ']')
1386 menu_readonly = 1; 1537 {
1387 break;
1388 } else if (p[n] == ':') {
1389 n++;
1390 if (p[n] == ']') {
1391 menu_readonly = 1; 1538 menu_readonly = 1;
1392 break; 1539 break;
1393 } else if (tag) { 1540 }
1541 else if (p[n] == ':')
1542 {
1543 n++;
1544 if (p[n] == ']')
1545 {
1546 menu_readonly = 1;
1547 break;
1548 }
1549 else if (tag)
1550 {
1394 n += rxvt_Str_match(p + n, tag); 1551 n += rxvt_Str_match (p + n, tag);
1395 if (p[n] == ']') { 1552 if (p[n] == ']')
1553 {
1396#ifdef DEBUG_MENU 1554#ifdef DEBUG_MENU
1397 fprintf(stderr, "[done:%s]\n", tag); 1555 fprintf (stderr, "[done:%s]\n", tag);
1398#endif 1556#endif
1399 menu_readonly = 1; 1557 menu_readonly = 1;
1400 break; 1558 break;
1401 } 1559 }
1402 } else { 1560 }
1561 else
1562 {
1403 /* what? ... skip this line */ 1563 /* what? ... skip this line */
1404 p[0] = COMMENT_CHAR; 1564 p[0] = COMMENT_CHAR;
1405 } 1565 }
1406 } 1566 }
1407 } 1567 }
1408 /* 1568
1569 /*
1409 * remove leading/trailing space 1570 * remove leading/trailing space
1410 * and strip-off leading/trailing quotes
1411 * skip blank or comment lines 1571 * skip blank or comment lines
1412 */ 1572 */
1413 rxvt_Str_trim(p); 1573 rxvt_Str_trim (p);
1414 if (*p && *p != '#') { 1574 if (*p && *p != '#')
1575 {
1415 menu_readonly = 0; /* if case we read another file */ 1576 menu_readonly = 0; /* if case we read another file */
1416 menubar_dispatch (p); 1577 menubar_dispatch (p);
1417 } 1578 }
1418 /* get another line */ 1579 /* get another line */
1419 p = fgets(buffer, sizeof(buffer), fp); 1580 p = fgets (buffer, sizeof (buffer), fp);
1420 } 1581 }
1421 1582
1422 fclose(fp); 1583 fclose (fp);
1423} 1584}
1424 1585
1425/* 1586/*
1426 * user interface for building/deleting and otherwise managing menus 1587 * user interface for building/deleting and otherwise managing menus
1427 */ 1588 */
1428void 1589void
1429rxvt_term::menubar_dispatch (char *str) 1590rxvt_term::menubar_dispatch (char *str)
1430{ 1591{
1431 int n, cmd; 1592 int n, cmd;
1432 char *path, *name, *name2; 1593 char *path, *name, *name2;
1433 1594
1434 if (menubar_visible(r) && ActiveMenu != NULL) 1595 if (menubar_visible () && ActiveMenu != NULL)
1435 menubar_expose (); 1596 menubar_expose ();
1436 else 1597 else
1437 ActiveMenu = NULL; 1598 ActiveMenu = NULL;
1438 1599
1439 cmd = *str; 1600 cmd = *str;
1440 switch (cmd) { 1601 switch (cmd)
1602 {
1441 case '.': 1603 case '.':
1442 case '/': /* absolute & relative path */ 1604 case '/': /* absolute & relative path */
1443 case MENUITEM_BEG: /* menuitem */ 1605 case MENUITEM_BEG: /* menuitem */
1444 /* add `+' prefix for these cases */ 1606 /* add `+' prefix for these cases */
1445 cmd = '+'; 1607 cmd = '+';
1446 break; 1608 break;
1447 1609
1448 case '+': 1610 case '+':
1449 case '-': 1611 case '-':
1450 str++; /* skip cmd character */ 1612 str++; /* skip cmd character */
1451 break; 1613 break;
1452 1614
1453 case '<': 1615 case '<':
1454#if (MENUBAR_MAX > 1) 1616#if (MENUBAR_MAX > 1)
1455 if (CurrentBar == NULL) 1617 if (CurrentBar == NULL)
1456 break; 1618 break;
1457#endif /* (MENUBAR_MAX > 1) */ 1619#endif /* (MENUBAR_MAX > 1) */
1458 if (str[1] && str[2] == '>') /* arrow commands */ 1620 if (str[1] && str[2] == '>') /* arrow commands */
1459 menuarrow_add (str); 1621 menuarrow_add (str);
1460 break; 1622 break;
1461 1623
1462 case '[': /* extended command */ 1624 case '[': /* extended command */
1463 while (str[0] == '[') { 1625 while (str[0] == '[')
1626 {
1464 char *next = (++str); /* skip leading '[' */ 1627 char *next = (++str); /* skip leading '[' */
1465 1628
1466 if (str[0] == ':') { /* [:command:] */
1467 do {
1468 next++;
1469 if ((next = STRCHR(next, ':')) == NULL)
1470 return; /* parse error */
1471 }
1472 while (next[1] != ']');
1473 /* remove and skip ':]' */
1474 *next = '\0';
1475 next += 2;
1476 } else {
1477 if ((next = STRCHR(next, ']')) == NULL)
1478 return; /* parse error */
1479 /* remove and skip ']' */
1480 *next = '\0';
1481 next++;
1482 }
1483
1484 if (str[0] == ':') { 1629 if (str[0] == ':')
1485 int saved; 1630 { /* [:command:] */
1631 do
1632 {
1633 next++;
1634 if ((next = strchr (next, ':')) == NULL)
1635 return; /* parse error */
1636 }
1637 while (next[1] != ']');
1638 /* remove and skip ':]' */
1639 *next = '\0';
1640 next += 2;
1641 }
1642 else
1643 {
1644 if ((next = strchr (next, ']')) == NULL)
1645 return; /* parse error */
1646 /* remove and skip ']' */
1647 *next = '\0';
1648 next++;
1649 }
1486 1650
1651 if (str[0] == ':')
1652 {
1653 int saved;
1654
1487 /* try and dispatch it, regardless of read/write status */ 1655 /* try and dispatch it, regardless of read/write status */
1488 saved = menu_readonly; 1656 saved = menu_readonly;
1489 menu_readonly = 0; 1657 menu_readonly = 0;
1490 menubar_dispatch (str + 1); 1658 menubar_dispatch (str + 1);
1491 menu_readonly = saved; 1659 menu_readonly = saved;
1492 } 1660 }
1493 /* these ones don't require menu stacking */ 1661 /* these ones don't require menu stacking */
1494 else if (!STRCMP(str, "clear")) { 1662 else if (!strcmp (str, "clear"))
1495 menubar_clear (); 1663 {
1664 menubar_clear ();
1665 }
1496 } else if (!STRCMP(str, "done") || rxvt_Str_match(str, "done:")) { 1666 else if (!strcmp (str, "done") || rxvt_Str_match (str, "done:"))
1497 menu_readonly = 1; 1667 {
1498 } else if (!STRCMP(str, "show")) { 1668 menu_readonly = 1;
1499 map_menuBar (1); 1669 }
1500 menu_readonly = 1; 1670 else if (!strcmp (str, "show"))
1501 } else if (!STRCMP(str, "hide")) { 1671 {
1502 map_menuBar (0); 1672 map_menuBar (1);
1503 menu_readonly = 1; 1673 menu_readonly = 1;
1674 }
1675 else if (!strcmp (str, "hide"))
1676 {
1677 map_menuBar (0);
1678 menu_readonly = 1;
1679 }
1504 } else if ((n = rxvt_Str_match(str, "read:")) != 0) { 1680 else if ((n = rxvt_Str_match (str, "read:")) != 0)
1681 {
1505 /* read in a menu from a file */ 1682 /* read in a menu from a file */
1506 str += n; 1683 str += n;
1507 menubar_read (str); 1684 menubar_read (str);
1685 }
1508 } else if ((n = rxvt_Str_match(str, "title:")) != 0) { 1686 else if ((n = rxvt_Str_match (str, "title:")) != 0)
1509 str += n; 1687 {
1688 str += n;
1510 if (CurrentBar != NULL && !menu_readonly) { 1689 if (CurrentBar != NULL && !menu_readonly)
1511 if (*str) { 1690 {
1512 name = rxvt_realloc(CurrentBar->title, 1691 if (*str)
1513 STRLEN(str) + 1); 1692 {
1514 if (name != NULL) { 1693 name = (char *)rxvt_realloc (CurrentBar->title, strlen (str) + 1);
1515 STRCPY(name, str); 1694 if (name != NULL)
1516 CurrentBar->title = name; 1695 {
1517 } 1696 strcpy (name, str);
1518 menubar_expose (); 1697 CurrentBar->title = name;
1519 } else { 1698 }
1520 free(CurrentBar->title); 1699 menubar_expose ();
1521 CurrentBar->title = NULL; 1700 }
1522 } 1701 else
1523 } 1702 {
1703 free (CurrentBar->title);
1704 CurrentBar->title = NULL;
1705 }
1706 }
1707 }
1524 } else if ((n = rxvt_Str_match(str, "pixmap:")) != 0) { 1708 else if ((n = rxvt_Str_match (str, "pixmap:")) != 0)
1525 str += n; 1709 {
1710 str += n;
1526 xterm_seq (XTerm_Pixmap, str, CHAR_ST); 1711 process_xterm_seq (XTerm_Pixmap, str, CHAR_ST);
1527 } 1712 }
1528#if (MENUBAR_MAX > 1) 1713#if (MENUBAR_MAX > 1)
1529 else if ((n = rxvt_Str_match(str, "rm")) != 0) { 1714 else if ((n = rxvt_Str_match (str, "rm")) != 0)
1530 str += n; 1715 {
1531 switch (str[0]) { 1716 str += n;
1532 case ':': 1717 switch (str[0])
1533 str++; 1718 {
1534 /* FALLTHROUGH */ 1719 case ':':
1535 case '\0': 1720 str++;
1536 /* FALLTHROUGH */ 1721 /* FALLTHROUGH */
1537 case '*': 1722 case '\0':
1538 menubar_remove (str); 1723 /* FALLTHROUGH */
1539 break; 1724 case '*':
1540 } 1725 menubar_remove (str);
1541 menu_readonly = 1; 1726 break;
1727 }
1728 menu_readonly = 1;
1729 }
1542 } else if ((n = rxvt_Str_match(str, "menu")) != 0) { 1730 else if ((n = rxvt_Str_match (str, "menu")) != 0)
1543 str += n; 1731 {
1544 switch (str[0]) { 1732 str += n;
1545 case ':': 1733 switch (str[0])
1546 str++; 1734 {
1547 /* add/access menuBar */ 1735 case ':':
1736 str++;
1737 /* add/access menuBar */
1548 if (*str != '\0' && *str != '*') 1738 if (*str != '\0' && *str != '*')
1549 menubar_push (str); 1739 menubar_push (str);
1550 break; 1740 break;
1551 default: 1741 default:
1552 if (CurrentBar == NULL) { 1742 if (CurrentBar == NULL)
1553 menubar_push ("default"); 1743 {
1554 } 1744 menubar_push ("default");
1555 } 1745 }
1746 }
1556 1747
1557 if (CurrentBar != NULL) 1748 if (CurrentBar != NULL)
1558 menu_readonly = 0; /* allow menu build commands */ 1749 menu_readonly = 0; /* allow menu build commands */
1559 } else if (!STRCMP(str, "dump")) { 1750 }
1751 else if (!strcmp (str, "dump"))
1752 {
1560 /* dump current menubars to a file */ 1753 /* dump current menubars to a file */
1561 FILE *fp; 1754 FILE *fp;
1562 1755
1563 /* enough space to hold the results */ 1756 /* enough space to hold the results */
1564 char buffer[32]; 1757 char buffer[32];
1565 1758
1566 sprintf(buffer, "/tmp/" APL_SUBCLASS "-%u", 1759 sprintf (buffer, "/tmp/" RESCLASS "-%u",
1567 (unsigned int)getpid()); 1760 (unsigned int)getpid ());
1568 1761
1569 if ((fp = fopen(buffer, "wb")) != NULL) { 1762 if ((fp = fopen (buffer, "wb")) != NULL)
1570 xterm_seq (XTerm_title, buffer, CHAR_ST); 1763 {
1571 menubar_dump (fp); 1764 process_xterm_seq (XTerm_title, buffer, CHAR_ST);
1572 fclose(fp); 1765 menubar_dump (fp);
1573 } 1766 fclose (fp);
1574 } else if (!STRCMP(str, "next")) { 1767 }
1575 if (CurrentBar) { 1768 }
1769 else if (!strcmp (str, "next"))
1770 {
1771 if (CurrentBar)
1772 {
1576 CurrentBar = CurrentBar->next; 1773 CurrentBar = CurrentBar->next;
1577 menu_readonly = 1; 1774 menu_readonly = 1;
1578 } 1775 }
1579 } else if (!STRCMP(str, "prev")) { 1776 }
1580 if (CurrentBar) { 1777 else if (!strcmp (str, "prev"))
1778 {
1779 if (CurrentBar)
1780 {
1581 CurrentBar = CurrentBar->prev; 1781 CurrentBar = CurrentBar->prev;
1582 menu_readonly = 1; 1782 menu_readonly = 1;
1583 } 1783 }
1584 } else if (!STRCMP(str, "swap")) { 1784 }
1585 /* swap the top 2 menus */ 1785 else if (!strcmp (str, "swap"))
1586 if (CurrentBar) { 1786 {
1787 /* swap the top 2 menus */
1788 if (CurrentBar)
1789 {
1587 bar_t *cbprev = CurrentBar->prev; 1790 bar_t *cbprev = CurrentBar->prev;
1588 bar_t *cbnext = CurrentBar->next; 1791 bar_t *cbnext = CurrentBar->next;
1589 1792
1590 cbprev->next = cbnext; 1793 cbprev->next = cbnext;
1591 cbnext->prev = cbprev; 1794 cbnext->prev = cbprev;
1592 1795
1593 CurrentBar->next = cbprev; 1796 CurrentBar->next = cbprev;
1594 CurrentBar->prev = cbprev->prev; 1797 CurrentBar->prev = cbprev->prev;
1595 1798
1596 cbprev->prev->next = CurrentBar; 1799 cbprev->prev->next = CurrentBar;
1597 cbprev->prev = CurrentBar; 1800 cbprev->prev = CurrentBar;
1598 1801
1599 CurrentBar = cbprev; 1802 CurrentBar = cbprev;
1600 menu_readonly = 1; 1803 menu_readonly = 1;
1601 } 1804 }
1602 } 1805 }
1603#endif /* (MENUBAR_MAX > 1) */ 1806#endif /* (MENUBAR_MAX > 1) */
1604 str = next; 1807 str = next;
1605 1808
1606 BuildMenu = ActiveMenu = NULL; 1809 BuildMenu = ActiveMenu = NULL;
1607 menubar_expose (); 1810 menubar_expose ();
1608#ifdef DEBUG_MENUBAR_STACKING 1811#ifdef DEBUG_MENUBAR_STACKING
1609 fprintf(stderr, "menus are read%s\n", 1812 fprintf (stderr, "menus are read%s\n",
1610 menu_readonly ? "only" : "/write"); 1813 menu_readonly ? "only" : "/write");
1611#endif 1814#endif
1612 } 1815
1613 return; 1816 }
1614 break; 1817 return;
1818 break;
1615 } 1819 }
1616 1820
1617#if (MENUBAR_MAX > 1) 1821#if (MENUBAR_MAX > 1)
1618 if (CurrentBar == NULL) 1822 if (CurrentBar == NULL)
1619 return; 1823 return;
1620 if (menu_readonly) { 1824 if (menu_readonly)
1825 {
1621#ifdef DEBUG_MENUBAR_STACKING 1826#ifdef DEBUG_MENUBAR_STACKING
1622 fprintf(stderr, "menus are read%s\n", 1827 fprintf (stderr, "menus are read%s\n",
1623 menu_readonly ? "only" : "/write"); 1828 menu_readonly ? "only" : "/write");
1624#endif 1829#endif
1625 return; 1830 return;
1626 } 1831 }
1627#endif /* (MENUBAR_MAX > 1) */ 1832#endif /* (MENUBAR_MAX > 1) */
1628 1833
1629 switch (cmd) { 1834 switch (cmd)
1835 {
1630 case '+': 1836 case '+':
1631 case '-': 1837 case '-':
1632 path = name = str; 1838 path = name = str;
1633 1839
1634 name2 = NULL; 1840 name2 = NULL;
1635 /* parse STR, allow spaces inside (name) */ 1841 /* parse STR, allow spaces inside (name) */
1636 if (path[0] != '\0') { 1842 if (path[0] != '\0')
1637 name = STRCHR(path, MENUITEM_BEG); 1843 {
1638 str = STRCHR(path, MENUITEM_END); 1844 name = strchr (path, MENUITEM_BEG);
1845 str = strchr (path, MENUITEM_END);
1639 if (name != NULL || str != NULL) { 1846 if (name != NULL || str != NULL)
1847 {
1640 if (name == NULL || str == NULL || str <= (name + 1) 1848 if (name == NULL || str == NULL || str <= (name + 1)
1641 || (name > path && name[-1] != '/')) { 1849 || (name > path && name[-1] != '/'))
1642 rxvt_print_error("menu error <%s>\n", path); 1850 {
1643 break; 1851 rxvt_warn ("menu error A<%s>, continuing.\n", path);
1644 } 1852 break;
1645 if (str[1] == MENUITEM_BEG) { 1853 }
1646 name2 = (str + 2); 1854 if (str[1] == MENUITEM_BEG)
1647 str = STRCHR(name2, MENUITEM_END); 1855 {
1856 name2 = (str + 2);
1857 str = strchr (name2, MENUITEM_END);
1648 1858
1649 if (str == NULL) { 1859 if (str == NULL)
1650 rxvt_print_error("menu error <%s>\n", path); 1860 {
1651 break; 1861 rxvt_warn ("menu error B<%s>, continuing.\n", path);
1652 } 1862 break;
1863 }
1653 name2[-2] = '\0'; /* remove prev MENUITEM_END */ 1864 name2[-2] = '\0'; /* remove prev MENUITEM_END */
1654 } 1865 }
1655 if (name > path && name[-1] == '/') 1866 if (name > path && name[-1] == '/')
1656 name[-1] = '\0'; 1867 name[-1] = '\0';
1657 1868
1658 *name++ = '\0'; /* delimit */ 1869 *name++ = '\0'; /* delimit */
1659 *str++ = '\0'; /* delimit */ 1870 *str++ = '\0'; /* delimit */
1660 1871
1661 while (isspace(*str)) 1872 while (isspace (*str))
1662 str++; /* skip space */ 1873 str++; /* skip space */
1663 } 1874 }
1664#ifdef DEBUG_MENU 1875#ifdef DEBUG_MENU
1665 fprintf(stderr, 1876 fprintf (stderr,
1666 "`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n", 1877 "`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n",
1667 cmd, (path ? path : "(nil)"), (name ? name : "(nil)"), 1878 cmd, (path ? path : " (nil)"), (name ? name : " (nil)"),
1668 (name2 ? name2 : "(nil)"), (str ? str : "(nil)") 1879 (name2 ? name2 : " (nil)"), (str ? str : " (nil)")
1669 ); 1880 );
1670#endif 1881#endif
1671 } 1882
1883 }
1672 /* process the different commands */ 1884 /* process the different commands */
1673 switch (cmd) { 1885 switch (cmd)
1886 {
1674 case '+': /* add/replace existing menu or menuitem */ 1887 case '+': /* add/replace existing menu or menuitem */
1675 if (path[0] != '\0') { 1888 if (path[0] != '\0')
1676 int len; 1889 {
1890 int len;
1677 1891
1678 path = menu_find_base (&(BuildMenu), path); 1892 path = menu_find_base (& (BuildMenu), path);
1679 len = STRLEN(path); 1893 len = strlen (path);
1680 1894
1681 /* don't allow menus called `*' */ 1895 /* don't allow menus called `*' */
1682 if (path[0] == '*') { 1896 if (path[0] == '*')
1683 menu_clear (BuildMenu); 1897 {
1684 break; 1898 menu_clear (BuildMenu);
1685 } else if (len >= 2 && !STRCMP((path + len - 2), "/*")) { 1899 break;
1686 path[len - 2] = '\0'; 1900 }
1687 } 1901 else if (len >= 2 && !strcmp ((path + len - 2), "/*"))
1688 if (path[0] != '\0') 1902 {
1903 path[len - 2] = '\0';
1904 }
1905 if (path[0] != '\0')
1689 BuildMenu = menu_add (BuildMenu, path); 1906 BuildMenu = menu_add (BuildMenu, path);
1690 } 1907 }
1691 if (name != NULL && name[0] != '\0') 1908 if (name != NULL && name[0] != '\0')
1692 rxvt_menuitem_add(BuildMenu, 1909 rxvt_menuitem_add (BuildMenu,
1693 (STRCMP(name, SEPARATOR_NAME) ? name : ""), 1910 (strcmp (name, SEPARATOR_NAME) ? name : ""),
1694 name2, str); 1911 name2, str);
1695 break; 1912 break;
1696 1913
1697 case '-': /* delete menu entry */ 1914 case '-': /* delete menu entry */
1698 if (!STRCMP(path, "/*") && (name == NULL || name[0] == '\0')) { 1915 if (!strcmp (path, "/*") && (name == NULL || name[0] == '\0'))
1699 menubar_clear (); 1916 {
1700 BuildMenu = NULL; 1917 menubar_clear ();
1701 menubar_expose (); 1918 BuildMenu = NULL;
1702 break; 1919 menubar_expose ();
1703 } else if (path[0] != '\0') { 1920 break;
1704 int len; 1921 }
1922 else if (path[0] != '\0')
1923 {
1924 int len;
1705 menu_t *menu = BuildMenu; 1925 menu_t *menu = BuildMenu;
1706 1926
1707 path = menu_find_base (&menu, path); 1927 path = menu_find_base (&menu, path);
1708 len = STRLEN(path); 1928 len = strlen (path);
1709 1929
1710 /* submenu called `*' clears all menu items */ 1930 /* submenu called `*' clears all menu items */
1711 if (path[0] == '*') { 1931 if (path[0] == '*')
1712 menu_clear (menu); 1932 {
1713 break; /* done */ 1933 menu_clear (menu);
1714 } else if (len >= 2 && !STRCMP(&path[len - 2], "/*")) { 1934 break; /* done */
1715 /* done */ 1935 }
1716 break; 1936 else if (len >= 2 && !strcmp (&path[len - 2], "/*"))
1717 } else if (path[0] != '\0') { 1937 {
1718 BuildMenu = NULL; 1938 /* done */
1719 break; 1939 break;
1720 } else 1940 }
1721 BuildMenu = menu; 1941 else if (path[0] != '\0')
1722 } 1942 {
1943 BuildMenu = NULL;
1944 break;
1945 }
1946 else
1947 BuildMenu = menu;
1948 }
1949
1723 if (BuildMenu != NULL) { 1950 if (BuildMenu != NULL)
1951 {
1724 if (name == NULL || name[0] == '\0') 1952 if (name == NULL || name[0] == '\0')
1725 BuildMenu = menu_delete (BuildMenu); 1953 BuildMenu = menu_delete (BuildMenu);
1726 else { 1954 else
1727 const char *n1; 1955 {
1728 menuitem_t *item; 1956 const char *n1;
1729 menu_t *BuildMenu = BuildMenu; 1957 menuitem_t *item;
1730 1958
1731 n1 = STRCMP(name, SEPARATOR_NAME) ? name : ""; 1959 n1 = strcmp (name, SEPARATOR_NAME) ? name : "";
1732 item = rxvt_menuitem_find(BuildMenu, n1); 1960 item = rxvt_menuitem_find (BuildMenu, n1);
1733 if (item != NULL && item->entry.type != MenuSubMenu) { 1961 if (item != NULL && item->entry.type != MenuSubMenu)
1734 menuitem_free (BuildMenu, item); 1962 {
1963 menuitem_free (BuildMenu, item);
1735 1964
1736 /* fix up the width */ 1965 /* fix up the width */
1737 BuildMenu->width = 0; 1966 BuildMenu->width = 0;
1738 for (item = BuildMenu->head; item != NULL; 1967 for (item = BuildMenu->head; item != NULL;
1739 item = item->next) { 1968 item = item->next)
1969 {
1740 short l = item->len + item->len2; 1970 short l = item->len + item->len2;
1741 1971
1742 MAX_IT(BuildMenu->width, l); 1972 max_it (BuildMenu->width, l);
1743 } 1973 }
1744 } 1974 }
1745 } 1975 }
1746 menubar_expose (); 1976
1747 } 1977 menubar_expose ();
1978 }
1979 break;
1980 }
1748 break; 1981 break;
1749 }
1750 break;
1751 } 1982 }
1752} 1983}
1753 1984
1754void 1985void
1755rxvt_term::draw_Arrows (int name, int state) 1986rxvt_term::draw_Arrows (int name, int state)
1756{ 1987{
1757 GC top, bot; 1988 GC top, bot;
1758 1989
1759 int i; 1990 int i;
1760 1991
1761#ifdef MENU_SHADOW_IN 1992#ifdef MENU_SHADOW_IN
1762 state = -state; 1993 state = -state;
1763#endif 1994#endif
1764 switch (state) { 1995 switch (state)
1996 {
1765 case +1: 1997 case +1:
1766 top = topShadowGC; 1998 top = topShadowGC;
1767 bot = botShadowGC; 1999 bot = botShadowGC;
1768 break; /* SHADOW_OUT */ 2000 break; /* SHADOW_OUT */
1769 case -1: 2001 case -1:
1770 top = botShadowGC; 2002 top = botShadowGC;
1771 bot = topShadowGC; 2003 bot = topShadowGC;
1772 break; /* SHADOW_IN */ 2004 break; /* SHADOW_IN */
1773 default: 2005 default:
1774 top = bot = scrollbarGC; 2006 top = bot = scrollbarGC;
1775 break; /* neutral */ 2007 break; /* neutral */
1776 } 2008 }
1777 2009
1778 if (!Arrows_x) 2010 if (!Arrows_x)
1779 return; 2011 return;
1780 2012
1781 for (i = 0; i < NARROWS; i++) { 2013 for (i = 0; i < NARROWS; i++)
2014 {
1782 const int w = Width2Pixel(1); 2015 const int w = Width2Pixel (1);
1783 const int y = (menuBar_TotalHeight() - w) / 2; 2016 const int y = (menuBar_TotalHeight () - w) / 2;
1784 int x = Arrows_x + (5 * Width2Pixel(i)) / 4; 2017 int x = Arrows_x + (5 * Width2Pixel (i)) / 4;
1785 2018
1786 if (!name || name == Arrows[i].name) 2019 if (!name || name == Arrows[i].name)
1787 rxvt_Draw_Triangle(Xdisplay, menuBar.win, top, bot, x, y, w, 2020 rxvt_Draw_Triangle (display->display, menuBar.win, top, bot, x, y, w,
1788 Arrows[i].name); 2021 Arrows[i].name);
1789 } 2022 }
1790 XFlush(Xdisplay); 2023 XFlush (display->display);
1791} 2024}
1792 2025
1793void 2026void
1794rxvt_term::menubar_expose () 2027rxvt_term::menubar_expose ()
1795{ 2028{
1796 menu_t *menu; 2029 menu_t *menu;
1797 int x; 2030 int x;
1798 2031
1799 if (!menubar_visible(r) || menuBar.win == 0) 2032 if (!menubar_visible () || menuBar.win == 0)
1800 return; 2033 return;
1801 2034
1802 if (menubarGC == None) { 2035 if (menubarGC == None)
2036 {
1803 /* Create the graphics context */ 2037 /* Create the graphics context */
1804 XGCValues gcvalue; 2038 XGCValues gcvalue;
1805 2039
1806 gcvalue.font = TermWin.font->fid; 2040 gcvalue.foreground = (display->depth <= 2 ? pix_colors[Color_fg]
1807 2041 : pix_colors[Color_Black]);
1808 gcvalue.foreground = (XDEPTH <= 2 ? PixColors[Color_fg]
1809 : PixColors[Color_Black]);
1810 menubarGC = XCreateGC(Xdisplay, menuBar.win, 2042 menubarGC = XCreateGC (display->display, menuBar.win,
1811 GCForeground | GCFont, &gcvalue); 2043 GCForeground, &gcvalue);
1812 2044
1813 } 2045 }
1814/* make sure the font is correct */ 2046 /* make sure the font is correct */
1815 XSetFont(Xdisplay, menubarGC, TermWin.font->fid);
1816 XSetFont(Xdisplay, botShadowGC, TermWin.font->fid);
1817 XClearWindow(Xdisplay, menuBar.win); 2047 XClearWindow (display->display, menuBar.win);
1818 2048
1819 menu_hide_all (); 2049 menu_hide_all ();
1820 2050
1821 x = 0; 2051 x = 0;
1822 if (CurrentBar != NULL) { 2052 if (CurrentBar != NULL)
2053 {
1823 for (menu = CurrentBar->head; menu != NULL; menu = menu->next) { 2054 for (menu = CurrentBar->head; menu != NULL; menu = menu->next)
2055 {
1824 int len = menu->len; 2056 int len = menu->len;
1825 2057
1826 x = (menu->x + menu->len + HSPACE); 2058 x = (menu->x + menu->len + HSPACE);
1827 2059
1828#ifdef DEBUG_MENU_LAYOUT 2060#ifdef DEBUG_MENU_LAYOUT
1829 rxvt_print_menu_descendants(menu); 2061 rxvt_print_menu_descendants (menu);
1830#endif 2062#endif
1831 2063
1832 if (x >= TermWin.ncol) 2064 if (x >= ncol)
1833 len = (TermWin.ncol - (menu->x + HSPACE)); 2065 len = (ncol - (menu->x + HSPACE));
1834 2066
1835 drawbox_menubar (menu->x, len, +1); 2067 drawbox_menubar (menu->x, len, +1);
1836#ifdef USE_XIM 2068 draw_string (*menuBar.drawable, menubarGC, fontset[0],
1837 if (TermWin.fontset)
1838 XmbDrawString(Xdisplay,
1839 menuBar.win, TermWin.fontset,
1840 menubarGC,
1841 (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), 2069 (Width2Pixel (menu->x) + Width2Pixel (HSPACE) / 2),
1842 menuBar_height() - SHADOW, menu->name, len); 2070 MENU_SHADOW, menu->name, len);
1843 else
1844#endif
1845 XDrawString(Xdisplay, menuBar.win, menubarGC,
1846 (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2),
1847 menuBar_height() - SHADOW, menu->name, len);
1848 2071
1849 if (x >= TermWin.ncol) 2072 if (x >= ncol)
1850 break; 2073 break;
1851 } 2074 }
1852 } 2075 }
1853 drawbox_menubar (x, TermWin.ncol, (CurrentBar ? +1 : -1)); 2076 drawbox_menubar (x, ncol, (CurrentBar ? +1 : -1));
1854 2077
1855/* add the menuBar title, if it exists and there's plenty of room */ 2078 /* add the menuBar title, if it exists and there's plenty of room */
1856 Arrows_x = 0; 2079 Arrows_x = 0;
1857 if (x < TermWin.ncol) { 2080 if (x < ncol)
2081 {
1858 const char *str; 2082 const char *str;
1859 int ncol;
1860 unsigned int len; 2083 unsigned int len;
1861 char title[256]; 2084 char title[256];
1862 2085
1863 ncol = (int)TermWin.ncol;
1864 if (x < (ncol - (NARROWS + 1))) { 2086 if (x < (ncol - (NARROWS + 1)))
2087 {
1865 ncol -= (NARROWS + 1); 2088 ncol -= (NARROWS + 1);
1866 Arrows_x = Width2Pixel(ncol); 2089 Arrows_x = Width2Pixel (ncol);
1867 } 2090 }
2091
1868 draw_Arrows (0, +1); 2092 draw_Arrows (0, +1);
1869 2093
1870 str = (CurrentBar 2094 str = (CurrentBar
1871 && CurrentBar->title) ? CurrentBar->title : "%n-%v"; 2095 && CurrentBar->title) ? CurrentBar->title : "%n-%v";
1872 for (len = 0; str[0] && len < sizeof(title) - 1; str++) { 2096 for (len = 0; str[0] && len < sizeof (title) - 1; str++)
2097 {
1873 const char *s = NULL; 2098 const char *s = NULL;
1874 2099
1875 switch (str[0]) { 2100 switch (str[0])
1876 case '%': 2101 {
1877 str++; 2102 case '%':
1878 switch (str[0]) { 2103 str++;
1879 case 'n': 2104 switch (str[0])
1880 s = rs[Rs_name]; 2105 {
2106 case 'n':
2107 s = rs[Rs_name];
1881 break; /* resource name */ 2108 break; /* resource name */
1882 case 'v': 2109 case 'v':
1883 s = VERSION; 2110 s = VERSION;
1884 break; /* version number */ 2111 break; /* version number */
1885 case '%': 2112 case '%':
1886 s = "%"; 2113 s = "%";
1887 break; /* literal '%' */ 2114 break; /* literal '%' */
1888 } 2115 }
1889 if (s != NULL) 2116 if (s != NULL)
1890 while (*s && len < sizeof(title) - 1) 2117 while (*s && len < sizeof (title) - 1)
1891 title[len++] = *s++; 2118 title[len++] = *s++;
1892 break; 2119 break;
1893 2120
1894 default: 2121 default:
1895 title[len++] = str[0]; 2122 title[len++] = str[0];
1896 break; 2123 break;
1897 } 2124 }
1898 } 2125 }
1899 title[len] = '\0'; 2126 title[len] = '\0';
1900 2127
1901 ncol -= (x + len + HSPACE); 2128 ncol -= (x + len + HSPACE);
1902 if (len > 0 && ncol >= 0) { 2129 if (len > 0 && ncol >= 0)
1903#ifdef USE_XIM 2130 draw_string (*menuBar.drawable, menubarGC, fontset[0],
1904 if (TermWin.fontset)
1905 XmbDrawString(Xdisplay,
1906 menuBar.win, TermWin.fontset,
1907 menubarGC,
1908 Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2, 2131 Width2Pixel (x) + Width2Pixel (ncol + HSPACE) / 2,
1909 menuBar_height() - SHADOW, title, len); 2132 MENU_SHADOW, title, len);
1910 else
1911#endif
1912 XDrawString(Xdisplay, menuBar.win, menubarGC,
1913 Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2,
1914 menuBar_height() - SHADOW, title, len);
1915 }
1916 } 2133 }
1917} 2134}
1918 2135
1919int 2136int
1920rxvt_term::menubar_mapping (int map) 2137rxvt_term::menubar_mapping (int map)
1921{ 2138{
1922 int change = 0; 2139 int change = 0;
1923 2140
1924 if (map && !menubar_visible(r)) { 2141 if (map && !menubar_visible ())
2142 {
1925 menuBar.state = 1; 2143 menuBar.state = 1;
1926 if (menuBar.win == 0) 2144 if (menuBar.win == 0)
1927 return 0; 2145 return 0;
1928 XMapWindow(Xdisplay, menuBar.win); 2146 XMapWindow (display->display, menuBar.win);
1929 change = 1; 2147 change = 1;
2148 }
1930 } else if (!map && menubar_visible(r)) { 2149 else if (!map && menubar_visible ())
2150 {
2151 menubar_expose ();
2152 menuBar.state = 0;
2153 XUnmapWindow (display->display, menuBar.win);
2154 change = 1;
2155 }
2156 else
1931 menubar_expose (); 2157 menubar_expose ();
1932 menuBar.state = 0;
1933 XUnmapWindow(Xdisplay, menuBar.win);
1934 change = 1;
1935 } else
1936 menubar_expose ();
1937 2158
1938 return change; 2159 return change;
1939} 2160}
1940 2161
1941int 2162int
1942rxvt_term::menu_select (XButtonEvent *ev) 2163rxvt_term::menu_select (XButtonEvent &ev)
1943{ 2164{
1944 menuitem_t *thisitem, *item = NULL; 2165 menuitem_t *thisitem, *item = NULL;
1945 int this_y, y; 2166 int this_y, y;
1946 menu_t *ActiveMenu = ActiveMenu;
1947 2167
1948 Window unused_root, unused_child; 2168 Window unused_root, unused_child;
1949 int unused_root_x, unused_root_y; 2169 int unused_root_x, unused_root_y;
1950 unsigned int unused_mask; 2170 unsigned int unused_mask;
1951 2171
1952 if (ActiveMenu == NULL) 2172 if (ActiveMenu == NULL)
1953 return 0; 2173 return 0;
1954 2174
1955 XQueryPointer(Xdisplay, ActiveMenu->win, 2175 XQueryPointer (display->display, ActiveMenu->win,
1956 &unused_root, &unused_child, 2176 &unused_root, &unused_child,
1957 &unused_root_x, &unused_root_y, 2177 &unused_root_x, &unused_root_y,
1958 &(ev->x), &(ev->y), &unused_mask); 2178 &ev.x, &ev.y, &unused_mask);
1959 2179
1960 if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0)) { 2180 if (ActiveMenu->parent != NULL && (ev.x < 0 || ev.y < 0))
1961 menu_hide ();
1962 return 1;
1963 } 2181 {
2182 menu_hide ();
2183 return 1;
2184 }
2185
1964/* determine the menu item corresponding to the Y index */ 2186 /* determine the menu item corresponding to the Y index */
1965 y = SHADOW; 2187 y = MENU_SHADOW;
1966 if (ev->x >= 0 && ev->x <= (ActiveMenu->w - SHADOW)) { 2188 if (ev.x >= 0 && ev.x <= (ActiveMenu->w - MENU_SHADOW))
2189 {
1967 for (item = ActiveMenu->head; item != NULL; item = item->next) { 2190 for (item = ActiveMenu->head; item != NULL; item = item->next)
2191 {
1968 int h = HEIGHT_TEXT + 2 * SHADOW; 2192 int h = HEIGHT_TEXT + 2 * MENU_SHADOW;
1969 2193
1970 if (isSeparator(item->name)) 2194 if (isSeparator (item->name))
1971 h = HEIGHT_SEPARATOR; 2195 h = HEIGHT_SEPARATOR;
1972 else if (ev->y >= y && ev->y < (y + h)) 2196 else if (ev.y >= y && ev.y < (y + h))
1973 break; 2197 break;
2198
1974 y += h; 2199 y += h;
1975 } 2200 }
1976 } 2201 }
2202
1977 if (item == NULL && ev->type == ButtonRelease) { 2203 if (item == NULL && ev.type == ButtonRelease)
2204 {
1978 menu_hide_all (); 2205 menu_hide_all ();
1979 return 0; 2206 return 0;
1980 } 2207 }
2208
1981 thisitem = item; 2209 thisitem = item;
1982 this_y = y - SHADOW; 2210 this_y = y - MENU_SHADOW;
1983 2211
1984/* erase the last item */ 2212 /* erase the last item */
1985 if (ActiveMenu->item != NULL) { 2213 if (ActiveMenu->item != NULL)
2214 {
1986 if (ActiveMenu->item != thisitem) { 2215 if (ActiveMenu->item != thisitem)
2216 {
1987 for (y = 0, item = ActiveMenu->head; item != NULL; 2217 for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next)
1988 item = item->next) { 2218 {
1989 int h; 2219 int h;
1990 2220
1991 if (isSeparator(item->name)) 2221 if (isSeparator (item->name))
1992 h = HEIGHT_SEPARATOR; 2222 h = HEIGHT_SEPARATOR;
1993 else if (item == ActiveMenu->item) { 2223 else if (item == ActiveMenu->item)
2224 {
1994 /* erase old menuitem */ 2225 /* erase old menuitem */
1995 drawbox_menuitem (y, 0); /* No Shadow */ 2226 drawbox_menuitem (y, 0); /* No Shadow */
1996 if (item->entry.type == MenuSubMenu) 2227 if (item->entry.type == MenuSubMenu)
1997 drawtriangle (ActiveMenu->w, y, +1); 2228 drawtriangle (ActiveMenu->w, y, +1);
1998 break; 2229
1999 } else 2230 break;
2231 }
2232 else
2000 h = HEIGHT_TEXT + 2 * SHADOW; 2233 h = HEIGHT_TEXT + 2 * MENU_SHADOW;
2001 y += h; 2234
2002 } 2235 y += h;
2003 } else { 2236 }
2237 }
2238 else
2239 {
2004 switch (ev->type) { 2240 switch (ev.type)
2241 {
2005 case ButtonRelease: 2242 case ButtonRelease:
2006 switch (item->entry.type) { 2243 switch (item->entry.type)
2007 case MenuLabel: 2244 {
2008 case MenuSubMenu: 2245 case MenuLabel:
2009 menu_hide_all (); 2246 case MenuSubMenu:
2010 break; 2247 menu_hide_all ();
2248 break;
2011 2249
2012 case MenuAction: 2250 case MenuAction:
2013 case MenuTerminalAction: 2251 case MenuTerminalAction:
2014 drawbox_menuitem (_y, -1); 2252 drawbox_menuitem (this_y, -1);
2015 { 2253 rxvt_usleep (MENU_DELAY_USEC);
2016#ifdef HAVE_NANOSLEEP
2017 struct timespec rqt;
2018
2019 rqt.tv_sec = 0;
2020 rqt.tv_nsec = MENU_DELAY_USEC * 1000;
2021 nanosleep(&rqt, NULL);
2022#else
2023 /* use select for timing */
2024 struct timeval tv;
2025
2026 tv.tv_sec = 0;
2027 tv.tv_usec = MENU_DELAY_USEC;
2028 select(0, NULL, NULL, NULL, &tv);
2029#endif
2030 }
2031 /* remove menu before sending keys to the application */ 2254 /* remove menu before sending keys to the application */
2032 menu_hide_all (); 2255 menu_hide_all ();
2033#ifndef DEBUG_MENU 2256#ifndef DEBUG_MENU
2034 action_dispatch (&(item->entry.action)); 2257 action_dispatch (& (item->entry.action));
2035#else /* DEBUG_MENU */ 2258#else /* DEBUG_MENU */
2036 fprintf(stderr, "%s: %s\n", item->name, 2259 fprintf (stderr, "%s: %s\n", item->name,
2037 item->entry.action.str); 2260 item->entry.action.str);
2038#endif /* DEBUG_MENU */ 2261#endif /* DEBUG_MENU */
2039 break; 2262 break;
2040 } 2263 }
2041 break; 2264 break;
2042 2265
2043 default: 2266 default:
2044 if (item->entry.type == MenuSubMenu) 2267 if (item->entry.type == MenuSubMenu)
2045 goto DoMenu; 2268 goto DoMenu;
2046 break; 2269 break;
2270 }
2271 return 0;
2272 }
2047 } 2273 }
2048 return 0; 2274
2049 }
2050 }
2051 DoMenu: 2275DoMenu:
2052 ActiveMenu->item = thisitem; 2276 ActiveMenu->item = thisitem;
2053 y = this_y; 2277 y = this_y;
2278
2054 if (item != NULL) { 2279 if (thisitem != NULL)
2280 {
2055 item = ActiveMenu->item; 2281 item = ActiveMenu->item;
2056 if (item->entry.type != MenuLabel) 2282 if (item->entry.type != MenuLabel)
2057 drawbox_menuitem (y, +1); 2283 drawbox_menuitem (y, +1);
2284
2058 if (item->entry.type == MenuSubMenu) { 2285 if (item->entry.type == MenuSubMenu)
2059 int x; 2286 {
2287 int x;
2060 2288
2061 drawtriangle (ActiveMenu->w, y, -1); 2289 drawtriangle (ActiveMenu->w, y, -1);
2062 2290
2063 x = ev->x + (ActiveMenu->parent 2291 x = ev.x + (ActiveMenu->parent
2064 ? ActiveMenu->x 2292 ? ActiveMenu->x
2065 : Width2Pixel(ActiveMenu->x)); 2293 : Width2Pixel (ActiveMenu->x));
2066 2294
2067 if (x >= item->entry.submenu.menu->x) { 2295 if (x >= item->entry.submenu.menu->x)
2296 {
2068 ActiveMenu = item->entry.submenu.menu; 2297 ActiveMenu = item->entry.submenu.menu;
2069 menu_show (); 2298 menu_show ();
2070 return 1; 2299 return 1;
2300 }
2301 }
2071 } 2302 }
2072 }
2073 }
2074 return 0; 2303 return 0;
2075} 2304}
2076 2305
2077void 2306void
2078rxvt_term::menubar_select (XButtonEvent *ev) 2307rxvt_term::menubar_select (XButtonEvent &ev)
2079{ 2308{
2080 menu_t *menu = NULL; 2309 menu_t *menu = NULL;
2081 2310
2082/* determine the pulldown menu corresponding to the X index */ 2311 /* determine the pulldown menu corresponding to the X index */
2083 if (ev->y >= 0 && ev->y <= menuBar_height() && CurrentBar != NULL) { 2312 if (ev.y >= 0 && ev.y <= menuBar_height () && CurrentBar != NULL)
2313 {
2084 for (menu = CurrentBar->head; menu != NULL; menu = menu->next) { 2314 for (menu = CurrentBar->head; menu != NULL; menu = menu->next)
2315 {
2085 int x = Width2Pixel(menu->x); 2316 int x = Width2Pixel (menu->x);
2086 int w = Width2Pixel(menu->len + HSPACE); 2317 int w = Width2Pixel (menu->len + HSPACE);
2087 2318
2088 if ((ev->x >= x && ev->x < x + w)) 2319 if ((ev.x >= x && ev.x < x + w))
2089 break; 2320 break;
2090 } 2321 }
2091 } 2322 }
2092 switch (ev->type) { 2323 switch (ev.type)
2324 {
2093 case ButtonRelease: 2325 case ButtonRelease:
2094 menu_hide_all (); 2326 menu_hide_all ();
2095 break; 2327 break;
2096 2328
2097 case ButtonPress: 2329 case ButtonPress:
2098 if (menu == NULL && Arrows_x && ev->x >= Arrows_x) { 2330 if (menu == NULL && Arrows_x && ev.x >= Arrows_x)
2331 {
2099 int i; 2332 int i;
2100 2333
2101 for (i = 0; i < NARROWS; i++) { 2334 for (i = 0; i < NARROWS; i++)
2335 {
2102 if (ev->x >= (Arrows_x + (Width2Pixel(4 * i + i)) / 4) 2336 if (ev.x >= (Arrows_x + (Width2Pixel (4 * i + i)) / 4)
2103 && ev->x < (Arrows_x 2337 && ev.x < (Arrows_x
2104 + (Width2Pixel(4 * i + i + 4)) / 4)) { 2338 + (Width2Pixel (4 * i + i + 4)) / 4))
2339 {
2105 draw_Arrows (Arrows[i].name, -1); 2340 draw_Arrows (Arrows[i].name, -1);
2106 { 2341 rxvt_usleep (MENU_DELAY_USEC);
2107#ifdef HAVE_NANOSLEEP
2108 struct timespec rqt;
2109
2110 rqt.tv_sec = 0;
2111 rqt.tv_nsec = MENU_DELAY_USEC * 1000;
2112 nanosleep(&rqt, NULL);
2113#else
2114 /* use select for timing */
2115 struct timeval tv;
2116
2117 tv.tv_sec = 0;
2118 tv.tv_usec = MENU_DELAY_USEC;
2119 select(0, NULL, NULL, NULL, &tv);
2120#endif
2121 }
2122 draw_Arrows (Arrows[i].name, +1); 2342 draw_Arrows (Arrows[i].name, +1);
2123#ifdef DEBUG_MENUARROWS 2343#ifdef DEBUG_MENUARROWS
2124 fprintf(stderr, "'%c': ", Arrows[i].name); 2344 fprintf (stderr, "'%c': ", Arrows[i].name);
2125 2345
2126 if (CurrentBar == NULL 2346 if (CurrentBar == NULL
2127 || (CurrentBar->arrows[i].type != MenuAction 2347 || (CurrentBar->arrows[i].type != MenuAction
2128 && CurrentBar->arrows[i].type != 2348 && CurrentBar->arrows[i].type !=
2129 MenuTerminalAction)) { 2349 MenuTerminalAction))
2350 {
2130 if (Arrows[i].str != NULL && Arrows[i].str[0]) 2351 if (Arrows[i].str != NULL && Arrows[i].str[0])
2131 fprintf(stderr, "(default) \\033%s\n", 2352 fprintf (stderr, " (default) \\033%s\n",
2132 &(Arrows[i].str[2])); 2353 & (Arrows[i].str[2]));
2133 } else { 2354 }
2134 fprintf(stderr, "%s\n", 2355 else
2135 CurrentBar->arrows[i].str); 2356 {
2136 } 2357 fprintf (stderr, "%s\n",
2358 CurrentBar->arrows[i].str);
2359 }
2137#else /* DEBUG_MENUARROWS */ 2360#else /* DEBUG_MENUARROWS */
2138 if (CurrentBar == NULL 2361 if (CurrentBar == NULL || action_dispatch (&CurrentBar->arrows[i]))
2139 || rxvt_action_dispatch(r, 2362 {
2140 &(CurrentBar->arrows[i]))
2141 ) {
2142 if (Arrows[i].str != NULL && Arrows[i].str[0] != 0) 2363 if (Arrows[i].str != NULL && Arrows[i].str[0] != 0)
2143 tt_write ((Arrows[i].str + 1), 2364 tt_write ((Arrows[i].str + 1),
2144 Arrows[i].str[0]); 2365 Arrows[i].str[0]);
2145 } 2366 }
2146#endif /* DEBUG_MENUARROWS */ 2367#endif /* DEBUG_MENUARROWS */
2147 return; 2368 return;
2148 } 2369 }
2149 } 2370 }
2150 } 2371 }
2151 /* FALLTHROUGH */ 2372 /* FALLTHROUGH */
2152 2373
2153 default: 2374 default:
2154 /* 2375 /*
2155 * press menubar or move to a new entry 2376 * press menubar or move to a new entry
2156 */ 2377 */
2157 if (menu != NULL && menu != ActiveMenu) { 2378 if (menu != NULL && menu != ActiveMenu)
2379 {
2158 menu_hide_all (); /* pop down old menu */ 2380 menu_hide_all (); /* pop down old menu */
2159 ActiveMenu = menu; 2381 ActiveMenu = menu;
2160 menu_show (); /* pop up new menu */ 2382 menu_show (); /* pop up new menu */
2161 } 2383 }
2162 break; 2384 break;
2163 } 2385 }
2164} 2386}
2165 2387
2166/* 2388/*
2167 * general dispatch routine, 2389 * general dispatch routine,
2168 * it would be nice to have `sticky' menus 2390 * it would be nice to have `sticky' menus
2169 */ 2391 */
2170void 2392void
2171rxvt_term::menubar_control (XButtonEvent *ev) 2393rxvt_term::menubar_control (XButtonEvent &ev)
2172{ 2394{
2173 switch (ev->type) { 2395 switch (ev.type)
2396 {
2174 case ButtonPress: 2397 case ButtonPress:
2175 if (ev->button == Button1) 2398 if (ev.button == Button1)
2176 menubar_select (ev); 2399 menubar_select (ev);
2177 break; 2400 break;
2178 2401
2179 case ButtonRelease: 2402 case ButtonRelease:
2180 if (ev->button == Button1) 2403 if (ev.button == Button1)
2181 menu_select (ev); 2404 menu_select (ev);
2182 break; 2405 break;
2183 2406
2184 case MotionNotify: 2407 case MotionNotify:
2185 while (XCheckTypedWindowEvent(Xdisplay, TermWin.parent[0], 2408 while (XCheckTypedWindowEvent (display->display, parent[0],
2186 MotionNotify, (XEvent *) ev)) ; 2409 MotionNotify, (XEvent *)&ev));
2187 2410
2188 if (ActiveMenu) 2411 if (ActiveMenu)
2189 while (menu_select (ev)) ; 2412 while (menu_select (ev)) ;
2190 else 2413 else
2191 ev->y = -1; 2414 ev.y = -1;
2192 if (ev->y < 0) { 2415 if (ev.y < 0)
2416 {
2193 Window unused_root, unused_child; 2417 Window unused_root, unused_child;
2194 int unused_root_x, unused_root_y; 2418 int unused_root_x, unused_root_y;
2195 unsigned int unused_mask; 2419 unsigned int unused_mask;
2196 2420
2197 XQueryPointer(Xdisplay, menuBar.win, 2421 XQueryPointer (display->display, menuBar.win,
2198 &unused_root, &unused_child, 2422 &unused_root, &unused_child,
2199 &unused_root_x, &unused_root_y, 2423 &unused_root_x, &unused_root_y,
2200 &(ev->x), &(ev->y), &unused_mask); 2424 &ev.x, &ev.y, &unused_mask);
2201 menubar_select (ev); 2425 menubar_select (ev);
2202 } 2426 }
2203 break; 2427 break;
2204 } 2428 }
2205} 2429}
2206 2430
2207void 2431void
2208rxvt_term::map_menuBar (int map) 2432rxvt_term::map_menuBar (int map)
2209{ 2433{
2210 if (menubar_mapping (map)) 2434 if (menubar_mapping (map))
2211 resize_all_windows (0, 0, 0); 2435 resize_all_windows (0, 0, 0);
2212} 2436}
2213#endif 2437#endif
2214/*----------------------- end-of-file (C source) -----------------------*/ 2438/*----------------------- end-of-file (C source) -----------------------*/

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines