Index: generic/tkInt.h ================================================================== --- generic/tkInt.h +++ generic/tkInt.h @@ -1074,10 +1074,13 @@ MODULE_SCOPE int Tk_ListboxObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_LowerObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_MenuObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_MenubuttonObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_MessageBoxObjCmd(ClientData clientData, @@ -1146,11 +1149,10 @@ MODULE_SCOPE void TkFreeGeometryMaster(Tk_Window tkwin, const char *master); MODULE_SCOPE void TkEventInit(void); MODULE_SCOPE void TkRegisterObjTypes(void); -MODULE_SCOPE int TkCreateMenuCmd(Tcl_Interp *interp); MODULE_SCOPE int TkDeadAppCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); MODULE_SCOPE int TkCanvasGetCoordObj(Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, double *doublePtr); Index: generic/tkMenu.c ================================================================== --- generic/tkMenu.c +++ generic/tkMenu.c @@ -79,10 +79,14 @@ typedef struct ThreadSpecificData { int menusInitialized; /* Flag indicates whether thread-specific * elements of the Windows Menu module have * been initialized. */ + Tk_OptionTable menuOptionTable; + /* The option table for menus. */ + Tk_OptionTable entryOptionTables[6]; + /* The tables for menu entries. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following flag indicates whether the process-wide state for the Menu @@ -347,12 +351,10 @@ static int MenuDoXPosition(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *objPtr); static int MenuAddOrInsert(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc, Tcl_Obj *const objv[]); -static int MenuCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); static void MenuCmdDeletedProc(ClientData clientData); static TkMenuEntry * MenuNewEntry(TkMenu *menuPtr, int index, int type); static char * MenuVarProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); @@ -379,67 +381,11 @@ }; /* *-------------------------------------------------------------- * - * TkCreateMenuCmd -- - * - * Called by Tk at initialization time to create the menu command. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *-------------------------------------------------------------- - */ - -static void -FreeOptionTables( - ClientData clientData, - Tcl_Interp *interp) -{ - ckfree(clientData); -} - -int -TkCreateMenuCmd( - Tcl_Interp *interp) /* Interpreter we are creating the command - * in. */ -{ - TkMenuOptionTables *optionTablesPtr = ckalloc(sizeof(TkMenuOptionTables)); - - optionTablesPtr->menuOptionTable = - Tk_CreateOptionTable(interp, tkMenuConfigSpecs); - optionTablesPtr->entryOptionTables[TEAROFF_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[TEAROFF_ENTRY]); - optionTablesPtr->entryOptionTables[COMMAND_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[COMMAND_ENTRY]); - optionTablesPtr->entryOptionTables[CASCADE_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[CASCADE_ENTRY]); - optionTablesPtr->entryOptionTables[SEPARATOR_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[SEPARATOR_ENTRY]); - optionTablesPtr->entryOptionTables[RADIO_BUTTON_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[RADIO_BUTTON_ENTRY]); - optionTablesPtr->entryOptionTables[CHECK_BUTTON_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[CHECK_BUTTON_ENTRY]); - - Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr, 0); - Tcl_CallWhenDeleted(interp, FreeOptionTables, optionTablesPtr); - - if (Tcl_IsSafe(interp)) { - Tcl_HideCommand(interp, "menu", "menu"); - } - - return TCL_OK; -} - -/* - *-------------------------------------------------------------- - * - * MenuCmd -- + * Tk_MenuObjCmd -- * * This function is invoked to process the "menu" Tcl command. See the * user documentation for details on what it does. * * Results: @@ -449,25 +395,26 @@ * See the user documentation. * *-------------------------------------------------------------- */ -static int -MenuCmd( +int +Tk_MenuObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { - Tk_Window tkwin = Tk_MainWindow(interp); + Tk_Window tkwin = clientData; Tk_Window newWin; register TkMenu *menuPtr; TkMenuReferences *menuRefPtr; int i, index, toplevel; const char *windowName; static const char *const typeStringList[] = {"-type", NULL}; - TkMenuOptionTables *optionTablesPtr = clientData; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?"); return TCL_ERROR; } @@ -509,20 +456,19 @@ MenuCmdDeletedProc); menuPtr->active = -1; menuPtr->cursorPtr = None; menuPtr->masterMenuPtr = menuPtr; menuPtr->menuType = UNKNOWN_TYPE; - menuPtr->optionTablesPtr = optionTablesPtr; TkMenuInitializeDrawingFields(menuPtr); Tk_SetClass(menuPtr->tkwin, "Menu"); Tk_SetClassProcs(menuPtr->tkwin, &menuClass, menuPtr); Tk_CreateEventHandler(newWin, ExposureMask|StructureNotifyMask|ActivateMask, TkMenuEventProc, menuPtr); if (Tk_InitOptions(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin) + tsdPtr->menuOptionTable, menuPtr->tkwin) != TCL_OK) { Tk_DestroyWindow(menuPtr->tkwin); return TCL_ERROR; } @@ -673,10 +619,12 @@ { register TkMenu *menuPtr = clientData; register TkMenuEntry *mePtr; int result = TCL_OK; int option; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } @@ -723,11 +671,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, objv[2], + tsdPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { goto error; } Tcl_SetObjResult(interp, resultPtr); @@ -743,21 +691,21 @@ case MENU_CONFIGURE: { Tcl_Obj *resultPtr; if (objc == 2) { resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, NULL, + tsdPtr->menuOptionTable, NULL, menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; } else { result = TCL_OK; Tcl_SetObjResult(interp, resultPtr); } } else if (objc == 3) { resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, objv[2], + tsdPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; } else { result = TCL_OK; @@ -1142,10 +1090,12 @@ TkMenu *menuInstancePtr; TkMenuEntry *cascadePtr, *nextCascadePtr; Tcl_Obj *newObjv[2]; TkMenu *parentMasterMenuPtr; TkMenuEntry *parentMasterEntryPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * If the menu has any cascade menu entries pointing to it, the cascade * entries need to be told that the menu is going away. We need to clear * the menu ptr field in the menu reference at this point in the code so @@ -1231,11 +1181,11 @@ if (menuPtr->entries != NULL) { ckfree(menuPtr->entries); } TkMenuFreeDrawOptions(menuPtr); Tk_FreeConfigOptions((char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin); + tsdPtr->menuOptionTable, menuPtr->tkwin); if (menuPtr->tkwin != NULL) { Tk_Window tkwin = menuPtr->tkwin; menuPtr->tkwin = NULL; Tk_DestroyWindow(tkwin); @@ -1564,16 +1514,18 @@ Tcl_Obj *const objv[]) /* Arguments. */ { int i; TkMenu *menuListPtr, *cleanupPtr; int result; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { menuListPtr->errorStructPtr = ckalloc(sizeof(Tk_SavedOptions)); result = Tk_SetOptions(interp, (char *) menuListPtr, - menuListPtr->optionTablesPtr->menuOptionTable, objc, objv, + tsdPtr->menuOptionTable, objc, objv, menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL); if (result != TCL_OK) { for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != menuListPtr; cleanupPtr = cleanupPtr->nextInstancePtr) { @@ -2285,10 +2237,12 @@ int type) /* The type of the new entry. */ { TkMenuEntry *mePtr; TkMenuEntry **newEntries; int i; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Create a new array of entries with an empty slot for the new entry. */ @@ -2306,11 +2260,11 @@ menuPtr->entries = newEntries; menuPtr->numEntries++; mePtr = ckalloc(sizeof(TkMenuEntry)); menuPtr->entries[index] = mePtr; mePtr->type = type; - mePtr->optionTable = menuPtr->optionTablesPtr->entryOptionTables[type]; + mePtr->optionTable = tsdPtr->entryOptionTables[type]; mePtr->menuPtr = menuPtr; mePtr->labelPtr = NULL; mePtr->labelLength = 0; mePtr->underline = -1; mePtr->bitmapPtr = NULL; @@ -3623,10 +3577,24 @@ TkCreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL); Tcl_MutexUnlock(&menuMutex); } if (!tsdPtr->menusInitialized) { TkpMenuThreadInit(); + tsdPtr->menuOptionTable = + Tk_CreateOptionTable(NULL, tkMenuConfigSpecs); + tsdPtr->entryOptionTables[TEAROFF_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[TEAROFF_ENTRY]); + tsdPtr->entryOptionTables[COMMAND_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[COMMAND_ENTRY]); + tsdPtr->entryOptionTables[CASCADE_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[CASCADE_ENTRY]); + tsdPtr->entryOptionTables[SEPARATOR_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[SEPARATOR_ENTRY]); + tsdPtr->entryOptionTables[RADIO_BUTTON_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[RADIO_BUTTON_ENTRY]); + tsdPtr->entryOptionTables[CHECK_BUTTON_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[CHECK_BUTTON_ENTRY]); tsdPtr->menusInitialized = 1; } } /* Index: generic/tkMenu.h ================================================================== --- generic/tkMenu.h +++ generic/tkMenu.h @@ -357,14 +357,11 @@ * chain. */ struct TkMenu *masterMenuPtr; /* A pointer to the original menu for this * clone chain. Points back to this structure * if this menu is a master menu. */ - struct TkMenuOptionTables *optionTablesPtr; - /* A pointer to the collection of option - * tables that work with menus and menu - * entries. */ + void *reserved1; /* not used any more. */ Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the * toplevel that owns the menu. Only * applicable for menubar clones. */ struct TkMenuReferences *menuRefPtr; /* Each menu is hashed into a table with the @@ -428,21 +425,10 @@ Tcl_HashEntry *hashEntryPtr;/* This is needed because the pathname of the * window (which is what we hash on) may not * be around when we are deleting. */ } TkMenuReferences; -/* - * This structure contains all of the option tables that are needed by menus. - */ - -typedef struct TkMenuOptionTables { - Tk_OptionTable menuOptionTable; - /* The option table for menus. */ - Tk_OptionTable entryOptionTables[6]; - /* The tables for menu entries. */ -} TkMenuOptionTables; - /* * Flag bits for menus: * * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has * already been queued to redraw this window. Index: generic/tkWindow.c ================================================================== --- generic/tkWindow.c +++ generic/tkWindow.c @@ -147,10 +147,11 @@ {"entry", Tk_EntryObjCmd, ISSAFE}, {"frame", Tk_FrameObjCmd, ISSAFE}, {"label", Tk_LabelObjCmd, ISSAFE}, {"labelframe", Tk_LabelframeObjCmd, ISSAFE}, {"listbox", Tk_ListboxObjCmd, ISSAFE}, + {"menu", Tk_MenuObjCmd, PASSMAINWINDOW}, {"menubutton", Tk_MenubuttonObjCmd, ISSAFE}, {"message", Tk_MessageObjCmd, ISSAFE}, {"panedwindow", Tk_PanedWindowObjCmd, ISSAFE}, {"radiobutton", Tk_RadiobuttonObjCmd, ISSAFE}, {"scale", Tk_ScaleObjCmd, ISSAFE}, @@ -985,12 +986,10 @@ if (isSafe && !(cmdPtr->flags & ISSAFE)) { Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name); } } - TkCreateMenuCmd(interp); - /* * Set variables for the intepreter. */ Tcl_SetVar2(interp, "tk_patchLevel", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);