~ubuntu-branches/ubuntu/dapper/tk8.0/dapper-updates

« back to all changes in this revision

Viewing changes to mac/tkMacMenu.c

  • Committer: Bazaar Package Importer
  • Author(s): Mike Markley
  • Date: 2001-07-24 21:57:40 UTC
  • Revision ID: james.westby@ubuntu.com-20010724215740-r70t25rtmbqjil2h
Tags: upstream-8.0.5
ImportĀ upstreamĀ versionĀ 8.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * tkMacMenu.c --
 
3
 *
 
4
 *      This module implements the Mac-platform specific features of menus.
 
5
 *
 
6
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
 
7
 *
 
8
 * See the file "license.terms" for information on usage and redistribution
 
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 
10
 *
 
11
 * RCS: @(#) $Id: tkMacMenu.c,v 1.6 1998/11/11 17:30:44 jingham Exp $
 
12
 */
 
13
 
 
14
#include <Menus.h>
 
15
#include <OSUtils.h>
 
16
#include <Palettes.h>
 
17
#include <Resources.h>
 
18
#include <string.h>
 
19
#include <ToolUtils.h>
 
20
#include <Balloons.h>
 
21
#include <Appearance.h>
 
22
#undef Status
 
23
#include <Devices.h>
 
24
#include "tkMenu.h"
 
25
#include "tkMacInt.h"
 
26
#include "tkMenuButton.h"
 
27
#include "tkColor.h"
 
28
 
 
29
typedef struct MacMenu {
 
30
    MenuHandle menuHdl;         /* The Menu Manager data structure. */
 
31
    Rect menuRect;              /* The rectangle as calculated in the
 
32
                                 * MDEF. This is used to figure ou the
 
33
                                 * clipping rgn before we push
 
34
                                 * the <<MenuSelect>> virtual binding
 
35
                                 * through. */
 
36
} MacMenu;
 
37
 
 
38
typedef struct MenuEntryUserData {
 
39
    Drawable mdefDrawable;
 
40
    TkMenuEntry *mePtr;
 
41
    Tk_Font tkfont;
 
42
    Tk_FontMetrics *fmPtr;
 
43
} MenuEntryUserData;
 
44
/*
 
45
 * Various geometry definitions:
 
46
 */
 
47
 
 
48
#define CASCADE_ARROW_HEIGHT    10
 
49
#define CASCADE_ARROW_WIDTH     8
 
50
#define DECORATION_BORDER_WIDTH 2
 
51
#define MAC_MARGIN_WIDTH        8
 
52
 
 
53
/*
 
54
 * The following are constants relating to the SICNs used for drawing the MDEF.
 
55
 */
 
56
 
 
57
#define SICN_RESOURCE_NUMBER            128
 
58
 
 
59
#define SICN_HEIGHT             16
 
60
#define SICN_ROWS               2
 
61
#define CASCADE_ICON_WIDTH      7
 
62
#define SHIFT_ICON_WIDTH        10
 
63
#define OPTION_ICON_WIDTH       16
 
64
#define CONTROL_ICON_WIDTH      12
 
65
#define COMMAND_ICON_WIDTH      10
 
66
 
 
67
#define CASCADE_ARROW           0
 
68
#define SHIFT_ICON              1
 
69
#define OPTION_ICON             2
 
70
#define CONTROL_ICON            3
 
71
#define COMMAND_ICON            4
 
72
#define DOWN_ARROW              5
 
73
#define UP_ARROW                6
 
74
 
 
75
/*
 
76
 * Platform specific flags for menu entries
 
77
 *
 
78
 * ENTRY_COMMAND_ACCEL          Indicates the entry has the command key
 
79
 *                              in its accelerator string.
 
80
 * ENTRY_OPTION_ACCEL           Indicates the entry has the option key
 
81
 *                              in its accelerator string.
 
82
 * ENTRY_SHIFT_ACCEL            Indicates the entry has the shift key
 
83
 *                              in its accelerator string.
 
84
 * ENTRY_CONTROL_ACCEL          Indicates the entry has the control key
 
85
 *                              in its accelerator string.
 
86
 */
 
87
 
 
88
#define ENTRY_COMMAND_ACCEL     ENTRY_PLATFORM_FLAG1
 
89
#define ENTRY_OPTION_ACCEL      ENTRY_PLATFORM_FLAG2
 
90
#define ENTRY_SHIFT_ACCEL       ENTRY_PLATFORM_FLAG3
 
91
#define ENTRY_CONTROL_ACCEL     ENTRY_PLATFORM_FLAG4
 
92
#define ENTRY_ACCEL_MASK        (ENTRY_COMMAND_ACCEL | ENTRY_OPTION_ACCEL \
 
93
                                | ENTRY_SHIFT_ACCEL | ENTRY_CONTROL_ACCEL)
 
94
 
 
95
/*
 
96
 * This structure is used to keep track of subfields within Macintosh menu
 
97
 * items.
 
98
 */
 
99
 
 
100
typedef struct EntryGeometry {
 
101
    int accelTextStart;         /* Offset into the accel string where
 
102
                                 * the text starts. Everything before
 
103
                                 * this is modifier key descriptions.
 
104
                                 */
 
105
    int modifierWidth;          /* Width of modifier symbols. */
 
106
    int accelTextWidth;         /* Width of the text after the modifier 
 
107
                                 * keys. */
 
108
    int nonAccelMargin;         /* The width of the margin for entries
 
109
                                 * without accelerators. */
 
110
} EntryGeometry;
 
111
 
 
112
/*
 
113
 * Structure to keep track of toplevel windows and their menubars.
 
114
 */
 
115
 
 
116
typedef struct TopLevelMenubarList {
 
117
    struct TopLevelMenubarList *nextPtr;
 
118
                                /* The next window in the list. */
 
119
    Tk_Window tkwin;            /* The toplevel window. */
 
120
    TkMenu *menuPtr;            /* The menu associated with this
 
121
                                 * toplevel. */
 
122
} TopLevelMenubarList;
 
123
 
 
124
/*
 
125
 * Platform-specific flags for menus.
 
126
 *
 
127
 * MENU_APPLE_MENU              0 indicates a custom Apple menu has
 
128
 *                              not been installed; 1 a custom Apple
 
129
 *                              menu has been installed.
 
130
 * MENU_HELP_MENU               0 indicates a custom Help menu has
 
131
 *                              not been installed; 1 a custom Help
 
132
 *                              menu has been installed.
 
133
 * MENU_RECONFIGURE_PENDING     1 indicates that an idle handler has
 
134
 *                              been scheduled to reconfigure the
 
135
 *                              Macintosh MenuHandle.
 
136
 */
 
137
 
 
138
#define MENU_APPLE_MENU                 MENU_PLATFORM_FLAG1
 
139
#define MENU_HELP_MENU                  MENU_PLATFORM_FLAG2
 
140
#define MENU_RECONFIGURE_PENDING        MENU_PLATFORM_FLAG3
 
141
 
 
142
#define CASCADE_CMD (0x1b)      
 
143
                                /* The special command char for cascade
 
144
                                 * menus. */
 
145
#define SEPARATOR_TEXT "\p(-"
 
146
                                /* The text for a menu separator. */
 
147
 
 
148
#define MENUBAR_REDRAW_PENDING 1
 
149
 
 
150
static int gNoTkMenus = 0;      /* This is used by Tk_MacTurnOffMenus as the
 
151
                                 * flag that Tk is not to draw any menus. */
 
152
RgnHandle tkMenuCascadeRgn = NULL;
 
153
                                /* The region to clip drawing to when the
 
154
                                 * MDEF is up. */
 
155
int tkUseMenuCascadeRgn = 0;    /* If this is 1, clipping code
 
156
                                 * should intersect tkMenuCascadeRgn
 
157
                                 * before drawing occurs.
 
158
                                 * tkMenuCascadeRgn will only
 
159
                                 * be valid when the value of this
 
160
                                 * variable is 1. */
 
161
 
 
162
static Tcl_HashTable commandTable;
 
163
                                /* The list of menuInstancePtrs associated with
 
164
                                 * menu ids */
 
165
static short currentAppleMenuID;
 
166
                                /* The id of the current Apple menu. 0 for
 
167
                                 * none. */
 
168
static short currentHelpMenuID; /* The id of the current Help menu. 0 for
 
169
                                 * none. */
 
170
static Tcl_Interp *currentMenuBarInterp;
 
171
                                /* The interpreter of the window that owns
 
172
                                 * the current menubar. */
 
173
static char *currentMenuBarName;
 
174
                                /* Malloced. Name of current menu in menu bar.
 
175
                                 * NULL if no menu set. TO DO: make this a
 
176
                                 * DString. */
 
177
static Tk_Window currentMenuBarOwner;
 
178
                                /* Which window owns the current menu bar. */
 
179
static int helpItemCount;       /* The number of items in the help menu. 
 
180
                                 * -1 means that the help menu is
 
181
                                 * unavailable. This does not include
 
182
                                 * the automatically generated separator. */
 
183
static int inPostMenu;          /* We cannot be re-entrant like X
 
184
                                 * windows. */
 
185
static short lastMenuID;        /* To pass to NewMenu; need to figure out
 
186
                                 * a good way to do this. */
 
187
static unsigned char lastCascadeID;
 
188
                                /* Cascades have to have ids that are
 
189
                                 * less than 256. */
 
190
static MacDrawable macMDEFDrawable;
 
191
                                /* Drawable for use by MDEF code */
 
192
static MDEFScrollFlag = 0;      /* Used so that popups don't scroll too soon. */
 
193
static int menuBarFlags;        /* Used for whether the menu bar needs
 
194
                                 * redrawing or not. */
 
195
static TkMenuDefUPP menuDefProc;/* The routine descriptor to the MDEF proc.
 
196
                                 * The MDEF is needed to draw menus with
 
197
                                 * non-standard attributes and to support
 
198
                                 * tearoff menus. */
 
199
static struct TearoffSelect {
 
200
    TkMenu *menuPtr;            /* The menu that is torn off */
 
201
    Point point;                /* The point to place the new menu */
 
202
    Rect excludeRect;           /* We don't want to drag tearoff highlights
 
203
                                 * when we are in this menu */
 
204
} tearoffStruct;
 
205
 
 
206
static RgnHandle totalMenuRgn = NULL;
 
207
                                /* Used to update windows which have been
 
208
                                 * obscured by menus. */
 
209
static RgnHandle utilRgn = NULL;/* Used when creating the region that is to
 
210
                                 * be clipped out while the MDEF is active. */
 
211
 
 
212
static TopLevelMenubarList *windowListPtr;
 
213
                                /* A list of windows that have menubars set. */
 
214
static MenuItemDrawingUPP tkThemeMenuItemDrawingUPP; 
 
215
                                /* Points to the UPP for theme Item drawing. */
 
216
 
 
217
static GC     appearanceGC = NULL; /* The fake appearance GC.  If you
 
218
                                      pass the foreground of this to TkMacSetColor, 
 
219
                                      it will return false, so you will know 
 
220
                                      not to set the foreground color */
 
221
                                          
 
222
                                
 
223
/*
 
224
 * Forward declarations for procedures defined later in this file:
 
225
 */
 
226
 
 
227
static void             CompleteIdlers _ANSI_ARGS_((TkMenu *menuPtr));
 
228
static void             DrawMenuBarWhenIdle _ANSI_ARGS_((
 
229
                            ClientData clientData));
 
230
static void             DrawMenuBackground _ANSI_ARGS_((
 
231
                            Rect *menuRectPtr, Drawable d, ThemeMenuType type));
 
232
static void             DrawMenuEntryAccelerator _ANSI_ARGS_((
 
233
                            TkMenu *menuPtr, TkMenuEntry *mePtr, 
 
234
                            Drawable d, GC gc, Tk_Font tkfont,
 
235
                            CONST Tk_FontMetrics *fmPtr,
 
236
                            Tk_3DBorder activeBorder, int x, int y,
 
237
                            int width, int height, int drawArrow));
 
238
static void             DrawMenuEntryBackground _ANSI_ARGS_((
 
239
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
 
240
                            Drawable d, Tk_3DBorder activeBorder,
 
241
                            Tk_3DBorder bgBorder, int x, int y,
 
242
                            int width, int heigth));
 
243
static void             DrawMenuEntryIndicator _ANSI_ARGS_((
 
244
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
 
245
                            Drawable d, GC gc, GC indicatorGC, 
 
246
                            Tk_Font tkfont,
 
247
                            CONST Tk_FontMetrics *fmPtr, int x, int y,
 
248
                            int width, int height));
 
249
static void             DrawMenuEntryLabel _ANSI_ARGS_((
 
250
                            TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
 
251
                            GC gc, Tk_Font tkfont,
 
252
                            CONST Tk_FontMetrics *fmPtr, int x, int y,
 
253
                            int width, int height));
 
254
static void             DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
 
255
                            TkMenuEntry *mePtr, Drawable d, GC gc, 
 
256
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, 
 
257
                            int x, int y, int width, int height));
 
258
static void             DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
 
259
                            TkMenuEntry *mePtr, Drawable d, GC gc, 
 
260
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, 
 
261
                            int x, int y, int width, int height));
 
262
static Handle           FixMDEF _ANSI_ARGS_((void));
 
263
static void             GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
 
264
                            TkMenuEntry *mePtr, Tk_Font tkfont,
 
265
                            CONST Tk_FontMetrics *fmPtr, int *modWidthPtr,
 
266
                            int *textWidthPtr, int *heightPtr));
 
267
static void             GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
 
268
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
 
269
                            int *widthPtr, int *heightPtr));
 
270
static void             GetMenuIndicatorGeometry _ANSI_ARGS_((
 
271
                            TkMenu *menuPtr, TkMenuEntry *mePtr, 
 
272
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, 
 
273
                            int *widthPtr, int *heightPtr));
 
274
static void             GetMenuSeparatorGeometry _ANSI_ARGS_((
 
275
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
 
276
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
 
277
                            int *widthPtr, int *heightPtr));
 
278
static void             GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
 
279
                            TkMenuEntry *mePtr, Tk_Font tkfont,
 
280
                            CONST Tk_FontMetrics *fmPtr, int *widthPtr,
 
281
                            int *heightPtr));
 
282
static int              GetNewID _ANSI_ARGS_((Tcl_Interp *interp,
 
283
                            TkMenu *menuInstPtr, int cascade, 
 
284
                            short *menuIDPtr));
 
285
static char             FindMarkCharacter _ANSI_ARGS_((TkMenuEntry *mePtr));
 
286
static void             FreeID _ANSI_ARGS_((short menuID));
 
287
static void             InvalidateMDEFRgns _ANSI_ARGS_((void));
 
288
static void             MenuDefProc _ANSI_ARGS_((short message,
 
289
                            MenuHandle menu, Rect *menuRectPtr,
 
290
                            Point hitPt, short *whichItem,
 
291
                            TkMenuLowMemGlobals *globalsPtr));
 
292
static void             MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));
 
293
static void             ReconfigureIndividualMenu _ANSI_ARGS_((
 
294
                            TkMenu *menuPtr, MenuHandle macMenuHdl, 
 
295
                            int base));
 
296
static void             ReconfigureMacintoshMenu _ANSI_ARGS_ ((
 
297
                            ClientData clientData));
 
298
static void             RecursivelyClearActiveMenu _ANSI_ARGS_((
 
299
                            TkMenu *menuPtr));
 
300
static void             RecursivelyDeleteMenu _ANSI_ARGS_((
 
301
                            TkMenu *menuPtr));
 
302
static void             RecursivelyInsertMenu _ANSI_ARGS_((
 
303
                            TkMenu *menuPtr));
 
304
static void             SetDefaultMenubar _ANSI_ARGS_((void));
 
305
static int              SetMenuCascade _ANSI_ARGS_((TkMenu *menuPtr));
 
306
static void             SetMenuIndicator _ANSI_ARGS_((TkMenuEntry *mePtr));
 
307
static void             AppearanceEntryDrawWrapper _ANSI_ARGS_((TkMenuEntry *mePtr, 
 
308
                            Rect * menuRectPtr, TkMenuLowMemGlobals *globalsPtr,     
 
309
                            Drawable d, Tk_FontMetrics *fmPtr, Tk_Font tkfont,
 
310
                            int x, int y, int width, int height));
 
311
pascal void             tkThemeMenuItemDrawingProc _ANSI_ARGS_ ((const Rect *inBounds,
 
312
                            SInt16 inDepth, Boolean inIsColorDevice, 
 
313
                            SInt32 inUserData));
 
314
 
 
315
 
 
316
/*
 
317
 *----------------------------------------------------------------------
 
318
 *
 
319
 * TkMacUseID --
 
320
 *
 
321
 *      Take the ID out of the available list for new menus. Used by the
 
322
 *      default menu bar's menus so that they do not get created at the tk
 
323
 *      level. See GetNewID for more information.
 
324
 *
 
325
 * Results:
 
326
 *      Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the
 
327
 *      id was in use.
 
328
 *
 
329
 * Side effects:
 
330
 *      A hash table entry in the command table is created with a NULL
 
331
 *      value.
 
332
 *
 
333
 *----------------------------------------------------------------------
 
334
 */
 
335
 
 
336
int
 
337
TkMacUseMenuID(
 
338
    short macID)                        /* The id to take out of the table */
 
339
{
 
340
    Tcl_HashEntry *commandEntryPtr;
 
341
    int newEntry;
 
342
    
 
343
    TkMenuInit();
 
344
    commandEntryPtr = Tcl_CreateHashEntry(&commandTable, (char *) macID,
 
345
            &newEntry);
 
346
    if (newEntry == 1) {
 
347
        Tcl_SetHashValue(commandEntryPtr, NULL);
 
348
        return TCL_OK;
 
349
    } else {
 
350
        return TCL_ERROR;
 
351
    }
 
352
}
 
353
 
 
354
/*
 
355
 *----------------------------------------------------------------------
 
356
 *
 
357
 * GetNewID --
 
358
 *
 
359
 *      Allocates a new menu id and marks it in use. Each menu on the
 
360
 *      mac must be designated by a unique id, which is a short. In
 
361
 *      addition, some ids are reserved by the system. Since Tk uses
 
362
 *      mostly dynamic menus, we must allocate and free these ids on
 
363
 *      the fly. We use the id as a key into a hash table; if there
 
364
 *      is no hash entry, we know that we can use the id.
 
365
 *
 
366
 * Results:
 
367
 *      Returns TCL_OK if succesful; TCL_ERROR if there are no more
 
368
 *      ids of the appropriate type to allocate. menuIDPtr contains
 
369
 *      the new id if succesful.
 
370
 *
 
371
 * Side effects:
 
372
 *      An entry is created for the menu in the command hash table,
 
373
 *      and the hash entry is stored in the appropriate field in the
 
374
 *      menu data structure.
 
375
 *
 
376
 *----------------------------------------------------------------------
 
377
 */
 
378
 
 
379
static int
 
380
GetNewID(
 
381
    Tcl_Interp *interp,         /* Used for error reporting */
 
382
    TkMenu *menuPtr,            /* The menu we are working with */
 
383
    int cascade,                /* 0 if we are working with a normal menu;
 
384
                                   1 if we are working with a cascade */
 
385
    short *menuIDPtr)           /* The resulting id */
 
386
{
 
387
    int found = 0;
 
388
    int newEntry;
 
389
    Tcl_HashEntry *commandEntryPtr;
 
390
    short returnID = *menuIDPtr;
 
391
 
 
392
    /*
 
393
     * The following code relies on shorts and unsigned chars wrapping
 
394
     * when the highest value is incremented. Also, the values between
 
395
     * 236 and 255 inclusive are reserved for DA's by the Mac OS.
 
396
     */
 
397
    
 
398
    if (!cascade) {
 
399
        short curID = lastMenuID + 1;
 
400
        if (curID == 236) {
 
401
            curID = 256;
 
402
        }
 
403
 
 
404
        while (curID != lastMenuID) {
 
405
            commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
 
406
                    (char *) curID, &newEntry);
 
407
            if (newEntry == 1) {
 
408
                found = 1;
 
409
                lastMenuID = returnID = curID;
 
410
                break;
 
411
            }
 
412
            curID++;
 
413
            if (curID == 236) {
 
414
                curID = 256;
 
415
            }
 
416
        }
 
417
    } else {
 
418
    
 
419
        /*
 
420
         * Cascade ids must be between 0 and 235 only, so they must be
 
421
         * dealt with separately.
 
422
         */
 
423
    
 
424
        unsigned char curID = lastCascadeID + 1;
 
425
        if (curID == 236) {
 
426
            curID = 0;
 
427
        }
 
428
        
 
429
        while (curID != lastCascadeID) {
 
430
            commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
 
431
                    (char *) curID, &newEntry);
 
432
            if (newEntry == 1) {
 
433
                found = 1;
 
434
                lastCascadeID = returnID = curID;
 
435
                break;
 
436
            }
 
437
            curID++;
 
438
            if (curID == 236) {
 
439
                curID = 0;
 
440
            }
 
441
        }
 
442
    }
 
443
 
 
444
    if (found) {
 
445
        Tcl_SetHashValue(commandEntryPtr, (char *) menuPtr);
 
446
        *menuIDPtr = returnID;
 
447
        return TCL_OK;
 
448
    } else {
 
449
        Tcl_AppendResult(interp, "No more menus can be allocated.", 
 
450
                (char *) NULL);
 
451
        return TCL_ERROR;
 
452
    }
 
453
}
 
454
 
 
455
/*
 
456
 *----------------------------------------------------------------------
 
457
 *
 
458
 * FreeID --
 
459
 *
 
460
 *      Marks the id as free.
 
461
 *
 
462
 * Results:
 
463
 *      None.
 
464
 *
 
465
 * Side effects:
 
466
 *      The hash table entry for the ID is cleared.
 
467
 *
 
468
 *----------------------------------------------------------------------
 
469
 */
 
470
 
 
471
static void
 
472
FreeID(
 
473
    short menuID)                       /* The id to free */
 
474
{
 
475
    Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
 
476
            (char *) menuID);
 
477
    
 
478
    if (entryPtr != NULL) {
 
479
         Tcl_DeleteHashEntry(entryPtr);
 
480
    }
 
481
    if (menuID == currentAppleMenuID) {
 
482
        currentAppleMenuID = 0;
 
483
    }
 
484
    if (menuID == currentHelpMenuID) {
 
485
        currentHelpMenuID = 0;
 
486
    }
 
487
}
 
488
 
 
489
/*
 
490
 *----------------------------------------------------------------------
 
491
 *
 
492
 * TkpNewMenu --
 
493
 *
 
494
 *      Gets a new blank menu. Only the platform specific options are filled
 
495
 *      in.
 
496
 *
 
497
 * Results:
 
498
 *      Returns a standard TCL error.
 
499
 *
 
500
 * Side effects:
 
501
 *      Allocates a Macintosh menu handle and puts in the platformData
 
502
 *      field of the menuPtr.
 
503
 *
 
504
 *----------------------------------------------------------------------
 
505
 */
 
506
 
 
507
int
 
508
TkpNewMenu(
 
509
    TkMenu *menuPtr)            /* The common structure we are making the
 
510
                                 * platform structure for. */
 
