1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/mainmenu.c,v 1.8 2011/05/16 16:21:58 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_MAINMENU_C_
22 
23 #include "tgifdefs.h"
24 
25 #include "align.e"
26 #include "choice.e"
27 #include "color.e"
28 #include "cursor.e"
29 #include "dialog.e"
30 #include "edit.e"
31 #include "file.e"
32 #include "font.e"
33 #include "grid.e"
34 #include "help.e"
35 #include "imgproc.e"
36 #include "mainloop.e"
37 #include "mainmenu.e"
38 #include "menu.e"
39 #include "menuinfo.e"
40 #include "msg.e"
41 #include "navigate.e"
42 #include "obj.e"
43 #include "page.e"
44 #include "pattern.e"
45 #include "raster.e"
46 #include "setup.e"
47 #include "shape.e"
48 #include "special.e"
49 #include "stretch.e"
50 #include "strtbl.e"
51 #include "tangram2.e"
52 #include "text.e"
53 #include "util.e"
54 
55 #define DEF_MAINMENUPINDIST 80
56 
57 int pinnedMainMenu=FALSE;
58 int mainMenuPinDistance=DEF_MAINMENUPINDIST;
59 Window mainMenuWindow=None;
60 
61 int numStacking=0;
62 Window *stackingWins=NULL;
63 
64 int titledPinnedMenu=TRUE;
65 int btn3PopupModeMenu=FALSE;
66 
67 static int mainMenuX=0;
68 static int mainMenuY=0;
69 static int mainMenuW=0;
70 static int mainMenuH=0;
71 
72 typedef struct SubMenuRec {
73    Window win;
74    int x, y, w, h, extra_index;
75 } * SubMenuRecPtr;
76 
77 static struct SubMenuRec subMenuInfo[MAXMENUS+1];
78 
79 static int savedMainWinX, savedMainWinY;
80 
81 static
InitPinnedMenus()82 void InitPinnedMenus()
83 {
84    int i;
85 
86    for (i=0; i < MAXMENUS+1; i++) subMenuInfo[i].win = None;
87 }
88 
InitMainMenu()89 void InitMainMenu()
90 {
91    int menu_w, menu_h;
92    int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
93    char *c_ptr;
94    XWMHints wmhints;
95    XSizeHints sizehints;
96    XSetWindowAttributes win_attrs;
97 
98    mainMenuPinDistance = DEF_MAINMENUPINDIST;
99    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MainMenuPinDistance")) !=
100          NULL) {
101       mainMenuPinDistance = atoi(c_ptr);
102       if (mainMenuPinDistance <= 0) {
103          sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
104                TOOL_NAME, "MainMenuPinDistance", c_ptr, DEF_MAINMENUPINDIST);
105          fprintf(stderr, "%s\n", gszMsgBox);
106          mainMenuPinDistance = DEF_MAINMENUPINDIST;
107       }
108    }
109    pinnedMainMenu = FALSE;
110 
111    btn3PopupModeMenu = FALSE;
112    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"Btn3PopupModeMenu")) != NULL &&
113          UtilStrICmp(c_ptr, "true") == 0) {
114       fprintf(stderr, TgLoadString(STID_NAMED_XDEF_IS_OBSOLETE), TOOL_NAME,
115             "Btn3PopupModeMenu");
116       fprintf(stderr, "\n");
117    }
118    menuRowsBeforeScroll = 20;
119    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MenuRowsBeforeScroll")) !=
120          NULL) {
121       /* well, this is really not used, yet */
122       menuRowsBeforeScroll = atoi(c_ptr);
123       if (menuRowsBeforeScroll <= 0) {
124          sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
125                TOOL_NAME, "MenuRowsBeforeScroll", c_ptr, 20);
126          fprintf(stderr, "%s\n", gszMsgBox);
127          menuRowsBeforeScroll = 20;
128       }
129    }
130    menuColsBeforeScroll = 26;
131    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MenuColsBeforeScroll")) !=
132          NULL) {
133       /* well, this is really not used, yet */
134       menuColsBeforeScroll = atoi(c_ptr);
135       if (menuColsBeforeScroll <= 0) {
136          sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
137                TOOL_NAME, "MenuColsBeforeScroll", c_ptr, 26);
138          fprintf(stderr, "%s\n", gszMsgBox);
139          menuColsBeforeScroll = 26;
140       }
141    }
142    menu_w = defaultFontWidth;
143    menu_h = defaultFontHeight;
144 
145    mainMenuX = 0;
146    mainMenuY = 0;
147    mainMenuW = menu_w+2*brdrW;
148    mainMenuH = menu_h+2*brdrW;
149 
150    if ((mainMenuWindow=XCreateSimpleWindow(mainDisplay, rootWindow, 0, 0,
151          menu_w, menu_h, brdrW, myBorderPixel, bg_pixel)) == 0) {
152       FailToCreateWindowMessage("InitMainMenu()", NULL, TRUE);
153    }
154    win_attrs.save_under = True;
155    win_attrs.override_redirect = (titledPinnedMenu ? False : True);
156    XChangeWindowAttributes(mainDisplay, mainMenuWindow,
157          CWSaveUnder | CWOverrideRedirect, &win_attrs);
158 
159    XSelectInput(mainDisplay, mainMenuWindow, StructureNotifyMask |
160          ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask |
161          EnterWindowMask | LeaveWindowMask);
162 
163    sizehints.flags = PSize | PMinSize | PMaxSize;
164    sizehints.width = sizehints.min_width = sizehints.max_width =
165          menu_w+2*brdrW;
166    sizehints.height = sizehints.min_height = sizehints.max_height =
167          menu_h+2*brdrW;
168 
169    sizehints.flags |= USPosition | PPosition;
170 #ifdef NOTR4MODE
171    XSetNormalHints(mainDisplay, mainMenuWindow, &sizehints);
172 #else
173    XSetWMNormalHints(mainDisplay, mainMenuWindow, &sizehints);
174 #endif
175 
176    wmhints.flags = InputHint;
177    wmhints.input = True;
178    XSetWMHints(mainDisplay, mainMenuWindow, &wmhints);
179 
180    if (!titledPinnedMenu) {
181       XSetTransientForHint(mainDisplay, mainMenuWindow, mainWindow);
182    }
183    RegisterWM_DELETE_WINDOW(mainMenuWindow);
184    XStoreName(mainDisplay, mainMenuWindow, TgLoadCachedString(CSTID_MAIN_MENU));
185 
186    InitPinnedMenus();
187 }
188 
CleanUpMainMenu()189 void CleanUpMainMenu()
190 {
191    int i;
192 
193    XDestroyWindow(mainDisplay, mainMenuWindow);
194 
195    for (i=0; i < MAXMENUS+1; i++) {
196       if (subMenuInfo[i].win != None) {
197          XDestroyWindow(mainDisplay, subMenuInfo[i].win);
198       }
199       subMenuInfo[i].win = None;
200    }
201 }
202 
203 static int mainMenuMoveDX=0, mainMenuMoveDY=0;
204 
SaveMainWinPosition(x,y)205 void SaveMainWinPosition(x, y)
206    unsigned int x, y;
207 {
208    mainMenuMoveDX = x - savedMainWinX;
209    mainMenuMoveDY = y - savedMainWinY;
210 
211    savedMainWinX = x;
212    savedMainWinY = y;
213 }
214 
MoveMainMenuWindow(x,y)215 void MoveMainMenuWindow(x, y)
216    unsigned int x, y;
217 {
218    mainMenuMoveDX = x - savedMainWinX;
219    mainMenuMoveDY = y - savedMainWinY;
220 
221    if (x == savedMainWinX && y == savedMainWinX) return;
222 
223    mainMenuX += mainMenuMoveDX;
224    mainMenuY += mainMenuMoveDY;
225 
226    /* no need to move the windows */
227    /* XMoveWindow(mainDisplay, mainMenuWindow, mainMenuX, mainMenuY); */
228 
229    savedMainWinX = x;
230    savedMainWinY = y;
231 }
232 
GetPopupXY(win,px,py)233 void GetPopupXY(win, px, py)
234    Window win;
235    int *px, *py;
236 {
237    *px = *py = 0;
238    for (;;) {
239       Window root_win=None, parent_win=None, *child_wins=NULL;
240       unsigned int num_child=0;
241       XWindowAttributes win_attrs;
242 
243       XGetWindowAttributes(mainDisplay, win, &win_attrs);
244       *px += win_attrs.x;
245       *py += win_attrs.y;
246       if (XQueryTree(mainDisplay, win, &root_win,
247             &parent_win, &child_wins, &num_child) == 0) {
248          return;
249       }
250       if (child_wins != NULL) XFree((void*)child_wins);
251       if (parent_win != rootWindow) {
252          win = parent_win;
253       } else {
254          break;
255       }
256    }
257 }
258 
GetPopupWH(win,pw,ph)259 void GetPopupWH(win, pw, ph)
260    Window win;
261    int *pw, *ph;
262 {
263    XWindowAttributes win_attrs;
264 
265    XGetWindowAttributes(mainDisplay, win, &win_attrs);
266    *pw = win_attrs.width;
267    *ph = win_attrs.height;
268 }
269 
270 static char checkExtra[33];
271 
SaveStackingOrder()272 void SaveStackingOrder()
273 {
274    register int i, j;
275    register unsigned char hash_value;
276    Window root_win, parent_win, *child_wins=NULL;
277    unsigned int num_child;
278 
279    for (i=0; i < 33; i++) checkExtra[i] = '\0';
280    if (pinnedMainMenu) {
281       hash_value = mainMenuWindow & 0xff;
282       checkExtra[hash_value>>3] |= (1<<(hash_value&0x7));
283    }
284    for (i = 0; i < numExtraWins; i++) {
285       if (extraWinInfo[i].raise && extraWinInfo[i].mapped &&
286             extraWinInfo[i].window != None) {
287          hash_value = extraWinInfo[i].window & 0xff;
288          checkExtra[hash_value>>3] |= (1<<(hash_value&0x7));
289       }
290    }
291 
292    XQueryTree(mainDisplay, rootWindow, &root_win, &parent_win, &child_wins,
293          &num_child);
294 
295    numStacking = 0;
296    if (stackingWins != NULL) free(stackingWins);
297    stackingWins = (Window*)malloc((numExtraWins+1)*sizeof(Window));
298    if (stackingWins == NULL) FailAllocMessage();
299 
300    for (i = 0; i < num_child; i++) {
301       hash_value = child_wins[i] & 0xff;
302       if (checkExtra[hash_value>>3] & (1<<(hash_value&0x7))) {
303          if (child_wins[i] == mainMenuWindow) {
304             stackingWins[numStacking++] = mainMenuWindow;
305          } else {
306             for (j = 0; j < numExtraWins; j++) {
307                if (extraWinInfo[j].raise && extraWinInfo[j].mapped &&
308                      extraWinInfo[j].window == child_wins[i]) {
309                   stackingWins[numStacking++] = child_wins[i];
310                   break;
311                }
312             }
313          }
314       }
315    }
316    if (child_wins != NULL) XFree((void*)child_wins);
317 }
318 
319 static
RepositionSubMenuWindow(win,menu_index,OrigCursorX,OrigCursorY)320 void RepositionSubMenuWindow(win, menu_index, OrigCursorX, OrigCursorY)
321    Window win;
322    int menu_index, OrigCursorX, OrigCursorY;
323 {
324    int moving=TRUE, x, y, w, h;
325    XEvent input;
326 
327    x = subMenuInfo[menu_index].x;
328    y = subMenuInfo[menu_index].y;
329    w = subMenuInfo[menu_index].w;
330    h = subMenuInfo[menu_index].h;
331 
332    if (!debugNoPointerGrab) {
333       XGrabPointer(mainDisplay, win, FALSE,
334          PointerMotionMask | ButtonReleaseMask,
335          GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
336    }
337    XSetSubwindowMode(mainDisplay, revDefaultGC, IncludeInferiors);
338    XDrawRectangle(mainDisplay, rootWindow, revDefaultGC, x, y, w, h);
339 
340    while (moving) {
341       XNextEvent(mainDisplay, &input);
342 
343       if (input.type == Expose || input.type == VisibilityNotify) {
344          ExposeEventHandler(&input, TRUE);
345       } else if (input.type == ButtonRelease) {
346          XDrawRectangle(mainDisplay, rootWindow, revDefaultGC, x, y, w, h);
347          XSetSubwindowMode(mainDisplay, revDefaultGC, ClipByChildren);
348          XMoveWindow(mainDisplay, win, x, y);
349          XRaiseWindow(mainDisplay, win);
350          subMenuInfo[menu_index].x = x;
351          subMenuInfo[menu_index].y = y;
352 
353          moving = FALSE;
354          XUngrabPointer(mainDisplay, CurrentTime);
355          XDefineCursor(mainDisplay, win, defaultCursor);
356       } else if (input.type == MotionNotify) {
357          XDrawRectangle(mainDisplay, rootWindow, revDefaultGC, x, y, w, h);
358          x = input.xbutton.x_root-OrigCursorX+subMenuInfo[menu_index].x;
359          y = input.xbutton.y_root-OrigCursorY+subMenuInfo[menu_index].y;
360          XDrawRectangle(mainDisplay, rootWindow, revDefaultGC, x, y, w, h);
361       }
362    }
363 }
364 
365 static
TgSubMenuExposeHandler(input,win_info)366 void TgSubMenuExposeHandler(input, win_info)
367    XEvent *input;
368    struct WinInfoRec *win_info;
369 {
370    int menu_index;
371    Window win;
372    XEvent ev;
373 
374    win = input->xany.window;
375    while (XCheckWindowEvent(mainDisplay, win, ExposureMask, &ev));
376    while (XCheckWindowEvent(mainDisplay, win, StructureNotifyMask, &ev));
377 
378    for (menu_index=0; menu_index <= MAXMENUS+1; menu_index++) {
379       if (subMenuInfo[menu_index].win == win && win != None) {
380          TgMenu *menu=(TgMenu*)(win_info->userdata);
381 
382          if (menu != NULL) TgDrawEntireMenu(menu);
383          break;
384       }
385    }
386 }
387 
388 static
ComputeSubMenuWinXY(win,x,y)389 void ComputeSubMenuWinXY(win, x, y)
390    Window win;
391    int *x, *y;
392 {
393    int win_x, win_y, done=FALSE;
394    unsigned int win_w, win_h, win_brdr_w, win_d, num_child;
395    Window root_win, parent_win, *child_wins=NULL;
396 
397    *x = *y = 0;
398    while (!done) {
399       XGetGeometry(mainDisplay, win, &root_win, &win_x, &win_y, &win_w,
400             &win_h, &win_brdr_w, &win_d);
401       *x += win_x;
402       *y += win_y;
403       if (XQueryTree(mainDisplay, win, &root_win, &parent_win, &child_wins,
404             &num_child) == 0) {
405          return;
406       }
407       if (child_wins != NULL) XFree((void*)child_wins);
408       if (parent_win == rootWindow) {
409          done = TRUE;
410       } else {
411          win = parent_win;
412       }
413    }
414 }
415 
416 static
TgUpdateMenuBBox(menu,pn_win_x,pn_win_y)417 void TgUpdateMenuBBox(menu, pn_win_x, pn_win_y)
418    TgMenu *menu;
419    int *pn_win_x, *pn_win_y;
420 {
421    int dx=0, dy=0;
422 
423    ComputeSubMenuWinXY(menu->window, pn_win_x, pn_win_y);
424    dx = (*pn_win_x) - menu->bbox.ltx;
425    dy = (*pn_win_y) - menu->bbox.lty;
426    menu->bbox.ltx += dx; menu->bbox.lty += dy;
427    menu->bbox.rbx += dx; menu->bbox.rby += dy;
428 }
429 
430 static
TgShowPullDownStatus(menu,new_selected)431 void TgShowPullDownStatus(menu, new_selected)
432    TgMenu *menu;
433    int new_selected;
434 {
435    TgMenuItem *menuitems=menu->menuitems;
436 
437    if (menuitems[new_selected].status_str != NULL) {
438       if (!titledPinnedMenu) {
439          SetMouseStatus(TgLoadCachedString(CSTID_MOVE_PINNED_MENU),
440                menuitems[new_selected].status_str,
441                TgLoadCachedString(CSTID_CLOSE_PINNED_MENU));
442       } else {
443          SetMouseStatus(menuitems[new_selected].status_str, "",
444                TgLoadCachedString(CSTID_CLOSE_PINNED_MENU));
445       }
446    }
447 }
448 
449 static
TgPullDownFromSubMenu(menu,new_selected)450 void TgPullDownFromSubMenu(menu, new_selected)
451    TgMenu *menu;
452    int new_selected;
453 {
454    TgMenuItem *menuitems=menu->menuitems;
455    int rc=BAD, last_selected_non_submenu_item=FALSE;
456    XEvent ev;
457 
458    while (rc == BAD || rc == (-3)) {
459       if (new_selected != INVALID &&
460             (menuitems[new_selected].flags & TGMU_DISABLED) == 0) {
461          if ((menuitems[new_selected].flags & TGMU_HAS_SUBMENU) ==
462                TGMU_HAS_SUBMENU &&
463                menuitems[new_selected].submenu_create_info != NULL) {
464             /*
465              * highlight the submenu item, popup the submenu,
466              * and unhighlight it
467              */
468             int win_x=0, win_y=0;
469             TgMenu *submenu=NULL;
470 
471             menuitems[new_selected].state = TGBS_RAISED;
472             TgDrawMenuItem(menu, &menuitems[new_selected]);
473             TgShowPullDownStatus(menu, new_selected);
474 
475             TgUpdateMenuBBox(menu, &win_x, &win_y);
476 
477             submenu = TgCreatePopUpSubMenu(menu, new_selected);
478             if (submenu != NULL) {
479                submenu->track_menubar = FALSE;
480                submenu->track_parent_menu = TRUE;
481 
482                rc = TgPopUpSubMenu(menu, win_x, win_y);
483 
484                submenu = menuitems[new_selected].detail.submenu;
485                if (submenu != NULL) {
486                   TgDestroyMenu(submenu, TRUE);
487                   menuitems[new_selected].detail.submenu = NULL;
488                }
489             }
490             menuitems[menu->selected_index].state = TGBS_NORMAL;
491             TgDrawMenuItem(menu, &menuitems[menu->selected_index]);
492          } else {
493             if (new_selected != last_selected_non_submenu_item) {
494                menuitems[new_selected].state = TGBS_RAISED;
495                TgDrawMenuItem(menu, &menuitems[new_selected]);
496                TgShowPullDownStatus(menu, new_selected);
497                last_selected_non_submenu_item = new_selected;
498             }
499          }
500       }
501       if (rc == BAD || rc == (-3)) {
502          Window root_win, child_win;
503          int mouse_x, mouse_y, root_x, root_y;
504          unsigned int status;
505 
506          XQueryPointer(mainDisplay, menu->window, &root_win, &child_win,
507                &root_x, &root_y, &mouse_x, &mouse_y, &status);
508          new_selected = TgWhichMenuIndex(menu, mouse_x, mouse_y, TRUE);
509          if (!(status & BUTTONSMASK)) {
510             break;
511          }
512          if (!(status & BUTTONSMASK) && !(mouse_x >= 0 && mouse_x <
513                menu->bbox.rbx-menu->bbox.ltx && mouse_y >= 0 &&
514                mouse_y < menu->bbox.rby-menu->bbox.lty)) {
515             break;
516          }
517          if (new_selected != last_selected_non_submenu_item &&
518                last_selected_non_submenu_item != INVALID) {
519             menuitems[last_selected_non_submenu_item].state = TGBS_NORMAL;
520             TgDrawMenuItem(menu, &menuitems[last_selected_non_submenu_item]);
521             last_selected_non_submenu_item = INVALID;
522          }
523          switch (new_selected) {
524          case INVALID: break;
525          case (-2): new_selected = INVALID; break; /* separator */
526          case (-3): new_selected = INVALID; break; /* scrollbar */
527          default: break;
528          }
529          menu->selected_index = new_selected;
530       }
531    }
532    XSync(mainDisplay, False);
533    while (XCheckWindowEvent(mainDisplay, menu->window,
534          ButtonPressMask|ButtonReleaseMask|PointerMotionMask, &ev)) ;
535 }
536 
537 static
MouseInsideWindow(win,win_w,win_h)538 int MouseInsideWindow(win, win_w, win_h)
539    Window win;
540    int win_w, win_h;
541 {
542    Window root_win, child_win;
543    int x, y, root_x, root_y;
544    unsigned int status;
545 
546    XQueryPointer(mainDisplay, win, &root_win, &child_win,
547          &root_x, &root_y, &x, &y, &status);
548    return (x >= 0 && x < win_w && y >=0 && y < win_h);
549 }
550 
551 static
TgSubMenuEventHandler(input,win_info)552 int TgSubMenuEventHandler(input, win_info)
553    XEvent *input;
554    struct WinInfoRec *win_info;
555 {
556    static TgMenu *clicked_menu=NULL;
557    static int clicked_index=INVALID;
558    TgMenu *menu=(TgMenu*)(win_info->userdata);
559    TgMenuItem *menuitems=menu->menuitems;
560    int menu_index=INVALID, new_selected=INVALID, rc=INVALID;
561    int menu_w=menu->bbox.rbx-menu->bbox.ltx+((menu->padding)<<1);
562    int menu_h=menu->bbox.rby-menu->bbox.lty+((menu->padding)<<1);
563    XButtonEvent *button_ev=NULL;
564    XEvent ev;
565    Window win=None;
566 
567    if (input->type == MapNotify || input->type == Expose) {
568       TgSubMenuExposeHandler(input, win_info);
569       clicked_menu = NULL;
570       clicked_index = INVALID;
571       return INVALID;
572    }
573    if (menu == NULL) return INVALID;
574 
575    win = input->xany.window;
576    for (menu_index=0; menu_index <= MAXMENUS; menu_index++) {
577       if (subMenuInfo[menu_index].win == win && win != None) {
578          break;
579       }
580    }
581    if (menu_index > MAXMENUS) return INVALID;
582 
583    if (menu->scroll_start > 0) {
584       switch (menu->type) {
585       case TGMUTYPE_TEXT:
586          menu_w += scrollBarW + menu->padding;
587          menu_h = maxScrollableMenuHeight;
588          break;
589       case TGMUTYPE_COLOR:
590       case TGMUTYPE_BITMAP:
591          menu_w = maxScrollableMenuWidth;
592          menu_h += scrollBarW + menu->padding;
593          break;
594       }
595    }
596    menu->parent_menu = NULL;
597    if (input->type == MotionNotify || input->type == ButtonPress ||
598          input->type == ButtonRelease) {
599       if (!MouseInsideWindow(menu->window, menu_w, menu_h)) {
600          return INVALID;
601       }
602    }
603    if (input->type == ConfigureNotify) {
604       ComputeSubMenuWinXY(win, &(subMenuInfo[menu_index].x),
605             &(subMenuInfo[menu_index].y));
606       clicked_menu = NULL;
607       clicked_index = INVALID;
608    } else if (input->type == EnterNotify) {
609       if (menu->selected_index != INVALID) {
610          menuitems[menu->selected_index].state = TGBS_NORMAL;
611          TgDrawMenuItem(menu, &menuitems[menu->selected_index]);
612       }
613       menu->selected_index = INVALID;
614       clicked_menu = NULL;
615       clicked_index = INVALID;
616       SetStringStatus("");
617    } else if (input->type == LeaveNotify) {
618       if (menu->selected_index != INVALID) {
619          menuitems[menu->selected_index].state = TGBS_NORMAL;
620          TgDrawMenuItem(menu, &menuitems[menu->selected_index]);
621       }
622       clicked_menu = NULL;
623       clicked_index = INVALID;
624       menu->selected_index = INVALID;
625    } else if (input->type == MotionNotify) {
626       while (XCheckWindowEvent(mainDisplay, menu->window,
627             PointerMotionMask, &ev)) ;
628       new_selected = TgWhichMenuIndex(menu, input->xmotion.x, input->xmotion.y,
629             FALSE);
630 
631       if (menu->selected_index != new_selected) {
632          if (menu->selected_index != INVALID) {
633             menuitems[menu->selected_index].state = TGBS_NORMAL;
634             TgDrawMenuItem(menu, &menuitems[menu->selected_index]);
635          }
636          switch (new_selected) {
637          case INVALID: break;
638          case (-2): new_selected = INVALID; break; /* separator */
639          case (-3): new_selected = INVALID; break; /* scrollbar */
640          default: break;
641          }
642          if (new_selected != INVALID) {
643             menuitems[new_selected].state = TGBS_RAISED;
644             TgDrawMenuItem(menu, &menuitems[new_selected]);
645             TgShowPullDownStatus(menu, new_selected);
646          }
647          menu->selected_index = new_selected;
648          if (clicked_menu != NULL && clicked_index != INVALID) {
649             clicked_index = INVALID;
650          }
651       }
652    } else if (input->type == ButtonPress) {
653       button_ev = &(input->xbutton);
654       switch (button_ev->button) {
655       case Button1:
656          if (!titledPinnedMenu) {
657             RepositionSubMenuWindow(win, menu_index, button_ev->x_root,
658                   button_ev->y_root);
659             break;
660          }
661          /* dropping through if titledPinnedMenu ! */
662       case Button2:
663          new_selected = TgWhichMenuIndex(menu, button_ev->x, button_ev->y,
664                FALSE);
665          clicked_menu = menu;
666          clicked_index = (new_selected < 0 ? INVALID : new_selected);
667          if (new_selected != INVALID) {
668             if (menu->selected_index != new_selected) {
669                if (menu->selected_index != INVALID) {
670                   menuitems[menu->selected_index].state = TGBS_NORMAL;
671                   TgDrawMenuItem(menu, &menuitems[menu->selected_index]);
672                }
673                switch (new_selected) {
674                case INVALID: break;
675                case (-2): new_selected = INVALID; break; /* separator */
676                case (-3):
677                   /* scrollbar */
678                   if (menu->scroll_start > 0) {
679                      /* loop to scroll */
680                      ScrollMenu(menu, button_ev->x, button_ev->y, menu_w,
681                            menu_h, (button_ev->button == Button1 ?
682                            Button1Mask : Button2Mask));
683                   }
684                   new_selected = INVALID;
685                   break;
686                default: break;
687                }
688                if (new_selected != INVALID) {
689                   menuitems[new_selected].state = TGBS_RAISED;
690                   TgDrawMenuItem(menu, &menuitems[new_selected]);
691                   TgShowPullDownStatus(menu, new_selected);
692                }
693                menu->selected_index = new_selected;
694             }
695             if (new_selected != INVALID &&
696                   (menuitems[new_selected].flags & TGMU_HAS_SUBMENU) ==
697                   TGMU_HAS_SUBMENU &&
698                   (menuitems[new_selected].flags & TGMU_DISABLED) == 0 &&
699                   menuitems[new_selected].submenu_create_info != NULL) {
700                TgPullDownFromSubMenu(menu, new_selected);
701                clicked_index = INVALID;
702             }
703          }
704          break;
705       case Button3:
706          if (TgWhichMenuIndex(menu, button_ev->x, button_ev->y, FALSE) !=
707                (-3)) {
708             clicked_menu = NULL;
709             clicked_index = INVALID;
710          } else if (!threeDLook && menu->scroll_start > 0) {
711             /* loop to scroll */
712             ScrollMenu(menu, button_ev->x, button_ev->y, menu_w,
713                   menu_h, Button3Mask);
714          }
715          break;
716       }
717    } else if (input->type == ButtonRelease) {
718       button_ev = &(input->xbutton);
719       switch (button_ev->button) {
720       case Button1:
721          if (!titledPinnedMenu) {
722             break;
723          }
724          /* dropping through if titledPinnedMenu ! */
725       case Button2:
726          new_selected = TgWhichMenuIndex(menu, button_ev->x, button_ev->y,
727                FALSE);
728          if (new_selected != INVALID) {
729             if (menu->selected_index != new_selected) {
730                if (menu->selected_index != INVALID) {
731                   menuitems[menu->selected_index].state = TGBS_NORMAL;
732                   TgDrawMenuItem(menu, &menuitems[menu->selected_index]);
733                }
734                switch (new_selected) {
735                case INVALID: break;
736                case (-2): new_selected = INVALID; break; /* separator */
737                case (-3): new_selected = INVALID; break; /* scrollbar */
738                default: break;
739                }
740                if (new_selected != INVALID) {
741                   menuitems[new_selected].state = TGBS_RAISED;
742                   TgDrawMenuItem(menu, &menuitems[new_selected]);
743                   TgShowPullDownStatus(menu, new_selected);
744                }
745                menu->selected_index = new_selected;
746             }
747             if (new_selected != INVALID &&
748                   (menuitems[new_selected].flags & TGMU_HAS_SUBMENU) ==
749                   TGMU_HAS_SUBMENU &&
750                   (menuitems[new_selected].flags & TGMU_DISABLED) == 0 &&
751                   menuitems[new_selected].submenu_create_info != NULL) {
752                TgPullDownFromSubMenu(menu, new_selected);
753                clicked_index = INVALID;
754             } else if (menu->menuitems[new_selected].cmdid != INVALID &&
755                   ((menu->menuitems[new_selected].flags & TGMU_DISABLED) !=
756                   TGMU_DISABLED)) {
757                if (clicked_menu != NULL && clicked_index != INVALID &&
758                      clicked_index == new_selected) {
759                   SendCommandToSelf(menu->menuitems[new_selected].cmdid,
760                         new_selected);
761                }
762             }
763          }
764          break;
765       case Button3:
766          if (TgWhichMenuIndex(menu, button_ev->x, button_ev->y, FALSE) !=
767                (-3)) {
768             if (button_ev->x>=0 && button_ev->x<=subMenuInfo[menu_index].w &&
769                   button_ev->y>=0 && button_ev->y<=subMenuInfo[menu_index].h) {
770                XDestroyWindow(mainDisplay, subMenuInfo[menu_index].win);
771                subMenuInfo[menu_index].win = None;
772                extraWinInfo[subMenuInfo[menu_index].extra_index].window = None;
773                TgDestroyMenu(menu, TRUE);
774                win_info->userdata = NULL;
775             }
776             clicked_menu = NULL;
777             clicked_index = INVALID;
778          }
779          break;
780       }
781    } else if (IsWM_DELETE_WINDOW(input)) {
782       XDestroyWindow(mainDisplay, subMenuInfo[menu_index].win);
783       subMenuInfo[menu_index].win = None;
784       extraWinInfo[subMenuInfo[menu_index].extra_index].window = None;
785       TgDestroyMenu(menu, TRUE);
786       win_info->userdata = NULL;
787       clicked_menu = NULL;
788       clicked_index = INVALID;
789    }
790    return rc;
791 }
792 
793 static
TgSubMenuCleanUp(win_info)794 void TgSubMenuCleanUp(win_info)
795    struct WinInfoRec *win_info;
796 {
797    TgMenu *menu=(TgMenu*)(win_info->userdata);
798 
799    if (menu != NULL) {
800       TgDestroyMenu(menu, TRUE);
801       win_info->userdata = NULL;
802    }
803 }
804 
TgRealizePinnedMenuWindow(menu,win_x,win_y,win_w,win_h)805 Window TgRealizePinnedMenuWindow(menu, win_x, win_y, win_w, win_h)
806    TgMenu *menu;
807    int win_x, win_y, win_w, win_h;
808 {
809    Window win;
810    XWMHints wmhints;
811    XSizeHints sizehints;
812    XSetWindowAttributes win_attrs;
813    TgMenu *dup_menu=NULL;
814    int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
815    TgMenuItemInfo *item_info=NULL;
816 
817    win_w -= (brdrW<<1);
818    win_h -= (brdrW<<1);
819 
820    if ((win=XCreateSimpleWindow(mainDisplay, rootWindow, win_x, win_y,
821          win_w, win_h, brdrW, myBorderPixel, bg_pixel)) == 0) {
822       FailToCreateWindowMessage("TgRealizePinnedMenuWindow()", NULL, TRUE);
823    }
824    XDefineCursor(mainDisplay, win, defaultCursor);
825 
826    win_attrs.save_under = True;
827    win_attrs.override_redirect = (titledPinnedMenu ? False : True);
828    win_attrs.colormap = mainColormap;
829    XChangeWindowAttributes(mainDisplay, win,
830          CWSaveUnder | CWOverrideRedirect | CWColormap, &win_attrs);
831 
832    if (!titledPinnedMenu) {
833       XSetTransientForHint(mainDisplay, win, mainWindow);
834    }
835    if (activeMenu == MENU_MAIN) {
836       XStoreName(mainDisplay, win, TgLoadCachedString(CSTID_MAIN_MENU));
837    } else {
838       for (item_info=mainMenuInfo.items; item_info->menu_str != NULL;
839             item_info++) {
840          if (item_info->menu_str != TGMUITEM_SEPARATOR &&
841                item_info->cmdid == activeMenu) {
842             XStoreName(mainDisplay, win, item_info->status_str);
843             break;
844          }
845       }
846    }
847    sizehints.flags = PSize | PMinSize | PMaxSize;
848    sizehints.width = sizehints.min_width = sizehints.max_width = win_w;
849    sizehints.height = sizehints.min_height = sizehints.max_height = win_h;
850 
851    sizehints.flags |= USPosition | PPosition;
852 #ifdef NOTR4MODE
853    XSetNormalHints(mainDisplay, win, &sizehints);
854 #else
855    XSetWMNormalHints(mainDisplay, win, &sizehints);
856 #endif
857 
858    wmhints.flags = InputHint;
859    wmhints.input = True;
860    XSetWMHints(mainDisplay, win, &wmhints);
861 
862    RegisterWM_DELETE_WINDOW(win);
863 
864 #ifdef MAPBEFORESELECT
865    XMapWindow(mainDisplay, win);
866    XSelectInput(mainDisplay, win, StructureNotifyMask |
867          ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask |
868          EnterWindowMask | LeaveWindowMask | PointerMotionMask);
869 #else
870    XSelectInput(mainDisplay, win, StructureNotifyMask |
871          ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask |
872          EnterWindowMask | LeaveWindowMask | PointerMotionMask);
873    XMapWindow(mainDisplay, win);
874 #endif
875 
876    if (subMenuInfo[activeMenu].win != None) {
877       int extra_index=subMenuInfo[activeMenu].extra_index;
878 
879       XDestroyWindow(mainDisplay, subMenuInfo[activeMenu].win);
880       extraWinInfo[extra_index].window = None;
881       TgDestroyMenu(menu, FALSE);
882       dup_menu = (TgMenu*)(extraWinInfo[extra_index].userdata);
883    } else {
884       if ((dup_menu=(TgMenu*)malloc(sizeof(TgMenu))) == NULL) {
885          FailAllocMessage();
886       }
887       memcpy(dup_menu, menu, sizeof(TgMenu));
888    }
889    dup_menu->window = win;
890    subMenuInfo[activeMenu].extra_index =
891          AddExtraWinInfo(win, TRUE, TRUE, TgSubMenuExposeHandler,
892          TgSubMenuEventHandler, TgSubMenuCleanUp, dup_menu);
893 
894    subMenuInfo[activeMenu].x = win_x;
895    subMenuInfo[activeMenu].y = win_y;
896    subMenuInfo[activeMenu].w = win_w;
897    subMenuInfo[activeMenu].h = win_h;
898    subMenuInfo[activeMenu].win = win;
899 
900    XDestroyWindow(mainDisplay, menu->window);
901    menu->window = None;
902    memset(menu, 0, sizeof(TgMenu));
903 
904    return win;
905 }
906 
TgWindowIsPinnedMenu(win,menu_index)907 int TgWindowIsPinnedMenu(win, menu_index)
908    Window win;
909    int menu_index;
910 {
911    return (subMenuInfo[menu_index].win != None &&
912          subMenuInfo[menu_index].win == win);
913 }
914 
TgHandlePinnedMenuEvent(win,menu_index,input)915 int TgHandlePinnedMenuEvent(win, menu_index, input)
916    Window win;
917    int menu_index;
918    XEvent *input;
919 {
920    if (TgWindowIsPinnedMenu(win, menu_index)) {
921       int extra_win_info_index=subMenuInfo[menu_index].extra_index;
922 
923       return (*(extraWinInfo[extra_win_info_index].ev_handler))(
924             input, &extraWinInfo[extra_win_info_index]);
925    }
926    return INVALID;
927 }
928 
UpdatePinnedMenu(menu_index)929 void UpdatePinnedMenu(menu_index)
930    int menu_index;
931 {
932    Window win=subMenuInfo[menu_index].win;
933 
934    if (win != None) {
935       int extra_win_info_index=subMenuInfo[menu_index].extra_index;
936 
937       if (extra_win_info_index >= 0 && extra_win_info_index < numExtraWins &&
938             extraWinInfo[extra_win_info_index].window == win) {
939          TgMenu *menu=(TgMenu*)(extraWinInfo[extra_win_info_index].userdata);
940 
941          if (menu != NULL) {
942             switch (menu_index) {
943             case MENU_FILE: RefreshFileMenu(menu); break;
944             case MENU_EDIT: RefreshEditMenu(menu); break;
945             case MENU_LAYOUT: RefreshLayoutMenu(menu); break;
946             case MENU_ARRANGE: RefreshArrangeMenu(menu); break;
947             case MENU_PROPERTIES: RefreshPropertiesMenu(menu); break;
948 
949             case MENU_MOVEMODE: RefreshMoveModeMenu(menu); break;
950             case MENU_HORIALIGN: RefreshHoriAlignMenu(menu); break;
951             case MENU_VERTALIGN: RefreshVertAlignMenu(menu); break;
952             case MENU_FONT: RefreshFontMenu(menu); break;
953             case MENU_STYLE: RefreshFontStyleMenu(menu); break;
954             case MENU_SIZE: RefreshFontSizeMenu(menu); break;
955             case MENU_SHAPE: RefreshShapeMenu(menu); break;
956             case MENU_STRETCHTEXT: RefreshStretchableTextModeMenu(menu); break;
957             case MENU_TRANSPAT: RefreshTransPatModeMenu(menu); break;
958 
959             case MENU_LINEWIDTH: RefreshLineWidthMenu(menu); break;
960             case MENU_LINESTYLE: RefreshLineStyleMenu(menu); break;
961             case MENU_LINETYPE: RefreshLineTypeMenu(menu); break;
962             case MENU_LINEDASH: RefreshLineDashMenu(menu); break;
963             case MENU_FILL: RefreshFillMenu(menu); break;
964             case MENU_PEN: RefreshPenMenu(menu); break;
965 
966             case MENU_COLOR: RefreshColorMenu(menu); break;
967 
968             case MENU_IMAGEPROC: RefreshImageProcMenu(menu); break;
969             case MENU_NAVIGATE: RefreshNavigateMenu(menu); break;
970             case MENU_SPECIAL: RefreshSpecialMenu(menu); break;
971             case MENU_PAGE: RefreshPageMenu(menu); break;
972             case MENU_PAGELAYOUT: RefreshPageLayoutMenu(menu); break;
973             case MENU_HELP: RefreshHelpMenu(menu); break;
974             case MENU_TANGRAM2:
975                if (cmdLineTgrm2) {
976                   RefreshTangram2Menu(menu);
977                }
978                break;
979 
980             case MENU_MODE: RefreshModeMenu(menu); break;
981 
982             case MENU_MAIN: RefreshMainMenu(menu); break;
983             }
984             TgDrawEntireMenu(menu);
985             return;
986          }
987       }
988    }
989 }
990 
UpdateAllPinnedMenus()991 void UpdateAllPinnedMenus()
992 {
993    UpdatePinnedMenu(MENU_HORIALIGN);
994    UpdatePinnedMenu(MENU_VERTALIGN);
995    UpdatePinnedMenu(MENU_STYLE);
996    UpdatePinnedMenu(MENU_FONT);
997    UpdatePinnedMenu(MENU_SIZE);
998    UpdatePinnedMenu(MENU_LINEWIDTH);
999    UpdatePinnedMenu(MENU_LINESTYLE);
1000    UpdatePinnedMenu(MENU_LINETYPE);
1001    UpdatePinnedMenu(MENU_LINEDASH);
1002    UpdatePinnedMenu(MENU_LAYOUT);
1003    UpdatePinnedMenu(MENU_MOVEMODE);
1004    UpdatePinnedMenu(MENU_STRETCHTEXT);
1005    UpdatePinnedMenu(MENU_TRANSPAT);
1006    UpdatePinnedMenu(MENU_PAGELAYOUT);
1007 
1008    UpdatePinnedMenu(MENU_MAIN);
1009 }
1010 
UseWireMenuItemInModeItem(connecting)1011 void UseWireMenuItemInModeItem(connecting)
1012    int connecting;
1013 {
1014    Window win=subMenuInfo[MENU_MODE].win;
1015 
1016    if (win != None) {
1017       int extra_win_info_index=subMenuInfo[MENU_MODE].extra_index;
1018 
1019       if (extra_win_info_index >= 0 && extra_win_info_index < numExtraWins &&
1020             extraWinInfo[extra_win_info_index].window == win) {
1021          TgMenu *menu=(TgMenu*)(extraWinInfo[extra_win_info_index].userdata);
1022 
1023          if (menu != NULL) {
1024             TgMenuItem stMenuItem;
1025 
1026             memset(&stMenuItem, 0, sizeof(TgMenuItem));
1027             if (connecting) {
1028                stMenuItem.menu_str = (char*)(&wireBitmap);
1029             } else {
1030                stMenuItem.menu_str = (char*)(&choicePixmap[DRAWPOLY]);
1031             }
1032             if (!TgSetMenuItemInfo(&menu->menuitems[DRAWPOLY],
1033                   TGMU_MASK_MENUSTR, &stMenuItem)) {
1034             }
1035             return;
1036          }
1037       }
1038    }
1039 }
1040 
DestroyPinnedMenu(menu_index)1041 void DestroyPinnedMenu(menu_index)
1042    int menu_index;
1043 {
1044    if (subMenuInfo[menu_index].win != None) {
1045       int extra_index=subMenuInfo[menu_index].extra_index;
1046       TgMenu *menu=(TgMenu*)(extraWinInfo[extra_index].userdata);
1047 
1048       XDestroyWindow(mainDisplay, subMenuInfo[menu_index].win);
1049       subMenuInfo[menu_index].win = None;
1050       extraWinInfo[extra_index].window = None;
1051       if (menu != NULL) {
1052          TgDestroyMenu(menu, TRUE);
1053          extraWinInfo[extra_index].userdata = NULL;
1054       }
1055    }
1056 }
1057 
1058 static IntPoint gaPopupCoords[MAXMENUS+5];
1059 
HidePopupMenusForSlideShow()1060 void HidePopupMenusForSlideShow()
1061 {
1062    int adj_caches=(zoomScale!=0 || zoomedIn!=FALSE);
1063    int menu_index=0, draw_win_x=0, draw_win_y=0, draw_win_w=0, draw_win_h=0;
1064    int dpy_w=DisplayWidth(mainDisplay,mainScreen);
1065    int dpy_h=DisplayHeight(mainDisplay,mainScreen);
1066 
1067    for (menu_index=0; menu_index <= MAXMENUS; menu_index++) {
1068       if (subMenuInfo[menu_index].win != None) {
1069          GetPopupXY(subMenuInfo[menu_index].win,
1070                &gaPopupCoords[menu_index].x, &gaPopupCoords[menu_index].y);
1071          XMoveWindow(mainDisplay, subMenuInfo[menu_index].win, -dpy_w, -dpy_h);
1072       }
1073    }
1074    GetPopupXY(drawWindow, &draw_win_x, &draw_win_y);
1075    GetPopupWH(drawWindow, &draw_win_w, &draw_win_h);
1076 
1077    GetPopupXY(mainWindow, &gaPopupCoords[MAXMENUS+1].x,
1078          &gaPopupCoords[MAXMENUS+1].y);
1079    GetPopupWH(mainWindow, &gaPopupCoords[MAXMENUS+2].x,
1080          &gaPopupCoords[MAXMENUS+2].y);
1081    gaPopupCoords[MAXMENUS+3].x = drawOrigX;
1082    gaPopupCoords[MAXMENUS+3].y = drawOrigY;
1083    gaPopupCoords[MAXMENUS+4].x = zoomedIn;
1084    gaPopupCoords[MAXMENUS+4].y = zoomScale;
1085 
1086    if (gaPopupCoords[MAXMENUS+3].x != 0 || gaPopupCoords[MAXMENUS+3].y != 0 ||
1087          adj_caches) {
1088       drawOrigX = drawOrigY = 0;
1089       zoomedIn = FALSE;
1090       zoomScale = 0;
1091 
1092       UpdDrawWinWH();
1093       UpdDrawWinBBox();
1094       ClearObjCachesInAllPages();
1095       if (adj_caches) { ShowZoom(); }
1096    }
1097 #ifndef NOKDE3BUG
1098    XMoveResizeWindow(mainDisplay, mainWindow, 0, 0,
1099          dpy_w+gaPopupCoords[MAXMENUS+2].x-draw_win_w+2,
1100          dpy_h+gaPopupCoords[MAXMENUS+2].y-draw_win_h+2);
1101 #endif /* ~NOKDE3BUG */
1102    XMoveResizeWindow(mainDisplay, mainWindow,
1103          gaPopupCoords[MAXMENUS+1].x-draw_win_x-1,
1104          gaPopupCoords[MAXMENUS+1].y-draw_win_y-1,
1105          dpy_w+gaPopupCoords[MAXMENUS+2].x-draw_win_w+2,
1106          dpy_h+gaPopupCoords[MAXMENUS+2].y-draw_win_h+2);
1107 }
1108 
ShowPopupMenusForSlideShow()1109 void ShowPopupMenusForSlideShow()
1110 {
1111    int menu_index=0;
1112 
1113    zoomScale = gaPopupCoords[MAXMENUS+4].y;
1114    zoomScale = gaPopupCoords[MAXMENUS+4].y;
1115    drawOrigX = gaPopupCoords[MAXMENUS+3].x;
1116    drawOrigY = gaPopupCoords[MAXMENUS+3].y;
1117    drawWinW = gaPopupCoords[MAXMENUS+2].x;
1118    drawWinH = gaPopupCoords[MAXMENUS+2].y;
1119    XMoveResizeWindow(mainDisplay, mainWindow,
1120          gaPopupCoords[MAXMENUS+1].x, gaPopupCoords[MAXMENUS+1].y,
1121          gaPopupCoords[MAXMENUS+2].x, gaPopupCoords[MAXMENUS+2].y);
1122    InitWinSizes();
1123    for (menu_index=0; menu_index <= MAXMENUS; menu_index++) {
1124       if (subMenuInfo[menu_index].win != None) {
1125          XMoveWindow(mainDisplay, subMenuInfo[menu_index].win,
1126                gaPopupCoords[menu_index].x, gaPopupCoords[menu_index].y);
1127          UpdatePinnedMenu(menu_index);
1128       }
1129    }
1130 }
1131 
EnumPopupMenuWindow(pFunc,pUserData)1132 void EnumPopupMenuWindow(pFunc, pUserData)
1133    ENUMPOPUPMENUFN *pFunc;
1134    void *pUserData;
1135 {
1136    int menu_index=0;
1137 
1138    for (menu_index=0; menu_index <= MAXMENUS; menu_index++) {
1139       if (subMenuInfo[menu_index].win != None) {
1140          if (!((pFunc)(menu_index, subMenuInfo[menu_index].win, pUserData))) {
1141             break;
1142          }
1143       }
1144    }
1145 }
1146