4 * This module implements a collection of button-like
5 * widgets for the Tk toolkit. The widgets implemented
6 * include labels, buttons, checkbuttons, and radiobuttons.
8 * Copyright (c) 1990-1994 The Regents of the University of California.
9 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
20 typedef struct ThreadSpecificData {
21 int defaultsInitialized;
23 static Tcl_ThreadDataKey dataKey;
26 * Class names for buttons, indexed by one of the type values defined
30 static char *classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"};
33 * The following table defines the legal values for the -default option.
34 * It is used together with the "enum defaultValue" declaration in tkButton.h.
37 static char *defaultStrings[] = {
38 "active", "disabled", "normal", (char *) NULL
42 * The following table defines the legal values for the -state option.
43 * It is used together with the "enum state" declaration in tkButton.h.
46 static char *stateStrings[] = {
47 "active", "disabled", "normal", (char *) NULL
51 * The following table defines the legal values for the -compound option.
52 * It is used with the "enum compound" declaration in tkButton.h
55 static char *compoundStrings[] = {
56 "bottom", "center", "left", "none", "right", "top", (char *) NULL
60 * Information used for parsing configuration options. There is a
61 * separate table for each of the four widget classes.
64 static Tk_OptionSpec labelOptionSpecs[] = {
65 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
66 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
67 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
68 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
69 DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
70 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
71 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
72 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
73 {TK_OPTION_BORDER, "-background", "background", "Background",
74 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
75 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
76 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
77 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
78 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
79 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
80 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
81 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
82 TK_OPTION_NULL_OK, 0, 0},
83 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
84 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
85 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
86 {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
87 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
88 (ClientData) compoundStrings, 0},
89 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
90 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
91 TK_OPTION_NULL_OK, 0, 0},
92 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
93 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
94 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
95 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
96 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
97 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
98 {TK_OPTION_FONT, "-font", "font", "Font",
99 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
100 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
101 DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
102 {TK_OPTION_STRING, "-height", "height", "Height",
103 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
104 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
105 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
106 -1, Tk_Offset(TkButton, highlightBorder), 0,
107 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
108 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
109 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
111 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
112 "HighlightThickness", DEF_LABEL_HIGHLIGHT_WIDTH,
113 Tk_Offset(TkButton, highlightWidthPtr),
114 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
115 {TK_OPTION_STRING, "-image", "image", "Image",
116 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
117 TK_OPTION_NULL_OK, 0, 0},
118 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
119 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
120 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
121 DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
122 Tk_Offset(TkButton, padX), 0, 0, 0},
123 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
124 DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
125 Tk_Offset(TkButton, padY), 0, 0, 0},
126 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
127 DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
128 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
129 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
130 0, (ClientData) stateStrings, 0},
131 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
132 DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
133 TK_OPTION_NULL_OK, 0, 0},
134 {TK_OPTION_STRING, "-text", "text", "Text",
135 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
136 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
137 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
138 TK_OPTION_NULL_OK, 0, 0},
139 {TK_OPTION_INT, "-underline", "underline", "Underline",
140 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
141 {TK_OPTION_STRING, "-width", "width", "Width",
142 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
143 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
144 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
145 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
146 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
147 (char *) NULL, 0, 0, 0, 0}
150 static Tk_OptionSpec buttonOptionSpecs[] = {
151 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
152 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
153 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
154 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
155 DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
156 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
157 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
158 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
159 {TK_OPTION_BORDER, "-background", "background", "Background",
160 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
161 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
162 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
163 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
164 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
165 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
166 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
167 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
168 TK_OPTION_NULL_OK, 0, 0},
169 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
170 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
171 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
172 {TK_OPTION_STRING, "-command", "command", "Command",
173 DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
174 TK_OPTION_NULL_OK, 0, 0},
175 {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
176 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
177 (ClientData) compoundStrings, 0},
178 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
179 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
180 TK_OPTION_NULL_OK, 0, 0},
181 {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
182 DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState),
183 0, (ClientData) defaultStrings, 0},
184 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
185 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
186 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
187 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
188 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
189 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
190 {TK_OPTION_FONT, "-font", "font", "Font",
191 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
192 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
193 DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
194 {TK_OPTION_STRING, "-height", "height", "Height",
195 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
196 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
197 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
198 -1, Tk_Offset(TkButton, highlightBorder), 0,
199 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
200 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
201 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
203 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
204 "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
205 Tk_Offset(TkButton, highlightWidthPtr),
206 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
207 {TK_OPTION_STRING, "-image", "image", "Image",
208 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
209 TK_OPTION_NULL_OK, 0, 0},
210 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
211 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
212 {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
213 DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
214 TK_OPTION_NULL_OK, 0, 0},
215 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
216 DEF_BUTTON_PADX, Tk_Offset(TkButton, padXPtr),
217 Tk_Offset(TkButton, padX), 0, 0, 0},
218 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
219 DEF_BUTTON_PADY, Tk_Offset(TkButton, padYPtr),
220 Tk_Offset(TkButton, padY), 0, 0, 0},
221 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
222 DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief),
224 {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
225 DEF_BUTTON_REPEAT_DELAY, -1, Tk_Offset(TkButton, repeatDelay),
227 {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
228 DEF_BUTTON_REPEAT_INTERVAL, -1, Tk_Offset(TkButton, repeatInterval),
230 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
231 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
232 0, (ClientData) stateStrings, 0},
233 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
234 DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
235 TK_OPTION_NULL_OK, 0, 0},
236 {TK_OPTION_STRING, "-text", "text", "Text",
237 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
238 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
239 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
240 TK_OPTION_NULL_OK, 0, 0},
241 {TK_OPTION_INT, "-underline", "underline", "Underline",
242 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
243 {TK_OPTION_STRING, "-width", "width", "Width",
244 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
245 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
246 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
247 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
248 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
249 (char *) NULL, 0, -1, 0, 0, 0}
252 static Tk_OptionSpec checkbuttonOptionSpecs[] = {
253 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
254 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
255 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
256 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
257 DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
258 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
259 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
260 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
261 {TK_OPTION_BORDER, "-background", "background", "Background",
262 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
263 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
264 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
265 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
266 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
267 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
268 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
269 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
270 TK_OPTION_NULL_OK, 0, 0},
271 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
272 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
273 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
274 {TK_OPTION_STRING, "-command", "command", "Command",
275 DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
276 TK_OPTION_NULL_OK, 0, 0},
277 {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
278 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
279 (ClientData) compoundStrings, 0},
280 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
281 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
282 TK_OPTION_NULL_OK, 0, 0},
283 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
284 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
285 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
286 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
287 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
288 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
289 {TK_OPTION_FONT, "-font", "font", "Font",
290 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
291 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
292 DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
293 {TK_OPTION_STRING, "-height", "height", "Height",
294 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
295 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
296 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
297 -1, Tk_Offset(TkButton, highlightBorder), 0,
298 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
299 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
300 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
302 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
303 "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
304 Tk_Offset(TkButton, highlightWidthPtr),
305 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
306 {TK_OPTION_STRING, "-image", "image", "Image",
307 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
308 TK_OPTION_NULL_OK, 0, 0},
309 {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
310 DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0},
311 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
312 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
313 {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief",
314 DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0},
315 {TK_OPTION_STRING, "-offvalue", "offValue", "Value",
316 DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0},
317 {TK_OPTION_STRING, "-onvalue", "onValue", "Value",
318 DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
319 {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
320 DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
321 TK_OPTION_NULL_OK, 0, 0},
322 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
323 DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
324 Tk_Offset(TkButton, padX), 0, 0, 0},
325 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
326 DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
327 Tk_Offset(TkButton, padY), 0, 0, 0},
328 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
329 DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
330 {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
331 DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
332 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},
333 {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
334 DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
335 TK_OPTION_NULL_OK, 0, 0},
336 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
337 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
338 0, (ClientData) stateStrings, 0},
339 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
340 DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
341 TK_OPTION_NULL_OK, 0, 0},
342 {TK_OPTION_STRING, "-text", "text", "Text",
343 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
344 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
345 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
346 TK_OPTION_NULL_OK, 0, 0},
347 {TK_OPTION_INT, "-underline", "underline", "Underline",
348 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
349 {TK_OPTION_STRING, "-variable", "variable", "Variable",
350 DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
351 TK_OPTION_NULL_OK, 0, 0},
352 {TK_OPTION_STRING, "-width", "width", "Width",
353 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
354 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
355 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
356 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
357 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
358 (char *) NULL, 0, -1, 0, 0, 0}
361 static Tk_OptionSpec radiobuttonOptionSpecs[] = {
362 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
363 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
364 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
365 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
366 DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
367 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
368 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
369 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
370 {TK_OPTION_BORDER, "-background", "background", "Background",
371 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
372 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
373 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
374 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
375 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
376 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
377 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
378 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
379 TK_OPTION_NULL_OK, 0, 0},
380 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
381 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
382 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
383 {TK_OPTION_STRING, "-command", "command", "Command",
384 DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
385 TK_OPTION_NULL_OK, 0, 0},
386 {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
387 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
388 (ClientData) compoundStrings, 0},
389 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
390 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
391 TK_OPTION_NULL_OK, 0, 0},
392 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
393 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
394 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
395 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
396 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
397 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
398 {TK_OPTION_FONT, "-font", "font", "Font",
399 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
400 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
401 DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
402 {TK_OPTION_STRING, "-height", "height", "Height",
403 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
404 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
405 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
406 -1, Tk_Offset(TkButton, highlightBorder), 0,
407 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
408 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
409 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
411 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
412 "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
413 Tk_Offset(TkButton, highlightWidthPtr),
414 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
415 {TK_OPTION_STRING, "-image", "image", "Image",
416 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
417 TK_OPTION_NULL_OK, 0, 0},
418 {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
419 DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn),
421 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
422 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
423 {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief",
424 DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0},
425 {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
426 DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
427 TK_OPTION_NULL_OK, 0, 0},
428 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
429 DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
430 Tk_Offset(TkButton, padX), 0, 0, 0},
431 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
432 DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
433 Tk_Offset(TkButton, padY), 0, 0, 0},
434 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
435 DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
436 {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
437 DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
438 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},
439 {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
440 DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
441 TK_OPTION_NULL_OK, 0, 0},
442 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
443 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
444 0, (ClientData) stateStrings, 0},
445 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
446 DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
447 TK_OPTION_NULL_OK, 0, 0},
448 {TK_OPTION_STRING, "-text", "text", "Text",
449 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
450 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
451 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
452 TK_OPTION_NULL_OK, 0, 0},
453 {TK_OPTION_INT, "-underline", "underline", "Underline",
454 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
455 {TK_OPTION_STRING, "-value", "value", "Value",
456 DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
457 {TK_OPTION_STRING, "-variable", "variable", "Variable",
458 DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
460 {TK_OPTION_STRING, "-width", "width", "Width",
461 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
462 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
463 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
464 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
465 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
466 (char *) NULL, 0, -1, 0, 0, 0}
470 * The following table maps from one of the type values defined in
471 * tkButton.h, such as TYPE_LABEL, to the option template for that
475 static Tk_OptionSpec *optionSpecs[] = {
478 checkbuttonOptionSpecs,
479 radiobuttonOptionSpecs
483 * The following tables define the widget commands supported by
484 * each of the classes, and map the indexes into the string tables
485 * into a single enumerated type used to dispatch the widget command.
488 static CONST char *commandNames[][8] = {
489 {"cget", "configure", (char *) NULL},
490 {"cget", "configure", "flash", "invoke", (char *) NULL},
491 {"cget", "configure", "deselect", "flash", "invoke", "select",
492 "toggle", (char *) NULL},
493 {"cget", "configure", "deselect", "flash", "invoke", "select",
497 COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
498 COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE
500 static enum command map[][8] = {
501 {COMMAND_CGET, COMMAND_CONFIGURE},
502 {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},
503 {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
504 COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},
505 {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
506 COMMAND_INVOKE, COMMAND_SELECT}
510 * Forward declarations for procedures defined later in this file:
513 static void ButtonCmdDeletedProc _ANSI_ARGS_((
514 ClientData clientData));
515 static int ButtonCreate _ANSI_ARGS_((ClientData clientData,
516 Tcl_Interp *interp, int objc,
517 Tcl_Obj *CONST objv[], int type));
518 static void ButtonEventProc _ANSI_ARGS_((ClientData clientData,
520 static void ButtonImageProc _ANSI_ARGS_((ClientData clientData,
521 int x, int y, int width, int height,
522 int imgWidth, int imgHeight));
523 static void ButtonSelectImageProc _ANSI_ARGS_((
524 ClientData clientData, int x, int y, int width,
525 int height, int imgWidth, int imgHeight));
526 static char * ButtonTextVarProc _ANSI_ARGS_((ClientData clientData,
527 Tcl_Interp *interp, CONST char *name1,
528 CONST char *name2, int flags));
529 static char * ButtonVarProc _ANSI_ARGS_((ClientData clientData,
530 Tcl_Interp *interp, CONST char *name1,
531 CONST char *name2, int flags));
532 static int ButtonWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
533 Tcl_Interp *interp, int objc,
534 Tcl_Obj *CONST objv[]));
535 static int ConfigureButton _ANSI_ARGS_((Tcl_Interp *interp,
536 TkButton *butPtr, int objc,
537 Tcl_Obj *CONST objv[]));
538 static void DestroyButton _ANSI_ARGS_((TkButton *butPtr));
541 *--------------------------------------------------------------
543 * Tk_ButtonCmd, Tk_CheckbuttonCmd, Tk_LabelCmd, Tk_RadiobuttonCmd --
545 * These procedures are invoked to process the "button", "label",
546 * "radiobutton", and "checkbutton" Tcl commands. See the
547 * user documentation for details on what they do.
550 * A standard Tcl result.
553 * See the user documentation. These procedures are just wrappers;
554 * they call ButtonCreate to do all of the real work.
556 *--------------------------------------------------------------
560 Tk_ButtonObjCmd(clientData, interp, objc, objv)
561 ClientData clientData; /* Either NULL or pointer to option table. */
562 Tcl_Interp *interp; /* Current interpreter. */
563 int objc; /* Number of arguments. */
564 Tcl_Obj *CONST objv[]; /* Argument values. */
566 return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON);
570 Tk_CheckbuttonObjCmd(clientData, interp, objc, objv)
571 ClientData clientData; /* Either NULL or pointer to option table. */
572 Tcl_Interp *interp; /* Current interpreter. */
573 int objc; /* Number of arguments. */
574 Tcl_Obj *CONST objv[]; /* Argument values. */
576 return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON);
580 Tk_LabelObjCmd(clientData, interp, objc, objv)
581 ClientData clientData; /* Either NULL or pointer to option table. */
582 Tcl_Interp *interp; /* Current interpreter. */
583 int objc; /* Number of arguments. */
584 Tcl_Obj *CONST objv[]; /* Argument values. */
586 return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL);
590 Tk_RadiobuttonObjCmd(clientData, interp, objc, objv)
591 ClientData clientData; /* Either NULL or pointer to option table. */
592 Tcl_Interp *interp; /* Current interpreter. */
593 int objc; /* Number of arguments. */
594 Tcl_Obj *CONST objv[]; /* Argument values. */
596 return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON);
600 *--------------------------------------------------------------
604 * This procedure does all the real work of implementing the
605 * "button", "label", "radiobutton", and "checkbutton" Tcl
606 * commands. See the user documentation for details on what it does.
609 * A standard Tcl result.
612 * See the user documentation.
614 *--------------------------------------------------------------
618 ButtonCreate(clientData, interp, objc, objv, type)
619 ClientData clientData; /* NULL. */
620 Tcl_Interp *interp; /* Current interpreter. */
621 int objc; /* Number of arguments. */
622 Tcl_Obj *CONST objv[]; /* Argument values. */
623 int type; /* Type of button to create: TYPE_LABEL,
624 * TYPE_BUTTON, TYPE_CHECK_BUTTON, or
625 * TYPE_RADIO_BUTTON. */
628 Tk_OptionTable optionTable;
630 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
631 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
633 if (!tsdPtr->defaultsInitialized) {
634 TkpButtonSetDefaults(optionSpecs[type]);
635 tsdPtr->defaultsInitialized = 1;
639 Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
644 * Create the new window.
647 tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
648 Tcl_GetString(objv[1]), (char *) NULL);
654 * Create the option table for this widget class. If it has already
655 * been created, the cached pointer will be returned.
658 optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);
660 Tk_SetClass(tkwin, classNames[type]);
661 butPtr = TkpCreateButton(tkwin);
663 Tk_SetClassProcs(tkwin, &tkpButtonProcs, (ClientData) butPtr);
666 * Initialize the data structure for the button.
669 butPtr->tkwin = tkwin;
670 butPtr->display = Tk_Display(tkwin);
671 butPtr->interp = interp;
672 butPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),
673 ButtonWidgetObjCmd, (ClientData) butPtr, ButtonCmdDeletedProc);
675 butPtr->optionTable = optionTable;
676 butPtr->textPtr = NULL;
677 butPtr->underline = -1;
678 butPtr->textVarNamePtr = NULL;
679 butPtr->bitmap = None;
680 butPtr->imagePtr = NULL;
681 butPtr->image = NULL;
682 butPtr->selectImagePtr = NULL;
683 butPtr->selectImage = NULL;
684 butPtr->state = STATE_NORMAL;
685 butPtr->normalBorder = NULL;
686 butPtr->activeBorder = NULL;
687 butPtr->borderWidthPtr = NULL;
688 butPtr->borderWidth = 0;
689 butPtr->relief = TK_RELIEF_FLAT;
690 butPtr->highlightWidthPtr = NULL;
691 butPtr->highlightWidth = 0;
692 butPtr->highlightBorder = NULL;
693 butPtr->highlightColorPtr = NULL;
695 butPtr->tkfont = NULL;
696 butPtr->normalFg = NULL;
697 butPtr->activeFg = NULL;
698 butPtr->disabledFg = NULL;
699 butPtr->normalTextGC = None;
700 butPtr->activeTextGC = None;
701 butPtr->disabledGC = None;
703 butPtr->copyGC = None;
704 butPtr->widthPtr = NULL;
706 butPtr->heightPtr = NULL;
708 butPtr->wrapLengthPtr = NULL;
709 butPtr->wrapLength = 0;
710 butPtr->padXPtr = NULL;
712 butPtr->padYPtr = NULL;
714 butPtr->anchor = TK_ANCHOR_CENTER;
715 butPtr->justify = TK_JUSTIFY_CENTER;
716 butPtr->indicatorOn = 0;
717 butPtr->selectBorder = NULL;
718 butPtr->textWidth = 0;
719 butPtr->textHeight = 0;
720 butPtr->textLayout = NULL;
721 butPtr->indicatorSpace = 0;
722 butPtr->indicatorDiameter = 0;
723 butPtr->defaultState = DEFAULT_DISABLED;
724 butPtr->selVarNamePtr = NULL;
725 butPtr->onValuePtr = NULL;
726 butPtr->offValuePtr = NULL;
727 butPtr->cursor = None;
728 butPtr->takeFocusPtr = NULL;
729 butPtr->commandPtr = NULL;
732 Tk_CreateEventHandler(butPtr->tkwin,
733 ExposureMask|StructureNotifyMask|FocusChangeMask,
734 ButtonEventProc, (ClientData) butPtr);
736 if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin)
738 Tk_DestroyWindow(butPtr->tkwin);
741 if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {
742 Tk_DestroyWindow(butPtr->tkwin);
746 Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(butPtr->tkwin),
752 *--------------------------------------------------------------
756 * This procedure is invoked to process the Tcl command
757 * that corresponds to a widget managed by this module.
758 * See the user documentation for details on what it does.
761 * A standard Tcl result.
764 * See the user documentation.
766 *--------------------------------------------------------------
770 ButtonWidgetObjCmd(clientData, interp, objc, objv)
771 ClientData clientData; /* Information about button widget. */
772 Tcl_Interp *interp; /* Current interpreter. */
773 int objc; /* Number of arguments. */
774 Tcl_Obj *CONST objv[]; /* Argument values. */
776 TkButton *butPtr = (TkButton *) clientData;
782 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
785 result = Tcl_GetIndexFromObj(interp, objv[1], commandNames[butPtr->type],
786 "option", 0, &index);
787 if (result != TCL_OK) {
790 Tcl_Preserve((ClientData) butPtr);
792 switch (map[butPtr->type][index]) {
795 Tcl_WrongNumArgs(interp, 1, objv, "cget option");
798 objPtr = Tk_GetOptionValue(interp, (char *) butPtr,
799 butPtr->optionTable, objv[2], butPtr->tkwin);
800 if (objPtr == NULL) {
803 Tcl_SetObjResult(interp, objPtr);
808 case COMMAND_CONFIGURE: {
810 objPtr = Tk_GetOptionInfo(interp, (char *) butPtr,
812 (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
814 if (objPtr == NULL) {
817 Tcl_SetObjResult(interp, objPtr);
820 result = ConfigureButton(interp, butPtr, objc-2, objv+2);
825 case COMMAND_DESELECT: {
827 Tcl_WrongNumArgs(interp, 1, objv, "deselect");
830 if (butPtr->type == TYPE_CHECK_BUTTON) {
831 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
832 butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
836 } else if (butPtr->flags & SELECTED) {
837 if (Tcl_ObjSetVar2(interp,
838 butPtr->selVarNamePtr, NULL, Tcl_NewObj(),
839 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
847 case COMMAND_FLASH: {
851 Tcl_WrongNumArgs(interp, 1, objv, "flash");
854 if (butPtr->state != STATE_DISABLED) {
855 for (i = 0; i < 4; i++) {
856 if (butPtr->state == STATE_NORMAL) {
857 butPtr->state = STATE_ACTIVE;
858 Tk_SetBackgroundFromBorder(butPtr->tkwin,
859 butPtr->activeBorder);
861 butPtr->state = STATE_NORMAL;
862 Tk_SetBackgroundFromBorder(butPtr->tkwin,
863 butPtr->normalBorder);
865 TkpDisplayButton((ClientData) butPtr);
868 * Special note: must cancel any existing idle handler
869 * for TkpDisplayButton; it's no longer needed, and
870 * TkpDisplayButton cleared the REDRAW_PENDING flag.
873 Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);
874 XFlush(butPtr->display);
881 case COMMAND_INVOKE: {
883 Tcl_WrongNumArgs(interp, 1, objv, "invoke");
886 if (butPtr->state != STATE_DISABLED) {
887 result = TkInvokeButton(butPtr);
892 case COMMAND_SELECT: {
894 Tcl_WrongNumArgs(interp, 1, objv, "select");
897 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
898 butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
905 case COMMAND_TOGGLE: {
907 Tcl_WrongNumArgs(interp, 1, objv, "toggle");
910 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
911 (butPtr->flags & SELECTED) ? butPtr->offValuePtr
912 : butPtr->onValuePtr,
913 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
920 Tcl_Release((ClientData) butPtr);
924 Tcl_Release((ClientData) butPtr);
929 *----------------------------------------------------------------------
933 * This procedure is invoked by ButtonEventProc to free all the
934 * resources of a button and clean up its state.
940 * Everything associated with the widget is freed.
942 *----------------------------------------------------------------------
946 DestroyButton(butPtr)
947 TkButton *butPtr; /* Info about button widget. */
949 butPtr->flags |= BUTTON_DELETED;
950 TkpDestroyButton(butPtr);
952 if (butPtr->flags & REDRAW_PENDING) {
953 Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);
957 * Free up all the stuff that requires special handling, then
958 * let Tk_FreeOptions handle all the standard option-related
962 Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);
963 if (butPtr->textVarNamePtr != NULL) {
964 Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr),
965 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
966 ButtonTextVarProc, (ClientData) butPtr);
968 if (butPtr->image != NULL) {
969 Tk_FreeImage(butPtr->image);
971 if (butPtr->selectImage != NULL) {
972 Tk_FreeImage(butPtr->selectImage);
974 if (butPtr->normalTextGC != None) {
975 Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
977 if (butPtr->activeTextGC != None) {
978 Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
980 if (butPtr->disabledGC != None) {
981 Tk_FreeGC(butPtr->display, butPtr->disabledGC);
983 if (butPtr->gray != None) {
984 Tk_FreeBitmap(butPtr->display, butPtr->gray);
986 if (butPtr->copyGC != None) {
987 Tk_FreeGC(butPtr->display, butPtr->copyGC);
989 if (butPtr->textLayout != NULL) {
990 Tk_FreeTextLayout(butPtr->textLayout);
992 if (butPtr->selVarNamePtr != NULL) {
993 Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr),
994 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
995 ButtonVarProc, (ClientData) butPtr);
997 Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable,
999 butPtr->tkwin = NULL;
1000 Tcl_EventuallyFree((ClientData) butPtr, TCL_DYNAMIC);
1004 *----------------------------------------------------------------------
1006 * ConfigureButton --
1008 * This procedure is called to process an objc/objv list to set
1009 * configuration options for a button widget.
1012 * The return value is a standard Tcl result. If TCL_ERROR is
1013 * returned, then an error message is left in interp's result.
1016 * Configuration information, such as text string, colors, font,
1017 * etc. get set for butPtr; old resources get freed, if there
1018 * were any. The button is redisplayed.
1020 *----------------------------------------------------------------------
1024 ConfigureButton(interp, butPtr, objc, objv)
1025 Tcl_Interp *interp; /* Used for error reporting. */
1026 register TkButton *butPtr; /* Information about widget; may or may
1027 * not already have values for some fields. */
1028 int objc; /* Number of arguments. */
1029 Tcl_Obj *CONST objv[]; /* Argument values. */
1031 Tk_SavedOptions savedOptions;
1032 Tcl_Obj *errorResult = NULL;
1033 int error, haveImage;
1037 * Eliminate any existing trace on variables monitored by the button.
1040 if (butPtr->textVarNamePtr != NULL) {
1041 Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),
1042 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1043 ButtonTextVarProc, (ClientData) butPtr);
1045 if (butPtr->selVarNamePtr != NULL) {
1046 Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),
1047 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1048 ButtonVarProc, (ClientData) butPtr);
1052 * The following loop is potentially executed twice. During the
1053 * first pass configuration options get set to their new values.
1054 * If there is an error in this pass, we execute a second pass
1055 * to restore all the options to their previous values.
1058 for (error = 0; error <= 1; error++) {
1061 * First pass: set options to new values.
1064 if (Tk_SetOptions(interp, (char *) butPtr,
1065 butPtr->optionTable, objc, objv,
1066 butPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
1071 * Second pass: restore options to old values.
1074 errorResult = Tcl_GetObjResult(interp);
1075 Tcl_IncrRefCount(errorResult);
1076 Tk_RestoreSavedOptions(&savedOptions);
1080 * A few options need special processing, such as setting the
1081 * background from a 3-D border, or filling in complicated
1082 * defaults that couldn't be specified to Tk_SetOptions.
1085 if ((butPtr->state == STATE_ACTIVE)
1086 && !Tk_StrictMotif(butPtr->tkwin)) {
1087 Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);
1089 Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);
1091 if (butPtr->borderWidth < 0) {
1092 butPtr->borderWidth = 0;
1094 if (butPtr->highlightWidth < 0) {
1095 butPtr->highlightWidth = 0;
1097 if (butPtr->padX < 0) {
1100 if (butPtr->padY < 0) {
1104 if (butPtr->type >= TYPE_CHECK_BUTTON) {
1105 Tcl_Obj *valuePtr, *namePtr;
1107 if (butPtr->selVarNamePtr == NULL) {
1108 butPtr->selVarNamePtr = Tcl_NewStringObj(
1109 Tk_Name(butPtr->tkwin), -1);
1110 Tcl_IncrRefCount(butPtr->selVarNamePtr);
1112 namePtr = butPtr->selVarNamePtr;
1115 * Select the button if the associated variable has the
1116 * appropriate value, initialize the variable if it doesn't
1117 * exist, then set a trace on the variable to monitor future
1118 * changes to its value.
1121 valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
1122 butPtr->flags &= ~SELECTED;
1123 if (valuePtr != NULL) {
1124 if (strcmp(Tcl_GetString(valuePtr),
1125 Tcl_GetString(butPtr->onValuePtr)) == 0) {
1126 butPtr->flags |= SELECTED;
1129 if (Tcl_ObjSetVar2(interp, namePtr, NULL,
1130 (butPtr->type == TYPE_CHECK_BUTTON)
1131 ? butPtr->offValuePtr : Tcl_NewObj(),
1132 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1138 * If a radiobutton has the empty string as value
1139 * it should be selected.
1142 if ((butPtr->type == TYPE_RADIO_BUTTON) &&
1143 (*Tcl_GetString(butPtr->onValuePtr) == 0)) {
1144 butPtr->flags |= SELECTED;
1150 * Get the images for the widget, if there are any. Allocate the
1151 * new images before freeing the old ones, so that the reference
1152 * counts don't go to zero and cause image data to be discarded.
1155 if (butPtr->imagePtr != NULL) {
1156 image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
1157 Tcl_GetString(butPtr->imagePtr), ButtonImageProc,
1158 (ClientData) butPtr);
1159 if (image == NULL) {
1165 if (butPtr->image != NULL) {
1166 Tk_FreeImage(butPtr->image);
1168 butPtr->image = image;
1169 if (butPtr->selectImagePtr != NULL) {
1170 image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
1171 Tcl_GetString(butPtr->selectImagePtr),
1172 ButtonSelectImageProc, (ClientData) butPtr);
1173 if (image == NULL) {
1179 if (butPtr->selectImage != NULL) {
1180 Tk_FreeImage(butPtr->selectImage);
1182 butPtr->selectImage = image;
1185 if (butPtr->imagePtr != NULL || butPtr->bitmap != None) {
1188 if ((!haveImage || butPtr->compound != COMPOUND_NONE)
1189 && (butPtr->textVarNamePtr != NULL)) {
1191 * The button must display the value of a variable: set up a trace
1192 * on the variable's value, create the variable if it doesn't
1193 * exist, and fetch its current value.
1196 Tcl_Obj *valuePtr, *namePtr;
1198 namePtr = butPtr->textVarNamePtr;
1199 valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
1200 if (valuePtr == NULL) {
1201 if (Tcl_ObjSetVar2(interp, namePtr, NULL, butPtr->textPtr,
1202 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1207 if (butPtr->textPtr != NULL) {
1208 Tcl_DecrRefCount(butPtr->textPtr);
1210 butPtr->textPtr = valuePtr;
1211 Tcl_IncrRefCount(butPtr->textPtr);
1215 if ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) {
1217 * The button must display the contents of an image or
1221 if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthPtr,
1222 &butPtr->width) != TCL_OK) {
1224 Tcl_AddErrorInfo(interp, "\n (processing -width option)");
1227 if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightPtr,
1228 &butPtr->height) != TCL_OK) {
1230 Tcl_AddErrorInfo(interp, "\n (processing -height option)");
1235 * The button displays an ordinary text string.
1238 if (Tcl_GetIntFromObj(interp, butPtr->widthPtr, &butPtr->width)
1242 if (Tcl_GetIntFromObj(interp, butPtr->heightPtr, &butPtr->height)
1250 Tk_FreeSavedOptions(&savedOptions);
1254 * Reestablish the variable traces, if they're needed.
1257 if (butPtr->textVarNamePtr != NULL) {
1258 Tcl_TraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),
1259 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1260 ButtonTextVarProc, (ClientData) butPtr);
1262 if (butPtr->selVarNamePtr != NULL) {
1263 Tcl_TraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),
1264 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1265 ButtonVarProc, (ClientData) butPtr);
1268 TkButtonWorldChanged((ClientData) butPtr);
1270 Tcl_SetObjResult(interp, errorResult);
1271 Tcl_DecrRefCount(errorResult);
1279 *---------------------------------------------------------------------------
1281 * TkButtonWorldChanged --
1283 * This procedure is called when the world has changed in some
1284 * way and the widget needs to recompute all its graphics contexts
1285 * and determine its new geometry.
1291 * Button will be relayed out and redisplayed.
1293 *---------------------------------------------------------------------------
1297 TkButtonWorldChanged(instanceData)
1298 ClientData instanceData; /* Information about widget. */
1305 butPtr = (TkButton *) instanceData;
1311 gcValues.font = Tk_FontId(butPtr->tkfont);
1312 gcValues.foreground = butPtr->normalFg->pixel;
1313 gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
1316 * Note: GraphicsExpose events are disabled in normalTextGC because it's
1317 * used to copy stuff from an off-screen pixmap onto the screen (we know
1318 * that there's no problem with obscured areas).
1321 gcValues.graphics_exposures = False;
1322 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
1323 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1324 if (butPtr->normalTextGC != None) {
1325 Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
1327 butPtr->normalTextGC = newGC;
1329 if (butPtr->activeFg != NULL) {
1330 gcValues.foreground = butPtr->activeFg->pixel;
1331 gcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;
1332 mask = GCForeground | GCBackground | GCFont;
1333 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1334 if (butPtr->activeTextGC != None) {
1335 Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
1337 butPtr->activeTextGC = newGC;
1341 * Allocate the disabled graphics context, for drawing the widget in
1342 * its disabled state
1344 gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
1345 if ((butPtr->disabledFg != NULL) && (butPtr->imagePtr == NULL)) {
1346 gcValues.foreground = butPtr->disabledFg->pixel;
1347 mask = GCForeground | GCBackground | GCFont;
1349 gcValues.foreground = gcValues.background;
1350 mask = GCForeground;
1351 if (butPtr->compound != COMPOUND_NONE) {
1354 if (butPtr->gray == None) {
1355 butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin, "gray50");
1357 if (butPtr->gray != None) {
1358 gcValues.fill_style = FillStippled;
1359 gcValues.stipple = butPtr->gray;
1360 mask |= GCFillStyle | GCStipple;
1363 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1364 if (butPtr->disabledGC != None) {
1365 Tk_FreeGC(butPtr->display, butPtr->disabledGC);
1367 butPtr->disabledGC = newGC;
1369 if (butPtr->copyGC == None) {
1370 butPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);
1373 TkpComputeButtonGeometry(butPtr);
1376 * Lastly, arrange for the button to be redisplayed.
1379 if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
1380 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1381 butPtr->flags |= REDRAW_PENDING;
1386 *--------------------------------------------------------------
1388 * ButtonEventProc --
1390 * This procedure is invoked by the Tk dispatcher for various
1391 * events on buttons.
1397 * When the window gets deleted, internal structures get
1398 * cleaned up. When it gets exposed, it is redisplayed.
1400 *--------------------------------------------------------------
1404 ButtonEventProc(clientData, eventPtr)
1405 ClientData clientData; /* Information about window. */
1406 XEvent *eventPtr; /* Information about event. */
1408 TkButton *butPtr = (TkButton *) clientData;
1409 if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
1411 } else if (eventPtr->type == ConfigureNotify) {
1413 * Must redraw after size changes, since layout could have changed
1414 * and borders will need to be redrawn.
1418 } else if (eventPtr->type == DestroyNotify) {
1419 DestroyButton(butPtr);
1420 } else if (eventPtr->type == FocusIn) {
1421 if (eventPtr->xfocus.detail != NotifyInferior) {
1422 butPtr->flags |= GOT_FOCUS;
1423 if (butPtr->highlightWidth > 0) {
1427 } else if (eventPtr->type == FocusOut) {
1428 if (eventPtr->xfocus.detail != NotifyInferior) {
1429 butPtr->flags &= ~GOT_FOCUS;
1430 if (butPtr->highlightWidth > 0) {
1438 if ((butPtr->tkwin != NULL) && !(butPtr->flags & REDRAW_PENDING)) {
1439 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1440 butPtr->flags |= REDRAW_PENDING;
1445 *----------------------------------------------------------------------
1447 * ButtonCmdDeletedProc --
1449 * This procedure is invoked when a widget command is deleted. If
1450 * the widget isn't already in the process of being destroyed,
1451 * this command destroys it.
1457 * The widget is destroyed.
1459 *----------------------------------------------------------------------
1463 ButtonCmdDeletedProc(clientData)
1464 ClientData clientData; /* Pointer to widget record for widget. */
1466 TkButton *butPtr = (TkButton *) clientData;
1469 * This procedure could be invoked either because the window was
1470 * destroyed and the command was then deleted or because the command
1471 * was deleted, and then this procedure destroys the widget. The
1472 * BUTTON_DELETED flag distinguishes these cases.
1475 if (!(butPtr->flags & BUTTON_DELETED)) {
1476 Tk_DestroyWindow(butPtr->tkwin);
1481 *----------------------------------------------------------------------
1485 * This procedure is called to carry out the actions associated
1486 * with a button, such as invoking a Tcl command or setting a
1487 * variable. This procedure is invoked, for example, when the
1488 * button is invoked via the mouse.
1491 * A standard Tcl return value. Information is also left in
1492 * the interp's result.
1495 * Depends on the button and its associated command.
1497 *----------------------------------------------------------------------
1501 TkInvokeButton(butPtr)
1502 TkButton *butPtr; /* Information about button. */
1504 Tcl_Obj *namePtr = butPtr->selVarNamePtr;
1506 if (butPtr->type == TYPE_CHECK_BUTTON) {
1507 if (butPtr->flags & SELECTED) {
1508 if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,
1509 butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1514 if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,
1515 butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1520 } else if (butPtr->type == TYPE_RADIO_BUTTON) {
1521 if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL, butPtr->onValuePtr,
1522 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1527 if ((butPtr->type != TYPE_LABEL) && (butPtr->commandPtr != NULL)) {
1528 return Tcl_EvalObjEx(butPtr->interp, butPtr->commandPtr,
1535 *--------------------------------------------------------------
1539 * This procedure is invoked when someone changes the
1540 * state variable associated with a radio button. Depending
1541 * on the new value of the button's variable, the button
1542 * may be selected or deselected.
1545 * NULL is always returned.
1548 * The button may become selected or deselected.
1550 *--------------------------------------------------------------
1555 ButtonVarProc(clientData, interp, name1, name2, flags)
1556 ClientData clientData; /* Information about button. */
1557 Tcl_Interp *interp; /* Interpreter containing variable. */
1558 CONST char *name1; /* Name of variable. */
1559 CONST char *name2; /* Second part of variable name. */
1560 int flags; /* Information about what happened. */
1562 register TkButton *butPtr = (TkButton *) clientData;
1566 name = Tcl_GetString(butPtr->selVarNamePtr);
1569 * If the variable is being unset, then just re-establish the
1570 * trace unless the whole interpreter is going away.
1573 if (flags & TCL_TRACE_UNSETS) {
1574 butPtr->flags &= ~SELECTED;
1575 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1576 Tcl_TraceVar(interp, name,
1577 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1578 ButtonVarProc, clientData);
1584 * Use the value of the variable to update the selected status of
1588 valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);
1589 if (valuePtr == NULL) {
1592 value = Tcl_GetString(valuePtr);
1594 if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {
1595 if (butPtr->flags & SELECTED) {
1596 return (char *) NULL;
1598 butPtr->flags |= SELECTED;
1599 } else if (butPtr->flags & SELECTED) {
1600 butPtr->flags &= ~SELECTED;
1602 return (char *) NULL;
1606 if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
1607 && !(butPtr->flags & REDRAW_PENDING)) {
1608 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1609 butPtr->flags |= REDRAW_PENDING;
1611 return (char *) NULL;
1615 *--------------------------------------------------------------
1617 * ButtonTextVarProc --
1619 * This procedure is invoked when someone changes the variable
1620 * whose contents are to be displayed in a button.
1623 * NULL is always returned.
1626 * The text displayed in the button will change to match the
1629 *--------------------------------------------------------------
1634 ButtonTextVarProc(clientData, interp, name1, name2, flags)
1635 ClientData clientData; /* Information about button. */
1636 Tcl_Interp *interp; /* Interpreter containing variable. */
1637 CONST char *name1; /* Not used. */
1638 CONST char *name2; /* Not used. */
1639 int flags; /* Information about what happened. */
1641 TkButton *butPtr = (TkButton *) clientData;
1645 if (butPtr->flags & BUTTON_DELETED) {
1646 return (char *) NULL;
1649 name = Tcl_GetString(butPtr->textVarNamePtr);
1652 * If the variable is unset, then immediately recreate it unless
1653 * the whole interpreter is going away.
1656 if (flags & TCL_TRACE_UNSETS) {
1657 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1658 Tcl_SetVar2Ex(interp, name, NULL, butPtr->textPtr,
1660 Tcl_TraceVar(interp, name,
1661 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1662 ButtonTextVarProc, clientData);
1664 return (char *) NULL;
1667 valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);
1668 if (valuePtr == NULL) {
1669 valuePtr = Tcl_NewObj();
1671 Tcl_DecrRefCount(butPtr->textPtr);
1672 butPtr->textPtr = valuePtr;
1673 Tcl_IncrRefCount(butPtr->textPtr);
1674 TkpComputeButtonGeometry(butPtr);
1676 if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
1677 && !(butPtr->flags & REDRAW_PENDING)) {
1678 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1679 butPtr->flags |= REDRAW_PENDING;
1681 return (char *) NULL;
1685 *----------------------------------------------------------------------
1687 * ButtonImageProc --
1689 * This procedure is invoked by the image code whenever the manager
1690 * for an image does something that affects the size or contents
1691 * of an image displayed in a button.
1697 * Arranges for the button to get redisplayed.
1699 *----------------------------------------------------------------------
1703 ButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
1704 ClientData clientData; /* Pointer to widget record. */
1705 int x, y; /* Upper left pixel (within image)
1706 * that must be redisplayed. */
1707 int width, height; /* Dimensions of area to redisplay
1709 int imgWidth, imgHeight; /* New dimensions of image. */
1711 register TkButton *butPtr = (TkButton *) clientData;
1713 if (butPtr->tkwin != NULL) {
1714 TkpComputeButtonGeometry(butPtr);
1715 if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
1716 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1717 butPtr->flags |= REDRAW_PENDING;
1723 *----------------------------------------------------------------------
1725 * ButtonSelectImageProc --
1727 * This procedure is invoked by the image code whenever the manager
1728 * for an image does something that affects the size or contents
1729 * of the image displayed in a button when it is selected.
1735 * May arrange for the button to get redisplayed.
1737 *----------------------------------------------------------------------
1741 ButtonSelectImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
1742 ClientData clientData; /* Pointer to widget record. */
1743 int x, y; /* Upper left pixel (within image)
1744 * that must be redisplayed. */
1745 int width, height; /* Dimensions of area to redisplay
1747 int imgWidth, imgHeight; /* New dimensions of image. */
1749 register TkButton *butPtr = (TkButton *) clientData;
1752 * Don't recompute geometry: it's controlled by the primary image.
1755 if ((butPtr->flags & SELECTED) && (butPtr->tkwin != NULL)
1756 && Tk_IsMapped(butPtr->tkwin)
1757 && !(butPtr->flags & REDRAW_PENDING)) {
1758 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1759 butPtr->flags |= REDRAW_PENDING;