From 41a1a2ac900531c2c44e34f1819991cd386ec7a3 Mon Sep 17 00:00:00 2001 From: hobbs Date: Tue, 3 Jul 2001 06:16:19 +0000 Subject: * generic/tkEntry.c: corrected missing Tcl_Release that caused font not freed complaints when trying valid cleanup calls. * generic/tkListbox.c: made use of Tcl_Preserve/Tcl_Release to prevent FMR errors in Display functions. --- generic/tkEntry.c | 54 +++++++++++++++++++++++++++++++---------------------- generic/tkListbox.c | 26 ++++++++++++++++++++------ 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/generic/tkEntry.c b/generic/tkEntry.c index 805b208..35464da 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.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: tkEntry.c,v 1.20 2001/07/02 23:52:36 hobbs Exp $ + * RCS: @(#) $Id: tkEntry.c,v 1.21 2001/07/03 06:16:19 hobbs Exp $ */ #include "tkInt.h" @@ -837,6 +837,13 @@ Tk_EntryObjCmd(clientData, interp, objc, objv) entryPtr->avgWidth = 1; entryPtr->validate = VALIDATE_NONE; + /* + * Keep a hold of the associated tkwin until we destroy the listbox, + * otherwise Tk might free it while we still need it. + */ + + Tcl_Preserve((ClientData) entryPtr->tkwin); + Tk_SetClass(entryPtr->tkwin, "Entry"); Tk_SetClassProcs(entryPtr->tkwin, &entryClass, (ClientData) entryPtr); Tk_CreateEventHandler(entryPtr->tkwin, @@ -889,7 +896,6 @@ EntryWidgetObjCmd(clientData, interp, objc, objv) Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } - Tcl_Preserve((ClientData) entryPtr); /* * Parse the widget command by looking up the second token in @@ -902,6 +908,7 @@ EntryWidgetObjCmd(clientData, interp, objc, objv) return result; } + Tcl_Preserve((ClientData) entryPtr); switch ((enum entryCmd) cmdIndex) { case COMMAND_BBOX: { int index, x, y, width, height; @@ -1360,18 +1367,10 @@ DestroyEntry(memPtr) Tk_FreeTextLayout(entryPtr->textLayout); Tk_FreeConfigOptions((char *) entryPtr, entryPtr->optionTable, entryPtr->tkwin); + Tcl_Release((ClientData) entryPtr->tkwin); entryPtr->tkwin = NULL; - /* - * Tcl_EventuallyFree should be used in - * DestroyNotify branch of EntryEventProc. However, that can lead - * complications in Tk_FreeConfigOptions where the display for the - * entry has been deleted by Tk_DestroyWindow, which is needed - * when freeing the cursor option. Also, there can be a timing - * issue were we wouldn't get called until too late in Tk clean-up, - * and it complains that we haven't freed our fonts yet. - */ - Tcl_EventuallyFree((ClientData) entryPtr, TCL_DYNAMIC); + ckfree((char *) entryPtr); } /* @@ -1810,16 +1809,20 @@ DisplayEntry(clientData) if (entryPtr->flags & UPDATE_SCROLLBAR) { entryPtr->flags &= ~UPDATE_SCROLLBAR; - EntryUpdateScrollbar(entryPtr); - } - /* - * We do this check twice because updating the scrollbar can have - * the side-effect of destroying or unmapping the entry widget. - */ + /* + * Preserve/Release because updating the scrollbar can have + * the side-effect of destroying or unmapping the entry widget. + */ - if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) { - return; + Tcl_Preserve((ClientData) entryPtr); + EntryUpdateScrollbar(entryPtr); + + if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) { + Tcl_Release((ClientData) entryPtr); + return; + } + Tcl_Release((ClientData) entryPtr); } /* @@ -2635,7 +2638,7 @@ EntryEventProc(clientData, eventPtr) if (entryPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayEntry, clientData); } - DestroyEntry((char *) entryPtr); + Tcl_EventuallyFree(clientData, DestroyEntry); } break; case ConfigureNotify: @@ -3782,6 +3785,13 @@ Tk_SpinboxObjCmd(clientData, interp, objc, objv) sbPtr->bdRelief = TK_RELIEF_FLAT; sbPtr->buRelief = TK_RELIEF_FLAT; + /* + * Keep a hold of the associated tkwin until we destroy the listbox, + * otherwise Tk might free it while we still need it. + */ + + Tcl_Preserve((ClientData) entryPtr->tkwin); + Tk_SetClass(entryPtr->tkwin, "Spinbox"); Tk_SetClassProcs(entryPtr->tkwin, &entryClass, (ClientData) entryPtr); Tk_CreateEventHandler(entryPtr->tkwin, @@ -3841,7 +3851,6 @@ SpinboxWidgetObjCmd(clientData, interp, objc, objv) Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } - Tcl_Preserve((ClientData) entryPtr); /* * Parse the widget command by looking up the second token in @@ -3854,6 +3863,7 @@ SpinboxWidgetObjCmd(clientData, interp, objc, objv) return result; } + Tcl_Preserve((ClientData) entryPtr); switch ((enum sbCmd) cmdIndex) { case SB_CMD_BBOX: { int index, x, y, width, height; diff --git a/generic/tkListbox.c b/generic/tkListbox.c index 6c45dfd..356f3af 100644 --- a/generic/tkListbox.c +++ b/generic/tkListbox.c @@ -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: tkListbox.c,v 1.20 2001/04/03 04:41:08 hobbs Exp $ + * RCS: @(#) $Id: tkListbox.c,v 1.21 2001/07/03 06:16:19 hobbs Exp $ */ #include "tkPort.h" @@ -574,6 +574,13 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) listPtr->gray = None; listPtr->flags = 0; + /* + * Keep a hold of the associated tkwin until we destroy the listbox, + * otherwise Tk might free it while we still need it. + */ + + Tcl_Preserve((ClientData) listPtr->tkwin); + Tk_SetClass(listPtr->tkwin, "Listbox"); Tk_SetClassProcs(listPtr->tkwin, &listboxClass, (ClientData) listPtr); Tk_CreateEventHandler(listPtr->tkwin, @@ -629,7 +636,6 @@ ListboxWidgetObjCmd(clientData, interp, objc, objv) Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } - Tcl_Preserve((ClientData)listPtr); /* * Parse the command by looking up the second argument in the list @@ -638,10 +644,10 @@ ListboxWidgetObjCmd(clientData, interp, objc, objv) result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, "option", 0, &cmdIndex); if (result != TCL_OK) { - Tcl_Release((ClientData)listPtr); return result; } + Tcl_Preserve((ClientData)listPtr); /* The subcommand was valid, so continue processing */ switch (cmdIndex) { case COMMAND_ACTIVATE: { @@ -1498,6 +1504,7 @@ DestroyListbox(memPtr) Tk_FreeConfigOptions((char *)listPtr, listPtr->optionTable, listPtr->tkwin); + Tcl_Release((ClientData) listPtr->tkwin); listPtr->tkwin = NULL; ckfree((char *) listPtr); } @@ -1834,16 +1841,23 @@ DisplayListbox(clientData) listPtr->flags |= UPDATE_H_SCROLLBAR; } + Tcl_Preserve((ClientData) listPtr); if (listPtr->flags & UPDATE_V_SCROLLBAR) { ListboxUpdateVScrollbar(listPtr); + if ((listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(tkwin)) { + Tcl_Release((ClientData) listPtr); + return; + } } if (listPtr->flags & UPDATE_H_SCROLLBAR) { ListboxUpdateHScrollbar(listPtr); + if ((listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(tkwin)) { + Tcl_Release((ClientData) listPtr); + return; + } } listPtr->flags &= ~(REDRAW_PENDING|UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR); - if ((listPtr->flags & LISTBOX_DELETED) || (!Tk_IsMapped(tkwin))) { - return; - } + Tcl_Release((ClientData) listPtr); /* * Redrawing is done in a temporary pixmap that is allocated -- cgit v0.12