diff options
Diffstat (limited to 'tk8.6/generic/tkMacWinMenu.c')
-rw-r--r-- | tk8.6/generic/tkMacWinMenu.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/tk8.6/generic/tkMacWinMenu.c b/tk8.6/generic/tkMacWinMenu.c new file mode 100644 index 0000000..ab92fec --- /dev/null +++ b/tk8.6/generic/tkMacWinMenu.c @@ -0,0 +1,146 @@ +/* + * tkMacWinMenu.c -- + * + * This module implements the common elements of the Mac and Windows + * specific features of menus. This file is not used for UNIX. + * + * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkInt.h" +#include "tkMenu.h" + +typedef struct { + int postCommandGeneration; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +static int PreprocessMenu(TkMenu *menuPtr); + +/* + *---------------------------------------------------------------------- + * + * PreprocessMenu -- + * + * The guts of the preprocessing. Recursive. + * + * Results: + * The return value is a standard Tcl result (errors can occur while the + * postcommands are being processed). + * + * Side effects: + * Since commands can get executed while this routine is being executed, + * the entire world can change. + * + *---------------------------------------------------------------------- + */ + +static int +PreprocessMenu( + TkMenu *menuPtr) +{ + int index, result, finished; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + Tcl_Preserve(menuPtr); + + /* + * First, let's process the post command on ourselves. If this command + * destroys this menu, or if there was an error, we are done. + */ + + result = TkPostCommand(menuPtr); + if ((result != TCL_OK) || (menuPtr->tkwin == NULL)) { + goto done; + } + + /* + * Now, we go through structure and process all of the commands. Since the + * structure is changing, we stop after we do one command, and start over. + * When we get through without doing any, we are done. + */ + + do { + finished = 1; + for (index = 0; index < menuPtr->numEntries; index++) { + register TkMenuEntry *entryPtr = menuPtr->entries[index]; + + if ((entryPtr->type == CASCADE_ENTRY) + && (entryPtr->namePtr != NULL) + && (entryPtr->childMenuRefPtr != NULL) + && (entryPtr->childMenuRefPtr->menuPtr != NULL)) { + TkMenu *cascadeMenuPtr = entryPtr->childMenuRefPtr->menuPtr; + + if (cascadeMenuPtr->postCommandGeneration != + tsdPtr->postCommandGeneration) { + cascadeMenuPtr->postCommandGeneration = + tsdPtr->postCommandGeneration; + result = PreprocessMenu(cascadeMenuPtr); + if (result != TCL_OK) { + goto done; + } + finished = 0; + break; + } + } + } + } while (!finished); + + done: + Tcl_Release(menuPtr); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TkPreprocessMenu -- + * + * On the Mac and on Windows, all of the postcommand processing has to be + * done on the entire tree underneath the main window to be posted. This + * means that we have to traverse the menu tree and issue the + * postcommands for all of the menus that have cascades attached. Since + * the postcommands can change the menu structure while we are + * traversing, we have to be extremely careful. Basically, the idea is to + * traverse the structure until we succesfully process one postcommand. + * Then we start over, and do it again until we traverse the whole + * structure without processing any postcommands. + * + * We are also going to set up the cascade back pointers in here since we + * have to traverse the entire structure underneath the menu anyway. We + * can clear the postcommand marks while we do that. + * + * Results: + * The return value is a standard Tcl result (errors can occur while the + * postcommands are being processed). + * + * Side effects: + * Since commands can get executed while this routine is being executed, + * the entire world can change. + * + *---------------------------------------------------------------------- + */ + +int +TkPreprocessMenu( + TkMenu *menuPtr) +{ + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->postCommandGeneration++; + menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration; + return PreprocessMenu(menuPtr); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |