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 */ |