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

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkbutton.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (6 years, 3 months ago) by dashley
File MIME type: text/plain
File size: 59302 byte(s)
License and property (keyword) changes.
1 /* $Header$ */
2
3 /*
4 * tkButton.c --
5 *
6 * This module implements a collection of button-like
7 * widgets for the Tk toolkit. The widgets implemented
8 * include labels, buttons, checkbuttons, and radiobuttons.
9 *
10 * Copyright (c) 1990-1994 The Regents of the University of California.
11 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
12 *
13 * See the file "license.terms" for information on usage and redistribution
14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 *
16 * RCS: @(#) $Id: tkbutton.c,v 1.1.1.1 2001/06/13 04:54:45 dtashley Exp $
17 */
18
19 #include "tkButton.h"
20 #include "default.h"
21
22 /*
23 * Class names for buttons, indexed by one of the type values defined
24 * in tkButton.h.
25 */
26
27 static char *classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"};
28
29 /*
30 * The following table defines the legal values for the -default option.
31 * It is used together with the "enum defaultValue" declaration in tkButton.h.
32 */
33
34 static char *defaultStrings[] = {
35 "active", "disabled", "normal", (char *) NULL
36 };
37
38 /*
39 * The following table defines the legal values for the -state option.
40 * It is used together with the "enum state" declaration in tkButton.h.
41 */
42
43 static char *stateStrings[] = {
44 "active", "disabled", "normal", (char *) NULL
45 };
46
47 /*
48 * Information used for parsing configuration options. There is a
49 * separate table for each of the four widget classes.
50 */
51
52 static Tk_OptionSpec labelOptionSpecs[] = {
53 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
54 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
55 {TK_OPTION_BORDER, "-background", "background", "Background",
56 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
57 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
58 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
59 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
60 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
61 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
62 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
63 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
64 TK_OPTION_NULL_OK, 0, 0},
65 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
66 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
67 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
68 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
69 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
70 TK_OPTION_NULL_OK, 0, 0},
71 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
72 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
73 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
74 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
75 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
76 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
77 {TK_OPTION_FONT, "-font", "font", "Font",
78 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
79 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
80 DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
81 {TK_OPTION_STRING, "-height", "height", "Height",
82 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
83 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
84 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
85 -1, Tk_Offset(TkButton, highlightBorder), 0,
86 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
87 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
88 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
89 0, 0, 0},
90 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
91 "HighlightThickness", DEF_LABEL_HIGHLIGHT_WIDTH,
92 Tk_Offset(TkButton, highlightWidthPtr),
93 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
94 {TK_OPTION_STRING, "-image", "image", "Image",
95 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
96 TK_OPTION_NULL_OK, 0, 0},
97 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
98 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
99 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
100 DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
101 Tk_Offset(TkButton, padX), 0, 0, 0},
102 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
103 DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
104 Tk_Offset(TkButton, padY), 0, 0, 0},
105 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
106 DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
107 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
108 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
109 0, (ClientData) stateStrings, 0},
110 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
111 DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
112 TK_OPTION_NULL_OK, 0, 0},
113 {TK_OPTION_STRING, "-text", "text", "Text",
114 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
115 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
116 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
117 TK_OPTION_NULL_OK, 0, 0},
118 {TK_OPTION_INT, "-underline", "underline", "Underline",
119 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
120 {TK_OPTION_STRING, "-width", "width", "Width",
121 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
122 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
123 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
124 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
125 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
126 (char *) NULL, 0, 0, 0, 0}
127 };
128
129 static Tk_OptionSpec buttonOptionSpecs[] = {
130 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
131 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
132 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
133 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
134 DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
135 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
136 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
137 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
138 {TK_OPTION_BORDER, "-background", "background", "Background",
139 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
140 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
141 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
142 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
143 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
144 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
145 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
146 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
147 TK_OPTION_NULL_OK, 0, 0},
148 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
149 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
150 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
151 {TK_OPTION_STRING, "-command", "command", "Command",
152 DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
153 TK_OPTION_NULL_OK, 0, 0},
154 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
155 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
156 TK_OPTION_NULL_OK, 0, 0},
157 {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
158 DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState),
159 0, (ClientData) defaultStrings, 0},
160 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
161 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
162 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
163 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
164 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
165 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
166 {TK_OPTION_FONT, "-font", "font", "Font",
167 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
168 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
169 DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
170 {TK_OPTION_STRING, "-height", "height", "Height",
171 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
172 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
173 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
174 -1, Tk_Offset(TkButton, highlightBorder), 0,
175 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
176 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
177 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
178 0, 0, 0},
179 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
180 "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
181 Tk_Offset(TkButton, highlightWidthPtr),
182 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
183 {TK_OPTION_STRING, "-image", "image", "Image",
184 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
185 TK_OPTION_NULL_OK, 0, 0},
186 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
187 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
188 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
189 DEF_BUTTON_PADX, Tk_Offset(TkButton, padXPtr),
190 Tk_Offset(TkButton, padX), 0, 0, 0},
191 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
192 DEF_BUTTON_PADY, Tk_Offset(TkButton, padYPtr),
193 Tk_Offset(TkButton, padY), 0, 0, 0},
194 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
195 DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
196 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
197 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
198 0, (ClientData) stateStrings, 0},
199 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
200 DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
201 TK_OPTION_NULL_OK, 0, 0},
202 {TK_OPTION_STRING, "-text", "text", "Text",
203 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
204 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
205 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
206 TK_OPTION_NULL_OK, 0, 0},
207 {TK_OPTION_INT, "-underline", "underline", "Underline",
208 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
209 {TK_OPTION_STRING, "-width", "width", "Width",
210 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
211 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
212 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
213 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
214 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
215 (char *) NULL, 0, -1, 0, 0, 0}
216 };
217
218 static Tk_OptionSpec checkbuttonOptionSpecs[] = {
219 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
220 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
221 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
222 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
223 DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
224 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
225 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
226 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
227 {TK_OPTION_BORDER, "-background", "background", "Background",
228 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
229 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
230 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
231 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
232 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
233 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
234 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
235 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
236 TK_OPTION_NULL_OK, 0, 0},
237 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
238 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
239 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
240 {TK_OPTION_STRING, "-command", "command", "Command",
241 DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
242 TK_OPTION_NULL_OK, 0, 0},
243 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
244 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
245 TK_OPTION_NULL_OK, 0, 0},
246 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
247 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
248 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
249 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
250 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
251 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
252 {TK_OPTION_FONT, "-font", "font", "Font",
253 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
254 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
255 DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
256 {TK_OPTION_STRING, "-height", "height", "Height",
257 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
258 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
259 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
260 -1, Tk_Offset(TkButton, highlightBorder), 0,
261 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
262 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
263 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
264 0, 0, 0},
265 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
266 "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
267 Tk_Offset(TkButton, highlightWidthPtr),
268 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
269 {TK_OPTION_STRING, "-image", "image", "Image",
270 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
271 TK_OPTION_NULL_OK, 0, 0},
272 {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
273 DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0},
274 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
275 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
276 {TK_OPTION_STRING, "-offvalue", "offValue", "Value",
277 DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0},
278 {TK_OPTION_STRING, "-onvalue", "onValue", "Value",
279 DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
280 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
281 DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
282 Tk_Offset(TkButton, padX), 0, 0, 0},
283 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
284 DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
285 Tk_Offset(TkButton, padY), 0, 0, 0},
286 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
287 DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
288 {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
289 DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
290 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},
291 {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
292 DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
293 TK_OPTION_NULL_OK, 0, 0},
294 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
295 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
296 0, (ClientData) stateStrings, 0},
297 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
298 DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
299 TK_OPTION_NULL_OK, 0, 0},
300 {TK_OPTION_STRING, "-text", "text", "Text",
301 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
302 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
303 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
304 TK_OPTION_NULL_OK, 0, 0},
305 {TK_OPTION_INT, "-underline", "underline", "Underline",
306 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
307 {TK_OPTION_STRING, "-variable", "variable", "Variable",
308 DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
309 TK_OPTION_NULL_OK, 0, 0},
310 {TK_OPTION_STRING, "-width", "width", "Width",
311 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
312 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
313 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
314 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
315 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
316 (char *) NULL, 0, -1, 0, 0, 0}
317 };
318
319 static Tk_OptionSpec radiobuttonOptionSpecs[] = {
320 {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
321 DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
322 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
323 {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
324 DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
325 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
326 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
327 DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
328 {TK_OPTION_BORDER, "-background", "background", "Background",
329 DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
330 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
331 {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
332 (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
333 {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
334 (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
335 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
336 DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
337 TK_OPTION_NULL_OK, 0, 0},
338 {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
339 DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
340 Tk_Offset(TkButton, borderWidth), 0, 0, 0},
341 {TK_OPTION_STRING, "-command", "command", "Command",
342 DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
343 TK_OPTION_NULL_OK, 0, 0},
344 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
345 DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
346 TK_OPTION_NULL_OK, 0, 0},
347 {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
348 "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
349 -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
350 (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
351 {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
352 (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
353 {TK_OPTION_FONT, "-font", "font", "Font",
354 DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
355 {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
356 DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
357 {TK_OPTION_STRING, "-height", "height", "Height",
358 DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
359 {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
360 "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
361 -1, Tk_Offset(TkButton, highlightBorder), 0,
362 (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
363 {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
364 DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
365 0, 0, 0},
366 {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
367 "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
368 Tk_Offset(TkButton, highlightWidthPtr),
369 Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
370 {TK_OPTION_STRING, "-image", "image", "Image",
371 DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
372 TK_OPTION_NULL_OK, 0, 0},
373 {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
374 DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn),
375 0, 0, 0},
376 {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
377 DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
378 {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
379 DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
380 Tk_Offset(TkButton, padX), 0, 0, 0},
381 {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
382 DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
383 Tk_Offset(TkButton, padY), 0, 0, 0},
384 {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
385 DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
386 {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
387 DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
388 TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},
389 {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
390 DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
391 TK_OPTION_NULL_OK, 0, 0},
392 {TK_OPTION_STRING_TABLE, "-state", "state", "State",
393 DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
394 0, (ClientData) stateStrings, 0},
395 {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
396 DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
397 TK_OPTION_NULL_OK, 0, 0},
398 {TK_OPTION_STRING, "-text", "text", "Text",
399 DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
400 {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
401 DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
402 TK_OPTION_NULL_OK, 0, 0},
403 {TK_OPTION_INT, "-underline", "underline", "Underline",
404 DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
405 {TK_OPTION_STRING, "-value", "value", "Value",
406 DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
407 {TK_OPTION_STRING, "-variable", "variable", "Variable",
408 DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
409 0, 0, 0},
410 {TK_OPTION_STRING, "-width", "width", "Width",
411 DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
412 {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
413 DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
414 Tk_Offset(TkButton, wrapLength), 0, 0, 0},
415 {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
416 (char *) NULL, 0, -1, 0, 0, 0}
417 };
418
419 /*
420 * The following table maps from one of the type values defined in
421 * tkButton.h, such as TYPE_LABEL, to the option template for that
422 * class of widgets.
423 */
424
425 static Tk_OptionSpec *optionSpecs[] = {
426 labelOptionSpecs,
427 buttonOptionSpecs,
428 checkbuttonOptionSpecs,
429 radiobuttonOptionSpecs
430 };
431
432 /*
433 * The following tables define the widget commands supported by
434 * each of the classes, and map the indexes into the string tables
435 * into a single enumerated type used to dispatch the widget command.
436 */
437
438 static char *commandNames[][8] = {
439 {"cget", "configure", (char *) NULL},
440 {"cget", "configure", "flash", "invoke", (char *) NULL},
441 {"cget", "configure", "deselect", "flash", "invoke", "select",
442 "toggle", (char *) NULL},
443 {"cget", "configure", "deselect", "flash", "invoke", "select",
444 (char *) NULL}
445 };
446 enum command {
447 COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
448 COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE
449 };
450 static enum command map[][8] = {
451 {COMMAND_CGET, COMMAND_CONFIGURE},
452 {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},
453 {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
454 COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},
455 {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
456 COMMAND_INVOKE, COMMAND_SELECT}
457 };
458
459 /*
460 * Forward declarations for procedures defined later in this file:
461 */
462
463 static void ButtonCmdDeletedProc _ANSI_ARGS_((
464 ClientData clientData));
465 static int ButtonCreate _ANSI_ARGS_((ClientData clientData,
466 Tcl_Interp *interp, int objc,
467 Tcl_Obj *CONST objv[], int type));
468 static void ButtonEventProc _ANSI_ARGS_((ClientData clientData,
469 XEvent *eventPtr));
470 static void ButtonImageProc _ANSI_ARGS_((ClientData clientData,
471 int x, int y, int width, int height,
472 int imgWidth, int imgHeight));
473 static void ButtonSelectImageProc _ANSI_ARGS_((
474 ClientData clientData, int x, int y, int width,
475 int height, int imgWidth, int imgHeight));
476 static char * ButtonTextVarProc _ANSI_ARGS_((ClientData clientData,
477 Tcl_Interp *interp, char *name1, char *name2,
478 int flags));
479 static char * ButtonVarProc _ANSI_ARGS_((ClientData clientData,
480 Tcl_Interp *interp, char *name1, char *name2,
481 int flags));
482 static int ButtonWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
483 Tcl_Interp *interp, int objc,
484 Tcl_Obj *CONST objv[]));
485 static int ConfigureButton _ANSI_ARGS_((Tcl_Interp *interp,
486 TkButton *butPtr, int objc,
487 Tcl_Obj *CONST objv[]));
488 static void DestroyButton _ANSI_ARGS_((TkButton *butPtr));
489
490 /*
491 *--------------------------------------------------------------
492 *
493 * Tk_ButtonCmd, Tk_CheckbuttonCmd, Tk_LabelCmd, Tk_RadiobuttonCmd --
494 *
495 * These procedures are invoked to process the "button", "label",
496 * "radiobutton", and "checkbutton" Tcl commands. See the
497 * user documentation for details on what they do.
498 *
499 * Results:
500 * A standard Tcl result.
501 *
502 * Side effects:
503 * See the user documentation. These procedures are just wrappers;
504 * they call ButtonCreate to do all of the real work.
505 *
506 *--------------------------------------------------------------
507 */
508
509 int
510 Tk_ButtonObjCmd(clientData, interp, objc, objv)
511 ClientData clientData; /* Either NULL or pointer to option table. */
512 Tcl_Interp *interp; /* Current interpreter. */
513 int objc; /* Number of arguments. */
514 Tcl_Obj *CONST objv[]; /* Argument values. */
515 {
516 return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON);
517 }
518
519 int
520 Tk_CheckbuttonObjCmd(clientData, interp, objc, objv)
521 ClientData clientData; /* Either NULL or pointer to option table. */
522 Tcl_Interp *interp; /* Current interpreter. */
523 int objc; /* Number of arguments. */
524 Tcl_Obj *CONST objv[]; /* Argument values. */
525 {
526 return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON);
527 }
528
529 int
530 Tk_LabelObjCmd(clientData, interp, objc, objv)
531 ClientData clientData; /* Either NULL or pointer to option table. */
532 Tcl_Interp *interp; /* Current interpreter. */
533 int objc; /* Number of arguments. */
534 Tcl_Obj *CONST objv[]; /* Argument values. */
535 {
536 return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL);
537 }
538
539 int
540 Tk_RadiobuttonObjCmd(clientData, interp, objc, objv)
541 ClientData clientData; /* Either NULL or pointer to option table. */
542 Tcl_Interp *interp; /* Current interpreter. */
543 int objc; /* Number of arguments. */
544 Tcl_Obj *CONST objv[]; /* Argument values. */
545 {
546 return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON);
547 }
548
549 /*
550 *--------------------------------------------------------------
551 *
552 * ButtonCreate --
553 *
554 * This procedure does all the real work of implementing the
555 * "button", "label", "radiobutton", and "checkbutton" Tcl
556 * commands. See the user documentation for details on what it does.
557 *
558 * Results:
559 * A standard Tcl result.
560 *
561 * Side effects:
562 * See the user documentation.
563 *
564 *--------------------------------------------------------------
565 */
566
567 static int
568 ButtonCreate(clientData, interp, objc, objv, type)
569 ClientData clientData; /* Option table for this widget class, or
570 * NULL if not created yet. */
571 Tcl_Interp *interp; /* Current interpreter. */
572 int objc; /* Number of arguments. */
573 Tcl_Obj *CONST objv[]; /* Argument values. */
574 int type; /* Type of button to create: TYPE_LABEL,
575 * TYPE_BUTTON, TYPE_CHECK_BUTTON, or
576 * TYPE_RADIO_BUTTON. */
577 {
578 TkButton *butPtr;
579 Tk_OptionTable optionTable;
580 Tk_Window tkwin;
581
582 optionTable = (Tk_OptionTable) clientData;
583 if (optionTable == NULL) {
584 Tcl_CmdInfo info;
585 char *name;
586
587 /*
588 * We haven't created the option table for this widget class
589 * yet. Do it now and save the table as the clientData for
590 * the command, so we'll have access to it in future
591 * invocations of the command.
592 */
593
594 TkpButtonSetDefaults(optionSpecs[type]);
595 optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);
596 name = Tcl_GetString(objv[0]);
597 Tcl_GetCommandInfo(interp, name, &info);
598 info.objClientData = (ClientData) optionTable;
599 Tcl_SetCommandInfo(interp, name, &info);
600 }
601
602 if (objc < 2) {
603 Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
604 return TCL_ERROR;
605 }
606
607 /*
608 * Create the new window.
609 */
610
611 tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
612 Tcl_GetString(objv[1]), (char *) NULL);
613 if (tkwin == NULL) {
614 return TCL_ERROR;
615 }
616
617 Tk_SetClass(tkwin, classNames[type]);
618 butPtr = TkpCreateButton(tkwin);
619
620 TkSetClassProcs(tkwin, &tkpButtonProcs, (ClientData) butPtr);
621
622 /*
623 * Initialize the data structure for the button.
624 */
625
626 butPtr->tkwin = tkwin;
627 butPtr->display = Tk_Display(tkwin);
628 butPtr->interp = interp;
629 butPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),
630 ButtonWidgetObjCmd, (ClientData) butPtr, ButtonCmdDeletedProc);
631 butPtr->type = type;
632 butPtr->optionTable = optionTable;
633 butPtr->textPtr = NULL;
634 butPtr->underline = -1;
635 butPtr->textVarNamePtr = NULL;
636 butPtr->bitmap = None;
637 butPtr->imagePtr = NULL;
638 butPtr->image = NULL;
639 butPtr->selectImagePtr = NULL;
640 butPtr->selectImage = NULL;
641 butPtr->state = STATE_NORMAL;
642 butPtr->normalBorder = NULL;
643 butPtr->activeBorder = NULL;
644 butPtr->borderWidthPtr = NULL;
645 butPtr->borderWidth = 0;
646 butPtr->relief = TK_RELIEF_FLAT;
647 butPtr->highlightWidthPtr = NULL;
648 butPtr->highlightWidth = 0;
649 butPtr->highlightBorder = NULL;
650 butPtr->highlightColorPtr = NULL;
651 butPtr->inset = 0;
652 butPtr->tkfont = NULL;
653 butPtr->normalFg = NULL;
654 butPtr->activeFg = NULL;
655 butPtr->disabledFg = NULL;
656 butPtr->normalTextGC = None;
657 butPtr->activeTextGC = None;
658 butPtr->disabledGC = None;
659 butPtr->gray = None;
660 butPtr->copyGC = None;
661 butPtr->widthPtr = NULL;
662 butPtr->width = 0;
663 butPtr->heightPtr = NULL;
664 butPtr->height = 0;
665 butPtr->wrapLengthPtr = NULL;
666 butPtr->wrapLength = 0;
667 butPtr->padXPtr = NULL;
668 butPtr->padX = 0;
669 butPtr->padYPtr = NULL;
670 butPtr->padY = 0;
671 butPtr->anchor = TK_ANCHOR_CENTER;
672 butPtr->justify = TK_JUSTIFY_CENTER;
673 butPtr->indicatorOn = 0;
674 butPtr->selectBorder = NULL;
675 butPtr->textWidth = 0;
676 butPtr->textHeight = 0;
677 butPtr->textLayout = NULL;
678 butPtr->indicatorSpace = 0;
679 butPtr->indicatorDiameter = 0;
680 butPtr->defaultState = DEFAULT_DISABLED;
681 butPtr->selVarNamePtr = NULL;
682 butPtr->onValuePtr = NULL;
683 butPtr->offValuePtr = NULL;
684 butPtr->cursor = None;
685 butPtr->takeFocusPtr = NULL;
686 butPtr->commandPtr = NULL;
687 butPtr->flags = 0;
688
689 Tk_CreateEventHandler(butPtr->tkwin,
690 ExposureMask|StructureNotifyMask|FocusChangeMask,
691 ButtonEventProc, (ClientData) butPtr);
692
693 if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin)
694 != TCL_OK) {
695 Tk_DestroyWindow(butPtr->tkwin);
696 return TCL_ERROR;
697 }
698 if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {
699 Tk_DestroyWindow(butPtr->tkwin);
700 return TCL_ERROR;
701 }
702
703 Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(butPtr->tkwin),
704 -1);
705 return TCL_OK;
706 }
707
708 /*
709 *--------------------------------------------------------------
710 *
711 * ButtonWidgetCmd --
712 *
713 * This procedure is invoked to process the Tcl command
714 * that corresponds to a widget managed by this module.
715 * See the user documentation for details on what it does.
716 *
717 * Results:
718 * A standard Tcl result.
719 *
720 * Side effects:
721 * See the user documentation.
722 *
723 *--------------------------------------------------------------
724 */
725
726 static int
727 ButtonWidgetObjCmd(clientData, interp, objc, objv)
728 ClientData clientData; /* Information about button widget. */
729 Tcl_Interp *interp; /* Current interpreter. */
730 int objc; /* Number of arguments. */
731 Tcl_Obj *CONST objv[]; /* Argument values. */
732 {
733 TkButton *butPtr = (TkButton *) clientData;
734 int index;
735 int result;
736 Tcl_Obj *objPtr;
737
738 if (objc < 2) {
739 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
740 return TCL_ERROR;
741 }
742 result = Tcl_GetIndexFromObj(interp, objv[1], commandNames[butPtr->type],
743 "option", 0, &index);
744 if (result != TCL_OK) {
745 return result;
746 }
747 Tcl_Preserve((ClientData) butPtr);
748
749 switch (map[butPtr->type][index]) {
750 case COMMAND_CGET: {
751 if (objc != 3) {
752 Tcl_WrongNumArgs(interp, 1, objv, "cget option");
753 goto error;
754 }
755 objPtr = Tk_GetOptionValue(interp, (char *) butPtr,
756 butPtr->optionTable, objv[2], butPtr->tkwin);
757 if (objPtr == NULL) {
758 goto error;
759 } else {
760 Tcl_SetObjResult(interp, objPtr);
761 }
762 break;
763 }
764
765 case COMMAND_CONFIGURE: {
766 if (objc <= 3) {
767 objPtr = Tk_GetOptionInfo(interp, (char *) butPtr,
768 butPtr->optionTable,
769 (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
770 butPtr->tkwin);
771 if (objPtr == NULL) {
772 goto error;
773 } else {
774 Tcl_SetObjResult(interp, objPtr);
775 }
776 } else {
777 result = ConfigureButton(interp, butPtr, objc-2, objv+2);
778 }
779 break;
780 }
781
782 case COMMAND_DESELECT: {
783 if (objc > 2) {
784 Tcl_WrongNumArgs(interp, 1, objv, "deselect");
785 goto error;
786 }
787 if (butPtr->type == TYPE_CHECK_BUTTON) {
788 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
789 butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
790 == NULL) {
791 goto error;
792 }
793 } else if (butPtr->flags & SELECTED) {
794 if (Tcl_ObjSetVar2(interp,
795 butPtr->selVarNamePtr, NULL, Tcl_NewObj(),
796 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
797 == NULL) {
798 goto error;
799 }
800 }
801 break;
802 }
803
804 case COMMAND_FLASH: {
805 int i;
806
807 if (objc > 2) {
808 Tcl_WrongNumArgs(interp, 1, objv, "flash");
809 goto error;
810 }
811 if (butPtr->state != STATE_DISABLED) {
812 for (i = 0; i < 4; i++) {
813 if (butPtr->state == STATE_NORMAL) {
814 butPtr->state = STATE_ACTIVE;
815 Tk_SetBackgroundFromBorder(butPtr->tkwin,
816 butPtr->activeBorder);
817 } else {
818 butPtr->state = STATE_NORMAL;
819 Tk_SetBackgroundFromBorder(butPtr->tkwin,
820 butPtr->normalBorder);
821 }
822 TkpDisplayButton((ClientData) butPtr);
823
824 /*
825 * Special note: must cancel any existing idle handler
826 * for TkpDisplayButton; it's no longer needed, and
827 * TkpDisplayButton cleared the REDRAW_PENDING flag.
828 */
829
830 Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);
831 XFlush(butPtr->display);
832 Tcl_Sleep(50);
833 }
834 }
835 break;
836 }
837
838 case COMMAND_INVOKE: {
839 if (objc > 2) {
840 Tcl_WrongNumArgs(interp, 1, objv, "invoke");
841 goto error;
842 }
843 if (butPtr->state != STATE_DISABLED) {
844 result = TkInvokeButton(butPtr);
845 }
846 break;
847 }
848
849 case COMMAND_SELECT: {
850 if (objc > 2) {
851 Tcl_WrongNumArgs(interp, 1, objv, "select");
852 goto error;
853 }
854 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
855 butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
856 == NULL) {
857 goto error;
858 }
859 break;
860 }
861
862 case COMMAND_TOGGLE: {
863 if (objc > 2) {
864 Tcl_WrongNumArgs(interp, 1, objv, "toggle");
865 goto error;
866 }
867 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
868 (butPtr->flags & SELECTED) ? butPtr->offValuePtr
869 : butPtr->onValuePtr,
870 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
871 == NULL) {
872 goto error;
873 }
874 break;
875 }
876 }
877 Tcl_Release((ClientData) butPtr);
878 return result;
879
880 error:
881 Tcl_Release((ClientData) butPtr);
882 return TCL_ERROR;
883 }
884
885 /*
886 *----------------------------------------------------------------------
887 *
888 * DestroyButton --
889 *
890 * This procedure is invoked by ButtonEventProc to free all the
891 * resources of a button and clean up its state.
892 *
893 * Results:
894 * None.
895 *
896 * Side effects:
897 * Everything associated with the widget is freed.
898 *
899 *----------------------------------------------------------------------
900 */
901
902 static void
903 DestroyButton(butPtr)
904 TkButton *butPtr; /* Info about button widget. */
905 {
906 TkpDestroyButton(butPtr);
907
908 butPtr->flags |= BUTTON_DELETED;
909 if (butPtr->flags & REDRAW_PENDING) {
910 Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);
911 }
912
913 /*
914 * Free up all the stuff that requires special handling, then
915 * let Tk_FreeOptions handle all the standard option-related
916 * stuff.
917 */
918
919 Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);
920 if (butPtr->textVarNamePtr != NULL) {
921 Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr),
922 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
923 ButtonTextVarProc, (ClientData) butPtr);
924 }
925 if (butPtr->image != NULL) {
926 Tk_FreeImage(butPtr->image);
927 }
928 if (butPtr->selectImage != NULL) {
929 Tk_FreeImage(butPtr->selectImage);
930 }
931 if (butPtr->normalTextGC != None) {
932 Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
933 }
934 if (butPtr->activeTextGC != None) {
935 Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
936 }
937 if (butPtr->disabledGC != None) {
938 Tk_FreeGC(butPtr->display, butPtr->disabledGC);
939 }
940 if (butPtr->gray != None) {
941 Tk_FreeBitmap(butPtr->display, butPtr->gray);
942 }
943 if (butPtr->copyGC != None) {
944 Tk_FreeGC(butPtr->display, butPtr->copyGC);
945 }
946 if (butPtr->textLayout != NULL) {
947 Tk_FreeTextLayout(butPtr->textLayout);
948 }
949 if (butPtr->selVarNamePtr != NULL) {
950 Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr),
951 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
952 ButtonVarProc, (ClientData) butPtr);
953 }
954 Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable,
955 butPtr->tkwin);
956 butPtr->tkwin = NULL;
957 Tcl_EventuallyFree((ClientData) butPtr, TCL_DYNAMIC);
958 }
959
960 /*
961 *----------------------------------------------------------------------
962 *
963 * ConfigureButton --
964 *
965 * This procedure is called to process an objc/objv list to set
966 * configuration options for a button widget.
967 *
968 * Results:
969 * The return value is a standard Tcl result. If TCL_ERROR is
970 * returned, then an error message is left in interp's result.
971 *
972 * Side effects:
973 * Configuration information, such as text string, colors, font,
974 * etc. get set for butPtr; old resources get freed, if there
975 * were any. The button is redisplayed.
976 *
977 *----------------------------------------------------------------------
978 */
979
980 static int
981 ConfigureButton(interp, butPtr, objc, objv)
982 Tcl_Interp *interp; /* Used for error reporting. */
983 register TkButton *butPtr; /* Information about widget; may or may
984 * not already have values for some fields. */
985 int objc; /* Number of arguments. */
986 Tcl_Obj *CONST objv[]; /* Argument values. */
987 {
988 Tk_SavedOptions savedOptions;
989 Tcl_Obj *errorResult = NULL;
990 int error;
991 Tk_Image image;
992
993 /*
994 * Eliminate any existing trace on variables monitored by the button.
995 */
996
997 if (butPtr->textVarNamePtr != NULL) {
998 Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),
999 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1000 ButtonTextVarProc, (ClientData) butPtr);
1001 }
1002 if (butPtr->selVarNamePtr != NULL) {
1003 Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),
1004 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1005 ButtonVarProc, (ClientData) butPtr);
1006 }
1007
1008 /*
1009 * The following loop is potentially executed twice. During the
1010 * first pass configuration options get set to their new values.
1011 * If there is an error in this pass, we execute a second pass
1012 * to restore all the options to their previous values.
1013 */
1014
1015 for (error = 0; error <= 1; error++) {
1016 if (!error) {
1017 /*
1018 * First pass: set options to new values.
1019 */
1020
1021 if (Tk_SetOptions(interp, (char *) butPtr,
1022 butPtr->optionTable, objc, objv,
1023 butPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
1024 continue;
1025 }
1026 } else {
1027 /*
1028 * Second pass: restore options to old values.
1029 */
1030
1031 errorResult = Tcl_GetObjResult(interp);
1032 Tcl_IncrRefCount(errorResult);
1033 Tk_RestoreSavedOptions(&savedOptions);
1034 }
1035
1036 /*
1037 * A few options need special processing, such as setting the
1038 * background from a 3-D border, or filling in complicated
1039 * defaults that couldn't be specified to Tk_SetOptions.
1040 */
1041
1042 if ((butPtr->state == STATE_ACTIVE)
1043 && !Tk_StrictMotif(butPtr->tkwin)) {
1044 Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);
1045 } else {
1046 Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);
1047 }
1048 if (butPtr->borderWidth < 0) {
1049 butPtr->borderWidth = 0;
1050 }
1051 if (butPtr->highlightWidth < 0) {
1052 butPtr->highlightWidth = 0;
1053 }
1054 if (butPtr->padX < 0) {
1055 butPtr->padX = 0;
1056 }
1057 if (butPtr->padY < 0) {
1058 butPtr->padY = 0;
1059 }
1060
1061 if (butPtr->type >= TYPE_CHECK_BUTTON) {
1062 Tcl_Obj *valuePtr, *namePtr;
1063
1064 if (butPtr->selVarNamePtr == NULL) {
1065 butPtr->selVarNamePtr = Tcl_NewStringObj(
1066 Tk_Name(butPtr->tkwin), -1);
1067 Tcl_IncrRefCount(butPtr->selVarNamePtr);
1068 }
1069 namePtr = butPtr->selVarNamePtr;
1070
1071 /*
1072 * Select the button if the associated variable has the
1073 * appropriate value, initialize the variable if it doesn't
1074 * exist, then set a trace on the variable to monitor future
1075 * changes to its value.
1076 */
1077
1078 valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
1079 butPtr->flags &= ~SELECTED;
1080 if (valuePtr != NULL) {
1081 if (strcmp(Tcl_GetString(valuePtr),
1082 Tcl_GetString(butPtr->onValuePtr)) == 0) {
1083 butPtr->flags |= SELECTED;
1084 }
1085 } else {
1086 if (Tcl_ObjSetVar2(interp, namePtr, NULL,
1087 (butPtr->type == TYPE_CHECK_BUTTON)
1088 ? butPtr->offValuePtr : Tcl_NewObj(),
1089 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1090 == NULL) {
1091 continue;
1092 }
1093 }
1094 }
1095
1096 /*
1097 * Get the images for the widget, if there are any. Allocate the
1098 * new images before freeing the old ones, so that the reference
1099 * counts don't go to zero and cause image data to be discarded.
1100 */
1101
1102 if (butPtr->imagePtr != NULL) {
1103 image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
1104 Tcl_GetString(butPtr->imagePtr), ButtonImageProc,
1105 (ClientData) butPtr);
1106 if (image == NULL) {
1107 continue;
1108 }
1109 } else {
1110 image = NULL;
1111 }
1112 if (butPtr->image != NULL) {
1113 Tk_FreeImage(butPtr->image);
1114 }
1115 butPtr->image = image;
1116 if (butPtr->selectImagePtr != NULL) {
1117 image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
1118 Tcl_GetString(butPtr->selectImagePtr),
1119 ButtonSelectImageProc, (ClientData) butPtr);
1120 if (image == NULL) {
1121 continue;
1122 }
1123 } else {
1124 image = NULL;
1125 }
1126 if (butPtr->selectImage != NULL) {
1127 Tk_FreeImage(butPtr->selectImage);
1128 }
1129 butPtr->selectImage = image;
1130
1131 if ((butPtr->imagePtr == NULL) && (butPtr->bitmap == None)
1132 && (butPtr->textVarNamePtr != NULL)) {
1133 /*
1134 * The button must display the value of a variable: set up a trace
1135 * on the variable's value, create the variable if it doesn't
1136 * exist, and fetch its current value.
1137 */
1138
1139 Tcl_Obj *valuePtr, *namePtr;
1140
1141 namePtr = butPtr->textVarNamePtr;
1142 valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
1143 if (valuePtr == NULL) {
1144 if (Tcl_ObjSetVar2(interp, namePtr, NULL, butPtr->textPtr,
1145 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1146 == NULL) {
1147 continue;
1148 }
1149 } else {
1150 if (butPtr->textPtr != NULL) {
1151 Tcl_DecrRefCount(butPtr->textPtr);
1152 }
1153 butPtr->textPtr = valuePtr;
1154 Tcl_IncrRefCount(butPtr->textPtr);
1155 }
1156 }
1157
1158 if ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) {
1159 /*
1160 * The button must display the contents of an image or
1161 * bitmap.
1162 */
1163
1164 if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthPtr,
1165 &butPtr->width) != TCL_OK) {
1166 widthError:
1167 Tcl_AddErrorInfo(interp, "\n (processing -width option)");
1168 continue;
1169 }
1170 if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightPtr,
1171 &butPtr->height) != TCL_OK) {
1172 heightError:
1173 Tcl_AddErrorInfo(interp, "\n (processing -height option)");
1174 continue;
1175 }
1176 } else {
1177 /*
1178 * The button displays an ordinary text string.
1179 */
1180
1181 if (Tcl_GetIntFromObj(interp, butPtr->widthPtr, &butPtr->width)
1182 != TCL_OK) {
1183 goto widthError;
1184 }
1185 if (Tcl_GetIntFromObj(interp, butPtr->heightPtr, &butPtr->height)
1186 != TCL_OK) {
1187 goto heightError;
1188 }
1189 }
1190 break;
1191 }
1192 if (!error) {
1193 Tk_FreeSavedOptions(&savedOptions);
1194 }
1195
1196 /*
1197 * Reestablish the variable traces, if they're needed.
1198 */
1199
1200 if (butPtr->textVarNamePtr != NULL) {
1201 Tcl_TraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),
1202 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1203 ButtonTextVarProc, (ClientData) butPtr);
1204 }
1205 if (butPtr->selVarNamePtr != NULL) {
1206 Tcl_TraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),
1207 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1208 ButtonVarProc, (ClientData) butPtr);
1209 }
1210
1211 TkButtonWorldChanged((ClientData) butPtr);
1212 if (error) {
1213 Tcl_SetObjResult(interp, errorResult);
1214 Tcl_DecrRefCount(errorResult);
1215 return TCL_ERROR;
1216 } else {
1217 return TCL_OK;
1218 }
1219 }
1220
1221 /*
1222 *---------------------------------------------------------------------------
1223 *
1224 * TkButtonWorldChanged --
1225 *
1226 * This procedure is called when the world has changed in some
1227 * way and the widget needs to recompute all its graphics contexts
1228 * and determine its new geometry.
1229 *
1230 * Results:
1231 * None.
1232 *
1233 * Side effects:
1234 * Button will be relayed out and redisplayed.
1235 *
1236 *---------------------------------------------------------------------------
1237 */
1238
1239 void
1240 TkButtonWorldChanged(instanceData)
1241 ClientData instanceData; /* Information about widget. */
1242 {
1243 XGCValues gcValues;
1244 GC newGC;
1245 unsigned long mask;
1246 TkButton *butPtr;
1247
1248 butPtr = (TkButton *) instanceData;
1249
1250 /*
1251 * Recompute GCs.
1252 */
1253
1254 gcValues.font = Tk_FontId(butPtr->tkfont);
1255 gcValues.foreground = butPtr->normalFg->pixel;
1256 gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
1257
1258 /*
1259 * Note: GraphicsExpose events are disabled in normalTextGC because it's
1260 * used to copy stuff from an off-screen pixmap onto the screen (we know
1261 * that there's no problem with obscured areas).
1262 */
1263
1264 gcValues.graphics_exposures = False;
1265 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
1266 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1267 if (butPtr->normalTextGC != None) {
1268 Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
1269 }
1270 butPtr->normalTextGC = newGC;
1271
1272 if (butPtr->activeFg != NULL) {
1273 gcValues.foreground = butPtr->activeFg->pixel;
1274 gcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;
1275 mask = GCForeground | GCBackground | GCFont;
1276 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1277 if (butPtr->activeTextGC != None) {
1278 Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
1279 }
1280 butPtr->activeTextGC = newGC;
1281 }
1282
1283 /*
1284 * Allocate the disabled graphics context, for drawing the widget in
1285 * its disabled state
1286 */
1287 gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
1288 if ((butPtr->disabledFg != NULL) && (butPtr->imagePtr == NULL)) {
1289 gcValues.foreground = butPtr->disabledFg->pixel;
1290 mask = GCForeground | GCBackground | GCFont;
1291 } else {
1292 gcValues.foreground = gcValues.background;
1293 mask = GCForeground;
1294 if (butPtr->gray == None) {
1295 butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin, "gray50");
1296 }
1297 if (butPtr->gray != None) {
1298 gcValues.fill_style = FillStippled;
1299 gcValues.stipple = butPtr->gray;
1300 mask |= GCFillStyle | GCStipple;
1301 }
1302 }
1303 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1304 if (butPtr->disabledGC != None) {
1305 Tk_FreeGC(butPtr->display, butPtr->disabledGC);
1306 }
1307 butPtr->disabledGC = newGC;
1308
1309 if (butPtr->copyGC == None) {
1310 butPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);
1311 }
1312
1313 TkpComputeButtonGeometry(butPtr);
1314
1315 /*
1316 * Lastly, arrange for the button to be redisplayed.
1317 */
1318
1319 if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
1320 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1321 butPtr->flags |= REDRAW_PENDING;
1322 }
1323 }
1324
1325 /*
1326 *--------------------------------------------------------------
1327 *
1328 * ButtonEventProc --
1329 *
1330 * This procedure is invoked by the Tk dispatcher for various
1331 * events on buttons.
1332 *
1333 * Results:
1334 * None.
1335 *
1336 * Side effects:
1337 * When the window gets deleted, internal structures get
1338 * cleaned up. When it gets exposed, it is redisplayed.
1339 *
1340 *--------------------------------------------------------------
1341 */
1342
1343 static void
1344 ButtonEventProc(clientData, eventPtr)
1345 ClientData clientData; /* Information about window. */
1346 XEvent *eventPtr; /* Information about event. */
1347 {
1348 TkButton *butPtr = (TkButton *) clientData;
1349 if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
1350 goto redraw;
1351 } else if (eventPtr->type == ConfigureNotify) {
1352 /*
1353 * Must redraw after size changes, since layout could have changed
1354 * and borders will need to be redrawn.
1355 */
1356
1357 goto redraw;
1358 } else if (eventPtr->type == DestroyNotify) {
1359 DestroyButton(butPtr);
1360 } else if (eventPtr->type == FocusIn) {
1361 if (eventPtr->xfocus.detail != NotifyInferior) {
1362 butPtr->flags |= GOT_FOCUS;
1363 if (butPtr->highlightWidth > 0) {
1364 goto redraw;
1365 }
1366 }
1367 } else if (eventPtr->type == FocusOut) {
1368 if (eventPtr->xfocus.detail != NotifyInferior) {
1369 butPtr->flags &= ~GOT_FOCUS;
1370 if (butPtr->highlightWidth > 0) {
1371 goto redraw;
1372 }
1373 }
1374 }
1375 return;
1376
1377 redraw:
1378 if ((butPtr->tkwin != NULL) && !(butPtr->flags & REDRAW_PENDING)) {
1379 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1380 butPtr->flags |= REDRAW_PENDING;
1381 }
1382 }
1383
1384 /*
1385 *----------------------------------------------------------------------
1386 *
1387 * ButtonCmdDeletedProc --
1388 *
1389 * This procedure is invoked when a widget command is deleted. If
1390 * the widget isn't already in the process of being destroyed,
1391 * this command destroys it.
1392 *
1393 * Results:
1394 * None.
1395 *
1396 * Side effects:
1397 * The widget is destroyed.
1398 *
1399 *----------------------------------------------------------------------
1400 */
1401
1402 static void
1403 ButtonCmdDeletedProc(clientData)
1404 ClientData clientData; /* Pointer to widget record for widget. */
1405 {
1406 TkButton *butPtr = (TkButton *) clientData;
1407
1408 /*
1409 * This procedure could be invoked either because the window was
1410 * destroyed and the command was then deleted or because the command
1411 * was deleted, and then this procedure destroys the widget. The
1412 * BUTTON_DELETED flag distinguishes these cases.
1413 */
1414
1415 if (!(butPtr->flags & BUTTON_DELETED)) {
1416 Tk_DestroyWindow(butPtr->tkwin);
1417 }
1418 }
1419
1420 /*
1421 *----------------------------------------------------------------------
1422 *
1423 * TkInvokeButton --
1424 *
1425 * This procedure is called to carry out the actions associated
1426 * with a button, such as invoking a Tcl command or setting a
1427 * variable. This procedure is invoked, for example, when the
1428 * button is invoked via the mouse.
1429 *
1430 * Results:
1431 * A standard Tcl return value. Information is also left in
1432 * the interp's result.
1433 *
1434 * Side effects:
1435 * Depends on the button and its associated command.
1436 *
1437 *----------------------------------------------------------------------
1438 */
1439
1440 int
1441 TkInvokeButton(butPtr)
1442 TkButton *butPtr; /* Information about button. */
1443 {
1444 Tcl_Obj *namePtr = butPtr->selVarNamePtr;
1445
1446 if (butPtr->type == TYPE_CHECK_BUTTON) {
1447 if (butPtr->flags & SELECTED) {
1448 if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,
1449 butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1450 == NULL) {
1451 return TCL_ERROR;
1452 }
1453 } else {
1454 if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,
1455 butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1456 == NULL) {
1457 return TCL_ERROR;
1458 }
1459 }
1460 } else if (butPtr->type == TYPE_RADIO_BUTTON) {
1461 if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL, butPtr->onValuePtr,
1462 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
1463 == NULL) {
1464 return TCL_ERROR;
1465 }
1466 }
1467 if ((butPtr->type != TYPE_LABEL) && (butPtr->commandPtr != NULL)) {
1468 return Tcl_EvalObjEx(butPtr->interp, butPtr->commandPtr,
1469 TCL_EVAL_GLOBAL);
1470 }
1471 return TCL_OK;
1472 }
1473
1474 /*
1475 *--------------------------------------------------------------
1476 *
1477 * ButtonVarProc --
1478 *
1479 * This procedure is invoked when someone changes the
1480 * state variable associated with a radio button. Depending
1481 * on the new value of the button's variable, the button
1482 * may be selected or deselected.
1483 *
1484 * Results:
1485 * NULL is always returned.
1486 *
1487 * Side effects:
1488 * The button may become selected or deselected.
1489 *
1490 *--------------------------------------------------------------
1491 */
1492
1493 /* ARGSUSED */
1494 static char *
1495 ButtonVarProc(clientData, interp, name1, name2, flags)
1496 ClientData clientData; /* Information about button. */
1497 Tcl_Interp *interp; /* Interpreter containing variable. */
1498 char *name1; /* Name of variable. */
1499 char *name2; /* Second part of variable name. */
1500 int flags; /* Information about what happened. */
1501 {
1502 register TkButton *butPtr = (TkButton *) clientData;
1503 char *name, *value;
1504 Tcl_Obj *valuePtr;
1505
1506 name = Tcl_GetString(butPtr->selVarNamePtr);
1507
1508 /*
1509 * If the variable is being unset, then just re-establish the
1510 * trace unless the whole interpreter is going away.
1511 */
1512
1513 if (flags & TCL_TRACE_UNSETS) {
1514 butPtr->flags &= ~SELECTED;
1515 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1516 Tcl_TraceVar(interp, name,
1517 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1518 ButtonVarProc, clientData);
1519 }
1520 goto redisplay;
1521 }
1522
1523 /*
1524 * Use the value of the variable to update the selected status of
1525 * the button.
1526 */
1527
1528 valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);
1529 if (valuePtr == NULL) {
1530 value = "";
1531 } else {
1532 value = Tcl_GetString(valuePtr);
1533 }
1534 if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {
1535 if (butPtr->flags & SELECTED) {
1536 return (char *) NULL;
1537 }
1538 butPtr->flags |= SELECTED;
1539 } else if (butPtr->flags & SELECTED) {
1540 butPtr->flags &= ~SELECTED;
1541 } else {
1542 return (char *) NULL;
1543 }
1544
1545 redisplay:
1546 if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
1547 && !(butPtr->flags & REDRAW_PENDING)) {
1548 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1549 butPtr->flags |= REDRAW_PENDING;
1550 }
1551 return (char *) NULL;
1552 }
1553
1554 /*
1555 *--------------------------------------------------------------
1556 *
1557 * ButtonTextVarProc --
1558 *
1559 * This procedure is invoked when someone changes the variable
1560 * whose contents are to be displayed in a button.
1561 *
1562 * Results:
1563 * NULL is always returned.
1564 *
1565 * Side effects:
1566 * The text displayed in the button will change to match the
1567 * variable.
1568 *
1569 *--------------------------------------------------------------
1570 */
1571
1572 /* ARGSUSED */
1573 static char *
1574 ButtonTextVarProc(clientData, interp, name1, name2, flags)
1575 ClientData clientData; /* Information about button. */
1576 Tcl_Interp *interp; /* Interpreter containing variable. */
1577 char *name1; /* Not used. */
1578 char *name2; /* Not used. */
1579 int flags; /* Information about what happened. */
1580 {
1581 TkButton *butPtr = (TkButton *) clientData;
1582 char *name;
1583 Tcl_Obj *valuePtr;
1584
1585 name = Tcl_GetString(butPtr->textVarNamePtr);
1586
1587 /*
1588 * If the variable is unset, then immediately recreate it unless
1589 * the whole interpreter is going away.
1590 */
1591
1592 if (flags & TCL_TRACE_UNSETS) {
1593 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1594 Tcl_SetVar2Ex(interp, name, NULL, butPtr->textPtr,
1595 TCL_GLOBAL_ONLY);
1596 Tcl_TraceVar(interp, name,
1597 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1598 ButtonTextVarProc, clientData);
1599 }
1600 return (char *) NULL;
1601 }
1602
1603 valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);
1604 if (valuePtr == NULL) {
1605 valuePtr = Tcl_NewObj();
1606 }
1607 Tcl_DecrRefCount(butPtr->textPtr);
1608 butPtr->textPtr = valuePtr;
1609 Tcl_IncrRefCount(butPtr->textPtr);
1610 TkpComputeButtonGeometry(butPtr);
1611
1612 if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
1613 && !(butPtr->flags & REDRAW_PENDING)) {
1614 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1615 butPtr->flags |= REDRAW_PENDING;
1616 }
1617 return (char *) NULL;
1618 }
1619
1620 /*
1621 *----------------------------------------------------------------------
1622 *
1623 * ButtonImageProc --
1624 *
1625 * This procedure is invoked by the image code whenever the manager
1626 * for an image does something that affects the size or contents
1627 * of an image displayed in a button.
1628 *
1629 * Results:
1630 * None.
1631 *
1632 * Side effects:
1633 * Arranges for the button to get redisplayed.
1634 *
1635 *----------------------------------------------------------------------
1636 */
1637
1638 static void
1639 ButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
1640 ClientData clientData; /* Pointer to widget record. */
1641 int x, y; /* Upper left pixel (within image)
1642 * that must be redisplayed. */
1643 int width, height; /* Dimensions of area to redisplay
1644 * (may be <= 0). */
1645 int imgWidth, imgHeight; /* New dimensions of image. */
1646 {
1647 register TkButton *butPtr = (TkButton *) clientData;
1648
1649 if (butPtr->tkwin != NULL) {
1650 TkpComputeButtonGeometry(butPtr);
1651 if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
1652 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1653 butPtr->flags |= REDRAW_PENDING;
1654 }
1655 }
1656 }
1657
1658 /*
1659 *----------------------------------------------------------------------
1660 *
1661 * ButtonSelectImageProc --
1662 *
1663 * This procedure is invoked by the image code whenever the manager
1664 * for an image does something that affects the size or contents
1665 * of the image displayed in a button when it is selected.
1666 *
1667 * Results:
1668 * None.
1669 *
1670 * Side effects:
1671 * May arrange for the button to get redisplayed.
1672 *
1673 *----------------------------------------------------------------------
1674 */
1675
1676 static void
1677 ButtonSelectImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
1678 ClientData clientData; /* Pointer to widget record. */
1679 int x, y; /* Upper left pixel (within image)
1680 * that must be redisplayed. */
1681 int width, height; /* Dimensions of area to redisplay
1682 * (may be <= 0). */
1683 int imgWidth, imgHeight; /* New dimensions of image. */
1684 {
1685 register TkButton *butPtr = (TkButton *) clientData;
1686
1687 /*
1688 * Don't recompute geometry: it's controlled by the primary image.
1689 */
1690
1691 if ((butPtr->flags & SELECTED) && (butPtr->tkwin != NULL)
1692 && Tk_IsMapped(butPtr->tkwin)
1693 && !(butPtr->flags & REDRAW_PENDING)) {
1694 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);
1695 butPtr->flags |= REDRAW_PENDING;
1696 }
1697 }
1698
1699 /* End of tkbutton.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25