OSDN Git Service

7749c6d00c555d4a91a3d3f7781e92d593e44dd9
[eos/base.git] / util / src / TclTk / tk8.6.12 / generic / tkMacWinMenu.c
1 /*
2  * tkMacWinMenu.c --
3  *
4  *      This module implements the common elements of the Mac and Windows
5  *      specific features of menus. This file is not used for UNIX.
6  *
7  * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
8  *
9  * See the file "license.terms" for information on usage and redistribution of
10  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  */
12
13 #include "tkInt.h"
14 #include "tkMenu.h"
15
16 typedef struct {
17     int postCommandGeneration;
18 } ThreadSpecificData;
19 static Tcl_ThreadDataKey dataKey;
20
21 static int              PreprocessMenu(TkMenu *menuPtr);
22 \f
23 /*
24  *----------------------------------------------------------------------
25  *
26  * PreprocessMenu --
27  *
28  *      The guts of the preprocessing. Recursive.
29  *
30  * Results:
31  *      The return value is a standard Tcl result (errors can occur while the
32  *      postcommands are being processed).
33  *
34  * Side effects:
35  *      Since commands can get executed while this routine is being executed,
36  *      the entire world can change.
37  *
38  *----------------------------------------------------------------------
39  */
40
41 static int
42 PreprocessMenu(
43     TkMenu *menuPtr)
44 {
45     int index, result, finished;
46     ThreadSpecificData *tsdPtr =
47             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
48
49     Tcl_Preserve(menuPtr);
50
51     /*
52      * First, let's process the post command on ourselves. If this command
53      * destroys this menu, or if there was an error, we are done.
54      */
55
56     result = TkPostCommand(menuPtr);
57     if ((result != TCL_OK) || (menuPtr->tkwin == NULL)) {
58         goto done;
59     }
60
61     /*
62      * Now, we go through structure and process all of the commands. Since the
63      * structure is changing, we stop after we do one command, and start over.
64      * When we get through without doing any, we are done.
65      */
66
67     do {
68         finished = 1;
69         for (index = 0; index < menuPtr->numEntries; index++) {
70             TkMenuEntry *entryPtr = menuPtr->entries[index];
71
72             if ((entryPtr->type == CASCADE_ENTRY)
73                     && (entryPtr->namePtr != NULL)
74                     && (entryPtr->childMenuRefPtr != NULL)
75                     && (entryPtr->childMenuRefPtr->menuPtr != NULL)) {
76                 TkMenu *cascadeMenuPtr = entryPtr->childMenuRefPtr->menuPtr;
77
78                 if (cascadeMenuPtr->postCommandGeneration !=
79                         tsdPtr->postCommandGeneration) {
80                     cascadeMenuPtr->postCommandGeneration =
81                             tsdPtr->postCommandGeneration;
82                     result = PreprocessMenu(cascadeMenuPtr);
83                     if (result != TCL_OK) {
84                         goto done;
85                     }
86                     finished = 0;
87                     break;
88                 }
89             }
90         }
91     } while (!finished);
92
93   done:
94     Tcl_Release(menuPtr);
95     return result;
96 }
97 \f
98 /*
99  *----------------------------------------------------------------------
100  *
101  * TkPreprocessMenu --
102  *
103  *      On the Mac and on Windows, all of the postcommand processing has to be
104  *      done on the entire tree underneath the main window to be posted. This
105  *      means that we have to traverse the menu tree and issue the
106  *      postcommands for all of the menus that have cascades attached. Since
107  *      the postcommands can change the menu structure while we are
108  *      traversing, we have to be extremely careful. Basically, the idea is to
109  *      traverse the structure until we succesfully process one postcommand.
110  *      Then we start over, and do it again until we traverse the whole
111  *      structure without processing any postcommands.
112  *
113  *      We are also going to set up the cascade back pointers in here since we
114  *      have to traverse the entire structure underneath the menu anyway. We
115  *      can clear the postcommand marks while we do that.
116  *
117  * Results:
118  *      The return value is a standard Tcl result (errors can occur while the
119  *      postcommands are being processed).
120  *
121  * Side effects:
122  *      Since commands can get executed while this routine is being executed,
123  *      the entire world can change.
124  *
125  *----------------------------------------------------------------------
126  */
127
128 int
129 TkPreprocessMenu(
130     TkMenu *menuPtr)
131 {
132     ThreadSpecificData *tsdPtr =
133             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
134
135     tsdPtr->postCommandGeneration++;
136     menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration;
137     return PreprocessMenu(menuPtr);
138 }
139 \f
140 /*
141  * Local Variables:
142  * mode: c
143  * c-basic-offset: 4
144  * fill-column: 78
145  * End:
146  */