511
{
 
512
    short menuID;
 
513
    Str255 itemText;
 
514
    int length;
 
515
    MenuHandle macMenuHdl;
 
516
    int error = TCL_OK;
 
517
    
 
518
    error = GetNewID(menuPtr->interp, menuPtr, 0, &menuID);
 
519
    if (error != TCL_OK) {
 
520
        return error;
 
521
    }
 
522
    length = strlen(Tk_PathName(menuPtr->tkwin));
 
523
    memmove(&itemText[1], Tk_PathName(menuPtr->tkwin), 
 
524
            (length > 230) ? 230 : length);
 
525
    itemText[0] = (length > 230) ? 230 : length;
 
526
    macMenuHdl = NewMenu(menuID, itemText);
 
527
#ifdef GENERATINGCFM
 
528
    {
 
529
        Handle mdefProc = FixMDEF();
 
530
        if ((mdefProc != NULL)) {
 
531
            (*macMenuHdl)->menuProc = mdefProc;
 
532
        }
 
533
    }
 
534
#endif
 
535
    menuPtr->platformData = (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
 
536
    ((MacMenu *) menuPtr->platformData)->menuHdl = macMenuHdl;
 
537
    SetRect(&((MacMenu *) menuPtr->platformData)->menuRect, 0, 0, 0, 0);
 
538
 
 
539
    if ((currentMenuBarInterp == menuPtr->interp)
 
540
            && (currentMenuBarName != NULL)) {
 
541
        Tk_Window parentWin = Tk_Parent(menuPtr->tkwin);
 
542
        
 
543
        if (strcmp(currentMenuBarName, Tk_PathName(parentWin)) == 0) {
 
544
            if ((strcmp(Tk_PathName(menuPtr->tkwin)
 
545
                    + strlen(Tk_PathName(parentWin)), ".apple") == 0)
 
546
                    || (strcmp(Tk_PathName(menuPtr->tkwin)
 
547
                    + strlen(Tk_PathName(parentWin)), ".help") == 0)) {
 
548
                if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
 
549
                    Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
 
550
                    menuBarFlags |= MENUBAR_REDRAW_PENDING;
 
551
                }
 
552
            }                           
 
553
        }
 
554
    }
 
555
    
 
556
    menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
557
    Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
 
558
    return TCL_OK;
 
559
}
 
560
 
 
561
/*
 
562
 *----------------------------------------------------------------------
 
563
 *
 
564
 * TkpDestroyMenu --
 
565
 *
 
566
 *      Destroys platform-specific menu structures.
 
567
 *
 
568
 * Results:
 
569
 *      None.
 
570
 *
 
571
 * Side effects:
 
572
 *      All platform-specific allocations are freed up.
 
573
 *
 
574
 *----------------------------------------------------------------------
 
575
 */
 
576
 
 
577
void
 
578
TkpDestroyMenu(
 
579
    TkMenu *menuPtr)            /* The common menu structure */
 
580
{
 
581
    MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
 
582
 
 
583
    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
 
584
        Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
 
585
        menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
 
586
    }
 
587
 
 
588
    if ((*macMenuHdl)->menuID == currentHelpMenuID) {
 
589
        MenuHandle helpMenuHdl;
 
590
        
 
591
        if ((HMGetHelpMenuHandle(&helpMenuHdl) == noErr) 
 
592
                && (helpMenuHdl != NULL)) {
 
593
            int i, count = CountMItems(helpMenuHdl);
 
594
            
 
595
            for (i = helpItemCount; i <= count; i++) {
 
596
                DeleteMenuItem(helpMenuHdl, helpItemCount);
 
597
            }
 
598
        }
 
599
        currentHelpMenuID = 0;
 
600
    }
 
601
 
 
602
    if (menuPtr->platformData != NULL) {
 
603
        DeleteMenu((*macMenuHdl)->menuID);
 
604
        FreeID((*macMenuHdl)->menuID);
 
605
        DisposeMenu(macMenuHdl);
 
606
        ckfree((char *) menuPtr->platformData);
 
607
        menuPtr->platformData = NULL;
 
608
    }
 
609
}
 
610
 
 
611
/*
 
612
 *----------------------------------------------------------------------
 
613
 *
 
614
 * SetMenuCascade --
 
615
 *
 
616
 *      Does any cleanup to change a menu from a normal to a cascade.
 
617
 *
 
618
 * Results:
 
619
 *      Standard Tcl error.
 
620
 *
 
621
 * Side effects:
 
622
 *      The mac menu id is reset.
 
623
 *
 
624
 *----------------------------------------------------------------------
 
625
 */
 
626
 
 
627
static int
 
628
SetMenuCascade(
 
629
    TkMenu* menuPtr)            /* The menu we are setting up to be a
 
630
                                 * cascade. */
 
631
{
 
632
    MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
 
633
    short newMenuID, menuID = (*macMenuHdl)->menuID;
 
634
    int error = TCL_OK;
 
635
    
 
636
    if (menuID >= 256) {
 
637
        error = GetNewID(menuPtr->interp, menuPtr, 1, &newMenuID);
 
638
        if (error == TCL_OK) {
 
639
            FreeID(menuID);
 
640
            (*macMenuHdl)->menuID = newMenuID;
 
641
        }
 
642
    }
 
643
    return error;
 
644
}
 
645
 
 
646
/*
 
647
 *----------------------------------------------------------------------
 
648
 *
 
649
 * TkpDestroyMenuEntry --
 
650
 *
 
651
 *      Cleans up platform-specific menu entry items.
 
652
 *
 
653
 * Results:
 
654
 *      None
 
655
 *
 
656
 * Side effects:
 
657
 *      All platform-specific allocations are freed up.
 
658
 *
 
659
 *----------------------------------------------------------------------
 
660
 */
 
661
 
 
662
void
 
663
TkpDestroyMenuEntry(
 
664
    TkMenuEntry *mePtr)         /* The common structure for the menu 
 
665
                                 * entry. */
 
666
{
 
667
    TkMenu *menuPtr = mePtr->menuPtr;    
 
668
  
 
669
    ckfree((char *) mePtr->platformEntryData);
 
670
    if ((menuPtr->platformData != NULL) 
 
671
            && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
 
672
        menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
673
        Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
 
674
    }
 
675
}
 
676
 
 
677
/*
 
678
 *----------------------------------------------------------------------
 
679
 *
 
680
 * GetEntryText --
 
681
 *
 
682
 *      Given a menu entry, gives back the text that should go in it.
 
683
 *      Separators should be done by the caller, as they have to be
 
684
 *      handled specially.
 
685
 *
 
686
 * Results:
 
687
 *      itemText points to the new text for the item.
 
688
 *
 
689
 * Side effects:
 
690
 *      None.
 
691
 *
 
692
 *----------------------------------------------------------------------
 
693
 */
 
694
 
 
695
static void
 
696
GetEntryText(
 
697
    TkMenuEntry *mePtr,         /* A pointer to the menu entry. */
 
698
    Str255 itemText)            /* The pascal string containing the text */
 
699
{
 
700
    if (mePtr->type == TEAROFF_ENTRY) {
 
701
        strcpy((char *)itemText, (const char *)"\p(Tear-off)");
 
702
    } else if (mePtr->imageString != NULL) {
 
703
        strcpy((char *)itemText, (const char *)"\p(Image)");
 
704
    } else if (mePtr->bitmap != None) {
 
705
        strcpy((char *)itemText, (const char *)"\p(Pixmap)");
 
706
    } else if (mePtr->label == NULL || mePtr->labelLength == 0) {
 
707
    
 
708
        /*
 
709
         * The Mac menu manager does not like null strings.
 
710
         */
 
711
         
 
712
        strcpy((char *)itemText, (const char *)"\p ");
 
713
    } else {
 
714
        char *text = mePtr->label;
 
715
        int i;
 
716
        
 
717
        itemText[0] = 0;
 
718
        for (i = 1; (*text != '\0') && (i <= 230); i++, text++) {
 
719
            if ((*text == '.')
 
720
                    && (*(text + 1) != '\0') && (*(text + 1) == '.')
 
721
                    && (*(text + 2) != '\0') && (*(text + 2) == '.')) {
 
722
                itemText[i] = 'ļæ½';
 
723
                text += 2;
 
724
            } else {
 
725
                itemText[i] = *text;
 
726
            }
 
727
            itemText[0] += 1;
 
728
        }
 
729
    }
 
730
}
 
731
 
 
732
/*
 
733
 *----------------------------------------------------------------------
 
734
 *
 
735
 * FindMarkCharacter --
 
736
 *
 
737
 *      Finds the Macintosh mark character based on the font of the
 
738
 *      item. We calculate a good mark character based on the font
 
739
 *      that this item is rendered in.
 
740
 *
 
741
 *      We try the following special mac characters. If none of them
 
742
 *      are present, just use the check mark.
 
743
 *      '' - Check mark character
 
744
 *      'ļæ½' - Bullet character
 
745
 *      '' - Filled diamond
 
746
 *      'ļæ½' - Hollow diamond
 
747
 *      'ļæ½' = Long dash ("em dash")
 
748
 *      '-' = short dash (minus, "en dash");
 
749
 *
 
750
 * Results:
 
751
 *      None.
 
752
 *
 
753
 * Side effects:
 
754
 *      New item is added to platform menu
 
755
 *
 
756
 *----------------------------------------------------------------------
 
757
 */
 
758
 
 
759
static char
 
760
FindMarkCharacter(
 
761
    TkMenuEntry *mePtr)         /* The entry we are finding the character
 
762
                                 * for. */
 
763
{
 
764
    char markChar;
 
765
    Tk_Font tkfont = (mePtr->tkfont == NULL) ? mePtr->menuPtr->tkfont
 
766
            : mePtr->tkfont;
 
767
            
 
768
    if (!TkMacIsCharacterMissing(tkfont, '')) {
 
769
        markChar = '';
 
770
    } else if (!TkMacIsCharacterMissing(tkfont, 'ļæ½')) {
 
771
        markChar = 'ļæ½';
 
772
    } else if (!TkMacIsCharacterMissing(tkfont, '')) {
 
773
        markChar = '';
 
774
    } else if (!TkMacIsCharacterMissing(tkfont, 'ļæ½')) {
 
775
        markChar = 'ļæ½';
 
776
    } else if (!TkMacIsCharacterMissing(tkfont, 'ļæ½')) {
 
777
        markChar = 'ļæ½';
 
778
    } else if (!TkMacIsCharacterMissing(tkfont, '-')) {
 
779
        markChar = '-';
 
780
    } else {
 
781
        markChar = '';
 
782
    }
 
783
    return markChar;
 
784
}
 
785
 
 
786
/*
 
787
 *----------------------------------------------------------------------
 
788
 *
 
789
 * SetMenuIndicator --
 
790
 *
 
791
 *      Sets the Macintosh mark character based on the font of the
 
792
 *      item.
 
793
 *
 
794
 * Results:
 
795
 *      None.
 
796
 *
 
797
 * Side effects:
 
798
 *      New item is added to platform menu
 
799
 *
 
800
 *----------------------------------------------------------------------
 
801
 */
 
802
 
 
803
static void
 
804
SetMenuIndicator(
 
805
    TkMenuEntry *mePtr)         /* The entry we are setting */
 
806
{
 
807
    TkMenu *menuPtr = mePtr->menuPtr;
 
808
    MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
 
809
    char markChar;
 
810
 
 
811
    /*
 
812
     * There can be no indicators on menus that are not checkbuttons
 
813
     * or radiobuttons. However, we should go ahead and set them
 
814
     * so that menus look right when they are displayed. We should
 
815
     * not set cascade entries, however, as the mark character
 
816
     * means something different for cascade items on the Mac.
 
817
     * Also, we do reflect the tearOff menu items in the Mac menu
 
818
     * handle, so we ignore them.
 
819
     */
 
820
 
 
821
    if (mePtr->type == CASCADE_ENTRY) {
 
822
        return;
 
823
    }
 
824
     
 
825
    if (((mePtr->type == RADIO_BUTTON_ENTRY) 
 
826
            || (mePtr->type == CHECK_BUTTON_ENTRY))
 
827
            && (mePtr->indicatorOn)
 
828
            && (mePtr->entryFlags & ENTRY_SELECTED)) {
 
829
        markChar = FindMarkCharacter(mePtr);
 
830
    } else {
 
831
        markChar = 0;
 
832
    }
 
833
    SetItemMark(macMenuHdl, mePtr->index + 1, markChar);
 
834
}
 
835
 
 
836
/*
 
837
 *----------------------------------------------------------------------
 
838
 *
 
839
 * SetMenuTitle --
 
840
 *
 
841
 *      Sets title of menu so that the text displays correctly in menubar.
 
842
 *      This code directly manipulates menu handle data. This code
 
843
 *      was originally part of an ancient Apple Developer Response mail.
 
844
 *
 
845
 * Results:
 
846
 *      None.
 
847
 *
 
848
 * Side effects:
 
849
 *      The menu handle will change size depending on the length of the
 
850
 *      title
 
851
 *
 
852
 *----------------------------------------------------------------------
 
853
 */
 
854
 
 
855
static void
 
856
SetMenuTitle(
 
857
    MenuHandle menuHdl,         /* The menu we are setting the title of. */
 
858
    char *title)                /* The C string to set the title to. */
 
859
{
 
860
    int oldLength, newLength, oldHandleSize, dataLength;
 
861
    Ptr menuDataPtr;
 
862
 
 
863
    menuDataPtr = (Ptr) (*menuHdl)->menuData;
 
864
 
 
865
    if (strncmp(title, menuDataPtr + 1, menuDataPtr[0]) != 0) {    
 
866
        newLength = strlen(title) + 1;
 
867
        oldLength = menuDataPtr[0] + 1;
 
868
        oldHandleSize = GetHandleSize((Handle) menuHdl);
 
869
        dataLength = oldHandleSize - (sizeof(MenuInfo) - sizeof(Str255)) 
 
870
                - oldLength;
 
871
        if (newLength > oldLength) {
 
872
            SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength 
 
873
                    - oldLength));
 
874
            menuDataPtr = (Ptr) (*menuHdl)->menuData;
 
875
        }
 
876
    
 
877
        BlockMove(menuDataPtr + oldLength, menuDataPtr + newLength, 
 
878
                dataLength);
 
879
        BlockMove(title, menuDataPtr + 1, newLength - 1);
 
880
        menuDataPtr[0] = newLength - 1;
 
881
    
 
882
        if (newLength < oldLength) {
 
883
            SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength 
 
884
                    - oldLength));
 
885
        }
 
886
    }
 
887
}
 
888
 
 
889
/*
 
890
 *----------------------------------------------------------------------
 
891
 *
 
892
 * TkpConfigureMenuEntry --
 
893
 *
 
894
 *      Processes configurations for menu entries.
 
895
 *
 
896
 * Results:
 
897
 *      Returns standard TCL result. If TCL_ERROR is returned, then
 
898
 *      interp->result contains an error message.
 
899
 *
 
900
 * Side effects:
 
901
 *      Configuration information get set for mePtr; old resources
 
902
 *      get freed, if any need it.
 
903
 *
 
904
 *----------------------------------------------------------------------
 
905
 */
 
906
 
 
907
int
 
908
TkpConfigureMenuEntry(
 
909
    register TkMenuEntry *mePtr)        /* Information about menu entry;  may
 
910
                                         * or may not already have values for
 
911
                                         * some fields. */
 
912
{
 
913
    TkMenu *menuPtr = mePtr->menuPtr;
 
914
    int index = mePtr->index;
 
915
    MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
 
916
    MenuHandle helpMenuHdl = NULL;
 
917
 
 
918
    /*
 
919
     * Cascade menus have to have menu IDs of less than 256. So
 
920
     * we need to change the child menu if this has been configured
 
921
     * for a cascade item.
 
922
     */
 
923
    
 
924
    if (mePtr->type == CASCADE_ENTRY) {
 
925
        if ((mePtr->childMenuRefPtr != NULL)
 
926
                && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
 
927
            MenuHandle childMenuHdl = ((MacMenu *) mePtr
 
928
                    ->childMenuRefPtr->menuPtr->platformData)->menuHdl;
 
929
            
 
930
            if (childMenuHdl != NULL) {
 
931
                int error = SetMenuCascade(mePtr->childMenuRefPtr->menuPtr);
 
932
                
 
933
                if (error != TCL_OK) {
 
934
                    return error;
 
935
                }
 
936
                
 
937
                if (menuPtr->menuType == MENUBAR) {
 
938
                    SetMenuTitle(childMenuHdl, mePtr->label);
 
939
                }
 
940
            }
 
941
        }
 
942
    }
 
943
        
 
944
    /*
 
945
     * We need to parse the accelerator string. If it has the strings
 
946
     * for Command, Control, Shift or Option, we need to flag it
 
947
     * so we can draw the symbols for it. We also need to precalcuate
 
948
     * the position of the first real character we are drawing.
 
949
     */
 
950
        
 
951
    if (0 == mePtr->accelLength) {
 
952
        ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart = -1;
 
953
    } else {
 
954
        char *accelString = mePtr->accel;
 
955
        mePtr->entryFlags |= ~ENTRY_ACCEL_MASK;
 
956
            
 
957
        while (1) {
 
958
            if ((0 == strncasecmp("Control", accelString, 6))
 
959
                    && (('-' == accelString[6]) || ('+' == accelString[6]))) {
 
960
                mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
 
961
                accelString += 7;
 
962
            } else if ((0 == strncasecmp("Ctrl", accelString, 4))
 
963
                    && (('-' == accelString[4]) || ('+' == accelString[4]))) {
 
964
                mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
 
965
                accelString += 5;
 
966
            } else if ((0 == strncasecmp("Shift", accelString, 5))
 
967
                    && (('-' == accelString[5]) || ('+' == accelString[5]))) {
 
968
                mePtr->entryFlags |= ENTRY_SHIFT_ACCEL;
 
969
                accelString += 6;
 
970
            } else if ((0 == strncasecmp("Option", accelString, 6))
 
971
                    && (('-' == accelString[6]) || ('+' == accelString[6]))) {
 
972
                mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
 
973
                accelString += 7;
 
974
            } else if ((0 == strncasecmp("Opt", accelString, 3))
 
975
                    && (('-' == accelString[3]) || ('+' == accelString[3]))) {
 
976
                mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
 
977
                accelString += 4;
 
978
            } else if ((0 == strncasecmp("Command", accelString, 7))
 
979
                    && (('-' == accelString[7]) || ('+' == accelString[7]))) {
 
980
                mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
 
981
                accelString += 8;
 
982
            } else if ((0 == strncasecmp("Cmd", accelString, 3))
 
983
                    && (('-' == accelString[3]) || ('+' == accelString[3]))) {
 
984
                mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
 
985
                accelString += 4;
 
986
            } else if ((0 == strncasecmp("Alt", accelString, 3))
 
987
                    && (('-' == accelString[3]) || ('+' == accelString[3]))) {
 
988
                mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
 
989
                accelString += 4;
 
990
            } else if ((0 == strncasecmp("Meta", accelString, 4))
 
991
                    && (('-' == accelString[4]) || ('+' == accelString[4]))) {
 
992
                mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
 
993
                accelString += 5;
 
994
            } else {
 
995
                break;
 
996
            }
 
997
        }
 
998
            
 
999
        ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart 
 
1000
                = ((long) accelString - (long) mePtr->accel);
 
1001
    }
 
1002
    
 
1003
    if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
 
1004
        menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
1005
        Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
 
1006
    }
 
1007
    
 
1008
    return TCL_OK;
 
1009
}
 
1010
 
 
1011
/*
 
1012
 *----------------------------------------------------------------------
 
1013
 *
 
1014
 * ReconfigureIndividualMenu --
 
1015
 *
 
1016
 *      This routine redoes the guts of the menu. It works from
 
1017
 *      a base item and offset, so that a regular menu will
 
1018
 *      just have all of its items added, but the help menu will
 
1019
 *      have all of its items appended after the apple-defined
 
1020
 *      items.
 
1021
 *
 
1022
 * Results:
 
1023
 *      None.
 
1024
 *
 
1025
 * Side effects:
 
1026
 *      The Macintosh menu handle is updated
 
1027
 *
 
1028
 *----------------------------------------------------------------------
 
1029
 */
 
1030
 
 
1031
static void
 
1032
ReconfigureIndividualMenu(
 
1033
    TkMenu *menuPtr,            /* The menu we are affecting. */
 
1034
    MenuHandle macMenuHdl,      /* The macintosh menu we are affecting.
 
1035
                                 * Will not necessarily be
 
1036
                                 * menuPtr->platformData because this could
 
1037
                                 * be the help menu. */
 
1038
    int base)                   /* The last index that we do not want
 
1039
                                 * touched. 0 for normal menus;
 
1040
                                 * helpMenuItemCount for help menus. */
 
