diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2001-08-21 14:43:08 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2001-08-21 14:43:08 (GMT) |
commit | c9fb1f587664806275461fcf4b872e8acdd913b9 (patch) | |
tree | 7e8433d81799a34d2318762f17b82e43ed5300d6 /generic | |
parent | 7f3008ca65c1e1b6e1b5079bd1eb28794c9e02fb (diff) | |
download | tk-c9fb1f587664806275461fcf4b872e8acdd913b9.zip tk-c9fb1f587664806275461fcf4b872e8acdd913b9.tar.gz tk-c9fb1f587664806275461fcf4b872e8acdd913b9.tar.bz2 |
TkGetWindowFromObj was useless CPU waster; now caches window names *safely*
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tkInt.h | 7 | ||||
-rw-r--r-- | generic/tkObj.c | 118 | ||||
-rw-r--r-- | generic/tkWindow.c | 7 |
3 files changed, 115 insertions, 17 deletions
diff --git a/generic/tkInt.h b/generic/tkInt.h index a39fa91..e94f0c6 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: $Id: tkInt.h,v 1.36 2001/08/15 15:44:36 dkf Exp $ + * RCS: $Id: tkInt.h,v 1.37 2001/08/21 14:43:08 dkf Exp $ */ #ifndef _TKINT @@ -474,6 +474,11 @@ typedef struct TkDisplay { int warpX; int warpY; int useInputMethods; /* Whether to use input methods */ + + /* + * The following field(s) were all added for Tk8.4 + */ + long deletionEpoch; /* Incremented by window deletions */ } TkDisplay; /* diff --git a/generic/tkObj.c b/generic/tkObj.c index 2fdc710..26d5f79 100644 --- a/generic/tkObj.c +++ b/generic/tkObj.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkObj.c,v 1.6 2001/08/17 09:38:30 dkf Exp $ + * RCS: @(#) $Id: tkObj.c,v 1.7 2001/08/21 14:43:08 dkf Exp $ */ #include "tkInt.h" @@ -55,6 +55,16 @@ typedef struct MMRep { } MMRep; /* + * The following structure is the internal representation for window objects. + */ + +typedef struct WindowRep { + Tk_Window tkwin; + Tk_Window mainwin; + long epoch; +} WindowRep; + +/* * Prototypes for procedures defined later in this file: */ @@ -62,8 +72,11 @@ static void DupMMInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)); static void DupPixelInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)); +static void DupWindowInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr)); static void FreeMMInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); static void FreePixelInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); +static void FreeWindowInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); static void UpdateStringOfMM _ANSI_ARGS_((Tcl_Obj *objPtr)); static int SetMMFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); @@ -71,7 +84,7 @@ static int SetPixelFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); static int SetWindowFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); - + /* * The following structure defines the implementation of the "pixel" * Tcl object, used for measuring distances. The pixel object remembers @@ -107,8 +120,8 @@ static Tcl_ObjType mmObjType = { static Tcl_ObjType windowObjType = { "window", /* name */ - (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ + FreeWindowInternalRep, /* freeIntRepProc */ + DupWindowInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetWindowFromAny /* setFromAnyProc */ }; @@ -666,10 +679,12 @@ int TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr) Tcl_Interp *interp; /* Used for error reporting if not NULL. */ Tk_Window tkwin; /* A token to get the main window from. */ - register Tcl_Obj *objPtr; /* The object from which to get boolean. */ + Tcl_Obj *objPtr; /* The object from which to get boolean. */ Tk_Window *windowPtr; /* Place to store resulting window. */ { - Tk_Window lastWindow; + register WindowRep *winPtr; + TkDisplay *dispPtr = ((TkWindow *)tkwin)->dispPtr; + Tk_Window foundWindow; if (objPtr->typePtr != &windowObjType) { register int result = SetWindowFromAny(interp, objPtr); @@ -678,19 +693,27 @@ TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr) } } - lastWindow = (Tk_Window) objPtr->internalRep.twoPtrValue.ptr1; - if (tkwin != lastWindow) { - Tk_Window foundWindow = Tk_NameToWindow(interp, - Tcl_GetStringFromObj(objPtr, NULL), tkwin); + winPtr = (WindowRep *) objPtr->internalRep.otherValuePtr; + if (winPtr == NULL) { + winPtr = (WindowRep *) ckalloc(sizeof(WindowRep)); + objPtr->internalRep.otherValuePtr = (VOID *) winPtr; + goto parseWindowString; + } else if (tkwin != winPtr->mainwin || + dispPtr->deletionEpoch != winPtr->epoch) { + parseWindowString: + foundWindow = Tk_NameToWindow(interp, + Tcl_GetStringFromObj(objPtr, NULL), tkwin); if (foundWindow == NULL) { return TCL_ERROR; } - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkwin; - objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) foundWindow; + + winPtr->tkwin = foundWindow; + winPtr->mainwin = tkwin; + winPtr->epoch = dispPtr->deletionEpoch; } - *windowPtr = (Tk_Window) objPtr->internalRep.twoPtrValue.ptr2; + *windowPtr = winPtr->tkwin; return TCL_OK; } @@ -731,8 +754,7 @@ SetWindowFromAny(interp, objPtr) (*typePtr->freeIntRepProc)(objPtr); } objPtr->typePtr = &windowObjType; - objPtr->internalRep.twoPtrValue.ptr1 = NULL; - objPtr->internalRep.twoPtrValue.ptr2 = NULL; + objPtr->internalRep.otherValuePtr = NULL; return TCL_OK; } @@ -740,6 +762,72 @@ SetWindowFromAny(interp, objPtr) /* *---------------------------------------------------------------------- * + * DupWindowInternalRep -- + * + * Initialize the internal representation of a window Tcl_Obj to a + * copy of the internal representation of an existing window object. + * + * Results: + * None. + * + * Side effects: + * copyPtr's internal rep is set to refer to the same window as + * srcPtr's internal rep. + * + *---------------------------------------------------------------------- + */ + +static void +DupWindowInternalRep(srcPtr, copyPtr) + register Tcl_Obj *srcPtr; + register Tcl_Obj *copyPtr; +{ + register WindowRep *oldPtr, *newPtr; + + copyPtr->typePtr = srcPtr->typePtr; + oldPtr = srcPtr->internalRep.otherValuePtr; + if (oldPtr == NULL) { + copyPtr->internalRep.otherValuePtr = NULL; + } else { + newPtr = (WindowRep *) ckalloc(sizeof(WindowRep)); + newPtr->tkwin = oldPtr->tkwin; + newPtr->mainwin = oldPtr->mainwin; + newPtr->epoch = oldPtr->epoch; + copyPtr->internalRep.otherValuePtr = (VOID *)newPtr; + } +} + +/* + *---------------------------------------------------------------------- + * + * FreeWindowInternalRep -- + * + * Deallocate the storage associated with a window object's internal + * representation. + * + * Results: + * None. + * + * Side effects: + * Frees objPtr's internal representation and sets objPtr's + * internalRep to NULL. + * + *---------------------------------------------------------------------- + */ + +static void +FreeWindowInternalRep(objPtr) + Tcl_Obj *objPtr; /* Window object with internal rep to free. */ +{ + if (objPtr->internalRep.otherValuePtr != NULL) { + ckfree((char *) objPtr->internalRep.otherValuePtr); + objPtr->internalRep.otherValuePtr = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * * TkRegisterObjTypes -- * * Registers Tk's Tcl_ObjType structures with the Tcl run-time. diff --git a/generic/tkWindow.c b/generic/tkWindow.c index ca1c9f7..1102fab 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.33 2001/08/15 15:44:36 dkf Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.34 2001/08/21 14:43:08 dkf Exp $ */ #include "tkPort.h" @@ -470,6 +470,7 @@ GetScreen(interp, screenName, screenPtr) dispPtr->useInputMethods = 0; OpenIM(dispPtr); TkInitXId(dispPtr); + dispPtr->deletionEpoch = 0L; tsdPtr->displayList = dispPtr; break; @@ -1387,6 +1388,10 @@ Tk_DestroyWindow(tkwin) (ClientData) winPtr->pathName); Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, winPtr->pathName)); + /* + * Invalidate all objects referring to windows on this display. + */ + dispPtr->deletionEpoch++; } winPtr->mainPtr->refCount--; if (winPtr->mainPtr->refCount == 0) { |