OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [unix/] [tkUnixMenu.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkUnixMenu.c --
3
 *
4
 *      This module implements the UNIX 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: tkUnixMenu.c,v 1.1.1.1 2002-01-16 10:26:01 markom Exp $
12
 */
13
 
14
#include "tkPort.h"
15
#include "default.h"
16
#include "tkInt.h"
17
#include "tkUnixInt.h"
18
#include "tkMenu.h"
19
 
20
/*
21
 * Constants used for menu drawing.
22
 */
23
 
24
#define MENU_MARGIN_WIDTH       2
25
#define MENU_DIVIDER_HEIGHT     2
26
 
27
/*
28
 * Platform specific flags for Unix.
29
 */
30
 
31
#define ENTRY_HELP_MENU         ENTRY_PLATFORM_FLAG1
32
 
33
/*
34
 * Procedures used internally.
35
 */
36
 
37
static void             SetHelpMenu _ANSI_ARGS_((TkMenu *menuPtr));
38
static void             DrawMenuEntryAccelerator _ANSI_ARGS_((
39
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
40
                            Drawable d, GC gc, Tk_Font tkfont,
41
                            CONST Tk_FontMetrics *fmPtr,
42
                            Tk_3DBorder activeBorder, int x, int y,
43
                            int width, int height, int drawArrow));
44
static void             DrawMenuEntryBackground _ANSI_ARGS_((
45
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
46
                            Drawable d, Tk_3DBorder activeBorder,
47
                            Tk_3DBorder bgBorder, int x, int y,
48
                            int width, int heigth));
49
static void             DrawMenuEntryIndicator _ANSI_ARGS_((
50
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
51
                            Drawable d, GC gc, GC indicatorGC,
52
                            Tk_Font tkfont,
53
                            CONST Tk_FontMetrics *fmPtr, int x, int y,
54
                            int width, int height));
55
static void             DrawMenuEntryLabel _ANSI_ARGS_((
56
                            TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
57
                            GC gc, Tk_Font tkfont,
58
                            CONST Tk_FontMetrics *fmPtr, int x, int y,
59
                            int width, int height));
60
static void             DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
61
                            TkMenuEntry *mePtr, Drawable d, GC gc,
62
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
63
                            int x, int y, int width, int height));
64
static void             DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
65
                            TkMenuEntry *mePtr, Drawable d, GC gc,
66
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
67
                            int x, int y, int width, int height));
68
static void             DrawMenuUnderline _ANSI_ARGS_((TkMenu *menuPtr,
69
                            TkMenuEntry *mePtr, Drawable d, GC gc,
70
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, int x,
71
                            int y, int width, int height));
72
static void             GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
73
                            TkMenuEntry *mePtr, Tk_Font tkfont,
74
                            CONST Tk_FontMetrics *fmPtr, int *widthPtr,
75
                            int *heightPtr));
76
static void             GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
77
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
78
                            int *widthPtr, int *heightPtr));
79
static void             GetMenuIndicatorGeometry _ANSI_ARGS_((
80
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
81
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
82
                            int *widthPtr, int *heightPtr));
83
static void             GetMenuSeparatorGeometry _ANSI_ARGS_((
84
                            TkMenu *menuPtr, TkMenuEntry *mePtr,
85
                            Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
86
                            int *widthPtr, int *heightPtr));
87
static void             GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
88
                            TkMenuEntry *mePtr, Tk_Font tkfont,
89
                            CONST Tk_FontMetrics *fmPtr, int *widthPtr,
90
                            int *heightPtr));
91
 
92
 
93
/*
94
 *----------------------------------------------------------------------
95
 *
96
 * TkpNewMenu --
97
 *
98
 *      Gets the platform-specific piece of the menu. Invoked during idle
99
 *      after the generic part of the menu has been created.
100
 *
101
 * Results:
102
 *      Standard TCL error.
103
 *
104
 * Side effects:
105
 *      Allocates any platform specific allocations and places them
106
 *      in the platformData field of the menuPtr.
107
 *
108
 *----------------------------------------------------------------------
109
 */
110
 
111
int
112
TkpNewMenu(menuPtr)
113
    TkMenu *menuPtr;
114
{
115
    SetHelpMenu(menuPtr);
116
    return TCL_OK;
117
}
118
 
119
/*
120
 *----------------------------------------------------------------------
121
 *
122
 * TkpDestroyMenu --
123
 *
124
 *      Destroys platform-specific menu structures. Called when the
125
 *      generic menu structure is destroyed for the menu.
126
 *
127
 * Results:
128
 *      None.
129
 *
130
 * Side effects:
131
 *      All platform-specific allocations are freed up.
132
 *
133
 *----------------------------------------------------------------------
134
 */
135
 
136
void
137
TkpDestroyMenu(menuPtr)
138
    TkMenu *menuPtr;
139
{
140
    /*
141
     * Nothing to do.
142
     */
143
}
144
 
145
/*
146
 *----------------------------------------------------------------------
147
 *
148
 * TkpDestroyMenuEntry --
149
 *
150
 *      Cleans up platform-specific menu entry items. Called when entry
151
 *      is destroyed in the generic code.
152
 *
153
 * Results:
154
 *      None.
155
 *
156
 * Side effects:
157
 *      All platform specific allocations are freed up.
158
 *
159
 *----------------------------------------------------------------------
160
 */
161
 
162
void
163
TkpDestroyMenuEntry(mEntryPtr)
164
    TkMenuEntry *mEntryPtr;
165
{
166
    /*
167
     * Nothing to do.
168
     */
169
}
170
 
171
/*
172
 *----------------------------------------------------------------------
173
 *
174
 * TkpConfigureMenuEntry --
175
 *
176
 *      Processes configuration options for menu entries. Called when
177
 *      the generic options are processed for the menu.
178
 *
179
 * Results:
180
 *      Returns standard TCL result. If TCL_ERROR is returned, then
181
 *      interp->result contains an error message.
182
 *
183
 * Side effects:
184
 *      Configuration information get set for mePtr; old resources
185
 *      get freed, if any need it.
186
 *
187
 *----------------------------------------------------------------------
188
 */
189
 
190
int
191
TkpConfigureMenuEntry(mePtr)
192
    register TkMenuEntry *mePtr;        /* Information about menu entry;  may
193
                                         * or may not already have values for
194
                                         * some fields. */
195
{
196
    /*
197
     * If this is a cascade menu, and the child menu exists, check to
198
     * see if the child menu is a help menu.
199
     */
200
 
201
    if ((mePtr->type == CASCADE_ENTRY) && (mePtr->name != NULL)) {
202
        TkMenuReferences *menuRefPtr;
203
 
204
        menuRefPtr = TkFindMenuReferences(mePtr->menuPtr->interp,
205
                mePtr->name);
206
        if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {
207
            SetHelpMenu(menuRefPtr->menuPtr);
208
        }
209
    }
210
    return TCL_OK;
211
}
212
 
