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

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkbutton.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

projs/trunk/shared_source/tk_base/tkbutton.c revision 42 by dashley, Fri Oct 14 01:50:00 2016 UTC projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkbutton.c revision 220 by dashley, Sun Jul 22 15:58:07 2018 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkbutton.c,v 1.1.1.1 2001/06/13 04:54:45 dtashley Exp $ */  
   
 /*  
  * tkButton.c --  
  *  
  *      This module implements a collection of button-like  
  *      widgets for the Tk toolkit.  The widgets implemented  
  *      include labels, buttons, checkbuttons, and radiobuttons.  
  *  
  * Copyright (c) 1990-1994 The Regents of the University of California.  
  * Copyright (c) 1994-1998 Sun Microsystems, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tkbutton.c,v 1.1.1.1 2001/06/13 04:54:45 dtashley Exp $  
  */  
   
 #include "tkButton.h"  
 #include "default.h"  
   
 /*  
  * Class names for buttons, indexed by one of the type values defined  
  * in tkButton.h.  
  */  
   
 static char *classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"};  
   
 /*  
  * The following table defines the legal values for the -default option.  
  * It is used together with the "enum defaultValue" declaration in tkButton.h.  
  */  
   
 static char *defaultStrings[] = {  
     "active", "disabled", "normal", (char *) NULL  
 };  
   
 /*  
  * The following table defines the legal values for the -state option.  
  * It is used together with the "enum state" declaration in tkButton.h.  
  */  
   
 static char *stateStrings[] = {  
     "active", "disabled", "normal", (char *) NULL  
 };  
   
 /*  
  * Information used for parsing configuration options.  There is a  
  * separate table for each of the four widget classes.  
  */  
   
 static Tk_OptionSpec labelOptionSpecs[] = {  
     {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",  
         DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},  
     {TK_OPTION_BORDER, "-background", "background", "Background",  
         DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),  
         0, (ClientData) DEF_BUTTON_BG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},  
     {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},  
     {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",  
         DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",  
         DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),  
         Tk_Offset(TkButton, borderWidth), 0, 0, 0},  
     {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",  
         DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",  
         "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,  
         -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,  
         (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},  
     {TK_OPTION_FONT, "-font", "font", "Font",  
         DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},  
     {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",  
         DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},  
     {TK_OPTION_STRING, "-height", "height", "Height",  
         DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},  
     {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",  
         "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,  
         -1, Tk_Offset(TkButton, highlightBorder), 0,  
         (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",  
         DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),  
         0, 0, 0},  
     {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",  
         "HighlightThickness", DEF_LABEL_HIGHLIGHT_WIDTH,  
         Tk_Offset(TkButton, highlightWidthPtr),  
         Tk_Offset(TkButton, highlightWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-image", "image", "Image",  
         DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",  
         DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-padx", "padX", "Pad",  
         DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),  
         Tk_Offset(TkButton, padX), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-pady", "padY", "Pad",  
         DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),  
         Tk_Offset(TkButton, padY), 0, 0, 0},  
     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",  
         DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},  
     {TK_OPTION_STRING_TABLE, "-state", "state", "State",  
         DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),  
         0, (ClientData) stateStrings, 0},  
     {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",  
         DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING, "-text", "text", "Text",  
         DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},  
     {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",  
         DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_INT, "-underline", "underline", "Underline",  
         DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},  
     {TK_OPTION_STRING, "-width", "width", "Width",  
         DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},  
     {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",  
         DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),  
         Tk_Offset(TkButton, wrapLength), 0, 0, 0},  
     {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, 0, 0, 0}  
 };  
   
 static Tk_OptionSpec buttonOptionSpecs[] = {  
     {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",  
         DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),  
         0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",  
         DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),  
         TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},  
     {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",  
         DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},  
     {TK_OPTION_BORDER, "-background", "background", "Background",  
         DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),  
         0, (ClientData) DEF_BUTTON_BG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},  
     {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},  
     {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",  
         DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",  
         DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),  
         Tk_Offset(TkButton, borderWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-command", "command", "Command",  
         DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",  
         DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING_TABLE, "-default", "default", "Default",  
         DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState),  
         0, (ClientData) defaultStrings, 0},  
     {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",  
         "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,  
         -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,  
         (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},  
     {TK_OPTION_FONT, "-font", "font", "Font",  
         DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},  
     {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",  
         DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},  
     {TK_OPTION_STRING, "-height", "height", "Height",  
         DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},  
     {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",  
         "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,  
         -1, Tk_Offset(TkButton, highlightBorder), 0,  
         (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",  
         DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),  
         0, 0, 0},  
     {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",  
         "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,  
         Tk_Offset(TkButton, highlightWidthPtr),  
         Tk_Offset(TkButton, highlightWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-image", "image", "Image",  
         DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",  
         DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-padx", "padX", "Pad",  
         DEF_BUTTON_PADX, Tk_Offset(TkButton, padXPtr),  
         Tk_Offset(TkButton, padX), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-pady", "padY", "Pad",  
         DEF_BUTTON_PADY, Tk_Offset(TkButton, padYPtr),  
         Tk_Offset(TkButton, padY), 0, 0, 0},  
     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",  
         DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},  
     {TK_OPTION_STRING_TABLE, "-state", "state", "State",  
         DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),  
         0, (ClientData) stateStrings, 0},  
     {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",  
         DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING, "-text", "text", "Text",  
         DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},  
     {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",  
         DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_INT, "-underline", "underline", "Underline",  
         DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},  
     {TK_OPTION_STRING, "-width", "width", "Width",  
         DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},  
     {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",  
         DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),  
         Tk_Offset(TkButton, wrapLength), 0, 0, 0},  
     {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, 0, 0}  
 };  
   
 static Tk_OptionSpec checkbuttonOptionSpecs[] = {  
     {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",  
         DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),  
         0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",  
         DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),  
         TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},  
     {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",  
         DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},  
     {TK_OPTION_BORDER, "-background", "background", "Background",  
         DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),  
         0, (ClientData) DEF_BUTTON_BG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},  
     {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},  
     {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",  
         DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",  
         DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),  
         Tk_Offset(TkButton, borderWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-command", "command", "Command",  
         DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",  
         DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",  
         "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,  
         -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,  
         (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},  
     {TK_OPTION_FONT, "-font", "font", "Font",  
         DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},  
     {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",  
         DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},  
     {TK_OPTION_STRING, "-height", "height", "Height",  
         DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},  
     {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",  
         "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,  
         -1, Tk_Offset(TkButton, highlightBorder), 0,  
         (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",  
         DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),  
         0, 0, 0},  
     {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",  
         "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,  
         Tk_Offset(TkButton, highlightWidthPtr),  
         Tk_Offset(TkButton, highlightWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-image", "image", "Image",  
         DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",  
         DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0},  
     {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",  
         DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},  
     {TK_OPTION_STRING, "-offvalue", "offValue", "Value",  
         DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0},  
     {TK_OPTION_STRING, "-onvalue", "onValue", "Value",  
         DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},  
     {TK_OPTION_PIXELS, "-padx", "padX", "Pad",  
         DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),  
         Tk_Offset(TkButton, padX), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-pady", "padY", "Pad",  
         DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),  
         Tk_Offset(TkButton, padY), 0, 0, 0},  
     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",  
         DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},  
     {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",  
         DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),  
         TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},  
     {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",  
         DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING_TABLE, "-state", "state", "State",  
         DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),  
         0, (ClientData) stateStrings, 0},  
     {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",  
         DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING, "-text", "text", "Text",  
         DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},  
     {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",  
         DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_INT, "-underline", "underline", "Underline",  
         DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},  
     {TK_OPTION_STRING, "-variable", "variable", "Variable",  
         DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING, "-width", "width", "Width",  
         DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},  
     {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",  
         DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),  
         Tk_Offset(TkButton, wrapLength), 0, 0, 0},  
     {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, 0, 0}  
 };  
   
 static Tk_OptionSpec radiobuttonOptionSpecs[] = {  
     {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",  
         DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),  
         0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",  
         DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),  
         TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},  
     {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",  
         DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},  
     {TK_OPTION_BORDER, "-background", "background", "Background",  
         DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),  
         0, (ClientData) DEF_BUTTON_BG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},  
     {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},  
     {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",  
         DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",  
         DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),  
         Tk_Offset(TkButton, borderWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-command", "command", "Command",  
         DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",  
         DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",  
         "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,  
         -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,  
         (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},  
     {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,  
         (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},  
     {TK_OPTION_FONT, "-font", "font", "Font",  
         DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},  
     {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",  
         DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},  
     {TK_OPTION_STRING, "-height", "height", "Height",  
         DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},  
     {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",  
         "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,  
         -1, Tk_Offset(TkButton, highlightBorder), 0,  
         (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},  
     {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",  
         DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),  
         0, 0, 0},  
     {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",  
         "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,  
         Tk_Offset(TkButton, highlightWidthPtr),  
         Tk_Offset(TkButton, highlightWidth), 0, 0, 0},  
     {TK_OPTION_STRING, "-image", "image", "Image",  
         DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",  
         DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn),  
         0, 0, 0},  
     {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",  
         DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-padx", "padX", "Pad",  
         DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),  
         Tk_Offset(TkButton, padX), 0, 0, 0},  
     {TK_OPTION_PIXELS, "-pady", "padY", "Pad",  
         DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),  
         Tk_Offset(TkButton, padY), 0, 0, 0},  
     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",  
         DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},  
     {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",  
         DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),  
         TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},  
     {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",  
         DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING_TABLE, "-state", "state", "State",  
         DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),  
         0, (ClientData) stateStrings, 0},  
     {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",  
         DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_STRING, "-text", "text", "Text",  
         DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},  
     {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",  
         DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,  
         TK_OPTION_NULL_OK, 0, 0},  
     {TK_OPTION_INT, "-underline", "underline", "Underline",  
         DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},  
     {TK_OPTION_STRING, "-value", "value", "Value",  
         DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},  
     {TK_OPTION_STRING, "-variable", "variable", "Variable",  
         DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,  
         0, 0, 0},  
     {TK_OPTION_STRING, "-width", "width", "Width",  
         DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},  
     {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",  
         DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),  
         Tk_Offset(TkButton, wrapLength), 0, 0, 0},  
     {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, -1, 0, 0, 0}  
 };  
   
 /*  
  * The following table maps from one of the type values defined in  
  * tkButton.h, such as TYPE_LABEL, to the option template for that  
  * class of widgets.  
  */  
   
 static Tk_OptionSpec *optionSpecs[] = {  
     labelOptionSpecs,  
     buttonOptionSpecs,  
     checkbuttonOptionSpecs,  
     radiobuttonOptionSpecs  
 };  
   
 /*  
  * The following tables define the widget commands supported by  
  * each of the classes, and map the indexes into the string tables  
  * into a single enumerated type used to dispatch the widget command.  
  */  
   
 static char *commandNames[][8] = {  
     {"cget", "configure", (char *) NULL},  
     {"cget", "configure", "flash", "invoke", (char *) NULL},  
     {"cget", "configure", "deselect", "flash", "invoke", "select",  
             "toggle", (char *) NULL},  
     {"cget", "configure", "deselect", "flash", "invoke", "select",  
             (char *) NULL}  
 };  
 enum command {  
     COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,  
     COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE  
 };  
 static enum command map[][8] = {  
     {COMMAND_CGET, COMMAND_CONFIGURE},  
     {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},  
     {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,  
             COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},  
     {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,  
             COMMAND_INVOKE, COMMAND_SELECT}  
 };  
   
 /*  
  * Forward declarations for procedures defined later in this file:  
  */  
   
 static void             ButtonCmdDeletedProc _ANSI_ARGS_((  
                             ClientData clientData));  
 static int              ButtonCreate _ANSI_ARGS_((ClientData clientData,  
                             Tcl_Interp *interp, int objc,  
                             Tcl_Obj *CONST objv[], int type));  
 static void             ButtonEventProc _ANSI_ARGS_((ClientData clientData,  
                             XEvent *eventPtr));  
 static void             ButtonImageProc _ANSI_ARGS_((ClientData clientData,  
                             int x, int y, int width, int height,  
                             int imgWidth, int imgHeight));  
 static void             ButtonSelectImageProc _ANSI_ARGS_((  
                             ClientData clientData, int x, int y, int width,  
                             int height, int imgWidth, int imgHeight));  
 static char *           ButtonTextVarProc _ANSI_ARGS_((ClientData clientData,  
                             Tcl_Interp *interp, char *name1, char *name2,  
                             int flags));  
 static char *           ButtonVarProc _ANSI_ARGS_((ClientData clientData,  
                             Tcl_Interp *interp, char *name1, char *name2,  
                             int flags));  
 static int              ButtonWidgetObjCmd _ANSI_ARGS_((ClientData clientData,  
                             Tcl_Interp *interp, int objc,  
                             Tcl_Obj *CONST objv[]));  
 static int              ConfigureButton _ANSI_ARGS_((Tcl_Interp *interp,  
                             TkButton *butPtr, int objc,  
                             Tcl_Obj *CONST objv[]));  
 static void             DestroyButton _ANSI_ARGS_((TkButton *butPtr));  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * Tk_ButtonCmd, Tk_CheckbuttonCmd, Tk_LabelCmd, Tk_RadiobuttonCmd --  
  *  
  *      These procedures are invoked to process the "button", "label",  
  *      "radiobutton", and "checkbutton" Tcl commands.  See the  
  *      user documentation for details on what they do.  
  *  
  * Results:  
  *      A standard Tcl result.  
  *  
  * Side effects:  
  *      See the user documentation.  These procedures are just wrappers;  
  *      they call ButtonCreate to do all of the real work.  
  *  
  *--------------------------------------------------------------  
  */  
   
 int  
 Tk_ButtonObjCmd(clientData, interp, objc, objv)  
     ClientData clientData;      /* Either NULL or pointer to option table. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
 {  
     return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON);  
 }  
   
 int  
 Tk_CheckbuttonObjCmd(clientData, interp, objc, objv)  
     ClientData clientData;      /* Either NULL or pointer to option table. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
 {  
     return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON);  
 }  
   
 int  
 Tk_LabelObjCmd(clientData, interp, objc, objv)  
     ClientData clientData;      /* Either NULL or pointer to option table. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
 {  
     return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL);  
 }  
   
 int  
 Tk_RadiobuttonObjCmd(clientData, interp, objc, objv)  
     ClientData clientData;      /* Either NULL or pointer to option table. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
 {  
     return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON);  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ButtonCreate --  
  *  
  *      This procedure does all the real work of implementing the  
  *      "button", "label", "radiobutton", and "checkbutton" Tcl  
  *      commands.  See the user documentation for details on what it does.  
  *  
  * Results:  
  *      A standard Tcl result.  
  *  
  * Side effects:  
  *      See the user documentation.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 ButtonCreate(clientData, interp, objc, objv, type)  
     ClientData clientData;      /* Option table for this widget class, or  
                                  * NULL if not created yet. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
     int type;                   /* Type of button to create: TYPE_LABEL,  
                                  * TYPE_BUTTON, TYPE_CHECK_BUTTON, or  
                                  * TYPE_RADIO_BUTTON. */  
 {  
     TkButton *butPtr;  
     Tk_OptionTable optionTable;  
     Tk_Window tkwin;  
   
     optionTable = (Tk_OptionTable) clientData;  
     if (optionTable == NULL) {  
         Tcl_CmdInfo info;  
         char *name;  
   
         /*  
          * We haven't created the option table for this widget class  
          * yet.  Do it now and save the table as the clientData for  
          * the command, so we'll have access to it in future  
          * invocations of the command.  
          */  
   
         TkpButtonSetDefaults(optionSpecs[type]);  
         optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);  
         name = Tcl_GetString(objv[0]);  
         Tcl_GetCommandInfo(interp, name, &info);  
         info.objClientData = (ClientData) optionTable;  
         Tcl_SetCommandInfo(interp, name, &info);  
     }  
   
     if (objc < 2) {  
         Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");  
         return TCL_ERROR;  
     }  
   
     /*  
      * Create the new window.  
      */  
   
     tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),  
             Tcl_GetString(objv[1]), (char *) NULL);  
     if (tkwin == NULL) {  
         return TCL_ERROR;  
     }  
   
     Tk_SetClass(tkwin, classNames[type]);  
     butPtr = TkpCreateButton(tkwin);  
   
     TkSetClassProcs(tkwin, &tkpButtonProcs, (ClientData) butPtr);  
   
     /*  
      * Initialize the data structure for the button.  
      */  
   
     butPtr->tkwin = tkwin;  
     butPtr->display = Tk_Display(tkwin);  
     butPtr->interp = interp;  
     butPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),  
             ButtonWidgetObjCmd, (ClientData) butPtr, ButtonCmdDeletedProc);  
     butPtr->type = type;  
     butPtr->optionTable = optionTable;  
     butPtr->textPtr = NULL;  
     butPtr->underline = -1;  
     butPtr->textVarNamePtr = NULL;  
     butPtr->bitmap = None;  
     butPtr->imagePtr = NULL;  
     butPtr->image = NULL;  
     butPtr->selectImagePtr = NULL;  
     butPtr->selectImage = NULL;  
     butPtr->state = STATE_NORMAL;  
     butPtr->normalBorder = NULL;  
     butPtr->activeBorder = NULL;  
     butPtr->borderWidthPtr = NULL;  
     butPtr->borderWidth = 0;  
     butPtr->relief = TK_RELIEF_FLAT;  
     butPtr->highlightWidthPtr = NULL;  
     butPtr->highlightWidth = 0;  
     butPtr->highlightBorder = NULL;  
     butPtr->highlightColorPtr = NULL;  
     butPtr->inset = 0;  
     butPtr->tkfont = NULL;  
     butPtr->normalFg = NULL;  
     butPtr->activeFg = NULL;  
     butPtr->disabledFg = NULL;  
     butPtr->normalTextGC = None;  
     butPtr->activeTextGC = None;  
     butPtr->disabledGC = None;  
     butPtr->gray = None;  
     butPtr->copyGC = None;  
     butPtr->widthPtr = NULL;  
     butPtr->width = 0;  
     butPtr->heightPtr = NULL;  
     butPtr->height = 0;  
     butPtr->wrapLengthPtr = NULL;  
     butPtr->wrapLength = 0;  
     butPtr->padXPtr = NULL;  
     butPtr->padX = 0;  
     butPtr->padYPtr = NULL;  
     butPtr->padY = 0;  
     butPtr->anchor = TK_ANCHOR_CENTER;  
     butPtr->justify = TK_JUSTIFY_CENTER;  
     butPtr->indicatorOn = 0;  
     butPtr->selectBorder = NULL;  
     butPtr->textWidth = 0;  
     butPtr->textHeight = 0;  
     butPtr->textLayout = NULL;  
     butPtr->indicatorSpace = 0;  
     butPtr->indicatorDiameter = 0;  
     butPtr->defaultState = DEFAULT_DISABLED;  
     butPtr->selVarNamePtr = NULL;  
     butPtr->onValuePtr = NULL;  
     butPtr->offValuePtr = NULL;  
     butPtr->cursor = None;  
     butPtr->takeFocusPtr = NULL;  
     butPtr->commandPtr = NULL;  
     butPtr->flags = 0;  
   
     Tk_CreateEventHandler(butPtr->tkwin,  
             ExposureMask|StructureNotifyMask|FocusChangeMask,  
             ButtonEventProc, (ClientData) butPtr);  
   
     if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin)  
             != TCL_OK) {  
         Tk_DestroyWindow(butPtr->tkwin);  
         return TCL_ERROR;  
     }  
     if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {  
         Tk_DestroyWindow(butPtr->tkwin);  
         return TCL_ERROR;  
     }  
   
     Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(butPtr->tkwin),  
             -1);  
     return TCL_OK;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ButtonWidgetCmd --  
  *  
  *      This procedure is invoked to process the Tcl command  
  *      that corresponds to a widget managed by this module.  
  *      See the user documentation for details on what it does.  
  *  
  * Results:  
  *      A standard Tcl result.  
  *  
  * Side effects:  
  *      See the user documentation.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 ButtonWidgetObjCmd(clientData, interp, objc, objv)  
     ClientData clientData;      /* Information about button widget. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
 {  
     TkButton *butPtr = (TkButton *) clientData;  
     int index;  
     int result;  
     Tcl_Obj *objPtr;  
   
     if (objc < 2) {  
         Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");  
         return TCL_ERROR;  
     }  
     result = Tcl_GetIndexFromObj(interp, objv[1], commandNames[butPtr->type],  
             "option", 0, &index);  
     if (result != TCL_OK) {  
         return result;  
     }  
     Tcl_Preserve((ClientData) butPtr);  
   
     switch (map[butPtr->type][index]) {  
         case COMMAND_CGET: {  
             if (objc != 3) {  
                 Tcl_WrongNumArgs(interp, 1, objv, "cget option");  
                 goto error;  
             }  
             objPtr = Tk_GetOptionValue(interp, (char *) butPtr,  
                     butPtr->optionTable, objv[2], butPtr->tkwin);  
             if (objPtr == NULL) {  
                  goto error;  
             } else {  
                 Tcl_SetObjResult(interp, objPtr);  
             }  
             break;  
         }  
   
         case COMMAND_CONFIGURE: {  
             if (objc <= 3) {  
                 objPtr = Tk_GetOptionInfo(interp, (char *) butPtr,  
                         butPtr->optionTable,  
                         (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,  
                         butPtr->tkwin);  
                 if (objPtr == NULL) {  
                     goto error;  
                 } else {  
                     Tcl_SetObjResult(interp, objPtr);  
                 }  
             } else {  
                 result = ConfigureButton(interp, butPtr, objc-2, objv+2);  
             }  
             break;  
         }  
   
         case COMMAND_DESELECT: {  
             if (objc > 2) {  
                 Tcl_WrongNumArgs(interp, 1, objv, "deselect");  
                 goto error;  
             }  
             if (butPtr->type == TYPE_CHECK_BUTTON) {  
                 if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,  
                         butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                         == NULL) {  
                     goto error;  
                 }  
             } else if (butPtr->flags & SELECTED) {  
                 if (Tcl_ObjSetVar2(interp,  
                         butPtr->selVarNamePtr, NULL, Tcl_NewObj(),  
                         TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                         == NULL) {  
                     goto error;  
                 }  
             }  
             break;  
         }  
   
         case COMMAND_FLASH: {  
             int i;  
   
             if (objc > 2) {  
                 Tcl_WrongNumArgs(interp, 1, objv, "flash");  
                 goto error;  
             }  
             if (butPtr->state != STATE_DISABLED) {  
                 for (i = 0; i < 4; i++) {  
                     if (butPtr->state == STATE_NORMAL) {  
                         butPtr->state = STATE_ACTIVE;  
                         Tk_SetBackgroundFromBorder(butPtr->tkwin,  
                                 butPtr->activeBorder);  
                     } else {  
                         butPtr->state = STATE_NORMAL;  
                         Tk_SetBackgroundFromBorder(butPtr->tkwin,  
                                 butPtr->normalBorder);  
                     }  
                     TkpDisplayButton((ClientData) butPtr);  
       
                     /*  
                      * Special note: must cancel any existing idle handler  
                      * for TkpDisplayButton;  it's no longer needed, and  
                      * TkpDisplayButton cleared the REDRAW_PENDING flag.  
                      */  
       
                     Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);  
                     XFlush(butPtr->display);  
                     Tcl_Sleep(50);  
                 }  
             }  
             break;  
         }  
   
         case COMMAND_INVOKE: {  
             if (objc > 2) {  
                 Tcl_WrongNumArgs(interp, 1, objv, "invoke");  
                 goto error;  
             }  
             if (butPtr->state != STATE_DISABLED) {  
                 result = TkInvokeButton(butPtr);  
             }  
             break;  
         }  
   
         case COMMAND_SELECT: {  
             if (objc > 2) {  
                 Tcl_WrongNumArgs(interp, 1, objv, "select");  
                 goto error;  
             }  
             if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,  
                     butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                     == NULL) {  
                 goto error;  
             }  
             break;  
         }  
   
         case COMMAND_TOGGLE: {  
             if (objc > 2) {  
                 Tcl_WrongNumArgs(interp, 1, objv, "toggle");  
                 goto error;  
             }  
             if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,  
                     (butPtr->flags & SELECTED) ? butPtr->offValuePtr  
                     : butPtr->onValuePtr,  
                     TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                     == NULL) {  
                 goto error;  
             }  
             break;  
         }  
     }  
     Tcl_Release((ClientData) butPtr);  
     return result;  
   
     error:  
     Tcl_Release((ClientData) butPtr);  
     return TCL_ERROR;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * DestroyButton --  
  *  
  *      This procedure is invoked by ButtonEventProc to free all the  
  *      resources of a button and clean up its state.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Everything associated with the widget is freed.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 DestroyButton(butPtr)  
     TkButton *butPtr;           /* Info about button widget. */  
 {  
     TkpDestroyButton(butPtr);  
   
     butPtr->flags |= BUTTON_DELETED;  
     if (butPtr->flags & REDRAW_PENDING) {  
         Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);  
     }  
   
     /*  
      * Free up all the stuff that requires special handling, then  
      * let Tk_FreeOptions handle all the standard option-related  
      * stuff.  
      */  
   
     Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);  
     if (butPtr->textVarNamePtr != NULL) {  
         Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr),  
                 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                 ButtonTextVarProc, (ClientData) butPtr);  
     }  
     if (butPtr->image != NULL) {  
         Tk_FreeImage(butPtr->image);  
     }  
     if (butPtr->selectImage != NULL) {  
         Tk_FreeImage(butPtr->selectImage);  
     }  
     if (butPtr->normalTextGC != None) {  
         Tk_FreeGC(butPtr->display, butPtr->normalTextGC);  
     }  
     if (butPtr->activeTextGC != None) {  
         Tk_FreeGC(butPtr->display, butPtr->activeTextGC);  
     }  
     if (butPtr->disabledGC != None) {  
         Tk_FreeGC(butPtr->display, butPtr->disabledGC);  
     }  
     if (butPtr->gray != None) {  
         Tk_FreeBitmap(butPtr->display, butPtr->gray);  
     }  
     if (butPtr->copyGC != None) {  
         Tk_FreeGC(butPtr->display, butPtr->copyGC);  
     }  
     if (butPtr->textLayout != NULL) {  
         Tk_FreeTextLayout(butPtr->textLayout);  
     }  
     if (butPtr->selVarNamePtr != NULL) {  
         Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr),  
                 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                 ButtonVarProc, (ClientData) butPtr);  
     }  
     Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable,  
             butPtr->tkwin);  
     butPtr->tkwin = NULL;  
     Tcl_EventuallyFree((ClientData) butPtr, TCL_DYNAMIC);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ConfigureButton --  
  *  
  *      This procedure is called to process an objc/objv list to set  
  *      configuration options for a button widget.  
  *  
  * Results:  
  *      The return value is a standard Tcl result.  If TCL_ERROR is  
  *      returned, then an error message is left in interp's result.  
  *  
  * Side effects:  
  *      Configuration information, such as text string, colors, font,  
  *      etc. get set for butPtr;  old resources get freed, if there  
  *      were any.  The button is redisplayed.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static int  
 ConfigureButton(interp, butPtr, objc, objv)  
     Tcl_Interp *interp;         /* Used for error reporting. */  
     register TkButton *butPtr;  /* Information about widget;  may or may  
                                  * not already have values for some fields. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument values. */  
 {  
     Tk_SavedOptions savedOptions;  
     Tcl_Obj *errorResult = NULL;  
     int error;  
     Tk_Image image;  
   
     /*  
      * Eliminate any existing trace on variables monitored by the button.  
      */  
   
     if (butPtr->textVarNamePtr != NULL) {  
         Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),  
                 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                 ButtonTextVarProc, (ClientData) butPtr);  
     }  
     if (butPtr->selVarNamePtr != NULL) {  
         Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),  
                 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                 ButtonVarProc, (ClientData) butPtr);  
     }  
   
     /*  
      * The following loop is potentially executed twice.  During the  
      * first pass configuration options get set to their new values.  
      * If there is an error in this pass, we execute a second pass  
      * to restore all the options to their previous values.  
      */  
   
     for (error = 0; error <= 1; error++) {  
         if (!error) {  
             /*  
              * First pass: set options to new values.  
              */  
   
             if (Tk_SetOptions(interp, (char *) butPtr,  
                     butPtr->optionTable, objc, objv,  
                     butPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {  
                 continue;  
             }  
         } else {  
             /*  
              * Second pass: restore options to old values.  
              */  
   
             errorResult = Tcl_GetObjResult(interp);  
             Tcl_IncrRefCount(errorResult);  
             Tk_RestoreSavedOptions(&savedOptions);  
         }  
   
         /*  
          * A few options need special processing, such as setting the  
          * background from a 3-D border, or filling in complicated  
          * defaults that couldn't be specified to Tk_SetOptions.  
          */  
   
         if ((butPtr->state == STATE_ACTIVE)  
                 && !Tk_StrictMotif(butPtr->tkwin)) {  
             Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);  
         } else {  
             Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);  
         }  
         if (butPtr->borderWidth < 0) {  
             butPtr->borderWidth = 0;  
         }  
         if (butPtr->highlightWidth < 0) {  
             butPtr->highlightWidth = 0;  
         }  
         if (butPtr->padX < 0) {  
             butPtr->padX = 0;  
         }  
         if (butPtr->padY < 0) {  
             butPtr->padY = 0;  
         }  
   
         if (butPtr->type >= TYPE_CHECK_BUTTON) {  
             Tcl_Obj *valuePtr, *namePtr;  
       
             if (butPtr->selVarNamePtr == NULL) {  
                 butPtr->selVarNamePtr = Tcl_NewStringObj(  
                         Tk_Name(butPtr->tkwin), -1);  
                 Tcl_IncrRefCount(butPtr->selVarNamePtr);  
             }  
             namePtr = butPtr->selVarNamePtr;  
       
             /*  
              * Select the button if the associated variable has the  
              * appropriate value, initialize the variable if it doesn't  
              * exist, then set a trace on the variable to monitor future  
              * changes to its value.  
              */  
       
             valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);  
             butPtr->flags &= ~SELECTED;  
             if (valuePtr != NULL) {  
                 if (strcmp(Tcl_GetString(valuePtr),  
                         Tcl_GetString(butPtr->onValuePtr)) == 0) {  
                     butPtr->flags |= SELECTED;  
                 }  
             } else {  
                 if (Tcl_ObjSetVar2(interp, namePtr, NULL,  
                         (butPtr->type == TYPE_CHECK_BUTTON)  
                         ? butPtr->offValuePtr : Tcl_NewObj(),  
                         TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                         == NULL) {  
                     continue;  
                 }  
             }  
         }  
   
         /*  
          * Get the images for the widget, if there are any.  Allocate the  
          * new images before freeing the old ones, so that the reference  
          * counts don't go to zero and cause image data to be discarded.  
          */  
       
         if (butPtr->imagePtr != NULL) {  
             image = Tk_GetImage(butPtr->interp, butPtr->tkwin,  
                     Tcl_GetString(butPtr->imagePtr), ButtonImageProc,  
                     (ClientData) butPtr);  
             if (image == NULL) {  
                 continue;  
             }  
         } else {  
             image = NULL;  
         }  
         if (butPtr->image != NULL) {  
             Tk_FreeImage(butPtr->image);  
         }  
         butPtr->image = image;  
         if (butPtr->selectImagePtr != NULL) {  
             image = Tk_GetImage(butPtr->interp, butPtr->tkwin,  
                     Tcl_GetString(butPtr->selectImagePtr),  
                     ButtonSelectImageProc, (ClientData) butPtr);  
             if (image == NULL) {  
                 continue;  
             }  
         } else {  
             image = NULL;  
         }  
         if (butPtr->selectImage != NULL) {  
             Tk_FreeImage(butPtr->selectImage);  
         }  
         butPtr->selectImage = image;  
   
         if ((butPtr->imagePtr == NULL) && (butPtr->bitmap == None)  
                 && (butPtr->textVarNamePtr != NULL)) {  
             /*  
              * The button must display the value of a variable: set up a trace  
              * on the variable's value, create the variable if it doesn't  
              * exist, and fetch its current value.  
              */  
       
             Tcl_Obj *valuePtr, *namePtr;  
   
             namePtr = butPtr->textVarNamePtr;  
             valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);  
             if (valuePtr == NULL) {  
                 if (Tcl_ObjSetVar2(interp, namePtr, NULL, butPtr->textPtr,  
                         TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                         == NULL) {  
                     continue;  
                 }  
             } else {  
                 if (butPtr->textPtr != NULL) {  
                     Tcl_DecrRefCount(butPtr->textPtr);  
                 }  
                 butPtr->textPtr = valuePtr;  
                 Tcl_IncrRefCount(butPtr->textPtr);  
             }  
         }  
       
         if ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) {  
             /*  
              * The button must display the contents of an image or  
              * bitmap.  
              */  
   
             if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthPtr,  
                     &butPtr->width) != TCL_OK) {  
                 widthError:  
                 Tcl_AddErrorInfo(interp, "\n    (processing -width option)");  
                 continue;  
             }  
             if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightPtr,  
                     &butPtr->height) != TCL_OK) {  
                 heightError:  
                 Tcl_AddErrorInfo(interp, "\n    (processing -height option)");  
                 continue;  
             }  
         } else {  
             /*  
              * The button displays an ordinary text string.  
              */  
   
             if (Tcl_GetIntFromObj(interp, butPtr->widthPtr, &butPtr->width)  
                     != TCL_OK) {  
                 goto widthError;  
             }  
             if (Tcl_GetIntFromObj(interp, butPtr->heightPtr, &butPtr->height)  
                     != TCL_OK) {  
                 goto heightError;  
             }  
         }  
         break;  
     }  
     if (!error) {  
         Tk_FreeSavedOptions(&savedOptions);  
     }  
   
     /*  
      * Reestablish the variable traces, if they're needed.  
      */  
   
     if (butPtr->textVarNamePtr != NULL) {  
         Tcl_TraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),  
                 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                 ButtonTextVarProc, (ClientData) butPtr);  
     }  
     if (butPtr->selVarNamePtr != NULL) {  
         Tcl_TraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),  
                 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                 ButtonVarProc, (ClientData) butPtr);  
     }  
       
     TkButtonWorldChanged((ClientData) butPtr);  
     if (error) {  
         Tcl_SetObjResult(interp, errorResult);  
         Tcl_DecrRefCount(errorResult);  
         return TCL_ERROR;  
     } else {  
         return TCL_OK;  
     }  
 }  
   
 /*  
  *---------------------------------------------------------------------------  
  *  
  * TkButtonWorldChanged --  
  *  
  *      This procedure is called when the world has changed in some  
  *      way and the widget needs to recompute all its graphics contexts  
  *      and determine its new geometry.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Button will be relayed out and redisplayed.  
  *  
  *---------------------------------------------------------------------------  
  */  
   
 void  
 TkButtonWorldChanged(instanceData)  
     ClientData instanceData;    /* Information about widget. */  
 {  
     XGCValues gcValues;  
     GC newGC;  
     unsigned long mask;  
     TkButton *butPtr;  
   
     butPtr = (TkButton *) instanceData;  
   
     /*  
      * Recompute GCs.  
      */  
   
     gcValues.font = Tk_FontId(butPtr->tkfont);  
     gcValues.foreground = butPtr->normalFg->pixel;  
     gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;  
       
     /*  
      * Note: GraphicsExpose events are disabled in normalTextGC because it's  
      * used to copy stuff from an off-screen pixmap onto the screen (we know  
      * that there's no problem with obscured areas).  
      */  
   
     gcValues.graphics_exposures = False;  
     mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;  
     newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);  
     if (butPtr->normalTextGC != None) {  
         Tk_FreeGC(butPtr->display, butPtr->normalTextGC);  
     }  
     butPtr->normalTextGC = newGC;  
   
     if (butPtr->activeFg != NULL) {  
         gcValues.foreground = butPtr->activeFg->pixel;  
         gcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;  
         mask = GCForeground | GCBackground | GCFont;  
         newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);  
         if (butPtr->activeTextGC != None) {  
             Tk_FreeGC(butPtr->display, butPtr->activeTextGC);  
         }  
         butPtr->activeTextGC = newGC;  
     }  
   
     /*  
      * Allocate the disabled graphics context, for drawing the widget in  
      * its disabled state  
      */  
     gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;  
     if ((butPtr->disabledFg != NULL) && (butPtr->imagePtr == NULL)) {  
         gcValues.foreground = butPtr->disabledFg->pixel;  
         mask = GCForeground | GCBackground | GCFont;  
     } else {  
         gcValues.foreground = gcValues.background;  
         mask = GCForeground;  
         if (butPtr->gray == None) {  
             butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin, "gray50");  
         }  
         if (butPtr->gray != None) {  
             gcValues.fill_style = FillStippled;  
             gcValues.stipple = butPtr->gray;  
             mask |= GCFillStyle | GCStipple;  
         }  
     }  
     newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);  
     if (butPtr->disabledGC != None) {  
         Tk_FreeGC(butPtr->display, butPtr->disabledGC);  
     }  
     butPtr->disabledGC = newGC;  
   
     if (butPtr->copyGC == None) {  
         butPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);  
     }  
   
     TkpComputeButtonGeometry(butPtr);  
   
     /*  
      * Lastly, arrange for the button to be redisplayed.  
      */  
   
     if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {  
         Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);  
         butPtr->flags |= REDRAW_PENDING;  
     }  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ButtonEventProc --  
  *  
  *      This procedure is invoked by the Tk dispatcher for various  
  *      events on buttons.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      When the window gets deleted, internal structures get  
  *      cleaned up.  When it gets exposed, it is redisplayed.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static void  
 ButtonEventProc(clientData, eventPtr)  
     ClientData clientData;      /* Information about window. */  
     XEvent *eventPtr;           /* Information about event. */  
 {  
     TkButton *butPtr = (TkButton *) clientData;  
     if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {  
         goto redraw;  
     } else if (eventPtr->type == ConfigureNotify) {  
         /*  
          * Must redraw after size changes, since layout could have changed  
          * and borders will need to be redrawn.  
          */  
   
         goto redraw;  
     } else if (eventPtr->type == DestroyNotify) {  
         DestroyButton(butPtr);  
     } else if (eventPtr->type == FocusIn) {  
         if (eventPtr->xfocus.detail != NotifyInferior) {  
             butPtr->flags |= GOT_FOCUS;  
             if (butPtr->highlightWidth > 0) {  
                 goto redraw;  
             }  
         }  
     } else if (eventPtr->type == FocusOut) {  
         if (eventPtr->xfocus.detail != NotifyInferior) {  
             butPtr->flags &= ~GOT_FOCUS;  
             if (butPtr->highlightWidth > 0) {  
                 goto redraw;  
             }  
         }  
     }  
     return;  
   
     redraw:  
     if ((butPtr->tkwin != NULL) && !(butPtr->flags & REDRAW_PENDING)) {  
         Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);  
         butPtr->flags |= REDRAW_PENDING;  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ButtonCmdDeletedProc --  
  *  
  *      This procedure is invoked when a widget command is deleted.  If  
  *      the widget isn't already in the process of being destroyed,  
  *      this command destroys it.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The widget is destroyed.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 ButtonCmdDeletedProc(clientData)  
     ClientData clientData;      /* Pointer to widget record for widget. */  
 {  
     TkButton *butPtr = (TkButton *) clientData;  
   
     /*  
      * This procedure could be invoked either because the window was  
      * destroyed and the command was then deleted or because the command  
      * was deleted, and then this procedure destroys the widget.  The  
      * BUTTON_DELETED flag distinguishes these cases.  
      */  
   
     if (!(butPtr->flags & BUTTON_DELETED)) {  
         Tk_DestroyWindow(butPtr->tkwin);  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkInvokeButton --  
  *  
  *      This procedure is called to carry out the actions associated  
  *      with a button, such as invoking a Tcl command or setting a  
  *      variable.  This procedure is invoked, for example, when the  
  *      button is invoked via the mouse.  
  *  
  * Results:  
  *      A standard Tcl return value.  Information is also left in  
  *      the interp's result.  
  *  
  * Side effects:  
  *      Depends on the button and its associated command.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 TkInvokeButton(butPtr)  
     TkButton *butPtr;                   /* Information about button. */  
 {  
     Tcl_Obj *namePtr = butPtr->selVarNamePtr;  
   
     if (butPtr->type == TYPE_CHECK_BUTTON) {  
         if (butPtr->flags & SELECTED) {  
             if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,  
                     butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                     == NULL) {  
                 return TCL_ERROR;  
             }  
         } else {  
             if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,  
                     butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                     == NULL) {  
                 return TCL_ERROR;  
             }  
         }  
     } else if (butPtr->type == TYPE_RADIO_BUTTON) {  
         if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL, butPtr->onValuePtr,  
                 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)  
                 == NULL) {  
             return TCL_ERROR;  
         }  
     }  
     if ((butPtr->type != TYPE_LABEL) && (butPtr->commandPtr != NULL)) {  
         return Tcl_EvalObjEx(butPtr->interp, butPtr->commandPtr,  
                 TCL_EVAL_GLOBAL);  
     }  
     return TCL_OK;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ButtonVarProc --  
  *  
  *      This procedure is invoked when someone changes the  
  *      state variable associated with a radio button.  Depending  
  *      on the new value of the button's variable, the button  
  *      may be selected or deselected.  
  *  
  * Results:  
  *      NULL is always returned.  
  *  
  * Side effects:  
  *      The button may become selected or deselected.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static char *  
 ButtonVarProc(clientData, interp, name1, name2, flags)  
     ClientData clientData;      /* Information about button. */  
     Tcl_Interp *interp;         /* Interpreter containing variable. */  
     char *name1;                /* Name of variable. */  
     char *name2;                /* Second part of variable name. */  
     int flags;                  /* Information about what happened. */  
 {  
     register TkButton *butPtr = (TkButton *) clientData;  
     char *name, *value;  
     Tcl_Obj *valuePtr;  
   
     name = Tcl_GetString(butPtr->selVarNamePtr);  
   
     /*  
      * If the variable is being unset, then just re-establish the  
      * trace unless the whole interpreter is going away.  
      */  
   
     if (flags & TCL_TRACE_UNSETS) {  
         butPtr->flags &= ~SELECTED;  
         if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {  
             Tcl_TraceVar(interp, name,  
                     TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                     ButtonVarProc, clientData);  
         }  
         goto redisplay;  
     }  
   
     /*  
      * Use the value of the variable to update the selected status of  
      * the button.  
      */  
   
     valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);  
     if (valuePtr == NULL) {  
         value = "";  
     } else {  
         value = Tcl_GetString(valuePtr);  
     }  
     if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {  
         if (butPtr->flags & SELECTED) {  
             return (char *) NULL;  
         }  
         butPtr->flags |= SELECTED;  
     } else if (butPtr->flags & SELECTED) {  
         butPtr->flags &= ~SELECTED;  
     } else {  
         return (char *) NULL;  
     }  
   
     redisplay:  
     if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)  
             && !(butPtr->flags & REDRAW_PENDING)) {  
         Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);  
         butPtr->flags |= REDRAW_PENDING;  
     }  
     return (char *) NULL;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ButtonTextVarProc --  
  *  
  *      This procedure is invoked when someone changes the variable  
  *      whose contents are to be displayed in a button.  
  *  
  * Results:  
  *      NULL is always returned.  
  *  
  * Side effects:  
  *      The text displayed in the button will change to match the  
  *      variable.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static char *  
 ButtonTextVarProc(clientData, interp, name1, name2, flags)  
     ClientData clientData;      /* Information about button. */  
     Tcl_Interp *interp;         /* Interpreter containing variable. */  
     char *name1;                /* Not used. */  
     char *name2;                /* Not used. */  
     int flags;                  /* Information about what happened. */  
 {  
     TkButton *butPtr = (TkButton *) clientData;  
     char *name;  
     Tcl_Obj *valuePtr;  
   
     name = Tcl_GetString(butPtr->textVarNamePtr);  
   
     /*  
      * If the variable is unset, then immediately recreate it unless  
      * the whole interpreter is going away.  
      */  
   
     if (flags & TCL_TRACE_UNSETS) {  
         if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {  
             Tcl_SetVar2Ex(interp, name, NULL, butPtr->textPtr,  
                     TCL_GLOBAL_ONLY);  
             Tcl_TraceVar(interp, name,  
                     TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,  
                     ButtonTextVarProc, clientData);  
         }  
         return (char *) NULL;  
     }  
   
     valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);  
     if (valuePtr == NULL) {  
         valuePtr = Tcl_NewObj();  
     }  
     Tcl_DecrRefCount(butPtr->textPtr);  
     butPtr->textPtr = valuePtr;  
     Tcl_IncrRefCount(butPtr->textPtr);  
     TkpComputeButtonGeometry(butPtr);  
   
     if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)  
             && !(butPtr->flags & REDRAW_PENDING)) {  
         Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);  
         butPtr->flags |= REDRAW_PENDING;  
     }  
     return (char *) NULL;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ButtonImageProc --  
  *  
  *      This procedure is invoked by the image code whenever the manager  
  *      for an image does something that affects the size or contents  
  *      of an image displayed in a button.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Arranges for the button to get redisplayed.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 ButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight)  
     ClientData clientData;              /* Pointer to widget record. */  
     int x, y;                           /* Upper left pixel (within image)  
                                          * that must be redisplayed. */  
     int width, height;                  /* Dimensions of area to redisplay  
                                          * (may be <= 0). */  
     int imgWidth, imgHeight;            /* New dimensions of image. */  
 {  
     register TkButton *butPtr = (TkButton *) clientData;  
   
     if (butPtr->tkwin != NULL) {  
         TkpComputeButtonGeometry(butPtr);  
         if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {  
             Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);  
             butPtr->flags |= REDRAW_PENDING;  
         }  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ButtonSelectImageProc --  
  *  
  *      This procedure is invoked by the image code whenever the manager  
  *      for an image does something that affects the size or contents  
  *      of the image displayed in a button when it is selected.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      May arrange for the button to get redisplayed.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 ButtonSelectImageProc(clientData, x, y, width, height, imgWidth, imgHeight)  
     ClientData clientData;              /* Pointer to widget record. */  
     int x, y;                           /* Upper left pixel (within image)  
                                          * that must be redisplayed. */  
     int width, height;                  /* Dimensions of area to redisplay  
                                          * (may be <= 0). */  
     int imgWidth, imgHeight;            /* New dimensions of image. */  
 {  
     register TkButton *butPtr = (TkButton *) clientData;  
   
     /*  
      * Don't recompute geometry:  it's controlled by the primary image.  
      */  
   
     if ((butPtr->flags & SELECTED) && (butPtr->tkwin != NULL)  
             && Tk_IsMapped(butPtr->tkwin)  
             && !(butPtr->flags & REDRAW_PENDING)) {  
         Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr);  
         butPtr->flags |= REDRAW_PENDING;  
     }  
 }  
   
   
 /* $History: tkButton.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 2:38a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKBUTTON.C */  
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 */

Legend:
Removed from v.42  
changed lines
  Added in v.220

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25