1041
{
 
1042
    int count;
 
1043
    int index;
 
1044
    TkMenuEntry *mePtr;
 
1045
    Str255 itemText;
 
1046
    int parentDisabled = 0;
 
1047
    
 
1048
    for (mePtr = menuPtr->menuRefPtr->parentEntryPtr; mePtr != NULL;
 
1049
            mePtr = mePtr->nextCascadePtr) {
 
1050
        if (strcmp(Tk_PathName(menuPtr->tkwin), mePtr->name) == 0) {
 
1051
            if (mePtr->state == tkDisabledUid) {
 
1052
                parentDisabled = 1;
 
1053
            }
 
1054
            break;
 
1055
        }
 
1056
    }
 
1057
    
 
1058
    /*
 
1059
     * First, we get rid of all of the old items.
 
1060
     */
 
1061
    
 
1062
    count = CountMItems(macMenuHdl);
 
1063
    for (index = base; index < count; index++) {
 
1064
        DeleteMenuItem(macMenuHdl, base + 1);
 
1065
    }
 
1066
 
 
1067
    count = menuPtr->numEntries;
 
1068
    
 
1069
    for (index = 1; index <= count; index++) {
 
1070
        mePtr = menuPtr->entries[index - 1];
 
1071
    
 
1072
        /*
 
1073
         * We have to do separators separately because SetMenuItemText
 
1074
         * does not parse meta-characters.
 
1075
         */
 
1076
    
 
1077
        if (mePtr->type == SEPARATOR_ENTRY) {
 
1078
            AppendMenu(macMenuHdl, SEPARATOR_TEXT);
 
1079
        } else {
 
1080
            GetEntryText(mePtr, itemText);
 
1081
            AppendMenu(macMenuHdl, "\px");
 
1082
            SetMenuItemText(macMenuHdl, base + index, itemText);
 
1083
        
 
1084
            /*
 
1085
             * Set enabling and disabling correctly.
 
1086
             */
 
1087
 
 
1088
            if (parentDisabled || (mePtr->state == tkDisabledUid)) {
 
1089
                DisableItem(macMenuHdl, base + index);
 
1090
            } else {
 
1091
                EnableItem(macMenuHdl, base + index);
 
1092
            }
 
1093
        
 
1094
            /*
 
1095
             * Set the check mark for check entries and radio entries.
 
1096
             */
 
1097
        
 
1098
            SetItemMark(macMenuHdl, base + index, 0);           
 
1099
            if ((mePtr->type == CHECK_BUTTON_ENTRY)
 
1100
                    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
 
1101
                CheckItem(macMenuHdl, base + index, (mePtr->entryFlags
 
1102
                        & ENTRY_SELECTED) && (mePtr->indicatorOn));
 
1103
                if ((mePtr->indicatorOn)
 
1104
                        && (mePtr->entryFlags & ENTRY_SELECTED)) {
 
1105
                    SetItemMark(macMenuHdl, base + index,
 
1106
                            FindMarkCharacter(mePtr));
 
1107
                }
 
1108
            }
 
1109
        
 
1110
            if (mePtr->type == CASCADE_ENTRY) {
 
1111
                if ((mePtr->childMenuRefPtr != NULL) 
 
1112
                        && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
 
1113
                    MenuHandle childMenuHdl = 
 
1114
                            ((MacMenu *) mePtr->childMenuRefPtr
 
1115
                            ->menuPtr->platformData)->menuHdl;
 
1116
 
 
1117
                    if (childMenuHdl == NULL) {
 
1118
                        childMenuHdl = ((MacMenu *) mePtr->childMenuRefPtr
 
1119
                                ->menuPtr->platformData)->menuHdl;
 
1120
                    }
 
1121
                    if (childMenuHdl != NULL) {
 
1122
                        if (TkMacHaveAppearance() > 1) {
 
1123
                            SetMenuItemHierarchicalID(macMenuHdl, base + index,
 
1124
                                    (*childMenuHdl)->menuID);
 
1125
                        } else {
 
1126
                        SetItemMark(macMenuHdl, base + index,
 
1127
                                (*childMenuHdl)->menuID);
 
1128
                        SetItemCmd(macMenuHdl, base + index, CASCADE_CMD);
 
1129
                    }
 
1130
                    }
 
1131
                    /*
 
1132
                     * If we changed the highligthing of this menu, its
 
1133
                     * children all have to be reconfigured so that
 
1134
                     * their state will be reflected in the menubar.
 
1135
                     */
 
1136
            
 
1137
                    if (!(mePtr->childMenuRefPtr->menuPtr->menuFlags 
 
1138
                                & MENU_RECONFIGURE_PENDING)) {
 
1139
                        mePtr->childMenuRefPtr->menuPtr->menuFlags
 
1140
                                |= MENU_RECONFIGURE_PENDING;
 
1141
                        Tcl_DoWhenIdle(ReconfigureMacintoshMenu, 
 
1142
                                (ClientData) mePtr->childMenuRefPtr->menuPtr);
 
1143
                    }
 
1144
                }
 
1145
            }
 
1146
            
 
1147
            if ((mePtr->type != CASCADE_ENTRY) 
 
1148
                    && (ENTRY_COMMAND_ACCEL 
 
1149
                    == (mePtr->entryFlags & ENTRY_ACCEL_MASK))) {
 
1150
                SetItemCmd(macMenuHdl, index, mePtr
 
1151
                        ->accel[((EntryGeometry *)mePtr->platformEntryData)
 
1152
                        ->accelTextStart]);
 
1153
            }
 
1154
        }
 
1155
    }
 
1156
}
 
1157
 
 
1158
/*
 
1159
 *----------------------------------------------------------------------
 
1160
 *
 
1161
 * ReconfigureMacintoshMenu --
 
1162
 *
 
1163
 *      Rebuilds the Macintosh MenuHandle items from the menu. Called
 
1164
 *      usually as an idle handler, but can be called synchronously
 
1165
 *      if the menu is about to be posted.
 
1166
 *
 
1167
 * Results:
 
1168
 *      None.
 
1169
 *
 
1170
 * Side effects:
 
1171
 *      Configuration information get set for mePtr; old resources
 
1172
 *      get freed, if any need it.
 
1173
 *
 
1174
 *----------------------------------------------------------------------
 
1175
 */
 
1176
 
 
1177
static void
 
1178
ReconfigureMacintoshMenu(
 
1179
    ClientData clientData)              /* Information about menu entry;  may
 
1180
                                         * or may not already have values for
 
1181
                                         * some fields. */
 
1182
{
 
1183
    TkMenu *menuPtr = (TkMenu *) clientData;
 
1184
    MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
 
1185
    MenuHandle helpMenuHdl = NULL;
 
1186
 
 
1187
    menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
 
1188
 
 
1189
    if (NULL == macMenuHdl) {
 
1190
        return;
 
1191
    }
 
1192
 
 
1193
    ReconfigureIndividualMenu(menuPtr, macMenuHdl, 0);
 
1194
 
 
1195
    if (menuPtr->menuFlags & MENU_APPLE_MENU) {
 
1196
        AddResMenu(macMenuHdl, 'DRVR');
 
1197
    }
 
1198
 
 
1199
    if ((*macMenuHdl)->menuID == currentHelpMenuID) {
 
1200
        HMGetHelpMenuHandle(&helpMenuHdl);
 
1201
        if (helpMenuHdl != NULL) {
 
1202
            ReconfigureIndividualMenu(menuPtr, helpMenuHdl, helpItemCount);
 
1203
        }
 
1204
    }
 
1205
 
 
1206
    if (menuPtr->menuType == MENUBAR) {
 
1207
        if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
 
1208
            Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
 
1209
            menuBarFlags |= MENUBAR_REDRAW_PENDING;
 
1210
        }
 
1211
    }
 
1212
}
 
1213
 
 
1214
/*
 
1215
 *----------------------------------------------------------------------
 
1216
 *
 
1217
 * CompleteIdlers --
 
1218
 *
 
1219
 *      Completes all idle handling so that the menus are in sync when
 
1220
 *      the user invokes them with the mouse.
 
1221
 *
 
1222
 * Results:
 
1223
 *      None.
 
1224
 *
 
1225
 * Side effects:
 
1226
 *      The Macintosh menu handles are flushed out.
 
1227
 *
 
1228
 *----------------------------------------------------------------------
 
1229
 */
 
1230
 
 
1231
static void
 
1232
CompleteIdlers(
 
1233
    TkMenu *menuPtr)                    /* The menu we are completing. */
 
1234
{
 
1235
    int i;
 
1236
 
 
1237
    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
 
1238
        Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
 
1239
        ReconfigureMacintoshMenu((ClientData) menuPtr);
 
1240
    }
 
1241
    
 
1242
    for (i = 0; i < menuPtr->numEntries; i++) {
 
1243
        if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
 
1244
            if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
 
1245
                    && (menuPtr->entries[i]->childMenuRefPtr->menuPtr
 
1246
                    != NULL)) {
 
1247
                CompleteIdlers(menuPtr->entries[i]->childMenuRefPtr
 
1248
                        ->menuPtr);
 
1249
            }
 
1250
        }
 
1251
    }
 
1252
}
 
1253
 
 
1254
/*
 
1255
 *----------------------------------------------------------------------
 
1256
 *
 
1257
 * TkpPostMenu --
 
1258
 *
 
1259
 *      Posts a menu on the screen
 
1260
 *
 
1261
 * Results:
 
1262
 *      None.
 
1263
 *
 
1264
 * Side effects:
 
1265
 *      The menu is posted and handled.
 
1266
 *
 
1267
 *----------------------------------------------------------------------
 
1268
 */
 
1269
 
 
1270
int
 
1271
TkpPostMenu(
 
1272
    Tcl_Interp *interp,         /* The interpreter this menu lives in */
 
1273
    TkMenu *menuPtr,            /* The menu we are posting */
 
1274
    int x,                      /* The global x-coordinate of the top, left-
 
1275
                                 * hand corner of where the menu is supposed
 
1276
                                 * to be posted. */
 
1277
    int y)                      /* The global y-coordinate */
 
1278
{
 
1279
    MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
 
1280
    long popUpResult;
 
1281
    int result;
 
1282
    int oldMode;
 
1283
 
 
1284
    if (inPostMenu) {
 
1285
        Tcl_AppendResult(interp,
 
1286
                "Cannot call post menu while already posting menu",
 
1287
                (char *) NULL);
 
1288
        result = TCL_ERROR;
 
1289
    } else {
 
1290
        Window dummyWin;
 
1291
        unsigned int state;
 
1292
        int dummy, mouseX, mouseY;
 
1293
        short menuID;
 
1294
        Window window;
 
1295
        int oldWidth = menuPtr->totalWidth;
 
1296
        Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
 
1297
    
 
1298
        inPostMenu++;
 
1299
        
 
1300
        result = TkPreprocessMenu(menuPtr);
 
1301
        if (result != TCL_OK) {
 
1302
            inPostMenu--;
 
1303
            return result;
 
1304
        }
 
1305
 
 
1306
        /*
 
1307
         * The post commands could have deleted the menu, which means
 
1308
         * we are dead and should go away.
 
1309
         */
 
1310
        
 
1311
        if (menuPtr->tkwin == NULL) {
 
1312
            inPostMenu--;
 
1313
            return TCL_OK;
 
1314
        }
 
1315
 
 
1316
        CompleteIdlers(menuPtr);
 
1317
        if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
 
1318
            Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
 
1319
            DrawMenuBarWhenIdle((ClientData *) NULL);
 
1320
        }
 
1321
        
 
1322
        if (NULL == parentWindow) {
 
1323
            tearoffStruct.excludeRect.top = tearoffStruct.excludeRect.left
 
1324
                    = tearoffStruct.excludeRect.bottom
 
1325
                    = tearoffStruct.excludeRect.right = SHRT_MAX;
 
1326
        } else {
 
1327
            int left, top;
 
1328
        
 
1329
            Tk_GetRootCoords(parentWindow, &left, &top);
 
1330
            tearoffStruct.excludeRect.left = left;
 
1331
            tearoffStruct.excludeRect.top = top;
 
1332
            tearoffStruct.excludeRect.right = left + Tk_Width(parentWindow);
 
1333
            tearoffStruct.excludeRect.bottom = top + Tk_Height(parentWindow);
 
1334
            if (Tk_Class(parentWindow) == Tk_GetUid("Menubutton")) {
 
1335
                TkWindow *parentWinPtr = (TkWindow *) parentWindow;
 
1336
                TkMenuButton *mbPtr = 
 
1337
                        (TkMenuButton *) parentWinPtr->instanceData;
 
1338
                int menuButtonWidth = Tk_Width(parentWindow)
 
1339
                        - 2 * (mbPtr->highlightWidth + mbPtr->borderWidth + 1);
 
1340
                menuPtr->totalWidth = menuButtonWidth > menuPtr->totalWidth
 
1341
                        ? menuButtonWidth : menuPtr->totalWidth;
 
1342
            }
 
1343
        }
 
1344
         
 
1345
        InsertMenu(macMenuHdl, -1);
 
1346
        RecursivelyInsertMenu(menuPtr);
 
1347
        CountMItems(macMenuHdl);
 
1348
        
 
1349
        FixMDEF();
 
1350
        oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
 
1351
        popUpResult = PopUpMenuSelect(macMenuHdl, y, x, menuPtr->active);
 
1352
        Tcl_SetServiceMode(oldMode);
 
1353
 
 
1354
        menuPtr->totalWidth = oldWidth;
 
1355
        RecursivelyDeleteMenu(menuPtr);
 
1356
        DeleteMenu((*macMenuHdl)->menuID);
 
1357
        
 
1358
        /*
 
1359
         * Simulate the mouse up.
 
1360
         */
 
1361
         
 
1362
        XQueryPointer(NULL, None, &dummyWin, &dummyWin, &mouseX,
 
1363
            &mouseY, &dummy, &dummy, &state);
 
1364
        window = Tk_WindowId(menuPtr->tkwin);
 
1365
        TkGenerateButtonEvent(mouseX, mouseY, window, state);
 
1366
        
 
1367
        /*
 
1368
         * Dispatch the command.
 
1369
         */
 
1370
         
 
1371
        menuID = HiWord(popUpResult);
 
1372
        if (menuID != 0) {
 
1373
            result = TkMacDispatchMenuEvent(menuID, LoWord(popUpResult));
 
1374
        } else {
 
1375
            TkMacHandleTearoffMenu();
 
1376
            result = TCL_OK;
 
1377
        }
 
1378
        InvalidateMDEFRgns();
 
1379
        RecursivelyClearActiveMenu(menuPtr);
 
1380
        
 
1381
        inPostMenu--;
 
1382
    }
 
1383
    return result;
 
1384
}
 
1385
 
 
1386
/*
 
1387
 *----------------------------------------------------------------------
 
1388
 *
 
1389
 * TkpMenuNewEntry --
 
1390
 *
 
1391
 *      Adds a pointer to a new menu entry structure with the platform-
 
1392
 *      specific fields filled in. The Macintosh uses the
 
1393
 *      platformEntryData field of the TkMenuEntry record to store
 
1394
 *      geometry information.
 
1395
 *
 
1396
 * Results:
 
1397
 *      Standard TCL error.
 
1398
 *
 
1399
 * Side effects:
 
1400
 *      Storage gets allocated. New menu entry data is put into the
 
1401
 *      platformEntryData field of the mePtr.
 
1402
 *
 
1403
 *----------------------------------------------------------------------
 
1404
 */
 
1405
 
 
1406
int
 
1407
TkpMenuNewEntry(
 
1408
    TkMenuEntry *mePtr)         /* The menu we are adding an entry to */
 
1409
{
 
1410
    EntryGeometry *geometryPtr =
 
1411
            (EntryGeometry *) ckalloc(sizeof(EntryGeometry));
 
1412
    TkMenu *menuPtr = mePtr->menuPtr;
 
1413
    
 
1414
    geometryPtr->accelTextStart = 0;
 
1415
    geometryPtr->accelTextWidth = 0;
 
1416
    geometryPtr->nonAccelMargin = 0;
 
1417
    geometryPtr->modifierWidth = 0;
 
1418
    mePtr->platformEntryData = (TkMenuPlatformEntryData) geometryPtr;
 
1419
    if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
 
1420
        menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
1421
        Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
 
1422
    }
 
1423
    return TCL_OK;
 
1424
}
 
1425
 
 
1426
/*
 
1427
 *----------------------------------------------------------------------
 
1428
 *
 
1429
 * 
 
1430
 * Tk_MacTurnOffMenus --
 
1431
 *
 
1432
 *      Turns off all the menu drawing code.  This is more than just disabling
 
1433
 *      the "menu" command, this means that Tk will NEVER touch the menubar.
 
1434
 *      It is needed in the Plugin, where Tk does not own the menubar.
 
1435
 *
 
1436
 * Results:
 
1437
 *      None.
 
1438
 *
 
1439
 * Side effects:
 
1440
 *      A flag is set which will disable all menu drawing.
 
1441
 *
 
1442
 *----------------------------------------------------------------------
 
1443
 */
 
1444
 
 
1445
EXTERN void
 
1446
Tk_MacTurnOffMenus()
 
1447
{
 
1448
    gNoTkMenus = 1;
 
1449
}
 
1450
 
 
1451
/*
 
1452
 *----------------------------------------------------------------------
 
1453
 *
 
1454
 * 
 
1455
 * DrawMenuBarWhenIdle --
 
1456
 *
 
1457
 *      Update the menu bar next time there is an idle event.
 
1458
 *
 
1459
 * Results:
 
1460
 *      None.
 
1461
 *
 
1462
 * Side effects:
 
1463
 *      Menu bar is redrawn.
 
1464
 *
 
1465
 *----------------------------------------------------------------------
 
1466
 */
 
1467
 
 
1468
static void
 
1469
DrawMenuBarWhenIdle(
 
1470
    ClientData clientData)      /* ignored here */
 
1471
{
 
1472
    TkMenuReferences *menuRefPtr;
 
1473
    TkMenu *appleMenuPtr, *helpMenuPtr;
 
1474
    MenuHandle macMenuHdl;
 
1475
    Tcl_HashEntry *hashEntryPtr;
 
1476
    
 
1477
    /*
 
1478
     * If we have been turned off, exit.
 
1479
     */
 
1480
     
 
1481
    if (gNoTkMenus) {
 
1482
        return;
 
1483
    }
 
1484
    
 
1485
    /*
 
1486
     * We need to clear the apple and help menus of any extra items.
 
1487
     */
 
1488
 
 
1489
    if (currentAppleMenuID != 0) {
 
1490
        hashEntryPtr = Tcl_FindHashEntry(&commandTable,
 
1491
                (char *) currentAppleMenuID);
 
1492
        appleMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
 
1493
        TkpDestroyMenu(appleMenuPtr);
 
1494
        TkpNewMenu(appleMenuPtr);
 
1495
        appleMenuPtr->menuFlags &= ~MENU_APPLE_MENU;
 
1496
        appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
1497
        Tcl_DoWhenIdle(ReconfigureMacintoshMenu, 
 
1498
                (ClientData) appleMenuPtr);
 
1499
    }
 
1500
 
 
1501
    if (currentHelpMenuID != 0) {
 
1502
        hashEntryPtr = Tcl_FindHashEntry(&commandTable,
 
1503
                (char *) currentHelpMenuID);
 
1504
        helpMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
 
1505
        TkpDestroyMenu(helpMenuPtr);
 
1506
        TkpNewMenu(helpMenuPtr);
 
1507
        helpMenuPtr->menuFlags &= ~MENU_HELP_MENU;
 
1508
        helpMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
1509
        Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
 
1510
                (ClientData) helpMenuPtr);
 
1511
    }
 
1512
    
 
1513
    /*
 
1514
     * We need to find the clone of this menu that is the menubar.
 
1515
     * Once we do that, for every cascade in the menu, we need to 
 
1516
     * insert the Mac menu in the Mac menubar. Finally, we need
 
1517
     * to redraw the menubar.
 
1518
     */
 
1519
 
 
1520
    menuRefPtr = NULL;
 
1521
    if (currentMenuBarName != NULL) {
 
1522
        menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
 
1523
                currentMenuBarName);
 
1524
    }
 
1525
    if (menuRefPtr != NULL) {
 
1526
        TkMenu *menuPtr, *menuBarPtr;
 
1527
        TkMenu *cascadeMenuPtr;
 
1528
        char *appleMenuName, *helpMenuName;
 
1529
        int appleIndex = -1, helpIndex = -1;
 
1530
        int i;
 
1531
        
 
1532
        menuPtr = menuRefPtr->menuPtr;
 
1533
        if (menuPtr != NULL) {
 
1534
            TkMenuReferences *specialMenuRefPtr;
 
1535
            TkMenuEntry *specialEntryPtr;
 
1536
            
 
1537
            appleMenuName = ckalloc(strlen(currentMenuBarName)
 
1538
                    + 1 + strlen(".apple") + 1);
 
1539
            sprintf(appleMenuName, "%s.apple", 
 
1540
                    Tk_PathName(menuPtr->tkwin));
 
1541
            specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp, 
 
1542
                    appleMenuName);
 
1543
            if ((specialMenuRefPtr != NULL) 
 
1544
                    && (specialMenuRefPtr->menuPtr != NULL)) {
 
1545
                for (specialEntryPtr 
 
1546
                        = specialMenuRefPtr->parentEntryPtr;
 
1547
                        specialEntryPtr != NULL;
 
1548
                        specialEntryPtr 
 
1549
                        = specialEntryPtr->nextCascadePtr) {
 
1550
                    if (specialEntryPtr->menuPtr == menuPtr) {
 
1551
                        appleIndex = specialEntryPtr->index;
 
1552
                        break;
 
1553
                    }
 
1554
                }
 
1555
            }                                       
 
1556
            ckfree(appleMenuName);
 
1557
            
 
1558
            helpMenuName = ckalloc(strlen(currentMenuBarName)
 
1559
                    + 1 + strlen(".help") + 1);
 
1560
            sprintf(helpMenuName, "%s.help", 
 
1561
                    Tk_PathName(menuPtr->tkwin));
 
1562
            specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp, 
 
1563
                    helpMenuName);
 
1564
            if ((specialMenuRefPtr != NULL)
 
1565
                    && (specialMenuRefPtr->menuPtr != NULL)) {
 
1566
                for (specialEntryPtr 
 
1567
                        = specialMenuRefPtr->parentEntryPtr;
 
1568
                        specialEntryPtr != NULL;
 
1569
                        specialEntryPtr 
 
1570
                        = specialEntryPtr->nextCascadePtr) {
 
1571
                    if (specialEntryPtr->menuPtr == menuPtr) {
 
1572
                        helpIndex = specialEntryPtr->index;
 
1573
                        break;
 
1574
                    }
 
1575
                }
 
1576
            }
 
1577
            ckfree(helpMenuName);  
 
1578
                
 
1579
        }
 
1580
        
 
1581
        for (menuBarPtr = menuPtr; 
 
1582
                (menuBarPtr != NULL) 
 
1583
                && (menuBarPtr->menuType != MENUBAR);
 
1584
                menuBarPtr = menuBarPtr->nextInstancePtr) {
 
1585
        
 
1586
            /*
 
1587
             * Null loop body.
 
1588
             */
 
1589
             
 
1590
        }
 
