📄 tkmenu.c
字号:
} Tk_SetClass(menuPtr->tkwin, "Menu"); TkSetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr); Tk_CreateEventHandler(new, ExposureMask|StructureNotifyMask|ActivateMask, TkMenuEventProc, (ClientData) menuPtr); if (ConfigureMenu(interp, menuPtr, argc-2, argv+2, 0) != TCL_OK) { goto error; } /* * If a menu has a parent menu pointing to it as a cascade entry, the * parent menu needs to be told that this menu now exists so that * the platform-part of the menu is correctly updated. * * If a menu has an instance and has cascade entries, then each cascade * menu must also have a parallel instance. This is especially true on * the Mac, where each menu has to have a separate title everytime it is in * a menubar. For instance, say you have a menu .m1 with a cascade entry * for .m2, where .m2 does not exist yet. You then put .m1 into a menubar. * This creates a menubar instance for .m1, but since .m2 is not there, * nothing else happens. When we go to create .m2, we hook it up properly * with .m1. However, we now need to clone .m2 and assign the clone of .m2 * to be the cascade entry for the clone of .m1. This is special case * #1 listed in the introductory comment. */ if (menuRefPtr->parentEntryPtr != NULL) { TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr; TkMenuEntry *nextCascadePtr; char *newMenuName; char *newArgv[2]; while (cascadeListPtr != NULL) { nextCascadePtr = cascadeListPtr->nextCascadePtr; /* * If we have a new master menu, and an existing cloned menu * points to this menu in a cascade entry, we have to clone * the new menu and point the entry to the clone instead * of the menu we are creating. Otherwise, ConfigureMenuEntry * will hook up the platform-specific cascade linkages now * that the menu we are creating exists. */ if ((menuPtr->masterMenuPtr != menuPtr) || ((menuPtr->masterMenuPtr == menuPtr) && ((cascadeListPtr->menuPtr->masterMenuPtr == cascadeListPtr->menuPtr)))) { newArgv[0] = "-menu"; newArgv[1] = Tk_PathName(menuPtr->tkwin); ConfigureMenuEntry(cascadeListPtr, 2, newArgv, TK_CONFIG_ARGV_ONLY); } else { newMenuName = TkNewMenuName(menuPtr->interp, Tk_PathName(cascadeListPtr->menuPtr->tkwin), menuPtr); CloneMenu(menuPtr, newMenuName, "normal"); /* * Now we can set the new menu instance to be the cascade entry * of the parent's instance. */ newArgv[0] = "-menu"; newArgv[1] = newMenuName; ConfigureMenuEntry(cascadeListPtr, 2, newArgv, TK_CONFIG_ARGV_ONLY); if (newMenuName != NULL) { ckfree(newMenuName); } } cascadeListPtr = nextCascadePtr; } } /* * If there already exist toplevel widgets that refer to this menu, * find them and notify them so that they can reconfigure their * geometry to reflect the menu. */ if (menuRefPtr->topLevelListPtr != NULL) { TkMenuTopLevelList *topLevelListPtr = menuRefPtr->topLevelListPtr; TkMenuTopLevelList *nextPtr; Tk_Window listtkwin; while (topLevelListPtr != NULL) { /* * Need to get the next pointer first. TkSetWindowMenuBar * changes the list, so that the next pointer is different * after calling it. */ nextPtr = topLevelListPtr->nextPtr; listtkwin = topLevelListPtr->tkwin; TkSetWindowMenuBar(menuPtr->interp, listtkwin, Tk_PathName(menuPtr->tkwin), Tk_PathName(menuPtr->tkwin)); topLevelListPtr = nextPtr; } } interp->result = Tk_PathName(menuPtr->tkwin); return TCL_OK; error: Tk_DestroyWindow(menuPtr->tkwin); return TCL_ERROR;}/* *-------------------------------------------------------------- * * MenuWidgetCmd -- * * This procedure is invoked to process the Tcl command * that corresponds to a widget managed by this module. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */static intMenuWidgetCmd(clientData, interp, argc, argv) ClientData clientData; /* Information about menu widget. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ register TkMenu *menuPtr = (TkMenu *) clientData; register TkMenuEntry *mePtr; int result = TCL_OK; size_t length; int c; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?arg arg ...?\"", (char *) NULL); return TCL_ERROR; } Tcl_Preserve((ClientData) menuPtr); c = argv[1][0]; length = strlen(argv[1]); if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0) && (length >= 2)) { int index; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " activate index\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if (menuPtr->active == index) { goto done; } if (index >= 0) { if ((menuPtr->entries[index]->type == SEPARATOR_ENTRY) || (menuPtr->entries[index]->state == tkDisabledUid)) { index = -1; } } result = TkActivateMenuEntry(menuPtr, index); } else if ((c == 'a') && (strncmp(argv[1], "add", length) == 0) && (length >= 2)) { if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " add type ?options?\"", (char *) NULL); goto error; } if (MenuAddOrInsert(interp, menuPtr, (char *) NULL, argc-2, argv+2) != TCL_OK) { goto error; } } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0) && (length >= 2)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cget option\"", (char *) NULL); goto error; } result = Tk_ConfigureValue(interp, menuPtr->tkwin, tkMenuConfigSpecs, (char *) menuPtr, argv[2], 0); } else if ((c == 'c') && (strncmp(argv[1], "clone", length) == 0) && (length >=2)) { if ((argc < 3) || (argc > 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " clone newMenuName ?menuType?\"", (char *) NULL); goto error; } result = CloneMenu(menuPtr, argv[2], (argc == 3) ? NULL : argv[3]); } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0) && (length >= 2)) { if (argc == 2) { result = Tk_ConfigureInfo(interp, menuPtr->tkwin, tkMenuConfigSpecs, (char *) menuPtr, (char *) NULL, 0); } else if (argc == 3) { result = Tk_ConfigureInfo(interp, menuPtr->tkwin, tkMenuConfigSpecs, (char *) menuPtr, argv[2], 0); } else { result = ConfigureMenu(interp, menuPtr, argc-2, argv+2, TK_CONFIG_ARGV_ONLY); } } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) { int first, last; if ((argc != 3) && (argc != 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " delete first ?last?\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &first) != TCL_OK) { goto error; } if (argc == 3) { last = first; } else { if (TkGetMenuIndex(interp, menuPtr, argv[3], 0, &last) != TCL_OK) { goto error; } } if (menuPtr->tearOff && (first == 0)) { /* * Sorry, can't delete the tearoff entry; must reconfigure * the menu. */ first = 1; } if ((first < 0) || (last < first)) { goto done; } DeleteMenuCloneEntries(menuPtr, first, last); } else if ((c == 'e') && (length >= 7) && (strncmp(argv[1], "entrycget", length) == 0)) { int index; if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " entrycget index option\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if (index < 0) { goto done; } mePtr = menuPtr->entries[index]; Tcl_Preserve((ClientData) mePtr); result = Tk_ConfigureValue(interp, menuPtr->tkwin, tkMenuEntryConfigSpecs, (char *) mePtr, argv[3], COMMAND_MASK << mePtr->type); Tcl_Release((ClientData) mePtr); } else if ((c == 'e') && (length >= 7) && (strncmp(argv[1], "entryconfigure", length) == 0)) { int index; if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " entryconfigure index ?option value ...?\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if (index < 0) { goto done; } mePtr = menuPtr->entries[index]; Tcl_Preserve((ClientData) mePtr); if (argc == 3) { result = Tk_ConfigureInfo(interp, menuPtr->tkwin, tkMenuEntryConfigSpecs, (char *) mePtr, (char *) NULL, COMMAND_MASK << mePtr->type); } else if (argc == 4) { result = Tk_ConfigureInfo(interp, menuPtr->tkwin, tkMenuEntryConfigSpecs, (char *) mePtr, argv[3], COMMAND_MASK << mePtr->type); } else { result = ConfigureMenuCloneEntries(interp, menuPtr, index, argc-3, argv+3, TK_CONFIG_ARGV_ONLY | COMMAND_MASK << mePtr->type); } Tcl_Release((ClientData) mePtr); } else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0) && (length >= 3)) { int index; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " index string\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if (index < 0) { interp->result = "none"; } else { sprintf(interp->result, "%d", index); } } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0) && (length >= 3)) { if (argc < 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " insert index type ?options?\"", (char *) NULL); goto error; } if (MenuAddOrInsert(interp, menuPtr, argv[2], argc-3, argv+3) != TCL_OK) { goto error; } } else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0) && (length >= 3)) { int index; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " invoke index\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if (index < 0) { goto done; } result = TkInvokeMenu(interp, menuPtr, index); } else if ((c == 'p') && (strncmp(argv[1], "post", length) == 0) && (length == 4)) { int x, y; if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " post x y\"", (char *) NULL); goto error; } if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) { goto error; } /* * Tearoff menus are posted differently on Mac and Windows than * non-tearoffs. TkpPostMenu does not actually map the menu's * window on those platforms, and popup menus have to be * handled specially. */ if (menuPtr->menuType != TEAROFF_MENU) { result = TkpPostMenu(interp, menuPtr, x, y); } else { result = TkPostTearoffMenu(interp, menuPtr, x, y); } } else if ((c == 'p') && (strncmp(argv[1], "postcascade", length) == 0) && (length > 4)) { int index; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " postcascade index\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) { result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL); } else { result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]); } } else if ((c == 't') && (strncmp(argv[1], "type", length) == 0)) { int index; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " type index\"", (char *) NULL); goto error; } if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) { goto error; } if (index < 0) { goto done; } mePtr = menuPtr->entries[index]; switch (mePtr->type) { case COMMAND_ENTRY: interp->result = "command"; break; case SEPARATOR_ENTRY: interp->result = "separator"; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -