From 4da4f3b1c0761c178c207a8218555cc886b44e72 Mon Sep 17 00:00:00 2001 From: hobbs Date: Tue, 3 Apr 2001 04:41:08 +0000 Subject: * tests/listbox.test: added test listbox-27.1, delete during scrollbar update * generic/tkListbox.c (DestroyListbox, ListboxEventProc): corrected listbox to make proper use of Tcl_EventuallyFree and protect against unusual listbox deletion. --- generic/tkListbox.c | 31 +++++++++++++++++-------------- tests/listbox.test | 18 +++++++++++++----- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/generic/tkListbox.c b/generic/tkListbox.c index 25e8563..6c45dfd 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.19 2000/11/22 01:49:38 ericm Exp $ + * RCS: @(#) $Id: tkListbox.c,v 1.20 2001/04/03 04:41:08 hobbs Exp $ */ #include "tkPort.h" @@ -1456,16 +1456,6 @@ DestroyListbox(memPtr) Tcl_HashEntry *entry; Tcl_HashSearch search; - listPtr->flags |= LISTBOX_DELETED; - - Tcl_DeleteCommandFromToken(listPtr->interp, listPtr->widgetCmd); - if (listPtr->setGrid) { - Tk_UnsetGrid(listPtr->tkwin); - } - if (listPtr->flags & REDRAW_PENDING) { - Tcl_CancelIdleCall(DisplayListbox, (ClientData) listPtr); - } - /* If we have an internal list object, free it */ if (listPtr->listObj != NULL) { Tcl_DecrRefCount(listPtr->listObj); @@ -1834,6 +1824,9 @@ DisplayListbox(clientData) Pixmap pixmap; listPtr->flags &= ~REDRAW_PENDING; + if (listPtr->flags & LISTBOX_DELETED) { + return; + } if (listPtr->flags & MAXWIDTH_IS_STALE) { ListboxComputeGeometry(listPtr, 0, 1, 0); @@ -1848,7 +1841,7 @@ DisplayListbox(clientData) ListboxUpdateHScrollbar(listPtr); } listPtr->flags &= ~(REDRAW_PENDING|UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR); - if ((listPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + if ((listPtr->flags & LISTBOX_DELETED) || (!Tk_IsMapped(tkwin))) { return; } @@ -2453,7 +2446,17 @@ ListboxEventProc(clientData, eventPtr) NearestListboxElement(listPtr, eventPtr->xexpose.y + eventPtr->xexpose.height)); } else if (eventPtr->type == DestroyNotify) { - DestroyListbox((char *) clientData); + if (!(listPtr->flags & LISTBOX_DELETED)) { + listPtr->flags |= LISTBOX_DELETED; + Tcl_DeleteCommandFromToken(listPtr->interp, listPtr->widgetCmd); + if (listPtr->setGrid) { + Tk_UnsetGrid(listPtr->tkwin); + } + if (listPtr->flags & REDRAW_PENDING) { + Tcl_CancelIdleCall(DisplayListbox, clientData); + } + Tcl_EventuallyFree(clientData, DestroyListbox); + } } else if (eventPtr->type == ConfigureNotify) { int vertSpace; @@ -3067,7 +3070,7 @@ EventuallyRedrawRange(listPtr, first, last) /* We don't have to register a redraw callback if one is already pending, * or if the window doesn't exist, or if the window isn't mapped */ if ((listPtr->flags & REDRAW_PENDING) - || (listPtr->tkwin == NULL) + || (listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(listPtr->tkwin)) { return; } diff --git a/tests/listbox.test b/tests/listbox.test index 45443f6..8d3d75e 100644 --- a/tests/listbox.test +++ b/tests/listbox.test @@ -6,7 +6,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: listbox.test,v 1.13 2000/07/28 16:34:55 ericm Exp $ +# RCS: @(#) $Id: listbox.test,v 1.14 2001/04/03 04:41:08 hobbs Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { source [file join [pwd] [file dirname [info script]] defs.tcl] @@ -2101,12 +2101,20 @@ test listbox-26.5 {listbox disabled state disallows active modification} { } 0 resetGridInfo -catch {destroy .l2} -catch {destroy .t} -catch {destroy .e} -catch {destroy .partial} +eval destroy [winfo children .] option clear +test listbox-27.1 {widget deletion while active} { + destroy .l + pack [listbox .l] + update + .l configure -cursor xterm -xscrollcommand { destroy .l } + update idle + winfo exists .l +} 0 + +eval destroy [winfo children .] + # cleanup ::tcltest::cleanupTests return -- cgit v0.12