213
/*
214
 *----------------------------------------------------------------------
215
 *
216
 * TkpMenuNewEntry --
217
 *
218
 *      Called when a new entry is created in a menu. Fills in platform
219
 *      specific data for the entry. The platformEntryData field
220
 *      is used to store the indicator diameter for radio button
221
 *      and check box entries.
222
 *
223
 * Results:
224
 *      Standard TCL error.
225
 *
226
 * Side effects:
227
 *      None on Unix.
228
 *
229
 *----------------------------------------------------------------------
230
 */
231
 
232
int
233
TkpMenuNewEntry(mePtr)
234
    TkMenuEntry *mePtr;
235
{
236
    return TCL_OK;
237
}
238
 
239
/*
240
 *----------------------------------------------------------------------
241
 *
242
 * TkpSetWindowMenuBar --
243
 *
244
 *      Sets up the menu as a menubar in the given window.
245
 *
246
 * Results:
247
 *      None.
248
 *
249
 * Side effects:
250
 *      Recomputes geometry of given window.
251
 *
252
 *----------------------------------------------------------------------
253
 */
254
 
255
void
256
TkpSetWindowMenuBar(tkwin, menuPtr)
257
    Tk_Window tkwin;                    /* The window we are setting */
258
    TkMenu *menuPtr;                    /* The menu we are setting */
259
{
260
    if (menuPtr == NULL) {
261
        TkUnixSetMenubar(tkwin, NULL);
262
    } else {
263
        TkUnixSetMenubar(tkwin, menuPtr->tkwin);
264
    }
265
}
266
 
267
/*
268
 *----------------------------------------------------------------------
269
 *
270
 * TkpSetMainMenuBar --
271
 *
272
 *      Called when a toplevel widget is brought to front. On the
273
 *      Macintosh, sets up the menubar that goes accross the top
274
 *      of the main monitor. On other platforms, nothing is necessary.
275
 *
276
 * Results:
277
 *      None.
278
 *
279
 * Side effects:
280
 *      Recompute geometry of given window.
281
 *
282
 *----------------------------------------------------------------------
283
 */
284
 
285
void
286
TkpSetMainMenubar(interp, tkwin, menuName)
287
    Tcl_Interp *interp;
288
    Tk_Window tkwin;
289
    char *menuName;
290
{
291
    /*
292
     * Nothing to do.
293
     */
294
}
295
 
296
/*
297
 *----------------------------------------------------------------------
298
 *
299
 * GetMenuIndicatorGeometry --
300
 *
301
 *      Fills out the geometry of the indicator in a menu item. Note
302
 *      that the mePtr->height field must have already been filled in
303
 *      by GetMenuLabelGeometry since this height depends on the label
304
 *      height.
305
 *
306
 * Results:
307
 *      widthPtr and heightPtr point to the new geometry values.
308
 *
309
 * Side effects:
310
 *      None.
311
 *
312
 *----------------------------------------------------------------------
313
 */
314
 
315
static void
316
GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr)
317
    TkMenu *menuPtr;                    /* The menu we are drawing. */
318
    TkMenuEntry *mePtr;                 /* The entry we are interested in. */
319
    Tk_Font tkfont;                     /* The precalculated font */
320
    CONST Tk_FontMetrics *fmPtr;        /* The precalculated metrics */
321
    int *widthPtr;                      /* The resulting width */
322
    int *heightPtr;                     /* The resulting height */
323
{
324
    if (!mePtr->hideMargin && mePtr->indicatorOn &&
325
            ((mePtr->type == CHECK_BUTTON_ENTRY)
326
            || (mePtr->type == RADIO_BUTTON_ENTRY))) {
327
        if ((mePtr->image != NULL) || (mePtr->bitmap != None)) {
328
            *widthPtr = (14 * mePtr->height) / 10;
329
            *heightPtr = mePtr->height;
330
            if (mePtr->type == CHECK_BUTTON_ENTRY) {
331
                mePtr->platformEntryData =
332
                        (TkMenuPlatformEntryData) ((65 * mePtr->height) / 100);
333
            } else {
334
                mePtr->platformEntryData =
335
                        (TkMenuPlatformEntryData) ((75 * mePtr->height) / 100);
336
            }
337
        } else {
338
            *widthPtr = *heightPtr = mePtr->height;
339
            if (mePtr->type == CHECK_BUTTON_ENTRY) {
340
                mePtr->platformEntryData = (TkMenuPlatformEntryData)
341
                        ((80 * mePtr->height) / 100);
342
            } else {
343
                mePtr->platformEntryData = (TkMenuPlatformEntryData)
344
                        mePtr->height;
345
            }
346
        }
347
    } else {
348
        *heightPtr = 0;
349
        *widthPtr = menuPtr->borderWidth;
350
    }
351
}
352
 
353
 
354
/*
355
 *----------------------------------------------------------------------
356
 *
357
 * GetMenuAccelGeometry --
358
 *
359
 *      Get the geometry of the accelerator area of a menu item.
360
 *
361
 * Results:
362
 *      heightPtr and widthPtr are set.
363
 *
364
 * Side effects:
365
 *      None.
366
 *
367
 *----------------------------------------------------------------------
368
 */
369
 
370
static void
371
GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr)
372
    TkMenu *menuPtr;            /* The menu was are drawing */
373
    TkMenuEntry *mePtr;         /* The entry we are getting the geometry for */
374
    Tk_Font tkfont;             /* The precalculated font */
375
    CONST Tk_FontMetrics *fmPtr;/* The precalculated font metrics */
376
    int *widthPtr;              /* The width of the acclerator area */
377
    int *heightPtr;             /* The height of the accelerator area */
378
{
379
    *heightPtr = fmPtr->linespace;
380
    if (mePtr->type == CASCADE_ENTRY) {
381
        *widthPtr = 2 * CASCADE_ARROW_WIDTH;
382
    } else if ((menuPtr->menuType != MENUBAR) && (mePtr->accel != NULL)) {
383
        *widthPtr = Tk_TextWidth(tkfont, mePtr->accel, mePtr->accelLength);
384
    } else {
385
        *widthPtr = 0;
386
    }
387
}
388
 
389
/*
390
 *----------------------------------------------------------------------
391
 *
392
 * DrawMenuEntryBackground --
393
 *
394
 *      This procedure draws the background part of a menu.
395
 *
396
 * Results:
397
 *      None.
398
 *
399
 * Side effects:
400
 *      Commands are output to X to display the menu in its
401
 *      current mode.
402
 *
403
 *----------------------------------------------------------------------
404
 */
405
 
406
static void
407
DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, bgBorder, x, y,
408
        width, height)
409
    TkMenu *menuPtr;            /* The menu we are drawing */
410
    TkMenuEntry *mePtr;         /* The entry we are drawing. */
411
    Drawable d;                 /* The drawable we are drawing into */
412
    Tk_3DBorder activeBorder;   /* The border for an active item */
413
    Tk_3DBorder bgBorder;       /* The background border */
414
    int x;                      /* Left coordinate of entry rect */
415
    int y;                      /* Right coordinate of entry rect */
416
    int width;                  /* Width of entry rect */
417
    int height;                 /* Height of entry rect */
