147 lines
4.1 KiB
C
147 lines
4.1 KiB
C
/*
|
||
* 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 ThreadSpecificData {
|
||
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:
|
||
*/
|