/*
* tkMenu.c --
*
* This module implements menus for the Tk toolkit. The menus
* support normal button entries, plus check buttons, radio
* buttons, iconic forms of all of the above, and separator
* entries.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tkMenu.c 1.105 96/12/17 11:16:18
*/
#include "tkInt.h"
#include "tkDefault.h"
#ifdef MAC_TCL
# include "tkMacInt.h"
#endif
/*
* One of the following data structures is kept for each entry of each
* menu managed by this file:
*/
typedef struct MenuEntry {
* valid types. */
* if no label). Malloc'ed. */
* If not None then label is ignored. */
* NULL. If non-NULL, bitmap, text, and
* textVarName are ignored. */
* none. */
* (malloc'ed), or NULL. */
* or NULL if none. Ignored if image is
* NULL. */
* of menu entry. NULL means no such
* accelerator. Malloc'ed. */
* accelerator. */
/*
* Information related to displaying entry:
*/
* normal, active, or disabled. */
* vertical dimension, including raised
* border drawn around entry when active. */
int y; /* Y-coordinate of topmost pixel in entry. */
* don't draw it. */
* entry. NULL means use overall border
* for menu. */
* means use foreground color from menu. */
* element is active. NULL means use
* activeBorder from menu. */
* active. NULL means use active foreground
* from menu. */
* use overall font for menu. */
* use overall textGC for menu. */
* NULL means use overall activeGC for
* menu. */
* NULL means use overall disabledGC from
* menu structure. See comments for
* disabledFg in menu structure for more
* information. */
* button entries. NULL means use indicatorFg
* GC from menu. */
* GC from menu. */
/*
* Information used to implement this entry's action:
*/
* Malloc'ed. */
* radio buttons) or menu (for cascade
* entries). Malloc'ed.*/
* (only for radio and check buttons).
* Malloc'ed. */
* selected (only for check buttons).
* Malloc'ed. */
/*
* Miscellaneous information:
*/
} MenuEntry;
/*
* Flag values defined for menu entries:
*
* ENTRY_SELECTED: Non-zero means this is a radio or check
* button and that it should be drawn in
* the "selected" state.
* ENTRY_NEEDS_REDISPLAY: Non-zero means the entry should be redisplayed.
*/
/*
* Types defined for MenuEntries:
*/
#define COMMAND_ENTRY 0
/*
* Mask bits for above types:
*/
/*
* Configuration specs for individual menu entries:
*/
(char *) NULL, 0, 0}
};
/*
* A data structure of the following type is kept for each
* menu managed by this file:
*/
typedef struct Menu {
* means that the window has been destroyed
* but the data structures haven't yet been
* cleaned up.*/
* other things, so that resources can be
* freed up even after tkwin has gone away. */
* in the menu. NULL means no entries. */
* nothing active. */
/*
* Information used when displaying widget:
*/
* border and background for menu. */
* active element (if any). */
* of menu entries. */
* means use normalFg with a 50% stipple
* instead. */
* a stippled fashion. None means not
* allocated yet. */
* disabledFg isn't NULL, this GC is used to
* draw text and icons for disabled entries.
* Otherwise text and icons are drawn with
* normalGC and this GC is used to stipple
* background across them. */
* button entries. */
* indicators in menu entries (includes extra
* space around indicator). */
* labels in menu entries. */
/*
* Miscellaneous information:
*/
* first entry always shows a dashed stripe
* for tearing off. */
* run whenever the menu is torn-off. */
* a popup or pulldown or cascade. 0 means
* menu is always visible, e.g. as a torn-off
* menu. Determines whether save_under and
* override_redirect should be set. */
* the C code, but used by keyboard traversal
* scripts. Malloc'ed, but may be NULL. */
* this menu, or NULL. Malloc-ed. */
* submenu that is currently posted, or
* NULL if no submenu posted. */
* definitions. */
} Menu;
/*
* Flag bits for menus:
*
* REDRAW_PENDING: Non-zero means a DoWhenIdle handler
* has already been queued to redraw
* this window.
* RESIZE_PENDING: Non-zero means a call to ComputeMenuGeometry
* has already been scheduled.
*/
/*
* Configuration specs valid for the menu as a whole:
*/
(char *) NULL, 0, 0},
(char *) NULL, 0, 0},
"DisabledForeground", DEF_MENU_DISABLED_FG_COLOR,
"DisabledForeground", DEF_MENU_DISABLED_FG_MONO,
(char *) NULL, 0, 0},
(char *) NULL, 0, 0}
};
/*
* Various geometry definitions:
*/
/*
* Forward declarations for procedures defined later in this file:
*/
int index));
static void ComputeMenuGeometry _ANSI_ARGS_((
int flags));
int *indexPtr));
char **argv));
static void MenuCmdDeletedProc _ANSI_ARGS_((
int imgHeight));
int type));
int imgHeight));
int flags));
/*
*--------------------------------------------------------------
*
* Tk_MenuCmd --
*
* This procedure is invoked to process the "menu" Tcl
* command. See the user documentation for details on
* what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*--------------------------------------------------------------
*/
int
* interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc < 2) {
return TCL_ERROR;
}
/*
* Create the new window. Set override-redirect so the window
* manager won't add a border or argue about placement, and set
* save-under so that the window can pop up and down without a
* lot of re-drawing.
*/
return TCL_ERROR;
}
/*
* Initialize the data structure for the menu.
*/
menuPtr->numEntries = 0;
menuPtr->borderWidth = 0;
menuPtr->activeBorderWidth = 0;
menuPtr->indicatorSpace = 0;
menuPtr->labelWidth = 0;
goto error;
}
return TCL_OK;
return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
* MenuWidgetCmd --
*
* This procedure is invoked to process the Tcl command
* that corresponds to a widget managed by this module.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*--------------------------------------------------------------
*/
static int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int c;
if (argc < 2) {
return TCL_ERROR;
}
c = argv[1][0];
&& (length >= 2)) {
int index;
if (argc != 3) {
goto error;
}
goto error;
}
goto done;
}
if (index >= 0) {
index = -1;
}
}
&& (length >= 2)) {
if (argc < 3) {
goto error;
}
goto error;
}
&& (length >= 2)) {
if (argc != 3) {
argv[0], " cget option\"",
(char *) NULL);
goto error;
}
&& (length >= 2)) {
if (argc == 2) {
} else if (argc == 3) {
} else {
}
goto error;
}
goto error;
}
if (argc == 3) {
} else {
goto error;
}
}
/*
* Sorry, can't delete the tearoff entry; must reconfigure
* the menu.
*/
first = 1;
}
goto done;
}
}
}
}
}
int index;
if (argc != 4) {
argv[0], " entrycget index option\"",
(char *) NULL);
goto error;
}
goto error;
}
if (index < 0) {
goto done;
}
int index;
if (argc < 3) {
argv[0], " entryconfigure index ?option value ...?\"",
(char *) NULL);
goto error;
}
goto error;
}
if (index < 0) {
goto done;
}
if (argc == 3) {
} else if (argc == 4) {
} else {
}
&& (length >= 3)) {
int index;
if (argc != 3) {
goto error;
}
goto error;
}
if (index < 0) {
} else {
}
&& (length >= 3)) {
if (argc < 4) {
goto error;
}
goto error;
}
&& (length >= 3)) {
int index;
if (argc != 3) {
goto error;
}
goto error;
}
if (index < 0) {
goto done;
}
goto done;
}
}
} else {
}
}
}
}
}
}
&& (length == 4)) {
if (argc != 4) {
goto error;
}
goto error;
}
/*
* De-activate any active element.
*/
/*
* If there is a command for the menu, execute it. This
* may change the size of the menu, so be sure to recompute
* the menu's geometry if needed.
*/
return result;
}
}
}
/*
* Adjust the position of the menu if necessary to keep it
* visible on the screen. There are two special tricks to
* make this work right:
*
* 1. If a virtual root window manager is being used then
* the coordinates are in the virtual root window of
* menuPtr's parent; since the menu uses override-redirect
* mode it will be in the *real* root window for the screen,
* so we have to map the coordinates from the virtual root
* (if any) to the real root. Can't get the virtual root
* from the menu itself (it will never be seen by the wm)
* so use its parent instead (it would be better to have an
* an option that names a window to use for this...).
* 2. The menu may not have been mapped yet, so its current size
* might be the default 1x1. To compute how much space it
* needs, use its requested size, not its actual size.
*/
&vRootWidth, &vRootHeight);
x += vRootX;
y += vRootY;
if (x > tmp) {
x = tmp;
}
if (x < 0) {
x = 0;
}
if (y > tmp) {
y = tmp;
}
if (y < 0) {
y = 0;
}
}
}
&& (length > 4)) {
int index;
if (argc != 3) {
goto error;
}
goto error;
}
} else {
}
int index;
if (argc != 3) {
goto error;
}
goto error;
}
if (index < 0) {
goto done;
}
case COMMAND_ENTRY:
break;
case SEPARATOR_ENTRY:
break;
case CHECK_BUTTON_ENTRY:
break;
case RADIO_BUTTON_ENTRY:
break;
case CASCADE_ENTRY:
break;
case TEAROFF_ENTRY:
break;
}
if (argc != 2) {
goto error;
}
}
int index;
if (argc != 3) {
goto error;
}
goto error;
}
if (index < 0) {
} else {
}
} else {
"\": must be activate, add, cget, configure, delete, ",
"entrycget, entryconfigure, index, insert, invoke, ",
"post, postcascade, type, unpost, or yposition",
(char *) NULL);
goto error;
}
done:
return result;
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* DestroyMenu --
*
* This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
* to clean up the internal structure of a menu at a safe time
* (when no-one is using it anymore).
*
* Results:
* None.
*
* Side effects:
* Everything associated with the menu is freed up.
*
*----------------------------------------------------------------------
*/
static void
char *memPtr; /* Info about menu widget. */
{
int i;
/*
* Free up all the stuff that requires special handling, then
* let Tk_FreeOptions handle all the standard option-related
* stuff.
*/
for (i = 0; i < menuPtr->numEntries; i++) {
}
}
}
}
}
}
}
}
/*
*----------------------------------------------------------------------
*
* DestroyMenuEntry --
*
* This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
* to clean up the internal structure of a menu entry at a safe time
* (when no-one is using it anymore).
*
* Results:
* None.
*
* Side effects:
* Everything associated with the menu entry is freed up.
*
*----------------------------------------------------------------------
*/
static void
char *memPtr; /* Pointer to entry to be freed. */
{
/*
* Free up all the stuff that requires special handling, then
* let Tk_FreeOptions handle all the standard option-related
* stuff.
*/
/*
* Ignore errors while unposting the menu, since it's possible
* that the menu has already been deleted and the unpost will
* generate an error.
*/
}
}
}
}
}
}
}
}
}
/*
*----------------------------------------------------------------------
*
* ConfigureMenu --
*
* the Tk option database, in order to configure (or
* reconfigure) a menu widget.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
* returned, then interp->result contains an error message.
*
* Side effects:
* Configuration information, such as colors, font, etc. get set
* for menuPtr; old resources get freed, if there were any.
*
*----------------------------------------------------------------------
*/
static int
* not already have values for some fields. */
int argc; /* Number of valid entries in argv. */
char **argv; /* Arguments. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
unsigned long mask;
int i;
return TCL_ERROR;
}
/*
* A few options need special processing, such as setting the
* background from a 3-D border, or filling in complicated
* defaults that couldn't be specified to Tk_ConfigureWidget.
*/
&gcValues);
}
} else {
Tk_GetUid("gray50"));
return TCL_ERROR;
}
}
}
}
&gcValues);
}
}
} else {
}
if ((atts.override_redirect
|| (atts.save_under
}
#ifdef MAC_TCL
#endif
/*
* After reconfiguring a menu, we need to reconfigure all of the
* entries in the menu, since some of the things in the children
* (such as graphics contexts) may have to change to reflect changes
* in the parent.
*/
for (i = 0; i < menuPtr->numEntries; i++) {
}
/*
* Depending on the -tearOff option, make sure that there is or
* isn't an initial tear-off entry at the beginning of the menu.
*/
if ((menuPtr->numEntries == 0)
}
} else if ((menuPtr->numEntries > 0)
}
menuPtr->numEntries--;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ConfigureMenuEntry --
*
* the Tk option database, in order to configure (or
* reconfigure) one entry in a menu.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
* returned, then interp->result contains an error message.
*
* Side effects:
* Configuration information such as label and accelerator get
* set for mePtr; old resources get freed, if there were any.
*
*----------------------------------------------------------------------
*/
static int
* or may not already have values for
* some fields. */
int index; /* Index of mePtr within menuPtr's
* entries. */
int argc; /* Number of valid entries in argv. */
char **argv; /* Arguments. */
int flags; /* Additional flags to pass to
* Tk_ConfigureWidget. */
{
unsigned long mask;
/*
* If this entry is a cascade and the cascade is posted, then unpost
* it before reconfiguring the entry (otherwise the reconfigure might
* change the name of the cascaded entry, leaving a posted menu
* high and dry).
*/
!= TCL_OK) {
}
}
/*
* If this entry is a check button or radio button, then remove
* its old trace procedure.
*/
}
return TCL_ERROR;
}
/*
* The code below handles special configuration stuff not taken
* care of by Tk_ConfigureWidget, such as special processing for
* defaults, sizing strings, graphics contexts, etc.
*/
mePtr->labelLength = 0;
} else {
}
mePtr->accelLength = 0;
} else {
}
}
} else {
}
"\": must be normal, active, or disabled", (char *) NULL);
return TCL_ERROR;
}
}
->pixel;
/*
* Note: disable GraphicsExpose events; we know there won't be
* obscured areas when copying from an off-screen pixmap to the
* screen and this gets rid of unnecessary events.
*/
&gcValues);
} else {
}
&gcValues);
} else {
newActiveGC = None;
}
}
}
}
} else {
}
}
char *value;
}
}
/*
* Select the entry if the associated variable has the
* appropriate value, initialize the variable if it doesn't
* exist, then set a trace on the variable to monitor future
* changes to its value.
*/
}
} else {
}
}
/*
* Get the images for the entry, if there are any. Allocate the
* new images before freeing the old ones, so that the reference
* counts don't go to zero and cause image data to be discarded.
*/
return TCL_ERROR;
}
} else {
}
}
return TCL_ERROR;
}
} else {
}
}
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* ComputeMenuGeometry --
*
* This procedure is invoked to recompute the size and
* layout of a menu. It is called as a when-idle handler so
* that it only gets done once, even if a group of changes is
* made to the menu.
*
* 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.
*
*--------------------------------------------------------------
*/
static void
{
int i, y;
return;
}
y = menuPtr->borderWidth;
for (i = 0; i < menuPtr->numEntries; i++) {
indicatorSpace = 0;
}
/*
* 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.
*/
width = imageWidth;
if (mePtr->indicatorOn) {
}
}
&imageWidth, &imageHeight);
goto imageOrBitmap;
} else {
} else {
width = 0;
}
if (mePtr->indicatorOn) {
}
}
}
if (width > maxLabelWidth) {
}
} else {
width = 0;
}
if (width > maxAccelWidth) {
}
}
}
if (indicatorSpace > maxIndicatorWidth) {
}
mePtr->y = y;
}
/*
* Got all the sizes. Update fields in the menu structure, then
* resize the window if necessary. Leave margins on either side
* of the indicator (or just one margin if there is no indicator).
* Leave another margin on the right side of the label, plus yet
* another margin to the right of the accelerator (if there is one).
*/
if (maxIndicatorWidth != 0) {
}
if (maxAccelWidth != 0) {
width += MARGIN_WIDTH;
}
/*
* 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;
}
} else {
/*
* Must always force a redisplay here if the window is mapped
* (even if the size didn't change, something else might have
* changed in the menu, such as a label or accelerator). The
* resize will force a redisplay above.
*/
}
}
/*
*----------------------------------------------------------------------
*
* DisplayMenu --
*
* This procedure is invoked to display a menu widget.
*
* Results:
* None.
*
* Side effects:
* Commands are output to X to display the menu in its
* current mode.
*
*----------------------------------------------------------------------
*/
static void
{
return;
}
/*
* Loop through all of the entries, drawing them one at a time.
*/
continue;
}
/*
* Background.
*/
}
if (strictMotif) {
} else {
if (activeBorder == NULL) {
}
}
} else {
0, TK_RELIEF_FLAT);
}
/*
* Choose the gc for drawing the foreground part of the entry.
*/
}
} else {
}
} else {
}
}
}
/*
* Draw label or bitmap or image for entry.
*/
}
} else {
}
} else {
}
}
}
/*
* Draw accelerator or cascade arrow.
*/
: TK_RELIEF_RAISED);
}
/*
* Draw check-button indicator.
*/
}
int dim, x, y;
x += DECORATION_BORDER_WIDTH;
y += DECORATION_BORDER_WIDTH;
}
}
/*
* Draw radio-button indicator.
*/
int radius;
} else {
}
}
/*
* Draw separator.
*/
points[0].x = 0;
}
/*
* Draw tear-off line.
*/
points[0].x = 0;
width = 6;
}
}
}
/*
* If the entry is disabled with a stipple rather than a special
* foreground color, generate the stippled effect.
*/
mePtr->y,
}
}
/*
* If there is extra space after the last entry in the menu,
* clear it.
*/
} else {
y = menuPtr->borderWidth;
}
if (height > 0) {
height, 0, TK_RELIEF_FLAT);
}
}
/*
*--------------------------------------------------------------
*
* GetMenuIndex --
*
* Parse a textual index into a menu and return the numerical
* index of the indicated entry.
*
* Results:
* A standard Tcl result. If all went well, then *indexPtr is
* filled in with the entry index corresponding to string
* (ranges from -1 to the number of entries in the menu minus
* one). Otherwise an error message is left in interp->result.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static int
* specified. */
char *string; /* Specification of an entry in menu. See
* manual entry for valid .*/
int lastOK; /* Non-zero means its OK to return index
* just *after* last entry. */
int *indexPtr; /* Where to store converted relief. */
{
int i, y;
return TCL_OK;
}
return TCL_OK;
}
*indexPtr = -1;
return TCL_OK;
}
if (string[0] == '@') {
for (i = 0; i < menuPtr->numEntries; i++) {
break;
}
}
if (i >= menuPtr->numEntries) {
}
*indexPtr = i;
return TCL_OK;
} else {
}
}
if (i >= menuPtr->numEntries) {
if (lastOK) {
i = menuPtr->numEntries;
} else {
}
} else if (i < 0) {
i = -1;
}
*indexPtr = i;
return TCL_OK;
}
}
for (i = 0; i < menuPtr->numEntries; i++) {
char *label;
*indexPtr = i;
return TCL_OK;
}
}
return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
* MenuEventProc --
*
* This procedure is invoked by the Tk dispatcher for various
* events on menus.
*
* Results:
* None.
*
* Side effects:
* When the window gets deleted, internal structures get
* cleaned up. When it gets exposed, it is redisplayed.
*
*--------------------------------------------------------------
*/
static void
{
}
}
}
}
}
/*
*----------------------------------------------------------------------
*
* MenuCmdDeletedProc --
*
* This procedure is invoked when a widget command is deleted. If
* the widget isn't already in the process of being destroyed,
* this command destroys it.
*
* Results:
* None.
*
* Side effects:
* The widget is destroyed.
*
*----------------------------------------------------------------------
*/
static void
{
/*
* This procedure could be invoked either because the window was
* destroyed and the command was then deleted (in which case tkwin
* is NULL) or because the command was deleted, and then this procedure
* destroys the widget.
*/
}
}
/*
*----------------------------------------------------------------------
*
* MenuNewEntry --
*
* This procedure allocates and initializes a new menu entry.
*
* Results:
* The return value is a pointer to a new menu entry structure,
* which has been malloc-ed, initialized, and entered into the
* entry array for the menu.
*
* Side effects:
* Storage gets allocated.
*
*----------------------------------------------------------------------
*/
static MenuEntry *
int index; /* Where in the menu the new entry is to
* go. */
int type; /* The type of the new entry. */
{
int i;
/*
* Create a new array of entries with an empty slot for the
* new entry.
*/
for (i = 0; i < index; i++) {
}
for ( ; i < menuPtr->numEntries; i++) {
}
if (menuPtr->numEntries != 0) {
}
menuPtr->numEntries++;
mePtr->labelLength = 0;
mePtr->accelLength = 0;
mePtr->y = 0;
mePtr->indicatorDiameter = 0;
return mePtr;
}
/*
*----------------------------------------------------------------------
*
* MenuAddOrInsert --
*
* This procedure does all of the work of the "add" and "insert"
* widget commands, allowing the code for these to be shared.
*
* Results:
* A standard Tcl return value.
*
* Side effects:
* A new menu entry is created in menuPtr.
*
*----------------------------------------------------------------------
*/
static int
* entry. */
char *indexString; /* String describing index at which
* to insert. NULL means insert at
* end. */
int argc; /* Number of elements in argv. */
char **argv; /* Arguments to command: first arg
* is type of entry, others are
* config options. */
{
if (indexString != NULL) {
return TCL_ERROR;
}
} else {
}
if (index < 0) {
(char *) NULL);
return TCL_ERROR;
}
index = 1;
}
/*
* Figure out the type of the new entry.
*/
c = argv[0][0];
&& (length >= 2)) {
&& (length >= 2)) {
&& (length >= 2)) {
} else if ((c == 'r')
} else if ((c == 's')
} else {
argv[0], "\": must be cascade, checkbutton, ",
"command, radiobutton, or separator", (char *) NULL);
return TCL_ERROR;
}
}
menuPtr->numEntries--;
return TCL_ERROR;
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* MenuVarProc --
*
* This procedure is invoked when someone changes the
* state variable associated with a radiobutton or checkbutton
* menu entry. The entry's selected state is set to match
* the value of the variable.
*
* Results:
* NULL is always returned.
*
* Side effects:
* The menu entry may become selected or deselected.
*
*--------------------------------------------------------------
*/
/* ARGSUSED */
static char *
char *name1; /* First part of variable's name. */
char *name2; /* Second part of variable's name. */
int flags; /* Describes what just happened. */
{
char *value;
/*
* If the variable is being unset, then re-establish the
* trace unless the whole interpreter is going away.
*/
if (flags & TCL_TRACE_UNSETS) {
}
return (char *) NULL;
}
/*
* Use the value of the variable to update the selected status of
* the menu entry.
*/
value = "";
}
return (char *) NULL;
}
} else {
return (char *) NULL;
}
return (char *) NULL;
}
/*
*----------------------------------------------------------------------
*
* EventuallyRedrawMenu --
*
* Arrange for an entry of a menu, or the whole menu, to be
* redisplayed at some point in the future.
*
* Results:
* None.
*
* Side effects:
* A when-idle hander is scheduled to do the redisplay, if there
* isn't one already scheduled.
*
*----------------------------------------------------------------------
*/
static void
* all the entries in the menu. */
{
int i;
return;
}
} else {
for (i = 0; i < menuPtr->numEntries; i++) {
}
}
return;
}
}
/*
*--------------------------------------------------------------
*
* PostSubmenu --
*
* This procedure arranges for a particular submenu (i.e. the
* menu corresponding to a given cascade entry) to be
* posted.
*
* Results:
* A standard Tcl return result. Errors may occur in the
* Tcl commands generated to post and unpost submenus.
*
* Side effects:
* If there is already a submenu posted, it is unposted.
* The new submenu is then posted.
*
*--------------------------------------------------------------
*/
static int
* reporting errors. */
* posted. NULL means make sure that
* no submenu is posted. */
{
int result, x, y;
return TCL_OK;
}
/*
* Note: when unposting a submenu, we have to redraw the entire
* parent menu. This is because of a combination of the following
* things:
* (a) the submenu partially overlaps the parent.
* (b) the submenu specifies "save under", which causes the X
* server to make a copy of the information under it when it
* is posted. When the submenu is unposted, the X server
* copies this data back and doesn't generate any Expose
* events for the parent.
* (c) the parent may have redisplayed itself after the submenu
* was posted, in which case the saved information is no
* longer correct.
* The simplest solution is just force a complete redisplay of
* the parent.
*/
" unpost", (char *) NULL);
return result;
}
}
/*
* Make sure that the cascaded submenu is a child of the
* parent menu.
*/
return TCL_ERROR;
}
return TCL_ERROR;
}
/*
* Position the cascade with its upper left corner slightly
* below and to the left of the upper right corner of the
* menu entry (this is an attempt to match Motif behavior).
*/
(char *) NULL);
return result;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ActivateMenuEntry --
*
* This procedure is invoked to make a particular menu entry
* the active one, deactivating any other entry that might
* currently be active.
*
* Results:
* The return value is a standard Tcl result (errors can occur
* while posting and unposting submenus).
*
* Side effects:
* Menu entries get redisplayed, and the active entry changes.
* Submenus may get posted and unposted.
*
*----------------------------------------------------------------------
*/
static int
int index; /* Index of entry to activate, or
* -1 to deactivate all entries. */
{
/*
* Don't change the state unless it's currently active (state
* might already have been changed to disabled).
*/
}
}
if (index >= 0) {
}
return result;
}
/*
*----------------------------------------------------------------------
*
* MenuImageProc --
*
* This procedure is invoked by the image code whenever the manager
* for an image does something that affects the size of contents
* of an image displayed in a menu entry.
*
* Results:
* None.
*
* Side effects:
* Arranges for the menu to get redisplayed.
*
*----------------------------------------------------------------------
*/
static void
int x, y; /* Upper left pixel (within image)
* that must be redisplayed. */
* (may be <= 0). */
{
}
}
/*
*----------------------------------------------------------------------
*
* MenuSelectImageProc --
*
* This procedure is invoked by the image code whenever the manager
* for an image does something that affects the size of contents
* of an image displayed in a menu entry when it is selected.
*
* Results:
* None.
*
* Side effects:
* Arranges for the menu to get redisplayed.
*
*----------------------------------------------------------------------
*/
static void
int x, y; /* Upper left pixel (within image)
* that must be redisplayed. */
* (may be <= 0). */
{
}
}