418
{
419
    if (mePtr->state == tkActiveUid) {
420
        int relief;
421
        bgBorder = activeBorder;
422
 
423
        if ((menuPtr->menuType == MENUBAR)
424
                && ((menuPtr->postedCascade == NULL)
425
                || (menuPtr->postedCascade != mePtr))) {
426
            relief = TK_RELIEF_FLAT;
427
        } else {
428
            relief = TK_RELIEF_RAISED;
429
        }
430
 
431
        Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
432
                menuPtr->activeBorderWidth, relief);
433
    } else {
434
        Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
435
                0, TK_RELIEF_FLAT);
436
    }
437
}
438
 
439
/*
440
 *----------------------------------------------------------------------
441
 *
442
 * DrawMenuEntryAccelerator --
443
 *
444
 *      This procedure draws the background part of a menu.
445
 *
446
 * Results:
447
 *      None.
448
 *
449
 * Side effects:
450
 *      Commands are output to X to display the menu in its
451
 *      current mode.
452
 *
453
 *----------------------------------------------------------------------
454
 */
455
 
456
static void
457
DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder,
458
        x, y, width, height, drawArrow)
459
    TkMenu *menuPtr;                    /* The menu we are drawing */
460
    TkMenuEntry *mePtr;                 /* The entry we are drawing */
461
    Drawable d;                         /* The drawable we are drawing into */
462
    GC gc;                              /* The precalculated gc to draw with */
463
    Tk_Font tkfont;                     /* The precalculated font */
464
    CONST Tk_FontMetrics *fmPtr;        /* The precalculated metrics */
465
    Tk_3DBorder activeBorder;           /* The border for an active item */
466
    int x;                              /* Left coordinate of entry rect */
467
    int y;                              /* Top coordinate of entry rect */
468
    int width;                          /* Width of entry */
469
    int height;                         /* Height of entry */
470
    int drawArrow;                      /* Whether or not to draw arrow. */
471
{
472
    XPoint points[3];
473
 
474
    /*
475
     * Draw accelerator or cascade arrow.
476
     */
477
 
478
    if (menuPtr->menuType == MENUBAR) {
479
        return;
480
    }
481
 
482
    if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {
483
        points[0].x = x + width - menuPtr->borderWidth
484
                - menuPtr->activeBorderWidth - CASCADE_ARROW_WIDTH;
485
        points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2;
486
        points[1].x = points[0].x;
487
        points[1].y = points[0].y + CASCADE_ARROW_HEIGHT;
488
        points[2].x = points[0].x + CASCADE_ARROW_WIDTH;
489
        points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2;
490
        Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points, 3,
491
                DECORATION_BORDER_WIDTH,
492
                (menuPtr->postedCascade == mePtr)
493
                ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
494
    } else if (mePtr->accel != NULL) {
495
        int left = x + mePtr->labelWidth + menuPtr->activeBorderWidth
496
                + mePtr->indicatorSpace;
497
        if (menuPtr->menuType == MENUBAR) {
498
            left += 5;
499
        }
500
        Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
501
                mePtr->accelLength, left,
502
                (y + (height + fmPtr->ascent - fmPtr->descent) / 2));
503
    }
504
}
505
 
506
/*
507
 *----------------------------------------------------------------------
508
 *
509
 * DrawMenuEntryIndicator --
510
 *
511
 *      This procedure draws the background part of a menu.
512
 *
513
 * Results:
514
 *      None.
515
 *
516
 * Side effects:
517
 *      Commands are output to X to display the menu in its
518
 *      current mode.
519
 *
520
 *----------------------------------------------------------------------
521
 */
522
 
523
static void
524
DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr,
525
        x, y, width, height)
526
    TkMenu *menuPtr;                    /* The menu we are drawing */
527
    TkMenuEntry *mePtr;                 /* The entry we are drawing */
528
    Drawable d;                         /* The drawable to draw into */
529
    GC gc;                              /* The gc to draw with */
530
    GC indicatorGC;                     /* The gc that indicators draw with */
531
    Tk_Font tkfont;                     /* The font to draw with */
532
    CONST Tk_FontMetrics *fmPtr;        /* The font metrics of the font */
533
    int x;                              /* The left of the entry rect */
534
    int y;                              /* The top of the entry rect */
535
    int width;                          /* Width of menu entry */
536
    int height;                         /* Height of menu entry */
537
{
538
 
539
    /*
540
     * Draw check-button indicator.
541
     */
542
 
543
    if ((mePtr->type == CHECK_BUTTON_ENTRY)
544
            && mePtr->indicatorOn) {
545
        int dim, top, left;
546
 
547
        dim = (int) mePtr->platformEntryData;
548
        left = x + menuPtr->activeBorderWidth
549
                + (mePtr->indicatorSpace - dim)/2;
550
        if (menuPtr->menuType == MENUBAR) {
551
            left += 5;
552
        }
553
        top = y + (height - dim)/2;
554
        Tk_Fill3DRectangle(menuPtr->tkwin, d, menuPtr->border, left, top, dim,
555
                dim, DECORATION_BORDER_WIDTH, TK_RELIEF_SUNKEN);
556
        left += DECORATION_BORDER_WIDTH;
557
        top += DECORATION_BORDER_WIDTH;
558
        dim -= 2*DECORATION_BORDER_WIDTH;
559
        if ((dim > 0) && (mePtr->entryFlags
560
                & ENTRY_SELECTED)) {
561
            XFillRectangle(menuPtr->display, d, indicatorGC, left, top,
562
                    (unsigned int) dim, (unsigned int) dim);
563
        }
564
    }
565
 
566
    /*
567
     * Draw radio-button indicator.
568
     */
569
 
570
    if ((mePtr->type == RADIO_BUTTON_ENTRY)
571
            && mePtr->indicatorOn) {
572
        XPoint points[4];
573
        int radius;
574
 
575
        radius = ((int) mePtr->platformEntryData)/2;
576
        points[0].x = x + (mePtr->indicatorSpace
577
                - (int) mePtr->platformEntryData)/2;
578
        points[0].y = y + (height)/2;
579
        points[1].x = points[0].x + radius;
580
        points[1].y = points[0].y + radius;
581
        points[2].x = points[1].x + radius;
582
        points[2].y = points[0].y;
583
        points[3].x = points[1].x;
584
        points[3].y = points[0].y - radius;
585
        if (mePtr->entryFlags & ENTRY_SELECTED) {
586
            XFillPolygon(menuPtr->display, d, indicatorGC, points, 4, Convex,
587
                    CoordModeOrigin);
588
        } else {
589
            Tk_Fill3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 4,
590
                    DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT);
591
        }
592
        Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 4,
593
                DECORATION_BORDER_WIDTH, TK_RELIEF_SUNKEN);
594
    }
595
}
596
 
597
/*
598
 *----------------------------------------------------------------------
599
 *
600
 * DrawMenuSeparator --
601
 *
602
 *      This procedure draws a separator menu item.
603
 *
604
 * Results:
605
 *      None.
606
 *
607
 * Side effects:
608
 *      Commands are output to X to display the menu in its
609
 *      current mode.
610
 *
611
 *----------------------------------------------------------------------
612
 */
613
 
