1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
|
/*
* 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.
*
* SCCS: @(#) tkMacWinMenu.c 1.39 97/04/09 14:56:59
*/
#include "tkMenu.h"
static int postCommandGeneration;
static int PreprocessMenu _ANSI_ARGS_((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(menuPtr)
TkMenu *menuPtr;
{
int index, result, finished;
TkMenu *cascadeMenuPtr;
Tcl_Preserve((ClientData) 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++) {
if ((menuPtr->entries[index]->type == CASCADE_ENTRY)
&& (menuPtr->entries[index]->name != NULL)) {
if ((menuPtr->entries[index]->childMenuRefPtr != NULL)
&& (menuPtr->entries[index]->childMenuRefPtr->menuPtr
!= NULL)) {
cascadeMenuPtr =
menuPtr->entries[index]->childMenuRefPtr->menuPtr;
if (cascadeMenuPtr->postCommandGeneration !=
postCommandGeneration) {
cascadeMenuPtr->postCommandGeneration =
postCommandGeneration;
result = PreprocessMenu(cascadeMenuPtr);
if (result != TCL_OK) {
goto done;
}
finished = 0;
break;
}
}
}
}
} while (!finished);
done:
Tcl_Release((ClientData)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(menuPtr)
TkMenu *menuPtr;
{
postCommandGeneration++;
menuPtr->postCommandGeneration = postCommandGeneration;
return PreprocessMenu(menuPtr);
}
|