1591
        
 
1592
        if (menuBarPtr == NULL) {
 
1593
            SetDefaultMenubar();
 
1594
        } else {                    
 
1595
            if (menuBarPtr->tearOff != menuPtr->tearOff) {
 
1596
                if (menuBarPtr->tearOff) {
 
1597
                    appleIndex = (-1 == appleIndex) ? appleIndex
 
1598
                            : appleIndex + 1;
 
1599
                    helpIndex = (-1 == helpIndex) ? helpIndex
 
1600
                            : helpIndex + 1;
 
1601
                } else {
 
1602
                    appleIndex = (-1 == appleIndex) ? appleIndex
 
1603
                            : appleIndex - 1;
 
1604
                    helpIndex = (-1 == helpIndex) ? helpIndex
 
1605
                            : helpIndex - 1;
 
1606
                }
 
1607
            }
 
1608
            ClearMenuBar();
 
1609
            
 
1610
            if (appleIndex == -1) {
 
1611
                InsertMenu(tkAppleMenu, 0);
 
1612
                currentAppleMenuID = 0;
 
1613
            } else {
 
1614
                short appleID;
 
1615
                appleMenuPtr = menuBarPtr->entries[appleIndex]
 
1616
                        ->childMenuRefPtr->menuPtr;
 
1617
                TkpDestroyMenu(appleMenuPtr);
 
1618
                GetNewID(appleMenuPtr->interp, appleMenuPtr, 0, 
 
1619
                        &appleID);
 
1620
                macMenuHdl = NewMenu(appleID, "\p\024");
 
1621
                appleMenuPtr->platformData = 
 
1622
                        (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
 
1623
                ((MacMenu *)appleMenuPtr->platformData)->menuHdl
 
1624
                        = macMenuHdl;
 
1625
                SetRect(&((MacMenu *) appleMenuPtr->platformData)->menuRect,
 
1626
                        0, 0, 0, 0);
 
1627
                appleMenuPtr->menuFlags |= MENU_APPLE_MENU;
 
1628
                if (!(appleMenuPtr->menuFlags 
 
1629
                        & MENU_RECONFIGURE_PENDING)) {
 
1630
                    appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
 
1631
                    Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
 
1632
                            (ClientData) appleMenuPtr);
 
1633
                }
 
1634
                InsertMenu(macMenuHdl, 0);
 
1635
                RecursivelyInsertMenu(appleMenuPtr);
 
1636
                currentAppleMenuID = appleID;
 
1637
            }
 
1638
            if (helpIndex == -1) {
 
1639
                currentHelpMenuID = 0;
 
1640
            }
 
1641
            
 
1642
            for (i = 0; i < menuBarPtr->numEntries; i++) {
 
1643
                if (i == appleIndex) {
 
1644
                    if (menuBarPtr->entries[i]->state == tkDisabledUid) {
 
1645
                        DisableItem(((MacMenu *) menuBarPtr->entries[i]
 
1646
                                ->childMenuRefPtr->menuPtr
 
1647
                                ->platformData)->menuHdl,
 
1648
                                0);
 
1649
                    } else {
 
1650
                        EnableItem(((MacMenu *) menuBarPtr->entries[i]
 
1651
                                ->childMenuRefPtr->menuPtr
 
1652
                                ->platformData)->menuHdl,
 
1653
                                0);
 
1654
                    }                   
 
1655
                    continue;
 
1656
                } else if (i == helpIndex) {
 
1657
                    TkMenu *helpMenuPtr = menuBarPtr->entries[i]
 
1658
                            ->childMenuRefPtr->menuPtr;
 
1659
                    MenuHandle helpMenuHdl = NULL;
 
1660
                    
 
1661
                    if (helpMenuPtr == NULL) {
 
1662
                        continue;
 
1663
                    }
 
1664
                    helpMenuPtr->menuFlags |= MENU_HELP_MENU;
 
1665
                    if (!(helpMenuPtr->menuFlags
 
1666
                            & MENU_RECONFIGURE_PENDING)) {
 
1667
                        helpMenuPtr->menuFlags 
 
1668
                                |= MENU_RECONFIGURE_PENDING;
 
1669
                        Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
 
1670
                                (ClientData) helpMenuPtr);
 
1671
                    }
 
1672
                    macMenuHdl = 
 
1673
                            ((MacMenu *) helpMenuPtr->platformData)->menuHdl;
 
1674
                    currentHelpMenuID = (*macMenuHdl)->menuID;
 
1675
                } else if (menuBarPtr->entries[i]->type 
 
1676
                        == CASCADE_ENTRY) {
 
1677
                    if ((menuBarPtr->entries[i]->childMenuRefPtr != NULL)
 
1678
                            && menuBarPtr->entries[i]->childMenuRefPtr
 
1679
                            ->menuPtr != NULL) {
 
1680
                        cascadeMenuPtr = menuBarPtr->entries[i]
 
1681
                                ->childMenuRefPtr->menuPtr;
 
1682
                        macMenuHdl = ((MacMenu *) cascadeMenuPtr
 
1683
                                ->platformData)->menuHdl;
 
1684
                        DeleteMenu((*macMenuHdl)->menuID);
 
1685
                        InsertMenu(macMenuHdl, 0);
 
1686
                        RecursivelyInsertMenu(cascadeMenuPtr);
 
1687
                        if (menuBarPtr->entries[i]->state == tkDisabledUid) {
 
1688
                            DisableItem(((MacMenu *) menuBarPtr->entries[i]
 
1689
                                    ->childMenuRefPtr->menuPtr
 
1690
                                    ->platformData)->menuHdl,
 
1691
                                    0);
 
1692
                        } else {
 
1693
                            EnableItem(((MacMenu *) menuBarPtr->entries[i]
 
1694
                                    ->childMenuRefPtr->menuPtr
 
1695
                                    ->platformData)->menuHdl,
 
1696
                                    0);
 
1697
                         }
 
1698
                    }
 
1699
                }
 
1700
            }
 
1701
        }
 
1702
    } else {
 
1703
        SetDefaultMenubar();
 
1704
    }
 
1705
    DrawMenuBar();
 
1706
    menuBarFlags &= ~MENUBAR_REDRAW_PENDING;
 
1707
}
 
1708
 
 
1709
 
 
1710
/*
 
1711
 *----------------------------------------------------------------------
 
1712
 *
 
1713
 * RecursivelyInsertMenu --
 
1714
 *
 
1715
 *      Puts all of the cascades of this menu in the Mac hierarchical list.
 
1716
 *
 
1717
 *
 
1718
 * Results:
 
1719
 *      None.
 
1720
 *
 
1721
 * Side effects:
 
1722
 *      The menubar is changed.
 
1723
 *
 
1724
 *----------------------------------------------------------------------
 
1725
 */
 
1726
 
 
1727
static void
 
1728
RecursivelyInsertMenu(
 
1729
    TkMenu *menuPtr)            /* All of the cascade items in this menu
 
1730
                                 * will be inserted into the mac menubar. */
 
1731
{
 
1732
    int i;
 
1733
    TkMenu *cascadeMenuPtr;
 
1734
    MenuHandle macMenuHdl;
 
1735
    
 
1736
    for (i = 0; i < menuPtr->numEntries; i++) {
 
1737
        if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
 
1738
            if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
 
1739
                    && (menuPtr->entries[i]->childMenuRefPtr->menuPtr
 
1740
                    != NULL)) {
 
1741
                cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr;
 
1742
                macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
 
1743
                InsertMenu(macMenuHdl, -1);
 
1744
                RecursivelyInsertMenu(cascadeMenuPtr);
 
1745
            }
 
1746
        }
 
1747
    }
 
1748
}
 
1749
 
 
1750
/*
 
1751
 *----------------------------------------------------------------------
 
1752
 *
 
1753
 * RecursivelyDeleteMenu --
 
1754
 *
 
1755
 *      Takes all of the cascades of this menu out of the Mac hierarchical
 
1756
 *      list.
 
1757
 *
 
1758
 *
 
1759
 * Results:
 
1760
 *      None.
 
1761
 *
 
1762
 * Side effects:
 
1763
 *      The menubar is changed.
 
1764
 *
 
1765
 *----------------------------------------------------------------------
 
1766
 */
 
1767
 
 
1768
static void
 
1769
RecursivelyDeleteMenu(
 
1770
    TkMenu *menuPtr)            /* All of the cascade items in this menu
 
1771
                                 * will be inserted into the mac menubar. */
 
1772
{
 
1773
    int i;
 
1774
    TkMenu *cascadeMenuPtr;
 
1775
    MenuHandle macMenuHdl;
 
1776
    
 
1777
    for (i = 0; i < menuPtr->numEntries; i++) {
 
1778
        if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
 
1779
            if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
 
1780
                    && (menuPtr->entries[i]->childMenuRefPtr->menuPtr
 
1781
                    != NULL)) {
 
1782
                cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr;
 
1783
                macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
 
1784
                DeleteMenu((*macMenuHdl)->menuID);
 
1785
                RecursivelyInsertMenu(cascadeMenuPtr);
 
1786
            }
 
1787
        }
 
1788
    }
 
1789
}
 
1790
 
 
1791
/*
 
1792
 *----------------------------------------------------------------------
 
1793
 *
 
1794
 * SetDefaultMenubar --
 
1795
 *
 
1796
 *      Puts the Apple, File and Edit menus into the Macintosh menubar.
 
1797
 *
 
1798
 * Results:
 
1799
 *      None.
 
1800
 *
 
1801
 * Side effects:
 
1802
 *      The menubar is changed.
 
1803
 *
 
1804
 *----------------------------------------------------------------------
 
1805
 */
 
1806
 
 
1807
static void
 
1808
SetDefaultMenubar()
 
1809
{
 
1810
    if (currentMenuBarName != NULL) {
 
1811
        ckfree(currentMenuBarName);
 
1812
        currentMenuBarName = NULL;
 
1813
    }
 
1814
    currentMenuBarOwner = NULL;
 
1815
    ClearMenuBar();
 
1816
    InsertMenu(tkAppleMenu, 0);
 
1817
    InsertMenu(tkFileMenu, 0);
 
1818
    InsertMenu(tkEditMenu, 0);
 
1819
    if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
 
1820
        Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
 
1821
        menuBarFlags |= MENUBAR_REDRAW_PENDING;
 
1822
    }
 
1823
}
 
1824
 
 
1825
/*
 
1826
 *----------------------------------------------------------------------
 
1827
 *
 
1828
 * TkpSetMainMenubar --
 
1829
 *
 
1830
 *      Puts the menu associated with a window into the menubar. Should
 
1831
 *      only be called when the window is in front.
 
1832
 *
 
1833
 * Results:
 
1834
 *      None.
 
1835
 *
 
1836
 * Side effects:
 
1837
 *      The menubar is changed.
 
1838
 *
 
1839
 *----------------------------------------------------------------------
 
1840
 */
 
1841
 
 
1842
void
 
1843
TkpSetMainMenubar(
 
1844
    Tcl_Interp *interp,         /* The interpreter of the application */
 
1845
    Tk_Window tkwin,            /* The frame we are setting up */
 
1846
    char *menuName)             /* The name of the menu to put in front.
 
1847
                                 * If NULL, use the default menu bar.
 
1848
                                 */
 
1849
{
 
1850
    TkWindow *winPtr = (TkWindow *) tkwin;
 
1851
    WindowRef macWindowPtr = (WindowRef) TkMacGetDrawablePort(winPtr->window);
 
1852
    
 
1853
    if ((macWindowPtr == NULL) || (macWindowPtr != FrontWindow())) {
 
1854
        return;
 
1855
    }
 
1856
 
 
1857
    if ((currentMenuBarInterp != interp) 
 
1858
            || (currentMenuBarOwner != tkwin) 
 
1859
            || (currentMenuBarName == NULL)
 
1860
            || (menuName == NULL) 
 
1861
            || (strcmp(menuName, currentMenuBarName) != 0)) {        
 
1862
        Tk_Window searchWindow;
 
1863
        TopLevelMenubarList *listPtr;
 
1864
                            
 
1865
        if (currentMenuBarName != NULL) {
 
1866
            ckfree(currentMenuBarName);
 
1867
        }
 
1868
 
 
1869
        if (menuName == NULL) {
 
1870
            searchWindow = tkwin;
 
1871
            if (strcmp(Tk_Class(searchWindow), "Menu") == 0) {
 
1872
                TkMenuReferences *menuRefPtr;
 
1873
                    
 
1874
                menuRefPtr = TkFindMenuReferences(interp, Tk_PathName(tkwin));
 
1875
                if (menuRefPtr != NULL) {
 
1876
                    TkMenu *menuPtr = menuRefPtr->menuPtr;
 
1877
                    if (menuPtr != NULL) {
 
1878
                        menuPtr = menuPtr->masterMenuPtr;
 
1879
                        searchWindow = menuPtr->tkwin;
 
1880
                    }
 
1881
                }
 
1882
            } 
 
1883
            for (; searchWindow != NULL;
 
1884
                    searchWindow = Tk_Parent(searchWindow)) {
 
1885
                
 
1886
                for (listPtr = windowListPtr; listPtr != NULL;
 
1887
                        listPtr = listPtr->nextPtr) {
 
1888
                    if (listPtr->tkwin == searchWindow) {
 
1889
                        break;
 
1890
                    }
 
1891
                }
 
1892
                if (listPtr != NULL) {
 
1893
                    menuName = Tk_PathName(listPtr->menuPtr->masterMenuPtr->tkwin);
 
1894
                    break;
 
1895
                }
 
1896
            }
 
1897
        }
 
1898
        
 
1899
        if (menuName == NULL) {
 
1900
            currentMenuBarName = NULL;
 
1901
        } else {            
 
1902
            currentMenuBarName = ckalloc(strlen(menuName) + 1);
 
1903
            strcpy(currentMenuBarName, menuName);
 
1904
        }
 
1905
        currentMenuBarOwner = tkwin;
 
1906
        currentMenuBarInterp = interp;
 
1907
    }
 
1908
    if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
 
1909
        Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
 
1910
        menuBarFlags |= MENUBAR_REDRAW_PENDING;
 
1911
    }
 
1912
}
 
1913
 
 
1914
/*
 
1915
 *----------------------------------------------------------------------
 
1916
 *
 
1917
 * TkpSetWindowMenuBar --
 
1918
 *
 
1919
 *      Associates a given menu with a window.
 
1920
 *
 
1921
 * Results:
 
1922
 *      None.
 
1923
 *
 
1924
 * Side effects:
 
1925
 *      On Windows and UNIX, associates the platform menu with the
 
1926
 *      platform window.
 
1927
 *
 
1928
 *----------------------------------------------------------------------
 
1929
 */
 
1930
 
 
1931
void
 
1932
TkpSetWindowMenuBar(
 
1933
    Tk_Window tkwin,            /* The window we are setting the menu in */
 
1934
    TkMenu *menuPtr)            /* The menu we are setting */
 
1935
{
 
1936
    TopLevelMenubarList *listPtr, *prevPtr;
 
1937
    
 
1938
    /*
 
1939
     * Remove any existing reference to this window.
 
1940
     */
 
1941
    
 
1942
    for (prevPtr = NULL, listPtr = windowListPtr; 
 
1943
            listPtr != NULL; 
 
1944
            prevPtr = listPtr, listPtr = listPtr->nextPtr) {
 
1945
        if (listPtr->tkwin == tkwin) {
 
1946
            break;
 
1947
        }        
 
1948
    }
 
1949
    
 
1950
    if (listPtr != NULL) {
 
1951
        if (prevPtr != NULL) {
 
1952
            prevPtr->nextPtr = listPtr->nextPtr;
 
1953
        } else {
 
1954
            windowListPtr = listPtr->nextPtr;
 
1955
        }
 
1956
        ckfree((char *) listPtr);
 
1957
    }
 
1958
    
 
1959
    if (menuPtr != NULL) {
 
1960
        listPtr = (TopLevelMenubarList *) ckalloc(sizeof(TopLevelMenubarList));
 
1961
        listPtr->nextPtr = windowListPtr;
 
1962
        windowListPtr = listPtr;
 
1963
        listPtr->tkwin = tkwin;
 
1964
        listPtr->menuPtr = menuPtr;
 
1965
    }
 
1966
}
 
1967
 
 
1968
/*
 
1969
 *----------------------------------------------------------------------
 
1970
 *
 
1971
 * TkMacDispatchMenuEvent --
 
1972
 *
 
1973
 *      Given a menu id and an item, dispatches the command associated
 
1974
 *      with it.
 
1975
 *
 
1976
 * Results:
 
1977
 *      None.
 
1978
 *
 
1979
 * Side effects:
 
1980
 *      Commands get executed.
 
1981
 *
 
1982
 *----------------------------------------------------------------------
 
1983
 */
 
1984
 
 
1985
int
 
1986
TkMacDispatchMenuEvent(
 
1987
    int menuID,         /* The menu id of the menu we are invoking */
 
1988
    int index)          /* The one-based index of the item that was 
 
1989
                         * selected. */
 
1990
{
 
1991
    int result = TCL_OK;
 
1992
    if (menuID != 0) {
 
1993
        if (menuID == kHMHelpMenuID) {
 
1994
            if (currentMenuBarOwner != NULL) {
 
1995
                TkMenuReferences *helpMenuRef;
 
1996
                char *helpMenuName = ckalloc(strlen(currentMenuBarName)
 
1997
                        + strlen(".help") + 1);
 
1998
                sprintf(helpMenuName, "%s.help", currentMenuBarName);
 
1999
                helpMenuRef = TkFindMenuReferences(currentMenuBarInterp,
 
2000
                        helpMenuName);
 
2001
                ckfree(helpMenuName);
 
2002
                if ((helpMenuRef != NULL) && (helpMenuRef->menuPtr != NULL)) {
 
2003
                    int newIndex = index - helpItemCount - 1;
 
2004
                    result = TkInvokeMenu(currentMenuBarInterp,
 
2005
                            helpMenuRef->menuPtr, newIndex);
 
2006
                }
 
2007
            }
 
2008
        } else {
 
2009
            Tcl_HashEntry *commandEntryPtr = 
 
2010
                    Tcl_FindHashEntry(&commandTable, (char *) menuID);
 
2011
            TkMenu *menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
 
2012
            if ((currentAppleMenuID == menuID) 
 
2013
                    && (index > menuPtr->numEntries + 1)) {
 
2014
                Str255 itemText;
 
2015
                
 
2016
                GetMenuItemText(GetMenuHandle(menuID), index, itemText);
 
2017
                OpenDeskAcc(itemText);
 
2018
                result = TCL_OK;
 
2019
            } else {
 
2020
                result = TkInvokeMenu(menuPtr->interp, menuPtr, index - 1);
 
2021
            }
 
2022
        }
 
2023
    }
 
2024
    return result;
 
2025
}
 
2026
 
 
2027
/*
 
2028
 *----------------------------------------------------------------------
 
2029
 *
 
2030
 * GetMenuIndicatorGeometry --
 
2031
 *
 
2032
 *      Gets the width and height of the indicator area of a menu.
 
2033
 *
 
2034
 * Results:
 
2035
 *      widthPtr and heightPtr are set.
 
2036
 *
 
2037
 * Side effects:
 
2038
 *      None.
 
2039
 *
 
2040
 *----------------------------------------------------------------------
 
2041
 */
 
2042
 
 
2043
static void
 
2044
GetMenuIndicatorGeometry (
 
2045
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
2046
    TkMenuEntry *mePtr,                 /* The entry we are measuring */
 
2047
    Tk_Font tkfont,                     /* Precalculated font */
 
2048
    CONST Tk_FontMetrics *fmPtr,        /* Precalculated font metrics */
 
2049
    int *widthPtr,                      /* The resulting width */
 
2050
    int *heightPtr)                     /* The resulting height */
 
2051
{
 
2052
    char markChar;
 
2053
    
 
2054
    *heightPtr = fmPtr->linespace;
 
2055
 
 
2056
    markChar = (char) FindMarkCharacter(mePtr);
 
2057
    *widthPtr = Tk_TextWidth(tkfont, &markChar, 1) + 4;
 
2058
}
 
2059
 
 
2060
/*
 
2061
 *----------------------------------------------------------------------
 
2062
 *
 
2063
 * GetMenuAccelGeometry --
 
2064
 *
 
2065
 *      Gets the width and height of the accelerator area of a menu.
 
2066
 *
 
2067
 * Results:
 
2068
 *      widthPtr and heightPtr are set.
 
2069
 *
 
2070
 * Side effects:
 
2071
 *      None.
 
2072
 *
 
2073
 *----------------------------------------------------------------------
 
2074
 */
 
2075
 
 
2076
static void
 
2077
GetMenuAccelGeometry (
 
2078
    TkMenu *menuPtr,                    /* The menu we are measuring */
 
2079
    TkMenuEntry *mePtr,                 /* The entry we are measuring */
 
2080
    Tk_Font tkfont,                     /* The precalculated font */
 
2081
    CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
 
2082
    int *modWidthPtr,                   /* The width of all of the key
 
2083
                                         * modifier symbols. */
 
2084
    int *textWidthPtr,                  /* The resulting width */
 
2085
    int *heightPtr)                     /* The resulting height */
 
2086
{
 
2087
    *heightPtr = fmPtr->linespace;
 
2088
    *modWidthPtr = 0;
 
2089
    if (mePtr->type == CASCADE_ENTRY) {
 
2090
        *textWidthPtr = SICN_HEIGHT;
 
2091
        *modWidthPtr = Tk_TextWidth(tkfont, "W", 1);
 
2092
    } else if (0 == mePtr->accelLength) {
 
2093
        *textWidthPtr = 0;
 
2094
    } else {
 
2095
        
 
2096
        if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
 
2097
            *textWidthPtr = Tk_TextWidth(tkfont, mePtr->accel,
 
2098
                    mePtr->accelLength);
 
2099
        } else {
 
2100
            int emWidth = Tk_TextWidth(tkfont, "W", 1) + 1;
 
2101
            if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
 
2102
                int width = Tk_TextWidth(tkfont, mePtr->accel,
 
2103
                        mePtr->accelLength);
 
2104
                *textWidthPtr = emWidth;
 
2105
                if (width < emWidth) {
 
2106
                    *modWidthPtr = 0;
 
2107
                } else {
 
2108
                    *modWidthPtr = width - emWidth;
 
2109
                }   
 
2110
            } else {
 
2111
                int length = ((EntryGeometry *)mePtr->platformEntryData)
 
2112
                        ->accelTextStart;
 
2113
                if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
 
2114
                    *modWidthPtr += CONTROL_ICON_WIDTH;
 
2115
                }
 
2116
                if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
 
2117
                    *modWidthPtr += SHIFT_ICON_WIDTH;
 
2118
                }
 
2119
                if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
 
2120
                    *modWidthPtr += OPTION_ICON_WIDTH;
 
2121
                }
 
2122
                if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
 
2123
                    *modWidthPtr += COMMAND_ICON_WIDTH;
 
2124
                }
 
2125
                if (1 == (mePtr->accelLength - length)) {
 
2126
                    *textWidthPtr = emWidth;
 
2127
                } else {
 
2128
                    *textWidthPtr += Tk_TextWidth(tkfont, mePtr->accel 
 
2129
                            + length, mePtr->accelLength - length);
 
2130
                }
 
2131
            }
 
2132
        }
 
2133
    }
 
2134
}
 
2135
 
 
2136
/*
 
2137
 *----------------------------------------------------------------------
 
2138
 *
 
2139
 * GetTearoffEntryGeometry --
 
2140
 *
 
2141
 *      Gets the width and height of of a tearoff entry.
 
2142
 *
 
2143
 * Results:
 
2144
 *      widthPtr and heightPtr are set.
 
2145
 *
 
2146
 * Side effects:
 
2147
 *      None.
 
2148
 *
 
2149
 *----------------------------------------------------------------------
 
2150
 */
 
2151
 
 
2152
static void
 
2153
GetTearoffEntryGeometry (
 
2154
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
2155
    TkMenuEntry *mePtr,                 /* The entry we are measuring */
 
2156
    Tk_Font tkfont,                     /* The precalculated font */
 
2157
    CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
 
2158
    int *widthPtr,                      /* The resulting width */
 
2159
    int *heightPtr)                     /* The resulting height */
 
2160
{
 
2161
    if ((GetResource('MDEF', 591) == NULL) &&
 
2162
            (menuPtr->menuType == MASTER_MENU)) {
 
2163
        *heightPtr = fmPtr->linespace;
 
2164
        *widthPtr = 0;
 
2165
    } else {
 
2166
        *widthPtr = *heightPtr = 0;
 
2167
    }
 
2168
}
 
2169
 
 
2170
/*
 
2171
 *----------------------------------------------------------------------
 
2172
 *
 
2173
 * GetMenuSeparatorGeometry --
 
2174
 *
 
2175
 *      Gets the width and height of menu separator.
 
2176
 *
 
2177
 * Results:
 
2178
 *      widthPtr and heightPtr are set.
 
2179
 *
 
2180
 * Side effects:
 
2181
 *      None.
 
2182
 *
 
2183
 *----------------------------------------------------------------------
 
2184
 */
 
2185
 
 
2186
static void
 
2187
GetMenuSeparatorGeometry(
 
2188
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
2189
    TkMenuEntry *mePtr,                 /* The entry we are measuring */
 
2190
    Tk_Font tkfont,                     /* The precalculated font */
 
2191
    CONST Tk_FontMetrics *fmPtr,        /* The precalcualted font metrics */
 
2192
    int *widthPtr,                      /* The resulting width */
 
2193
    int *heightPtr)                     /* The resulting height */
 