614
static void
615
DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
616
    TkMenu *menuPtr;                    /* The menu we are drawing */
617
    TkMenuEntry *mePtr;                 /* The entry we are drawing */
618
    Drawable d;                         /* The drawable we are using */
619
    GC gc;                              /* The gc to draw into */
620
    Tk_Font tkfont;                     /* The font to draw with */
621
    CONST Tk_FontMetrics *fmPtr;        /* The font metrics from the font */
622
    int x;
623
    int y;
624
    int width;
625
    int height;
626
{
627
    XPoint points[2];
628
    int margin;
629
 
630
    if (menuPtr->menuType == MENUBAR) {
631
        return;
632
    }
633
 
634
    margin = (fmPtr->ascent + fmPtr->descent)/2;
635
    points[0].x = x;
636
    points[0].y = y + height/2;
637
    points[1].x = width - 1;
638
    points[1].y = points[0].y;
639
    Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
640
            TK_RELIEF_RAISED);
641
}
642
 
643
/*
644
 *----------------------------------------------------------------------
645
 *
646
 * DrawMenuEntryLabel --
647
 *
648
 *      This procedure draws the label part of a menu.
649
 *
650
 * Results:
651
 *      None.
652
 *
653
 * Side effects:
654
 *      Commands are output to X to display the menu in its
655
 *      current mode.
656
 *
657
 *----------------------------------------------------------------------
658
 */
659
 
660
static void
661
DrawMenuEntryLabel(
662
    menuPtr,                    /* The menu we are drawing */
663
    mePtr,                      /* The entry we are drawing */
664
    d,                          /* What we are drawing into */
665
    gc,                         /* The gc we are drawing into */
666
    tkfont,                     /* The precalculated font */
667
    fmPtr,                      /* The precalculated font metrics */
668
    x,                          /* left edge */
669
    y,                          /* right edge */
670
    width,                      /* width of entry */
671
    height)                     /* height of entry */
672
    TkMenu *menuPtr;
673
    TkMenuEntry *mePtr;
674
    Drawable d;
675
    GC gc;
676
    Tk_Font tkfont;
677
    CONST Tk_FontMetrics *fmPtr;
678
    int x, y, width, height;
679
{
680
    int baseline;
681
    int indicatorSpace =  mePtr->indicatorSpace;
682
    int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
683
    int imageHeight, imageWidth;
684
 
685
    if (menuPtr->menuType == MENUBAR) {
686
        leftEdge += 5;
687
    }
688
 
689
    /*
690
     * Draw label or bitmap or image for entry.
691
     */
692
 
693
    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
694
    if (mePtr->image != NULL) {
695
        Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
696
        if ((mePtr->selectImage != NULL)
697
                && (mePtr->entryFlags & ENTRY_SELECTED)) {
698
            Tk_RedrawImage(mePtr->selectImage, 0, 0,
699
                    imageWidth, imageHeight, d, leftEdge,
700
                    (int) (y + (mePtr->height - imageHeight)/2));
701
        } else {
702
            Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
703
                    imageHeight, d, leftEdge,
704
                    (int) (y + (mePtr->height - imageHeight)/2));
705
        }
706
    } else if (mePtr->bitmap != None) {
707
        int width, height;
708
 
709
        Tk_SizeOfBitmap(menuPtr->display,
710
                mePtr->bitmap, &width, &height);
711
        XCopyPlane(menuPtr->display,
712
                mePtr->bitmap, d,
713
                gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
714
                (int) (y + (mePtr->height - height)/2), 1);
715
    } else {
716
        if (mePtr->labelLength > 0) {
717
            Tk_DrawChars(menuPtr->display, d, gc,
718
                    tkfont, mePtr->label, mePtr->labelLength,
719
                    leftEdge, baseline);
720
            DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
721
                    width, height);
722
        }
723
    }
724
 
725
    if (mePtr->state == tkDisabledUid) {
726
        if (menuPtr->disabledFg == NULL) {
727
            XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
728
                    (unsigned) width, (unsigned) height);
729
        } else if ((mePtr->image != NULL)
730
                && (menuPtr->disabledImageGC != None)) {
731
            XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
732
                    leftEdge,
733
                    (int) (y + (mePtr->height - imageHeight)/2),
734
                    (unsigned) imageWidth, (unsigned) imageHeight);
735
        }
736
    }
737
}
738
 
739
/*
740
 *----------------------------------------------------------------------
741
 *
742
 * DrawMenuUnderline --
743
 *
744
 *      On appropriate platforms, draw the underline character for the
745
 *      menu.
746
 *
747
 * Results:
748
 *      None.
749
 *
750
 * Side effects:
751
 *      Commands are output to X to display the menu in its
752
 *      current mode.
753
 *
754
 *----------------------------------------------------------------------
755
 */
756
 
757
static void
758
DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
759
    TkMenu *menuPtr;                    /* The menu to draw into */
760
    TkMenuEntry *mePtr;                 /* The entry we are drawing */
761
    Drawable d;                         /* What we are drawing into */
762
    GC gc;                              /* The gc to draw into */
763
    Tk_Font tkfont;                     /* The precalculated font */
764
    CONST Tk_FontMetrics *fmPtr;        /* The precalculated font metrics */
765
    int x;
766
    int y;
767
    int width;
768
    int height;
769
{
770
    int indicatorSpace = mePtr->indicatorSpace;
771
    if (mePtr->underline >= 0) {
772
        int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
773
        if (menuPtr->menuType == MENUBAR) {
774
            leftEdge += 5;
775
        }
776
 
777
        Tk_UnderlineChars(menuPtr->display, d, gc, tkfont, mePtr->label,
778
                leftEdge, y + (height + fmPtr->ascent - fmPtr->descent) / 2,
779
                mePtr->underline, mePtr->underline + 1);
780
    }
781
}
782
 
783
/*
784
 *----------------------------------------------------------------------
785
 *
786
 * TkpPostMenu --
787
 *
788
 *      Posts a menu on the screen
789
 *
790
 * Results:
791
 *      None.
792
 *
793
 * Side effects:
794
 *      The menu is posted and handled.
795
 *
796
 *----------------------------------------------------------------------
797
 */
798
 
799
int
800
TkpPostMenu(interp, menuPtr, x, y)
801
    Tcl_Interp *interp;
802
    TkMenu *menuPtr;
803
    int x;
804
    int y;
805
{
806
    return TkPostTearoffMenu(interp, menuPtr, x, y);
807
}
808
 
809
/*
810
 *----------------------------------------------------------------------
811
 *
812
 * GetMenuSeparatorGeometry --
813
 *
814
 *      Gets the width and height of the indicator area of a menu.
815
 *
816
 * Results:
817
 *      widthPtr and heightPtr are set.
818
 *
819
 * Side effects:
820
 *      None.
821
 *
822
 *----------------------------------------------------------------------
823
 */
824
 
825
static void
826
GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr,
827
        heightPtr)
828
    TkMenu *menuPtr;                    /* The menu we are measuring */
829
    TkMenuEntry *mePtr;                 /* The entry we are measuring */
830
    Tk_Font tkfont;                     /* The precalculated font */
