67
67
* cloned cascade menu has to be discarded, and the new one has to be cloned.
74
* used only to test for old config code
77
#define __NO_OLD_CONFIG
71
80
#include "tkPort.h"
72
81
#include "tkMenu.h"
74
83
#define MENU_HASH_KEY "tkMenus"
76
static int menusInitialized; /* Whether or not the hash tables, etc., have
85
typedef struct ThreadSpecificData {
86
int menusInitialized; /* Flag indicates whether thread-specific
87
* elements of the Windows Menu module
88
* have been initialized. */
90
static Tcl_ThreadDataKey dataKey;
80
* Custom option for handling "-state" and "-tile"
93
* The following flag indicates whether the process-wide state for
94
* the Menu module has been intialized. The Mutex protects access to
83
static Tk_CustomOption stateOption = {
86
(ClientData) 1 /* allow "normal", "active" and "disabled" */
89
static Tk_CustomOption tileOption = {
95
static Tk_CustomOption offsetOption = {
98
static int menusInitialized;
99
TCL_DECLARE_MUTEX(menuMutex)
102
102
* Configuration specs for individual menu entries. If this changes, be sure
103
103
* to update code in TkpMenuInit that changes the font string entry.
106
Tk_ConfigSpec tkMenuEntryConfigSpecs[] = {
107
{TK_CONFIG_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
108
DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorder),
109
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
111
{TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
112
DEF_MENU_ENTRY_ACTIVE_FG, Tk_Offset(TkMenuEntry, activeFg),
113
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
115
{TK_CONFIG_CUSTOM, "-activetile", "activeTile", "Tile", (char *) NULL,
116
Tk_Offset(TkMenuEntry, activeTile), COMMAND_MASK|CHECK_BUTTON_MASK|
117
RADIO_BUTTON_MASK|CASCADE_MASK|TK_CONFIG_DONT_SET_DEFAULT,
119
{TK_CONFIG_STRING, "-accelerator", (char *) NULL, (char *) NULL,
120
DEF_MENU_ENTRY_ACCELERATOR, Tk_Offset(TkMenuEntry, accel),
121
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
123
{TK_CONFIG_BORDER, "-background", "background", "Background",
124
DEF_MENU_ENTRY_BG, Tk_Offset(TkMenuEntry, border),
125
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
126
|SEPARATOR_MASK|TEAROFF_MASK|TK_CONFIG_NULL_OK},
127
{TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
129
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
130
{TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
131
DEF_MENU_ENTRY_BITMAP, Tk_Offset(TkMenuEntry, bitmap),
132
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
134
{TK_CONFIG_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
135
DEF_MENU_ENTRY_COLUMN_BREAK, Tk_Offset(TkMenuEntry, columnBreak),
136
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
137
{TK_CONFIG_CALLBACK, "-command", (char *) NULL, (char *) NULL,
138
DEF_MENU_ENTRY_COMMAND, Tk_Offset(TkMenuEntry, command),
139
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
141
{TK_CONFIG_CUSTOM, "-disabledtile", "disabledTile", "Tile", (char *) NULL,
142
Tk_Offset(TkMenuEntry, disabledTile), COMMAND_MASK|CHECK_BUTTON_MASK|
143
RADIO_BUTTON_MASK|CASCADE_MASK|TK_CONFIG_DONT_SET_DEFAULT,
145
{TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
146
DEF_MENU_ENTRY_FONT, Tk_Offset(TkMenuEntry, tkfont),
147
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
149
{TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
150
DEF_MENU_ENTRY_FG, Tk_Offset(TkMenuEntry, fg),
151
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
153
{TK_CONFIG_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
154
DEF_MENU_ENTRY_HIDE_MARGIN, Tk_Offset(TkMenuEntry, hideMargin),
155
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
156
|SEPARATOR_MASK|TEAROFF_MASK},
157
{TK_CONFIG_OBJECT, "-image", (char *) NULL, (char *) NULL,
158
DEF_MENU_ENTRY_IMAGE, Tk_Offset(TkMenuEntry, imageString),
159
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
161
{TK_CONFIG_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
162
DEF_MENU_ENTRY_INDICATOR, Tk_Offset(TkMenuEntry, indicatorOn),
163
CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_DONT_SET_DEFAULT},
164
{TK_CONFIG_STRING, "-label", (char *) NULL, (char *) NULL,
165
DEF_MENU_ENTRY_LABEL, Tk_Offset(TkMenuEntry, label),
166
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
167
{TK_CONFIG_LANGARG, "-menu", (char *) NULL, (char *) NULL,
168
DEF_MENU_ENTRY_MENU, Tk_Offset(TkMenuEntry, name),
169
CASCADE_MASK|TK_CONFIG_NULL_OK},
170
{TK_CONFIG_CUSTOM, "-offset", "offset", "Offset", "0 0",
171
Tk_Offset(TkMenuEntry, tsoffset), COMMAND_MASK|CHECK_BUTTON_MASK|
172
RADIO_BUTTON_MASK|CASCADE_MASK|TK_CONFIG_DONT_SET_DEFAULT,
174
{TK_CONFIG_LANGARG, "-offvalue", (char *) NULL, (char *) NULL,
175
DEF_MENU_ENTRY_OFF_VALUE, Tk_Offset(TkMenuEntry, offValue),
177
{TK_CONFIG_LANGARG, "-onvalue", (char *) NULL, (char *) NULL,
178
DEF_MENU_ENTRY_ON_VALUE, Tk_Offset(TkMenuEntry, onValue),
180
{TK_CONFIG_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
181
DEF_MENU_ENTRY_SELECT, Tk_Offset(TkMenuEntry, indicatorFg),
182
CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
183
{TK_CONFIG_OBJECT, "-selectimage", (char *) NULL, (char *) NULL,
184
DEF_MENU_ENTRY_SELECT_IMAGE, Tk_Offset(TkMenuEntry, selectImageString),
185
CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
186
{TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
187
DEF_MENU_ENTRY_STATE, Tk_Offset(TkMenuEntry, state),
188
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
189
|TEAROFF_MASK|TK_CONFIG_DONT_SET_DEFAULT, &stateOption},
190
{TK_CONFIG_CUSTOM, "-tile", "tile", "Tile", (char *) NULL,
191
Tk_Offset(TkMenuEntry, tile), COMMAND_MASK|CHECK_BUTTON_MASK|
192
RADIO_BUTTON_MASK|CASCADE_MASK|TK_CONFIG_DONT_SET_DEFAULT,
194
{TK_CONFIG_LANGARG, "-value", (char *) NULL, (char *) NULL,
195
DEF_MENU_ENTRY_VALUE, Tk_Offset(TkMenuEntry, onValue),
196
RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
197
{TK_CONFIG_SCALARVAR, "-variable", (char *) NULL, (char *) NULL,
198
DEF_MENU_ENTRY_CHECK_VARIABLE, Tk_Offset(TkMenuEntry, variable),
199
CHECK_BUTTON_MASK|TK_CONFIG_NULL_OK},
200
{TK_CONFIG_SCALARVAR, "-variable", (char *) NULL, (char *) NULL,
201
DEF_MENU_ENTRY_RADIO_VARIABLE, Tk_Offset(TkMenuEntry, variable),
203
{TK_CONFIG_INT, "-underline", (char *) NULL, (char *) NULL,
204
DEF_MENU_ENTRY_UNDERLINE, Tk_Offset(TkMenuEntry, underline),
205
COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
206
|TK_CONFIG_DONT_SET_DEFAULT},
207
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
212
* Configuration specs valid for the menu as a whole. If this changes, be sure
213
* to update code in TkpMenuInit that changes the font string entry.
216
Tk_ConfigSpec tkMenuConfigSpecs[] = {
217
{TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
218
DEF_MENU_ACTIVE_BG_COLOR, Tk_Offset(TkMenu, activeBorder),
219
TK_CONFIG_COLOR_ONLY},
220
{TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
221
DEF_MENU_ACTIVE_BG_MONO, Tk_Offset(TkMenu, activeBorder),
222
TK_CONFIG_MONO_ONLY},
223
{TK_CONFIG_PIXELS, "-activeborderwidth", "activeBorderWidth",
224
"BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
225
Tk_Offset(TkMenu, activeBorderWidth), 0},
226
{TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
227
DEF_MENU_ACTIVE_FG_COLOR, Tk_Offset(TkMenu, activeFg),
228
TK_CONFIG_COLOR_ONLY},
229
{TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
230
DEF_MENU_ACTIVE_FG_MONO, Tk_Offset(TkMenu, activeFg),
231
TK_CONFIG_MONO_ONLY},
232
{TK_CONFIG_CUSTOM, "-activetile", "activeTile", "Tile", (char *) NULL,
233
Tk_Offset(TkMenu, activeTile), TK_CONFIG_DONT_SET_DEFAULT,
235
{TK_CONFIG_BORDER, "-background", "background", "Background",
236
DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, border), TK_CONFIG_COLOR_ONLY},
237
{TK_CONFIG_BORDER, "-background", "background", "Background",
238
DEF_MENU_BG_MONO, Tk_Offset(TkMenu, border), TK_CONFIG_MONO_ONLY},
239
{TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
240
(char *) NULL, 0, 0},
241
{TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
242
(char *) NULL, 0, 0},
243
{TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
244
DEF_MENU_BORDER_WIDTH, Tk_Offset(TkMenu, borderWidth), 0},
245
{TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
246
DEF_MENU_CURSOR, Tk_Offset(TkMenu, cursor), TK_CONFIG_NULL_OK},
247
{TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
106
char *tkMenuStateStrings[] = {"active", "normal", "disabled", (char *) NULL};
108
static CONST char *menuEntryTypeStrings[] = {
109
"cascade", "checkbutton", "command", "radiobutton", "separator",
114
* The following table defines the legal values for the -compound option.
115
* It is used with the "enum compound" declaration in tkMenu.h
118
static char *compoundStrings[] = {
119
"bottom", "center", "left", "none", "right", "top", (char *) NULL
122
Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
123
{TK_OPTION_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
124
DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1,
126
{TK_OPTION_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
127
DEF_MENU_ENTRY_ACTIVE_FG,
128
Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK},
129
{TK_OPTION_STRING, "-accelerator", (char *) NULL, (char *) NULL,
130
DEF_MENU_ENTRY_ACCELERATOR,
131
Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK},
132
{TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
134
Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
135
{TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
136
(char *) NULL, 0, -1, 0, (ClientData) "-background"},
137
{TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
138
DEF_MENU_ENTRY_BITMAP,
139
Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK},
140
{TK_OPTION_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
141
DEF_MENU_ENTRY_COLUMN_BREAK,
142
-1, Tk_Offset(TkMenuEntry, columnBreak)},
143
{TK_OPTION_CALLBACK, "-command", (char *) NULL, (char *) NULL,
144
DEF_MENU_ENTRY_COMMAND,
145
-1, Tk_Offset(TkMenuEntry, commandPtr), TK_OPTION_NULL_OK},
146
{TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
147
DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
148
(ClientData) compoundStrings, 0},
149
{TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL,
151
Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK},
152
{TK_OPTION_COLOR, "-foreground", (char *) NULL, (char *) NULL,
154
Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK},
155
{TK_OPTION_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
156
DEF_MENU_ENTRY_HIDE_MARGIN,
157
-1, Tk_Offset(TkMenuEntry, hideMargin)},
158
{TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL,
159
DEF_MENU_ENTRY_IMAGE,
160
Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK},
161
{TK_OPTION_STRING, "-label", (char *) NULL, (char *) NULL,
162
DEF_MENU_ENTRY_LABEL,
163
Tk_Offset(TkMenuEntry, labelPtr), -1, 0},
164
{TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
165
DEF_MENU_ENTRY_STATE,
166
-1, Tk_Offset(TkMenuEntry, state), 0,
167
(ClientData) tkMenuStateStrings},
168
{TK_OPTION_INT, "-underline", (char *) NULL, (char *) NULL,
169
DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline)},
173
Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
174
{TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
176
Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
180
Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
181
{TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
182
DEF_MENU_ENTRY_INDICATOR,
183
-1, Tk_Offset(TkMenuEntry, indicatorOn)},
184
{TK_OPTION_STRING, "-offvalue", (char *) NULL, (char *) NULL,
185
DEF_MENU_ENTRY_OFF_VALUE,
186
Tk_Offset(TkMenuEntry, offValuePtr), -1},
187
{TK_OPTION_STRING, "-onvalue", (char *) NULL, (char *) NULL,
188
DEF_MENU_ENTRY_ON_VALUE,
189
Tk_Offset(TkMenuEntry, onValuePtr), -1},
190
{TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
191
DEF_MENU_ENTRY_SELECT,
192
Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK},
193
{TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL,
194
DEF_MENU_ENTRY_SELECT_IMAGE,
195
Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
196
{TK_OPTION_SCALARVAR, "-variable", (char *) NULL, (char *) NULL,
197
DEF_MENU_ENTRY_CHECK_VARIABLE,
198
-1, Tk_Offset(TkMenuEntry, namePtr), TK_OPTION_NULL_OK},
199
{TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
200
(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
203
Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
204
{TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
205
DEF_MENU_ENTRY_INDICATOR,
206
-1, Tk_Offset(TkMenuEntry, indicatorOn)},
207
{TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
208
DEF_MENU_ENTRY_SELECT,
209
Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK},
210
{TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL,
211
DEF_MENU_ENTRY_SELECT_IMAGE,
212
Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
213
{TK_OPTION_STRING, "-value", (char *) NULL, (char *) NULL,
214
DEF_MENU_ENTRY_VALUE,
215
Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK},
216
{TK_OPTION_SCALARVAR, "-variable", (char *) NULL, (char *) NULL,
217
DEF_MENU_ENTRY_RADIO_VARIABLE,
218
-1, Tk_Offset(TkMenuEntry, namePtr), 0},
219
{TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
220
(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
223
Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
224
{TK_OPTION_STRING, "-menu", (char *) NULL, (char *) NULL,
226
Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK},
227
{TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
228
(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
231
Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
232
{TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
234
Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
235
{TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
236
DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0,
237
(ClientData) tkMenuStateStrings},
241
static Tk_OptionSpec *specsArray[] = {
242
tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,
243
tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,
244
tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs};
247
* Menu type strings for use with Tcl_GetIndexFromObj.
250
static CONST char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
253
Tk_OptionSpec tkMenuConfigSpecs[] = {
254
{TK_OPTION_BORDER, "-activebackground", "activeBackground",
255
"Foreground", DEF_MENU_ACTIVE_BG_COLOR,
256
Tk_Offset(TkMenu, activeBorderPtr), -1, 0,
257
(ClientData) DEF_MENU_ACTIVE_BG_MONO},
258
{TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
259
"BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
260
Tk_Offset(TkMenu, activeBorderWidthPtr), -1},
261
{TK_OPTION_COLOR, "-activeforeground", "activeForeground",
262
"Background", DEF_MENU_ACTIVE_FG_COLOR,
263
Tk_Offset(TkMenu, activeFgPtr), -1, 0,
264
(ClientData) DEF_MENU_ACTIVE_FG_MONO},
265
{TK_OPTION_BORDER, "-background", "background", "Background",
266
DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0,
267
(ClientData) DEF_MENU_BG_MONO},
268
{TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
269
(char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"},
270
{TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
271
(char *) NULL, 0, -1, 0, (ClientData) "-background"},
272
{TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
273
DEF_MENU_BORDER_WIDTH,
274
Tk_Offset(TkMenu, borderWidthPtr), -1, 0},
275
{TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
277
Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK},
278
{TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
248
279
"DisabledForeground", DEF_MENU_DISABLED_FG_COLOR,
249
Tk_Offset(TkMenu, disabledFg), TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
250
{TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
251
"DisabledForeground", DEF_MENU_DISABLED_FG_MONO,
252
Tk_Offset(TkMenu, disabledFg), TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
253
{TK_CONFIG_CUSTOM, "-disabledtile", "disabledTile", "Tile", (char *) NULL,
254
Tk_Offset(TkMenu, disabledTile), TK_CONFIG_DONT_SET_DEFAULT,
256
{TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
257
(char *) NULL, 0, 0},
258
{TK_CONFIG_FONT, "-font", "font", "Font",
259
DEF_MENU_FONT, Tk_Offset(TkMenu, tkfont), 0},
260
{TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
261
DEF_MENU_FG, Tk_Offset(TkMenu, fg), 0},
262
{TK_CONFIG_CUSTOM, "-offset", "offset", "Offset", "0 0",
263
Tk_Offset(TkMenu, tsoffset), TK_CONFIG_DONT_SET_DEFAULT,
265
{TK_CONFIG_CALLBACK, "-postcommand", "postCommand", "Command",
266
DEF_MENU_POST_COMMAND, Tk_Offset(TkMenu, postCommand),
268
{TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
269
DEF_MENU_RELIEF, Tk_Offset(TkMenu, relief), 0},
270
{TK_CONFIG_COLOR, "-selectcolor", "selectColor", "Background",
271
DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFg),
272
TK_CONFIG_COLOR_ONLY},
273
{TK_CONFIG_COLOR, "-selectcolor", "selectColor", "Background",
274
DEF_MENU_SELECT_MONO, Tk_Offset(TkMenu, indicatorFg),
275
TK_CONFIG_MONO_ONLY},
276
{TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
277
DEF_MENU_TAKE_FOCUS, Tk_Offset(TkMenu, takeFocus), TK_CONFIG_NULL_OK},
278
{TK_CONFIG_BOOLEAN, "-tearoff", "tearOff", "TearOff",
279
DEF_MENU_TEAROFF, Tk_Offset(TkMenu, tearOff), 0},
280
{TK_CONFIG_CALLBACK, "-tearoffcommand", "tearOffCommand", "TearOffCommand",
281
DEF_MENU_TEAROFF_CMD, Tk_Offset(TkMenu, tearOffCommand),
283
{TK_CONFIG_CUSTOM, "-tile", "tile", "Tile", (char *) NULL,
284
Tk_Offset(TkMenu, tile), TK_CONFIG_DONT_SET_DEFAULT, &tileOption},
285
{TK_CONFIG_STRING, "-title", "title", "Title",
286
DEF_MENU_TITLE, Tk_Offset(TkMenu, title), TK_CONFIG_NULL_OK},
287
{TK_CONFIG_STRING, "-type", "type", "Type",
288
DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypeName), TK_CONFIG_NULL_OK},
289
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
280
Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK,
281
(ClientData) DEF_MENU_DISABLED_FG_MONO},
282
{TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL,
283
(char *) NULL, 0, -1, 0, (ClientData) "-foreground"},
284
{TK_OPTION_FONT, "-font", "font", "Font",
285
DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1},
286
{TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
287
DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1, 0},
288
{TK_OPTION_CALLBACK, "-postcommand", "postCommand", "Command",
289
DEF_MENU_POST_COMMAND,
290
-1, Tk_Offset(TkMenu, postCommandPtr), TK_OPTION_NULL_OK},
291
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
292
DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1},
293
{TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background",
294
DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0,
295
(ClientData) DEF_MENU_SELECT_MONO},
296
{TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
298
Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK},
299
{TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff",
300
DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff)},
301
{TK_OPTION_CALLBACK, "-tearoffcommand", "tearOffCommand",
302
"TearOffCommand", DEF_MENU_TEAROFF_CMD,
303
-1, Tk_Offset(TkMenu, tearoffCommandPtr), TK_OPTION_NULL_OK},
304
{TK_OPTION_STRING, "-title", "title", "Title",
305
DEF_MENU_TITLE, Tk_Offset(TkMenu, titlePtr), -1,
307
{TK_OPTION_STRING_TABLE, "-type", "type", "Type",
308
DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK,
309
(ClientData) menuTypeStrings},
314
* Command line options. Put here because MenuCmd has to look at them
315
* along with MenuWidgetObjCmd.
318
static CONST char *menuOptions[] = {
319
"activate", "add", "cget", "clone", "configure", "delete", "entrycget",
320
"entryconfigure", "index", "insert", "invoke", "post", "postcascade",
321
"type", "unpost", "yposition", (char *) NULL
324
MENU_ACTIVATE, MENU_ADD, MENU_CGET, MENU_CLONE, MENU_CONFIGURE,
325
MENU_DELETE, MENU_ENTRYCGET, MENU_ENTRYCONFIGURE, MENU_INDEX,
326
MENU_INSERT, MENU_INVOKE, MENU_POST, MENU_POSTCASCADE, MENU_TYPE,
327
MENU_UNPOST, MENU_YPOSITION
599
MenuWidgetCmd(clientData, interp, argc, argv)
703
MenuWidgetObjCmd(clientData, interp, objc, objv)
600
704
ClientData clientData; /* Information about menu widget. */
601
Tcl_Interp *interp; /* Current interpreter. */
602
int argc; /* Number of arguments. */
603
char **argv; /* Argument strings. */
705
Tcl_Interp *interp; /* Current interpreter. */
706
int objc; /* Number of arguments. */
707
Tcl_Obj *CONST objv[]; /* Argument strings. */
605
709
register TkMenu *menuPtr = (TkMenu *) clientData;
606
710
register TkMenuEntry *mePtr;
607
711
int result = TCL_OK;
612
Tcl_AppendResult(interp, "wrong # args: should be \"",
613
argv[0], " option ?arg arg ...?\"", (char *) NULL);
715
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
718
if (Tcl_GetIndexFromObj(interp, objv[1], menuOptions, "option", 0,
719
&option) != TCL_OK) {
614
720
return TCL_ERROR;
616
722
Tcl_Preserve((ClientData) menuPtr);
618
length = strlen(argv[1]);
619
if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)
624
Tcl_AppendResult(interp, "wrong # args: should be \"",
625
argv[0], " activate index\"", (char *) NULL);
628
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
631
if (menuPtr->active == index) {
635
if ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
636
|| (menuPtr->entries[index]->state == TK_STATE_DISABLED)) {
724
switch ((enum options) option) {
725
case MENU_ACTIVATE: {
729
Tcl_WrongNumArgs(interp, 1, objv, "activate index");
732
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
736
if (menuPtr->active == index) {
740
&& ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
741
|| (menuPtr->entries[index]->state
742
== ENTRY_DISABLED))) {
640
result = TkActivateMenuEntry(menuPtr, index);
641
} else if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)
644
Tcl_AppendResult(interp, "wrong # args: should be \"",
645
argv[0], " add type ?options?\"", (char *) NULL);
648
if (MenuAddOrInsert(interp, menuPtr, (char *) NULL,
649
argc-2, argv+2) != TCL_OK) {
652
} else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
655
Tcl_AppendResult(interp, "wrong # args: should be \"",
656
argv[0], " cget option\"",
660
result = Tk_ConfigureValue(interp, menuPtr->tkwin, tkMenuConfigSpecs,
661
(char *) menuPtr, argv[2], 0);
662
} else if ((c == 'c') && (strncmp(argv[1], "clone", length) == 0)
664
if ((argc < 3) || (argc > 4)) {
665
Tcl_AppendResult(interp, "wrong # args: should be \"",
666
argv[0], " clone newMenuName ?menuType?\"",
670
Tcl_IncrRefCount(objv[2]);
671
result = CloneMenu(menuPtr, &objv[2], (argc == 3) ? NULL : argv[3]);
672
if (result == TCL_OK) {
673
Tcl_SetObjResult(interp, objv[2]);
675
} else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
678
result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
679
tkMenuConfigSpecs, (char *) menuPtr, (char *) NULL, 0);
680
} else if (argc == 3) {
681
result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
682
tkMenuConfigSpecs, (char *) menuPtr, argv[2], 0);
684
result = ConfigureMenu(interp, menuPtr, argc-2, argv+2,
685
TK_CONFIG_ARGV_ONLY);
687
} else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
690
if ((argc != 3) && (argc != 4)) {
691
Tcl_AppendResult(interp, "wrong # args: should be \"",
692
argv[0], " delete first ?last?\"", (char *) NULL);
695
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first) != TCL_OK) {
701
if (TkGetMenuIndex(interp, menuPtr, objv[3], 0, &last) != TCL_OK) {
705
if (menuPtr->tearOff && (first == 0)) {
745
result = TkActivateMenuEntry(menuPtr, index);
750
Tcl_WrongNumArgs(interp, 1, objv, "add type ?options?");
754
if (MenuAddOrInsert(interp, menuPtr, (Tcl_Obj *) NULL,
755
objc - 2, objv + 2) != TCL_OK) {
763
Tcl_WrongNumArgs(interp, 1, objv, "cget option");
766
resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr,
767
menuPtr->optionTablesPtr->menuOptionTable, objv[2],
769
if (resultPtr == NULL) {
772
Tcl_SetObjResult(interp, resultPtr);
776
if ((objc < 3) || (objc > 4)) {
777
Tcl_WrongNumArgs(interp, 1, objv,
778
"clone newMenuName ?menuType?");
781
result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);
782
if (result == TCL_OK) {
783
Tcl_SetObjResult(interp, objv[2]);
786
case MENU_CONFIGURE: {
790
resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
791
menuPtr->optionTablesPtr->menuOptionTable,
792
(Tcl_Obj *) NULL, menuPtr->tkwin);
793
if (resultPtr == NULL) {
797
Tcl_SetObjResult(interp, resultPtr);
799
} else if (objc == 3) {
800
resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
801
menuPtr->optionTablesPtr->menuOptionTable,
802
objv[2], menuPtr->tkwin);
803
if (resultPtr == NULL) {
807
Tcl_SetObjResult(interp, resultPtr);
810
result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
812
if (result != TCL_OK) {
820
if ((objc != 3) && (objc != 4)) {
821
Tcl_WrongNumArgs(interp, 1, objv, "delete first ?last?");
824
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first)
831
if (TkGetMenuIndex(interp, menuPtr, objv[3], 0, &last)
836
if (menuPtr->tearoff && (first == 0)) {
839
* Sorry, can't delete the tearoff entry; must reconfigure
845
if ((first < 0) || (last < first)) {
848
DeleteMenuCloneEntries(menuPtr, first, last);
851
case MENU_ENTRYCGET: {
856
Tcl_WrongNumArgs(interp, 1, objv, "entrycget index option");
859
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
866
mePtr = menuPtr->entries[index];
867
Tcl_Preserve((ClientData) mePtr);
868
resultPtr = Tk_GetOptionValue(interp, (char *) mePtr,
869
mePtr->optionTable, objv[3], menuPtr->tkwin);
870
Tcl_Release((ClientData) mePtr);
871
if (resultPtr == NULL) {
874
Tcl_SetObjResult(interp, resultPtr);
877
case MENU_ENTRYCONFIGURE: {
882
Tcl_WrongNumArgs(interp, 1, objv,
883
"entryconfigure index ?option value ...?");
886
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
893
mePtr = menuPtr->entries[index];
894
Tcl_Preserve((ClientData) mePtr);
896
resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
897
mePtr->optionTable, (Tcl_Obj *) NULL, menuPtr->tkwin);
898
if (resultPtr == NULL) {
902
Tcl_SetObjResult(interp, resultPtr);
904
} else if (objc == 4) {
905
resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
906
mePtr->optionTable, objv[3], menuPtr->tkwin);
907
if (resultPtr == NULL) {
911
Tcl_SetObjResult(interp, resultPtr);
914
result = ConfigureMenuCloneEntries(interp, menuPtr, index,
917
Tcl_Release((ClientData) mePtr);
924
Tcl_WrongNumArgs(interp, 1, objv, "index string");
927
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
932
Tcl_SetResult(interp, "none", TCL_STATIC);
934
Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
940
Tcl_WrongNumArgs(interp, 1, objv,
941
"insert index type ?options?");
944
if (MenuAddOrInsert(interp, menuPtr, objv[2], objc - 3,
945
objv + 3) != TCL_OK) {
953
Tcl_WrongNumArgs(interp, 1, objv, "invoke index");
956
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
963
result = TkInvokeMenu(interp, menuPtr, index);
970
Tcl_WrongNumArgs(interp, 1, objv, "post x y");
973
if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
974
|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
708
* Sorry, can't delete the tearoff entry; must reconfigure
979
* Tearoff menus are posted differently on Mac and Windows than
980
* non-tearoffs. TkpPostMenu does not actually map the menu's
981
* window on those platforms, and popup menus have to be
714
if ((first < 0) || (last < first)) {
717
DeleteMenuCloneEntries(menuPtr, first, last);
718
} else if ((c == 'e') && (length >= 7)
719
&& (strncmp(argv[1], "entrycget", length) == 0)) {
723
Tcl_AppendResult(interp, "wrong # args: should be \"",
724
argv[0], " entrycget index option\"",
728
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
734
mePtr = menuPtr->entries[index];
735
Tcl_Preserve((ClientData) mePtr);
736
result = Tk_ConfigureValue(interp, menuPtr->tkwin,
737
tkMenuEntryConfigSpecs, (char *) mePtr, argv[3],
738
COMMAND_MASK << mePtr->type);
739
Tcl_Release((ClientData) mePtr);
740
} else if ((c == 'e') && (length >= 7)
741
&& (strncmp(argv[1], "entryconfigure", length) == 0)) {
745
Tcl_AppendResult(interp, "wrong # args: should be \"",
746
argv[0], " entryconfigure index ?option value ...?\"",
750
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
756
mePtr = menuPtr->entries[index];
757
Tcl_Preserve((ClientData) mePtr);
759
result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
760
tkMenuEntryConfigSpecs, (char *) mePtr, (char *) NULL,
761
COMMAND_MASK << mePtr->type);
762
} else if (argc == 4) {
763
result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
764
tkMenuEntryConfigSpecs, (char *) mePtr, argv[3],
765
COMMAND_MASK << mePtr->type);
767
result = ConfigureMenuCloneEntries(interp, menuPtr, index,
769
TK_CONFIG_ARGV_ONLY | COMMAND_MASK << mePtr->type);
771
Tcl_Release((ClientData) mePtr);
772
} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
777
Tcl_AppendResult(interp, "wrong # args: should be \"",
778
argv[0], " index string\"", (char *) NULL);
781
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
785
interp->result = "none";
787
sprintf(interp->result, "%d", index);
789
} else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
792
Tcl_AppendResult(interp, "wrong # args: should be \"",
793
argv[0], " insert index type ?options?\"", (char *) NULL);
796
if (MenuAddOrInsert(interp, menuPtr, objv[2],
797
argc-3, argv+3) != TCL_OK) {
800
} else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0)
805
Tcl_AppendResult(interp, "wrong # args: should be \"",
806
argv[0], " invoke index\"", (char *) NULL);
809
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
815
result = TkInvokeMenu(interp, menuPtr, index);
816
} else if ((c == 'p') && (strncmp(argv[1], "post", length) == 0)
821
Tcl_AppendResult(interp, "wrong # args: should be \"",
822
argv[0], " post x y\"", (char *) NULL);
825
if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
826
|| (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
831
* Tearoff menus are posted differently on Mac and Windows than
832
* non-tearoffs. TkpPostMenu does not actually map the menu's
833
* window on those platforms, and popup menus have to be
837
if (menuPtr->menuType != TEAROFF_MENU) {
838
result = TkpPostMenu(interp, menuPtr, x, y);
840
result = TkPostTearoffMenu(interp, menuPtr, x, y);
842
} else if ((c == 'p') && (strncmp(argv[1], "postcascade", length) == 0)
846
Tcl_AppendResult(interp, "wrong # args: should be \"",
847
argv[0], " postcascade index\"", (char *) NULL);
850
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
853
if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
985
if (menuPtr->menuType != TEAROFF_MENU) {
986
result = TkpPostMenu(interp, menuPtr, x, y);
988
result = TkPostTearoffMenu(interp, menuPtr, x, y);
992
case MENU_POSTCASCADE: {
996
Tcl_WrongNumArgs(interp, 1, objv, "postcascade index");
1000
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
1004
if ((index < 0) || (menuPtr->entries[index]->type
1005
!= CASCADE_ENTRY)) {
1006
result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
1008
result = TkPostSubmenu(interp, menuPtr,
1009
menuPtr->entries[index]);
1017
Tcl_WrongNumArgs(interp, 1, objv, "type index");
1020
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
1027
if (menuPtr->entries[index]->type == TEAROFF_ENTRY) {
1028
Tcl_SetResult(interp, "tearoff", TCL_STATIC);
1030
Tcl_SetStringObj(Tcl_GetObjResult(interp),
1031
menuEntryTypeStrings[menuPtr->entries[index]->type],
1038
Tcl_WrongNumArgs(interp, 1, objv, "unpost");
1041
Tk_UnmapWindow(menuPtr->tkwin);
854
1042
result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
856
result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);
858
} else if ((c == 't') && (strncmp(argv[1], "type", length) == 0)) {
861
Tcl_AppendResult(interp, "wrong # args: should be \"",
862
argv[0], " type index\"", (char *) NULL);
865
if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
871
mePtr = menuPtr->entries[index];
872
switch (mePtr->type) {
874
interp->result = "command";
876
case SEPARATOR_ENTRY:
877
interp->result = "separator";
879
case CHECK_BUTTON_ENTRY:
880
interp->result = "checkbutton";
882
case RADIO_BUTTON_ENTRY:
883
interp->result = "radiobutton";
886
interp->result = "cascade";
889
interp->result = "tearoff";
892
} else if ((c == 'u') && (strncmp(argv[1], "unpost", length) == 0)) {
894
Tcl_AppendResult(interp, "wrong # args: should be \"",
895
argv[0], " unpost\"", (char *) NULL);
898
Tk_UnmapWindow(menuPtr->tkwin);
899
result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
900
} else if ((c == 'y') && (strncmp(argv[1], "yposition", length) == 0)) {
902
Tcl_AppendResult(interp, "wrong # args: should be \"",
903
argv[0], " yposition index\"", (char *) NULL);
906
result = MenuDoYPosition(interp, menuPtr, objv[2]);
908
Tcl_AppendResult(interp, "bad option \"", argv[1],
909
"\": must be activate, add, cget, clone, configure, delete, ",
910
"entrycget, entryconfigure, index, insert, invoke, ",
911
"post, postcascade, type, unpost, or yposition",
1044
case MENU_YPOSITION:
1046
Tcl_WrongNumArgs(interp, 1, objv, "yposition index");
1049
result = MenuDoYPosition(interp, menuPtr, objv[2]);
916
1053
Tcl_Release((ClientData) menuPtr);