2194
{
 
2195
    if (TkMacHaveAppearance() > 1) {
 
2196
        SInt16 outHeight;
 
2197
        
 
2198
        GetThemeMenuSeparatorHeight(&outHeight);
 
2199
        *widthPtr = 0;
 
2200
        *heightPtr = outHeight;
 
2201
    } else {
 
2202
        *widthPtr = 0;
 
2203
        *heightPtr = fmPtr->linespace;
 
2204
    }
 
2205
}
 
2206
 
 
2207
/*
 
2208
 *----------------------------------------------------------------------
 
2209
 *
 
2210
 * DrawMenuEntryIndicator --
 
2211
 *
 
2212
 *      This procedure draws the indicator part of a menu.
 
2213
 *
 
2214
 * Results:
 
2215
 *      None.
 
2216
 *
 
2217
 * Side effects:
 
2218
 *      Commands are output to X to display the menu in its
 
2219
 *      current mode.
 
2220
 *
 
2221
 *----------------------------------------------------------------------
 
2222
 */
 
2223
 
 
2224
static void
 
2225
DrawMenuEntryIndicator(
 
2226
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
2227
    TkMenuEntry *mePtr,                 /* The entry we are drawing */
 
2228
    Drawable d,                         /* The drawable we are drawing */
 
2229
    GC gc,                              /* The GC we are drawing with */
 
2230
    GC indicatorGC,                     /* The GC to use for the indicator */
 
2231
    Tk_Font tkfont,                     /* The precalculated font */
 
2232
    CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
 
2233
    int x,                              /* topleft hand corner of entry */
 
2234
    int y,                              /* topleft hand corner of entry */
 
2235
    int width,                          /* width of entry */
 
2236
    int height)                         /* height of entry */
 
2237
{
 
2238
    if (((mePtr->type == CHECK_BUTTON_ENTRY) || 
 
2239
            (mePtr->type == RADIO_BUTTON_ENTRY))
 
2240
            && (mePtr->indicatorOn)
 
2241
            && (mePtr->entryFlags & ENTRY_SELECTED)) {
 
2242
        int baseline;
 
2243
        short markShort;
 
2244
        char markChar;
 
2245
    
 
2246
        baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
 
2247
        GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl,
 
2248
                mePtr->index + 1, &markShort);
 
2249
        if (markShort != 0) {
 
2250
            markChar = (char) markShort;
 
2251
            Tk_DrawChars(menuPtr->display, d, gc, tkfont, &markChar, 1,
 
2252
                    x + 2, baseline);
 
2253
        }
 
2254
    }    
 
2255
}
 
2256
 
 
2257
/*
 
2258
 *----------------------------------------------------------------------
 
2259
 *
 
2260
 * DrawMenuBackground --
 
2261
 *
 
2262
 *      If Appearance is present, draws the Appearance background
 
2263
 *
 
2264
 * Results:
 
2265
 *      Nothing
 
2266
 *
 
2267
 * Side effects:
 
2268
 *      Commands are output to X to display the menu in its
 
2269
 *      current mode.
 
2270
 *
 
2271
 *----------------------------------------------------------------------
 
2272
 */
 
2273
static void
 
2274
DrawMenuBackground(
 
2275
    Rect     *menuRectPtr,      /* The menu rect */
 
2276
    Drawable d,                 /* What we are drawing into */
 
2277
    ThemeMenuType type                  /* Type of menu */    
 
2278
    )
 
2279
{
 
2280
    if (!TkMacHaveAppearance()) {
 
2281
        return;
 
2282
    } else {
 
2283
        CGrafPtr saveWorld;
 
2284
        GDHandle saveDevice;
 
2285
        GWorldPtr destPort;
 
2286
 
 
2287
        destPort = TkMacGetDrawablePort(d);
 
2288
        GetGWorld(&saveWorld, &saveDevice);
 
2289
        SetGWorld(destPort, NULL);
 
2290
        TkMacSetUpClippingRgn(d);
 
2291
        DrawThemeMenuBackground (menuRectPtr, type);
 
2292
        SetGWorld(saveWorld, saveDevice);    
 
2293
        return;
 
2294
    }
 
2295
}
 
2296
 
 
2297
/*
 
2298
 *----------------------------------------------------------------------
 
2299
 *
 
2300
 * DrawSICN --
 
2301
 *
 
2302
 *      Given a resource id and an index, loads the appropriate SICN
 
2303
 *      and draws it into a given drawable using the given gc.
 
2304
 *
 
2305
 * Results:
 
2306
 *      Returns 1 if the SICN was found, 0 if not found.
 
2307
 *
 
2308
 * Side effects:
 
2309
 *      Commands are output to X to display the menu in its
 
2310
 *      current mode.
 
2311
 *
 
2312
 *----------------------------------------------------------------------
 
2313
 */
 
2314
static int
 
2315
DrawSICN(
 
2316
    int resourceID,                 /* The resource # of the SICN table */
 
2317
    int index,                      /* The index into the SICN table of the
 
2318
                                     * icon we want. */
 
2319
    Drawable d,                     /* What we are drawing into */
 
2320
    GC gc,                          /* The GC to draw with */
 
2321
    int x,                          /* The left hand coord of the SICN */
 
2322
    int y)                          /* The top coord of the SICN */
 
2323
{
 
2324
    Handle sicnHandle = (Handle) GetResource('SICN', SICN_RESOURCE_NUMBER);
 
2325
    
 
2326
    if (NULL == sicnHandle) {
 
2327
        return 0;
 
2328
    } else {
 
2329
        BitMap sicnBitmap;
 
2330
        Rect destRect;
 
2331
        CGrafPtr saveWorld;
 
2332
        GDHandle saveDevice;
 
2333
        GWorldPtr destPort;
 
2334
        BitMapPtr destBitMap;
 
2335
        RGBColor origForeColor, origBackColor, foreColor, backColor;
 
2336
 
 
2337
        HLock(sicnHandle);
 
2338
        destPort = TkMacGetDrawablePort(d);
 
2339
        GetGWorld(&saveWorld, &saveDevice);
 
2340
        SetGWorld(destPort, NULL);
 
2341
        TkMacSetUpClippingRgn(d);
 
2342
        TkMacSetUpGraphicsPort(gc);
 
2343
        GetForeColor(&origForeColor);
 
2344
        GetBackColor(&origBackColor);
 
2345
        
 
2346
        if (TkSetMacColor(gc->foreground, &foreColor) == true) {
 
2347
            RGBForeColor(&foreColor);
 
2348
        }
 
2349
        
 
2350
        if (TkSetMacColor(gc->background, &backColor) == true) {
 
2351
            RGBBackColor(&backColor);
 
2352
        }
 
2353
 
 
2354
        SetRect(&destRect, x, y, x + SICN_HEIGHT, y + SICN_HEIGHT);
 
2355
        sicnBitmap.baseAddr = (Ptr) (*sicnHandle) + index * SICN_HEIGHT
 
2356
            * SICN_ROWS;
 
2357
        sicnBitmap.rowBytes = SICN_ROWS;
 
2358
        SetRect(&sicnBitmap.bounds, 0, 0, 16, 16);
 
2359
        destBitMap = &((GrafPtr) destPort)->portBits;
 
2360
        CopyBits(&sicnBitmap, destBitMap, &sicnBitmap.bounds, &destRect, 
 
2361
            destPort->txMode, NULL);
 
2362
        HUnlock(sicnHandle);
 
2363
        RGBForeColor(&origForeColor);
 
2364
        RGBBackColor(&origBackColor);
 
2365
        SetGWorld(saveWorld, saveDevice);    
 
2366
        return 1;
 
2367
    }
 
2368
}
 
2369
 
 
2370
/*
 
2371
 *----------------------------------------------------------------------
 
2372
 *
 
2373
 * DrawMenuEntryAccelerator --
 
2374
 *
 
2375
 *      This procedure draws the accelerator part of a menu. We
 
2376
 *      need to decide what to draw here. Should we replace strings
 
2377
 *      like "Control", "Command", etc?
 
2378
 *
 
2379
 * Results:
 
2380
 *      None.
 
2381
 *
 
2382
 * Side effects:
 
2383
 *      Commands are output to X to display the menu in its
 
2384
 *      current mode.
 
2385
 *
 
2386
 *----------------------------------------------------------------------
 
2387
 */
 
2388
 
 
2389
static void
 
2390
DrawMenuEntryAccelerator(
 
2391
    TkMenu *menuPtr,                /* The menu we are drawing */
 
2392
    TkMenuEntry *mePtr,             /* The entry we are drawing */
 
2393
    Drawable d,                     /* The drawable we are drawing in */
 
2394
    GC gc,                          /* The gc to draw into */
 
2395
    Tk_Font tkfont,                 /* The precalculated font */
 
2396
    CONST Tk_FontMetrics *fmPtr,    /* The precalculated font metrics */
 
2397
    Tk_3DBorder activeBorder,       /* border for menu background */
 
2398
    int x,                          /* The left side of the entry */
 
2399
    int y,                          /* The top of the entry */
 
2400
    int width,                      /* The width of the entry */
 
2401
    int height,                     /* The height of the entry */
 
2402
    int drawArrow)                  /* Whether or not to draw cascade arrow */
 
2403
{
 
2404
    if (mePtr->type == CASCADE_ENTRY) {
 
2405
        /*
 
2406
         * Under Appearance, we let the Appearance Manager draw the icon
 
2407
         */
 
2408
         
 
2409
        if (!TkMacHaveAppearance()) {
 
2410
        if (0 == DrawSICN(SICN_RESOURCE_NUMBER, CASCADE_ARROW, d, gc,
 
2411
                x + width - SICN_HEIGHT, (y + (height / 2))
 
2412
                - (SICN_HEIGHT / 2))) {
 
2413
            XPoint points[3];
 
2414
            Tk_Window tkwin = menuPtr->tkwin;
 
2415
 
 
2416
            if (mePtr->type == CASCADE_ENTRY) {
 
2417
                points[0].x = width - menuPtr->activeBorderWidth
 
2418
                        - MAC_MARGIN_WIDTH - CASCADE_ARROW_WIDTH;
 
2419
                points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2;
 
2420
                points[1].x = points[0].x;
 
2421
                points[1].y = points[0].y + CASCADE_ARROW_HEIGHT;
 
2422
                points[2].x = points[0].x + CASCADE_ARROW_WIDTH;
 
2423
                points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2;
 
2424
                Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points, 
 
2425
                        3, DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT);
 
2426
            }
 
2427
        }
 
2428
        }
 
2429
    } else if (mePtr->accelLength != 0) {
 
2430
        int leftEdge = x + width;
 
2431
        int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
 
2432
 
 
2433
        if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
 
2434
            leftEdge -= ((EntryGeometry *) mePtr->platformEntryData)
 
2435
                    ->accelTextWidth;
 
2436
            Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
 
2437
                    mePtr->accelLength, leftEdge, baseline);
 
2438
        } else {
 
2439
            EntryGeometry *geometryPtr = 
 
2440
                    (EntryGeometry *) mePtr->platformEntryData;
 
2441
            int length = mePtr->accelLength - geometryPtr->accelTextStart;
 
2442
            
 
2443
            leftEdge -= geometryPtr->accelTextWidth;
 
2444
            if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
 
2445
                leftEdge -= geometryPtr->modifierWidth;
 
2446
            }
 
2447
            
 
2448
            Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel 
 
2449
                    + geometryPtr->accelTextStart, length, leftEdge, baseline);
 
2450
 
 
2451
            if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
 
2452
                leftEdge -= COMMAND_ICON_WIDTH;
 
2453
                DrawSICN(SICN_RESOURCE_NUMBER, COMMAND_ICON, d, gc,
 
2454
                        leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
 
2455
            }
 
2456
 
 
2457
            if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
 
2458
                leftEdge -= OPTION_ICON_WIDTH;
 
2459
                DrawSICN(SICN_RESOURCE_NUMBER, OPTION_ICON, d, gc,
 
2460
                        leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
 
2461
            }
 
2462
 
 
2463
            if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
 
2464
                leftEdge -= SHIFT_ICON_WIDTH;
 
2465
                DrawSICN(SICN_RESOURCE_NUMBER, SHIFT_ICON, d, gc,
 
2466
                        leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
 
2467
            }
 
2468
 
 
2469
            if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
 
2470
                leftEdge -= CONTROL_ICON_WIDTH;
 
2471
                DrawSICN(SICN_RESOURCE_NUMBER, CONTROL_ICON, d, gc,
 
2472
                        leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
 
2473
            }
 
2474
        }
 
2475
    }
 
2476
}
 
2477
 
 
2478
/*
 
2479
 *----------------------------------------------------------------------
 
2480
 *
 
2481
 * DrawMenuSeparator --
 
2482
 *
 
2483
 *      The menu separator is drawn.
 
2484
 *
 
2485
 * Results:
 
2486
 *      None.
 
2487
 *
 
2488
 * Side effects:
 
2489
 *      Commands are output to X to display the menu in its
 
2490
 *      current mode.
 
2491
 *
 
2492
 *----------------------------------------------------------------------
 
2493
 */
 
2494
 
 
2495
static void
 
2496
DrawMenuSeparator(
 
2497
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
2498
    TkMenuEntry *mePtr,                 /* The entry we are drawing */
 
2499
    Drawable d,                         /* The drawable we are drawing into */
 
2500
    GC gc,                              /* The gc we are drawing with */
 
2501
    Tk_Font tkfont,                     /* The precalculated font */
 
2502
    CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
 
2503
    int x,                              /* left coordinate of entry */
 
2504
    int y,                              /* top coordinate of entry */
 
2505
    int width,                          /* width of entry */
 
2506
    int height)                         /* height of entry */
 
2507
{
 
2508
    CGrafPtr saveWorld;
 
2509
    GDHandle saveDevice;
 
2510
    GWorldPtr destPort;
 
2511
   
 
2512
    destPort = TkMacGetDrawablePort(d);
 
2513
    GetGWorld(&saveWorld, &saveDevice);
 
2514
    SetGWorld(destPort, NULL);
 
2515
    TkMacSetUpClippingRgn(d);
 
2516
    if (TkMacHaveAppearance() > 1) {
 
2517
        Rect r;
 
2518
        r.top = y;
 
2519
        r.left = x;
 
2520
        r.bottom = y + height;
 
2521
        r.right = x + width;
 
2522
         
 
2523
        DrawThemeMenuSeparator(&r);
 
2524
    } else {
 
2525
    /*
 
2526
     * We don't want to use the text GC for drawing the separator. It
 
2527
     * needs to be the same color as disabled items.
 
2528
     */
 
2529
    
 
2530
    TkMacSetUpGraphicsPort(mePtr->disabledGC != None ? mePtr->disabledGC
 
2531
            : menuPtr->disabledGC);
 
2532
    
 
2533
    MoveTo(x, y + (height / 2));
 
2534
    Line(width, 0);
 
2535
    
 
2536
    SetGWorld(saveWorld, saveDevice);
 
2537
}
 
2538
}
 
2539
 
 
2540
/*
 
2541
 *----------------------------------------------------------------------
 
2542
 *
 
2543
 * MenuDefProc --
 
2544
 *
 
2545
 *      This routine is the MDEF handler for Tk. It receives all messages
 
2546
 *      for the menu and dispatches them.
 
2547
 *
 
2548
 * Results:
 
2549
 *      None.
 
2550
 *
 
2551
 * Side effects:
 
2552
 *      This routine causes menus to be drawn and will certainly allocate
 
2553
 *      memory as a result. Also, the menu can scroll up and down, and
 
2554
 *      various other interface actions can take place.
 
2555
 *
 
2556
 *----------------------------------------------------------------------
 
2557
 */
 
2558
 
 
2559
static void
 
2560
MenuDefProc(
 
2561
    short message,                      /* What action are we taking? */
 
2562
    MenuHandle menu,                    /* The menu we are working with */
 
2563
    Rect *menuRectPtr,                  /* A pointer to the rect for the
 
2564
                                         * whole menu. */
 
2565
    Point hitPt,                        /* Where the mouse was clicked for
 
2566
                                         * the appropriate messages. */
 
2567
    short *whichItem,                   /* Output result. Which item was
 
2568
                                         * hit by the user? */
 
2569
    TkMenuLowMemGlobals *globalsPtr)    /* The low mem globals we have
 
2570
                                         * to change */
 
2571
{
 
2572
#define SCREEN_MARGIN 5
 
2573
    TkMenu *menuPtr;
 
2574
    TkMenuEntry *parentEntryPtr;
 
2575
    Tcl_HashEntry *commandEntryPtr;
 
2576
    GrafPtr windowMgrPort;
 
2577
    Tk_Font tkfont;
 
2578
    Tk_FontMetrics fontMetrics, entryMetrics;
 
2579
    Tk_FontMetrics *fmPtr;
 
2580
    TkMenuEntry *mePtr;
 
2581
    int i;
 
2582
    int maxMenuHeight;
 
2583
    int oldItem;
 
2584
    int newItem = -1;
 
2585
    GDHandle device;
 
2586
    Rect itemRect;
 
2587
    short windowPart;
 
2588
    WindowRef whichWindow;
 
2589
    RGBColor bgColor;
 
2590
    RGBColor fgColor;
 
2591
    RGBColor origFgColor;
 
2592
    PenState origPenState;
 
2593
    Rect dragRect;
 
2594
    Rect scratchRect = {-32768, -32768, 32767, 32767};
 
2595
    RgnHandle oldClipRgn;
 
2596
    TkMenuReferences *menuRefPtr;
 
2597
    TkMenu *searchMenuPtr;
 
2598
    Rect menuClipRect;
 
2599
    
 
2600
    HLock((Handle) menu);
 
2601
    commandEntryPtr = Tcl_FindHashEntry(&commandTable,
 
2602
            (char *) (*menu)->menuID);
 
2603
    HUnlock((Handle) menu);
 
2604
    menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
 
2605
 
 
2606
    switch (message) {
 
2607
        case mSizeMsg:
 
2608
            GetWMgrPort(&windowMgrPort);
 
2609
            maxMenuHeight = windowMgrPort->portRect.bottom
 
2610
                    - windowMgrPort->portRect.top
 
2611
                    - GetMBarHeight() - SCREEN_MARGIN;
 
2612
            (*menu)->menuWidth = menuPtr->totalWidth;
 
2613
            (*menu)->menuHeight = maxMenuHeight < menuPtr->totalHeight ?
 
2614
                    maxMenuHeight : menuPtr->totalHeight;
 
2615
            break;
 
2616
 
 
2617
        case mDrawMsg:
 
2618
        
 
2619
            /*
 
2620
             * Store away the menu rectangle so we can keep track of the
 
2621
             * different regions that the menu obscures.
 
2622
             */
 
2623
            
 
2624
            ((MacMenu *) menuPtr->platformData)->menuRect = *menuRectPtr;
 
2625
            if (tkMenuCascadeRgn == NULL) {
 
2626
                tkMenuCascadeRgn = NewRgn();
 
2627
            }
 
2628
            if (utilRgn == NULL) {
 
2629
                utilRgn = NewRgn();
 
2630
            }
 
2631
            if (totalMenuRgn == NULL) {
 
2632
                totalMenuRgn = NewRgn();
 
2633
            }
 
2634
            SetEmptyRgn(tkMenuCascadeRgn);
 
2635
            for (searchMenuPtr = menuPtr; searchMenuPtr != NULL; ) {
 
2636
                RectRgn(utilRgn, 
 
2637
                        &((MacMenu *) searchMenuPtr->platformData)->menuRect);
 
2638
                InsetRgn(utilRgn, -1, -1);
 
2639
                UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
 
2640
                OffsetRgn(utilRgn, 1, 1);
 
2641
                UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
 
2642
                
 
2643
                if (searchMenuPtr->menuRefPtr->parentEntryPtr != NULL) {
 
2644
                    searchMenuPtr = searchMenuPtr->menuRefPtr
 
2645
                            ->parentEntryPtr->menuPtr;
 
2646
                } else {
 
2647
                    break;
 
2648
                }
 
2649
                if (searchMenuPtr->menuType == MENUBAR) {
 
2650
                    break;
 
2651
                }
 
2652
            }
 
2653
            UnionRgn(totalMenuRgn, tkMenuCascadeRgn, totalMenuRgn);
 
2654
            SetEmptyRgn(utilRgn);
 
2655
            
 
2656
            /*
 
2657
             * Now draw the background if Appearance is present...
 
2658
             */
 
2659
             
 
2660
            GetGWorld(&macMDEFDrawable.portPtr, &device);
 
2661
            if (TkMacHaveAppearance() > 1) {
 
2662
                ThemeMenuType menuType;
 
2663
                
 
2664
                if (menuPtr->menuRefPtr->topLevelListPtr != NULL) {
 
2665
                    menuType = kThemeMenuTypePullDown;
 
2666
                } else if (menuPtr->menuRefPtr->parentEntryPtr != NULL) {
 
2667
                    menuType = kThemeMenuTypeHierarchical;
 
2668
                } else {
 
2669
                    menuType = kThemeMenuTypePopUp;
 
2670
                }
 
2671
                    
 
2672
                DrawMenuBackground(menuRectPtr, (Drawable) &macMDEFDrawable, 
 
2673
                        menuType);
 
2674
            }
 
2675
            
 
2676
            /*
 
2677
             * Next, figure out scrolling information.
 
2678
             */
 
2679
            
 
2680
            menuClipRect = *menuRectPtr;
 
2681
            if ((menuClipRect.bottom - menuClipRect.top) 
 
2682
                    < menuPtr->totalHeight) {
 
2683
                if (globalsPtr->menuTop < menuRectPtr->top) {
 
2684
                    DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW, 
 
2685
                            (Drawable) &macMDEFDrawable,
 
2686
                            menuPtr->textGC, 
 
2687
                            menuRectPtr->left 
 
2688
                            + menuPtr->entries[1]->indicatorSpace,
 
2689
                            menuRectPtr->top);
 
2690
                    menuClipRect.top += SICN_HEIGHT;
 
2691
                }
 
2692
                if ((globalsPtr->menuTop + menuPtr->totalHeight)
 
2693
                        > menuRectPtr->bottom) {
 
2694
                    DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
 
2695
                            (Drawable) &macMDEFDrawable,
 
2696
                            menuPtr->textGC, 
 
2697
                            menuRectPtr->left 
 
2698
                            + menuPtr->entries[1]->indicatorSpace,
 
2699
                            menuRectPtr->bottom - SICN_HEIGHT);
 
2700
                    menuClipRect.bottom -= SICN_HEIGHT;
 
2701
                }
 
2702
                GetClip(utilRgn);
 
2703
            }
 
2704
            
 
2705
            /*
 
2706
             * Now, actually draw the menu. Don't draw entries that
 
2707
             * are higher than the top arrow, and don't draw entries
 
2708
             * that are lower than the bottom.
 
2709
             */
 
2710
            
 
2711
            Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);               
 
