/[dtapublic]/projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkmenudraw.c
ViewVC logotype

Diff of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkmenudraw.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkMenuDraw.c --   * tkMenuDraw.c --
5   *   *
6   *      This module implements the platform-independent drawing and   *      This module implements the platform-independent drawing and
7   *      geometry calculations of menu widgets.   *      geometry calculations of menu widgets.
8   *   *
9   * Copyright (c) 1996-1997 by Sun Microsystems, Inc.   * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
10   *   *
11   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
12   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13   *   *
14   * RCS: @(#) $Id: tkmenudraw.c,v 1.1.1.1 2001/06/13 05:06:08 dtashley Exp $   * RCS: @(#) $Id: tkmenudraw.c,v 1.1.1.1 2001/06/13 05:06:08 dtashley Exp $
15   */   */
16    
17  #include "tkMenu.h"  #include "tkMenu.h"
18    
19  /*  /*
20   * Forward declarations for procedures defined later in this file:   * Forward declarations for procedures defined later in this file:
21   */   */
22    
23  static void             AdjustMenuCoords _ANSI_ARGS_ ((TkMenu *menuPtr,  static void             AdjustMenuCoords _ANSI_ARGS_ ((TkMenu *menuPtr,
24                              TkMenuEntry *mePtr, int *xPtr, int *yPtr,                              TkMenuEntry *mePtr, int *xPtr, int *yPtr,
25                              char *string));                              char *string));
26  static void             ComputeMenuGeometry _ANSI_ARGS_((  static void             ComputeMenuGeometry _ANSI_ARGS_((
27                              ClientData clientData));                              ClientData clientData));
28  static void             DisplayMenu _ANSI_ARGS_((ClientData clientData));  static void             DisplayMenu _ANSI_ARGS_((ClientData clientData));
29    
30  /*  /*
31   *----------------------------------------------------------------------   *----------------------------------------------------------------------
32   *   *
33   * TkMenuInitializeDrawingFields --   * TkMenuInitializeDrawingFields --
34   *   *
35   *      Fills in drawing fields of a new menu. Called when new menu is   *      Fills in drawing fields of a new menu. Called when new menu is
36   *      created by MenuCmd.   *      created by MenuCmd.
37   *   *
38   * Results:   * Results:
39   *      None.   *      None.
40   *   *
41   * Side effects:   * Side effects:
42   *      menuPtr fields are initialized.   *      menuPtr fields are initialized.
43   *   *
44   *----------------------------------------------------------------------   *----------------------------------------------------------------------
45   */   */
46    
47  void  void
48  TkMenuInitializeDrawingFields(menuPtr)  TkMenuInitializeDrawingFields(menuPtr)
49      TkMenu *menuPtr;            /* The menu we are initializing. */      TkMenu *menuPtr;            /* The menu we are initializing. */
50  {  {
51      menuPtr->textGC = None;      menuPtr->textGC = None;
52      menuPtr->gray = None;      menuPtr->gray = None;
53      menuPtr->disabledGC = None;      menuPtr->disabledGC = None;
54      menuPtr->activeGC = None;      menuPtr->activeGC = None;
55      menuPtr->indicatorGC = None;      menuPtr->indicatorGC = None;
56      menuPtr->disabledImageGC = None;      menuPtr->disabledImageGC = None;
57      menuPtr->totalWidth = menuPtr->totalHeight = 0;      menuPtr->totalWidth = menuPtr->totalHeight = 0;
58  }  }
59    
60  /*  /*
61   *----------------------------------------------------------------------   *----------------------------------------------------------------------
62   *   *
63   * TkMenuInitializeEntryDrawingFields --   * TkMenuInitializeEntryDrawingFields --
64   *   *
65   *      Fills in drawing fields of a new menu entry. Called when an   *      Fills in drawing fields of a new menu entry. Called when an
66   *      entry is created.   *      entry is created.
67   *   *
68   * Results:   * Results:
69   *      None.   *      None.
70   *   *
71   * Side effects:   * Side effects:
72   *      None.   *      None.
73   *   *
74   *----------------------------------------------------------------------   *----------------------------------------------------------------------
75   */   */
76    
77  void  void
78  TkMenuInitializeEntryDrawingFields(mePtr)  TkMenuInitializeEntryDrawingFields(mePtr)
79      TkMenuEntry *mePtr;         /* The menu we are initializing. */      TkMenuEntry *mePtr;         /* The menu we are initializing. */
80  {  {
81      mePtr->width = 0;      mePtr->width = 0;
82      mePtr->height = 0;      mePtr->height = 0;
83      mePtr->x = 0;      mePtr->x = 0;
84      mePtr->y = 0;      mePtr->y = 0;
85      mePtr->indicatorSpace = 0;      mePtr->indicatorSpace = 0;
86      mePtr->labelWidth = 0;      mePtr->labelWidth = 0;
87      mePtr->textGC = None;      mePtr->textGC = None;
88      mePtr->activeGC = None;      mePtr->activeGC = None;
89      mePtr->disabledGC = None;      mePtr->disabledGC = None;
90      mePtr->indicatorGC = None;      mePtr->indicatorGC = None;
91  }  }
92    
93  /*  /*
94   *----------------------------------------------------------------------   *----------------------------------------------------------------------
95   *   *
96   * TkMenuFreeDrawOptions --   * TkMenuFreeDrawOptions --
97   *   *
98   *      Frees up any structures allocated for the drawing of a menu.   *      Frees up any structures allocated for the drawing of a menu.
99   *      Called when menu is deleted.   *      Called when menu is deleted.
100   *   *
101   * Results:   * Results:
102   *      None.   *      None.
103   *   *
104   * Side effects:   * Side effects:
105   *      Storage is released.   *      Storage is released.
106   *   *
107   *----------------------------------------------------------------------   *----------------------------------------------------------------------
108   */   */
109    
110  void  void
111  TkMenuFreeDrawOptions(menuPtr)  TkMenuFreeDrawOptions(menuPtr)
112      TkMenu *menuPtr;      TkMenu *menuPtr;
113  {  {
114      if (menuPtr->textGC != None) {      if (menuPtr->textGC != None) {
115          Tk_FreeGC(menuPtr->display, menuPtr->textGC);          Tk_FreeGC(menuPtr->display, menuPtr->textGC);
116      }      }
117      if (menuPtr->disabledImageGC != None) {      if (menuPtr->disabledImageGC != None) {
118          Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);          Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
119      }      }
120      if (menuPtr->gray != None) {      if (menuPtr->gray != None) {
121          Tk_FreeBitmap(menuPtr->display, menuPtr->gray);          Tk_FreeBitmap(menuPtr->display, menuPtr->gray);
122      }      }
123      if (menuPtr->disabledGC != None) {      if (menuPtr->disabledGC != None) {
124          Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);          Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
125      }      }
126      if (menuPtr->activeGC != None) {      if (menuPtr->activeGC != None) {
127          Tk_FreeGC(menuPtr->display, menuPtr->activeGC);          Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
128      }      }
129      if (menuPtr->indicatorGC != None) {      if (menuPtr->indicatorGC != None) {
130          Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);          Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
131      }      }
132  }  }
133    
134  /*  /*
135   *----------------------------------------------------------------------   *----------------------------------------------------------------------
136   *   *
137   * TkMenuEntryFreeDrawOptions --   * TkMenuEntryFreeDrawOptions --
138   *   *
139   *      Frees up drawing structures for a menu entry. Called when   *      Frees up drawing structures for a menu entry. Called when
140   *      menu entry is freed.   *      menu entry is freed.
141   *   *
142   * RESULTS:   * RESULTS:
143   *      None.   *      None.
144   *   *
145   * Side effects:   * Side effects:
146   *      Storage is freed.   *      Storage is freed.
147   *   *
148   *----------------------------------------------------------------------   *----------------------------------------------------------------------
149   */   */
150    
151  void  void
152  TkMenuEntryFreeDrawOptions(mePtr)  TkMenuEntryFreeDrawOptions(mePtr)
153      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
154  {  {
155      if (mePtr->textGC != None) {      if (mePtr->textGC != None) {
156          Tk_FreeGC(mePtr->menuPtr->display, mePtr->textGC);          Tk_FreeGC(mePtr->menuPtr->display, mePtr->textGC);
157      }      }
158      if (mePtr->disabledGC != None) {      if (mePtr->disabledGC != None) {
159          Tk_FreeGC(mePtr->menuPtr->display, mePtr->disabledGC);          Tk_FreeGC(mePtr->menuPtr->display, mePtr->disabledGC);
160      }      }
161      if (mePtr->activeGC != None) {      if (mePtr->activeGC != None) {
162          Tk_FreeGC(mePtr->menuPtr->display, mePtr->activeGC);          Tk_FreeGC(mePtr->menuPtr->display, mePtr->activeGC);
163      }      }
164      if (mePtr->indicatorGC != None) {      if (mePtr->indicatorGC != None) {
165          Tk_FreeGC(mePtr->menuPtr->display, mePtr->indicatorGC);          Tk_FreeGC(mePtr->menuPtr->display, mePtr->indicatorGC);
166      }      }
167  }  }
168    
169  /*  /*
170   *----------------------------------------------------------------------   *----------------------------------------------------------------------
171   *   *
172   * TkMenuConfigureDrawOptions --   * TkMenuConfigureDrawOptions --
173   *   *
174   *      Sets the menu's drawing attributes in preparation for drawing   *      Sets the menu's drawing attributes in preparation for drawing
175   *      the menu.   *      the menu.
176   *   *
177   * RESULTS:   * RESULTS:
178   *      None.   *      None.
179   *   *
180   * Side effects:   * Side effects:
181   *      Storage is allocated.   *      Storage is allocated.
182   *   *
183   *----------------------------------------------------------------------   *----------------------------------------------------------------------
184   */   */
185    
186  void  void
187  TkMenuConfigureDrawOptions(menuPtr)  TkMenuConfigureDrawOptions(menuPtr)
188      TkMenu *menuPtr;            /* The menu we are configuring. */      TkMenu *menuPtr;            /* The menu we are configuring. */
189  {  {
190      XGCValues gcValues;      XGCValues gcValues;
191      GC newGC;      GC newGC;
192      unsigned long mask;      unsigned long mask;
193      Tk_3DBorder border, activeBorder;      Tk_3DBorder border, activeBorder;
194      Tk_Font tkfont;      Tk_Font tkfont;
195      XColor *fg, *activeFg, *indicatorFg;      XColor *fg, *activeFg, *indicatorFg;
196    
197      /*      /*
198       * A few options need special processing, such as setting the       * A few options need special processing, such as setting the
199       * background from a 3-D border, or filling in complicated       * background from a 3-D border, or filling in complicated
200       * defaults that couldn't be specified to Tk_ConfigureWidget.       * defaults that couldn't be specified to Tk_ConfigureWidget.
201       */       */
202    
203      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
204      Tk_SetBackgroundFromBorder(menuPtr->tkwin, border);      Tk_SetBackgroundFromBorder(menuPtr->tkwin, border);
205    
206      tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);      tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
207      gcValues.font = Tk_FontId(tkfont);      gcValues.font = Tk_FontId(tkfont);
208      fg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->fgPtr);      fg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->fgPtr);
209      gcValues.foreground = fg->pixel;      gcValues.foreground = fg->pixel;
210      gcValues.background = Tk_3DBorderColor(border)->pixel;      gcValues.background = Tk_3DBorderColor(border)->pixel;
211      newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,      newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
212              &gcValues);              &gcValues);
213      if (menuPtr->textGC != None) {      if (menuPtr->textGC != None) {
214          Tk_FreeGC(menuPtr->display, menuPtr->textGC);          Tk_FreeGC(menuPtr->display, menuPtr->textGC);
215      }      }
216      menuPtr->textGC = newGC;      menuPtr->textGC = newGC;
217    
218      gcValues.font = Tk_FontId(tkfont);      gcValues.font = Tk_FontId(tkfont);
219      gcValues.background = Tk_3DBorderColor(border)->pixel;      gcValues.background = Tk_3DBorderColor(border)->pixel;
220      if (menuPtr->disabledFgPtr != NULL) {      if (menuPtr->disabledFgPtr != NULL) {
221          XColor *disabledFg;          XColor *disabledFg;
222    
223          disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,          disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
224                  menuPtr->disabledFgPtr);                  menuPtr->disabledFgPtr);
225          gcValues.foreground = disabledFg->pixel;          gcValues.foreground = disabledFg->pixel;
226          mask = GCForeground|GCBackground|GCFont;          mask = GCForeground|GCBackground|GCFont;
227      } else {      } else {
228          gcValues.foreground = gcValues.background;          gcValues.foreground = gcValues.background;
229          mask = GCForeground;          mask = GCForeground;
230          if (menuPtr->gray == None) {          if (menuPtr->gray == None) {
231              menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,              menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,
232                      "gray50");                      "gray50");
233          }          }
234          if (menuPtr->gray != None) {          if (menuPtr->gray != None) {
235              gcValues.fill_style = FillStippled;              gcValues.fill_style = FillStippled;
236              gcValues.stipple = menuPtr->gray;              gcValues.stipple = menuPtr->gray;
237              mask = GCForeground|GCFillStyle|GCStipple;              mask = GCForeground|GCFillStyle|GCStipple;
238          }          }
239      }      }
240      newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);      newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
241      if (menuPtr->disabledGC != None) {      if (menuPtr->disabledGC != None) {
242          Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);          Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
243      }      }
244      menuPtr->disabledGC = newGC;      menuPtr->disabledGC = newGC;
245    
246      gcValues.foreground = Tk_3DBorderColor(border)->pixel;      gcValues.foreground = Tk_3DBorderColor(border)->pixel;
247      if (menuPtr->gray == None) {      if (menuPtr->gray == None) {
248          menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,          menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,
249                  "gray50");                  "gray50");
250      }      }
251      if (menuPtr->gray != None) {      if (menuPtr->gray != None) {
252          gcValues.fill_style = FillStippled;          gcValues.fill_style = FillStippled;
253          gcValues.stipple = menuPtr->gray;          gcValues.stipple = menuPtr->gray;
254          newGC = Tk_GetGC(menuPtr->tkwin,          newGC = Tk_GetGC(menuPtr->tkwin,
255              GCForeground|GCFillStyle|GCStipple, &gcValues);              GCForeground|GCFillStyle|GCStipple, &gcValues);
256      }      }
257      if (menuPtr->disabledImageGC != None) {      if (menuPtr->disabledImageGC != None) {
258          Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);          Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
259      }      }
260      menuPtr->disabledImageGC = newGC;      menuPtr->disabledImageGC = newGC;
261    
262      gcValues.font = Tk_FontId(tkfont);      gcValues.font = Tk_FontId(tkfont);
263      activeFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->activeFgPtr);      activeFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->activeFgPtr);
264      gcValues.foreground = activeFg->pixel;      gcValues.foreground = activeFg->pixel;
265      activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,      activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
266              menuPtr->activeBorderPtr);              menuPtr->activeBorderPtr);
267      gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;      gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;
268      newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,      newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
269              &gcValues);              &gcValues);
270      if (menuPtr->activeGC != None) {      if (menuPtr->activeGC != None) {
271          Tk_FreeGC(menuPtr->display, menuPtr->activeGC);          Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
272      }      }
273      menuPtr->activeGC = newGC;      menuPtr->activeGC = newGC;
274    
275      indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,      indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,
276              menuPtr->indicatorFgPtr);              menuPtr->indicatorFgPtr);
277      gcValues.foreground = indicatorFg->pixel;      gcValues.foreground = indicatorFg->pixel;
278      gcValues.background = Tk_3DBorderColor(border)->pixel;      gcValues.background = Tk_3DBorderColor(border)->pixel;
279      newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,      newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
280              &gcValues);              &gcValues);
281      if (menuPtr->indicatorGC != None) {      if (menuPtr->indicatorGC != None) {
282          Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);          Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
283      }      }
284      menuPtr->indicatorGC = newGC;      menuPtr->indicatorGC = newGC;
285  }  }
286    
287  /*  /*
288   *----------------------------------------------------------------------   *----------------------------------------------------------------------
289   *   *
290   * TkMenuConfigureEntryDrawOptions --   * TkMenuConfigureEntryDrawOptions --
291   *   *
292   *      Calculates any entry-specific draw options for the given menu   *      Calculates any entry-specific draw options for the given menu
293   *      entry.   *      entry.
294   *   *
295   * Results:   * Results:
296   *      Returns a standard Tcl error.   *      Returns a standard Tcl error.
297   *   *
298   * Side effects:   * Side effects:
299   *      Storage may be allocated.   *      Storage may be allocated.
300   *   *
301   *----------------------------------------------------------------------   *----------------------------------------------------------------------
302   */   */
303    
304  int  int
305  TkMenuConfigureEntryDrawOptions(mePtr, index)  TkMenuConfigureEntryDrawOptions(mePtr, index)
306      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
307      int index;      int index;
308  {  {
309    
310      XGCValues gcValues;      XGCValues gcValues;
311      GC newGC, newActiveGC, newDisabledGC, newIndicatorGC;      GC newGC, newActiveGC, newDisabledGC, newIndicatorGC;
312      unsigned long mask;      unsigned long mask;
313      Tk_Font tkfont;      Tk_Font tkfont;
314      TkMenu *menuPtr = mePtr->menuPtr;      TkMenu *menuPtr = mePtr->menuPtr;
315    
316      tkfont = Tk_GetFontFromObj(menuPtr->tkwin,      tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
317              (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr);              (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr);
318            
319      if (mePtr->state == ENTRY_ACTIVE) {      if (mePtr->state == ENTRY_ACTIVE) {
320          if (index != menuPtr->active) {          if (index != menuPtr->active) {
321              TkActivateMenuEntry(menuPtr, index);              TkActivateMenuEntry(menuPtr, index);
322          }          }
323      } else {      } else {
324          if (index == menuPtr->active) {          if (index == menuPtr->active) {
325              TkActivateMenuEntry(menuPtr, -1);              TkActivateMenuEntry(menuPtr, -1);
326          }          }
327      }      }
328    
329      if ((mePtr->fontPtr != NULL)      if ((mePtr->fontPtr != NULL)
330              || (mePtr->borderPtr != NULL)              || (mePtr->borderPtr != NULL)
331              || (mePtr->fgPtr != NULL)              || (mePtr->fgPtr != NULL)
332              || (mePtr->activeBorderPtr != NULL)              || (mePtr->activeBorderPtr != NULL)
333              || (mePtr->activeFgPtr != NULL)              || (mePtr->activeFgPtr != NULL)
334              || (mePtr->indicatorFgPtr != NULL)) {              || (mePtr->indicatorFgPtr != NULL)) {
335          XColor *fg, *indicatorFg, *activeFg;          XColor *fg, *indicatorFg, *activeFg;
336          Tk_3DBorder border, activeBorder;          Tk_3DBorder border, activeBorder;
337            
338          fg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->fgPtr != NULL)          fg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->fgPtr != NULL)
339                  ? mePtr->fgPtr : menuPtr->fgPtr);                  ? mePtr->fgPtr : menuPtr->fgPtr);
340          gcValues.foreground = fg->pixel;          gcValues.foreground = fg->pixel;
341          border = Tk_Get3DBorderFromObj(menuPtr->tkwin,          border = Tk_Get3DBorderFromObj(menuPtr->tkwin,
342                  (mePtr->borderPtr != NULL) ? mePtr->borderPtr                  (mePtr->borderPtr != NULL) ? mePtr->borderPtr
343                  : menuPtr->borderPtr);                  : menuPtr->borderPtr);
344          gcValues.background = Tk_3DBorderColor(border)->pixel;          gcValues.background = Tk_3DBorderColor(border)->pixel;
345    
346          gcValues.font = Tk_FontId(tkfont);          gcValues.font = Tk_FontId(tkfont);
347    
348          /*          /*
349           * Note: disable GraphicsExpose events;  we know there won't be           * Note: disable GraphicsExpose events;  we know there won't be
350           * obscured areas when copying from an off-screen pixmap to the           * obscured areas when copying from an off-screen pixmap to the
351           * screen and this gets rid of unnecessary events.           * screen and this gets rid of unnecessary events.
352           */           */
353    
354          gcValues.graphics_exposures = False;          gcValues.graphics_exposures = False;
355          newGC = Tk_GetGC(menuPtr->tkwin,          newGC = Tk_GetGC(menuPtr->tkwin,
356                  GCForeground|GCBackground|GCFont|GCGraphicsExposures,                  GCForeground|GCBackground|GCFont|GCGraphicsExposures,
357                  &gcValues);                  &gcValues);
358    
359          indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,          indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,
360                  (mePtr->indicatorFgPtr != NULL) ? mePtr->indicatorFgPtr                  (mePtr->indicatorFgPtr != NULL) ? mePtr->indicatorFgPtr
361                  : menuPtr->indicatorFgPtr);                  : menuPtr->indicatorFgPtr);
362          gcValues.foreground = indicatorFg->pixel;          gcValues.foreground = indicatorFg->pixel;
363          newIndicatorGC = Tk_GetGC(menuPtr->tkwin,          newIndicatorGC = Tk_GetGC(menuPtr->tkwin,
364                  GCForeground|GCBackground|GCGraphicsExposures,                  GCForeground|GCBackground|GCGraphicsExposures,
365                  &gcValues);                  &gcValues);
366    
367          if ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) {          if ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) {
368              XColor *disabledFg;              XColor *disabledFg;
369    
370              disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,              disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
371                      menuPtr->disabledFgPtr);                      menuPtr->disabledFgPtr);
372              gcValues.foreground = disabledFg->pixel;              gcValues.foreground = disabledFg->pixel;
373              mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures;              mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures;
374          } else {          } else {
375              gcValues.foreground = gcValues.background;              gcValues.foreground = gcValues.background;
376              gcValues.fill_style = FillStippled;              gcValues.fill_style = FillStippled;
377              gcValues.stipple = menuPtr->gray;              gcValues.stipple = menuPtr->gray;
378              mask = GCForeground|GCFillStyle|GCStipple;              mask = GCForeground|GCFillStyle|GCStipple;
379          }          }
380          newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);          newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
381    
382          activeFg = Tk_GetColorFromObj(menuPtr->tkwin,          activeFg = Tk_GetColorFromObj(menuPtr->tkwin,
383                  (mePtr->activeFgPtr != NULL) ? mePtr->activeFgPtr                  (mePtr->activeFgPtr != NULL) ? mePtr->activeFgPtr
384                  : menuPtr->activeFgPtr);                  : menuPtr->activeFgPtr);
385          activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,          activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
386                  (mePtr->activeBorderPtr != NULL) ? mePtr->activeBorderPtr                  (mePtr->activeBorderPtr != NULL) ? mePtr->activeBorderPtr
387                  : menuPtr->activeBorderPtr);                  : menuPtr->activeBorderPtr);
388                                    
389          gcValues.foreground = activeFg->pixel;          gcValues.foreground = activeFg->pixel;
390          gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;          gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;
391          newActiveGC = Tk_GetGC(menuPtr->tkwin,          newActiveGC = Tk_GetGC(menuPtr->tkwin,
392                  GCForeground|GCBackground|GCFont|GCGraphicsExposures,                  GCForeground|GCBackground|GCFont|GCGraphicsExposures,
393                  &gcValues);                  &gcValues);
394      } else {      } else {
395          newGC = None;          newGC = None;
396          newActiveGC = None;          newActiveGC = None;
397          newDisabledGC = None;          newDisabledGC = None;
398          newIndicatorGC = None;          newIndicatorGC = None;
399      }      }
400      if (mePtr->textGC != None) {      if (mePtr->textGC != None) {
401              Tk_FreeGC(menuPtr->display, mePtr->textGC);              Tk_FreeGC(menuPtr->display, mePtr->textGC);
402      }      }
403      mePtr->textGC = newGC;      mePtr->textGC = newGC;
404      if (mePtr->activeGC != None) {      if (mePtr->activeGC != None) {
405              Tk_FreeGC(menuPtr->display, mePtr->activeGC);              Tk_FreeGC(menuPtr->display, mePtr->activeGC);
406      }      }
407      mePtr->activeGC = newActiveGC;      mePtr->activeGC = newActiveGC;
408      if (mePtr->disabledGC != None) {      if (mePtr->disabledGC != None) {
409              Tk_FreeGC(menuPtr->display, mePtr->disabledGC);              Tk_FreeGC(menuPtr->display, mePtr->disabledGC);
410      }      }
411      mePtr->disabledGC = newDisabledGC;      mePtr->disabledGC = newDisabledGC;
412      if (mePtr->indicatorGC != None) {      if (mePtr->indicatorGC != None) {
413          Tk_FreeGC(menuPtr->display, mePtr->indicatorGC);          Tk_FreeGC(menuPtr->display, mePtr->indicatorGC);
414      }      }
415      mePtr->indicatorGC = newIndicatorGC;      mePtr->indicatorGC = newIndicatorGC;
416      return TCL_OK;      return TCL_OK;
417  }  }
418    
419  /*  /*
420   *----------------------------------------------------------------------   *----------------------------------------------------------------------
421   *   *
422   * TkEventuallyRecomputeMenu --   * TkEventuallyRecomputeMenu --
423   *   *
424   *      Tells Tcl to redo the geometry because this menu has changed.   *      Tells Tcl to redo the geometry because this menu has changed.
425   *   *
426   * Results:   * Results:
427   *      None.   *      None.
428   *   *
429   * Side effects:   * Side effects:
430   *      Menu geometry is recomputed at idle time, and the menu will be   *      Menu geometry is recomputed at idle time, and the menu will be
431   *      redisplayed.   *      redisplayed.
432   *   *
433   *----------------------------------------------------------------------   *----------------------------------------------------------------------
434   */   */
435    
436  void  void
437  TkEventuallyRecomputeMenu(menuPtr)  TkEventuallyRecomputeMenu(menuPtr)
438      TkMenu *menuPtr;      TkMenu *menuPtr;
439  {  {
440      if (!(menuPtr->menuFlags & RESIZE_PENDING)) {      if (!(menuPtr->menuFlags & RESIZE_PENDING)) {
441          menuPtr->menuFlags |= RESIZE_PENDING;          menuPtr->menuFlags |= RESIZE_PENDING;
442          Tcl_DoWhenIdle(ComputeMenuGeometry, (ClientData) menuPtr);          Tcl_DoWhenIdle(ComputeMenuGeometry, (ClientData) menuPtr);
443      }      }
444  }  }
445    
446  /*  /*
447   *----------------------------------------------------------------------   *----------------------------------------------------------------------
448   *   *
449   * TkRecomputeMenu --   * TkRecomputeMenu --
450   *   *
451   *      Tells Tcl to redo the geometry because this menu has changed.   *      Tells Tcl to redo the geometry because this menu has changed.
452   *      Does it now; removes any ComputeMenuGeometries from the idler.   *      Does it now; removes any ComputeMenuGeometries from the idler.
453   *   *
454   * Results:   * Results:
455   *      None.   *      None.
456   *   *
457   * Side effects:   * Side effects:
458   *      Menu geometry is immediately reconfigured.   *      Menu geometry is immediately reconfigured.
459   *   *
460   *----------------------------------------------------------------------   *----------------------------------------------------------------------
461   */   */
462    
463  void  void
464  TkRecomputeMenu(menuPtr)  TkRecomputeMenu(menuPtr)
465      TkMenu *menuPtr;      TkMenu *menuPtr;
466  {      {    
467      if (menuPtr->menuFlags & RESIZE_PENDING) {      if (menuPtr->menuFlags & RESIZE_PENDING) {
468          Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr);          Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr);
469          ComputeMenuGeometry((ClientData) menuPtr);          ComputeMenuGeometry((ClientData) menuPtr);
470      }      }
471  }  }
472    
473  /*  /*
474   *----------------------------------------------------------------------   *----------------------------------------------------------------------
475   *   *
476   * TkEventuallyRedrawMenu --   * TkEventuallyRedrawMenu --
477   *   *
478   *      Arrange for an entry of a menu, or the whole menu, to be   *      Arrange for an entry of a menu, or the whole menu, to be
479   *      redisplayed at some point in the future.   *      redisplayed at some point in the future.
480   *   *
481   * Results:   * Results:
482   *      None.   *      None.
483   *   *
484   * Side effects:   * Side effects:
485   *      A when-idle hander is scheduled to do the redisplay, if there   *      A when-idle hander is scheduled to do the redisplay, if there
486   *      isn't one already scheduled.   *      isn't one already scheduled.
487   *   *
488   *----------------------------------------------------------------------   *----------------------------------------------------------------------
489   */   */
490    
491  void  void
492  TkEventuallyRedrawMenu(menuPtr, mePtr)  TkEventuallyRedrawMenu(menuPtr, mePtr)
493      register TkMenu *menuPtr;   /* Information about menu to redraw. */      register TkMenu *menuPtr;   /* Information about menu to redraw. */
494      register TkMenuEntry *mePtr;/* Entry to redraw.  NULL means redraw      register TkMenuEntry *mePtr;/* Entry to redraw.  NULL means redraw
495                                   * all the entries in the menu. */                                   * all the entries in the menu. */
496  {  {
497      int i;      int i;
498            
499      if (menuPtr->tkwin == NULL) {      if (menuPtr->tkwin == NULL) {
500          return;          return;
501      }      }
502      if (mePtr != NULL) {      if (mePtr != NULL) {
503          mePtr->entryFlags |= ENTRY_NEEDS_REDISPLAY;          mePtr->entryFlags |= ENTRY_NEEDS_REDISPLAY;
504      } else {      } else {
505          for (i = 0; i < menuPtr->numEntries; i++) {          for (i = 0; i < menuPtr->numEntries; i++) {
506              menuPtr->entries[i]->entryFlags |= ENTRY_NEEDS_REDISPLAY;              menuPtr->entries[i]->entryFlags |= ENTRY_NEEDS_REDISPLAY;
507          }          }
508      }      }
509      if (!Tk_IsMapped(menuPtr->tkwin)      if (!Tk_IsMapped(menuPtr->tkwin)
510              || (menuPtr->menuFlags & REDRAW_PENDING)) {              || (menuPtr->menuFlags & REDRAW_PENDING)) {
511          return;          return;
512      }      }
513      Tcl_DoWhenIdle(DisplayMenu, (ClientData) menuPtr);      Tcl_DoWhenIdle(DisplayMenu, (ClientData) menuPtr);
514      menuPtr->menuFlags |= REDRAW_PENDING;      menuPtr->menuFlags |= REDRAW_PENDING;
515  }  }
516    
517  /*  /*
518   *--------------------------------------------------------------   *--------------------------------------------------------------
519   *   *
520   * ComputeMenuGeometry --   * ComputeMenuGeometry --
521   *   *
522   *      This procedure is invoked to recompute the size and   *      This procedure is invoked to recompute the size and
523   *      layout of a menu.  It is called as a when-idle handler so   *      layout of a menu.  It is called as a when-idle handler so
524   *      that it only gets done once, even if a group of changes is   *      that it only gets done once, even if a group of changes is
525   *      made to the menu.   *      made to the menu.
526   *   *
527   * Results:   * Results:
528   *      None.   *      None.
529   *   *
530   * Side effects:   * Side effects:
531   *      Fields of menu entries are changed to reflect their   *      Fields of menu entries are changed to reflect their
532   *      current positions, and the size of the menu window   *      current positions, and the size of the menu window
533   *      itself may be changed.   *      itself may be changed.
534   *   *
535   *--------------------------------------------------------------   *--------------------------------------------------------------
536   */   */
537    
538  static void  static void
539  ComputeMenuGeometry(clientData)  ComputeMenuGeometry(clientData)
540      ClientData clientData;              /* Structure describing menu. */      ClientData clientData;              /* Structure describing menu. */
541  {  {
542      TkMenu *menuPtr = (TkMenu *) clientData;      TkMenu *menuPtr = (TkMenu *) clientData;
543    
544      if (menuPtr->tkwin == NULL) {      if (menuPtr->tkwin == NULL) {
545          return;          return;
546      }      }
547    
548      if (menuPtr->menuType == MENUBAR) {      if (menuPtr->menuType == MENUBAR) {
549          TkpComputeMenubarGeometry(menuPtr);          TkpComputeMenubarGeometry(menuPtr);
550      } else {      } else {
551          TkpComputeStandardMenuGeometry(menuPtr);          TkpComputeStandardMenuGeometry(menuPtr);
552      }      }
553    
554      if ((menuPtr->totalWidth != Tk_ReqWidth(menuPtr->tkwin)) ||      if ((menuPtr->totalWidth != Tk_ReqWidth(menuPtr->tkwin)) ||
555              (menuPtr->totalHeight != Tk_ReqHeight(menuPtr->tkwin))) {              (menuPtr->totalHeight != Tk_ReqHeight(menuPtr->tkwin))) {
556          Tk_GeometryRequest(menuPtr->tkwin, menuPtr->totalWidth,          Tk_GeometryRequest(menuPtr->tkwin, menuPtr->totalWidth,
557                  menuPtr->totalHeight);                  menuPtr->totalHeight);
558      }      }
559                    
560      /*      /*
561       * Must always force a redisplay here if the window is mapped       * Must always force a redisplay here if the window is mapped
562       * (even if the size didn't change, something else might have       * (even if the size didn't change, something else might have
563       * changed in the menu, such as a label or accelerator).  The       * changed in the menu, such as a label or accelerator).  The
564       * resize will force a redisplay above.       * resize will force a redisplay above.
565       */       */
566            
567      TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);      TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
568            
569      menuPtr->menuFlags &= ~RESIZE_PENDING;      menuPtr->menuFlags &= ~RESIZE_PENDING;
570  }  }
571    
572  /*  /*
573   *----------------------------------------------------------------------   *----------------------------------------------------------------------
574   *   *
575   * TkMenuSelectImageProc --   * TkMenuSelectImageProc --
576   *   *
577   *      This procedure is invoked by the image code whenever the manager   *      This procedure is invoked by the image code whenever the manager
578   *      for an image does something that affects the size of contents   *      for an image does something that affects the size of contents
579   *      of an image displayed in a menu entry when it is selected.   *      of an image displayed in a menu entry when it is selected.
580   *   *
581   * Results:   * Results:
582   *      None.   *      None.
583   *   *
584   * Side effects:   * Side effects:
585   *      Arranges for the menu to get redisplayed.   *      Arranges for the menu to get redisplayed.
586   *   *
587   *----------------------------------------------------------------------   *----------------------------------------------------------------------
588   */   */
589    
590  void  void
591  TkMenuSelectImageProc(clientData, x, y, width, height, imgWidth,  TkMenuSelectImageProc(clientData, x, y, width, height, imgWidth,
592          imgHeight)          imgHeight)
593      ClientData clientData;              /* Pointer to widget record. */      ClientData clientData;              /* Pointer to widget record. */
594      int x, y;                           /* Upper left pixel (within image)      int x, y;                           /* Upper left pixel (within image)
595                                           * that must be redisplayed. */                                           * that must be redisplayed. */
596      int width, height;                  /* Dimensions of area to redisplay      int width, height;                  /* Dimensions of area to redisplay
597                                           * (may be <= 0). */                                           * (may be <= 0). */
598      int imgWidth, imgHeight;            /* New dimensions of image. */      int imgWidth, imgHeight;            /* New dimensions of image. */
599  {  {
600      register TkMenuEntry *mePtr = (TkMenuEntry *) clientData;      register TkMenuEntry *mePtr = (TkMenuEntry *) clientData;
601    
602      if ((mePtr->entryFlags & ENTRY_SELECTED)      if ((mePtr->entryFlags & ENTRY_SELECTED)
603              && !(mePtr->menuPtr->menuFlags &              && !(mePtr->menuPtr->menuFlags &
604              REDRAW_PENDING)) {              REDRAW_PENDING)) {
605          mePtr->menuPtr->menuFlags |= REDRAW_PENDING;          mePtr->menuPtr->menuFlags |= REDRAW_PENDING;
606          Tcl_DoWhenIdle(DisplayMenu, (ClientData) mePtr->menuPtr);          Tcl_DoWhenIdle(DisplayMenu, (ClientData) mePtr->menuPtr);
607      }      }
608  }  }
609    
610  /*  /*
611   *----------------------------------------------------------------------   *----------------------------------------------------------------------
612   *   *
613   * DisplayMenu --   * DisplayMenu --
614   *   *
615   *      This procedure is invoked to display a menu widget.   *      This procedure is invoked to display a menu widget.
616   *   *
617   * Results:   * Results:
618   *      None.   *      None.
619   *   *
620   * Side effects:   * Side effects:
621   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
622   *      current mode.   *      current mode.
623   *   *
624   *----------------------------------------------------------------------   *----------------------------------------------------------------------
625   */   */
626    
627  static void  static void
628  DisplayMenu(clientData)  DisplayMenu(clientData)
629      ClientData clientData;      /* Information about widget. */      ClientData clientData;      /* Information about widget. */
630  {  {
631      register TkMenu *menuPtr = (TkMenu *) clientData;      register TkMenu *menuPtr = (TkMenu *) clientData;
632      register TkMenuEntry *mePtr;      register TkMenuEntry *mePtr;
633      register Tk_Window tkwin = menuPtr->tkwin;      register Tk_Window tkwin = menuPtr->tkwin;
634      int index, strictMotif;      int index, strictMotif;
635      Tk_Font tkfont;      Tk_Font tkfont;
636      Tk_FontMetrics menuMetrics;      Tk_FontMetrics menuMetrics;
637      int width;      int width;
638      int borderWidth;      int borderWidth;
639      Tk_3DBorder border;      Tk_3DBorder border;
640      int activeBorderWidth;      int activeBorderWidth;
641      int relief;      int relief;
642    
643    
644      menuPtr->menuFlags &= ~REDRAW_PENDING;      menuPtr->menuFlags &= ~REDRAW_PENDING;
645      if ((menuPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {      if ((menuPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
646          return;          return;
647      }      }
648    
649      Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,      Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
650              &borderWidth);              &borderWidth);
651      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
652      Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,      Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
653              menuPtr->activeBorderWidthPtr, &activeBorderWidth);              menuPtr->activeBorderWidthPtr, &activeBorderWidth);
654    
655      if (menuPtr->menuType == MENUBAR) {      if (menuPtr->menuType == MENUBAR) {
656          Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth,          Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth,
657                  borderWidth, Tk_Width(tkwin) - 2 * borderWidth,                  borderWidth, Tk_Width(tkwin) - 2 * borderWidth,
658                  Tk_Height(tkwin) - 2 * borderWidth, 0, TK_RELIEF_FLAT);                  Tk_Height(tkwin) - 2 * borderWidth, 0, TK_RELIEF_FLAT);
659      }      }
660    
661      strictMotif = Tk_StrictMotif(menuPtr->tkwin);      strictMotif = Tk_StrictMotif(menuPtr->tkwin);
662    
663      /*      /*
664       * See note in ComputeMenuGeometry. We don't want to be doing font metrics       * See note in ComputeMenuGeometry. We don't want to be doing font metrics
665       * all of the time.       * all of the time.
666       */       */
667    
668      tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);      tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
669      Tk_GetFontMetrics(tkfont, &menuMetrics);      Tk_GetFontMetrics(tkfont, &menuMetrics);
670    
671      /*      /*
672       * Loop through all of the entries, drawing them one at a time.       * Loop through all of the entries, drawing them one at a time.
673       */       */
674    
675      for (index = 0; index < menuPtr->numEntries; index++) {      for (index = 0; index < menuPtr->numEntries; index++) {
676          mePtr = menuPtr->entries[index];          mePtr = menuPtr->entries[index];
677          if (menuPtr->menuType != MENUBAR) {          if (menuPtr->menuType != MENUBAR) {
678              if (!(mePtr->entryFlags & ENTRY_NEEDS_REDISPLAY)) {              if (!(mePtr->entryFlags & ENTRY_NEEDS_REDISPLAY)) {
679                  continue;                  continue;
680              }              }
681          }          }
682          mePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY;          mePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY;
683    
684          if (menuPtr->menuType == MENUBAR) {          if (menuPtr->menuType == MENUBAR) {
685              width = mePtr->width;              width = mePtr->width;
686          } else {          } else {
687              if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {              if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
688                  width = Tk_Width(menuPtr->tkwin) - mePtr->x                  width = Tk_Width(menuPtr->tkwin) - mePtr->x
689                          - activeBorderWidth;                          - activeBorderWidth;
690              } else {              } else {
691                  width = mePtr->width + borderWidth;                  width = mePtr->width + borderWidth;
692              }              }
693          }          }
694          TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont,          TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont,
695                  &menuMetrics, mePtr->x, mePtr->y, width,                  &menuMetrics, mePtr->x, mePtr->y, width,
696                  mePtr->height, strictMotif, 1);                  mePtr->height, strictMotif, 1);
697          if ((index > 0) && (menuPtr->menuType != MENUBAR)          if ((index > 0) && (menuPtr->menuType != MENUBAR)
698                  && mePtr->columnBreak) {                  && mePtr->columnBreak) {
699              mePtr = menuPtr->entries[index - 1];              mePtr = menuPtr->entries[index - 1];
700              Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,              Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,
701                  mePtr->x, mePtr->y + mePtr->height,                  mePtr->x, mePtr->y + mePtr->height,
702                  mePtr->width,                  mePtr->width,
703                  Tk_Height(tkwin) - mePtr->y - mePtr->height -                  Tk_Height(tkwin) - mePtr->y - mePtr->height -
704                  activeBorderWidth, 0,                  activeBorderWidth, 0,
705                  TK_RELIEF_FLAT);                  TK_RELIEF_FLAT);
706          }          }
707      }      }
708    
709      if (menuPtr->menuType != MENUBAR) {      if (menuPtr->menuType != MENUBAR) {
710          int x, y, height;          int x, y, height;
711    
712          if (menuPtr->numEntries == 0) {          if (menuPtr->numEntries == 0) {
713              x = y = borderWidth;              x = y = borderWidth;
714              width = Tk_Width(tkwin) - 2 * activeBorderWidth;              width = Tk_Width(tkwin) - 2 * activeBorderWidth;
715              height = Tk_Height(tkwin) - 2 * activeBorderWidth;              height = Tk_Height(tkwin) - 2 * activeBorderWidth;
716          } else {          } else {
717              mePtr = menuPtr->entries[menuPtr->numEntries - 1];              mePtr = menuPtr->entries[menuPtr->numEntries - 1];
718              Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),              Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
719                  border, mePtr->x, mePtr->y + mePtr->height, mePtr->width,                  border, mePtr->x, mePtr->y + mePtr->height, mePtr->width,
720                  Tk_Height(tkwin) - mePtr->y - mePtr->height                  Tk_Height(tkwin) - mePtr->y - mePtr->height
721                  - activeBorderWidth, 0,                  - activeBorderWidth, 0,
722                  TK_RELIEF_FLAT);                  TK_RELIEF_FLAT);
723              x = mePtr->x + mePtr->width;              x = mePtr->x + mePtr->width;
724              y = mePtr->y + mePtr->height;              y = mePtr->y + mePtr->height;
725              width = Tk_Width(tkwin) - x - activeBorderWidth;              width = Tk_Width(tkwin) - x - activeBorderWidth;
726              height = Tk_Height(tkwin) - y - activeBorderWidth;              height = Tk_Height(tkwin) - y - activeBorderWidth;
727          }          }
728          Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y,          Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y,
729                  width, height, 0, TK_RELIEF_FLAT);                  width, height, 0, TK_RELIEF_FLAT);
730      }      }
731    
732      Tk_GetReliefFromObj(NULL, menuPtr->reliefPtr, &relief);      Tk_GetReliefFromObj(NULL, menuPtr->reliefPtr, &relief);
733      Tk_Draw3DRectangle(menuPtr->tkwin, Tk_WindowId(tkwin),      Tk_Draw3DRectangle(menuPtr->tkwin, Tk_WindowId(tkwin),
734              border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth,              border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth,
735              relief);              relief);
736  }  }
737    
738  /*  /*
739   *--------------------------------------------------------------   *--------------------------------------------------------------
740   *   *
741   * TkMenuEventProc --   * TkMenuEventProc --
742   *   *
743   *      This procedure is invoked by the Tk dispatcher for various   *      This procedure is invoked by the Tk dispatcher for various
744   *      events on menus.   *      events on menus.
745   *   *
746   * Results:   * Results:
747   *      None.   *      None.
748   *   *
749   * Side effects:   * Side effects:
750   *      When the window gets deleted, internal structures get   *      When the window gets deleted, internal structures get
751   *      cleaned up.  When it gets exposed, it is redisplayed.   *      cleaned up.  When it gets exposed, it is redisplayed.
752   *   *
753   *--------------------------------------------------------------   *--------------------------------------------------------------
754   */   */
755    
756  void  void
757  TkMenuEventProc(clientData, eventPtr)  TkMenuEventProc(clientData, eventPtr)
758      ClientData clientData;      /* Information about window. */      ClientData clientData;      /* Information about window. */
759      XEvent *eventPtr;           /* Information about event. */      XEvent *eventPtr;           /* Information about event. */
760  {  {
761      TkMenu *menuPtr = (TkMenu *) clientData;      TkMenu *menuPtr = (TkMenu *) clientData;
762            
763      if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {      if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
764          TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);          TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
765      } else if (eventPtr->type == ConfigureNotify) {      } else if (eventPtr->type == ConfigureNotify) {
766          TkEventuallyRecomputeMenu(menuPtr);          TkEventuallyRecomputeMenu(menuPtr);
767          TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);          TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
768      } else if (eventPtr->type == ActivateNotify) {      } else if (eventPtr->type == ActivateNotify) {
769          if (menuPtr->menuType == TEAROFF_MENU) {          if (menuPtr->menuType == TEAROFF_MENU) {
770              TkpSetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL);              TkpSetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL);
771          }          }
772      } else if (eventPtr->type == DestroyNotify) {      } else if (eventPtr->type == DestroyNotify) {
773          if (menuPtr->tkwin != NULL) {          if (menuPtr->tkwin != NULL) {
774              TkDestroyMenu(menuPtr);              TkDestroyMenu(menuPtr);
775              menuPtr->tkwin = NULL;              menuPtr->tkwin = NULL;
776              Tcl_DeleteCommandFromToken(menuPtr->interp, menuPtr->widgetCmd);              Tcl_DeleteCommandFromToken(menuPtr->interp, menuPtr->widgetCmd);
777          }          }
778          if (menuPtr->menuFlags & REDRAW_PENDING) {          if (menuPtr->menuFlags & REDRAW_PENDING) {
779              Tcl_CancelIdleCall(DisplayMenu, (ClientData) menuPtr);              Tcl_CancelIdleCall(DisplayMenu, (ClientData) menuPtr);
780          }          }
781          if (menuPtr->menuFlags & RESIZE_PENDING) {          if (menuPtr->menuFlags & RESIZE_PENDING) {
782              Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr);              Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr);
783          }          }
784          Tcl_EventuallyFree((ClientData) menuPtr, TCL_DYNAMIC);          Tcl_EventuallyFree((ClientData) menuPtr, TCL_DYNAMIC);
785      }      }
786  }  }
787    
788  /*  /*
789   *----------------------------------------------------------------------   *----------------------------------------------------------------------
790   *   *
791   * TkMenuImageProc --   * TkMenuImageProc --
792   *   *
793   *      This procedure is invoked by the image code whenever the manager   *      This procedure is invoked by the image code whenever the manager
794   *      for an image does something that affects the size of contents   *      for an image does something that affects the size of contents
795   *      of an image displayed in a menu entry.   *      of an image displayed in a menu entry.
796   *   *
797   * Results:   * Results:
798   *      None.   *      None.
799   *   *
800   * Side effects:   * Side effects:
801   *      Arranges for the menu to get redisplayed.   *      Arranges for the menu to get redisplayed.
802   *   *
803   *----------------------------------------------------------------------   *----------------------------------------------------------------------
804   */   */
805    
806  void  void
807  TkMenuImageProc(clientData, x, y, width, height, imgWidth,  TkMenuImageProc(clientData, x, y, width, height, imgWidth,
808          imgHeight)          imgHeight)
809      ClientData clientData;              /* Pointer to widget record. */      ClientData clientData;              /* Pointer to widget record. */
810      int x, y;                           /* Upper left pixel (within image)      int x, y;                           /* Upper left pixel (within image)
811                                           * that must be redisplayed. */                                           * that must be redisplayed. */
812      int width, height;                  /* Dimensions of area to redisplay      int width, height;                  /* Dimensions of area to redisplay
813                                           * (may be <= 0). */                                           * (may be <= 0). */
814      int imgWidth, imgHeight;            /* New dimensions of image. */      int imgWidth, imgHeight;            /* New dimensions of image. */
815  {  {
816      register TkMenu *menuPtr = ((TkMenuEntry *)clientData)->menuPtr;      register TkMenu *menuPtr = ((TkMenuEntry *)clientData)->menuPtr;
817    
818      if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags      if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags
819              & RESIZE_PENDING)) {              & RESIZE_PENDING)) {
820          menuPtr->menuFlags |= RESIZE_PENDING;          menuPtr->menuFlags |= RESIZE_PENDING;
821          Tcl_DoWhenIdle(ComputeMenuGeometry, (ClientData) menuPtr);          Tcl_DoWhenIdle(ComputeMenuGeometry, (ClientData) menuPtr);
822      }      }
823  }  }
824    
825  /*  /*
826   *----------------------------------------------------------------------   *----------------------------------------------------------------------
827   *   *
828   * TkPostTearoffMenu --   * TkPostTearoffMenu --
829   *   *
830   *      Posts a menu on the screen. Used to post tearoff menus. On Unix,   *      Posts a menu on the screen. Used to post tearoff menus. On Unix,
831   *      all menus are posted this way. Adjusts the menu's position   *      all menus are posted this way. Adjusts the menu's position
832   *      so that it fits on the screen, and maps and raises the menu.   *      so that it fits on the screen, and maps and raises the menu.
833   *   *
834   * Results:   * Results:
835   *      Returns a standard Tcl Error.   *      Returns a standard Tcl Error.
836   *   *
837   * Side effects:   * Side effects:
838   *      The menu is posted.   *      The menu is posted.
839   *   *
840   *----------------------------------------------------------------------   *----------------------------------------------------------------------
841   */   */
842    
843  int  int
844  TkPostTearoffMenu(interp, menuPtr, x, y)  TkPostTearoffMenu(interp, menuPtr, x, y)
845      Tcl_Interp *interp;                 /* The interpreter of the menu */      Tcl_Interp *interp;                 /* The interpreter of the menu */
846      TkMenu *menuPtr;                    /* The menu we are posting */      TkMenu *menuPtr;                    /* The menu we are posting */
847      int x;                              /* The root X coordinate where we      int x;                              /* The root X coordinate where we
848                                           * are posting */                                           * are posting */
849      int y;                              /* The root Y coordinate where we      int y;                              /* The root Y coordinate where we
850                                           * are posting */                                           * are posting */
851  {  {
852      int vRootX, vRootY, vRootWidth, vRootHeight;      int vRootX, vRootY, vRootWidth, vRootHeight;
853      int tmp, result;      int tmp, result;
854    
855      TkActivateMenuEntry(menuPtr, -1);      TkActivateMenuEntry(menuPtr, -1);
856      TkRecomputeMenu(menuPtr);      TkRecomputeMenu(menuPtr);
857      result = TkPostCommand(menuPtr);      result = TkPostCommand(menuPtr);
858      if (result != TCL_OK) {      if (result != TCL_OK) {
859          return result;          return result;
860      }      }
861    
862      /*      /*
863       * The post commands could have deleted the menu, which means       * The post commands could have deleted the menu, which means
864       * we are dead and should go away.       * we are dead and should go away.
865       */       */
866    
867      if (menuPtr->tkwin == NULL) {      if (menuPtr->tkwin == NULL) {
868          return TCL_OK;          return TCL_OK;
869      }      }
870    
871      /*      /*
872       * Adjust the position of the menu if necessary to keep it       * Adjust the position of the menu if necessary to keep it
873       * visible on the screen.  There are two special tricks to       * visible on the screen.  There are two special tricks to
874       * make this work right:       * make this work right:
875       *       *
876       * 1. If a virtual root window manager is being used then       * 1. If a virtual root window manager is being used then
877       *    the coordinates are in the virtual root window of       *    the coordinates are in the virtual root window of
878       *    menuPtr's parent;  since the menu uses override-redirect       *    menuPtr's parent;  since the menu uses override-redirect
879       *    mode it will be in the *real* root window for the screen,       *    mode it will be in the *real* root window for the screen,
880       *    so we have to map the coordinates from the virtual root       *    so we have to map the coordinates from the virtual root
881       *    (if any) to the real root.  Can't get the virtual root       *    (if any) to the real root.  Can't get the virtual root
882       *    from the menu itself (it will never be seen by the wm)       *    from the menu itself (it will never be seen by the wm)
883       *    so use its parent instead (it would be better to have an       *    so use its parent instead (it would be better to have an
884       *    an option that names a window to use for this...).       *    an option that names a window to use for this...).
885       * 2. The menu may not have been mapped yet, so its current size       * 2. The menu may not have been mapped yet, so its current size
886       *    might be the default 1x1.  To compute how much space it       *    might be the default 1x1.  To compute how much space it
887       *    needs, use its requested size, not its actual size.       *    needs, use its requested size, not its actual size.
888       *       *
889       * Note that this code assumes square screen regions and all       * Note that this code assumes square screen regions and all
890       * positive coordinates. This does not work on a Mac with       * positive coordinates. This does not work on a Mac with
891       * multiple monitors. But then again, Tk has other problems       * multiple monitors. But then again, Tk has other problems
892       * with this.       * with this.
893       */       */
894    
895      Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,      Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
896          &vRootWidth, &vRootHeight);          &vRootWidth, &vRootHeight);
897      x += vRootX;      x += vRootX;
898      y += vRootY;      y += vRootY;
899      tmp = WidthOfScreen(Tk_Screen(menuPtr->tkwin))      tmp = WidthOfScreen(Tk_Screen(menuPtr->tkwin))
900          - Tk_ReqWidth(menuPtr->tkwin);          - Tk_ReqWidth(menuPtr->tkwin);
901      if (x > tmp) {      if (x > tmp) {
902          x = tmp;          x = tmp;
903      }      }
904      if (x < 0) {      if (x < 0) {
905          x = 0;          x = 0;
906      }      }
907      tmp = HeightOfScreen(Tk_Screen(menuPtr->tkwin))      tmp = HeightOfScreen(Tk_Screen(menuPtr->tkwin))
908          - Tk_ReqHeight(menuPtr->tkwin);          - Tk_ReqHeight(menuPtr->tkwin);
909      if (y > tmp) {      if (y > tmp) {
910          y = tmp;          y = tmp;
911      }      }
912      if (y < 0) {      if (y < 0) {
913          y = 0;          y = 0;
914      }      }
915      Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);      Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
916      if (!Tk_IsMapped(menuPtr->tkwin)) {      if (!Tk_IsMapped(menuPtr->tkwin)) {
917          Tk_MapWindow(menuPtr->tkwin);          Tk_MapWindow(menuPtr->tkwin);
918      }      }
919      TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);      TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
920      return TCL_OK;      return TCL_OK;
921  }  }
922    
923  /*  /*
924   *--------------------------------------------------------------   *--------------------------------------------------------------
925   *   *
926   * TkPostSubmenu --   * TkPostSubmenu --
927   *   *
928   *      This procedure arranges for a particular submenu (i.e. the   *      This procedure arranges for a particular submenu (i.e. the
929   *      menu corresponding to a given cascade entry) to be   *      menu corresponding to a given cascade entry) to be
930   *      posted.   *      posted.
931   *   *
932   * Results:   * Results:
933   *      A standard Tcl return result.  Errors may occur in the   *      A standard Tcl return result.  Errors may occur in the
934   *      Tcl commands generated to post and unpost submenus.   *      Tcl commands generated to post and unpost submenus.
935   *   *
936   * Side effects:   * Side effects:
937   *      If there is already a submenu posted, it is unposted.   *      If there is already a submenu posted, it is unposted.
938   *      The new submenu is then posted.   *      The new submenu is then posted.
939   *   *
940   *--------------------------------------------------------------   *--------------------------------------------------------------
941   */   */
942    
943  int  int
944  TkPostSubmenu(interp, menuPtr, mePtr)  TkPostSubmenu(interp, menuPtr, mePtr)
945      Tcl_Interp *interp;         /* Used for invoking sub-commands and      Tcl_Interp *interp;         /* Used for invoking sub-commands and
946                                   * reporting errors. */                                   * reporting errors. */
947      register TkMenu *menuPtr;   /* Information about menu as a whole. */      register TkMenu *menuPtr;   /* Information about menu as a whole. */
948      register TkMenuEntry *mePtr;        /* Info about submenu that is to be      register TkMenuEntry *mePtr;        /* Info about submenu that is to be
949                                   * posted.  NULL means make sure that                                   * posted.  NULL means make sure that
950                                   * no submenu is posted. */                                   * no submenu is posted. */
951  {  {
952      int result, x, y;      int result, x, y;
953    
954      if (mePtr == menuPtr->postedCascade) {      if (mePtr == menuPtr->postedCascade) {
955          return TCL_OK;          return TCL_OK;
956      }      }
957    
958      if (menuPtr->postedCascade != NULL) {      if (menuPtr->postedCascade != NULL) {
959          char *name = Tcl_GetStringFromObj(menuPtr->postedCascade->namePtr,          char *name = Tcl_GetStringFromObj(menuPtr->postedCascade->namePtr,
960                  NULL);                  NULL);
961    
962          /*          /*
963           * Note: when unposting a submenu, we have to redraw the entire           * Note: when unposting a submenu, we have to redraw the entire
964           * parent menu.  This is because of a combination of the following           * parent menu.  This is because of a combination of the following
965           * things:           * things:
966           * (a) the submenu partially overlaps the parent.           * (a) the submenu partially overlaps the parent.
967           * (b) the submenu specifies "save under", which causes the X           * (b) the submenu specifies "save under", which causes the X
968           *     server to make a copy of the information under it when it           *     server to make a copy of the information under it when it
969           *     is posted.  When the submenu is unposted, the X server           *     is posted.  When the submenu is unposted, the X server
970           *     copies this data back and doesn't generate any Expose           *     copies this data back and doesn't generate any Expose
971           *     events for the parent.           *     events for the parent.
972           * (c) the parent may have redisplayed itself after the submenu           * (c) the parent may have redisplayed itself after the submenu
973           *     was posted, in which case the saved information is no           *     was posted, in which case the saved information is no
974           *     longer correct.           *     longer correct.
975           * The simplest solution is just force a complete redisplay of           * The simplest solution is just force a complete redisplay of
976           * the parent.           * the parent.
977           */           */
978    
979          TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);          TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
980          result = Tcl_VarEval(interp, name, " unpost", (char *) NULL);          result = Tcl_VarEval(interp, name, " unpost", (char *) NULL);
981          menuPtr->postedCascade = NULL;          menuPtr->postedCascade = NULL;
982          if (result != TCL_OK) {          if (result != TCL_OK) {
983              return result;              return result;
984          }          }
985      }      }
986    
987      if ((mePtr != NULL) && (mePtr->namePtr != NULL)      if ((mePtr != NULL) && (mePtr->namePtr != NULL)
988              && Tk_IsMapped(menuPtr->tkwin)) {              && Tk_IsMapped(menuPtr->tkwin)) {
989          /*          /*
990           * Position the cascade with its upper left corner slightly           * Position the cascade with its upper left corner slightly
991           * below and to the left of the upper right corner of the           * below and to the left of the upper right corner of the
992           * menu entry (this is an attempt to match Motif behavior).           * menu entry (this is an attempt to match Motif behavior).
993           *           *
994           * The menu has to redrawn so that the entry can change relief.           * The menu has to redrawn so that the entry can change relief.
995           */           */
996    
997          char string[TCL_INTEGER_SPACE * 2];          char string[TCL_INTEGER_SPACE * 2];
998          char *name;          char *name;
999    
1000          name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);          name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
1001          Tk_GetRootCoords(menuPtr->tkwin, &x, &y);          Tk_GetRootCoords(menuPtr->tkwin, &x, &y);
1002          AdjustMenuCoords(menuPtr, mePtr, &x, &y, string);          AdjustMenuCoords(menuPtr, mePtr, &x, &y, string);
1003          result = Tcl_VarEval(interp, name, " post ", string, (char *) NULL);          result = Tcl_VarEval(interp, name, " post ", string, (char *) NULL);
1004          if (result != TCL_OK) {          if (result != TCL_OK) {
1005              return result;              return result;
1006          }          }
1007          menuPtr->postedCascade = mePtr;          menuPtr->postedCascade = mePtr;
1008          TkEventuallyRedrawMenu(menuPtr, mePtr);          TkEventuallyRedrawMenu(menuPtr, mePtr);
1009      }      }
1010      return TCL_OK;      return TCL_OK;
1011  }  }
1012    
1013  /*  /*
1014   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1015   *   *
1016   * AdjustMenuCoords --   * AdjustMenuCoords --
1017   *   *
1018   *      Adjusts the given coordinates down and the left to give a Motif   *      Adjusts the given coordinates down and the left to give a Motif
1019   *      look.   *      look.
1020   *   *
1021   * Results:   * Results:
1022   *      None.   *      None.
1023   *   *
1024   * Side effects:   * Side effects:
1025   *      The menu is eventually redrawn if necessary.   *      The menu is eventually redrawn if necessary.
1026   *   *
1027   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1028   */   */
1029    
1030  static void  static void
1031  AdjustMenuCoords(menuPtr, mePtr, xPtr, yPtr, string)  AdjustMenuCoords(menuPtr, mePtr, xPtr, yPtr, string)
1032      TkMenu *menuPtr;      TkMenu *menuPtr;
1033      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
1034      int *xPtr;      int *xPtr;
1035      int *yPtr;      int *yPtr;
1036      char *string;      char *string;
1037  {  {
1038      if (menuPtr->menuType == MENUBAR) {      if (menuPtr->menuType == MENUBAR) {
1039          *xPtr += mePtr->x;          *xPtr += mePtr->x;
1040          *yPtr += mePtr->y + mePtr->height;          *yPtr += mePtr->y + mePtr->height;
1041      } else {      } else {
1042          int borderWidth, activeBorderWidth;          int borderWidth, activeBorderWidth;
1043    
1044          Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,          Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
1045                  &borderWidth);                  &borderWidth);
1046          Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,          Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
1047                  menuPtr->activeBorderWidthPtr, &activeBorderWidth);                  menuPtr->activeBorderWidthPtr, &activeBorderWidth);
1048          *xPtr += Tk_Width(menuPtr->tkwin) - borderWidth - activeBorderWidth          *xPtr += Tk_Width(menuPtr->tkwin) - borderWidth - activeBorderWidth
1049                  - 2;                  - 2;
1050          *yPtr += mePtr->y + activeBorderWidth + 2;          *yPtr += mePtr->y + activeBorderWidth + 2;
1051      }      }
1052      sprintf(string, "%d %d", *xPtr, *yPtr);      sprintf(string, "%d %d", *xPtr, *yPtr);
1053  }  }
1054    
1055  /* End of tkmenudraw.c */  /* End of tkmenudraw.c */

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25