831
    CONST Tk_FontMetrics *fmPtr;        /* The precalcualted font metrics */
832
    int *widthPtr;                      /* The resulting width */
833
    int *heightPtr;                     /* The resulting height */
834
{
835
    *widthPtr = 0;
836
    *heightPtr = fmPtr->linespace;
837
}
838
 
839
/*
840
 *----------------------------------------------------------------------
841
 *
842
 * GetTearoffEntryGeometry --
843
 *
844
 *      Gets the width and height of the indicator area of a menu.
845
 *
846
 * Results:
847
 *      widthPtr and heightPtr are set.
848
 *
849
 * Side effects:
850
 *      None.
851
 *
852
 *----------------------------------------------------------------------
853
 */
854
 
855
static void
856
GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr)
857
    TkMenu *menuPtr;                    /* The menu we are drawing */
858
    TkMenuEntry *mePtr;                 /* The entry we are measuring */
859
    Tk_Font tkfont;                     /* The precalculated font */
860
    CONST Tk_FontMetrics *fmPtr;        /* The precalculated font metrics */
861
    int *widthPtr;                      /* The resulting width */
862
    int *heightPtr;                     /* The resulting height */
863
{
864
    if (menuPtr->menuType != MASTER_MENU) {
865
        *heightPtr = 0;
866
        *widthPtr = 0;
867
    } else {
868
        *heightPtr = fmPtr->linespace;
869
        *widthPtr = Tk_TextWidth(tkfont, "W", -1);
870
    }
871
}
872
 
873
/*
874
 *--------------------------------------------------------------
875
 *
876
 * TkpComputeMenubarGeometry --
877
 *
878
 *      This procedure is invoked to recompute the size and
879
 *      layout of a menu that is a menubar clone.
880
 *
881
 * Results:
882
 *      None.
883
 *
884
 * Side effects:
885
 *      Fields of menu entries are changed to reflect their
886
 *      current positions, and the size of the menu window
887
 *      itself may be changed.
888
 *
889
 *--------------------------------------------------------------
890
 */
891
 
892
void
893
TkpComputeMenubarGeometry(menuPtr)
894
    TkMenu *menuPtr;            /* Structure describing menu. */
895
{
896
    Tk_Font tkfont;
897
    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
898
    int width, height;
899
    int i, j;
900
    int x, y, currentRowHeight, currentRowWidth, maxWidth;
901
    int maxWindowWidth;
902
    int lastRowBreak;
903
    int helpMenuIndex = -1;
904
    TkMenuEntry *mePtr;
905
    int lastEntry;
906
 
907
    if (menuPtr->tkwin == NULL) {
908
        return;
909
    }
910
 
911
    maxWidth = 0;
912
    if (menuPtr->numEntries == 0) {
913
        height = 0;
914
    } else {
915
        maxWindowWidth = Tk_Width(menuPtr->tkwin);
916
        if (maxWindowWidth == 1) {
917
            maxWindowWidth = 0x7ffffff;
918
        }
919
        currentRowHeight = 0;
920
        x = y = menuPtr->borderWidth;
921
        lastRowBreak = 0;
922
        currentRowWidth = 0;
923
 
924
        /*
925
         * On the Mac especially, getting font metrics can be quite slow,
926
         * so we want to do it intelligently. We are going to precalculate
927
         * them and pass them down to all of the measureing and drawing
928
         * routines. We will measure the font metrics of the menu once,
929
         * and if an entry has a font set, we will measure it as we come
930
         * to it, and then we decide which set to give the geometry routines.
931
         */
932
 
933
        Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
934
 
935
        for (i = 0; i < menuPtr->numEntries; i++) {
936
            mePtr = menuPtr->entries[i];
937
            mePtr->entryFlags &= ~ENTRY_LAST_COLUMN;
938
            tkfont = mePtr->tkfont;
939
            if (tkfont == NULL) {
940
                tkfont = menuPtr->tkfont;
941
                fmPtr = &menuMetrics;
942
            } else {
943
                Tk_GetFontMetrics(tkfont, &entryMetrics);
944
                fmPtr = &entryMetrics;
945
            }
946
 
947
            /*
948
             * For every entry, we need to check to see whether or not we
949
             * wrap. If we do wrap, then we have to adjust all of the previous
950
             * entries' height and y position, because when we see them
951
             * the first time, we don't know how big its neighbor might
952
             * be.
953
             */
954
 
955
            if ((mePtr->type == SEPARATOR_ENTRY)
956
                    || (mePtr->type == TEAROFF_ENTRY)) {
957
                mePtr->height = mePtr->width = 0;
958
            } else {
959
 
960
                GetMenuLabelGeometry(mePtr, tkfont, fmPtr,
961
                        &width, &height);
962
                mePtr->height = height + 2 * menuPtr->activeBorderWidth + 10;
963
                mePtr->width = width;
964
 
965
                GetMenuIndicatorGeometry(menuPtr, mePtr,
966
                        tkfont, fmPtr, &width, &height);
967
                mePtr->indicatorSpace = width;
968
                if (width > 0) {
969
                    mePtr->width += width;
970
                }
971
                mePtr->width += 2 * menuPtr->activeBorderWidth + 10;
972
            }
973
            if (mePtr->entryFlags & ENTRY_HELP_MENU) {
974
                helpMenuIndex = i;
975
            } else if (x + mePtr->width + menuPtr->borderWidth
976
                    > maxWindowWidth) {
977
 
978
                if (i == lastRowBreak) {
979
                    mePtr->y = y;
980
                    mePtr->x = x;
981
                    lastRowBreak++;
982
                    y += mePtr->height;
983
                    currentRowHeight = 0;
984
                } else {
985
                    x = menuPtr->borderWidth;
986
                    for (j = lastRowBreak; j < i; j++) {
987
                        menuPtr->entries[j]->y = y + currentRowHeight
988
                                - menuPtr->entries[j]->height;
989
                        menuPtr->entries[j]->x = x;
990
                        x += menuPtr->entries[j]->width;
991
                    }
992
                    lastRowBreak = i;
993
                    y += currentRowHeight;
994
                    currentRowHeight = mePtr->height;
995
                }
996
                if (x > maxWidth) {
997
                    maxWidth = x;
998
                }
999
                x = menuPtr->borderWidth;
1000
            } else {
1001
                x += mePtr->width;
1002
                if (mePtr->height > currentRowHeight) {
1003
                    currentRowHeight = mePtr->height;
1004
                }
1005
            }
1006
        }
1007
 
1008
        lastEntry = menuPtr->numEntries - 1;
1009
        if (helpMenuIndex == lastEntry) {
1010
            lastEntry--;
1011
        }
1012
        if ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width
1013
                + menuPtr->borderWidth > maxWidth)) {
1014
            maxWidth = x + menuPtr->entries[lastEntry]->width
1015
                    + menuPtr->borderWidth;
1016
        }
1017
        x = menuPtr->borderWidth;
