head	1.61;
access;
symbols
	core-8-5-9:1.41.2.5
	core-8-5-8:1.41.2.2
	macosx-cocoa-merge:1.51
	macosx-cocoa-premerge:1.51
	macosx-carbon-freeze:1.51
	core-8-5-7:1.41.2.2
	core-8-5-6:1.41
	core-8-6-b1:1.48
	core-8-6-a3:1.44
	core-8-5-5:1.41
	core-8-6-a2:1.43
	core-8-5-4:1.41
	core-8-5-3:1.41
	core-8-6-a1:1.42
	core-8-4-19:1.20.2.7
	core-8-5-branch:1.41.0.2
	core-8-5-2:1.41
	core-8-4-18:1.20.2.7
	core-8-5-1:1.41
	core-8-4-17:1.20.2.7
	core-8-5-0:1.41
	core-8-5-b3:1.40
	core-8-5-b2:1.40
	core-8-4-16:1.20.2.7
	core-8-5-b1:1.40
	core-stablilizer-merge:1.39
	core-stabilizer-branch:1.38.0.2
	core-stabilizer-merge:1.41
	core-8-4-15:1.20.2.7
	core-8-5-a6:1.38
	core-8-5-a5:1.36
	core-8-4-14:1.20.2.7
	core-8-5-a4:1.35
	core-8-4-13:1.20.2.6
	core-8-4-12:1.20.2.6
	core-8-4-11:1.20.2.5
	core-8-5-a3:1.27
	core-8-4-10:1.20.2.5
	core-8-4-9-branch:1.20.2.4.0.2
	core-8-5-a2:1.26
	core-8-4-9:1.20.2.4
	core-8-4-8:1.20.2.4
	core-8-4-7:1.20.2.2
	core-8-5-a1:1.25
	core-8-4-6:1.20.2.2
	core-8-4-5:1.20.2.1
	mistachkin-dev-branch:1.21.0.2
	core-8-4-4:1.20.2.1
	core-8-4-3:1.20
	core-8-4-branch:1.20.0.2
	core-8-4-2:1.20
	core-8-4-1:1.19
	core-8-3-5:1.6.2.4
	core-8-4-0:1.19
	macosx-8-4-merge-2002-08-31-trunk:1.19
	macosx-8-4-premerge-2002-08-31-branch:1.13.2.3
	macosx-8-4-premerge-2002-08-31-trunk:1.19
	macosx-8-4-merge-2002-08-30-branch:1.13.2.3
	macosx-8-4-merge-2002-08-30-trunk:1.19
	macosx-8-4-merge-2002-08-20-branch:1.13.2.3
	macosx-8-4-merge-2002-08-20-trunk:1.19
	core-8-4-b2:1.19
	core-8-4-b1:1.18
	macosx-premerge-6-9-02:1.13.2.1
	core-8-4-a4:1.16
	core-8-3-4:1.6.2.3
	macosx-8-4-branch:1.13.0.2
	macosx-8-4-branchpoint:1.13
	core-8-4-a3:1.11
	core-8-3-3:1.6.2.2
	dgp-privates-into-namespace:1.9.0.2
	tclpro-1-5-0:1.6.2.1
	core-8-4-win-speedup:1.8.0.2
	core-8-4-a2:1.8
	tclpro-1-4-1:1.6.2.1
	tclpro-1-4-0:1.6.2.1
	core-8-3-2:1.6.2.1
	ajuba-ajuba2-2-1-base:1.6
	ajuba-ajuba2-2-0:1.6
	core-8-4-a1:1.6
	core-8-3-1-branch:1.6.0.2
	core-8-3-1:1.6
	scriptics-sc-2-0-b5:1.6
	scriptics-sc-2-0-fixed:1.6
	scriptics-sc-2-0-b2:1.6
	scriptics-sc-2-0-b1:1.6
	core-8-3-0:1.6
	core-8-3-b2:1.5
	core-8-3-b1:1.5
	scriptics-sc-1-1:1.5
	scriptics-sc-1-1-b1:1.5
	core-8-2-3:1.5
	scriptics-sc-1-1-branch:1.5.0.10
	scriptics-sc-1-1-base:1.5
	scriptics-sc-1-0:1.5
	scriptics-sc-1-0-branch:1.5.0.8
	scriptics-sc-1-0-base:1.5
	core-8-2-2:1.5
	core-8-2-1:1.5
	scriptics-bc-1-0-b1:1.5
	core-8-2-1-branch:1.5.0.6
	scriptics-tclpro-1-3-0:1.5
	core-8-2-0:1.5
	core-8-2-b3-branch:1.5.0.2
	core-8-2-b3-base:1.5
	scriptics-tclpro-1-3-b4:1.5
	core-8-2-b2:1.5
	scriptics-tclpro-1-3-b3:1.5
	core-8-2-b1:1.5
	scriptics-tclpro-1-3-b2:1.5
	merge-to-mainline-5/21/99:1.5
	scriptics-tclpro-1-3-b2-branch:1.5.0.4
	core-8-1-1:1.5
	scriptics-tclpro-1-3-b1:1.5
	core-8-1-1-base:1.5
	core-8-1-0:1.5
	merge-to-mainline-4-29-99:1.5
	merge-to-mainline-4-23-99:1.5
	core-8-1-branch-old:1.1.0.4
	core-8-0-6-branch:1.2.0.6
	core-8-0-6-base:1.2
	core-8-0-5:1.2
	core-8-1-b3:1.1.4.8
	core-8-1-b2:1.1.4.8
	dev-8-1-stubs-branch:1.1.4.7.0.2
	dev-stubs-branch:1.2.0.4
	scriptics-tclpro-1-2:1.2
	scriptics-tclpro-1-2-b2:1.2
	core-8-1-merge-2/10/99:1.2
	core-8-0-5-branch:1.2.0.2
	core-8-0-5-base:1.2
	scriptics-tclpro-1-2-b1:1.2
	scriptics-tclpro-1-2-a1:1.2
	core-8-1-b1:1.1.4.5
	core-8-0-4:1.2
	core-8-1-a2:1.1.4.1
	core-8-0-2:1.1
	core-8-0-3:1.2;
locks; strict;
comment	@ * @;


1.61
date	2010.11.19.14.48.00;	author nijtmans;	state Exp;
branches;
next	1.60;

1.60
date	2010.05.10.20.58.18;	author nijtmans;	state Exp;
branches;
next	1.59;

1.59
date	2010.02.17.20.58.32;	author jenglish;	state Exp;
branches;
next	1.58;

1.58
date	2010.01.18.20.43.38;	author nijtmans;	state Exp;
branches;
next	1.57;

1.57
date	2010.01.13.23.08.09;	author nijtmans;	state Exp;
branches;
next	1.56;

1.56
date	2010.01.05.09.40.46;	author dkf;	state Exp;
branches;
next	1.55;

1.55
date	2010.01.02.22.52.38;	author dkf;	state Exp;
branches;
next	1.54;

1.54
date	2009.12.30.00.24.27;	author patthoyts;	state Exp;
branches;
next	1.53;

1.53
date	2009.12.09.10.45.30;	author dkf;	state Exp;
branches;
next	1.52;

1.52
date	2009.09.07.07.29.04;	author das;	state Exp;
branches;
next	1.51;

1.51
date	2009.04.10.16.16.02;	author das;	state Exp;
branches;
next	1.50;

1.50
date	2009.02.06.08.12.07;	author das;	state Exp;
branches;
next	1.49;

1.49
date	2009.01.14.22.48.10;	author nijtmans;	state Exp;
branches;
next	1.48;

1.48
date	2008.11.27.23.26.05;	author nijtmans;	state Exp;
branches;
next	1.47;

1.47
date	2008.11.08.22.52.29;	author dkf;	state Exp;
branches;
next	1.46;

1.46
date	2008.10.30.23.18.59;	author nijtmans;	state Exp;
branches;
next	1.45;

1.45
date	2008.10.17.23.18.37;	author nijtmans;	state Exp;
branches;
next	1.44;

1.44
date	2008.10.05.18.22.21;	author dkf;	state Exp;
branches;
next	1.43;

1.43
date	2008.07.23.23.24.23;	author nijtmans;	state Exp;
branches;
next	1.42;

1.42
date	2008.04.27.22.38.56;	author dkf;	state Exp;
branches;
next	1.41;

1.41
date	2007.12.13.15.24.15;	author dgp;	state Exp;
branches
	1.41.2.1;
next	1.40;

1.40
date	2007.09.07.00.34.53;	author dgp;	state Exp;
branches;
next	1.39;

1.39
date	2007.06.24.16.07.35;	author dkf;	state Exp;
branches;
next	1.38;

1.38
date	2007.01.03.05.06.26;	author nijtmans;	state Exp;
branches
	1.38.2.1;
next	1.37;

1.37
date	2006.12.04.15.16.30;	author dkf;	state Exp;
branches;
next	1.36;

1.36
date	2006.05.25.23.50.16;	author hobbs;	state Exp;
branches;
next	1.35;

1.35
date	2006.04.05.20.59.03;	author hobbs;	state Exp;
branches;
next	1.34;

1.34
date	2005.11.27.02.36.14;	author das;	state Exp;
branches;
next	1.33;

1.33
date	2005.11.17.16.21.55;	author dkf;	state Exp;
branches;
next	1.32;

1.32
date	2005.11.17.10.57.35;	author dkf;	state Exp;
branches;
next	1.31;

1.31
date	2005.10.12.09.43.37;	author dkf;	state Exp;
branches;
next	1.30;

1.30
date	2005.10.12.09.29.21;	author dkf;	state Exp;
branches;
next	1.29;

1.29
date	2005.10.10.20.26.31;	author hobbs;	state Exp;
branches;
next	1.28;

1.28
date	2005.10.10.19.28.27;	author hobbs;	state Exp;
branches;
next	1.27;

1.27
date	2005.05.31.05.11.40;	author hobbs;	state Exp;
branches;
next	1.26;

1.26
date	2004.09.16.20.06.33;	author hobbs;	state Exp;
branches;
next	1.25;

1.25
date	2004.01.13.02.06.00;	author davygrvy;	state Exp;
branches;
next	1.24;

1.24
date	2003.12.21.23.50.13;	author davygrvy;	state Exp;
branches;
next	1.23;

1.23
date	2003.12.03.16.38.23;	author dkf;	state Exp;
branches;
next	1.22;

1.22
date	2003.12.03.04.58.09;	author hobbs;	state Exp;
branches;
next	1.21;

1.21
date	2003.05.30.11.03.00;	author vincentdarley;	state Exp;
branches;
next	1.20;

1.20
date	2003.02.26.02.32.56;	author hobbs;	state Exp;
branches
	1.20.2.1;
next	1.19;

1.19
date	2002.08.05.04.30.40;	author dgp;	state Exp;
branches;
next	1.18;

1.18
date	2002.04.12.07.28.06;	author hobbs;	state Exp;
branches;
next	1.17;

1.17
date	2002.03.20.22.55.16;	author dgp;	state Exp;
branches;
next	1.16;

1.16
date	2002.01.31.21.05.27;	author uid38226;	state Exp;
branches;
next	1.15;

1.15
date	2002.01.25.21.09.37;	author dgp;	state Exp;
branches;
next	1.14;

1.14
date	2002.01.17.05.13.11;	author dgp;	state Exp;
branches;
next	1.13;

1.13
date	2001.10.12.13.30.31;	author tmh;	state Exp;
branches
	1.13.2.1;
next	1.12;

1.12
date	2001.09.14.20.35.58;	author andreas_kupries;	state Exp;
branches;
next	1.11;

1.11
date	2001.08.01.16.21.11;	author dgp;	state Exp;
branches;
next	1.10;

1.10
date	2001.04.03.06.54.33;	author hobbs;	state Exp;
branches;
next	1.9;

1.9
date	2000.11.22.01.49.38;	author ericm;	state Exp;
branches
	1.9.2.1;
next	1.8;

1.8
date	2000.08.03.20.36.16;	author ericm;	state Exp;
branches
	1.8.2.1;
next	1.7;

1.7
date	2000.06.27.17.15.58;	author ericm;	state Exp;
branches;
next	1.6;

1.6
date	2000.02.10.08.52.35;	author hobbs;	state Exp;
branches
	1.6.2.1;
next	1.5;

1.5
date	99.04.21.21.53.26;	author rjohnson;	state Exp;
branches;
next	1.4;

1.4
date	99.04.16.18.30.28;	author surles;	state Exp;
branches;
next	1.3;

1.3
date	99.04.16.01.51.19;	author stanton;	state Exp;
branches
	1.3.2.1;
next	1.2;

1.2
date	98.09.14.18.23.14;	author stanton;	state Exp;
branches;
next	1.1;

1.1
date	98.04.01.09.52.00;	author rjohnson;	state Exp;
branches
	1.1.4.1;
next	;

1.1.4.1
date	98.09.29.00.25.22;	author stanton;	state Exp;
branches;
next	1.1.4.2;

1.1.4.2
date	98.09.30.02.17.08;	author stanton;	state Exp;
branches;
next	1.1.4.3;

1.1.4.3
date	98.11.24.21.42.39;	author stanton;	state Exp;
branches;
next	1.1.4.4;

1.1.4.4
date	98.11.25.22.36.50;	author stanton;	state Exp;
branches;
next	1.1.4.5;

1.1.4.5
date	98.12.04.07.21.20;	author welch;	state Exp;
branches;
next	1.1.4.6;

1.1.4.6
date	99.02.11.04.13.46;	author stanton;	state Exp;
branches;
next	1.1.4.7;

1.1.4.7
date	99.03.09.01.51.26;	author lfb;	state Exp;
branches
	1.1.4.7.2.1;
next	1.1.4.8;

1.1.4.8
date	99.03.10.07.13.44;	author stanton;	state Exp;
branches;
next	;

1.1.4.7.2.1
date	99.03.09.17.50.35;	author redman;	state Exp;
branches;
next	;

1.3.2.1
date	99.04.21.02.31.52;	author rjohnson;	state Exp;
branches;
next	;

1.6.2.1
date	2000.08.05.23.53.12;	author hobbs;	state Exp;
branches;
next	1.6.2.2;

1.6.2.2
date	2001.04.04.07.57.17;	author hobbs;	state Exp;
branches;
next	1.6.2.3;

1.6.2.3
date	2001.09.14.20.39.23;	author andreas_kupries;	state Exp;
branches;
next	1.6.2.4;

1.6.2.4
date	2002.01.31.21.08.19;	author uid38226;	state Exp;
branches;
next	;

1.8.2.1
date	2002.04.02.21.00.53;	author hobbs;	state Exp;
branches;
next	;

1.9.2.1
date	2001.02.28.23.29.55;	author dgp;	state Exp;
branches;
next	1.9.2.2;

1.9.2.2
date	2001.07.03.20.01.08;	author dgp;	state Exp;
branches;
next	;

1.13.2.1
date	2002.02.05.02.25.15;	author wolfsuit;	state Exp;
branches;
next	1.13.2.2;

1.13.2.2
date	2002.06.10.05.38.23;	author wolfsuit;	state Exp;
branches;
next	1.13.2.3;

1.13.2.3
date	2002.08.20.20.27.05;	author das;	state Exp;
branches;
next	;

1.20.2.1
date	2003.07.15.13.59.06;	author vincentdarley;	state Exp;
branches;
next	1.20.2.2;

1.20.2.2
date	2003.12.03.04.57.37;	author hobbs;	state Exp;
branches;
next	1.20.2.3;

1.20.2.3
date	2004.09.16.20.05.44;	author hobbs;	state Exp;
branches;
next	1.20.2.4;

1.20.2.4
date	2004.10.27.00.37.38;	author davygrvy;	state Exp;
branches;
next	1.20.2.5;

1.20.2.5
date	2005.05.31.05.05.35;	author hobbs;	state Exp;
branches;
next	1.20.2.6;

1.20.2.6
date	2005.11.27.02.44.25;	author das;	state Exp;
branches;
next	1.20.2.7;

1.20.2.7
date	2006.05.25.23.51.37;	author hobbs;	state Exp;
branches;
next	1.20.2.8;

1.20.2.8
date	2009.02.06.08.14.29;	author das;	state Exp;
branches;
next	1.20.2.9;

1.20.2.9
date	2010.02.17.20.57.03;	author jenglish;	state Exp;
branches;
next	;

1.38.2.1
date	2007.06.25.19.12.13;	author dgp;	state Exp;
branches;
next	1.38.2.2;

1.38.2.2
date	2007.09.07.01.25.35;	author dgp;	state Exp;
branches;
next	;

1.41.2.1
date	2009.02.06.08.13.23;	author das;	state Exp;
branches;
next	1.41.2.2;

1.41.2.2
date	2009.04.10.16.16.04;	author das;	state Exp;
branches;
next	1.41.2.3;

1.41.2.3
date	2009.12.30.00.29.38;	author patthoyts;	state Exp;
branches;
next	1.41.2.4;

1.41.2.4
date	2010.01.05.09.44.54;	author dkf;	state Exp;
branches;
next	1.41.2.5;

1.41.2.5
date	2010.02.17.20.58.01;	author jenglish;	state Exp;
branches;
next	;


desc
@@


1.61
log
@Revise Tcl_Panic() calls ending with a newline removing the newline, because Tcl_Panic() outputs a final newline already
@
text
@/*
 * tkMenu.c --
 *
 * This file contains most of the code for implementing menus in Tk. It takes
 * care of all of the generic (platform-independent) parts of menus, and is
 * supplemented by platform-specific files. The geometry calculation and
 * drawing code for menus is in the file tkMenuDraw.c
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @@(#) $Id: tkMenu.c,v 1.60 2010/05/10 20:58:18 nijtmans Exp $
 */

/*
 * Notes on implementation of menus:
 *
 * Menus can be used in three ways:
 * - as a popup menu, either as part of a menubutton or standalone.
 * - as a menubar. The menu's cascade items are arranged according to the
 *   specific platform to provide the user access to the menus at all times
 * - as a tearoff palette. This is a window with the menu's items in it.
 *
 * The goal is to provide the Tk developer with a way to use a common set of
 * menus for all of these tasks.
 *
 * In order to make the bindings for cascade menus work properly under Unix,
 * the cascade menus' pathnames must be proper children of the menu that they
 * are cascade from. So if there is a menu .m, and it has two cascades
 * labelled "File" and "Edit", the cascade menus might have the pathnames
 * .m.file and .m.edit. Another constraint is that the menus used for menubars
 * must be children of the toplevel widget that they are attached to. And on
 * the Macintosh, the platform specific menu handle for cascades attached to a
 * menu bar must have a title that matches the label for the cascade menu.
 *
 * To handle all of the constraints, Tk menubars and tearoff menus are
 * implemented using menu clones. Menu clones are full menus in their own
 * right; they have a Tk window and pathname associated with them; they have a
 * TkMenu structure and array of entries. However, they are linked with the
 * original menu that they were cloned from. The reflect the attributes of the
 * original, or "master", menu. So if an item is added to a menu, and that
 * menu has clones, then the item must be added to all of its clones also.
 * Menus are cloned when a menu is torn-off or when a menu is assigned as a
 * menubar using the "-menu" option of the toplevel's pathname configure
 * subcommand. When a clone is destroyed, only the clone is destroyed, but
 * when the master menu is destroyed, all clones are also destroyed. This
 * allows the developer to just deal with one set of menus when creating and
 * destroying.
 *
 * Clones are rather tricky when a menu with cascade entries is cloned (such
 * as a menubar). Not only does the menu have to be cloned, but each cascade
 * entry's corresponding menu must also be cloned. This maintains the pathname
 * parent-child hierarchy necessary for menubars and toplevels to work. This
 * leads to several special cases:
 *
 * 1. When a new menu is created, and it is pointed to by cascade entries in
 * cloned menus, the new menu has to be cloned to parallel the cascade
 * structure.
 * 2. When a cascade item is added to a menu that has been cloned, and the
 * menu that the cascade item points to exists, that menu has to be cloned.
 * 3. When the menu that a cascade entry points to is changed, the old cloned
 * cascade menu has to be discarded, and the new one has to be cloned.
 */

#if 0

/*
 * used only to test for old config code
 */

#define __NO_OLD_CONFIG
#endif

#include "tkInt.h"
#include "tkMenu.h"

#define MENU_HASH_KEY "tkMenus"

typedef struct ThreadSpecificData {
    int menusInitialized;	/* Flag indicates whether thread-specific
				 * elements of the Windows Menu module have
				 * been initialized. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following flag indicates whether the process-wide state for the Menu
 * module has been intialized. The Mutex protects access to that flag.
 */

static int menusInitialized;
TCL_DECLARE_MUTEX(menuMutex)

/*
 * Configuration specs for individual menu entries. If this changes, be sure
 * to update code in TkpMenuInit that changes the font string entry.
 */

static const char *const menuStateStrings[] = {"active", "normal", "disabled", NULL};

static const char *const menuEntryTypeStrings[] = {
    "cascade", "checkbutton", "command", "radiobutton", "separator", NULL
};

/*
 * The following table defines the legal values for the -compound option. It
 * is used with the "enum compound" declaration in tkMenu.h
 */

static const char *const compoundStrings[] = {
    "bottom", "center", "left", "none", "right", "top", NULL
};

static const Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", NULL, NULL,
	DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1,
	TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_COLOR, "-activeforeground", NULL, NULL,
	DEF_MENU_ENTRY_ACTIVE_FG,
	Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-accelerator", NULL, NULL,
	DEF_MENU_ENTRY_ACCELERATOR,
	Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BITMAP, "-bitmap", NULL, NULL,
	DEF_MENU_ENTRY_BITMAP,
	Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BOOLEAN, "-columnbreak", NULL, NULL,
	DEF_MENU_ENTRY_COLUMN_BREAK,
	-1, Tk_Offset(TkMenuEntry, columnBreak), 0, NULL, 0},
    {TK_OPTION_STRING, "-command", NULL, NULL,
	DEF_MENU_ENTRY_COMMAND,
	Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
	(ClientData) compoundStrings, 0},
    {TK_OPTION_FONT, "-font", NULL, NULL,
	DEF_MENU_ENTRY_FONT,
	Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_COLOR, "-foreground", NULL, NULL,
	DEF_MENU_ENTRY_FG,
	Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BOOLEAN, "-hidemargin", NULL, NULL,
	DEF_MENU_ENTRY_HIDE_MARGIN,
	-1, Tk_Offset(TkMenuEntry, hideMargin), 0, NULL, 0},
    {TK_OPTION_STRING, "-image", NULL, NULL,
	DEF_MENU_ENTRY_IMAGE,
	Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-label", NULL, NULL,
	DEF_MENU_ENTRY_LABEL,
	Tk_Offset(TkMenuEntry, labelPtr), -1, 0, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-state", NULL, NULL,
	DEF_MENU_ENTRY_STATE,
	-1, Tk_Offset(TkMenuEntry, state), 0,
	(ClientData) menuStateStrings, 0},
    {TK_OPTION_INT, "-underline", NULL, NULL,
	DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline), 0, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

static const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

static const Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
    {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL,
	DEF_MENU_ENTRY_INDICATOR,
	-1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0},
    {TK_OPTION_STRING, "-offvalue", NULL, NULL,
	DEF_MENU_ENTRY_OFF_VALUE,
	Tk_Offset(TkMenuEntry, offValuePtr), -1, 0, NULL, 0},
    {TK_OPTION_STRING, "-onvalue", NULL, NULL,
	DEF_MENU_ENTRY_ON_VALUE,
	Tk_Offset(TkMenuEntry, onValuePtr), -1, 0, NULL, 0},
    {TK_OPTION_COLOR, "-selectcolor", NULL, NULL,
	DEF_MENU_ENTRY_SELECT,
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-selectimage", NULL, NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE,
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-variable", NULL, NULL,
	DEF_MENU_ENTRY_CHECK_VARIABLE,
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs, 0}
};

static const Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
    {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL,
	DEF_MENU_ENTRY_INDICATOR,
	-1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0},
    {TK_OPTION_COLOR, "-selectcolor", NULL, NULL,
	DEF_MENU_ENTRY_SELECT,
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-selectimage", NULL, NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE,
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-value", NULL, NULL,
	DEF_MENU_ENTRY_VALUE,
	Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-variable", NULL, NULL,
	DEF_MENU_ENTRY_RADIO_VARIABLE,
	Tk_Offset(TkMenuEntry, namePtr), -1, 0, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs, 0}
};

static const Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
    {TK_OPTION_STRING, "-menu", NULL, NULL,
	DEF_MENU_ENTRY_MENU,
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs, 0}
};

static const Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-state", NULL, NULL,
	DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0,
	(ClientData) menuStateStrings, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

static const Tk_OptionSpec *specsArray[] = {
    tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,
    tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,
    tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs
};

/*
 * Menu type strings for use with Tcl_GetIndexFromObj.
 */

static const char *const menuTypeStrings[] = {
    "normal", "tearoff", "menubar", NULL
};

static const Tk_OptionSpec tkMenuConfigSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground",
	"Foreground", DEF_MENU_ACTIVE_BG_COLOR,
	Tk_Offset(TkMenu, activeBorderPtr), -1, 0,
	(ClientData) DEF_MENU_ACTIVE_BG_MONO, 0},
    {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
	"BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
	Tk_Offset(TkMenu, activeBorderWidthPtr), -1, 0, NULL, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground",
	"Background", DEF_MENU_ACTIVE_FG_COLOR,
	Tk_Offset(TkMenu, activeFgPtr), -1, 0,
	(ClientData) DEF_MENU_ACTIVE_FG_MONO, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0,
	(ClientData) DEF_MENU_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, (ClientData) "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_MENU_BORDER_WIDTH,
	Tk_Offset(TkMenu, borderWidthPtr), -1, 0, NULL, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_MENU_CURSOR,
	Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_MENU_DISABLED_FG_COLOR,
	Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK,
	(ClientData) DEF_MENU_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", NULL, NULL,
	NULL, 0, -1, 0, (ClientData) "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1, 0, NULL, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1, 0, NULL, 0},
    {TK_OPTION_STRING, "-postcommand", "postCommand", "Command",
	DEF_MENU_POST_COMMAND,
	Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1, 0, NULL, 0},
    {TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background",
	DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0,
	(ClientData) DEF_MENU_SELECT_MONO, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_MENU_TAKE_FOCUS,
	Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff",
	DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff), 0, NULL, 0},
    {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand",
	"TearOffCommand", DEF_MENU_TEAROFF_CMD,
	Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-title", "title", "Title",
	DEF_MENU_TITLE,	 Tk_Offset(TkMenu, titlePtr), -1,
	TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-type", "type", "Type",
	DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK,
	(ClientData) menuTypeStrings, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

/*
 * Command line options. Put here because MenuCmd has to look at them along
 * with MenuWidgetObjCmd.
 */

static const char *const menuOptions[] = {
    "activate", "add", "cget", "clone", "configure", "delete", "entrycget",
    "entryconfigure", "index", "insert", "invoke", "post", "postcascade",
    "type", "unpost", "xposition", "yposition", NULL
};
enum options {
    MENU_ACTIVATE, MENU_ADD, MENU_CGET, MENU_CLONE, MENU_CONFIGURE,
    MENU_DELETE, MENU_ENTRYCGET, MENU_ENTRYCONFIGURE, MENU_INDEX,
    MENU_INSERT, MENU_INVOKE, MENU_POST, MENU_POSTCASCADE, MENU_TYPE,
    MENU_UNPOST, MENU_XPOSITION, MENU_YPOSITION
};

/*
 * Prototypes for static functions in this file:
 */

static int		CloneMenu(TkMenu *menuPtr, Tcl_Obj *newMenuName,
			    Tcl_Obj *newMenuTypeString);
static int		ConfigureMenu(Tcl_Interp *interp, TkMenu *menuPtr,
			    int objc, Tcl_Obj *const objv[]);
static int		ConfigureMenuCloneEntries(Tcl_Interp *interp,
			    TkMenu *menuPtr, int index,
			    int objc, Tcl_Obj *const objv[]);
static int		ConfigureMenuEntry(TkMenuEntry *mePtr,
			    int objc, Tcl_Obj *const objv[]);
static void		DeleteMenuCloneEntries(TkMenu *menuPtr,
			    int first, int last);
static void		DestroyMenuHashTable(ClientData clientData,
			    Tcl_Interp *interp);
static void		DestroyMenuInstance(TkMenu *menuPtr);
static void		DestroyMenuEntry(char *memPtr);
static int		GetIndexFromCoords(Tcl_Interp *interp,
			    TkMenu *menuPtr, const char *string,
			    int *indexPtr);
static int		MenuDoYPosition(Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *objPtr);
static int		MenuDoXPosition(Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *objPtr);
static int		MenuAddOrInsert(Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc,
			    Tcl_Obj *const objv[]);
static int		MenuCmd(ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static void		MenuCmdDeletedProc(ClientData clientData);
static TkMenuEntry *	MenuNewEntry(TkMenu *menuPtr, int index, int type);
static char *		MenuVarProc(ClientData clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static int		MenuWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		MenuWorldChanged(ClientData instanceData);
static int		PostProcessEntry(TkMenuEntry *mePtr);
static void		RecursivelyDeleteMenu(TkMenu *menuPtr);
static void		UnhookCascadeEntry(TkMenuEntry *mePtr);
static void		TkMenuCleanup(ClientData unused);

/*
 * The structure below is a list of procs that respond to certain window
 * manager events. One of these includes a font change, which forces the
 * geometry proc to be called.
 */

static const Tk_ClassProcs menuClass = {
    sizeof(Tk_ClassProcs),	/* size */
    MenuWorldChanged,		/* worldChangedProc */
    NULL,					/* createProc */
    NULL					/* modalProc */
};

/*
 *--------------------------------------------------------------
 *
 * TkCreateMenuCmd --
 *
 *	Called by Tk at initialization time to create the menu command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

static void
FreeOptionTables(
    ClientData clientData,
    Tcl_Interp *interp)
{
    ckfree(clientData);
}

int
TkCreateMenuCmd(
    Tcl_Interp *interp)		/* Interpreter we are creating the command
				 * in. */
{
    TkMenuOptionTables *optionTablesPtr = (TkMenuOptionTables *)
	    ckalloc(sizeof(TkMenuOptionTables));

    optionTablesPtr->menuOptionTable =
	    Tk_CreateOptionTable(interp, tkMenuConfigSpecs);
    optionTablesPtr->entryOptionTables[TEAROFF_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[TEAROFF_ENTRY]);
    optionTablesPtr->entryOptionTables[COMMAND_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[COMMAND_ENTRY]);
    optionTablesPtr->entryOptionTables[CASCADE_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[CASCADE_ENTRY]);
    optionTablesPtr->entryOptionTables[SEPARATOR_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[SEPARATOR_ENTRY]);
    optionTablesPtr->entryOptionTables[RADIO_BUTTON_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[RADIO_BUTTON_ENTRY]);
    optionTablesPtr->entryOptionTables[CHECK_BUTTON_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[CHECK_BUTTON_ENTRY]);

    Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr, 0);
    Tcl_CallWhenDeleted(interp, FreeOptionTables, optionTablesPtr);

    if (Tcl_IsSafe(interp)) {
	Tcl_HideCommand(interp, "menu", "menu");
    }

    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * MenuCmd --
 *
 *	This function 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.
 *
 *--------------------------------------------------------------
 */

static int
MenuCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    Tk_Window tkwin = Tk_MainWindow(interp);
    Tk_Window newWin;
    register TkMenu *menuPtr;
    TkMenuReferences *menuRefPtr;
    int i, index, toplevel;
    const char *windowName;
    static const char *const typeStringList[] = {"-type", NULL};
    TkMenuOptionTables *optionTablesPtr = clientData;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    TkMenuInit();

    toplevel = 1;
    for (i = 2; i < (objc - 1); i++) {
	if (Tcl_GetIndexFromObj(NULL, objv[i], typeStringList, NULL, 0,
		&index) != TCL_ERROR) {
	    if ((Tcl_GetIndexFromObj(NULL, objv[i + 1], menuTypeStrings, NULL,
		    0, &index) == TCL_OK) && (index == MENUBAR)) {
		toplevel = 0;
	    }
	    break;
	}
    }

    windowName = Tcl_GetString(objv[1]);
    newWin = Tk_CreateWindowFromPath(interp, tkwin, windowName,
	    toplevel ? "" : NULL);
    if (newWin == NULL) {
	return TCL_ERROR;
    }

    /*
     * Initialize the data structure for the menu. Note that the menuPtr is
     * eventually freed in 'TkMenuEventProc' in tkMenuDraw.c, when
     * Tcl_EventuallyFree is called.
     */

    menuPtr = (TkMenu *) ckalloc(sizeof(TkMenu));
    memset(menuPtr, 0, sizeof(TkMenu));
    menuPtr->tkwin = newWin;
    menuPtr->display = Tk_Display(newWin);
    menuPtr->interp = interp;
    menuPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, menuPtr,
	    MenuCmdDeletedProc);
    menuPtr->active = -1;
    menuPtr->cursorPtr = None;
    menuPtr->masterMenuPtr = menuPtr;
    menuPtr->menuType = UNKNOWN_TYPE;
    menuPtr->optionTablesPtr = optionTablesPtr;
    TkMenuInitializeDrawingFields(menuPtr);

    Tk_SetClass(menuPtr->tkwin, "Menu");
    Tk_SetClassProcs(menuPtr->tkwin, &menuClass, menuPtr);
    Tk_CreateEventHandler(newWin,
	    ExposureMask|StructureNotifyMask|ActivateMask,
	    TkMenuEventProc, menuPtr);
    if (Tk_InitOptions(interp, (char *) menuPtr,
	    menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin)
	    != TCL_OK) {
    	Tk_DestroyWindow(menuPtr->tkwin);
    	return TCL_ERROR;
    }


    menuRefPtr = TkCreateMenuReferences(menuPtr->interp,
	    Tk_PathName(menuPtr->tkwin));
    menuRefPtr->menuPtr = menuPtr;
    menuPtr->menuRefPtr = menuRefPtr;
    if (TCL_OK != TkpNewMenu(menuPtr)) {
    	Tk_DestroyWindow(menuPtr->tkwin);
    	return TCL_ERROR;
    }

    if (ConfigureMenu(interp, menuPtr, objc - 2, objv + 2) != TCL_OK) {
    	Tk_DestroyWindow(menuPtr->tkwin);
    	return TCL_ERROR;
    }

    /*
     * If a menu has a parent menu pointing to it as a cascade entry, the
     * parent menu needs to be told that this menu now exists so that the
     * platform-part of the menu is correctly updated.
     *
     * If a menu has an instance and has cascade entries, then each cascade
     * menu must also have a parallel instance. This is especially true on the
     * Mac, where each menu has to have a separate title everytime it is in a
     * menubar. For instance, say you have a menu .m1 with a cascade entry for
     * .m2, where .m2 does not exist yet. You then put .m1 into a menubar.
     * This creates a menubar instance for .m1, but since .m2 is not there,
     * nothing else happens. When we go to create .m2, we hook it up properly
     * with .m1. However, we now need to clone .m2 and assign the clone of .m2
     * to be the cascade entry for the clone of .m1. This is special case #1
     * listed in the introductory comment.
     */

    if (menuRefPtr->parentEntryPtr != NULL) {
	TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr;
	TkMenuEntry *nextCascadePtr;
	Tcl_Obj *newMenuName, *newObjv[2];

	while (cascadeListPtr != NULL) {
	    nextCascadePtr = cascadeListPtr->nextCascadePtr;

     	    /*
	     * If we have a new master menu, and an existing cloned menu
	     * points to this menu in a cascade entry, we have to clone the
	     * new menu and point the entry to the clone instead of the menu
	     * we are creating. Otherwise, ConfigureMenuEntry will hook up the
	     * platform-specific cascade linkages now that the menu we are
	     * creating exists.
     	     */

     	    if ((menuPtr->masterMenuPtr != menuPtr)
     	    	    || ((menuPtr->masterMenuPtr == menuPtr)
     	    	    && ((cascadeListPtr->menuPtr->masterMenuPtr
		    == cascadeListPtr->menuPtr)))) {
		newObjv[0] = Tcl_NewStringObj("-menu", -1);
		newObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin),-1);
		Tcl_IncrRefCount(newObjv[0]);
		Tcl_IncrRefCount(newObjv[1]);
     	    	ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
		Tcl_DecrRefCount(newObjv[0]);
		Tcl_DecrRefCount(newObjv[1]);
     	    } else {
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
		Tcl_Obj *windowNamePtr = Tcl_NewStringObj(
			Tk_PathName(cascadeListPtr->menuPtr->tkwin), -1);

		Tcl_IncrRefCount(normalPtr);
		Tcl_IncrRefCount(windowNamePtr);
		newMenuName = TkNewMenuName(menuPtr->interp,
     	    		windowNamePtr, menuPtr);
		Tcl_IncrRefCount(newMenuName);
		CloneMenu(menuPtr, newMenuName, normalPtr);

		/*
		 * Now we can set the new menu instance to be the cascade
		 * entry of the parent's instance.
		 */

		newObjv[0] = Tcl_NewStringObj("-menu", -1);
		newObjv[1] = newMenuName;
		Tcl_IncrRefCount(newObjv[0]);
		ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
		Tcl_DecrRefCount(normalPtr);
		Tcl_DecrRefCount(newObjv[0]);
		Tcl_DecrRefCount(newObjv[1]);
		Tcl_DecrRefCount(windowNamePtr);
	    }
	    cascadeListPtr = nextCascadePtr;
	}
    }

    /*
     * If there already exist toplevel widgets that refer to this menu, find
     * them and notify them so that they can reconfigure their geometry to
     * reflect the menu.
     */

    if (menuRefPtr->topLevelListPtr != NULL) {
    	TkMenuTopLevelList *topLevelListPtr = menuRefPtr->topLevelListPtr;
    	TkMenuTopLevelList *nextPtr;
    	Tk_Window listtkwin;

	while (topLevelListPtr != NULL) {
    	    /*
    	     * Need to get the next pointer first. TkSetWindowMenuBar changes
    	     * the list, so that the next pointer is different after calling
    	     * it.
    	     */

    	    nextPtr = topLevelListPtr->nextPtr;
    	    listtkwin = topLevelListPtr->tkwin;
    	    TkSetWindowMenuBar(menuPtr->interp, listtkwin,
    	    	    Tk_PathName(menuPtr->tkwin), Tk_PathName(menuPtr->tkwin));
    	    topLevelListPtr = nextPtr;
    	}
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(menuPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * MenuWidgetObjCmd --
 *
 *	This function 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
MenuWidgetObjCmd(
    ClientData clientData,	/* Information about menu widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    register TkMenu *menuPtr = clientData;
    register TkMenuEntry *mePtr;
    int result = TCL_OK;
    int option;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], menuOptions, "option", 0,
	    &option) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_Preserve(menuPtr);

    switch ((enum options) option) {
    case MENU_ACTIVATE: {
	int index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (menuPtr->active == index) {
	    goto done;
	}
	if ((index >= 0) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY)
		|| (menuPtr->entries[index]->state == ENTRY_DISABLED))) {
	    index = -1;
	}
	result = TkActivateMenuEntry(menuPtr, index);
	break;
    }
    case MENU_ADD:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "type ?-option value ...?");
	    goto error;
	}

	if (MenuAddOrInsert(interp, menuPtr, NULL, objc-2, objv+2) != TCL_OK){
	    goto error;
	}
	break;
    case MENU_CGET: {
	Tcl_Obj *resultPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    goto error;
	}
	resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr,
		menuPtr->optionTablesPtr->menuOptionTable, objv[2],
		menuPtr->tkwin);
	if (resultPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, resultPtr);
	break;
    }
    case MENU_CLONE:
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "newMenuName ?menuType?");
	    goto error;
	}
	result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);
	break;
    case MENU_CONFIGURE: {
	Tcl_Obj *resultPtr;

	if (objc == 2) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
		    menuPtr->optionTablesPtr->menuOptionTable, NULL,
		    menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else if (objc == 3) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
		    menuPtr->optionTablesPtr->menuOptionTable, objv[2],
		    menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else {
	    result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
	}
	if (result != TCL_OK) {
	    goto error;
	}
	break;
    }
    case MENU_DELETE: {
	int first, last;

	if ((objc != 3) && (objc != 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "first ?last?");
	    goto error;
	}

	/*
	 * If 'first' explicitly refers to past the end of the menu, we don't
	 * do anything. [Bug 220950]
	 */

	if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))
		&& Tcl_GetIntFromObj(NULL, objv[2], &first) == TCL_OK) {
	    if (first >= menuPtr->numEntries) {
		goto done;
	    }
	} else if (TkGetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){
	    goto error;
	}
	if (objc == 3) {
	    last = first;
	} else if (TkGetMenuIndex(interp,menuPtr,objv[3],0,&last) != TCL_OK) {
	    goto error;
	}

	if (menuPtr->tearoff && (first == 0)) {
	    /*
	     * Sorry, can't delete the tearoff entry; must reconfigure the
	     * menu.
	     */

	    first = 1;
	}
	if ((first < 0) || (last < first)) {
	    goto done;
	}
	DeleteMenuCloneEntries(menuPtr, first, last);
	break;
    }
    case MENU_ENTRYCGET: {
	int index;
	Tcl_Obj *resultPtr;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index option");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	Tcl_Preserve(mePtr);
	resultPtr = Tk_GetOptionValue(interp, (char *) mePtr,
		mePtr->optionTable, objv[3], menuPtr->tkwin);
	Tcl_Release(mePtr);
	if (resultPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, resultPtr);
	break;
    }
    case MENU_ENTRYCONFIGURE: {
	int index;
	Tcl_Obj *resultPtr;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index ?-option value ...?");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	Tcl_Preserve(mePtr);
	if (objc == 3) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
		    mePtr->optionTable, NULL, menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else if (objc == 4) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
		    mePtr->optionTable, objv[3], menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else {
	    result = ConfigureMenuCloneEntries(interp, menuPtr, index,
		    objc-3, objv+3);
	}
	Tcl_Release(mePtr);
	break;
    }
    case MENU_INDEX: {
	int index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    Tcl_SetResult(interp, "none", TCL_STATIC);
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	}
	break;
    }
    case MENU_INSERT:
	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "index type ?-option value ...?");
	    goto error;
	}
	if (MenuAddOrInsert(interp,menuPtr,objv[2],objc-3,objv+3) != TCL_OK) {
	    goto error;
	}
	break;
    case MENU_INVOKE: {
	int index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	result = TkInvokeMenu(interp, menuPtr, index);
	break;
    }
    case MENU_POST: {
	int x, y;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
	    goto error;
	}

	/*
	 * Tearoff menus are posted differently on Mac and Windows than
	 * non-tearoffs. TkpPostMenu does not actually map the menu's window
	 * on those platforms, and popup menus have to be handled specially.
	 */

	if (menuPtr->menuType != TEAROFF_MENU) {
	    result = TkpPostMenu(interp, menuPtr, x, y);
	} else {
	    result = TkPostTearoffMenu(interp, menuPtr, x, y);
	}
	break;
    }
    case MENU_POSTCASCADE: {
	int index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}

	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
	    result = TkPostSubmenu(interp, menuPtr, NULL);
	} else {
	    result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);
	}
	break;
    }
    case MENU_TYPE: {
	int index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	if (menuPtr->entries[index]->type == TEAROFF_ENTRY) {
	    Tcl_SetResult(interp, "tearoff", TCL_STATIC);
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    menuEntryTypeStrings[menuPtr->entries[index]->type], -1));
	}
	break;
    }
    case MENU_UNPOST:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    goto error;
	}
	Tk_UnmapWindow(menuPtr->tkwin);
	result = TkPostSubmenu(interp, menuPtr, NULL);
	break;
    case MENU_XPOSITION:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	result = MenuDoXPosition(interp, menuPtr, objv[2]);
	break;
    case MENU_YPOSITION:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	result = MenuDoYPosition(interp, menuPtr, objv[2]);
	break;
    }
  done:
    Tcl_Release(menuPtr);
    return result;

  error:
    Tcl_Release(menuPtr);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TkInvokeMenu --
 *
 *	Given a menu and an index, takes the appropriate action for the entry
 *	associated with that index.
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Commands may get excecuted; variables may get set; sub-menus may get
 *	posted.
 *
 *----------------------------------------------------------------------
 */

int
TkInvokeMenu(
    Tcl_Interp *interp,		/* The interp that the menu lives in. */
    TkMenu *menuPtr,		/* The menu we are invoking. */
    int index)			/* The zero based index of the item we are
    				 * invoking. */
{
    int result = TCL_OK;
    TkMenuEntry *mePtr;

    if (index < 0) {
    	goto done;
    }
    mePtr = menuPtr->entries[index];
    if (mePtr->state == ENTRY_DISABLED) {
	goto done;
    }

    Tcl_Preserve(mePtr);
    if (mePtr->type == TEAROFF_ENTRY) {
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, "tk::TearOffMenu ", -1);
	Tcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), -1);
	result = Tcl_Eval(interp, Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
    } else if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    && (mePtr->namePtr != NULL)) {
	Tcl_Obj *valuePtr;

	if (mePtr->entryFlags & ENTRY_SELECTED) {
	    valuePtr = mePtr->offValuePtr;
	} else {
	    valuePtr = mePtr->onValuePtr;
	}
	if (valuePtr == NULL) {
	    valuePtr = Tcl_NewObj();
	}
	Tcl_IncrRefCount(valuePtr);
	if (Tcl_ObjSetVar2(interp, mePtr->namePtr, NULL, valuePtr,
		TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
	    result = TCL_ERROR;
	}
	Tcl_DecrRefCount(valuePtr);
    } else if ((mePtr->type == RADIO_BUTTON_ENTRY)
	    && (mePtr->namePtr != NULL)) {
	Tcl_Obj *valuePtr = mePtr->onValuePtr;

	if (valuePtr == NULL) {
	    valuePtr = Tcl_NewObj();
	}
	Tcl_IncrRefCount(valuePtr);
	if (Tcl_ObjSetVar2(interp, mePtr->namePtr, NULL, valuePtr,
		TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
	    result = TCL_ERROR;
	}
	Tcl_DecrRefCount(valuePtr);
    }

    /*
     * We check numEntries in addition to whether the menu entry has a command
     * because that goes to zero if the menu gets deleted (e.g., during
     * command evaluation).
     */

    if ((menuPtr->numEntries != 0) && (result == TCL_OK)
	    && (mePtr->commandPtr != NULL)) {
	Tcl_Obj *commandPtr = mePtr->commandPtr;

	Tcl_IncrRefCount(commandPtr);
	result = Tcl_EvalObjEx(interp, commandPtr, TCL_EVAL_GLOBAL);
	Tcl_DecrRefCount(commandPtr);
    }
    Tcl_Release(mePtr);

  done:
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DestroyMenuInstance --
 *
 *	This function is invoked by TkDestroyMenu to clean up the internal
 *	structure of a menu at a safe time (when no-one is using it anymore).
 *	Only takes care of one instance of the menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Everything associated with the menu is freed up.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyMenuInstance(
    TkMenu *menuPtr)		/* Info about menu widget. */
{
    int i;
    TkMenu *menuInstancePtr;
    TkMenuEntry *cascadePtr, *nextCascadePtr;
    Tcl_Obj *newObjv[2];
    TkMenu *parentMasterMenuPtr;
    TkMenuEntry *parentMasterEntryPtr;

    /*
     * If the menu has any cascade menu entries pointing to it, the cascade
     * entries need to be told that the menu is going away. We need to clear
     * the menu ptr field in the menu reference at this point in the code so
     * that everything else can forget about this menu properly. We also need
     * to reset -menu field of all entries that are not master menus back to
     * this entry name if this is a master menu pointed to by another master
     * menu. If there is a clone menu that points to this menu, then this menu
     * is itself a clone, so when this menu goes away, the -menu field of the
     * pointing entry must be set back to this menu's master menu name so that
     * later if another menu is created the cascade hierarchy can be
     * maintained.
     */

    TkpDestroyMenu(menuPtr);
    if (menuPtr->menuRefPtr == NULL) {
	return;
    }
    cascadePtr = menuPtr->menuRefPtr->parentEntryPtr;
    menuPtr->menuRefPtr->menuPtr = NULL;
    if (TkFreeMenuReferences(menuPtr->menuRefPtr)) {
	menuPtr->menuRefPtr = NULL;
    }

    for (; cascadePtr != NULL; cascadePtr = nextCascadePtr) {
    	nextCascadePtr = cascadePtr->nextCascadePtr;

    	if (menuPtr->masterMenuPtr != menuPtr) {
	    Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);

	    parentMasterMenuPtr = cascadePtr->menuPtr->masterMenuPtr;
	    parentMasterEntryPtr =
		    parentMasterMenuPtr->entries[cascadePtr->index];
	    newObjv[0] = menuNamePtr;
	    newObjv[1] = parentMasterEntryPtr->namePtr;

	    /*
	     * It is possible that the menu info is out of sync, and these
	     * things point to NULL, so verify existence [Bug: 3402]
	     */

	    if (newObjv[0] && newObjv[1]) {
		Tcl_IncrRefCount(newObjv[0]);
		Tcl_IncrRefCount(newObjv[1]);
		ConfigureMenuEntry(cascadePtr, 2, newObjv);
		Tcl_DecrRefCount(newObjv[0]);
		Tcl_DecrRefCount(newObjv[1]);
	    }
    	} else {
    	    ConfigureMenuEntry(cascadePtr, 0, NULL);
    	}
    }

    if (menuPtr->masterMenuPtr != menuPtr) {
	for (menuInstancePtr = menuPtr->masterMenuPtr;
		menuInstancePtr != NULL;
		menuInstancePtr = menuInstancePtr->nextInstancePtr) {
	    if (menuInstancePtr->nextInstancePtr == menuPtr) {
		menuInstancePtr->nextInstancePtr =
			menuInstancePtr->nextInstancePtr->nextInstancePtr;
		break;
	    }
	}
    } else if (menuPtr->nextInstancePtr != NULL) {
	Tcl_Panic("Attempting to delete master menu when there are still clones");
    }

    /*
     * Free up all the stuff that requires special handling, then let
     * Tk_FreeConfigOptions handle all the standard option-related stuff.
     */

    for (i = menuPtr->numEntries; --i >= 0; ) {
	/*
	 * As each menu entry is deleted from the end of the array of entries,
	 * decrement menuPtr->numEntries. Otherwise, the act of deleting menu
	 * entry i will dereference freed memory attempting to queue a redraw
	 * for menu entries (i+1)...numEntries.
	 */

	DestroyMenuEntry((char *) menuPtr->entries[i]);
	menuPtr->numEntries = i;
    }
    if (menuPtr->entries != NULL) {
	ckfree((char *) menuPtr->entries);
    }
    TkMenuFreeDrawOptions(menuPtr);
    Tk_FreeConfigOptions((char *) menuPtr,
	    menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin);
    if (menuPtr->tkwin != NULL) {
	Tk_Window tkwin = menuPtr->tkwin;

	menuPtr->tkwin = NULL;
	Tk_DestroyWindow(tkwin);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkDestroyMenu --
 *
 *	This function 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). If called on a master instance, destroys all of the
 *	slave instances. If called on a non-master instance, just destroys
 *	that instance.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Everything associated with the menu is freed up.
 *
 *----------------------------------------------------------------------
 */

void
TkDestroyMenu(
    TkMenu *menuPtr)		/* Info about menu widget. */
{
    TkMenu *menuInstancePtr;
    TkMenuTopLevelList *topLevelListPtr, *nextTopLevelPtr;

    if (menuPtr->menuFlags & MENU_DELETION_PENDING) {
    	return;
    }

    Tcl_Preserve(menuPtr);

    /*
     * Now destroy all non-tearoff instances of this menu if this is a parent
     * menu. Is this loop safe enough? Are there going to be destroy bindings
     * on child menus which kill the parent? If not, we have to do a slightly
     * more complex scheme.
     */

    menuPtr->menuFlags |= MENU_DELETION_PENDING;
    if (menuPtr->menuRefPtr != NULL) {
	/*
	 * If any toplevel widgets have this menu as their menubar, the
	 * geometry of the window may have to be recalculated.
	 */

	topLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr;
	while (topLevelListPtr != NULL) {
	    nextTopLevelPtr = topLevelListPtr->nextPtr;
	    TkpSetWindowMenuBar(topLevelListPtr->tkwin, NULL);
	    topLevelListPtr = nextTopLevelPtr;
	}
    }
    if (menuPtr->masterMenuPtr == menuPtr) {
	while (menuPtr->nextInstancePtr != NULL) {
	    menuInstancePtr = menuPtr->nextInstancePtr;
	    menuPtr->nextInstancePtr = menuInstancePtr->nextInstancePtr;
    	    if (menuInstancePtr->tkwin != NULL) {
		Tk_Window tkwin = menuInstancePtr->tkwin;

		/*
		 * Note: it may be desirable to NULL out the tkwin field of
		 * menuInstancePtr here:
		 * menuInstancePtr->tkwin = NULL;
		 */

	     	Tk_DestroyWindow(tkwin);
	    }
	}
    }

    DestroyMenuInstance(menuPtr);

    Tcl_Release(menuPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * UnhookCascadeEntry --
 *
 *	This entry is removed from the list of entries that point to the
 *	cascade menu. This is done in preparation for changing the menu that
 *	this entry points to.
 *
 *	At the end of this function, the menu entry no longer contains a
 *	reference to a 'TkMenuReferences' structure, and therefore no such
 *	structure contains a reference to this menu entry either.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	The appropriate lists are modified.
 *
 *----------------------------------------------------------------------
 */

static void
UnhookCascadeEntry(
    TkMenuEntry *mePtr)		/* The cascade entry we are removing from the
				 * cascade list. */
{
    TkMenuEntry *cascadeEntryPtr;
    TkMenuEntry *prevCascadePtr;
    TkMenuReferences *menuRefPtr;

    menuRefPtr = mePtr->childMenuRefPtr;
    if (menuRefPtr == NULL) {
	return;
    }

    cascadeEntryPtr = menuRefPtr->parentEntryPtr;
    if (cascadeEntryPtr == NULL) {
	TkFreeMenuReferences(menuRefPtr);
	mePtr->childMenuRefPtr = NULL;
    	return;
    }

    /*
     * Singularly linked list deletion. The two special cases are 1. one
     * element; 2. The first element is the one we want.
     */

    if (cascadeEntryPtr == mePtr) {
    	if (cascadeEntryPtr->nextCascadePtr == NULL) {
	    /*
	     * This is the last menu entry which points to this menu, so we
	     * need to clear out the list pointer in the cascade itself.
	     */

	    menuRefPtr->parentEntryPtr = NULL;

	    /*
	     * The original field is set to zero below, after it is freed.
	     */

	    TkFreeMenuReferences(menuRefPtr);
    	} else {
    	    menuRefPtr->parentEntryPtr = cascadeEntryPtr->nextCascadePtr;
    	}
    	mePtr->nextCascadePtr = NULL;
    } else {
	for (prevCascadePtr = cascadeEntryPtr,
		cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr;
		cascadeEntryPtr != NULL;
		prevCascadePtr = cascadeEntryPtr,
		cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
    	    if (cascadeEntryPtr == mePtr){
    	    	prevCascadePtr->nextCascadePtr =
			cascadeEntryPtr->nextCascadePtr;
    	    	cascadeEntryPtr->nextCascadePtr = NULL;
    	    	break;
    	    }
	}
	mePtr->nextCascadePtr = NULL;
    }
    mePtr->childMenuRefPtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * DestroyMenuEntry --
 *
 *	This function 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.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyMenuEntry(
    char *memPtr)		/* Pointer to entry to be freed. */
{
    register TkMenuEntry *mePtr = (TkMenuEntry *) memPtr;
    TkMenu *menuPtr = mePtr->menuPtr;

    if (menuPtr->postedCascade == mePtr) {
    	/*
	 * Ignore errors while unposting the menu, since it's possible that
	 * the menu has already been deleted and the unpost will generate an
	 * error.
	 */

	TkPostSubmenu(menuPtr->interp, menuPtr, NULL);
    }

    /*
     * Free up all the stuff that requires special handling, then let
     * Tk_FreeConfigOptions handle all the standard option-related stuff.
     */

    if (mePtr->type == CASCADE_ENTRY) {
	if (menuPtr->masterMenuPtr != menuPtr) {
	    TkMenu *destroyThis = NULL;
	    TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr;

	    /*
	     * The menu as a whole is a clone. We must delete the clone of the
	     * cascaded menu for the particular entry we are destroying.
	     */

	    if (menuRefPtr != NULL) {
		destroyThis = menuRefPtr->menuPtr;

		/*
		 * But only if it is a clone. What can happen is that we are
		 * in the middle of deleting a menu and this menu pointer has
		 * already been reset to point to the original menu. In that
		 * case we have nothing special to do.
		 */

		if ((destroyThis != NULL)
			&& (destroyThis->masterMenuPtr == destroyThis)) {
		    destroyThis = NULL;
		}
	    }
	    UnhookCascadeEntry(mePtr);
	    if (menuRefPtr != NULL) {
		if (menuRefPtr->menuPtr == destroyThis) {
		    menuRefPtr->menuPtr = NULL;
		}
		if (destroyThis != NULL) {
		    TkDestroyMenu(destroyThis);
		}
	    }
	} else {
	    UnhookCascadeEntry(mePtr);
	}
    }
    if (mePtr->image != NULL) {
	Tk_FreeImage(mePtr->image);
    }
    if (mePtr->selectImage != NULL) {
	Tk_FreeImage(mePtr->selectImage);
    }
    if (((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY))
	    && (mePtr->namePtr != NULL)) {
	const char *varName = Tcl_GetString(mePtr->namePtr);

	Tcl_UntraceVar(menuPtr->interp, varName,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuVarProc, mePtr);
    }
    TkpDestroyMenuEntry(mePtr);
    TkMenuEntryFreeDrawOptions(mePtr);
    Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable, menuPtr->tkwin);
    ckfree((char *) mePtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * MenuWorldChanged --
 *
 *	This function is called when the world has changed in some way (such
 *	as the fonts in the system changing) and the widget needs to recompute
 *	all its graphics contexts and determine its new geometry.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Menu will be relayed out and redisplayed.
 *
 *---------------------------------------------------------------------------
 */

static void
MenuWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    TkMenu *menuPtr = instanceData;
    int i;

    TkMenuConfigureDrawOptions(menuPtr);
    for (i = 0; i < menuPtr->numEntries; i++) {
    	TkMenuConfigureEntryDrawOptions(menuPtr->entries[i],
		menuPtr->entries[i]->index);
	TkpConfigureMenuEntry(menuPtr->entries[i]);
    }
    TkEventuallyRecomputeMenu(menuPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureMenu --
 *
 *	This function is called to process an argv/argc list, plus 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 the interp's 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
ConfigureMenu(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkMenu *menuPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    int i;
    TkMenu *menuListPtr, *cleanupPtr;
    int result;

    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
	    menuListPtr = menuListPtr->nextInstancePtr) {
	menuListPtr->errorStructPtr = (Tk_SavedOptions *)
		ckalloc(sizeof(Tk_SavedOptions));
	result = Tk_SetOptions(interp, (char *) menuListPtr,
		menuListPtr->optionTablesPtr->menuOptionTable, objc, objv,
		menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL);
	if (result != TCL_OK) {
	    for (cleanupPtr = menuPtr->masterMenuPtr;
		    cleanupPtr != menuListPtr;
		    cleanupPtr = cleanupPtr->nextInstancePtr) {
		Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
		ckfree((char *) cleanupPtr->errorStructPtr);
		cleanupPtr->errorStructPtr = NULL;
	    }
	    if (menuListPtr->errorStructPtr != NULL) {
		Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
		ckfree((char *) menuListPtr->errorStructPtr);
		menuListPtr->errorStructPtr = NULL;
	    }
	    return TCL_ERROR;
	}

	/*
	 * When a menu is created, the type is in all of the arguments to the
	 * menu command. Let Tk_ConfigureWidget take care of parsing them, and
	 * then set the type after we can look at the type string. Once set, a
	 * menu's type cannot be changed
	 */

	if (menuListPtr->menuType == UNKNOWN_TYPE) {
	    Tcl_GetIndexFromObj(NULL, menuListPtr->menuTypePtr,
		    menuTypeStrings, NULL, 0, &menuListPtr->menuType);

	    /*
	     * Configure the new window to be either a pop-up menu or a
	     * tear-off menu. We don't do this for menubars since they are not
	     * toplevel windows. Also, since this gets called before CloneMenu
	     * has a chance to set the menuType field, we have to look at the
	     * menuTypeName field to tell that this is a menu bar.
	     */

	    if (menuListPtr->menuType == MASTER_MENU) {
		int typeFlag = TK_MAKE_MENU_POPUP;
		Tk_Window tkwin = menuPtr->tkwin;

		/*
		 * Work out if we are the child of a menubar or a popup.
		 */

		while (1) {
		    Tk_Window parent = Tk_Parent(tkwin);

		    if (Tk_Class(parent) != Tk_Class(menuPtr->tkwin)) {
			break;
		    }
		    tkwin = parent;
		}
		if (((TkMenu *) tkwin)->menuType == MENUBAR) {
		    typeFlag = TK_MAKE_MENU_DROPDOWN;
		}

		TkpMakeMenuWindow(menuListPtr->tkwin, typeFlag);
	    } else if (menuListPtr->menuType == TEAROFF_MENU) {
		TkpMakeMenuWindow(menuListPtr->tkwin, TK_MAKE_MENU_TEAROFF);
	    }
	}

	/*
	 * 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 (menuListPtr->tearoff) {
	    if ((menuListPtr->numEntries == 0)
		    || (menuListPtr->entries[0]->type != TEAROFF_ENTRY)) {
		if (MenuNewEntry(menuListPtr, 0, TEAROFF_ENTRY) == NULL) {
		    for (cleanupPtr = menuPtr->masterMenuPtr;
			    cleanupPtr != menuListPtr;
			    cleanupPtr = cleanupPtr->nextInstancePtr) {
			Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
			ckfree((char *) cleanupPtr->errorStructPtr);
			cleanupPtr->errorStructPtr = NULL;
		    }
		    if (menuListPtr->errorStructPtr != NULL) {
			Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
			ckfree((char *) menuListPtr->errorStructPtr);
			menuListPtr->errorStructPtr = NULL;
		    }
		    return TCL_ERROR;
		}
	    }
	} else if ((menuListPtr->numEntries > 0)
		&& (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) {
	    int i;

	    Tcl_EventuallyFree(menuListPtr->entries[0], DestroyMenuEntry);

	    for (i = 0; i < menuListPtr->numEntries - 1; i++) {
		menuListPtr->entries[i] = menuListPtr->entries[i + 1];
		menuListPtr->entries[i]->index = i;
	    }
	    menuListPtr->numEntries--;
	    if (menuListPtr->numEntries == 0) {
		ckfree((char *) menuListPtr->entries);
		menuListPtr->entries = NULL;
	    }
	}

	TkMenuConfigureDrawOptions(menuListPtr);

	/*
	 * 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 < menuListPtr->numEntries; i++) {
	    TkMenuEntry *mePtr;

	    mePtr = menuListPtr->entries[i];
	    ConfigureMenuEntry(mePtr, 0, NULL);
	}

	TkEventuallyRecomputeMenu(menuListPtr);
    }

    for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != NULL;
	    cleanupPtr = cleanupPtr->nextInstancePtr) {
	Tk_FreeSavedOptions(cleanupPtr->errorStructPtr);
	ckfree((char *) cleanupPtr->errorStructPtr);
	cleanupPtr->errorStructPtr = NULL;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * PostProcessEntry --
 *
 *	This is called by ConfigureMenuEntry to do all of the configuration
 *	after Tk_SetOptions is called. This is separate so that error handling
 *	is easier.
 *
 * Results:
 *	The return value is a standard Tcl result. If TCL_ERROR is returned,
 *	then the interp's 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
PostProcessEntry(
    TkMenuEntry *mePtr)			/* The entry we are configuring. */
{
    TkMenu *menuPtr = mePtr->menuPtr;
    int index = mePtr->index;
    const char *name;
    Tk_Image image;

    /*
     * 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.
     */

    if (mePtr->labelPtr == NULL) {
	mePtr->labelLength = 0;
    } else {
	Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);
    }
    if (mePtr->accelPtr == NULL) {
	mePtr->accelLength = 0;
    } else {
	Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength);
    }

    /*
     * If this is a cascade entry, the platform-specific data of the child
     * menu has to be updated. Also, the links that point to parents and
     * cascades have to be updated.
     */

    if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {
 	TkMenuEntry *cascadeEntryPtr;
	int alreadyThere;
	TkMenuReferences *menuRefPtr;
	char *oldHashKey = NULL;	/* Initialization only needed to
					 * prevent compiler warning. */

	/*
	 * This is a cascade entry. If the menu that the cascade entry is
	 * pointing to has changed, we need to remove this entry from the list
	 * of entries pointing to the old menu, and add a cascade reference to
	 * the list of entries pointing to the new menu.
	 *
	 * BUG: We are not recloning for special case #3 yet.
	 */

	name = Tcl_GetString(mePtr->namePtr);
	if (mePtr->childMenuRefPtr != NULL) {
	    oldHashKey = Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp),
		    mePtr->childMenuRefPtr->hashEntryPtr);
	    if (strcmp(oldHashKey, name) != 0) {
		UnhookCascadeEntry(mePtr);
	    }
	}

	if ((mePtr->childMenuRefPtr == NULL)
		|| (strcmp(oldHashKey, name) != 0)) {
	    menuRefPtr = TkCreateMenuReferences(menuPtr->interp, name);
	    mePtr->childMenuRefPtr = menuRefPtr;

	    if (menuRefPtr->parentEntryPtr == NULL) {
		menuRefPtr->parentEntryPtr = mePtr;
	    } else {
		alreadyThere = 0;
		for (cascadeEntryPtr = menuRefPtr->parentEntryPtr;
			cascadeEntryPtr != NULL;
			cascadeEntryPtr =
			cascadeEntryPtr->nextCascadePtr) {
		    if (cascadeEntryPtr == mePtr) {
			alreadyThere = 1;
			break;
		    }
		}

		/*
		 * Put the item at the front of the list.
		 */

		if (!alreadyThere) {
		    mePtr->nextCascadePtr = menuRefPtr->parentEntryPtr;
		    menuRefPtr->parentEntryPtr = mePtr;
		}
	    }
	}
    }

    if (TkMenuConfigureEntryDrawOptions(mePtr, index) != TCL_OK) {
    	return TCL_ERROR;
    }

    /*
     * 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.
     */

    if (mePtr->imagePtr != NULL) {
	const char *imageString = Tcl_GetString(mePtr->imagePtr);

	image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, imageString,
		TkMenuImageProc, mePtr);
	if (image == NULL) {
	    return TCL_ERROR;
	}
    } else {
	image = NULL;
    }
    if (mePtr->image != NULL) {
	Tk_FreeImage(mePtr->image);
    }
    mePtr->image = image;
    if (mePtr->selectImagePtr != NULL) {
	const char *selectImageString = Tcl_GetString(mePtr->selectImagePtr);

	image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, selectImageString,
		TkMenuSelectImageProc, mePtr);
	if (image == NULL) {
	    return TCL_ERROR;
	}
    } else {
	image = NULL;
    }
    if (mePtr->selectImage != NULL) {
	Tk_FreeImage(mePtr->selectImage);
    }
    mePtr->selectImage = image;

    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
	Tcl_Obj *valuePtr;
	const char *name;

	if (mePtr->namePtr == NULL) {
	    if (mePtr->labelPtr == NULL) {
		mePtr->namePtr = NULL;
	    } else {
		mePtr->namePtr = Tcl_DuplicateObj(mePtr->labelPtr);
		Tcl_IncrRefCount(mePtr->namePtr);
	    }
	}
	if (mePtr->onValuePtr == NULL) {
	    if (mePtr->labelPtr == NULL) {
		mePtr->onValuePtr = NULL;
	    } else {
		mePtr->onValuePtr = Tcl_DuplicateObj(mePtr->labelPtr);
		Tcl_IncrRefCount(mePtr->onValuePtr);
	    }
	}

	/*
	 * 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.
	 */

	if (mePtr->namePtr != NULL) {
	    valuePtr = Tcl_ObjGetVar2(menuPtr->interp, mePtr->namePtr, NULL,
		    TCL_GLOBAL_ONLY);
	} else {
	    valuePtr = NULL;
	}
	mePtr->entryFlags &= ~ENTRY_SELECTED;
	if (valuePtr != NULL) {
	    if (mePtr->onValuePtr != NULL) {
		const char *value = Tcl_GetString(valuePtr);
		const char *onValue = Tcl_GetString(mePtr->onValuePtr);

		if (strcmp(value, onValue) == 0) {
		    mePtr->entryFlags |= ENTRY_SELECTED;
		}
	    }
	} else {
	    if (mePtr->namePtr != NULL) {
		Tcl_ObjSetVar2(menuPtr->interp, mePtr->namePtr, NULL,
			(mePtr->type == CHECK_BUTTON_ENTRY)
			? mePtr->offValuePtr : Tcl_NewObj(), TCL_GLOBAL_ONLY);
	    }
	}
	if (mePtr->namePtr != NULL) {
	    name = Tcl_GetString(mePtr->namePtr);
	    Tcl_TraceVar(menuPtr->interp, name,
		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		    MenuVarProc, mePtr);
	}
    }

    if (TkpConfigureMenuEntry(mePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureMenuEntry --
 *
 *	This function is called to process an argv/argc list 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 the interp's 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
ConfigureMenuEntry(
    register TkMenuEntry *mePtr,/* Information about menu entry; may or may
				 * not already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    TkMenu *menuPtr = mePtr->menuPtr;
    Tk_SavedOptions errorStruct;
    int result;

    /*
     * If this entry is a check button or radio button, then remove its old
     * trace function.
     */

    if ((mePtr->namePtr != NULL)
    	    && ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY))) {
	const char *name = Tcl_GetString(mePtr->namePtr);

	Tcl_UntraceVar(menuPtr->interp, name,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuVarProc, mePtr);
    }

    result = TCL_OK;
    if (menuPtr->tkwin != NULL) {
	if (Tk_SetOptions(menuPtr->interp, (char *) mePtr,
		mePtr->optionTable, objc, objv, menuPtr->tkwin,
		&errorStruct, NULL) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = PostProcessEntry(mePtr);
	if (result != TCL_OK) {
	    Tk_RestoreSavedOptions(&errorStruct);
	    PostProcessEntry(mePtr);
	}
	Tk_FreeSavedOptions(&errorStruct);
    }

    TkEventuallyRecomputeMenu(menuPtr);

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureMenuCloneEntries --
 *
 *	Calls ConfigureMenuEntry for each menu in the clone chain.
 *
 * Results:
 *	The return value is a standard Tcl result. If TCL_ERROR is returned,
 *	then the interp's 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
ConfigureMenuCloneEntries(
    Tcl_Interp *interp,		/* Used for error reporting. */
    TkMenu *menuPtr,		/* Information about whole menu. */
    int index,			/* Index of mePtr within menuPtr's entries. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    TkMenuEntry *mePtr;
    TkMenu *menuListPtr;
    int cascadeEntryChanged = 0;
    TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL;
    Tcl_Obj *oldCascadePtr = NULL;
    const char *newCascadeName;

    /*
     * Cascades are kind of tricky here. This is special case #3 in the
     * comment at the top of this file. Basically, if a menu is the master
     * menu of a clone chain, and has an entry with a cascade menu, the clones
     * of the menu will point to clones of the cascade menu. We have to
     * destroy the clones of the cascades, clone the new cascade menu, and
     * configure the entry to point to the new clone.
     */

    mePtr = menuPtr->masterMenuPtr->entries[index];
    if (mePtr->type == CASCADE_ENTRY) {
	oldCascadePtr = mePtr->namePtr;
	if (oldCascadePtr != NULL) {
	    Tcl_IncrRefCount(oldCascadePtr);
	}
    }

    if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
	return TCL_ERROR;
    }

    if (mePtr->type == CASCADE_ENTRY) {
	const char *oldCascadeName;

	if (mePtr->namePtr != NULL) {
	    newCascadeName = Tcl_GetString(mePtr->namePtr);
	} else {
	    newCascadeName = NULL;
	}

	if ((oldCascadePtr == NULL) && (mePtr->namePtr == NULL)) {
	    cascadeEntryChanged = 0;
	} else if (((oldCascadePtr == NULL) && (mePtr->namePtr != NULL))
		|| ((oldCascadePtr != NULL)
		&& (mePtr->namePtr == NULL))) {
	    cascadeEntryChanged = 1;
	} else {
	    oldCascadeName = Tcl_GetString(oldCascadePtr);
	    cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName)
		    != 0);
	}
	if (oldCascadePtr != NULL) {
	    Tcl_DecrRefCount(oldCascadePtr);
	}
    }

    if (cascadeEntryChanged) {
	if (mePtr->namePtr != NULL) {
	    newCascadeName = Tcl_GetString(mePtr->namePtr);
	    cascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp,
		    newCascadeName);
	}
    }

    for (menuListPtr = menuPtr->masterMenuPtr->nextInstancePtr;
    	    menuListPtr != NULL;
	    menuListPtr = menuListPtr->nextInstancePtr) {

    	mePtr = menuListPtr->entries[index];

	if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
	    oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
		    mePtr->namePtr);

	    if ((oldCascadeMenuRefPtr != NULL)
		    && (oldCascadeMenuRefPtr->menuPtr != NULL)) {
		RecursivelyDeleteMenu(oldCascadeMenuRefPtr->menuPtr);
	    }
	}

    	if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
    	    return TCL_ERROR;
    	}

	if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
	    if (cascadeMenuRefPtr && cascadeMenuRefPtr->menuPtr != NULL) {
		Tcl_Obj *newObjv[2];
		Tcl_Obj *newCloneNamePtr;
		Tcl_Obj *pathNamePtr = Tcl_NewStringObj(
			Tk_PathName(menuListPtr->tkwin), -1);
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
		Tcl_Obj *menuObjPtr = Tcl_NewStringObj("-menu", -1);

		Tcl_IncrRefCount(pathNamePtr);
		newCloneNamePtr = TkNewMenuName(menuPtr->interp,
			pathNamePtr,
			cascadeMenuRefPtr->menuPtr);
		Tcl_IncrRefCount(newCloneNamePtr);
		Tcl_IncrRefCount(normalPtr);
		CloneMenu(cascadeMenuRefPtr->menuPtr, newCloneNamePtr,
			normalPtr);

		newObjv[0] = menuObjPtr;
		newObjv[1] = newCloneNamePtr;
		Tcl_IncrRefCount(menuObjPtr);
		ConfigureMenuEntry(mePtr, 2, newObjv);
		Tcl_DecrRefCount(newCloneNamePtr);
		Tcl_DecrRefCount(pathNamePtr);
		Tcl_DecrRefCount(normalPtr);
		Tcl_DecrRefCount(menuObjPtr);
	    }
	}
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * TkGetMenuIndex --
 *
 *	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 the interp's result.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkGetMenuIndex(
    Tcl_Interp *interp,		/* For error messages. */
    TkMenu *menuPtr,		/* Menu for which the index is being
				 * specified. */
    Tcl_Obj *objPtr,		/* 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 index. */
{
    int i;
    const char *string = Tcl_GetString(objPtr);

    if ((string[0] == 'a') && (strcmp(string, "active") == 0)) {
	*indexPtr = menuPtr->active;
	goto success;
    }

    if (((string[0] == 'l') && (strcmp(string, "last") == 0))
	    || ((string[0] == 'e') && (strcmp(string, "end") == 0))) {
	*indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);
	goto success;
    }

    if ((string[0] == 'n') && (strcmp(string, "none") == 0)) {
	*indexPtr = -1;
	goto success;
    }

    if (string[0] == '@@') {
	if (GetIndexFromCoords(interp, menuPtr, string, indexPtr)
		== TCL_OK) {
	    goto success;
	}
    }

    if (isdigit(UCHAR(string[0]))) {
	if (Tcl_GetInt(interp, string, &i) == TCL_OK) {
	    if (i >= menuPtr->numEntries) {
		if (lastOK) {
		    i = menuPtr->numEntries;
		} else {
		    i = menuPtr->numEntries-1;
		}
	    } else if (i < 0) {
		i = -1;
	    }
	    *indexPtr = i;
	    goto success;
	}
	Tcl_ResetResult(interp);
    }

    for (i = 0; i < menuPtr->numEntries; i++) {
	Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;
	const char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr);

	if ((label != NULL) && (Tcl_StringMatch(label, string))) {
	    *indexPtr = i;
	    goto success;
	}
    }

    Tcl_AppendResult(interp, "bad menu entry index \"", string, "\"", NULL);
    return TCL_ERROR;

  success:
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * MenuCmdDeletedProc --
 *
 *	This function 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
MenuCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkMenu *menuPtr = clientData;
    Tk_Window tkwin = menuPtr->tkwin;

    /*
     * This function 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 function destroys the
     * widget.
     */

    if (tkwin != NULL) {
	/*
	 * Note: it may be desirable to NULL out the tkwin field of menuPtr
	 * here:
	 * menuPtr->tkwin = NULL;
	 */

	Tk_DestroyWindow(tkwin);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * MenuNewEntry --
 *
 *	This function 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 TkMenuEntry *
MenuNewEntry(
    TkMenu *menuPtr,		/* Menu that will hold the new entry. */
    int index,			/* Where in the menu the new entry is to
				 * go. */
    int type)			/* The type of the new entry. */
{
    TkMenuEntry *mePtr;
    TkMenuEntry **newEntries;
    int i;

    /*
     * Create a new array of entries with an empty slot for the new entry.
     */

    newEntries = (TkMenuEntry **)
	    ckalloc((unsigned) (menuPtr->numEntries+1)*sizeof(TkMenuEntry *));
    for (i = 0; i < index; i++) {
	newEntries[i] = menuPtr->entries[i];
    }
    for (; i < menuPtr->numEntries; i++) {
	newEntries[i+1] = menuPtr->entries[i];
	newEntries[i+1]->index = i + 1;
    }
    if (menuPtr->numEntries != 0) {
	ckfree((char *) menuPtr->entries);
    }
    menuPtr->entries = newEntries;
    menuPtr->numEntries++;
    mePtr = (TkMenuEntry *) ckalloc(sizeof(TkMenuEntry));
    menuPtr->entries[index] = mePtr;
    mePtr->type = type;
    mePtr->optionTable = menuPtr->optionTablesPtr->entryOptionTables[type];
    mePtr->menuPtr = menuPtr;
    mePtr->labelPtr = NULL;
    mePtr->labelLength = 0;
    mePtr->underline = -1;
    mePtr->bitmapPtr = NULL;
    mePtr->imagePtr = NULL;
    mePtr->image = NULL;
    mePtr->selectImagePtr = NULL;
    mePtr->selectImage = NULL;
    mePtr->accelPtr = NULL;
    mePtr->accelLength = 0;
    mePtr->state = ENTRY_DISABLED;
    mePtr->borderPtr = NULL;
    mePtr->fgPtr = NULL;
    mePtr->activeBorderPtr = NULL;
    mePtr->activeFgPtr = NULL;
    mePtr->fontPtr = NULL;
    mePtr->indicatorOn = 0;
    mePtr->indicatorFgPtr = NULL;
    mePtr->columnBreak = 0;
    mePtr->hideMargin = 0;
    mePtr->commandPtr = NULL;
    mePtr->namePtr = NULL;
    mePtr->childMenuRefPtr = NULL;
    mePtr->onValuePtr = NULL;
    mePtr->offValuePtr = NULL;
    mePtr->entryFlags = 0;
    mePtr->index = index;
    mePtr->nextCascadePtr = NULL;
    if (Tk_InitOptions(menuPtr->interp, (char *) mePtr,
	    mePtr->optionTable, menuPtr->tkwin) != TCL_OK) {
	ckfree((char *) mePtr);
	return NULL;
    }
    TkMenuInitializeEntryDrawingFields(mePtr);
    if (TkpMenuNewEntry(mePtr) != TCL_OK) {
	Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable,
		menuPtr->tkwin);
    	ckfree((char *) mePtr);
    	return NULL;
    }

    return mePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * MenuAddOrInsert --
 *
 *	This function 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
MenuAddOrInsert(
    Tcl_Interp *interp,		/* Used for error reporting. */
    TkMenu *menuPtr,		/* Widget in which to create new entry. */
    Tcl_Obj *indexPtr,		/* Object describing index at which to insert.
				 * NULL means insert at end. */
    int objc,			/* Number of elements in objv. */
    Tcl_Obj *const objv[])	/* Arguments to command: first arg is type of
				 * entry, others are config options. */
{
    int type, index;
    TkMenuEntry *mePtr;
    TkMenu *menuListPtr;

    if (indexPtr != NULL) {
	if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
    } else {
	index = menuPtr->numEntries;
    }
    if (index < 0) {
	const char *indexString = Tcl_GetString(indexPtr);

	Tcl_AppendResult(interp, "bad index \"", indexString, "\"", NULL);
	return TCL_ERROR;
    }
    if (menuPtr->tearoff && (index == 0)) {
	index = 1;
    }

    /*
     * Figure out the type of the new entry.
     */

    if (Tcl_GetIndexFromObj(interp, objv[0], menuEntryTypeStrings,
	    "menu entry type", 0, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Now we have to add an entry for every instance related to this menu.
     */

    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
    	    menuListPtr = menuListPtr->nextInstancePtr) {

    	mePtr = MenuNewEntry(menuListPtr, index, type);
    	if (mePtr == NULL) {
    	    return TCL_ERROR;
    	}
    	if (ConfigureMenuEntry(mePtr, objc - 1, objv + 1) != TCL_OK) {
	    TkMenu *errorMenuPtr;
	    int i;

	    for (errorMenuPtr = menuPtr->masterMenuPtr;
		    errorMenuPtr != NULL;
		    errorMenuPtr = errorMenuPtr->nextInstancePtr) {
    		Tcl_EventuallyFree(errorMenuPtr->entries[index],
    	    		DestroyMenuEntry);
		for (i = index; i < errorMenuPtr->numEntries - 1; i++) {
		    errorMenuPtr->entries[i] = errorMenuPtr->entries[i + 1];
		    errorMenuPtr->entries[i]->index = i;
		}
		errorMenuPtr->numEntries--;
		if (errorMenuPtr->numEntries == 0) {
		    ckfree((char *) errorMenuPtr->entries);
		    errorMenuPtr->entries = NULL;
		}
		if (errorMenuPtr == menuListPtr) {
		    break;
		}
	    }
    	    return TCL_ERROR;
    	}

    	/*
	 * If a menu has cascades, then every instance of the menu has to have
	 * its own parallel cascade structure. So adding an entry to a menu
	 * with clones means that the menu that the entry points to has to be
	 * cloned for every clone the master menu has. This is special case #2
	 * in the comment at the top of this file.
    	 */

    	if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) {
    	    if ((mePtr->namePtr != NULL)
		    && (mePtr->childMenuRefPtr != NULL)
    	    	    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
		TkMenu *cascadeMenuPtr =
			mePtr->childMenuRefPtr->menuPtr->masterMenuPtr;
		Tcl_Obj *newCascadePtr, *newObjv[2];
		Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
		Tcl_Obj *windowNamePtr =
			Tcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), -1);
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
		TkMenuReferences *menuRefPtr;

		Tcl_IncrRefCount(windowNamePtr);
		newCascadePtr = TkNewMenuName(menuListPtr->interp,
			windowNamePtr, cascadeMenuPtr);
		Tcl_IncrRefCount(newCascadePtr);
		Tcl_IncrRefCount(normalPtr);
		CloneMenu(cascadeMenuPtr, newCascadePtr, normalPtr);

		menuRefPtr = TkFindMenuReferencesObj(menuListPtr->interp,
			newCascadePtr);
		if (menuRefPtr == NULL) {
		    Tcl_Panic("CloneMenu failed inside of MenuAddOrInsert");
		}
		newObjv[0] = menuNamePtr;
		newObjv[1] = newCascadePtr;
		Tcl_IncrRefCount(menuNamePtr);
		Tcl_IncrRefCount(newCascadePtr);
		ConfigureMenuEntry(mePtr, 2, newObjv);
		Tcl_DecrRefCount(newCascadePtr);
		Tcl_DecrRefCount(menuNamePtr);
		Tcl_DecrRefCount(windowNamePtr);
		Tcl_DecrRefCount(normalPtr);
    	    }
    	}
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * MenuVarProc --
 *
 *	This function 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.
 *
 *--------------------------------------------------------------
 */

static char *
MenuVarProc(
    ClientData clientData,	/* Information about menu entry. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* First part of variable's name. */
    const char *name2,		/* Second part of variable's name. */
    int flags)			/* Describes what just happened. */
{
    TkMenuEntry *mePtr = clientData;
    TkMenu *menuPtr;
    const char *value;
    const char *name, *onValue;

    if (flags & TCL_INTERP_DESTROYED) {
	/*
	 * Do nothing if the interpreter is going away.
	 */

    	return NULL;
    }

    menuPtr = mePtr->menuPtr;
    name = Tcl_GetString(mePtr->namePtr);

    /*
     * If the variable is being unset, then re-establish the trace.
     */

    if (flags & TCL_TRACE_UNSETS) {
	mePtr->entryFlags &= ~ENTRY_SELECTED;
	if (flags & TCL_TRACE_DESTROYED) {
	    Tcl_TraceVar(interp, name,
		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		    MenuVarProc, clientData);
	}
	TkpConfigureMenuEntry(mePtr);
	TkEventuallyRedrawMenu(menuPtr, NULL);
	return NULL;
    }

    /*
     * Use the value of the variable to update the selected status of the menu
     * entry.
     */

    value = Tcl_GetVar(interp, name, TCL_GLOBAL_ONLY);
    if (value == NULL) {
	value = "";
    }
    if (mePtr->onValuePtr != NULL) {
	onValue = Tcl_GetString(mePtr->onValuePtr);
	if (strcmp(value, onValue) == 0) {
	    if (mePtr->entryFlags & ENTRY_SELECTED) {
		return NULL;
	    }
	    mePtr->entryFlags |= ENTRY_SELECTED;
	} else if (mePtr->entryFlags & ENTRY_SELECTED) {
	    mePtr->entryFlags &= ~ENTRY_SELECTED;
	} else {
	    return NULL;
	}
    } else {
	return NULL;
    }
    TkpConfigureMenuEntry(mePtr);
    TkEventuallyRedrawMenu(menuPtr, mePtr);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TkActivateMenuEntry --
 *
 *	This function 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.
 *
 *----------------------------------------------------------------------
 */

int
TkActivateMenuEntry(
    register TkMenu *menuPtr,	/* Menu in which to activate. */
    int index)			/* Index of entry to activate, or -1 to
				 * deactivate all entries. */
{
    register TkMenuEntry *mePtr;
    int result = TCL_OK;

    if (menuPtr->active >= 0) {
	mePtr = menuPtr->entries[menuPtr->active];

	/*
	 * Don't change the state unless it's currently active (state might
	 * already have been changed to disabled).
	 */

	if (mePtr->state == ENTRY_ACTIVE) {
	    mePtr->state = ENTRY_NORMAL;
	}
	TkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]);
    }
    menuPtr->active = index;
    if (index >= 0) {
	mePtr = menuPtr->entries[index];
	mePtr->state = ENTRY_ACTIVE;
	TkEventuallyRedrawMenu(menuPtr, mePtr);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TkPostCommand --
 *
 *	Execute the postcommand for the given menu.
 *
 * Results:
 *	The return value is a standard Tcl result (errors can occur while the
 *	postcommands are being processed).
 *
 * Side effects:
 *	Since commands can get executed while this routine is being executed,
 *	the entire world can change.
 *
 *----------------------------------------------------------------------
 */

int
TkPostCommand(
    TkMenu *menuPtr)
{
    int result;

    /*
     * 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.
     */

    if (menuPtr->postCommandPtr != NULL) {
	Tcl_Obj *postCommandPtr = menuPtr->postCommandPtr;

	Tcl_IncrRefCount(postCommandPtr);
	result = Tcl_EvalObjEx(menuPtr->interp, postCommandPtr,
		TCL_EVAL_GLOBAL);
	Tcl_DecrRefCount(postCommandPtr);
	if (result != TCL_OK) {
	    return result;
	}
	TkRecomputeMenu(menuPtr);
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * CloneMenu --
 *
 *	Creates a child copy of the menu. It will be inserted into the menu's
 *	instance chain. All attributes and entry attributes will be
 *	duplicated.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Allocates storage. After the menu is created, any configuration done
 *	with this menu or any related one will be reflected in all of them.
 *
 *--------------------------------------------------------------
 */

static int
CloneMenu(
    TkMenu *menuPtr,		/* The menu we are going to clone. */
    Tcl_Obj *newMenuNamePtr,	/* The name to give the new menu. */
    Tcl_Obj *newMenuTypePtr)	/* What kind of menu is this, a normal menu a
    				 * menubar, or a tearoff? */
{
    int returnResult;
    int menuType, i;
    TkMenuReferences *menuRefPtr;
    Tcl_Obj *menuDupCommandArray[4];

    if (newMenuTypePtr == NULL) {
	menuType = MASTER_MENU;
    } else {
	if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr,
		menuTypeStrings, "menu type", 0, &menuType) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    menuDupCommandArray[0] = Tcl_NewStringObj("tk::MenuDup", -1);
    menuDupCommandArray[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
    menuDupCommandArray[2] = newMenuNamePtr;
    if (newMenuTypePtr == NULL) {
	menuDupCommandArray[3] = Tcl_NewStringObj("normal", -1);
    } else {
	menuDupCommandArray[3] = newMenuTypePtr;
    }
    for (i = 0; i < 4; i++) {
	Tcl_IncrRefCount(menuDupCommandArray[i]);
    }
    Tcl_Preserve(menuPtr);
    returnResult = Tcl_EvalObjv(menuPtr->interp, 4, menuDupCommandArray, 0);
    for (i = 0; i < 4; i++) {
	Tcl_DecrRefCount(menuDupCommandArray[i]);
    }

    /*
     * Make sure the tcl command actually created the clone.
     */

    if ((returnResult == TCL_OK) &&
	    ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
	    newMenuNamePtr)) != NULL)
	    && (menuPtr->numEntries == menuRefPtr->menuPtr->numEntries)) {
	TkMenu *newMenuPtr = menuRefPtr->menuPtr;
	Tcl_Obj *newObjv[3];
	int i, numElements;

	/*
	 * Now put this newly created menu into the parent menu's instance
	 * chain.
	 */

	if (menuPtr->nextInstancePtr == NULL) {
	    menuPtr->nextInstancePtr = newMenuPtr;
	    newMenuPtr->masterMenuPtr = menuPtr->masterMenuPtr;
	} else {
	    TkMenu *masterMenuPtr;

	    masterMenuPtr = menuPtr->masterMenuPtr;
	    newMenuPtr->nextInstancePtr = masterMenuPtr->nextInstancePtr;
	    masterMenuPtr->nextInstancePtr = newMenuPtr;
	    newMenuPtr->masterMenuPtr = masterMenuPtr;
	}

	/*
	 * Add the master menu's window to the bind tags for this window after
	 * this window's tag. This is so the user can bind to either this
	 * clone (which may not be easy to do) or the entire menu clone
	 * structure.
	 */

	newObjv[0] = Tcl_NewStringObj("bindtags", -1);
	newObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1);
	Tcl_IncrRefCount(newObjv[0]);
	Tcl_IncrRefCount(newObjv[1]);
	if (Tk_BindtagsObjCmd(newMenuPtr->tkwin, newMenuPtr->interp, 2,
		newObjv) == TCL_OK) {
	    const char *windowName;
	    Tcl_Obj *bindingsPtr =
		    Tcl_DuplicateObj(Tcl_GetObjResult(newMenuPtr->interp));
	    Tcl_Obj *elementPtr;

	    Tcl_IncrRefCount(bindingsPtr);
	    Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements);
	    for (i = 0; i < numElements; i++) {
		Tcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i,
			&elementPtr);
		windowName = Tcl_GetString(elementPtr);
		if (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin))
			== 0) {
		    Tcl_Obj *newElementPtr = Tcl_NewStringObj(
			    Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1);

		    /*
		     * The newElementPtr will have its refCount incremented
		     * here, so we don't need to worry about it any more.
		     */

		    Tcl_ListObjReplace(menuPtr->interp, bindingsPtr,
			    i + 1, 0, 1, &newElementPtr);
		    newObjv[2] = bindingsPtr;
		    Tk_BindtagsObjCmd(newMenuPtr->tkwin, menuPtr->interp, 3,
			    newObjv);
		    break;
		}
	    }
	    Tcl_DecrRefCount(bindingsPtr);
	}
	Tcl_DecrRefCount(newObjv[0]);
	Tcl_DecrRefCount(newObjv[1]);
	Tcl_ResetResult(menuPtr->interp);

	/*
	 * Clone all of the cascade menus that this menu points to.
	 */

	for (i = 0; i < menuPtr->numEntries; i++) {
	    TkMenuReferences *cascadeRefPtr;
	    TkMenu *oldCascadePtr;

	    if ((menuPtr->entries[i]->type == CASCADE_ENTRY)
		&& (menuPtr->entries[i]->namePtr != NULL)) {
		cascadeRefPtr =
			TkFindMenuReferencesObj(menuPtr->interp,
			menuPtr->entries[i]->namePtr);
		if ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) {
		    Tcl_Obj *windowNamePtr =
			    Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin),
			    -1);
		    Tcl_Obj *newCascadePtr;

		    oldCascadePtr = cascadeRefPtr->menuPtr;

		    Tcl_IncrRefCount(windowNamePtr);
		    newCascadePtr = TkNewMenuName(menuPtr->interp,
			    windowNamePtr, oldCascadePtr);
		    Tcl_IncrRefCount(newCascadePtr);
		    CloneMenu(oldCascadePtr, newCascadePtr, NULL);

		    newObjv[0] = Tcl_NewStringObj("-menu", -1);
		    newObjv[1] = newCascadePtr;
		    Tcl_IncrRefCount(newObjv[0]);
		    ConfigureMenuEntry(newMenuPtr->entries[i], 2, newObjv);
		    Tcl_DecrRefCount(newObjv[0]);
		    Tcl_DecrRefCount(newCascadePtr);
		    Tcl_DecrRefCount(windowNamePtr);
		}
	    }
	}

	returnResult = TCL_OK;
    } else {
	returnResult = TCL_ERROR;
    }
    Tcl_Release(menuPtr);
    return returnResult;
}

/*
 *----------------------------------------------------------------------
 *
 * MenuDoXPosition --
 *
 *	Given arguments from an option command line, returns the X position.
 *
 * Results:
 *	Returns TCL_OK or TCL_Error
 *
 * Side effects:
 *	xPosition is set to the X-position of the menu entry.
 *
 *----------------------------------------------------------------------
 */

static int
MenuDoXPosition(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    Tcl_Obj *objPtr)
{
    int index;

    TkRecomputeMenu(menuPtr);
    if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_ResetResult(interp);
    if (index < 0) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
    } else {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->x));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * MenuDoYPosition --
 *
 *	Given arguments from an option command line, returns the Y position.
 *
 * Results:
 *	Returns TCL_OK or TCL_Error
 *
 * Side effects:
 *	yPosition is set to the Y-position of the menu entry.
 *
 *----------------------------------------------------------------------
 */

static int
MenuDoYPosition(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    Tcl_Obj *objPtr)
{
    int index;

    TkRecomputeMenu(menuPtr);
    if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
	goto error;
    }
    Tcl_ResetResult(interp);
    if (index < 0) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
    } else {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->y));
    }

    return TCL_OK;

  error:
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * GetIndexFromCoords --
 *
 *	Given a string of the form "@@integer", return the menu item
 *	corresponding to the provided y-coordinate in the menu window.
 *
 * Results:
 *	If int is a valid number, *indexPtr will be the number of the
 *	menuentry that is the correct height. If int is invalid, *indexPtr
 *	will be unchanged. Returns appropriate Tcl error number.
 *
 * Side effects:
 *	If int is invalid, interp's result will be set to NULL.
 *
 *----------------------------------------------------------------------
 */

static int
GetIndexFromCoords(
    Tcl_Interp *interp,		/* Interpreter of menu. */
    TkMenu *menuPtr,		/* The menu we are searching. */
    const char *string,		/* The @@string we are parsing. */
    int *indexPtr)		/* The index of the item that matches. */
{
    int x, y, i;
    const char *p;
    char *end;
    int x2, borderwidth, max;

    TkRecomputeMenu(menuPtr);
    p = string + 1;
    y = strtol(p, &end, 0);
    if (end == p) {
	goto error;
    }
    Tk_GetPixelsFromObj(interp, menuPtr->tkwin,
	menuPtr->borderWidthPtr, &borderwidth);
    if (*end == ',') {
	x = y;
	p = end + 1;
	y = strtol(p, &end, 0);
	if (end == p) {
	    goto error;
	}
    } else {
	x = borderwidth;
    }

    *indexPtr = -1;

    /* set the width of the final column to the remainder of the window 
     * being aware of windows that may not be mapped yet.
     */
    max = Tk_IsMapped(menuPtr->tkwin) 
      ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin);
    max -= borderwidth;

    for (i = 0; i < menuPtr->numEntries; i++) {
	if (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) {
	    x2 = max;
	} else {
	    x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width;
	}
	if ((x >= menuPtr->entries[i]->x) && (y >= menuPtr->entries[i]->y)
		&& (x < x2)
		&& (y < (menuPtr->entries[i]->y
		+ menuPtr->entries[i]->height))) {
	    *indexPtr = i;
	    break;
	}
    }
    return TCL_OK;

  error:
    Tcl_ResetResult(interp);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * RecursivelyDeleteMenu --
 *
 *	Deletes a menu and any cascades underneath it. Used for deleting
 *	instances when a menu is no longer being used as a menubar, for
 *	instance.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Destroys the menu and all cascade menus underneath it.
 *
 *----------------------------------------------------------------------
 */

static void
RecursivelyDeleteMenu(
    TkMenu *menuPtr)		/* The menubar instance we are deleting. */
{
    int i;
    TkMenuEntry *mePtr;

    /*
     * It is not 100% clear that this preserve/release pair is required, but
     * we have added them for safety in this very complex code.
     */

    Tcl_Preserve(menuPtr);

    for (i = 0; i < menuPtr->numEntries; i++) {
    	mePtr = menuPtr->entries[i];
    	if ((mePtr->type == CASCADE_ENTRY)
    		&& (mePtr->childMenuRefPtr != NULL)
    		&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
    	    RecursivelyDeleteMenu(mePtr->childMenuRefPtr->menuPtr);
    	}
    }
    if (menuPtr->tkwin != NULL) {
	Tk_DestroyWindow(menuPtr->tkwin);
    }

    Tcl_Release(menuPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TkNewMenuName --
 *
 *	Makes a new unique name for a cloned menu. Will be a child of oldName.
 *
 * Results:
 *	Returns a char * which has been allocated; caller must free.
 *
 * Side effects:
 *	Memory is allocated.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TkNewMenuName(
    Tcl_Interp *interp,		/* The interp the new name has to live in.*/
    Tcl_Obj *parentPtr,		/* The prefix path of the new name. */
    TkMenu *menuPtr)		/* The menu we are cloning. */
{
    Tcl_Obj *resultPtr = NULL;	/* Initialization needed only to prevent
				 * compiler warning. */
    Tcl_Obj *childPtr;
    char *destString;
    int i;
    int doDot;
    Tcl_CmdInfo cmdInfo;
    Tcl_HashTable *nameTablePtr = NULL;
    TkWindow *winPtr = (TkWindow *) menuPtr->tkwin;
    const char *parentName = Tcl_GetString(parentPtr);

    if (winPtr->mainPtr != NULL) {
	nameTablePtr = &(winPtr->mainPtr->nameTable);
    }

    doDot = parentName[strlen(parentName) - 1] != '.';

    childPtr = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
    for (destString = Tcl_GetString(childPtr);
    	    *destString != '\0'; destString++) {
    	if (*destString == '.') {
    	    *destString = '#';
    	}
    }

    for (i = 0; ; i++) {
    	if (i == 0) {
	    resultPtr = Tcl_DuplicateObj(parentPtr);
    	    if (doDot) {
		Tcl_AppendToObj(resultPtr, ".", -1);
    	    }
	    Tcl_AppendObjToObj(resultPtr, childPtr);
    	} else {
	    Tcl_Obj *intPtr;

	    Tcl_DecrRefCount(resultPtr);
	    resultPtr = Tcl_DuplicateObj(parentPtr);
	    if (doDot) {
		Tcl_AppendToObj(resultPtr, ".", -1);
	    }
	    Tcl_AppendObjToObj(resultPtr, childPtr);
	    intPtr = Tcl_NewIntObj(i);
	    Tcl_AppendObjToObj(resultPtr, intPtr);
	    Tcl_DecrRefCount(intPtr);
    	}
	destString = Tcl_GetString(resultPtr);
    	if ((Tcl_GetCommandInfo(interp, destString, &cmdInfo) == 0)
		&& ((nameTablePtr == NULL)
		|| (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) {
    	    break;
    	}
    }
    Tcl_DecrRefCount(childPtr);
    return resultPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkSetWindowMenuBar --
 *
 *	Associates a menu with a window. Called by ConfigureFrame in in
 *	response to a "-menu .foo" configuration option for a top level.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The old menu clones for the menubar are thrown away, and a handler is
 *	set up to allocate the new ones.
 *
 *----------------------------------------------------------------------
 */

void
TkSetWindowMenuBar(
    Tcl_Interp *interp,		/* The interpreter the toplevel lives in. */
    Tk_Window tkwin,		/* The toplevel window. */
    const char *oldMenuName, /* The name of the menubar previously set in
    				 * this toplevel. NULL means no menu was set
    				 * previously. */
    const char *menuName)	/* The name of the new menubar that the
				 * toplevel needs to be set to. NULL means
				 * that their is no menu now. */
{
    TkMenuTopLevelList *topLevelListPtr, *prevTopLevelPtr;
    TkMenu *menuPtr;
    TkMenuReferences *menuRefPtr;

    /*
     * Destroy the menubar instances of the old menu. Take this window out of
     * the old menu's top level reference list.
     */

    if (oldMenuName != NULL) {
	menuRefPtr = TkFindMenuReferences(interp, oldMenuName);
	if (menuRefPtr != NULL) {
	    /*
	     * Find the menubar instance that is to be removed. Destroy it and
	     * all of the cascades underneath it.
	     */

	    if (menuRefPtr->menuPtr != NULL) {
		TkMenu *instancePtr;

		menuPtr = menuRefPtr->menuPtr;

		for (instancePtr = menuPtr->masterMenuPtr;
			instancePtr != NULL;
			instancePtr = instancePtr->nextInstancePtr) {
		    if (instancePtr->menuType == MENUBAR
			    && instancePtr->parentTopLevelPtr == tkwin) {
			RecursivelyDeleteMenu(instancePtr);
			break;
		    }
		}
	    }

	    /*
	     * Now we need to remove this toplevel from the list of toplevels
	     * that reference this menu.
	     */

	    topLevelListPtr = menuRefPtr->topLevelListPtr;
	    prevTopLevelPtr = NULL;

	    while ((topLevelListPtr != NULL)
		    && (topLevelListPtr->tkwin != tkwin)) {
		prevTopLevelPtr = topLevelListPtr;
		topLevelListPtr = topLevelListPtr->nextPtr;
	    }

	    /*
	     * Now we have found the toplevel reference that matches the
	     * tkwin; remove this reference from the list.
	     */

	    if (topLevelListPtr != NULL) {
		if (prevTopLevelPtr == NULL) {
		    menuRefPtr->topLevelListPtr =
			    menuRefPtr->topLevelListPtr->nextPtr;
		} else {
		    prevTopLevelPtr->nextPtr = topLevelListPtr->nextPtr;
		}
		ckfree((char *) topLevelListPtr);
		TkFreeMenuReferences(menuRefPtr);
	    }
	}
    }

    /*
     * Now, add the clone references for the new menu.
     */

    if (menuName != NULL && menuName[0] != 0) {
	TkMenu *menuBarPtr = NULL;

	menuRefPtr = TkCreateMenuReferences(interp, menuName);

	menuPtr = menuRefPtr->menuPtr;
	if (menuPtr != NULL) {
	    Tcl_Obj *cloneMenuPtr;
	    TkMenuReferences *cloneMenuRefPtr;
	    Tcl_Obj *newObjv[4];
	    Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin),
		    -1);
	    Tcl_Obj *menubarPtr = Tcl_NewStringObj("menubar", -1);

	    /*
	     * Clone the menu and all of the cascades underneath it.
	     */

	    Tcl_IncrRefCount(windowNamePtr);
	    cloneMenuPtr = TkNewMenuName(interp, windowNamePtr,
		    menuPtr);
	    Tcl_IncrRefCount(cloneMenuPtr);
	    Tcl_IncrRefCount(menubarPtr);
	    CloneMenu(menuPtr, cloneMenuPtr, menubarPtr);

	    cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr);
	    if ((cloneMenuRefPtr != NULL)
		    && (cloneMenuRefPtr->menuPtr != NULL)) {
		Tcl_Obj *cursorPtr = Tcl_NewStringObj("-cursor", -1);
		Tcl_Obj *nullPtr = Tcl_NewObj();
		cloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin;
		menuBarPtr = cloneMenuRefPtr->menuPtr;
		newObjv[0] = cursorPtr;
		newObjv[1] = nullPtr;
		Tcl_IncrRefCount(cursorPtr);
		Tcl_IncrRefCount(nullPtr);
		ConfigureMenu(menuPtr->interp, cloneMenuRefPtr->menuPtr,
			2, newObjv);
		Tcl_DecrRefCount(cursorPtr);
		Tcl_DecrRefCount(nullPtr);
	    }

	    TkpSetWindowMenuBar(tkwin, menuBarPtr);
	    Tcl_DecrRefCount(cloneMenuPtr);
	    Tcl_DecrRefCount(menubarPtr);
	    Tcl_DecrRefCount(windowNamePtr);
	} else {
	    TkpSetWindowMenuBar(tkwin, NULL);
	}

	/*
	 * Add this window to the menu's list of windows that refer to this
	 * menu.
	 */

	topLevelListPtr = (TkMenuTopLevelList *)
		ckalloc(sizeof(TkMenuTopLevelList));
	topLevelListPtr->tkwin = tkwin;
	topLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr;
	menuRefPtr->topLevelListPtr = topLevelListPtr;
    } else {
	TkpSetWindowMenuBar(tkwin, NULL);
    }
    TkpSetMainMenubar(interp, tkwin, menuName);
}

/*
 *----------------------------------------------------------------------
 *
 * DestroyMenuHashTable --
 *
 *	Called when an interp is deleted and a menu hash table has been set in
 *	it.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The hash table is destroyed.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyMenuHashTable(
    ClientData clientData,	/* The menu hash table we are destroying. */
    Tcl_Interp *interp)		/* The interpreter we are destroying. */
{
    Tcl_DeleteHashTable(clientData);
    ckfree(clientData);
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetMenuHashTable --
 *
 *	For a given interp, give back the menu hash table that goes with it.
 *	If the hash table does not exist, it is created.
 *
 * Results:
 *	Returns a hash table pointer.
 *
 * Side effects:
 *	A new hash table is created if there were no table in the interp
 *	originally.
 *
 *----------------------------------------------------------------------
 */

Tcl_HashTable *
TkGetMenuHashTable(
    Tcl_Interp *interp)		/* The interp we need the hash table in.*/
{
    Tcl_HashTable *menuTablePtr;

    menuTablePtr = (Tcl_HashTable *)
	    Tcl_GetAssocData(interp, MENU_HASH_KEY, NULL);
    if (menuTablePtr == NULL) {
	menuTablePtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(menuTablePtr, TCL_STRING_KEYS);
	Tcl_SetAssocData(interp, MENU_HASH_KEY, DestroyMenuHashTable,
		menuTablePtr);
    }
    return menuTablePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkCreateMenuReferences --
 *
 *	Given a pathname, gives back a pointer to a TkMenuReferences
 *	structure. If a reference is not already in the hash table, one is
 *	created.
 *
 * Results:
 *	Returns a pointer to a menu reference structure. Should not be freed
 *	by calller; when a field of the reference is cleared,
 *	TkFreeMenuReferences should be called.
 *
 * Side effects:
 *	A new hash table entry is created if there were no references to the
 *	menu originally.
 *
 *----------------------------------------------------------------------
 */

TkMenuReferences *
TkCreateMenuReferences(
    Tcl_Interp *interp,
    const char *pathName)		/* The path of the menu widget. */
{
    Tcl_HashEntry *hashEntryPtr;
    TkMenuReferences *menuRefPtr;
    int newEntry;
    Tcl_HashTable *menuTablePtr = TkGetMenuHashTable(interp);

    hashEntryPtr = Tcl_CreateHashEntry(menuTablePtr, pathName, &newEntry);
    if (newEntry) {
    	menuRefPtr = (TkMenuReferences *) ckalloc(sizeof(TkMenuReferences));
    	menuRefPtr->menuPtr = NULL;
    	menuRefPtr->topLevelListPtr = NULL;
    	menuRefPtr->parentEntryPtr = NULL;
    	menuRefPtr->hashEntryPtr = hashEntryPtr;
    	Tcl_SetHashValue(hashEntryPtr, menuRefPtr);
    } else {
    	menuRefPtr = Tcl_GetHashValue(hashEntryPtr);
    }
    return menuRefPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkFindMenuReferences --
 *
 *	Given a pathname, gives back a pointer to the TkMenuReferences
 *	structure.
 *
 * Results:
 *	Returns a pointer to a menu reference structure. Should not be freed
 *	by calller; when a field of the reference is cleared,
 *	TkFreeMenuReferences should be called. Returns NULL if no reference
 *	with this pathname exists.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkMenuReferences *
TkFindMenuReferences(
    Tcl_Interp *interp,		/* The interp the menu is living in. */
    const char *pathName)	/* The path of the menu widget. */
{
    Tcl_HashEntry *hashEntryPtr;
    TkMenuReferences *menuRefPtr = NULL;
    Tcl_HashTable *menuTablePtr;

    menuTablePtr = TkGetMenuHashTable(interp);
    hashEntryPtr = Tcl_FindHashEntry(menuTablePtr, pathName);
    if (hashEntryPtr != NULL) {
    	menuRefPtr = Tcl_GetHashValue(hashEntryPtr);
    }
    return menuRefPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkFindMenuReferencesObj --
 *
 *	Given a pathname, gives back a pointer to the TkMenuReferences
 *	structure.
 *
 * Results:
 *	Returns a pointer to a menu reference structure. Should not be freed
 *	by calller; when a field of the reference is cleared,
 *	TkFreeMenuReferences should be called. Returns NULL if no reference
 *	with this pathname exists.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkMenuReferences *
TkFindMenuReferencesObj(
    Tcl_Interp *interp,		/* The interp the menu is living in. */
    Tcl_Obj *objPtr)		/* The path of the menu widget. */
{
    const char *pathName = Tcl_GetString(objPtr);
    return TkFindMenuReferences(interp, pathName);
}

/*
 *----------------------------------------------------------------------
 *
 * TkFreeMenuReferences --
 *
 *	This is called after one of the fields in a menu reference is cleared.
 *	It cleans up the ref if it is now empty.
 *
 * Results:
 *	Returns 1 if the references structure was freed, and 0 otherwise.
 *
 * Side effects:
 *	If this is the last field to be cleared, the menu ref is taken out of
 *	the hash table.
 *
 *----------------------------------------------------------------------
 */

int
TkFreeMenuReferences(
    TkMenuReferences *menuRefPtr)
				/* The menu reference to free. */
{
    if ((menuRefPtr->menuPtr == NULL)
    	    && (menuRefPtr->parentEntryPtr == NULL)
    	    && (menuRefPtr->topLevelListPtr == NULL)) {
    	Tcl_DeleteHashEntry(menuRefPtr->hashEntryPtr);
    	ckfree((char *) menuRefPtr);
	return 1;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteMenuCloneEntries --
 *
 *	For every clone in this clone chain, delete the menu entries given by
 *	the parameters.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The appropriate entries are deleted from all clones of this menu.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteMenuCloneEntries(
    TkMenu *menuPtr,		/* The menu the command was issued with. */
    int	first,			/* The zero-based first entry in the set of
				 * entries to delete. */
    int last)			/* The zero-based last entry. */
{
    TkMenu *menuListPtr;
    int numDeleted, i, j;

    numDeleted = last + 1 - first;
    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
	    menuListPtr = menuListPtr->nextInstancePtr) {
	for (i = last; i >= first; i--) {
	    Tcl_EventuallyFree(menuListPtr->entries[i], DestroyMenuEntry);
	}
	for (i = last + 1; i < menuListPtr->numEntries; i++) {
	    j = i - numDeleted;
	    menuListPtr->entries[j] = menuListPtr->entries[i];
	    menuListPtr->entries[j]->index = j;
	}
	menuListPtr->numEntries -= numDeleted;
	if (menuListPtr->numEntries == 0) {
	    ckfree((char *) menuListPtr->entries);
	    menuListPtr->entries = NULL;
	}
	if ((menuListPtr->active >= first)
		&& (menuListPtr->active <= last)) {
	    menuListPtr->active = -1;
	} else if (menuListPtr->active > last) {
	    menuListPtr->active -= numDeleted;
	}
	TkEventuallyRecomputeMenu(menuListPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkMenuCleanup --
 *
 *	Resets menusInitialized to allow Tk to be finalized and reused without
 *	the DLL being unloaded.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TkMenuCleanup(
    ClientData unused)
{
    menusInitialized = 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMenuInit --
 *
 *	Sets up the hash tables and the variables used by the menu package.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	lastMenuID gets initialized, and the parent hash and the command hash
 *	are allocated.
 *
 *----------------------------------------------------------------------
 */

void
TkMenuInit(void)
{
    ThreadSpecificData *tsdPtr =
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!menusInitialized) {
	Tcl_MutexLock(&menuMutex);
	if (!menusInitialized) {
	    TkpMenuInit();
	    menusInitialized = 1;
	}

	/*
	 * Make sure we cleanup on finalize.
	 */

	TkCreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL);
	Tcl_MutexUnlock(&menuMutex);
    }
    if (!tsdPtr->menusInitialized) {
	TkpMenuThreadInit();
	tsdPtr->menusInitialized = 1;
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
@


1.60
log
@CONSTify TkCopyAndGlobalEval, TkpSetMainMenubar,
TkpMenuNotifyToplevelCreate, and TkSetWindowMenuBar
Bring Tk_CreateBinding doc and signature (param name) in line.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.59 2010/02/17 20:58:32 jenglish Exp $
d1214 1
a1214 1
	Tcl_Panic("Attempting to delete master menu when there are still clones.");
d2483 1
a2483 1
		    Tcl_Panic("CloneMenu failed inside of MenuAddOrInsert.");
@


1.59
log
@generic/tkMenu.c: Defer TkMenuOptionTables cleanup to CallWhenDeleted() time,
to ensure that the record doesn't get freed until after all widget
instance commands have been deleted (Fixes [Bug#2952745]).
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.58 2010/01/18 20:43:38 nijtmans Exp $
d3167 1
a3167 1
    char *oldMenuName,		/* The name of the menubar previously set in
d3170 1
a3170 1
    char *menuName)		/* The name of the new menubar that the
@


1.58
log
@fix more gcc warnings: missing initializer
Apply patch [#2932808]: Canvas items
not updating on widget state change
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.57 2010/01/13 23:08:09 nijtmans Exp $
d401 2
a402 1
    ClientData clientData)
d430 2
a431 2
    Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr,
	    FreeOptionTables);
@


1.57
log
@Eliminate tkpMenubuttonClass
make tkpButtonProcs CONST
fix gcc warnings: missing initializer
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.56 2010/01/05 09:40:46 dkf Exp $
d120 1
a120 1
	TK_OPTION_NULL_OK},
d123 1
a123 1
	Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK},
d126 1
a126 1
	Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK},
d129 1
a129 1
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
d132 1
a132 1
	Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK},
d135 1
a135 1
	-1, Tk_Offset(TkMenuEntry, columnBreak)},
d138 1
a138 1
	Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK},
d144 1
a144 1
	Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK},
d147 1
a147 1
	Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK},
d150 1
a150 1
	-1, Tk_Offset(TkMenuEntry, hideMargin)},
d153 1
a153 1
	Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK},
d156 1
a156 1
	Tk_Offset(TkMenuEntry, labelPtr), -1, 0},
d160 1
a160 1
	(ClientData) menuStateStrings},
d162 2
a163 2
	DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline)},
    {TK_OPTION_END}
d169 2
a170 2
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_END}
d176 1
a176 1
	-1, Tk_Offset(TkMenuEntry, indicatorOn)},
d179 1
a179 1
	Tk_Offset(TkMenuEntry, offValuePtr), -1},
d182 1
a182 1
	Tk_Offset(TkMenuEntry, onValuePtr), -1},
d185 1
a185 1
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK},
d188 1
a188 1
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
d191 1
a191 1
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK},
d193 1
a193 1
	NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
d199 1
a199 1
	-1, Tk_Offset(TkMenuEntry, indicatorOn)},
d202 1
a202 1
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK},
d205 1
a205 1
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
d208 1
a208 1
	Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK},
d211 1
a211 1
	Tk_Offset(TkMenuEntry, namePtr), -1, 0},
d213 1
a213 1
	NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
d219 1
a219 1
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK},
d221 1
a221 1
	NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
d227 1
a227 1
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
d230 2
a231 2
	(ClientData) menuStateStrings},
    {TK_OPTION_END}
d252 1
a252 1
	(ClientData) DEF_MENU_ACTIVE_BG_MONO},
d255 1
a255 1
	Tk_Offset(TkMenu, activeBorderWidthPtr), -1},
d259 1
a259 1
	(ClientData) DEF_MENU_ACTIVE_FG_MONO},
d262 1
a262 1
	(ClientData) DEF_MENU_BG_MONO},
d264 1
a264 1
	NULL, 0, -1, 0, (ClientData) "-borderwidth"},
d266 1
a266 1
	NULL, 0, -1, 0, (ClientData) "-background"},
d269 1
a269 1
	Tk_Offset(TkMenu, borderWidthPtr), -1, 0},
d272 1
a272 1
	Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK},
d276 1
a276 1
	(ClientData) DEF_MENU_DISABLED_FG_MONO},
d278 1
a278 1
	NULL, 0, -1, 0, (ClientData) "-foreground"},
d280 1
a280 1
	DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1},
d282 1
a282 1
	DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1},
d285 1
a285 1
	Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK},
d287 1
a287 1
	DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1},
d290 1
a290 1
	(ClientData) DEF_MENU_SELECT_MONO},
d293 1
a293 1
	Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK},
d295 1
a295 1
	DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff)},
d298 1
a298 1
	Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK},
d301 1
a301 1
	TK_OPTION_NULL_OK},
d304 2
a305 2
	(ClientData) menuTypeStrings},
    {TK_OPTION_END}
@


1.56
log
@[Bug 220950]: Don't delete the last menu entry when it is obvious that is not
what was intended.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.55 2010/01/02 22:52:38 dkf Exp $
d376 1
a376 1
static Tk_ClassProcs menuClass = {
d378 3
a380 1
    MenuWorldChanged		/* worldChangedProc */
@


1.55
log
@SMALL FIX: Remove useless explicit casts now that we require C89 or later.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.54 2009/12/30 00:24:27 patthoyts Exp $
d781 12
a792 1
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first) != TCL_OK) {
@


1.54
log
@Patch 2879789: Make torn-off menu entrys activate across whole window

The torn-off menu entries do not activate except immediately over the
label or icon. If the window containing the torn-off menu is expanded
then a lot of dead space may be created, including the cascade arrow.
This patch fixes this making the whole width for any menu entry capable
of activation when the pointer hovers over the item.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.53 2009/12/09 10:45:30 dkf Exp $
d1616 1
a1616 1
		if (((TkMenu*) tkwin)->menuType == MENUBAR) {
@


1.53
log
@Improve generation of EWMH hints for windows.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.52 2009/09/07 07:29:04 das Exp $
d2931 2
a2932 2
 *	Given a string of the form "@@int", return the menu item corresponding
 *	to int.
d2936 1
a2936 1
 *	menuentry that is the correct height. If int is invaled, *indexPtr
d2940 1
a2940 1
 *	If int is invalid, interp's result will set to NULL.
d2955 1
d2963 2
d2973 1
a2973 2
	Tk_GetPixelsFromObj(interp, menuPtr->tkwin,
		menuPtr->borderWidthPtr, &x);
d2976 9
d2986 5
d2992 1
a2992 1
		&& (x < (menuPtr->entries[i]->x + menuPtr->entries[i]->width))
d2995 1
a2998 5
    if (i >= menuPtr->numEntries) {
	/* i = menuPtr->numEntries - 1; */
	i = -1;
    }
    *indexPtr = i;
@


1.52
log
@	* generic/tkFocus.c:	fix potential null dereference flagged by clang
	* generic/tkMenu.c:	static analyzer.
	* generic/tkTextBTree.c:
	* generic/tkTextDisp.c:
	* generic/tkTextIndex.c:

	* generic/tkConsole.c:	silence false positives from clang static
	* generic/tkTest.c:	analyzer about potential null dereference.
	* generic/tkText.c:
	* generic/tkTextBTree.c:
	* generic/tkTextTag.c:
	* generic/tkVisual.c:
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.51 2009/04/10 16:16:02 das Exp $
d344 3
a346 2
static int		GetIndexFromCoords(Tcl_Interp *interp, TkMenu *menuPtr,
			    const char *string, int *indexPtr);
d409 2
a410 2
    TkMenuOptionTables *optionTablesPtr =
	    (TkMenuOptionTables *) ckalloc(sizeof(TkMenuOptionTables));
d479 2
a480 2
	if (Tcl_GetIndexFromObj(NULL, objv[i], typeStringList, NULL, 0, &index)
		!= TCL_ERROR) {
d583 1
a583 1
		newObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
d716 1
a716 1
	if (MenuAddOrInsert(interp, menuPtr, NULL, objc-2, objv+2) != TCL_OK) {
d889 2
a890 1
	    Tcl_WrongNumArgs(interp, 2, objv, "index type ?-option value ...?");
d1227 1
d1437 2
a1443 2
	    TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr;

d1601 20
a1620 1
		TkpMakeMenuWindow(menuListPtr->tkwin, 1);
d1622 1
a1622 1
		TkpMakeMenuWindow(menuListPtr->tkwin, 0);
a1625 1

d1636 2
a1637 2
			 cleanupPtr != menuListPtr;
			 cleanupPtr = cleanupPtr->nextInstancePtr) {
d2282 2
a2283 2
    newEntries = (TkMenuEntry **) ckalloc((unsigned)
	    ((menuPtr->numEntries+1)*sizeof(TkMenuEntry *)));
d2385 1
@


1.51
log
@	* generic/tkMenu.c (PostProcessEntry): delay call to
	TkpConfigureMenuEntry() until all menu entry attributes are setup.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.50 2009/02/06 08:12:07 das Exp $
d2063 1
a2063 1
	    if (cascadeMenuRefPtr->menuPtr != NULL) {
@


1.50
log
@	* generic/tkImgPhInstance.c:	fix numerous leaks discovered with the
	* generic/tkMenu.c:		Mac OS X Instruments.app Leaks tool.
	* generic/tkText.c:
	* generic/tkTextImage.c:
	* generic/tkTextIndex.c:
	* generic/tkUndo.c:
	* generic/tkUtil.c:
	* generic/ttk/ttkFrame.c:
	* macosx/tkMacOSXWm.c:
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.49 2009/01/14 22:48:10 nijtmans Exp $
a1786 4
    if (TkpConfigureMenuEntry(mePtr) != TCL_OK) {
    	return TCL_ERROR;
    }

d1883 4
@


1.49
log
@- fix for aMSN compatibility [tcl-Bug 2507326]
- CONSTify Tk(Create|Find)menuReferences
- various internal "const" decorations
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.48 2008/11/27 23:26:05 nijtmans Exp $
d396 7
d426 2
a427 1
    Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr, NULL);
@


1.48
log
@elminate warning: unused variable 'tkwin'
Replace Tcl_SetResult(interp, NULL, ....) calls
with Tcl_ResetResult(interp) everywhere
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.47 2008/11/08 22:52:29 dkf Exp $
d345 1
a345 1
			    char *string, int *indexPtr);
d457 1
a457 1
    char *windowName;
d1470 1
a1470 1
	char *varName = Tcl_GetString(mePtr->namePtr);
d1693 1
a1693 1
    char *name;
d1790 1
a1790 1
	char *imageString = Tcl_GetString(mePtr->imagePtr);
d1805 1
a1805 1
	char *selectImageString = Tcl_GetString(mePtr->selectImagePtr);
d1823 1
a1823 1
	char *name;
d1857 2
a1858 2
		char *value = Tcl_GetString(valuePtr);
		char *onValue = Tcl_GetString(mePtr->onValuePtr);
d1920 1
a1920 1
	char *name = Tcl_GetString(mePtr->namePtr);
d1978 1
a1978 1
    char *newCascadeName;
d2002 1
a2002 1
	char *oldCascadeName;
d2118 1
a2118 1
    char *string = Tcl_GetString(objPtr);
d2162 1
a2162 1
	char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr);
d2355 1
a2355 1
	char *indexString = Tcl_GetString(indexPtr);
d2485 1
a2485 1
    char *name, *onValue;
d2737 1
a2737 1
	    char *windowName;
d2919 1
a2919 1
    char *string,		/* The @@string we are parsing. */
d2923 2
a2924 1
    char *p, *end;
d3042 1
a3042 1
    char *parentName = Tcl_GetString(parentPtr);
d3338 1
a3338 1
    char *pathName)		/* The path of the menu widget. */
d3382 1
a3382 1
    char *pathName)		/* The path of the menu widget. */
d3421 1
a3421 1
    char *pathName = Tcl_GetString(objPtr);
@


1.47
log
@More small changes to use C89 better and manage the result more efficiently.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.46 2008/10/30 23:18:59 nijtmans Exp $
d2157 1
a2157 1
	Tcl_SetResult(interp, NULL, TCL_STATIC);
d2959 1
a2959 1
    Tcl_SetResult(interp, NULL, TCL_STATIC);
@


1.46
log
@more internal -Wwrite-strings warning fixes
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.45 2008/10/17 23:18:37 nijtmans Exp $
d636 1
a636 1
    Tcl_SetResult(interp, Tk_PathName(menuPtr->tkwin), TCL_STATIC);
@


1.45
log
@Add "const" to many internal
const tables, so those will be
put by the C-compiler in the
TEXT segment in stead of the
DATA segment. This makes those
table sharable in shared libraries.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.44 2008/10/05 18:22:21 dkf Exp $
d113 1
a113 1
static char *const compoundStrings[] = {
@


1.44
log
@Greatly clean up Tk's handling of the writability of the Tcl result object.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.43 2008/07/23 23:24:23 nijtmans Exp $
d102 1
a102 1
char *tkMenuStateStrings[] = {"active", "normal", "disabled", NULL};
d104 1
a104 1
static const char *menuEntryTypeStrings[] = {
d113 1
a113 1
static char *compoundStrings[] = {
d160 1
a160 1
	(ClientData) tkMenuStateStrings},
d230 1
a230 1
	(ClientData) tkMenuStateStrings},
d244 1
a244 1
static const char *menuTypeStrings[] = {
d313 1
a313 1
static const char *menuOptions[] = {
d458 1
a458 1
    static const char *typeStringList[] = {"-type", NULL};
@


1.43
log
@fix [2021443] inconsistant "wrong # args" messages (for Tk)
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.42 2008/04/27 22:38:56 dkf Exp $
d874 1
a874 1
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
d962 2
a963 2
	    Tcl_SetStringObj(Tcl_GetObjResult(interp),
		    menuEntryTypeStrings[menuPtr->entries[index]->type], -1);
@


1.42
log
@Get rid of pre-C89-isms (esp. CONST vs const).
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.41 2007/12/13 15:24:15 dgp Exp $
d462 1
a462 1
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
d671 1
a671 1
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
d703 1
a703 1
	    Tcl_WrongNumArgs(interp, 2, objv, "type ?options?");
d825 1
a825 1
	    Tcl_WrongNumArgs(interp, 2, objv, "index ?option value ...?");
d880 1
a880 1
	    Tcl_WrongNumArgs(interp, 2, objv, "index type ?options?");
@


1.41
log
@merge stable branch onto HEAD
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.38.2.2 2007/09/07 01:25:35 dgp Exp $
d104 1
a104 1
static CONST char *menuEntryTypeStrings[] = {
d313 1
a313 1
static CONST char *menuOptions[] = {
d332 1
a332 1
			    int objc, Tcl_Obj *CONST objv[]);
d335 1
a335 1
			    int objc, Tcl_Obj *CONST objv[]);
d337 1
a337 1
			    int objc, Tcl_Obj *CONST objv[]);
d352 1
a352 1
			    Tcl_Obj *CONST objv[]);
d354 1
a354 1
			    int objc, Tcl_Obj *CONST objv[]);
d358 2
a359 2
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags);
d362 1
a362 1
			    Tcl_Obj *CONST objv[]);
d419 1
a419 2
    Tcl_CreateObjCommand(interp, "menu", MenuCmd,
	    (ClientData) optionTablesPtr, NULL);
d450 1
a450 1
    Tcl_Obj *CONST objv[])	/* Argument strings. */
d458 2
a459 2
    static CONST char *typeStringList[] = {"-type", NULL};
    TkMenuOptionTables *optionTablesPtr = (TkMenuOptionTables *) clientData;
d499 2
a500 2
	    Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd,
	    (ClientData) menuPtr, MenuCmdDeletedProc);
d509 1
a509 1
    Tk_SetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
d512 1
a512 1
	    TkMenuEventProc, (ClientData) menuPtr);
d663 1
a663 1
    Tcl_Obj *CONST objv[])	/* Argument strings. */
d665 1
a665 1
    register TkMenu *menuPtr = (TkMenu *) clientData;
d678 1
a678 1
    Tcl_Preserve((ClientData) menuPtr);
d810 1
a810 1
	Tcl_Preserve((ClientData) mePtr);
d813 1
a813 1
	Tcl_Release((ClientData) mePtr);
d835 1
a835 1
	Tcl_Preserve((ClientData) mePtr);
d858 1
a858 1
	Tcl_Release((ClientData) mePtr);
d991 1
a991 1
    Tcl_Release((ClientData) menuPtr);
d995 1
a995 1
    Tcl_Release((ClientData) menuPtr);
d1034 2
a1035 1
    Tcl_Preserve((ClientData) mePtr);
d1038 1
d1091 2
a1092 1
    Tcl_Release((ClientData) mePtr);
d1474 1
a1474 1
		MenuVarProc, (ClientData) mePtr);
d1504 1
a1504 1
    TkMenu *menuPtr = (TkMenu *) instanceData;
d1541 1
a1541 1
    Tcl_Obj *CONST objv[])	/* Arguments. */
d1625 1
a1625 2
	    Tcl_EventuallyFree((ClientData) menuListPtr->entries[0],
	    	    DestroyMenuEntry);
d1793 1
a1793 1
		TkMenuImageProc, (ClientData) mePtr);
d1808 1
a1808 1
		TkMenuSelectImageProc, (ClientData) mePtr);
d1875 1
a1875 1
		    MenuVarProc, (ClientData) mePtr);
d1906 1
a1906 1
    Tcl_Obj *CONST objv[])	/* Arguments. */
d1924 1
a1924 1
		MenuVarProc, (ClientData) mePtr);
d1971 1
a1971 1
    Tcl_Obj *CONST objv[])	/* Arguments. */
d2199 1
a2199 1
    TkMenu *menuPtr = (TkMenu *) clientData;
d2340 1
a2340 1
    Tcl_Obj *CONST objv[])	/* Arguments to command: first arg is type of
d2390 1
a2390 1
    		Tcl_EventuallyFree((ClientData) errorMenuPtr->entries[index],
d2478 2
a2479 2
    CONST char *name1,		/* First part of variable's name. */
    CONST char *name2,		/* Second part of variable's name. */
d2482 1
a2482 1
    TkMenuEntry *mePtr = (TkMenuEntry *) clientData;
d2484 2
a2485 3
    CONST char *value;
    char *name;
    char *onValue;
d2689 1
a2689 1
    Tcl_Preserve((ClientData) menuPtr);
d2735 2
a2736 2
	if (Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin,
		newMenuPtr->interp, 2, newObjv) == TCL_OK) {
d2761 2
a2762 2
		    Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin,
			    menuPtr->interp, 3, newObjv);
d2814 1
a2814 1
    Tcl_Release((ClientData) menuPtr);
d3274 2
a3275 2
    Tcl_DeleteHashTable((Tcl_HashTable *) clientData);
    ckfree((char *) clientData);
d3308 1
a3308 1
		(ClientData) menuTablePtr);
d3351 1
a3351 1
    	Tcl_SetHashValue(hashEntryPtr, (char *) menuRefPtr);
d3353 1
a3353 1
    	menuRefPtr = (TkMenuReferences *) Tcl_GetHashValue(hashEntryPtr);
d3390 1
a3390 1
    	menuRefPtr = (TkMenuReferences *) Tcl_GetHashValue(hashEntryPtr);
d3488 1
a3488 2
	    Tcl_EventuallyFree((ClientData) menuListPtr->entries[i],
		    DestroyMenuEntry);
d3554 1
a3554 1
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
@


1.41.2.1
log
@	* generic/tkImgPhoto.c:		fix numerous leaks discovered with the
	* generic/tkMenu.c:		Mac OS X Instruments.app Leaks tool.
	* generic/tkText.c:
	* generic/tkTextImage.c:
	* generic/tkTextIndex.c:
	* generic/tkUndo.c:
	* generic/ttk/ttkFrame.c:
	* macosx/tkMacOSXWm.c:
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.41 2007/12/13 15:24:15 dgp Exp $
a395 7
static void
FreeOptionTables(
    ClientData clientData)
{
    ckfree(clientData);
}

d420 1
a420 1
	    (ClientData) optionTablesPtr, FreeOptionTables);
@


1.41.2.2
log
@	* generic/tkMenu.c (PostProcessEntry): delay call to
	TkpConfigureMenuEntry() until all menu entry attributes are setup.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.41.2.1 2009/02/06 08:13:23 das Exp $
d1785 4
a1884 4
    if (TkpConfigureMenuEntry(mePtr) != TCL_OK) {
	return TCL_ERROR;
    }

@


1.41.2.3
log
@Patch 2879789: Make torn-off menu entrys activate across whole window
backported from HEAD.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.41.2.2 2009/04/10 16:16:04 das Exp $
d2908 2
a2909 2
 *	Given a string of the form "@@integer", return the menu item
 *	corresponding to the provided y-coordinate in the menu window.
d2913 1
a2913 1
 *	menuentry that is the correct height. If int is invalid, *indexPtr
d2917 1
a2917 1
 *	If int is invalid, interp's result will be set to NULL.
a2930 1
    int x2, borderwidth, max;
a2937 2
    Tk_GetPixelsFromObj(interp, menuPtr->tkwin,
	menuPtr->borderWidthPtr, &borderwidth);
d2946 2
a2947 1
	x = borderwidth;
a2949 9
    *indexPtr = -1;

    /* set the width of the final column to the remainder of the window 
     * being aware of windows that may not be mapped yet.
     */
    max = Tk_IsMapped(menuPtr->tkwin) 
      ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin);
    max -= borderwidth;

a2950 5
	if (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) {
	    x2 = max;
	} else {
	    x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width;
	}
d2952 1
a2952 1
		&& (x < x2)
a2954 1
	    *indexPtr = i;
d2958 5
@


1.41.2.4
log
@[Bug 220950]: Don't delete the last menu entry when it is obvious that is not
what was intended.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.41.2.3 2009/12/30 00:29:38 patthoyts Exp $
d780 1
a780 12

	/*
	 * If 'first' explicitly refers to past the end of the menu, we don't
	 * do anything. [Bug 220950]
	 */

	if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))
		&& Tcl_GetIntFromObj(NULL, objv[2], &first) == TCL_OK) {
	    if (first >= menuPtr->numEntries) {
		goto done;
	    }
	} else if (TkGetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){
@


1.41.2.5
log
@generic/tkMenu.c: Defer TkMenuOptionTables cleanup to CallWhenDeleted() time,
to ensure that the record doesn't get freed until after all widget
instance commands have been deleted (Fixes [Bug#2952745]).
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.41.2.4 2010/01/05 09:44:54 dkf Exp $
d398 1
a398 2
    ClientData clientData,
    Tcl_Interp *interp)
d426 2
a427 2
    Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr, 0);
    Tcl_CallWhenDeleted(interp, FreeOptionTables, optionTablesPtr);
@


1.40
log
@header cleanup
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.39 2007/06/24 16:07:35 dkf Exp $
@


1.39
log
@Cleaning up whitespace, comments, declarations. No functional changes.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.38 2007/01/03 05:06:26 nijtmans Exp $
d77 1
a77 1
#include "tkPort.h"
@


1.38
log
@various "const" additions, in line with TIP #27
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.37 2006/12/04 15:16:30 dkf Exp $
d56 1
a56 1
 * parent-child hierarchy necessary for menubars and toplevels to work.  This
d64 2
a65 2
 * 3. When the menu that a cascade entry points to is changed, the old
 * cloned cascade menu has to be discarded, and the new one has to be cloned.
d83 3
a85 3
    int menusInitialized;       /* Flag indicates whether thread-specific
				 * elements of the Windows Menu module
				 * have been initialized. */
d140 1
a140 1
        DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
d254 2
a255 2
        "BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
        Tk_Offset(TkMenu, activeBorderWidthPtr), -1},
d300 1
a300 1
	DEF_MENU_TITLE,  Tk_Offset(TkMenu, titlePtr), -1,
d457 1
a457 2
    int i, index;
    int toplevel;
d554 3
a556 4
        TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr;
        TkMenuEntry *nextCascadePtr;
        Tcl_Obj *newMenuName;
	Tcl_Obj *newObjv[2];
d558 1
a558 1
        while (cascadeListPtr != NULL) {
d588 1
a588 1
      	    	newMenuName = TkNewMenuName(menuPtr->interp,
d591 1
a591 1
            	CloneMenu(menuPtr, newMenuName, normalPtr);
d593 4
a596 4
                /*
                 * Now we can set the new menu instance to be the cascade
                 * entry of the parent's instance.
                 */
d601 1
a601 1
                ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
d606 3
a608 3
            }
            cascadeListPtr = nextCascadePtr;
        }
a620 1
   	while (topLevelListPtr != NULL) {
d622 1
d1023 1
a1023 1
    				 * invoking */
d1178 12
a1189 12
        for (menuInstancePtr = menuPtr->masterMenuPtr;
        	menuInstancePtr != NULL;
        	menuInstancePtr = menuInstancePtr->nextInstancePtr) {
            if (menuInstancePtr->nextInstancePtr == menuPtr) {
                menuInstancePtr->nextInstancePtr =
                	menuInstancePtr->nextInstancePtr->nextInstancePtr;
                break;
            }
        }
   } else if (menuPtr->nextInstancePtr != NULL) {
       Tcl_Panic("Attempting to delete master menu when there are still clones.");
   }
d1330 1
a1330 1
        return;
d1367 1
a1367 1
	        prevCascadePtr = cascadeEntryPtr,
d1371 1
a1371 1
            	    	cascadeEntryPtr->nextCascadePtr;
d1375 1
a1375 1
        }
d1448 3
a1450 3
	        if (menuRefPtr->menuPtr == destroyThis) {
	            menuRefPtr->menuPtr = NULL;
	        }
d1490 1
a1490 1
 *      None.
d1493 1
a1493 1
 *      Menu will be relayed out and redisplayed.
d1536 2
a1537 2
    register TkMenu *menuPtr,	/* Information about widget;  may or may
				 * not already have values for some fields. */
d2143 1
a2143 1
	if (Tcl_GetInt(interp, string,  &i) == TCL_OK) {
d2257 1
a2257 1
    for (  ; i < menuPtr->numEntries; i++) {
d2419 1
a2419 1
    	        TkMenu *cascadeMenuPtr =
d2421 1
a2421 1
    	        Tcl_Obj *newCascadePtr;
a2425 1
  		Tcl_Obj *newObjv[2];
d2444 2
a2445 2
    	        ConfigureMenuEntry(mePtr, 2, newObjv);
    	        Tcl_DecrRefCount(newCascadePtr);
d2659 2
a2660 2
    TkMenu *menuPtr,		/* The menu we are going to clone */
    Tcl_Obj *newMenuNamePtr,	/* The name to give the new menu */
d2917 4
a2920 4
    Tcl_Interp *interp,		/* interp of menu */
    TkMenu *menuPtr,		/* the menu we are searching */
    char *string,		/* The @@string we are parsing */
    int *indexPtr)		/* The index of the item that matches */
d2983 1
a2983 1
    TkMenu *menuPtr)		/* The menubar instance we are deleting */
d3109 1
a3109 1
    Tk_Window tkwin,		/* The toplevel window */
d3159 1
a3159 1
		   && (topLevelListPtr->tkwin != tkwin)) {
d3271 2
a3272 2
    ClientData clientData,	/* The menu hash table we are destroying */
    Tcl_Interp *interp)		/* The interpreter we are destroying */
d3337 1
a3337 1
    char *pathName)		/* The path of the menu widget */
d3381 1
a3381 1
    char *pathName)		/* The path of the menu widget */
d3418 1
a3418 1
    Tcl_Obj *objPtr)		/* The path of the menu widget */
d3445 1
a3445 1
				/* The menu reference to free */
d3516 2
a3517 2
 *      Resets menusInitialized to allow Tk to be finalized and reused without
 *      the DLL being unloaded.
d3520 1
a3520 1
 *      None.
d3523 1
a3523 1
 *      None.
@


1.38.2.1
log
@merge updates from HEAD
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.38 2007/01/03 05:06:26 nijtmans Exp $
d56 1
a56 1
 * parent-child hierarchy necessary for menubars and toplevels to work. This
d64 2
a65 2
 * 3. When the menu that a cascade entry points to is changed, the old cloned
 * cascade menu has to be discarded, and the new one has to be cloned.
d83 3
a85 3
    int menusInitialized;	/* Flag indicates whether thread-specific
				 * elements of the Windows Menu module have
				 * been initialized. */
d140 1
a140 1
	DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
d254 2
a255 2
	"BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
	Tk_Offset(TkMenu, activeBorderWidthPtr), -1},
d300 1
a300 1
	DEF_MENU_TITLE,	 Tk_Offset(TkMenu, titlePtr), -1,
d457 2
a458 1
    int i, index, toplevel;
d555 4
a558 3
	TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr;
	TkMenuEntry *nextCascadePtr;
	Tcl_Obj *newMenuName, *newObjv[2];
d560 1
a560 1
	while (cascadeListPtr != NULL) {
d590 1
a590 1
		newMenuName = TkNewMenuName(menuPtr->interp,
d593 1
a593 1
		CloneMenu(menuPtr, newMenuName, normalPtr);
d595 4
a598 4
		/*
		 * Now we can set the new menu instance to be the cascade
		 * entry of the parent's instance.
		 */
d603 1
a603 1
		ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
d608 3
a610 3
	    }
	    cascadeListPtr = nextCascadePtr;
	}
d623 1
a624 1
	while (topLevelListPtr != NULL) {
d1025 1
a1025 1
    				 * invoking. */
d1180 12
a1191 12
	for (menuInstancePtr = menuPtr->masterMenuPtr;
		menuInstancePtr != NULL;
		menuInstancePtr = menuInstancePtr->nextInstancePtr) {
	    if (menuInstancePtr->nextInstancePtr == menuPtr) {
		menuInstancePtr->nextInstancePtr =
			menuInstancePtr->nextInstancePtr->nextInstancePtr;
		break;
	    }
	}
    } else if (menuPtr->nextInstancePtr != NULL) {
	Tcl_Panic("Attempting to delete master menu when there are still clones.");
    }
d1332 1
a1332 1
	return;
d1369 1
a1369 1
		prevCascadePtr = cascadeEntryPtr,
d1373 1
a1373 1
			cascadeEntryPtr->nextCascadePtr;
d1377 1
a1377 1
	}
d1450 3
a1452 3
		if (menuRefPtr->menuPtr == destroyThis) {
		    menuRefPtr->menuPtr = NULL;
		}
d1492 1
a1492 1
 *	None.
d1495 1
a1495 1
 *	Menu will be relayed out and redisplayed.
d1538 2
a1539 2
    register TkMenu *menuPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
d2145 1
a2145 1
	if (Tcl_GetInt(interp, string, &i) == TCL_OK) {
d2259 1
a2259 1
    for (; i < menuPtr->numEntries; i++) {
d2421 1
a2421 1
		TkMenu *cascadeMenuPtr =
d2423 1
a2423 1
		Tcl_Obj *newCascadePtr, *newObjv[2];
d2428 1
d2447 2
a2448 2
		ConfigureMenuEntry(mePtr, 2, newObjv);
		Tcl_DecrRefCount(newCascadePtr);
d2662 2
a2663 2
    TkMenu *menuPtr,		/* The menu we are going to clone. */
    Tcl_Obj *newMenuNamePtr,	/* The name to give the new menu. */
d2920 4
a2923 4
    Tcl_Interp *interp,		/* Interpreter of menu. */
    TkMenu *menuPtr,		/* The menu we are searching. */
    char *string,		/* The @@string we are parsing. */
    int *indexPtr)		/* The index of the item that matches. */
d2986 1
a2986 1
    TkMenu *menuPtr)		/* The menubar instance we are deleting. */
d3112 1
a3112 1
    Tk_Window tkwin,		/* The toplevel window. */
d3162 1
a3162 1
		    && (topLevelListPtr->tkwin != tkwin)) {
d3274 2
a3275 2
    ClientData clientData,	/* The menu hash table we are destroying. */
    Tcl_Interp *interp)		/* The interpreter we are destroying. */
d3340 1
a3340 1
    char *pathName)		/* The path of the menu widget. */
d3384 1
a3384 1
    char *pathName)		/* The path of the menu widget. */
d3421 1
a3421 1
    Tcl_Obj *objPtr)		/* The path of the menu widget. */
d3448 1
a3448 1
				/* The menu reference to free. */
d3519 2
a3520 2
 *	Resets menusInitialized to allow Tk to be finalized and reused without
 *	the DLL being unloaded.
d3523 1
a3523 1
 *	None.
d3526 1
a3526 1
 *	None.
@


1.38.2.2
log
@merge updates from HEAD
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.38.2.1 2007/06/25 19:12:13 dgp Exp $
d77 1
a77 1
#include "tkInt.h"
@


1.37
log
@TIP#286 implementation. [Patch 1152376]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.36 2006/05/25 23:50:16 hobbs Exp $
d117 1
a117 1
static Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
d166 1
a166 1
static Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
d173 1
a173 1
static Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
d196 1
a196 1
static Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
d216 1
a216 1
static Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
d224 1
a224 1
static Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
d234 1
a234 1
static Tk_OptionSpec *specsArray[] = {
d244 1
a244 1
static CONST char *menuTypeStrings[] = {
d248 1
a248 1
static Tk_OptionSpec tkMenuConfigSpecs[] = {
@


1.36
log
@	* generic/tkMenu.c (DeleteMenuCloneEntries): Modify entry index
	changes to work around VC6 optimization bug. [Bug 1224330]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.35 2006/04/05 20:59:03 hobbs Exp $
d316 1
a316 1
    "type", "unpost", "yposition", NULL
d322 1
a322 1
    MENU_UNPOST, MENU_YPOSITION
d348 2
d688 1
a688 1
	    Tcl_WrongNumArgs(interp, 1, objv, "activate index");
d706 1
a706 1
	    Tcl_WrongNumArgs(interp, 1, objv, "add type ?options?");
d718 1
a718 1
	    Tcl_WrongNumArgs(interp, 1, objv, "cget option");
d732 1
a732 1
	    Tcl_WrongNumArgs(interp, 1, objv, "clone newMenuName ?menuType?");
d772 1
a772 1
	    Tcl_WrongNumArgs(interp, 1, objv, "delete first ?last?");
d803 1
a803 1
	    Tcl_WrongNumArgs(interp, 1, objv, "entrycget index option");
d828 1
a828 2
	    Tcl_WrongNumArgs(interp, 1, objv,
		    "entryconfigure index ?option value ...?");
d868 1
a868 1
	    Tcl_WrongNumArgs(interp, 1, objv, "index string");
d883 1
a883 1
	    Tcl_WrongNumArgs(interp, 1, objv, "insert index type ?options?");
d894 1
a894 1
	    Tcl_WrongNumArgs(interp, 1, objv, "invoke index");
d910 1
a910 1
	    Tcl_WrongNumArgs(interp, 1, objv, "post x y");
d935 1
a935 1
	    Tcl_WrongNumArgs(interp, 1, objv, "postcascade index");
d953 1
a953 1
	    Tcl_WrongNumArgs(interp, 1, objv, "type index");
d972 1
a972 1
	    Tcl_WrongNumArgs(interp, 1, objv, "unpost");
d978 7
d987 1
a987 1
	    Tcl_WrongNumArgs(interp, 1, objv, "yposition index");
d2824 37
@


1.35
log
@	* generic/tkMenu.c (TkSetWindowMenuBar): remove extra TkMenuInit
	call that caused finalization panic. [Bug 1456851]
	* win/tkWinMenu.c (FreeID, TkpNewMenu, MenuExitHandler)
	(MenuThreadExitHandler, TkpMenuInit, TkpMenuThreadInit): rework
	Windows menu init/finalization to better respect per-process and
	per-thread boundaries. [Bug 1456851]
	(TkWinMenuKeyObjCmd): Do not error when unknown window is passed
	in. [Bug 1236306]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.34 2005/11/27 02:36:14 das Exp $
d3440 1
a3440 1
    int numDeleted, i;
d3450 3
a3452 2
	    menuListPtr->entries[i - numDeleted] = menuListPtr->entries[i];
	    menuListPtr->entries[i - numDeleted]->index = i - numDeleted;
@


1.34
log
@	* unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(),
	add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to
	configure (flag can't be present twice, so can't be in both CFLAGS and
	LDFLAGS during configure), don't use -prebind when deploying on 10.4,
	define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542).
	(SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete
	autoconf macros. Sync with tcl/unix/tcl.m4.

	* unix/configure.in: fix obsolete autoconf macros, sync gratuitous
	formatting/ordering differences with tcl/unix/configure.in.

	* unix/Makefile.in: add CFLAGS to wish/tktest link to make executable
	linking the same as during configure (needed to avoid loosing any linker
	relevant flags in CFLAGS, in particular flags that can't be in LDFLAGS).
	Avoid concurrent linking of wish and compiling of tkTestInit.o during
	parallel make, fix dependencies and flags for building tkMacOSXInit.o
	(checkstubs, checkexports): dependency and Darwin fixes
	(dist): add new macosx files.

	* macosx/tkMacOSXEvent.c (TkMacOSXProcessEvent):
	* macosx/tkMacOSXEvent.h:
	* macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent):
	* macosx/tkMacOSXCarbonEvents.c: install standard application event
	handler, add & call functions to start and stop carbon even timer that
	runs the tcl event loop periodically during a nested carbon event loop
	in the toolbox (e.g. during menutracking) to ensure tcl timers etc
	continue to fire, register app event handler for menu tracking and HI
	command carbon events, move menu event handling to new handlers for
	those carbon events, no longer register for/handle appleevent carbon
	event (now dealt with by standard application event handler), event
	debugging code dynamically acquires carbon event debugging functions to
	allow use on Tiger where they are no longer exported from HIToolbox.

	* macosx/tkMacOSXFont.c (TkMacOSXUseAntialiasedText):
	* macosx/tkMacOSXKeyEvent.c (GetKeyboardLayout):
	* macosx/tkMacOSXCarbonEvents.c (TkMacOSXInitCarbonEvents):
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXInt.h: abstract common code to dynamically acquire
	address of a named symbol (from a loaded dynamic library) into new
	function TkMacOSXGetNamedSymbol() and macro TkMacOSXInitNamedSymbol.

	* macosx/tkMacOSXMenu.c (TkpNewMenu):
	* macosx/tkMacOSXMenubutton.c (MenuButtonInitControl):
	* macosx/tkMacOSXMenus.c (TkMacOSXHandleMenuSelect): switch to  modern
	utf8 aware menu manager API, remove obsolete code, add error handling.

	* macosx/tkMacOSXMouseEvent.c: define OSX 10.3 or later only constants
	if necessary to allow compilation on OSX 10.2

	* macosx/tkMacOSXWm.c (UpdateSizeHints): remove code that is never
	executed.

	* xlib/xgc.c (XCreateGC): sync with core-8-4-branch change.

	* generic/tk.h: add/correct location of version numbers in macosx files.

	* generic/tkInt.h: clarify fat compile comment.

	* macosx/Wish.pbproj/default.pbxuser (new file):
	* macosx/Wish.pbproj/jingham.pbxuser:
	* macosx/Wish.pbproj/project.pbxproj:
	* macosx/Wish.xcode/default.pbxuser:
	* macosx/Wish.xcode/project.pbxproj:
	* macosx/Wish.xcodeproj/default.pbxuser (new file):
	* macosx/Wish.xcodeproj/project.pbxproj (new file): new/updated projects
	for Xcode 2.2 on 10.4, Xcode 1.5 on 10.3 & ProjectBuilder on 10.2, with
	native tktest targets and support for universal (fat) compiles.

	* macosx/Tk-Info.plist (removed):
	* macosx/Wish-Info.plist (removed):
	* macosx/buildTkConfig.tcl (removed): remove obsolete build files.

	* macosx/README: clarification/cleanup, document new Xcode projects and
	universal (fat) builds via CFLAGS (i.e. ppc and i386 at the same time).

	* unix/Makefile.in:
	* unix/aclocal.m4:
	* unix/configure.in:
	* macosx/configure.ac (new file): add support for inclusion of
	unix/configure.in by macosx/configure.ac, allows generation of a config
	headers enabled configure script in macosx (required by Xcode projects).

	* macosx/GNUmakefile: rename from Makefile to avoid overwriting by
	configure run in tk/macosx, add support for reusing configure cache,
	build target fixes.

	* generic/tk3d.h:
	* generic/tkButton.h:
	* generic/tkCanvas.c:
	* generic/tkCanvas.h:
	* generic/tkColor.h:
	* generic/tkEntry.h:
	* generic/tkFileFilter.h:
	* generic/tkFont.c:
	* generic/tkFont.h:
	* generic/tkImage.c:
	* generic/tkImgPhoto.c:
	* generic/tkInt.h:
	* generic/tkMenu.c:
	* generic/tkMenu.h:
	* generic/tkMenubutton.h:
	* generic/tkScale.h:
	* generic/tkScrollbar.h:
	* generic/tkSelect.h:
	* generic/tkStubInit.c:
	* generic/tkStubLib.c:
	* generic/tkText.h:
	* generic/tkUndo.h:
	* macosx/tkMacOSXButton.c:
	* macosx/tkMacOSXDebug.c:
	* macosx/tkMacOSXDebug.h:
	* macosx/tkMacOSXDialog.c:
	* macosx/tkMacOSXDraw.c:
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXInt.h:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXSend.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:
	* unix/tkUnixButton.c:
	* unix/tkUnixMenu.c:
	* xlib/xgc.c: ensure externally visible symbols not contained in stubs
	table are declared as MODULE_SCOPE (or as static if not used outside of
	own source file), #ifdef out a few Xlib and aqua functions that are
	never called. These changes allow 'make checkstubs' to complete without
	error on Darwin with gcc 4.

	* macosx/tkMacOSXTest.c:
	* macosx/tkMacOSXPort.h:
	* win/tkWinTest.c:
	* generic/tkInt.decls: add functions needed by tktest to internal stubs
	table, correct signature of TkMacOSXHandleMenuSelect, add XSync to aqua
	Xlib stubs.

	* unix/tkUnixSend.c:
	* generic/tkText.c:
	* generic/tkTest.c: #ifdef unix only declarations.
	(TestmetricsCmd): unify win and mac implementation.
	(TestsendCmd): move to tkUnixSend.c to avoid access to global var.
	(TesttextCmd): move to tkText.c to avoid having to put all the internal
	text functions it uses into the stubs table.

	* generic/tkTextDisp.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXXStubs.c: fix gcc 4 warnings.

	* macosx/tkMacOSXNotify.c:
	* macosx/tkMacOSXScrlbr.c: sync with core-8-4-branch.

	* generic/tkIntDecls.h:
	* generic/tkIntPlatDecls.h:
	* generic/tkIntXlibDecls.h:
	* generic/tkStubInit.c:
	* unix/configure:
	* unix/tkConfig.h.in: regen.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.33 2005/11/17 16:21:55 dkf Exp $
a3074 1
    TkWindow *winPtr = (TkWindow *)tkwin;
a3079 10
     * Avoid reinitialization if we are just cleaning up dead windows.
     * Perhaps knowing when Tcl was really exiting would be better than just
     * checking for this winPtr being dead. [Bug 749908]
     */

    if (!(winPtr->flags & TK_ALREADY_DEAD)) {
	TkMenuInit();
    }

    /*
@


1.33
log
@ANSIfy and reduce casting of NULL to promote readability
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.32 2005/11/17 10:57:35 dkf Exp $
d117 1
a117 1
Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
d166 1
a166 1
Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
d173 1
a173 1
Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
d196 1
a196 1
Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
d216 1
a216 1
Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
d224 1
a224 1
Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
d248 1
a248 1
Tk_OptionSpec tkMenuConfigSpecs[] = {
@


1.32
log
@Lots of ANSIfying of function decls.
Also a few spots where code has been cleaned up more completely.
@
text
@d1 1
a1 1
/* 
d5 3
a7 3
 * care of all of the generic (platform-independent) parts of menus, and
 * is supplemented by platform-specific files. The geometry calculation
 * and drawing code for menus is in the file tkMenuDraw.c
d12 2
a13 2
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.31 2005/10/12 09:43:37 dkf Exp $
d23 2
a24 3
 * - as a menubar. The menu's cascade items are arranged according to
 * the specific platform to provide the user access to the menus at all
 * times
d27 2
a28 2
 * The goal is to provide the Tk developer with a way to use a common
 * set of menus for all of these tasks.
d31 7
a37 8
 * the cascade menus' pathnames must be proper children of the menu that
 * they are cascade from. So if there is a menu .m, and it has two
 * cascades labelled "File" and "Edit", the cascade menus might have
 * the pathnames .m.file and .m.edit. Another constraint is that the menus
 * used for menubars must be children of the toplevel widget that they
 * are attached to. And on the Macintosh, the platform specific menu handle
 * for cascades attached to a menu bar must have a title that matches the
 * label for the cascade menu.
d41 7
a47 7
 * right; they have a Tk window and pathname associated with them; they have
 * a TkMenu structure and array of entries. However, they are linked with the
 * original menu that they were cloned from. The reflect the attributes of
 * the original, or "master", menu. So if an item is added to a menu, and
 * that menu has clones, then the item must be added to all of its clones
 * also. Menus are cloned when a menu is torn-off or when a menu is assigned
 * as a menubar using the "-menu" option of the toplevel's pathname configure
d50 2
a51 2
 * allows the developer to just deal with one set of menus when creating
 * and destroying.
d56 2
a57 2
 * parent-child hierarchy necessary for menubars and toplevels to work.
 * This leads to several special cases:
a65 1
 *
d90 2
a91 3
 * The following flag indicates whether the process-wide state for
 * the Menu module has been intialized.  The Mutex protects access to
 * that flag.
d102 1
a102 1
char *tkMenuStateStrings[] = {"active", "normal", "disabled", (char *) NULL};
d105 1
a105 2
    "cascade", "checkbutton", "command", "radiobutton", "separator",
    (char *) NULL
d109 2
a110 2
 * The following table defines the legal values for the -compound option.
 * It is used with the "enum compound" declaration in tkMenu.h
d114 1
a114 1
    "bottom", "center", "left", "none", "right", "top", (char *) NULL
d118 1
a118 1
    {TK_OPTION_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
d121 1
a121 1
    {TK_OPTION_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
d124 1
a124 1
    {TK_OPTION_STRING, "-accelerator", (char *) NULL, (char *) NULL,
d127 1
a127 1
    {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
d130 1
a130 1
    {TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
d133 1
a133 1
    {TK_OPTION_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
d136 1
a136 1
    {TK_OPTION_STRING, "-command", (char *) NULL, (char *) NULL,
d142 1
a142 1
    {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL,
d145 1
a145 1
    {TK_OPTION_COLOR, "-foreground", (char *) NULL, (char *) NULL,
d148 1
a148 1
    {TK_OPTION_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
d151 1
a151 1
    {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL,
d154 1
a154 1
    {TK_OPTION_STRING, "-label", (char *) NULL, (char *) NULL,
d157 1
a157 1
    {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
d161 1
a161 1
    {TK_OPTION_INT, "-underline", (char *) NULL, (char *) NULL,
d167 1
a167 1
    {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
d174 1
a174 1
    {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
d177 1
a177 1
    {TK_OPTION_STRING, "-offvalue", (char *) NULL, (char *) NULL,
d180 1
a180 1
    {TK_OPTION_STRING, "-onvalue", (char *) NULL, (char *) NULL,
d183 1
a183 1
    {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
d186 1
a186 1
    {TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL,
d189 1
a189 1
    {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) NULL,
d192 2
a193 2
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
d197 1
a197 1
    {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
d200 1
a200 1
    {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
d203 2
a204 2
    {TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE, 
d206 1
a206 1
    {TK_OPTION_STRING, "-value", (char *) NULL, (char *) NULL,
d209 1
a209 1
    {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) NULL,
d212 2
a213 2
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
d217 1
a217 1
    {TK_OPTION_STRING, "-menu", (char *) NULL, (char *) NULL,
d220 2
a221 2
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
d225 1
a225 1
    {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
d228 1
a228 1
    {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
d237 3
a239 2
    tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs};
    
d244 3
a246 2
static CONST char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
	(char *) NULL};
d249 2
a250 2
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", 
	"Foreground", DEF_MENU_ACTIVE_BG_COLOR, 
d256 2
a257 2
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", 
	"Background", DEF_MENU_ACTIVE_FG_COLOR, 
d263 4
a266 4
    {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"},
    {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) "-background"},
d277 2
a278 2
    {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) "-foreground"},
d284 1
a284 1
	DEF_MENU_POST_COMMAND, 
d296 1
a296 1
    {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand", 
d309 2
a310 2
 * Command line options. Put here because MenuCmd has to look at them
 * along with MenuWidgetObjCmd.
d316 1
a316 1
    "type", "unpost", "yposition", (char *) NULL
d326 1
a326 1
 * Prototypes for static procedures in this file:
d329 20
a348 21
static int		CloneMenu _ANSI_ARGS_((TkMenu *menuPtr,
			    Tcl_Obj *newMenuName, Tcl_Obj *newMenuTypeString));
static int		ConfigureMenu _ANSI_ARGS_((Tcl_Interp *interp,
			    TkMenu *menuPtr, int objc, Tcl_Obj *CONST objv[]));
static int		ConfigureMenuCloneEntries _ANSI_ARGS_((
			    Tcl_Interp *interp, TkMenu *menuPtr, int index,
			    int objc, Tcl_Obj *CONST objv[]));
static int		ConfigureMenuEntry _ANSI_ARGS_((TkMenuEntry *mePtr,
			    int objc, Tcl_Obj *CONST objv[]));
static void		DeleteMenuCloneEntries _ANSI_ARGS_((TkMenu *menuPtr,
			    int first, int last));
static void		DestroyMenuHashTable _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp));
static void		DestroyMenuInstance _ANSI_ARGS_((TkMenu *menuPtr));
static void		DestroyMenuEntry _ANSI_ARGS_((char *memPtr));
static int		GetIndexFromCoords
			    _ANSI_ARGS_((Tcl_Interp *interp, TkMenu *menuPtr,
			    char *string, int *indexPtr));
static int		MenuDoYPosition _ANSI_ARGS_((Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *objPtr));
static int		MenuAddOrInsert _ANSI_ARGS_((Tcl_Interp *interp,
d350 6
a355 9
			    Tcl_Obj *CONST objv[]));
static int		MenuCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, 
			    Tcl_Obj *CONST objv[]));
static void		MenuCmdDeletedProc _ANSI_ARGS_((
			    ClientData clientData));
static TkMenuEntry *	MenuNewEntry _ANSI_ARGS_((TkMenu *menuPtr, int index,
			    int type));
static char *		MenuVarProc _ANSI_ARGS_((ClientData clientData,
d357 9
a365 10
			    CONST char *name2, int flags));
static int		MenuWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, 
			    Tcl_Obj *CONST objv[]));
static void		MenuWorldChanged _ANSI_ARGS_((
			    ClientData instanceData));
static int		PostProcessEntry _ANSI_ARGS_((TkMenuEntry *mePtr));
static void		RecursivelyDeleteMenu _ANSI_ARGS_((TkMenu *menuPtr));
static void		UnhookCascadeEntry _ANSI_ARGS_((TkMenuEntry *mePtr));
static void		TkMenuCleanup _ANSI_ARGS_((ClientData unused));
d369 2
a370 2
 * manager events. One of these includes a font change, which forces
 * the geometry proc to be called.
d383 1
a383 2
 *	Called by Tk at initialization time to create the menu
 *	command.
d395 3
a397 3
TkCreateMenuCmd(interp)
    Tcl_Interp *interp;		/* Interpreter we are creating the 
				 * command in. */
d399 1
a399 1
    TkMenuOptionTables *optionTablesPtr = 
d402 1
a402 1
    optionTablesPtr->menuOptionTable = 
d432 2
a433 3
 *	This procedure is invoked to process the "menu" Tcl
 *	command.  See the user documentation for details on
 *	what it does.
d445 5
a449 6
MenuCmd(clientData, interp, objc, objv)
    ClientData clientData;	/* Main window associated with
				 * interpreter. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument strings. */
d480 1
a480 1
    windowName = Tcl_GetStringFromObj(objv[1], NULL);
d488 3
a490 3
     * Initialize the data structure for the menu.  Note that the
     * menuPtr is eventually freed in 'TkMenuEventProc' in tkMenuDraw.c,
     * when Tcl_EventuallyFree is called.
d537 2
a538 2
     * parent menu needs to be told that this menu now exists so that
     * the platform-part of the menu is correctly updated.
d541 4
a544 4
     * menu must also have a parallel instance. This is especially true on
     * the Mac, where each menu has to have a separate title everytime it is in
     * a menubar. For instance, say you have a menu .m1 with a cascade entry
     * for .m2, where .m2 does not exist yet. You then put .m1 into a menubar.
d548 2
a549 2
     * to be the cascade entry for the clone of .m1. This is special case
     * #1 listed in the introductory comment.
a558 1

d562 6
a567 6
     	     * If we have a new master menu, and an existing cloned menu
	     * points to this menu in a cascade entry, we have to clone
	     * the new menu and point the entry to the clone instead
	     * of the menu we are creating. Otherwise, ConfigureMenuEntry
	     * will hook up the platform-specific cascade linkages now
	     * that the menu we are creating exists.
d594 2
a595 2
                 * Now we can set the new menu instance to be the cascade entry
                 * of the parent's instance.
d612 3
a614 3
     * If there already exist toplevel widgets that refer to this menu,
     * find them and notify them so that they can reconfigure their
     * geometry to reflect the menu.
d624 3
a626 3
    	     * Need to get the next pointer first. TkSetWindowMenuBar
    	     * changes the list, so that the next pointer is different
    	     * after calling it.
d631 1
a631 1
    	    TkSetWindowMenuBar(menuPtr->interp, listtkwin, 
d646 3
a648 3
 *	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.
d660 5
a664 5
MenuWidgetObjCmd(clientData, interp, objc, objv)
    ClientData clientData;	/* Information about menu widget. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument strings. */
d682 2
a683 2
	case MENU_ACTIVATE: {
	    int index;
d685 21
a705 19
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "activate index");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if (menuPtr->active == index) {
		goto done;
	    }
	    if ((index >= 0) 
		    && ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
			    || (menuPtr->entries[index]->state
				    == ENTRY_DISABLED))) {
		index = -1;
	    }
	    result = TkActivateMenuEntry(menuPtr, index);
	    break;
a706 5
	case MENU_ADD:
	    if (objc < 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "add type ?options?");
		goto error;
	    }
d708 6
a713 7
	    if (MenuAddOrInsert(interp, menuPtr, (Tcl_Obj *) NULL,
		    objc - 2, objv + 2) != TCL_OK) {
		goto error;
	    }
	    break;
	case MENU_CGET: {
	    Tcl_Obj *resultPtr;
d715 32
a746 3
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "cget option");
		goto error;
d748 2
a749 1
	    resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr,
d753 4
a756 1
		goto error;
d758 5
a762 2
	    Tcl_SetObjResult(interp, resultPtr);
	    break;
d764 4
a767 10
	case MENU_CLONE:
	    if ((objc < 3) || (objc > 4)) {
		Tcl_WrongNumArgs(interp, 1, objv,
			"clone newMenuName ?menuType?");
		goto error;
	    }
    	    result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);
	    break;
	case MENU_CONFIGURE: {
	    Tcl_Obj *resultPtr;
d769 11
a779 27
	    if (objc == 2) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
			menuPtr->optionTablesPtr->menuOptionTable,
			(Tcl_Obj *) NULL, menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else if (objc == 3) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
			menuPtr->optionTablesPtr->menuOptionTable,
			objv[2], menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else {
    		result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
	    }
	    if (result != TCL_OK) {
		goto error;
	    }
	    break;
a780 2
	case MENU_DELETE: {
	    int first, last;
d782 5
a786 17
	    if ((objc != 3) && (objc != 4)) {
		Tcl_WrongNumArgs(interp, 1, objv, "delete first ?last?");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first) 
		    != TCL_OK) {
		goto error;
	    }
	    if (objc == 3) {
		last = first;
	    } else {
		if (TkGetMenuIndex(interp, menuPtr, objv[3], 0, &last) 
			!= TCL_OK) {
		    goto error;
		}
	    }
	    if (menuPtr->tearoff && (first == 0)) {
d788 11
a798 4
		/*
		 * Sorry, can't delete the tearoff entry;  must reconfigure
		 * the menu.
		 */
d800 46
a845 4
		first = 1;
	    }
	    if ((first < 0) || (last < first)) {
		goto done;
d847 2
a848 21
	    DeleteMenuCloneEntries(menuPtr, first, last);
	    break;
	}
	case MENU_ENTRYCGET: {
	    int index;
	    Tcl_Obj *resultPtr;

	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "entrycget index option");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) 
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    mePtr = menuPtr->entries[index];
	    Tcl_Preserve((ClientData) mePtr);
	    resultPtr = Tk_GetOptionValue(interp, (char *) mePtr, 
a849 1
	    Tcl_Release((ClientData) mePtr);
d851 1
a851 41
		goto error;
	    }
	    Tcl_SetObjResult(interp, resultPtr);
	    break;
	}
	case MENU_ENTRYCONFIGURE: {
	    int index;
	    Tcl_Obj *resultPtr;

	    if (objc < 3) {
		Tcl_WrongNumArgs(interp, 1, objv, 
			"entryconfigure index ?option value ...?");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    mePtr = menuPtr->entries[index];
	    Tcl_Preserve((ClientData) mePtr);
	    if (objc == 3) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
			mePtr->optionTable, (Tcl_Obj *) NULL, menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else if (objc == 4) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
			mePtr->optionTable, objv[3], menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
d853 2
a854 2
		result = ConfigureMenuCloneEntries(interp, menuPtr, index,
			objc - 3, objv + 3);
d856 3
a858 2
	    Tcl_Release((ClientData) mePtr);
	    break;
d860 5
a864 2
	case MENU_INDEX: {
	    int index;
d866 21
a886 14
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "index string");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) 
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		Tcl_SetResult(interp, "none", TCL_STATIC);
	    } else {
		Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
	    }
	    break;
d888 3
a890 13
	case MENU_INSERT:
	    if (objc < 4) {
		Tcl_WrongNumArgs(interp, 1, objv, 
			"insert index type ?options?");
		goto error;
	    }
	    if (MenuAddOrInsert(interp, menuPtr, objv[2], objc - 3,
		    objv + 3) != TCL_OK) {
		goto error;
	    }
	    break;
	case MENU_INVOKE: {
	    int index;
d892 9
a900 13
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "invoke index");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    result = TkInvokeMenu(interp, menuPtr, index);
	    break;
d902 5
a906 2
	case MENU_POST: {
	    int x, y;
d908 8
a915 8
	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "post x y");
		goto error;
	    }
	    if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		    || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
		goto error;
	    }
d917 5
a921 6
	    /*
	     * Tearoff menus are posted differently on Mac and Windows than
	     * non-tearoffs. TkpPostMenu does not actually map the menu's
	     * window on those platforms, and popup menus have to be
	     * handled specially.
	     */
d923 4
a926 6
    	    if (menuPtr->menuType != TEAROFF_MENU) {
    		result = TkpPostMenu(interp, menuPtr, x, y);
    	    } else {
    		result = TkPostTearoffMenu(interp, menuPtr, x, y);
    	    }
	    break;
d928 4
a931 2
	case MENU_POSTCASCADE: {
	    int index;
d933 4
a936 4
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "postcascade index");
		goto error;
	    }
d938 7
a944 12
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if ((index < 0) || (menuPtr->entries[index]->type 
		    != CASCADE_ENTRY)) {
		result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
	    } else {
		result = TkPostSubmenu(interp, menuPtr, 
			menuPtr->entries[index]);
	    }
	    break;
d946 4
a949 2
	case MENU_TYPE: {
	    int index;
d951 30
a980 19
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "type index");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) 
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    if (menuPtr->entries[index]->type == TEAROFF_ENTRY) {
		Tcl_SetResult(interp, "tearoff", TCL_STATIC);
	    } else {
		Tcl_SetStringObj(Tcl_GetObjResult(interp),
			menuEntryTypeStrings[menuPtr->entries[index]->type],
			-1);
	    }
	    break;
d982 2
a983 15
	case MENU_UNPOST:
	    if (objc != 2) {
		Tcl_WrongNumArgs(interp, 1, objv, "unpost");
		goto error;
	    }
	    Tk_UnmapWindow(menuPtr->tkwin);
	    result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
	    break;
	case MENU_YPOSITION:
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "yposition index");
		goto error;
	    }
	    result = MenuDoYPosition(interp, menuPtr, objv[2]);
	    break;
d985 1
a985 1
    done:
d989 1
a989 1
    error:
d999 2
a1000 2
 *	Given a menu and an index, takes the appropriate action for the
 *	entry associated with that index.
d1006 2
a1007 2
 *	Commands may get excecuted; variables may get set; sub-menus may
 *	get posted.
d1013 5
a1017 5
TkInvokeMenu(interp, menuPtr, index)
    Tcl_Interp *interp;		/* The interp that the menu lives in. */
    TkMenu *menuPtr;		/* The menu we are invoking. */
    int index;			/* The zero based index of the item we
    				 * are invoking */
d1021 1
a1021 1
    
d1069 1
d1071 3
a1073 3
     * We check numEntries in addition to whether the menu entry
     * has a command because that goes to zero if the menu gets
     * deleted (e.g., during command evaluation).
d1075 1
d1085 1
a1085 1
    done:
d1094 3
a1096 4
 *	This procedure is invoked by TkDestroyMenu
 *	to clean up the internal structure of a menu at a safe time
 *	(when no-one is using it anymore). Only takes care of one instance
 *	of the menu.
d1108 2
a1109 2
DestroyMenuInstance(menuPtr)
    TkMenu *menuPtr;	/* Info about menu widget. */
d1117 1
a1117 1
    
d1121 9
a1129 9
     * the menu ptr field in the menu reference at this point in the code
     * so that everything else can forget about this menu properly. We also
     * need to reset -menu field of all entries that are not master menus
     * back to this entry name if this is a master menu pointed to by another
     * master menu. If there is a clone menu that points to this menu,
     * then this menu is itself a clone, so when this menu goes away,
     * the -menu field of the pointing entry must be set back to this
     * menu's master menu name so that later if another menu is created
     * the cascade hierarchy can be maintained.
d1153 1
d1155 2
a1156 2
	     * It is possible that the menu info is out of sync, and
	     * these things point to NULL, so verify existence [Bug: 3402]
d1158 1
d1167 1
a1167 1
    	    ConfigureMenuEntry(cascadePtr, 0, (Tcl_Obj **) NULL);
d1172 1
a1172 1
        for (menuInstancePtr = menuPtr->masterMenuPtr; 
d1176 1
a1176 1
                menuInstancePtr->nextInstancePtr = 
d1186 2
a1187 3
     * Free up all the stuff that requires special handling, then
     * let Tk_FreeConfigOptions handle all the standard option-related
     * stuff.
d1192 4
a1195 4
	 * As each menu entry is deleted from the end of the array of
	 * entries, decrement menuPtr->numEntries.  Otherwise, the act of
	 * deleting menu entry i will dereference freed memory attempting
	 * to queue a redraw for menu entries (i+1)...numEntries.
d1205 1
a1205 1
    Tk_FreeConfigOptions((char *) menuPtr, 
d1219 5
a1223 5
 *	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).  If called on a master instance,
 *	destroys all of the slave instances. If called on a non-master
 *	instance, just destroys that instance.
d1235 2
a1236 2
TkDestroyMenu(menuPtr)
    TkMenu *menuPtr;	/* Info about menu widget. */
d1248 4
a1251 4
     * Now destroy all non-tearoff instances of this menu if this is a 
     * parent menu. Is this loop safe enough? Are there going to be
     * destroy bindings on child menus which kill the parent? If not,
     * we have to do a slightly more complex scheme.
d1257 2
a1258 2
	 * If any toplevel widgets have this menu as their menubar,
	 * the geometry of the window may have to be recalculated.
d1260 1
d1274 4
a1277 3
		/* 
		 * Note: it may be desirable to NULL out the tkwin
		 * field of menuInstancePtr here:
d1280 1
d1297 2
a1298 2
 *	cascade menu. This is done in preparation for changing the menu
 *	that this entry points to.
d1300 3
a1302 3
 *	At the end of this function, the menu entry no longer contains
 *	a reference to a 'TkMenuReferences' structure, and therefore
 *	no such structure contains a reference to this menu entry either.
d1314 3
a1316 3
UnhookCascadeEntry(mePtr)
    TkMenuEntry *mePtr;			/* The cascade entry we are removing
					 * from the cascade list. */
d1335 2
a1336 2
     * Singularly linked list deletion. The two special cases are
     * 1. one element; 2. The first element is the one we want.
a1340 1

d1342 2
a1343 3
	     * This is the last menu entry which points to this
	     * menu, so we need to clear out the list pointer in the
	     * cascade itself.
d1347 3
a1349 3
	    /* 
	     * The original field is set to zero below, after it is
	     * freed.
d1351 1
d1380 3
a1382 3
 *	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).
d1394 2
a1395 2
DestroyMenuEntry(memPtr)
    char *memPtr;		/* Pointer to entry to be freed. */
d1402 3
a1404 3
	 * Ignore errors while unposting the menu, since it's possible
	 * that the menu has already been deleted and the unpost will
	 * generate an error.
d1407 1
a1407 1
	TkPostSubmenu(menuPtr->interp, menuPtr, (TkMenuEntry *) NULL);
d1411 2
a1412 3
     * Free up all the stuff that requires special handling, then
     * let Tk_FreeConfigOptions handle all the standard option-related
     * stuff.
d1418 3
a1420 4
	    /* 
	     * The menu as a whole is a clone.  We must delete the clone
	     * of the cascaded menu for the particular entry we are
	     * destroying.
d1422 1
d1424 1
d1427 6
a1432 6
		/* 
		 * But only if it is a clone.  What can happen is that
		 * we are in the middle of deleting a menu and this
		 * menu pointer has already been reset to point to the
		 * original menu.  In that case we have nothing special
		 * to do.
d1434 3
a1436 2
		if ((destroyThis != NULL) 
		  && (destroyThis->masterMenuPtr == destroyThis)) {
d1459 1
a1459 1
    if (((mePtr->type == CHECK_BUTTON_ENTRY) 
d1462 2
a1463 1
	char *varName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d1479 3
a1481 3
 *      This procedure is called when the world has changed in some
 *      way (such as the fonts in the system changing) and the widget needs
 *	to recompute all its graphics contexts and determine its new geometry.
d1493 2
a1494 2
MenuWorldChanged(instanceData)
    ClientData instanceData;	/* Information about widget. */
d1513 2
a1514 3
 *	This procedure is called to process an argv/argc list, plus
 *	the Tk option database, in order to configure (or
 *	reconfigure) a menu widget.
d1517 2
a1518 2
 *	The return value is a standard Tcl result.  If TCL_ERROR is
 *	returned, then the interp's result contains an error message.
d1521 2
a1522 2
 *	Configuration information, such as colors, font, etc. get set
 *	for menuPtr;  old resources get freed, if there were any.
d1528 3
a1530 3
ConfigureMenu(interp, menuPtr, objc, objv)
    Tcl_Interp *interp;		/* Used for error reporting. */
    register TkMenu *menuPtr;	/* Information about widget;  may or may
d1532 2
a1533 2
    int objc;			/* Number of valid entries in argv. */
    Tcl_Obj *CONST objv[];	/* Arguments. */
d1544 2
a1545 2
		menuListPtr->optionTablesPtr->menuOptionTable, objc, objv, 
		menuListPtr->tkwin, menuListPtr->errorStructPtr, (int *) NULL);
d1563 4
a1566 4
	 * When a menu is created, the type is in all of the arguments
	 * to the menu command. Let Tk_ConfigureWidget take care of
	 * parsing them, and then set the type after we can look at
	 * the type string. Once set, a menu's type cannot be changed
d1574 4
a1577 5
	     * Configure the new window to be either a pop-up menu
	     * or a tear-off menu.
	     * We don't do this for menubars since they are not toplevel
	     * windows. Also, since this gets called before CloneMenu has
	     * a chance to set the menuType field, we have to look at the
d1590 2
a1591 2
	 * Depending on the -tearOff option, make sure that there is or
	 * isn't an initial tear-off entry at the beginning of the menu.
d1635 3
a1637 3
	 * 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.
d1644 1
a1644 1
	    ConfigureMenuEntry(mePtr, 0, (Tcl_Obj **) NULL);
d1666 2
a1667 2
 *	after Tk_SetOptions is called. This is separate
 *	so that error handling is easier.
d1670 2
a1671 2
 *	The return value is a standard Tcl result.  If TCL_ERROR is
 *	returned, then the interp's result contains an error message.
d1674 2
a1675 2
 *	Configuration information such as label and accelerator get
 *	set for mePtr;  old resources get freed, if there were any.
d1681 2
a1682 2
PostProcessEntry(mePtr)
    TkMenuEntry *mePtr;			/* The entry we are configuring. */
d1690 3
a1692 3
     * 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.
d1720 4
a1723 5
	 * This is a cascade entry. If the menu that the cascade entry
	 * is pointing to has changed, we need to remove this entry
	 * from the list of entries pointing to the old menu, and add a
	 * cascade reference to the list of entries pointing to the
	 * new menu.
d1728 1
a1728 1
	name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d1737 1
a1737 1
	if ((mePtr->childMenuRefPtr == NULL) 
d1777 3
a1779 3
     * 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.
d1783 2
a1784 1
	char *imageString = Tcl_GetStringFromObj(mePtr->imagePtr, NULL);
d1798 2
a1799 2
	char *selectImageString = Tcl_GetStringFromObj(
		mePtr->selectImagePtr, NULL);
d1836 3
a1838 4
	 * 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.
d1850 2
a1851 4
		char *value = Tcl_GetStringFromObj(valuePtr, NULL);
		char *onValue = Tcl_GetStringFromObj(mePtr->onValuePtr,
			NULL);

d1861 1
a1861 3
			? mePtr->offValuePtr
			: Tcl_NewObj(),
			TCL_GLOBAL_ONLY);
d1865 1
a1865 1
	    name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d1880 2
a1881 2
 *	This procedure is called to process an argv/argc list in order
 *	to configure (or reconfigure) one entry in a menu.
d1884 2
a1885 2
 *	The return value is a standard Tcl result.  If TCL_ERROR is
 *	returned, then the interp's result contains an error message.
d1888 2
a1889 2
 *	Configuration information such as label and accelerator get
 *	set for mePtr;  old resources get freed, if there were any.
d1895 5
a1899 6
ConfigureMenuEntry(mePtr, objc, objv)
    register TkMenuEntry *mePtr;	/* Information about menu entry;  may
					 * or may not already have values for
					 * some fields. */
    int objc;				/* Number of valid entries in argv. */
    Tcl_Obj *CONST objv[];		/* Arguments. */
d1906 2
a1907 2
     * If this entry is a check button or radio button, then remove
     * its old trace procedure.
d1913 2
a1914 1
	char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d1924 1
a1924 1
		&errorStruct, (int *) NULL) != TCL_OK) {
d1948 2
a1949 2
 *	The return value is a standard Tcl result.  If TCL_ERROR is
 *	returned, then the interp's result contains an error message.
d1952 2
a1953 2
 *	Configuration information such as label and accelerator get
 *	set for mePtr;  old resources get freed, if there were any.
d1959 6
a1964 7
ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv)
    Tcl_Interp *interp;			/* Used for error reporting. */
    TkMenu *menuPtr;			/* Information about whole menu. */
    int index;				/* Index of mePtr within menuPtr's
					 * entries. */
    int objc;				/* Number of valid entries in argv. */
    Tcl_Obj *CONST objv[];		/* Arguments. */
d1969 1
a1969 1
    TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL; 
d1974 6
a1979 6
     * Cascades are kind of tricky here. This is special case #3 in the comment
     * at the top of this file. Basically, if a menu is the master menu of a
     * clone chain, and has an entry with a cascade menu, the clones of
     * the menu will point to clones of the cascade menu. We have
     * to destroy the clones of the cascades, clone the new cascade
     * menu, and configure the entry to point to the new clone.
d1998 1
a1998 1
	    newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d2006 1
a2006 1
		|| ((oldCascadePtr != NULL) 
d2010 2
a2011 3
	    oldCascadeName = Tcl_GetStringFromObj(oldCascadePtr,
		    NULL);
	    cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName) 
d2021 1
a2021 1
	    newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d2027 1
a2027 1
    for (menuListPtr = menuPtr->masterMenuPtr->nextInstancePtr; 
d2034 1
a2034 1
	    oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, 
d2058 1
a2058 1
			pathNamePtr, 
d2084 2
a2085 2
 *	Parse a textual index into a menu and return the numerical
 *	index of the indicated entry.
d2088 4
a2091 4
 *	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 the interp's result.
d2100 3
a2102 3
TkGetMenuIndex(interp, menuPtr, objPtr, lastOK, indexPtr)
    Tcl_Interp *interp;		/* For error messages. */
    TkMenu *menuPtr;		/* Menu for which the index is being
d2104 1
a2104 1
    Tcl_Obj *objPtr;		/* Specification of an entry in menu.  See
d2106 3
a2108 3
    int lastOK;			/* Non-zero means its OK to return index
				 * just *after* last entry. */
    int *indexPtr;		/* Where to store converted index. */
d2111 1
a2111 1
    char *string = Tcl_GetStringFromObj(objPtr, NULL);
d2150 1
a2150 1
	Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
d2155 1
a2155 2
	char *label = (labelPtr == NULL) ? NULL
	        : Tcl_GetStringFromObj(labelPtr, NULL);
d2157 1
a2157 2
	if ((label != NULL)
		&& (Tcl_StringMatch(label, string))) {
d2163 1
a2163 2
    Tcl_AppendResult(interp, "bad menu entry index \"",
	    string, "\"", (char *) NULL);
d2166 1
a2166 1
success:
d2175 3
a2177 3
 *	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.
d2189 2
a2190 2
MenuCmdDeletedProc(clientData)
    ClientData clientData;	/* Pointer to widget record for widget. */
d2196 4
a2199 4
     * 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.
d2203 3
a2205 3
	/* 
	 * Note: it may be desirable to NULL out the tkwin
	 * field of menuPtr here:
d2208 1
d2218 1
a2218 1
 *	This procedure allocates and initializes a new menu entry.
d2221 3
a2223 3
 *	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.
d2232 3
a2234 3
MenuNewEntry(menuPtr, index, type)
    TkMenu *menuPtr;		/* Menu that will hold the new entry. */
    int index;			/* Where in the menu the new entry is to
d2236 1
a2236 1
    int type;			/* The type of the new entry. */
d2243 1
a2243 2
     * Create a new array of entries with an empty slot for the
     * new entry.
d2314 2
a2315 2
 *	This procedure does all of the work of the "add" and "insert"
 *	widget commands, allowing the code for these to be shared.
d2327 8
a2334 11
MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv)
    Tcl_Interp *interp;			/* Used for error reporting. */
    TkMenu *menuPtr;			/* Widget in which to create new
					 * entry. */
    Tcl_Obj *indexPtr;			/* Object describing index at which
					 * to insert.  NULL means insert at
					 * end. */
    int objc;				/* Number of elements in objv. */
    Tcl_Obj *CONST objv[];		/* Arguments to command:  first arg
					 * is type of entry, others are
					 * config options. */
d2341 1
a2341 2
	if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index)
		!= TCL_OK) {
d2348 2
a2349 3
	char *indexString = Tcl_GetStringFromObj(indexPtr, NULL);
	Tcl_AppendResult(interp, "bad index \"", indexString, "\"",
		 (char *) NULL);
d2402 5
a2406 6
    	 * If a menu has cascades, then every instance of the menu has
    	 * to have its own parallel cascade structure. So adding an
	 * entry to a menu with clones means that the menu that the
	 * entry points to has to be cloned for every clone the
	 * master menu has. This is special case #2 in the comment
	 * at the top of this file.
d2417 1
a2417 1
		Tcl_Obj *windowNamePtr = 
d2455 3
a2457 4
 *	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.
d2469 6
a2474 6
MenuVarProc(clientData, interp, name1, name2, flags)
    ClientData clientData;	/* Information about menu entry. */
    Tcl_Interp *interp;		/* Interpreter containing variable. */
    CONST char *name1;		/* First part of variable's name. */
    CONST char *name2;		/* Second part of variable's name. */
    int flags;			/* Describes what just happened. */
d2487 1
a2487 1
    	return (char *) NULL;
d2491 1
a2491 1
    name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d2505 2
a2506 2
	TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
	return (char *) NULL;
d2510 2
a2511 2
     * Use the value of the variable to update the selected status of
     * the menu entry.
d2519 1
a2519 1
	onValue = Tcl_GetStringFromObj(mePtr->onValuePtr, NULL);
d2522 1
a2522 1
		return (char *) NULL;
d2528 1
a2528 1
	    return (char *) NULL;
d2531 1
a2531 1
	return (char *) NULL;
d2535 1
a2535 1
    return (char *) NULL;
d2543 2
a2544 3
 *	This procedure is invoked to make a particular menu entry
 *	the active one, deactivating any other entry that might
 *	currently be active.
d2547 2
a2548 2
 *	The return value is a standard Tcl result (errors can occur
 *	while posting and unposting submenus).
d2551 2
a2552 2
 *	Menu entries get redisplayed, and the active entry changes.
 *	Submenus may get posted and unposted.
d2558 4
a2561 4
TkActivateMenuEntry(menuPtr, index)
    register TkMenu *menuPtr;		/* Menu in which to activate. */
    int index;				/* Index of entry to activate, or
					 * -1 to deactivate all entries. */
d2570 2
a2571 2
	 * Don't change the state unless it's currently active (state
	 * might already have been changed to disabled).
d2596 2
a2597 2
 *	The return value is a standard Tcl result (errors can occur
 *	while the postcommands are being processed).
d2605 1
a2605 1
 
d2607 2
a2608 2
TkPostCommand(menuPtr)
    TkMenu *menuPtr;
d2613 3
a2615 3
     * 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.
d2638 3
a2640 3
 *	Creates a child copy of the menu. It will be inserted into
 *	the menu's instance chain. All attributes and entry
 *	attributes will be duplicated.
d2646 2
a2647 3
 *	Allocates storage. After the menu is created, any 
 *	configuration done with this menu or any related one
 *	will be reflected in all of them.
d2653 5
a2657 5
CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr)
    TkMenu *menuPtr;		/* The menu we are going to clone */
    Tcl_Obj *newMenuNamePtr;	/* The name to give the new menu */
    Tcl_Obj *newMenuTypePtr;	/* What kind of menu is this, a normal menu
    				 * a menubar, or a tearoff? */
d2667 1
a2667 1
	if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr, 
d2695 2
a2696 2
	    ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, 
	    newMenuNamePtr)) != (TkMenuReferences *) NULL)
d2720 4
a2723 4
	 * Add the master menu's window to the bind tags for this window
	 * after this window's tag. This is so the user can bind to either
	 * this clone (which may not be easy to do) or the entire menu
	 * clone structure.
d2730 1
a2730 1
	if (Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin, 
d2742 1
a2742 1
		windowName = Tcl_GetStringFromObj(elementPtr, NULL);
d2747 2
a2748 1
		    /* 
d2752 1
d2781 1
a2781 1
		    Tcl_Obj *windowNamePtr = 
d2830 4
a2833 4
MenuDoYPosition(interp, menuPtr, objPtr)
    Tcl_Interp *interp;
    TkMenu *menuPtr;
    Tcl_Obj *objPtr;
d2850 1
a2850 1
error:
d2863 3
a2865 3
 *	If int is a valid number, *indexPtr will be the number of the menuentry
 *	that is the correct height. If int is invaled, *indexPtr will be
 *	unchanged. Returns appropriate Tcl error number.
d2874 5
a2878 5
GetIndexFromCoords(interp, menuPtr, string, indexPtr)
    Tcl_Interp *interp;		/* interp of menu */
    TkMenu *menuPtr;		/* the menu we are searching */
    char *string;		/* The @@string we are parsing */
    int *indexPtr;		/* The index of the item that matches */
d2882 1
a2882 1
    
d2897 1
a2897 1
	Tk_GetPixelsFromObj(interp, menuPtr->tkwin, 
d2916 2
a2917 2
    error:
    Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
d2927 2
a2928 2
 *	instances when a menu is no longer being used as a menubar,
 *	for instance.
d2940 2
a2941 2
RecursivelyDeleteMenu(menuPtr)
    TkMenu *menuPtr;		/* The menubar instance we are deleting */
d2947 2
a2948 3
     * It is not 100% clear that this preserve/release pair is
     * required, but we have added them for safety in this
     * very complex code.
d2950 1
d2973 1
a2973 2
 *	Makes a new unique name for a cloned menu. Will be a child
 *	of oldName.
d2985 4
a2988 4
TkNewMenuName(interp, parentPtr, menuPtr)
    Tcl_Interp *interp;		/* The interp the new name has to live in.*/
    Tcl_Obj *parentPtr;		/* The prefix path of the new name. */
    TkMenu *menuPtr;		/* The menu we are cloning. */
d2999 1
a2999 1
    char *parentName = Tcl_GetStringFromObj(parentPtr, NULL);
d3008 1
a3008 1
    for (destString = Tcl_GetStringFromObj(childPtr, NULL);
d3035 1
a3035 1
	destString = Tcl_GetStringFromObj(resultPtr, NULL);
d3051 2
a3052 3
 *	Associates a menu with a window. Called by ConfigureFrame in
 *	in response to a "-menu .foo" configuration option for a top
 *	level.
d3058 2
a3059 2
 *	The old menu clones for the menubar are thrown away, and a
 *	handler is set up to allocate the new ones.
d3063 1
d3065 7
a3071 7
TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName)
    Tcl_Interp *interp;		/* The interpreter the toplevel lives in. */
    Tk_Window tkwin;		/* The toplevel window */
    char *oldMenuName;		/* The name of the menubar previously set in
    				 * this toplevel. NULL means no menu was
				 * set previously. */
    char *menuName;		/* The name of the new menubar that the
d3082 2
a3083 2
     * Perhaps knowing when Tcl was really exiting would be better than
     * just checking for this winPtr being dead. [Bug 749908]
d3085 1
d3091 2
a3092 2
     * Destroy the menubar instances of the old menu. Take this window
     * out of the old menu's top level reference list.
a3097 1

d3099 2
a3100 2
	     * Find the menubar instance that is to be removed. Destroy
	     * it and all of the cascades underneath it.
d3109 1
a3109 1
			instancePtr != NULL; 
d3111 1
a3111 1
		    if (instancePtr->menuType == MENUBAR 
d3127 1
a3127 1
	    while ((topLevelListPtr != NULL) 
d3165 1
a3165 1
	    Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin), 
d3206 2
a3207 2
	 * Add this window to the menu's list of windows that refer
	 * to this menu.
d3226 2
a3227 2
 *	Called when an interp is deleted and a menu hash table has
 *	been set in it.
d3239 3
a3241 3
DestroyMenuHashTable(clientData, interp)
    ClientData clientData;	/* The menu hash table we are destroying */
    Tcl_Interp *interp;		/* The interpreter we are destroying */
d3252 2
a3253 2
 *	For a given interp, give back the menu hash table that goes with
 *	it. If the hash table does not exist, it is created.
d3266 2
a3267 2
TkGetMenuHashTable(interp)
    Tcl_Interp *interp;		/* The interp we need the hash table in.*/
d3271 2
a3272 2
    menuTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, MENU_HASH_KEY,
	    NULL);
d3287 3
a3289 2
 *	Given a pathname, gives back a pointer to a TkMenuReferences structure.
 *	If a reference is not already in the hash table, one is created.
d3292 2
a3293 2
 *	Returns a pointer to a menu reference structure. Should not
 *	be freed by calller; when a field of the reference is cleared,
d3297 2
a3298 2
 *	A new hash table entry is created if there were no references
 *	to the menu originally.
d3304 3
a3306 3
TkCreateMenuReferences(interp, pathName)
    Tcl_Interp *interp;
    char *pathName;		/* The path of the menu widget */
d3336 2
a3337 2
 *	Returns a pointer to a menu reference structure. Should not
 *	be freed by calller; when a field of the reference is cleared,
d3348 3
a3350 3
TkFindMenuReferences(interp, pathName)
    Tcl_Interp *interp;		/* The interp the menu is living in. */
    char *pathName;		/* The path of the menu widget */
d3373 2
a3374 2
 *	Returns a pointer to a menu reference structure. Should not
 *	be freed by calller; when a field of the reference is cleared,
d3385 3
a3387 3
TkFindMenuReferencesObj(interp, objPtr)
    Tcl_Interp *interp;		/* The interp the menu is living in. */
    Tcl_Obj *objPtr;		/* The path of the menu widget */
d3389 1
a3389 1
    char *pathName = Tcl_GetStringFromObj(objPtr, NULL);
d3398 2
a3399 2
 *	This is called after one of the fields in a menu reference
 *	is cleared. It cleans up the ref if it is now empty.
d3402 1
a3402 2
 *	Returns 1 if the references structure was freed, and 0 
 *	otherwise.
d3405 2
a3406 2
 *	If this is the last field to be cleared, the menu ref is
 *	taken out of the hash table.
d3412 3
a3414 3
TkFreeMenuReferences(menuRefPtr)
    TkMenuReferences *menuRefPtr;		/* The menu reference to
						 * free */
d3416 1
a3416 1
    if ((menuRefPtr->menuPtr == NULL) 
d3431 2
a3432 2
 *	For every clone in this clone chain, delete the menu entries
 *	given by the parameters.
d3444 5
a3448 5
DeleteMenuCloneEntries(menuPtr, first, last)
    TkMenu *menuPtr;		    /* the menu the command was issued with */
    int	first;			    /* the zero-based first entry in the set
				     * of entries to delete. */
    int last;			    /* the zero-based last entry */
a3449 1

d3469 1
a3469 1
	if ((menuListPtr->active >= first) 
d3484 2
a3485 2
 *      Resets menusInitialized to allow Tk to be finalized and reused
 *      without the DLL being unloaded.
d3496 3
a3498 2
static void 
TkMenuCleanup(ClientData unused)
d3521 1
a3521 1
TkMenuInit()
d3523 1
a3523 1
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
d3532 1
d3536 1
d3545 8
@


1.31
log
@Undo accidental checkin
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.29 2005/10/10 20:26:31 hobbs Exp $
d463 1
a463 1
    Tk_Window new;
d469 1
a469 1
    static CONST char *typeStringList[] = {"-type", (char *) NULL};
d492 3
a494 3
    new = Tk_CreateWindowFromPath(interp, tkwin, windowName, toplevel ? ""
	    : NULL);
    if (new == NULL) {
d506 2
a507 2
    menuPtr->tkwin = new;
    menuPtr->display = Tk_Display(new);
d521 2
a522 1
    Tk_CreateEventHandler(new, ExposureMask|StructureNotifyMask|ActivateMask,
@


1.30
log
@Arrange the test suite so that it only accesses images in the same directory.
This enables packaging of the test suite as a starkit.
@
text
@a1330 4
 *	At the end of this function, the menu entry no longer contains
 *	a reference to a 'TkMenuReferences' structure, and therefore
 *	no such structure contains a reference to this menu entry either.
 *
@


1.29
log
@	* generic/tkMenu.c (TkSetWindowMenuBar): do not call TkMenuInit if
	the winPtr indicates TK_ALREADY_DEAD.  This prevents reinit that
	creates a Tk exit handler after all exit handlers should be
	called.  [Bug 749908, 1322294]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.28 2005/10/10 19:28:27 hobbs Exp $
d1331 4
@


1.28
log
@whitespace changes only
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.27 2005/05/31 05:11:40 hobbs Exp $
d3121 1
d3126 8
a3133 1
    TkMenuInit();
@


1.27
log
@	* generic/tkMenu.c (MenuCmd): create event handler earlier to
	ensure proper destruction of menu through DestroyNotify.
	[Bug 1159367]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.26 2004/09/16 20:06:33 hobbs Exp $
d124 1
a124 1
	DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1, 
d784 1
a784 1
	    
d807 1
a807 1
		
d949 1
a949 1
	    
d1175 1
a1175 1
    	
d1199 1
a1199 1
    
d1227 1
a1227 1
	 
d1276 1
a1276 1
    
d1326 1
a1326 1
 *	
d1353 1
a1353 1
    
d1360 1
a1360 1
    
d1565 1
a1565 1
    
d1595 1
a1595 1
	
d1608 1
a1608 1
	    
d1621 1
a1621 1
	
d1644 1
a1644 1
	    
d1660 1
a1660 1
	
d1667 1
a1667 1
	
d1670 1
a1670 1
	
d1674 1
a1674 1
	
a1686 1

d1756 1
a1756 1
	
d1784 1
a1784 1
    
d1788 1
a1788 1
	    
d1796 1
a1796 1
    
d1804 1
a1804 1
    
d1869 1
a1869 1
	
d1904 1
a1904 1
    
d1969 1
a1969 1
    
d2036 1
a2036 1
 
d2065 1
a2065 1
  	
d2081 1
a2081 1
	
d2192 1
a2192 1
	
d2412 1
a2412 1
    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; 
d2414 1
a2414 1
    	
d2443 1
a2443 1
    	
d2452 2
a2453 2
 
    	if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) {    	    
d2466 1
a2466 1
    	          
d2473 1
a2473 1
		
d2710 1
a2710 1
    
d2712 1
a2712 1
    	menuType = MASTER_MENU;
d2740 1
a2740 1
    
d2742 1
a2742 1
    	    ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, 
d2745 1
a2745 1
    	TkMenu *newMenuPtr = menuRefPtr->menuPtr;
d2759 1
a2759 1
	    
d2765 8
a2772 8
   	
   	/*
   	 * Add the master menu's window to the bind tags for this window
   	 * after this window's tag. This is so the user can bind to either
   	 * this clone (which may not be easy to do) or the entire menu
   	 * clone structure.
   	 */
   	
d2774 1
a2774 1
   	newObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1);
d2777 4
a2780 4
   	if (Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin, 
   		newMenuPtr->interp, 2, newObjv) == TCL_OK) {
   	    char *windowName;
   	    Tcl_Obj *bindingsPtr =
d2782 2
a2783 2
   	    Tcl_Obj *elementPtr;
     
d2785 3
a2787 3
   	    Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements);
   	    for (i = 0; i < numElements; i++) {
   	    	Tcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i,
d2789 5
a2793 5
   	    	windowName = Tcl_GetStringFromObj(elementPtr, NULL);
   	    	if (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin))
   	    		== 0) {
   	    	    Tcl_Obj *newElementPtr = Tcl_NewStringObj(
   	    	    	    Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1);
d2798 2
a2799 2
   	    	    Tcl_ListObjReplace(menuPtr->interp, bindingsPtr,
   	    	    	    i + 1, 0, 1, &newElementPtr);
d2803 5
a2807 5
   	    	    break;
   	    	}
   	    }
   	    Tcl_DecrRefCount(bindingsPtr);   	    
   	}
d2810 11
a2820 11
   	Tcl_ResetResult(menuPtr->interp);
      	
   	/*
   	 * Clone all of the cascade menus that this menu points to.
   	 */
   	
   	for (i = 0; i < menuPtr->numEntries; i++) {
   	    TkMenuReferences *cascadeRefPtr;
   	    TkMenu *oldCascadePtr;
   	    
   	    if ((menuPtr->entries[i]->type == CASCADE_ENTRY)
d2822 1
a2822 1
   	    	cascadeRefPtr =
d2825 1
a2825 1
   	    	if ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) {
d2830 2
a2831 2
		    
   	    	    oldCascadePtr = cascadeRefPtr->menuPtr;
d2834 2
a2835 2
   	    	    newCascadePtr = TkNewMenuName(menuPtr->interp,
   	    	     	    windowNamePtr, oldCascadePtr);
d2846 5
a2850 5
   	    	}
   	    }
   	}
   	
    	returnResult = TCL_OK;
d2852 1
a2852 1
    	returnResult = TCL_ERROR;
d2873 1
a2873 1
    
d2881 1
a2881 1
    
d2884 1
a2884 1
    	goto error;
d2894 1
a2894 1
    
d2945 1
a2945 1
    
d2990 2
a2991 2
    
    /* 
d2997 1
a2997 1
    
d3009 1
a3009 1
    
d3060 1
a3060 1
    
d3124 1
a3124 1
    
d3131 1
a3131 1
    
d3133 2
a3134 2
        menuRefPtr = TkFindMenuReferences(interp, oldMenuName);
    	if (menuRefPtr != NULL) {
d3141 15
a3155 2
	    if (menuRefPtr->menuPtr != NULL) {    	    
    	    	TkMenu *instancePtr;
d3157 2
a3158 15
    	    	menuPtr = menuRefPtr->menuPtr;
    	        	    
    	    	for (instancePtr = menuPtr->masterMenuPtr;
		        instancePtr != NULL; 
    	    	    	instancePtr = instancePtr->nextInstancePtr) {
    	    	    if (instancePtr->menuType == MENUBAR 
    	    		    && instancePtr->parentTopLevelPtr == tkwin) {
    	    	    	RecursivelyDeleteMenu(instancePtr);
    	    	    	break;
    	    	    }
    	    	}
    	    }
 
 	    /*
 	     * Now we need to remove this toplevel from the list of toplevels
d3160 2
a3161 2
 	     */
 
d3164 2
a3165 2
	    
            while ((topLevelListPtr != NULL) 
d3177 1
a3177 1
            	if (prevTopLevelPtr == NULL) {
d3181 6
a3186 6
            	    prevTopLevelPtr->nextPtr = topLevelListPtr->nextPtr;
            	}
            	ckfree((char *) topLevelListPtr);
            	TkFreeMenuReferences(menuRefPtr);
            }
        }
d3192 1
a3192 1
    
d3194 3
a3196 1
    	TkMenu *menuBarPtr = NULL;
d3198 4
a3201 6
	menuRefPtr = TkCreateMenuReferences(interp, menuName);    	
    	
    	menuPtr = menuRefPtr->menuPtr;
    	if (menuPtr != NULL) {
   	    Tcl_Obj *cloneMenuPtr;
   	    TkMenuReferences *cloneMenuRefPtr;
d3206 4
a3209 4
    	
            /*
             * Clone the menu and all of the cascades underneath it.
             */
d3212 2
a3213 2
    	    cloneMenuPtr = TkNewMenuName(interp, windowNamePtr,
    	    	    menuPtr);
d3216 4
a3219 4
            CloneMenu(menuPtr, cloneMenuPtr, menubarPtr);
	    
            cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr);
            if ((cloneMenuRefPtr != NULL)
d3223 2
a3224 2
            	cloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin;
            	menuBarPtr = cloneMenuRefPtr->menuPtr;
d3233 1
a3233 1
            }
d3239 2
a3240 2
        } else {
    	    TkpSetWindowMenuBar(tkwin, NULL);
d3243 4
a3246 5
        
        /*
         * Add this window to the menu's list of windows that refer
         * to this menu.
         */
d3248 1
a3248 1
        topLevelListPtr = (TkMenuTopLevelList *)
d3250 3
a3252 3
        topLevelListPtr->tkwin = tkwin;
        topLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr;
        menuRefPtr->topLevelListPtr = topLevelListPtr;
d3518 16
a3533 16
/* 
 *---------------------------------------------------------------------- 
 * 
 * TkMenuCleanup -- 
 * 
 *      Resets menusInitialized to allow Tk to be finalized and reused 
 *      without the DLL being unloaded. 
 * 
 * Results: 
 *      None. 
 * 
 * Side effects: 
 *      None. 
 * 
 *---------------------------------------------------------------------- 
 */ 
d3536 4
a3539 4
TkMenuCleanup(ClientData unused) 
{ 
    menusInitialized = 0; 
} 
d3563 1
a3563 1
    
d3570 4
a3573 4
	/* 
	 * Make sure we cleanup on finalize. 
	 */ 
	TkCreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL); 
@


1.26
log
@	* generic/tkMenu.c (MenuWorldChanged): ensure that we recompute
	the menu geometry on WorldChanged to handle font size
	changes. [Bug 607649]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.25 2004/01/13 02:06:00 davygrvy Exp $
d505 1
a511 2
    menuPtr->entries = NULL;
    menuPtr->numEntries = 0;
a512 12
    menuPtr->borderPtr = NULL;
    menuPtr->borderWidthPtr = NULL;
    menuPtr->reliefPtr = NULL;
    menuPtr->activeBorderPtr = NULL;
    menuPtr->activeBorderWidthPtr = NULL;
    menuPtr->fontPtr = NULL;
    menuPtr->fgPtr = NULL;
    menuPtr->disabledFgPtr = NULL;
    menuPtr->activeFgPtr = NULL;
    menuPtr->indicatorFgPtr = NULL;
    menuPtr->tearoff = 0;
    menuPtr->tearoffCommandPtr = NULL;
a513 5
    menuPtr->takeFocusPtr = NULL;
    menuPtr->postCommandPtr = NULL;
    menuPtr->postCommandGeneration = 0;
    menuPtr->postedCascade = NULL;
    menuPtr->nextInstancePtr = NULL;
a515 5
    menuPtr->menuFlags = 0;
    menuPtr->parentTopLevelPtr = NULL;
    menuPtr->menuTypePtr = NULL;
    menuPtr->titlePtr = NULL;
    menuPtr->errorStructPtr = NULL;
d521 2
a526 1
    	ckfree((char *) menuPtr);
a536 1
    	ckfree((char *) menuPtr);
a539 2
    Tk_CreateEventHandler(new, ExposureMask|StructureNotifyMask|ActivateMask,
	    TkMenuEventProc, (ClientData) menuPtr);
d561 1
a561 1
    
d571 1
a571 1
     
d580 1
a580 1
     	     
d603 1
a603 1
    	            
d621 1
a621 1
    
d627 1
a627 1
 
d633 1
a633 1
    	
d639 1
a639 1
    	
d1164 3
@


1.25
log
@	* generic/tk3d.c:	All uses of 'panic' (the macro) changed
	* generic/tkBind.c:	to 'Tcl_Panic' (the function).  The #define
	* generic/tkBitmap.c:	of panic in tcl.h clearly states it is
	* generic/tkCanvArc.c:	deprecated in the comments.
	* generic/tkCanvBmap.c: [Tcl Patch 865264]
	* generic/tkCanvImg.c:
	* generic/tkCanvLine.c:
	* generic/tkCanvPoly.c:
	* generic/tkCanvText.c:
	* generic/tkCanvWind.c:
	* generic/tkColor.c:
	* generic/tkConfig.c:
	* generic/tkCursor.c:
	* generic/tkError.c:
	* generic/tkEvent.c:
	* generic/tkFocus.c:
	* generic/tkFont.c:
	* generic/tkFrame.c:
	* generic/tkGC.c:
	* generic/tkGrid.c:
	* generic/tkImgBmap.c:
	* generic/tkImgPhoto.c:
	* generic/tkImgUtil.c:
	* generic/tkMenu.c:
	* generic/tkObj.c:
	* generic/tkPack.c:
	* generic/tkPlace.c:
	* generic/tkRectOval.c:
	* generic/tkSelect.c:
	* generic/tkText.c:
	* generic/tkTextBTree.c:
	* generic/tkTextDisp.c:
	* generic/tkTextImage.c:
	* generic/tkTextIndex.c:
	* generic/tkTextMark.c:
	* generic/tkTextWind.c:
	* generic/tkVisual.c:
	* generic/tkWindow.c:
	* mac/tkMacAppInit.c:
	* mac/tkMacAppearanceStubs.c:
	* mac/tkMacButton.c:
	* mac/tkMacDraw.c:
	* mac/tkMacEmbed.c:
	* mac/tkMacFont.c:
	* mac/tkMacInit.c:
	* mac/tkMacMenus.c:
	* mac/tkMacPort.h:
	* mac/tkMacSubwindows.c:
	* mac/tkMacWm.c:
	* mac/tkMacXStubs.c:
	* macosx/tkMacOSXEmbed.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXNotify.c:
	* macosx/tkMacOSXPort.h:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:
	* unix/tkUnix3d.c:
	* unix/tkUnixColor.c:
	* unix/tkUnixEmbed.c:
	* unix/tkUnixEvent.c:
	* unix/tkUnixFocus.c:
	* unix/tkUnixFont.c:
	* unix/tkUnixSelect.c:
	* unix/tkUnixSend.c:
	* unix/tkUnixWm.c:
	* win/tkWin3d.c:
	* win/tkWinButton.c:
	* win/tkWinColor.c:
	* win/tkWinDialog.c:
	* win/tkWinDraw.c:
	* win/tkWinEmbed.c:
	* win/tkWinFont.c:
	* win/tkWinPixmap.c:
	* win/tkWinPointer.c:
	* win/tkWinScrlbr.c:
	* win/tkWinWm.c:
	* win/tkWinX.c:
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.24 2003/12/21 23:50:13 davygrvy Exp $
d1387 1
a1387 1
 
d1396 1
a1396 1
	
a1450 1
	
d1539 1
a1539 1
 
d1546 1
a1546 1
    
d1551 1
a1551 1
	TkpConfigureMenuEntry(menuPtr->entries[i]);	
d1553 1
@


1.24
log
@	* generic/tkEvent.c:  Added three new functions: TkCreateExitHandler,
	* generic/tkInt.h:    TkDeleteExitHandler, and TkFinalize.  This adds
	* generic/tkMenu.c:   an insertion point so Tk's exit handlers can be
	* generic/tkWindow.c: called on their own from tk85.dll's DllMain
	* mac/tkMacButton.c:  for DLL_PROCESS_DETACH.  These are private to
	* unix/tkUnixEvent.c: the binary and not exported.  It is possible
	* win/tkWin32Dll.c:   the Windows OS can unload Tk _prior_ to Tcl
	* win/tkWinEmbed.c:   under some conditions such as ExitProcess().
	* win/tkWinMenu.c:    This avoids a dangling pointer problem when Tcl
	* win/tkWinX.c:	      does Tcl_Finalize after Tk has been unloaded.
	* win/winMain.c:      DllMain's DLL_PROCESS_DETACH now protected with
			      SEH as DeleteWindowsExitProc is causing an
			      exception of its own under some teardown
			      conditions.  AT&T assembly syntax has not been
			      added for MinGW yet.  [Tcl Patch 858493]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.23 2003/12/03 16:38:23 dkf Exp $
d1233 1
a1233 1
       panic("Attempting to delete master menu when there are still clones.");
d2500 1
a2500 1
		    panic("CloneMenu failed inside of MenuAddOrInsert.");
@


1.23
log
@Typo fix
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.22 2003/12/03 04:58:09 hobbs Exp $
d3597 1
a3597 1
	Tcl_CreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL); 
@


1.22
log
@	* generic/tkMenu.c (MenuVarProc): prevent this from triggering
	while interp is being destroyed.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.21 2003/05/30 11:03:00 vincentdarley Exp $
d2567 1
a2567 1
	if ((flags & TCL_TRACE_DESTROYED) {
@


1.21
log
@fix to menu clone deletion bug
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20 2003/02/26 02:32:56 hobbs Exp $
d2547 1
a2547 1
    char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d2550 8
d2559 1
d2562 1
a2562 2
     * If the variable is being unset, then re-establish the
     * trace unless the whole interpreter is going away.
d2567 1
a2567 1
	if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
@


1.20
log
@	* generic/tkMenu.c (TkMenuCleanup): make sure to reset static
	menusInitialized on finalize. [Bug #548729]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.19 2002/08/05 04:30:40 dgp Exp $
d499 3
a501 1
     * Initialize the data structure for the menu.
d1191 3
a1193 1
    TkFreeMenuReferences(menuPtr->menuRefPtr);
d1259 5
d1297 2
d1306 13
a1319 1
    	menuPtr->menuFlags |= MENU_DELETION_PENDING;
d1324 7
a1330 1
	     	Tk_DestroyWindow(menuInstancePtr->tkwin);
a1332 1
    	menuPtr->menuFlags &= ~MENU_DELETION_PENDING;
d1335 1
a1335 4
    /*
     * If any toplevel widgets have this menu as their menubar,
     * the geometry of the window may have to be recalculated.
     */
d1337 1
a1337 7
    topLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr;
    while (topLevelListPtr != NULL) {
         nextTopLevelPtr = topLevelListPtr->nextPtr;
         TkpSetWindowMenuBar(topLevelListPtr->tkwin, NULL);
    	 topLevelListPtr = nextTopLevelPtr;
    }
    DestroyMenuInstance(menuPtr);
d1348 4
d1378 2
d1398 4
d1420 1
d1468 34
a1501 1
        UnhookCascadeEntry(mePtr);
d2264 5
d3006 7
d3021 5
a3025 1
    Tk_DestroyWindow(menuPtr->tkwin);
d3177 8
a3184 12
            for (topLevelListPtr = menuRefPtr->topLevelListPtr,
		    prevTopLevelPtr = NULL;
		    (topLevelListPtr != NULL) 
            	    && (topLevelListPtr->tkwin != tkwin);
		    prevTopLevelPtr = topLevelListPtr,
		    topLevelListPtr = topLevelListPtr->nextPtr) {

		/*
		 * Empty loop body.
		 */
		
            }
d3455 2
a3456 1
 *	None.
d3465 1
a3465 1
void
d3475 1
d3477 1
d3534 22
a3555 22
/*
 *----------------------------------------------------------------------
 *
 * TkMenuCleanup --
 *
 *	Resets menusInitialized to allow Tk to be finalized and reused
 *	without the DLL being unloaded.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TkMenuCleanup(ClientData unused)
{
    menusInitialized = 0;
}
d3579 1
a3579 1

d3586 4
a3589 4
	/*
	 * Make sure we cleanup on finalize.
	 */
	Tcl_CreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL);
@


1.20.2.1
log
@menu clone cleanup bug fix
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.21 2003/05/30 11:03:00 vincentdarley Exp $
d499 1
a499 3
     * Initialize the data structure for the menu.  Note that the
     * menuPtr is eventually freed in 'TkMenuEventProc' in tkMenuDraw.c,
     * when Tcl_EventuallyFree is called.
d1189 1
a1189 3
    if (TkFreeMenuReferences(menuPtr->menuRefPtr)) {
	menuPtr->menuRefPtr = NULL;
    }
a1254 5
    if (menuPtr->tkwin != NULL) {
	Tk_Window tkwin = menuPtr->tkwin;
	menuPtr->tkwin = NULL;
	Tk_DestroyWindow(tkwin);
    }
a1287 2
    Tcl_Preserve(menuPtr);
    
a1294 13
    menuPtr->menuFlags |= MENU_DELETION_PENDING;
    if (menuPtr->menuRefPtr != NULL) {
	/*
	 * If any toplevel widgets have this menu as their menubar,
	 * the geometry of the window may have to be recalculated.
	 */
	topLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr;
	while (topLevelListPtr != NULL) {
	    nextTopLevelPtr = topLevelListPtr->nextPtr;
	    TkpSetWindowMenuBar(topLevelListPtr->tkwin, NULL);
	    topLevelListPtr = nextTopLevelPtr;
	}
    }
d1296 1
d1301 1
a1301 7
		Tk_Window tkwin = menuInstancePtr->tkwin;
		/* 
		 * Note: it may be desirable to NULL out the tkwin
		 * field of menuInstancePtr here:
		 * menuInstancePtr->tkwin = NULL;
		 */
	     	Tk_DestroyWindow(tkwin);
d1304 1
d1307 11
a1318 2

    Tcl_Release(menuPtr);
a1328 4
 *	
 *	At the end of this function, the menu entry no longer contains
 *	a reference to a 'TkMenuReferences' structure, and therefore
 *	no such structure contains a reference to this menu entry either.
a1354 2
	TkFreeMenuReferences(menuRefPtr);
	mePtr->childMenuRefPtr = NULL;
a1372 4
	    /* 
	     * The original field is set to zero below, after it is
	     * freed.
	     */
a1390 1
	mePtr->nextCascadePtr = NULL;
d1438 1
a1438 34
	if (menuPtr->masterMenuPtr != menuPtr) {
	    TkMenu *destroyThis = NULL;
	    /* 
	     * The menu as a whole is a clone.  We must delete the clone
	     * of the cascaded menu for the particular entry we are
	     * destroying.
	     */
	    TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr;
	    if (menuRefPtr != NULL) {
		destroyThis = menuRefPtr->menuPtr;
		/* 
		 * But only if it is a clone.  What can happen is that
		 * we are in the middle of deleting a menu and this
		 * menu pointer has already been reset to point to the
		 * original menu.  In that case we have nothing special
		 * to do.
		 */
		if ((destroyThis != NULL) 
		  && (destroyThis->masterMenuPtr == destroyThis)) {
		    destroyThis = NULL;
		}
	    }
	    UnhookCascadeEntry(mePtr);
	    if (menuRefPtr != NULL) {
	        if (menuRefPtr->menuPtr == destroyThis) {
	            menuRefPtr->menuPtr = NULL;
	        }
		if (destroyThis != NULL) {
		    TkDestroyMenu(destroyThis);
		}
	    }
	} else {
	    UnhookCascadeEntry(mePtr);
	}
a2200 5
	/* 
	 * Note: it may be desirable to NULL out the tkwin
	 * field of menuPtr here:
	 * menuPtr->tkwin = NULL;
	 */
a2937 7
    /* 
     * It is not 100% clear that this preserve/release pair is
     * required, but we have added them for safety in this
     * very complex code.
     */
    Tcl_Preserve(menuPtr);
    
d2946 1
a2946 5
    if (menuPtr->tkwin != NULL) {
	Tk_DestroyWindow(menuPtr->tkwin);
    }
    
    Tcl_Release(menuPtr);
d3098 12
a3109 8
	    topLevelListPtr = menuRefPtr->topLevelListPtr;
	    prevTopLevelPtr = NULL;
	    
            while ((topLevelListPtr != NULL) 
		   && (topLevelListPtr->tkwin != tkwin)) {
		prevTopLevelPtr = topLevelListPtr;
		topLevelListPtr = topLevelListPtr->nextPtr;
	    }
d3380 1
a3380 2
 *	Returns 1 if the references structure was freed, and 0 
 *	otherwise.
d3389 1
a3389 1
int
a3398 1
	return 1;
a3399 1
    return 0;
d3456 22
a3477 22
/* 
 *---------------------------------------------------------------------- 
 * 
 * TkMenuCleanup -- 
 * 
 *      Resets menusInitialized to allow Tk to be finalized and reused 
 *      without the DLL being unloaded. 
 * 
 * Results: 
 *      None. 
 * 
 * Side effects: 
 *      None. 
 * 
 *---------------------------------------------------------------------- 
 */ 

static void 
TkMenuCleanup(ClientData unused) 
{ 
    menusInitialized = 0; 
} 
d3501 1
a3501 1
    
d3508 4
a3511 4
	/* 
	 * Make sure we cleanup on finalize. 
	 */ 
	Tcl_CreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL); 
@


1.20.2.2
log
@	* generic/tkMenu.c (MenuVarProc): prevent this from triggering
	while interp is being destroyed.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.1 2003/07/15 13:59:06 vincentdarley Exp $
d2547 1
a2547 1
    char *name;
a2549 8
    if (flags & TCL_INTERP_DESTROYED) {
	/*
	 * Do nothing if the interpreter is going away.
	 */

    	return (char *) NULL;
    }

a2550 1
    name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d2553 2
a2554 1
     * If the variable is being unset, then re-establish the trace.
d2559 1
a2559 1
	if (flags & TCL_TRACE_DESTROYED) {
@


1.20.2.3
log
@	* generic/tkMenu.c (MenuWorldChanged): ensure that we recompute
	the menu geometry on WorldChanged to handle font size
	changes. [Bug 607649]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.2 2003/12/03 04:57:37 hobbs Exp $
d1387 1
a1387 1

d1396 1
a1396 1

d1451 1
d1540 1
a1540 1

d1547 1
a1547 1

d1552 1
a1552 1
	TkpConfigureMenuEntry(menuPtr->entries[i]);
a1553 1
    TkEventuallyRecomputeMenu(menuPtr);
@


1.20.2.4
log
@* generic/tkInt.h:	Backport of shutdown safety mods from the HEAD
* generic/tkMenu.c:	dating from 2003-12-21
* generic/tkUtil.c:
* generic/tkWindow.c:
* mac/tkMacButton.c:
* unix/tkUnixEvent.c:
* win/tkWin32Dll.c:
* win/tkWinEmbed.c:
* win/tkWinMenu.c:
* win/tkWinX.c:
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.3 2004/09/16 20:05:44 hobbs Exp $
d373 1
a373 1
static Tcl_ExitProc	TkMenuCleanup;
d3597 1
a3597 1
	TkCreateExitHandler(TkMenuCleanup, NULL); 
@


1.20.2.5
log
@	* generic/tkMenu.c (MenuCmd): create event handler earlier to
	ensure proper destruction of menu through DestroyNotify.
	[Bug 1159367]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.4 2004/10/27 00:37:38 davygrvy Exp $
a504 1
    memset(menuPtr, 0, sizeof(TkMenu));
d511 2
d514 12
d527 5
d534 5
a543 2
    Tk_CreateEventHandler(new, ExposureMask|StructureNotifyMask|ActivateMask,
	    TkMenuEventProc, (ClientData) menuPtr);
d548 1
d559 1
d563 2
d586 1
a586 1

d596 1
a596 1

d605 1
a605 1

d628 1
a628 1

d646 1
a646 1

d652 1
a652 1

d658 1
a658 1

d664 1
a664 1

a1188 3
    if (menuPtr->menuRefPtr == NULL) {
	return;
    }
@


1.20.2.6
log
@	* unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(),
	add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to
	configure (flag can't be present twice, so can't be in both CFLAGS and
	LDFLAGS during configure), don't use -prebind when deploying on 10.4,
	define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542).
	(SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete
	autoconf macros. Sync with tk/unix/tcl.m4, sync whitespace with HEAD.

	* unix/configure.in: fix obsolete autoconf macros, sync gratuitous
	formatting/ordering differences with tcl/unix/configure.in.

	* unix/Makefile.in: add CFLAGS to wish/tktest link to make executable
	linking the same as during configure (needed to avoid loosing any linker
	relevant flags in CFLAGS, in particular flags that can't be in LDFLAGS).
	Avoid concurrent linking of wish and compiling of tkTestInit.o during
	parallel make, fix dependencies and flags for building tkMacOSXInit.o
	(checkstubs, checkexports): dependency and Darwin fixes

	* macosx/tkMacOSXEvent.c (TkMacOSXProcessEvent):
	* macosx/tkMacOSXEvent.h:
	* macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent):
	* macosx/tkMacOSXCarbonEvents.c: install standard application event
	handler, add & call functions to start and stop carbon even timer that
	runs the tcl event loop periodically during a nested carbon event loop
	in the toolbox (e.g. during menutracking) to ensure tcl timers etc
	continue to fire, register app event handler for menu tracking and HI
	command carbon events, move menu event handling to new handlers for
	those carbon events, no longer register for/handle appleevent carbon
	event (now dealt with by standard application event handler), event
	debugging code dynamically acquires carbon event debugging functions to
	allow use on Tiger where they are no longer exported from HIToolbox.

	* macosx/tkMacOSXFont.c (TkMacOSXUseAntialiasedText):
	* macosx/tkMacOSXKeyEvent.c (GetKeyboardLayout):
	* macosx/tkMacOSXCarbonEvents.c (TkMacOSXInitCarbonEvents):
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXInt.h: abstract common code to dynamically acquire
	address of a named symbol (from a loaded dynamic library) into new
	function TkMacOSXGetNamedSymbol() and macro TkMacOSXInitNamedSymbol.

	* macosx/tkMacOSXMenu.c (TkpNewMenu):
	* macosx/tkMacOSXMenubutton.c (MenuButtonInitControl):
	* macosx/tkMacOSXMenus.c (TkMacOSXHandleMenuSelect): switch to  modern
	utf8 aware menu manager API, remove obsolete code, add error handling.

	* macosx/tkMacOSXMouseEvent.c: define OSX 10.3 or later only constants
	if necessary to allow compilation on OSX 10.2

	* macosx/tkMacOSXWm.c (UpdateSizeHints): remove code that is never
	executed.

	* generic/tk.h: add/correct location of version numbers in macosx files.

	* generic/tkInt.h: clarify fat compile comment.

	* macosx/Wish.pbproj/default.pbxuser (new file):
	* macosx/Wish.pbproj/jingham.pbxuser:
	* macosx/Wish.pbproj/project.pbxproj: sync with HEAD.

	* macosx/buildTkConfig.tcl (removed): remove obsolete build files.

	* macosx/README: clarification/cleanup, sync with HEAD, document
	universal (fat) builds via CFLAGS (i.e. ppc and i386 at the same time).

	* macosx/Makefile: add support for reusing configure cache, build target
	fixes.

	* generic/tkMenu.c:
	* macosx/tkMacOSXButton.c:
	* macosx/tkMacOSXDebug.c:
	* macosx/tkMacOSXDebug.h:
	* macosx/tkMacOSXDialog.c:
	* macosx/tkMacOSXDraw.c:
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXXStubs.c:
	* macosx/tkMacOSXSubwindows.c:
	* xlib/xgc.c: declare functions and globals used only in own file as
	static, #ifdef out a few Xlib and aqua functions that are never called
	(sync with HEAD).

	* macosx/tkMacOSXPort.h:
	* generic/tkInt.decls: correct signature of TkMacOSXHandleMenuSelect,
	add XSync to aqua Xlib stubs.

	* generic/tkTest.c: #ifdef unix only declarations.
	(TestmetricsCmd): unify win and mac implementation.

	* generic/tkTextDisp.c:
	* generic/tkTextBTree.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXXStubs.c: fix gcc 4 warnings.

	* macosx/tkMacOSXNotify.c:
	* macosx/tkMacOSXTest.c: sync with HEAD.

	* generic/tkIntPlatDecls.h:
	* generic/tkIntXlibDecls.h:
	* generic/tkStubInit.c:
	* unix/configure: regen.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.5 2005/05/31 05:05:35 hobbs Exp $
d122 1
a122 1
static Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
d171 1
a171 1
static Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
d178 1
a178 1
static Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
d201 1
a201 1
static Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
d221 1
a221 1
static Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
d229 1
a229 1
static Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
d251 1
a251 1
static Tk_OptionSpec tkMenuConfigSpecs[] = {
@


1.20.2.7
log
@	* generic/tkMenu.c (DeleteMenuCloneEntries): Modify entry index
	changes to work around VC6 optimization bug. [Bug 1224330]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.6 2005/11/27 02:44:25 das Exp $
d3492 1
a3492 1
    int numDeleted, i, j;
d3502 3
a3504 4
	    j = i - numDeleted;
	    menuListPtr->entries[j] = menuListPtr->entries[i];
	    menuListPtr->entries[j]->index = j;
	  }
@


1.20.2.8
log
@	* generic/tkImgPhoto.c:		fix leaks discovered with the Mac OS X
	* generic/tkMenu.c:		Instruments.app Leaks tool.
	* macosx/tkMacOSXWm.c:
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.7 2006/05/25 23:51:37 hobbs Exp $
a402 7
static void
FreeOptionTables(
    ClientData clientData)
{
    ckfree(clientData);
}

d427 1
a427 1
	    (ClientData) optionTablesPtr, FreeOptionTables);
@


1.20.2.9
log
@generic/tkMenu.c: Defer TkMenuOptionTables cleanup to CallWhenDeleted() time,
to ensure that the record doesn't get freed until after all widget
instance commands have been deleted (Fixes [Bug#2952745]).
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.20.2.8 2009/02/06 08:14:29 das Exp $
d405 1
a405 2
    ClientData clientData,
    Tcl_Interp *interp)
d433 2
a434 2
    Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr, 0);
    Tcl_CallWhenDeleted(interp, FreeOptionTables, optionTablesPtr);
@


1.19
log
@Applied companion patch for Tcl Patch 585105,
updating Tk to use Tcl 8.4's fully CONST-ified
interface, and fully CONSTifying Tk at the
same time.

This patch includes purging Tk of its last
direct access to interp->result.  [Bug 589853]

The substantial changes include copying
event sequence strings into Tcl_DStrings
in tkBind.c, and copying [text] indices into
Tcl_DStrings because parsing them involved
overwriting them.  If this causes performance
trouble, that can be resolved by further
converting them to Tcl_Obj's.

The #defines USE_NON_CONST and USE_COMPAT_CONST
have the same effect for Tk as they do for Tcl.
(They actually change tcl.h)
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.18 2002/04/12 07:28:06 hobbs Exp $
d373 1
d3459 23
d3501 1
a3501 1
    
d3508 4
@


1.18
log
@generic/tkMenu.c (ConfigureMenu): freed saved options in all error cases
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.17 2002/03/20 22:55:16 dgp Exp $
d363 2
a364 2
			    Tcl_Interp *interp, char *name1, CONST char *name2,
			    int flags));
d2471 1
a2471 1
    char *name1;		/* First part of variable's name. */
@


1.17
log
@	* Updates to handle change in type of part2 argument of
	Tcl_VarTraceProc typedef. [TIP 27] [Patch 532644].
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.16 2002/01/31 21:05:27 uid38226 Exp $
d1539 5
d1584 3
a1586 8
		    if (menuListPtr->errorStructPtr != NULL) {
			for (cleanupPtr = menuPtr->masterMenuPtr;
				cleanupPtr != menuListPtr;
				cleanupPtr = cleanupPtr->nextInstancePtr) {
			    Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
			    ckfree((char *) cleanupPtr->errorStructPtr);
			    cleanupPtr->errorStructPtr = NULL;
			}
d1590 5
@


1.16
log
@Correct and test for logic error when cloning menus. Bug 508988
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.15 2002/01/25 21:09:37 dgp Exp $
d363 1
a363 1
			    Tcl_Interp *interp, char *name1, char *name2,
d2467 1
a2467 1
    char *name2;		/* Second part of variable's name. */
@


1.15
log
@	* Updated callers of Tcl_SplitList and Tcl_Merge.
	* Updated callers of Tcl_GetStringResult.
	  Rewrote PrintScrollFractions to ScrollFractions to stop scribbling
	  directly on interp->result.
	* Updated callers of Tcl_GetVar, Tcl_GetVar2
	* Updated callers of Tcl_SplitPath, Tcl_JoinPath, and
	  Tcl_TranslateFileName.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.14 2002/01/17 05:13:11 dgp Exp $
d2001 1
a2001 1
		    == 0);
@


1.14
log
@	* Updates to handle change in type of tablePtr
        argument of Tcl_GetIndexFromObj(Struct) from (char **) to
        (CONST char **).  [TIP 27] [Patch 504705]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.13 2001/10/12 13:30:31 tmh Exp $
d2472 1
a2472 1
    char *value;
@


1.13
log
@implementation of TIP 63 (accepted) -compound option to menu items.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.12 2001/09/14 20:35:58 andreas_kupries Exp $
d108 4
a111 2
static char *menuEntryTypeStrings[] = {"cascade", "checkbutton", "command", 
	"radiobutton", "separator", (char *) NULL};
d248 1
a248 1
static char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
d316 1
a316 1
static char *menuOptions[] = {
d468 1
a468 1
    static char *typeStringList[] = {"-type", (char *) NULL};
d1017 1
a1017 1
		Tcl_SetResult(interp,
d1019 1
a1019 1
			TCL_STATIC);
@


1.13.2.1
log
@Merge with current TOT
Added support for the wm stackorder command
Fixed crash when selecting Menu items in the Application menu that we didn't
put there.
Added first bits of the use of CG for low-level drawing.  The line-drawing works,
the rest doesn't yet.  You have to set the file static useCGDrawing to 1 and
rebuild to activate this code.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.13 2001/10/12 13:30:31 tmh Exp $
d108 2
a109 4
static CONST char *menuEntryTypeStrings[] = {
    "cascade", "checkbutton", "command", "radiobutton", "separator",
    (char *) NULL
};
d246 1
a246 1
static CONST char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
d314 1
a314 1
static CONST char *menuOptions[] = {
d466 1
a466 1
    static CONST char *typeStringList[] = {"-type", (char *) NULL};
d1015 1
a1015 1
		Tcl_SetStringObj(Tcl_GetObjResult(interp),
d1017 1
a1017 1
			-1);
d1999 1
a1999 1
		    != 0);
d2470 1
a2470 1
    CONST char *value;
@


1.13.2.2
log
@Merging with TOT as of 06/09/2002.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id$
d363 1
a363 1
			    Tcl_Interp *interp, char *name1, CONST char *name2,
a1538 5
	    if (menuListPtr->errorStructPtr != NULL) {
		Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
		ckfree((char *) menuListPtr->errorStructPtr);
		menuListPtr->errorStructPtr = NULL;
	    }
d1579 8
a1586 3
		    for (cleanupPtr = menuPtr->masterMenuPtr;
			 cleanupPtr != menuListPtr;
			 cleanupPtr = cleanupPtr->nextInstancePtr) {
a1590 5
		    if (menuListPtr->errorStructPtr != NULL) {
			Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
			ckfree((char *) menuListPtr->errorStructPtr);
			menuListPtr->errorStructPtr = NULL;
		    }
d2467 1
a2467 1
    CONST char *name2;		/* Second part of variable's name. */
@


1.13.2.3
log
@merged with trunk at tag macosx-8-4-merge-2002-08-20-trunk
@
text
@d363 2
a364 2
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags));
d2471 1
a2471 1
    CONST char *name1;		/* First part of variable's name. */
@


1.12
log
@
	* generic/tkImgGIF.c:
	* generic/tkImgPPM.c:
	* generic/tkImgPhoto.c:
	* generic/tkMenu.c: Applied patch [461578], provided by Vincent
	  Darley. This fixes several memory leaks in the image code. They
	  happen if there are errors during the initialization of the
	  channel the image is supposed to be read from.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.11 2001/08/01 16:21:11 dgp Exp $
d111 9
d142 3
@


1.11
log
@	Merged changes from feature branch dgp-privates-into-namespace,
	implementing TIP 44.  All Tk commands and variables matching
	tk[A-Z]* are now in the ::tk namespace.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.10 2001/04/03 06:54:33 hobbs Exp $
d2721 4
a2724 1
		    Tcl_IncrRefCount(newElementPtr);
@


1.10
log
@	* generic/tkMenu.c (TkInvokeMenu): checked for menu deletion
	before calling associated menu entry command.  [Bug #220821]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.9 2000/11/22 01:49:38 ericm Exp $
d1073 1
a1073 1
	Tcl_DStringAppend(&ds, "tkTearOffMenu ", -1);
d2647 1
a2647 1
    menuDupCommandArray[0] = Tcl_NewStringObj("tkMenuDup", -1);
@


1.9
log
@	Overall change:  Implemented TIP 5, which exports
	TkClassProcs/TkSetClassProcs as Tk_ClassProcs/Tk_SetClassProcs,
	adding a size field to Tk_ClassProcs to allow for future
	expansion, and renaming the geometryProc to worldChangedProc,
	which is more in keeping with the actual use of the callback.

	See ChangeLog for details.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.8 2000/08/03 20:36:16 ericm Exp $
d1109 7
a1115 1
    if ((result == TCL_OK) && (mePtr->commandPtr != NULL)) {
d1124 1
a1124 1
    return result; 
d1272 1
a1272 1
    
d1279 1
a1279 1
    
d1296 1
a1296 1
    
d1302 1
a1302 1
    }   
@


1.9.2.1
log
@2001-02-28  Don Porter  <dgp@@users.sourceforge.net>

        BRANCH dgp-privates-into-namespace:  Feature branch to move all
        of Tk's private commands and variable into the ::tk namespace
        and its children.

        * doc/tkvars.n:  Documented private variable tkPriv renamed tk::Priv.

        * generic/tkBind.c:
        * generic/tkMenu.c:
        * generic/tkTextDisp.c:
        * library/bgerror.tcl:
        * library/button.tcl:
        * library/choosedir.tcl:
        * library/clrpick.tcl:
        * library/comdlg.tcl:
        * library/console.tcl:
        * library/dialog.tcl:
        * library/entry.tcl:
        * library/focus.tcl:
        * library/listbox.tcl:
        * library/menu.tcl:
        * library/msgbox.tcl:
        * library/optMenu.tcl:
        * library/palette.tcl:
        * library/scale.tcl:
        * library/scrlbar.tcl:
        * library/spinbox.tcl:
        * library/tclIndex:
        * library/tearoff.tcl:
        * library/text.tcl:
        * library/tk.tcl:
        * library/tkfbox.tcl:
        * library/xmfbox.tcl:
        * mac/tkMacMenu.c:
        * tests/clrpick.test:
        * tests/filebox.test:
        * tests/macMenu.test:
        * tests/menu.test:
        * tests/menuDraw.test:
        * tests/msgbox.test:
        * tests/text.test:
        * tests/textDisp.test:
        * tests/unixMenu.test:
        * tests/winMenu.test:
        * tests/xmfbox.test:
        * unix/tkUnixDialog.c:  All Tk commands matching ::tk[A-Z]* and
        all Tk private variables in the global namespace were renamed to
        live in the namespace ::tk or one of its children.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.9 2000/11/22 01:49:38 ericm Exp $
d1073 1
a1073 1
	Tcl_DStringAppend(&ds, "tk::TearOffMenu ", -1);
d2641 1
a2641 1
    menuDupCommandArray[0] = Tcl_NewStringObj("tk::MenuDup", -1);
@


1.9.2.2
log
@        * Merged in updates from HEAD branch.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.9.2.1 2001/02/28 23:29:55 dgp Exp $
d1109 1
a1109 7
    /*
     * We check numEntries in addition to whether the menu entry
     * has a command because that goes to zero if the menu gets
     * deleted (e.g., during command evaluation).
     */
    if ((menuPtr->numEntries != 0) && (result == TCL_OK)
	    && (mePtr->commandPtr != NULL)) {
d1118 1
a1118 1
    return result;
d1266 1
a1266 1

d1273 1
a1273 1

d1290 1
a1290 1

d1296 1
a1296 1
    }
@


1.8
log
@* tests/bind.test: Tweaked expected error messages for [bindtags]
to comply with updated error messages.

* generic/tkMenu.c (CloneMenu): Replaced calls to Tk_BindtagsCmd
with equivalent calls to Tk_BindtagsObjCmd.

* generic/tkInt.h: Replace Tk_BindtagsCmd prototype with
Tk_BindtagsObjCmd prototype.

* generic/tkWindow.c: Updated "bindtags" command entry to use
Tcl_Obj'ified command.

* generic/tkCmds.c (Tk_BindtagsObjCmd): Tcl_Obj'ified [bindtags]
command.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.7 2000/06/27 17:15:58 ericm Exp $
d366 3
a368 3
static TkClassProcs menuClass = {
    NULL,			/* createProc. */
    MenuWorldChanged		/* geometryProc. */
d374 1
a374 1
 * Tk_CreateMenuCmd --
d526 1
a526 1
    TkSetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
@


1.8.2.1
log
@sync with head
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.17 2002/03/20 22:55:16 dgp Exp $
d108 2
a109 13
static CONST char *menuEntryTypeStrings[] = {
    "cascade", "checkbutton", "command", "radiobutton", "separator",
    (char *) NULL
};

/*
 * The following table defines the legal values for the -compound option.
 * It is used with the "enum compound" declaration in tkMenu.h
 */

static char *compoundStrings[] = {
    "bottom", "center", "left", "none", "right", "top", (char *) NULL
};
a132 3
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
        DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
	(ClientData) compoundStrings, 0},
d234 1
a234 1
static CONST char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
d302 1
a302 1
static CONST char *menuOptions[] = {
d349 1
a349 1
			    Tcl_Interp *interp, char *name1, CONST char *name2,
d366 3
a368 3
static Tk_ClassProcs menuClass = {
    sizeof(Tk_ClassProcs),	/* size */
    MenuWorldChanged		/* worldChangedProc */
d374 1
a374 1
 * TkCreateMenuCmd --
d454 1
a454 1
    static CONST char *typeStringList[] = {"-type", (char *) NULL};
d526 1
a526 1
    Tk_SetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
d1003 1
a1003 1
		Tcl_SetStringObj(Tcl_GetObjResult(interp),
d1005 1
a1005 1
			-1);
d1073 1
a1073 1
	Tcl_DStringAppend(&ds, "tk::TearOffMenu ", -1);
d1109 1
a1109 7
    /*
     * We check numEntries in addition to whether the menu entry
     * has a command because that goes to zero if the menu gets
     * deleted (e.g., during command evaluation).
     */
    if ((menuPtr->numEntries != 0) && (result == TCL_OK)
	    && (mePtr->commandPtr != NULL)) {
d1118 1
a1118 1
    return result;
d1266 1
a1266 1

d1273 1
a1273 1

d1290 1
a1290 1

d1296 1
a1296 1
    }
d1981 1
a1981 1
		    != 0);
d2447 1
a2447 1
    CONST char *name2;		/* Second part of variable's name. */
d2452 1
a2452 1
    CONST char *value;
d2641 1
a2641 1
    menuDupCommandArray[0] = Tcl_NewStringObj("tk::MenuDup", -1);
d2715 1
a2715 4
		    /* 
		     * The newElementPtr will have its refCount incremented
		     * here, so we don't need to worry about it any more.
		     */
@


1.7
log
@* generic/tkMenu.c (DeleteMenuCloneEntries): Applied fix from
[Bug: 5275], which corrected a segfault-causing indexing problem
when deleting entries from torn-off menus.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.6 2000/02/10 08:52:35 hobbs Exp $
a2667 1
	char *newArgv[3];
d2694 6
a2699 4
   	newArgv[0] = "bindtags";
   	newArgv[1] = Tk_PathName(newMenuPtr->tkwin);
   	if (Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin, 
   		newMenuPtr->interp, 2, newArgv) == TCL_OK) {
d2705 1
d2718 3
a2720 3
   	    	    newArgv[2] = Tcl_GetStringFromObj(bindingsPtr, NULL);
		    Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin,
			    menuPtr->interp, 3, newArgv);
d2726 2
@


1.6
log
@	* generic/tkImgGIF.c (FileReadGIF): added cast for trashBuffer

	* generic/tkIntXlibDecls.h:
	* generic/tkInt.decls: declared some Xlib emulation calls for
	the Mac

	* generic/tkFrame.c (TkInstallFrameMenu): added extra panic to
	inform user of bad call when framePtr is NULL [Bug: 2530]

	* generic/tkMenu.c (DestroyMenuInstance): Placed checks around
	menu name objects before trying to incr the ref.  [Bug: 3402]

	* generic/tkTest.c: removed USE_OLD_IMAGE def for Mac
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.5 1999/04/21 21:53:26 rjohnson Exp $
d3406 1
a3406 1
	    menuListPtr->entries[i - numDeleted]->index = i;
@


1.6.2.1
log
@	* BACKPORTED FROM 8.4 (HEAD) BRANCH:

	* tests/button.test:
	* generic/tkButton.c: Added -activeforeground, -activebackground
	for labels, for the -state option.

	* doc/label.n: Added -disabledforeground to list of options [Bug:
	6053].

	* tests/focus.test (focusSetupAlt): removed wm withdraw from proc
	as it would cause a hang for tkwait visibility

	* tests/menu.test:
	* generic/tk3d.c:
	* generic/tkColor.c:
	* generic/tkCursor.c: corrected handling of 3DBorder, Cursor and
	Color objects on multiple screens. [Bug: 5454]

	* generic/tkCursor.c: Added initialization for nextPtr field of
	TkCursor, patch from Nijtmans/Howlett.

	* canvas.test: added test for 5783.
	* generic/tkCanvPoly.c (DisplayPolygon): added checks for the
	polygon fillGC not being empty to prevent segfault. [Bug: 5783]

	* generic/tkImgGIF.c: Applied patch from Jan Nijtmans to fix a
	problem with the GIF writing code [Bug:	5823].
	* generic/tkImgGIF.c: Changed defines for GIF87a/GIF89a to be
	static char arrays with integer initialization, to address EBCIDIC
	vs. ASCII encoding issues and to handle compilers that don't deal
	with "\xAB" syntax for specifying hex values in strings.

	* generic/tkMenu.c (DeleteMenuCloneEntries): Applied fix from
	[Bug: 5275], which corrected a segfault-causing indexing problem
	when deleting entries from torn-off menus.

	* generic/tkPlace.c (Tk_PlaceCmd): reworked place master/slave
	table init'n to prevent seg fault when using place on multiple
	displays.

	* tests/text.test: Added tests for -regexp -nocase searches with
	backslash character classes.
	* tests/text.test: Added tests for searching when text is elided.
	* generic/tkText.c (TextSearchCmd): Text search did not work
	properly when -regexp and -nocase were used, in combination with
	backslash character classes represented by capital letters (ie,
	\W, \M); altered implementation of -regexp -nocase searches to use
	new regexp interfaces to fix this problem.  [Bug: 5988].
	* generic/tkText.c (TextSearchCmd): Text search was not returning
	the correct index when the search covered (but did not search)
	elided characters; corrected this by adjusting the match index by
	the number of elided characters preceeding the start of the match,
	just as is done with embedded windows, etc. [Bug: 5470].
	* generic/tkText.c (TextSearchCmd): Added a test for a NULL
	segment pointer when doing backwards searches for "" on an empty
	text widget. [Bug: 6007].

	* library/focus.tcl: fixed calling of takeFocus proc [Bug: 5372]

	* win/tkWinMenu.c (ReconfigureWindowsMenu): Added MF_GRAYED bit
	for disabled menu entries, to ensure that those which are drawn by
	the system are shown grayed (such as entries on menubars) [Bug: 4372].
	* win/tkWinMenu.c (ReconfigureWindowsMenu): Added code to add the
	MF_SEPARATOR bit for SEPARATOR_ENTRY menu items.  This causes
	separator entries on the system menu to be drawn correctly [Bug: 5451].
	* win/tkWinMenu.c (GetMenuSeparatorGeometry): Tweaked height
	requested for separator bars to be (linespace - (2*descent))
	instead of just (linespace); this makes the separator occupy a
	more correct amount of vertical space. [Bug: 5303].
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.6 2000/02/10 08:52:35 hobbs Exp $
d3406 1
a3406 1
	    menuListPtr->entries[i - numDeleted]->index = i - numDeleted;
@


1.6.2.2
log
@see ChangeLog for specific file details
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.6.2.1 2000/08/05 23:53:12 hobbs Exp $
d1109 1
a1109 7
    /*
     * We check numEntries in addition to whether the menu entry
     * has a command because that goes to zero if the menu gets
     * deleted (e.g., during command evaluation).
     */
    if ((menuPtr->numEntries != 0) && (result == TCL_OK)
	    && (mePtr->commandPtr != NULL)) {
@


1.6.2.3
log
@
	* generic/tkImgGIF.c:
	* generic/tkImgPPM.c:
	* generic/tkImgPhoto.c:
	* generic/tkMenu.c: Applied patch [461578], provided by Vincent
	  Darley. This fixes several memory leaks in the image code. They
	  happen if there are errors during the initialization of the
	  channel the image is supposed to be read from.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.6.2.2 2001/04/04 07:57:17 hobbs Exp $
d2719 1
a2719 4
		    /* 
		     * The newElementPtr will have its refCount incremented
		     * here, so we don't need to worry about it any more.
		     */
@


1.6.2.4
log
@Correct and test for logic error when cloning menus. Bug 508988
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.6.2.3 2001/09/14 20:39:23 andreas_kupries Exp $
d1987 1
a1987 1
		    != 0);
@


1.5
log
@
Merged 8-1-0 into mainline.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.4 1999/04/16 18:30:28 surles Exp $
d1181 11
a1191 5
	    Tcl_IncrRefCount(newObjv[0]);
	    Tcl_IncrRefCount(newObjv[1]);
    	    ConfigureMenuEntry(cascadePtr, 2, newObjv);
	    Tcl_DecrRefCount(newObjv[0]);
	    Tcl_DecrRefCount(newObjv[1]);
@


1.4
log
@fixed Tk comment errors
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.3 1999/04/16 01:51:19 stanton Exp $
@


1.3
log
@* Merged 8.1 branch into the main trunk
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id$
d1207 1
a1207 1
     * let Tk_FreeConfigurationOptions handle all the standard option-related
d1406 1
a1406 1
     * let Tk_FreeConfigurationOptions handle all the standard option-related
@


1.3.2.1
log
@
Merged with mainline.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.4 1999/04/16 18:30:28 surles Exp $
d1207 1
a1207 1
     * let Tk_FreeConfigOptions handle all the standard option-related
d1406 1
a1406 1
     * let Tk_FreeConfigOptions handle all the standard option-related
@


1.2
log
@Replaced SCCS strings, fixed binary files
@
text
@d10 1
a10 1
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
d71 9
d85 15
a99 2
static int menusInitialized;	/* Whether or not the hash tables, etc., have
				 * been setup */
d106 79
a184 84
Tk_ConfigSpec tkMenuEntryConfigSpecs[] = {
    {TK_CONFIG_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorder),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ACTIVE_FG, Tk_Offset(TkMenuEntry, activeFg),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-accelerator", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ACCELERATOR, Tk_Offset(TkMenuEntry, accel),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_BORDER, "-background", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_BG, Tk_Offset(TkMenuEntry, border),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|SEPARATOR_MASK|TEAROFF_MASK|TK_CONFIG_NULL_OK},
    {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_BITMAP, Tk_Offset(TkMenuEntry, bitmap),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_COLUMN_BREAK, Tk_Offset(TkMenuEntry, columnBreak),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
    {TK_CONFIG_STRING, "-command", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_COMMAND, Tk_Offset(TkMenuEntry, command),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_FONT, Tk_Offset(TkMenuEntry, tkfont),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_FG, Tk_Offset(TkMenuEntry, fg),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_HIDE_MARGIN, Tk_Offset(TkMenuEntry, hideMargin),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|SEPARATOR_MASK|TEAROFF_MASK},
    {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_IMAGE, Tk_Offset(TkMenuEntry, imageString),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_NULL_OK},
    {TK_CONFIG_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_INDICATOR, Tk_Offset(TkMenuEntry, indicatorOn),
	CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_DONT_SET_DEFAULT},
    {TK_CONFIG_STRING, "-label", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_LABEL, Tk_Offset(TkMenuEntry, label),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
    {TK_CONFIG_STRING, "-menu", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_MENU, Tk_Offset(TkMenuEntry, name),
	CASCADE_MASK|TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-offvalue", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_OFF_VALUE, Tk_Offset(TkMenuEntry, offValue),
	CHECK_BUTTON_MASK},
    {TK_CONFIG_STRING, "-onvalue", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ON_VALUE, Tk_Offset(TkMenuEntry, onValue),
	CHECK_BUTTON_MASK},
    {TK_CONFIG_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT, Tk_Offset(TkMenuEntry, indicatorFg),
	CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-selectimage", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE, Tk_Offset(TkMenuEntry, selectImageString),
	CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
    {TK_CONFIG_UID, "-state", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_STATE, Tk_Offset(TkMenuEntry, state),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TEAROFF_MASK|TK_CONFIG_DONT_SET_DEFAULT},
    {TK_CONFIG_STRING, "-value", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_VALUE, Tk_Offset(TkMenuEntry, onValue),
	RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-variable", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_CHECK_VARIABLE, Tk_Offset(TkMenuEntry, name),
	CHECK_BUTTON_MASK|TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-variable", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_RADIO_VARIABLE, Tk_Offset(TkMenuEntry, name),
	RADIO_BUTTON_MASK},
    {TK_CONFIG_INT, "-underline", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_UNDERLINE, Tk_Offset(TkMenuEntry, underline),
	COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
	|TK_CONFIG_DONT_SET_DEFAULT},
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, 0}
d187 43
d231 1
a231 2
 * Configuration specs valid for the menu as a whole. If this changes, be sure
 * to update code in TkpMenuInit that changes the font string entry.
d234 9
a242 8
Tk_ConfigSpec tkMenuConfigSpecs[] = {
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_MENU_ACTIVE_BG_COLOR, Tk_Offset(TkMenu, activeBorder),
	TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_MENU_ACTIVE_BG_MONO, Tk_Offset(TkMenu, activeBorder),
	TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_PIXELS, "-activeborderwidth", "activeBorderWidth",
d244 19
a262 20
        Tk_Offset(TkMenu, activeBorderWidth), 0},
    {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_MENU_ACTIVE_FG_COLOR, Tk_Offset(TkMenu, activeFg),
	TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_MENU_ACTIVE_FG_MONO, Tk_Offset(TkMenu, activeFg),
	TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
	DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, border), TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
	DEF_MENU_BG_MONO, Tk_Offset(TkMenu, border), TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
	(char *) NULL, 0, 0},
    {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
	(char *) NULL, 0, 0},
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_MENU_BORDER_WIDTH, Tk_Offset(TkMenu, borderWidth), 0},
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_MENU_CURSOR, Tk_Offset(TkMenu, cursor), TK_CONFIG_NULL_OK},
    {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
d264 48
a311 34
	Tk_Offset(TkMenu, disabledFg), TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
    {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_MENU_DISABLED_FG_MONO,
	Tk_Offset(TkMenu, disabledFg), TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
    {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
	(char *) NULL, 0, 0},
    {TK_CONFIG_FONT, "-font", "font", "Font",
	DEF_MENU_FONT, Tk_Offset(TkMenu, tkfont), 0},
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
	DEF_MENU_FG, Tk_Offset(TkMenu, fg), 0},
    {TK_CONFIG_STRING, "-postcommand", "postCommand", "Command",
	DEF_MENU_POST_COMMAND, Tk_Offset(TkMenu, postCommand),
        TK_CONFIG_NULL_OK},
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
	DEF_MENU_RELIEF, Tk_Offset(TkMenu, relief), 0},
    {TK_CONFIG_COLOR, "-selectcolor", "selectColor", "Background",
	DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFg),
	TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_COLOR, "-selectcolor", "selectColor", "Background",
	DEF_MENU_SELECT_MONO, Tk_Offset(TkMenu, indicatorFg),
	TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_MENU_TAKE_FOCUS, Tk_Offset(TkMenu, takeFocus), TK_CONFIG_NULL_OK},
    {TK_CONFIG_BOOLEAN, "-tearoff", "tearOff", "TearOff",
	DEF_MENU_TEAROFF, Tk_Offset(TkMenu, tearOff), 0},
    {TK_CONFIG_STRING, "-tearoffcommand", "tearOffCommand", "TearOffCommand",
	DEF_MENU_TEAROFF_CMD, Tk_Offset(TkMenu, tearOffCommand),
	TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-title", "title", "Title",
    	DEF_MENU_TITLE, Tk_Offset(TkMenu, title), TK_CONFIG_NULL_OK},
    {TK_CONFIG_STRING, "-type", "type", "Type",
	DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypeName), TK_CONFIG_NULL_OK},
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, 0}
d319 1
a319 1
			    char *newMenuName, char *newMenuTypeString));
d321 1
a321 2
			    TkMenu *menuPtr, int argc, char **argv,
			    int flags));
d324 1
a324 1
			    int argc, char **argv, int flags));
d326 1
a326 1
			    int argc, char **argv, int flags));
d337 1
a337 1
			    TkMenu *menuPtr, char *arg));
d339 5
a343 2
			    TkMenu *menuPtr, char *indexString, int argc,
			    char **argv));
d351 3
a353 2
static int		MenuWidgetCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int argc, char **argv));
d356 1
d370 17
d388 29
d418 2
d424 1
a424 1
 * Tk_MenuCmd --
d439 2
a440 2
int
Tk_MenuCmd(clientData, interp, argc, argv)
d444 2
a445 2
    int argc;			/* Number of arguments. */
    char **argv;		/* Argument strings. */
d447 1
a447 1
    Tk_Window tkwin = (Tk_Window) clientData;
d451 1
a451 2
    int i, len;
    char *arg, c;
d453 3
d457 2
a458 3
    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"",
		argv[0], " pathName ?options?\"", (char *) NULL);
d465 5
a469 10
    for (i = 2; i < argc; i += 2) {
	arg = argv[i];
	len = strlen(arg);
	if (len < 2) {
	    continue;
	}
	c = arg[1];
	if ((c == 't') && (strncmp(arg, "-type", strlen(arg)) == 0)
		&& (len >= 3)) {
	    if (strcmp(argv[i + 1], "menubar") == 0) {
d476 2
a477 1
    new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], toplevel ? ""
d491 2
a492 2
    menuPtr->widgetCmd = Tcl_CreateCommand(interp,
	    Tk_PathName(menuPtr->tkwin), MenuWidgetCmd,
d497 15
a511 15
    menuPtr->border = NULL;
    menuPtr->borderWidth = 0;
    menuPtr->relief = TK_RELIEF_FLAT;
    menuPtr->activeBorder = NULL;
    menuPtr->activeBorderWidth = 0;
    menuPtr->tkfont = NULL;
    menuPtr->fg = NULL;
    menuPtr->disabledFg = NULL;
    menuPtr->activeFg = NULL;
    menuPtr->indicatorFg = NULL;
    menuPtr->tearOff = 1;
    menuPtr->tearOffCommand = NULL;
    menuPtr->cursor = None;
    menuPtr->takeFocus = NULL;
    menuPtr->postCommand = NULL;
d519 4
a522 2
    menuPtr->menuTypeName = NULL;
    menuPtr->title = NULL;
d525 11
d541 3
a543 1
    	goto error;
a545 2
    Tk_SetClass(menuPtr->tkwin, "Menu");
    TkSetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
d548 3
a550 2
    if (ConfigureMenu(interp, menuPtr, argc-2, argv+2, 0) != TCL_OK) {
	goto error;
d573 2
a574 2
        char *newMenuName;
        char *newArgv[2];
d593 7
a599 4
		newArgv[0] = "-menu";
		newArgv[1] = Tk_PathName(menuPtr->tkwin);
     	    	ConfigureMenuEntry(cascadeListPtr, 2, newArgv,
     	    	    TK_CONFIG_ARGV_ONLY);
d601 6
d608 3
a610 3
     	    		Tk_PathName(cascadeListPtr->menuPtr->tkwin),
     	    		menuPtr);
            	CloneMenu(menuPtr, newMenuName, "normal");
d617 8
a624 7
		newArgv[0] = "-menu";
                newArgv[1] = newMenuName;
                ConfigureMenuEntry(cascadeListPtr, 2, newArgv, 
                	TK_CONFIG_ARGV_ONLY);
	        if (newMenuName != NULL) {
	            ckfree(newMenuName);
	        }
d656 1
a656 1
    interp->result = Tk_PathName(menuPtr->tkwin);
a657 4

    error:
    Tk_DestroyWindow(menuPtr->tkwin);
    return TCL_ERROR;
d663 1
a663 1
 * MenuWidgetCmd --
d679 1
a679 1
MenuWidgetCmd(clientData, interp, argc, argv)
d682 2
a683 2
    int argc;			/* Number of arguments. */
    char **argv;		/* Argument strings. */
d688 1
a688 2
    size_t length;
    int c;
d690 6
a695 3
    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"",
		argv[0], " option ?arg arg ...?\"", (char *) NULL);
d699 24
a722 10
    c = argv[1][0];
    length = strlen(argv[1]);
    if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)
	    && (length >= 2)) {
	int index;

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " activate index\"", (char *) NULL);
	    goto error;
d724 26
a749 2
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
d751 38
a788 2
	if (menuPtr->active == index) {
	    goto done;
d790 30
a819 4
	if (index >= 0) {
	    if ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
		    || (menuPtr->entries[index]->state == tkDisabledUid)) {
		index = -1;
d821 2
d824 25
a848 7
	result = TkActivateMenuEntry(menuPtr, index);
    } else if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)
	    && (length >= 2)) {
	if (argc < 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " add type ?options?\"", (char *) NULL);
	    goto error;
d850 42
a891 3
	if (MenuAddOrInsert(interp, menuPtr, (char *) NULL,
		argc-2, argv+2) != TCL_OK) {
	    goto error;
d893 17
a909 7
    } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
	    && (length >= 2)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " cget option\"",
		    (char *) NULL);
	    goto error;
d911 27
a937 22
	result = Tk_ConfigureValue(interp, menuPtr->tkwin, tkMenuConfigSpecs,
		(char *) menuPtr, argv[2], 0);
    } else if ((c == 'c') && (strncmp(argv[1], "clone", length) == 0)
    	    && (length >=2)) {
    	if ((argc < 3) || (argc > 4)) {
    	    Tcl_AppendResult(interp, "wrong # args: should be \"",
    	    	    argv[0], " clone newMenuName ?menuType?\"",
    	    	    (char *) NULL);
    	    goto error;
    	}
    	result = CloneMenu(menuPtr, argv[2], (argc == 3) ? NULL : argv[3]);
    } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
	    && (length >= 2)) {
	if (argc == 2) {
	    result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
		    tkMenuConfigSpecs, (char *) menuPtr, (char *) NULL, 0);
	} else if (argc == 3) {
	    result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
		    tkMenuConfigSpecs, (char *) menuPtr, argv[2], 0);
	} else {
	    result = ConfigureMenu(interp, menuPtr, argc-2, argv+2,
		    TK_CONFIG_ARGV_ONLY);
d939 2
a940 2
    } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
	int first, last;
d942 7
a948 13
	if ((argc != 3) && (argc != 4)) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " delete first ?last?\"", (char *) NULL);
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &first) != TCL_OK) {
	    goto error;
	}
	if (argc == 3) {
	    last = first;
	} else {
	    if (TkGetMenuIndex(interp, menuPtr, argv[3], 0, &last) != TCL_OK) {
	        goto error;
a949 2
	}
	if (menuPtr->tearOff && (first == 0)) {
d952 4
a955 2
	     * Sorry, can't delete the tearoff entry;  must reconfigure
	     * the menu.
d958 6
a963 1
	    first = 1;
d965 20
a984 114
	if ((first < 0) || (last < first)) {
	    goto done;
	}
	DeleteMenuCloneEntries(menuPtr, first, last);
    } else if ((c == 'e') && (length >= 7)
	    && (strncmp(argv[1], "entrycget", length) == 0)) {
	int index;

	if (argc != 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " entrycget index option\"",
		    (char *) NULL);
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	Tcl_Preserve((ClientData) mePtr);
	result = Tk_ConfigureValue(interp, menuPtr->tkwin,
		tkMenuEntryConfigSpecs, (char *) mePtr, argv[3],
		COMMAND_MASK << mePtr->type);
	Tcl_Release((ClientData) mePtr);
    } else if ((c == 'e') && (length >= 7)
	    && (strncmp(argv[1], "entryconfigure", length) == 0)) {
	int index;

	if (argc < 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " entryconfigure index ?option value ...?\"",
		    (char *) NULL);
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	Tcl_Preserve((ClientData) mePtr);
	if (argc == 3) {
	    result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
		    tkMenuEntryConfigSpecs, (char *) mePtr, (char *) NULL,
		    COMMAND_MASK << mePtr->type);
	} else if (argc == 4) {
	    result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
		    tkMenuEntryConfigSpecs, (char *) mePtr, argv[3],
		    COMMAND_MASK << mePtr->type);
	} else {
	    result = ConfigureMenuCloneEntries(interp, menuPtr, index, 
	    	    argc-3, argv+3, 
	    	    TK_CONFIG_ARGV_ONLY | COMMAND_MASK << mePtr->type);
	}
	Tcl_Release((ClientData) mePtr);
    } else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
	    && (length >= 3)) {
	int index;

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " index string\"", (char *) NULL);
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    interp->result = "none";
	} else {
	    sprintf(interp->result, "%d", index);
	}
    } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
	    && (length >= 3)) {
	if (argc < 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " insert index type ?options?\"", (char *) NULL);
	    goto error;
	}
	if (MenuAddOrInsert(interp, menuPtr, argv[2],
		argc-3, argv+3) != TCL_OK) {
	    goto error;
	}
    } else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0)
	    && (length >= 3)) {
	int index;

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " invoke index\"", (char *) NULL);
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	result = TkInvokeMenu(interp, menuPtr, index);
    } else if ((c == 'p') && (strncmp(argv[1], "post", length) == 0)
	    && (length == 4)) {
	int x, y;

	if (argc != 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " post x y\"", (char *) NULL);
	    goto error;
	}
	if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
	    goto error;
d986 2
d989 19
a1007 19
	/*
	 * Tearoff menus are posted differently on Mac and Windows than
	 * non-tearoffs. TkpPostMenu does not actually map the menu's
	 * window on those platforms, and popup menus have to be
	 * handled specially.
	 */
	
    	if (menuPtr->menuType != TEAROFF_MENU) {
    	    result = TkpPostMenu(interp, menuPtr, x, y);
    	} else {
    	    result = TkPostTearoffMenu(interp, menuPtr, x, y);
    	}
    } else if ((c == 'p') && (strncmp(argv[1], "postcascade", length) == 0)
	    && (length > 4)) {
	int index;
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " postcascade index\"", (char *) NULL);
	    goto error;
d1009 6
a1014 4
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
d1016 8
a1023 59
	} else {
	    result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);
	}
    } else if ((c == 't') && (strncmp(argv[1], "type", length) == 0)) {
	int index;
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " type index\"", (char *) NULL);
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	switch (mePtr->type) {
	    case COMMAND_ENTRY:
		interp->result = "command";
		break;
	    case SEPARATOR_ENTRY:
		interp->result = "separator";
		break;
	    case CHECK_BUTTON_ENTRY:
		interp->result = "checkbutton";
		break;
	    case RADIO_BUTTON_ENTRY:
		interp->result = "radiobutton";
		break;
	    case CASCADE_ENTRY:
		interp->result = "cascade";
		break;
	    case TEAROFF_ENTRY:
		interp->result = "tearoff";
		break;
	}
    } else if ((c == 'u') && (strncmp(argv[1], "unpost", length) == 0)) {
	if (argc != 2) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " unpost\"", (char *) NULL);
	    goto error;
	}
	Tk_UnmapWindow(menuPtr->tkwin);
	result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
    } else if ((c == 'y') && (strncmp(argv[1], "yposition", length) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " yposition index\"", (char *) NULL);
	    goto error;
	}
	result = MenuDoYPosition(interp, menuPtr, argv[2]);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be activate, add, cget, clone, configure, delete, ",
		"entrycget, entryconfigure, index, insert, invoke, ",
		"post, postcascade, type, unpost, or yposition",
		(char *) NULL);
	goto error;
a1032 1

d1066 1
a1066 1
    if (mePtr->state == tkDisabledUid) {
d1071 10
a1080 8
    	Tcl_DString commandDString;
    	
    	Tcl_DStringInit(&commandDString);
    	Tcl_DStringAppendElement(&commandDString, "tkTearOffMenu");
    	Tcl_DStringAppendElement(&commandDString, Tk_PathName(menuPtr->tkwin));
    	result = Tcl_Eval(interp, Tcl_DStringValue(&commandDString));
    	Tcl_DStringFree(&commandDString);
    } else if (mePtr->type == CHECK_BUTTON_ENTRY) {
d1082 1
a1082 4
	    if (Tcl_SetVar(interp, mePtr->name, mePtr->offValue,
		    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
d1084 17
a1100 4
	    if (Tcl_SetVar(interp, mePtr->name, mePtr->onValue,
		    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
d1102 2
a1103 2
    } else if (mePtr->type == RADIO_BUTTON_ENTRY) {
	if (Tcl_SetVar(interp, mePtr->name, mePtr->onValue,
d1107 1
d1109 6
a1114 2
    if ((result == TCL_OK) && (mePtr->command != NULL)) {
	result = TkCopyAndGlobalEval(interp, mePtr->command);
a1119 2


d1144 1
a1144 1
    int i, numEntries = menuPtr->numEntries;
d1147 1
a1147 1
    char *newArgv[2];
a1149 1
    TkMenu *parentMenuPtr;
a1170 1
    	parentMenuPtr = cascadePtr->menuPtr;
d1174 2
d1179 7
a1185 3
	    newArgv[0] = "-menu";
	    newArgv[1] = parentMasterEntryPtr->name;
    	    ConfigureMenuEntry(cascadePtr, 2, newArgv, TK_CONFIG_ARGV_ONLY);
d1187 1
a1187 1
    	    ConfigureMenuEntry(cascadePtr, 0, (char **) NULL, 0);
d1207 1
a1207 1
     * let Tk_FreeOptions handle all the standard option-related
d1211 8
a1218 1
    for (i = numEntries - 1; i >= 0; i--) {
d1220 1
d1226 2
a1227 3
    Tk_FreeOptions(tkMenuConfigSpecs, (char *) menuPtr, menuPtr->display, 0);

    Tcl_EventuallyFree((ClientData) menuPtr, TCL_DYNAMIC);
d1406 1
a1406 1
     * let Tk_FreeOptions handle all the standard option-related
d1419 5
a1423 2
    if (mePtr->name != NULL) {
	Tcl_UntraceVar(menuPtr->interp, mePtr->name,
d1429 1
a1429 2
    Tk_FreeOptions(tkMenuEntryConfigSpecs, (char *) mePtr, menuPtr->display, 
	    (COMMAND_MASK << mePtr->type));
a1464 1

d1477 1
a1477 1
 *	returned, then interp->result contains an error message.
d1487 1
a1487 1
ConfigureMenu(interp, menuPtr, argc, argv, flags)
d1491 2
a1492 3
    int argc;			/* Number of valid entries in argv. */
    char **argv;		/* Arguments. */
    int flags;			/* Flags to pass to Tk_ConfigureWidget. */
d1495 2
a1496 1
    TkMenu* menuListPtr;
d1500 13
a1512 4
    
	if (Tk_ConfigureWidget(interp, menuListPtr->tkwin,
		tkMenuConfigSpecs, argc, argv, (char *) menuListPtr,
		flags) != TCL_OK) {
d1524 16
a1539 6
	    if (strcmp(menuListPtr->menuTypeName, "menubar") == 0) {
	    	menuListPtr->menuType = MENUBAR;
	    } else if (strcmp(menuListPtr->menuTypeName, "tearoff") == 0) {
	    	menuListPtr->menuType = TEAROFF_MENU;
	    } else {
	    	menuListPtr->menuType = MASTER_MENU;
d1542 2
a1543 1
	
d1549 1
a1549 1
	if (menuListPtr->tearOff) {
d1553 12
d1571 1
a1571 1

d1574 1
a1586 15

	/*
	 * Configure the new window to be either a pop-up menu
	 * or a tear-off menu.
	 * We don't do this for menubars since they are not toplevel
	 * windows. Also, since this gets called before CloneMenu has
	 * a chance to set the menuType field, we have to look at the
	 * menuTypeName field to tell that this is a menu bar.
	 */
	
	if (strcmp(menuListPtr->menuTypeName, "normal") == 0) {
	    TkpMakeMenuWindow(menuListPtr->tkwin, 1);
	} else if (strcmp(menuListPtr->menuTypeName, "tearoff") == 0) {
	    TkpMakeMenuWindow(menuListPtr->tkwin, 0);
	}
d1599 1
a1599 3
	    ConfigureMenuEntry(mePtr, 0,
	    	    (char **) NULL, TK_CONFIG_ARGV_ONLY 
	    	    | COMMAND_MASK << mePtr->type);
d1605 7
d1614 1
d1619 1
a1619 1
 * ConfigureMenuEntry --
d1621 3
a1623 2
 *	This procedure is called to process an argv/argc list in order
 *	to configure (or reconfigure) one entry in a menu.
d1627 1
a1627 1
 *	returned, then interp->result contains an error message.
d1637 2
a1638 8
ConfigureMenuEntry(mePtr, argc, argv, flags)
    register TkMenuEntry *mePtr;		/* Information about menu entry;  may
					 * or may not already have values for
					 * some fields. */
    int argc;				/* Number of valid entries in argv. */
    char **argv;			/* Arguments. */
    int flags;				/* Additional flags to pass to
					 * Tk_ConfigureWidget. */
d1642 1
a1645 21
     * If this entry is a check button or radio button, then remove
     * its old trace procedure.
     */

    if ((mePtr->name != NULL)
    	    && ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY))) {
	Tcl_UntraceVar(menuPtr->interp, mePtr->name,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuVarProc, (ClientData) mePtr);
    }
    
    if (menuPtr->tkwin != NULL) {
	if (Tk_ConfigureWidget(menuPtr->interp, menuPtr->tkwin, 
		tkMenuEntryConfigSpecs, argc, argv, (char *) mePtr,
		flags | (COMMAND_MASK << mePtr->type)) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    /*
d1651 1
a1651 1
    if (mePtr->label == NULL) {
d1654 1
a1654 1
	mePtr->labelLength = strlen(mePtr->label);
d1656 1
a1656 1
    if (mePtr->accel == NULL) {
d1659 1
a1659 1
	mePtr->accelLength = strlen(mePtr->accel);
d1668 1
a1668 1
    if ((mePtr->type == CASCADE_ENTRY) && (mePtr->name != NULL)) {
a1669 1
 	TkMenu *cascadeMenuPtr;
d1685 1
d1689 1
a1689 1
	    if (strcmp(oldHashKey, mePtr->name) != 0) {
d1695 2
a1696 4
		|| (strcmp(oldHashKey, mePtr->name) != 0)) {
	    menuRefPtr = TkCreateMenuReferences(menuPtr->interp,
		    mePtr->name);
	    cascadeMenuPtr = menuRefPtr->menuPtr;
a1732 38
    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
	char *value;

	if (mePtr->name == NULL) {
	    mePtr->name =
		    (char *) ckalloc((unsigned) (mePtr->labelLength + 1));
	    strcpy(mePtr->name, (mePtr->label == NULL) ? "" : mePtr->label);
	}
	if (mePtr->onValue == NULL) {
	    mePtr->onValue = (char *) ckalloc((unsigned)
		    (mePtr->labelLength + 1));
	    strcpy(mePtr->onValue, (mePtr->label == NULL) ? "" : mePtr->label);
	}

	/*
	 * 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.
	 */

	value = Tcl_GetVar(menuPtr->interp, mePtr->name, TCL_GLOBAL_ONLY);
	mePtr->entryFlags &= ~ENTRY_SELECTED;
	if (value != NULL) {
	    if (strcmp(value, mePtr->onValue) == 0) {
		mePtr->entryFlags |= ENTRY_SELECTED;
	    }
	} else {
	    Tcl_SetVar(menuPtr->interp, mePtr->name,
		    (mePtr->type == CHECK_BUTTON_ENTRY) ? mePtr->offValue : "",
		    TCL_GLOBAL_ONLY);
	}
	Tcl_TraceVar(menuPtr->interp, mePtr->name,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuVarProc, (ClientData) mePtr);
    }

d1739 3
a1741 2
    if (mePtr->imageString != NULL) {
	image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, mePtr->imageString,
d1753 4
a1756 2
    if (mePtr->selectImageString != NULL) {
	image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, mePtr->selectImageString,
d1769 127
d1898 1
a1898 1
    return TCL_OK;
d1910 1
a1910 1
 *	returned, then interp->result contains an error message.
d1920 1
a1920 1
ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
d1925 2
a1926 4
    int argc;				/* Number of valid entries in argv. */
    char **argv;			/* Arguments. */
    int flags;				/* Additional flags to pass to
					 * Tk_ConfigureWidget. */
d1930 1
a1930 2
    char *oldCascadeName = NULL, *newMenuName = NULL;
    int cascadeEntryChanged;
d1932 3
a1934 1
    
d1946 4
a1949 1
	oldCascadeName = mePtr->name;
d1952 1
a1952 1
    if (ConfigureMenuEntry(mePtr, argc, argv, flags) != TCL_OK) {
d1956 25
a1980 2
    cascadeEntryChanged = (mePtr->type == CASCADE_ENTRY)
	    && (oldCascadeName != mePtr->name);
d1983 2
a1984 2
	newMenuName = mePtr->name;
	if (newMenuName != NULL) {
d1986 1
a1986 1
		    mePtr->name);
d1996 3
a1998 3
	if (cascadeEntryChanged && (mePtr->name != NULL)) {
	    oldCascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp, 
		    mePtr->name);
d2006 1
a2006 1
    	if (ConfigureMenuEntry(mePtr, argc, argv, flags) != TCL_OK) {
d2010 1
a2010 1
	if (cascadeEntryChanged && (newMenuName != NULL)) {
d2012 10
a2021 5
		char *newArgV[2];
		char *newCloneName;

		newCloneName = TkNewMenuName(menuPtr->interp,
			Tk_PathName(menuListPtr->tkwin), 
d2023 13
a2035 7
		CloneMenu(cascadeMenuRefPtr->menuPtr, newCloneName,
			"normal");

		newArgV[0] = "-menu";
		newArgV[1] = newCloneName;
		ConfigureMenuEntry(mePtr, 2, newArgV, flags);
		ckfree(newCloneName);
d2054 1
a2054 1
 *	one).  Otherwise an error message is left in interp->result.
d2063 1
a2063 1
TkGetMenuIndex(interp, menuPtr, string, lastOK, indexPtr)
d2067 1
a2067 1
    char *string;		/* Specification of an entry in menu.  See
d2071 1
a2071 1
    int *indexPtr;		/* Where to store converted relief. */
d2074 1
d2078 1
a2078 1
	return TCL_OK;
d2084 1
a2084 1
	return TCL_OK;
d2089 1
a2089 1
	return TCL_OK;
d2095 1
a2095 1
	    return TCL_OK;
d2111 1
a2111 1
	    return TCL_OK;
d2117 4
a2120 3
	char *label;

	label = menuPtr->entries[i]->label;
d2122 1
a2122 1
		&& (Tcl_StringMatch(menuPtr->entries[i]->label, string))) {
d2124 1
a2124 1
	    return TCL_OK;
d2131 3
a2168 1
	menuPtr->tkwin = NULL;
d2224 1
d2226 1
a2226 1
    mePtr->label = NULL;
d2229 2
a2230 2
    mePtr->bitmap = None;
    mePtr->imageString = NULL;
d2232 1
a2232 1
    mePtr->selectImageString  = NULL;
d2234 1
a2234 1
    mePtr->accel = NULL;
d2236 8
a2243 8
    mePtr->state = tkNormalUid;
    mePtr->border = NULL;
    mePtr->fg = NULL;
    mePtr->activeBorder = NULL;
    mePtr->activeFg = NULL;
    mePtr->tkfont = NULL;
    mePtr->indicatorOn = 1;
    mePtr->indicatorFg = NULL;
d2246 2
a2247 2
    mePtr->command = NULL;
    mePtr->name = NULL;
d2249 2
a2250 2
    mePtr->onValue = NULL;
    mePtr->offValue = NULL;
d2254 5
d2261 2
d2266 1
a2266 1
    
d2288 1
a2288 1
MenuAddOrInsert(interp, menuPtr, indexString, argc, argv)
d2292 1
a2292 1
    char *indexString;			/* String describing index at which
d2295 2
a2296 2
    int argc;				/* Number of elements in argv. */
    char **argv;			/* Arguments to command:  first arg
d2300 1
a2300 2
    int c, type, index;
    size_t length;
d2304 2
a2305 2
    if (indexString != NULL) {
	if (TkGetMenuIndex(interp, menuPtr, indexString, 1, &index)
d2313 1
d2318 1
a2318 1
    if (menuPtr->tearOff && (index == 0)) {
d2326 2
a2327 21
    c = argv[0][0];
    length = strlen(argv[0]);
    if ((c == 'c') && (strncmp(argv[0], "cascade", length) == 0)
	    && (length >= 2)) {
	type = CASCADE_ENTRY;
    } else if ((c == 'c') && (strncmp(argv[0], "checkbutton", length) == 0)
	    && (length >= 2)) {
	type = CHECK_BUTTON_ENTRY;
    } else if ((c == 'c') && (strncmp(argv[0], "command", length) == 0)
	    && (length >= 2)) {
	type = COMMAND_ENTRY;
    } else if ((c == 'r')
	    && (strncmp(argv[0], "radiobutton", length) == 0)) {
	type = RADIO_BUTTON_ENTRY;
    } else if ((c == 's')
	    && (strncmp(argv[0], "separator", length) == 0)) {
	type = SEPARATOR_ENTRY;
    } else {
	Tcl_AppendResult(interp, "bad menu entry type \"",
		argv[0], "\": must be cascade, checkbutton, ",
		"command, radiobutton, or separator", (char *) NULL);
d2330 1
a2330 1
    
d2342 1
a2342 1
    	if (ConfigureMenuEntry(mePtr, argc-1, argv+1, 0) != TCL_OK) {
d2344 1
a2344 1
	    int i; 
d2377 2
a2378 1
    	    if ((mePtr->name != NULL)  && (mePtr->childMenuRefPtr != NULL)
d2382 6
a2387 2
    	        char *newCascadeName;
  		char *newArgv[2];
d2389 7
a2395 5
    	            
		newCascadeName = TkNewMenuName(menuListPtr->interp,
			Tk_PathName(menuListPtr->tkwin),
			cascadeMenuPtr);
		CloneMenu(cascadeMenuPtr, newCascadeName, "normal");
d2397 2
a2398 2
		menuRefPtr = TkFindMenuReferences(menuListPtr->interp,
			newCascadeName);
d2402 9
a2410 4
		newArgv[0] = "-menu";
		newArgv[1] = newCascadeName;
    	        ConfigureMenuEntry(mePtr, 2, newArgv, 0);
    	        ckfree(newCascadeName);
d2447 2
d2460 1
a2460 1
	    Tcl_TraceVar(interp, mePtr->name,
d2474 1
a2474 1
    value = Tcl_GetVar(interp, mePtr->name, TCL_GLOBAL_ONLY);
d2478 10
a2487 2
    if (strcmp(value, mePtr->onValue) == 0) {
	if (mePtr->entryFlags & ENTRY_SELECTED) {
a2489 3
	mePtr->entryFlags |= ENTRY_SELECTED;
    } else if (mePtr->entryFlags & ENTRY_SELECTED) {
	mePtr->entryFlags &= ~ENTRY_SELECTED;
d2535 2
a2536 2
	if (mePtr->state == tkActiveUid) {
	    mePtr->state = tkNormalUid;
d2543 1
a2543 1
	mePtr->state = tkActiveUid;
d2579 7
a2585 3
    if (menuPtr->postCommand != NULL) {
    	result = TkCopyAndGlobalEval(menuPtr->interp,
	        menuPtr->postCommand);
d2615 1
a2615 1
CloneMenu(menuPtr, newMenuName, newMenuTypeString)
d2617 2
a2618 2
    char *newMenuName;		/* The name to give the new menu */
    char *newMenuTypeString;	/* What kind of menu is this, a normal menu
d2622 1
a2622 2
    int menuType;
    size_t length;
d2624 1
a2624 1
    Tcl_Obj *commandObjPtr;
d2626 1
a2626 1
    if (newMenuTypeString == NULL) {
d2629 4
a2632 13
    	length = strlen(newMenuTypeString);
    	if (strncmp(newMenuTypeString, "normal", length) == 0) {
            menuType = MASTER_MENU;
    	} else if (strncmp(newMenuTypeString, "tearoff", length) == 0) {
            menuType = TEAROFF_MENU;
    	} else if (strncmp(newMenuTypeString, "menubar", length) == 0) {
            menuType = MENUBAR;
    	} else {
            Tcl_AppendResult(menuPtr->interp, 
            	    "bad menu type - must be normal, tearoff, or menubar",
        	    (char *) NULL);
            return TCL_ERROR;
    	}
d2635 5
a2639 10
    commandObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
    	    Tcl_NewStringObj("tkMenuDup", -1));
    Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
    	    Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1));
    Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
    	    Tcl_NewStringObj(newMenuName, -1));
    if ((newMenuTypeString == NULL) || (newMenuTypeString[0] == '\0')) {
    	Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
    		Tcl_NewStringObj("normal", -1));
d2641 4
a2644 2
    	Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
    		Tcl_NewStringObj(newMenuTypeString, -1));
a2645 1
    Tcl_IncrRefCount(commandObjPtr);
d2647 4
a2650 2
    returnResult = Tcl_EvalObj(menuPtr->interp, commandObjPtr);
    Tcl_DecrRefCount(commandObjPtr);
d2657 2
a2658 2
    	    ((menuRefPtr = TkFindMenuReferences(menuPtr->interp, newMenuName))
	    != (TkMenuReferences *) NULL)
d2661 1
d2694 2
a2695 2
   	    Tcl_Obj *bindingsPtr = 
   	    		Tcl_NewStringObj(newMenuPtr->interp->result, -1);
d2707 1
d2711 2
a2712 2
   	    	    Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin,
   	    	    	    menuPtr->interp, 3, newArgv);
a2724 1
   	    char *newCascadeName;
d2729 1
a2729 1
		&& (menuPtr->entries[i]->name != NULL)) {
d2731 2
a2732 2
			TkFindMenuReferences(menuPtr->interp,
			menuPtr->entries[i]->name);
d2734 4
a2737 1
   	    	    char *nameString;
d2741 13
a2753 10
		    nameString = Tk_PathName(newMenuPtr->tkwin);
   	    	    newCascadeName = TkNewMenuName(menuPtr->interp,
   	    	     	    nameString, oldCascadePtr);
		    CloneMenu(oldCascadePtr, newCascadeName, NULL);

		    newArgv[0] = "-menu";
		    newArgv[1] = newCascadeName;
		    ConfigureMenuEntry(newMenuPtr->entries[i], 2, newArgv, 
		    	    TK_CONFIG_ARGV_ONLY);
		    ckfree(newCascadeName);
d2783 1
a2783 1
MenuDoYPosition(interp, menuPtr, arg)
d2786 1
a2786 1
    char *arg;
d2791 1
a2791 1
    if (TkGetMenuIndex(interp, menuPtr, arg, 0, &index) != TCL_OK) {
d2794 1
d2796 1
a2796 1
        interp->result = "0";
d2798 1
a2798 1
    	sprintf(interp->result, "%d", menuPtr->entries[index]->y);
d2800 1
d2850 2
a2851 1
	x = menuPtr->borderWidth;
d2927 2
a2928 2
char *
TkNewMenuName(interp, parentName, menuPtr)
d2930 1
a2930 1
    char *parentName;		/* The prefix path of the new name. */
d2933 3
a2935 2
    Tcl_DString resultDString;
    Tcl_DString childDString;
d2937 2
a2938 2
    int offset, i;
    int doDot = parentName[strlen(parentName) - 1] != '.';
a2939 1
    char *returnString;
d2942 2
d2947 5
a2951 4
    
    Tcl_DStringInit(&childDString);
    Tcl_DStringAppend(&childDString, Tk_PathName(menuPtr->tkwin), -1);
    for (destString = Tcl_DStringValue(&childDString);
a2957 2
    offset = 0;
    
d2960 1
a2960 2
    	    Tcl_DStringInit(&resultDString);
    	    Tcl_DStringAppend(&resultDString, parentName, -1);
d2962 1
a2962 1
    	    	Tcl_DStringAppend(&resultDString, ".", -1);
d2964 1
a2964 3
    	    Tcl_DStringAppend(&resultDString,
    	    	    Tcl_DStringValue(&childDString), -1);
    	    destString = Tcl_DStringValue(&resultDString);
d2966 11
a2976 6
    	    if (i == 1) {
    	    	offset = Tcl_DStringLength(&resultDString);
    	    	Tcl_DStringSetLength(&resultDString, offset + 10);
    	    	destString = Tcl_DStringValue(&resultDString);
    	    }
    	    sprintf(destString + offset, "%d", i);
d2978 1
d2985 2
a2986 5
    returnString = ckalloc(strlen(destString) + 1);
    strcpy(returnString, destString);
    Tcl_DStringFree(&resultDString);
    Tcl_DStringFree(&childDString);
    return returnString;    	   
d3101 1
a3101 1
   	    char *cloneMenuName;
d3103 4
a3106 1
	    char *newArgv[4];
d3112 2
a3113 1
    	    cloneMenuName = TkNewMenuName(interp, Tk_PathName(tkwin),
d3115 3
a3117 1
            CloneMenu(menuPtr, cloneMenuName, "menubar");
d3119 1
a3119 1
            cloneMenuRefPtr = TkFindMenuReferences(interp, cloneMenuName);
d3122 2
d3126 4
a3129 2
		newArgv[0] = "-cursor";
		newArgv[1] = "";
d3131 3
a3133 1
			2, newArgv, TK_CONFIG_ARGV_ONLY);
d3137 3
a3139 2
		        
            ckfree(cloneMenuName);
d3306 29
d3437 3
d3441 10
a3450 2
    	TkpMenuInit();
    	menusInitialized = 1;
@


1.1
log
@Initial revision
@
text
@d15 1
a15 1
 * SCCS: @@(#) tkMenu.c 1.148 97/10/29 09:22:00
@


1.1.4.1
log
@initial tk8.1a2 version
@
text
@d10 1
a10 1
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
d15 1
a15 1
 * SCCS: @@(#) tkMenu.c 1.165 98/02/11 19:02:31
a70 1
#define __NO_OLD_CONFIG
d84 84
a167 99
char *tkMenuStateStrings[] = {"active", "normal", "disabled", (char *) NULL};

static char *menuEntryTypeStrings[] = {"cascade", "checkbutton", "command", 
	"radiobutton", "separator", (char *) NULL};

Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1, 
	TK_OPTION_NULL_OK},
    {TK_OPTION_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ACTIVE_FG,
	Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-accelerator", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ACCELERATOR,
	Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_BITMAP,
	Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_COLUMN_BREAK,
        Tk_Offset(TkMenuEntry, columnBreakPtr), -1},
    {TK_OPTION_STRING, "-command", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_COMMAND,
	Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_FONT,
	Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_COLOR, "-foreground", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_FG,
	Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_HIDE_MARGIN,
	Tk_Offset(TkMenuEntry, hideMarginPtr), -1},
    {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_IMAGE,
	Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-label", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_LABEL,
	Tk_Offset(TkMenuEntry, labelPtr), -1, 0},
    {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_STATE,
	Tk_Offset(TkMenuEntry, statePtr), -1, 0,
	(ClientData) tkMenuStateStrings},
    {TK_OPTION_INT, "-underline", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline)},
    {TK_OPTION_END}
};

Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_END}
};

Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
    {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_INDICATOR,
	Tk_Offset(TkMenuEntry, indicatorOnPtr), -1},
    {TK_OPTION_STRING, "-offvalue", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_OFF_VALUE,
	Tk_Offset(TkMenuEntry, offValuePtr), -1},
    {TK_OPTION_STRING, "-onvalue", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_ON_VALUE,
	Tk_Offset(TkMenuEntry, onValuePtr), -1},
    {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT,
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE,
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_CHECK_VARIABLE,
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
};

Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
    {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_INDICATOR,
	Tk_Offset(TkMenuEntry, indicatorOnPtr), -1},
    {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT,
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE, 
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-value", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_VALUE,
	Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_RADIO_VARIABLE,
	Tk_Offset(TkMenuEntry, namePtr), -1, 0},
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
a169 23
Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
    {TK_OPTION_STRING, "-menu", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_MENU,
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs}
};

Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
	DEF_MENU_ENTRY_STATE, Tk_Offset(TkMenuEntry, statePtr), -1, 0,
	(ClientData) tkMenuStateStrings},
    {TK_OPTION_END}
};

static Tk_OptionSpec *specsArray[] = {
    tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,
    tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,
    tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs};
    
d171 2
a172 1
 * Menu type strings for use with Tcl_GetIndexFromObj.
d175 8
a182 9
static char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
	(char *) NULL};

Tk_OptionSpec tkMenuConfigSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", 
	"Foreground", DEF_MENU_ACTIVE_BG_COLOR, 
	Tk_Offset(TkMenu, activeBorderPtr), -1, 0,
	(ClientData) DEF_MENU_ACTIVE_BG_MONO},
    {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
d184 20
a203 19
        Tk_Offset(TkMenu, activeBorderWidthPtr), -1},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", 
	"Background", DEF_MENU_ACTIVE_FG_COLOR, 
	Tk_Offset(TkMenu, activeFgPtr), -1, 0,
	(ClientData) DEF_MENU_ACTIVE_FG_MONO},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0,
	(ClientData) DEF_MENU_BG_MONO},
    {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"},
    {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) "-background"},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_MENU_BORDER_WIDTH,
	Tk_Offset(TkMenu, borderWidthPtr), -1, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_MENU_CURSOR,
	Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
d205 34
a238 49
	Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK,
	(ClientData) DEF_MENU_DISABLED_FG_MONO},
    {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL,
	(char *) NULL, 0, -1, 0, (ClientData) "-foreground"},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1},
    {TK_OPTION_STRING, "-postcommand", "postCommand", "Command",
	DEF_MENU_POST_COMMAND, 
	Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1},
    {TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background",
	DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0,
	(ClientData) DEF_MENU_SELECT_MONO},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_MENU_TAKE_FOCUS,
	Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff",
	DEF_MENU_TEAROFF,
	Tk_Offset(TkMenu, tearoffPtr), -1},
    {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand", 
	"TearOffCommand", DEF_MENU_TEAROFF_CMD,
	Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK},
    {TK_OPTION_STRING, "-title", "title", "Title",
	DEF_MENU_TITLE,  Tk_Offset(TkMenu, titlePtr), -1,
	TK_OPTION_NULL_OK},
    {TK_OPTION_STRING_TABLE, "-type", "type", "Type",
	DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK,
	(ClientData) menuTypeStrings},
    {TK_OPTION_END}
};

/*
 * Command line options. Put here because MenuCmd has to look at them
 * along with MenuWidgetObjCmd.
 */

static char *menuOptions[] = {
    "activate", "add", "cget", "clone", "configure", "delete", "entrycget",
    "entryconfigure", "index", "insert", "invoke", "post", "postcascade",
    "type", "unpost", "yposition", (char *) NULL
};
enum options {
    MENU_ACTIVATE, MENU_ADD, MENU_CGET, MENU_CLONE, MENU_CONFIGURE,
    MENU_DELETE, MENU_ENTRYCGET, MENU_ENTRYCONFIGURE, MENU_INDEX,
    MENU_INSERT, MENU_INVOKE, MENU_POST, MENU_POSTCASCADE, MENU_TYPE,
    MENU_UNPOST, MENU_YPOSITION
d246 1
a246 1
			    Tcl_Obj *newMenuName, Tcl_Obj *newMenuTypeString));
d248 2
a249 1
			    TkMenu *menuPtr, int objc, Tcl_Obj *CONST objv[]));
d252 1
a252 1
			    int objc, Tcl_Obj *CONST objv[]));
d254 1
a254 1
			    int objc, Tcl_Obj *CONST objv[]));
d265 1
a265 1
			    TkMenu *menuPtr, Tcl_Obj *objPtr));
d267 2
a268 5
			    TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc,
			    Tcl_Obj *CONST objv[]));
static int		MenuCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, 
			    Tcl_Obj *CONST objv[]));
d276 2
a277 3
static int		MenuWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, 
			    Tcl_Obj *CONST objv[]));
a279 1
static int		PostProcessEntry _ANSI_ARGS_((TkMenuEntry *mePtr));
a292 17

/*
 *--------------------------------------------------------------
 *
 * Tk_CreateMenuCmd --
 *
 *	Called by Tk at initialization time to create the menu
 *	command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */
a293 22
int
TkCreateMenuCmd(interp)
    Tcl_Interp *interp;		/* Interpreter we are creating the 
				 * command in. */
{
    TkMenuOptionTables *optionTablesPtr = 
	    (TkMenuOptionTables *) ckalloc(sizeof(TkMenuOptionTables));

    optionTablesPtr->menuOptionTable = 
	    Tk_CreateOptionTable(interp, tkMenuConfigSpecs);
    optionTablesPtr->entryOptionTables[TEAROFF_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[TEAROFF_ENTRY]);
    optionTablesPtr->entryOptionTables[COMMAND_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[COMMAND_ENTRY]);
    optionTablesPtr->entryOptionTables[CASCADE_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[CASCADE_ENTRY]);
    optionTablesPtr->entryOptionTables[SEPARATOR_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[SEPARATOR_ENTRY]);
    optionTablesPtr->entryOptionTables[RADIO_BUTTON_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[RADIO_BUTTON_ENTRY]);
    optionTablesPtr->entryOptionTables[CHECK_BUTTON_ENTRY] =
	    Tk_CreateOptionTable(interp, specsArray[CHECK_BUTTON_ENTRY]);
a294 9
    Tcl_CreateObjCommand(interp, "menu", MenuCmd,
	    (ClientData) optionTablesPtr, NULL);

    if (Tcl_IsSafe(interp)) {
	Tcl_HideCommand(interp, "menu", "menu");
    }

    return TCL_OK;
}
d299 1
a299 1
 * MenuCmd --
d314 2
a315 2
static int
MenuCmd(clientData, interp, objc, objv)
d319 2
a320 2
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument strings. */
d322 1
a322 1
    Tk_Window tkwin = Tk_MainWindow(interp);
d326 2
a327 1
    int i, index;
a328 3
    char *windowName;
    static char *typeStringList[] = {"-type", (char *) NULL};
    TkMenuOptionTables *optionTablesPtr = (TkMenuOptionTables *) clientData;
d330 3
a332 2
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
d339 10
a348 5
    for (i = 2; i < (objc - 1); i++) {
	if (Tcl_GetIndexFromObj(NULL, objv[i], typeStringList, NULL, 0, &index)
		!= TCL_ERROR) {
	    if ((Tcl_GetIndexFromObj(NULL, objv[i + 1], menuTypeStrings, NULL,
		    0, &index) == TCL_OK) && (index == MENUBAR)) {
d355 1
a355 2
    windowName = Tcl_GetStringFromObj(objv[1], NULL);
    new = Tk_CreateWindowFromPath(interp, tkwin, windowName, toplevel ? ""
d369 2
a370 2
    menuPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd,
d375 15
a389 15
    menuPtr->borderPtr = NULL;
    menuPtr->borderWidthPtr = NULL;
    menuPtr->reliefPtr = NULL;
    menuPtr->activeBorderPtr = NULL;
    menuPtr->activeBorderWidthPtr = NULL;
    menuPtr->fontPtr = NULL;
    menuPtr->fgPtr = NULL;
    menuPtr->disabledFgPtr = NULL;
    menuPtr->activeFgPtr = NULL;
    menuPtr->indicatorFgPtr = NULL;
    menuPtr->tearoffPtr = NULL;
    menuPtr->tearoffCommandPtr = NULL;
    menuPtr->cursorPtr = None;
    menuPtr->takeFocusPtr = NULL;
    menuPtr->postCommandPtr = NULL;
d397 2
a398 4
    menuPtr->menuTypePtr = NULL;
    menuPtr->titlePtr = NULL;
    menuPtr->errorStructPtr = NULL;
    menuPtr->optionTablesPtr = optionTablesPtr;
a400 11
    Tk_SetClass(menuPtr->tkwin, "Menu");
    TkSetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
    if (Tk_InitOptions(interp, (char *) menuPtr,
	    menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin)
	    != TCL_OK) {
    	Tk_DestroyWindow(menuPtr->tkwin);
    	ckfree((char *) menuPtr);
    	return TCL_ERROR;
    }


d406 1
a406 3
    	Tk_DestroyWindow(menuPtr->tkwin);
    	ckfree((char *) menuPtr);
    	return TCL_ERROR;
d409 2
d413 2
a414 3
    if (ConfigureMenu(interp, menuPtr, objc - 2, objv + 2) != TCL_OK) {
    	Tk_DestroyWindow(menuPtr->tkwin);
    	return TCL_ERROR;
d437 2
a438 2
        Tcl_Obj *newMenuName;
	Tcl_Obj *newObjv[2];
d457 4
a460 7
		newObjv[0] = Tcl_NewStringObj("-menu", -1);
		newObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
		Tcl_IncrRefCount(newObjv[0]);
		Tcl_IncrRefCount(newObjv[1]);
     	    	ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
		Tcl_DecrRefCount(newObjv[0]);
		Tcl_DecrRefCount(newObjv[1]);
a461 6
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
		Tcl_Obj *windowNamePtr = Tcl_NewStringObj(
			Tk_PathName(cascadeListPtr->menuPtr->tkwin), -1);

		Tcl_IncrRefCount(normalPtr);
		Tcl_IncrRefCount(windowNamePtr);
d463 3
a465 3
     	    		windowNamePtr, menuPtr);
		Tcl_IncrRefCount(newMenuName);
            	CloneMenu(menuPtr, newMenuName, normalPtr);
d472 7
a478 8
		newObjv[0] = Tcl_NewStringObj("-menu", -1);
		newObjv[1] = newMenuName;
		Tcl_IncrRefCount(newObjv[0]);
                ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
		Tcl_DecrRefCount(normalPtr);
		Tcl_DecrRefCount(newObjv[0]);
		Tcl_DecrRefCount(newObjv[1]);
		Tcl_DecrRefCount(windowNamePtr);
d510 1
a510 1
    Tcl_SetResult(interp, Tk_PathName(menuPtr->tkwin), TCL_STATIC);
d512 4
d521 1
a521 1
 * MenuWidgetObjCmd --
d537 1
a537 1
MenuWidgetObjCmd(clientData, interp, objc, objv)
d540 2
a541 2
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument strings. */
d546 2
a547 1
    int option;
d549 3
a551 6
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], menuOptions, "option", 0,
	    &option) != TCL_OK) {
d555 16
a570 30

    switch ((enum options) option) {
	case MENU_ACTIVATE: {
	    int index;

	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "activate index");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if (menuPtr->active == index) {
		goto done;
	    }
	    if (index >= 0) {
		if (menuPtr->entries[index]->type == SEPARATOR_ENTRY) {
		    int state;
		    
		    Tcl_GetIndexFromObj(interp, 
			    menuPtr->entries[index]->statePtr, 
			    tkMenuStateStrings, NULL, 0, &state);
		    if (state == ENTRY_DISABLED) {
			index = -1;
		    }
		}
	    }
	    result = TkActivateMenuEntry(menuPtr, index);
	    break;
d572 4
a575 23
	case MENU_ADD:
	    if (objc < 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "add type ?options?");
		goto error;
	    }

	    if (MenuAddOrInsert(interp, menuPtr, (Tcl_Obj *) NULL,
		    objc - 2, objv + 2) != TCL_OK) {
		goto error;
	    }
	    break;
	case MENU_CGET: {
	    Tcl_Obj *resultPtr;

	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "cget option");
		goto error;
	    }
	    resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr,
		    menuPtr->optionTablesPtr->menuOptionTable, objv[2],
		    menuPtr->tkwin);
	    if (resultPtr == NULL) {
		goto error;
a576 2
	    Tcl_SetObjResult(interp, resultPtr);
	    break;
d578 7
a584 38
	case MENU_CLONE:
	    if ((objc < 3) || (objc > 4)) {
		Tcl_WrongNumArgs(interp, 1, objv,
			"clone newMenuName ?menuType?");
		goto error;
	    }
    	    result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);
	    break;
	case MENU_CONFIGURE: {
	    Tcl_Obj *resultPtr;

	    if (objc == 2) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
			menuPtr->optionTablesPtr->menuOptionTable,
			(Tcl_Obj *) NULL, menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else if (objc == 3) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
			menuPtr->optionTablesPtr->menuOptionTable,
			objv[2], menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else {
    		result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
	    }
	    if (result != TCL_OK) {
		goto error;
	    }
	    break;
d586 3
a588 34
	case MENU_DELETE: {
	    int first, last, tearoff;
	    
	    if ((objc != 3) && (objc != 4)) {
		Tcl_WrongNumArgs(interp, 1, objv, "delete first ?last?");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first) 
		    != TCL_OK) {
		goto error;
	    }
	    if (objc == 3) {
		last = first;
	    } else {
		if (TkGetMenuIndex(interp, menuPtr, objv[3], 0, &last) 
			!= TCL_OK) {
		    goto error;
		}
	    }
	    Tcl_GetBooleanFromObj(interp, menuPtr->tearoffPtr, &tearoff);
	    if (tearoff && (first == 0)) {

		/*
		 * Sorry, can't delete the tearoff entry;  must reconfigure
		 * the menu.
		 */
		
		first = 1;
	    }
	    if ((first < 0) || (last < first)) {
		goto done;
	    }
	    DeleteMenuCloneEntries(menuPtr, first, last);
	    break;
d590 7
a596 25
	case MENU_ENTRYCGET: {
	    int index;
	    Tcl_Obj *resultPtr;

	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "entrycget index option");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) 
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    mePtr = menuPtr->entries[index];
	    Tcl_Preserve((ClientData) mePtr);
	    resultPtr = Tk_GetOptionValue(interp, (char *) mePtr, 
		    mePtr->optionTable, objv[3], menuPtr->tkwin);
	    Tcl_Release((ClientData) mePtr);
	    if (resultPtr == NULL) {
		goto error;
	    }
	    Tcl_SetObjResult(interp, resultPtr);
	    break;
d598 22
a619 42
	case MENU_ENTRYCONFIGURE: {
	    int index;
	    Tcl_Obj *resultPtr;

	    if (objc < 3) {
		Tcl_WrongNumArgs(interp, 1, objv, 
			"entryconfigure index ?option value ...?");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    mePtr = menuPtr->entries[index];
	    Tcl_Preserve((ClientData) mePtr);
	    if (objc == 3) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
			mePtr->optionTable, (Tcl_Obj *) NULL, menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else if (objc == 4) {
		resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
			mePtr->optionTable, objv[3], menuPtr->tkwin);
		if (resultPtr == NULL) {
		    result = TCL_ERROR;
		} else {
		    result = TCL_OK;
		    Tcl_SetObjResult(interp, resultPtr);
		}
	    } else {
		result = ConfigureMenuCloneEntries(interp, menuPtr, index,
			objc - 3, objv + 3);
	    }
	    Tcl_Release((ClientData) mePtr);
	    break;
d621 2
a622 2
	case MENU_INDEX: {
	    int index;
d624 7
a630 14
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "index string");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) 
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	    }
	    break;
d632 5
a636 9
	case MENU_INSERT:
	    if (objc < 4) {
		Tcl_WrongNumArgs(interp, 1, objv, 
			"insert index type ?options?");
		goto error;
	    }
	    if (MenuAddOrInsert(interp, menuPtr, objv[2], objc - 3,
		    objv + 3) != TCL_OK) {
		goto error;
a637 17
	    break;
	case MENU_INVOKE: {
	    int index;

	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "invoke index");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    result = TkInvokeMenu(interp, menuPtr, index);
	    break;
d639 1
a639 11
	case MENU_POST: {
	    int x, y;

	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "post x y");
		goto error;
	    }
	    if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		    || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
		goto error;
	    }
d642 2
a643 4
	     * Tearoff menus are posted differently on Mac and Windows than
	     * non-tearoffs. TkpPostMenu does not actually map the menu's
	     * window on those platforms, and popup menus have to be
	     * handled specially.
d646 116
a761 6
    	    if (menuPtr->menuType != TEAROFF_MENU) {
    		result = TkpPostMenu(interp, menuPtr, x, y);
    	    } else {
    		result = TkPostTearoffMenu(interp, menuPtr, x, y);
    	    }
	    break;
a762 2
	case MENU_POSTCASCADE: {
	    int index;
d764 19
a782 17
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "postcascade index");
		goto error;
	    }

	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
		    != TCL_OK) {
		goto error;
	    }
	    if ((index < 0) || (menuPtr->entries[index]->type 
		    != CASCADE_ENTRY)) {
		result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
	    } else {
		result = TkPostSubmenu(interp, menuPtr, 
			menuPtr->entries[index]);
	    }
	    break;
d784 2
a785 22
	case MENU_TYPE: {
	    int index;

	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "type index");
		goto error;
	    }
	    if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) 
		    != TCL_OK) {
		goto error;
	    }
	    if (index < 0) {
		goto done;
	    }
	    if (menuPtr->entries[index]->type == TEAROFF_ENTRY) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("tearoff", -1));
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			menuEntryTypeStrings[menuPtr->entries[index]->type], 
			-1));
	    }
	    break;
d787 1
a787 6
	case MENU_UNPOST:
	    if (objc != 2) {
		Tcl_WrongNumArgs(interp, 1, objv, "unpost");
		goto error;
	    }
	    Tk_UnmapWindow(menuPtr->tkwin);
d789 59
a847 8
	    break;
	case MENU_YPOSITION:
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "yposition index");
		goto error;
	    }
	    result = MenuDoYPosition(interp, menuPtr, objv[2]);
	    break;
d857 1
a885 1
    int state;
d891 1
a891 3
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL, 0,
	    &state);
    if (state == ENTRY_DISABLED) {
d896 8
a903 14
	Tcl_Obj *objv[2];

	objv[0] = Tcl_NewStringObj("tkTearOffMenu", -1);
	Tcl_IncrRefCount(objv[0]);
	objv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
	Tcl_IncrRefCount(objv[1]);
	result = Tcl_EvalObjv(interp, 2, objv, "", -1, 0);
	Tcl_DecrRefCount(objv[0]);
	Tcl_DecrRefCount(objv[1]);
    } else if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    && (mePtr->namePtr != NULL)) {
	Tcl_Obj *valuePtr;
	char *name;

d905 4
a908 1
	    valuePtr = mePtr->offValuePtr;
d910 4
a913 4
	    valuePtr = mePtr->onValuePtr;
	}
	if (valuePtr == NULL) {
	    valuePtr = Tcl_NewStringObj("", -1);
d915 2
a916 3
	Tcl_IncrRefCount(valuePtr);
	name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	if (Tcl_SetObjVar2(interp, name, NULL, valuePtr,
a919 15
	Tcl_DecrRefCount(valuePtr);
    } else if ((mePtr->type == RADIO_BUTTON_ENTRY)
	    && (mePtr->namePtr != NULL)) {
	Tcl_Obj *valuePtr = mePtr->onValuePtr;
	char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	
	if (valuePtr == NULL) {
	    valuePtr = Tcl_NewStringObj("", -1);
	}
	Tcl_IncrRefCount(valuePtr);
	if (Tcl_SetObjVar2(interp, name, NULL, valuePtr,
		TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
	    result = TCL_ERROR;
	}
	Tcl_DecrRefCount(valuePtr);
d921 2
a922 6
    if ((result == TCL_OK) && (mePtr->commandPtr != NULL)) {
	Tcl_Obj *commandPtr = mePtr->commandPtr;

	Tcl_IncrRefCount(commandPtr);
	result = Tcl_EvalObj(interp, commandPtr, TCL_EVAL_GLOBAL);
	Tcl_DecrRefCount(commandPtr);
d928 2
d954 1
a954 1
    int i;
d957 1
a957 1
    Tcl_Obj *newObjv[2];
d960 1
d982 1
a985 2
	    Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);

d989 3
a991 7
	    newObjv[0] = menuNamePtr;
	    newObjv[1] = parentMasterEntryPtr->namePtr;
	    Tcl_IncrRefCount(newObjv[0]);
	    Tcl_IncrRefCount(newObjv[1]);
    	    ConfigureMenuEntry(cascadePtr, 2, newObjv);
	    Tcl_DecrRefCount(newObjv[0]);
	    Tcl_DecrRefCount(newObjv[1]);
d993 1
a993 1
    	    ConfigureMenuEntry(cascadePtr, 0, (Tcl_Obj **) NULL);
d1013 1
a1013 1
     * let Tk_FreeConfigurationOptions handle all the standard option-related
d1017 1
a1017 8
    for (i = menuPtr->numEntries; --i >= 0; ) {
	/*
	 * As each menu entry is deleted from the end of the array of
	 * entries, decrement menuPtr->numEntries.  Otherwise, the act of
	 * deleting menu entry i will dereference freed memory attempting
	 * to queue a redraw for menu entries (i+1)...numEntries.
	 */
	 
a1018 1
	menuPtr->numEntries = i;
d1024 3
a1026 2
    Tk_FreeConfigOptions((char *) menuPtr, 
	    menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin);
d1205 1
a1205 1
     * let Tk_FreeConfigurationOptions handle all the standard option-related
d1218 2
a1219 5
    if (((mePtr->type == CHECK_BUTTON_ENTRY) 
	    || (mePtr->type == RADIO_BUTTON_ENTRY))
	    && (mePtr->namePtr != NULL)) {
	char *varName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	Tcl_UntraceVar(menuPtr->interp, varName,
d1225 2
a1226 1
    Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable, menuPtr->tkwin);
d1262 1
d1275 1
a1275 1
 *	returned, then the interp's result contains an error message.
d1285 1
a1285 1
ConfigureMenu(interp, menuPtr, objc, objv)
d1289 3
a1291 2
    int objc;			/* Number of valid entries in argv. */
    Tcl_Obj *CONST objv[];	/* Arguments. */
d1294 1
a1294 3
    TkMenu *menuListPtr, *cleanupPtr;
    int result;
    int tearoff;
d1298 4
a1301 13
	menuListPtr->errorStructPtr = (Tk_SavedOptions *)
		ckalloc(sizeof(Tk_SavedOptions));
	result = Tk_SetOptions(interp, (char *) menuListPtr,
		menuListPtr->optionTablesPtr->menuOptionTable, objc, objv, 
		menuListPtr->tkwin, menuListPtr->errorStructPtr, (int *) NULL);
	if (result != TCL_OK) {
	    for (cleanupPtr = menuPtr->masterMenuPtr;
		    cleanupPtr != menuListPtr;
		    cleanupPtr = cleanupPtr->nextInstancePtr) {
		Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
		ckfree((char *) cleanupPtr->errorStructPtr);
		cleanupPtr->errorStructPtr = NULL;
	    }
d1313 6
a1318 16
	    Tcl_GetIndexFromObj(NULL, menuListPtr->menuTypePtr,
		    menuTypeStrings, NULL, 0, &menuListPtr->menuType);

	    /*
	     * Configure the new window to be either a pop-up menu
	     * or a tear-off menu.
	     * We don't do this for menubars since they are not toplevel
	     * windows. Also, since this gets called before CloneMenu has
	     * a chance to set the menuType field, we have to look at the
	     * menuTypeName field to tell that this is a menu bar.
	     */
	    
	    if (menuListPtr->menuType == MASTER_MENU) {
		TkpMakeMenuWindow(menuListPtr->tkwin, 1);
	    } else if (menuListPtr->menuType == TEAROFF_MENU) {
		TkpMakeMenuWindow(menuListPtr->tkwin, 0);
d1321 1
a1321 2


d1327 1
a1327 2
	Tcl_GetBooleanFromObj(NULL, menuListPtr->tearoffPtr, &tearoff);
	if (tearoff) {
a1330 12
		    if (menuListPtr->errorStructPtr != NULL) {
			for (cleanupPtr = menuPtr->masterMenuPtr;
				cleanupPtr != menuListPtr;
				cleanupPtr = cleanupPtr->nextInstancePtr) {
			    Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
			    ckfree((char *) cleanupPtr->errorStructPtr);
			    cleanupPtr->errorStructPtr = NULL;
			}
			Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
			ckfree((char *) cleanupPtr->errorStructPtr);
			cleanupPtr->errorStructPtr = NULL;
		    }
d1337 1
a1337 1
	    
a1339 1

d1352 15
d1379 3
a1381 1
	    ConfigureMenuEntry(mePtr, 0, (Tcl_Obj **) NULL);
a1386 7
    for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != NULL;
	    cleanupPtr = cleanupPtr->nextInstancePtr) {
	Tk_FreeSavedOptions(cleanupPtr->errorStructPtr);
	ckfree((char *) cleanupPtr->errorStructPtr);
	cleanupPtr->errorStructPtr = NULL;
    }

a1388 1

d1393 1
a1393 1
 * PostProcessEntry --
d1395 2
a1396 3
 *	This is called by ConfigureMenuEntry to do all of the configuration
 *	after Tk_SetOptions is called. This is separate
 *	so that error handling is easier.
d1400 1
a1400 1
 *	returned, then the interp's result contains an error message.
d1410 8
a1417 2
PostProcessEntry(mePtr)
    TkMenuEntry *mePtr;			/* The entry we are configuring. */
a1420 1
    char *name;
d1424 21
d1450 1
a1450 1
    if (mePtr->labelPtr == NULL) {
d1453 1
a1453 1
	Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);
d1455 1
a1455 1
    if (mePtr->accelPtr == NULL) {
d1458 1
a1458 1
	Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength);
d1467 1
a1467 1
    if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {
d1469 1
a1484 1
	name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d1488 1
a1488 1
	    if (strcmp(oldHashKey, name) != 0) {
d1494 4
a1497 2
		|| (strcmp(oldHashKey, name) != 0)) {
	    menuRefPtr = TkCreateMenuReferences(menuPtr->interp, name);
d1534 38
d1578 2
a1579 3
    if (mePtr->imagePtr != NULL) {
	char *imageString = Tcl_GetStringFromObj(mePtr->imagePtr, NULL);
	image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, imageString,
d1591 2
a1592 4
    if (mePtr->selectImagePtr != NULL) {
	char *selectImageString = Tcl_GetStringFromObj(
		mePtr->selectImagePtr, NULL);
	image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, selectImageString,
d1605 1
a1605 65
    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
	Tcl_Obj *valuePtr;
	char *name;

	if (mePtr->namePtr == NULL) {
	    if (mePtr->labelPtr == NULL) {
		mePtr->namePtr = NULL;
	    } else {
		mePtr->namePtr = Tcl_DuplicateObj(mePtr->labelPtr);
		Tcl_IncrRefCount(mePtr->namePtr);
	    }
	}
	if (mePtr->onValuePtr == NULL) {
	    if (mePtr->labelPtr == NULL) {
		mePtr->onValuePtr = NULL;
	    } else {
		mePtr->onValuePtr = Tcl_DuplicateObj(mePtr->labelPtr);
		Tcl_IncrRefCount(mePtr->onValuePtr);
	    }
	}

	/*
	 * 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.
	 */
	
	if (mePtr->namePtr != NULL) {
	    char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	    valuePtr = Tcl_GetObjVar2(menuPtr->interp, name, NULL,
		    TCL_GLOBAL_ONLY);
	} else {
	    valuePtr = NULL;
	}
	mePtr->entryFlags &= ~ENTRY_SELECTED;
	if (valuePtr != NULL) {
	    if (mePtr->onValuePtr != NULL) {
		char *value = Tcl_GetStringFromObj(valuePtr, NULL);
		char *onValue = Tcl_GetStringFromObj(mePtr->onValuePtr,
			NULL);


		if (strcmp(value, onValue) == 0) {
		    mePtr->entryFlags |= ENTRY_SELECTED;
		}
	    }
	} else {
	    if (mePtr->namePtr != NULL) {
		char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
		Tcl_SetObjVar2(menuPtr->interp, name, NULL,
			(mePtr->type == CHECK_BUTTON_ENTRY)
			? mePtr->offValuePtr : 
			Tcl_NewStringObj("", 0),
			TCL_GLOBAL_ONLY);
	    }
	}
	if (mePtr->namePtr != NULL) {
	    name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	    Tcl_TraceVar(menuPtr->interp, name,
		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		    MenuVarProc, (ClientData) mePtr);
	}
    }
a1612 65
 * ConfigureMenuEntry --
 *
 *	This procedure is called to process an argv/argc list 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 the interp's 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
ConfigureMenuEntry(mePtr, objc, objv)
    register TkMenuEntry *mePtr;	/* Information about menu entry;  may
					 * or may not already have values for
					 * some fields. */
    int objc;				/* Number of valid entries in argv. */
    Tcl_Obj *CONST objv[];		/* Arguments. */
{
    TkMenu *menuPtr = mePtr->menuPtr;
    Tk_SavedOptions errorStruct;
    int result;

    /*
     * If this entry is a check button or radio button, then remove
     * its old trace procedure.
     */

    if ((mePtr->namePtr != NULL)
    	    && ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY))) {
	char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	Tcl_UntraceVar(menuPtr->interp, name,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuVarProc, (ClientData) mePtr);
    }

    result = TCL_OK;
    if (menuPtr->tkwin != NULL) {
	if (Tk_SetOptions(menuPtr->interp, (char *) mePtr,
		mePtr->optionTable, objc, objv, menuPtr->tkwin,
		&errorStruct, (int *) NULL) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = PostProcessEntry(mePtr);
	if (result != TCL_OK) {
	    Tk_RestoreSavedOptions(&errorStruct);
	    PostProcessEntry(mePtr);
	}
	Tk_FreeSavedOptions(&errorStruct);
    }

    TkEventuallyRecomputeMenu(menuPtr);
    
    return result;
}

/*
 *----------------------------------------------------------------------
 *
d1619 1
a1619 1
 *	returned, then the interp's result contains an error message.
d1629 1
a1629 1
ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv)
d1634 4
a1637 2
    int objc;				/* Number of valid entries in argv. */
    Tcl_Obj *CONST objv[];		/* Arguments. */
d1641 2
a1642 1
    int cascadeEntryChanged = 0;
d1644 1
a1644 3
    Tcl_Obj *oldCascadePtr = NULL;
    char *newCascadeName;

d1656 1
a1656 4
	oldCascadePtr = mePtr->namePtr;
	if (oldCascadePtr != NULL) {
	    Tcl_IncrRefCount(oldCascadePtr);
	}
d1659 1
a1659 1
    if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
d1663 2
a1664 25
    if (mePtr->type == CASCADE_ENTRY) {
	char *oldCascadeName;

	if (mePtr->namePtr != NULL) {
	    newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
	} else {
	    newCascadeName = NULL;
	}
 
	if ((oldCascadePtr == NULL) && (mePtr->namePtr == NULL)) {
	    cascadeEntryChanged = 0;
	} else if (((oldCascadePtr == NULL) && (mePtr->namePtr != NULL))
		|| ((oldCascadePtr != NULL) 
		&& (mePtr->namePtr == NULL))) {
	    cascadeEntryChanged = 1;
	} else {
	    oldCascadeName = Tcl_GetStringFromObj(oldCascadePtr,
		    NULL);
	    cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName) 
		    == 0);
	}
	if (oldCascadePtr != NULL) {
	    Tcl_DecrRefCount(oldCascadePtr);
	}
    }
d1667 2
a1668 2
	if (mePtr->namePtr != NULL) {
	    newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
d1670 1
a1670 1
		    newCascadeName);
d1680 3
a1682 3
	if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
	    oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, 
		    mePtr->namePtr);
d1690 1
a1690 1
    	if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
d1694 1
a1694 1
	if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
d1696 5
a1700 10
		Tcl_Obj *newObjv[2];
		Tcl_Obj *newCloneNamePtr;
		Tcl_Obj *pathNamePtr = Tcl_NewStringObj(
			Tk_PathName(menuListPtr->tkwin), -1);
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
		Tcl_Obj *menuObjPtr = Tcl_NewStringObj("menu", -1);

		Tcl_IncrRefCount(pathNamePtr);
		newCloneNamePtr = TkNewMenuName(menuPtr->interp,
			pathNamePtr, 
d1702 7
a1708 13
		Tcl_IncrRefCount(newCloneNamePtr);
		Tcl_IncrRefCount(normalPtr);
		CloneMenu(cascadeMenuRefPtr->menuPtr, newCloneNamePtr,
			normalPtr);

		newObjv[0] = menuObjPtr;
		newObjv[1] = newCloneNamePtr;
		Tcl_IncrRefCount(menuObjPtr);
		ConfigureMenuEntry(mePtr, 2, newObjv);
		Tcl_DecrRefCount(newCloneNamePtr);
		Tcl_DecrRefCount(pathNamePtr);
		Tcl_DecrRefCount(normalPtr);
		Tcl_DecrRefCount(menuObjPtr);
d1727 1
a1727 1
 *	one).  Otherwise an error message is left in the interp's result.
d1736 1
a1736 1
TkGetMenuIndex(interp, menuPtr, objPtr, lastOK, indexPtr)
d1740 1
a1740 1
    Tcl_Obj *objPtr;		/* Specification of an entry in menu.  See
d1744 1
a1744 1
    int *indexPtr;		/* Where to store converted index. */
a1746 1
    char *string = Tcl_GetStringFromObj(objPtr, NULL);
d1750 1
a1750 1
	goto success;
d1756 1
a1756 1
	goto success;
d1761 1
a1761 1
	goto success;
d1767 1
a1767 1
	    goto success;
d1783 1
a1783 1
	    goto success;
d1789 3
a1791 4
	Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;
	char *label = (labelPtr == NULL) ? NULL
	        : Tcl_GetStringFromObj(labelPtr, NULL);
	
d1793 1
a1793 1
		&& (Tcl_StringMatch(label, string))) {
d1795 1
a1795 1
	    goto success;
a1801 3

success:
    return TCL_OK;
d1837 1
a1892 1
    mePtr->optionTable = menuPtr->optionTablesPtr->entryOptionTables[type];
d1894 1
a1894 1
    mePtr->labelPtr = NULL;
d1897 2
a1898 2
    mePtr->bitmapPtr = NULL;
    mePtr->imagePtr = NULL;
d1900 1
a1900 1
    mePtr->selectImagePtr = NULL;
d1902 1
a1902 1
    mePtr->accelPtr = NULL;
d1904 12
a1915 16
    mePtr->statePtr = Tcl_NewStringObj("disabled", -1);
    Tcl_IncrRefCount(mePtr->statePtr);
    mePtr->borderPtr = NULL;
    mePtr->fgPtr = NULL;
    mePtr->activeBorderPtr = NULL;
    mePtr->activeFgPtr = NULL;
    mePtr->fontPtr = NULL;
    mePtr->indicatorOnPtr = Tcl_NewBooleanObj(1);
    Tcl_IncrRefCount(mePtr->indicatorOnPtr);
    mePtr->indicatorFgPtr = NULL;
    mePtr->columnBreakPtr = Tcl_NewBooleanObj(0);
    Tcl_IncrRefCount(mePtr->columnBreakPtr);
    mePtr->hideMarginPtr = Tcl_NewBooleanObj(0);
    Tcl_IncrRefCount(mePtr->hideMarginPtr);
    mePtr->commandPtr = NULL;
    mePtr->namePtr = NULL;
d1917 2
a1918 2
    mePtr->onValuePtr = NULL;
    mePtr->offValuePtr = NULL;
a1921 5
    if (Tk_InitOptions(menuPtr->interp, (char *) mePtr,
	    mePtr->optionTable, menuPtr->tkwin) != TCL_OK) {
	ckfree((char *) mePtr);
	return NULL;
    }
a1923 2
	Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable,
		menuPtr->tkwin);
d1927 1
a1927 1

d1949 1
a1949 1
MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv)
d1953 1
a1953 1
    Tcl_Obj *indexPtr;			/* Object describing index at which
d1956 2
a1957 2
    int objc;				/* Number of elements in objv. */
    Tcl_Obj *CONST objv[];		/* Arguments to command:  first arg
d1961 2
a1962 1
    int type, index;
a1964 1
    int tearoff;
d1966 2
a1967 2
    if (indexPtr != NULL) {
	if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index)
a1974 1
	char *indexString = Tcl_GetStringFromObj(indexPtr, NULL);
d1979 1
a1979 2
    Tcl_GetBooleanFromObj(NULL, menuPtr->tearoffPtr, &tearoff);
    if (tearoff && (index == 0)) {
d1987 21
a2007 2
    if (Tcl_GetIndexFromObj(interp, objv[0], menuEntryTypeStrings,
	    "menu entry type", 0, &type) != TCL_OK) {
d2010 1
a2010 1

d2022 1
a2022 1
    	if (ConfigureMenuEntry(mePtr, objc - 1, objv + 1) != TCL_OK) {
d2024 1
a2024 1
	    int i;
d2057 1
a2057 2
    	    if ((mePtr->namePtr != NULL)
		    && (mePtr->childMenuRefPtr != NULL)
d2061 2
a2062 6
    	        Tcl_Obj *newCascadePtr;
		Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
		Tcl_Obj *windowNamePtr = 
			Tcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), -1);
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
  		Tcl_Obj *newObjv[2];
d2064 5
a2068 7
    	          
		Tcl_IncrRefCount(windowNamePtr);
		newCascadePtr = TkNewMenuName(menuListPtr->interp,
			windowNamePtr, cascadeMenuPtr);
		Tcl_IncrRefCount(newCascadePtr);
		Tcl_IncrRefCount(normalPtr);
		CloneMenu(cascadeMenuPtr, newCascadePtr, normalPtr);
d2070 2
a2071 2
		menuRefPtr = TkFindMenuReferencesObj(menuListPtr->interp,
			newCascadePtr);
d2075 4
a2078 9
		newObjv[0] = menuNamePtr;
		newObjv[1] = newCascadePtr;
		Tcl_IncrRefCount(menuNamePtr);
		Tcl_IncrRefCount(newCascadePtr);
    	        ConfigureMenuEntry(mePtr, 2, newObjv);
    	        Tcl_DecrRefCount(newCascadePtr);
		Tcl_DecrRefCount(menuNamePtr);
		Tcl_DecrRefCount(windowNamePtr);
		Tcl_DecrRefCount(normalPtr);
a2114 2
    char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
    char *onValue;
d2126 1
a2126 1
	    Tcl_TraceVar(interp, name,
d2140 1
a2140 1
    value = Tcl_GetVar(interp, name, TCL_GLOBAL_ONLY);
d2144 2
a2145 10
    if (mePtr->onValuePtr != NULL) {
	onValue = Tcl_GetStringFromObj(mePtr->onValuePtr, NULL);
	if (strcmp(value, onValue) == 0) {
	    if (mePtr->entryFlags & ENTRY_SELECTED) {
		return (char *) NULL;
	    }
	    mePtr->entryFlags |= ENTRY_SELECTED;
	} else if (mePtr->entryFlags & ENTRY_SELECTED) {
	    mePtr->entryFlags &= ~ENTRY_SELECTED;
	} else {
d2148 3
a2186 1
    int state;
d2196 2
a2197 6
	Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
		NULL, 0, &state);
	if (state == ENTRY_ACTIVE) {
	    Tcl_DecrRefCount(mePtr->statePtr);
	    mePtr->statePtr = Tcl_NewStringObj("normal", -1);
	    Tcl_IncrRefCount(mePtr->statePtr);
d2204 1
a2204 3
    	Tcl_DecrRefCount(mePtr->statePtr);
	mePtr->statePtr = Tcl_NewStringObj("active", -1);
	Tcl_IncrRefCount(mePtr->statePtr);
d2240 3
a2242 7
    if (menuPtr->postCommandPtr != NULL) {
	Tcl_Obj *postCommandPtr = menuPtr->postCommandPtr;

	Tcl_IncrRefCount(postCommandPtr);
	result = Tcl_EvalObj(menuPtr->interp, postCommandPtr,
		TCL_EVAL_GLOBAL);
	Tcl_DecrRefCount(postCommandPtr);
d2272 1
a2272 1
CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr)
d2274 2
a2275 2
    Tcl_Obj *newMenuNamePtr;	/* The name to give the new menu */
    Tcl_Obj *newMenuTypePtr;	/* What kind of menu is this, a normal menu
d2279 2
a2280 1
    int menuType, i;
d2282 1
a2282 1
    Tcl_Obj *menuDupCommandArray[4];
d2284 1
a2284 1
    if (newMenuTypePtr == NULL) {
d2287 13
a2299 4
	if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr, 
		menuTypeStrings, "menu type", 0, &menuType) != TCL_OK) {
	    return TCL_ERROR;
	}
d2302 10
a2311 5
    menuDupCommandArray[0] = Tcl_NewStringObj("tkMenuDup", -1);
    menuDupCommandArray[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
    menuDupCommandArray[2] = newMenuNamePtr;
    if (newMenuTypePtr == NULL) {
	menuDupCommandArray[3] = Tcl_NewStringObj("normal", -1);
d2313 2
a2314 4
	menuDupCommandArray[3] = newMenuTypePtr;
    }
    for (i = 0; i < 4; i++) {
	Tcl_IncrRefCount(menuDupCommandArray[i]);
d2316 1
d2318 2
a2319 5
    returnResult = Tcl_EvalObjv(menuPtr->interp, 4, menuDupCommandArray, "",
	    -1, 0);
    for (i = 0; i < 4; i++) {
	Tcl_DecrRefCount(menuDupCommandArray[i]);
    }
d2326 2
a2327 2
    	    ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, 
	    newMenuNamePtr)) != (TkMenuReferences *) NULL)
a2329 1
	Tcl_Obj *newObjv[3];
d2362 2
a2363 2
   	    Tcl_Obj *bindingsPtr =
		    Tcl_DuplicateObj(Tcl_GetObjResult(newMenuPtr->interp));
a2374 1
		    Tcl_IncrRefCount(newElementPtr);
d2378 2
a2379 2
		    Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin,
			    menuPtr->interp, 3, newArgv);
d2392 1
d2397 1
a2397 1
		&& (menuPtr->entries[i]->namePtr != NULL)) {
d2399 2
a2400 2
			TkFindMenuReferencesObj(menuPtr->interp,
			menuPtr->entries[i]->namePtr);
d2402 1
a2402 4
		    Tcl_Obj *windowNamePtr = 
			    Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin),
			    -1);
		    Tcl_Obj *newCascadePtr;
d2406 10
a2415 13
		    Tcl_IncrRefCount(windowNamePtr);
   	    	    newCascadePtr = TkNewMenuName(menuPtr->interp,
   	    	     	    windowNamePtr, oldCascadePtr);
		    Tcl_IncrRefCount(newCascadePtr);
		    CloneMenu(oldCascadePtr, newCascadePtr, NULL);

		    newObjv[0] = Tcl_NewStringObj("-menu", -1);
		    newObjv[1] = newCascadePtr;
		    Tcl_IncrRefCount(newObjv[0]);
		    ConfigureMenuEntry(newMenuPtr->entries[i], 2, newObjv);
		    Tcl_DecrRefCount(newObjv[0]);
		    Tcl_DecrRefCount(newCascadePtr);
		    Tcl_DecrRefCount(windowNamePtr);
d2445 1
a2445 1
MenuDoYPosition(interp, menuPtr, objPtr)
d2448 1
a2448 1
    Tcl_Obj *objPtr;
d2453 1
a2453 1
    if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
a2455 1
    Tcl_ResetResult(interp);
d2457 1
a2457 1
	Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
d2459 1
a2459 1
	Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->y));
a2460 1

d2510 1
a2510 2
	Tk_GetPixelsFromObj(interp, menuPtr->tkwin, 
		menuPtr->borderWidthPtr, &x);
d2586 2
a2587 2
Tcl_Obj *
TkNewMenuName(interp, parentPtr, menuPtr)
d2589 1
a2589 1
    Tcl_Obj *parentPtr;		/* The prefix path of the new name. */
d2592 2
a2593 3
    Tcl_Obj *resultPtr = NULL;	/* Initialization needed only to prevent
				 * compiler warning. */
    Tcl_Obj *childPtr;
d2595 2
a2596 2
    int i;
    int doDot;
d2598 1
a2600 2
    char *parentName = Tcl_GetStringFromObj(parentPtr, NULL);

d2604 4
a2607 5

    doDot = parentName[strlen(parentName) - 1] != '.';

    childPtr = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
    for (destString = Tcl_GetStringFromObj(childPtr, NULL);
d2614 2
d2618 2
a2619 1
	    resultPtr = Tcl_DuplicateObj(parentPtr);
d2621 1
a2621 1
		Tcl_AppendToObj(resultPtr, ".", -1);
d2623 3
a2625 1
	    Tcl_AppendObjToObj(resultPtr, childPtr);
d2627 6
a2632 11
	    Tcl_Obj *intPtr;

	    Tcl_DecrRefCount(resultPtr);
	    resultPtr = Tcl_DuplicateObj(parentPtr);
	    if (doDot) {
		Tcl_AppendToObj(resultPtr, ".", -1);
	    }
	    Tcl_AppendObjToObj(resultPtr, childPtr);
	    intPtr = Tcl_NewIntObj(i);
	    Tcl_AppendObjToObj(resultPtr, intPtr);
	    Tcl_DecrRefCount(intPtr);
a2633 1
	destString = Tcl_GetStringFromObj(resultPtr, NULL);
d2640 5
a2644 2
    Tcl_DecrRefCount(childPtr);
    return resultPtr;
d2759 1
a2759 1
   	    Tcl_Obj *cloneMenuPtr;
d2761 1
a2761 4
	    Tcl_Obj *newObjv[4];
	    Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin), 
		    -1);
	    Tcl_Obj *menubarPtr = Tcl_NewStringObj("menubar", -1);
d2767 1
a2767 2
	    Tcl_IncrRefCount(windowNamePtr);
    	    cloneMenuPtr = TkNewMenuName(interp, windowNamePtr,
d2769 1
a2769 3
	    Tcl_IncrRefCount(cloneMenuPtr);
	    Tcl_IncrRefCount(menubarPtr);
            CloneMenu(menuPtr, cloneMenuPtr, menubarPtr);
d2771 1
a2771 1
            cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr);
a2773 2
		Tcl_Obj *cursorPtr = Tcl_NewStringObj("-cursor", -1);
		Tcl_Obj *nullPtr = Tcl_NewStringObj("", -1);
d2776 2
a2777 4
		newObjv[0] = cursorPtr;
		newObjv[1] = nullPtr;
		Tcl_IncrRefCount(cursorPtr);
		Tcl_IncrRefCount(nullPtr);
d2779 1
a2779 3
			2, newObjv);
		Tcl_DecrRefCount(cursorPtr);
		Tcl_DecrRefCount(nullPtr);
d2783 2
a2784 3
	    Tcl_DecrRefCount(cloneMenuPtr);
	    Tcl_DecrRefCount(menubarPtr);
	    Tcl_DecrRefCount(windowNamePtr);
a2945 29
}

/*
 *----------------------------------------------------------------------
 *
 * TkFindMenuReferencesObj --
 *
 *	Given a pathname, gives back a pointer to the TkMenuReferences
 *	structure.
 *
 * Results:
 *	Returns a pointer to a menu reference structure. Should not
 *	be freed by calller; when a field of the reference is cleared,
 *	TkFreeMenuReferences should be called. Returns NULL if no reference
 *	with this pathname exists.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkMenuReferences *
TkFindMenuReferencesObj(interp, objPtr)
    Tcl_Interp *interp;		/* The interp the menu is living in. */
    Tcl_Obj *objPtr;		/* The path of the menu widget */
{
    char *pathName = Tcl_GetStringFromObj(objPtr, NULL);
    return TkFindMenuReferences(interp, pathName);
@


1.1.4.2
log
@Merged 8.0.3 changes into 8.1
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.2 1998/09/14 18:23:14 stanton Exp $
@


1.1.4.3
log
@* tkMacMenu.c, tkUnixMenu.c, tkWinMenu.c, tkMenuDraw.c, tkMenu.h,
* tkMenu.c: Backed out the previous fix for bug 620 and
eliminated a bunch of code that created unnecessary objects.
Changed back to using internal types instead of objects for many
configuration options.  There are many more fixes like this that
could be made, but some require a little restructuring of the
code. In any case the leaks are fixed and there is a lot less
allocation happening. [Bug: 620]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.1.4.2 1998/09/30 02:17:08 stanton Exp $
d108 1
a108 1
	-1, Tk_Offset(TkMenuEntry, columnBreak)},
d120 1
a120 1
	-1, Tk_Offset(TkMenuEntry, hideMargin)},
d129 1
a129 1
	-1, Tk_Offset(TkMenuEntry, state), 0,
d146 1
a146 1
	-1, Tk_Offset(TkMenuEntry, indicatorOn)},
d169 1
a169 1
	-1, Tk_Offset(TkMenuEntry, indicatorOn)},
d199 1
a199 1
	DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0,
d263 2
a264 1
	DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff)},
d487 1
a487 1
    menuPtr->tearoff = 0;
d695 11
a705 4
	    if ((index >= 0) 
		    && (menuPtr->entries[index]->type == SEPARATOR_ENTRY)
		    && (menuPtr->entries[index]->state == ENTRY_DISABLED)) {
		index = -1;
d777 1
a777 1
	    int first, last;
d795 2
a796 1
	    if (menuPtr->tearoff && (first == 0)) {
d892 1
a892 1
		Tcl_SetResult(interp, "none", TCL_STATIC);
d894 1
a894 1
		Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
d988 1
a988 1
		Tcl_SetResult(interp, "tearoff", TCL_STATIC);
d990 3
a992 3
		Tcl_SetResult(interp,
			menuEntryTypeStrings[menuPtr->entries[index]->type],
			TCL_STATIC);
d1048 1
d1054 3
a1056 1
    if (mePtr->state == ENTRY_DISABLED) {
d1061 9
a1069 6
	Tcl_DString ds;
	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, "tkTearOffMenu ", -1);
	Tcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), -1);
	result = Tcl_Eval(interp, Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
d1081 1
a1081 1
	    valuePtr = Tcl_NewObj();
d1096 1
a1096 1
	    valuePtr = Tcl_NewObj();
d1493 1
d1546 2
a1547 1
	if (menuListPtr->tearoff) {
d1820 2
a1821 2
			? mePtr->offValuePtr
			: Tcl_NewObj(),
d2236 2
a2237 1
    mePtr->state = ENTRY_DISABLED;
d2243 2
a2244 1
    mePtr->indicatorOn = 0;
d2246 4
a2249 2
    mePtr->columnBreak = 0;
    mePtr->hideMargin = 0;
d2307 1
d2323 2
a2324 1
    if (menuPtr->tearoff && (index == 0)) {
d2532 1
d2542 6
a2547 2
	if (mePtr->state == ENTRY_ACTIVE) {
	    mePtr->state = ENTRY_NORMAL;
d2554 3
a2556 1
	mePtr->state = ENTRY_ACTIVE;
d3137 1
a3137 1
		Tcl_Obj *nullPtr = Tcl_NewObj();
@


1.1.4.4
log
@* generic/tkMenu.c (MenuWidgetObjCmd): disabled menu entries were
getting reenabled whenever the mouse passed over the entry [Bug: 860]
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id$
d695 2
a696 3
		    && ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
			    || (menuPtr->entries[index]->state
				    == ENTRY_DISABLED))) {
@


1.1.4.5
log
@Changed patch level to 8.1b1
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.1.4.4 1998/11/25 22:36:50 stanton Exp $
d2001 1
a2001 1
		Tcl_Obj *menuObjPtr = Tcl_NewStringObj("-menu", -1);
d2631 2
a2632 1
    returnResult = Tcl_EvalObjv(menuPtr->interp, 4, menuDupCommandArray, 0);
@


1.1.4.6
log
@* Various cleanup related to the Tcl_Eval and Tcl_ObjSetVar
changes in Tcl.

* Integrated patches from 8.0.5b2
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id$
d1059 1
d1070 2
a1071 1
	if (Tcl_ObjSetVar2(interp, mePtr->namePtr, NULL, valuePtr,
d1079 2
a1080 1

d1085 1
a1085 1
	if (Tcl_ObjSetVar2(interp, mePtr->namePtr, NULL, valuePtr,
d1095 1
a1095 1
	result = Tcl_EvalObjEx(interp, commandPtr, TCL_EVAL_GLOBAL);
d1781 2
a1782 1
	    valuePtr = Tcl_ObjGetVar2(menuPtr->interp, mePtr->namePtr, NULL,
d1801 2
a1802 1
		Tcl_ObjSetVar2(menuPtr->interp, mePtr->namePtr, NULL,
d2567 1
a2567 1
	result = Tcl_EvalObjEx(menuPtr->interp, postCommandPtr,
@


1.1.4.7
log
@Added call to TkpMenuThread Init for thread-specific menu initialization.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.1.4.6 1999/02/11 04:13:46 stanton Exp $
d77 2
a78 15
typedef struct ThreadSpecificData {
    int menusInitialized;       /* Flag indicates whether thread-specific
				 * elements of the Windows Menu module
				 * have been initialized. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following flag indicates whether the process-wide state for
 * the Menu module has been intialized.  The Mutex protects access to
 * that flag.
 */

static int menusInitialized;
TCL_DECLARE_MUTEX(menuMutex)
a3415 3
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    
d3417 2
a3418 10
	Tcl_MutexLock(&menuMutex);
	if (!menusInitialized) {
	    TkpMenuInit();
	    menusInitialized = 1;
	}
	Tcl_MutexUnlock(&menuMutex);
    }
    if (!tsdPtr->menusInitialized) {
	TkpMenuThreadInit();
	tsdPtr->menusInitialized = 1;
@


1.1.4.8
log
@integrated stubs from development branch
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.1.4.7 1999/03/09 01:51:26 lfb Exp $
a70 6
#if 0

/*
 * used only to test for old config code
 */

a71 2
#endif

@


1.1.4.7.2.1
log
@Changes to support stubs in 8.1. Merged from 8.0.6 code base.
@
text
@d15 1
a15 1
 * RCS: @@(#) $Id: tkMenu.c,v 1.1.4.7 1999/03/09 01:51:26 lfb Exp $
a70 6
#if 0

/*
 * used only to test for old config code
 */

a71 2
#endif

@


