From 72a139a4ee101796fcc487b5b3bba46295f13b8c Mon Sep 17 00:00:00 2001 From: vincentdarley Date: Tue, 27 May 2003 15:35:52 +0000 Subject: text widget cleanup fix --- ChangeLog | 8 +++++++ generic/tkText.c | 61 ++++++++++++++++++++++++++++------------------------ generic/tkText.h | 9 ++++++-- generic/tkTextDisp.c | 16 ++++++++------ generic/tkTextTag.c | 10 +++++---- 5 files changed, 63 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f48bc9..f04f21e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-05-27 Vince Darley + + * generic/tkText.c + * generic/tkTextTag.c + * generic/tkTextDisp.c + * generic/tkText.h: refactoring of text widget cleanup code + to ensure all resources are freed. [Bug#741179] + 2003-05-23 Mo DeJong * unix/mkLinks: Set the var S to "" at the top diff --git a/generic/tkText.c b/generic/tkText.c index 0f43d34..4ec38d7 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkText.c,v 1.37 2003/05/21 09:21:57 dkf Exp $ + * RCS: @(#) $Id: tkText.c,v 1.38 2003/05/27 15:35:52 vincentdarley Exp $ */ #include "default.h" @@ -1336,32 +1336,36 @@ TextEventProc(clientData, eventPtr) textPtr->prevHeight = Tk_Height(textPtr->tkwin); } } else if (eventPtr->type == DestroyNotify) { - if (textPtr->tkwin != NULL) { - /* - * NOTE: we must zero out selBorder, selBorderWidthPtr and - * selFgColorPtr: they are duplicates of information in the - * "sel" tag, which will be freed up when we delete all tags. - * Hence we don't want the automatic config options freeing - * process to delete them as well. - */ + /* + * NOTE: we must zero out selBorder, selBorderWidthPtr and + * selFgColorPtr: they are duplicates of information in the + * "sel" tag, which will be freed up when we delete all tags. + * Hence we don't want the automatic config options freeing + * process to delete them as well. + */ - textPtr->selBorder = NULL; - textPtr->selBorderWidthPtr = NULL; - textPtr->selBorderWidth = 0; - textPtr->selFgColorPtr = NULL; - if (textPtr->setGrid) { - Tk_UnsetGrid(textPtr->tkwin); - } + textPtr->selBorder = NULL; + textPtr->selBorderWidthPtr = NULL; + textPtr->selBorderWidth = 0; + textPtr->selFgColorPtr = NULL; + if (textPtr->setGrid) { + Tk_UnsetGrid(textPtr->tkwin); + textPtr->setGrid = 0; + } + if (!(textPtr->flags & OPTIONS_FREED)) { Tk_FreeConfigOptions((char *) textPtr, textPtr->optionTable, textPtr->tkwin); - /* - * We don't delete the associated Tcl command yet, because - * that will cause textPtr->tkWin to be nulled out, and that - * is needed inside DestroyText to clean up certain tags - * which might have been created (e.g. in the text widget - * styles demo). - */ + textPtr->flags |= OPTIONS_FREED; } + textPtr->flags |= DESTROYED; + + /* + * We don't delete the associated Tcl command yet, because + * that will cause textPtr->tkWin to be nulled out, and that + * is needed inside DestroyText to clean up certain tags + * which might have been created (e.g. in the text widget + * styles demo). + */ Tcl_EventuallyFree((ClientData) textPtr, DestroyText); } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) { if (eventPtr->xfocus.detail != NotifyInferior) { @@ -1418,16 +1422,17 @@ TextCmdDeletedProc(clientData) /* * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * destroyed and the command was then deleted (in which this flag is + * already set) or because the command was deleted, and then this + * procedure destroys the widget. */ - if (tkwin != NULL) { + if (!(textPtr->flags & DESTROYED)) { if (textPtr->setGrid) { Tk_UnsetGrid(textPtr->tkwin); + textPtr->setGrid = 0; } - textPtr->tkwin = NULL; + textPtr->flags |= DESTROYED; Tk_DestroyWindow(tkwin); } } diff --git a/generic/tkText.h b/generic/tkText.h index 7521fc5..d17735c 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkText.h,v 1.14 2003/05/19 13:04:23 vincentdarley Exp $ + * RCS: @(#) $Id: tkText.h,v 1.15 2003/05/27 15:35:53 vincentdarley Exp $ */ #ifndef _TKTEXT @@ -513,7 +513,6 @@ typedef struct TkText { * it here. */ int state; /* Either STATE_NORMAL or STATE_DISABLED. A * text widget is read-only when disabled. */ - /* * Default information for displaying (may be overridden by tags * applied to ranges of characters). @@ -707,6 +706,10 @@ typedef struct TkText { * for the duration of button presses. * UPDATE_SCROLLBARS: Non-zero means scrollbar(s) should be updated * during next redisplay operation. + * NEED_REPICK This appears unused and should probably + * be ignored + * OPTIONS_FREED The widget's options have been freed + * DESTROYED The widget is going away */ #define GOT_SELECTION 1 @@ -715,6 +718,8 @@ typedef struct TkText { #define BUTTON_DOWN 8 #define UPDATE_SCROLLBARS 0x10 #define NEED_REPICK 0x20 +#define OPTIONS_FREED 0x40 +#define DESTROYED 0x80 /* * Records of the following type define segment types in terms of diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 6c9f7fc..f94281d 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.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: tkTextDisp.c,v 1.15 2003/05/19 13:04:23 vincentdarley Exp $ + * RCS: @(#) $Id: tkTextDisp.c,v 1.16 2003/05/27 15:35:53 vincentdarley Exp $ */ #include "tkPort.h" @@ -2188,7 +2188,7 @@ DisplayText(clientData) * compiler warnings. */ Tcl_Interp *interp; - if (textPtr->tkwin == NULL) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. @@ -2205,7 +2205,7 @@ DisplayText(clientData) TCL_GLOBAL_ONLY); } - if (textPtr->tkwin == NULL) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. @@ -2226,7 +2226,7 @@ DisplayText(clientData) TCL_GLOBAL_ONLY); } - if (textPtr->tkwin == NULL) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. @@ -2244,12 +2244,14 @@ DisplayText(clientData) */ while (dInfoPtr->flags & REPICK_NEEDED) { + int flags = textPtr->flags; + Tcl_Preserve((ClientData) textPtr); dInfoPtr->flags &= ~REPICK_NEEDED; TkTextPickCurrent(textPtr, &textPtr->pickEvent); tkwin = textPtr->tkwin; Tcl_Release((ClientData) textPtr); - if (tkwin == NULL) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { goto end; } } @@ -2494,7 +2496,7 @@ DisplayText(clientData) TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); } - if (textPtr->tkwin == NULL) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. @@ -2524,7 +2526,7 @@ DisplayText(clientData) GetYView(textPtr->interp, textPtr, 1); } - if (textPtr->tkwin == NULL) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c index fa8a2b9..e3bf289 100644 --- a/generic/tkTextTag.c +++ b/generic/tkTextTag.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: tkTextTag.c,v 1.9 2003/05/19 13:04:24 vincentdarley Exp $ + * RCS: @(#) $Id: tkTextTag.c,v 1.10 2003/05/27 15:35:53 vincentdarley Exp $ */ #include "default.h" @@ -1187,7 +1187,7 @@ TkTextBindProc(clientData, eventPtr) TkTextPickCurrent(textPtr, eventPtr); } if ((textPtr->numCurTags > 0) && (textPtr->bindingTable != NULL) - && (textPtr->tkwin != NULL)) { + && (textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) { Tk_BindEvent(textPtr->bindingTable, eventPtr, textPtr->tkwin, textPtr->numCurTags, (ClientData *) textPtr->curTagArrayPtr); } @@ -1359,7 +1359,8 @@ TkTextPickCurrent(textPtr, eventPtr) oldArrayPtr = textPtr->curTagArrayPtr; textPtr->curTagArrayPtr = newArrayPtr; if (numOldTags != 0) { - if ((textPtr->bindingTable != NULL) && (textPtr->tkwin != NULL)) { + if ((textPtr->bindingTable != NULL) && (textPtr->tkwin != NULL) + && !(textPtr->flags & DESTROYED)) { event = textPtr->pickEvent; event.type = LeaveNotify; @@ -1387,7 +1388,8 @@ TkTextPickCurrent(textPtr, eventPtr) textPtr->pickEvent.xcrossing.y, &index); TkTextSetMark(textPtr, "current", &index); if (numNewTags != 0) { - if ((textPtr->bindingTable != NULL) && (textPtr->tkwin != NULL)) { + if ((textPtr->bindingTable != NULL) && (textPtr->tkwin != NULL) + && !(textPtr->flags & DESTROYED)) { event = textPtr->pickEvent; event.type = EnterNotify; event.xcrossing.detail = NotifyAncestor; -- cgit v0.12