1018
        for (j = lastRowBreak; j < menuPtr->numEntries; j++) {
1019
            if (j == helpMenuIndex) {
1020
                continue;
1021
            }
1022
            menuPtr->entries[j]->y = y + currentRowHeight
1023
                    - menuPtr->entries[j]->height;
1024
            menuPtr->entries[j]->x = x;
1025
            x += menuPtr->entries[j]->width;
1026
        }
1027
 
1028
 
1029
        if (helpMenuIndex != -1) {
1030
            mePtr = menuPtr->entries[helpMenuIndex];
1031
            if (x + mePtr->width + menuPtr->borderWidth > maxWindowWidth) {
1032
                y += currentRowHeight;
1033
                currentRowHeight = mePtr->height;
1034
                x = menuPtr->borderWidth;
1035
            } else if (mePtr->height > currentRowHeight) {
1036
                currentRowHeight = mePtr->height;
1037
            }
1038
            mePtr->x = maxWindowWidth - menuPtr->borderWidth - mePtr->width;
1039
            mePtr->y = y + currentRowHeight - mePtr->height;
1040
        }
1041
        height = y + currentRowHeight + menuPtr->borderWidth;
1042
    }
1043
    width = Tk_Width(menuPtr->tkwin);
1044
 
1045
    /*
1046
     * The X server doesn't like zero dimensions, so round up to at least
1047
     * 1 (a zero-sized menu should never really occur, anyway).
1048
     */
1049
 
1050
    if (width <= 0) {
1051
        width = 1;
1052
    }
1053
    if (height <= 0) {
1054
        height = 1;
1055
    }
1056
    menuPtr->totalWidth = maxWidth;
1057
    menuPtr->totalHeight = height;
1058
}
1059
 
1060
/*
1061
 *----------------------------------------------------------------------
1062
 *
1063
 * DrawTearoffEntry --
1064
 *
1065
 *      This procedure draws the background part of a menu.
1066
 *
1067
 * Results:
1068
 *      None.
1069
 *
1070
 * Side effects:
1071
 *      Commands are output to X to display the menu in its
1072
 *      current mode.
1073
 *
1074
 *----------------------------------------------------------------------
1075
 */
1076
 
1077
static void
1078
DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
1079
    TkMenu *menuPtr;                    /* The menu we are drawing */
1080
    TkMenuEntry *mePtr;                 /* The entry we are drawing */
1081
    Drawable d;                         /* The drawable we are drawing into */
1082
    GC gc;                              /* The gc we are drawing with */
1083
    Tk_Font tkfont;                     /* The font we are drawing with */
1084
    CONST Tk_FontMetrics *fmPtr;        /* The metrics we are drawing with */
1085
    int x;
1086
    int y;
1087
    int width;
1088
    int height;
1089
{
1090
    XPoint points[2];
1091
    int margin, segmentWidth, maxX;
1092
 
1093
    if (menuPtr->menuType != MASTER_MENU) {
1094
        return;
1095
    }
1096
 
1097
    margin = (fmPtr->ascent + fmPtr->descent)/2;
1098
    points[0].x = x;
1099
    points[0].y = y + height/2;
1100
    points[1].y = points[0].y;
1101
    segmentWidth = 6;
1102
    maxX  = width - 1;
1103
 
1104
    while (points[0].x < maxX) {
1105
        points[1].x = points[0].x + segmentWidth;
1106
        if (points[1].x > maxX) {
1107
            points[1].x = maxX;
1108
        }
1109
        Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
1110
                TK_RELIEF_RAISED);
1111
        points[0].x += 2*segmentWidth;
1112
    }
1113
}
1114
 
1115
/*
1116
 *--------------------------------------------------------------
1117
 *
1118
 * TkpInitializeMenuBindings --
1119
 *
1120
 *      For every interp, initializes the bindings for Windows
1121
 *      menus. Does nothing on Mac or XWindows.
1122
 *
1123
 * Results:
1124
 *      None.
1125
 *
1126
 * Side effects:
1127
 *      C-level bindings are setup for the interp which will
1128
 *      handle Alt-key sequences for menus without beeping
1129
 *      or interfering with user-defined Alt-key bindings.
1130
 *
1131
 *--------------------------------------------------------------
1132
 */
1133
 
1134
void
1135
TkpInitializeMenuBindings(interp, bindingTable)
1136
    Tcl_Interp *interp;             /* The interpreter to set. */
1137
    Tk_BindingTable bindingTable;   /* The table to add to. */
1138
{
1139
    /*
1140
     * Nothing to do.
1141
     */
1142
}
1143
 
1144
/*
1145
 *----------------------------------------------------------------------
1146
 *
1147
 * SetHelpMenu --
1148
 *
1149
 *      Given a menu, check to see whether or not it is a help menu
1150
 *      cascade in a menubar. If it is, the entry that points to
1151
 *      this menu will be marked.
1152
 *
1153
 * RESULTS:
1154
 *      None.
1155
 *
1156
 * Side effects:
1157
 *      Will set the ENTRY_HELP_MENU flag appropriately.
1158
 *
1159
 *----------------------------------------------------------------------
1160
 */
1161
 
1162
static void
1163
SetHelpMenu(menuPtr)
1164
     TkMenu *menuPtr;           /* The menu we are checking */
1165
{
1166
    TkMenuEntry *cascadeEntryPtr;
1167
 
1168
    for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
1169
            cascadeEntryPtr != NULL;
1170
            cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
1171
        if ((cascadeEntryPtr->menuPtr->menuType == MENUBAR)
1172
                && (cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin != NULL)
1173
                && (menuPtr->masterMenuPtr->tkwin != NULL)) {
1174
            TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
1175
            char *helpMenuName = ckalloc(strlen(Tk_PathName(
1176
                    masterMenuPtr->tkwin)) + strlen(".help") + 1);
1177
 
1178
            strcpy(helpMenuName, Tk_PathName(masterMenuPtr->tkwin));
1179
            strcat(helpMenuName, ".help");
1180
            if (strcmp(helpMenuName,
1181
                    Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
1182
                cascadeEntryPtr->entryFlags |= ENTRY_HELP_MENU;
1183
            } else {
1184
                cascadeEntryPtr->entryFlags &= ~ENTRY_HELP_MENU;
1185
            }
1186
            ckfree(helpMenuName);
1187
        }
1188
    }
1189
}
1190
 
1191
/*
1192
 *----------------------------------------------------------------------
1193
 *
1194
 * TkpDrawMenuEntry --
1195
 *
1196
 *      Draws the given menu entry at the given coordinates with the
1197
 *      given attributes.
1198
 *
1199
 * Results:
1200
 *      None.
1201
 *
1202
 * Side effects:
1203
 *      X Server commands are executed to display the menu entry.
1204
 *
1205
 *----------------------------------------------------------------------
1206
 */
1207
 
1208
void
1209
TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
1210
        strictMotif, drawArrow)
1211
    TkMenuEntry *mePtr;             /* The entry to draw */
1212
    Drawable d;                     /* What to draw into */
1213
    Tk_Font tkfont;                 /* Precalculated font for menu */
1214
    CONST Tk_FontMetrics *menuMetricsPtr;
1215
                                    /* Precalculated metrics for menu */
1216
    int x;                          /* X-coordinate of topleft of entry */
