1998-04-10 06:59:06 -04:00
|
|
|
|
/*
|
|
|
|
|
* tkUnixMenu.c --
|
|
|
|
|
*
|
|
|
|
|
* This module implements the UNIX platform-specific features of menus.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 1996-1997 by Sun Microsystems, Inc.
|
|
|
|
|
*
|
|
|
|
|
* See the file "license.terms" for information on usage and redistribution
|
|
|
|
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
|
|
|
*
|
1998-09-30 07:11:02 -04:00
|
|
|
|
* SCCS: @(#) tkUnixMenu.c 1.76 97/11/05 09:08:22
|
1998-04-10 06:59:06 -04:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "tkPort.h"
|
|
|
|
|
#include "default.h"
|
|
|
|
|
#include "tkInt.h"
|
|
|
|
|
#include "tkUnixInt.h"
|
|
|
|
|
#include "tkMenu.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Constants used for menu drawing.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define MENU_MARGIN_WIDTH 2
|
|
|
|
|
#define MENU_DIVIDER_HEIGHT 2
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Platform specific flags for Unix.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define ENTRY_HELP_MENU ENTRY_PLATFORM_FLAG1
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Procedures used internally.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void SetHelpMenu _ANSI_ARGS_((TkMenu *menuPtr));
|
|
|
|
|
static void DrawMenuEntryAccelerator _ANSI_ARGS_((
|
|
|
|
|
TkMenu *menuPtr, TkMenuEntry *mePtr,
|
|
|
|
|
Drawable d, GC gc, Tk_Font tkfont,
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr,
|
|
|
|
|
Tk_3DBorder activeBorder, int x, int y,
|
|
|
|
|
int width, int height, int drawArrow));
|
|
|
|
|
static void DrawMenuEntryBackground _ANSI_ARGS_((
|
|
|
|
|
TkMenu *menuPtr, TkMenuEntry *mePtr,
|
|
|
|
|
Drawable d, Tk_3DBorder activeBorder,
|
|
|
|
|
Tk_3DBorder bgBorder, int x, int y,
|
|
|
|
|
int width, int heigth));
|
|
|
|
|
static void DrawMenuEntryIndicator _ANSI_ARGS_((
|
|
|
|
|
TkMenu *menuPtr, TkMenuEntry *mePtr,
|
|
|
|
|
Drawable d, GC gc, GC indicatorGC,
|
|
|
|
|
Tk_Font tkfont,
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr, int x, int y,
|
|
|
|
|
int width, int height));
|
|
|
|
|
static void DrawMenuEntryLabel _ANSI_ARGS_((
|
|
|
|
|
TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
|
|
|
|
|
GC gc, Tk_Font tkfont,
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr, int x, int y,
|
|
|
|
|
int width, int height));
|
|
|
|
|
static void DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
|
|
|
|
|
TkMenuEntry *mePtr, Drawable d, GC gc,
|
|
|
|
|
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
|
|
|
|
|
int x, int y, int width, int height));
|
|
|
|
|
static void DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
|
|
|
|
|
TkMenuEntry *mePtr, Drawable d, GC gc,
|
|
|
|
|
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
|
|
|
|
|
int x, int y, int width, int height));
|
|
|
|
|
static void DrawMenuUnderline _ANSI_ARGS_((TkMenu *menuPtr,
|
|
|
|
|
TkMenuEntry *mePtr, Drawable d, GC gc,
|
|
|
|
|
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, int x,
|
|
|
|
|
int y, int width, int height));
|
|
|
|
|
static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
|
|
|
|
|
TkMenuEntry *mePtr, Tk_Font tkfont,
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr, int *widthPtr,
|
|
|
|
|
int *heightPtr));
|
|
|
|
|
static void GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
|
|
|
|
|
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
|
|
|
|
|
int *widthPtr, int *heightPtr));
|
|
|
|
|
static void GetMenuIndicatorGeometry _ANSI_ARGS_((
|
|
|
|
|
TkMenu *menuPtr, TkMenuEntry *mePtr,
|
|
|
|
|
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
|
|
|
|
|
int *widthPtr, int *heightPtr));
|
|
|
|
|
static void GetMenuSeparatorGeometry _ANSI_ARGS_((
|
|
|
|
|
TkMenu *menuPtr, TkMenuEntry *mePtr,
|
|
|
|
|
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
|
|
|
|
|
int *widthPtr, int *heightPtr));
|
|
|
|
|
static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
|
|
|
|
|
TkMenuEntry *mePtr, Tk_Font tkfont,
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr, int *widthPtr,
|
|
|
|
|
int *heightPtr));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpNewMenu --
|
|
|
|
|
*
|
|
|
|
|
* Gets the platform-specific piece of the menu. Invoked during idle
|
|
|
|
|
* after the generic part of the menu has been created.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Standard TCL error.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Allocates any platform specific allocations and places them
|
|
|
|
|
* in the platformData field of the menuPtr.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
TkpNewMenu(menuPtr)
|
|
|
|
|
TkMenu *menuPtr;
|
|
|
|
|
{
|
|
|
|
|
SetHelpMenu(menuPtr);
|
|
|
|
|
return TCL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpDestroyMenu --
|
|
|
|
|
*
|
|
|
|
|
* Destroys platform-specific menu structures. Called when the
|
|
|
|
|
* generic menu structure is destroyed for the menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* All platform-specific allocations are freed up.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpDestroyMenu(menuPtr)
|
|
|
|
|
TkMenu *menuPtr;
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Nothing to do.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpDestroyMenuEntry --
|
|
|
|
|
*
|
|
|
|
|
* Cleans up platform-specific menu entry items. Called when entry
|
|
|
|
|
* is destroyed in the generic code.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* All platform specific allocations are freed up.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpDestroyMenuEntry(mEntryPtr)
|
|
|
|
|
TkMenuEntry *mEntryPtr;
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Nothing to do.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpConfigureMenuEntry --
|
|
|
|
|
*
|
|
|
|
|
* Processes configuration options for menu entries. Called when
|
|
|
|
|
* the generic options are processed for the menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns standard TCL result. If TCL_ERROR is returned, then
|
|
|
|
|
* interp->result contains an error message.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Configuration information get set for mePtr; old resources
|
|
|
|
|
* get freed, if any need it.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
TkpConfigureMenuEntry(mePtr)
|
|
|
|
|
register TkMenuEntry *mePtr; /* Information about menu entry; may
|
|
|
|
|
* or may not already have values for
|
|
|
|
|
* some fields. */
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* If this is a cascade menu, and the child menu exists, check to
|
|
|
|
|
* see if the child menu is a help menu.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((mePtr->type == CASCADE_ENTRY) && (mePtr->name != NULL)) {
|
|
|
|
|
TkMenuReferences *menuRefPtr;
|
|
|
|
|
|
|
|
|
|
menuRefPtr = TkFindMenuReferences(mePtr->menuPtr->interp,
|
|
|
|
|
mePtr->name);
|
|
|
|
|
if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {
|
|
|
|
|
SetHelpMenu(menuRefPtr->menuPtr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return TCL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpMenuNewEntry --
|
|
|
|
|
*
|
|
|
|
|
* Called when a new entry is created in a menu. Fills in platform
|
|
|
|
|
* specific data for the entry. The platformEntryData field
|
|
|
|
|
* is used to store the indicator diameter for radio button
|
|
|
|
|
* and check box entries.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Standard TCL error.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None on Unix.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
TkpMenuNewEntry(mePtr)
|
|
|
|
|
TkMenuEntry *mePtr;
|
|
|
|
|
{
|
|
|
|
|
return TCL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpSetWindowMenuBar --
|
|
|
|
|
*
|
|
|
|
|
* Sets up the menu as a menubar in the given window.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Recomputes geometry of given window.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpSetWindowMenuBar(tkwin, menuPtr)
|
|
|
|
|
Tk_Window tkwin; /* The window we are setting */
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are setting */
|
|
|
|
|
{
|
|
|
|
|
if (menuPtr == NULL) {
|
|
|
|
|
TkUnixSetMenubar(tkwin, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
TkUnixSetMenubar(tkwin, menuPtr->tkwin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpSetMainMenuBar --
|
|
|
|
|
*
|
|
|
|
|
* Called when a toplevel widget is brought to front. On the
|
|
|
|
|
* Macintosh, sets up the menubar that goes accross the top
|
|
|
|
|
* of the main monitor. On other platforms, nothing is necessary.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Recompute geometry of given window.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpSetMainMenubar(interp, tkwin, menuName)
|
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
|
Tk_Window tkwin;
|
|
|
|
|
char *menuName;
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Nothing to do.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* GetMenuIndicatorGeometry --
|
|
|
|
|
*
|
|
|
|
|
* Fills out the geometry of the indicator in a menu item. Note
|
|
|
|
|
* that the mePtr->height field must have already been filled in
|
|
|
|
|
* by GetMenuLabelGeometry since this height depends on the label
|
|
|
|
|
* height.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* widthPtr and heightPtr point to the new geometry values.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing. */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are interested in. */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The precalculated metrics */
|
|
|
|
|
int *widthPtr; /* The resulting width */
|
|
|
|
|
int *heightPtr; /* The resulting height */
|
|
|
|
|
{
|
|
|
|
|
if (!mePtr->hideMargin && mePtr->indicatorOn &&
|
|
|
|
|
((mePtr->type == CHECK_BUTTON_ENTRY)
|
|
|
|
|
|| (mePtr->type == RADIO_BUTTON_ENTRY))) {
|
|
|
|
|
if ((mePtr->image != NULL) || (mePtr->bitmap != None)) {
|
|
|
|
|
*widthPtr = (14 * mePtr->height) / 10;
|
|
|
|
|
*heightPtr = mePtr->height;
|
|
|
|
|
if (mePtr->type == CHECK_BUTTON_ENTRY) {
|
|
|
|
|
mePtr->platformEntryData =
|
|
|
|
|
(TkMenuPlatformEntryData) ((65 * mePtr->height) / 100);
|
|
|
|
|
} else {
|
|
|
|
|
mePtr->platformEntryData =
|
|
|
|
|
(TkMenuPlatformEntryData) ((75 * mePtr->height) / 100);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
*widthPtr = *heightPtr = mePtr->height;
|
|
|
|
|
if (mePtr->type == CHECK_BUTTON_ENTRY) {
|
|
|
|
|
mePtr->platformEntryData = (TkMenuPlatformEntryData)
|
|
|
|
|
((80 * mePtr->height) / 100);
|
|
|
|
|
} else {
|
|
|
|
|
mePtr->platformEntryData = (TkMenuPlatformEntryData)
|
|
|
|
|
mePtr->height;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
*heightPtr = 0;
|
|
|
|
|
*widthPtr = menuPtr->borderWidth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* GetMenuAccelGeometry --
|
|
|
|
|
*
|
|
|
|
|
* Get the geometry of the accelerator area of a menu item.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* heightPtr and widthPtr are set.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr)
|
|
|
|
|
TkMenu *menuPtr; /* The menu was are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are getting the geometry for */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr;/* The precalculated font metrics */
|
|
|
|
|
int *widthPtr; /* The width of the acclerator area */
|
|
|
|
|
int *heightPtr; /* The height of the accelerator area */
|
|
|
|
|
{
|
|
|
|
|
*heightPtr = fmPtr->linespace;
|
|
|
|
|
if (mePtr->type == CASCADE_ENTRY) {
|
|
|
|
|
*widthPtr = 2 * CASCADE_ARROW_WIDTH;
|
|
|
|
|
} else if ((menuPtr->menuType != MENUBAR) && (mePtr->accel != NULL)) {
|
|
|
|
|
*widthPtr = Tk_TextWidth(tkfont, mePtr->accel, mePtr->accelLength);
|
|
|
|
|
} else {
|
|
|
|
|
*widthPtr = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawMenuEntryBackground --
|
|
|
|
|
*
|
|
|
|
|
* This procedure draws the background part of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, bgBorder, x, y,
|
|
|
|
|
width, height)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are drawing. */
|
|
|
|
|
Drawable d; /* The drawable we are drawing into */
|
|
|
|
|
Tk_3DBorder activeBorder; /* The border for an active item */
|
|
|
|
|
Tk_3DBorder bgBorder; /* The background border */
|
|
|
|
|
int x; /* Left coordinate of entry rect */
|
|
|
|
|
int y; /* Right coordinate of entry rect */
|
|
|
|
|
int width; /* Width of entry rect */
|
|
|
|
|
int height; /* Height of entry rect */
|
|
|
|
|
{
|
|
|
|
|
if (mePtr->state == tkActiveUid) {
|
|
|
|
|
int relief;
|
|
|
|
|
bgBorder = activeBorder;
|
|
|
|
|
|
|
|
|
|
if ((menuPtr->menuType == MENUBAR)
|
|
|
|
|
&& ((menuPtr->postedCascade == NULL)
|
|
|
|
|
|| (menuPtr->postedCascade != mePtr))) {
|
|
|
|
|
relief = TK_RELIEF_FLAT;
|
|
|
|
|
} else {
|
|
|
|
|
relief = TK_RELIEF_RAISED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
|
|
|
|
|
menuPtr->activeBorderWidth, relief);
|
|
|
|
|
} else {
|
|
|
|
|
Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
|
|
|
|
|
0, TK_RELIEF_FLAT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawMenuEntryAccelerator --
|
|
|
|
|
*
|
|
|
|
|
* This procedure draws the background part of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder,
|
|
|
|
|
x, y, width, height, drawArrow)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are drawing */
|
|
|
|
|
Drawable d; /* The drawable we are drawing into */
|
|
|
|
|
GC gc; /* The precalculated gc to draw with */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The precalculated metrics */
|
|
|
|
|
Tk_3DBorder activeBorder; /* The border for an active item */
|
|
|
|
|
int x; /* Left coordinate of entry rect */
|
|
|
|
|
int y; /* Top coordinate of entry rect */
|
|
|
|
|
int width; /* Width of entry */
|
|
|
|
|
int height; /* Height of entry */
|
|
|
|
|
int drawArrow; /* Whether or not to draw arrow. */
|
|
|
|
|
{
|
|
|
|
|
XPoint points[3];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Draw accelerator or cascade arrow.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (menuPtr->menuType == MENUBAR) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {
|
|
|
|
|
points[0].x = x + width - menuPtr->borderWidth
|
|
|
|
|
- menuPtr->activeBorderWidth - CASCADE_ARROW_WIDTH;
|
|
|
|
|
points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2;
|
|
|
|
|
points[1].x = points[0].x;
|
|
|
|
|
points[1].y = points[0].y + CASCADE_ARROW_HEIGHT;
|
|
|
|
|
points[2].x = points[0].x + CASCADE_ARROW_WIDTH;
|
|
|
|
|
points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2;
|
|
|
|
|
Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points, 3,
|
|
|
|
|
DECORATION_BORDER_WIDTH,
|
|
|
|
|
(menuPtr->postedCascade == mePtr)
|
|
|
|
|
? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
|
|
|
|
|
} else if (mePtr->accel != NULL) {
|
|
|
|
|
int left = x + mePtr->labelWidth + menuPtr->activeBorderWidth
|
|
|
|
|
+ mePtr->indicatorSpace;
|
|
|
|
|
if (menuPtr->menuType == MENUBAR) {
|
|
|
|
|
left += 5;
|
|
|
|
|
}
|
|
|
|
|
Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
|
|
|
|
|
mePtr->accelLength, left,
|
|
|
|
|
(y + (height + fmPtr->ascent - fmPtr->descent) / 2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawMenuEntryIndicator --
|
|
|
|
|
*
|
|
|
|
|
* This procedure draws the background part of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr,
|
|
|
|
|
x, y, width, height)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are drawing */
|
|
|
|
|
Drawable d; /* The drawable to draw into */
|
|
|
|
|
GC gc; /* The gc to draw with */
|
|
|
|
|
GC indicatorGC; /* The gc that indicators draw with */
|
|
|
|
|
Tk_Font tkfont; /* The font to draw with */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The font metrics of the font */
|
|
|
|
|
int x; /* The left of the entry rect */
|
|
|
|
|
int y; /* The top of the entry rect */
|
|
|
|
|
int width; /* Width of menu entry */
|
|
|
|
|
int height; /* Height of menu entry */
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Draw check-button indicator.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((mePtr->type == CHECK_BUTTON_ENTRY)
|
|
|
|
|
&& mePtr->indicatorOn) {
|
|
|
|
|
int dim, top, left;
|
|
|
|
|
|
|
|
|
|
dim = (int) mePtr->platformEntryData;
|
|
|
|
|
left = x + menuPtr->activeBorderWidth
|
|
|
|
|
+ (mePtr->indicatorSpace - dim)/2;
|
|
|
|
|
if (menuPtr->menuType == MENUBAR) {
|
|
|
|
|
left += 5;
|
|
|
|
|
}
|
|
|
|
|
top = y + (height - dim)/2;
|
|
|
|
|
Tk_Fill3DRectangle(menuPtr->tkwin, d, menuPtr->border, left, top, dim,
|
|
|
|
|
dim, DECORATION_BORDER_WIDTH, TK_RELIEF_SUNKEN);
|
|
|
|
|
left += DECORATION_BORDER_WIDTH;
|
|
|
|
|
top += DECORATION_BORDER_WIDTH;
|
|
|
|
|
dim -= 2*DECORATION_BORDER_WIDTH;
|
|
|
|
|
if ((dim > 0) && (mePtr->entryFlags
|
|
|
|
|
& ENTRY_SELECTED)) {
|
|
|
|
|
XFillRectangle(menuPtr->display, d, indicatorGC, left, top,
|
|
|
|
|
(unsigned int) dim, (unsigned int) dim);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Draw radio-button indicator.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((mePtr->type == RADIO_BUTTON_ENTRY)
|
|
|
|
|
&& mePtr->indicatorOn) {
|
|
|
|
|
XPoint points[4];
|
|
|
|
|
int radius;
|
|
|
|
|
|
|
|
|
|
radius = ((int) mePtr->platformEntryData)/2;
|
|
|
|
|
points[0].x = x + (mePtr->indicatorSpace
|
|
|
|
|
- (int) mePtr->platformEntryData)/2;
|
|
|
|
|
points[0].y = y + (height)/2;
|
|
|
|
|
points[1].x = points[0].x + radius;
|
|
|
|
|
points[1].y = points[0].y + radius;
|
|
|
|
|
points[2].x = points[1].x + radius;
|
|
|
|
|
points[2].y = points[0].y;
|
|
|
|
|
points[3].x = points[1].x;
|
|
|
|
|
points[3].y = points[0].y - radius;
|
|
|
|
|
if (mePtr->entryFlags & ENTRY_SELECTED) {
|
|
|
|
|
XFillPolygon(menuPtr->display, d, indicatorGC, points, 4, Convex,
|
|
|
|
|
CoordModeOrigin);
|
|
|
|
|
} else {
|
|
|
|
|
Tk_Fill3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 4,
|
|
|
|
|
DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT);
|
|
|
|
|
}
|
|
|
|
|
Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 4,
|
|
|
|
|
DECORATION_BORDER_WIDTH, TK_RELIEF_SUNKEN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawMenuSeparator --
|
|
|
|
|
*
|
|
|
|
|
* This procedure draws a separator menu item.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are drawing */
|
|
|
|
|
Drawable d; /* The drawable we are using */
|
|
|
|
|
GC gc; /* The gc to draw into */
|
|
|
|
|
Tk_Font tkfont; /* The font to draw with */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The font metrics from the font */
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
int width;
|
|
|
|
|
int height;
|
|
|
|
|
{
|
|
|
|
|
XPoint points[2];
|
|
|
|
|
int margin;
|
|
|
|
|
|
|
|
|
|
if (menuPtr->menuType == MENUBAR) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
margin = (fmPtr->ascent + fmPtr->descent)/2;
|
|
|
|
|
points[0].x = x;
|
|
|
|
|
points[0].y = y + height/2;
|
|
|
|
|
points[1].x = width - 1;
|
|
|
|
|
points[1].y = points[0].y;
|
|
|
|
|
Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
|
|
|
|
|
TK_RELIEF_RAISED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawMenuEntryLabel --
|
|
|
|
|
*
|
|
|
|
|
* This procedure draws the label part of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawMenuEntryLabel(
|
|
|
|
|
menuPtr, /* The menu we are drawing */
|
|
|
|
|
mePtr, /* The entry we are drawing */
|
|
|
|
|
d, /* What we are drawing into */
|
|
|
|
|
gc, /* The gc we are drawing into */
|
|
|
|
|
tkfont, /* The precalculated font */
|
|
|
|
|
fmPtr, /* The precalculated font metrics */
|
|
|
|
|
x, /* left edge */
|
|
|
|
|
y, /* right edge */
|
|
|
|
|
width, /* width of entry */
|
|
|
|
|
height) /* height of entry */
|
|
|
|
|
TkMenu *menuPtr;
|
|
|
|
|
TkMenuEntry *mePtr;
|
|
|
|
|
Drawable d;
|
|
|
|
|
GC gc;
|
|
|
|
|
Tk_Font tkfont;
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr;
|
|
|
|
|
int x, y, width, height;
|
|
|
|
|
{
|
|
|
|
|
int baseline;
|
|
|
|
|
int indicatorSpace = mePtr->indicatorSpace;
|
|
|
|
|
int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
|
|
|
|
|
int imageHeight, imageWidth;
|
|
|
|
|
|
|
|
|
|
if (menuPtr->menuType == MENUBAR) {
|
|
|
|
|
leftEdge += 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Draw label or bitmap or image for entry.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
|
|
|
|
|
if (mePtr->image != NULL) {
|
|
|
|
|
Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
|
|
|
|
|
if ((mePtr->selectImage != NULL)
|
|
|
|
|
&& (mePtr->entryFlags & ENTRY_SELECTED)) {
|
|
|
|
|
Tk_RedrawImage(mePtr->selectImage, 0, 0,
|
|
|
|
|
imageWidth, imageHeight, d, leftEdge,
|
|
|
|
|
(int) (y + (mePtr->height - imageHeight)/2));
|
|
|
|
|
} else {
|
|
|
|
|
Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
|
|
|
|
|
imageHeight, d, leftEdge,
|
|
|
|
|
(int) (y + (mePtr->height - imageHeight)/2));
|
|
|
|
|
}
|
|
|
|
|
} else if (mePtr->bitmap != None) {
|
|
|
|
|
int width, height;
|
|
|
|
|
|
|
|
|
|
Tk_SizeOfBitmap(menuPtr->display,
|
|
|
|
|
mePtr->bitmap, &width, &height);
|
|
|
|
|
XCopyPlane(menuPtr->display,
|
|
|
|
|
mePtr->bitmap, d,
|
|
|
|
|
gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
|
|
|
|
|
(int) (y + (mePtr->height - height)/2), 1);
|
|
|
|
|
} else {
|
|
|
|
|
if (mePtr->labelLength > 0) {
|
|
|
|
|
Tk_DrawChars(menuPtr->display, d, gc,
|
|
|
|
|
tkfont, mePtr->label, mePtr->labelLength,
|
|
|
|
|
leftEdge, baseline);
|
|
|
|
|
DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
|
|
|
|
|
width, height);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mePtr->state == tkDisabledUid) {
|
|
|
|
|
if (menuPtr->disabledFg == NULL) {
|
|
|
|
|
XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
|
|
|
|
|
(unsigned) width, (unsigned) height);
|
|
|
|
|
} else if ((mePtr->image != NULL)
|
|
|
|
|
&& (menuPtr->disabledImageGC != None)) {
|
|
|
|
|
XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
|
|
|
|
|
leftEdge,
|
|
|
|
|
(int) (y + (mePtr->height - imageHeight)/2),
|
|
|
|
|
(unsigned) imageWidth, (unsigned) imageHeight);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawMenuUnderline --
|
|
|
|
|
*
|
|
|
|
|
* On appropriate platforms, draw the underline character for the
|
|
|
|
|
* menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
|
|
|
|
|
TkMenu *menuPtr; /* The menu to draw into */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are drawing */
|
|
|
|
|
Drawable d; /* What we are drawing into */
|
|
|
|
|
GC gc; /* The gc to draw into */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
int width;
|
|
|
|
|
int height;
|
|
|
|
|
{
|
|
|
|
|
int indicatorSpace = mePtr->indicatorSpace;
|
|
|
|
|
if (mePtr->underline >= 0) {
|
|
|
|
|
int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
|
|
|
|
|
if (menuPtr->menuType == MENUBAR) {
|
|
|
|
|
leftEdge += 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Tk_UnderlineChars(menuPtr->display, d, gc, tkfont, mePtr->label,
|
|
|
|
|
leftEdge, y + (height + fmPtr->ascent - fmPtr->descent) / 2,
|
|
|
|
|
mePtr->underline, mePtr->underline + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpPostMenu --
|
|
|
|
|
*
|
|
|
|
|
* Posts a menu on the screen
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The menu is posted and handled.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
TkpPostMenu(interp, menuPtr, x, y)
|
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
|
TkMenu *menuPtr;
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
{
|
|
|
|
|
return TkPostTearoffMenu(interp, menuPtr, x, y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* GetMenuSeparatorGeometry --
|
|
|
|
|
*
|
|
|
|
|
* Gets the width and height of the indicator area of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* widthPtr and heightPtr are set.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr,
|
|
|
|
|
heightPtr)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are measuring */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are measuring */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The precalcualted font metrics */
|
|
|
|
|
int *widthPtr; /* The resulting width */
|
|
|
|
|
int *heightPtr; /* The resulting height */
|
|
|
|
|
{
|
|
|
|
|
*widthPtr = 0;
|
|
|
|
|
*heightPtr = fmPtr->linespace;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* GetTearoffEntryGeometry --
|
|
|
|
|
*
|
|
|
|
|
* Gets the width and height of the indicator area of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* widthPtr and heightPtr are set.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are measuring */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */
|
|
|
|
|
int *widthPtr; /* The resulting width */
|
|
|
|
|
int *heightPtr; /* The resulting height */
|
|
|
|
|
{
|
|
|
|
|
if (menuPtr->menuType != MASTER_MENU) {
|
|
|
|
|
*heightPtr = 0;
|
|
|
|
|
*widthPtr = 0;
|
|
|
|
|
} else {
|
|
|
|
|
*heightPtr = fmPtr->linespace;
|
|
|
|
|
*widthPtr = Tk_TextWidth(tkfont, "W", -1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*--------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpComputeMenubarGeometry --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is invoked to recompute the size and
|
|
|
|
|
* layout of a menu that is a menubar clone.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Fields of menu entries are changed to reflect their
|
|
|
|
|
* current positions, and the size of the menu window
|
|
|
|
|
* itself may be changed.
|
|
|
|
|
*
|
|
|
|
|
*--------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpComputeMenubarGeometry(menuPtr)
|
|
|
|
|
TkMenu *menuPtr; /* Structure describing menu. */
|
|
|
|
|
{
|
|
|
|
|
Tk_Font tkfont;
|
|
|
|
|
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
|
|
|
|
|
int width, height;
|
|
|
|
|
int i, j;
|
|
|
|
|
int x, y, currentRowHeight, currentRowWidth, maxWidth;
|
|
|
|
|
int maxWindowWidth;
|
|
|
|
|
int lastRowBreak;
|
|
|
|
|
int helpMenuIndex = -1;
|
|
|
|
|
TkMenuEntry *mePtr;
|
|
|
|
|
int lastEntry;
|
|
|
|
|
|
|
|
|
|
if (menuPtr->tkwin == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maxWidth = 0;
|
|
|
|
|
if (menuPtr->numEntries == 0) {
|
|
|
|
|
height = 0;
|
|
|
|
|
} else {
|
|
|
|
|
maxWindowWidth = Tk_Width(menuPtr->tkwin);
|
|
|
|
|
if (maxWindowWidth == 1) {
|
|
|
|
|
maxWindowWidth = 0x7ffffff;
|
|
|
|
|
}
|
|
|
|
|
currentRowHeight = 0;
|
|
|
|
|
x = y = menuPtr->borderWidth;
|
|
|
|
|
lastRowBreak = 0;
|
|
|
|
|
currentRowWidth = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* On the Mac especially, getting font metrics can be quite slow,
|
|
|
|
|
* so we want to do it intelligently. We are going to precalculate
|
|
|
|
|
* them and pass them down to all of the measureing and drawing
|
|
|
|
|
* routines. We will measure the font metrics of the menu once,
|
|
|
|
|
* and if an entry has a font set, we will measure it as we come
|
|
|
|
|
* to it, and then we decide which set to give the geometry routines.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < menuPtr->numEntries; i++) {
|
|
|
|
|
mePtr = menuPtr->entries[i];
|
|
|
|
|
mePtr->entryFlags &= ~ENTRY_LAST_COLUMN;
|
|
|
|
|
tkfont = mePtr->tkfont;
|
|
|
|
|
if (tkfont == NULL) {
|
|
|
|
|
tkfont = menuPtr->tkfont;
|
|
|
|
|
fmPtr = &menuMetrics;
|
|
|
|
|
} else {
|
|
|
|
|
Tk_GetFontMetrics(tkfont, &entryMetrics);
|
|
|
|
|
fmPtr = &entryMetrics;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For every entry, we need to check to see whether or not we
|
|
|
|
|
* wrap. If we do wrap, then we have to adjust all of the previous
|
|
|
|
|
* entries' height and y position, because when we see them
|
|
|
|
|
* the first time, we don't know how big its neighbor might
|
|
|
|
|
* be.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((mePtr->type == SEPARATOR_ENTRY)
|
|
|
|
|
|| (mePtr->type == TEAROFF_ENTRY)) {
|
|
|
|
|
mePtr->height = mePtr->width = 0;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
GetMenuLabelGeometry(mePtr, tkfont, fmPtr,
|
|
|
|
|
&width, &height);
|
1998-09-30 07:11:02 -04:00
|
|
|
|
mePtr->height = height + 2 * menuPtr->activeBorderWidth + 10;
|
1998-04-10 06:59:06 -04:00
|
|
|
|
mePtr->width = width;
|
|
|
|
|
|
|
|
|
|
GetMenuIndicatorGeometry(menuPtr, mePtr,
|
|
|
|
|
tkfont, fmPtr, &width, &height);
|
|
|
|
|
mePtr->indicatorSpace = width;
|
|
|
|
|
if (width > 0) {
|
|
|
|
|
mePtr->width += width;
|
|
|
|
|
}
|
1998-09-30 07:11:02 -04:00
|
|
|
|
mePtr->width += 2 * menuPtr->activeBorderWidth + 10;
|
1998-04-10 06:59:06 -04:00
|
|
|
|
}
|
|
|
|
|
if (mePtr->entryFlags & ENTRY_HELP_MENU) {
|
|
|
|
|
helpMenuIndex = i;
|
|
|
|
|
} else if (x + mePtr->width + menuPtr->borderWidth
|
|
|
|
|
> maxWindowWidth) {
|
|
|
|
|
|
|
|
|
|
if (i == lastRowBreak) {
|
|
|
|
|
mePtr->y = y;
|
|
|
|
|
mePtr->x = x;
|
|
|
|
|
lastRowBreak++;
|
|
|
|
|
y += mePtr->height;
|
|
|
|
|
currentRowHeight = 0;
|
|
|
|
|
} else {
|
|
|
|
|
x = menuPtr->borderWidth;
|
|
|
|
|
for (j = lastRowBreak; j < i; j++) {
|
|
|
|
|
menuPtr->entries[j]->y = y + currentRowHeight
|
|
|
|
|
- menuPtr->entries[j]->height;
|
|
|
|
|
menuPtr->entries[j]->x = x;
|
|
|
|
|
x += menuPtr->entries[j]->width;
|
|
|
|
|
}
|
|
|
|
|
lastRowBreak = i;
|
|
|
|
|
y += currentRowHeight;
|
1998-09-30 07:11:02 -04:00
|
|
|
|
currentRowHeight = mePtr->height;
|
1998-04-10 06:59:06 -04:00
|
|
|
|
}
|
|
|
|
|
if (x > maxWidth) {
|
|
|
|
|
maxWidth = x;
|
|
|
|
|
}
|
|
|
|
|
x = menuPtr->borderWidth;
|
|
|
|
|
} else {
|
|
|
|
|
x += mePtr->width;
|
1998-09-30 07:11:02 -04:00
|
|
|
|
if (mePtr->height > currentRowHeight) {
|
|
|
|
|
currentRowHeight = mePtr->height;
|
1998-04-10 06:59:06 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lastEntry = menuPtr->numEntries - 1;
|
|
|
|
|
if (helpMenuIndex == lastEntry) {
|
|
|
|
|
lastEntry--;
|
|
|
|
|
}
|
|
|
|
|
if ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width
|
|
|
|
|
+ menuPtr->borderWidth > maxWidth)) {
|
|
|
|
|
maxWidth = x + menuPtr->entries[lastEntry]->width
|
|
|
|
|
+ menuPtr->borderWidth;
|
|
|
|
|
}
|
|
|
|
|
x = menuPtr->borderWidth;
|
|
|
|
|
for (j = lastRowBreak; j < menuPtr->numEntries; j++) {
|
|
|
|
|
if (j == helpMenuIndex) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
menuPtr->entries[j]->y = y + currentRowHeight
|
|
|
|
|
- menuPtr->entries[j]->height;
|
|
|
|
|
menuPtr->entries[j]->x = x;
|
|
|
|
|
x += menuPtr->entries[j]->width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (helpMenuIndex != -1) {
|
|
|
|
|
mePtr = menuPtr->entries[helpMenuIndex];
|
|
|
|
|
if (x + mePtr->width + menuPtr->borderWidth > maxWindowWidth) {
|
|
|
|
|
y += currentRowHeight;
|
|
|
|
|
currentRowHeight = mePtr->height;
|
|
|
|
|
x = menuPtr->borderWidth;
|
|
|
|
|
} else if (mePtr->height > currentRowHeight) {
|
|
|
|
|
currentRowHeight = mePtr->height;
|
|
|
|
|
}
|
|
|
|
|
mePtr->x = maxWindowWidth - menuPtr->borderWidth - mePtr->width;
|
|
|
|
|
mePtr->y = y + currentRowHeight - mePtr->height;
|
|
|
|
|
}
|
|
|
|
|
height = y + currentRowHeight + menuPtr->borderWidth;
|
|
|
|
|
}
|
|
|
|
|
width = Tk_Width(menuPtr->tkwin);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The X server doesn't like zero dimensions, so round up to at least
|
|
|
|
|
* 1 (a zero-sized menu should never really occur, anyway).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (width <= 0) {
|
|
|
|
|
width = 1;
|
|
|
|
|
}
|
|
|
|
|
if (height <= 0) {
|
|
|
|
|
height = 1;
|
|
|
|
|
}
|
|
|
|
|
menuPtr->totalWidth = maxWidth;
|
|
|
|
|
menuPtr->totalHeight = height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DrawTearoffEntry --
|
|
|
|
|
*
|
|
|
|
|
* This procedure draws the background part of a menu.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Commands are output to X to display the menu in its
|
|
|
|
|
* current mode.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are drawing */
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are drawing */
|
|
|
|
|
Drawable d; /* The drawable we are drawing into */
|
|
|
|
|
GC gc; /* The gc we are drawing with */
|
|
|
|
|
Tk_Font tkfont; /* The font we are drawing with */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The metrics we are drawing with */
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
int width;
|
|
|
|
|
int height;
|
|
|
|
|
{
|
|
|
|
|
XPoint points[2];
|
|
|
|
|
int margin, segmentWidth, maxX;
|
|
|
|
|
|
|
|
|
|
if (menuPtr->menuType != MASTER_MENU) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
margin = (fmPtr->ascent + fmPtr->descent)/2;
|
|
|
|
|
points[0].x = x;
|
|
|
|
|
points[0].y = y + height/2;
|
|
|
|
|
points[1].y = points[0].y;
|
|
|
|
|
segmentWidth = 6;
|
|
|
|
|
maxX = width - 1;
|
|
|
|
|
|
|
|
|
|
while (points[0].x < maxX) {
|
|
|
|
|
points[1].x = points[0].x + segmentWidth;
|
|
|
|
|
if (points[1].x > maxX) {
|
|
|
|
|
points[1].x = maxX;
|
|
|
|
|
}
|
|
|
|
|
Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
|
|
|
|
|
TK_RELIEF_RAISED);
|
|
|
|
|
points[0].x += 2*segmentWidth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*--------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpInitializeMenuBindings --
|
|
|
|
|
*
|
|
|
|
|
* For every interp, initializes the bindings for Windows
|
|
|
|
|
* menus. Does nothing on Mac or XWindows.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* C-level bindings are setup for the interp which will
|
|
|
|
|
* handle Alt-key sequences for menus without beeping
|
|
|
|
|
* or interfering with user-defined Alt-key bindings.
|
|
|
|
|
*
|
|
|
|
|
*--------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpInitializeMenuBindings(interp, bindingTable)
|
|
|
|
|
Tcl_Interp *interp; /* The interpreter to set. */
|
|
|
|
|
Tk_BindingTable bindingTable; /* The table to add to. */
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Nothing to do.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* SetHelpMenu --
|
|
|
|
|
*
|
|
|
|
|
* Given a menu, check to see whether or not it is a help menu
|
|
|
|
|
* cascade in a menubar. If it is, the entry that points to
|
|
|
|
|
* this menu will be marked.
|
|
|
|
|
*
|
|
|
|
|
* RESULTS:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Will set the ENTRY_HELP_MENU flag appropriately.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
SetHelpMenu(menuPtr)
|
|
|
|
|
TkMenu *menuPtr; /* The menu we are checking */
|
|
|
|
|
{
|
|
|
|
|
TkMenuEntry *cascadeEntryPtr;
|
|
|
|
|
|
|
|
|
|
for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
|
|
|
|
|
cascadeEntryPtr != NULL;
|
|
|
|
|
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
|
|
|
|
|
if ((cascadeEntryPtr->menuPtr->menuType == MENUBAR)
|
|
|
|
|
&& (cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin != NULL)
|
|
|
|
|
&& (menuPtr->masterMenuPtr->tkwin != NULL)) {
|
|
|
|
|
TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
|
|
|
|
|
char *helpMenuName = ckalloc(strlen(Tk_PathName(
|
|
|
|
|
masterMenuPtr->tkwin)) + strlen(".help") + 1);
|
|
|
|
|
|
|
|
|
|
strcpy(helpMenuName, Tk_PathName(masterMenuPtr->tkwin));
|
|
|
|
|
strcat(helpMenuName, ".help");
|
|
|
|
|
if (strcmp(helpMenuName,
|
|
|
|
|
Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
|
|
|
|
|
cascadeEntryPtr->entryFlags |= ENTRY_HELP_MENU;
|
|
|
|
|
} else {
|
|
|
|
|
cascadeEntryPtr->entryFlags &= ~ENTRY_HELP_MENU;
|
|
|
|
|
}
|
|
|
|
|
ckfree(helpMenuName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpDrawMenuEntry --
|
|
|
|
|
*
|
|
|
|
|
* Draws the given menu entry at the given coordinates with the
|
|
|
|
|
* given attributes.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* X Server commands are executed to display the menu entry.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
|
|
|
|
|
strictMotif, drawArrow)
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry to draw */
|
|
|
|
|
Drawable d; /* What to draw into */
|
|
|
|
|
Tk_Font tkfont; /* Precalculated font for menu */
|
|
|
|
|
CONST Tk_FontMetrics *menuMetricsPtr;
|
|
|
|
|
/* Precalculated metrics for menu */
|
|
|
|
|
int x; /* X-coordinate of topleft of entry */
|
|
|
|
|
int y; /* Y-coordinate of topleft of entry */
|
|
|
|
|
int width; /* Width of the entry rectangle */
|
|
|
|
|
int height; /* Height of the current rectangle */
|
|
|
|
|
int strictMotif; /* Boolean flag */
|
|
|
|
|
int drawArrow; /* Whether or not to draw the cascade
|
|
|
|
|
* arrow for cascade items. Only applies
|
|
|
|
|
* to Windows. */
|
|
|
|
|
{
|
|
|
|
|
GC gc, indicatorGC;
|
|
|
|
|
TkMenu *menuPtr = mePtr->menuPtr;
|
|
|
|
|
Tk_3DBorder bgBorder, activeBorder;
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr;
|
|
|
|
|
Tk_FontMetrics entryMetrics;
|
|
|
|
|
int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
|
|
|
|
|
int adjustedY = y + padY;
|
|
|
|
|
int adjustedHeight = height - 2 * padY;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Choose the gc for drawing the foreground part of the entry.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((mePtr->state == tkActiveUid)
|
|
|
|
|
&& !strictMotif) {
|
|
|
|
|
gc = mePtr->activeGC;
|
|
|
|
|
if (gc == NULL) {
|
|
|
|
|
gc = menuPtr->activeGC;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
TkMenuEntry *cascadeEntryPtr;
|
|
|
|
|
int parentDisabled = 0;
|
|
|
|
|
|
|
|
|
|
for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
|
|
|
|
|
cascadeEntryPtr != NULL;
|
|
|
|
|
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
|
|
|
|
|
if (strcmp(cascadeEntryPtr->name,
|
|
|
|
|
Tk_PathName(menuPtr->tkwin)) == 0) {
|
|
|
|
|
if (cascadeEntryPtr->state == tkDisabledUid) {
|
|
|
|
|
parentDisabled = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (((parentDisabled || (mePtr->state == tkDisabledUid)))
|
|
|
|
|
&& (menuPtr->disabledFg != NULL)) {
|
|
|
|
|
gc = mePtr->disabledGC;
|
|
|
|
|
if (gc == NULL) {
|
|
|
|
|
gc = menuPtr->disabledGC;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
gc = mePtr->textGC;
|
|
|
|
|
if (gc == NULL) {
|
|
|
|
|
gc = menuPtr->textGC;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
indicatorGC = mePtr->indicatorGC;
|
|
|
|
|
if (indicatorGC == NULL) {
|
|
|
|
|
indicatorGC = menuPtr->indicatorGC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bgBorder = mePtr->border;
|
|
|
|
|
if (bgBorder == NULL) {
|
|
|
|
|
bgBorder = menuPtr->border;
|
|
|
|
|
}
|
|
|
|
|
if (strictMotif) {
|
|
|
|
|
activeBorder = bgBorder;
|
|
|
|
|
} else {
|
|
|
|
|
activeBorder = mePtr->activeBorder;
|
|
|
|
|
if (activeBorder == NULL) {
|
|
|
|
|
activeBorder = menuPtr->activeBorder;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mePtr->tkfont == NULL) {
|
|
|
|
|
fmPtr = menuMetricsPtr;
|
|
|
|
|
} else {
|
|
|
|
|
tkfont = mePtr->tkfont;
|
|
|
|
|
Tk_GetFontMetrics(tkfont, &entryMetrics);
|
|
|
|
|
fmPtr = &entryMetrics;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Need to draw the entire background, including padding. On Unix,
|
|
|
|
|
* for menubars, we have to draw the rest of the entry taking
|
|
|
|
|
* into account the padding.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,
|
|
|
|
|
bgBorder, x, y, width, height);
|
|
|
|
|
|
|
|
|
|
if (mePtr->type == SEPARATOR_ENTRY) {
|
|
|
|
|
DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
|
|
|
|
|
fmPtr, x, adjustedY, width, adjustedHeight);
|
|
|
|
|
} else if (mePtr->type == TEAROFF_ENTRY) {
|
|
|
|
|
DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
|
|
|
|
|
width, adjustedHeight);
|
|
|
|
|
} else {
|
|
|
|
|
DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
|
|
|
|
|
width, adjustedHeight);
|
|
|
|
|
DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
|
|
|
|
|
activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
|
|
|
|
|
if (!mePtr->hideMargin) {
|
|
|
|
|
DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
|
|
|
|
|
fmPtr, x, adjustedY, width, adjustedHeight);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* GetMenuLabelGeometry --
|
|
|
|
|
*
|
|
|
|
|
* Figures out the size of the label portion of a menu item.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* widthPtr and heightPtr are filled in with the correct geometry
|
|
|
|
|
* information.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)
|
|
|
|
|
TkMenuEntry *mePtr; /* The entry we are computing */
|
|
|
|
|
Tk_Font tkfont; /* The precalculated font */
|
|
|
|
|
CONST Tk_FontMetrics *fmPtr; /* The precalculated metrics */
|
|
|
|
|
int *widthPtr; /* The resulting width of the label
|
|
|
|
|
* portion */
|
|
|
|
|
int *heightPtr; /* The resulting height of the label
|
|
|
|
|
* portion */
|
|
|
|
|
{
|
|
|
|
|
TkMenu *menuPtr = mePtr->menuPtr;
|
|
|
|
|
|
|
|
|
|
if (mePtr->image != NULL) {
|
|
|
|
|
Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
|
|
|
|
|
} else if (mePtr->bitmap != (Pixmap) NULL) {
|
|
|
|
|
Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
|
|
|
|
|
} else {
|
|
|
|
|
*heightPtr = fmPtr->linespace;
|
|
|
|
|
|
|
|
|
|
if (mePtr->label != NULL) {
|
|
|
|
|
*widthPtr = Tk_TextWidth(tkfont, mePtr->label, mePtr->labelLength);
|
|
|
|
|
} else {
|
|
|
|
|
*widthPtr = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*heightPtr += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*--------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpComputeStandardMenuGeometry --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is invoked to recompute the size and
|
|
|
|
|
* layout of a menu that is not a menubar clone.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Fields of menu entries are changed to reflect their
|
|
|
|
|
* current positions, and the size of the menu window
|
|
|
|
|
* itself may be changed.
|
|
|
|
|
*
|
|
|
|
|
*--------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpComputeStandardMenuGeometry(
|
|
|
|
|
menuPtr) /* Structure describing menu. */
|
|
|
|
|
TkMenu *menuPtr;
|
|
|
|
|
{
|
|
|
|
|
Tk_Font tkfont;
|
|
|
|
|
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
|
|
|
|
|
int x, y, height, width, indicatorSpace, labelWidth, accelWidth;
|
|
|
|
|
int windowWidth, windowHeight, accelSpace;
|
|
|
|
|
int i, j, lastColumnBreak = 0;
|
|
|
|
|
TkMenuEntry *mePtr;
|
|
|
|
|
|
|
|
|
|
if (menuPtr->tkwin == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
x = y = menuPtr->borderWidth;
|
|
|
|
|
indicatorSpace = labelWidth = accelWidth = 0;
|
|
|
|
|
windowHeight = windowWidth = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* On the Mac especially, getting font metrics can be quite slow,
|
|
|
|
|
* so we want to do it intelligently. We are going to precalculate
|
|
|
|
|
* them and pass them down to all of the measuring and drawing
|
|
|
|
|
* routines. We will measure the font metrics of the menu once.
|
|
|
|
|
* If an entry does not have its own font set, then we give
|
|
|
|
|
* the geometry/drawing routines the menu's font and metrics.
|
|
|
|
|
* If an entry has its own font, we will measure that font and
|
|
|
|
|
* give all of the geometry/drawing the entry's font and metrics.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
|
|
|
|
|
accelSpace = Tk_TextWidth(menuPtr->tkfont, "M", 1);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < menuPtr->numEntries; i++) {
|
|
|
|
|
mePtr = menuPtr->entries[i];
|
|
|
|
|
tkfont = mePtr->tkfont;
|
|
|
|
|
if (tkfont == NULL) {
|
|
|
|
|
tkfont = menuPtr->tkfont;
|
|
|
|
|
fmPtr = &menuMetrics;
|
|
|
|
|
} else {
|
|
|
|
|
Tk_GetFontMetrics(tkfont, &entryMetrics);
|
|
|
|
|
fmPtr = &entryMetrics;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((i > 0) && mePtr->columnBreak) {
|
|
|
|
|
if (accelWidth != 0) {
|
|
|
|
|
labelWidth += accelSpace;
|
|
|
|
|
}
|
|
|
|
|
for (j = lastColumnBreak; j < i; j++) {
|
|
|
|
|
menuPtr->entries[j]->indicatorSpace = indicatorSpace;
|
|
|
|
|
menuPtr->entries[j]->labelWidth = labelWidth;
|
|
|
|
|
menuPtr->entries[j]->width = indicatorSpace + labelWidth
|
|
|
|
|
+ accelWidth + 2 * menuPtr->activeBorderWidth;
|
|
|
|
|
menuPtr->entries[j]->x = x;
|
|
|
|
|
menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;
|
|
|
|
|
}
|
|
|
|
|
x += indicatorSpace + labelWidth + accelWidth
|
|
|
|
|
+ 2 * menuPtr->activeBorderWidth;
|
|
|
|
|
windowWidth = x;
|
|
|
|
|
indicatorSpace = labelWidth = accelWidth = 0;
|
|
|
|
|
lastColumnBreak = i;
|
|
|
|
|
y = menuPtr->borderWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mePtr->type == SEPARATOR_ENTRY) {
|
|
|
|
|
GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont,
|
|
|
|
|
fmPtr, &width, &height);
|
|
|
|
|
mePtr->height = height;
|
|
|
|
|
} else if (mePtr->type == TEAROFF_ENTRY) {
|
|
|
|
|
GetTearoffEntryGeometry(menuPtr, mePtr, tkfont,
|
|
|
|
|
fmPtr, &width, &height);
|
|
|
|
|
mePtr->height = height;
|
|
|
|
|
labelWidth = width;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For each entry, compute the height required by that
|
|
|
|
|
* particular entry, plus three widths: the width of the
|
|
|
|
|
* label, the width to allow for an indicator to be displayed
|
|
|
|
|
* to the left of the label (if any), and the width of the
|
|
|
|
|
* accelerator to be displayed to the right of the label
|
|
|
|
|
* (if any). These sizes depend, of course, on the type
|
|
|
|
|
* of the entry.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width,
|
|
|
|
|
&height);
|
|
|
|
|
mePtr->height = height;
|
|
|
|
|
if (!mePtr->hideMargin) {
|
|
|
|
|
width += MENU_MARGIN_WIDTH;
|
|
|
|
|
}
|
|
|
|
|
if (width > labelWidth) {
|
|
|
|
|
labelWidth = width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
|
|
|
|
|
fmPtr, &width, &height);
|
|
|
|
|
if (height > mePtr->height) {
|
|
|
|
|
mePtr->height = height;
|
|
|
|
|
}
|
|
|
|
|
if (!mePtr->hideMargin) {
|
|
|
|
|
width += MENU_MARGIN_WIDTH;
|
|
|
|
|
}
|
|
|
|
|
if (width > accelWidth) {
|
|
|
|
|
accelWidth = width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont,
|
|
|
|
|
fmPtr, &width, &height);
|
|
|
|
|
if (height > mePtr->height) {
|
|
|
|
|
mePtr->height = height;
|
|
|
|
|
}
|
|
|
|
|
if (!mePtr->hideMargin) {
|
|
|
|
|
width += MENU_MARGIN_WIDTH;
|
|
|
|
|
}
|
|
|
|
|
if (width > indicatorSpace) {
|
|
|
|
|
indicatorSpace = width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mePtr->height += 2 * menuPtr->activeBorderWidth +
|
|
|
|
|
MENU_DIVIDER_HEIGHT;
|
|
|
|
|
}
|
|
|
|
|
mePtr->y = y;
|
|
|
|
|
y += mePtr->height;
|
|
|
|
|
if (y > windowHeight) {
|
|
|
|
|
windowHeight = y;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (accelWidth != 0) {
|
|
|
|
|
labelWidth += accelSpace;
|
|
|
|
|
}
|
|
|
|
|
for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
|
|
|
|
|
menuPtr->entries[j]->indicatorSpace = indicatorSpace;
|
|
|
|
|
menuPtr->entries[j]->labelWidth = labelWidth;
|
|
|
|
|
menuPtr->entries[j]->width = indicatorSpace + labelWidth
|
|
|
|
|
+ accelWidth + 2 * menuPtr->activeBorderWidth;
|
|
|
|
|
menuPtr->entries[j]->x = x;
|
|
|
|
|
menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
|
|
|
|
|
}
|
|
|
|
|
windowWidth = x + indicatorSpace + labelWidth + accelWidth
|
|
|
|
|
+ 2 * menuPtr->activeBorderWidth + 2 * menuPtr->borderWidth;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
windowHeight += menuPtr->borderWidth;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The X server doesn't like zero dimensions, so round up to at least
|
|
|
|
|
* 1 (a zero-sized menu should never really occur, anyway).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (windowWidth <= 0) {
|
|
|
|
|
windowWidth = 1;
|
|
|
|
|
}
|
|
|
|
|
if (windowHeight <= 0) {
|
|
|
|
|
windowHeight = 1;
|
|
|
|
|
}
|
|
|
|
|
menuPtr->totalWidth = windowWidth;
|
|
|
|
|
menuPtr->totalHeight = windowHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpMenuNotifyToplevelCreate --
|
|
|
|
|
*
|
|
|
|
|
* This routine reconfigures the menu and the clones indicated by
|
|
|
|
|
* menuName becuase a toplevel has been created and any system
|
|
|
|
|
* menus need to be created. Not applicable to UNIX.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* An idle handler is set up to do the reconfiguration.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpMenuNotifyToplevelCreate(interp, menuName)
|
|
|
|
|
Tcl_Interp *interp; /* The interp the menu lives in. */
|
|
|
|
|
char *menuName; /* The name of the menu to
|
|
|
|
|
* reconfigure. */
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Nothing to do.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpMenuInit --
|
|
|
|
|
*
|
|
|
|
|
* Does platform-specific initialization of menus.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpMenuInit()
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Nothing to do.
|
|
|
|
|
*/
|
|
|
|
|
}
|