Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Bug [069c9e43c4]: FreeOptionInternalRep() breaks Tk_CreateOptionTable() |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
aaf11bdce2085809d8fe033855f4cac5 |
User & Date: | jan.nijtmans 2013-08-14 13:16:07 |
References
2013-10-31
| ||
10:04 | • Ticket [f214b8ad] shutdown woes status still Open with 3 other changes artifact: 0c6cd482 user: jan.nijtmans | |
2013-08-14
| ||
13:16 | • Closed ticket [069c9e43]: FreeOptionInternalRep() breaks Tk_CreateOptionTable() plus 6 other changes artifact: 5736cf7b user: jan.nijtmans | |
Context
2013-08-15
| ||
03:56 | Bug [c597acdab3]: Call [$pb step] in tail position in ttk::progressbar::Autoincrement, so that the widget is in a consistent state when any write traces on the linked -variable are fired. check-in: 8ea3ccb4 user: jenglish tags: trunk | |
2013-08-14
| ||
13:16 | Bug [069c9e43c4]: FreeOptionInternalRep() breaks Tk_CreateOptionTable() check-in: aaf11bdc user: jan.nijtmans tags: trunk | |
10:53 | Fix reference counting for "option" objects, when being duplicated. Closed-Leaf check-in: bc21cf92 user: jan.nijtmans tags: bug-069c9e43c4 | |
2013-08-11
| ||
14:51 | Sync with Tcl version of tcl.m4 check-in: f2303527 user: jan.nijtmans tags: trunk | |
Changes
Changes to ChangeLog.
1 2 3 4 5 6 7 | 2013-07-02 Jan Nijtmans <[email protected]> * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 * unix/configure: (thanks to Brian Griffin) 2012-06-28 Jan Nijtmans <[email protected]> | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | 2013-08-14 Jan Nijtmans <[email protected]> * generic/tkConfig.c: Bug [069c9e43c4]: FreeOptionInternalRep() breaks * tests/config.test: Tk_CreateOptionTable() 2013-07-02 Jan Nijtmans <[email protected]> * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 * unix/configure: (thanks to Brian Griffin) 2012-06-28 Jan Nijtmans <[email protected]> |
︙ | ︙ |
Changes to generic/tkConfig.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | #define __NO_OLD_CONFIG #endif #include "tkInt.h" #include "tkFont.h" /* | | | > > > > > | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #define __NO_OLD_CONFIG #endif #include "tkInt.h" #include "tkFont.h" /* * The following definition keeps track of all of * the option tables that have been created for a thread. */ typedef struct ThreadSpecificData { int initialized; /* 0 means table below needs initializing. */ Tcl_HashTable hashTable; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following two structures are used along with Tk_OptionSpec structures * to manage configuration options. Tk_OptionSpec is static templates that are * compiled into the code of a widget or other object manager. However, to * look up options efficiently we need to supplement the static information * with additional dynamic information, and this dynamic information may be |
︙ | ︙ | |||
96 97 98 99 100 101 102 | * used to delete the entry. */ struct OptionTable *nextPtr;/* If templatePtr was part of a chain of * templates, this points to the table * corresponding to the next template in the * chain. */ int numOptions; /* The number of items in the options array * below. */ | < < < < > | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | * used to delete the entry. */ struct OptionTable *nextPtr;/* If templatePtr was part of a chain of * templates, this points to the table * corresponding to the next template in the * chain. */ int numOptions; /* The number of items in the options array * below. */ Option options[1]; /* Information about the individual options in * the table. This must be the last field in * the structure: the actual size of the array * will be numOptions, not 1. */ } OptionTable; /* * Forward declarations for functions defined later in this file: */ static int DoObjConfig(Tcl_Interp *interp, char *recordPtr, Option *optionPtr, Tcl_Obj *valuePtr, Tk_Window tkwin, Tk_SavedOption *savePtr); static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr, char *internalPtr, Tk_Window tkwin); static Tcl_Obj * GetConfigList(char *recordPtr, Option *optionPtr, Tk_Window tkwin); static Tcl_Obj * GetObjectForOption(char *recordPtr, Option *optionPtr, Tk_Window tkwin); static Option * GetOption(const char *name, OptionTable *tablePtr); static Option * GetOptionFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, OptionTable *tablePtr); static int ObjectIsEmpty(Tcl_Obj *objPtr); static void FreeOptionInternalRep(Tcl_Obj *objPtr); static void DupOptionInternalRep(Tcl_Obj *, Tcl_Obj *); /* * The structure below defines an object type that is used to cache the result * of looking up an option name. If an object has this type, then its * internalPtr1 field points to the OptionTable in which it was looked up, and * the internalPtr2 field points to the entry that matched. */ static const Tcl_ObjType optionObjType = { "option", /* name */ FreeOptionInternalRep, /* freeIntRepProc */ DupOptionInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; /* *-------------------------------------------------------------- * |
︙ | ︙ | |||
166 167 168 169 170 171 172 | Tk_CreateOptionTable( Tcl_Interp *interp, /* Interpreter associated with the application * in which this table will be used. */ const Tk_OptionSpec *templatePtr) /* Static information about the configuration * options. */ { | < > > | | | < < | < | < | < | | < | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | Tk_CreateOptionTable( Tcl_Interp *interp, /* Interpreter associated with the application * in which this table will be used. */ const Tk_OptionSpec *templatePtr) /* Static information about the configuration * options. */ { Tcl_HashEntry *hashEntryPtr; int newEntry; OptionTable *tablePtr; const Tk_OptionSpec *specPtr, *specPtr2; Option *optionPtr; int numOptions, i; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * We use an TSD in the thread to keep a hash table of * all the option tables we've created for this application. This is * used for allowing us to share the tables (e.g. in several chains). * The code below finds the hash table or creates a new one if it * doesn't already exist. */ if (!tsdPtr->initialized) { Tcl_InitHashTable(&tsdPtr->hashTable, TCL_ONE_WORD_KEYS); tsdPtr->initialized = 1; } /* * See if a table has already been created for this template. If so, just * reuse the existing table. */ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *) templatePtr, &newEntry); if (!newEntry) { tablePtr = Tcl_GetHashValue(hashEntryPtr); tablePtr->refCount++; return (Tk_OptionTable) tablePtr; } /* * Count the number of options in the template, then create the table * structure. */ numOptions = 0; for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) { numOptions++; } tablePtr = ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option))); tablePtr->refCount = 1; tablePtr->hashEntryPtr = hashEntryPtr; tablePtr->nextPtr = NULL; tablePtr->numOptions = numOptions; /* * Initialize all of the Option structures in the table. */ |
︙ | ︙ | |||
352 353 354 355 356 357 358 | if (((optionPtr->specPtr->type == TK_OPTION_COLOR) || (optionPtr->specPtr->type == TK_OPTION_BORDER)) && (optionPtr->extra.monoColorPtr != NULL)) { Tcl_DecrRefCount(optionPtr->extra.monoColorPtr); } } Tcl_DeleteHashEntry(tablePtr->hashEntryPtr); | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | if (((optionPtr->specPtr->type == TK_OPTION_COLOR) || (optionPtr->specPtr->type == TK_OPTION_BORDER)) && (optionPtr->extra.monoColorPtr != NULL)) { Tcl_DecrRefCount(optionPtr->extra.monoColorPtr); } } Tcl_DeleteHashEntry(tablePtr->hashEntryPtr); ckfree(tablePtr); } /* *-------------------------------------------------------------- * * Tk_InitOptions -- * |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | if ((objPtr->typePtr != NULL) && (objPtr->typePtr->freeIntRepProc != NULL)) { objPtr->typePtr->freeIntRepProc(objPtr); } objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr; objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr; objPtr->typePtr = &optionObjType; | | | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | if ((objPtr->typePtr != NULL) && (objPtr->typePtr->freeIntRepProc != NULL)) { objPtr->typePtr->freeIntRepProc(objPtr); } objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr; objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr; objPtr->typePtr = &optionObjType; tablePtr->refCount++; return bestPtr; error: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown option \"%s\"", name)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "OPTION", name, NULL); |
︙ | ︙ | |||
1220 1221 1222 1223 1224 1225 1226 | *---------------------------------------------------------------------- */ static void FreeOptionInternalRep( register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { | | < < | < > > > > > > > > > > > > > > > > > > > > > > | 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | *---------------------------------------------------------------------- */ static void FreeOptionInternalRep( register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { register Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1; Tk_DeleteOptionTable(tablePtr); objPtr->typePtr = NULL; objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->internalRep.twoPtrValue.ptr2 = NULL; } /* *--------------------------------------------------------------------------- * * DupOptionInternalRep -- * * When a cached option object is duplicated, this is called to update the * internal reps. * *--------------------------------------------------------------------------- */ static void DupOptionInternalRep( Tcl_Obj *srcObjPtr, /* The object we are copying from. */ Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { register OptionTable *tablePtr = (OptionTable *) srcObjPtr->internalRep.twoPtrValue.ptr1; tablePtr->refCount++; dupObjPtr->typePtr = srcObjPtr->typePtr; dupObjPtr->internalRep = srcObjPtr->internalRep; } /* *-------------------------------------------------------------- * * Tk_SetOptions -- * * Process one or more name-value pairs for configuration options and |
︙ | ︙ | |||
2109 2110 2111 2112 2113 2114 2115 | Tcl_Interp *interp, /* Interpreter in which the table is * defined. */ Tk_OptionTable table) /* Table about which information is to be * returned. May not necessarily exist in the * interpreter anymore. */ { OptionTable *tablePtr = (OptionTable *) table; | < > > < | | | 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 | Tcl_Interp *interp, /* Interpreter in which the table is * defined. */ Tk_OptionTable table) /* Table about which information is to be * returned. May not necessarily exist in the * interpreter anymore. */ { OptionTable *tablePtr = (OptionTable *) table; Tcl_HashEntry *hashEntryPtr; Tcl_HashSearch search; Tcl_Obj *objPtr; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); objPtr = Tcl_NewObj(); if (!tablePtr || !tsdPtr->initialized) { return objPtr; } /* * Scan all the tables for this interpreter to make sure that the one we * want still is valid. */ for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search); hashEntryPtr != NULL; hashEntryPtr = Tcl_NextHashEntry(&search)) { if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) { for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(tablePtr->refCount)); Tcl_ListObjAppendElement(NULL, objPtr, |
︙ | ︙ |
Changes to tests/config.test.
︙ | ︙ | |||
130 131 132 133 134 135 136 | deleteWindows testobjconfig delete chain3 lappend x [testobjconfig info chain2] [testobjconfig info chain1] testobjconfig delete chain2 lappend x [testobjconfig info chain2] [testobjconfig info chain1] } -cleanup { killTables | | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | deleteWindows testobjconfig delete chain3 lappend x [testobjconfig info chain2] [testobjconfig info chain1] testobjconfig delete chain2 lappend x [testobjconfig info chain2] [testobjconfig info chain1] } -cleanup { killTables } -result {{3 4 -three 2 2 -one} {2 2 -one} {} {2 2 -one}} # No tests for DestroyOptionHashTable; couldn't figure out how to test. test config-3.1 {Tk_InitOptions - priority of chained tables} -constraints { testobjconfig } -body { testobjconfig chain1 .a |
︙ | ︙ |