2712
            for (i = 0; i < menuPtr->numEntries; i++) {
 
2713
                mePtr = menuPtr->entries[i];
 
2714
                if (globalsPtr->menuTop + mePtr->y + mePtr->height
 
2715
                        < menuClipRect.top) {
 
2716
                    continue;
 
2717
                } else if (globalsPtr->menuTop + mePtr->y
 
2718
                        > menuClipRect.bottom) {
 
2719
                    continue;
 
2720
                }
 
2721
                /* ClipRect(&menuClipRect); */
 
2722
                if (mePtr->tkfont == NULL) {
 
2723
                    fmPtr = &fontMetrics;
 
2724
                    tkfont = menuPtr->tkfont;
 
2725
                } else {
 
2726
                    tkfont = mePtr->tkfont;
 
2727
                    Tk_GetFontMetrics(tkfont, &entryMetrics);
 
2728
                    fmPtr = &entryMetrics;
 
2729
                }
 
2730
                AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
 
2731
                        (Drawable) &macMDEFDrawable, fmPtr, tkfont, 
 
2732
                        menuRectPtr->left + mePtr->x,
 
2733
                        globalsPtr->menuTop + mePtr->y,
 
2734
                        (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
 
2735
                            menuPtr->totalWidth - mePtr->x : mePtr->width,
 
2736
                        menuPtr->entries[i]->height);
 
2737
            }
 
2738
            globalsPtr->menuBottom = globalsPtr->menuTop 
 
2739
                    + menuPtr->totalHeight;
 
2740
            if (!EmptyRgn(utilRgn)) {
 
2741
                SetClip(utilRgn);
 
2742
                SetEmptyRgn(utilRgn);
 
2743
            }
 
2744
            MDEFScrollFlag = 1;
 
2745
            break;
 
2746
 
 
2747
        case mChooseMsg: {
 
2748
            int hasTopScroll, hasBottomScroll;
 
2749
            enum {
 
2750
                DONT_SCROLL, DOWN_SCROLL, UP_SCROLL
 
2751
            } scrollDirection;
 
2752
            Rect updateRect;
 
2753
            short scrollAmt;
 
2754
            RGBColor origForeColor, origBackColor, foreColor, backColor;
 
2755
            
 
2756
            GetGWorld(&macMDEFDrawable.portPtr, &device);
 
2757
            GetForeColor(&origForeColor);
 
2758
            GetBackColor(&origBackColor);
 
2759
 
 
2760
            if (TkSetMacColor(menuPtr->textGC->foreground, 
 
2761
                    &foreColor) == true) {
 
2762
                if (!TkMacHaveAppearance()) {
 
2763
                    RGBForeColor(&foreColor);
 
2764
                }
 
2765
            }
 
2766
            if (TkSetMacColor(menuPtr->textGC->background, 
 
2767
                    &backColor) == true) {
 
2768
                if (!TkMacHaveAppearance()) {
 
2769
                    RGBBackColor(&backColor);
 
2770
                }
 
2771
            }
 
2772
 
 
2773
            /*
 
2774
             * Find out which item was hit. If it is the same as the old item,
 
2775
             * we don't need to do anything.
 
2776
             */
 
2777
 
 
2778
            oldItem = *whichItem - 1;
 
2779
             
 
2780
            if (PtInRect(hitPt, menuRectPtr)) {
 
2781
                for (i = 0; i < menuPtr->numEntries; i++) {
 
2782
                    mePtr = menuPtr->entries[i];
 
2783
                    itemRect.left = menuRectPtr->left + mePtr->x;
 
2784
                    itemRect.top = globalsPtr->menuTop + mePtr->y;
 
2785
                    if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
 
2786
                        itemRect.right = itemRect.left + menuPtr->totalWidth
 
2787
                                - mePtr->x;
 
2788
                    } else {
 
2789
                        itemRect.right = itemRect.left + mePtr->width;
 
2790
                    }
 
2791
                    itemRect.bottom = itemRect.top
 
2792
                            + menuPtr->entries[i]->height;
 
2793
                    if (PtInRect(hitPt, &itemRect)) {
 
2794
                        if ((mePtr->type == SEPARATOR_ENTRY)
 
2795
                                || (mePtr->state == tkDisabledUid)) {
 
2796
                            newItem = -1;
 
2797
                        } else {
 
2798
                            TkMenuEntry *cascadeEntryPtr;
 
2799
                            int parentDisabled = 0;
 
2800
                            
 
2801
                            for (cascadeEntryPtr
 
2802
                                    = menuPtr->menuRefPtr->parentEntryPtr;
 
2803
                                    cascadeEntryPtr != NULL;
 
2804
                                    cascadeEntryPtr 
 
2805
                                    = cascadeEntryPtr->nextCascadePtr) {
 
2806
                                if (strcmp(cascadeEntryPtr->name,
 
2807
                                        Tk_PathName(menuPtr->tkwin)) == 0) {
 
2808
                                    if (cascadeEntryPtr->state
 
2809
                                            == tkDisabledUid) {
 
2810
                                        parentDisabled = 1;
 
2811
                                    }
 
2812
                                    break;
 
2813
                                }
 
2814
                            }
 
2815
                            if (parentDisabled) {
 
2816
                                newItem = -1;
 
2817
                            } else {                
 
2818
                                newItem = i;
 
2819
                                if ((mePtr->type == CASCADE_ENTRY) 
 
2820
                                        && (oldItem != newItem)) {
 
2821
                                    globalsPtr->itemRect = itemRect;
 
2822
                                }
 
2823
                            }
 
2824
                        }
 
2825
                        break;
 
2826
                    }
 
2827
                }
 
2828
            }
 
2829
 
 
2830
            /*
 
2831
             * Now we need to take care of scrolling the menu.
 
2832
             */
 
2833
            
 
2834
            hasTopScroll = globalsPtr->menuTop < menuRectPtr->top;
 
2835
            hasBottomScroll = globalsPtr->menuBottom > menuRectPtr->bottom;
 
2836
            scrollDirection = DONT_SCROLL;
 
2837
            if (hasTopScroll 
 
2838
                    && (hitPt.v < menuRectPtr->top + SICN_HEIGHT)) {
 
2839
                newItem = -1;
 
2840
                scrollDirection = DOWN_SCROLL;
 
2841
            } else if (hasBottomScroll
 
2842
                    && (hitPt.v > menuRectPtr->bottom - SICN_HEIGHT)) {
 
2843
                newItem = -1;
 
2844
                scrollDirection = UP_SCROLL;
 
2845
            }           
 
2846
            menuClipRect = *menuRectPtr;
 
2847
            if (hasTopScroll) {
 
2848
                menuClipRect.top += SICN_HEIGHT;
 
2849
            }
 
2850
            if (hasBottomScroll) {
 
2851
                menuClipRect.bottom -= SICN_HEIGHT;
 
2852
            }
 
2853
            if (MDEFScrollFlag) {
 
2854
                scrollDirection = DONT_SCROLL;
 
2855
                MDEFScrollFlag = 0;
 
2856
            }
 
2857
            GetClip(utilRgn);
 
2858
            ClipRect(&menuClipRect);
 
2859
 
 
2860
            if (oldItem != newItem) {
 
2861
                if (oldItem >= 0) {
 
2862
                    mePtr = menuPtr->entries[oldItem];
 
2863
                    tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
 
2864
                    Tk_GetFontMetrics(tkfont, &fontMetrics);
 
2865
                    AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
 
2866
                        (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, 
 
2867
                        menuRectPtr->left + mePtr->x,
 
2868
                        globalsPtr->menuTop + mePtr->y,
 
2869
                        (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
 
2870
                            menuPtr->totalWidth - mePtr->x : mePtr->width,
 
2871
                        mePtr->height);
 
2872
                }
 
2873
                if (newItem != -1) {
 
2874
                    int oldActiveItem = menuPtr->active;
 
2875
                    
 
2876
                    mePtr = menuPtr->entries[newItem];
 
2877
                    if (mePtr->state != tkDisabledUid) {
 
2878
                        TkActivateMenuEntry(menuPtr, newItem);
 
2879
                    }
 
2880
                    tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
 
2881
                    Tk_GetFontMetrics(tkfont, &fontMetrics);
 
2882
                    AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
 
2883
                        (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, 
 
2884
                        menuRectPtr->left + mePtr->x,
 
2885
                        globalsPtr->menuTop + mePtr->y,
 
2886
                        (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
 
2887
                            menuPtr->totalWidth - mePtr->x : mePtr->width,
 
2888
                        mePtr->height);
 
2889
                }
 
2890
 
 
2891
                tkUseMenuCascadeRgn = 1;
 
2892
                MenuSelectEvent(menuPtr);
 
2893
                Tcl_ServiceAll();
 
2894
                tkUseMenuCascadeRgn = 0;
 
2895
                if (mePtr->state != tkDisabledUid) {
 
2896
                    TkActivateMenuEntry(menuPtr, -1);
 
2897
                }
 
2898
                *whichItem = newItem + 1;
 
2899
            }
 
2900
            globalsPtr->menuDisable = ((*menu)->menuID << 16) | (newItem + 1);
 
2901
            
 
2902
            if (scrollDirection == UP_SCROLL) {
 
2903
                scrollAmt = menuClipRect.bottom - hitPt.v;
 
2904
                if (scrollAmt < menuRectPtr->bottom 
 
2905
                        - globalsPtr->menuBottom) {
 
2906
                    scrollAmt = menuRectPtr->bottom - globalsPtr->menuBottom;
 
2907
                }
 
2908
                if (!hasTopScroll && ((globalsPtr->menuTop + scrollAmt) < menuRectPtr->top)) {
 
2909
                    SetRect(&updateRect, menuRectPtr->left,
 
2910
                            globalsPtr->menuTop, menuRectPtr->right,
 
2911
                            globalsPtr->menuTop + SICN_HEIGHT);
 
2912
                    EraseRect(&updateRect);
 
2913
                    DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
 
2914
                            (Drawable) &macMDEFDrawable,
 
2915
                            menuPtr->textGC, menuRectPtr->left
 
2916
                            + menuPtr->entries[1]->indicatorSpace,
 
2917
                            menuRectPtr->top);
 
2918
                    menuClipRect.top += SICN_HEIGHT;
 
2919
                }
 
2920
            } else if (scrollDirection == DOWN_SCROLL) {
 
2921
                scrollAmt = menuClipRect.top - hitPt.v;
 
2922
                if (scrollAmt > menuRectPtr->top - globalsPtr->menuTop) {
 
2923
                    scrollAmt = menuRectPtr->top - globalsPtr->menuTop;
 
2924
                }
 
2925
                if (!hasBottomScroll && ((globalsPtr->menuBottom + scrollAmt)
 
2926
                        > menuRectPtr->bottom)) {
 
2927
                    SetRect(&updateRect, menuRectPtr->left, 
 
2928
                            globalsPtr->menuBottom - SICN_HEIGHT,
 
2929
                            menuRectPtr->right, globalsPtr->menuBottom);
 
2930
                    EraseRect(&updateRect);
 
2931
                    DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
 
2932
                            (Drawable) &macMDEFDrawable,
 
2933
                            menuPtr->textGC, menuRectPtr->left
 
2934
                            + menuPtr->entries[1]->indicatorSpace,
 
2935
                            menuRectPtr->bottom - SICN_HEIGHT);
 
2936
                    menuClipRect.bottom -= SICN_HEIGHT;
 
2937
                }
 
2938
            }
 
2939
            if (scrollDirection != DONT_SCROLL) {
 
2940
                RgnHandle updateRgn = NewRgn();
 
2941
                ScrollRect(&menuClipRect, 0, scrollAmt, updateRgn);
 
2942
                updateRect = (*updateRgn)->rgnBBox;
 
2943
                DisposeRgn(updateRgn);
 
2944
                globalsPtr->menuTop += scrollAmt;
 
2945
                globalsPtr->menuBottom += scrollAmt;
 
2946
                if (globalsPtr->menuTop == menuRectPtr->top) {
 
2947
                    updateRect.top -= SICN_HEIGHT;
 
2948
                }
 
2949
                if (globalsPtr->menuBottom == menuRectPtr->bottom) {
 
2950
                    updateRect.bottom += SICN_HEIGHT;
 
2951
                }
 
2952
                ClipRect(&updateRect);
 
2953
                EraseRect(&updateRect);
 
2954
                Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);           
 
2955
                for (i = 0; i < menuPtr->numEntries; i++) {
 
2956
                    mePtr = menuPtr->entries[i];
 
2957
                    if (globalsPtr->menuTop + mePtr->y + mePtr->height
 
2958
                            < updateRect.top) {
 
2959
                        continue;
 
2960
                    } else if (globalsPtr->menuTop + mePtr->y
 
2961
                            > updateRect.bottom) {
 
2962
                        continue;
 
2963
                    }
 
2964
                    if (mePtr->tkfont == NULL) {
 
2965
                        fmPtr = &fontMetrics;
 
2966
                        tkfont = menuPtr->tkfont;
 
2967
                    } else {
 
2968
                        tkfont = mePtr->tkfont;
 
2969
                        Tk_GetFontMetrics(tkfont, &entryMetrics);
 
2970
                        fmPtr = &entryMetrics;
 
2971
                    }
 
2972
                    AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
 
2973
                        (Drawable) &macMDEFDrawable, fmPtr, tkfont, 
 
2974
                        menuRectPtr->left + mePtr->x,
 
2975
                        globalsPtr->menuTop + mePtr->y,
 
2976
                        (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
 
2977
                            menuPtr->totalWidth - mePtr->x : mePtr->width,
 
2978
                        menuPtr->entries[i]->height);
 
2979
                }               
 
2980
            }
 
2981
 
 
2982
            SetClip(utilRgn);
 
2983
            SetEmptyRgn(utilRgn);
 
2984
            RGBForeColor(&origForeColor);
 
2985
            RGBBackColor(&origBackColor);
 
2986
 
 
2987
            /*
 
2988
             * If the menu is a tearoff, and the mouse is outside the menu,
 
2989
             * we need to draw the drag rectangle.
 
2990
             *
 
2991
             * In order for tearoffs to work properly, we need to set
 
2992
             * the active member of the containing menubar.
 
2993
             */
 
2994
            
 
2995
            menuRefPtr = TkFindMenuReferences(menuPtr->interp,
 
2996
                    Tk_PathName(menuPtr->tkwin));
 
2997
            if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) {
 
2998
                for (parentEntryPtr = menuRefPtr->parentEntryPtr;
 
2999
                        strcmp(parentEntryPtr->name,
 
3000
                        Tk_PathName(menuPtr->tkwin)) == 0;
 
3001
                        parentEntryPtr = parentEntryPtr->nextCascadePtr) {
 
3002
                }
 
3003
                if (parentEntryPtr != NULL) {
 
3004
                    TkActivateMenuEntry(parentEntryPtr->menuPtr,
 
3005
                            parentEntryPtr->index);
 
3006
                }
 
3007
            }
 
3008
            
 
3009
            if (menuPtr->tearOff) {
 
3010
                scratchRect = *menuRectPtr;
 
3011
                if (tearoffStruct.menuPtr == NULL) {
 
3012
                    scratchRect.top -= 10;
 
3013
                    scratchRect.bottom += 10;
 
3014
                    scratchRect.left -= 10;
 
3015
                    scratchRect.right += 10;
 
3016
                }
 
3017
 
 
3018
                windowPart = FindWindow(hitPt, &whichWindow);
 
3019
                if ((windowPart != inMenuBar) && (newItem == -1)
 
3020
                        && (hitPt.v != 0) && (hitPt.h != 0)
 
3021
                        && (!PtInRect(hitPt, &scratchRect))
 
3022
                        && (!PtInRect(hitPt, &tearoffStruct.excludeRect))) {
 
3023
/*
 
3024
 * This is the second argument to the Toolbox Delay function.  It changed
 
3025
 * from long to unsigned long between Universal Headers 2.0 & 3.0
 
3026
 */
 
3027
#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
 
3028
                    long dummy;
 
3029
#else
 
3030
                    unsigned long dummy;
 
3031
#endif              
 
3032
                    oldClipRgn = NewRgn();
 
3033
                    GetClip(oldClipRgn);
 
3034
                    GetForeColor(&origFgColor);
 
3035
                    GetPenState(&origPenState);
 
3036
                    GetForeColor(&fgColor);
 
3037
                    GetBackColor(&bgColor);
 
3038
                    GetGray(device, &bgColor, &fgColor);
 
3039
                    RGBForeColor(&fgColor);
 
3040
                    SetRect(&scratchRect, -32768, -32768, 32767, 32767);
 
3041
                    ClipRect(&scratchRect);
 
3042
                    
 
3043
                    dragRect = *menuRectPtr;
 
3044
                    tearoffStruct.menuPtr = menuPtr;
 
3045
 
 
3046
                    PenMode(srcXor);
 
3047
                    dragRect = *menuRectPtr;
 
3048
                    OffsetRect(&dragRect, -dragRect.left, -dragRect.top);
 
3049
                    OffsetRect(&dragRect, tearoffStruct.point.h,
 
3050
                            tearoffStruct.point.v);
 
3051
                    if ((dragRect.top != 0) && (dragRect.left != 0)) {
 
3052
                        FrameRect(&dragRect);
 
3053
                        Delay(1, &dummy);
 
3054
                        FrameRect(&dragRect);
 
3055
                    }
 
3056
                    tearoffStruct.point = hitPt;
 
3057
 
 
3058
                    SetClip(oldClipRgn);
 
3059
                    DisposeRgn(oldClipRgn);
 
3060
                    RGBForeColor(&origFgColor);
 
3061
                    SetPenState(&origPenState);    
 
3062
                } else {
 
3063
                    tearoffStruct.menuPtr = NULL;
 
3064
                    tearoffStruct.point.h = tearoffStruct.point.v = 0;
 
3065
                }
 
3066
            } else {
 
3067
                tearoffStruct.menuPtr = NULL;
 
3068
                tearoffStruct.point.h = tearoffStruct.point.v = 0;
 
3069
            }
 
3070
            
 
3071
            break;
 
3072
        }
 
3073
 
 
3074
        case mPopUpMsg:
 
3075
        
 
3076
            /*
 
3077
             * Note that for some oddball reason, h and v are reversed in the
 
3078
             * point given to us by the MDEF.
 
3079
             */
 
3080
        
 
3081
            oldItem = *whichItem;
 
3082
            if (oldItem >= menuPtr->numEntries) {
 
3083
                oldItem = -1;
 
3084
            }
 
3085
            GetWMgrPort(&windowMgrPort);
 
3086
            maxMenuHeight = windowMgrPort->portRect.bottom
 
3087
                    - windowMgrPort->portRect.top
 
3088
                    - GetMBarHeight() - SCREEN_MARGIN;
 
3089
            if (menuPtr->totalHeight > maxMenuHeight) {
 
3090
                menuRectPtr->top = GetMBarHeight();
 
3091
            } else {
 
3092
                menuRectPtr->top = hitPt.h;
 
3093
                if (oldItem >= 0) {
 
3094
                    menuRectPtr->top -= menuPtr->entries[oldItem]->y;
 
3095
                }
 
3096
                if (menuRectPtr->top + menuPtr->totalHeight > maxMenuHeight) {
 
3097
                    menuRectPtr->top -= maxMenuHeight - menuPtr->totalHeight;
 
3098
                }
 
3099
            }
 
3100
            menuRectPtr->left = hitPt.v;
 
3101
            menuRectPtr->right = menuRectPtr->left + menuPtr->totalWidth;
 
3102
            menuRectPtr->bottom = menuRectPtr->top + 
 
3103
                    ((maxMenuHeight < menuPtr->totalHeight) 
 
3104
                    ? maxMenuHeight : menuPtr->totalHeight);
 
3105
            if (menuRectPtr->top == GetMBarHeight()) {
 
3106
                *whichItem = hitPt.h;
 
3107
            } else {
 
3108
                *whichItem = menuRectPtr->top;
 
3109
            }
 
3110
            break;
 
3111
    }
 
3112
}
 
3113
 
 
3114
/*
 
3115
 *----------------------------------------------------------------------
 
3116
 *
 
3117
 *   AppearanceEntryDrawWrapper --
 
3118
 *
 
3119
 *      This routine wraps the TkpDrawMenuEntry function.  Under Appearance, 
 
3120
 *      it routes to the Appearance Managers DrawThemeEntry, otherwise it
 
3121
 *      just goes straight to TkpDrawMenuEntry.
 
3122
 *
 
3123
 * Results:
 
3124
 *      A menu entry is drawn
 
3125
 *
 
3126
 * Side effects:
 
3127
 *      None
 
3128
 *
 
3129
 *----------------------------------------------------------------------
 
3130
 */
 
3131
static void 
 
3132
AppearanceEntryDrawWrapper(
 
3133
    TkMenuEntry *mePtr,
 
3134
    Rect *menuRectPtr,
 
3135
    TkMenuLowMemGlobals *globalsPtr,     
 
3136
    Drawable d,
 
3137
    Tk_FontMetrics *fmPtr, 
 
3138
    Tk_Font tkfont, 
 
3139
    int x, 
 
3140
    int y, 
 
3141
    int width, 
 
3142
    int height)
 
3143
{
 
3144
    if (TkMacHaveAppearance() > 1) {
 
3145
        MenuEntryUserData meData;
 
3146
        Rect itemRect;
 
3147
        ThemeMenuState theState;
 
3148
        ThemeMenuItemType theType;
 
3149
    
 
3150
        meData.mePtr = mePtr;
 
3151
        meData.mdefDrawable = d;
 
3152
        meData.fmPtr = fmPtr;
 
3153
        meData.tkfont = tkfont;
 
3154
    
 
3155
        itemRect.top = y;
 
3156
        itemRect.left = x;
 
3157
        itemRect.bottom = itemRect.top + height;
 
3158
        itemRect.right = itemRect.left + width;
 
3159
    
 
3160
        if (mePtr->state == tkActiveUid) {
 
3161
            theState = kThemeMenuSelected;
 
3162
        } else if (mePtr->state == tkDisabledUid) {
 
3163
            theState = kThemeMenuDisabled;
 
3164
        } else {
 
3165
            theState = kThemeMenuActive;
 
3166
        }
 
3167
        
 
3168
        if (mePtr->type == CASCADE_ENTRY) {
 
3169
            theType = kThemeMenuItemHierarchical;
 
3170
        } else {
 
3171
            theType = kThemeMenuItemPlain;
 
3172
        }
 
3173
        
 
3174
        DrawThemeMenuItem (menuRectPtr, &itemRect,
 
3175
                globalsPtr->menuTop, globalsPtr->menuBottom, theState,
 
3176
                theType, tkThemeMenuItemDrawingUPP, 
 
3177
                (unsigned long) &meData);
 
3178
        
 
3179
    } else {
 
3180
        TkpDrawMenuEntry(mePtr, d, tkfont, fmPtr,
 
3181
                x, y, width, height, 0, 1);
 
3182
    }
 
3183
}
 
3184
 
 
3185
/*
 
3186
 *----------------------------------------------------------------------
 
3187
 *
 
3188
 *  tkThemeMenuItemDrawingProc --
 
3189
 *
 
3190
 *      This routine is called from the Appearance DrawThemeMenuEntry
 
3191
 *
 
3192
 * Results:
 
3193
 *      A menu entry is drawn
 
3194
 *
 
3195
 * Side effects:
 
3196
 *      None
 
3197
 *
 
3198
 *----------------------------------------------------------------------
 
3199
 */
 