1217
    int y;                          /* Y-coordinate of topleft of entry */
1218
    int width;                      /* Width of the entry rectangle */
1219
    int height;                     /* Height of the current rectangle */
1220
    int strictMotif;                /* Boolean flag */
1221
    int drawArrow;                  /* Whether or not to draw the cascade
1222
                                     * arrow for cascade items. Only applies
1223
                                     * to Windows. */
1224
{
1225
    GC gc, indicatorGC;
1226
    TkMenu *menuPtr = mePtr->menuPtr;
1227
    Tk_3DBorder bgBorder, activeBorder;
1228
    CONST Tk_FontMetrics *fmPtr;
1229
    Tk_FontMetrics entryMetrics;
1230
    int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
1231
    int adjustedY = y + padY;
1232
    int adjustedHeight = height - 2 * padY;
1233
 
1234
    /*
1235
     * Choose the gc for drawing the foreground part of the entry.
1236
     */
1237
 
1238
    if ((mePtr->state == tkActiveUid)
1239
            && !strictMotif) {
1240
        gc = mePtr->activeGC;
1241
        if (gc == NULL) {
1242
            gc = menuPtr->activeGC;
1243
        }
1244
    } else {
1245
        TkMenuEntry *cascadeEntryPtr;
1246
        int parentDisabled = 0;
1247
 
1248
        for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
1249
                cascadeEntryPtr != NULL;
1250
                cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
1251
            if (strcmp(cascadeEntryPtr->name,
1252
                    Tk_PathName(menuPtr->tkwin)) == 0) {
1253
                if (cascadeEntryPtr->state == tkDisabledUid) {
1254
                    parentDisabled = 1;
1255
                }
1256
                break;
1257
            }
1258
        }
1259
 
1260
        if (((parentDisabled || (mePtr->state == tkDisabledUid)))
1261
                && (menuPtr->disabledFg != NULL)) {
1262
            gc = mePtr->disabledGC;
1263
            if (gc == NULL) {
1264
                gc = menuPtr->disabledGC;
1265
            }
1266
        } else {
1267
            gc = mePtr->textGC;
1268
            if (gc == NULL) {
1269
                gc = menuPtr->textGC;
1270
            }
1271
        }
1272
    }
1273
    indicatorGC = mePtr->indicatorGC;
1274
    if (indicatorGC == NULL) {
1275
        indicatorGC = menuPtr->indicatorGC;
1276
    }
1277
 
1278
    bgBorder = mePtr->border;
1279
    if (bgBorder == NULL) {
1280
        bgBorder = menuPtr->border;
1281
    }
1282
    if (strictMotif) {
1283
        activeBorder = bgBorder;
1284
    } else {
1285
        activeBorder = mePtr->activeBorder;
1286
        if (activeBorder == NULL) {
1287
            activeBorder = menuPtr->activeBorder;
1288
        }
1289
    }
1290
 
1291
    if (mePtr->tkfont == NULL) {
1292
        fmPtr = menuMetricsPtr;
1293
    } else {
1294
        tkfont = mePtr->tkfont;
1295
        Tk_GetFontMetrics(tkfont, &entryMetrics);
1296
        fmPtr = &entryMetrics;
1297
    }
1298
 
1299
    /*
1300
     * Need to draw the entire background, including padding. On Unix,
1301
     * for menubars, we have to draw the rest of the entry taking
1302
     * into account the padding.
1303
     */
1304
 
1305
    DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,
1306
            bgBorder, x, y, width, height);
1307
 
1308
    if (mePtr->type == SEPARATOR_ENTRY) {
1309
        DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
1310
                fmPtr, x, adjustedY, width, adjustedHeight);
1311
    } else if (mePtr->type == TEAROFF_ENTRY) {
1312
        DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
1313
                width, adjustedHeight);
1314
    } else {
1315
        DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
1316
                width, adjustedHeight);
1317
        DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
1318
                activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
1319
        if (!mePtr->hideMargin) {
1320
            DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
1321
                    fmPtr, x, adjustedY, width, adjustedHeight);
1322
        }
1323
    }
1324
}
1325
 
1326
/*
1327
 *----------------------------------------------------------------------
1328
 *
1329
 * GetMenuLabelGeometry --
1330
 *
1331
 *      Figures out the size of the label portion of a menu item.
1332
 *
1333
 * Results:
1334
 *      widthPtr and heightPtr are filled in with the correct geometry
1335
 *      information.
1336
 *
1337
 * Side effects:
1338
 *      None.
1339
 *
1340
 *----------------------------------------------------------------------
1341
 */
1342
 
1343
static void
1344
GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)
1345
    TkMenuEntry *mePtr;                 /* The entry we are computing */
1346
    Tk_Font tkfont;                     /* The precalculated font */
1347
    CONST Tk_FontMetrics *fmPtr;        /* The precalculated metrics */
1348
    int *widthPtr;                      /* The resulting width of the label
1349
                                         * portion */
1350
    int *heightPtr;                     /* The resulting height of the label
1351
                                         * portion */
1352
{
1353
    TkMenu *menuPtr = mePtr->menuPtr;
1354
 
1355
    if (mePtr->image != NULL) {
1356
        Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
1357
    } else if (mePtr->bitmap != (Pixmap) NULL) {
1358
        Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
1359
    } else {
1360
        *heightPtr = fmPtr->linespace;
1361
 
1362
        if (mePtr->label != NULL) {
1363
            *widthPtr = Tk_TextWidth(tkfont, mePtr->label, mePtr->labelLength);
1364
        } else {
1365
            *widthPtr = 0;
1366
        }
1367
    }
1368
    *heightPtr += 1;
1369
}
1370
 
1371
/*
1372
 *--------------------------------------------------------------
1373
 *
1374
 * TkpComputeStandardMenuGeometry --
1375
 *
1376
 *      This procedure is invoked to recompute the size and
1377
 *      layout of a menu that is not a menubar clone.
1378
 *
1379
 * Results:
1380
 *      None.
1381
 *
1382
 * Side effects:
1383
 *      Fields of menu entries are changed to reflect their
1384
 *      current positions, and the size of the menu window
1385
 *      itself may be changed.
1386
 *
1387
 *--------------------------------------------------------------
1388
 */
1389
 
1390
void
1391
TkpComputeStandardMenuGeometry(
1392
    menuPtr)            /* Structure describing menu. */
1393
    TkMenu *menuPtr;
