Files
cpython-source-deps/generic/tixDiStyle.c
2017-05-22 16:16:49 -05:00

1071 lines
30 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* tixDiStyle.c --
*
* This file implements the "Display Item Styles" in the Tix library.
*
* Copyright (c) 1993-1999 Ioi Kim Lam.
* Copyright (c) 2000-2001 Tix Project Group.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* $Id: tixDiStyle.c,v 1.6 2004/03/28 02:44:56 hobbs Exp $
*/
#include <tixPort.h>
#include <tixInt.h>
typedef struct StyleLink {
Tix_DItemInfo * diTypePtr;
Tix_DItemStyle* stylePtr;
struct StyleLink * next;
} StyleLink;
typedef struct StyleInfo {
Tix_StyleTemplate * tmplPtr;
Tix_StyleTemplate tmpl;
StyleLink * linkHead;
} StyleInfo;
static int DItemStyleParseProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, Tk_Window tkwin,
CONST84 char *value,char *widRec, int offset));
static char * DItemStylePrintProc _ANSI_ARGS_((
ClientData clientData, Tk_Window tkwin,
char *widRec, int offset,
Tcl_FreeProc **freeProcPtr));
static Tix_DItemStyle* FindDefaultStyle _ANSI_ARGS_((
Tix_DItemInfo * diTypePtr, Tk_Window tkwin));
static Tix_DItemStyle* FindStyle _ANSI_ARGS_((
CONST84 char *styleName, Tcl_Interp *interp));
static Tix_DItemStyle* GetDItemStyle _ANSI_ARGS_((
Tix_DispData * ddPtr, Tix_DItemInfo * diTypePtr,
CONST84 char *styleName, int *isNew_ret));
static void ListAdd _ANSI_ARGS_((Tix_DItemStyle * stylePtr,
Tix_DItem *iPtr));
static void ListDelete _ANSI_ARGS_((Tix_DItemStyle * stylePtr,
Tix_DItem *iPtr));
static void ListDeleteAll _ANSI_ARGS_((Tix_DItemStyle * stylePtr));
static void StyleCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static int StyleCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, CONST84 char **argv));
static int StyleConfigure _ANSI_ARGS_((Tcl_Interp *interp,
Tix_DItemStyle* stylePtr, int argc,
CONST84 char **argv, int flags));
static void StyleDestroy _ANSI_ARGS_((ClientData clientData));
static void DeleteStyle _ANSI_ARGS_((Tix_DItemStyle * stylePtr));
static void DefWindowStructureProc _ANSI_ARGS_((
ClientData clientData, XEvent *eventPtr));
static void RefWindowStructureProc _ANSI_ARGS_((
ClientData clientData, XEvent *eventPtr));
static void SetDefaultStyle _ANSI_ARGS_((Tix_DItemInfo *diTypePtr,
Tk_Window tkwin, Tix_DItemStyle * stylePtr));
static TIX_DECLARE_SUBCMD(StyleConfigCmd);
static TIX_DECLARE_SUBCMD(StyleCGetCmd);
static TIX_DECLARE_SUBCMD(StyleDeleteCmd);
static Tcl_HashTable defaultTable;
/*
* This macro returns a hashtable to convert from style names (such as
* "tixStyle0") to Tix_DItemStyle structures.
*/
#define GetStyleTable(x) \
(TixGetHashTable((x), "tixStyleTab", NULL, TCL_STRING_KEYS))
/*
*--------------------------------------------------------------
*
* TixInitializeDisplayItems --
*
* Initializes the Display Item subsystem.
*
* Results:
* Nothing
*
* Side effects:
* Built-in Display Types styles are created.
*
*--------------------------------------------------------------
*/
void
TixInitializeDisplayItems()
{
static int inited = 0;
if (!inited) {
inited = 1;
Tcl_InitHashTable(&defaultTable, TCL_ONE_WORD_KEYS);
Tix_AddDItemType(&tix_ImageTextItemType);
Tix_AddDItemType(&tix_TextItemType);
Tix_AddDItemType(&tix_WindowItemType);
Tix_AddDItemType(&tix_ImageItemType);
}
}
/*
*--------------------------------------------------------------
*
* TixDItemStyleFree --
*
* When an item does not need a style anymore (when the item
* is destroyed, e.g.), it must call this procedute to free the
* style).
*
* Results:
* Nothing
*
* Side effects:
* The item is freed from the list of attached items in the style.
* Also, the style will be freed if it was already destroyed and
* it has no more items attached to it.
*
*--------------------------------------------------------------
*/
void
TixDItemStyleFree(iPtr, stylePtr)
Tix_DItem *iPtr;
Tix_DItemStyle * stylePtr;
{
ListDelete(stylePtr, iPtr);
}
/*
*--------------------------------------------------------------
*
* Tix_ItemStyleCmd --
*
* This procedure is invoked to process the "tixItemStyle" Tcl
* command.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* A new widget is created and configured.
*
*--------------------------------------------------------------
*/
int
Tix_ItemStyleCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
CONST84 char **argv; /* Argument strings. */
{
Tix_DItemInfo * diTypePtr;
Tk_Window tkwin = (Tk_Window)clientData;
CONST84 char * styleName = NULL;
Tix_DispData dispData;
char buff[16 + TCL_INTEGER_SPACE];
int i, n;
static int counter = 0;
Tix_DItemStyle * stylePtr;
if (argc < 2) {
return Tix_ArgcError(interp, argc, argv, 1,
"itemtype ?option value ...");
}
if ((diTypePtr=Tix_GetDItemType(interp, argv[1])) == NULL) {
return TCL_ERROR;
}
/*
* Parse the -refwindow option: this tells the style to use this
* window to query the default values for background, foreground
* etc. Usually, you should set the -refwindow to the window that
* holds the display items which are controlled by this style.
*/
if (argc > 2) {
size_t len;
if (argc %2 != 0) {
Tcl_AppendResult(interp, "value for \"", argv[argc-1],
"\" missing", NULL);
return TCL_ERROR;
}
for (n=i=2; i<argc; i+=2) {
len = strlen(argv[i]);
if (strncmp(argv[i], "-refwindow", len) == 0) {
if ((tkwin=Tk_NameToWindow(interp,argv[i+1],tkwin)) == NULL) {
return TCL_ERROR;
}
continue;
}
if (strncmp(argv[i], "-stylename", len) == 0) {
styleName = argv[i+1];
if (FindStyle(styleName, interp) != NULL) {
Tcl_AppendResult(interp, "style \"", argv[i+1],
"\" already exists", NULL);
return TCL_ERROR;
}
continue;
}
if (n!=i) {
argv[n] = argv[i];
argv[n+1] = argv[i+1];
}
n+=2;
}
argc = n;
}
if (styleName == NULL) {
/*
* No name is given, we'll make a unique name by default. The
* following loop hopefully will not run forever (unless
* the user has created more than 4 billion styles with default
* names ...:-)
*/
while (1) {
sprintf(buff, "tixStyle%d", counter++);
if (Tcl_FindHashEntry(GetStyleTable(interp), buff) == NULL) {
styleName = buff;
break;
}
}
}
dispData.interp = interp;
dispData.display = Tk_Display(tkwin);
dispData.tkwin = tkwin;
if ((stylePtr = GetDItemStyle(&dispData, diTypePtr,
styleName, NULL)) == NULL) {
return TCL_ERROR;
}
if (StyleConfigure(interp, stylePtr, argc-2, argv+2, 0) != TCL_OK) {
DeleteStyle(stylePtr);
return TCL_ERROR;
}
Tk_CreateEventHandler(tkwin, StructureNotifyMask,
RefWindowStructureProc, (ClientData)stylePtr);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, styleName, NULL);
return TCL_OK;
}
static int
StyleCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
CONST84 char **argv;
{
int code;
static Tix_SubCmdInfo subCmdInfo[] = {
{TIX_DEFAULT_LEN, "cget", 1, 1, StyleCGetCmd,
"option"},
{TIX_DEFAULT_LEN, "configure", 0, TIX_VAR_ARGS, StyleConfigCmd,
"?option? ?value? ?option value ... ?"},
{TIX_DEFAULT_LEN, "delete", 0, 0, StyleDeleteCmd,
""},
};
static Tix_CmdInfo cmdInfo = {
Tix_ArraySize(subCmdInfo), 1, TIX_VAR_ARGS, "?option? arg ?arg ...?",
};
Tk_Preserve(clientData);
code = Tix_HandleSubCmds(&cmdInfo, subCmdInfo, clientData,
interp, argc, argv);
Tk_Release(clientData);
return code;
}
/*----------------------------------------------------------------------
* "cget" sub command
*----------------------------------------------------------------------
*/
static int
StyleCGetCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
CONST84 char **argv; /* Argument strings. */
{
Tix_DItemStyle* stylePtr= (Tix_DItemStyle*) clientData;
return Tk_ConfigureValue(interp, stylePtr->base.tkwin,
stylePtr->base.diTypePtr->styleConfigSpecs,
(char *)stylePtr, argv[0], 0);
}
/*----------------------------------------------------------------------
* "configure" sub command
*----------------------------------------------------------------------
*/
static int
StyleConfigCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
CONST84 char **argv; /* Argument strings. */
{
Tix_DItemStyle* stylePtr= (Tix_DItemStyle*) clientData;
if (argc == 0) {
return Tk_ConfigureInfo(interp, stylePtr->base.tkwin,
stylePtr->base.diTypePtr->styleConfigSpecs,
(char *)stylePtr, (char *) NULL, 0);
} else if (argc == 1) {
return Tk_ConfigureInfo(interp, stylePtr->base.tkwin,
stylePtr->base.diTypePtr->styleConfigSpecs,
(char *)stylePtr, argv[0], 0);
} else {
return StyleConfigure(interp, stylePtr, argc, argv,
TK_CONFIG_ARGV_ONLY);
}
}
/*----------------------------------------------------------------------
* "delete" sub command
*----------------------------------------------------------------------
*/
static int
StyleDeleteCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
CONST84 char **argv; /* Argument strings. */
{
Tix_DItemStyle* stylePtr= (Tix_DItemStyle*) clientData;
if (stylePtr->base.flags & TIX_STYLE_DEFAULT) {
Tcl_AppendResult(interp, "Cannot delete default item style",
NULL);
return TCL_ERROR;
}
DeleteStyle(stylePtr);
return TCL_OK;
}
static int
StyleConfigure(interp, stylePtr, argc, argv, flags)
Tcl_Interp *interp; /* Used for error reporting. */
Tix_DItemStyle* stylePtr; /* Information about the style; may or may
* not already have values for some fields. */
int argc; /* Number of valid entries in argv. */
CONST84 char **argv; /* Arguments. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
Tix_DItemInfo * diTypePtr = stylePtr->base.diTypePtr;
if (diTypePtr->styleConfigureProc(stylePtr, argc, argv, flags) != TCL_OK) {
return TCL_ERROR;
}
return TCL_OK;
}
/*----------------------------------------------------------------------
* StyleDestroy --
*
* Destroy a display style.
*----------------------------------------------------------------------
*/
static void
StyleDestroy(clientData)
ClientData clientData;
{
Tix_DItemStyle* stylePtr= (Tix_DItemStyle*) clientData;
int i;
if ((stylePtr->base.flags & TIX_STYLE_DEFAULT)) {
/*
* If this is the default style for the display items, we
* can't tell the display items that it has lost its style,
* otherwise the ditem will just attempt to create the default
* style again, and we will go into an infinite loop
*/
if (stylePtr->base.refCount != 0) {
/*
* If the refcount is not zero, this style will NOT be
* destroyed. The real destroy will be triggered if all
* DItems associated with this style is destroyed (in the
* ListDelete() function).
*
* If a widget is destroyed, it is the responsibility of the
* widget writer to delete all DItems associated with this
* widget. We can discover memory leak if the widget is
* destroyed but some default styles associated with it still
* exist
*/
return;
}
} else {
stylePtr->base.refCount = 0;
}
Tcl_DeleteHashTable(&stylePtr->base.items);
ckfree((char*)stylePtr->base.name);
for (i=0; i<4; i++) {
if (stylePtr->base.colors[i].backGC != None) {
Tk_FreeGC(Tk_Display(stylePtr->base.tkwin),
stylePtr->base.colors[i].backGC);
}
if (stylePtr->base.colors[i].foreGC != None) {
Tk_FreeGC(Tk_Display(stylePtr->base.tkwin),
stylePtr->base.colors[i].foreGC);
}
if (stylePtr->base.colors[i].anchorGC != None) {
Tk_FreeGC(Tk_Display(stylePtr->base.tkwin),
stylePtr->base.colors[i].anchorGC);
}
}
stylePtr->base.diTypePtr->styleFreeProc(stylePtr);
}
static void
StyleCmdDeletedProc(clientData)
ClientData clientData;
{
Tix_DItemStyle * stylePtr = (Tix_DItemStyle *)clientData;
stylePtr->base.styleCmd = NULL;
if (stylePtr->base.flags & TIX_STYLE_DEFAULT) {
/*
* Don't do anything
* ToDo: maybe should give a background warning:
*/
} else {
DeleteStyle(stylePtr);
}
}
static void
DeleteStyle(stylePtr)
Tix_DItemStyle * stylePtr;
{
Tcl_HashEntry * hashPtr;
if (!(stylePtr->base.flags & TIX_STYLE_DELETED)) {
stylePtr->base.flags |= TIX_STYLE_DELETED;
/*
* Delete the Tcl command of this style
*/
if (stylePtr->base.styleCmd != NULL) {
Tcl_DeleteCommand(stylePtr->base.interp,
Tcl_GetCommandName(stylePtr->base.interp,
stylePtr->base.styleCmd));
}
/*
* Remove info about this style from the hash table.
*/
hashPtr = Tcl_FindHashEntry(GetStyleTable(stylePtr->base.interp),
stylePtr->base.name);
if (hashPtr != NULL) {
Tcl_DeleteHashEntry(hashPtr);
}
ListDeleteAll(stylePtr);
/*
* Make sure the event handler is removed. Otherwise we'd crash
* when the interpreter exits.
*/
Tk_DeleteEventHandler(stylePtr->base.tkwin, StructureNotifyMask,
RefWindowStructureProc, (ClientData)stylePtr);
/*
* Schedule it to be free'd
*/
Tk_EventuallyFree((ClientData)stylePtr, (Tix_FreeProc *)StyleDestroy);
}
}
/*
*----------------------------------------------------------------------
* FindDefaultStyle --
*
* Return the default style of the given type of ditem for the
* given tkwin, if such a default style exists.
*
* Results:
* Pointer to the default style or NULL.
*
* Side effects:
* None.
*----------------------------------------------------------------------
*/
static Tix_DItemStyle*
FindDefaultStyle(diTypePtr, tkwin)
Tix_DItemInfo * diTypePtr;
Tk_Window tkwin;
{
Tcl_HashEntry *hashPtr;
StyleInfo * infoPtr;
StyleLink * linkPtr;
if ((hashPtr=Tcl_FindHashEntry(&defaultTable, (char*)tkwin)) == NULL) {
return NULL;
}
infoPtr = (StyleInfo *)Tcl_GetHashValue(hashPtr);
for (linkPtr = infoPtr->linkHead; linkPtr; linkPtr=linkPtr->next) {
if (linkPtr->diTypePtr == diTypePtr) {
return linkPtr->stylePtr;
}
}
return NULL;
}
static void SetDefaultStyle(diTypePtr, tkwin, stylePtr)
Tix_DItemInfo * diTypePtr;
Tk_Window tkwin;
Tix_DItemStyle * stylePtr;
{
Tcl_HashEntry *hashPtr;
StyleInfo * infoPtr;
StyleLink * newPtr;
int isNew;
newPtr = (StyleLink *)ckalloc(sizeof(StyleLink));
newPtr->diTypePtr = diTypePtr;
newPtr->stylePtr = stylePtr;
hashPtr = Tcl_CreateHashEntry(&defaultTable, (char*)tkwin, &isNew);
if (!isNew) {
infoPtr = (StyleInfo *)Tcl_GetHashValue(hashPtr);
if (infoPtr->tmplPtr) {
if (diTypePtr->styleSetTemplateProc != NULL) {
diTypePtr->styleSetTemplateProc(stylePtr,
infoPtr->tmplPtr);
}
}
} else {
infoPtr = (StyleInfo *)ckalloc(sizeof(StyleInfo));
infoPtr->linkHead = NULL;
infoPtr->tmplPtr = NULL;
Tk_CreateEventHandler(tkwin, StructureNotifyMask,
DefWindowStructureProc, (ClientData)tkwin);
Tcl_SetHashValue(hashPtr, (char*)infoPtr);
}
newPtr->next = infoPtr->linkHead;
infoPtr->linkHead = newPtr;
}
/*
*----------------------------------------------------------------------
* TixGetDefaultDItemStyle --
*
* Gets the default style for an item if the application doesn't
* explicitly give it an style with the -style switch.
*
* Results:
* The default style.
*
* Side effects:
*
*----------------------------------------------------------------------
*/
Tix_DItemStyle*
TixGetDefaultDItemStyle(ddPtr, diTypePtr, iPtr, oldStylePtr)
Tix_DispData * ddPtr; /* Info about the display. */
Tix_DItemInfo * diTypePtr; /* Info about the DItem type. */
Tix_DItem *iPtr; /* Get default style for this DItem. */
Tix_DItemStyle* oldStylePtr; /* ?? */
{
Tcl_DString dString;
Tix_DItemStyle* stylePtr;
int isNew;
stylePtr = FindDefaultStyle(diTypePtr, ddPtr->tkwin);
if (stylePtr == NULL) {
/*
* Format default name for this style+window
*/
Tcl_DStringInit(&dString);
Tcl_DStringAppend(&dString, "style", 5);
Tcl_DStringAppend(&dString, Tk_PathName(ddPtr->tkwin),
(int) strlen(Tk_PathName(ddPtr->tkwin)));
Tcl_DStringAppend(&dString, ":", 1);
Tcl_DStringAppend(&dString, diTypePtr->name,
(int) strlen(diTypePtr->name));
/*
* Create the new style
*/
stylePtr = GetDItemStyle(ddPtr, diTypePtr, dString.string, &isNew);
if (isNew) {
diTypePtr->styleConfigureProc(stylePtr, 0, NULL, 0);
stylePtr->base.flags |= TIX_STYLE_DEFAULT;
}
SetDefaultStyle(diTypePtr, ddPtr->tkwin, stylePtr);
Tcl_DStringFree(&dString);
}
if (oldStylePtr) {
ListDelete(oldStylePtr, iPtr);
}
ListAdd(stylePtr, iPtr);
return stylePtr;
}
void Tix_SetDefaultStyleTemplate(tkwin, tmplPtr)
Tk_Window tkwin;
Tix_StyleTemplate * tmplPtr;
{
Tcl_HashEntry * hashPtr;
StyleInfo * infoPtr;
StyleLink * linkPtr;
int isNew;
hashPtr=Tcl_CreateHashEntry(&defaultTable, (char*)tkwin, &isNew);
if (!isNew) {
infoPtr = (StyleInfo *)Tcl_GetHashValue(hashPtr);
infoPtr->tmplPtr = &infoPtr->tmpl;
infoPtr->tmpl = *tmplPtr;
for (linkPtr = infoPtr->linkHead; linkPtr; linkPtr=linkPtr->next) {
if (linkPtr->diTypePtr->styleSetTemplateProc != NULL) {
linkPtr->diTypePtr->styleSetTemplateProc(linkPtr->stylePtr,
tmplPtr);
}
}
} else {
infoPtr = (StyleInfo *)ckalloc(sizeof(StyleInfo));
infoPtr->linkHead = NULL;
infoPtr->tmplPtr = &infoPtr->tmpl;
infoPtr->tmpl = *tmplPtr;
Tk_CreateEventHandler(tkwin, StructureNotifyMask,
DefWindowStructureProc, (ClientData)tkwin);
Tcl_SetHashValue(hashPtr, (char*)infoPtr);
}
}
/*
*----------------------------------------------------------------------
* GetDItemStyle --
*
* Returns an ItemStyle with the given name.
*
* Results:
* Pointer to the given Tix_DItsmStyle.
*
* Side effects:
* If the style doesn't already exist, it is allocated.
*----------------------------------------------------------------------
*/
static Tix_DItemStyle*
GetDItemStyle(ddPtr, diTypePtr, styleName, isNew_ret)
Tix_DispData * ddPtr;
Tix_DItemInfo * diTypePtr;
CONST84 char * styleName;
int * isNew_ret;
{
Tcl_HashEntry *hashPtr;
int isNew, i;
Tix_DItemStyle * stylePtr;
hashPtr = Tcl_CreateHashEntry(GetStyleTable(ddPtr->interp),
styleName, &isNew);
if (!isNew) {
stylePtr = (Tix_DItemStyle *)Tcl_GetHashValue(hashPtr);
} else {
stylePtr = diTypePtr->styleCreateProc(ddPtr->interp,
ddPtr->tkwin, diTypePtr, (char *) styleName);
stylePtr->base.styleCmd = Tcl_CreateCommand(ddPtr->interp,
styleName, StyleCmd, (ClientData)stylePtr,
StyleCmdDeletedProc);
stylePtr->base.interp = ddPtr->interp;
stylePtr->base.tkwin = ddPtr->tkwin;
stylePtr->base.diTypePtr = diTypePtr;
stylePtr->base.name = tixStrDup(styleName);
stylePtr->base.pad[0] = 0;
stylePtr->base.pad[1] = 0;
stylePtr->base.anchor = TK_ANCHOR_CENTER;
stylePtr->base.refCount = 0;
stylePtr->base.flags = 0;
for (i=0; i<4; i++) {
stylePtr->base.colors[i].bg = NULL;
stylePtr->base.colors[i].fg = NULL;
stylePtr->base.colors[i].backGC= None;
stylePtr->base.colors[i].foreGC = None;
stylePtr->base.colors[i].anchorGC = None;
}
Tcl_InitHashTable(&stylePtr->base.items, TCL_ONE_WORD_KEYS);
Tcl_SetHashValue(hashPtr, (char*)stylePtr);
}
if (isNew_ret != NULL) {
* isNew_ret = isNew;
}
return stylePtr;
}
static Tix_DItemStyle *
FindStyle(styleName, interp)
CONST84 char *styleName;
Tcl_Interp *interp; /* Current interpreter. */
{
Tix_DItemStyle* retval = NULL;
Tcl_HashEntry *hashPtr;
if ((hashPtr=Tcl_FindHashEntry(GetStyleTable(interp), styleName))!= NULL) {
retval = (Tix_DItemStyle *)Tcl_GetHashValue(hashPtr);
}
return retval;
}
/*----------------------------------------------------------------------
* TixDItemStyleChanged --
*
* Tell each Ditem that are affected by this style that the style
* has changed. The Ditems will respond by updating their
* attributes according to the new values of the style.
*----------------------------------------------------------------------
*/
void
TixDItemStyleChanged(diTypePtr, stylePtr)
Tix_DItemInfo * diTypePtr;
Tix_DItemStyle * stylePtr;
{
Tcl_HashSearch hashSearch;
Tcl_HashEntry *hashPtr;
Tix_DItem * iPtr;
for (hashPtr = Tcl_FirstHashEntry(&stylePtr->base.items, &hashSearch);
hashPtr;
hashPtr = Tcl_NextHashEntry(&hashSearch)) {
iPtr = (Tix_DItem *)Tcl_GetHashValue(hashPtr);
diTypePtr->styleChangedProc(iPtr);
}
}
/*----------------------------------------------------------------------
* ListAdd --
*
* Add an item to the list of items affected by a style.
*----------------------------------------------------------------------
*/
static void
ListAdd(stylePtr, iPtr)
Tix_DItemStyle * stylePtr;
Tix_DItem *iPtr;
{
Tcl_HashEntry *hashPtr;
int isNew;
hashPtr = Tcl_CreateHashEntry(&stylePtr->base.items, (char*)iPtr, &isNew);
if (!isNew) {
panic("DItem is already associated with style");
} else {
Tcl_SetHashValue(hashPtr, (char*)iPtr);
}
++ stylePtr->base.refCount;
}
static void
ListDelete(stylePtr, iPtr)
Tix_DItemStyle * stylePtr;
Tix_DItem *iPtr;
{
Tcl_HashEntry *hashPtr;
hashPtr = Tcl_FindHashEntry(&stylePtr->base.items, (char*)iPtr);
if (hashPtr == NULL) {
panic("DItem is not associated with style");
}
Tcl_DeleteHashEntry(hashPtr);
stylePtr->base.refCount--;
if ((stylePtr->base.refCount == 0) &&
(stylePtr->base.flags & TIX_STYLE_DELETED) &&
(stylePtr->base.flags & TIX_STYLE_DEFAULT)) {
Tk_EventuallyFree((ClientData)stylePtr, (Tix_FreeProc *)StyleDestroy);
}
}
static void
ListDeleteAll(stylePtr)
Tix_DItemStyle * stylePtr;
{
Tcl_HashSearch hashSearch;
Tcl_HashEntry *hashPtr;
Tix_DItem * iPtr;
for (hashPtr = Tcl_FirstHashEntry(&stylePtr->base.items, &hashSearch);
hashPtr;
hashPtr = Tcl_NextHashEntry(&hashSearch)) {
iPtr = (Tix_DItem *)Tcl_GetHashValue(hashPtr);
if (stylePtr->base.diTypePtr->lostStyleProc != NULL) {
stylePtr->base.diTypePtr->lostStyleProc(iPtr);
}
Tcl_DeleteHashEntry(hashPtr);
}
}
/*
*--------------------------------------------------------------
*
* DefWindowStructureProc --
*
* This procedure is invoked whenever StructureNotify events
* occur for a window that has some default style(s) associated with it
*
* Results:
* None.
*
* Side effects:
* The style(s) associated with this window will all be deleted.
*
*--------------------------------------------------------------
*/
static void
DefWindowStructureProc(clientData, eventPtr)
ClientData clientData; /* Pointer to record describing window item. */
XEvent *eventPtr; /* Describes what just happened. */
{
Tk_Window tkwin = (Tk_Window)clientData;
Tcl_HashEntry *hashPtr;
StyleInfo * infoPtr;
StyleLink * linkPtr, *toFree;
if (eventPtr->type != DestroyNotify) {
return;
}
if ((hashPtr=Tcl_FindHashEntry(&defaultTable, (char*)tkwin)) == NULL) {
return;
}
infoPtr = (StyleInfo *)Tcl_GetHashValue(hashPtr);
for (linkPtr = infoPtr->linkHead; linkPtr; ) {
toFree = linkPtr;
linkPtr=linkPtr->next;
DeleteStyle(toFree->stylePtr);
ckfree((char*)toFree);
}
ckfree((char*)infoPtr);
Tcl_DeleteHashEntry(hashPtr);
}
/*
*--------------------------------------------------------------
*
* RefWindowStructureProc --
*
* This procedure is invoked when the refwindow of a non-default
* style is deleted.
*
* Results:
* None.
*
* Side effects:
* The style is deleted.
*
*--------------------------------------------------------------
*/
static void
RefWindowStructureProc(clientData, eventPtr)
ClientData clientData; /* Pointer to record describing window item. */
XEvent *eventPtr; /* Describes what just happened. */
{
Tix_DItemStyle * stylePtr = (Tix_DItemStyle *)clientData;
if (eventPtr->type == DestroyNotify) {
/*
* If some DItems are still associated with this window, they
* will receive a "LostStyle" notification.
*/
DeleteStyle(stylePtr);
}
}
/*----------------------------------------------------------------------
*
* The Tix Customed Config Options
*
*----------------------------------------------------------------------
*/
/*
* The global data structures to use in widget configSpecs arrays
*
* These are declared in <tix.h>
*/
Tk_CustomOption tixConfigItemStyle = {
DItemStyleParseProc, DItemStylePrintProc, 0,
};
/*----------------------------------------------------------------------
* DItemStyleParseProc --
*
* Parse the text string and store the Tix_DItemStyleType information
* inside the widget record.
*----------------------------------------------------------------------
*/
static int DItemStyleParseProc(clientData, interp, tkwin, value, widRec,offset)
ClientData clientData;
Tcl_Interp *interp;
Tk_Window tkwin;
CONST84 char *value;
char *widRec; /* Must point to a valid Tix_DItem struct */
int offset;
{
Tix_DItem * iPtr = (Tix_DItem *)widRec;
Tix_DItemStyle ** ptr = (Tix_DItemStyle **)(widRec + offset);
Tix_DItemStyle * oldPtr = *ptr;
Tix_DItemStyle * newPtr;
if (value == NULL || strlen(value) == 0) {
/*
* User gives a NULL string -- meaning he wants the default
* style
*/
if (oldPtr && oldPtr->base.flags & TIX_STYLE_DEFAULT) {
/*
* This ditem is already associated with a default style. Let's
* keep it.
*/
newPtr = oldPtr;
} else {
if (oldPtr) {
ListDelete(oldPtr, iPtr);
}
newPtr = NULL;
}
} else {
if ((newPtr = FindStyle(value, interp)) == NULL) {
goto not_found;
}
if (newPtr->base.flags & TIX_STYLE_DELETED) {
goto not_found;
}
if (newPtr->base.diTypePtr != iPtr->base.diTypePtr) {
Tcl_AppendResult(interp, "Style type mismatch ",
"Needed ", iPtr->base.diTypePtr->name, " style but got ",
newPtr->base.diTypePtr->name, " style", NULL);
return TCL_ERROR;
}
if (oldPtr != newPtr) {
if (oldPtr != NULL) {
ListDelete(oldPtr, iPtr);
}
ListAdd(newPtr, iPtr);
}
}
*ptr = newPtr;
return TCL_OK;
not_found:
Tcl_AppendResult(interp, "Display style \"", value,
"\" not found", NULL);
return TCL_ERROR;
}
static char *DItemStylePrintProc(clientData, tkwin, widRec,offset, freeProcPtr)
ClientData clientData;
Tk_Window tkwin;
char *widRec;
int offset;
Tcl_FreeProc **freeProcPtr;
{
Tix_DItemStyle *stylePtr = *((Tix_DItemStyle**)(widRec+offset));
if (stylePtr != NULL) {
return stylePtr->base.name;
} else {
return 0;
}
}
void
TixDItemStyleConfigureGCs(style)
Tix_DItemStyle *style;
{
TixColorStyle * stylePtr = (TixColorStyle *)style;
XGCValues gcValues;
GC newGC;
int i;
gcValues.graphics_exposures = False;
for (i=0; i<4; i++) {
/*
* Foreground GC
*/
gcValues.background = stylePtr->colors[i].bg->pixel;
gcValues.foreground = stylePtr->colors[i].fg->pixel;
newGC = Tk_GetGC(stylePtr->tkwin,
GCForeground|GCBackground|GCGraphicsExposures, &gcValues);
if (stylePtr->colors[i].foreGC != None) {
Tk_FreeGC(Tk_Display(stylePtr->tkwin),
stylePtr->colors[i].foreGC);
}
stylePtr->colors[i].foreGC = newGC;
/*
* Background GC
*/
gcValues.foreground = stylePtr->colors[i].bg->pixel;
newGC = Tk_GetGC(stylePtr->tkwin,
GCForeground|GCGraphicsExposures, &gcValues);
if (stylePtr->colors[i].backGC != None) {
Tk_FreeGC(Tk_Display(stylePtr->tkwin),
stylePtr->colors[i].backGC);
}
stylePtr->colors[i].backGC = newGC;
/*
* Anchor GC
*/
newGC = Tix_GetAnchorGC(stylePtr->tkwin,
stylePtr->colors[i].bg);
if (stylePtr->colors[i].anchorGC != None) {
Tk_FreeGC(Tk_Display(stylePtr->tkwin),
stylePtr->colors[i].anchorGC);
}
stylePtr->colors[i].anchorGC = newGC;
}
}