3200
pascal void
 
3201
tkThemeMenuItemDrawingProc (
 
3202
        const Rect *inBounds,
 
3203
        SInt16 inDepth, 
 
3204
        Boolean inIsColorDevice, 
 
3205
        SInt32 inUserData)
 
3206
{
 
3207
    MenuEntryUserData *meData = (MenuEntryUserData *) inUserData;
 
3208
 
 
3209
    TkpDrawMenuEntry(meData->mePtr, meData->mdefDrawable,
 
3210
         meData->tkfont, meData->fmPtr, inBounds->left, 
 
3211
         inBounds->top, inBounds->right - inBounds->left,
 
3212
         inBounds->bottom - inBounds->top, 0, 1);
 
3213
 
 
3214
}
 
3215
 
 
3216
/*
 
3217
 *----------------------------------------------------------------------
 
3218
 *
 
3219
 * TkMacHandleTearoffMenu() --
 
3220
 *
 
3221
 *      This routine sees if the MDEF has set a menu and a mouse position
 
3222
 *      for tearing off and makes a tearoff menu if it has.
 
3223
 *
 
3224
 * Results:
 
3225
 *      menuPtr->interp will have the result of the tearoff command.
 
3226
 *
 
3227
 * Side effects:
 
3228
 *      A new tearoff menu is created if it is supposed to be.
 
3229
 *
 
3230
 *----------------------------------------------------------------------
 
3231
 */
 
3232
 
 
3233
void
 
3234
TkMacHandleTearoffMenu(void)
 
3235
{
 
3236
    if (tearoffStruct.menuPtr != NULL) {
 
3237
        Tcl_DString tearoffCmdStr;
 
3238
        char intString[20];
 
3239
        short windowPart;
 
3240
        WindowRef whichWindow;
 
3241
        
 
3242
        windowPart = FindWindow(tearoffStruct.point, &whichWindow);
 
3243
        
 
3244
        if (windowPart != inMenuBar) {
 
3245
            Tcl_DStringInit(&tearoffCmdStr);
 
3246
            Tcl_DStringAppendElement(&tearoffCmdStr, "tkTearOffMenu");
 
3247
            Tcl_DStringAppendElement(&tearoffCmdStr, 
 
3248
                    Tk_PathName(tearoffStruct.menuPtr->tkwin));
 
3249
            sprintf(intString, "%d", tearoffStruct.point.h);
 
3250
            Tcl_DStringAppendElement(&tearoffCmdStr, intString);
 
3251
            sprintf(intString, "%d", tearoffStruct.point.v);
 
3252
            Tcl_DStringAppendElement(&tearoffCmdStr, intString);
 
3253
            Tcl_Eval(tearoffStruct.menuPtr->interp,
 
3254
                    Tcl_DStringValue(&tearoffCmdStr));
 
3255
            Tcl_DStringFree(&tearoffCmdStr);
 
3256
            tearoffStruct.menuPtr = NULL;
 
3257
        }
 
3258
    }
 
3259
}
 
3260
 
 
3261
/*
 
3262
 *--------------------------------------------------------------
 
3263
 *
 
3264
 * TkpInitializeMenuBindings --
 
3265
 *
 
3266
 *      For every interp, initializes the bindings for Windows
 
3267
 *      menus. Does nothing on Mac or XWindows.
 
3268
 *
 
3269
 * Results:
 
3270
 *      None.
 
3271
 *
 
3272
 * Side effects:
 
3273
 *      C-level bindings are setup for the interp which will
 
3274
 *      handle Alt-key sequences for menus without beeping
 
3275
 *      or interfering with user-defined Alt-key bindings.
 
3276
 *
 
3277
 *--------------------------------------------------------------
 
3278
 */
 
3279
 
 
3280
void
 
3281
TkpInitializeMenuBindings(interp, bindingTable)
 
3282
    Tcl_Interp *interp;             /* The interpreter to set. */
 
3283
    Tk_BindingTable bindingTable;   /* The table to add to. */
 
3284
{
 
3285
    /*
 
3286
     * Nothing to do.
 
3287
     */
 
3288
}
 
3289
 
 
3290
/*
 
3291
 *--------------------------------------------------------------
 
3292
 *
 
3293
 * TkpComputeMenubarGeometry --
 
3294
 *
 
3295
 *      This procedure is invoked to recompute the size and
 
3296
 *      layout of a menu that is a menubar clone.
 
3297
 *
 
3298
 * Results:
 
3299
 *      None.
 
3300
 *
 
3301
 * Side effects:
 
3302
 *      Fields of menu entries are changed to reflect their
 
3303
 *      current positions, and the size of the menu window
 
3304
 *      itself may be changed.
 
3305
 *
 
3306
 *--------------------------------------------------------------
 
3307
 */
 
3308
 
 
3309
void
 
3310
TkpComputeMenubarGeometry(menuPtr)
 
3311
    TkMenu *menuPtr;            /* Structure describing menu. */
 
3312
{
 
3313
    TkpComputeStandardMenuGeometry(menuPtr);
 
3314
}
 
3315
 
 
3316
/*
 
3317
 *----------------------------------------------------------------------
 
3318
 *
 
3319
 * DrawTearoffEntry --
 
3320
 *
 
3321
 *      This procedure draws the background part of a menu.
 
3322
 *
 
3323
 * Results:
 
3324
 *      None.
 
3325
 *
 
3326
 * Side effects:
 
3327
 *      Commands are output to X to display the menu in its
 
3328
 *      current mode.
 
3329
 *
 
3330
 *----------------------------------------------------------------------
 
3331
 */
 
3332
 
 
3333
void
 
3334
DrawTearoffEntry(
 
3335
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
3336
    TkMenuEntry *mePtr,                 /* The entry we are drawing */
 
3337
    Drawable d,                         /* The drawable we are drawing into */
 
3338
    GC gc,                              /* The gc we are drawing with */
 
3339
    Tk_Font tkfont,                     /* The font we are drawing with */
 
3340
    CONST Tk_FontMetrics *fmPtr,        /* The metrics we are drawing with */
 
3341
    int x,                              /* Left edge of entry. */
 
3342
    int y,                              /* Top edge of entry. */
 
3343
    int width,                          /* Width of entry. */
 
3344
    int height)                         /* Height of entry. */
 
3345
{
 
3346
    XPoint points[2];
 
3347
    int margin, segmentWidth, maxX;
 
3348
 
 
3349
    if ((menuPtr->menuType != MASTER_MENU) || (FixMDEF() != NULL)) {
 
3350
        return;
 
3351
    }
 
3352
    
 
3353
    margin = (fmPtr->ascent + fmPtr->descent)/2;
 
3354
    points[0].x = x;
 
3355
    points[0].y = y + height/2;
 
3356
    points[1].y = points[0].y;
 
3357
    segmentWidth = 6;
 
3358
    maxX  = width - 1;
 
3359
 
 
3360
    while (points[0].x < maxX) {
 
3361
        points[1].x = points[0].x + segmentWidth;
 
3362
        if (points[1].x > maxX) {
 
3363
            points[1].x = maxX;
 
3364
        }
 
3365
        Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
 
3366
                TK_RELIEF_RAISED);
 
3367
        points[0].x += 2*segmentWidth;
 
3368
    }
 
3369
}
 
3370
 
 
3371
/*
 
3372
 *----------------------------------------------------------------------
 
3373
 *
 
3374
 * TkMacSetHelpMenuItemCount --
 
3375
 *
 
3376
 *      Has to be called after the first call to InsertMenu. Sets
 
3377
 *      up the global variable for the number of items in the
 
3378
 *      unmodified help menu.
 
3379
 *
 
3380
 * Results:
 
3381
 *      None.
 
3382
 *
 
3383
 * Side effects:
 
3384
 *      Sets the global helpItemCount.
 
3385
 *
 
3386
 *----------------------------------------------------------------------
 
3387
 */
 
3388
 
 
3389
void 
 
3390
TkMacSetHelpMenuItemCount()
 
3391
{
 
3392
    MenuHandle helpMenuHandle;
 
3393
    
 
3394
    if ((HMGetHelpMenuHandle(&helpMenuHandle) != noErr) 
 
3395
            || (helpMenuHandle == NULL)) {
 
3396
        helpItemCount = -1;
 
3397
    } else {
 
3398
        helpItemCount = CountMItems(helpMenuHandle);
 
3399
        DeleteMenuItem(helpMenuHandle, helpItemCount);
 
3400
    }
 
3401
}
 
3402
 
 
3403
/*
 
3404
 *----------------------------------------------------------------------
 
3405
 *
 
3406
 * TkMacMenuClick --
 
3407
 *
 
3408
 *      Prepares a menubar for MenuSelect or MenuKey.
 
3409
 *
 
3410
 * Results:
 
3411
 *      None.
 
3412
 *
 
3413
 * Side effects:
 
3414
 *      Any pending configurations of the menubar are completed.
 
3415
 *
 
3416
 *----------------------------------------------------------------------
 
3417
 */
 
3418
 
 
3419
void
 
3420
TkMacMenuClick()
 
3421
{
 
3422
    TkMenu *menuPtr;
 
3423
    TkMenuReferences *menuRefPtr;
 
3424
    
 
3425
    if ((currentMenuBarInterp != NULL) && (currentMenuBarName != NULL)) {
 
3426
        menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
 
3427
                currentMenuBarName);
 
3428
        for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr;
 
3429
                menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) {
 
3430
            if (menuPtr->menuType == MENUBAR) {
 
3431
                CompleteIdlers(menuPtr);
 
3432
                break;
 
3433
            }
 
3434
        }
 
3435
    }
 
3436
    
 
3437
    if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
 
3438
        Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
 
3439
        DrawMenuBarWhenIdle((ClientData *) NULL);
 
3440
    }
 
3441
}
 
3442
 
 
3443
/*
 
3444
 *----------------------------------------------------------------------
 
3445
 *
 
3446
 * TkpDrawMenuEntry --
 
3447
 *
 
3448
 *      Draws the given menu entry at the given coordinates with the
 
3449
 *      given attributes.
 
3450
 *
 
3451
 * Results:
 
3452
 *      None.
 
3453
 *
 
3454
 * Side effects:
 
3455
 *      X Server commands are executed to display the menu entry.
 
3456
 *
 
3457
 *----------------------------------------------------------------------
 
3458
 */
 
3459
 
 
3460
void
 
3461
TkpDrawMenuEntry(
 
3462
    TkMenuEntry *mePtr,             /* The entry to draw */
 
3463
    Drawable d,                     /* What to draw into */
 
3464
    Tk_Font tkfont,                 /* Precalculated font for menu */
 
3465
    CONST Tk_FontMetrics *menuMetricsPtr,
 
3466
                                    /* Precalculated metrics for menu */
 
3467
    int x,                          /* X-coordinate of topleft of entry */
 
3468
    int y,                          /* Y-coordinate of topleft of entry */
 
3469
    int width,                      /* Width of the entry rectangle */
 
3470
    int height,                     /* Height of the current rectangle */
 
3471
    int strictMotif,                /* Boolean flag */
 
3472
    int drawArrow)                  /* Whether or not to draw the cascade
 
3473
                                     * arrow for cascade items. Only applies
 
3474
                                     * to Windows. */
 
3475
{
 
3476
    GC gc, indicatorGC;
 
3477
    TkMenu *menuPtr = mePtr->menuPtr;
 
3478
    Tk_3DBorder bgBorder, activeBorder;
 
3479
    CONST Tk_FontMetrics *fmPtr;
 
3480
    Tk_FontMetrics entryMetrics;
 
3481
    int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
 
3482
    int adjustedY = y + padY;
 
3483
    int adjustedHeight = height - 2 * padY;
 
3484
 
 
3485
    /*
 
3486
     * Choose the gc for drawing the foreground part of the entry.
 
3487
     * Under Appearance, we pass a null (appearanceGC) to tell 
 
3488
     * ourselves not to change whatever color the appearance manager has set.
 
3489
     */
 
3490
 
 
3491
    if ((mePtr->state == tkActiveUid)
 
3492
            && !strictMotif) {
 
3493
        gc = mePtr->activeGC;
 
3494
        if (gc == NULL) {
 
3495
            if ((TkMacHaveAppearance() > 1) && (menuPtr->menuType != TEAROFF_MENU)) {
 
3496
                SetThemeTextColor(kThemeSelectedMenuItemTextColor,32,true);
 
3497
                gc = appearanceGC;
 
3498
            } else {
 
3499
                gc = menuPtr->activeGC;
 
3500
            }
 
3501
        }
 
3502
    } else {
 
3503
        TkMenuEntry *cascadeEntryPtr;
 
3504
        int parentDisabled = 0;
 
3505
        
 
3506
        for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
 
3507
                cascadeEntryPtr != NULL;
 
3508
                cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
 
3509
            if (strcmp(cascadeEntryPtr->name, 
 
3510
                    Tk_PathName(menuPtr->tkwin)) == 0) {
 
3511
                if (cascadeEntryPtr->state == tkDisabledUid) {
 
3512
                    parentDisabled = 1;
 
3513
                }
 
3514
                break;
 
3515
            }
 
3516
        }
 
3517
 
 
3518
        if (((parentDisabled || (mePtr->state == tkDisabledUid)))
 
3519
                && (menuPtr->disabledFg != NULL)) {
 
3520
            gc = mePtr->disabledGC;
 
3521
            if (gc == NULL) {
 
3522
                if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
 
3523
                    SetThemeTextColor(kThemeDisabledMenuItemTextColor,32,true);
 
3524
                    gc = appearanceGC;
 
3525
                } else {
 
3526
                gc = menuPtr->disabledGC;
 
3527
            }
 
3528
            }
 
3529
        } else {
 
3530
            gc = mePtr->textGC;
 
3531
            if (gc == NULL) {
 
3532
                if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
 
3533
                    SetThemeTextColor(kThemeActiveMenuItemTextColor,32,true);
 
3534
                    gc = appearanceGC;
 
3535
                } else {
 
3536
                    gc = menuPtr->textGC;
 
3537
                }
 
3538
            }
 
3539
        }
 
3540
    }
 
3541
    
 
3542
    indicatorGC = mePtr->indicatorGC;
 
3543
    if (indicatorGC == NULL) {
 
3544
        indicatorGC = menuPtr->indicatorGC;
 
3545
    }
 
3546
            
 
3547
    bgBorder = mePtr->border;
 
3548
    if (bgBorder == NULL) {
 
3549
        bgBorder = menuPtr->border;
 
3550
    }
 
3551
    if (strictMotif) {
 
3552
        activeBorder = bgBorder;
 
3553
    } else {
 
3554
        activeBorder = mePtr->activeBorder;
 
3555
        if (activeBorder == NULL) {
 
3556
            activeBorder = menuPtr->activeBorder;
 
3557
        }
 
3558
    }
 
3559
 
 
3560
    if (mePtr->tkfont == NULL) {
 
3561
        fmPtr = menuMetricsPtr;
 
3562
    } else {
 
3563
        tkfont = mePtr->tkfont;
 
3564
        Tk_GetFontMetrics(tkfont, &entryMetrics);
 
3565
        fmPtr = &entryMetrics;
 
3566
    }
 
3567
 
 
3568
    /*
 
3569
     * Need to draw the entire background, including padding. On Unix,
 
3570
     * for menubars, we have to draw the rest of the entry taking
 
3571
     * into account the padding.
 
3572
     */
 
3573
    
 
3574
    DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, 
 
3575
            bgBorder, x, y, width, height);
 
3576
    
 
3577
    if (mePtr->type == SEPARATOR_ENTRY) {
 
3578
        DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, 
 
3579
                fmPtr, x, adjustedY, width, adjustedHeight);
 
3580
    } else if (mePtr->type == TEAROFF_ENTRY) {
 
3581
        DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
 
3582
                width, adjustedHeight);
 
3583
    } else {
 
3584
        DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, 
 
3585
                adjustedY, width, adjustedHeight);
 
3586
        DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
 
3587
                activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
 
3588
        if (!mePtr->hideMargin) {
 
3589
            DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
 
3590
                    fmPtr, x, adjustedY, width, adjustedHeight);
 
3591
        }
 
3592
    
 
3593
    }
 
3594
}
 
3595
 
 
3596
/*
 
3597
 *--------------------------------------------------------------
 
3598
 *
 
3599
 * TkpComputeStandardMenuGeometry --
 
3600
 *
 
3601
 *      This procedure is invoked to recompute the size and
 
3602
 *      layout of a menu that is not a menubar clone.
 
3603
 *
 
3604
 * Results:
 
3605
 *      None.
 
3606
 *
 
3607
 * Side effects:
 
3608
 *      Fields of menu entries are changed to reflect their
 
3609
 *      current positions, and the size of the menu window
 
3610
 *      itself may be changed.
 
3611
 *
 
3612
 *--------------------------------------------------------------
 
3613
 */
 
3614
 
 
3615
void
 
3616
TkpComputeStandardMenuGeometry(
 
3617
    TkMenu *menuPtr)            /* Structure describing menu. */
 
3618
{
 
3619
    Tk_Font tkfont;
 
3620
    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
 
3621
    int x, y, height, modifierWidth, labelWidth, indicatorSpace;
 
3622
    int windowWidth, windowHeight, accelWidth, maxAccelTextWidth;
 
3623
    int i, j, lastColumnBreak, maxModifierWidth, maxWidth, nonAccelMargin;
 
3624
    int maxNonAccelMargin, maxEntryWithAccelWidth, maxEntryWithoutAccelWidth;
 
3625
    int entryWidth, maxIndicatorSpace;
 
3626
    TkMenuEntry *mePtr, *columnEntryPtr;
 
3627
    EntryGeometry *geometryPtr;
 
3628
    
 
3629
    if (menuPtr->tkwin == NULL) {
 
3630
        return;
 
3631
    }
 
3632
 
 
3633
    x = y = menuPtr->borderWidth;
 
3634
    indicatorSpace = labelWidth = accelWidth = maxAccelTextWidth = 0;
 
3635
    windowHeight = windowWidth = maxWidth = lastColumnBreak = 0;
 
3636
    maxModifierWidth = nonAccelMargin = maxNonAccelMargin = 0;
 
3637
    maxEntryWithAccelWidth = maxEntryWithoutAccelWidth = 0;
 
3638
    maxIndicatorSpace = 0;
 
3639
 
 
3640
    /*
 
3641
     * On the Mac especially, getting font metrics can be quite slow,
 
3642
     * so we want to do it intelligently. We are going to precalculate
 
3643
     * them and pass them down to all of the measuring and drawing
 
3644
     * routines. We will measure the font metrics of the menu once.
 
3645
     * If an entry does not have its own font set, then we give
 
3646
     * the geometry/drawing routines the menu's font and metrics.
 
3647
     * If an entry has its own font, we will measure that font and
 
3648
     * give all of the geometry/drawing the entry's font and metrics.
 
3649
     */
 
3650
 
 
3651
    Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
 
3652
 
 
3653
    for (i = 0; i < menuPtr->numEntries; i++) {
 
3654
        mePtr = menuPtr->entries[i];
 
3655
        tkfont = mePtr->tkfont;
 
3656
        if (tkfont == NULL) {
 
3657
            tkfont = menuPtr->tkfont;
 
3658
            fmPtr = &menuMetrics;
 
3659
        } else {
 
3660
            Tk_GetFontMetrics(tkfont, &entryMetrics);
 
3661
            fmPtr = &entryMetrics;
 
3662
        }
 
3663
        
 
3664
        if ((i > 0) && mePtr->columnBreak) {
 
3665
            if (maxIndicatorSpace != 0) {
 
3666
                maxIndicatorSpace += 2;
 
3667
            }
 
3668
            for (j = lastColumnBreak; j < i; j++) {
 
3669
                columnEntryPtr = menuPtr->entries[j];
 
3670
                geometryPtr =
 
3671
                        (EntryGeometry *) columnEntryPtr->platformEntryData;
 
3672
                
 
3673
                columnEntryPtr->indicatorSpace = maxIndicatorSpace;
 
3674
                columnEntryPtr->width = maxIndicatorSpace + maxWidth 
 
3675
                        + 2 * menuPtr->activeBorderWidth;
 
3676
                geometryPtr->accelTextWidth = maxAccelTextWidth;
 
3677
                geometryPtr->modifierWidth = maxModifierWidth;
 
3678
                columnEntryPtr->x = x;
 
3679
                columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
 
3680
                if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
 
3681
                    geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
 
3682
                            - maxEntryWithAccelWidth;
 
3683
                    if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
 
3684
                        geometryPtr->nonAccelMargin = maxNonAccelMargin;
 
3685
                    }
 
3686
                } else {
 
3687
                    geometryPtr->nonAccelMargin = 0;
 
3688
                }               
 
3689
            }
 
3690
            x += maxIndicatorSpace + maxWidth + 2 * menuPtr->borderWidth;
 
3691
            windowWidth = x;
 
3692
            maxWidth = maxIndicatorSpace = maxAccelTextWidth = 0;
 
3693
            maxModifierWidth = maxNonAccelMargin = maxEntryWithAccelWidth = 0;
 
3694
            maxEntryWithoutAccelWidth = 0;
 
3695
            lastColumnBreak = i;
 
3696
            y = menuPtr->borderWidth;
 
3697
        }
 
3698
 
 
3699
        if (mePtr->type == SEPARATOR_ENTRY) {
 
3700
            GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont,
 
3701
                    fmPtr, &entryWidth, &height);
 
3702
            mePtr->height = height;
 
3703
        } else if (mePtr->type == TEAROFF_ENTRY) {
 
3704
            GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, 
 
3705
                    fmPtr, &entryWidth, &height);
 
3706
            mePtr->height = height;
 
3707
        } else {
 
3708
            
 
3709
            /*
 
3710
             * For each entry, compute the height required by that
 
3711
             * particular entry, plus three widths:  the width of the
 
3712
             * label, the width to allow for an indicator to be displayed
 
3713
             * to the left of the label (if any), and the width of the
 
3714
             * accelerator to be displayed to the right of the label
 
3715
             * (if any).  These sizes depend, of course, on the type
 
3716
             * of the entry.
 
3717
             */
 
3718
            
 
3719
            GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &labelWidth,
 
3720
                    &height);
 
3721
            mePtr->height = height;
 
3722
        
 
3723
            if (mePtr->type == CASCADE_ENTRY) {
 
3724
                GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr,
 
3725
                        &modifierWidth, &accelWidth, &height);
 
3726
                nonAccelMargin = 0;
 
3727
            } else if (mePtr->accelLength == 0) {
 
3728
                nonAccelMargin = mePtr->hideMargin ? 0 
 
3729
                        : Tk_TextWidth(tkfont, "m", 1);
 
3730
                accelWidth = modifierWidth = 0;
 
3731
            } else {
 
3732
                labelWidth += Tk_TextWidth(tkfont, "m", 1);
 
3733
                GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
 
3734
                        fmPtr, &modifierWidth, &accelWidth, &height);
 
3735
                if (height > mePtr->height) {
 
3736
                    mePtr->height = height;
 
3737
                }
 
3738
                nonAccelMargin = 0;
 
3739
            }
 