1394
{
1395
    Tk_Font tkfont;
1396
    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
1397
    int x, y, height, width, indicatorSpace, labelWidth, accelWidth;
1398
    int windowWidth, windowHeight, accelSpace;
1399
    int i, j, lastColumnBreak = 0;
1400
    TkMenuEntry *mePtr;
1401
 
1402
    if (menuPtr->tkwin == NULL) {
1403
        return;
1404
    }
1405
 
1406
    x = y = menuPtr->borderWidth;
1407
    indicatorSpace = labelWidth = accelWidth = 0;
1408
    windowHeight = windowWidth = 0;
1409
 
1410
    /*
1411
     * On the Mac especially, getting font metrics can be quite slow,
1412
     * so we want to do it intelligently. We are going to precalculate
1413
     * them and pass them down to all of the measuring and drawing
1414
     * routines. We will measure the font metrics of the menu once.
1415
     * If an entry does not have its own font set, then we give
1416
     * the geometry/drawing routines the menu's font and metrics.
1417
     * If an entry has its own font, we will measure that font and
1418
     * give all of the geometry/drawing the entry's font and metrics.
1419
     */
1420
 
1421
    Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
1422
    accelSpace = Tk_TextWidth(menuPtr->tkfont, "M", 1);
1423
 
1424
    for (i = 0; i < menuPtr->numEntries; i++) {
1425
        mePtr = menuPtr->entries[i];
1426
        tkfont = mePtr->tkfont;
1427
        if (tkfont == NULL) {
1428
            tkfont = menuPtr->tkfont;
1429
            fmPtr = &menuMetrics;
1430
        } else {
1431
            Tk_GetFontMetrics(tkfont, &entryMetrics);
1432
            fmPtr = &entryMetrics;
1433
        }
1434
 
1435
        if ((i > 0) && mePtr->columnBreak) {
1436
            if (accelWidth != 0) {
1437
                labelWidth += accelSpace;
1438
            }
1439
            for (j = lastColumnBreak; j < i; j++) {
1440
                menuPtr->entries[j]->indicatorSpace = indicatorSpace;
1441
                menuPtr->entries[j]->labelWidth = labelWidth;
1442
                menuPtr->entries[j]->width = indicatorSpace + labelWidth
1443
                        + accelWidth + 2 * menuPtr->activeBorderWidth;
1444
                menuPtr->entries[j]->x = x;
1445
                menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;
1446
            }
1447
            x += indicatorSpace + labelWidth + accelWidth
1448
                    + 2 * menuPtr->activeBorderWidth;
1449
            windowWidth = x;
1450
            indicatorSpace = labelWidth = accelWidth = 0;
1451
            lastColumnBreak = i;
1452
            y = menuPtr->borderWidth;
1453
        }
1454
 
1455
        if (mePtr->type == SEPARATOR_ENTRY) {
1456
            GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont,
1457
                    fmPtr, &width, &height);
1458
            mePtr->height = height;
1459
        } else if (mePtr->type == TEAROFF_ENTRY) {
1460
            GetTearoffEntryGeometry(menuPtr, mePtr, tkfont,
1461
                    fmPtr, &width, &height);
1462
            mePtr->height = height;
1463
            labelWidth = width;
1464
        } else {
1465
 
1466
            /*
1467
             * For each entry, compute the height required by that
1468
             * particular entry, plus three widths:  the width of the
1469
             * label, the width to allow for an indicator to be displayed
1470
             * to the left of the label (if any), and the width of the
1471
             * accelerator to be displayed to the right of the label
1472
             * (if any).  These sizes depend, of course, on the type
1473
             * of the entry.
1474
             */
1475
 
1476
            GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width,
1477
                    &height);
1478
            mePtr->height = height;
1479
            if (!mePtr->hideMargin) {
1480
                width += MENU_MARGIN_WIDTH;
1481
            }
1482
            if (width > labelWidth) {
1483
                labelWidth = width;
1484
            }
1485
 
1486
            GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
1487
                    fmPtr, &width, &height);
1488
            if (height > mePtr->height) {
1489
                mePtr->height = height;
1490
            }
1491
            if (!mePtr->hideMargin) {
1492
                width += MENU_MARGIN_WIDTH;
1493
            }
1494
            if (width > accelWidth) {
1495
                accelWidth = width;
1496
            }
1497
 
1498
            GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont,
1499
                    fmPtr, &width, &height);
1500
            if (height > mePtr->height) {
1501
                mePtr->height = height;
1502
            }
1503
            if (!mePtr->hideMargin) {
1504
                width += MENU_MARGIN_WIDTH;
1505
            }
1506
            if (width > indicatorSpace) {
1507
                indicatorSpace = width;
1508
            }
1509
 
1510
            mePtr->height += 2 * menuPtr->activeBorderWidth +
1511
                    MENU_DIVIDER_HEIGHT;
1512
        }
1513
        mePtr->y = y;
1514
        y += mePtr->height;
1515
        if (y > windowHeight) {
1516
            windowHeight = y;
1517
        }
1518
    }
1519
 
1520
    if (accelWidth != 0) {
1521
        labelWidth += accelSpace;
1522
    }
1523
    for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
1524
        menuPtr->entries[j]->indicatorSpace = indicatorSpace;
1525
        menuPtr->entries[j]->labelWidth = labelWidth;
1526
        menuPtr->entries[j]->width = indicatorSpace + labelWidth
1527
                + accelWidth + 2 * menuPtr->activeBorderWidth;
1528
        menuPtr->entries[j]->x = x;
1529
        menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
1530
    }
1531
    windowWidth = x + indicatorSpace + labelWidth + accelWidth
1532
            + 2 * menuPtr->activeBorderWidth + 2 * menuPtr->borderWidth;
1533
 
1534
 
1535
    windowHeight += menuPtr->borderWidth;
1536
 
1537
    /*
1538
     * The X server doesn't like zero dimensions, so round up to at least
1539
     * 1 (a zero-sized menu should never really occur, anyway).
1540
     */
1541
 
1542
    if (windowWidth <= 0) {
1543
        windowWidth = 1;
1544
    }
1545
    if (windowHeight <= 0) {
1546
        windowHeight = 1;
1547
    }
1548
    menuPtr->totalWidth = windowWidth;
1549
    menuPtr->totalHeight = windowHeight;
1550
}
1551
 
1552
/*
1553
 *----------------------------------------------------------------------
1554
 *
1555
 * TkpMenuNotifyToplevelCreate --
1556
 *
1557
 *      This routine reconfigures the menu and the clones indicated by
1558
 *      menuName becuase a toplevel has been created and any system
1559
 *      menus need to be created. Not applicable to UNIX.
1560
 *
1561
 * Results:
1562
 *      None.
1563
 *
1564
 * Side effects:
1565
 *      An idle handler is set up to do the reconfiguration.
1566
 *
1567
 *----------------------------------------------------------------------
1568
 */
1569
 
1570
void
1571
TkpMenuNotifyToplevelCreate(interp, menuName)
1572
    Tcl_Interp *interp;                 /* The interp the menu lives in. */
1573
    char *menuName;                     /* The name of the menu to
1574
                                         * reconfigure. */
1575
{
1576
    /*
1577
     * Nothing to do.
1578
     */
1579
}
1580
 
1581
/*
1582
 *----------------------------------------------------------------------
1583
 *
1584
 * TkpMenuInit --
1585
 *
1586
 *      Does platform-specific initialization of menus.
1587
 *
1588
 * Results:
1589
 *      None.
1590
 *
1591
 * Side effects:
1592
 *      None.
1593
 *
1594
 *----------------------------------------------------------------------
1595
 */
1596
 
1597
void
1598
TkpMenuInit()
1599
{
1600
    /*
1601
     * Nothing to do.
1602
     */
1603
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.