diff options
author | hobbs <hobbs> | 2001-08-24 23:58:29 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2001-08-24 23:58:29 (GMT) |
commit | 0c277553ca23338b5ec307d60a0b2c6eced4ce4b (patch) | |
tree | 590d4a711dcd7d4203c59e9135c6977154ce54d2 | |
parent | f8f7182882d121f3de4e5aea0ae0428fdc8bed19 (diff) | |
download | tk-0c277553ca23338b5ec307d60a0b2c6eced4ce4b.zip tk-0c277553ca23338b5ec307d60a0b2c6eced4ce4b.tar.gz tk-0c277553ca23338b5ec307d60a0b2c6eced4ce4b.tar.bz2 |
* tests/listbox.test:
* generic/tkListbox.c: made use of Tcl_Preserve/Tcl_Release to
prevent FMR errors in Display functions.
-rw-r--r-- | generic/tkListbox.c | 92 | ||||
-rw-r--r-- | tests/listbox.test | 8 |
2 files changed, 44 insertions, 56 deletions
diff --git a/generic/tkListbox.c b/generic/tkListbox.c index 44ea895..7014811 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.16.2.2 2001/04/05 19:44:16 hobbs Exp $ + * RCS: @(#) $Id: tkListbox.c,v 1.16.2.3 2001/08/24 23:58:29 hobbs Exp $ */ #include "tkPort.h" @@ -490,9 +490,13 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) /* * Initialize the fields of the structure that won't be initialized * by ConfigureListbox, or that ConfigureListbox requires to be - * initialized already (e.g. resource pointers). + * initialized already (e.g. resource pointers). Only the non-NULL/0 + * data must be initialized as memset covers the rest. */ + listPtr = (Listbox *) ckalloc(sizeof(Listbox)); + memset((VOID *) listPtr, 0, sizeof(Listbox)); + listPtr->tkwin = tkwin; listPtr->display = Tk_Display(tkwin); listPtr->interp = interp; @@ -501,53 +505,27 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) (ClientData) listPtr, ListboxCmdDeletedProc); listPtr->optionTable = optionTables->listboxOptionTable; listPtr->itemAttrOptionTable = optionTables->itemAttrOptionTable; - listPtr->listVarName = NULL; - listPtr->listObj = NULL; listPtr->selection = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(listPtr->selection, TCL_ONE_WORD_KEYS); listPtr->itemAttrTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS); - listPtr->nElements = 0; - listPtr->normalBorder = NULL; - listPtr->borderWidth = 0; listPtr->relief = TK_RELIEF_RAISED; - listPtr->highlightWidth = 0; - listPtr->highlightBgColorPtr = NULL; - listPtr->highlightColorPtr = NULL; - listPtr->inset = 0; - listPtr->tkfont = NULL; - listPtr->fgColorPtr = NULL; listPtr->textGC = None; - listPtr->selBorder = NULL; - listPtr->selBorderWidth = 0; listPtr->selFgColorPtr = None; listPtr->selTextGC = None; - listPtr->width = 0; - listPtr->height = 0; - listPtr->lineHeight = 0; - listPtr->topIndex = 0; listPtr->fullLines = 1; - listPtr->partialLine = 0; - listPtr->setGrid = 0; - listPtr->maxWidth = 0; listPtr->xScrollUnit = 1; - listPtr->xOffset = 0; - listPtr->selectMode = NULL; - listPtr->numSelected = 0; - listPtr->selectAnchor = 0; listPtr->exportSelection = 1; - listPtr->active = 0; - listPtr->scanMarkX = 0; - listPtr->scanMarkY = 0; - listPtr->scanMarkXOffset = 0; - listPtr->scanMarkYIndex = 0; listPtr->cursor = None; - listPtr->takeFocus = NULL; - listPtr->xScrollCmd = NULL; - listPtr->yScrollCmd = NULL; - 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"); TkSetClassProcs(listPtr->tkwin, &listboxClass, (ClientData) listPtr); @@ -604,7 +582,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 @@ -613,10 +590,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: { @@ -1412,16 +1389,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); @@ -1460,6 +1427,7 @@ DestroyListbox(memPtr) } Tk_FreeConfigOptions((char *)listPtr, listPtr->optionTable, listPtr->tkwin); + Tcl_Release((ClientData) listPtr->tkwin); listPtr->tkwin = NULL; ckfree((char *) listPtr); } @@ -1766,6 +1734,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); @@ -1773,16 +1744,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->tkwin == NULL) || !Tk_IsMapped(tkwin)) { - return; - } + Tcl_Release((ClientData) listPtr); /* * Redrawing is done in a temporary pixmap that is allocated @@ -2365,7 +2343,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; @@ -2979,7 +2967,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 3960928..ea3ade2 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.12.2.2 2001/04/05 19:44:16 hobbs Exp $ +# RCS: @(#) $Id: listbox.test,v 1.12.2.3 2001/08/24 23:58:29 hobbs Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { source [file join [pwd] [file dirname [info script]] defs.tcl] @@ -1964,7 +1964,7 @@ test listbox-23.5 {ConfigureListboxItem, multiple calls} { catch {destroy .l} listbox .l set i 0 - foreach color {red orange yellow green blue darkblue violet} { + foreach color {red orange yellow green blue white violet} { .l insert end $color .l itemconfigure $i -bg $color incr i @@ -1974,7 +1974,7 @@ test listbox-23.5 {ConfigureListboxItem, multiple calls} { list [.l itemcget 0 -bg] [.l itemcget 1 -bg] [.l itemcget 2 -bg] \ [.l itemcget 3 -bg] [.l itemcget 4 -bg] [.l itemcget 5 -bg] \ [.l itemcget 6 -bg] -} {red orange yellow green blue darkblue violet} +} {red orange yellow green blue white violet} catch {destroy .l} listbox .l .l insert end a b c d @@ -2055,7 +2055,7 @@ resetGridInfo eval destroy [winfo children .] option clear -test listbox-27.1 {widget deletion while active} {knownBug} { +test listbox-27.1 {widget deletion while active} { destroy .l pack [listbox .l] update |