/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkmenubutton.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkmenubutton.c

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

revision 70 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   * tkMenubutton.c --   * tkMenubutton.c --
5   *   *
6   *      This module implements button-like widgets that are used   *      This module implements button-like widgets that are used
7   *      to invoke pull-down menus.   *      to invoke pull-down menus.
8   *   *
9   * Copyright (c) 1990-1994 The Regents of the University of California.   * Copyright (c) 1990-1994 The Regents of the University of California.
10   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11   *   *
12   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
13   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14   *   *
15   * RCS: @(#) $Id: tkmenubutton.c,v 1.1.1.1 2001/06/13 05:05:54 dtashley Exp $   * RCS: @(#) $Id: tkmenubutton.c,v 1.1.1.1 2001/06/13 05:05:54 dtashley Exp $
16   */   */
17    
18  #include "tkMenubutton.h"  #include "tkMenubutton.h"
19  #include "tkPort.h"  #include "tkPort.h"
20  #include "default.h"  #include "default.h"
21    
22  /*  /*
23   * The following table defines the legal values for the -direction   * The following table defines the legal values for the -direction
24   * option.  It is used together with the "enum direction" declaration   * option.  It is used together with the "enum direction" declaration
25   * in tkMenubutton.h.   * in tkMenubutton.h.
26   */   */
27    
28  static char *directionStrings[] = {  static char *directionStrings[] = {
29      "above", "below", "flush", "left", "right", (char *) NULL      "above", "below", "flush", "left", "right", (char *) NULL
30  };  };
31    
32  /*  /*
33   * The following table defines the legal values for the -state option.   * The following table defines the legal values for the -state option.
34   * It is used together with the "enum state" declaration in tkMenubutton.h.   * It is used together with the "enum state" declaration in tkMenubutton.h.
35   */   */
36    
37  static char *stateStrings[] = {  static char *stateStrings[] = {
38      "active", "disabled", "normal", (char *) NULL      "active", "disabled", "normal", (char *) NULL
39  };  };
40    
41  /*  /*
42   * Information used for parsing configuration specs:   * Information used for parsing configuration specs:
43   */   */
44    
45  static Tk_OptionSpec optionSpecs[] = {  static Tk_OptionSpec optionSpecs[] = {
46      {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",      {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
47          DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1,          DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1,
48          Tk_Offset(TkMenuButton, activeBorder), 0,          Tk_Offset(TkMenuButton, activeBorder), 0,
49          (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0},          (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0},
50      {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",      {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
51          DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1,          DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1,
52           Tk_Offset(TkMenuButton, activeFg),           Tk_Offset(TkMenuButton, activeFg),
53           0, (ClientData) DEF_MENUBUTTON_ACTIVE_FG_MONO, 0},           0, (ClientData) DEF_MENUBUTTON_ACTIVE_FG_MONO, 0},
54      {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",      {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
55          DEF_MENUBUTTON_ANCHOR, -1,          DEF_MENUBUTTON_ANCHOR, -1,
56          Tk_Offset(TkMenuButton, anchor), 0, 0, 0},          Tk_Offset(TkMenuButton, anchor), 0, 0, 0},
57      {TK_OPTION_BORDER, "-background", "background", "Background",      {TK_OPTION_BORDER, "-background", "background", "Background",
58          DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder),          DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder),
59          0, (ClientData) DEF_MENUBUTTON_BG_MONO, 0},          0, (ClientData) DEF_MENUBUTTON_BG_MONO, 0},
60      {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,      {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
61          (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},          (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
62      {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,      {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
63          (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},          (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
64      {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",      {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
65          DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap),          DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap),
66          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
67      {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",      {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
68          DEF_MENUBUTTON_BORDER_WIDTH, -1,          DEF_MENUBUTTON_BORDER_WIDTH, -1,
69          Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0},          Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0},
70      {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",      {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
71          DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor),          DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor),
72          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
73      {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",      {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",
74          DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction),          DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction),
75          0, (ClientData) directionStrings, 0},          0, (ClientData) directionStrings, 0},
76      {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",      {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
77          "DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR,          "DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR,
78          -1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,          -1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,
79          (ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0},          (ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0},
80      {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,      {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
81          (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},          (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
82      {TK_OPTION_FONT, "-font", "font", "Font",      {TK_OPTION_FONT, "-font", "font", "Font",
83          DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0},          DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0},
84      {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",      {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
85          DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0},          DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0},
86      {TK_OPTION_STRING, "-height", "height", "Height",      {TK_OPTION_STRING, "-height", "height", "Height",
87          DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString),          DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString),
88          0, 0, 0},          0, 0, 0},
89      {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",      {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
90          "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR,          "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR,
91          -1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0},          -1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0},
92      {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",      {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
93          DEF_MENUBUTTON_HIGHLIGHT, -1,          DEF_MENUBUTTON_HIGHLIGHT, -1,
94          Tk_Offset(TkMenuButton, highlightColorPtr),     0, 0, 0},          Tk_Offset(TkMenuButton, highlightColorPtr),     0, 0, 0},
95      {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",      {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
96          "HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH,          "HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH,
97          -1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0},          -1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0},
98      {TK_OPTION_STRING, "-image", "image", "Image",      {TK_OPTION_STRING, "-image", "image", "Image",
99          DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString),          DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString),
100          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
101      {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",      {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
102          DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn),          DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn),
103          0, 0, 0},          0, 0, 0},
104      {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",      {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
105          DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0},          DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0},
106      {TK_OPTION_STRING, "-menu", "menu", "Menu",      {TK_OPTION_STRING, "-menu", "menu", "Menu",
107          DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName),          DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName),
108          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
109      {TK_OPTION_PIXELS, "-padx", "padX", "Pad",      {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
110          DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX),          DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX),
111          0, 0, 0},          0, 0, 0},
112      {TK_OPTION_PIXELS, "-pady", "padY", "Pad",      {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
113          DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY),          DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY),
114          0, 0, 0},          0, 0, 0},
115      {TK_OPTION_RELIEF, "-relief", "relief", "Relief",      {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
116          DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief),          DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief),
117          0, 0, 0},          0, 0, 0},
118      {TK_OPTION_STRING_TABLE, "-state", "state", "State",      {TK_OPTION_STRING_TABLE, "-state", "state", "State",
119          DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state),          DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state),
120          0, (ClientData) stateStrings, 0},          0, (ClientData) stateStrings, 0},
121      {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",      {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
122          DEF_MENUBUTTON_TAKE_FOCUS, -1,          DEF_MENUBUTTON_TAKE_FOCUS, -1,
123          Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0},          Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0},
124      {TK_OPTION_STRING, "-text", "text", "Text",      {TK_OPTION_STRING, "-text", "text", "Text",
125          DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0},          DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0},
126      {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",      {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
127          DEF_MENUBUTTON_TEXT_VARIABLE, -1,          DEF_MENUBUTTON_TEXT_VARIABLE, -1,
128          Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0},          Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0},
129      {TK_OPTION_INT, "-underline", "underline", "Underline",      {TK_OPTION_INT, "-underline", "underline", "Underline",
130          DEF_MENUBUTTON_UNDERLINE, -1, Tk_Offset(TkMenuButton, underline),          DEF_MENUBUTTON_UNDERLINE, -1, Tk_Offset(TkMenuButton, underline),
131           0, 0, 0},           0, 0, 0},
132      {TK_OPTION_STRING, "-width", "width", "Width",      {TK_OPTION_STRING, "-width", "width", "Width",
133          DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString),          DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString),
134          0, 0, 0},          0, 0, 0},
135      {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",      {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
136          DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength),          DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength),
137          0, 0, 0},          0, 0, 0},
138      {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
139          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
140  };  };
141    
142  /*  /*
143   * The following tables define the menubutton widget commands and map the   * The following tables define the menubutton widget commands and map the
144   * indexes into the string tables into a single enumerated type used   * indexes into the string tables into a single enumerated type used
145   * to dispatch the scale widget command.   * to dispatch the scale widget command.
146   */   */
147    
148  static char *commandNames[] = {  static char *commandNames[] = {
149      "cget", "configure", (char *) NULL      "cget", "configure", (char *) NULL
150  };  };
151    
152  enum command {  enum command {
153      COMMAND_CGET, COMMAND_CONFIGURE      COMMAND_CGET, COMMAND_CONFIGURE
154  };  };
155    
156  /*  /*
157   * Forward declarations for procedures defined later in this file:   * Forward declarations for procedures defined later in this file:
158   */   */
159    
160  static void             MenuButtonCmdDeletedProc _ANSI_ARGS_((  static void             MenuButtonCmdDeletedProc _ANSI_ARGS_((
161                              ClientData clientData));                              ClientData clientData));
162  static void             MenuButtonEventProc _ANSI_ARGS_((ClientData clientData,  static void             MenuButtonEventProc _ANSI_ARGS_((ClientData clientData,
163                              XEvent *eventPtr));                              XEvent *eventPtr));
164  static void             MenuButtonImageProc _ANSI_ARGS_((ClientData clientData,  static void             MenuButtonImageProc _ANSI_ARGS_((ClientData clientData,
165                              int x, int y, int width, int height, int imgWidth,                              int x, int y, int width, int height, int imgWidth,
166                              int imgHeight));                              int imgHeight));
167  static char *           MenuButtonTextVarProc _ANSI_ARGS_((  static char *           MenuButtonTextVarProc _ANSI_ARGS_((
168                              ClientData clientData, Tcl_Interp *interp,                              ClientData clientData, Tcl_Interp *interp,
169                              char *name1, char *name2, int flags));                              char *name1, char *name2, int flags));
170  static int              MenuButtonWidgetObjCmd _ANSI_ARGS_((  static int              MenuButtonWidgetObjCmd _ANSI_ARGS_((
171                              ClientData clientData, Tcl_Interp *interp,                              ClientData clientData, Tcl_Interp *interp,
172                              int objc, Tcl_Obj *CONST objv[]));                              int objc, Tcl_Obj *CONST objv[]));
173  static int              ConfigureMenuButton _ANSI_ARGS_((Tcl_Interp *interp,  static int              ConfigureMenuButton _ANSI_ARGS_((Tcl_Interp *interp,
174                              TkMenuButton *mbPtr, int objc,                              TkMenuButton *mbPtr, int objc,
175                              Tcl_Obj *CONST objv[]));                              Tcl_Obj *CONST objv[]));
176  static void             DestroyMenuButton _ANSI_ARGS_((char *memPtr));  static void             DestroyMenuButton _ANSI_ARGS_((char *memPtr));
177    
178  /*  /*
179   *--------------------------------------------------------------   *--------------------------------------------------------------
180   *   *
181   * Tk_MenubuttonObjCmd --   * Tk_MenubuttonObjCmd --
182   *   *
183   *      This procedure is invoked to process the "button", "label",   *      This procedure is invoked to process the "button", "label",
184   *      "radiobutton", and "checkbutton" Tcl commands.  See the   *      "radiobutton", and "checkbutton" Tcl commands.  See the
185   *      user documentation for details on what it does.   *      user documentation for details on what it does.
186   *   *
187   * Results:   * Results:
188   *      A standard Tcl result.   *      A standard Tcl result.
189   *   *
190   * Side effects:   * Side effects:
191   *      See the user documentation.   *      See the user documentation.
192   *   *
193   *--------------------------------------------------------------   *--------------------------------------------------------------
194   */   */
195    
196  int  int
197  Tk_MenubuttonObjCmd(clientData, interp, objc, objv)  Tk_MenubuttonObjCmd(clientData, interp, objc, objv)
198      ClientData clientData;      /* Either NULL or pointer to      ClientData clientData;      /* Either NULL or pointer to
199                                   * option table. */                                   * option table. */
200      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
201      int objc;                   /* Number of arguments. */      int objc;                   /* Number of arguments. */
202      Tcl_Obj *CONST objv[];      /* Argument objects. */      Tcl_Obj *CONST objv[];      /* Argument objects. */
203  {  {
204      register TkMenuButton *mbPtr;      register TkMenuButton *mbPtr;
205      Tk_OptionTable optionTable;      Tk_OptionTable optionTable;
206      Tk_Window tkwin;      Tk_Window tkwin;
207    
208      optionTable = (Tk_OptionTable) clientData;      optionTable = (Tk_OptionTable) clientData;
209      if (optionTable == NULL) {      if (optionTable == NULL) {
210          Tcl_CmdInfo info;          Tcl_CmdInfo info;
211          char *name;          char *name;
212    
213          /*          /*
214           * We haven't created the option table for this widget class           * We haven't created the option table for this widget class
215           * yet.  Do it now and save the table as the clientData for           * yet.  Do it now and save the table as the clientData for
216           * the command, so we'll have access to it in future           * the command, so we'll have access to it in future
217           * invocations of the command.           * invocations of the command.
218           */           */
219    
220          optionTable = Tk_CreateOptionTable(interp, optionSpecs);          optionTable = Tk_CreateOptionTable(interp, optionSpecs);
221          name = Tcl_GetString(objv[0]);          name = Tcl_GetString(objv[0]);
222          Tcl_GetCommandInfo(interp, name, &info);          Tcl_GetCommandInfo(interp, name, &info);
223          info.objClientData = (ClientData) optionTable;          info.objClientData = (ClientData) optionTable;
224          Tcl_SetCommandInfo(interp, name, &info);          Tcl_SetCommandInfo(interp, name, &info);
225      }      }
226    
227      if (objc < 2) {      if (objc < 2) {
228          Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");          Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
229          return TCL_ERROR;          return TCL_ERROR;
230      }      }
231    
232      /*      /*
233       * Create the new window.       * Create the new window.
234       */       */
235    
236      tkwin = Tk_CreateWindowFromPath(interp,      tkwin = Tk_CreateWindowFromPath(interp,
237          Tk_MainWindow(interp), Tcl_GetString(objv[1]), (char *) NULL);          Tk_MainWindow(interp), Tcl_GetString(objv[1]), (char *) NULL);
238      if (tkwin == NULL) {      if (tkwin == NULL) {
239          return TCL_ERROR;          return TCL_ERROR;
240      }      }
241    
242      Tk_SetClass(tkwin, "Menubutton");      Tk_SetClass(tkwin, "Menubutton");
243      mbPtr = TkpCreateMenuButton(tkwin);      mbPtr = TkpCreateMenuButton(tkwin);
244    
245      TkSetClassProcs(tkwin, &tkpMenubuttonClass, (ClientData) mbPtr);      TkSetClassProcs(tkwin, &tkpMenubuttonClass, (ClientData) mbPtr);
246    
247      /*      /*
248       * Initialize the data structure for the button.       * Initialize the data structure for the button.
249       */       */
250    
251      mbPtr->tkwin = tkwin;      mbPtr->tkwin = tkwin;
252      mbPtr->display = Tk_Display (tkwin);      mbPtr->display = Tk_Display (tkwin);
253      mbPtr->interp = interp;      mbPtr->interp = interp;
254      mbPtr->widgetCmd = Tcl_CreateObjCommand(interp,      mbPtr->widgetCmd = Tcl_CreateObjCommand(interp,
255              Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd,              Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd,
256              (ClientData) mbPtr, MenuButtonCmdDeletedProc);              (ClientData) mbPtr, MenuButtonCmdDeletedProc);
257      mbPtr->optionTable = optionTable;      mbPtr->optionTable = optionTable;
258      mbPtr->menuName = NULL;      mbPtr->menuName = NULL;
259      mbPtr->text = NULL;      mbPtr->text = NULL;
260      mbPtr->underline = -1;      mbPtr->underline = -1;
261      mbPtr->textVarName = NULL;      mbPtr->textVarName = NULL;
262      mbPtr->bitmap = None;      mbPtr->bitmap = None;
263      mbPtr->imageString = NULL;      mbPtr->imageString = NULL;
264      mbPtr->image = NULL;      mbPtr->image = NULL;
265      mbPtr->state = STATE_NORMAL;      mbPtr->state = STATE_NORMAL;
266      mbPtr->normalBorder = NULL;      mbPtr->normalBorder = NULL;
267      mbPtr->activeBorder = NULL;      mbPtr->activeBorder = NULL;
268      mbPtr->borderWidth = 0;      mbPtr->borderWidth = 0;
269      mbPtr->relief = TK_RELIEF_FLAT;      mbPtr->relief = TK_RELIEF_FLAT;
270      mbPtr->highlightWidth = 0;      mbPtr->highlightWidth = 0;
271      mbPtr->highlightBgColorPtr = NULL;      mbPtr->highlightBgColorPtr = NULL;
272      mbPtr->highlightColorPtr = NULL;      mbPtr->highlightColorPtr = NULL;
273      mbPtr->inset = 0;      mbPtr->inset = 0;
274      mbPtr->tkfont = NULL;      mbPtr->tkfont = NULL;
275      mbPtr->normalFg = NULL;      mbPtr->normalFg = NULL;
276      mbPtr->activeFg = NULL;      mbPtr->activeFg = NULL;
277      mbPtr->disabledFg = NULL;      mbPtr->disabledFg = NULL;
278      mbPtr->normalTextGC = None;      mbPtr->normalTextGC = None;
279      mbPtr->activeTextGC = None;      mbPtr->activeTextGC = None;
280      mbPtr->gray = None;      mbPtr->gray = None;
281      mbPtr->disabledGC = None;      mbPtr->disabledGC = None;
282      mbPtr->leftBearing = 0;      mbPtr->leftBearing = 0;
283      mbPtr->rightBearing = 0;      mbPtr->rightBearing = 0;
284      mbPtr->widthString = NULL;      mbPtr->widthString = NULL;
285      mbPtr->heightString = NULL;      mbPtr->heightString = NULL;
286      mbPtr->width = 0;      mbPtr->width = 0;
287      mbPtr->width = 0;      mbPtr->width = 0;
288      mbPtr->wrapLength = 0;      mbPtr->wrapLength = 0;
289      mbPtr->padX = 0;      mbPtr->padX = 0;
290      mbPtr->padY = 0;      mbPtr->padY = 0;
291      mbPtr->anchor = TK_ANCHOR_CENTER;      mbPtr->anchor = TK_ANCHOR_CENTER;
292      mbPtr->justify = TK_JUSTIFY_CENTER;      mbPtr->justify = TK_JUSTIFY_CENTER;
293      mbPtr->textLayout = NULL;      mbPtr->textLayout = NULL;
294      mbPtr->indicatorOn = 0;      mbPtr->indicatorOn = 0;
295      mbPtr->indicatorWidth = 0;      mbPtr->indicatorWidth = 0;
296      mbPtr->indicatorHeight = 0;      mbPtr->indicatorHeight = 0;
297      mbPtr->direction = DIRECTION_FLUSH;      mbPtr->direction = DIRECTION_FLUSH;
298      mbPtr->cursor = None;      mbPtr->cursor = None;
299      mbPtr->takeFocus = NULL;      mbPtr->takeFocus = NULL;
300      mbPtr->flags = 0;      mbPtr->flags = 0;
301    
302      Tk_CreateEventHandler(mbPtr->tkwin,      Tk_CreateEventHandler(mbPtr->tkwin,
303              ExposureMask|StructureNotifyMask|FocusChangeMask,              ExposureMask|StructureNotifyMask|FocusChangeMask,
304              MenuButtonEventProc, (ClientData) mbPtr);              MenuButtonEventProc, (ClientData) mbPtr);
305    
306      if (Tk_InitOptions(interp, (char *) mbPtr, optionTable, tkwin)      if (Tk_InitOptions(interp, (char *) mbPtr, optionTable, tkwin)
307              != TCL_OK) {              != TCL_OK) {
308          Tk_DestroyWindow(mbPtr->tkwin);          Tk_DestroyWindow(mbPtr->tkwin);
309          return TCL_ERROR;          return TCL_ERROR;
310      }      }
311    
312      if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) {      if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) {
313          Tk_DestroyWindow(mbPtr->tkwin);          Tk_DestroyWindow(mbPtr->tkwin);
314          return TCL_ERROR;          return TCL_ERROR;
315      }      }
316    
317      Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(mbPtr->tkwin),      Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(mbPtr->tkwin),
318              -1);              -1);
319      return TCL_OK;      return TCL_OK;
320  }  }
321    
322  /*  /*
323   *--------------------------------------------------------------   *--------------------------------------------------------------
324   *   *
325   * MenuButtonWidgetObjCmd --   * MenuButtonWidgetObjCmd --
326   *   *
327   *      This procedure is invoked to process the Tcl command   *      This procedure is invoked to process the Tcl command
328   *      that corresponds to a widget managed by this module.   *      that corresponds to a widget managed by this module.
329   *      See the user documentation for details on what it does.   *      See the user documentation for details on what it does.
330   *   *
331   * Results:   * Results:
332   *      A standard Tcl result.   *      A standard Tcl result.
333   *   *
334   * Side effects:   * Side effects:
335   *      See the user documentation.   *      See the user documentation.
336   *   *
337   *--------------------------------------------------------------   *--------------------------------------------------------------
338   */   */
339    
340  static int  static int
341  MenuButtonWidgetObjCmd(clientData, interp, objc, objv)  MenuButtonWidgetObjCmd(clientData, interp, objc, objv)
342      ClientData clientData;      /* Information about button widget. */      ClientData clientData;      /* Information about button widget. */
343      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
344      int objc;                   /* Number of arguments. */      int objc;                   /* Number of arguments. */
345      Tcl_Obj *CONST objv[];      /* Argument objects. */      Tcl_Obj *CONST objv[];      /* Argument objects. */
346  {  {
347      register TkMenuButton *mbPtr = (TkMenuButton *) clientData;      register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
348      int result, index;      int result, index;
349      Tcl_Obj *objPtr;      Tcl_Obj *objPtr;
350    
351      if (objc < 2) {      if (objc < 2) {
352          Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");          Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
353          return TCL_ERROR;          return TCL_ERROR;
354      }      }
355      result = Tcl_GetIndexFromObj(interp, objv[1],      result = Tcl_GetIndexFromObj(interp, objv[1],
356              commandNames, "option", 0, &index);              commandNames, "option", 0, &index);
357      if (result != TCL_OK) {      if (result != TCL_OK) {
358          return result;          return result;
359      }      }
360      Tcl_Preserve((ClientData) mbPtr);      Tcl_Preserve((ClientData) mbPtr);
361    
362      switch (index) {      switch (index) {
363          case COMMAND_CGET: {          case COMMAND_CGET: {
364              if (objc != 3) {              if (objc != 3) {
365                  Tcl_WrongNumArgs(interp, 1, objv, "cget option");                  Tcl_WrongNumArgs(interp, 1, objv, "cget option");
366              goto error;              goto error;
367              }              }
368    
369              objPtr = Tk_GetOptionValue(interp, (char *) mbPtr,              objPtr = Tk_GetOptionValue(interp, (char *) mbPtr,
370                      mbPtr->optionTable, objv[2], mbPtr->tkwin);                      mbPtr->optionTable, objv[2], mbPtr->tkwin);
371              if (objPtr == NULL) {              if (objPtr == NULL) {
372                  goto error;                  goto error;
373              } else {              } else {
374                  Tcl_SetObjResult(interp, objPtr);                  Tcl_SetObjResult(interp, objPtr);
375              }              }
376              break;              break;
377          }          }
378    
379          case COMMAND_CONFIGURE: {          case COMMAND_CONFIGURE: {
380              if (objc <= 3) {              if (objc <= 3) {
381                  objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr,                  objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr,
382                          mbPtr->optionTable,                          mbPtr->optionTable,
383                          (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,                          (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
384                          mbPtr->tkwin);                          mbPtr->tkwin);
385                  if (objPtr == NULL) {                  if (objPtr == NULL) {
386                      goto error;                      goto error;
387                  } else {                  } else {
388                      Tcl_SetObjResult(interp, objPtr);                      Tcl_SetObjResult(interp, objPtr);
389                  }                  }
390              } else {              } else {
391                  result = ConfigureMenuButton(interp, mbPtr, objc-2,                  result = ConfigureMenuButton(interp, mbPtr, objc-2,
392                          objv+2);                          objv+2);
393              }              }
394              break;              break;
395          }          }
396      }      }
397      Tcl_Release((ClientData) mbPtr);      Tcl_Release((ClientData) mbPtr);
398      return result;      return result;
399    
400      error:      error:
401      Tcl_Release((ClientData) mbPtr);      Tcl_Release((ClientData) mbPtr);
402      return TCL_ERROR;      return TCL_ERROR;
403  }  }
404    
405  /*  /*
406   *----------------------------------------------------------------------   *----------------------------------------------------------------------
407   *   *
408   * DestroyMenuButton --   * DestroyMenuButton --
409   *   *
410   *      This procedure is invoked to recycle all of the resources   *      This procedure is invoked to recycle all of the resources
411   *      associated with a menubutton widget.  It is invoked as a   *      associated with a menubutton widget.  It is invoked as a
412   *      when-idle handler in order to make sure that there is no   *      when-idle handler in order to make sure that there is no
413   *      other use of the menubutton pending at the time of the deletion.   *      other use of the menubutton pending at the time of the deletion.
414   *   *
415   * Results:   * Results:
416   *      None.   *      None.
417   *   *
418   * Side effects:   * Side effects:
419   *      Everything associated with the widget is freed up.   *      Everything associated with the widget is freed up.
420   *   *
421   *----------------------------------------------------------------------   *----------------------------------------------------------------------
422   */   */
423    
424  static void  static void
425  DestroyMenuButton(memPtr)  DestroyMenuButton(memPtr)
426      char *memPtr;               /* Info about button widget. */      char *memPtr;               /* Info about button widget. */
427  {  {
428      register TkMenuButton *mbPtr = (TkMenuButton *) memPtr;      register TkMenuButton *mbPtr = (TkMenuButton *) memPtr;
429      TkpDestroyMenuButton(mbPtr);      TkpDestroyMenuButton(mbPtr);
430    
431      if (mbPtr->flags & REDRAW_PENDING) {      if (mbPtr->flags & REDRAW_PENDING) {
432          Tcl_CancelIdleCall(TkpDisplayMenuButton, (ClientData) mbPtr);          Tcl_CancelIdleCall(TkpDisplayMenuButton, (ClientData) mbPtr);
433      }      }
434    
435      /*      /*
436       * Free up all the stuff that requires special handling, then       * Free up all the stuff that requires special handling, then
437       * let Tk_FreeOptions handle all the standard option-related       * let Tk_FreeOptions handle all the standard option-related
438       * stuff.       * stuff.
439       */       */
440    
441      Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd);      Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd);
442      if (mbPtr->textVarName != NULL) {      if (mbPtr->textVarName != NULL) {
443          Tcl_UntraceVar(mbPtr->interp, mbPtr->textVarName,          Tcl_UntraceVar(mbPtr->interp, mbPtr->textVarName,
444                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
445                  MenuButtonTextVarProc, (ClientData) mbPtr);                  MenuButtonTextVarProc, (ClientData) mbPtr);
446      }      }
447      if (mbPtr->image != NULL) {      if (mbPtr->image != NULL) {
448          Tk_FreeImage(mbPtr->image);          Tk_FreeImage(mbPtr->image);
449      }      }
450      if (mbPtr->normalTextGC != None) {      if (mbPtr->normalTextGC != None) {
451          Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);          Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
452      }      }
453      if (mbPtr->activeTextGC != None) {      if (mbPtr->activeTextGC != None) {
454          Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);          Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
455      }      }
456      if (mbPtr->disabledGC != None) {      if (mbPtr->disabledGC != None) {
457          Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);          Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
458      }      }
459      if (mbPtr->gray != None) {      if (mbPtr->gray != None) {
460          Tk_FreeBitmap(mbPtr->display, mbPtr->gray);          Tk_FreeBitmap(mbPtr->display, mbPtr->gray);
461      }      }
462      if (mbPtr->textLayout != NULL) {      if (mbPtr->textLayout != NULL) {
463          Tk_FreeTextLayout(mbPtr->textLayout);          Tk_FreeTextLayout(mbPtr->textLayout);
464      }      }
465      Tk_FreeConfigOptions((char *) mbPtr, mbPtr->optionTable,      Tk_FreeConfigOptions((char *) mbPtr, mbPtr->optionTable,
466              mbPtr->tkwin);              mbPtr->tkwin);
467      mbPtr->tkwin = NULL;      mbPtr->tkwin = NULL;
468      Tcl_EventuallyFree((ClientData) mbPtr, TCL_DYNAMIC);      Tcl_EventuallyFree((ClientData) mbPtr, TCL_DYNAMIC);
469  }  }
470    
471  /*  /*
472   *----------------------------------------------------------------------   *----------------------------------------------------------------------
473   *   *
474   * ConfigureMenuButton --   * ConfigureMenuButton --
475   *   *
476   *      This procedure is called to process an argv/argc list, plus   *      This procedure is called to process an argv/argc list, plus
477   *      the Tk option database, in order to configure (or   *      the Tk option database, in order to configure (or
478   *      reconfigure) a menubutton widget.   *      reconfigure) a menubutton widget.
479   *   *
480   * Results:   * Results:
481   *      The return value is a standard Tcl result.  If TCL_ERROR is   *      The return value is a standard Tcl result.  If TCL_ERROR is
482   *      returned, then the interp's result contains an error message.   *      returned, then the interp's result contains an error message.
483   *   *
484   * Side effects:   * Side effects:
485   *      Configuration information, such as text string, colors, font,   *      Configuration information, such as text string, colors, font,
486   *      etc. get set for mbPtr;  old resources get freed, if there   *      etc. get set for mbPtr;  old resources get freed, if there
487   *      were any.  The menubutton is redisplayed.   *      were any.  The menubutton is redisplayed.
488   *   *
489   *----------------------------------------------------------------------   *----------------------------------------------------------------------
490   */   */
491    
492  static int  static int
493  ConfigureMenuButton(interp, mbPtr, objc, objv)  ConfigureMenuButton(interp, mbPtr, objc, objv)
494      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
495      register TkMenuButton *mbPtr;            register TkMenuButton *mbPtr;      
496                                  /* Information about widget;  may or may                                  /* Information about widget;  may or may
497                                   * not already have values for some                                   * not already have values for some
498                                   * fields. */                                   * fields. */
499      int objc;                   /* Number of valid entries in objv. */      int objc;                   /* Number of valid entries in objv. */
500      Tcl_Obj *CONST objv[];      /* Arguments. */      Tcl_Obj *CONST objv[];      /* Arguments. */
501  {  {
502      Tk_SavedOptions savedOptions;      Tk_SavedOptions savedOptions;
503      Tcl_Obj *errorResult = NULL;      Tcl_Obj *errorResult = NULL;
504      int error;      int error;
505      Tk_Image image;      Tk_Image image;
506    
507      /*      /*
508       * Eliminate any existing trace on variables monitored by the       * Eliminate any existing trace on variables monitored by the
509       * menubutton.       * menubutton.
510       */       */
511    
512      if (mbPtr->textVarName != NULL) {      if (mbPtr->textVarName != NULL) {
513          Tcl_UntraceVar(interp, mbPtr->textVarName,          Tcl_UntraceVar(interp, mbPtr->textVarName,
514                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
515                  MenuButtonTextVarProc, (ClientData) mbPtr);                  MenuButtonTextVarProc, (ClientData) mbPtr);
516      }      }
517    
518      /*      /*
519       * The following loop is potentially executed twice.  During the       * The following loop is potentially executed twice.  During the
520       * first pass configuration options get set to their new values.       * first pass configuration options get set to their new values.
521       * If there is an error in this pass, we execute a second pass       * If there is an error in this pass, we execute a second pass
522       * to restore all the options to their previous values.       * to restore all the options to their previous values.
523       */       */
524    
525      for (error = 0; error <= 1; error++) {      for (error = 0; error <= 1; error++) {
526          if (!error) {          if (!error) {
527              /*              /*
528               * First pass: set options to new values.               * First pass: set options to new values.
529               */               */
530    
531              if (Tk_SetOptions(interp, (char *) mbPtr,              if (Tk_SetOptions(interp, (char *) mbPtr,
532                      mbPtr->optionTable, objc, objv,                      mbPtr->optionTable, objc, objv,
533                      mbPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {                      mbPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
534                  continue;                  continue;
535              }              }
536          } else {          } else {
537              /*              /*
538               * Second pass: restore options to old values.               * Second pass: restore options to old values.
539               */               */
540    
541              errorResult = Tcl_GetObjResult(interp);              errorResult = Tcl_GetObjResult(interp);
542              Tcl_IncrRefCount(errorResult);              Tcl_IncrRefCount(errorResult);
543              Tk_RestoreSavedOptions(&savedOptions);              Tk_RestoreSavedOptions(&savedOptions);
544          }          }
545    
546          /*          /*
547           * A few options need special processing, such as setting the           * A few options need special processing, such as setting the
548           * background from a 3-D border, or filling in complicated           * background from a 3-D border, or filling in complicated
549           * defaults that couldn't be specified to Tk_SetOptions.           * defaults that couldn't be specified to Tk_SetOptions.
550           */           */
551    
552          if ((mbPtr->state == STATE_ACTIVE)          if ((mbPtr->state == STATE_ACTIVE)
553                  && !Tk_StrictMotif(mbPtr->tkwin)) {                  && !Tk_StrictMotif(mbPtr->tkwin)) {
554              Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);              Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);
555          } else {          } else {
556              Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);              Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);
557          }          }
558    
559          if (mbPtr->highlightWidth < 0) {          if (mbPtr->highlightWidth < 0) {
560              mbPtr->highlightWidth = 0;              mbPtr->highlightWidth = 0;
561          }          }
562    
563          if (mbPtr->padX < 0) {          if (mbPtr->padX < 0) {
564              mbPtr->padX = 0;              mbPtr->padX = 0;
565          }          }
566          if (mbPtr->padY < 0) {          if (mbPtr->padY < 0) {
567              mbPtr->padY = 0;              mbPtr->padY = 0;
568          }          }
569    
570          /*          /*
571           * Get the image for the widget, if there is one.  Allocate the           * Get the image for the widget, if there is one.  Allocate the
572           * new image before freeing the old one, so that the reference           * new image before freeing the old one, so that the reference
573           * count doesn't go to zero and cause image data to be discarded.           * count doesn't go to zero and cause image data to be discarded.
574           */           */
575    
576          if (mbPtr->imageString != NULL) {          if (mbPtr->imageString != NULL) {
577              image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,              image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,
578                      mbPtr->imageString, MenuButtonImageProc,                      mbPtr->imageString, MenuButtonImageProc,
579                      (ClientData) mbPtr);                      (ClientData) mbPtr);
580              if (image == NULL) {              if (image == NULL) {
581                  return TCL_ERROR;                  return TCL_ERROR;
582              }              }
583          } else {          } else {
584              image = NULL;              image = NULL;
585          }          }
586          if (mbPtr->image != NULL) {          if (mbPtr->image != NULL) {
587              Tk_FreeImage(mbPtr->image);              Tk_FreeImage(mbPtr->image);
588          }          }
589          mbPtr->image = image;          mbPtr->image = image;
590    
591          /*          /*
592           * Recompute the geometry for the button.           * Recompute the geometry for the button.
593           */           */
594    
595          if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {          if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {
596              if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString,              if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString,
597                      &mbPtr->width) != TCL_OK) {                      &mbPtr->width) != TCL_OK) {
598                  widthError:                  widthError:
599                  Tcl_AddErrorInfo(interp, "\n    (processing -width option)");                  Tcl_AddErrorInfo(interp, "\n    (processing -width option)");
600                  continue;                  continue;
601              }              }
602              if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString,              if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString,
603                      &mbPtr->height) != TCL_OK) {                      &mbPtr->height) != TCL_OK) {
604                  heightError:                  heightError:
605                  Tcl_AddErrorInfo(interp, "\n    (processing -height option)");                  Tcl_AddErrorInfo(interp, "\n    (processing -height option)");
606                  continue;                  continue;
607              }              }
608          } else {          } else {
609              if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width)              if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width)
610                      != TCL_OK) {                      != TCL_OK) {
611                  goto widthError;                  goto widthError;
612              }              }
613              if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height)              if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height)
614                      != TCL_OK) {                      != TCL_OK) {
615                  goto heightError;                  goto heightError;
616              }              }
617          }          }
618          break;          break;
619      }      }
620    
621      if (!error) {      if (!error) {
622        Tk_FreeSavedOptions(&savedOptions);        Tk_FreeSavedOptions(&savedOptions);
623      }      }
624    
625      if ((mbPtr->image == NULL) && (mbPtr->bitmap == None)      if ((mbPtr->image == NULL) && (mbPtr->bitmap == None)
626              && (mbPtr->textVarName != NULL)) {              && (mbPtr->textVarName != NULL)) {
627    
628        /*        /*
629         * The menubutton displays the value of a variable.           * The menubutton displays the value of a variable.  
630         * Set up a trace to watch for any changes in it, create         * Set up a trace to watch for any changes in it, create
631         * the variable if it doesn't exist, and fetch its         * the variable if it doesn't exist, and fetch its
632         * current value.         * current value.
633         */         */
634    
635        char *value;        char *value;
636    
637        value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);        value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);
638        if (value == NULL) {        if (value == NULL) {
639            Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,            Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,
640                       TCL_GLOBAL_ONLY);                       TCL_GLOBAL_ONLY);
641        } else {        } else {
642            if (mbPtr->text != NULL) {            if (mbPtr->text != NULL) {
643                ckfree(mbPtr->text);                ckfree(mbPtr->text);
644            }            }
645            mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));            mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
646            strcpy(mbPtr->text, value);            strcpy(mbPtr->text, value);
647        }        }
648        Tcl_TraceVar(interp, mbPtr->textVarName,        Tcl_TraceVar(interp, mbPtr->textVarName,
649                     TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                     TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
650                     MenuButtonTextVarProc, (ClientData) mbPtr);                     MenuButtonTextVarProc, (ClientData) mbPtr);
651      }      }
652    
653      TkMenuButtonWorldChanged((ClientData) mbPtr);      TkMenuButtonWorldChanged((ClientData) mbPtr);
654      if (error) {      if (error) {
655          Tcl_SetObjResult(interp, errorResult);          Tcl_SetObjResult(interp, errorResult);
656          Tcl_DecrRefCount(errorResult);          Tcl_DecrRefCount(errorResult);
657          return TCL_ERROR;          return TCL_ERROR;
658      } else {      } else {
659          return TCL_OK;          return TCL_OK;
660      }      }
661  }  }
662    
663  /*  /*
664   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
665   *   *
666   * TkMenuButtonWorldChanged --   * TkMenuButtonWorldChanged --
667   *   *
668   *      This procedure is called when the world has changed in some   *      This procedure is called when the world has changed in some
669   *      way and the widget needs to recompute all its graphics contexts   *      way and the widget needs to recompute all its graphics contexts
670   *      and determine its new geometry.   *      and determine its new geometry.
671   *   *
672   * Results:   * Results:
673   *      None.   *      None.
674   *   *
675   * Side effects:   * Side effects:
676   *      TkMenuButton will be relayed out and redisplayed.   *      TkMenuButton will be relayed out and redisplayed.
677   *   *
678   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
679   */   */
680    
681  void  void
682  TkMenuButtonWorldChanged(instanceData)  TkMenuButtonWorldChanged(instanceData)
683      ClientData instanceData;    /* Information about widget. */      ClientData instanceData;    /* Information about widget. */
684  {  {
685      XGCValues gcValues;      XGCValues gcValues;
686      GC gc;      GC gc;
687      unsigned long mask;      unsigned long mask;
688      TkMenuButton *mbPtr;      TkMenuButton *mbPtr;
689    
690      mbPtr = (TkMenuButton *) instanceData;      mbPtr = (TkMenuButton *) instanceData;
691    
692      gcValues.font = Tk_FontId(mbPtr->tkfont);      gcValues.font = Tk_FontId(mbPtr->tkfont);
693      gcValues.foreground = mbPtr->normalFg->pixel;      gcValues.foreground = mbPtr->normalFg->pixel;
694      gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;      gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;
695    
696      /*      /*
697       * Note: GraphicsExpose events are disabled in GC's because they're       * Note: GraphicsExpose events are disabled in GC's because they're
698       * used to copy stuff from an off-screen pixmap onto the screen (we know       * used to copy stuff from an off-screen pixmap onto the screen (we know
699       * that there's no problem with obscured areas).       * that there's no problem with obscured areas).
700       */       */
701    
702      gcValues.graphics_exposures = False;      gcValues.graphics_exposures = False;
703      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
704      gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);      gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
705      if (mbPtr->normalTextGC != None) {      if (mbPtr->normalTextGC != None) {
706          Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);          Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
707      }      }
708      mbPtr->normalTextGC = gc;      mbPtr->normalTextGC = gc;
709    
710      gcValues.font = Tk_FontId(mbPtr->tkfont);      gcValues.font = Tk_FontId(mbPtr->tkfont);
711      gcValues.foreground = mbPtr->activeFg->pixel;      gcValues.foreground = mbPtr->activeFg->pixel;
712      gcValues.background = Tk_3DBorderColor(mbPtr->activeBorder)->pixel;      gcValues.background = Tk_3DBorderColor(mbPtr->activeBorder)->pixel;
713      mask = GCForeground | GCBackground | GCFont;      mask = GCForeground | GCBackground | GCFont;
714      gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);      gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
715      if (mbPtr->activeTextGC != None) {      if (mbPtr->activeTextGC != None) {
716          Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);          Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
717      }      }
718      mbPtr->activeTextGC = gc;      mbPtr->activeTextGC = gc;
719    
720      gcValues.font = Tk_FontId(mbPtr->tkfont);      gcValues.font = Tk_FontId(mbPtr->tkfont);
721      gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;      gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;
722      if ((mbPtr->disabledFg != NULL) && (mbPtr->imageString == NULL)) {      if ((mbPtr->disabledFg != NULL) && (mbPtr->imageString == NULL)) {
723          gcValues.foreground = mbPtr->disabledFg->pixel;          gcValues.foreground = mbPtr->disabledFg->pixel;
724          mask = GCForeground | GCBackground | GCFont;          mask = GCForeground | GCBackground | GCFont;
725      } else {      } else {
726          gcValues.foreground = gcValues.background;          gcValues.foreground = gcValues.background;
727          mask = GCForeground;          mask = GCForeground;
728          if (mbPtr->gray == None) {          if (mbPtr->gray == None) {
729              mbPtr->gray = Tk_GetBitmap(NULL, mbPtr->tkwin,              mbPtr->gray = Tk_GetBitmap(NULL, mbPtr->tkwin,
730                      Tk_GetUid("gray50"));                      Tk_GetUid("gray50"));
731          }          }
732          if (mbPtr->gray != None) {          if (mbPtr->gray != None) {
733              gcValues.fill_style = FillStippled;              gcValues.fill_style = FillStippled;
734              gcValues.stipple = mbPtr->gray;              gcValues.stipple = mbPtr->gray;
735              mask |= GCFillStyle | GCStipple;              mask |= GCFillStyle | GCStipple;
736          }          }
737      }      }
738      gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);      gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
739      if (mbPtr->disabledGC != None) {      if (mbPtr->disabledGC != None) {
740          Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);          Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
741      }      }
742      mbPtr->disabledGC = gc;      mbPtr->disabledGC = gc;
743    
744      TkpComputeMenuButtonGeometry(mbPtr);      TkpComputeMenuButtonGeometry(mbPtr);
745    
746      /*      /*
747       * Lastly, arrange for the button to be redisplayed.       * Lastly, arrange for the button to be redisplayed.
748       */       */
749    
750      if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {      if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {
751          Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);          Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);
752          mbPtr->flags |= REDRAW_PENDING;          mbPtr->flags |= REDRAW_PENDING;
753      }      }
754  }  }
755    
756  /*  /*
757   *--------------------------------------------------------------   *--------------------------------------------------------------
758   *   *
759   * MenuButtonEventProc --   * MenuButtonEventProc --
760   *   *
761   *      This procedure is invoked by the Tk dispatcher for various   *      This procedure is invoked by the Tk dispatcher for various
762   *      events on buttons.   *      events on buttons.
763   *   *
764   * Results:   * Results:
765   *      None.   *      None.
766   *   *
767   * Side effects:   * Side effects:
768   *      When the window gets deleted, internal structures get   *      When the window gets deleted, internal structures get
769   *      cleaned up.  When it gets exposed, it is redisplayed.   *      cleaned up.  When it gets exposed, it is redisplayed.
770   *   *
771   *--------------------------------------------------------------   *--------------------------------------------------------------
772   */   */
773    
774  static void  static void
775  MenuButtonEventProc(clientData, eventPtr)  MenuButtonEventProc(clientData, eventPtr)
776      ClientData clientData;      /* Information about window. */      ClientData clientData;      /* Information about window. */
777      XEvent *eventPtr;           /* Information about event. */      XEvent *eventPtr;           /* Information about event. */
778  {  {
779      TkMenuButton *mbPtr = (TkMenuButton *) clientData;      TkMenuButton *mbPtr = (TkMenuButton *) clientData;
780      if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {      if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
781          goto redraw;          goto redraw;
782      } else if (eventPtr->type == ConfigureNotify) {      } else if (eventPtr->type == ConfigureNotify) {
783          /*          /*
784           * Must redraw after size changes, since layout could have changed           * Must redraw after size changes, since layout could have changed
785           * and borders will need to be redrawn.           * and borders will need to be redrawn.
786           */           */
787    
788          goto redraw;          goto redraw;
789      } else if (eventPtr->type == DestroyNotify) {      } else if (eventPtr->type == DestroyNotify) {
790          DestroyMenuButton((char *) mbPtr);          DestroyMenuButton((char *) mbPtr);
791      } else if (eventPtr->type == FocusIn) {      } else if (eventPtr->type == FocusIn) {
792          if (eventPtr->xfocus.detail != NotifyInferior) {          if (eventPtr->xfocus.detail != NotifyInferior) {
793              mbPtr->flags |= GOT_FOCUS;              mbPtr->flags |= GOT_FOCUS;
794              if (mbPtr->highlightWidth > 0) {              if (mbPtr->highlightWidth > 0) {
795                  goto redraw;                  goto redraw;
796              }              }
797          }          }
798      } else if (eventPtr->type == FocusOut) {      } else if (eventPtr->type == FocusOut) {
799          if (eventPtr->xfocus.detail != NotifyInferior) {          if (eventPtr->xfocus.detail != NotifyInferior) {
800              mbPtr->flags &= ~GOT_FOCUS;              mbPtr->flags &= ~GOT_FOCUS;
801              if (mbPtr->highlightWidth > 0) {              if (mbPtr->highlightWidth > 0) {
802                  goto redraw;                  goto redraw;
803              }              }
804          }          }
805      }      }
806      return;      return;
807    
808      redraw:      redraw:
809      if ((mbPtr->tkwin != NULL) && !(mbPtr->flags & REDRAW_PENDING)) {      if ((mbPtr->tkwin != NULL) && !(mbPtr->flags & REDRAW_PENDING)) {
810          Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);          Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);
811          mbPtr->flags |= REDRAW_PENDING;          mbPtr->flags |= REDRAW_PENDING;
812      }      }
813  }  }
814    
815  /*  /*
816   *----------------------------------------------------------------------   *----------------------------------------------------------------------
817   *   *
818   * MenuButtonCmdDeletedProc --   * MenuButtonCmdDeletedProc --
819   *   *
820   *      This procedure is invoked when a widget command is deleted.  If   *      This procedure is invoked when a widget command is deleted.  If
821   *      the widget isn't already in the process of being destroyed,   *      the widget isn't already in the process of being destroyed,
822   *      this command destroys it.   *      this command destroys it.
823   *   *
824   * Results:   * Results:
825   *      None.   *      None.
826   *   *
827   * Side effects:   * Side effects:
828   *      The widget is destroyed.   *      The widget is destroyed.
829   *   *
830   *----------------------------------------------------------------------   *----------------------------------------------------------------------
831   */   */
832    
833  static void  static void
834  MenuButtonCmdDeletedProc(clientData)  MenuButtonCmdDeletedProc(clientData)
835      ClientData clientData;      /* Pointer to widget record for widget. */      ClientData clientData;      /* Pointer to widget record for widget. */
836  {  {
837      TkMenuButton *mbPtr = (TkMenuButton *) clientData;      TkMenuButton *mbPtr = (TkMenuButton *) clientData;
838      Tk_Window tkwin = mbPtr->tkwin;      Tk_Window tkwin = mbPtr->tkwin;
839    
840      /*      /*
841       * This procedure could be invoked either because the window was       * This procedure could be invoked either because the window was
842       * destroyed and the command was then deleted (in which case tkwin       * destroyed and the command was then deleted (in which case tkwin
843       * is NULL) or because the command was deleted, and then this procedure       * is NULL) or because the command was deleted, and then this procedure
844       * destroys the widget.       * destroys the widget.
845       */       */
846    
847      if (tkwin != NULL) {      if (tkwin != NULL) {
848          Tk_DestroyWindow(tkwin);          Tk_DestroyWindow(tkwin);
849      }      }
850  }  }
851    
852  /*  /*
853   *--------------------------------------------------------------   *--------------------------------------------------------------
854   *   *
855   * MenuButtonTextVarProc --   * MenuButtonTextVarProc --
856   *   *
857   *      This procedure is invoked when someone changes the variable   *      This procedure is invoked when someone changes the variable
858   *      whose contents are to be displayed in a menu button.   *      whose contents are to be displayed in a menu button.
859   *   *
860   * Results:   * Results:
861   *      NULL is always returned.   *      NULL is always returned.
862   *   *
863   * Side effects:   * Side effects:
864   *      The text displayed in the menu button will change to match the   *      The text displayed in the menu button will change to match the
865   *      variable.   *      variable.
866   *   *
867   *--------------------------------------------------------------   *--------------------------------------------------------------
868   */   */
869    
870          /* ARGSUSED */          /* ARGSUSED */
871  static char *  static char *
872  MenuButtonTextVarProc(clientData, interp, name1, name2, flags)  MenuButtonTextVarProc(clientData, interp, name1, name2, flags)
873      ClientData clientData;      /* Information about button. */      ClientData clientData;      /* Information about button. */
874      Tcl_Interp *interp;         /* Interpreter containing variable. */      Tcl_Interp *interp;         /* Interpreter containing variable. */
875      char *name1;                /* Name of variable. */      char *name1;                /* Name of variable. */
876      char *name2;                /* Second part of variable name. */      char *name2;                /* Second part of variable name. */
877      int flags;                  /* Information about what happened. */      int flags;                  /* Information about what happened. */
878  {  {
879      register TkMenuButton *mbPtr = (TkMenuButton *) clientData;      register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
880      char *value;      char *value;
881    
882      /*      /*
883       * If the variable is unset, then immediately recreate it unless       * If the variable is unset, then immediately recreate it unless
884       * the whole interpreter is going away.       * the whole interpreter is going away.
885       */       */
886    
887      if (flags & TCL_TRACE_UNSETS) {      if (flags & TCL_TRACE_UNSETS) {
888          if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {          if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
889              Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,              Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,
890                      TCL_GLOBAL_ONLY);                      TCL_GLOBAL_ONLY);
891              Tcl_TraceVar(interp, mbPtr->textVarName,              Tcl_TraceVar(interp, mbPtr->textVarName,
892                      TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                      TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
893                      MenuButtonTextVarProc, clientData);                      MenuButtonTextVarProc, clientData);
894          }          }
895          return (char *) NULL;          return (char *) NULL;
896      }      }
897    
898      value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);      value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);
899      if (value == NULL) {      if (value == NULL) {
900          value = "";          value = "";
901      }      }
902      if (mbPtr->text != NULL) {      if (mbPtr->text != NULL) {
903          ckfree(mbPtr->text);          ckfree(mbPtr->text);
904      }      }
905      mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));      mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
906      strcpy(mbPtr->text, value);      strcpy(mbPtr->text, value);
907      TkpComputeMenuButtonGeometry(mbPtr);      TkpComputeMenuButtonGeometry(mbPtr);
908    
909      if ((mbPtr->tkwin != NULL) && Tk_IsMapped(mbPtr->tkwin)      if ((mbPtr->tkwin != NULL) && Tk_IsMapped(mbPtr->tkwin)
910              && !(mbPtr->flags & REDRAW_PENDING)) {              && !(mbPtr->flags & REDRAW_PENDING)) {
911          Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);          Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);
912          mbPtr->flags |= REDRAW_PENDING;          mbPtr->flags |= REDRAW_PENDING;
913      }      }
914      return (char *) NULL;      return (char *) NULL;
915  }  }
916    
917  /*  /*
918   *----------------------------------------------------------------------   *----------------------------------------------------------------------
919   *   *
920   * MenuButtonImageProc --   * MenuButtonImageProc --
921   *   *
922   *      This procedure is invoked by the image code whenever the manager   *      This procedure is invoked by the image code whenever the manager
923   *      for an image does something that affects the size of contents   *      for an image does something that affects the size of contents
924   *      of an image displayed in a button.   *      of an image displayed in a button.
925   *   *
926   * Results:   * Results:
927   *      None.   *      None.
928   *   *
929   * Side effects:   * Side effects:
930   *      Arranges for the button to get redisplayed.   *      Arranges for the button to get redisplayed.
931   *   *
932   *----------------------------------------------------------------------   *----------------------------------------------------------------------
933   */   */
934    
935  static void  static void
936  MenuButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight)  MenuButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
937      ClientData clientData;              /* Pointer to widget record. */      ClientData clientData;              /* Pointer to widget record. */
938      int x, y;                           /* Upper left pixel (within image)      int x, y;                           /* Upper left pixel (within image)
939                                           * that must be redisplayed. */                                           * that must be redisplayed. */
940      int width, height;                  /* Dimensions of area to redisplay      int width, height;                  /* Dimensions of area to redisplay
941                                           * (may be <= 0). */                                           * (may be <= 0). */
942      int imgWidth, imgHeight;            /* New dimensions of image. */      int imgWidth, imgHeight;            /* New dimensions of image. */
943  {  {
944      register TkMenuButton *mbPtr = (TkMenuButton *) clientData;      register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
945    
946      if (mbPtr->tkwin != NULL) {      if (mbPtr->tkwin != NULL) {
947          TkpComputeMenuButtonGeometry(mbPtr);          TkpComputeMenuButtonGeometry(mbPtr);
948          if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {          if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {
949              Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);              Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr);
950              mbPtr->flags |= REDRAW_PENDING;              mbPtr->flags |= REDRAW_PENDING;
951          }          }
952      }      }
953  }  }
954    
955  /* End of tkmenubutton.c */  /* End of tkmenubutton.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25