Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tk iconbutton widget (part 1/2)

0 views
Skip to first unread message

Trevor Lowe

unread,
Feb 20, 1992, 11:58:29 PM2/20/92
to

This is an iconbutton widget for Tk version 1.4.
An iconbutton is a widget that is similar to a button widget,
except that it displays bitmaps instead of text.
--------cut here--------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 2)."
# Contents: ICONBUTTON ICONBUTTON/tkIcon.c ICONBUTTON/tkIconButton.c
# ICONBUTTON/iconbutton.patch
# Wrapped by tl...@moa-pt.comp.vuw.ac.nz on Fri Feb 21 17:21:11 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'ICONBUTTON' ; then
echo shar: Creating directory \"'ICONBUTTON'\"
mkdir 'ICONBUTTON'
fi
if test -f 'ICONBUTTON/tkIcon.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ICONBUTTON/tkIcon.c'\"
else
echo shar: Extracting \"'ICONBUTTON/tkIcon.c'\" \(15973 characters\)
sed "s/^X//" >'ICONBUTTON/tkIcon.c' <<'END_OF_FILE'
X/*
X * tkIcon.c --
X *
X * This file maintains a database of read-only icons for the Tk
X * toolkit. This allows icons to be shared between widgets and
X * also avoids interactions with the X server.
X *
X * Author:
X * Trevor Lowe
X * Department of Computer Science
X * Victoria University of Wellington
X * New Zealand
X * Trevo...@comp.vuw.ac.nz
X *
X * Copyright 1990 Regents of the University of California
X * Permission to use, copy, modify, and distribute this
X * software and its documentation for any purpose and without
X * fee is hereby granted, provided that the above copyright
X * notice appear in all copies. The University of California
X * makes no representations about the suitability of this
X * software for any purpose. It is provided "as is" without
X * express or implied warranty.
X *
X * Copyright 1992 Victoria University of Wellington of New Zealand.
X * Permission to use, copy, modify, and distribute this
X * software and its documentation for any purpose and without
X * fee is hereby granted, provided that the above copyright
X * notice appear in all copies. Victoria University of Wellington
X * makes no representations about the suitability of this
X * software for any purpose. It is provided "as is" without
X * express or implied warranty.
X */
X
X#include "tkConfig.h"
X#include "tk.h"
X
X/*
X * One of the following data structures exists for each icon that is
X * currently active. Each structure is indexed with two hash tables
X * defined below. One of the tables is "idTable", and the other is
X * either "nameTable", "dataTable", or "iconTable".
X */
X
Xtypedef struct {
X Tk_Icon icon; /* Icon containing X identifier for bitmap. */
X Display *display; /* Display for which icon is valid. */
X int refCount; /* Number of active uses of icon. */
X Tcl_HashTable *otherTable; /* Second table (other than idTable) used
X * to index this entry. */
X Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure
X * (needed when deleting). */
X} TkIcon;
X
X/*
X * Hash table to map from a textual description of an icon to the
X * TkIcon record for the icon, and key structure used in that
X * hash table:
X */
X
Xstatic Tcl_HashTable nameTable;
Xtypedef struct {
X Tk_Uid name; /* Textual name for desired icon. */
X Display *display; /* Display for which icon will be used. */
X} NameKey;
X
X/*
X * Hash table to map from an icon created by TkGetIconFromIcon
X * to the TkIcon record for the icon.
X */
X
Xstatic Tcl_HashTable iconTable;
Xtypedef struct {
X Tk_Uid name; /* Textual name for desired icon. */
X Tk_Icon icon; /* Forced to add this so that hashing will not
X * get confused between similar icons. ie. Icons
X * with same bits set, but different colors. */
X Tk_Uid fg,bg; /* Foreground & background colors of this icon. */
X int depth; /* Depth of icon. */
X Display *display; /* Display for which icon will be used. */
X} IconKey;
X
X/*
X * Hash table to map from a collection of in-core data about an
X * icon to a TkIcon structure:
X */
X
Xstatic Tcl_HashTable dataTable;
Xtypedef struct {
X char *source; /* Icon bits. */
X unsigned int width, height; /* Dimensions of icon. */
X Display *display; /* Display on which icon will be used. */
X} DataKey;
X
X/*
X * Hash table that maps from icon identifiers to the TkIcon structure
X * for the icon. This table is indexed by icon addresses, and is used by
X * Tk_FreeIcon.
X */
X
Xstatic Tcl_HashTable idTable;
X
Xstatic int initialized = 0; /* 0 means static structures haven't been
X * initialized yet. */
X
X/*
X * Forward declarations for procedures defined in this file:
X */
X
Xstatic void IconInit _ANSI_ARGS_((void));
X
X/*
X *----------------------------------------------------------------------
X *
X * Tk_GetIcon --
X *
X * Given a string describing an icon, locate (or create if necessary)
X * an icon that fits the description.
X *
X * Results:
X * The return value is a Tk_Icon structure containing the X
X * identifer for the desired bitmap (i.e. a Pixmap with a single
X * plane) and the dimensions of the bitmap, unless string couldn't be
X * parsed correctly. In this case, None is returned in the
X * bitmap field of the Tk_Icon structure, and an error
X * message is left in interp->result. The caller should never
X * modify the icon that is returned, and should eventually call
X * Tk_FreeIcon when the icon is no longer needed.
X *
X * Side effects:
X * The icon is added to an internal database with a reference count.
X * For each call to this procedure, there should eventually be a call
X * to Tk_FreeIcon, so that the database can be cleaned up when icons
X * aren't needed anymore.
X *
X *----------------------------------------------------------------------
X */
X
XTk_Icon
XTk_GetIcon(interp, tkwin, string)
X Tcl_Interp *interp; /* Interpreter to use for error reporting. */
X Tk_Window tkwin; /* Window in which icon will be used. */
X Tk_Uid string; /* Description of icon. See manual entry
X * for details on legal syntax. */
X{
X NameKey key;
X Tcl_HashEntry *nameHashPtr, *idHashPtr;
X register TkIcon *iconPtr;
X int new;
X Tk_Icon icon;
X int dummy;
X
X if (!initialized) {
X IconInit();
X }
X
X key.name = string;
X key.display = Tk_Display(tkwin);
X nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &key, &new);
X if (!new) {
X iconPtr = (TkIcon *) Tcl_GetHashValue(nameHashPtr);
X iconPtr->refCount++;
X return iconPtr->icon;
X }
X
X /*
X * No suitable icon exists. Create a new icon from the
X * file indicated by the string. Note: the "@" at the beginning
X * the file name is required, in order to allow for built-in
X * icons to be referenced by names without the "@". No built-in
X * icons are defined yet.
X */
X
X if (*string != '@') {
X Tcl_AppendResult(interp, "bad icon description \"", string,
X "\"", (char *) NULL);
X goto error;
X }
X if (XReadBitmapFile(key.display, RootWindowOfScreen(Tk_Screen(tkwin)),
X string+1, &(icon.width), &(icon.height), &(icon.bitmap), &dummy, &dummy)
X != BitmapSuccess) {
X Tcl_AppendResult(interp, "error reading icon file \"", string+1,
X "\"", (char *) NULL);
X goto error;
X }
X
X /*
X * Add information about this icon to our database.
X */
X
X iconPtr = (TkIcon *) ckalloc(sizeof(TkIcon));
X iconPtr->icon = icon;
X iconPtr->display = key.display;
X iconPtr->refCount = 1;
X iconPtr->otherTable = &nameTable;
X iconPtr->hashPtr = nameHashPtr;
X idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &iconPtr->icon, &new);
X if (!new) {
X panic("icon already registered in Tk_GetIcon");
X }
X Tcl_SetHashValue(nameHashPtr, iconPtr);
X Tcl_SetHashValue(idHashPtr, iconPtr);
X return iconPtr->icon;
X
X error:
X Tcl_DeleteHashEntry(nameHashPtr);
X icon.bitmap = None;
X return icon;
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * Tk_GetIconFromData --
X *
X * Given a description of the bits for a bitmap, make an icon that
X * has the given properties.
X *
X * Results:
X * The return value is a Tk_Icon structure containing the X identifer
X * for the desired bitmap (a one-plane Pixmap), unless it couldn't
X * be created properly. In this case, None is returned in the bitmap
X * field and an error message is left in interp->result.
X * The caller should never modify the icon that is returned, and
X * should eventually call Tk_FreeIcon when the icon is no longer
X * needed.
X *
X * Side effects:
X * The icon is added to an internal database with a reference count.
X * For each call to this procedure, there should eventually be a call
X * to Tk_FreeIcon, so that the database can be cleaned up when icons
X * aren't needed anymore.
X *
X *----------------------------------------------------------------------
X */
X
XTk_Icon
XTk_GetIconFromData(interp, tkwin, source, width, height)
X Tcl_Interp *interp; /* Interpreter to use for error reporting. */
X Tk_Window tkwin; /* Window in which icon will be used. */
X char *source; /* Bitmap data for icon shape. */
X unsigned int width, height; /* Dimensions of icon. */
X{
X DataKey key;
X Tcl_HashEntry *dataHashPtr, *idHashPtr;
X register TkIcon *iconPtr;
X int new;
X Tk_Icon icon;
X
X if (!initialized) {
X IconInit();
X }
X
X key.source = source;
X key.width = width;
X key.height = height;
X key.display = Tk_Display(tkwin);
X dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &key, &new);
X if (!new) {
X iconPtr = (TkIcon *) Tcl_GetHashValue(dataHashPtr);
X iconPtr->refCount++;
X return iconPtr->icon;
X }
X
X /*
X * No suitable icon exists yet. Make one using the data
X * available and add it to the database.
X */
X
X iconPtr = (TkIcon *) ckalloc(sizeof(TkIcon));
X iconPtr->icon.bitmap = XCreateBitmapFromData(key.display,
X RootWindowOfScreen(Tk_Screen(tkwin)), source, width, height);
X iconPtr->icon.width = width;
X iconPtr->icon.height = height;
X iconPtr->display = key.display;
X iconPtr->refCount = 1;
X iconPtr->otherTable = &dataTable;
X iconPtr->hashPtr = dataHashPtr;
X idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &iconPtr->icon, &new);
X if (!new) {
X panic("icon already registered in Tk_GetIconFromData");
X }
X Tcl_SetHashValue(dataHashPtr, iconPtr);
X Tcl_SetHashValue(idHashPtr, iconPtr);
X return iconPtr->icon;
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * Tk_GetIconFromIcon --
X *
X * Given an icon containing a bitmap, create a new icon containing
X * a pixmap. The original icon must have been allocated by either
X * Tk_GetIcon or Tk_GetIconFromData.
X *
X * Results:
X * The return value is a Tk_Icon structure containing the X
X * identifer for the desired pixmap and the dimensions of
X * the pixmap, unless it couldn't be created properly.
X * In this case, None is returned in the bitmap field
X * of the Tk_Icon structure The caller should never modify
X * the icon that is returned, and should eventually call
X * Tk_FreeIcon when the icon is no longer needed.
X *
X * Side effects:
X * The new icon is added to an internal database with a reference count.
X * For each call to this procedure, there should eventually be a call
X * to Tk_FreeIcon, so that the database can be cleaned up when icons
X * aren't needed anymore.
X *
X *----------------------------------------------------------------------
X */
X
XTk_Icon
XTk_GetIconFromIcon(interp, tkwin, icon, fgName, bgName)
X Tcl_Interp *interp; /* Interpreter to use for error reporting. */
X Tk_Window tkwin; /* Window in which icon will be used. */
X Tk_Icon icon; /* Single plane icon. */
X Tk_Uid fgName; /* Textual description of desired
X foreground color. */
X Tk_Uid bgName; /* Textual description of desired
X background color. */
X{
X Tk_Icon newIcon;
X Tcl_HashEntry *idHashPtr, *iconHashPtr;
X register TkIcon *iconPtr;
X int new;
X unsigned int depth;
X IconKey key;
X XColor *bgColorPtr, *fgColorPtr;
X Colormap colormap;
X
X /*
X * Allocate the colors for the new pixmap.
X */
X
X colormap = DefaultColormapOfScreen(Tk_Screen(tkwin));
X bgColorPtr = Tk_GetColor(interp, tkwin, colormap, bgName);
X fgColorPtr = Tk_GetColor(interp, tkwin, colormap, fgName);
X
X depth = DefaultDepth(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
X
X /*
X * Create the new pixmap.
X */
X
X newIcon.bitmap = XCreatePixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
X icon.width, icon.height, depth);
X newIcon.width = icon.width;
X newIcon.height = icon.height;
X if (newIcon.bitmap != None) {
X GC gc;
X XGCValues gcValues;
X
X gcValues.foreground = fgColorPtr->pixel;
X gcValues.background = bgColorPtr->pixel;
X gc = Tk_GetGC(tkwin, (GCForeground|GCBackground), &gcValues);
X Tk_FreeColor(bgColorPtr);
X Tk_FreeColor(fgColorPtr);
X
X if (gc != None) {
X XCopyPlane(Tk_Display(tkwin), icon.bitmap, newIcon.bitmap,
X gc, 0, 0, icon.width, icon.height, 0, 0, 1);
X Tk_FreeGC(gc);
X
X /*
X * Add information about this new icon to our database.
X */
X
X key.name = Tk_NameOfIcon(newIcon);
X key.icon = newIcon;
X key.depth = depth;
X key.fg = fgName;
X key.bg = bgName;
X key.display = Tk_Display(tkwin);
X iconHashPtr = Tcl_CreateHashEntry(&iconTable, (char *) &key, &new);
X if (!new) {
X iconPtr = (TkIcon *) Tcl_GetHashValue(iconHashPtr);
X iconPtr->refCount++;
X return iconPtr->icon;
X }
X iconPtr = (TkIcon *) ckalloc(sizeof(TkIcon));
X iconPtr->icon = newIcon;
X iconPtr->display = Tk_Display(tkwin);
X iconPtr->refCount = 1;
X iconPtr->otherTable = &iconTable;
X iconPtr->hashPtr = iconHashPtr;
X idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &iconPtr->icon, &new);
X if (!new) {
X panic("icon already registered in Tk_GetIconFromIcon");
X }
X Tcl_SetHashValue(iconHashPtr, iconPtr);
X Tcl_SetHashValue(idHashPtr, iconPtr);
X } else {
X XFreePixmap(Tk_Display(tkwin), newIcon.bitmap);
X newIcon.bitmap = None;
X Tcl_AppendResult(interp, "error creating icon gc", (char *) NULL);
X }
X } else {
X Tcl_AppendResult(interp, "error creating icon pixmap", (char *) NULL);
X }
X return newIcon;
X}
X
X/*
X *--------------------------------------------------------------
X *
X * Tk_NameOfIcon --
X *
X * Given an icon, return a textual string identifying the
X * icon.
X *
X * Results:
X * If icon was created by Tk_GetIcon, then the return
X * value is the "string" that was used to create it.
X * Otherwise the return value is a string giving the
X * icon's X id. The storage for the return string is
X * only guaranteed to persist until the next call to this
X * procedure.
X *
X * Side effects:
X * None.
X *
X *--------------------------------------------------------------
X */
X
Xchar *
XTk_NameOfIcon(icon)
X Tk_Icon icon; /* Icon to get name of. */
X{
X Tcl_HashEntry *idHashPtr;
X TkIcon *iconPtr;
X static char string[40];
X
X if (!initialized) {
X printid:
X sprintf(string, "icon id 0x%x", icon.bitmap);
X return string;
X }
X
X idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &icon);
X if (idHashPtr == NULL) {
X goto printid;
X }
X iconPtr = (TkIcon *) Tcl_GetHashValue(idHashPtr);
X if (iconPtr->otherTable != &nameTable) {
X goto printid;
X }
X return ((NameKey *) iconPtr->hashPtr->key.words)->name;
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * Tk_FreeIcon --
X *
X * This procedure is called to release an icon allocated by
X * Tk_GetIcon, Tk_GetIconFromData, or Tk_GetIconFromIcon.
X *
X * Results:
X * None.
X *
X * Side effects:
X * The reference count associated with the icon is decremented,
X * and it is officially deallocated if no-one is using it anymore.
X *
X *----------------------------------------------------------------------
X */
X
Xvoid
XTk_FreeIcon(icon)
X Tk_Icon icon; /* Icon to be released. */
X{
X Tcl_HashEntry *idHashPtr;
X register TkIcon *iconPtr;
X
X if (!initialized) {
X panic("Tk_FreeIcon called before Tk_GetIcon");
X }
X
X idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &icon);
X if (idHashPtr == NULL) {
X panic("Tk_FreeIcon received unknown icon argument");
X }
X
X iconPtr = (TkIcon *) Tcl_GetHashValue(idHashPtr);
X iconPtr->refCount--;
X if (iconPtr->refCount == 0) {
X XFreePixmap(iconPtr->display, iconPtr->icon.bitmap);
X Tcl_DeleteHashEntry(iconPtr->hashPtr);
X Tcl_DeleteHashEntry(idHashPtr);
X ckfree((char *) iconPtr);
X }
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * IconInit --
X *
X * Initialize the structures used for icon management.
X *
X * Results:
X * None.
X *
X * Side effects:
X * Read the code.
X *
X *----------------------------------------------------------------------
X */
X
Xstatic void
XIconInit()
X{
X initialized = 1;
X Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
X Tcl_InitHashTable(&iconTable, sizeof(IconKey)/sizeof(int));
X Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
X Tcl_InitHashTable(&idTable, sizeof(Tk_Icon)/sizeof(int));
X}
END_OF_FILE
if test 15973 -ne `wc -c <'ICONBUTTON/tkIcon.c'`; then
echo shar: \"'ICONBUTTON/tkIcon.c'\" unpacked with wrong size!
fi
chmod +x 'ICONBUTTON/tkIcon.c'
# end of 'ICONBUTTON/tkIcon.c'
fi
if test -f 'ICONBUTTON/tkIconButton.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ICONBUTTON/tkIconButton.c'\"
else
echo shar: Extracting \"'ICONBUTTON/tkIconButton.c'\" \(24320 characters\)
sed "s/^X//" >'ICONBUTTON/tkIconButton.c' <<'END_OF_FILE'
X/*
X * tkIconButton.c --
X *
X * This module implements an iconbutton widget for the Tk
X * toolkit.
X *
X * Author:
X * Trevor Lowe
X * Department of Computer Science
X * Victoria University of Wellington
X * New Zealand
X * Trevo...@comp.vuw.ac.nz
X *
X * Copyright 1990 Regents of the University of California.
X * Permission to use, copy, modify, and distribute this
X * software and its documentation for any purpose and without
X * fee is hereby granted, provided that the above copyright
X * notice appear in all copies. The University of California
X * makes no representations about the suitability of this
X * software for any purpose. It is provided "as is" without
X * express or implied warranty.
X *
X * Copyright 1992 Victoria University of Wellington of New Zealand.
X * Permission to use, copy, modify, and distribute this
X * software and its documentation for any purpose and without
X * fee is hereby granted, provided that the above copyright
X * notice appear in all copies. Victoria University of Wellington
X * makes no representations about the suitability of this
X * software for any purpose. It is provided "as is" without
X * express or implied warranty.
X */
X
X#include "default.h"
X#include "tkConfig.h"
X#include "tkInt.h"
X
X/*
X * Default bitmap for iconbuttons.
X */
X
X#include "bitmaps/defaultIcon.bmp"
X
X/*
X * A data structure of the following type is kept for each
X * widget managed by this file:
X */
X
Xtypedef struct {
X Tk_Window tkwin; /* Window that embodies the iconbutton. NULL
X * means that the window has been destroyed. */
X Tcl_Interp *interp; /* Interpreter associated with iconbutton. */
X
X /*
X * Information used when displaying widget:
X */
X
X Tk_3DBorder normalBorder; /* Structure used to draw 3-D
X * border and background when window
X * isn't active. NULL means no such
X * border exists. */
X Tk_3DBorder activeBorder; /* Structure used to draw 3-D
X * border and background when window
X * is active. NULL means no such
X * border exists. */
X int borderWidth; /* Width of border. */
X int relief; /* 3-d effect: TK_RELIEF_RAISED, etc. */
X XColor *normalFg; /* Foreground color in normal mode. */
X XColor *activeFg; /* Foreground color in active mode. NULL
X * means use normalFg instead. */
X Tk_Icon icon; /* Icon to display in the iconbutton. */
X Tk_Icon normalIcon; /* Icon actually being used to display in
X * the iconbutton in normal mode. */
X Tk_Icon activeIcon; /* Icon actually being used to display in
X * the iconbutton in active mode. */
X GC normalIconGC; /* GC for drawing icon in normal mode. */
X GC activeIconGC; /* GC for drawing icon in active mode (NULL
X * means use normalIconGC. */
X int padX, padY; /* Desired extra space around icon. */
X
X /*
X * Miscellaneous information:
X */
X
X char *command; /* Command to execute when iconbutton is
X * invoked; valid for buttons only.
X * If not NULL, it's malloc-ed. */
X int flags; /* Various flags; see below for
X * definitions. */
X
X} IconButton;
X
X/*
X * Flag bits for iconbuttons:
X *
X * REDRAW_PENDING: Non-zero means a DoWhenIdle handler
X * has already been queued to redraw
X * this window.
X * ACTIVE: Non-zero means this window should be
X * drawn using "active" parameters.
X * CLEAR_NEEDED: Need to clear the window when redrawing.
X * PRESS_ACTIVE: Non-zero means a mouse button has been
X * pressed in the window but not yet released.
X * MOUSE_IN_WINDOW: Non-zero means mouse is in window.
X * NEW_ICON: Non-zero means a new icon needs to be
X * created and displayed in the button.
X */
X
X#define REDRAW_PENDING 1
X#define ACTIVE 2
X#define CLEAR_NEEDED 4
X#define PRESS_ACTIVE 8
X#define MOUSE_IN_WINDOW 16
X#define NEW_ICON 32
X
X/*
X * Information used for parsing configuration specs:
X */
X
Xstatic Tk_ConfigSpec configSpecs[] = {
X {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
X DEF_ICONBUTTON_ACTIVE_BG_COLOR, Tk_Offset(IconButton, activeBorder),
X TK_CONFIG_COLOR_ONLY},
X {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
X DEF_ICONBUTTON_ACTIVE_BG_MONO, Tk_Offset(IconButton, activeBorder),
X TK_CONFIG_MONO_ONLY},
X {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
X DEF_ICONBUTTON_ACTIVE_FG_COLOR, Tk_Offset(IconButton, activeFg),
X TK_CONFIG_COLOR_ONLY},
X {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
X DEF_ICONBUTTON_ACTIVE_FG_MONO, Tk_Offset(IconButton, activeFg),
X TK_CONFIG_MONO_ONLY},
X {TK_CONFIG_BORDER, "-background", "background", "Background",
X DEF_ICONBUTTON_BG_COLOR, Tk_Offset(IconButton, normalBorder),
X TK_CONFIG_COLOR_ONLY},
X {TK_CONFIG_BORDER, "-background", "background", "Background",
X DEF_ICONBUTTON_BG_MONO, Tk_Offset(IconButton, normalBorder),
X TK_CONFIG_MONO_ONLY},
X {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
X (char *) NULL, 0,
X 0},
X {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
X (char *) NULL, 0,
X 0},
X {TK_CONFIG_INT, "-borderwidth", "borderWidth", "BorderWidth",
X DEF_ICONBUTTON_BORDER_WIDTH, Tk_Offset(IconButton, borderWidth),
X 0},
X {TK_CONFIG_STRING, "-command", "command", "Command",
X DEF_ICONBUTTON_COMMAND, Tk_Offset(IconButton, command),
X 0},
X {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
X (char *) NULL, 0,
X 0},
X {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
X DEF_ICONBUTTON_FG, Tk_Offset(IconButton, normalFg),
X 0},
X {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
X DEF_ICONBUTTON_RELIEF, Tk_Offset(IconButton, relief),
X 0},
X {TK_CONFIG_ICON, "-icon", "icon", "Icon",
X DEF_ICONBUTTON_ICON, Tk_Offset(IconButton, icon),
X 0},
X {TK_CONFIG_INT, "-padx", "padX", "Pad",
X DEF_ICONBUTTON_PADX, Tk_Offset(IconButton, padX),
X 0},
X {TK_CONFIG_INT, "-pady", "padY", "Pad",
X DEF_ICONBUTTON_PADY, Tk_Offset(IconButton, padY),
X 0},
X {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
X (char *) NULL, 0,
X 0}
X};
X
X/*
X * Forward declarations for procedures defined later in this file:
X */
X
Xstatic void IconButtonEventProc _ANSI_ARGS_((ClientData clientData,
X XEvent *eventPtr));
Xstatic void IconButtonMouseProc _ANSI_ARGS_((ClientData clientData,
X XEvent *eventPtr));
Xstatic int IconButtonWidgetCmd _ANSI_ARGS_((IconButton *icoPtr,
X Tcl_Interp *interp, int argc, char **argv));
Xstatic int ConfigureIconButton _ANSI_ARGS_((Tcl_Interp *interp,
X IconButton *icoPtr, int argc, char **argv,
X int flags));
Xstatic void DestroyIconButton _ANSI_ARGS_((ClientData clientData));
Xstatic void DisplayIconButton _ANSI_ARGS_((ClientData clientData));
Xstatic int InvokeIconButton _ANSI_ARGS_((IconButton *icoPtr));
X
X/*
X *--------------------------------------------------------------
X *
X * Tk_IconButtonCmd --
X *
X * This procedure is invoked to process the "iconbutton"
X * Tcl command. See the user documentation for details
X * on what it does.
X *
X * Results:
X * A standard Tcl result.
X *
X * Side effects:
X * See the user documentation.
X *
X *--------------------------------------------------------------
X */
X
Xint
XTk_IconButtonCmd(clientData, interp, argc, argv)
X ClientData clientData; /* Main window associated with
X * interpreter. */
X Tcl_Interp *interp; /* Current interpreter. */
X int argc; /* Number of arguments. */
X char **argv; /* Argument strings. */
X{
X register IconButton *icoPtr;
X Tk_Window new;
X Tk_Window tkwin = (Tk_Window) clientData;
X
X if (argc < 2) {
X Tcl_AppendResult(interp, "wrong # args: should be \"",
X argv[0], " pathName [options]\"", (char *) NULL);
X return TCL_ERROR;
X }
X new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
X if (new == NULL) {
X return TCL_ERROR;
X }
X icoPtr = (IconButton *) ckalloc(sizeof(IconButton));
X
X icoPtr->tkwin = new;
X icoPtr->interp = interp;
X icoPtr->normalBorder = NULL;
X icoPtr->activeBorder = NULL;
X icoPtr->borderWidth = 0;
X icoPtr->relief = TK_RELIEF_FLAT;
X icoPtr->normalFg = NULL;
X icoPtr->activeFg = NULL;
X icoPtr->icon = Tk_GetIconFromData(interp, tkwin, defaultIcon_bits,
X defaultIcon_width, defaultIcon_height);
X icoPtr->normalIcon.bitmap = None;
X icoPtr->activeIcon.bitmap = None;
X icoPtr->normalIconGC = None;
X icoPtr->activeIconGC = None;
X icoPtr->command = NULL;
X icoPtr->flags = 0;
X
X Tk_SetClass(icoPtr->tkwin, "IconButton");
X Tk_CreateEventHandler(icoPtr->tkwin, (ExposureMask | StructureNotifyMask),
X IconButtonEventProc, (ClientData) icoPtr);
X Tk_CreateEventHandler(icoPtr->tkwin, (EnterWindowMask | LeaveWindowMask | ButtonPressMask |
X ButtonReleaseMask), IconButtonMouseProc, (ClientData) icoPtr);
X
X Tcl_CreateCommand(interp, Tk_PathName(icoPtr->tkwin), IconButtonWidgetCmd,
X (ClientData) icoPtr, (void (*)()) NULL);
X if (ConfigureIconButton(interp, icoPtr, argc-2, argv+2, 0) != TCL_OK) {
X goto error;
X }
X interp->result = Tk_PathName(icoPtr->tkwin);
X return TCL_OK;
X
X error:
X Tk_DestroyWindow(icoPtr->tkwin);
X return TCL_ERROR;
X}
X
X/*
X *--------------------------------------------------------------
X *
X * IconButtonWidgetCmd --
X *
X * This procedure is invoked to process the Tcl command
X * that corresponds to a widget managed by this module.
X * See the user documentation for details on what it does.
X *
X * Results:
X * A standard Tcl result.
X *
X * Side effects:
X * See the user documentation.
X *
X *--------------------------------------------------------------
X */
X
Xstatic int
XIconButtonWidgetCmd(icoPtr, interp, argc, argv)
X register IconButton *icoPtr;/* Information about button widget. */
X Tcl_Interp *interp; /* Current interpreter. */
X int argc; /* Number of arguments. */
X char **argv; /* Argument strings. */
X{
X int result = TCL_OK;
X int length;
X char c;
X
X if (argc < 2) {
X sprintf(interp->result,
X "wrong # args: should be \"%.50s option [arg arg ...]\"",
X argv[0]);
X return TCL_ERROR;
X }
X Tk_Preserve((ClientData) icoPtr);
X c = argv[1][0];
X length = strlen(argv[1]);
X if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)) {
X if (argc > 2) {
X sprintf(interp->result,
X "wrong # args: should be \"%.50s activate\"",
X argv[0]);
X goto error;
X }
X icoPtr->flags |= ACTIVE|CLEAR_NEEDED;
X Tk_SetBackgroundFromBorder(icoPtr->tkwin, icoPtr->activeBorder);
X goto redisplay;
X } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) {
X if (argc == 2) {
X result = Tk_ConfigureInfo(interp, icoPtr->tkwin, configSpecs,
X (char *) icoPtr, (char *) NULL, 0);
X } else if (argc == 3) {
X result = Tk_ConfigureInfo(interp, icoPtr->tkwin, configSpecs,
X (char *) icoPtr, argv[2], 0);
X } else {
X result = ConfigureIconButton(interp, icoPtr, argc-2, argv+2,
X TK_CONFIG_ARGV_ONLY);
X }
X } else if ((c == 'd') && (strncmp(argv[1], "deactivate", length) == 0)
X && (length >= 3)) {
X if (argc > 2) {
X sprintf(interp->result,
X "wrong # args: should be \"%.50s deactivate\"",
X argv[0]);
X goto error;
X }
X icoPtr->flags &= ~ACTIVE;
X icoPtr->flags |= CLEAR_NEEDED;
X Tk_SetBackgroundFromBorder(icoPtr->tkwin, icoPtr->normalBorder);
X goto redisplay;
X } else if ((c == 'f') && (strncmp(argv[1], "flash", length) == 0)) {
X int i;
X
X if (argc > 2) {
X sprintf(interp->result,
X "wrong # args: should be \"%.50s flash\"",
X argv[0]);
X goto error;
X }
X for (i = 0; i < 4; i++) {
X icoPtr->flags ^= ACTIVE;
X icoPtr->flags |= CLEAR_NEEDED;
X Tk_SetBackgroundFromBorder(icoPtr->tkwin,
X icoPtr->flags & ACTIVE ? icoPtr->activeBorder
X : icoPtr->normalBorder);
X DisplayIconButton((ClientData) icoPtr);
X XFlush(Tk_Display(icoPtr->tkwin));
X Tk_Sleep(50);
X }
X } else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0)) {
X if (argc > 2) {
X sprintf(interp->result,
X "wrong # args: should be \"%.50s invoke\"",
X argv[0]);
X goto error;
X }
X result = InvokeIconButton(icoPtr);
X } else {
X Tcl_AppendResult(interp, "bad option \"", argv[1],
X "\": must be activate, configure, deactivate, ",
X "or flash", (char *) NULL);
X goto error;
X }
X Tk_Release((ClientData) icoPtr);
X return result;
X
X redisplay:
X if (Tk_IsMapped(icoPtr->tkwin) && !(icoPtr->flags & REDRAW_PENDING)) {
X Tk_DoWhenIdle(DisplayIconButton, (ClientData) icoPtr);
X icoPtr->flags |= REDRAW_PENDING;
X }
X Tk_Release((ClientData) icoPtr);
X return TCL_OK;
X
X error:
X Tk_Release((ClientData) icoPtr);
X return TCL_ERROR;
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * DestroyIconButton --
X *
X * This procedure is invoked by Tk_EventuallyFree or Tk_Release
X * to clean up the internal structure of an iconbutton at a safe time
X * (when no-one is using it anymore).
X *
X * Results:
X * None.
X *
X * Side effects:
X * Everything associated with the widget is freed up.
X *
X *----------------------------------------------------------------------
X */
X
Xstatic void
XDestroyIconButton(clientData)
X ClientData clientData; /* Info about entry widget. */
X{
X register IconButton *icoPtr = (IconButton *) clientData;
X
X if (icoPtr->normalBorder != NULL) {
X Tk_Free3DBorder(icoPtr->normalBorder);
X }
X if (icoPtr->activeBorder != NULL) {
X Tk_Free3DBorder(icoPtr->activeBorder);
X }
X if (icoPtr->normalFg != NULL) {
X Tk_FreeColor(icoPtr->normalFg);
X }
X if (icoPtr->activeFg != NULL) {
X Tk_FreeColor(icoPtr->activeFg);
X }
X if (icoPtr->icon.bitmap != None) {
X Tk_FreeIcon(icoPtr->icon);
X }
X if (icoPtr->normalIcon.bitmap != None) {
X Tk_FreeIcon(icoPtr->normalIcon);
X }
X if (icoPtr->activeIcon.bitmap != None) {
X Tk_FreeIcon(icoPtr->activeIcon);
X }
X if (icoPtr->normalIconGC != None) {
X Tk_FreeGC(icoPtr->normalIconGC);
X }
X if (icoPtr->activeIconGC != None) {
X Tk_FreeGC(icoPtr->activeIconGC);
X }
X if (icoPtr->command != NULL) {
X ckfree(icoPtr->command);
X }
X ckfree((char *) icoPtr);
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * DisplayIconButton --
X *
X * This procedure is invoked to display an iconbutton widget.
X *
X * Results:
X * None.
X *
X * Side effects:
X * Commands are output to X to display the iconbutton in its
X * current mode.
X *
X *----------------------------------------------------------------------
X */
X
Xstatic void
XDisplayIconButton(clientData)
X ClientData clientData; /* Information about widget. */
X{
X register IconButton *icoPtr = (IconButton *) clientData;
X GC gc;
X Tk_3DBorder border;
X int x, y, relief;
X register Tk_Window tkwin = icoPtr->tkwin;
X char bg_color_name[40];
X char fg_color_name[40];
X
X icoPtr->flags &= ~REDRAW_PENDING;
X if ((icoPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
X return;
X }
X
X if (icoPtr->flags & ACTIVE) {
X gc = icoPtr->activeIconGC;
X border = icoPtr->activeBorder;
X } else {
X gc = icoPtr->normalIconGC;
X border = icoPtr->normalBorder;
X }
X relief = icoPtr->relief;
X if ((icoPtr->flags & (PRESS_ACTIVE|MOUSE_IN_WINDOW))
X == (PRESS_ACTIVE|MOUSE_IN_WINDOW)) {
X relief = TK_RELIEF_SUNKEN;
X }
X
X /*
X * Draw icon first, then border; if icon is too
X * large for window the border will overlay it, instead of
X * vice versa.
X */
X
X x = (Tk_Width(tkwin) - icoPtr->icon.width )/2;
X y = (Tk_Height(tkwin) - icoPtr->icon.height )/2;
X if (relief == TK_RELIEF_RAISED) {
X x -= 1;
X y -= 1;
X } else if (relief == TK_RELIEF_SUNKEN) {
X x += 1;
X y += 1;
X }
X if (icoPtr->flags & CLEAR_NEEDED) {
X XClearWindow(Tk_Display(tkwin), Tk_WindowId(tkwin));
X icoPtr->flags &= ~CLEAR_NEEDED;
X }
X
X
X if ((icoPtr->flags & NEW_ICON) || (icoPtr->normalIcon.bitmap == None)
X || (icoPtr->activeIcon.bitmap == None)) {
X
X /*
X * Either the iconbutton has been re-configured (in which case the colors or
X * icon may have changed) or the normal or active icons do not exist.
X * Either way get new icons with the correct depth and foreground and
X * background colors.
X */
X
X if (icoPtr->normalIcon.bitmap != None) {
X Tk_FreeIcon(icoPtr->normalIcon);
X }
X sprintf(bg_color_name, "%s", Tk_NameOf3DBorder(icoPtr->normalBorder));
X sprintf(fg_color_name, "%s", Tk_NameOfColor(icoPtr->normalFg));
X icoPtr->normalIcon = Tk_GetIconFromIcon(icoPtr->interp, tkwin,
X icoPtr->icon, fg_color_name, bg_color_name);
X
X if (icoPtr->activeIcon.bitmap != None) {
X Tk_FreeIcon(icoPtr->activeIcon);
X }
X sprintf(bg_color_name, "%s", Tk_NameOf3DBorder(icoPtr->activeBorder));
X sprintf(fg_color_name, "%s", Tk_NameOfColor(icoPtr->activeFg));
X icoPtr->activeIcon = Tk_GetIconFromIcon(icoPtr->interp, tkwin,
X icoPtr->icon, fg_color_name, bg_color_name);
X
X icoPtr->flags &= ~NEW_ICON;
X }
X
X /*
X * Display the icon.
X */
X
X if (icoPtr->flags & ACTIVE) {
X XCopyArea(Tk_Display(tkwin), icoPtr->activeIcon.bitmap, Tk_WindowId(tkwin),
X gc, 0, 0, icoPtr->activeIcon.width, icoPtr->activeIcon.height, x, y);
X } else {
X XCopyArea(Tk_Display(tkwin), icoPtr->normalIcon.bitmap, Tk_WindowId(tkwin),
X gc, 0, 0, icoPtr->normalIcon.width, icoPtr->normalIcon.height, x, y);
X }
X
X if (relief != TK_RELIEF_FLAT) {
X Tk_Draw3DRectangle(Tk_Display(tkwin), Tk_WindowId(tkwin), border,
X 0, 0, Tk_Width(tkwin), Tk_Height(tkwin),
X icoPtr->borderWidth, relief);
X }
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * ConfigureIconButton --
X *
X * This procedure is called to process an argv/argc list, plus
X * the Tk option database, in order to configure (or
X * reconfigure) an iconbutton widget.
X *
X * Results:
X * The return value is a standard Tcl result. If TCL_ERROR is
X * returned, then interp->result contains an error message.
X *
X * Side effects:
X * Configuration information, such as icon bitmap, colors, font,
X * etc. get set for icoPtr; old resources get freed, if there
X * were any. The iconbutton is redisplayed.
X *
X *----------------------------------------------------------------------
X */
X
Xstatic int
XConfigureIconButton(interp, icoPtr, argc, argv, flags)
X Tcl_Interp *interp; /* Used for error reporting. */
X register IconButton *icoPtr;/* Information about widget; may or may
X * not already have values for some fields. */
X int argc; /* Number of valid entries in argv. */
X char **argv; /* Arguments. */
X int flags; /* Flags to pass to Tk_ConfigureWidget. */
X{
X XGCValues gcValues;
X GC newGC;
X int dummy;
X
X if (Tk_ConfigureWidget(interp, icoPtr->tkwin, configSpecs,
X argc, argv, (char *) icoPtr, flags) != TCL_OK) {
X return TCL_ERROR;
X }
X
X /*
X * Iconbutton has been re-configured, need to create a new icon
X * and display it in the button.
X */
X
X icoPtr->flags |= NEW_ICON;
X
X /*
X * A few options need special processing, such as setting the
X * background from a 3-D border, or filling in complicated
X * defaults that couldn't be specified to Tk_ConfigureWidget.
X */
X
X if (icoPtr->flags & ACTIVE) {
X Tk_SetBackgroundFromBorder(icoPtr->tkwin, icoPtr->activeBorder);
X } else {
X Tk_SetBackgroundFromBorder(icoPtr->tkwin, icoPtr->normalBorder);
X }
X
X gcValues.foreground = icoPtr->normalFg->pixel;
X newGC = Tk_GetGC(icoPtr->tkwin, GCForeground, &gcValues);
X if (icoPtr->normalIconGC != None) {
X Tk_FreeGC(icoPtr->normalIconGC);
X }
X icoPtr->normalIconGC = newGC;
X
X if (icoPtr->activeFg != NULL) {
X gcValues.foreground = icoPtr->activeFg->pixel;
X newGC = Tk_GetGC(icoPtr->tkwin, GCForeground, &gcValues);
X
X if (icoPtr->activeIconGC != None) {
X Tk_FreeGC(icoPtr->activeIconGC);
X }
X icoPtr->activeIconGC = newGC;
X }
X
X if (icoPtr->padX == -1) {
X icoPtr->padX = icoPtr->icon.height/2;
X }
X if (icoPtr->padY == -1) {
X icoPtr->padY = icoPtr->icon.width/4;
X }
X /*
X * Recompute the geometry for the button.
X */
X
X Tk_GeometryRequest(icoPtr->tkwin,
X (icoPtr->icon.width + 2*icoPtr->padX + 2*icoPtr->borderWidth),
X (icoPtr->icon.height + 2*icoPtr->padY + 2*icoPtr->borderWidth));
X Tk_SetInternalBorder(icoPtr->tkwin, icoPtr->borderWidth);
X
X /*
X * Lastly, arrange for the button to be redisplayed.
X */
X
X icoPtr->flags |= CLEAR_NEEDED;
X if (Tk_IsMapped(icoPtr->tkwin) && !(icoPtr->flags & REDRAW_PENDING)) {
X Tk_DoWhenIdle(DisplayIconButton, (ClientData) icoPtr);
X icoPtr->flags |= REDRAW_PENDING;
X }
X
X return TCL_OK;
X}
X
X/*
X *--------------------------------------------------------------
X *
X * IconButtonEventProc --
X *
X * This procedure is invoked by the Tk dispatcher for various
X * events on iconbuttons.
X *
X * Results:
X * None.
X *
X * Side effects:
X * When the window gets deleted, internal structures get
X * cleaned up. When it gets exposed, it is redisplayed.
X *
X *--------------------------------------------------------------
X */
X
Xstatic void
XIconButtonEventProc(clientData, eventPtr)
X ClientData clientData; /* Information about window. */
X XEvent *eventPtr; /* Information about event. */
X{
X IconButton *icoPtr = (IconButton *) clientData;
X
X if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
X if ((icoPtr->tkwin != NULL) && !(icoPtr->flags & REDRAW_PENDING)) {
X Tk_DoWhenIdle(DisplayIconButton, (ClientData) icoPtr);
X icoPtr->flags |= REDRAW_PENDING;
X }
X } else if (eventPtr->type == DestroyNotify) {
X Tcl_DeleteCommand(icoPtr->interp, Tk_PathName(icoPtr->tkwin));
X icoPtr->tkwin = NULL;
X if (icoPtr->flags & REDRAW_PENDING) {
X Tk_CancelIdleCall(DisplayIconButton, (ClientData) icoPtr);
X }
X Tk_EventuallyFree((ClientData) icoPtr, DestroyIconButton);
X }
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * InvokeIconButton --
X *
X * This procedure is called to carry out the actions associated
X * with an iconbutton, such as invoking a Tcl command.
X * This procedure is invoked, for example, when the
X * button is invoked via the mouse.
X *
X * Results:
X * A standard Tcl return value. Information is also left in
X * interp->result.
X *
X * Side effects:
X * Depends on the iconbutton and its associated command.
X *
X *----------------------------------------------------------------------
X */
X
Xstatic int
XInvokeIconButton(icoPtr)
X register IconButton *icoPtr; /* Information about button. */
X{
X if (icoPtr->command != NULL) {
X return Tcl_Eval(icoPtr->interp, icoPtr->command, 0, (char **) NULL);
X }
X return TCL_OK;
X}
X
X/*
X *----------------------------------------------------------------------
X *
X * IconButtonMouseProc --
X *
X * This procedure is called back by the Tk dispatcher to process
X * mouse-related events on iconbutton widgets.
X *
X * Results:
X * None.
X *
X * Side effects:
X * Depends on the action. This procedure implements the default
X * iconbutton behavior; see the manual entry for details.
X *
X *----------------------------------------------------------------------
X */
X
Xstatic void
XIconButtonMouseProc(clientData, eventPtr)
X ClientData clientData; /* Information about widget. */
X register XEvent *eventPtr; /* Information about event. */
X{
X IconButton *icoPtr = (IconButton *) clientData;
X
X Tk_Preserve((ClientData) icoPtr);
X if (eventPtr->type == EnterNotify) {
X icoPtr->flags |= ACTIVE|MOUSE_IN_WINDOW|CLEAR_NEEDED;
X Tk_SetBackgroundFromBorder(icoPtr->tkwin, icoPtr->activeBorder);
X } else if (eventPtr->type == LeaveNotify) {
X icoPtr->flags &= ~(ACTIVE|MOUSE_IN_WINDOW);
X icoPtr->flags |= CLEAR_NEEDED;
X Tk_SetBackgroundFromBorder(icoPtr->tkwin, icoPtr->normalBorder);
X } else if ((eventPtr->type == ButtonPress)
X && (eventPtr->xbutton.button == 1)
X && (eventPtr->xbutton.state == 0)) {
X icoPtr->flags |= PRESS_ACTIVE|CLEAR_NEEDED;
X } else if ((eventPtr->type == ButtonRelease)
X && (eventPtr->xbutton.button == 1)) {
X if ((icoPtr->flags & PRESS_ACTIVE)
X && (icoPtr->flags & MOUSE_IN_WINDOW)) {
X int result;
X
X result = InvokeIconButton(icoPtr);
X if (result != TCL_OK) {
X TkBindError(icoPtr->interp);
X }
X Tcl_Return(icoPtr->interp, (char *) NULL, TCL_STATIC);
X }
X icoPtr->flags &= ~PRESS_ACTIVE;
X icoPtr->flags |= CLEAR_NEEDED;
X }
X if ((icoPtr->tkwin != NULL) && !(icoPtr->flags & REDRAW_PENDING)) {
X Tk_DoWhenIdle(DisplayIconButton, (ClientData) icoPtr);
X icoPtr->flags |= REDRAW_PENDING;
X }
X Tk_Release((ClientData) icoPtr);
X}
END_OF_FILE
if test 24320 -ne `wc -c <'ICONBUTTON/tkIconButton.c'`; then
echo shar: \"'ICONBUTTON/tkIconButton.c'\" unpacked with wrong size!
fi
chmod +x 'ICONBUTTON/tkIconButton.c'
# end of 'ICONBUTTON/tkIconButton.c'
fi
if test -f 'ICONBUTTON/iconbutton.patch' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ICONBUTTON/iconbutton.patch'\"
else
echo shar: Extracting \"'ICONBUTTON/iconbutton.patch'\" \(7630 characters\)
sed "s/^X//" >'ICONBUTTON/iconbutton.patch' <<'END_OF_FILE'
Xdiff -c old//Makefile new//Makefile
X*** old//Makefile Mon Feb 10 14:06:19 1992
X--- new//Makefile Wed Feb 12 11:32:11 1992
X***************
X*** 29,51 ****
X
X LIBS = libtk.a $(TCL_DIR)/libtcl.a
X
X! WIDGOBJS = tkButton.o tkEntry.o tkFrame.o tkListbox.o \
X tkMenu.o tkMenubutton.o tkMessage.o tkScale.o \
X tkScrollbar.o
X
X OBJS = tk3d.o tkArgv.o tkAtom.o tkBind.o tkBitmap.o \
X tkCmds.o tkColor.o tkConfig.o tkCursor.o tkError.o \
X! tkEvent.o tkFont.o tkGet.o tkGC.o tkGeometry.o \
X tkOption.o tkPack.o tkPreserve.o tkSelect.o \
X tkSend.o tkShare.o tkWindow.o tkWm.o $(WIDGOBJS)
X
X! WIDGSRCS = tkButton.c tkEntry.c tkFrame.c tkListbox.c \
X tkMenu.c tkMenubutton.c tkMessage.c tkScale.c \
X tkScrollbar.c
X
X SRCS = tk3d.c tkArgv.c tkAtom.c tkBind.c tkBitmap.c \
X tkCmds.o tkColor.c tkConfig.c tkCursor.c tkError.c \
X! tkEvent.c tkFont.c tkGet.c tkGC.c tkGeometry.c \
X tkOption.c tkPack.c tkPreserve.c tkSelect.c \
X tkSend.c tkShare.c tkWindow.c tkWm.c $(WIDGSRCS)
X
X--- 29,51 ----
X
X LIBS = libtk.a $(TCL_DIR)/libtcl.a
X
X! WIDGOBJS = tkButton.o tkEntry.o tkFrame.o tkIconButton.o tkListbox.o \
X tkMenu.o tkMenubutton.o tkMessage.o tkScale.o \
X tkScrollbar.o
X
X OBJS = tk3d.o tkArgv.o tkAtom.o tkBind.o tkBitmap.o \
X tkCmds.o tkColor.o tkConfig.o tkCursor.o tkError.o \
X! tkEvent.o tkFont.o tkGet.o tkGC.o tkGeometry.o tkIcon.o \
X tkOption.o tkPack.o tkPreserve.o tkSelect.o \
X tkSend.o tkShare.o tkWindow.o tkWm.o $(WIDGOBJS)
X
X! WIDGSRCS = tkButton.c tkEntry.c tkFrame.c tkIconButton.c tkListbox.c \
X tkMenu.c tkMenubutton.c tkMessage.c tkScale.c \
X tkScrollbar.c
X
X SRCS = tk3d.c tkArgv.c tkAtom.c tkBind.c tkBitmap.c \
X tkCmds.o tkColor.c tkConfig.c tkCursor.c tkError.c \
X! tkEvent.c tkFont.c tkGet.c tkGC.c tkGeometry.c tkIcon.c \
X tkOption.c tkPack.c tkPreserve.c tkSelect.c \
X tkSend.c tkShare.c tkWindow.c tkWm.c $(WIDGSRCS)
X
Xdiff -c old//default.h new//default.h
X*** old//default.h Mon Feb 10 14:01:38 1992
X--- new//default.h Wed Feb 19 16:41:48 1992
X***************
X*** 122,127 ****
X--- 122,145 ----
X #define DEF_FRAME_RELIEF "flat"
X
X /*
X+ * Defaults for iconbuttons:
X+ */
X+
X+ #define DEF_ICONBUTTON_ACTIVE_BG_COLOR BISQUE2
X+ #define DEF_ICONBUTTON_ACTIVE_BG_MONO BLACK
X+ #define DEF_ICONBUTTON_ACTIVE_FG_COLOR BLACK
X+ #define DEF_ICONBUTTON_ACTIVE_FG_MONO WHITE
X+ #define DEF_ICONBUTTON_BG_COLOR BISQUE1
X+ #define DEF_ICONBUTTON_BG_MONO WHITE
X+ #define DEF_ICONBUTTON_BORDER_WIDTH "2"
X+ #define DEF_ICONBUTTON_COMMAND ((char *) NULL)
X+ #define DEF_ICONBUTTON_FG BLACK
X+ #define DEF_ICONBUTTON_RELIEF "raised"
X+ #define DEF_ICONBUTTON_ICON ((char *) NULL)
X+ #define DEF_ICONBUTTON_PADX "1"
X+ #define DEF_ICONBUTTON_PADY "1"
X+
X+ /*
X * Defaults for listboxes:
X */
X
Xdiff -c old//tk.h new//tk.h
X*** old//tk.h Mon Feb 10 14:01:23 1992
X--- new//tk.h Wed Feb 19 16:41:21 1992
X***************
X*** 43,48 ****
X--- 43,57 ----
X typedef char *Tk_Uid;
X
X /*
X+ * Structure for storing information about an icon.
X+ */
X+
X+ typedef struct {
X+ Pixmap bitmap; /* X identifier for icon. */
X+ unsigned int height, width; /* Dimensions of the icon. */
X+ } Tk_Icon;
X+
X+ /*
X * Structure used to specify how to handle argv options.
X */
X
X***************
X*** 133,138 ****
X--- 142,148 ----
X #define TK_CONFIG_CAP_STYLE 15
X #define TK_CONFIG_JOIN_STYLE 16
X #define TK_CONFIG_END 17
X+ #define TK_CONFIG_ICON 18
X
X /*
X * Macro to use to fill in "offset" fields of Tk_ConfigInfos.
X***************
X*** 431,436 ****
X--- 441,447 ----
X extern void Tk_FreeFontStruct _ANSI_ARGS_((
X XFontStruct *fontStructPtr));
X extern void Tk_FreeGC _ANSI_ARGS_((GC gc));
X+ extern void Tk_FreeIcon _ANSI_ARGS_((Tk_Icon icon));
X extern void Tk_GeometryRequest _ANSI_ARGS_((Tk_Window tkwin,
X int reqWidth, int reqHeight));
X extern Tk_3DBorder Tk_Get3DBorder _ANSI_ARGS_((Tcl_Interp *interp,
X***************
X*** 467,472 ****
X--- 478,490 ----
X Tk_Window tkwin, Tk_Uid name));
X extern GC Tk_GetGC _ANSI_ARGS_((Tk_Window tkwin,
X unsigned long valueMask, XGCValues *valuePtr));
X+ extern Tk_Icon Tk_GetIcon _ANSI_ARGS_((Tcl_Interp *interp,
X+ Tk_Window tkwin, Tk_Uid string));
X+ extern Tk_Icon Tk_GetIconFromData _ANSI_ARGS_((Tcl_Interp *interp,
X+ Tk_Window tkwin, char *source, unsigned int width,
X+ unsigned int height));
X+ extern Tk_Icon Tk_GetIconFromIcon _ANSI_ARGS_((Tcl_Interp *interp,
X+ Tk_Window tkwin, Tk_Icon icon, Tk_Uid fgName, Tk_Uid bgName));
X extern int Tk_GetJoinStyle _ANSI_ARGS_((Tcl_Interp *interp,
X char *string, int *joinPtr));
X extern int Tk_GetJustify _ANSI_ARGS_((Tcl_Interp *interp,
X***************
X*** 502,507 ****
X--- 520,526 ----
X extern char * Tk_NameOfCursor _ANSI_ARGS_((Cursor cursor));
X extern char * Tk_NameOfFontStruct _ANSI_ARGS_((
X XFontStruct *fontStructPtr));
X+ extern char * Tk_NameOfIcon _ANSI_ARGS_((Tk_Icon icon));
X extern char * Tk_NameOfJoinStyle _ANSI_ARGS_((int join));
X extern char * Tk_NameOfJustify _ANSI_ARGS_((Tk_Justify justify));
X extern char * Tk_NameOfRelief _ANSI_ARGS_((int relief));
X***************
X*** 568,573 ****
X--- 587,594 ----
X Tcl_Interp *interp, int argc, char **argv));
X extern int Tk_FocusCmd _ANSI_ARGS_((ClientData clientData,
X Tcl_Interp *interp, int argc, char **argv));
X+ extern int Tk_IconButtonCmd _ANSI_ARGS_((ClientData clientData,
X+ Tcl_Interp *interp, int argc, char **argv));
X extern int Tk_ListboxCmd _ANSI_ARGS_((ClientData clientData,
X Tcl_Interp *interp, int argc, char **argv));
X extern int Tk_MenuCmd _ANSI_ARGS_((ClientData clientData,
Xdiff -c old//tkConfig.c new//tkConfig.c
X*** old//tkConfig.c Mon Feb 10 14:00:53 1992
X--- new//tkConfig.c Wed Feb 19 16:41:37 1992
X***************
X*** 436,441 ****
X--- 436,459 ----
X *((Pixmap *) ptr) = new;
X break;
X }
X+ case TK_CONFIG_ICON: {
X+ Tk_Icon new, old;
X+
X+ if (uid == NULL) {
X+ new.bitmap = None;
X+ } else {
X+ new = Tk_GetIcon(interp, tkwin, uid);
X+ if (new.bitmap == None) {
X+ return TCL_ERROR;
X+ }
X+ }
X+ old = *((Tk_Icon *) ptr);
X+ if (old.bitmap != None) {
X+ Tk_FreeIcon(old);
X+ }
X+ *((Tk_Icon *) ptr) = new;
X+ break;
X+ }
X case TK_CONFIG_BORDER: {
X Tk_3DBorder new, old;
X
X***************
X*** 689,694 ****
X--- 707,721 ----
X }
X break;
X }
X+ case TK_CONFIG_ICON: {
X+ Tk_Icon icon;
X+
X+ icon = *((Tk_Icon *) ptr);
X+ if (icon.bitmap != None) {
X+ argv[4] = Tk_NameOfIcon(icon);
X+ }
X+ break;
X+ }
X case TK_CONFIG_BORDER: {
X Tk_3DBorder border = *((Tk_3DBorder *) ptr);
X if (border != NULL) {
Xdiff -c old//tkWindow.c new//tkWindow.c
X*** old//tkWindow.c Mon Feb 10 15:57:37 1992
X--- new//tkWindow.c Wed Feb 19 16:41:30 1992
X***************
X*** 111,116 ****
X--- 111,117 ----
X {"checkbutton", Tk_ButtonCmd},
X {"entry", Tk_EntryCmd},
X {"frame", Tk_FrameCmd},
X+ {"iconbutton", Tk_IconButtonCmd},
X {"label", Tk_ButtonCmd},
X {"listbox", Tk_ListboxCmd},
X {"menu", Tk_MenuCmd},
END_OF_FILE
if test 7630 -ne `wc -c <'ICONBUTTON/iconbutton.patch'`; then
echo shar: \"'ICONBUTTON/iconbutton.patch'\" unpacked with wrong size!
fi
# end of 'ICONBUTTON/iconbutton.patch'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked both archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0

Pekka Nikander

unread,
Feb 22, 1992, 10:52:32 AM2/22/92
to
In article <1992Feb21....@comp.vuw.ac.nz> Trevo...@comp.vuw.ac.nz (Trevor Lowe) writes:
> This is an iconbutton widget for Tk version 1.4.
> An iconbutton is a widget that is similar to a button widget,
> except that it displays bitmaps instead of text.

I have sent the following patches to John Ousterhoust. I have no idea
weather he will or won't include anything based on these or something
else in the next release of Tk.

As I haven't access to color X environment, I don't know weather these
patches work correctly with colors. There may well be problems with many
other X environments as well. If you use this and find any bugs, please
send me mail and I'll see what I can do.

These patches make it possible to customize "standard" Tk checkbutton and
radiobutton "icons", and add support for additional icons in all kinds Tk
buttons.

Apply the patch, define TK_BUTTON_BITMAP in your Makefile, and
recompile. The following options are added:

Command line Resource Name Resource Class Description

-bitmap bitmap Bitmap "icon"
-bitmapside bitmapSide BitmapSide where to place the
icon, on the left,
right, bottom or top
side of the text
(if there is any text)
-offbitmap offBitmap Bitmap "off" icon for radio
and checkboxes
-onbitmap onBitmap Bitmap "on" icon for radio
and checkboxes

The default value for -bitmapside is left (Athena widgets allow left
bitmap). You can use any of the values left, right, top or bottom. The
basic -bitmap should also work with labels, even though I haven't tested
it.

Tk_GetBitmap is used to retrieve Bitmaps; therefore, you should add the
@-character in the font of any bitmap file name in order to indicate that
it's a bitmap file.

Pekka Nikander Internet: p...@ajk.tele.fi -or-
Telecom Finland Pekka.N...@ajk.tele.fi
----------------------------------------------------------------
*** tkButton.c.orig Sat Jan 11 10:47:09 1992
--- tkButton.c Sat Feb 22 17:41:01 1992
***************
*** 24,29 ****
--- 24,34 ----
#include "tkConfig.h"
#include "tkInt.h"

+ #ifdef TK_BUTTON_BITMAP
+ #include <assert.h>
+ typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side;
+ #endif
+
/*


* A data structure of the following type is kept for each

* widget managed by this file:

***************
*** 59,64 ****
--- 64,88 ----
GC normalTextGC; /* GC for drawing text in normal mode. */
GC activeTextGC; /* GC for drawing text in active mode (NULL
* means use normalTextGC). */
+ #ifdef TK_BUTTON_BITMAP
+ GC normalPixmapGC; /* GC for displaying pixmap in normal mode. */
+ GC activePixmapGC; /* GC for displaying pixmap in active mode */
+
+ Pixmap pixmap; /* Pixmap to display in button, or None */
+ char *pixmapSideString; /* We don't have TK_CONFIG_SIDE... */
+ Side pixmapSide; /* Location of the pixmap, default LEFT */
+ int pixmapHeight; /* Height of the pixmap */
+ int pixmapWidth; /* Width of the pixmap */
+
+ Pixmap onPixmap; /* For radio and check buttons */
+ int onPixmapHeight;
+ int onPixmapWidth;
+ Pixmap offPixmap; /* For radio and check buttons */
+ int offPixmapHeight;
+ int offPixmapWidth;
+ int oPixmapHeight; /* Max of (onPixmapHeight, offPixMapHeight */
+ int oPixmapWidth; /* Max of (onPixmapWidth, offPixmapWidth */
+ #endif /* TK_BUTTON_BITMAP */
char *text; /* Text to display in button (malloc'ed)
* or NULL. */
int textLength; /* # of characters in text. */
***************
*** 183,188 ****
--- 207,218 ----
(char *) NULL, 0, ALL_MASK},


{TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,

(char *) NULL, 0, ALL_MASK},
+ #ifdef TK_BUTTON_BITMAP
+ {TK_CONFIG_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, Tk_Offset(Button, pixmap), ALL_MASK},
+ {TK_CONFIG_STRING, "-bitmapside", "bitmapSide", "BitmapSide",
+ DEF_BUTTON_BITMAP_SIDE, Tk_Offset(Button, pixmapSideString), ALL_MASK},
+ #endif /* TK_BUTTON_BITMAP */


{TK_CONFIG_INT, "-borderwidth", "borderWidth", "BorderWidth",

DEF_BUTTON_BORDER_WIDTH, Tk_Offset(Button, borderWidth), ALL_MASK},


{TK_CONFIG_STRING, "-command", "command", "Command",

***************
*** 195,203 ****
--- 225,253 ----
ALL_MASK},


{TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",

DEF_BUTTON_FG, Tk_Offset(Button, normalFg), ALL_MASK},
+ #ifdef TK_BUTTON_BITMAP
+ {TK_CONFIG_BITMAP, "-offbitmap", "offBitmap", "Bitmap",
+ DEF_BUTTON_OFF_BITMAP, Tk_Offset(Button, offPixmap),
+ CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
+ #ifdef TK_CONFIG_PIXMAP
+ {TK_CONFIG_PIXMAP, "-offpixmap", "offPixmap", "Pixmap",
+ DEF_BUTTON_OFF_PIXMAP, Tk_Offset(Button, offPixmap),
+ CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
+ #endif /* TK_CONFIG_PIXMAP */
+ #endif /* TK_BUTTON_BITMAP */
{TK_CONFIG_STRING, "-offvalue", "offValue", "Value",
DEF_BUTTON_OFF_VALUE, Tk_Offset(Button, offValue),
CHECK_BUTTON_MASK},
+ #ifdef TK_BUTTON_BITMAP
+ {TK_CONFIG_BITMAP, "-onbitmap", "onBitmap", "Bitmap",
+ DEF_BUTTON_ON_BITMAP, Tk_Offset(Button, onPixmap),
+ CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
+ #ifdef TK_CONFIG_PIXMAP
+ {TK_CONFIG_PIXMAP, "-onpixmap", "onPixmap", "Pixmap",
+ DEF_BUTTON_ON_PIXMAP, Tk_Offset(Button, onPixmap),
+ CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
+ #endif /* TK_CONFIG_PIXMAP */
+ #endif /* TK_BUTTON_BITMAP */
{TK_CONFIG_STRING, "-onvalue", "onValue", "Value",
DEF_BUTTON_ON_VALUE, Tk_Offset(Button, onValue),
CHECK_BUTTON_MASK},
***************
*** 205,210 ****
--- 255,267 ----
DEF_BUTTON_PADX, Tk_Offset(Button, padX), ALL_MASK},


{TK_CONFIG_INT, "-pady", "padY", "Pad",

DEF_BUTTON_PADY, Tk_Offset(Button, padY), ALL_MASK},
+ #if defined(TK_BUTTON_BITMAP) && defined(TK_CONFIG_PIXMAP)
+ {TK_CONFIG_PIXMAP, "-pixmap", "pixmap", "Pixmap",
+ DEF_BUTTON_PIXMAP, Tk_Offset(Button, pixmap), ALL_MASK},
+ /* maybe should make this non-synonym for easier database access? */
+ {TK_CONFIG_SYNONYM, "-pixmapside", "bitmapSide", (char *) NULL,
+ (char *) NULL, 0, ALL_MASK},
+ #endif


{TK_CONFIG_RELIEF, "-relief", "relief", "Relief",

DEF_BUTTON_RELIEF, Tk_Offset(Button, relief),
BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
***************
*** 556,561 ****
--- 613,633 ----
butPtr->offValue = NULL;
butPtr->command = NULL;
butPtr->flags = 0;
+ #ifdef TK_BUTTON_BITMAP
+ butPtr->activePixmapGC = None;
+ butPtr->normalPixmapGC = None;
+ butPtr->pixmap = None;
+ butPtr->pixmapSideString = NULL;
+ butPtr->pixmapSide = LEFT;
+ butPtr->pixmapHeight = 0;
+ butPtr->pixmapWidth = 0;
+ butPtr->onPixmap = None;
+ butPtr->onPixmapHeight = 0;
+ butPtr->onPixmapWidth = 0;
+ butPtr->offPixmap = None;
+ butPtr->offPixmapHeight = 0;
+ butPtr->offPixmapWidth = 0;
+ #endif

Tk_CreateEventHandler(butPtr->tkwin, ExposureMask|StructureNotifyMask,
ButtonEventProc, (ClientData) butPtr);
***************
*** 639,644 ****
--- 711,740 ----
if (butPtr->command != NULL) {
ckfree(butPtr->command);
}
+ #ifdef TK_BUTTON_BITMAP
+ #ifdef TK_CONFIG_PIXMAP
+ /* THESE WILL FAIL IF WE HAVE BOTH BITMAPS AND PIXMAPS */
+ generate syntax error on this;
+ #endif
+ if (butPtr->activePixmapGC != None) {
+ Tk_FreeGC(butPtr->activePixmapGC);
+ }
+ if (butPtr->normalPixmapGC != None) {
+ Tk_FreeGC(butPtr->normalPixmapGC);
+ }
+ if (butPtr->pixmap != None) {
+ Tk_FreeBitmap(butPtr->pixmap);
+ }
+ if (butPtr->pixmapSideString != NULL) {
+ ckfree(butPtr->pixmapSideString);
+ }
+ if (butPtr->onPixmap != None) {
+ Tk_FreeBitmap(butPtr->onPixmap);
+ }
+ if (butPtr->offPixmap != None) {
+ Tk_FreeBitmap(butPtr->offPixmap);
+ }
+ #endif
ckfree((char *) butPtr);
}

***************
*** 668,673 ****
--- 764,772 ----
Tk_3DBorder border;
int x, y, selectorWidth, relief;
register Tk_Window tkwin = butPtr->tkwin;
+ #ifdef TK_BUTTON_BITMAP
+ int window_cleared = 0;
+ #endif

butPtr->flags &= ~REDRAW_PENDING;
if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
***************
*** 687,698 ****
relief = TK_RELIEF_SUNKEN;
}

! /*
! * Draw text first, then selector, then border; if text is too
! * large for window the border will overlay it, instead of
! * vice versa.
*/

selectorWidth = 0;
if (butPtr->type == TYPE_CHECK_BUTTON) {
selectorWidth = (15*butPtr->fontPtr->ascent)/10;
--- 786,840 ----
relief = TK_RELIEF_SUNKEN;
}

! /*
! * Draw pixmap first, then text, then selector, then
! * border; if text is too large for window the
! * border will overlay it, instead of vice versa.
*/

+ if (butPtr->flags & CLEAR_NEEDED) {
+ XClearWindow(Tk_Display(tkwin), Tk_WindowId(tkwin));
+ butPtr->flags &= ~CLEAR_NEEDED;
+ #ifdef TK_BUTTON_BITMAP
+ window_cleared = 1;
+ #endif
+ }
+
+ #ifdef TK_BUTTON_BITMAP
+ if (butPtr->pixmap != None) {
+ switch (butPtr->pixmapSide) {
+ case TOP:
+ x = (Tk_Width(tkwin) - butPtr->pixmapWidth) / 2;
+ y = butPtr->borderWidth;
+ break;
+ case BOTTOM:
+ x = (Tk_Width(tkwin) - butPtr->pixmapWidth) / 2;
+ y = Tk_Height(tkwin) - butPtr->pixmapHeight - butPtr->borderWidth;
+ break;
+ case LEFT:
+ x = butPtr->borderWidth;
+ y = (Tk_Height(tkwin) - butPtr->pixmapHeight) / 2;
+ break;
+ case RIGHT:
+ x = Tk_Width(tkwin) - butPtr->pixmapWidth - butPtr->borderWidth;
+ y = (Tk_Height(tkwin) - butPtr->pixmapHeight) / 2;
+ break;
+ }
+ if (relief == TK_RELIEF_RAISED) {
+ x -= 1;
+ y -= 1;
+ } else if (relief == TK_RELIEF_SUNKEN) {
+ x += 1;
+ y += 1;
+ }
+ XCopyArea(Tk_Display(tkwin), butPtr->pixmap, Tk_WindowId(tkwin),
+ butPtr->flags & ACTIVE?
+ butPtr->activePixmapGC: butPtr->normalPixmapGC,
+ 0, 0, butPtr->pixmapWidth, butPtr->pixmapHeight,
+ x, y);
+ }
+ #endif
+
selectorWidth = 0;
if (butPtr->type == TYPE_CHECK_BUTTON) {
selectorWidth = (15*butPtr->fontPtr->ascent)/10;
***************
*** 700,709 ****
--- 842,878 ----
selectorWidth = (15*(butPtr->fontPtr->ascent
+ butPtr->fontPtr->descent))/10 - 1;
}
+ #ifdef TK_BUTTON_BITMAP
+ if (butPtr->onPixmap != None || butPtr->offPixmap != None) {
+ assert(butPtr->type == TYPE_CHECK_BUTTON ||
+ butPtr->type == TYPE_RADIO_BUTTON);
+ if (butPtr->oPixmapWidth > selectorWidth)
+ selectorWidth = butPtr->oPixmapWidth;
+ }
+ #endif
+
x = (Tk_Width(tkwin) + selectorWidth + butPtr->leftBearing
- butPtr->rightBearing)/2;
y = (Tk_Height(tkwin) + butPtr->fontPtr->ascent
- butPtr->fontPtr->descent)/2;
+ #ifdef TK_BUTTON_BITMAP
+ if (butPtr->pixmap != None) {
+ switch (butPtr->pixmapSide) {
+ case LEFT:
+ x += butPtr->pixmapWidth/2;
+ break;
+ case RIGHT:
+ x -= butPtr->pixmapWidth/2;
+ break;
+ case TOP:
+ y += butPtr->pixmapHeight/2;
+ break;
+ case BOTTOM:
+ y -= butPtr->pixmapHeight/2;
+ break;
+ }
+ }
+ #endif /* TK_BUTTON_BITMAP */
if (relief == TK_RELIEF_RAISED) {
x -= 1;
y -= 1;
***************
*** 711,723 ****
x += 1;
y += 1;
}
- if (butPtr->flags & CLEAR_NEEDED) {
- XClearWindow(Tk_Display(tkwin), Tk_WindowId(tkwin));
- butPtr->flags &= ~CLEAR_NEEDED;
- }
XDrawString(Tk_Display(tkwin), Tk_WindowId(tkwin),
gc, x, y, butPtr->text, butPtr->textLength);

if (butPtr->type == TYPE_CHECK_BUTTON) {
int dim;

--- 880,924 ----
x += 1;
y += 1;
}
XDrawString(Tk_Display(tkwin), Tk_WindowId(tkwin),
gc, x, y, butPtr->text, butPtr->textLength);

+ #ifdef TK_BUTTON_BITMAP
+ if (butPtr->onPixmap != None && butPtr->flags & SELECTED ||
+ butPtr->offPixmap != None && (butPtr->flags & SELECTED) == 0) {
+ int dim;
+ int width, height;
+
+ assert(butPtr->type == TYPE_CHECK_BUTTON ||
+ butPtr->type == TYPE_RADIO_BUTTON);
+
+ width = (butPtr->flags & SELECTED?
+ butPtr->onPixmapWidth : butPtr->offPixmapWidth);
+ height = (butPtr->flags & SELECTED?
+ butPtr->onPixmapHeight : butPtr->offPixmapHeight);
+
+ /* Find the lower left corner of pixmap area and clear it if needed */
+ dim = butPtr->oPixmapHeight;
+ x -= selectorWidth;
+ y -= (butPtr->fontPtr->ascent + dim)/2;
+ if (!window_cleared && (width < butPtr->oPixmapWidth ||
+ height < butPtr->oPixmapHeight)) {
+ XClearArea(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ x, y, butPtr->oPixmapWidth, butPtr->oPixmapHeight, 0);
+ }
+
+ /* Center the pixmap widthin the area */
+ x += (butPtr->oPixmapWidth - width) / 2;
+ y += (butPtr->oPixmapHeight - height) / 2;
+ XCopyArea(Tk_Display(tkwin),
+ butPtr->flags & SELECTED?
+ butPtr->onPixmap: butPtr->offPixmap,
+ Tk_WindowId(tkwin),
+ butPtr->flags & ACTIVE?
+ butPtr->activePixmapGC: butPtr->normalPixmapGC,
+ 0, 0, width, height, x, y);
+ } else
+ #endif
if (butPtr->type == TYPE_CHECK_BUTTON) {
int dim;

***************
*** 856,861 ****
--- 1057,1087 ----
}
butPtr->activeTextGC = newGC;
}
+ #ifdef TK_BUTTON_BITMAP
+ if (butPtr->pixmap != None
+ || butPtr->onPixmap != None
+ || butPtr->offPixmap != None) {
+ gcValues.function = GXandInverted;
+ gcValues.plane_mask = AllPlanes;
+ /* subwindow-mode not needed */
+ gcValues.graphics_exposures = False;
+ gcValues.clip_mask = None;
+ newGC = Tk_GetGC(butPtr->tkwin,
+ GCFunction|GCPlaneMask|GCGraphicsExposures|GCClipMask,
+ &gcValues);
+ if (butPtr->normalPixmapGC != None)
+ Tk_FreeGC(butPtr->normalPixmapGC);
+ butPtr->normalPixmapGC = newGC;
+
+ gcValues.function = GXor;
+ newGC = Tk_GetGC(butPtr->tkwin,
+ GCFunction|GCPlaneMask|GCGraphicsExposures|GCClipMask,
+ &gcValues);
+ if (butPtr->activePixmapGC != None)
+ Tk_FreeGC(butPtr->activePixmapGC);
+ butPtr->activePixmapGC = newGC;
+ }
+ #endif

if (butPtr->padX == -1) {
butPtr->padX = butPtr->fontPtr->ascent/2;
***************
*** 865,870 ****
--- 1091,1155 ----
butPtr->padY = butPtr->fontPtr->ascent/4;
}

+ #ifdef TK_BUTTON_BITMAP
+ if (butPtr->pixmap != None) {
+ Window dummy1;
+ int dummy2;
+ unsigned int dummy3;
+ int len, c;
+
+ XGetGeometry(Tk_Display(butPtr->tkwin), butPtr->pixmap,
+ &dummy1, &dummy2, &dummy2,
+ &(butPtr->pixmapWidth), &(butPtr->pixmapHeight),
+ &dummy3, &dummy3);
+
+ c = butPtr->pixmapSideString[0];
+ len = strlen(butPtr->pixmapSideString);
+
+ if (c == 'b' && strncmp(butPtr->pixmapSideString, "bottom", len) == 0)
+ butPtr->pixmapSide = BOTTOM;
+ else if (c == 't' && strncmp(butPtr->pixmapSideString,"top",len) == 0)
+ butPtr->pixmapSide = TOP;
+ else if (c == 'l' && strncmp(butPtr->pixmapSideString,"left",len) == 0)
+ butPtr->pixmapSide = LEFT;
+ else if (c == 'r' && strncmp(butPtr->pixmapSideString,"right",len)== 0)
+ butPtr->pixmapSide = RIGHT;
+ else {
+ sprintf(interp->result,
+ "bad pixmapside \"%.50s\": must be top, bottom, left or right",
+ butPtr->pixmapSideString);
+ return TCL_ERROR;
+ }
+ }
+ if (butPtr->onPixmap != None) {
+ Window dummy1;
+ int dummy2;
+ unsigned int dummy3;
+
+ XGetGeometry(Tk_Display(butPtr->tkwin), butPtr->onPixmap,
+ &dummy1, &dummy2, &dummy2,
+ &(butPtr->onPixmapWidth), &(butPtr->onPixmapHeight),
+ &dummy3, &dummy3);
+ butPtr->oPixmapWidth = butPtr->onPixmapWidth;
+ butPtr->oPixmapHeight = butPtr->onPixmapHeight;
+ }
+ if (butPtr->offPixmap != None) {
+ Window dummy1;
+ int dummy2;
+ unsigned int dummy3;
+
+ XGetGeometry(Tk_Display(butPtr->tkwin), butPtr->offPixmap,
+ &dummy1, &dummy2, &dummy2,
+ &(butPtr->offPixmapWidth), &(butPtr->offPixmapHeight),
+ &dummy3, &dummy3);
+
+ if (butPtr->offPixmapWidth > butPtr->oPixmapWidth)
+ butPtr->oPixmapWidth = butPtr->offPixmapWidth;
+ if (butPtr->offPixmapHeight > butPtr->oPixmapHeight)
+ butPtr->oPixmapHeight = butPtr->offPixmapHeight;
+ }
+ #endif /* TK_BUTTON_BITMAP */
+
if (butPtr->type >= TYPE_CHECK_BUTTON) {
char *value;

***************
*** 936,946 ****
--- 1221,1268 ----
extraWidth += (15*(butPtr->fontPtr->ascent + butPtr->fontPtr->descent))
/ 10;
}
+ #ifdef TK_BUTTON_BITMAP
+ {
+ int width, height, dim;
+
+ dim = butPtr->fontPtr->ascent + butPtr->fontPtr->descent;
+
+ if (butPtr->onPixmap != None || butPtr->offPixmap != None) {
+ if (butPtr->oPixmapWidth > extraWidth) {
+ extraWidth = butPtr->oPixmapWidth;
+ }
+ if (butPtr->oPixmapHeight > dim) {
+ dim = butPtr->oPixmapHeight;
+ }
+ }
+
+
+ width = butPtr->rightBearing + butPtr->leftBearing
+ + 2*butPtr->padX
+ + 2*butPtr->borderWidth
+ + extraWidth;
+ height = dim + 2*butPtr->padY + 2*butPtr->borderWidth;
+
+ if (butPtr->pixmap != None) {
+ if (butPtr->pixmapSide == LEFT || butPtr->pixmapSide == RIGHT) {
+ width += butPtr->pixmapHeight;
+ if (height < butPtr->pixmapHeight + 2*butPtr->borderWidth)
+ height = butPtr->pixmapHeight + 2*butPtr->borderWidth;
+ } else {
+ if (width < butPtr->pixmapWidth + 2*butPtr->borderWidth)
+ width = butPtr->pixmapWidth + 2*butPtr->borderWidth;
+ height += butPtr->pixmapHeight;
+ }
+ }
+ Tk_GeometryRequest(butPtr->tkwin, width, height);
+ }
+ #else
Tk_GeometryRequest(butPtr->tkwin, butPtr->rightBearing
+ butPtr->leftBearing + 2*butPtr->padX
+ 2*butPtr->borderWidth + extraWidth,
butPtr->fontPtr->ascent + butPtr->fontPtr->descent
+ 2*butPtr->padY + 2*butPtr->borderWidth);
+ #endif
Tk_SetInternalBorder(butPtr->tkwin, butPtr->borderWidth);

/*
*** default.h.orig Sat Jan 11 10:47:03 1992
--- default.h Sat Jan 11 13:07:05 1992
***************
*** 49,54 ****
--- 49,64 ----
#define DEF_BUTTON_ACTIVE_FG_MONO WHITE
#define DEF_BUTTON_BG_COLOR BISQUE1
#define DEF_BUTTON_BG_MONO WHITE
+ #ifdef TK_BUTTON_BITMAP
+ #define DEF_BUTTON_BITMAP ((char *) NULL)
+ #define DEF_BUTTON_BITMAP_SIDE "left"
+ #define DEF_BUTTON_OFF_BITMAP ((char *) NULL)
+ #define DEF_BUTTON_ON_BITMAP ((char *) NULL)
+ #ifdef TK_CONFIG_PIXMAP
+ #define DEF_BUTTON_ON_PIXMAP ((char *) NULL)
+ #define DEF_BUTTON_OFF_PIXMAP ((char *) NULL)
+ #endif /* TK_CONFIG_PIXMAP */
+ #endif /* TK_BUTTON_BITMAP */
#define DEF_BUTTON_BORDER_WIDTH "2"
#define DEF_BUTTON_COMMAND ((char *) NULL)
#define DEF_BUTTON_FONT "*-Helvetica-Bold-R-Normal-*-120-*"
----------------------------------------------------------------
End of patch.
--
Pekka Nikander

0 new messages