3740
 
 
3741
            if (!(mePtr->hideMargin)) {
 
3742
                GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, 
 
3743
                        fmPtr, &indicatorSpace, &height);
 
3744
                if (height > mePtr->height) {
 
3745
                    mePtr->height = height;
 
3746
                }
 
3747
            } else {
 
3748
                indicatorSpace = 0;
 
3749
            }
 
3750
 
 
3751
            if (nonAccelMargin > maxNonAccelMargin) {
 
3752
                maxNonAccelMargin = nonAccelMargin;
 
3753
            }
 
3754
            if (accelWidth > maxAccelTextWidth) {
 
3755
                maxAccelTextWidth = accelWidth;
 
3756
            }
 
3757
            if (modifierWidth > maxModifierWidth) {
 
3758
                maxModifierWidth = modifierWidth;
 
3759
            }
 
3760
            if (indicatorSpace > maxIndicatorSpace) {
 
3761
                maxIndicatorSpace = indicatorSpace;
 
3762
            }
 
3763
 
 
3764
            entryWidth = labelWidth + modifierWidth + accelWidth
 
3765
                    + nonAccelMargin;
 
3766
 
 
3767
            if (entryWidth > maxWidth) {
 
3768
                maxWidth = entryWidth;
 
3769
            }
 
3770
            
 
3771
            if (mePtr->accelLength > 0) {
 
3772
                if (entryWidth > maxEntryWithAccelWidth) {
 
3773
                    maxEntryWithAccelWidth = entryWidth;
 
3774
                }
 
3775
            } else {
 
3776
                if (entryWidth > maxEntryWithoutAccelWidth) {
 
3777
                    maxEntryWithoutAccelWidth = entryWidth;
 
3778
                }
 
3779
            }
 
3780
            
 
3781
            mePtr->height += 2 * menuPtr->activeBorderWidth;
 
3782
        }
 
3783
        mePtr->y = y;
 
3784
        y += menuPtr->entries[i]->height + menuPtr->borderWidth;
 
3785
        if (y > windowHeight) {
 
3786
            windowHeight = y;
 
3787
        }
 
3788
    }
 
3789
 
 
3790
    for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
 
3791
        columnEntryPtr = menuPtr->entries[j];
 
3792
        geometryPtr = (EntryGeometry *) columnEntryPtr->platformEntryData;
 
3793
        
 
3794
        columnEntryPtr->indicatorSpace = maxIndicatorSpace;
 
3795
        columnEntryPtr->width = maxIndicatorSpace + maxWidth 
 
3796
                + 2 * menuPtr->activeBorderWidth;
 
3797
        geometryPtr->accelTextWidth = maxAccelTextWidth;
 
3798
        geometryPtr->modifierWidth = maxModifierWidth;
 
3799
        columnEntryPtr->x = x;
 
3800
        columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
 
3801
        if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
 
3802
            geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
 
3803
                    - maxEntryWithAccelWidth;
 
3804
            if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
 
3805
                geometryPtr->nonAccelMargin = maxNonAccelMargin;
 
3806
            }
 
3807
        } else {
 
3808
            geometryPtr->nonAccelMargin = 0;
 
3809
        }               
 
3810
    }
 
3811
    windowWidth = x + maxIndicatorSpace + maxWidth
 
3812
            + 2 * menuPtr->activeBorderWidth + menuPtr->borderWidth;
 
3813
    windowHeight += menuPtr->borderWidth;
 
3814
    
 
3815
    /*
 
3816
     * The X server doesn't like zero dimensions, so round up to at least
 
3817
     * 1 (a zero-sized menu should never really occur, anyway).
 
3818
     */
 
3819
 
 
3820
    if (windowWidth <= 0) {
 
3821
        windowWidth = 1;
 
3822
    }
 
3823
    if (windowHeight <= 0) {
 
3824
        windowHeight = 1;
 
3825
    }
 
3826
    menuPtr->totalWidth = windowWidth;
 
3827
    menuPtr->totalHeight = windowHeight;
 
3828
}
 
3829
 
 
3830
/*
 
3831
 *----------------------------------------------------------------------
 
3832
 *
 
3833
 * DrawMenuEntryLabel --
 
3834
 *
 
3835
 *      This procedure draws the label part of a menu.
 
3836
 *
 
3837
 * Results:
 
3838
 *      None.
 
3839
 *
 
3840
 * Side effects:
 
3841
 *      Commands are output to X to display the menu in its
 
3842
 *      current mode.
 
3843
 *
 
3844
 *----------------------------------------------------------------------
 
3845
 */
 
3846
 
 
3847
static void
 
3848
DrawMenuEntryLabel(
 
3849
    TkMenu *menuPtr,                    /* The menu we are drawing */
 
3850
    TkMenuEntry *mePtr,                 /* The entry we are drawing */
 
3851
    Drawable d,                         /* What we are drawing into */
 
3852
    GC gc,                              /* The gc we are drawing into */
 
3853
    Tk_Font tkfont,                     /* The precalculated font */
 
3854
    CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
 
3855
    int x,                              /* left edge */
 
3856
    int y,                              /* right edge */
 
3857
    int width,                          /* width of entry */
 
3858
    int height)                         /* height of entry */
 
3859
{
 
3860
    int baseline;
 
3861
    int indicatorSpace =  mePtr->indicatorSpace;
 
3862
    int leftEdge = x + indicatorSpace;
 
3863
    int imageHeight, imageWidth;
 
3864
    
 
3865
    /*
 
3866
     * Draw label or bitmap or image for entry.
 
3867
     */
 
3868
 
 
3869
    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
 
3870
    if (mePtr->image != NULL) {
 
3871
        Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
 
3872
        if ((mePtr->selectImage != NULL)
 
3873
                && (mePtr->entryFlags & ENTRY_SELECTED)) {
 
3874
            Tk_RedrawImage(mePtr->selectImage, 0, 0,
 
3875
                    imageWidth, imageHeight, d, leftEdge,
 
3876
                    (int) (y + (mePtr->height - imageHeight)/2));
 
3877
        } else {
 
3878
            Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
 
3879
                    imageHeight, d, leftEdge,
 
3880
                    (int) (y + (mePtr->height - imageHeight)/2));
 
3881
        }
 
3882
    } else if (mePtr->bitmap != None) {
 
3883
        int width, height;
 
3884
 
 
3885
        Tk_SizeOfBitmap(menuPtr->display,
 
3886
                mePtr->bitmap, &width, &height);
 
3887
        XCopyPlane(menuPtr->display,
 
3888
                mePtr->bitmap, d,
 
3889
                gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
 
3890
                (int) (y + (mePtr->height - height)/2), 1);
 
3891
    } else {
 
3892
        if (mePtr->labelLength > 0) {
 
3893
            Str255 itemText;
 
3894
            
 
3895
            GetEntryText(mePtr, itemText);
 
3896
            Tk_DrawChars(menuPtr->display, d, gc,
 
3897
                    tkfont, (char *) itemText + 1, itemText[0],
 
3898
                    leftEdge, baseline);
 
3899
/*          TkpDrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
 
3900
                    width, height);*/
 
3901
        }
 
3902
    }
 
3903
 
 
3904
    if (mePtr->state == tkDisabledUid) {
 
3905
        if (menuPtr->disabledFg == NULL) {
 
3906
            if (!TkMacHaveAppearance()) {
 
3907
                XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
 
3908
                        (unsigned) width, (unsigned) height);
 
3909
            }
 
3910
        } else if ((mePtr->image != NULL) 
 
3911
                && (menuPtr->disabledImageGC != None)) {
 
3912
            XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
 
3913
                    leftEdge,
 
3914
                    (int) (y + (mePtr->height - imageHeight)/2),
 
3915
                    (unsigned) imageWidth, (unsigned) imageHeight);
 
3916
        }
 
3917
    }
 
3918
}
 
3919
 
 
3920
/*
 
3921
 *----------------------------------------------------------------------
 
3922
 *
 
3923
 * DrawMenuEntryBackground --
 
3924
 *
 
3925
 *      This procedure draws the background part of a menu entry.
 
3926
 *      Under Appearance, we only draw the background if the entry's
 
3927
 *      border is set, we DO NOT inherit it from the menu...
 
3928
 *
 
3929
 * Results:
 
3930
 *      None.
 
3931
 *
 
3932
 * Side effects:
 
3933
 *      Commands are output to X to display the menu in its
 
3934
 *      current mode.
 
3935
 *
 
3936
 *----------------------------------------------------------------------
 
3937
 */
 
3938
 
 
3939
static void
 
3940
DrawMenuEntryBackground(
 
3941
    TkMenu *menuPtr,                    /* The menu we are drawing. */
 
3942
    TkMenuEntry *mePtr,                 /* The entry we are drawing. */
 
3943
    Drawable d,                         /* What we are drawing into */
 
3944
    Tk_3DBorder activeBorder,           /* Border for active items */
 
3945
    Tk_3DBorder bgBorder,               /* Border for the background */
 
3946
    int x,                              /* left edge */
 
3947
    int y,                              /* top edge */
 
3948
    int width,                          /* width of rectangle to draw */
 
3949
    int height)                         /* height of rectangle to draw */
 
3950
{
 
3951
    if (!TkMacHaveAppearance()
 
3952
            || (menuPtr->menuType == TEAROFF_MENU)
 
3953
            || ((mePtr->state == tkActiveUid) && (mePtr->activeBorder != NULL)) 
 
3954
            || ((mePtr->state != tkActiveUid) && (mePtr->border != NULL))) {
 
3955
        if (mePtr->state == tkActiveUid) {
 
3956
            bgBorder = activeBorder;
 
3957
        }
 
3958
        Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
 
3959
                x, y, width, height, 0, TK_RELIEF_FLAT);
 
3960
    }
 
3961
}
 
3962
 
 
3963
/*
 
3964
 *----------------------------------------------------------------------
 
3965
 *
 
3966
 * GetMenuLabelGeometry --
 
3967
 *
 
3968
 *      Figures out the size of the label portion of a menu item.
 
3969
 *
 
3970
 * Results:
 
3971
 *      widthPtr and heightPtr are filled in with the correct geometry
 
3972
 *      information.
 
3973
 *
 
3974
 * Side effects:
 
3975
 *      None.
 
3976
 *
 
3977
 *----------------------------------------------------------------------
 
3978
 */
 
3979
 
 
3980
static void
 
3981
GetMenuLabelGeometry(
 
3982
    TkMenuEntry *mePtr,                 /* The entry we are computing */
 
3983
    Tk_Font tkfont,                     /* The precalculated font */
 
3984
    CONST Tk_FontMetrics *fmPtr,        /* The precalculated metrics */
 
3985
    int *widthPtr,                      /* The resulting width of the label
 
3986
                                         * portion */
 
3987
    int *heightPtr)                     /* The resulting height of the label
 
3988
                                         * portion */
 
3989
{
 
3990
    TkMenu *menuPtr = mePtr->menuPtr;
 
3991
 
 
3992
    if (mePtr->image != NULL) {
 
3993
        Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
 
3994
    } else if (mePtr->bitmap != (Pixmap) NULL) {
 
3995
        Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
 
3996
    } else {
 
3997
        *heightPtr = fmPtr->linespace;
 
3998
        
 
3999
        if (mePtr->label != NULL) {
 
4000
            Str255 itemText;
 
4001
            
 
4002
            GetEntryText(mePtr, itemText);
 
4003
            *widthPtr = Tk_TextWidth(tkfont, (char *) itemText + 1,
 
4004
                    itemText[0]);
 
4005
        } else {
 
4006
            *widthPtr = 0;
 
4007
        }
 
4008
    }
 
4009
    *heightPtr += 1;
 
4010
}
 
4011
 
 
4012
/*
 
4013
 *----------------------------------------------------------------------
 
4014
 *
 
4015
 * MenuSelectEvent --
 
4016
 *
 
4017
 *      Generates a "MenuSelect" virtual event. This can be used to
 
4018
 *      do context-sensitive menu help.
 
4019
 *
 
4020
 * Results:
 
4021
 *      None.
 
4022
 *
 
4023
 * Side effects:
 
4024
 *      Places a virtual event on the event queue.
 
4025
 *
 
4026
 *----------------------------------------------------------------------
 
4027
 */
 
4028
 
 
4029
static void
 
4030
MenuSelectEvent(
 
4031
    TkMenu *menuPtr)            /* the menu we have selected. */
 
4032
{
 
4033
    XVirtualEvent event;
 
4034
    Point where;
 
4035
   
 
4036
    event.type = VirtualEvent;
 
4037
    event.serial = menuPtr->display->request;
 
4038
    event.send_event = false;
 
4039
    event.display = menuPtr->display;
 
4040
    Tk_MakeWindowExist(menuPtr->tkwin);
 
4041
    event.event = Tk_WindowId(menuPtr->tkwin);
 
4042
    event.root = XRootWindow(menuPtr->display, 0);
 
4043
    event.subwindow = None;
 
4044
    event.time = TkpGetMS();
 
4045
    
 
4046
    GetMouse(&where);
 
4047
    event.x_root = where.h;
 
4048
    event.y_root = where.v;
 
4049
    event.state = TkMacButtonKeyState();
 
4050
    event.same_screen = true;
 
4051
    event.name = Tk_GetUid("MenuSelect");
 
4052
    Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
 
4053
}
 
4054
 
 
4055
/*
 
4056
 *----------------------------------------------------------------------
 
4057
 *
 
4058
 * RecursivelyClearActiveMenu --
 
4059
 *
 
4060
 *      Recursively clears the active entry in the menu's cascade hierarchy.
 
4061
 *
 
4062
 * Results:
 
4063
 *      None.
 
4064
 *
 
4065
 * Side effects:
 
4066
 *      Generates <<MenuSelect>> virtual events.
 
4067
 *
 
4068
 *----------------------------------------------------------------------
 
4069
 */
 
4070
 
 
4071
void
 
4072
RecursivelyClearActiveMenu(
 
4073
    TkMenu *menuPtr)            /* The menu to reset. */
 
4074
{
 
4075
    int i;
 
4076
    TkMenuEntry *mePtr;
 
4077
    
 
4078
    TkActivateMenuEntry(menuPtr, -1);
 
4079
    MenuSelectEvent(menuPtr);
 
4080
    for (i = 0; i < menuPtr->numEntries; i++) {
 
4081
        mePtr = menuPtr->entries[i];
 
4082
        if (mePtr->type == CASCADE_ENTRY) {
 
4083
            if ((mePtr->childMenuRefPtr != NULL)
 
4084
                    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
 
4085
                RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
 
4086
            }
 
4087
        }
 
4088
    }
 
4089
}
 
4090
 
 
4091
/*
 
4092
 *----------------------------------------------------------------------
 
4093
 *
 
4094
 * InvalidateMDEFRgns --
 
4095
 *
 
4096
 *      Invalidates the regions covered by menus that did redrawing and
 
4097
 *      might be damaged.
 
4098
 *
 
4099
 * Results:
 
4100
 *      None.
 
4101
 *
 
4102
 * Side effects:
 
4103
 *      Generates Mac update events for affected windows.
 
4104
 *
 
4105
 *----------------------------------------------------------------------
 
4106
 */
 
4107
 
 
4108
void
 
4109
InvalidateMDEFRgns(void) {
 
4110
    GDHandle saveDevice;
 
4111
    GWorldPtr saveWorld, destPort;
 
4112
    Point scratch;
 
4113
    MacDrawable *macDraw;
 
4114
    TkMacWindowList *listPtr;
 
4115
    
 
4116
    if (totalMenuRgn == NULL) {
 
4117
        return;
 
4118
    }
 
4119
    
 
4120
    GetGWorld(&saveWorld, &saveDevice);
 
4121
    for (listPtr = tkMacWindowListPtr ; listPtr != NULL; 
 
4122
            listPtr = listPtr->nextPtr) {
 
4123
        macDraw = (MacDrawable *) Tk_WindowId(listPtr->winPtr);
 
4124
        if (macDraw->flags & TK_DRAWN_UNDER_MENU) {
 
4125
            destPort = TkMacGetDrawablePort(Tk_WindowId(listPtr->winPtr));
 
4126
            SetGWorld(destPort, NULL);
 
4127
            scratch.h = scratch.v = 0;
 
4128
            GlobalToLocal(&scratch);
 
4129
            OffsetRgn(totalMenuRgn, scratch.v, scratch.h);
 
4130
            InvalRgn(totalMenuRgn);
 
4131
            OffsetRgn(totalMenuRgn, -scratch.v, -scratch.h);
 
4132
            macDraw->flags &= ~TK_DRAWN_UNDER_MENU;
 
4133
        }
 
4134
    }
 
4135
    
 
4136
    SetGWorld(saveWorld, saveDevice);
 
4137
    SetEmptyRgn(totalMenuRgn);
 
4138
}
 
4139
 
 
4140
/*
 
4141
 *----------------------------------------------------------------------
 
4142
 *
 
4143
 * TkMacClearMenubarActive --
 
4144
 *
 
4145
 *      Recursively clears the active entry in the current menubar hierarchy.
 
4146
 *
 
4147
 * Results:
 
4148
 *      None.
 
4149
 *
 
4150
 * Side effects:
 
4151
 *      Generates <<MenuSelect>> virtual events.
 
4152
 *
 
4153
 *----------------------------------------------------------------------
 
4154
 */
 
4155
 
 
4156
void
 
4157
TkMacClearMenubarActive(void) {
 
4158
    TkMenuReferences *menuBarRefPtr;
 
4159
    
 
4160
    if (currentMenuBarName != NULL) {
 
4161
        menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp,
 
4162
                currentMenuBarName);
 
4163
        if ((menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL)) {
 
4164
            TkMenu *menuPtr;
 
4165
            
 
4166
            for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
 
4167
                    menuPtr = menuPtr->nextInstancePtr) {
 
4168
                if (menuPtr->menuType == MENUBAR) {
 
4169
                    RecursivelyClearActiveMenu(menuPtr);
 
4170
                }
 
4171
            }
 
4172
        }
 
4173
    }
 
4174
    InvalidateMDEFRgns();
 
4175
    FixMDEF();
 
4176
}
 
4177
 
 
4178
/*
 
4179
 *----------------------------------------------------------------------
 
4180
 *
 
4181
 * TkpMenuNotifyToplevelCreate --
 
4182
 *
 
4183
 *      This routine reconfigures the menu and the clones indicated by
 
4184
 *      menuName becuase a toplevel has been created and any system
 
4185
 *      menus need to be created. Only applicable to Windows.
 
4186
 *
 
4187
 * Results:
 
4188
 *      None.
 
4189
 *
 
4190
 * Side effects:
 
4191
 *      An idle handler is set up to do the reconfiguration.
 
4192
 *
 
4193
 *----------------------------------------------------------------------
 
4194
 */
 
4195
 
 
4196
void
 
4197
TkpMenuNotifyToplevelCreate(
 
4198
    Tcl_Interp *interp,                 /* The interp the menu lives in. */
 
4199
    char *menuName)                     /* The name of the menu to 
 
4200
                                         * reconfigure. */
 
4201
{
 
4202
    /*
 
4203
     * Nothing to do.
 
4204
     */
 
4205
}
 
4206
 
 
4207
/*
 
4208
 *----------------------------------------------------------------------
 
4209
 *
 
4210
 * FixMDEF --
 
4211
 *
 
4212
 *      Loads the MDEF and blasts our routine descriptor into it.
 
4213
 *      We have to set up the MDEF. This is pretty slimy. The real MDEF
 
4214
 *      resource is 68K code. All this code does is call another procedure.
 
4215
 *      When the application in launched, a dummy value for the procedure
 
4216
 *      is compiled into the MDEF. We are going to replace that dummy
 
4217
 *      value with a routine descriptor. When the routine descriptor
 
4218
 *      is invoked, the globals and everything will be setup, and we
 
4219
 *      can do what we need. This will not work from 68K or CFM 68k
 
4220
 *      currently, so we will conditional compile this until we
 
4221
 *      figure it out. 
 
4222
 *
 
4223
 * Results:
 
4224
 *      Returns the MDEF handle.
 
4225
 *
 
4226
 * Side effects:
 
4227
 *      The MDEF is read in and massaged.
 
4228
 *
 
4229
 *----------------------------------------------------------------------
 
4230
 */
 
4231
 
 
4232
static Handle
 
4233
FixMDEF(void)
 
4234
{
 
4235
#ifdef GENERATINGCFM
 
4236
    Handle MDEFHandle = GetResource('MDEF', 591);
 
4237
    Handle SICNHandle = GetResource('SICN', SICN_RESOURCE_NUMBER);
 
4238
    if ((MDEFHandle != NULL) && (SICNHandle != NULL)) {
 
4239
        HLock(MDEFHandle);
 
4240
        HLock(SICNHandle);
 
4241
        if (menuDefProc == NULL) {
 
4242
            menuDefProc = TkNewMenuDefProc(MenuDefProc);
 
4243
        }
 
4244
        memmove((void *) (((long) (*MDEFHandle)) + 0x24), &menuDefProc, 4);
 
4245
        return MDEFHandle;
 
4246
    } else {
 
4247
        return NULL;
 
4248
    }
 
4249
#else
 
4250
    return NULL;
 
4251
#endif
 
4252
}
 
4253
 
 
4254
/*
 
4255
 *----------------------------------------------------------------------
 
4256
 *
 
4257
 * TkpMenuInit --
 
4258
 *
 
4259
 *      Initializes Mac-specific menu data.
 
4260
 *
 
4261
 * Results:
 
4262
 *      None.
 
4263
 *
 
4264
 * Side effects:
 
4265
 *      Allcates a hash table.
 
4266
 *
 
4267
 *----------------------------------------------------------------------
 
4268
 */
 
4269
 
 
4270
void
 
4271
TkpMenuInit(void)
 
4272
{
 
4273
    lastMenuID = 256;
 
4274
    Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
 
4275
    currentMenuBarOwner = NULL;
 
4276
    tearoffStruct.menuPtr = NULL;
 
4277
    currentAppleMenuID = 0;
 
4278
    currentHelpMenuID = 0;
 
4279
    currentMenuBarInterp = NULL;
 
4280
    currentMenuBarName = NULL;
 
4281
    windowListPtr = NULL;
 
4282
    
 
4283
    /*
 
4284
     * Get the GC that we will use as the sign to the font
 
4285
     * routines that they should not muck with the foreground color...
 
4286
     */
 
4287
    
 
4288
    if (TkMacHaveAppearance() > 1) {
 
4289
        XGCValues tmpValues;
 
4290
        TkColor *tmpColorPtr;
 
4291
        
 
4292
        tmpColorPtr = TkpGetColor(NULL, "systemAppearanceColor");
 
4293
        tmpValues.foreground = tmpColorPtr->color.pixel;
 
4294
        tmpValues.background = tmpColorPtr->color.pixel;
 
4295
        appearanceGC = XCreateGC(NULL, NULL, GCForeground | GCBackground, &tmpValues);
 
4296
        ckfree((char *) tmpColorPtr);
 
4297
        
 
4298
        tkThemeMenuItemDrawingUPP = NewMenuItemDrawingProc(tkThemeMenuItemDrawingProc);                         
 
4299
    }
 
4300
    FixMDEF();
 
4301
 
 
4302
}