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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 29 - (hide annotations) (download)
Sat Oct 8 07:08:47 2016 UTC (7 years, 5 months ago) by dashley
Original Path: to_be_filed/sf_code/esrgpcpj/shared/tk_base/tkbutton.c
File MIME type: text/plain
File size: 59624 byte(s)
Directories relocated.
1 dashley 25 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkbutton.c,v 1.1.1.1 2001/06/13 04:54:45 dtashley Exp $ */
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    
1700     /* $History: tkButton.c $
1701     *
1702     * ***************** Version 1 *****************
1703     * User: Dtashley Date: 1/02/01 Time: 2:38a
1704     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
1705     * Initial check-in.
1706     */
1707    
1708     /* End of TKBUTTON.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25