head	1.79;
access;
symbols
	core-8-5-9:1.59.2.6
	core-8-5-8:1.59.2.3
	macosx-cocoa-merge:1.67
	macosx-cocoa-premerge:1.67
	macosx-carbon-freeze:1.67
	core-8-5-7:1.59.2.1
	core-8-5-6:1.59
	core-8-6-b1:1.62
	core-8-6-a3:1.59
	core-8-5-5:1.59
	core-8-6-a2:1.59
	core-8-5-4:1.59
	core-8-5-3:1.59
	core-8-6-a1:1.59
	core-8-4-19:1.21.2.9
	core-8-5-branch:1.59.0.2
	core-8-5-2:1.59
	core-8-4-18:1.21.2.9
	core-8-5-1:1.59
	core-8-4-17:1.21.2.9
	core-8-5-0:1.59
	core-8-5-b3:1.58
	core-8-5-b2:1.58
	core-8-4-16:1.21.2.9
	core-8-5-b1:1.58
	core-stablilizer-merge:1.57
	core-stabilizer-branch:1.56.0.2
	core-stabilizer-merge:1.59
	core-8-4-15:1.21.2.8
	core-8-5-a6:1.55
	core-8-5-a5:1.49
	core-8-4-14:1.21.2.6
	core-8-5-a4:1.47
	core-8-4-13:1.21.2.5
	core-8-4-12:1.21.2.4
	core-8-4-11:1.21.2.4
	core-8-5-a3:1.44
	core-8-4-10:1.21.2.4
	core-8-4-9-branch:1.21.2.4.0.2
	core-8-5-a2:1.36
	core-8-4-9:1.21.2.4
	core-8-4-8:1.21.2.4
	core-8-4-7:1.21.2.2
	core-8-5-a1:1.31
	core-8-4-6:1.21
	core-8-4-5:1.21
	mistachkin-dev-branch:1.23.0.2
	core-8-4-4:1.21
	core-8-4-3:1.21
	core-8-4-branch:1.21.0.2
	core-8-4-2:1.21
	core-8-4-1:1.21
	core-8-3-5:1.8.2.3
	core-8-4-0:1.21
	macosx-8-4-merge-2002-08-31-trunk:1.21
	macosx-8-4-premerge-2002-08-31-branch:1.16.2.2
	macosx-8-4-premerge-2002-08-31-trunk:1.21
	macosx-8-4-merge-2002-08-30-branch:1.16.2.2
	macosx-8-4-merge-2002-08-30-trunk:1.21
	macosx-8-4-merge-2002-08-20-branch:1.16.2.2
	macosx-8-4-merge-2002-08-20-trunk:1.21
	core-8-4-b2:1.21
	core-8-4-b1:1.19
	macosx-premerge-6-9-02:1.16.2.1
	core-8-4-a4:1.19
	core-8-3-4:1.8.2.3
	macosx-8-4-branch:1.16.0.2
	macosx-8-4-branchpoint:1.16
	core-8-4-a3:1.14
	core-8-3-3:1.8.2.3
	dgp-privates-into-namespace:1.13.0.4
	tclpro-1-5-0:1.8.2.1
	core-8-4-win-speedup:1.13.0.2
	core-8-4-a2:1.13
	tclpro-1-4-1:1.8.2.1
	tclpro-1-4-0:1.8.2.1
	core-8-3-2:1.8.2.1
	ajuba-ajuba2-2-1-base:1.8
	ajuba-ajuba2-2-0:1.8
	core-8-4-a1:1.10
	core-8-3-1-branch:1.8.0.2
	core-8-3-1:1.8
	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.6
	core-8-3-b1:1.6
	scriptics-sc-1-1:1.5.6.1
	scriptics-sc-1-1-b1:1.5.6.1
	core-8-2-3:1.5.6.1
	scriptics-sc-1-1-branch:1.5.6.1.0.4
	scriptics-sc-1-1-base:1.5.6.1
	scriptics-sc-1-0:1.5.6.1
	scriptics-sc-1-0-branch:1.5.6.1.0.2
	scriptics-sc-1-0-base:1.5.6.1
	core-8-2-2:1.5.6.1
	core-8-2-1:1.5.6.1
	scriptics-bc-1-0-b1:1.5.6.1
	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.4
	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.2
	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.4.0.6
	core-8-0-6-base:1.4
	core-8-0-5:1.4
	core-8-1-b3:1.1.4.11
	core-8-1-b2:1.1.4.10
	dev-8-1-stubs-branch:1.1.4.10.0.2
	dev-stubs-branch:1.4.0.4
	scriptics-tclpro-1-2:1.4
	scriptics-tclpro-1-2-b2:1.4
	core-8-1-merge-2/10/99:1.4
	core-8-0-5-branch:1.4.0.2
	core-8-0-5-base:1.4
	scriptics-tclpro-1-2-b1:1.3
	scriptics-tclpro-1-2-a1:1.3
	core-8-1-b1:1.1.4.6
	core-8-0-4:1.3
	core-8-1-a2:1.1.4.1
	core-8-0-2:1.1
	core-8-0-3:1.3;
locks; strict;
comment	@ * @;


1.79
date	2010.11.19.14.48.00;	author nijtmans;	state Exp;
branches;
next	1.78;

1.78
date	2010.11.03.12.11.44;	author nijtmans;	state Exp;
branches;
next	1.77;

1.77
date	2010.10.11.13.33.30;	author nijtmans;	state Exp;
branches;
next	1.76;

1.76
date	2010.10.06.14.33.29;	author nijtmans;	state Exp;
branches;
next	1.75;

1.75
date	2010.09.13.08.11.59;	author nijtmans;	state Exp;
branches;
next	1.74;

1.74
date	2010.09.10.08.59.25;	author nijtmans;	state Exp;
branches;
next	1.73;

1.73
date	2010.05.10.20.58.18;	author nijtmans;	state Exp;
branches;
next	1.72;

1.72
date	2010.01.22.14.17.53;	author nijtmans;	state Exp;
branches;
next	1.71;

1.71
date	2010.01.03.19.50.59;	author patthoyts;	state Exp;
branches;
next	1.70;

1.70
date	2009.12.27.23.36.25;	author patthoyts;	state Exp;
branches;
next	1.69;

1.69
date	2009.09.14.23.41.42;	author hobbs;	state Exp;
branches;
next	1.68;

1.68
date	2009.08.02.21.40.17;	author nijtmans;	state Exp;
branches;
next	1.67;

1.67
date	2009.05.21.22.52.06;	author patthoyts;	state Exp;
branches;
next	1.66;

1.66
date	2009.03.25.23.39.35;	author nijtmans;	state Exp;
branches;
next	1.65;

1.65
date	2009.03.01.21.54.40;	author patthoyts;	state Exp;
branches;
next	1.64;

1.64
date	2009.02.23.10.18.38;	author patthoyts;	state Exp;
branches;
next	1.63;

1.63
date	2009.01.28.20.47.49;	author nijtmans;	state Exp;
branches;
next	1.62;

1.62
date	2008.12.09.21.22.56;	author dgp;	state Exp;
branches;
next	1.61;

1.61
date	2008.11.08.18.44.40;	author dkf;	state Exp;
branches;
next	1.60;

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

1.59
date	2007.12.13.15.28.56;	author dgp;	state Exp;
branches
	1.59.2.1;
next	1.58;

1.58
date	2007.09.08.16.13.45;	author dkf;	state Exp;
branches;
next	1.57;

1.57
date	2007.06.09.23.53.05;	author hobbs;	state Exp;
branches;
next	1.56;

1.56
date	2007.05.05.07.33.08;	author dkf;	state Exp;
branches
	1.56.2.1;
next	1.55;

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

1.54
date	2007.02.22.13.56.34;	author dkf;	state Exp;
branches;
next	1.53;

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

1.52
date	2007.01.11.15.35.40;	author dkf;	state Exp;
branches;
next	1.51;

1.51
date	2006.11.24.18.11.32;	author hobbs;	state Exp;
branches;
next	1.50;

1.50
date	2006.11.24.01.51.51;	author hobbs;	state Exp;
branches;
next	1.49;

1.49
date	2006.09.21.00.13.36;	author hobbs;	state Exp;
branches;
next	1.48;

1.48
date	2006.05.25.23.50.31;	author hobbs;	state Exp;
branches;
next	1.47;

1.47
date	2006.04.05.20.59.04;	author hobbs;	state Exp;
branches;
next	1.46;

1.46
date	2005.11.10.11.38.29;	author dkf;	state Exp;
branches;
next	1.45;

1.45
date	2005.08.10.22.02.22;	author dkf;	state Exp;
branches;
next	1.44;

1.44
date	2005.04.28.02.40.19;	author chengyemao;	state Exp;
branches;
next	1.43;

1.43
date	2005.01.18.15.24.18;	author chengyemao;	state Exp;
branches;
next	1.42;

1.42
date	2005.01.17.07.00.11;	author chengyemao;	state Exp;
branches;
next	1.41;

1.41
date	2005.01.13.01.48.03;	author chengyemao;	state Exp;
branches;
next	1.40;

1.40
date	2005.01.09.06.59.20;	author chengyemao;	state Exp;
branches;
next	1.39;

1.39
date	2005.01.09.00.26.59;	author chengyemao;	state Exp;
branches;
next	1.38;

1.38
date	2005.01.04.02.09.45;	author chengyemao;	state Exp;
branches;
next	1.37;

1.37
date	2004.12.28.08.45.31;	author chengyemao;	state Exp;
branches;
next	1.36;

1.36
date	2004.09.21.19.13.58;	author mdejong;	state Exp;
branches;
next	1.35;

1.35
date	2004.09.03.14.09.05;	author dkf;	state Exp;
branches;
next	1.34;

1.34
date	2004.08.25.22.23.33;	author dgp;	state Exp;
branches;
next	1.33;

1.33
date	2004.05.03.23.23.14;	author hobbs;	state Exp;
branches;
next	1.32;

1.32
date	2004.05.03.22.40.30;	author hobbs;	state Exp;
branches;
next	1.31;

1.31
date	2004.01.07.13.25.56;	author vincentdarley;	state Exp;
branches;
next	1.30;

1.30
date	2003.12.28.23.11.10;	author mdejong;	state Exp;
branches;
next	1.29;

1.29
date	2003.12.28.05.04.18;	author mdejong;	state Exp;
branches;
next	1.28;

1.28
date	2003.12.26.22.29.07;	author mdejong;	state Exp;
branches;
next	1.27;

1.27
date	2003.12.26.20.46.03;	author mdejong;	state Exp;
branches;
next	1.26;

1.26
date	2003.12.21.23.50.13;	author davygrvy;	state Exp;
branches;
next	1.25;

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

1.24
date	2003.10.31.08.55.03;	author vincentdarley;	state Exp;
branches;
next	1.23;

1.23
date	2003.04.15.01.06.09;	author mdejong;	state Exp;
branches;
next	1.22;

1.22
date	2003.04.14.23.34.50;	author mdejong;	state Exp;
branches;
next	1.21;

1.21
date	2002.08.08.01.42.57;	author hobbs;	state Exp;
branches
	1.21.2.1;
next	1.20;

1.20
date	2002.08.05.04.30.41;	author dgp;	state Exp;
branches;
next	1.19;

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

1.18
date	2002.01.08.15.40.15;	author drh;	state Exp;
branches;
next	1.17;

1.17
date	2001.11.27.04.36.18;	author drh;	state Exp;
branches;
next	1.16;

1.16
date	2001.10.12.13.30.32;	author tmh;	state Exp;
branches
	1.16.2.1;
next	1.15;

1.15
date	2001.09.21.21.34.10;	author hobbs;	state Exp;
branches;
next	1.14;

1.14
date	2001.04.04.18.37.18;	author hobbs;	state Exp;
branches;
next	1.13;

1.13
date	2000.08.29.21.00.13;	author ericm;	state Exp;
branches
	1.13.2.1
	1.13.4.1;
next	1.12;

1.12
date	2000.07.28.17.37.24;	author ericm;	state Exp;
branches;
next	1.11;

1.11
date	2000.07.06.03.17.44;	author mo;	state Exp;
branches;
next	1.10;

1.10
date	2000.05.16.17.57.32;	author ericm;	state Exp;
branches;
next	1.9;

1.9
date	2000.05.10.00.09.40;	author ericm;	state Exp;
branches;
next	1.8;

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

1.7
date	2000.03.31.09.24.27;	author hobbs;	state Exp;
branches;
next	1.6;

1.6
date	99.09.15.22.35.42;	author hobbs;	state Exp;
branches;
next	1.5;

1.5
date	99.04.16.01.51.52;	author stanton;	state Exp;
branches
	1.5.6.1;
next	1.4;

1.4
date	99.02.04.21.44.18;	author stanton;	state Exp;
branches;
next	1.3;

1.3
date	98.09.14.18.24.00;	author stanton;	state Exp;
branches;
next	1.2;

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

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

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

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

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

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

1.1.4.5
date	98.11.24.21.42.48;	author stanton;	state Exp;
branches;
next	1.1.4.6;

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

1.1.4.7
date	98.12.13.08.16.18;	author lfb;	state Exp;
branches;
next	1.1.4.8;

1.1.4.8
date	98.12.13.09.54.45;	author lfb;	state Exp;
branches;
next	1.1.4.9;

1.1.4.9
date	99.02.11.04.13.51;	author stanton;	state Exp;
branches;
next	1.1.4.10;

1.1.4.10
date	99.03.09.01.36.06;	author lfb;	state Exp;
branches;
next	1.1.4.11;

1.1.4.11
date	99.03.30.04.13.01;	author stanton;	state Exp;
branches;
next	;

1.5.6.1
date	99.09.22.06.53.24;	author hobbs;	state Exp;
branches;
next	;

1.8.2.1
date	2000.08.05.23.53.15;	author hobbs;	state Exp;
branches;
next	1.8.2.2;

1.8.2.2
date	2001.04.04.07.57.18;	author hobbs;	state Exp;
branches;
next	1.8.2.3;

1.8.2.3
date	2001.04.04.18.46.56;	author hobbs;	state Exp;
branches;
next	;

1.13.2.1
date	2000.11.03.22.49.27;	author hobbs;	state Exp;
branches;
next	1.13.2.2;

1.13.2.2
date	2002.04.02.21.17.04;	author hobbs;	state Exp;
branches;
next	;

1.13.4.1
date	2001.07.03.20.01.10;	author dgp;	state Exp;
branches;
next	;

1.16.2.1
date	2002.02.05.02.25.18;	author wolfsuit;	state Exp;
branches;
next	1.16.2.2;

1.16.2.2
date	2002.08.20.20.27.19;	author das;	state Exp;
branches;
next	;

1.21.2.1
date	2004.05.03.22.40.58;	author hobbs;	state Exp;
branches;
next	1.21.2.2;

1.21.2.2
date	2004.05.03.23.23.42;	author hobbs;	state Exp;
branches;
next	1.21.2.3;

1.21.2.3
date	2004.09.23.00.56.15;	author mdejong;	state Exp;
branches;
next	1.21.2.4;

1.21.2.4
date	2004.10.27.00.37.38;	author davygrvy;	state Exp;
branches
	1.21.2.4.2.1;
next	1.21.2.5;

1.21.2.5
date	2006.04.05.19.47.39;	author hobbs;	state Exp;
branches;
next	1.21.2.6;

1.21.2.6
date	2006.09.21.00.13.54;	author hobbs;	state Exp;
branches;
next	1.21.2.7;

1.21.2.7
date	2006.11.24.01.52.08;	author hobbs;	state Exp;
branches;
next	1.21.2.8;

1.21.2.8
date	2006.11.24.18.11.54;	author hobbs;	state Exp;
branches;
next	1.21.2.9;

1.21.2.9
date	2007.06.09.23.52.40;	author hobbs;	state Exp;
branches;
next	1.21.2.10;

1.21.2.10
date	2009.09.14.23.39.53;	author hobbs;	state Exp;
branches;
next	;

1.21.2.4.2.1
date	2005.01.04.05.07.03;	author chengyemao;	state Exp;
branches;
next	1.21.2.4.2.2;

1.21.2.4.2.2
date	2005.01.19.02.03.48;	author chengyemao;	state Exp;
branches;
next	;

1.56.2.1
date	2007.06.12.16.22.45;	author dgp;	state Exp;
branches;
next	1.56.2.2;

1.56.2.2
date	2007.09.09.04.15.55;	author dgp;	state Exp;
branches;
next	;

1.59.2.1
date	2009.02.23.10.37.38;	author patthoyts;	state Exp;
branches;
next	1.59.2.2;

1.59.2.2
date	2009.05.21.23.01.33;	author patthoyts;	state Exp;
branches;
next	1.59.2.3;

1.59.2.3
date	2009.09.14.23.40.42;	author hobbs;	state Exp;
branches;
next	1.59.2.4;

1.59.2.4
date	2009.12.27.23.42.45;	author patthoyts;	state Exp;
branches;
next	1.59.2.5;

1.59.2.5
date	2010.01.03.20.03.55;	author patthoyts;	state Exp;
branches;
next	1.59.2.6;

1.59.2.6
date	2010.03.12.13.02.36;	author nijtmans;	state Exp;
branches;
next	;


desc
@@


1.79
log
@Revise Tcl_Panic() calls ending with a newline removing the newline, because Tcl_Panic() outputs a final newline already
@
text
@/*
 * tkWinMenu.c --
 *
 *	This module implements the Windows platform-specific features of
 *	menus.
 *
 * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.78 2010/11/03 12:11:44 nijtmans Exp $
 */

#define OEMRESOURCE
#include "tkWinInt.h"
#include "tkMenu.h"

/*
 * The class of the window for popup menus.
 */

#define MENU_CLASS_NAME			TEXT("MenuWindowClass")
#define EMBEDDED_MENU_CLASS_NAME	TEXT("EmbeddedMenuWindowClass")

/*
 * Used to align a windows bitmap inside a rectangle
 */

#define ALIGN_BITMAP_LEFT	0x00000001
#define ALIGN_BITMAP_RIGHT	0x00000002
#define ALIGN_BITMAP_TOP	0x00000004
#define ALIGN_BITMAP_BOTTOM	0x00000008


/*
 * Platform-specific menu flags:
 *
 * MENU_SYSTEM_MENU	Non-zero means that the Windows menu handle was
 *			retrieved with GetSystemMenu and needs to be disposed
 *			of specially.
 * MENU_RECONFIGURE_PENDING
 *			Non-zero means that an idle handler has been set up to
 *			reconfigure the Windows menu handle for this menu.
 */

#define MENU_SYSTEM_MENU		MENU_PLATFORM_FLAG1
#define MENU_RECONFIGURE_PENDING	MENU_PLATFORM_FLAG2

/*
 * ODS_NOACCEL flag forbids drawing accelerator cues (i.e. underlining labels)
 * on Windows 2000 and above.  The ODS_NOACCEL define is missing from mingw32
 * headers and undefined for _WIN32_WINNT < 0x0500 in Microsoft SDK.  We might
 * check for _WIN32_WINNT here, but I think it's not needed, as checking for
 * this flag does no harm on even on NT: reserved bits should be zero, and in
 * fact they are.
 */

#ifndef ODS_NOACCEL
#define ODS_NOACCEL 0x100
#endif
#ifndef SPI_GETKEYBOARDCUES
#define SPI_GETKEYBOARDCUES             0x100A
#endif
#ifndef WM_UPDATEUISTATE
#define WM_UPDATEUISTATE                0x0128
#endif
#ifndef UIS_SET
#define UIS_SET                         1
#endif
#ifndef UIS_CLEAR
#define UIS_CLEAR                       2
#endif
#ifndef UISF_HIDEACCEL
#define UISF_HIDEACCEL                  2
#endif

#ifndef WM_UNINITMENUPOPUP
#define WM_UNINITMENUPOPUP              0x0125
#endif

static int indicatorDimensions[2];
				/* The dimensions of the indicator space in a
				 * menu entry. Calculated at init time to save
				 * time. */

static BOOL showMenuAccelerators;

typedef struct ThreadSpecificData {
    int inPostMenu;		/* We cannot be re-entrant like X Windows. */
    WORD lastCommandID;		/* The last command ID we allocated. */
    HWND menuHWND;		/* A window to service popup-menu messages
				 * in. */
    HWND embeddedMenuHWND;	/* A window to service embedded menu
				 * messages */
    int oldServiceMode;		/* Used while processing a menu; we need to
				 * set the event mode specially when we enter
				 * the menu processing modal loop and reset it
				 * when menus go away. */
    TkMenu *modalMenuPtr;	/* The menu we are processing inside the modal
				 * loop. We need this to reset all of the
				 * active items when menus go away since
				 * Windows does not see fit to give this to us
				 * when it sends its WM_MENUSELECT. */
    Tcl_HashTable commandTable;	/* A map of command ids to menu entries */
    Tcl_HashTable winMenuTable;	/* Need this to map HMENUs back to menuPtrs */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following are default menu value strings.
 */

static int defaultBorderWidth;	/* The windows default border width. */
static Tcl_DString menuFontDString;
				/* A buffer to store the default menu font
				 * string. */
/*
 * Forward declarations for functions defined later in this file:
 */

static void		DrawMenuEntryAccelerator(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d, GC gc,
			    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,
			    Tk_3DBorder activeBorder, int x, int y,
			    int width, int height);
static void		DrawMenuEntryArrow(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_3DBorder activeBorder,
			    int x,int y, int width, int height, int drawArrow);
static void		DrawMenuEntryBackground(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d,
			    Tk_3DBorder activeBorder, Tk_3DBorder bgBorder,
			    int x, int y, int width, int heigth);
static void		DrawMenuEntryIndicator(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d, GC gc,
			    GC indicatorGC, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int x, int y,
			    int width, int height);
static void		DrawMenuEntryLabel(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int x, int y,
			    int width, int height, int underline);
static void		DrawMenuSeparator(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr,
			    int x, int y, int width, int height);
static void		DrawTearoffEntry(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int x, int y,
			    int width, int height);
static void		DrawMenuUnderline(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int x, int y,
			    int width, int height);
static void		DrawWindowsSystemBitmap(Display *display,
			    Drawable drawable, GC gc, const RECT *rectPtr,
			    int bitmapID, int alignFlags);
static void		FreeID(WORD commandID);
static char *	GetEntryText(TkMenuEntry *mePtr);
static void		GetMenuAccelGeometry(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int *widthPtr,
			    int *heightPtr);
static void		GetMenuLabelGeometry(TkMenuEntry *mePtr,
			    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,
			    int *widthPtr, int *heightPtr);
static void		GetMenuIndicatorGeometry(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr,
			    int *widthPtr, int *heightPtr);
static void		GetMenuSeparatorGeometry(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr,
			    int *widthPtr, int *heightPtr);
static void		GetTearoffEntryGeometry(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int *widthPtr,
			    int *heightPtr);
static int		GetNewID(TkMenuEntry *mePtr, WORD *menuIDPtr);
static int		TkWinMenuKeyObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		MenuSelectEvent(TkMenu *menuPtr);
static void		ReconfigureWindowsMenu(ClientData clientData);
static void		RecursivelyClearActiveMenu(TkMenu *menuPtr);
static void		SetDefaults(int firstTime);
static LRESULT CALLBACK	TkWinMenuProc(HWND hwnd, UINT message, WPARAM wParam,
			    LPARAM lParam);
static LRESULT CALLBACK	TkWinEmbeddedMenuProc(HWND hwnd, UINT message,
			    WPARAM wParam, LPARAM lParam);

/*
 *----------------------------------------------------------------------
 *
 * GetNewID --
 *
 *	Allocates a new menu id and marks it in use.
 *
 * Results:
 *	Returns TCL_OK if succesful; TCL_ERROR if there are no more ids of the
 *	appropriate type to allocate. menuIDPtr contains the new id if
 *	succesful.
 *
 * Side effects:
 *	An entry is created for the menu in the command hash table, and the
 *	hash entry is stored in the appropriate field in the menu data
 *	structure.
 *
 *----------------------------------------------------------------------
 */

static int
GetNewID(
    TkMenuEntry *mePtr,		/* The menu we are working with. */
    WORD *menuIDPtr)		/* The resulting id. */
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    WORD curID = tsdPtr->lastCommandID + 1;

    /*
     * The following code relies on WORD wrapping when the highest value is
     * incremented.
     */

    while (curID != tsdPtr->lastCommandID) {
	Tcl_HashEntry *commandEntryPtr;
	int newEntry;

    	commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,
		((char *) NULL) + curID, &newEntry);
    	if (newEntry == 1) {
	    Tcl_SetHashValue(commandEntryPtr, mePtr);
	    *menuIDPtr = curID;
	    tsdPtr->lastCommandID = curID;
	    return TCL_OK;
    	}
    	curID++;
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeID --
 *
 *	Marks the itemID as free.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The hash table entry for the ID is cleared.
 *
 *----------------------------------------------------------------------
 */

static void
FreeID(
    WORD commandID)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * If the menuHWND is NULL, this table has been finalized already.
     */

    if (tsdPtr->menuHWND != NULL) {
	Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
		((char *) NULL) + commandID);
	if (entryPtr != NULL) {
	    Tcl_DeleteHashEntry(entryPtr);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpNewMenu --
 *
 *	Gets a new blank menu. Only the platform specific options are filled
 *	in.
 *
 * Results:
 *	Standard TCL error.
 *
 * Side effects:
 *	Allocates a Windows menu handle and places it in the platformData
 *	field of the menuPtr.
 *
 *----------------------------------------------------------------------
 */

int
TkpNewMenu(
    TkMenu *menuPtr)		/* The common structure we are making the
				 * platform structure for. */
{
    HMENU winMenuHdl;
    Tcl_HashEntry *hashEntryPtr;
    int newEntry;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    winMenuHdl = CreatePopupMenu();

    if (winMenuHdl == NULL) {
    	Tcl_AppendResult(menuPtr->interp, "No more menus can be allocated.",
    		(char *) NULL);
    	return TCL_ERROR;
    }

    /*
     * We hash all of the HMENU's so that we can get their menu ptrs back when
     * dispatch messages.
     */

    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
	    (char *) winMenuHdl, &newEntry);
    Tcl_SetHashValue(hashEntryPtr, menuPtr);

    menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDestroyMenu --
 *
 *	Destroys platform-specific menu structures.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	All platform-specific allocations are freed up.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenu(
    TkMenu *menuPtr)		/* The common menu structure */
{
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    const char *searchName;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
	Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
    }

    if (winMenuHdl == NULL) {
	return;
    }

    if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {
	TkMenuEntry *searchEntryPtr;
	Tcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);
	char *menuName = Tcl_GetHashKey(tablePtr,
		menuPtr->menuRefPtr->hashEntryPtr);

	/*
	 * Search for the menu in the menubar, if it is present, get the
	 * wrapper window associated with the toplevel and reset its
	 * system menu to the default menu.
	 */

	for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
		searchEntryPtr != NULL;
		searchEntryPtr = searchEntryPtr->nextCascadePtr) {
	    searchName = Tcl_GetString(searchEntryPtr->namePtr);
	    if (strcmp(searchName, menuName) == 0) {
		Tk_Window parentTopLevelPtr = searchEntryPtr
			->menuPtr->parentTopLevelPtr;

		if (parentTopLevelPtr != NULL) {
		    GetSystemMenu(
			    TkWinGetWrapperWindow(parentTopLevelPtr), TRUE);
		}
		break;
	    }
	}
    } else {
	/*
	 * Remove the menu from the menu hash table, then destroy the handle.
	 * If the menuHWND is NULL, this table has been finalized already.
	 */

	if (tsdPtr->menuHWND != NULL) {
	    Tcl_HashEntry *hashEntryPtr =
		Tcl_FindHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl);
	    if (hashEntryPtr != NULL) {
		Tcl_DeleteHashEntry(hashEntryPtr);
	    }
	}
 	DestroyMenu(winMenuHdl);
    }
    menuPtr->platformData = NULL;

    if (menuPtr == tsdPtr->modalMenuPtr) {
	tsdPtr->modalMenuPtr = NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDestroyMenuEntry --
 *
 *	Cleans up platform-specific menu entry items.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	All platform-specific allocations are freed up.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenuEntry(
    TkMenuEntry *mePtr)		/* The entry to destroy */
{
    TkMenu *menuPtr = mePtr->menuPtr;
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;

    if (NULL != winMenuHdl) {
	if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
	    menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
	    Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
	}
    }
    FreeID((WORD) (UINT) mePtr->platformEntryData);
    mePtr->platformEntryData = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * GetEntryText --
 *
 *	Given a menu entry, gives back the text that should go in it.
 *	Separators should be done by the caller, as they have to be handled
 *	specially. Allocates the memory with alloc. The caller should free the
 *	memory.
 *
 * Results:
 *	itemText points to the new text for the item.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
GetEntryText(
    TkMenuEntry *mePtr)		/* A pointer to the menu entry. */
{
    char *itemText;

    if (mePtr->type == TEAROFF_ENTRY) {
	itemText = ckalloc(sizeof("(Tear-off)"));
	strcpy(itemText, "(Tear-off)");
    } else if (mePtr->imagePtr != NULL) {
	itemText = ckalloc(sizeof("(Image)"));
	strcpy(itemText, "(Image)");
    } else if (mePtr->bitmapPtr != NULL) {
	itemText = ckalloc(sizeof("(Pixmap)"));
	strcpy(itemText, "(Pixmap)");
    } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
	itemText = ckalloc(sizeof("( )"));
	strcpy(itemText, "( )");
    } else {
	int i;
	const char *label = (mePtr->labelPtr == NULL) ? ""
		: Tcl_GetString(mePtr->labelPtr);
	const char *accel = (mePtr->accelPtr == NULL) ? ""
		: Tcl_GetString(mePtr->accelPtr);
	const char *p, *next;
	Tcl_DString itemString;

	/*
	 * We have to construct the string with an ampersand preceeding the
	 * underline character, and a tab seperating the text and the accel
	 * text. We have to be careful with ampersands in the string.
	 */

	Tcl_DStringInit(&itemString);

	for (p = label, i = 0; *p != '\0'; i++, p = next) {
	    if (i == mePtr->underline) {
		Tcl_DStringAppend(&itemString, "&", 1);
	    }
	    if (*p == '&') {
		Tcl_DStringAppend(&itemString, "&", 1);
	    }
	    next = Tcl_UtfNext(p);
	    Tcl_DStringAppend(&itemString, p, (int) (next - p));
	}
	if (mePtr->accelLength > 0) {
	    Tcl_DStringAppend(&itemString, "\t", 1);
	    for (p = accel, i = 0; *p != '\0'; i++, p = next) {
		if (*p == '&') {
		    Tcl_DStringAppend(&itemString, "&", 1);
		}
		next = Tcl_UtfNext(p);
		Tcl_DStringAppend(&itemString, p, (int) (next - p));
	    }
	}

	itemText = ckalloc((unsigned)Tcl_DStringLength(&itemString) + 1);
	strcpy(itemText, Tcl_DStringValue(&itemString));
	Tcl_DStringFree(&itemString);
    }
    return itemText;
}

/*
 *----------------------------------------------------------------------
 *
 * ReconfigureWindowsMenu --
 *
 *	Tears down and rebuilds the platform-specific part of this menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Configuration information get set for mePtr; old resources get freed,
 *	if any need it.
 *
 *----------------------------------------------------------------------
 */

static void
ReconfigureWindowsMenu(
    ClientData clientData)	/* The menu we are rebuilding */
{
    TkMenu *menuPtr = (TkMenu *) clientData;
    TkMenuEntry *mePtr;
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    char *itemText = NULL;
    const TCHAR *lpNewItem;
    UINT flags;
    UINT itemID;
    int i, count, systemMenu = 0, base;
    Tcl_DString translatedText;

    if (NULL == winMenuHdl) {
    	return;
    }

    /*
     * Reconstruct the entire menu. Takes care of nasty system menu and index
     * problem.
     */

    base = (menuPtr->menuFlags & MENU_SYSTEM_MENU) ? 7 : 0;
    count = GetMenuItemCount(winMenuHdl);
    for (i = base; i < count; i++) {
	RemoveMenu(winMenuHdl, base, MF_BYPOSITION);
    }

    count = menuPtr->numEntries;
    for (i = 0; i < count; i++) {
	mePtr = menuPtr->entries[i];
	lpNewItem = NULL;
	flags = MF_BYPOSITION;
	itemID = 0;
	Tcl_DStringInit(&translatedText);

	if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {
	    continue;
	}

	itemText = GetEntryText(mePtr);
	if ((menuPtr->menuType == MENUBAR)
		|| (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
	    Tcl_WinUtfToTChar(itemText, -1, &translatedText);
	    lpNewItem = (const TCHAR *) Tcl_DStringValue(&translatedText);
	    flags |= MF_STRING;
	} else {
	    lpNewItem = (LPCTSTR) mePtr;
	    flags |= MF_OWNERDRAW;
	}

	/*
	 * Set enabling and disabling correctly.
	 */

	if (mePtr->state == ENTRY_DISABLED) {
	    flags |= MF_DISABLED | MF_GRAYED;
	}

	/*
	 * Set the check mark for check entries and radio entries.
	 */

	if (((mePtr->type == CHECK_BUTTON_ENTRY)
		|| (mePtr->type == RADIO_BUTTON_ENTRY))
		&& (mePtr->entryFlags & ENTRY_SELECTED)) {
	    flags |= MF_CHECKED;
	}

	/*
	 * Set the SEPARATOR bit for separator entries. This bit is not used
	 * by our internal drawing functions, but it is used by the system
	 * when drawing the system menu (we do not draw the system menu
	 * ourselves). If this bit is not set, separator entries on the system
	 * menu will not be drawn correctly.
	 */

	if (mePtr->type == SEPARATOR_ENTRY) {
	    flags |= MF_SEPARATOR;
	}

	if (mePtr->columnBreak) {
	    flags |= MF_MENUBREAK;
	}

	itemID = (UINT) mePtr->platformEntryData;
	if ((mePtr->type == CASCADE_ENTRY)
		&& (mePtr->childMenuRefPtr != NULL)
		&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
	    HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr
		->platformData;
	    if (childMenuHdl != NULL) {
		/*
		 * Win32 draws the popup arrow in the wrong color for a
		 * disabled cascade menu, so do it by hand. Given it is
		 * disabled, there's no need for it to be connected to its
		 * child.
		 */

		if (mePtr->state != ENTRY_DISABLED) {
		    flags |= MF_POPUP;
		    /*
		     * If the MF_POPUP flag is set, then the id is interpreted
		     * as the handle of a submenu.
		     */
		    itemID = (UINT) childMenuHdl;
		}
	    }
	    if ((menuPtr->menuType == MENUBAR)
		    && !(mePtr->childMenuRefPtr->menuPtr->menuFlags
			    & MENU_SYSTEM_MENU)) {
		Tcl_DString ds;
		TkMenuReferences *menuRefPtr;
		TkMenu *systemMenuPtr = mePtr->childMenuRefPtr->menuPtr;

		Tcl_DStringInit(&ds);
		Tcl_DStringAppend(&ds,
			Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
		Tcl_DStringAppend(&ds, ".system", 7);

		menuRefPtr = TkFindMenuReferences(menuPtr->interp,
			Tcl_DStringValue(&ds));

		Tcl_DStringFree(&ds);

		if ((menuRefPtr != NULL)
			&& (menuRefPtr->menuPtr != NULL)
			&& (menuPtr->parentTopLevelPtr != NULL)
			&& (systemMenuPtr->masterMenuPtr
				== menuRefPtr->menuPtr)) {
		    HMENU systemMenuHdl =
			(HMENU) systemMenuPtr->platformData;
		    HWND wrapper = TkWinGetWrapperWindow(menuPtr
			    ->parentTopLevelPtr);
		    if (wrapper != NULL) {
			DestroyMenu(systemMenuHdl);
			systemMenuHdl = GetSystemMenu(wrapper, FALSE);
			systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
			systemMenuPtr->platformData =
				(TkMenuPlatformData) systemMenuHdl;
			if (!(systemMenuPtr->menuFlags
				& MENU_RECONFIGURE_PENDING)) {
			    systemMenuPtr->menuFlags
				    |= MENU_RECONFIGURE_PENDING;
			    Tcl_DoWhenIdle(ReconfigureWindowsMenu,
				    (ClientData) systemMenuPtr);
			}
		    }
		}
	    }
	    if (mePtr->childMenuRefPtr->menuPtr->menuFlags
		    & MENU_SYSTEM_MENU) {
		systemMenu++;
	    }
	}
	if (!systemMenu) {
	    InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
	}
	Tcl_DStringFree(&translatedText);
	if (itemText != NULL) {
	    ckfree(itemText);
	    itemText = NULL;
	}
    }


    if ((menuPtr->menuType == MENUBAR)
	    && (menuPtr->parentTopLevelPtr != NULL)) {
	HANDLE bar;
	bar = TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr);
	if (bar) {
	    DrawMenuBar(bar);
	}
    }

    menuPtr->menuFlags &= ~(MENU_RECONFIGURE_PENDING);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	Posts a menu on the screen
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    int x, int y)
{
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    int result, flags;
    RECT noGoawayRect;
    POINT point;
    Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
    int oldServiceMode = Tcl_GetServiceMode();
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->inPostMenu++;

    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
	Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
	ReconfigureWindowsMenu((ClientData) menuPtr);
    }

    result = TkPreprocessMenu(menuPtr);
    if (result != TCL_OK) {
	tsdPtr->inPostMenu--;
	return result;
    }

    /*
     * The post commands could have deleted the menu, which means
     * we are dead and should go away.
     */

    if (menuPtr->tkwin == NULL) {
	tsdPtr->inPostMenu--;
    	return TCL_OK;
    }

    if (NULL == parentWindow) {
	noGoawayRect.top = y - 50;
	noGoawayRect.bottom = y + 50;
	noGoawayRect.left = x - 50;
	noGoawayRect.right = x + 50;
    } else {
	int left, top;
	Tk_GetRootCoords(parentWindow, &left, &top);
	noGoawayRect.left = left;
	noGoawayRect.top = top;
	noGoawayRect.bottom = noGoawayRect.top + Tk_Height(parentWindow);
	noGoawayRect.right = noGoawayRect.left + Tk_Width(parentWindow);
    }

    Tcl_SetServiceMode(TCL_SERVICE_NONE);

    /*
     * Make an assumption here. If the right button is down,
     * then we want to track it. Otherwise, track the left mouse button.
     */

    flags = TPM_LEFTALIGN;
    if (GetSystemMetrics(SM_SWAPBUTTON)) {
	if (GetAsyncKeyState(VK_LBUTTON) < 0) {
	    flags |= TPM_RIGHTBUTTON;
	} else {
	    flags |= TPM_LEFTBUTTON;
	}
    } else {
	if (GetAsyncKeyState(VK_RBUTTON) < 0) {
	    flags |= TPM_RIGHTBUTTON;
	} else {
	    flags |= TPM_LEFTBUTTON;
	}
    }

    TrackPopupMenu(winMenuHdl, flags, x, y, 0,
	    tsdPtr->menuHWND, &noGoawayRect);
    Tcl_SetServiceMode(oldServiceMode);

    GetCursorPos(&point);
    Tk_PointerEvent(NULL, point.x, point.y);

    if (tsdPtr->inPostMenu) {
	tsdPtr->inPostMenu = 0;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuNewEntry --
 *
 *	Adds a pointer to a new menu entry structure with the platform-
 *	specific fields filled in.
 *
 * Results:
 *	Standard TCL error.
 *
 * Side effects:
 *	A new command ID is allocated and stored in the platformEntryData
 *	field of mePtr.
 *
 *----------------------------------------------------------------------
 */

int
TkpMenuNewEntry(
    TkMenuEntry *mePtr)
{
    WORD commandID;
    TkMenu *menuPtr = mePtr->menuPtr;

    if (GetNewID(mePtr, &commandID) != TCL_OK) {
    	return TCL_ERROR;
    }

    if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
    	menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
    	Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
    }

    mePtr->platformEntryData = (TkMenuPlatformEntryData) (UINT) commandID;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinMenuProc --
 *
 *	The window proc for the dummy window we put popups in. This allows
 *	is to post a popup whether or not we know what the parent window
 *	is.
 *
 * Results:
 *	Returns whatever is appropriate for the message in question.
 *
 * Side effects:
 *	Normal side-effect for windows messages.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
TkWinMenuProc(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    LRESULT lResult;

    if (!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) {
	lResult = DefWindowProcA(hwnd, message, wParam, lParam);
    }
    return lResult;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateEmbeddedMenu --
 *
 *	This function is used as work-around for updating the pull-down window
 *	of an embedded menu which may show as a blank popup window.
 *
 * Results:
 *	Invalidate the client area of the embedded pull-down menu and
 *	redraw it.
 *
 * Side effects:
 *	Redraw the embedded menu window.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateEmbeddedMenu(
    ClientData clientData)
{
    RECT rc;
    HWND hMenuWnd = (HWND)clientData;
    GetClientRect(hMenuWnd, &rc);
    InvalidateRect(hMenuWnd, &rc, FALSE);
    UpdateWindow(hMenuWnd);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinEmbeddedMenuProc --
 *
 *	This window proc is for the embedded menu windows. It provides
 *	message services to an embedded menu in a different process.
 *
 * Results:
 *	Returns 1 if the message has been handled or 0 otherwise.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
TkWinEmbeddedMenuProc(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    static int nIdles = 0;
    LRESULT lResult = 1;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    switch(message) {
    case WM_ENTERIDLE:
	if ((wParam == MSGF_MENU) && (nIdles < 1)
		&& (hwnd == tsdPtr->embeddedMenuHWND)) {
	    Tcl_CreateTimerHandler(200, UpdateEmbeddedMenu,
		    (ClientData) lParam);
	    nIdles++;
	}
	break;

    case WM_INITMENUPOPUP:
	nIdles = 0;
	break;

    case WM_SETTINGCHANGE:
	if (wParam == SPI_SETNONCLIENTMETRICS
		|| wParam == SPI_SETKEYBOARDCUES) {
	    SetDefaults(0);
	}
	break;

    case WM_INITMENU:
    case WM_SYSCOMMAND:
    case WM_COMMAND:
    case WM_MENUCHAR:
    case WM_MEASUREITEM:
    case WM_DRAWITEM:
    case WM_MENUSELECT:
	lResult = TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,
		&lResult);
	if (lResult || (GetCapture() != hwnd)) {
	    break;
	}

    default:
	lResult = DefWindowProcA(hwnd, message, wParam, lParam);
	break;
    }
    return lResult;
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinHandleMenuEvent --
 *
 *	Filters out menu messages from messages passed to a top-level. Will
 *	respond appropriately to WM_COMMAND, WM_MENUSELECT, WM_MEASUREITEM,
 *	WM_DRAWITEM
 *
 * Result:
 *	Returns 1 if this handled the message; 0 if it did not.
 *
 * Side effects:
 *	All of the parameters may be modified so that the caller can think it
 *	is getting a different message. plResult points to the result that
 *	should be returned to windows from this message.
 *
 *----------------------------------------------------------------------
 */

int
TkWinHandleMenuEvent(
    HWND *phwnd,
    UINT *pMessage,
    WPARAM *pwParam,
    LPARAM *plParam,
    LRESULT *plResult)
{
    Tcl_HashEntry *hashEntryPtr;
    int returnResult = 0;
    TkMenu *menuPtr;
    TkMenuEntry *mePtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    switch (*pMessage) {
    case WM_UNINITMENUPOPUP:
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *pwParam);
	if (hashEntryPtr != NULL) {
	    menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
	    if ((menuPtr->menuRefPtr != NULL)
		    && (menuPtr->menuRefPtr->parentEntryPtr != NULL)) {
		TkPostSubmenu(menuPtr->interp,
			menuPtr->menuRefPtr->parentEntryPtr->menuPtr, NULL);
	    }
	}
	break;

    case WM_INITMENU:
	TkMenuInit();
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *pwParam);
	if (hashEntryPtr != NULL) {
	    tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
	    menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
	    tsdPtr->modalMenuPtr = menuPtr;
	    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
		Tcl_CancelIdleCall(ReconfigureWindowsMenu,
			(ClientData) menuPtr);
		ReconfigureWindowsMenu((ClientData) menuPtr);
	    }
	    RecursivelyClearActiveMenu(menuPtr);
	    if (!tsdPtr->inPostMenu) {
		Tcl_Interp *interp;
		int code;

		interp = menuPtr->interp;
		Tcl_Preserve((ClientData)interp);
		code = TkPreprocessMenu(menuPtr);
		if ((code != TCL_OK) && (code != TCL_CONTINUE)
			&& (code != TCL_BREAK)) {
		    Tcl_AddErrorInfo(interp, "\n    (menu preprocess)");
		    Tcl_BackgroundException(interp, code);
		}
		Tcl_Release((ClientData)interp);
	    }
	    TkActivateMenuEntry(menuPtr, -1);
	    *plResult = 0;
	    returnResult = 1;
	} else {
	    tsdPtr->modalMenuPtr = NULL;
	}
	break;

    case WM_SYSCOMMAND:
    case WM_COMMAND:
	TkMenuInit();
	if (HIWORD(*pwParam) != 0) {
	    break;
	}
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
		((char *) NULL) + LOWORD(*pwParam));
	if (hashEntryPtr == NULL) {
	    break;
	}
	mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
	if (mePtr != NULL) {
	    TkMenuReferences *menuRefPtr;
	    TkMenuEntry *parentEntryPtr;
	    Tcl_Interp *interp;
	    int code;

	    /*
	     * We have to set the parent of this menu to be active if this is
	     * a submenu so that tearoffs will get the correct title.
	     */

	    menuPtr = mePtr->menuPtr;
	    menuRefPtr = TkFindMenuReferences(menuPtr->interp,
		    Tk_PathName(menuPtr->tkwin));
	    if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) {
		for (parentEntryPtr = menuRefPtr->parentEntryPtr ; ;
			parentEntryPtr = parentEntryPtr->nextCascadePtr) {
		    const char *name = Tcl_GetString(parentEntryPtr->namePtr);

		    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
			break;
		    }
		}
		if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]
			->state != ENTRY_DISABLED) {
		    TkActivateMenuEntry(parentEntryPtr->menuPtr,
			    parentEntryPtr->index);
		}
	    }

	    interp = menuPtr->interp;
	    Tcl_Preserve((ClientData)interp);
	    code = TkInvokeMenu(interp, menuPtr, mePtr->index);
	    if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) {
		Tcl_AddErrorInfo(interp, "\n    (menu invoke)");
		Tcl_BackgroundException(interp, code);
	    }
	    Tcl_Release((ClientData)interp);
	    *plResult = 0;
	    returnResult = 1;
	}
	break;

    case WM_MENUCHAR: {
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *plParam);
	if (hashEntryPtr != NULL) {
	    int i, len, underline;
	    Tcl_Obj *labelPtr;
	    Tcl_UniChar *wlabel, menuChar;

	    *plResult = 0;
	    menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
	    /*
	     * Assume we have something directly convertable to Tcl_UniChar.
	     * True at least for wide systems.
	     */
	    menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam));

	    for (i = 0; i < menuPtr->numEntries; i++) {
		underline = menuPtr->entries[i]->underline;
		labelPtr = menuPtr->entries[i]->labelPtr;
		if ((underline >= 0) && (labelPtr != NULL)) {
		    /*
		     * Ensure we don't exceed the label length, then check
		     */
		    wlabel = Tcl_GetUnicodeFromObj(labelPtr, &len);
		    if ((underline < len) && (menuChar ==
				Tcl_UniCharToUpper(wlabel[underline]))) {
			*plResult = (2 << 16) | i;
			returnResult = 1;
			break;
		    }
		}
	    }
	}
	break;
    }

    case WM_MEASUREITEM: {
	LPMEASUREITEMSTRUCT itemPtr = (LPMEASUREITEMSTRUCT) *plParam;

	if (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) {
	    mePtr = (TkMenuEntry *) itemPtr->itemData;
	    menuPtr = mePtr->menuPtr;

	    TkRecomputeMenu(menuPtr);
	    itemPtr->itemHeight = mePtr->height;
	    itemPtr->itemWidth = mePtr->width;
	    if (mePtr->hideMargin) {
		itemPtr->itemWidth += 2 - indicatorDimensions[1];
	    } else {
		int activeBorderWidth;

		Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
			menuPtr->activeBorderWidthPtr, &activeBorderWidth);
		itemPtr->itemWidth += 2 * activeBorderWidth;
	    }
	    *plResult = 1;
	    returnResult = 1;
	}
	break;
    }

    case WM_DRAWITEM: {
	TkWinDrawable *twdPtr;
	LPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam;
	Tk_FontMetrics fontMetrics;
	int drawingParameters = 0;

	if (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) {
	    Tk_Font tkfont;

	    if (itemPtr->itemState & ODS_NOACCEL && !showMenuAccelerators) {
		drawingParameters |= DRAW_MENU_ENTRY_NOUNDERLINE;
	    }
	    mePtr = (TkMenuEntry *) itemPtr->itemData;
	    menuPtr = mePtr->menuPtr;
	    twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable));
	    twdPtr->type = TWD_WINDC;
	    twdPtr->winDC.hdc = itemPtr->hDC;

	    if (mePtr->state != ENTRY_DISABLED) {
		if (itemPtr->itemState & ODS_SELECTED) {
		    TkActivateMenuEntry(menuPtr, mePtr->index);
		} else {
		    TkActivateMenuEntry(menuPtr, -1);
		}
	    } else {
		/*
		 * On windows, menu entries should highlight even if they are
		 * disabled. (I know this seems dumb, but it is the way native
		 * windows menus works so we ought to mimic it.) The
		 * ENTRY_PLATFORM_FLAG1 flag will indicate that the entry
		 * should be highlighted even though it is disabled.
		 */

		if (itemPtr->itemState & ODS_SELECTED) {
		    mePtr->entryFlags |= ENTRY_PLATFORM_FLAG1;
		} else {
		    mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
		}

		/*
		 * Also, set the DRAW_MENU_ENTRY_ARROW flag for a disabled
		 * cascade menu since we need to draw the arrow ourselves.
		 */

		if (mePtr->type == CASCADE_ENTRY) {
		    drawingParameters |= DRAW_MENU_ENTRY_ARROW;
		}
	    }

	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
	    Tk_GetFontMetrics(tkfont, &fontMetrics);
	    TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont, &fontMetrics,
		    itemPtr->rcItem.left, itemPtr->rcItem.top,
		    itemPtr->rcItem.right - itemPtr->rcItem.left,
		    itemPtr->rcItem.bottom - itemPtr->rcItem.top,
		    0, drawingParameters);

	    ckfree((char *) twdPtr);
	}
	*plResult = 1;
	returnResult = 1;
	break;
    }

    case WM_MENUSELECT: {
	UINT flags = HIWORD(*pwParam);

	TkMenuInit();

	if ((flags == 0xFFFF) && (*plParam == 0)) {
	    if (tsdPtr->modalMenuPtr != NULL) {
		Tcl_SetServiceMode(tsdPtr->oldServiceMode);
		RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
	    }
	} else {
	    menuPtr = NULL;
	    if (*plParam != 0) {
		hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
			(char *) *plParam);
		if (hashEntryPtr != NULL) {
		    menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
		}
	    }

	    if (menuPtr != NULL) {
		long entryIndex = LOWORD(*pwParam);

		mePtr = NULL;
		if (flags != 0xFFFF) {
		    if ((flags&MF_POPUP) && (entryIndex<menuPtr->numEntries)) {
			mePtr = menuPtr->entries[entryIndex];
		    } else {
			hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
				((char *) NULL) + entryIndex);
			if (hashEntryPtr != NULL) {
			    mePtr = (TkMenuEntry *)
				    Tcl_GetHashValue(hashEntryPtr);
			}
		    }
		}

		if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
		    TkActivateMenuEntry(menuPtr, -1);
		} else {
		    if (mePtr->index >= menuPtr->numEntries) {
			Tcl_Panic("Trying to activate an entry which doesn't exist");
		    }
		    TkActivateMenuEntry(menuPtr, mePtr->index);
		}
		MenuSelectEvent(menuPtr);
		Tcl_ServiceAll();
		*plResult = 0;
		returnResult = 1;
	    }
	}
	break;
    }
    }
    return returnResult;
}

/*
 *----------------------------------------------------------------------
 *
 * RecursivelyClearActiveMenu --
 *
 *	Recursively clears the active entry in the menu's cascade hierarchy.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Generates <<MenuSelect>> virtual events.
 *
 *----------------------------------------------------------------------
 */

void
RecursivelyClearActiveMenu(
    TkMenu *menuPtr)		/* The menu to reset. */
{
    int i;
    TkMenuEntry *mePtr;

    TkActivateMenuEntry(menuPtr, -1);
    MenuSelectEvent(menuPtr);
    for (i = 0; i < menuPtr->numEntries; i++) {
    	mePtr = menuPtr->entries[i];
	if (mePtr->state == ENTRY_ACTIVE) {
	    mePtr->state = ENTRY_NORMAL;
	}
	mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
    	if (mePtr->type == CASCADE_ENTRY) {
    	    if ((mePtr->childMenuRefPtr != NULL)
    	    	    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
    	    	RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
    	    }
    	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetWindowMenuBar --
 *
 *	Associates a given menu with a window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	On Windows and UNIX, associates the platform menu with the
 *	platform window.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetWindowMenuBar(
    Tk_Window tkwin,		/* The window we are putting the menubar
				 * into.*/
    TkMenu *menuPtr)		/* The menu we are inserting */
{
    HMENU winMenuHdl;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (menuPtr != NULL) {
	Tcl_HashEntry *hashEntryPtr;
	int newEntry;

	winMenuHdl = (HMENU) menuPtr->platformData;
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) winMenuHdl);
	Tcl_DeleteHashEntry(hashEntryPtr);
	DestroyMenu(winMenuHdl);
	winMenuHdl = CreateMenu();
	hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
		(char *) winMenuHdl, &newEntry);
	Tcl_SetHashValue(hashEntryPtr, menuPtr);
	menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
	TkWinSetMenu(tkwin, winMenuHdl);
	if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
	    menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
	    Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
	}
    } else {
	TkWinSetMenu(tkwin, NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetMainMenubar --
 *
 *	Puts the menu associated with a window into the menubar. Should only
 *	be called when the window is in front.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The menubar is changed.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetMainMenubar(
    Tcl_Interp *interp,		/* The interpreter of the application */
    Tk_Window tkwin,		/* The frame we are setting up */
    const char *menuName)	/* The name of the menu to put in front. If
    				 * NULL, use the default menu bar. */
{
    /*
     * Nothing to do.
     */
}

/*
 *----------------------------------------------------------------------
 *
 * GetMenuIndicatorGeometry --
 *
 *	Gets the width and height of the indicator area of a menu.
 *
 * Results:
 *	widthPtr and heightPtr are set.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
GetMenuIndicatorGeometry(
    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* Precalculated font */
    const Tk_FontMetrics *fmPtr,/* Precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    *heightPtr = indicatorDimensions[0];
    if (mePtr->hideMargin) {
	*widthPtr = 0;
    } else {
	int borderWidth;

	Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
		menuPtr->borderWidthPtr, &borderWidth);
	*widthPtr = indicatorDimensions[1] - borderWidth;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GetMenuAccelGeometry --
 *
 *	Gets the width and height of the indicator area of a menu.
 *
 * Results:
 *	widthPtr and heightPtr are set.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
GetMenuAccelGeometry(
    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    *heightPtr = fmPtr->linespace;
    if (mePtr->type == CASCADE_ENTRY) {
	*widthPtr = 0;
    } else if (mePtr->accelPtr == NULL) {
	*widthPtr = 0;
    } else {
	const char *accel = Tcl_GetString(mePtr->accelPtr);

	*widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GetTearoffEntryGeometry --
 *
 *	Gets the width and height of the indicator area of a menu.
 *
 * Results:
 *	widthPtr and heightPtr are set.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
GetTearoffEntryGeometry(
    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    if (menuPtr->menuType != MASTER_MENU) {
	*heightPtr = 0;
    } else {
	*heightPtr = fmPtr->linespace;
    }
    *widthPtr = 0;
}

/*
 *----------------------------------------------------------------------
 *
 * GetMenuSeparatorGeometry --
 *
 *	Gets the width and height of the indicator area of a menu.
 *
 * Results:
 *	widthPtr and heightPtr are set.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
GetMenuSeparatorGeometry(
    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    *widthPtr = 0;
    *heightPtr = fmPtr->linespace - (2 * fmPtr->descent);
}

/*
 *----------------------------------------------------------------------
 *
 * DrawWindowsSystemBitmap --
 *
 *	Draws the windows system bitmap given by bitmapID into the rect given
 *	by rectPtr in the drawable. The bitmap is centered in the rectangle.
 *	It is not clipped, so if the bitmap is bigger than the rect it will
 *	bleed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Drawing occurs. Some storage is allocated and released.
 *
 *----------------------------------------------------------------------
 */

static void
DrawWindowsSystemBitmap(
    Display *display,		/* The display we are drawing into */
    Drawable drawable,		/* The drawable we are working with */
    GC gc,			/* The GC to draw with */
    const RECT *rectPtr,	/* The rectangle to draw into */
    int bitmapID,		/* The windows id of the system bitmap to
				 * draw. */
    int alignFlags)		/* How to align the bitmap inside the
				 * rectangle. */
{
    TkWinDCState state;
    HDC hdc = TkWinGetDrawableDC(display, drawable, &state);
    HDC scratchDC;
    HBITMAP bitmap;
    BITMAP bm;
    POINT ptSize;
    POINT ptOrg;
    int topOffset, leftOffset;

    SetBkColor(hdc, gc->background);
    SetTextColor(hdc, gc->foreground);

    scratchDC = CreateCompatibleDC(hdc);
    bitmap = LoadBitmap(NULL, MAKEINTRESOURCE(bitmapID));

    SelectObject(scratchDC, bitmap);
    SetMapMode(scratchDC, GetMapMode(hdc));
    GetObjectA(bitmap, sizeof(BITMAP), &bm);
    ptSize.x = bm.bmWidth;
    ptSize.y = bm.bmHeight;
    DPtoLP(scratchDC, &ptSize, 1);

    ptOrg.y = ptOrg.x = 0;
    DPtoLP(scratchDC, &ptOrg, 1);

    if (alignFlags & ALIGN_BITMAP_TOP) {
	topOffset = 0;
    } else if (alignFlags & ALIGN_BITMAP_BOTTOM) {
	topOffset = (rectPtr->bottom - rectPtr->top) - ptSize.y;
    } else {
	topOffset = (rectPtr->bottom - rectPtr->top) / 2 - (ptSize.y / 2);
    }

    if (alignFlags & ALIGN_BITMAP_LEFT) {
	leftOffset = 0;
    } else if (alignFlags & ALIGN_BITMAP_RIGHT) {
	leftOffset = (rectPtr->right - rectPtr->left) - ptSize.x;
    } else {
	leftOffset = (rectPtr->right - rectPtr->left) / 2 - (ptSize.x / 2);
    }

    BitBlt(hdc, rectPtr->left + leftOffset, rectPtr->top + topOffset, ptSize.x,
	    ptSize.y, scratchDC, ptOrg.x, ptOrg.y, SRCCOPY);
    DeleteDC(scratchDC);
    DeleteObject(bitmap);

    TkWinReleaseDrawableDC(drawable, hdc, &state);
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryIndicator --
 *
 *	This function draws the indicator part of a menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the menu in its current mode.
 *
 *----------------------------------------------------------------------
 */

void
DrawMenuEntryIndicator(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc we are drawing with */
    GC indicatorGC,		/* The gc for indicator objects */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x,			/* Left edge */
    int y,			/* Top edge */
    int width,
    int height)
{
    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
    	if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
	    RECT rect;
	    GC whichGC;
	    int borderWidth, activeBorderWidth;

	    if (mePtr->state != ENTRY_NORMAL) {
		whichGC = gc;
	    } else {
		whichGC = indicatorGC;
	    }

	    rect.top = y;
	    rect.bottom = y + mePtr->height;
	    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
		    menuPtr->borderWidthPtr, &borderWidth);
	    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
		    menuPtr->activeBorderWidthPtr, &activeBorderWidth);
	    rect.left = borderWidth + activeBorderWidth + x;
	    rect.right = mePtr->indicatorSpace + x;

	    if ((mePtr->state == ENTRY_DISABLED)
		    && (menuPtr->disabledFgPtr != NULL)) {
		RECT hilightRect;
		COLORREF oldFgColor = whichGC->foreground;

		whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
		hilightRect.top = rect.top + 1;
		hilightRect.bottom = rect.bottom + 1;
		hilightRect.left = rect.left + 1;
		hilightRect.right = rect.right + 1;
		DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,
			&hilightRect, OBM_CHECK, 0);
		whichGC->foreground = oldFgColor;
	    }

	    DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,
		    OBM_CHECK, 0);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryAccelerator --
 *
 *	This function draws the accelerator part of a menu. For example, the
 *	string "CTRL-Z" could be drawn to to the right of the label text for
 *	an Undo menu entry. Need to decide what to draw here. Should we
 *	replace strings like "Control", "Command", etc?
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to display the menu in its
 *	current mode.
 *
 *----------------------------------------------------------------------
 */

void
DrawMenuEntryAccelerator(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc we are drawing with */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    Tk_3DBorder activeBorder,	/* The border when an item is active */
    int x,			/* left edge */
    int y,			/* top edge */
    int width,			/* Width of menu entry */
    int height)			/* Height of menu entry */
{
    int baseline;
    int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;
    const char *accel;

    if (mePtr->accelPtr != NULL) {
	accel = Tcl_GetString(mePtr->accelPtr);
    } else {
	accel = NULL;
    }

    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;

    /*
     * Draw disabled 3D text highlight only with the Win95/98 look.
     */

    if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) {
	if ((mePtr->state == ENTRY_DISABLED)
		&& (menuPtr->disabledFgPtr != NULL) && (accel != NULL)) {
	    COLORREF oldFgColor = gc->foreground;

	    gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	    if ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0) {
		Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
			mePtr->accelLength, leftEdge + 1, baseline + 1);
	    }
	    gc->foreground = oldFgColor;
	}
    }

    if (accel != NULL) {
	Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
		mePtr->accelLength, leftEdge, baseline);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryArrow --
 *
 *	This function draws the arrow bitmap on the right side of a menu
 *	entry. This function is only used when drawing the arrow for a
 *	disabled cascade menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
DrawMenuEntryArrow(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc we are drawing with */
    Tk_3DBorder activeBorder,	/* The border when an item is active */
    int x,			/* left edge */
    int y,			/* top edge */
    int width,			/* Width of menu entry */
    int height,			/* Height of menu entry */
    int drawArrow)		/* For cascade menus, whether of not to draw
				 * the arraw. I cannot figure out Windows'
				 * algorithm for where to draw this. */
{
    COLORREF oldFgColor;
    COLORREF oldBgColor;
    RECT rect;

    if (!drawArrow || (mePtr->type != CASCADE_ENTRY)) {
	return;
    }

    oldFgColor = gc->foreground;
    oldBgColor = gc->background;

    /*
     * Set bitmap bg to highlight color if the menu is highlighted.
     */

    if (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) {
	XColor *activeBgColor = Tk_3DBorderColor(Tk_Get3DBorderFromObj(
		mePtr->menuPtr->tkwin, (mePtr->activeBorderPtr == NULL)
		? mePtr->menuPtr->activeBorderPtr
		: mePtr->activeBorderPtr));
	gc->background = activeBgColor->pixel;
    }

    gc->foreground = GetSysColor((mePtr->state == ENTRY_DISABLED)
	? COLOR_GRAYTEXT
		: ((mePtr->state == ENTRY_ACTIVE)
		? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));

    rect.top = y + GetSystemMetrics(SM_CYBORDER);
    rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER);
    rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth;
    rect.right = x + width;

    DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,
	    ALIGN_BITMAP_RIGHT);

    gc->foreground = oldFgColor;
    gc->background = oldBgColor;
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuSeparator --
 *
 *	The menu separator is drawn.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the menu in its current mode.
 *
 *----------------------------------------------------------------------
 */

void
DrawMenuSeparator(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc we are drawing with */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x,			/* left edge */
    int y,			/* top edge */
    int width,			/* width of item */
    int height)			/* height of item */
{
    XPoint points[2];
    Tk_3DBorder border;

    points[0].x = x;
    points[0].y = y + height / 2;
    points[1].x = x + width - 1;
    points[1].y = points[0].y;
    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
    Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
	    TK_RELIEF_RAISED);
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuUnderline --
 *
 *	On appropriate platforms, draw the underline character for the menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the menu in its current mode.
 *
 *----------------------------------------------------------------------
 */

static void
DrawMenuUnderline(
    TkMenu *menuPtr,		/* The menu to draw into */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc to draw into */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x,			/* Left Edge */
    int y,			/* Top Edge */
    int width,			/* Width of entry */
    int height)			/* Height of entry */
{
    if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
	int len;

	/* do the unicode call just to prevent overruns */
	Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len);
	if (mePtr->underline < len) {
	    const char *label, *start, *end;

	    label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
	    start = Tcl_UtfAtIndex(label, mePtr->underline);
	    end = Tcl_UtfNext(start);
	    Tk_UnderlineChars(menuPtr->display, d,
		    gc, tkfont, label, x + mePtr->indicatorSpace,
		    y + (height + fmPtr->ascent - fmPtr->descent) / 2,
		    (int) (start - label), (int) (end - label));
	}
    }
}

/*
 *--------------------------------------------------------------
 *
 * TkWinMenuKeyObjCmd --
 *
 *	This function is invoked when keys related to pulling down menus is
 *	pressed. The corresponding Windows events are generated and passed to
 *	DefWindowProc if appropriate. This cmd is registered as tk::WinMenuKey
 *	in the interp.
 *
 * Results:
 *	Always returns TCL_OK.
 *
 * Side effects:
 *	The menu system may take over and process user events for menu input.
 *
 *--------------------------------------------------------------
 */

static int
TkWinMenuKeyObjCmd(
    ClientData clientData,	/* Unused. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    UINT scanCode;
    UINT virtualKey;
    XEvent *eventPtr;
    Tk_Window tkwin;
    TkWindow *winPtr;
    KeySym keySym;
    int i;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "window keySym");
	return TCL_ERROR;
    }

    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]),
	    Tk_MainWindow(interp));

    if (tkwin == NULL) {
	/*
	 * If we don't find the key, just return, as the window may have
	 * been destroyed in the binding. [Bug 1236306]
	 */
	return TCL_OK;
    }

    eventPtr = TkpGetBindingXEvent(interp);

    winPtr = (TkWindow *)tkwin;

    if (Tcl_GetIntFromObj(interp, objv[2], &i) != TCL_OK) {
	return TCL_ERROR;
    }
    keySym = i;

    if (eventPtr->type == KeyPress) {
	switch (keySym) {
	case XK_Alt_L:
	    scanCode = MapVirtualKeyA(VK_LMENU, 0);
	    CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYDOWN, VK_MENU,
		    (int) (scanCode << 16) | (1 << 29));
	    break;
	case XK_Alt_R:
	    scanCode = MapVirtualKeyA(VK_RMENU, 0);
	    CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYDOWN, VK_MENU,
		    (int) (scanCode << 16) | (1 << 29) | (1 << 24));
	    break;
	case XK_F10:
	    scanCode = MapVirtualKeyA(VK_F10, 0);
	    CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYDOWN, VK_F10, (int) (scanCode << 16));
	    break;
	default:
	    virtualKey = XKeysymToKeycode(winPtr->display, keySym);
	    scanCode = MapVirtualKeyA(virtualKey, 0);
	    if (0 != scanCode) {
		XKeyEvent xkey = eventPtr->xkey;
		CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
			WM_SYSKEYDOWN, virtualKey,
			(int) ((scanCode << 16) | (1 << 29)));
		if (xkey.nbytes > 0) {
		    for (i = 0; i < xkey.nbytes; i++) {
			CallWindowProcA(DefWindowProcA,
				Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR,
				xkey.trans_chars[i],
				(int) ((scanCode << 16) | (1 << 29)));
		    }
		}
	    }
	}
    } else if (eventPtr->type == KeyRelease) {
	switch (keySym) {
	case XK_Alt_L:
	    scanCode = MapVirtualKeyA(VK_LMENU, 0);
	    CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16)
		    | (1 << 29) | (1 << 30) | (1 << 31));
	    break;
	case XK_Alt_R:
	    scanCode = MapVirtualKeyA(VK_RMENU, 0);
	    CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16) | (1 << 24)
		    | (0x111 << 29) | (1 << 30) | (1 << 31));
	    break;
	case XK_F10:
	    scanCode = MapVirtualKeyA(VK_F10, 0);
	    CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_F10,
		    (int) (scanCode << 16) | (1 << 30) | (1 << 31));
	    break;
	default:
	    virtualKey = XKeysymToKeycode(winPtr->display, keySym);
	    scanCode = MapVirtualKeyA(virtualKey, 0);
	    if (0 != scanCode) {
		CallWindowProcA(DefWindowProcA, Tk_GetHWND(Tk_WindowId(tkwin)),
			WM_SYSKEYUP, virtualKey, (int) ((scanCode << 16)
			| (1 << 29) | (1 << 30) | (1 << 31)));
	    }
	}
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * TkpInitializeMenuBindings --
 *
 *	For every interp, initializes the bindings for Windows menus. Does
 *	nothing on Mac or XWindows.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	bindings are setup for the interp which will handle Alt-key sequences
 *	for menus without beeping or interfering with user-defined Alt-key
 *	bindings.
 *
 *--------------------------------------------------------------
 */

void
TkpInitializeMenuBindings(
    Tcl_Interp *interp,		/* The interpreter to set. */
    Tk_BindingTable bindingTable)
				/* The table to add to. */
{
    Tk_Uid uid = Tk_GetUid("all");

    /*
     * We need to set up the bindings for menubars. These have to recreate
     * windows events, so we need to invoke C code to generate the
     * WM_SYSKEYDOWNS and WM_SYSKEYUPs appropriately. Trick is, we can't
     * create a C level binding directly since we may want to modify the
     * binding in Tcl code.
     */

    (void) Tcl_CreateObjCommand(interp, "tk::WinMenuKey",
	    TkWinMenuKeyObjCmd,
	    (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt_L>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyRelease-Alt_L>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt_R>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyRelease-Alt_R>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt-KeyPress>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt-KeyRelease>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyPress-F10>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyRelease-F10>", "tk::WinMenuKey %W %N", 0);
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryLabel --
 *
 *	This function draws the label part of a menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the menu in its
 *	current mode.
 *
 *----------------------------------------------------------------------
 */

static void
DrawMenuEntryLabel(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc we are drawing into */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x,			/* left edge */
    int y,			/* right edge */
    int width,			/* width of entry */
    int height,			/* height of entry */
    int underline)		/* accelerator cue should be drawn */
{
    int indicatorSpace = mePtr->indicatorSpace;
    int activeBorderWidth;
    int leftEdge;
    int imageHeight, imageWidth;
    int textHeight = 0, textWidth = 0;
    int haveImage = 0, haveText = 0;
    int imageXOffset = 0, imageYOffset = 0;
    int textXOffset = 0, textYOffset = 0;

    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
	    menuPtr->activeBorderWidthPtr, &activeBorderWidth);
    leftEdge = x + indicatorSpace + activeBorderWidth;

    /*
     * Work out what we will need to draw first.
     */

    if (mePtr->image != NULL) {
    	Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
	haveImage = 1;
    } else if (mePtr->bitmapPtr != NULL) {
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
	Tk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight);
	haveImage = 1;
    }
    if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
	if (mePtr->labelLength > 0) {
	    const char *label = Tcl_GetString(mePtr->labelPtr);

	    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);
	    textHeight = fmPtr->linespace;
	    haveText = 1;
	}
    }

    /*
     * Now work out what the relative positions are.
     */

    if (haveImage && haveText) {
	int fullWidth = (imageWidth > textWidth ? imageWidth : textWidth);
	switch ((enum compound) mePtr->compound) {
	case COMPOUND_TOP:
	    textXOffset = (fullWidth - textWidth)/2;
	    textYOffset = imageHeight/2 + 2;
	    imageXOffset = (fullWidth - imageWidth)/2;
	    imageYOffset = -textHeight/2;
	    break;
	case COMPOUND_BOTTOM:
	    textXOffset = (fullWidth - textWidth)/2;
	    textYOffset = -imageHeight/2;
	    imageXOffset = (fullWidth - imageWidth)/2;
	    imageYOffset = textHeight/2 + 2;
	    break;
	case COMPOUND_LEFT:
	    /*
	     * The standard image position on Windows is in the indicator
	     * space to the left of the entries, unless this entry is a
	     * radio|check button because then the indicator space will be
	     * used.
	     */

	    textXOffset = imageWidth + 2;
	    textYOffset = 0;
	    imageXOffset = 0;
	    imageYOffset = 0;
	    if ((mePtr->type != CHECK_BUTTON_ENTRY)
		    && (mePtr->type != RADIO_BUTTON_ENTRY)) {
		textXOffset -= indicatorSpace;
		if (textXOffset < 0) {
		    textXOffset = 0;
		}
		imageXOffset = -indicatorSpace;
	    }
	    break;
	case COMPOUND_RIGHT:
	    textXOffset = 0;
	    textYOffset = 0;
	    imageXOffset = textWidth + 2;
	    imageYOffset = 0;
	    break;
	case COMPOUND_CENTER:
	    textXOffset = (fullWidth - textWidth)/2;
	    textYOffset = 0;
	    imageXOffset = (fullWidth - imageWidth)/2;
	    imageYOffset = 0;
	    break;
	case COMPOUND_NONE:
	    break;
	}
    } else {
	textXOffset = 0;
	textYOffset = 0;
	imageXOffset = 0;
	imageYOffset = 0;
    }

    /*
     * Draw label and/or bitmap or image for entry.
     */

    if (mePtr->image != NULL) {
    	if ((mePtr->selectImage != NULL)
	    	&& (mePtr->entryFlags & ENTRY_SELECTED)) {
	    Tk_RedrawImage(mePtr->selectImage, 0, 0,
		    imageWidth, imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));
    	} else {
	    Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
		    imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));
    	}
    } else if (mePtr->bitmapPtr != NULL) {
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
    	XCopyPlane(menuPtr->display, bitmap, d,	gc, 0, 0,
		(unsigned) imageWidth, (unsigned) imageHeight,
		leftEdge + imageXOffset,
		(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);
    }
    if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {
    	if (mePtr->labelLength > 0) {
	    int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
	    const char *label = Tcl_GetString(mePtr->labelPtr);

	    if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) {
		/*
		 * Win 95/98 systems draw disabled menu text with a 3D
		 * highlight, unless the menu item is highlighted,
		 */

		if ((mePtr->state == ENTRY_DISABLED) &&
			((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
		    COLORREF oldFgColor = gc->foreground;
		    gc->foreground = GetSysColor(COLOR_3DHILIGHT);
		    Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,
			    mePtr->labelLength, leftEdge + textXOffset + 1,
			    baseline + textYOffset + 1);
		    gc->foreground = oldFgColor;
		}
	    }
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,
		    mePtr->labelLength, leftEdge + textXOffset,
		    baseline + textYOffset);
	    if (underline) {
		DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr,
			x + textXOffset, y + textYOffset, width, height);
	    }
	}
    }

    if (mePtr->state == ENTRY_DISABLED) {
	if (menuPtr->disabledFgPtr == NULL) {
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
		    (unsigned) width, (unsigned) height);
	} else if ((mePtr->image != NULL)
		&& (menuPtr->disabledImageGC != None)) {
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
		    leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
		    (unsigned) imageWidth, (unsigned) imageHeight);
	}
    }
}

/*
 *--------------------------------------------------------------
 *
 * TkpComputeMenubarGeometry --
 *
 *	This function is invoked to recompute the size and layout of a menu
 *	that is a menubar clone.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Fields of menu entries are changed to reflect their current positions,
 *	and the size of the menu window itself may be changed.
 *
 *--------------------------------------------------------------
 */

void
TkpComputeMenubarGeometry(
    TkMenu *menuPtr)		/* Structure describing menu. */
{
    TkpComputeStandardMenuGeometry(menuPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * DrawTearoffEntry --
 *
 *	This function draws the background part of a menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the menu in its current mode.
 *
 *----------------------------------------------------------------------
 */

void
DrawTearoffEntry(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* The drawable we are drawing into */
    GC gc,			/* The gc we are drawing with */
    Tk_Font tkfont,		/* The font we are drawing with */
    const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */
    int x, int y,
    int width, int height)
{
    XPoint points[2];
    int segmentWidth, maxX;
    Tk_3DBorder border;

    if (menuPtr->menuType != MASTER_MENU) {
	return;
    }

    points[0].x = x;
    points[0].y = y + height/2;
    points[1].y = points[0].y;
    segmentWidth = 6;
    maxX = width - 1;
    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);

    while (points[0].x < maxX) {
	points[1].x = points[0].x + segmentWidth;
	if (points[1].x > maxX) {
	    points[1].x = maxX;
	}
	Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
		TK_RELIEF_RAISED);
	points[0].x += 2*segmentWidth;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpConfigureMenuEntry --
 *
 *	Processes configurations for menu entries.
 *
 * Results:
 *	Returns standard TCL result. If TCL_ERROR is returned, then the
 *	interp's result contains an error message.
 *
 * Side effects:
 *	Configuration information get set for mePtr; old resources get freed,
 *	if any need it.
 *
 *----------------------------------------------------------------------
 */

int
TkpConfigureMenuEntry(
    register TkMenuEntry *mePtr)/* Information about menu entry; may or may
				 * not already have values for some fields. */
{
    TkMenu *menuPtr = mePtr->menuPtr;

    if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
	menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
	Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDrawMenuEntry --
 *
 *	Draws the given menu entry at the given coordinates with the given
 *	attributes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	X Server commands are executed to display the menu entry.
 *
 *----------------------------------------------------------------------
 */

void
TkpDrawMenuEntry(
    TkMenuEntry *mePtr,		/* The entry to draw */
    Drawable menuDrawable,	/* Menu to draw into */
    Tk_Font tkfont,		/* Precalculated font for menu */
    const Tk_FontMetrics *menuMetricsPtr,
				/* Precalculated metrics for menu */
    int x,			/* X-coordinate of topleft of entry */
    int y,			/* Y-coordinate of topleft of entry */
    int width,			/* Width of the entry rectangle */
    int height,			/* Height of the current rectangle */
    int strictMotif,		/* Boolean flag */
    int drawingParameters)	/* Whether or not to draw the cascade arrow
				 * for cascade items and accelerator
				 * cues. Only applies to Windows. */
{
    GC gc, indicatorGC;
    TkMenu *menuPtr = mePtr->menuPtr;
    Tk_3DBorder bgBorder, activeBorder;
    const Tk_FontMetrics *fmPtr;
    Tk_FontMetrics entryMetrics;
    int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
    int adjustedX, adjustedY;
    int adjustedHeight = height - 2 * padY;
    TkWinDrawable memWinDraw;
    TkWinDCState dcState;
    HBITMAP oldBitmap = NULL;
    Drawable d;
    HDC memDc = NULL, menuDc = NULL;

    /*
     * If the menu entry includes an image then draw the entry into a
     * compatible bitmap first.  This avoids problems with clipping on
     * animated menus.  [Bug 1329198]
     */

    if (mePtr->image != NULL) {
	menuDc = TkWinGetDrawableDC(menuPtr->display, menuDrawable, &dcState);

	memDc = CreateCompatibleDC(menuDc);
	oldBitmap = SelectObject(memDc,
    			CreateCompatibleBitmap(menuDc, width, height) );

	memWinDraw.type = TWD_WINDC;
	memWinDraw.winDC.hdc = memDc;
	d = (Drawable)&memWinDraw;
	adjustedX = 0;
	adjustedY = padY;

    } else {
	d = menuDrawable;
	adjustedX = x;
	adjustedY = y + padY;
    }

    /*
     * Choose the gc for drawing the foreground part of the entry.
     */

    if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
	gc = mePtr->activeGC;
	if (gc == NULL) {
	    gc = menuPtr->activeGC;
	}
    } else {
    	TkMenuEntry *cascadeEntryPtr;
    	int parentDisabled = 0;
    	const char *name;

    	for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
    		cascadeEntryPtr != NULL;
    		cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
	    name = Tcl_GetString(cascadeEntryPtr->namePtr);
    	    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
    	    	if (mePtr->state == ENTRY_DISABLED) {
    	    	    parentDisabled = 1;
    	    	}
    	    	break;
    	    }
    	}

	if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))
		&& (menuPtr->disabledFgPtr != NULL)) {
	    gc = mePtr->disabledGC;
	    if (gc == NULL) {
		gc = menuPtr->disabledGC;
	    }
	} else {
	    gc = mePtr->textGC;
	    if (gc == NULL) {
		gc = menuPtr->textGC;
	    }
	}
    }
    indicatorGC = mePtr->indicatorGC;
    if (indicatorGC == NULL) {
	indicatorGC = menuPtr->indicatorGC;
    }

    bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
	    (mePtr->borderPtr == NULL) ? menuPtr->borderPtr
	    : mePtr->borderPtr);
    if (strictMotif) {
	activeBorder = bgBorder;
    } else {
	activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
	    (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr
	    : mePtr->activeBorderPtr);
    }

    if (mePtr->fontPtr == NULL) {
	fmPtr = menuMetricsPtr;
    } else {
	tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
	Tk_GetFontMetrics(tkfont, &entryMetrics);
	fmPtr = &entryMetrics;
    }

    /*
     * Need to draw the entire background, including padding. On Unix, for
     * menubars, we have to draw the rest of the entry taking into account the
     * padding.
     */

    DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,
	    bgBorder, adjustedX, adjustedY-padY, width, height);

    if (mePtr->type == SEPARATOR_ENTRY) {
	DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
		fmPtr, adjustedX, adjustedY, width, adjustedHeight);
    } else if (mePtr->type == TEAROFF_ENTRY) {
	DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr,
		adjustedX, adjustedY, width, adjustedHeight);
    } else {
	DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr,
		adjustedX, adjustedY, width, adjustedHeight,
		(drawingParameters & DRAW_MENU_ENTRY_NOUNDERLINE)?0:1);
	DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
		activeBorder, adjustedX, adjustedY, width, adjustedHeight);
	DrawMenuEntryArrow(menuPtr, mePtr, d, gc,
		activeBorder, adjustedX, adjustedY, width, adjustedHeight,
		(drawingParameters & DRAW_MENU_ENTRY_ARROW)?1:0);
	if (!mePtr->hideMargin) {
	    DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
		    fmPtr, adjustedX, adjustedY, width, adjustedHeight);
	}
    }

    /*
     * Copy the entry contents from the temporary bitmap to the menu.
     */

    if (mePtr->image != NULL) {
	BitBlt(menuDc, x, y, width, height, memDc, 0, 0, SRCCOPY);
	DeleteObject(SelectObject(memDc, oldBitmap));
	DeleteDC(memDc);

	TkWinReleaseDrawableDC(menuDrawable, menuDc, &dcState);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GetMenuLabelGeometry --
 *
 *	Figures out the size of the label portion of a menu item.
 *
 * Results:
 *	widthPtr and heightPtr are filled in with the correct geometry
 *	information.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
GetMenuLabelGeometry(
    TkMenuEntry *mePtr,		/* The entry we are computing */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated metrics */
    int *widthPtr,		/* The resulting width of the label portion */
    int *heightPtr)		/* The resulting height of the label
				 * portion */
{
    TkMenu *menuPtr = mePtr->menuPtr;
    int haveImage = 0;

    if (mePtr->image != NULL) {
    	Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
	haveImage = 1;
    } else if (mePtr->bitmapPtr != NULL) {
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
    	Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
	haveImage = 1;
    } else {
	*heightPtr = 0;
	*widthPtr = 0;
    }

    if (haveImage && (mePtr->compound == COMPOUND_NONE)) {
	/*
	 * We don't care about the text in this case.
	 */
    } else {
	/*
	 * Either it is compound or we don't have an image,
	 */

    	if (mePtr->labelPtr != NULL) {
	    int textWidth;
	    const char *label = Tcl_GetString(mePtr->labelPtr);

	    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);

	    if ((mePtr->compound != COMPOUND_NONE) && haveImage) {
		switch ((enum compound) mePtr->compound) {
		case COMPOUND_TOP:
		case COMPOUND_BOTTOM:
		    if (textWidth > *widthPtr) {
			*widthPtr = textWidth;
		    }

		    /*
		     * Add text and padding.
		     */

		    *heightPtr += fmPtr->linespace + 2;
		    break;
		case COMPOUND_LEFT:
		case COMPOUND_RIGHT:
		    if (fmPtr->linespace > *heightPtr) {
			*heightPtr = fmPtr->linespace;
		    }

		    /*
		     * Add text and padding.
		     */

		    *widthPtr += textWidth + 2;
		    break;
		case COMPOUND_CENTER:
		    if (fmPtr->linespace > *heightPtr) {
			*heightPtr = fmPtr->linespace;
		    }
		    if (textWidth > *widthPtr) {
			*widthPtr = textWidth;
		    }
		    break;
		case COMPOUND_NONE:
		    break;
		}
	    } else {
		/*
		 * We don't have an image or we're not compound.
		 */

		*heightPtr = fmPtr->linespace;
		*widthPtr = textWidth;
	    }
	} else {
	    /*
	     * An empty entry still has this height.
	     */

	    *heightPtr = fmPtr->linespace;
    	}
    }
    *heightPtr += 1;
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryBackground --
 *
 *	This function draws the background part of a menu.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the menu in its current mode.
 *
 *----------------------------------------------------------------------
 */

static void
DrawMenuEntryBackground(
    TkMenu *menuPtr,		/* The menu we are drawing. */
    TkMenuEntry *mePtr,		/* The entry we are drawing. */
    Drawable d,			/* What we are drawing into */
    Tk_3DBorder activeBorder,	/* Border for active items */
    Tk_3DBorder bgBorder,	/* Border for the background */
    int x,			/* left edge */
    int y,			/* top edge */
    int width,			/* width of rectangle to draw */
    int height)			/* height of rectangle to draw */
{
    if (mePtr->state == ENTRY_ACTIVE
		|| (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)!=0 ) {
	bgBorder = activeBorder;
    }
    Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height, 0,
	    TK_RELIEF_FLAT);
}

/*
 *--------------------------------------------------------------
 *
 * TkpComputeStandardMenuGeometry --
 *
 *	This function is invoked to recompute the size and layout of a menu
 *	that is not a menubar clone.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Fields of menu entries are changed to reflect their current positions,
 *	and the size of the menu window itself may be changed.
 *
 *--------------------------------------------------------------
 */

void
TkpComputeStandardMenuGeometry(
    TkMenu *menuPtr)		/* Structure describing menu. */
{
    Tk_Font menuFont, tkfont;
    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
    int x, y, height, width, indicatorSpace, labelWidth, accelWidth;
    int windowWidth, windowHeight, accelSpace;
    int i, j, lastColumnBreak = 0;
    int activeBorderWidth, borderWidth;

    if (menuPtr->tkwin == NULL) {
	return;
    }

    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
	    menuPtr->borderWidthPtr, &borderWidth);
    x = y = borderWidth;
    indicatorSpace = labelWidth = accelWidth = 0;
    windowHeight = 0;

    /*
     * On the Mac especially, getting font metrics can be quite slow, so we
     * want to do it intelligently. We are going to precalculate them and pass
     * them down to all of the measuring and drawing routines. We will measure
     * the font metrics of the menu once. If an entry does not have its own
     * font set, then we give the geometry/drawing routines the menu's font
     * and metrics. If an entry has its own font, we will measure that font
     * and give all of the geometry/drawing the entry's font and metrics.
     */

    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
    Tk_GetFontMetrics(menuFont, &menuMetrics);
    accelSpace = Tk_TextWidth(menuFont, "M", 1);
    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
	    menuPtr->activeBorderWidthPtr, &activeBorderWidth);

    for (i = 0; i < menuPtr->numEntries; i++) {
	if (menuPtr->entries[i]->fontPtr == NULL) {
	    tkfont = menuFont;
	    fmPtr = &menuMetrics;
	} else {
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
		    menuPtr->entries[i]->fontPtr);
    	    Tk_GetFontMetrics(tkfont, &entryMetrics);
    	    fmPtr = &entryMetrics;
    	}
	if ((i > 0) && menuPtr->entries[i]->columnBreak) {
	    if (accelWidth != 0) {
		labelWidth += accelSpace;
	    }
	    for (j = lastColumnBreak; j < i; j++) {
		menuPtr->entries[j]->indicatorSpace = indicatorSpace;
		menuPtr->entries[j]->labelWidth = labelWidth;
		menuPtr->entries[j]->width = indicatorSpace + labelWidth
			+ accelWidth + 2 * activeBorderWidth;
		menuPtr->entries[j]->x = x;
		menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;
	    }
	    x += indicatorSpace + labelWidth + accelWidth
		    + 2 * borderWidth;
	    indicatorSpace = labelWidth = accelWidth = 0;
	    lastColumnBreak = i;
	    y = borderWidth;
	}

	if (menuPtr->entries[i]->type == SEPARATOR_ENTRY) {
	    GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
	    	    fmPtr, &width, &height);
	    menuPtr->entries[i]->height = height;
	} else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {
	    GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,
	    	    fmPtr, &width, &height);
	    menuPtr->entries[i]->height = height;

	} else {
	    /*
	     * For each entry, compute the height required by that particular
	     * entry, plus three widths: the width of the label, the width to
	     * allow for an indicator to be displayed to the left of the label
	     * (if any), and the width of the accelerator to be displayed to
	     * the right of the label (if any). These sizes depend, of course,
	     * on the type of the entry.
	     */

	    GetMenuLabelGeometry(menuPtr->entries[i], tkfont, fmPtr, &width,
	    	    &height);
	    menuPtr->entries[i]->height = height;
	    if (width > labelWidth) {
	    	labelWidth = width;
	    }

	    GetMenuAccelGeometry(menuPtr, menuPtr->entries[i], tkfont,
		    fmPtr, &width, &height);
	    if (height > menuPtr->entries[i]->height) {
	    	menuPtr->entries[i]->height = height;
	    }
	    if (width > accelWidth) {
	    	accelWidth = width;
	    }

	    GetMenuIndicatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
	    	    fmPtr, &width, &height);
	    if (height > menuPtr->entries[i]->height) {
	    	menuPtr->entries[i]->height = height;
	    }
	    if (width > indicatorSpace) {
	    	indicatorSpace = width;
	    }

	    menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;
    	}
	menuPtr->entries[i]->y = y;
	y += menuPtr->entries[i]->height;
	if (y > windowHeight) {
	    windowHeight = y;
	}
    }

    if (accelWidth != 0) {
	labelWidth += accelSpace;
    }
    for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
	menuPtr->entries[j]->indicatorSpace = indicatorSpace;
	menuPtr->entries[j]->labelWidth = labelWidth;
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
    windowWidth = x + indicatorSpace + labelWidth + accelWidth + accelSpace
	    + 2 * activeBorderWidth + 2 * borderWidth;


    windowHeight += borderWidth;

    /*
     * The X server doesn't like zero dimensions, so round up to at least 1 (a
     * zero-sized menu should never really occur, anyway).
     */

    if (windowWidth <= 0) {
	windowWidth = 1;
    }
    if (windowHeight <= 0) {
	windowHeight = 1;
    }
    menuPtr->totalWidth = windowWidth;
    menuPtr->totalHeight = windowHeight;
}

/*
 *----------------------------------------------------------------------
 *
 * MenuSelectEvent --
 *
 *	Generates a "MenuSelect" virtual event. This can be used to do
 *	context-sensitive menu help.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Places a virtual event on the event queue.
 *
 *----------------------------------------------------------------------
 */

static void
MenuSelectEvent(
    TkMenu *menuPtr)		/* the menu we have selected. */
{
    XVirtualEvent event;
    union {DWORD msgpos; POINTS point;} root;

    event.type = VirtualEvent;
    event.serial = menuPtr->display->request;
    event.send_event = 0;
    event.display = menuPtr->display;
    Tk_MakeWindowExist(menuPtr->tkwin);
    event.event = Tk_WindowId(menuPtr->tkwin);
    event.root = XRootWindow(menuPtr->display, 0);
    event.subwindow = None;
    event.time = TkpGetMS();

    root.msgpos = GetMessagePos();
    event.x_root = root.point.x;
    event.y_root = root.point.y;
    event.state = TkWinGetModifierState();
    event.same_screen = 1;
    event.name = Tk_GetUid("MenuSelect");
    event.user_data = NULL;
    Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuNotifyToplevelCreate --
 *
 *	This routine reconfigures the menu and the clones indicated by
 *	menuName becuase a toplevel has been created and any system menus need
 *	to be created.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	An idle handler is set up to do the reconfiguration.
 *
 *----------------------------------------------------------------------
 */

void
TkpMenuNotifyToplevelCreate(
    Tcl_Interp *interp,		/* The interp the menu lives in. */
    const char *menuName)	/* The name of the menu to reconfigure. */
{
    TkMenuReferences *menuRefPtr;
    TkMenu *menuPtr;

    if ((menuName != NULL) && (menuName[0] != '\0')) {
	menuRefPtr = TkFindMenuReferences(interp, menuName);
	if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {
	    for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
		    menuPtr = menuPtr->nextInstancePtr) {
		if ((menuPtr->menuType == MENUBAR)
			&& !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
		    menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
		    Tcl_DoWhenIdle(ReconfigureWindowsMenu,
			    (ClientData) menuPtr);
		}
	    }
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_GetMenuHWND --
 *
 *	This function returns the HWND of a hidden menu Window that processes
 *	messages of a popup menu. This hidden menu window is used to handle
 *	either a dynamic popup menu in the same process or a pull-down menu of
 *	an embedded window in a different process.
 *
 * Results:
 *	Returns the HWND of the hidden menu Window.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

HWND
Tk_GetMenuHWND(
    Tk_Window tkwin)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    TkMenuInit();
    return tsdPtr->embeddedMenuHWND;
}

/*
 *----------------------------------------------------------------------
 *
 * MenuExitHandler --
 *
 *	Unregisters the class of utility windows.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Menus have to be reinitialized next time.
 *
 *----------------------------------------------------------------------
 */

static void
MenuExitHandler(
    ClientData clientData)	    /* Not used */
{
    UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
    UnregisterClass(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());
}

/*
 *----------------------------------------------------------------------
 *
 * MenuExitHandler --
 *
 *	Throws away the utility window needed for menus and delete hash
 *	tables.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Menus have to be reinitialized next time.
 *
 *----------------------------------------------------------------------
 */

static void
MenuThreadExitHandler(
    ClientData clientData)	    /* Not used */
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    DestroyWindow(tsdPtr->menuHWND);
    DestroyWindow(tsdPtr->embeddedMenuHWND);
    tsdPtr->menuHWND = NULL;
    tsdPtr->embeddedMenuHWND = NULL;

    Tcl_DeleteHashTable(&tsdPtr->winMenuTable);
    Tcl_DeleteHashTable(&tsdPtr->commandTable);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinGetMenuSystemDefault --
 *
 *	Gets the Windows specific default value for a given X resource
 *	database name.
 *
 * Results:
 *	Returns a Tcl_Obj* with the default value. If there is no
 *	Windows-specific default for this attribute, returns NULL. This object
 *	has a ref count of 0.
 *
 * Side effects:
 *	Storage is allocated.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TkWinGetMenuSystemDefault(
    Tk_Window tkwin,		/* A window to use. */
    const char *dbName,		/* The option database name. */
    const char *className)	/* The name of the option class. */
{
    Tcl_Obj *valuePtr = NULL;

    if ((strcmp(dbName, "activeBorderWidth") == 0) ||
	    (strcmp(dbName, "borderWidth") == 0)) {
	valuePtr = Tcl_NewIntObj(defaultBorderWidth);
    } else if (strcmp(dbName, "font") == 0) {
	valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString), -1);
    }

    return valuePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * SetDefaults --
 *
 *	Read system menu settings (font, sizes of items, use of accelerators)
 *	This is called if the UI theme or settings are changed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May result in menu items being redrawn with different appearance.
 *
 *----------------------------------------------------------------------
 */

static void
SetDefaults(
    int firstTime)		/* Is this the first time this has been
				 * called? */
{
    char sizeString[TCL_INTEGER_SPACE];
    char faceName[LF_FACESIZE];
    HDC scratchDC;
    int bold = 0;
    int italic = 0;
    TEXTMETRICA tm;
    int pointSize;
    HFONT menuFont;
    NONCLIENTMETRICSA ncMetrics;

    /*
     * Set all of the default options. The loop will terminate when we run out
     * of options via a break statement.
     */

    defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);
    if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {
	defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
    }

    scratchDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
    if (!firstTime) {
	Tcl_DStringFree(&menuFontDString);
    }
    Tcl_DStringInit(&menuFontDString);

    ncMetrics.cbSize = sizeof(ncMetrics);
    SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
	    &ncMetrics, 0);
    menuFont = CreateFontIndirectA(&ncMetrics.lfMenuFont);
    SelectObject(scratchDC, menuFont);
    GetTextMetricsA(scratchDC, &tm);
    GetTextFaceA(scratchDC, LF_FACESIZE, faceName);
    pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
	    72, GetDeviceCaps(scratchDC, LOGPIXELSY));
    if (tm.tmWeight >= 700) {
	bold = 1;
    }
    if (tm.tmItalic) {
	italic = 1;
    }

    SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
    DeleteDC(scratchDC);

    DeleteObject(menuFont);

    Tcl_DStringAppendElement(&menuFontDString, faceName);
    sprintf(sizeString, "%d", pointSize);
    Tcl_DStringAppendElement(&menuFontDString, sizeString);

    if (bold || italic) {
	Tcl_DString boldItalicDString;

	Tcl_DStringInit(&boldItalicDString);
	if (bold) {
	    Tcl_DStringAppendElement(&boldItalicDString, "bold");
	}
	if (italic) {
	    Tcl_DStringAppendElement(&boldItalicDString, "italic");
	}
	Tcl_DStringAppendElement(&menuFontDString,
		Tcl_DStringValue(&boldItalicDString));
	Tcl_DStringFree(&boldItalicDString);
    }

    /*
     * Now we go ahead and get the dimensions of the check mark and the
     * appropriate margins. Since this is fairly hairy, we do it here to save
     * time when traversing large sets of menu items.
     *
     * The code below was given to me by Microsoft over the phone. It is the
     * only way to ensure menu items line up, and is not documented.
     */

    indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK);
    indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) +
	    GetSystemMetrics(SM_CXBORDER)
	    + GetSystemMetrics(SM_CXMENUCHECK) + 7) & 0xFFF8)
	    - GetSystemMetrics(SM_CXFIXEDFRAME);

    /*
     * Accelerators used to be always underlines until Win2K when a system
     * parameter was introduced to hide them unless Alt is pressed.
     */

    showMenuAccelerators = TRUE;
    if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
	SystemParametersInfoA(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuInit --
 *
 *	Sets up the process-wide variables used by the menu package.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	lastMenuID gets initialized.
 *
 *----------------------------------------------------------------------
 */

void
TkpMenuInit(void)
{
    WNDCLASS wndClass;

    wndClass.style = CS_OWNDC;
    wndClass.lpfnWndProc = TkWinMenuProc;
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hInstance = Tk_GetHINSTANCE();
    wndClass.hIcon = NULL;
    wndClass.hCursor = NULL;
    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName = MENU_CLASS_NAME;
    if (!RegisterClass(&wndClass)) {
	Tcl_Panic("Failed to register menu window class");
    }

    wndClass.lpfnWndProc = TkWinEmbeddedMenuProc;
    wndClass.lpszClassName = EMBEDDED_MENU_CLASS_NAME;
    if (!RegisterClass(&wndClass)) {
	Tcl_Panic("Failed to register embedded menu window class");
    }

    TkCreateExitHandler(MenuExitHandler, (ClientData) NULL);
    SetDefaults(1);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuThreadInit --
 *
 *	Sets up the thread-local hash tables used by the menu module. Assumes
 *	that TkpMenuInit has been called.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Hash tables winMenuTable and commandTable are initialized.
 *
 *----------------------------------------------------------------------
 */

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

    tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, TEXT("MenuWindow"), WS_POPUP,
	    0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    if (!tsdPtr->menuHWND) {
	Tcl_Panic("Failed to create the menu window");
    }

    tsdPtr->embeddedMenuHWND =
	    CreateWindow(EMBEDDED_MENU_CLASS_NAME, TEXT("EmbeddedMenuWindow"),
	    WS_POPUP, 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    if (!tsdPtr->embeddedMenuHWND) {
	Tcl_Panic("Failed to create the embedded menu window");
    }

    Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);

    TkCreateThreadExitHandler(MenuThreadExitHandler, (ClientData) NULL);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
@


1.78
log
@[FRQ 2965056]: Windows build with -DUNICODE
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.77 2010/10/11 13:33:30 nijtmans Exp $
d1303 1
a1303 1
			Tcl_Panic("Trying to activate an entry which doesn't exist.");
d3308 1
a3308 1
	Tcl_Panic("Failed to register menu window class.");
d3314 1
a3314 1
	Tcl_Panic("Failed to register embedded menu window class.");
d3348 1
a3348 1
	Tcl_Panic("Failed to create the menu window.");
d3356 1
a3356 1
	Tcl_Panic("Failed to create the embedded menu window.");
@


1.77
log
@[FRQ 2965056]: Windows build with -DUNICODE
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.76 2010/10/06 14:33:29 nijtmans Exp $
d3259 5
a3263 11
    if (TkWinGetPlatformId() >= VER_PLATFORM_WIN32_WINDOWS) {
	indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK);
	indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) +
		GetSystemMetrics(SM_CXBORDER)
		+ GetSystemMetrics(SM_CXMENUCHECK) + 7) & 0xFFF8)
		- GetSystemMetrics(SM_CXFIXEDFRAME);
    } else {
	DWORD dimensions = GetMenuCheckMarkDimensions();
	indicatorDimensions[0] = HIWORD(dimensions);
	indicatorDimensions[1] = LOWORD(dimensions);
    }
@


1.76
log
@ [FRQ 2965056]: Windows build with -DUNICODE
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.75 2010/09/13 08:11:59 nijtmans Exp $
d701 1
a701 2
	    tkWinProcs->insertMenu(winMenuHdl, 0xFFFFFFFF, flags,
		    itemID, lpNewItem);
d971 1
a971 1
	if (wParam == SPI_SETNONCLIENTMETRICS 
@


1.75
log
@Move definitions of WINVER/_WIN32_WINNT to one place, now that we only support Win2000+
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.74 2010/09/10 08:59:25 nijtmans Exp $
a15 6
/* TODO: This file does not compile in UNICODE mode.
 * See [Freq 2965056]: Windows build with -DUNICODE
 */
#undef UNICODE
#undef _UNICODE

d24 2
a25 2
#define MENU_CLASS_NAME			"MenuWindowClass"
#define EMBEDDED_MENU_CLASS_NAME	"EmbeddedMenuWindowClass"
d160 1
a160 1
static TCHAR *		GetEntryText(TkMenuEntry *mePtr);
d551 1
a551 1
    TCHAR *itemText = NULL;
d589 1
a589 1
	    lpNewItem = Tcl_DStringValue(&translatedText);
d894 1
a894 1
	lResult = DefWindowProc(hwnd, message, wParam, lParam);
d992 1
a992 1
	lResult = DefWindowProc(hwnd, message, wParam, lParam);
d1623 1
a1623 1
    GetObject(bitmap, sizeof(BITMAP), &bm);
d2023 2
a2024 2
	    scanCode = MapVirtualKey(VK_LMENU, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2029 2
a2030 2
	    scanCode = MapVirtualKey(VK_RMENU, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2035 2
a2036 2
	    scanCode = MapVirtualKey(VK_F10, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2041 1
a2041 1
	    scanCode = MapVirtualKey(virtualKey, 0);
d2044 1
a2044 1
		CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2049 1
a2049 1
			CallWindowProc(DefWindowProc,
d2060 2
a2061 2
	    scanCode = MapVirtualKey(VK_LMENU, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2066 2
a2067 2
	    scanCode = MapVirtualKey(VK_RMENU, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2072 2
a2073 2
	    scanCode = MapVirtualKey(VK_F10, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d2079 1
a2079 1
	    scanCode = MapVirtualKey(virtualKey, 0);
d2081 1
a2081 1
		CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
d3190 1
a3190 1
    TEXTMETRIC tm;
d3193 1
a3193 1
    NONCLIENTMETRICS ncMetrics;
d3205 1
a3205 1
    scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
d3212 1
a3212 1
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
d3214 1
a3214 1
    menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
d3216 2
a3217 2
    GetTextMetrics(scratchDC, &tm);
    GetTextFace(scratchDC, LF_FACESIZE, faceName);
d3279 1
a3279 1
	SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0);
d3351 1
a3351 1
    tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
d3359 1
a3359 1
	    CreateWindow(EMBEDDED_MENU_CLASS_NAME, "EmbeddedMenuWindow",
@


1.74
log
@Make compilable with -DUNICODE, or mark files with a TODO which are not done yet.
tkWinPort.h:  mingw/cygwin fixes: <tchar.h> should always be included here.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.73 2010/05/10 20:58:18 nijtmans Exp $
a21 2
#define WINVER        0x0500   /* Requires Windows 2K definitions */
#define _WIN32_WINNT  0x0500
@


1.73
log
@CONSTify TkCopyAndGlobalEval, TkpSetMainMenubar,
TkpMenuNotifyToplevelCreate, and TkSetWindowMenuBar
Bring Tk_CreateBinding doc and signature (param name) in line.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.72 2010/01/22 14:17:53 nijtmans Exp $
d16 6
@


1.72
log
@fix more gcc warnings: missing initializer
Eliminate use of __argc and __argv for CYGWIN
Make cygwin configuration error into
 a warning: CYGWIN compilation works
although there still are test failures.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.71 2010/01/03 19:50:59 patthoyts Exp $
d1434 1
a1434 1
    char *menuName)		/* The name of the menu to put in front. If
d3021 1
a3021 1
    char *menuName)		/* The name of the menu to reconfigure. */
@


1.71
log
@Patch 2848897: Support the system keyboard cues setting on Windows

This patch by Anton Kovalenko adds support for the Windows system-wide
UI setting that prevents accelerators being underlined unless the Alt
key is pressed.

Modified to support the system keyboard cues flag and to handle dynamic
changes to the system parameters by the user.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.70 2009/12/27 23:36:25 patthoyts Exp $
a21 2
#include <string.h>

@


1.70
log
@Highlight for cascade items in torn-off menus is incorrect on Windows.
Applied patch from [Bug 2879927].
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.69 2009/09/14 23:41:42 hobbs Exp $
d16 2
d55 28
d92 2
d147 1
a147 1
			    int width, int height);
d975 7
d1207 1
a1207 1
	int drawArrow = 0;
d1212 3
d1243 2
a1244 2
		 * Also, set the drawArrow flag for a disabled cascade menu
		 * since we need to draw the arrow ourselves.
d1248 1
a1248 1
		    drawArrow = 1;
d1257 2
a1258 1
		    itemPtr->rcItem.bottom - itemPtr->rcItem.top, 0,drawArrow);
d2186 2
a2187 1
    int height)			/* height of entry */
d2332 4
a2335 2
	    DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr,
		    x + textXOffset, y + textYOffset, width, height);
d2492 3
a2494 3
    int drawArrow)		/* Whether or not to draw the cascade arrow
				 * for cascade items. Only applies to
				 * Windows. */
d2615 2
a2616 1
		adjustedX, adjustedY, width, adjustedHeight);
d2621 1
a2621 1
		drawArrow);
d3170 1
a3170 1
 * TkWinMenuSetDefaults --
d3172 2
a3173 1
 *	Sets up the hash tables and the variables used by the menu package.
d3179 1
a3179 2
 *	lastMenuID gets initialized, and the parent hash and the command hash
 *	are allocated.
d3184 1
a3184 1
void
d3275 10
@


1.69
log
@	* generic/tkMenuDraw.c (TkPostSubmenu): Fix reposting of submenu in
	* win/tkWinMenu.c (TkWinHandleMenuEvent): torn off Windows menu.
	[Bug 873613]
	(DrawMenuEntryArrow): Draw Win menu arrow after being torn
	off. [Bug 873608]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.68 2009/08/02 21:40:17 nijtmans Exp $
d1815 4
a1818 2
    gc->foreground = GetSysColor((mePtr->state == ENTRY_DISABLED) ?
	    COLOR_GRAYTEXT : COLOR_MENUTEXT);
@


1.68
log
@eliminate various gcc and msvc compiler warnings
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.67 2009/05/21 22:52:06 patthoyts Exp $
d53 4
d999 13
d1796 1
a1796 2
    if (!drawArrow || (mePtr->type != CASCADE_ENTRY)
	    || (mePtr->state != ENTRY_DISABLED)) {
d1815 2
a1816 1
    gc->foreground = GetSysColor(COLOR_GRAYTEXT);
@


1.67
log
@[Bug 2794778]: Calls to CallWindowProc can lead to other functions
overwriting the event strucure. Therefore preserve a local copy of the
XKeyEvent while looping over the key events.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.66 2009/03/25 23:39:35 nijtmans Exp $
d2914 1
a2914 2
    POINTS rootPoint;
    DWORD msgPos;
d2926 3
a2928 4
    msgPos = GetMessagePos();
    rootPoint = MAKEPOINTS(msgPos);
    event.x_root = rootPoint.x;
    event.y_root = rootPoint.y;
@


1.66
log
@Eliminate a few compiler warnings on mingw
spacing
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.65 2009/03/01 21:54:40 patthoyts Exp $
d1985 1
d1989 2
a1990 2
		if (eventPtr->xkey.nbytes > 0) {
		    for (i = 0; i < eventPtr->xkey.nbytes; i++) {
d1993 1
a1993 1
				eventPtr->xkey.trans_chars[i],
@


1.65
log
@update comment to reflect reality
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.64 2009/02/23 10:18:38 patthoyts Exp $
d2440 1
a2440 1
    HBITMAP oldBitmap;
d2442 1
a2442 1
    HDC memDc, menuDc;
d2560 1
a2560 1
    
@


1.64
log
@[Patch 2507419] fixes the image drawing bug on windows menus.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.63 2009/01/28 20:47:49 nijtmans Exp $
d1748 2
a1749 1
 *	entry. This function is currently unused.
@


1.63
log
@- eliminate some unnessary type casts
- some internal const decorations
- spacing
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.62 2008/12/09 21:22:56 dgp Exp $
a37 3
#ifndef TPM_NOANIMATION
#define TPM_NOANIMATION 0x4000L
#endif
d715 1
a715 1
    int i, result, flags;
a719 1
    TkMenuEntry *mePtr;
a781 12
    /*
     * Disable menu animation if an image is present, as clipping isn't
     * handled correctly with temp DCs.  [Bug 1329198]
     */
    for (i = 0; i < menuPtr->numEntries; i++) {
	mePtr = menuPtr->entries[i];
	if (mePtr->image != NULL) {
	    flags |= TPM_NOANIMATION;
	    break;
	}
    }

d2416 1
a2416 1
    Drawable d,			/* What to draw into */
d2435 1
a2435 1
    int adjustedY = y + padY;
d2437 30
d2538 1
a2538 1
	    bgBorder, x, y, width, height);
d2542 1
a2542 1
		fmPtr, x, adjustedY, width, adjustedHeight);
d2544 2
a2545 2
	DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
		width, adjustedHeight);
d2547 2
a2548 2
	DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
		width, adjustedHeight);
d2550 1
a2550 1
		activeBorder, x, adjustedY, width, adjustedHeight);
d2552 2
a2553 1
		activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
d2556 1
a2556 1
		    fmPtr, x, adjustedY, width, adjustedHeight);
d2559 12
@


1.62
log
@        TIP 337

        * generic/tkBind.c:     Updated callers of Tcl_BackgroundError()
        * generic/tkCanvas.c:   to use the new routine
        * generic/tkEntry.c:    Tcl_BackgroundException() as appropriate.
        * generic/tkImgBmap.c:
        * generic/tkListbox.c:
        * generic/tkSelect.c:
        * generic/tkTextDisp.c:
        * generic/tkTextWind.c:
        * macosx/tkMacOSXHLEvents.c:
        * macosx/tkMacOSXMenu.c:
        * macosx/tkMacOSXMenus.c:
        * macosx/tkMacOSXScale.c:
        * macosx/tkMacOSXWindowEvent.c:
        * unix/tkUnixScale.c:
        * unix/tkUnixWm.c:
        * win/tkWinButton.c:
        * win/tkWinMenu.c:
        * win/tkWinScrlbr.c:
        * win/tkWinWm.c:
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.61 2008/11/08 18:44:40 dkf Exp $
d205 1
a205 1
	    Tcl_SetHashValue(commandEntryPtr, (char *) mePtr);
d295 1
a295 1
    Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
d322 1
a322 1
    char *searchName;
d1076 1
a1076 1
		    char *name = Tcl_GetString(parentEntryPtr->namePtr);
d1359 1
a1359 1
	Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
d1468 1
a1468 1
	char *accel = Tcl_GetString(mePtr->accelPtr);
d1724 1
a1724 1
    char *accel;
d2167 1
a2167 1
	    char *label = Tcl_GetString(mePtr->labelPtr);
d2262 1
a2262 1
	    char *label = Tcl_GetString(mePtr->labelPtr);
d2466 1
a2466 1
	char *name;
d2598 1
a2598 1
	    char *label = Tcl_GetString(mePtr->labelPtr);
@


1.61
log
@Lots of small changes to make code more pretty and C89-like.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.60 2008/10/17 23:18:38 nijtmans Exp $
d1035 1
a1035 1
		    Tcl_BackgroundError(interp);
d1094 1
a1094 1
		Tcl_BackgroundError(interp);
@


1.60
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
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59 2007/12/13 15:28:56 dgp Exp $
d672 1
a672 1
	    (*tkWinProcs->insertMenu)(winMenuHdl, 0xFFFFFFFF, flags,
@


1.59
log
@merge stable branch onto HEAD
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.56.2.2 2007/09/09 04:15:55 dgp Exp $
d455 1
a455 1
	char *label = (mePtr->labelPtr == NULL) ? ""
d457 1
a457 1
	char *accel = (mePtr->accelPtr == NULL) ? ""
@


1.59.2.1
log
@[Patch 2507419] fix menu image display issue on windows
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59 2007/12/13 15:28:56 dgp Exp $
d38 3
d718 1
a718 1
    int result, flags;
d723 1
d786 12
d2432 1
a2432 1
    Drawable menuDrawable,	/* Menu to draw into */
d2451 1
a2451 1
    int adjustedX, adjustedY;
a2452 30
    TkWinDrawable memWinDraw;
    TkWinDCState dcState;
    HBITMAP oldBitmap;
    Drawable d;
    HDC memDc, menuDc;

    /*
     * If the menu entry includes an image then draw the entry into a
     * compatible bitmap first.  This avoids problems with clipping on
     * animated menus.  [Bug 1329198]
     */

    if (mePtr->image != NULL) {
	menuDc = TkWinGetDrawableDC(menuPtr->display, menuDrawable, &dcState);

	memDc = CreateCompatibleDC(menuDc);
	oldBitmap = SelectObject(memDc,
    			CreateCompatibleBitmap(menuDc, width, height) );

	memWinDraw.type = TWD_WINDC;
	memWinDraw.winDC.hdc = memDc;
	d = (Drawable)&memWinDraw;
	adjustedX = 0;
	adjustedY = padY;

    } else {
	d = menuDrawable;
	adjustedX = x;
	adjustedY = y + padY;
    }
d2524 1
a2524 1
	    bgBorder, adjustedX, adjustedY-padY, width, height);
d2528 1
a2528 1
		fmPtr, adjustedX, adjustedY, width, adjustedHeight);
d2530 2
a2531 2
	DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr,
		adjustedX, adjustedY, width, adjustedHeight);
d2533 2
a2534 2
	DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr,
		adjustedX, adjustedY, width, adjustedHeight);
d2536 1
a2536 1
		activeBorder, adjustedX, adjustedY, width, adjustedHeight);
d2538 1
a2538 2
		activeBorder, adjustedX, adjustedY, width, adjustedHeight,
		drawArrow);
d2541 1
a2541 1
		    fmPtr, adjustedX, adjustedY, width, adjustedHeight);
a2543 12
    
    /*
     * Copy the entry contents from the temporary bitmap to the menu.
     */

    if (mePtr->image != NULL) {
	BitBlt(menuDc, x, y, width, height, memDc, 0, 0, SRCCOPY);
	DeleteObject(SelectObject(memDc, oldBitmap));
	DeleteDC(memDc);

	TkWinReleaseDrawableDC(menuDrawable, menuDc, &dcState);
    }
@


1.59.2.2
log
@[Bug 2794778]: backported fix for keyboard transversal of the menus on Windows.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59.2.1 2009/02/23 10:37:38 patthoyts Exp $
a1983 1
		XKeyEvent xkey = eventPtr->xkey;
d1987 2
a1988 2
		if (xkey.nbytes > 0) {
		    for (i = 0; i < xkey.nbytes; i++) {
d1991 1
a1991 1
				xkey.trans_chars[i],
@


1.59.2.3
log
@	* generic/tkMenuDraw.c (TkPostSubmenu): Fix reposting of submenu in
	* win/tkWinMenu.c (TkWinHandleMenuEvent): torn off Windows menu.
	[Bug 873613]
	(DrawMenuEntryArrow): Draw Win menu arrow after being torn
	off. [Bug 873608]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59.2.2 2009/05/21 23:01:33 patthoyts Exp $
a52 4
#ifndef WM_UNINITMENUPOPUP
#define WM_UNINITMENUPOPUP              0x0125
#endif

a994 13
    case WM_UNINITMENUPOPUP:
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *pwParam);
	if (hashEntryPtr != NULL) {
	    menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
	    if ((menuPtr->menuRefPtr != NULL)
		    && (menuPtr->menuRefPtr->parentEntryPtr != NULL)) {
		TkPostSubmenu(menuPtr->interp,
			menuPtr->menuRefPtr->parentEntryPtr->menuPtr, NULL);
	    }
	}
	break;

d1778 2
a1779 1
    if (!drawArrow || (mePtr->type != CASCADE_ENTRY)) {
d1798 1
a1798 2
    gc->foreground = GetSysColor((mePtr->state == ENTRY_DISABLED) ?
	    COLOR_GRAYTEXT : COLOR_MENUTEXT);
@


1.59.2.4
log
@Highlight for cascade items in torn-off menus is incorrect on Windows.
Applied patch from [Bug 2879927].
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59.2.3 2009/09/14 23:40:42 hobbs Exp $
d1765 1
a1765 2
 *	entry. This function is only used when drawing the arrow for a
 *	disabled cascade menu.
d1814 2
a1815 4
    gc->foreground = GetSysColor((mePtr->state == ENTRY_DISABLED)
	? COLOR_GRAYTEXT
		: ((mePtr->state == ENTRY_ACTIVE)
		? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));
@


1.59.2.5
log
@Patch 2848897: Support the system keyboard cues setting on Windows
Backported this patch from HEAD (kovalenko, thoyts)
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59.2.4 2009/12/27 23:42:45 patthoyts Exp $
a15 2
#define WINVER        0x0500   /* Requires Windows 2K definitions */
#define _WIN32_WINNT  0x0500
a52 28
/*
 * ODS_NOACCEL flag forbids drawing accelerator cues (i.e. underlining labels)
 * on Windows 2000 and above.  The ODS_NOACCEL define is missing from mingw32
 * headers and undefined for _WIN32_WINNT < 0x0500 in Microsoft SDK.  We might
 * check for _WIN32_WINNT here, but I think it's not needed, as checking for
 * this flag does no harm on even on NT: reserved bits should be zero, and in
 * fact they are.
 */

#ifndef ODS_NOACCEL
#define ODS_NOACCEL 0x100
#endif
#ifndef SPI_GETKEYBOARDCUES
#define SPI_GETKEYBOARDCUES             0x100A
#endif
#ifndef WM_UPDATEUISTATE
#define WM_UPDATEUISTATE                0x0128
#endif
#ifndef UIS_SET
#define UIS_SET                         1
#endif
#ifndef UIS_CLEAR
#define UIS_CLEAR                       2
#endif
#ifndef UISF_HIDEACCEL
#define UISF_HIDEACCEL                  2
#endif

a61 2
static BOOL showMenuAccelerators;

d115 1
a115 1
			    int width, int height, int underline);
a942 7
    case WM_SETTINGCHANGE:
	if (wParam == SPI_SETNONCLIENTMETRICS 
		|| wParam == SPI_SETKEYBOARDCUES) {
	    SetDefaults(0);
	}
	break;

d1168 1
a1168 1
	int drawingParameters = 0;
a1172 3
	    if (itemPtr->itemState & ODS_NOACCEL && !showMenuAccelerators) {
		drawingParameters |= DRAW_MENU_ENTRY_NOUNDERLINE;
	    }
d1201 2
a1202 2
		 * Also, set the DRAW_MENU_ENTRY_ARROW flag for a disabled
		 * cascade menu since we need to draw the arrow ourselves.
d1206 1
a1206 1
		    drawingParameters |= DRAW_MENU_ENTRY_ARROW;
d1215 1
a1215 2
		    itemPtr->rcItem.bottom - itemPtr->rcItem.top,
		    0, drawingParameters);
d2143 1
a2143 2
    int height,			/* height of entry */
    int underline)		/* accelerator cue should be drawn */
d2288 2
a2289 4
	    if (underline) {
		DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr,
			x + textXOffset, y + textYOffset, width, height);
	    }
d2446 3
a2448 3
    int drawingParameters)	/* Whether or not to draw the cascade arrow
				 * for cascade items and accelerator
				 * cues. Only applies to Windows. */
d2569 1
a2569 2
		adjustedX, adjustedY, width, adjustedHeight,
		(drawingParameters & DRAW_MENU_ENTRY_NOUNDERLINE)?0:1);
d2574 1
a2574 1
		(drawingParameters & DRAW_MENU_ENTRY_ARROW)?1:0);
d3125 1
a3125 1
 * SetDefaults --
d3127 1
a3127 2
 *	Read system menu settings (font, sizes of items, use of accelerators)
 *	This is called if the UI theme or settings are changed.
d3133 2
a3134 1
 *	May result in menu items being redrawn with different appearance.
d3139 1
a3139 1
static void
a3229 10

    /*
     * Accelerators used to be always underlines until Win2K when a system
     * parameter was introduced to hide them unless Alt is pressed.
     */

    showMenuAccelerators = TRUE;
    if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
	SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0);
    }
@


1.59.2.6
log
@[Bug 2956548] TkpButtonSetDefaults only initializes one button type
Fix various gcc warnings, all backported from Tk 8.6
VC6++ does not have SPI_SETKEYBOARDCUES
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.59.2.5 2010/01/03 20:03:55 patthoyts Exp $
d2506 1
a2506 1
    HBITMAP oldBitmap = NULL;
d2508 1
a2508 1
    HDC memDc = NULL, menuDc = NULL;
d2980 2
a2981 1
    union {DWORD msgpos; POINTS point;} root;
d2993 4
a2996 3
    root.msgpos = GetMessagePos();
    event.x_root = root.point.x;
    event.y_root = root.point.y;
@


1.58
log
@Assorted minor cleanups.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.57 2007/06/09 23:53:05 hobbs Exp $
@


1.57
log
@	* win/tkWinMenu.c (TkWinHandleMenuEvent): improve handling to
	allow for unicode char menu indices and not use CharUpper on Tcl
	utf strings. [Bug #1734223]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.56 2007/05/05 07:33:08 dkf Exp $
d96 1
a96 1
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
d109 1
a109 1
			    CONST Tk_FontMetrics *fmPtr, int x, int y,
d113 1
a113 1
			    CONST Tk_FontMetrics *fmPtr, int x, int y,
d117 1
a117 1
			    CONST Tk_FontMetrics *fmPtr,
d119 8
a126 8
static void		DrawTearoffEntry(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d, GC gc,
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
			    int x, int y, int width, int height);
static void		DrawMenuUnderline(TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d, GC gc,
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, int x,
			    int y, int width, int height);
d128 1
a128 1
			    Drawable drawable, GC gc, CONST RECT *rectPtr,
d134 1
a134 1
			    CONST Tk_FontMetrics *fmPtr, int *widthPtr,
d137 1
a137 1
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
d141 1
a141 1
			    CONST Tk_FontMetrics *fmPtr,
d145 1
a145 1
			    CONST Tk_FontMetrics *fmPtr,
d149 1
a149 1
			    CONST Tk_FontMetrics *fmPtr, int *widthPtr,
d154 1
a154 1
			    Tcl_Obj *CONST objv[]);
d459 1
a459 1
	CONST char *p, *next;
d1421 1
a1421 1
    CONST Tk_FontMetrics *fmPtr,/* Precalculated font metrics */
d1458 1
a1458 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1495 1
a1495 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1528 1
a1528 1
    CONST Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */
d1560 1
a1560 1
    CONST RECT *rectPtr,	/* The rectangle to draw into */
d1639 1
a1639 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1715 1
a1715 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1852 1
a1852 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1893 1
a1893 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1905 1
a1905 1
	    CONST char *label, *start, *end;
d1942 1
a1942 1
    Tcl_Obj *CONST objv[])	/* Argument objects. */
d2134 1
a2134 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d2350 1
a2350 1
    CONST Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */
d2434 1
a2434 1
    CONST Tk_FontMetrics *menuMetricsPtr,
d2448 1
a2448 1
    CONST Tk_FontMetrics *fmPtr;
d2567 1
a2567 1
    CONST Tk_FontMetrics *fmPtr,/* The precalculated metrics */
d3059 2
a3060 2
    CONST char *dbName,		/* The option database name. */
    CONST char *className)	/* The name of the option class. */
@


1.56
log
@Slight simplification
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.55 2007/02/23 14:15:34 dkf Exp $
a1102 2
	unsigned char menuChar = (unsigned char) LOWORD(*pwParam);

d1108 1
d1112 6
d1123 1
a1123 1
		     * Do the unicode call just to prevent overruns.
d1125 6
a1130 12

		    Tcl_GetUnicodeFromObj(labelPtr, &len);
		    if (underline < len) {
			char *label = Tcl_GetString(labelPtr);
			char underlined = *Tcl_UtfAtIndex(label, underline);

			if (CharUpper((LPTSTR) menuChar) ==
				CharUpper((LPTSTR) underlined)) {
			    *plResult = (2 << 16) | i;
			    returnResult = 1;
			    break;
			}
@


1.56.2.1
log
@merge updates from HEAD
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.56 2007/05/05 07:33:08 dkf Exp $
d1103 2
a1109 1
	    Tcl_UniChar *wlabel, menuChar;
a1112 6
	    /*
	     * Assume we have something directly convertable to Tcl_UniChar.
	     * True at least for wide systems.
	     */
	    menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam));

d1118 1
a1118 1
		     * Ensure we don't exceed the label length, then check
d1120 12
a1131 6
		    wlabel = Tcl_GetUnicodeFromObj(labelPtr, &len);
		    if ((underline < len) && (menuChar ==
				Tcl_UniCharToUpper(wlabel[underline]))) {
			*plResult = (2 << 16) | i;
			returnResult = 1;
			break;
@


1.56.2.2
log
@merge updates from HEAD
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.56.2.1 2007/06/12 16:22:45 dgp Exp $
d96 1
a96 1
			    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,
d109 1
a109 1
			    const Tk_FontMetrics *fmPtr, int x, int y,
d113 1
a113 1
			    const Tk_FontMetrics *fmPtr, int x, int y,
d117 1
a117 1
			    const Tk_FontMetrics *fmPtr,
d119 8
a126 8
static void		DrawTearoffEntry(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int x, int y,
			    int width, int height);
static void		DrawMenuUnderline(TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, Tk_Font tkfont,
			    const Tk_FontMetrics *fmPtr, int x, int y,
			    int width, int height);
d128 1
a128 1
			    Drawable drawable, GC gc, const RECT *rectPtr,
d134 1
a134 1
			    const Tk_FontMetrics *fmPtr, int *widthPtr,
d137 1
a137 1
			    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,
d141 1
a141 1
			    const Tk_FontMetrics *fmPtr,
d145 1
a145 1
			    const Tk_FontMetrics *fmPtr,
d149 1
a149 1
			    const Tk_FontMetrics *fmPtr, int *widthPtr,
d154 1
a154 1
			    Tcl_Obj *const objv[]);
d459 1
a459 1
	const char *p, *next;
d1421 1
a1421 1
    const Tk_FontMetrics *fmPtr,/* Precalculated font metrics */
d1458 1
a1458 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1495 1
a1495 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1528 1
a1528 1
    const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */
d1560 1
a1560 1
    const RECT *rectPtr,	/* The rectangle to draw into */
d1639 1
a1639 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1715 1
a1715 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1852 1
a1852 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1893 1
a1893 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d1905 1
a1905 1
	    const char *label, *start, *end;
d1942 1
a1942 1
    Tcl_Obj *const objv[])	/* Argument objects. */
d2134 1
a2134 1
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
d2350 1
a2350 1
    const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */
d2434 1
a2434 1
    const Tk_FontMetrics *menuMetricsPtr,
d2448 1
a2448 1
    const Tk_FontMetrics *fmPtr;
d2567 1
a2567 1
    const Tk_FontMetrics *fmPtr,/* The precalculated metrics */
d3059 2
a3060 2
    const char *dbName,		/* The option database name. */
    const char *className)	/* The name of the option class. */
@


1.55
log
@Reduce the number of warnings
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.54 2007/02/22 13:56:34 dkf Exp $
d1124 1
d1126 2
a1127 2
			if (CharUpper((LPTSTR) menuChar) == CharUpper((LPTSTR)
				*Tcl_UtfAtIndex(label, underline))) {
@


1.54
log
@Less of that K&R or wrongly indented function header style!
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.53 2007/01/12 10:41:23 dkf Exp $
d172 3
a174 3
 *	Returns TCL_OK if succesful; TCL_ERROR if there are no more
 *	ids of the appropriate type to allocate. menuIDPtr contains
 *	the new id if succesful.
d177 3
a179 3
 *	An entry is created for the menu in the command hash table,
 *	and the hash entry is stored in the appropriate field in the
 *	menu data structure.
d186 2
a187 2
    TkMenuEntry *mePtr,		/* The menu we are working with */
    WORD *menuIDPtr)		/* The resulting id */
a188 4
    int found = 0;
    int newEntry;
    Tcl_HashEntry *commandEntryPtr;
    WORD returnID;
a190 1

d199 3
d203 1
a203 1
		(char *) curID, &newEntry);
d205 4
a208 3
    	    found = 1;
    	    returnID = curID;
    	    break;
d212 1
a212 9

    if (found) {
    	Tcl_SetHashValue(commandEntryPtr, (char *) mePtr);
    	*menuIDPtr = returnID;
    	tsdPtr->lastCommandID = returnID;
    	return TCL_OK;
    } else {
    	return TCL_ERROR;
    }
d244 1
a244 1
		(char *) commandID);
d412 1
a412 1
    FreeID((WORD) mePtr->platformEntryData);
d845 1
a845 1
    mePtr->platformEntryData = (TkMenuPlatformEntryData) commandID;
d1054 1
a1054 1
		(char *) LOWORD(*pwParam));
d1117 4
a1120 1
		    /* do the unicode call just to prevent overruns */
d1123 4
a1126 5
			char *label;
			label = Tcl_GetStringFromObj(labelPtr, NULL);
			if (CharUpper((LPTSTR) menuChar)
				== CharUpper((LPTSTR)
					*Tcl_UtfAtIndex(label, underline))) {
d1252 1
a1252 1
				(char *) entryIndex);
d3234 2
a3235 2
 *	Sets up the thread-local hash tables used by the menu module.
 *	Assumes that TkpMenuInit has been called.
@


1.53
log
@More warning squelching (mostly uninit variable warnings)
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.52 2007/01/11 15:35:40 dkf Exp $
d185 3
a187 3
GetNewID(mePtr, menuIDPtr)
    TkMenuEntry *mePtr;		/* The menu we are working with */
    WORD *menuIDPtr;		/* The resulting id */
d241 2
a242 2
FreeID(commandID)
    WORD commandID;
d279 2
a280 2
TkpNewMenu(menuPtr)
    TkMenu *menuPtr;		/* The common structure we are making the
d327 2
a328 2
TkpDestroyMenu(menuPtr)
    TkMenu *menuPtr;		/* The common menu structure */
d409 2
a410 2
TkpDestroyMenuEntry(mePtr)
    TkMenuEntry *mePtr;		/* The entry to destroy */
d445 2
a446 2
GetEntryText(mePtr)
    TkMenuEntry *mePtr;		/* A pointer to the menu entry. */
d721 4
a724 5
TkpPostMenu(interp, menuPtr, x, y)
    Tcl_Interp *interp;
    TkMenu *menuPtr;
    int x;
    int y;
d839 2
a840 2
TkpMenuNewEntry(mePtr)
    TkMenuEntry *mePtr;
d878 5
a882 5
TkWinMenuProc(hwnd, message, wParam, lParam)
    HWND hwnd;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
d910 4
a913 1
static void UpdateEmbeddedMenu(ClientData clientData) {
d939 5
a943 5
TkWinEmbeddedMenuProc(hwnd, message, wParam, lParam)
    HWND hwnd;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
d1005 6
a1010 6
TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
    HWND *phwnd;
    UINT *pMessage;
    WPARAM *pwParam;
    LPARAM *plParam;
    LRESULT *plResult;
d1345 2
a1346 2
TkpSetWindowMenuBar(tkwin, menuPtr)
    Tk_Window tkwin;		/* The window we are putting the menubar
d1348 1
a1348 1
    TkMenu *menuPtr;		/* The menu we are inserting */
d1424 1
a1424 1
GetMenuIndicatorGeometry (
d1461 1
a1461 1
GetMenuAccelGeometry (
d1498 1
a1498 1
GetTearoffEntryGeometry (
d1531 1
a1531 1
GetMenuSeparatorGeometry (
d1563 6
a1568 6
DrawWindowsSystemBitmap(display, drawable, gc, rectPtr, bitmapID, alignFlags)
    Display *display;		/* The display we are drawing into */
    Drawable drawable;		/* The drawable we are working with */
    GC gc;			/* The GC to draw with */
    CONST RECT *rectPtr;	/* The rectangle to draw into */
    int bitmapID;		/* The windows id of the system bitmap to
d1570 1
a1570 1
    int alignFlags;		/* How to align the bitmap inside the
d1639 12
a1650 13
DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x,
	y, width, height)
    TkMenu *menuPtr;		/* The menu we are drawing */
    TkMenuEntry *mePtr;		/* The entry we are drawing */
    Drawable d;			/* What we are drawing into */
    GC gc;			/* The gc we are drawing with */
    GC indicatorGC;		/* The gc for indicator objects */
    Tk_Font tkfont;		/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;/* The precalculated font metrics */
    int x;			/* Left edge */
    int y;			/* Top edge */
    int width;
    int height;
d1783 11
a1793 12
DrawMenuEntryArrow(menuPtr, mePtr, d, gc, activeBorder, x, y, width, height,
	drawArrow)
    TkMenu *menuPtr;		/* The menu we are drawing */
    TkMenuEntry *mePtr;		/* The entry we are drawing */
    Drawable d;			/* What we are drawing into */
    GC gc;			/* The gc we are drawing with */
    Tk_3DBorder activeBorder;	/* The border when an item is active */
    int x;			/* left edge */
    int y;			/* top edge */
    int width;			/* Width of menu entry */
    int height;			/* Height of menu entry */
    int drawArrow;		/* For cascade menus, whether of not to draw
d1853 11
a1863 11
DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
    TkMenu *menuPtr;		/* The menu we are drawing */
    TkMenuEntry *mePtr;		/* The entry we are drawing */
    Drawable d;			/* What we are drawing into */
    GC gc;			/* The gc we are drawing with */
    Tk_Font tkfont;		/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;/* The precalculated font metrics */
    int x;			/* left edge */
    int y;			/* top edge */
    int width;			/* width of item */
    int height;			/* height of item */
d1945 5
a1949 5
TkWinMenuKeyObjCmd(clientData, interp, objc, objv)
    ClientData clientData;	/* Unused. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
d2073 3
a2075 3
TkpInitializeMenuBindings(interp, bindingTable)
    Tcl_Interp *interp;		/* The interpreter to set. */
    Tk_BindingTable bindingTable;
d2328 2
a2329 2
TkpComputeMenubarGeometry(menuPtr)
    TkMenu *menuPtr;		/* Structure describing menu. */
d2351 9
a2359 11
DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
    TkMenu *menuPtr;		/* The menu we are drawing */
    TkMenuEntry *mePtr;		/* The entry we are drawing */
    Drawable d;			/* The drawable we are drawing into */
    GC gc;			/* The gc we are drawing with */
    Tk_Font tkfont;		/* The font we are drawing with */
    CONST Tk_FontMetrics *fmPtr;/* The metrics we are drawing with */
    int x;
    int y;
    int width;
    int height;
d2406 2
a2407 2
TkpConfigureMenuEntry(mePtr)
    register TkMenuEntry *mePtr;/* Information about menu entry; may or may
d2437 5
a2441 6
TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
	strictMotif, drawArrow)
    TkMenuEntry *mePtr;		/* The entry to draw */
    Drawable d;			/* What to draw into */
    Tk_Font tkfont;		/* Precalculated font for menu */
    CONST Tk_FontMetrics *menuMetricsPtr;
d2443 6
a2448 6
    int x;			/* X-coordinate of topleft of entry */
    int y;			/* Y-coordinate of topleft of entry */
    int width;			/* Width of the entry rectangle */
    int height;			/* Height of the current rectangle */
    int strictMotif;		/* Boolean flag */
    int drawArrow;		/* Whether or not to draw the cascade arrow
d2571 6
a2576 6
GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)
    TkMenuEntry *mePtr;		/* The entry we are computing */
    Tk_Font tkfont;		/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;/* The precalculated metrics */
    int *widthPtr;		/* The resulting width of the label portion */
    int *heightPtr;		/* The resulting height of the label
d2978 2
a2979 2
Tk_GetMenuHWND(tkwin)
    Tk_Window tkwin;
d3208 1
a3208 1
TkpMenuInit()
d3254 1
a3254 1
TkpMenuThreadInit()
@


1.52
log
@Many minute fixes to reduce number of minor warnings from GCC.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.51 2006/11/24 18:11:32 hobbs Exp $
d1715 12
a1726 13
DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder,
	x, y, width, height)
    TkMenu *menuPtr;		/* The menu we are drawing */
    TkMenuEntry *mePtr;		/* The entry we are drawing */
    Drawable d;			/* What we are drawing into */
    GC gc;			/* The gc we are drawing with */
    Tk_Font tkfont;		/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;/* The precalculated font metrics */
    Tk_3DBorder activeBorder;	/* The border when an item is active */
    int x;			/* left edge */
    int y;			/* top edge */
    int width;			/* Width of menu entry */
    int height;			/* Height of menu entry */
d1734 2
d1746 1
a1746 2
		&& (menuPtr->disabledFgPtr != NULL)
		&& (mePtr->accelPtr != NULL)) {
d1750 1
a1750 2
	    if ((mePtr->accelPtr != NULL) &&
		    ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
d1758 1
a1758 1
    if (mePtr->accelPtr != NULL) {
d2151 1
a2151 1
    int textHeight, textWidth;
@


1.51
log
@	* unix/tkUnixMenu.c (DrawMenuUnderline): bound Tcl_UtfAtIndex usage
	* tests/menu.test (menu-36.1): [Bug 1599877]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.50 2006/11/24 01:51:51 hobbs Exp $
d500 1
a500 1
	itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);
d943 1
a943 1
    static nIdles = 0;
d1990 2
a1991 1
		    WM_SYSKEYDOWN, VK_MENU, (scanCode << 16) | (1 << 29));
d1996 2
a1997 2
		    WM_SYSKEYDOWN, VK_MENU, (scanCode << 16)
		    | (1 << 29) | (1 << 24));
d2002 1
a2002 1
		    WM_SYSKEYDOWN, VK_F10, (scanCode << 16));
d2009 2
a2010 2
			WM_SYSKEYDOWN, virtualKey, ((scanCode << 16)
			| (1 << 29)));
d2016 1
a2016 1
				((scanCode << 16) | (1 << 29)));
d2026 1
a2026 1
		    WM_SYSKEYUP, VK_MENU, (scanCode << 16)
d2032 1
a2032 1
		    WM_SYSKEYUP, VK_MENU, (scanCode << 16) | (1 << 24)
d2038 2
a2039 2
		    WM_SYSKEYUP, VK_F10, (scanCode << 16)
		    | (1 << 30) | (1 << 31));
d2046 1
a2046 1
			WM_SYSKEYUP, virtualKey, ((scanCode << 16)
d2584 1
a2584 1
    int haveImage = 0, haveText = 0;
@


1.50
log
@	* win/tkWinMenu.c (TkWinHandleMenuEvent, DrawMenuUnderline):
	handle unichar underlining correctly and safely. [Bug 1599877]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.49 2006/09/21 00:13:36 hobbs Exp $
d1128 1
a1128 1
			label = Tcl_GetStringFromObj(labelPtr, &len);
d1915 1
a1915 1
	    label = Tcl_GetStringFromObj(mePtr->labelPtr, &len);
@


1.49
log
@	* win/tkWinMenu.c (TkpPostMenu): disable menu animation in menus
	with images to avoid clipping bug.  [Bug 1329198]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.48 2006/05/25 23:50:31 hobbs Exp $
d1115 2
a1116 1
	    int i;
a1120 3
		int underline;
		char *label;

d1122 15
a1136 10
		if (menuPtr->entries[i]->labelPtr != NULL) {
		    label = Tcl_GetString(menuPtr->entries[i]->labelPtr);
		}
		if ((-1 != underline)
			&& (NULL != menuPtr->entries[i]->labelPtr)
			&& (CharUpper((LPTSTR) menuChar)
			== CharUpper((LPTSTR) UCHAR(label[underline])))) {
		    *plResult = (2 << 16) | i;
		    returnResult = 1;
		    break;
d1907 16
a1922 9
    if (mePtr->underline >= 0) {
	char *label = Tcl_GetString(mePtr->labelPtr);
	CONST char *start = Tcl_UtfAtIndex(label, mePtr->underline);
	CONST char *end = Tcl_UtfNext(start);

    	Tk_UnderlineChars(menuPtr->display, d,
    		gc, tkfont, label, x + mePtr->indicatorSpace,
    		y + (height + fmPtr->ascent - fmPtr->descent) / 2,
		(int) (start - label), (int) (end - label));
@


1.48
log
@	* win/tkWinMenu.c (TkWinMenuKeyObjCmd): get eventPtr after we know
	the window is still alive. [AS bug 45987] [Bug 1236306]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.47 2006/04/05 20:59:04 hobbs Exp $
d38 4
d728 1
a728 1
    int result, flags;
d733 1
d796 12
@


1.47
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
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.46 2005/11/10 11:38:29 dkf Exp $
a1937 2
    eventPtr = TkpGetBindingXEvent(interp);

d1949 2
@


1.46
log
@Fixes of other issues raised in [Bug 1353022]
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.45 2005/08/10 22:02:22 dkf Exp $
a57 2
    Tcl_HashTable commandTable;
				/* A map of command ids to menu entries */
d73 2
a74 2
    Tcl_HashTable winMenuTable;
				/* Need this to map HMENUs back to menuPtrs */
d243 3
a245 2
    Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
	    (char *) commandID);
d247 6
a252 2
    if (entryPtr != NULL) {
    	 Tcl_DeleteHashEntry(entryPtr);
a366 2
	Tcl_HashEntry *hashEntryPtr;

d369 1
d372 6
a377 4
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) winMenuHdl);
	if (hashEntryPtr != NULL) {
	    Tcl_DeleteHashEntry(hashEntryPtr);
d1940 2
a1941 3
    tkwin = Tk_NameToWindow(interp,
	Tcl_GetString(objv[1]),
	Tk_MainWindow(interp));
d1944 5
a1948 1
	return TCL_ERROR;
d2937 29
d2968 1
a2968 2
 *	Throws away the utility window needed for menus and unregisters the
 *	class.
d2983 25
d3012 3
a3014 1
    UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
d3016 2
a3017 2
    DestroyWindow(tsdPtr->embeddedMenuHWND);
    UnregisterClass(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());
a3186 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
a3201 7
    tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
	    0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    if (!tsdPtr->menuHWND) {
	Tcl_Panic("Failed to create the menu window.");
    }

a3207 8
    tsdPtr->embeddedMenuHWND =
	    CreateWindow(EMBEDDED_MENU_CLASS_NAME, "EmbeddedMenuWindow",
	    WS_POPUP, 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    if (!tsdPtr->embeddedMenuHWND) {
	Tcl_Panic("Failed to create the embedded menu window.");
    }

a3210 29

/*
 *----------------------------------------------------------------------
 *
 * Tk_GetMenuHWND --
 *
 *	This function returns the HWND of a hidden menu Window that processes
 *	messages of a popup menu. This hidden menu window is used to handle
 *	either a dynamic popup menu in the same process or a pull-down menu of
 *	an embedded window in a different process.
 *
 * Results:
 *	Returns the HWND of the hidden menu Window.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

HWND
Tk_GetMenuHWND(tkwin)
    Tk_Window tkwin;
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    TkMenuInit();
    return tsdPtr->embeddedMenuHWND;
}
d3218 1
d3235 15
d3252 2
@


1.45
log
@Getting more systematic about style
Also start removing _ANSI_ARGS_; the core's required ANSI C for a while now
Also fix [Bug 1252702]; size_t doesn't mix with Tcl_GetStringFromObj
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.44 2005/04/28 02:40:19 chengyemao Exp $
a3019 1
    Tcl_DString boldItalicDString;
d3068 3
a3070 1
    if (bold == 1 || italic == 1) {
d3072 1
a3072 1
	if (bold == 1) {
d3075 1
a3075 1
	if (italic == 1) {
d3080 1
@


1.44
log
@Fixed bug # 1189939
@
text
@d1 1
a1 1
/* 
d4 2
a5 1
 *	This module implements the Windows platform-specific features of menus.
d10 2
a11 2
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
d13 1
a13 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.43 2005/01/18 15:24:18 chengyemao Exp $
d26 2
a27 2
#define MENU_CLASS_NAME "MenuWindowClass"
#define EMBEDDED_MENU_CLASS_NAME "EmbeddedMenuWindowClass"
d33 4
a36 4
#define ALIGN_BITMAP_LEFT   0x00000001
#define ALIGN_BITMAP_RIGHT  0x00000002
#define ALIGN_BITMAP_TOP    0x00000004
#define ALIGN_BITMAP_BOTTOM 0x00000008
d41 3
a43 3
 * MENU_SYSTEM_MENU	Non-zero means that the Windows menu handle
 *			was retrieved with GetSystemMenu and needs
 *			to be disposed of specially.
d45 2
a46 3
 *			Non-zero means that an idle handler has
 *			been set up to reconfigure the Windows menu
 *			handle for this menu.
d49 2
a50 2
#define MENU_SYSTEM_MENU	    MENU_PLATFORM_FLAG1
#define MENU_RECONFIGURE_PENDING    MENU_PLATFORM_FLAG2
d53 3
a55 3
				/* The dimensions of the indicator space
				 * in a menu entry. Calculated at init
				 * time to save time. */
d61 1
a61 1
    WORD lastCommandID;	        /* The last command ID we allocated. */
d64 6
a69 5
    HWND embeddedMenuHWND;	/* A window to service embedded menu messages */
    int oldServiceMode;	        /* Used while processing a menu; we need
				 * to set the event mode specially when we
				 * enter the menu processing modal loop
				 * and reset it when menus go away. */
d71 1
a71 1
				 * loop. We need this to reset all of the 
d73 2
a74 2
				 * Windows does not see fit to give this
				 * to us when it sends its WM_MENUSELECT. */
d89 1
a89 1
 * Forward declarations for procedures defined later in this file:
d92 3
a94 4
static void		DrawMenuEntryAccelerator _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr, 
			    Drawable d, GC gc, Tk_Font tkfont,
			    CONST Tk_FontMetrics *fmPtr,
d96 11
a106 15
			    int width, int height));
static void		DrawMenuEntryArrow _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr, 
			    Drawable d, GC gc,
			    Tk_3DBorder activeBorder, int x, int y,
			    int width, int height, int drawArrow));
static void		DrawMenuEntryBackground _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, Tk_3DBorder activeBorder,
			    Tk_3DBorder bgBorder, int x, int y,
			    int width, int heigth));
static void		DrawMenuEntryIndicator _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Drawable d, GC gc, GC indicatorGC, 
			    Tk_Font tkfont,
d108 3
a110 4
			    int width, int height));
static void		DrawMenuEntryLabel _ANSI_ARGS_((
			    TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
			    GC gc, Tk_Font tkfont,
d112 10
a121 10
			    int width, int height));
static void		DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d, GC gc, 
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, 
			    int x, int y, int width, int height));
static void		DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
			    TkMenuEntry *mePtr, Drawable d, GC gc, 
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, 
			    int x, int y, int width, int height));
static void		DrawMenuUnderline _ANSI_ARGS_((TkMenu *menuPtr,
d124 7
a130 8
			    int y, int width, int height));
static void		DrawWindowsSystemBitmap _ANSI_ARGS_((
			    Display *display, Drawable drawable, 
			    GC gc, CONST RECT *rectPtr, int bitmapID,
			    int alignFlags));
static void		FreeID _ANSI_ARGS_((WORD commandID));
static TCHAR *		GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
static void		GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
d133 2
a134 2
			    int *heightPtr));
static void		GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
d136 10
a145 10
			    int *widthPtr, int *heightPtr));
static void		GetMenuIndicatorGeometry _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr, 
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, 
			    int *widthPtr, int *heightPtr));
static void		GetMenuSeparatorGeometry _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr,
			    Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
			    int *widthPtr, int *heightPtr));
static void		GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
d148 13
a160 19
			    int *heightPtr));
static int		GetNewID _ANSI_ARGS_((TkMenuEntry *mePtr,
			    WORD *menuIDPtr));
static int		TkWinMenuKeyObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, 
			    Tcl_Obj *CONST objv[]));
static void		MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));
static void		ReconfigureWindowsMenu _ANSI_ARGS_((
			    ClientData clientData));
static void		RecursivelyClearActiveMenu _ANSI_ARGS_((
			    TkMenu *menuPtr));
static void		SetDefaults _ANSI_ARGS_((int firstTime));
static LRESULT CALLBACK	TkWinMenuProc _ANSI_ARGS_((HWND hwnd,
			    UINT message, WPARAM wParam,
			    LPARAM lParam));
static LRESULT CALLBACK	TkWinEmbeddedMenuProc _ANSI_ARGS_((HWND hwnd,
			    UINT message, WPARAM wParam,
			    LPARAM lParam));

d191 2
a192 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d200 1
a200 1
    
d242 2
a243 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d247 1
a247 1
    
d273 2
a274 2
    TkMenu *menuPtr;	/* The common structure we are making the
			 * platform structure for. */
d279 2
a280 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d283 1
a283 1
    
d291 2
a292 2
     * We hash all of the HMENU's so that we can get their menu ptrs
     * back when dispatch messages.
d295 2
a296 2
    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl,
	    &newEntry);
d321 1
a321 1
    TkMenu *menuPtr;	    /* The common menu structure */
d325 2
a326 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d331 1
a331 1
    
d339 1
a339 1
	char *menuName = Tcl_GetHashKey(tablePtr, 
d349 3
a351 3
	     searchEntryPtr != NULL;
	     searchEntryPtr = searchEntryPtr->nextCascadePtr) {
	    searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, NULL);
d354 1
a354 1
		    ->menuPtr->parentTopLevelPtr;
d357 2
a358 2
		    GetSystemMenu(TkWinGetWrapperWindow(parentTopLevelPtr),
			    TRUE);
d365 1
a365 1
 
d370 2
a371 2
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                (char *) winMenuHdl);
d402 1
a402 1
    TkMenuEntry *mePtr;		    /* The entry to destroy */
d408 1
a408 1
        if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
d423 3
a425 3
 *	Separators should be done by the caller, as they have to be
 *	handled specially. Allocates the memory with alloc. The caller
 *	should free the memory.
d456 4
a459 4
	char *label = (mePtr->labelPtr == NULL) ? "" 
		: Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
	char *accel = (mePtr->accelPtr == NULL) ? "" 
		: Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
d464 3
a466 4
	 * We have to construct the string with an ampersand
	 * preceeding the underline character, and a tab seperating
	 * the text and the accel text. We have to be careful with
	 * ampersands in the string.
d481 1
a481 1
        if (mePtr->accelLength > 0) {
d490 1
a490 1
	} 	    
d510 2
a511 2
 *	Configuration information get set for mePtr; old resources
 *	get freed, if any need it.
d518 1
a518 1
    ClientData clientData)	    /* The menu we are rebuilding */
d529 1
a529 1
  
a536 1
     *
d571 1
a571 1
	
d575 1
a575 1
	
d579 1
a579 1
	
d585 1
a585 1
	
d587 4
a590 4
	 * Set the SEPARATOR bit for separator entries.  This bit is not
	 * used by our internal drawing functions, but it is used by the
	 * system when drawing the system menu (we do not draw the system menu
	 * ourselves).  If this bit is not set, separator entries on the system
d597 1
a597 1
	
d601 1
a601 1
	
d609 5
a613 5
		/* 
		 * Win32 draws the popup arrow in the wrong color 
		 * for a disabled cascade menu, so do it by hand.
		 * Given it is disabled, there's no need for it to
		 * be connected to its child.
d615 1
d619 2
a620 2
		     * If the MF_POPUP flag is set, then the id
		     * is interpreted as the handle of a submenu.
d623 1
a623 1
		}	
d625 1
a625 1
	    if ((menuPtr->menuType == MENUBAR) 
d631 1
a631 1
		
d636 1
a636 1
		
d639 1
a639 1
		
d641 2
a642 2
		
		if ((menuRefPtr != NULL) 
d647 1
a647 1
		    HMENU systemMenuHdl = 
d655 3
a657 3
			systemMenuPtr->platformData = 
			    (TkMenuPlatformData) systemMenuHdl;
			if (!(systemMenuPtr->menuFlags 
d659 2
a660 2
			    systemMenuPtr->menuFlags 
				|= MENU_RECONFIGURE_PENDING;
d684 1
a684 1
    if ((menuPtr->menuType == MENUBAR) 
d692 1
a692 1
    
d725 2
a726 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d745 1
a745 1
    
d766 1
a766 1
    
d787 1
a787 1
    TrackPopupMenu(winMenuHdl, flags, x, y, 0, 
d833 1
a833 1
    
d877 2
a878 2
 *	This function is used as work-around for updating the pull-down 
 *	window of an embedded menu which may show as a blank popup window.
d881 1
a881 1
 *	Invalidate the client area of the embedded pull-down menu and 
d924 2
a925 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d928 5
a932 3
	case WM_ENTERIDLE: 
        if((wParam == MSGF_MENU) && (nIdles < 1) && (hwnd == tsdPtr->embeddedMenuHWND)) {
	    Tcl_CreateTimerHandler(200, UpdateEmbeddedMenu, (ClientData)lParam);
d936 2
a937 2
	
	case WM_INITMENUPOPUP:
d941 12
a952 9
	case WM_INITMENU:
	case WM_SYSCOMMAND:
	case WM_COMMAND:
	case WM_MENUCHAR:
	case WM_MEASUREITEM:
	case WM_DRAWITEM:
	case WM_MENUSELECT:
	lResult = TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult);
	if(lResult || (GetCapture() != hwnd)) break;
d954 1
a954 1
	default:
d966 3
a968 3
 *	Filters out menu messages from messages passed to a top-level.
 *	Will respond appropriately to WM_COMMAND, WM_MENUSELECT,
 *	WM_MEASUREITEM, WM_DRAWITEM
d974 3
a976 3
 *	All of the parameters may be modified so that the caller can
 *	think it is getting a different message. plResult points to
 *	the result that should be returned to windows from this message.
d993 2
a994 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d997 12
a1008 41
	case WM_INITMENU:
	    TkMenuInit();
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                    (char *) *pwParam);
	    if (hashEntryPtr != NULL) {
		tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
		menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
		tsdPtr->modalMenuPtr = menuPtr;
		if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
		    Tcl_CancelIdleCall(ReconfigureWindowsMenu, 
			    (ClientData) menuPtr);
		    ReconfigureWindowsMenu((ClientData) menuPtr);
		}
		RecursivelyClearActiveMenu(menuPtr);
		if (!tsdPtr->inPostMenu) {
		    Tcl_Interp *interp;
		    int code;

		    interp = menuPtr->interp;
		    Tcl_Preserve((ClientData)interp);
		    code = TkPreprocessMenu(menuPtr);
		    if ((code != TCL_OK) && (code != TCL_CONTINUE)
			    && (code != TCL_BREAK)) {
			Tcl_AddErrorInfo(interp, "\n    (menu preprocess)");
			Tcl_BackgroundError(interp);
		    }
		    Tcl_Release((ClientData)interp);
		}
		TkActivateMenuEntry(menuPtr, -1);
		*plResult = 0;
		returnResult = 1;
	    } else {
		tsdPtr->modalMenuPtr = NULL;
	    }
	    break;

	case WM_SYSCOMMAND:
	case WM_COMMAND: {
	    TkMenuInit();
	    if (HIWORD(*pwParam) != 0) {
		break;
d1010 2
a1011 9
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
		    (char *)LOWORD(*pwParam));
	    if (hashEntryPtr == NULL) {
		break;
	    }
	    mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
	    if (mePtr != NULL) {
		TkMenuReferences *menuRefPtr;
		TkMenuEntry *parentEntryPtr;
a1014 31
		/*
		 * We have to set the parent of this menu to be active
		 * if this is a submenu so that tearoffs will get the
		 * correct title.
		 */

		menuPtr = mePtr->menuPtr;
		menuRefPtr = TkFindMenuReferences(menuPtr->interp,
			Tk_PathName(menuPtr->tkwin));
		if ((menuRefPtr != NULL)
			&& (menuRefPtr->parentEntryPtr != NULL)) {
		    char *name;

		    for (parentEntryPtr = menuRefPtr->parentEntryPtr;
			 ; 
			 parentEntryPtr = 
			     parentEntryPtr->nextCascadePtr) {
			name = Tcl_GetStringFromObj(
			    parentEntryPtr->namePtr, NULL);
			if (strcmp(name, Tk_PathName(menuPtr->tkwin))
				== 0) {
			    break;
			}
		    }
		    if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]
			    ->state != ENTRY_DISABLED) {
			TkActivateMenuEntry(parentEntryPtr->menuPtr, 
				parentEntryPtr->index);
		    }
		}

d1017 4
a1020 4
		code = TkInvokeMenu(interp, menuPtr, mePtr->index);
		if (code != TCL_OK && code != TCL_CONTINUE
			&& code != TCL_BREAK) {
		    Tcl_AddErrorInfo(interp, "\n    (menu invoke)");
a1023 2
		*plResult = 0;
		returnResult = 1;
d1025 12
d1039 16
d1056 7
a1062 6
	case WM_MENUCHAR: {
	    unsigned char menuChar = (unsigned char) LOWORD(*pwParam);
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                    (char *) *plParam);
	    if (hashEntryPtr != NULL) {
		int i;
d1064 1
a1064 18
		*plResult = 0;
		menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
		for (i = 0; i < menuPtr->numEntries; i++) {
		    int underline;
		    char *label;

		    underline = menuPtr->entries[i]->underline;
		    if (menuPtr->entries[i]->labelPtr != NULL) {
			label = Tcl_GetStringFromObj(
				menuPtr->entries[i]->labelPtr, NULL);
		    }
		    if ((-1 != underline) 
			    && (NULL != menuPtr->entries[i]->labelPtr)
			    && (CharUpper((LPTSTR) menuChar) 
			    == CharUpper((LPTSTR) (unsigned char) 
			    label[underline]))) {
			*plResult = (2 << 16) | i;
			returnResult = 1;
d1068 5
d1074 11
a1084 1
	    break;
d1086 1
d1088 25
a1112 19
	case WM_MEASUREITEM: {
	    LPMEASUREITEMSTRUCT itemPtr = (LPMEASUREITEMSTRUCT) *plParam;
    
	    if (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) {
		mePtr = (TkMenuEntry *) itemPtr->itemData;
		menuPtr = mePtr->menuPtr;

		TkRecomputeMenu(menuPtr);
		itemPtr->itemHeight = mePtr->height;
		itemPtr->itemWidth = mePtr->width;
		if (mePtr->hideMargin) {
		    itemPtr->itemWidth += 2 - indicatorDimensions[1];
		} else {
		    int activeBorderWidth;
		    
		    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
			    menuPtr->activeBorderWidthPtr, 
			    &activeBorderWidth);
		    itemPtr->itemWidth += 2 * activeBorderWidth;
a1113 2
		*plResult = 1;
		returnResult = 1;
a1114 1
	    break;
d1116 57
a1172 15
	
	case WM_DRAWITEM: {
	    TkWinDrawable *twdPtr;
	    LPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam;
	    Tk_FontMetrics fontMetrics;
	    int drawArrow = 0;

	    if (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) {
		Tk_Font tkfont;

		mePtr = (TkMenuEntry *) itemPtr->itemData;
		menuPtr = mePtr->menuPtr;
		twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable));
		twdPtr->type = TWD_WINDC;
		twdPtr->winDC.hdc = itemPtr->hDC;
d1174 2
a1175 6
		if (mePtr->state != ENTRY_DISABLED) {
		    if (itemPtr->itemState & ODS_SELECTED) {
			TkActivateMenuEntry(menuPtr, mePtr->index);
		    } else {
			TkActivateMenuEntry(menuPtr, -1);
		    }
d1177 1
a1177 17
		    /* On windows, menu entries should highlight even if they
		    ** are disabled. (I know this seems dumb, but it is the way
		    ** native windows menus works so we ought to mimic it.)
		    ** The ENTRY_PLATFORM_FLAG1 flag will indicate that the
		    ** entry should be highlighted even though it is disabled.
		    */
		    if (itemPtr->itemState & ODS_SELECTED) {
			mePtr->entryFlags |= ENTRY_PLATFORM_FLAG1;
		    } else {
			mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
		    }
		    /* Also, set the drawArrow flag for a disabled cascade
		    ** menu since we need to draw the arrow ourselves.
		    */
		    if (mePtr->type == CASCADE_ENTRY) {
		        drawArrow = 1;
		    }
d1180 4
a1183 7
		tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
		Tk_GetFontMetrics(tkfont, &fontMetrics);
		TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont,
			&fontMetrics, itemPtr->rcItem.left,
			itemPtr->rcItem.top, itemPtr->rcItem.right
			- itemPtr->rcItem.left, itemPtr->rcItem.bottom
			- itemPtr->rcItem.top, 0, drawArrow);
d1185 3
a1187 1
		ckfree((char *) twdPtr);
d1189 9
a1197 3
    	    *plResult = 1;
	    returnResult = 1;
	    break;
d1199 4
d1204 2
a1205 2
	case WM_MENUSELECT: {
	    UINT flags = HIWORD(*pwParam);
d1207 1
a1207 1
	    TkMenuInit();
d1209 12
a1220 13
	    if ((flags == 0xFFFF) && (*plParam == 0)) {
		if (tsdPtr->modalMenuPtr != NULL) {
		    Tcl_SetServiceMode(tsdPtr->oldServiceMode);
		    RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
		}
	    } else {
		menuPtr = NULL;
 		if (*plParam != 0) {
		    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
			    (char *) *plParam);
		    if (hashEntryPtr != NULL) {
			menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
		    }
d1222 1
d1224 2
a1225 16
		if (menuPtr != NULL) {
		    long entryIndex = LOWORD(*pwParam);
	    	    mePtr = NULL;
		    if (flags != 0xFFFF) {
			if ((flags & MF_POPUP) && (entryIndex < menuPtr->numEntries)) {
			    mePtr = menuPtr->entries[entryIndex];
			} else {
			    hashEntryPtr = Tcl_FindHashEntry(
                                    &tsdPtr->commandTable,
				    (char *) entryIndex);
			    if (hashEntryPtr != NULL) {
				mePtr = (TkMenuEntry *) 
					Tcl_GetHashValue(hashEntryPtr);
			    }
			}
		    }	 
d1227 4
a1230 2
		    if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
			TkActivateMenuEntry(menuPtr, -1);
d1232 5
a1236 2
			if (mePtr->index >= menuPtr->numEntries) {
			    Tcl_Panic("Trying to activate an entry which doesn't exist.");
a1237 1
			TkActivateMenuEntry(menuPtr, mePtr->index);
a1238 4
		    MenuSelectEvent(menuPtr);
		    Tcl_ServiceAll();
		    *plResult = 0;
		    returnResult = 1;
d1240 13
a1253 1
	    break;
d1255 2
d1283 1
a1283 1
    
d1320 3
a1322 2
    Tk_Window tkwin;	    /* The window we are putting the menubar into.*/
    TkMenu *menuPtr;	    /* The menu we are inserting */
d1325 2
a1326 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d1333 2
a1334 2
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                (char *) winMenuHdl);
d1338 2
a1339 2
	hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, 
                (char *) winMenuHdl, &newEntry);
d1357 2
a1358 2
 *	Puts the menu associated with a window into the menubar. Should
 *	only be called when the window is in front.
d1368 1
d1373 2
a1374 3
    char *menuName)		/* The name of the menu to put in front.
    				 * If NULL, use the default menu bar.
    				 */
d1399 6
a1404 6
    TkMenu *menuPtr,			/* The menu we are measuring */
    TkMenuEntry *mePtr,			/* The entry we are measuring */
    Tk_Font tkfont,			/* Precalculated font */
    CONST Tk_FontMetrics *fmPtr,	/* Precalculated font metrics */
    int *widthPtr,			/* The resulting width */
    int *heightPtr)			/* The resulting height */
d1436 6
a1441 6
    TkMenu *menuPtr,			/* The menu we are measuring */
    TkMenuEntry *mePtr,			/* The entry we are measuring */
    Tk_Font tkfont,			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr,	/* The precalculated font metrics */
    int *widthPtr,			/* The resulting width */
    int *heightPtr)			/* The resulting height */
d1449 2
a1450 1
	char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
d1473 6
a1478 6
    TkMenu *menuPtr,			/* The menu we are measuring */
    TkMenuEntry *mePtr,			/* The entry we are measuring */
    Tk_Font tkfont,			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr,	/* The precalculated font metrics */
    int *widthPtr,			/* The resulting width */
    int *heightPtr)			/* The resulting height */
d1506 6
a1511 6
    TkMenu *menuPtr,			/* The menu we are measuring */
    TkMenuEntry *mePtr,			/* The entry we are measuring */
    Tk_Font tkfont,			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr,	/* The precalcualted font metrics */
    int *widthPtr,			/* The resulting width */
    int *heightPtr)			/* The resulting height */
d1522 4
a1525 4
 *	Draws the windows system bitmap given by bitmapID into the rect
 *	given by rectPtr in the drawable. The bitmap is centered in the
 *	rectangle. It is not clipped, so if the bitmap is bigger than
 *	the rect it will bleed.
d1538 8
a1545 8
    Display *display;			/* The display we are drawing into */
    Drawable drawable;			/* The drawable we are working with */
    GC gc;				/* The GC to draw with */
    CONST RECT *rectPtr;		/* The rectangle to draw into */
    int bitmapID;			/* The windows id of the system
					 * bitmap to draw. */
    int alignFlags;			/* How to align the bitmap inside the
					 * rectangle. */
d1555 1
a1555 1
    
d1587 1
a1587 1
    
d1601 1
a1601 1
 *	This procedure draws the indicator part of a menu.
d1607 1
a1607 2
 *	Commands are output to X to display the menu in its
 *	current mode.
d1611 1
d1615 9
a1623 9
    TkMenu *menuPtr;		    /* The menu we are drawing */
    TkMenuEntry *mePtr;		    /* The entry we are drawing */
    Drawable d;			    /* What we are drawing into */
    GC gc;			    /* The gc we are drawing with */
    GC indicatorGC;		    /* The gc for indicator objects */
    Tk_Font tkfont;		    /* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;    /* The precalculated font metrics */
    int x;			    /* Left edge */
    int y;			    /* Top edge */
d1627 1
a1627 1
    if ((mePtr->type == CHECK_BUTTON_ENTRY) 
d1633 1
d1653 1
a1653 1
	    
d1659 1
a1659 1
		DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, 
d1664 1
a1664 1
	    DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect, 
d1667 1
a1667 1
    }    
d1675 4
a1678 5
 *	This procedure draws the accelerator part of a menu.
 *	For example, the string "CTRL-Z" could be drawn to
 *	to the right of the label text for an Undo menu entry.
 *	Need to decide what to draw here. Should we replace strings
 *	like "Control", "Command", etc?
d1691 13
a1703 13
DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
	activeBorder, x, y, width, height)
    TkMenu *menuPtr;			/* The menu we are drawing */
    TkMenuEntry *mePtr;			/* The entry we are drawing */
    Drawable d;				/* What we are drawing into */
    GC gc;				/* The gc we are drawing with */
    Tk_Font tkfont;			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;	/* The precalculated font metrics */
    Tk_3DBorder activeBorder;		/* The border when an item is active */
    int x;				/* left edge */
    int y;				/* top edge */
    int width;				/* Width of menu entry */
    int height;				/* Height of menu entry */
d1708 1
a1708 1
    
d1710 1
a1710 1
	accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
d1715 3
a1717 1
    /* Draw disabled 3D text highlight only with the Win95/98 look. */
d1720 3
a1722 2
	if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
	        && (mePtr->accelPtr != NULL)) {
d1727 3
a1729 3
	            ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
	        Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
		        mePtr->accelLength, leftEdge + 1, baseline + 1);
d1736 1
a1736 1
	Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, 
d1746 2
a1747 2
 *	This function draws the arrow bitmap on the right side of a
 *	a menu entry. This function is currently unused.
d1759 14
a1772 15
DrawMenuEntryArrow(menuPtr, mePtr, d, gc,
	activeBorder, x, y, width, height, drawArrow)
    TkMenu *menuPtr;			/* The menu we are drawing */
    TkMenuEntry *mePtr;			/* The entry we are drawing */
    Drawable d;				/* What we are drawing into */
    GC gc;				/* The gc we are drawing with */
    Tk_3DBorder activeBorder;		/* The border when an item is active */
    int x;				/* left edge */
    int y;				/* top edge */
    int width;				/* Width of menu entry */
    int height;				/* Height of menu entry */
    int drawArrow;			/* For cascade menus, whether of not
					 * to draw the arraw. I cannot figure
					 * out Windows' algorithm for where
					 * to draw this. */
d1778 4
a1781 3
    if (!drawArrow || (mePtr->type != CASCADE_ENTRY) ||
            (mePtr->state != ENTRY_DISABLED))
        return;
d1786 4
a1789 1
    /* Set bitmap bg to highlight color if the menu is highlighted */
d1791 5
a1795 6
        XColor *activeBgColor = Tk_3DBorderColor(Tk_Get3DBorderFromObj(
                mePtr->menuPtr->tkwin,
                (mePtr->activeBorderPtr == NULL) ?
                mePtr->menuPtr->activeBorderPtr :
                mePtr->activeBorderPtr));
        gc->background = activeBgColor->pixel;
d1806 1
a1806 1
            ALIGN_BITMAP_RIGHT);
d1824 1
a1824 2
 *	Commands are output to X to display the menu in its
 *	current mode.
d1828 1
d1831 10
a1840 10
    TkMenu *menuPtr;			/* The menu we are drawing */
    TkMenuEntry *mePtr;			/* The entry we are drawing */
    Drawable d;				/* What we are drawing into */
    GC gc;				/* The gc we are drawing with */
    Tk_Font tkfont;			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;	/* The precalculated font metrics */
    int x;				/* left edge */
    int y;				/* top edge */
    int width;				/* width of item */
    int height;				/* height of item */
d1850 1
a1850 1
    Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, 
d1859 1
a1859 2
 *	On appropriate platforms, draw the underline character for the
 *	menu.
d1865 1
a1865 2
 *	Commands are output to X to display the menu in its
 *	current mode.
d1869 1
d1872 10
a1881 10
    TkMenu *menuPtr,			/* The menu to draw into */
    TkMenuEntry *mePtr,			/* The entry we are drawing */
    Drawable d,				/* What we are drawing into */
    GC gc,				/* The gc to draw into */
    Tk_Font tkfont,			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr,	/* The precalculated font metrics */
    int x,				/* Left Edge */
    int y,				/* Top Edge */
    int width,				/* Width of entry */
    int height)				/* Height of entry */
d1884 1
a1884 1
	char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
d1890 1
a1890 1
    		y + (height + fmPtr->ascent - fmPtr->descent) / 2, 
d1892 1
a1892 1
    }		
d1900 4
a1903 4
 *	This procedure is invoked when keys related to pulling
 *	down menus is pressed. The corresponding Windows events
 *	are generated and passed to DefWindowProc if appropriate.
 *	This cmd is registered as tk::WinMenuKey in the interp.
d1909 1
a1909 2
 *	The menu system may take over and process user events
 *	for menu input.
d1941 1
a1941 1
        return TCL_ERROR;
d1947 1
a1947 1
        return TCL_ERROR;
d1956 1
a1956 2
		    WM_SYSKEYDOWN, VK_MENU, (scanCode << 16)
		    | (1 << 29));
d1979 1
a1979 2
				Tk_GetHWND(Tk_WindowId(tkwin)),
				WM_SYSCHAR,
d2024 2
a2025 2
 *	For every interp, initializes the bindings for Windows
 *	menus. Does nothing on Mac or XWindows.
d2031 3
a2033 3
 *	bindings are setup for the interp which will
 *	handle Alt-key sequences for menus without beeping
 *	or interfering with user-defined Alt-key bindings.
d2040 3
a2042 2
    Tcl_Interp *interp;		    /* The interpreter to set. */
    Tk_BindingTable bindingTable;   /* The table to add to. */
d2047 5
a2051 5
     * We need to set up the bindings for menubars. These have to
     * recreate windows events, so we need to invoke C code to
     * generate the WM_SYSKEYDOWNS and WM_SYSKEYUPs appropriately.
     * Trick is, we can't create a C level binding directly since
     * we may want to modify the binding in Tcl code.
d2058 23
a2080 47
    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<Alt_L>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<KeyRelease-Alt_L>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<Alt_R>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<KeyRelease-Alt_R>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<Alt-KeyPress>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<Alt-KeyRelease>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<KeyPress-F10>",
        "tk::WinMenuKey %W %N",
        0);

    (void) Tk_CreateBinding(interp, bindingTable,
        (ClientData) uid,
        "<KeyRelease-F10>",
        "tk::WinMenuKey %W %N",
        0);
d2088 1
a2088 1
 *	This procedure draws the label part of a menu.
d2099 1
d2102 10
a2111 10
    TkMenu *menuPtr,			/* The menu we are drawing */
    TkMenuEntry *mePtr,			/* The entry we are drawing */
    Drawable d,				/* What we are drawing into */
    GC gc,				/* The gc we are drawing into */
    Tk_Font tkfont,			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr,	/* The precalculated font metrics */
    int x,				/* left edge */
    int y,				/* right edge */
    int width,				/* width of entry */
    int height)				/* height of entry */
d2113 1
a2113 1
    int indicatorSpace =  mePtr->indicatorSpace;
d2132 1
a2132 1
        haveImage = 1;
d2139 3
a2141 2
        if (mePtr->labelLength > 0) {
	    char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
d2145 1
a2145 1
        }
d2147 1
a2147 1
    
d2155 29
a2183 32
	    case COMPOUND_TOP: {
		textXOffset = (fullWidth - textWidth)/2;
		textYOffset = imageHeight/2 + 2;
		imageXOffset = (fullWidth - imageWidth)/2;
		imageYOffset = -textHeight/2;
		break;
	    }
	    case COMPOUND_BOTTOM: {
		textXOffset = (fullWidth - textWidth)/2;
		textYOffset = -imageHeight/2;
		imageXOffset = (fullWidth - imageWidth)/2;
		imageYOffset = textHeight/2 + 2;
		break;
	    }
	    case COMPOUND_LEFT: {
		/*
		 * The standard image position on Windows is in the indicator
		 * space to the left of the entries, unless this entry is a
		 * radio|check button because then the indicator space will
		 * be used.
		 */
		textXOffset = imageWidth + 2;
		textYOffset = 0;
		imageXOffset = 0;
		imageYOffset = 0;
		if ((mePtr->type != CHECK_BUTTON_ENTRY) 
			&& (mePtr->type != RADIO_BUTTON_ENTRY)) {
		    textXOffset -= indicatorSpace;
		    if (textXOffset < 0) {
			textXOffset = 0;
		    }
		    imageXOffset = -indicatorSpace;
d2185 1
a2185 1
		break;
d2187 15
a2201 15
	    case COMPOUND_RIGHT: {
		textXOffset = 0;
		textYOffset = 0;
		imageXOffset = textWidth + 2;
		imageYOffset = 0;
		break;
	    }
	    case COMPOUND_CENTER: {
		textXOffset = (fullWidth - textWidth)/2;
		textYOffset = 0;
		imageXOffset = (fullWidth - imageWidth)/2;
		imageYOffset = 0;
		break;
	    }
	    case COMPOUND_NONE: {break;}
d2209 1
a2209 1
    
d2219 1
a2219 1
	            (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
d2223 1
a2223 1
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
d2227 2
a2228 2
    	XCopyPlane(menuPtr->display, bitmap, d,	gc, 0, 0, 
		(unsigned) imageWidth, (unsigned) imageHeight, 
d2235 2
a2236 1
	    char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
d2238 8
a2245 5
	        /* Win 95/98 systems draw disabled menu text with a
	         * 3D highlight, unless the menu item is highlighted */
	        if ((mePtr->state == ENTRY_DISABLED) &&
	                ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
	            COLORREF oldFgColor = gc->foreground;
d2247 3
a2249 3
	            Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, 
		            mePtr->labelLength, leftEdge + textXOffset + 1, 
		            baseline + textYOffset + 1);
d2251 1
a2251 1
	        }
d2253 2
a2254 2
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, 
		    mePtr->labelLength, leftEdge + textXOffset, 
d2256 2
a2257 3
	    DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, 
	            x + textXOffset, y + textYOffset,
		    width, height);
d2265 1
a2265 1
	} else if ((mePtr->image != NULL) 
d2280 2
a2281 2
 *	This procedure is invoked to recompute the size and
 *	layout of a menu that is a menubar clone.
d2287 2
a2288 3
 *	Fields of menu entries are changed to reflect their
 *	current positions, and the size of the menu window
 *	itself may be changed.
d2305 1
a2305 1
 *	This procedure draws the background part of a menu.
d2311 1
a2311 2
 *	Commands are output to X to display the menu in its
 *	current mode.
d2318 6
a2323 6
    TkMenu *menuPtr;			/* The menu we are drawing */
    TkMenuEntry *mePtr;			/* The entry we are drawing */
    Drawable d;				/* The drawable we are drawing into */
    GC gc;				/* The gc we are drawing with */
    Tk_Font tkfont;			/* The font we are drawing with */
    CONST Tk_FontMetrics *fmPtr;	/* The metrics we are drawing with */
d2336 1
a2336 1
    
d2341 1
a2341 1
    maxX  = width - 1;
d2363 2
a2364 2
 *	Returns standard TCL result. If TCL_ERROR is returned, then
 *	the interp's result contains an error message.
d2367 2
a2368 2
 *	Configuration information get set for mePtr; old resources
 *	get freed, if any need it.
d2375 2
a2376 3
    register TkMenuEntry *mePtr;	/* Information about menu entry;  may
					 * or may not already have values for
					 * some fields. */
d2392 2
a2393 2
 *	Draws the given menu entry at the given coordinates with the
 *	given attributes.
d2405 1
a2405 1
TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height, 
d2407 3
a2409 3
    TkMenuEntry *mePtr;		    /* The entry to draw */
    Drawable d;			    /* What to draw into */
    Tk_Font tkfont;		    /* Precalculated font for menu */
d2411 9
a2419 9
				    /* Precalculated metrics for menu */
    int x;			    /* X-coordinate of topleft of entry */
    int y;			    /* Y-coordinate of topleft of entry */
    int width;			    /* Width of the entry rectangle */
    int height;			    /* Height of the current rectangle */
    int strictMotif;		    /* Boolean flag */
    int drawArrow;		    /* Whether or not to draw the cascade
				     * arrow for cascade items. Only applies
				     * to Windows. */
d2443 1
a2443 1
    	
d2447 1
a2447 1
	    name = Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
d2494 3
a2496 3
     * Need to draw the entire background, including padding. On Unix,
     * for menubars, we have to draw the rest of the entry taking
     * into account the padding.
d2498 2
a2499 2
    
    DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, 
d2501 1
a2501 1
    
d2503 1
a2503 1
	DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, 
d2541 6
a2546 7
    TkMenuEntry *mePtr;			/* The entry we are computing */
    Tk_Font tkfont;			/* The precalculated font */
    CONST Tk_FontMetrics *fmPtr;	/* The precalculated metrics */
    int *widthPtr;			/* The resulting width of the label
					 * portion */
    int *heightPtr;			/* The resulting height of the label
					 * portion */
d2550 1
a2550 1
 
d2562 1
a2562 1
    	
d2564 3
a2566 1
	/* We don't care about the text in this case */
d2568 4
a2571 1
	/* Either it is compound or we don't have an image */
d2574 2
a2575 1
	    char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
d2580 16
a2595 8
		    case COMPOUND_TOP:
		    case COMPOUND_BOTTOM: {
			if (textWidth > *widthPtr) {
			    *widthPtr = textWidth;
			}
			/* Add text and padding */
			*heightPtr += fmPtr->linespace + 2;
			break;
d2597 10
a2606 8
		    case COMPOUND_LEFT:
		    case COMPOUND_RIGHT: {
			if (fmPtr->linespace > *heightPtr) {
			    *heightPtr = fmPtr->linespace;
			}
			/* Add text and padding */
			*widthPtr += textWidth + 2;
			break;
d2608 2
a2609 8
		    case COMPOUND_CENTER: {
			if (fmPtr->linespace > *heightPtr) {
			    *heightPtr = fmPtr->linespace;
			}
			if (textWidth > *widthPtr) {
			    *widthPtr = textWidth;
			}
			break;
d2611 3
a2613 1
		    case COMPOUND_NONE: {break;}
d2615 5
a2619 2
    	} else {
		/* We don't have an image or we're not compound */
d2624 4
a2627 1
	    /* An empty entry still has this height */
d2639 1
a2639 1
 *	This procedure draws the background part of a menu.
d2645 1
a2645 2
 *	Commands are output to X to display the menu in its
 *	current mode.
d2652 9
a2660 9
    TkMenu *menuPtr,			/* The menu we are drawing. */
    TkMenuEntry *mePtr,			/* The entry we are drawing. */
    Drawable d,				/* What we are drawing into */
    Tk_3DBorder activeBorder,		/* Border for active items */
    Tk_3DBorder bgBorder,		/* Border for the background */
    int x,				/* left edge */
    int y,				/* top edge */
    int width,				/* width of rectangle to draw */
    int height)				/* height of rectangle to draw */
d2662 1
a2662 1
    if (mePtr->state == ENTRY_ACTIVE 
d2666 2
a2667 2
    Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
    	    x, y, width, height, 0, TK_RELIEF_FLAT);
d2675 2
a2676 2
 *	This procedure is invoked to recompute the size and
 *	layout of a menu that is not a menubar clone.
d2682 2
a2683 3
 *	Fields of menu entries are changed to reflect their
 *	current positions, and the size of the menu window
 *	itself may be changed.
d2698 1
a2698 1
    
d2703 1
a2703 1
    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin, 
d2710 7
a2716 8
     * On the Mac especially, getting font metrics can be quite slow,
     * so we want to do it intelligently. We are going to precalculate
     * them and pass them down to all of the measuring and drawing
     * routines. We will measure the font metrics of the menu once.
     * If an entry does not have its own font set, then we give
     * the geometry/drawing routines the menu's font and metrics.
     * If an entry has its own font, we will measure that font and
     * give all of the geometry/drawing the entry's font and metrics.
d2759 1
a2759 1
	    GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont, 
d2762 1
a2763 1
	    
d2765 6
a2770 7
	     * For each entry, compute the height required by that
	     * particular entry, plus three widths:  the width of the
	     * label, the width to allow for an indicator to be displayed
	     * to the left of the label (if any), and the width of the
	     * accelerator to be displayed to the right of the label
	     * (if any).  These sizes depend, of course, on the type
	     * of the entry.
d2772 1
a2772 1
	    
d2779 1
a2779 1
	
d2789 1
a2789 1
	    GetMenuIndicatorGeometry(menuPtr, menuPtr->entries[i], tkfont, 
d2800 1
a2800 1
        menuPtr->entries[i]->y = y;
d2823 1
a2823 1
    
d2825 2
a2826 2
     * The X server doesn't like zero dimensions, so round up to at least
     * 1 (a zero-sized menu should never really occur, anyway).
d2844 2
a2845 2
 *	Generates a "MenuSelect" virtual event. This can be used to
 *	do context-sensitive menu help.
d2863 1
a2863 1
   
d2873 1
a2873 1
    
d2891 2
a2892 2
 *	menuName becuase a toplevel has been created and any system
 *	menus need to be created.
d2905 2
a2906 3
    Tcl_Interp *interp,			/* The interp the menu lives in. */
    char *menuName)			/* The name of the menu to 
					 * reconfigure. */
d2916 1
a2916 1
		if ((menuPtr->menuType == MENUBAR) 
d2919 1
a2919 1
		    Tcl_DoWhenIdle(ReconfigureWindowsMenu, 
d2932 2
a2933 2
 *	Throws away the utility window needed for menus and unregisters
 *	the class.
d2948 2
a2949 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d2967 3
a2969 3
 *	Returns a Tcl_Obj * with the default value. If there is no
 *	Windows-specific default for this attribute, returns NULL.
 *	This object has a ref count of 0.
d2989 1
a2989 2
	valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString),
		-1);
d3014 2
a3015 2
    int firstTime)		    /* Is this the first time this
				     * has been called? */
d3021 1
a3021 1
    int bold = 0; 
d3029 2
a3030 2
     * Set all of the default options. The loop will terminate when we run 
     * out of options via a break statement.
d3064 1
a3064 1
    
d3077 1
a3077 1
	Tcl_DStringAppendElement(&menuFontDString, 
d3083 2
a3084 2
     * appropriate margins. Since this is fairly hairy, we do it here
     * to save time when traversing large sets of menu items.
d3086 2
a3087 3
     * The code below was given to me by Microsoft over the phone. It
     * is the only way to insure menu items lining up, and is not
     * documented.
d3093 1
a3093 1
		GetSystemMetrics(SM_CXBORDER) 
d3100 1
a3100 1
   }
d3123 2
a3124 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d3136 2
a3137 2
    if(!RegisterClass(&wndClass)) {
	panic("Failed to register menu window class.");
d3141 1
a3141 1
	0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
d3143 2
a3144 2
    if(!tsdPtr->menuHWND) {
	panic("Failed to create the menu window.");
d3149 2
a3150 2
    if(!RegisterClass(&wndClass)) {
	panic ("Failed to register embedded menu window class.");
d3153 3
a3155 2
    tsdPtr->embeddedMenuHWND = CreateWindow(EMBEDDED_MENU_CLASS_NAME, "EmbeddedMenuWindow", WS_POPUP,
	0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
d3157 2
a3158 2
    if(!tsdPtr->embeddedMenuHWND) {
	panic("Failed to create the embedded menu window.");
d3170 4
a3173 5
 *	This function returns the HWND of a hidden menu Window that
 *	processes messages of a popup menu.  This hidden menu window
 *	is used to handle either a dynamic popup menu in the same 
 *	process or a pull-down menu of an embedded window in a 
 *	different process.
d3188 2
a3189 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d3213 2
a3214 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d3219 8
@


1.43
log
@Fixed a bug by adding code the check menu index in selection.  This bug caused an access violation in an embedded menu testing when the mouse clicked the last pull-down menu entry
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.42 2005/01/17 07:00:11 chengyemao Exp $
d1242 2
a1243 2
		    if (flags != 0xFFFF && entryIndex < menuPtr->numEntries) {
			if (flags & MF_POPUP) {
@


1.42
log
@minor bug fix: should return 0 and indicate handled after processing WM_MENUSELECT message
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.41 2005/01/13 01:48:03 chengyemao Exp $
d1240 1
d1242 1
a1242 1
		    if (flags != 0xFFFF) {
d1244 1
a1244 1
			    mePtr = menuPtr->entries[LOWORD(*pwParam)];
d1248 1
a1248 1
				    (char *) LOWORD(*pwParam));
@


1.41
log
@Removed WM_UNINITMENUPOPUP that may cause compiling error in WINVER < 0x0500
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.40 2005/01/09 06:59:20 chengyemao Exp $
d1099 2
a1101 2
	    *plResult = 0;
	    returnResult = 1;
a1212 2
		*plResult = 1;
		returnResult = 1;
d1214 2
d1265 2
@


1.40
log
@bug fix [637653]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.39 2005/01/09 00:26:59 chengyemao Exp $
d935 1
a935 1
    static nPopupMenus = 0, nIdles = 0;
a949 1
	nPopupMenus++;
a951 4
	case WM_UNINITMENUPOPUP:
	nPopupMenus--;
 	break;

@


1.39
log
@Bug fix in ReconfigureWindowsMenu.  The bug caused a wrong geometry of a toplevel when created with a menu (bug# 1098625)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.38 2005/01/04 02:09:45 chengyemao Exp $
d1145 1
a1145 1
	    if (itemPtr != NULL) {
d1174 1
a1174 1
	    if (itemPtr != NULL) {
@


1.38
log
@Modified for separating an embedded menu's window handler from a normal popup menu window's handler; improved an embedded menu display in Windows/XP
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.37 2004/12/28 08:45:31 chengyemao Exp $
a540 1
    int width, height;
a552 6
    if ((menuPtr->menuType == MENUBAR)
	    && (menuPtr->parentTopLevelPtr != NULL)) {
	width = Tk_Width(menuPtr->parentTopLevelPtr);
	height = Tk_Height(menuPtr->parentTopLevelPtr);
    }

a703 1
	Tk_GeometryRequest(menuPtr->parentTopLevelPtr, width, height);
@


1.37
log
@Modified to support embedded menu widget
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.36 2004/09/21 19:13:58 mdejong Exp $
d26 1
d64 1
d169 3
a171 1

d896 89
a1117 1

d2987 3
d3172 3
a3174 1
    RegisterClass(&wndClass);
d3179 17
d3227 1
a3227 1
    return tsdPtr->menuHWND;
@


1.36
log
@	* generic/tkInt.decls: Add decl for TkWinGetPlatformTheme.
	It is only defined under Win32.
	* generic/tkIntPlatDecls.h: Regen.
	* generic/tkStubInit.c: Regen.
	* win/tkWinInt.h: Define TK_THEME_WIN_CLASSIC and
	TK_THEME_WIN_XP.
	* win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryLabel):
	Draw a disabled 3D text highlight for the accelerator only
	with the Win95/98 look. Same goes for the menu entry text.
	* win/tkWinX.c (TkWinGetPlatformId, TkWinGetPlatformTheme):
	Automatically detect the Windows theme in use and return
	either TK_THEME_WIN_CLASSIC or TK_THEME_WIN_XP when the
	TkWinGetPlatformTheme function is invoked.
	[Patch 866194]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.35 2004/09/03 14:09:05 dkf Exp $
d3085 30
@


1.35
log
@Make sure user_data is NULL everywhere it isn't set. [Bug 1021812]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.34 2004/08/25 22:23:33 dgp Exp $
d1605 4
a1608 2
 *	This procedure draws the accelerator part of a menu. We
 *	need to decide what to draw here. Should we replace strings
d1615 1
a1615 1
 *	Commands are output to X to display the menu in its
d1646 14
a1659 9
    if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
	    && (mePtr->accelPtr != NULL)) {
	COLORREF oldFgColor = gc->foreground;

	gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	if ((mePtr->accelPtr != NULL) &&
	        ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
		    mePtr->accelLength, leftEdge + 1, baseline + 1);
a1660 2

	gc->foreground = oldFgColor;
d2190 12
a2201 10
	    /* Win 95/98 systems draw disabled menu text with a
	     * 3D highlight, unless the menu item is highlighted */
	    if ((mePtr->state == ENTRY_DISABLED) &&
	            ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)){
	        COLORREF oldFgColor = gc->foreground;
		gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	        Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, 
		        mePtr->labelLength, leftEdge + textXOffset + 1, 
		        baseline + textYOffset + 1);
		gc->foreground = oldFgColor;
d2209 1
a2209 1
    	}
@


1.34
log
@        * macosx/tkMacOSXWm.c:  Made use of Tcl_WrongNumArgs in a few
        * win/tkWinMenu.c:      appropriate spots.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.33 2004/05/03 23:23:14 hobbs Exp $
d2815 1
@


1.33
log
@	* win/tkWinMenu.c, unix/tkUnixMenu.c (DrawMenuEntryLabel): place
	images of compound menu entries in indicator space if not a radio
	of checkbutton. [Bug #756952] (eserte)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.32 2004/05/03 22:40:30 hobbs Exp $
d1853 1
a1853 3
	Tcl_AppendResult(interp, "wrong # args: should be \"",
	        Tcl_GetString(objv[0]),
	        " window keySym\"", (char *) NULL);
@


1.32
log
@	* win/tkWinX.c:                fix drawing of unicode chars in menu
	* win/tkWinInt.h (TkWinProcs): titles. [Bug #904371] (riefenstahl)
	* win/tkWinMenu.c (ReconfigureWindowsMenu):
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.31 2004/01/07 13:25:56 vincentdarley Exp $
d2119 4
a2122 5
		 * The standard image position on Windows is
		 * in the indicator space to the left of
		 * the entries.  Of course if this entry is
		 * a radio/check button, we can't do that 
		 * because the indicator space will be used.
d2124 7
a2130 8
		if ((mePtr->type == CHECK_BUTTON_ENTRY) 
		  || (mePtr->type == RADIO_BUTTON_ENTRY)) {
		    textXOffset = imageWidth + 2;
		    textYOffset = 0;
		    imageXOffset = 0;
		    imageYOffset = 0;
		} else {
		    textXOffset = imageWidth + 2 - indicatorSpace;
a2133 1
		    textYOffset = 0;
a2134 1
		    imageYOffset = 0;
@


1.31
log
@disabled submenu fix
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.30 2003/12/28 23:11:10 mdejong Exp $
d577 1
a577 1
	    Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);
d689 2
a690 1
	    InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
@


1.30
log
@	* win/tkWinMenu.c (ReconfigureWindowsMenu,
	TkWinHandleMenuEvent, DrawMenuEntryArrow):
	Fix drawing of a disabled cascade menu
	arrow. Tk was displaying a disabled cascade
	menu arrow in black instead of gray. This
	was caused by a bug in the Win32 code for
	user drawn menu items. The fix is to avoid
	telling Windows that the menu item is a
	cascade type and then draw the gray arrow
	bitmap on our own.
	[Patch 865842]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.29 2003/12/28 05:04:18 mdejong Exp $
d132 1
a132 1
static void		FreeID _ANSI_ARGS_((int commandID));
d154 1
a154 1
			    int *menuIDPtr));
d193 1
a193 1
    int *menuIDPtr;		/* The resulting id */
d222 1
a222 1
    	*menuIDPtr = (int) returnID;
d248 1
a248 1
    int commandID;
d421 1
a421 1
    FreeID((int) mePtr->platformEntryData);
d619 1
a619 1
	itemID = (int) mePtr->platformEntryData;
d626 6
a631 3
		itemID = (UINT) childMenuHdl;
		/* Win32 draws the popup arrow in the wrong color    *
		 * for a disabled cascade menu, so do it by hand.    */
d634 5
d838 1
a838 1
    int commandID;
d1178 3
@


1.29
log
@	* win/tkWinMenu.c (DrawWindowsSystemBitmap):
	Fix a strange Win32 bug where the logical
	coordinates returned by a call to DPtoLP
	are wrong the first time a menu is posted.
	This bug manifested itself by drawing the
	bitmap in the wrong place in a menu.
	The fix was to pass the newly created DC
	instead of the DC from the window.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.28 2003/12/26 22:29:07 mdejong Exp $
d579 1
d627 5
a631 1
		flags |= MF_POPUP;
d1079 1
d1108 6
d1122 1
a1122 1
			- itemPtr->rcItem.top, 0, 0);
d1686 34
a1719 29
    if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
	    && ((mePtr->type == CASCADE_ENTRY) && drawArrow)) {
	COLORREF oldFgColor = gc->foreground;

	gc->foreground = GetSysColor(COLOR_3DHILIGHT);

	if (mePtr->type == CASCADE_ENTRY) {
	    RECT rect;

	    rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1;
	    rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1;
	    rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1;
	    rect.right = x + width;
	    DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, 
		    OBM_MNARROW, ALIGN_BITMAP_RIGHT);
	}
	gc->foreground = oldFgColor;
    }

    if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {
	RECT rect;

	rect.top = y + GetSystemMetrics(SM_CYBORDER);
	rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER);
	rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth;
	rect.right = x + width - 1;
	DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW, 
		ALIGN_BITMAP_RIGHT);
    }
@


1.28
log
@	* win/tkWinMenu.c (DrawMenuEntryAccelerator,
	DrawMenuEntryLabel): When drawing the label
	text and accelerator text for a disabled
	menu entry be sure to draw a 3D highlight.
	The only exception to this is when a
	disabled menu entry is highlighted, in that
	case do not draw a 3D hightlight.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.27 2003/12/26 20:46:03 mdejong Exp $
d1474 1
a1474 1
    DPtoLP(hdc, &ptSize, 1);
@


1.27
log
@	* win/tkWinMenu.c (DrawMenuEntryAccelerator,
	DrawMenuEntryArrow): Move the unused menu
	arrow drawing code in DrawMenuEntryAccelerator
	into a new function named DrawMenuEntryArrow.
	This makes no functional change but it will
	make it easier to fix things in the future.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.26 2003/12/21 23:50:13 davygrvy Exp $
d1625 2
a1626 1
	if (mePtr->accelPtr != NULL) {
d2162 11
@


1.26
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
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.25 2003/12/16 03:12:51 davygrvy Exp $
d94 5
d1597 1
a1597 1
	activeBorder, x, y, width, height, drawArrow)
a1608 4
    int drawArrow;			/* For cascade menus, whether of not
					 * to draw the arraw. I cannot figure
					 * out Windows' algorithm for where
					 * to draw this. */
d1621 1
a1621 2
	    && ((mePtr->accelPtr != NULL)
		    || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {
d1630 49
a1691 5
    if (mePtr->accelPtr != NULL) {
	Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, 
		mePtr->accelLength, leftEdge, baseline);
    }

d2424 2
@


1.25
log
@(ReconfigureWindowsMenu) : Only redraw the menubar when a menubar
exists.  Although the invalid handle doesn't cause an exception, it was
discovered with NuMega's BoundsChecker and flagged as a problem.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.24 2003/10/31 08:55:03 vincentdarley Exp $
d2993 1
a2993 1
    Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
@


1.24
log
@compound menu entries
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.23 2003/04/15 01:06:09 mdejong Exp $
d683 5
a687 1
	DrawMenuBar(TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr));
@


1.23
log
@	* win/tkWinMenu.c (TkpInitializeMenuBindings):
	Rename the private menu helper cmd from
	tk::tkWinMenuKey to tk::WinMenuKey.
	[Bug 721514]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.22 2003/04/14 23:34:50 mdejong Exp $
d2040 22
a2061 4
		textXOffset = imageWidth + 2;
		textYOffset = 0;
		imageXOffset = 0;
		imageYOffset = 0;
@


1.22
log
@	* generic/tkBind.c (TkpGetBindingXEvent): Add helper method
	that can be used to query the XEvent* for the currently
	executing binding.
	* generic/tkInt.h: Declare TkpGetBindingXEvent.
	* win/tkWinMenu.c (MenuKeyBindProc, TkWinMenuKeyObjCmd,
	TkpInitializeMenuBindings): Rename MenuKeyBindProc to
	TkWinMenuKeyObjCmd and convert it into a Tcl command
	named tk::tkWinMenuKey. Bind keyboard accelerator
	actions to this Tcl command instead of using a native
	C binding. This makes it possible to extend the
	existing binding with Tcl code and makes the Windows
	version work just like the unix version.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21 2002/08/08 01:42:57 hobbs Exp $
d1747 1
a1747 1
 *	This cmd is registered as tk::tkWinMenuKey in the interp.
d1902 1
a1902 1
    (void) Tcl_CreateObjCommand(interp, "tk::tkWinMenuKey",
d1909 1
a1909 1
        "tk::tkWinMenuKey %W %N",
d1915 1
a1915 1
        "tk::tkWinMenuKey %W %N",
d1921 1
a1921 1
        "tk::tkWinMenuKey %W %N",
d1927 1
a1927 1
        "tk::tkWinMenuKey %W %N",
d1933 1
a1933 1
        "tk::tkWinMenuKey %W %N",
d1939 1
a1939 1
        "tk::tkWinMenuKey %W %N",
d1945 1
a1945 1
        "tk::tkWinMenuKey %W %N",
d1951 1
a1951 1
        "tk::tkWinMenuKey %W %N",
@


1.21
log
@	* win/tkWinMenu.c (TkpSetWindowMenuBar): fixed logic bug in when
	to idle call ReconfigureWindowsMenu.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.20 2002/08/05 04:30:41 dgp Exp $
d150 3
a152 4
static int		MenuKeyBindProc _ANSI_ARGS_((
			    ClientData clientData, 
			    Tcl_Interp *interp, XEvent *eventPtr,
			    Tk_Window tkwin, KeySym keySym));
d1742 1
a1742 1
 * MenuKeyBindProc --
d1747 1
d1760 5
a1764 6
MenuKeyBindProc(clientData, interp, eventPtr, tkwin, keySym)
    ClientData clientData;	/* not used in this proc */
    Tcl_Interp *interp;		/* The interpreter of the receiving window. */
    XEvent *eventPtr;		/* The XEvent to process */
    Tk_Window tkwin;		/* The window receiving the event */
    KeySym keySym;		/* The key sym that is produced. */
d1768 4
a1771 1
    TkWindow *winPtr = (TkWindow *)tkwin;
d1774 24
d1866 1
a1866 1
}   
d1880 1
a1880 1
 *	C-level bindings are setup for the interp which will
d1896 4
a1899 3
     * recreate windows events, so we need to have a C-level
     * binding for this. We have to generate the WM_SYSKEYDOWNS
     * and WM_SYSKEYUPs appropriately.
d1901 52
a1952 17
    
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, 
	    "<Alt_L>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
	    "<KeyRelease-Alt_L>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, 
	    "<Alt_R>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
	    "<KeyRelease-Alt_R>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
	    "<Alt-KeyPress>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
	    "<Alt-KeyRelease>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
	    "<KeyPress-F10>", MenuKeyBindProc, NULL, NULL);
    TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
	    "<KeyRelease-F10>", MenuKeyBindProc, NULL, NULL);
@


1.21.2.1
log
@	* win/tkWinX.c:                fix drawing of unicode chars in menu
	* win/tkWinInt.h (TkWinProcs): titles. [Bug #904371] (riefenstahl)
	* win/tkWinMenu.c (ReconfigureWindowsMenu):
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21 2002/08/08 01:42:57 hobbs Exp $
d573 1
a573 1
	    Tcl_WinUtfToTChar(itemText, -1, &translatedText);
d672 1
a672 2
	    (*tkWinProcs->insertMenu)(winMenuHdl, 0xFFFFFFFF, flags,
		    itemID, lpNewItem);
@


1.21.2.2
log
@	* win/tkWinMenu.c, unix/tkUnixMenu.c (DrawMenuEntryLabel): place
	images of compound menu entries in indicator space if not a radio
	of checkbutton. [Bug #756952] (eserte)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.1 2004/05/03 22:40:58 hobbs Exp $
a1978 6
		/*
		 * The standard image position on Windows is in the indicator
		 * space to the left of the entries, unless this entry is a
		 * radio|check button because then the indicator space will
		 * be used.
		 */
a1982 8
		if ((mePtr->type != CHECK_BUTTON_ENTRY) 
			&& (mePtr->type != RADIO_BUTTON_ENTRY)) {
		    textXOffset -= indicatorSpace;
		    if (textXOffset < 0) {
			textXOffset = 0;
		    }
		    imageXOffset = -indicatorSpace;
		}
@


1.21.2.3
log
@	* generic/tkInt.decls: Add decl for TkWinGetPlatformTheme.
	It is only defined under Win32.
	* generic/tkIntPlatDecls.h: Regen.
	* generic/tkStubInit.c: Regen.
	* win/tkWinInt.h: Define TK_THEME_WIN_CLASSIC and
	TK_THEME_WIN_XP.
	* win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryLabel):
	Draw a disabled 3D text highlight for the accelerator only
	with the Win95/98 look. Same goes for the menu entry text.
	* win/tkWinX.c (TkWinGetPlatformId, TkWinGetPlatformTheme):
	Automatically detect the Windows theme in use and return
	either TK_THEME_WIN_CLASSIC or TK_THEME_WIN_XP when the
	TkWinGetPlatformTheme function is invoked.
	[Patch 866194]

	* win/tkWinMenu.c: only provide a submenu handle when the
	MF_POPUP flag is given, fixing a recently-introduced crash
	when submenus are disabled.  Also better error checking for
	this sort of situation in the future.

	* win/tkWinMenu.c (ReconfigureWindowsMenu): Fix drawing of a disabled
	(TkWinHandleMenuEvent, DrawMenuEntryArrow): cascade menu arrow. Tk was
	displaying a disabled cascade menu arrow in black instead of
	gray. This was caused by a bug in the Win32 code for user drawn
	menu items. The fix is to avoid telling Windows that the menu item
	is a cascade type and then draw the gray arrow bitmap on our own.
	[Patch 865842]

	* win/tkWinMenu.c (DrawWindowsSystemBitmap): Fix a strange Win32
	bug where the logical coordinates returned by a call to DPtoLP are
	wrong the first time a menu is posted.  This bug manifested itself
	by drawing the bitmap in the wrong place in a menu.  The fix was
	to pass the newly created DC instead of the DC from the window.

	* win/tkWinMenu.c (DrawMenuEntryAccelerator):
	(DrawMenuEntryLabel): When drawing the label text and accelerator
	text for a disabled menu entry be sure to draw a 3D highlight.
	The only exception to this is when a disabled menu entry is
	highlighted, in that case do not draw a 3D hightlight.

	* win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryArrow):
	Move the unused menu arrow drawing code in
	DrawMenuEntryAccelerator into a new function named
	DrawMenuEntryArrow.  This makes no functional change but it will
	make it easier to fix things in the future.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.2 2004/05/03 23:23:42 hobbs Exp $
a93 5
			    int width, int height));
static void		DrawMenuEntryArrow _ANSI_ARGS_((
			    TkMenu *menuPtr, TkMenuEntry *mePtr, 
			    Drawable d, GC gc,
			    Tk_3DBorder activeBorder, int x, int y,
d127 1
a127 1
static void		FreeID _ANSI_ARGS_((WORD commandID));
d149 1
a149 1
			    WORD *menuIDPtr));
d189 1
a189 1
    WORD *menuIDPtr;		/* The resulting id */
d218 1
a218 1
    	*menuIDPtr = returnID;
d244 1
a244 1
    WORD commandID;
d417 1
a417 1
    FreeID((WORD) mePtr->platformEntryData);
a574 1
	    flags |= MF_STRING;
d614 1
a614 1
	itemID = (UINT) mePtr->platformEntryData;
d621 2
a622 14
		/* 
		 * Win32 draws the popup arrow in the wrong color 
		 * for a disabled cascade menu, so do it by hand.
		 * Given it is disabled, there's no need for it to
		 * be connected to its child.
		 */
		if (mePtr->state != ENTRY_DISABLED) {
		    flags |= MF_POPUP;
		    /*
		     * If the MF_POPUP flag is set, then the id
		     * is interpreted as the handle of a submenu.
		     */
		    itemID = (UINT) childMenuHdl;
		}	
d818 1
a818 1
    WORD commandID;
a1066 1
	    int drawArrow = 0;
a1094 6
		    /* Also, set the drawArrow flag for a disabled cascade
		    ** menu since we need to draw the arrow ourselves.
		    */
		    if (mePtr->type == CASCADE_ENTRY) {
		        drawArrow = 1;
		    }
d1103 1
a1103 1
			- itemPtr->rcItem.top, 0, drawArrow);
a1150 3
			if (mePtr->index >= menuPtr->numEntries) {
			    Tcl_Panic("Trying to activate an entry which doesn't exist.");
			}
d1467 1
a1467 1
    DPtoLP(scratchDC, &ptSize, 1);
d1574 2
a1575 4
 *	This procedure draws the accelerator part of a menu.
 *	For example, the string "CTRL-Z" could be drawn to
 *	to the right of the label text for an Undo menu entry.
 *	Need to decide what to draw here. Should we replace strings
d1582 1
a1582 1
 *	Commands are output to display the menu in its
d1590 1
a1590 1
	activeBorder, x, y, width, height)
d1602 4
d1617 13
a1629 1
    /* Draw disabled 3D text highlight only with the Win95/98 look. */
d1631 6
a1636 12
    if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) {
	if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
	        && (mePtr->accelPtr != NULL)) {
	    COLORREF oldFgColor = gc->foreground;

	    gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	    if ((mePtr->accelPtr != NULL) &&
	            ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
	        Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
		        mePtr->accelLength, leftEdge + 1, baseline + 1);
	    }
	    gc->foreground = oldFgColor;
d1638 1
a1644 18
}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryArrow --
 *
 *	This function draws the arrow bitmap on the right side of a
 *	a menu entry. This function is currently unused.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
d1646 10
a1655 51
void
DrawMenuEntryArrow(menuPtr, mePtr, d, gc,
	activeBorder, x, y, width, height, drawArrow)
    TkMenu *menuPtr;			/* The menu we are drawing */
    TkMenuEntry *mePtr;			/* The entry we are drawing */
    Drawable d;				/* What we are drawing into */
    GC gc;				/* The gc we are drawing with */
    Tk_3DBorder activeBorder;		/* The border when an item is active */
    int x;				/* left edge */
    int y;				/* top edge */
    int width;				/* Width of menu entry */
    int height;				/* Height of menu entry */
    int drawArrow;			/* For cascade menus, whether of not
					 * to draw the arraw. I cannot figure
					 * out Windows' algorithm for where
					 * to draw this. */
{
    COLORREF oldFgColor;
    COLORREF oldBgColor;
    RECT rect;

    if (!drawArrow || (mePtr->type != CASCADE_ENTRY) ||
            (mePtr->state != ENTRY_DISABLED))
        return;

    oldFgColor = gc->foreground;
    oldBgColor = gc->background;

    /* Set bitmap bg to highlight color if the menu is highlighted */
    if (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) {
        XColor *activeBgColor = Tk_3DBorderColor(Tk_Get3DBorderFromObj(
                mePtr->menuPtr->tkwin,
                (mePtr->activeBorderPtr == NULL) ?
                mePtr->menuPtr->activeBorderPtr :
                mePtr->activeBorderPtr));
        gc->background = activeBgColor->pixel;
    }

    gc->foreground = GetSysColor(COLOR_GRAYTEXT);

    rect.top = y + GetSystemMetrics(SM_CYBORDER);
    rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER);
    rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth;
    rect.right = x + width;

    DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,
            ALIGN_BITMAP_RIGHT);

    gc->foreground = oldFgColor;
    gc->background = oldBgColor;
    return;
a2047 13
	    if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) {
	        /* Win 95/98 systems draw disabled menu text with a
	         * 3D highlight, unless the menu item is highlighted */
	        if ((mePtr->state == ENTRY_DISABLED) &&
	                ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) {
	            COLORREF oldFgColor = gc->foreground;
		    gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	            Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, 
		            mePtr->labelLength, leftEdge + textXOffset + 1, 
		            baseline + textYOffset + 1);
		    gc->foreground = oldFgColor;
	        }
	    }
d2054 1
a2054 1
	}
a2310 2
		activeBorder, x, adjustedY, width, adjustedHeight);
	DrawMenuEntryArrow(menuPtr, mePtr, d, gc,
@


1.21.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
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.3 2004/09/23 00:56:15 mdejong Exp $
d3017 1
a3017 1
    TkCreateExitHandler(MenuExitHandler, (ClientData) NULL);
@


1.21.2.5
log
@	* win/tkWinMenu.c (FreeID, TkpNewMenu, MenuExitHandler)
	(MenuThreadExitHandler, TkpMenuInit, TkpMenuThreadInit): rework
	Windows menu init/finalization to better respect per-process and
	per-thread boundaries.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.4 2004/10/27 00:37:38 davygrvy Exp $
d57 2
d72 2
a73 2
    Tcl_HashTable commandTable;	/* A map of command ids to menu entries */
    Tcl_HashTable winMenuTable;	/* Need this to map HMENUs back to menuPtrs */
d254 5
a258 10
    /*
     * If the menuHWND is NULL, this table has been finalized already.
     */

    if (tsdPtr->menuHWND != NULL) {
	Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
		(char *) commandID);
	if (entryPtr != NULL) {
	    Tcl_DeleteHashEntry(entryPtr);
	}
d292 1
a292 1

d304 2
a305 2
    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
	    (char *) winMenuHdl, &newEntry);
d373 2
a376 1
	 * If the menuHWND is NULL, this table has been finalized already.
d379 4
a382 6
	if (tsdPtr->menuHWND != NULL) {
	    Tcl_HashEntry *hashEntryPtr =
		Tcl_FindHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl);
	    if (hashEntryPtr != NULL) {
		Tcl_DeleteHashEntry(hashEntryPtr);
	    }
d2809 2
a2810 1
 *	Unregisters the class of utility windows.
d2825 2
a2826 26
    UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
}

/*
 *----------------------------------------------------------------------
 *
 * MenuExitHandler --
 *
 *	Throws away the utility window needed for menus and delete hash
 *	tables.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Menus have to be reinitialized next time.
 *
 *----------------------------------------------------------------------
 */

static void
MenuThreadExitHandler(
    ClientData clientData)	    /* Not used */
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d2829 1
a2829 4
    tsdPtr->menuHWND = NULL;

    Tcl_DeleteHashTable(&tsdPtr->winMenuTable);
    Tcl_DeleteHashTable(&tsdPtr->commandTable);
d2999 2
d3014 3
a3042 3
    tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
	0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

a3044 2

    Tcl_CreateThreadExitHandler(MenuThreadExitHandler, (ClientData) NULL);
@


1.21.2.6
log
@	* win/tkWinMenu.c (TkpPostMenu): disable menu animation in menus
	with images to avoid clipping bug.  [Bug 1329198]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.5 2006/04/05 19:47:39 hobbs Exp $
a35 4
#ifndef TPM_NOANIMATION
#define TPM_NOANIMATION 0x4000L
#endif

d738 1
a738 1
    int i, result, flags;
a742 1
    TkMenuEntry *mePtr;
d763 1
a763 1

d784 1
a784 1

a804 12
    /*
     * Disable menu animation if an image is present, as clipping isn't
     * handled correctly with temp DCs.  [Bug 1329198]
     */
    for (i = 0; i < menuPtr->numEntries; i++) {
	mePtr = menuPtr->entries[i];
	if (mePtr->image != NULL) {
	    flags |= TPM_NOANIMATION;
	    break;
	}
    }

@


1.21.2.7
log
@	* win/tkWinMenu.c (TkWinHandleMenuEvent, DrawMenuUnderline):
	handle unichar underlining correctly and safely. [Bug 1599877]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.6 2006/09/21 00:13:54 hobbs Exp $
d508 1
a508 1
	}
d1049 1
a1049 2
		int i, len, underline;
		Tcl_Obj *labelPtr;
d1054 3
d1058 12
a1069 15
		    labelPtr = menuPtr->entries[i]->labelPtr;
		    if ((underline >= 0) && (labelPtr != NULL)) {
			/* do the unicode call just to prevent overruns */
			Tcl_GetUnicodeFromObj(labelPtr, &len);
			if (underline < len) {
			    char *label;
			    label = Tcl_GetStringFromObj(labelPtr, &len);
			    if (CharUpper((LPTSTR) menuChar)
				    == CharUpper((LPTSTR)
					*Tcl_UtfAtIndex(label, underline))) {
				*plResult = (2 << 16) | i;
				returnResult = 1;
				break;
			    }
			}
d1078 1
a1078 1

d1090 1
a1090 1

d1101 1
a1101 1

d1185 2
a1186 2
				&tsdPtr->commandTable,
				(char *) LOWORD(*pwParam));
d1189 1
a1189 1
				    Tcl_GetHashValue(hashEntryPtr);
d1276 1
a1276 1
	Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d1735 4
a1738 4
						     mePtr->menuPtr->tkwin,
						     (mePtr->activeBorderPtr == NULL) ?
						     mePtr->menuPtr->activeBorderPtr :
						     mePtr->activeBorderPtr));
d1803 2
a1804 1
 *	On appropriate platforms, draw the underline character for the menu.
d1828 10
a1837 17
    if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
	int len;

	/* do the unicode call just to prevent overruns */
	Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len);
	if (mePtr->underline < len) {
	    CONST char *label, *start, *end;

	    label = Tcl_GetStringFromObj(mePtr->labelPtr, &len);
	    start = Tcl_UtfAtIndex(label, mePtr->underline);
	    end = Tcl_UtfNext(start);
	    Tk_UnderlineChars(menuPtr->display, d,
		    gc, tkfont, label, x + mePtr->indicatorSpace,
		    y + (height + fmPtr->ascent - fmPtr->descent) / 2,
		    (int) (start - label), (int) (end - label));
	}
    }
@


1.21.2.8
log
@	* unix/tkUnixMenu.c (DrawMenuUnderline): bound Tcl_UtfAtIndex usage
	* tests/menu.test (menu-36.1): [Bug 1599877]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.7 2006/11/24 01:52:08 hobbs Exp $
d1062 1
a1062 1
			    label = Tcl_GetStringFromObj(labelPtr, NULL);
d1836 1
a1836 1
	    label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
@


1.21.2.9
log
@	* win/tkWinMenu.c (TkWinHandleMenuEvent): improve handling to
	allow for unicode char menu indices and not use CharUpper on Tcl
	utf strings. [Bug #1734223]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.8 2006/11/24 18:11:54 hobbs Exp $
d1045 3
a1047 2
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		    (char *) *plParam);
a1050 1
		Tcl_UniChar *wlabel, menuChar;
a1053 6
		/*
		 * Assume we have something directly convertable to
		 * Tcl_UniChar.  True at least for wide systems.
		 */
		menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam));

d1058 12
a1069 9
			/*
			 * Ensure we don't exceed the label length, then check
			 */
			wlabel = Tcl_GetUnicodeFromObj(labelPtr, &len);
			if ((underline < len) && (menuChar ==
				    Tcl_UniCharToUpper(wlabel[underline]))) {
			    *plResult = (2 << 16) | i;
			    returnResult = 1;
			    break;
@


1.21.2.10
log
@	* generic/tkMenuDraw.c (TkPostSubmenu): Fix reposting of submenu in
	* win/tkWinMenu.c (TkWinHandleMenuEvent): torn off Windows menu.
	[Bug 873613]
	(DrawMenuEntryArrow): Draw Win menu arrow after being torn
	off. [Bug 873608]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.9 2007/06/09 23:52:40 hobbs Exp $
a54 4
#ifndef WM_UNINITMENUPOPUP
#define WM_UNINITMENUPOPUP              0x0125
#endif

a942 13
 	case WM_UNINITMENUPOPUP:
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		    (char *) *pwParam);
	    if (hashEntryPtr != NULL) {
   		menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
		if ((menuPtr->menuRefPtr != NULL)
			&& (menuPtr->menuRefPtr->parentEntryPtr != NULL)) {
		    TkPostSubmenu(menuPtr->interp,
			    menuPtr->menuRefPtr->parentEntryPtr->menuPtr, NULL);
		}
	    }
	    break;

d1729 2
a1730 1
    if (!drawArrow || (mePtr->type != CASCADE_ENTRY))
d1746 1
a1746 2
    gc->foreground = GetSysColor((mePtr->state == ENTRY_DISABLED) ?
	    COLOR_GRAYTEXT : COLOR_MENUTEXT);
@


1.21.2.4.2.1
log
@bug fixes (crahes/panic during finalization/exit); feature implementation for embedding/embedded Tk (Windows). See Tk 8.5 changes (12/17/04 - 01/03/05) for details
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.4 2004/10/27 00:37:38 davygrvy Exp $
d20 1
d26 1
a26 1
#define EMBEDDED_MENU_CLASS_NAME "EmbeddedMenuWindowClass"
a62 1
    HWND embeddedMenuHWND;	/* A window to service embedded menu messages */
d168 1
a168 3
static LRESULT CALLBACK	TkWinEmbeddedMenuProc _ANSI_ARGS_((HWND hwnd,
			    UINT message, WPARAM wParam,
			    LPARAM lParam));
d879 2
a880 1
    if(!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) {
a888 91
 * UpdateEmbeddedMenu --
 *
 *	This function is used as work-around for updating the pull-down 
 *	window of an embedded menu which may show as a blank popup window.
 *
 * Results:
 *	Invalidate the client area of the embedded pull-down menu and 
 *	redraw it.
 *
 * Side effects:
 *	Redraw the embedded menu window.
 *
 *----------------------------------------------------------------------
 */

static void UpdateEmbeddedMenu(ClientData clientData) {
    RECT rc;
    HWND hMenuWnd = (HWND)clientData;
    GetClientRect(hMenuWnd, &rc);
    InvalidateRect(hMenuWnd, &rc, FALSE);
    UpdateWindow(hMenuWnd);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinEmbeddedMenuProc --
 *
 *	This window proc is for the embedded menu windows. It provides
 *	message services to an embedded menu in a different process.
 *
 * Results:
 *	To an embedded menu message, returns 1 if the message has been 
 *	handled or 0 otherwise.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
TkWinEmbeddedMenuProc(hwnd, message, wParam, lParam)
    HWND hwnd;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
{
    static nPopupMenus = 0, nIdles = 0;
    LRESULT lResult = 1;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    switch(message) {
	case WM_ENTERIDLE: 
	if((wParam == MSGF_MENU) && (nIdles < 1) && (hwnd == tsdPtr->embeddedMenuHWND)) {
	    Tcl_CreateTimerHandler(200, UpdateEmbeddedMenu, (ClientData)lParam);
	    nIdles++;
	}
	break;
	
	case WM_INITMENUPOPUP:
	nIdles = 0;
	nPopupMenus++;
	break;

	case WM_UNINITMENUPOPUP:
	nPopupMenus--;
 	break;

	case WM_INITMENU:
	case WM_SYSCOMMAND:
	case WM_COMMAND:
	case WM_MENUCHAR:
	case WM_MEASUREITEM:
	case WM_DRAWITEM:
	case WM_MENUSELECT:
	lResult = TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult);
	if(lResult || (GetCapture() != hwnd)) break;

	default:
	lResult = DefWindowProc(hwnd, message, wParam, lParam);
	break;

    }
    return lResult;
}

/*
 *----------------------------------------------------------------------
 *
d920 1
d1022 1
d1129 1
a2829 3

    DestroyWindow(tsdPtr->embeddedMenuHWND);
    UnregisterClass(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());
d3012 1
a3012 3
    if(!RegisterClass(&wndClass)) {
	panic("Failed to register menu window class.");
    }
a3016 17
    if(!tsdPtr->menuHWND) {
	panic("Failed to create the menu window.");
    }

    wndClass.lpfnWndProc = TkWinEmbeddedMenuProc;
    wndClass.lpszClassName = EMBEDDED_MENU_CLASS_NAME;
    if(!RegisterClass(&wndClass)) {
	panic ("Failed to register embedded menu window class.");
    }

    tsdPtr->embeddedMenuHWND = CreateWindow(EMBEDDED_MENU_CLASS_NAME, "EmbeddedMenuWindow", WS_POPUP,
	0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    if(!tsdPtr->embeddedMenuHWND) {
	panic("Failed to create the embedded menu window.");
    }

a3019 30

/*
 *----------------------------------------------------------------------
 *
 * Tk_GetMenuHWND --
 *
 *	This function returns the HWND of a hidden menu Window that
 *	processes messages of a popup menu.  This hidden menu window
 *	is used to handle either a dynamic popup menu in the same 
 *	process or a pull-down menu of an embedded window in a 
 *	different process.
 *
 * Results:
 *	Returns the HWND of the hidden menu Window.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

HWND
Tk_GetMenuHWND(tkwin)
    Tk_Window tkwin;
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    TkMenuInit();
    return tsdPtr->embeddedMenuHWND;
}
@


1.21.2.4.2.2
log
@Updated for embedded/embedding implementation for Windows
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.21.2.4.2.1 2005/01/04 05:07:03 chengyemao Exp $
d540 1
d552 7
d706 1
d938 1
a938 1
    static nIdles = 0;
d953 1
d956 4
a1106 2
		*plResult = 0;
		returnResult = 1;
d1108 2
d1148 1
a1148 1
	    if (itemPtr != NULL && itemPtr->itemData != 0 && tsdPtr->modalMenuPtr != NULL) {
d1177 1
a1177 1
	    if (itemPtr != NULL && itemPtr->itemData != 0 && tsdPtr->modalMenuPtr != NULL) {
d1220 2
a1222 2
    	    *plResult = 1;
	    returnResult = 1;
a1246 1
		    long entryIndex = LOWORD(*pwParam);
d1248 1
a1248 1
		    if (flags != 0xFFFF && entryIndex < menuPtr->numEntries) {
d1250 1
a1250 1
			    mePtr = menuPtr->entries[entryIndex];
d1254 1
a1254 1
				    (char *) entryIndex);
a1271 2
		    *plResult = 0;
		    returnResult = 1;
@


1.20
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
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.19 2002/01/17 03:35:01 dgp Exp $
d1243 2
a1244 1
	if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
a1245 1
	    menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
a1251 1

@


1.19
log
@	* Updated callers of Tcl_Utf* and Tcl_Regexp* APIs to reflect TIP 27
	API changes (see Tcl Patch 471509). [Patch 471513]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.18 2002/01/08 15:40:15 drh Exp $
d2747 2
a2748 2
    char *dbName,		/* The option database name. */
    char *className)		/* The name of the option class. */
@


1.18
log
@Fix the following bug: If you select an entry on a cascade menu (on Win32)
then the next time the parent menu is posted, the cascade entry appears active.
Also, if you traverse to a disabled menu entry using keystrokes and press
ENTER on the disabled entry, then that entry appears active the next time
the menu is posted.  The same patch fixes both problems.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.17 2001/11/27 04:36:18 drh Exp $
d464 1
a464 1
	char *p, *next;
d1731 2
a1732 2
	char *start = Tcl_UtfAtIndex(label, mePtr->underline);
	char *end = Tcl_UtfNext(start);
@


1.17
log
@Change the behavior of menus on windows to be more consistent with native
windows menus.  Disabled menu entries show their active background color
on mouseover and keyboard traversal.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.16 2001/10/12 13:30:32 tmh Exp $
d916 1
d1083 6
d1156 1
d1189 4
@


1.16
log
@implementation of TIP 63 (accepted) -compound option to menu items.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.15 2001/09/21 21:34:10 hobbs Exp $
d1081 6
d2417 2
a2418 1
    if (mePtr->state == ENTRY_ACTIVE) {
@


1.16.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
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.16 2001/10/12 13:30:32 tmh Exp $
d464 1
a464 1
	CONST char *p, *next;
a915 1
		RecursivelyClearActiveMenu(menuPtr);
a1080 12
		} else {
		    /* On windows, menu entries should highlight even if they
		    ** are disabled. (I know this seems dumb, but it is the way
		    ** native windows menus works so we ought to mimic it.)
		    ** The ENTRY_PLATFORM_FLAG1 flag will indicate that the
		    ** entry should be highlighted even though it is disabled.
		    */
		    if (itemPtr->itemState & ODS_SELECTED) {
			mePtr->entryFlags |= ENTRY_PLATFORM_FLAG1;
		    } else {
			mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
		    }
a1142 1
	    break;
a1174 4
	if (mePtr->state == ENTRY_ACTIVE) {
	    mePtr->state = ENTRY_NORMAL;
	}
	mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
d1713 2
a1714 2
	CONST char *start = Tcl_UtfAtIndex(label, mePtr->underline);
	CONST char *end = Tcl_UtfNext(start);
d2411 1
a2411 2
    if (mePtr->state == ENTRY_ACTIVE 
		|| (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)!=0 ) {
@


1.16.2.2
log
@merged with trunk at tag macosx-8-4-merge-2002-08-20-trunk
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
d1243 2
a1244 1
	if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
a1245 1
	    Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
d1252 1
d2747 2
a2748 2
    CONST char *dbName,		/* The option database name. */
    CONST char *className)	/* The name of the option class. */
@


1.15
log
@minor cast fixes to prevent 64bit warnings
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.14 2001/04/04 18:37:18 hobbs Exp $
a1891 1

a1904 1
    int baseline;
d1909 4
d1919 1
a1919 1
     * Draw label or bitmap or image for entry.
a1921 1
    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
d1924 71
d1998 2
a1999 2
		    imageWidth, imageHeight, d, leftEdge,
	            (int) (y + (mePtr->height - imageHeight)/2));
d2002 2
a2003 2
		    imageHeight, d, leftEdge,
		    (int) (y + (mePtr->height - imageHeight)/2));
a2005 1
    	int width, height;
d2007 6
a2012 5
        Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
    	XCopyPlane(menuPtr->display, bitmap, d,	gc, 0, 0, (unsigned) width, 
		(unsigned) height, leftEdge,
		(int) (y + (mePtr->height - height)/2), 1);
    } else {
d2014 1
d2017 4
a2020 2
		    mePtr->labelLength, leftEdge, baseline);
	    DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
d2032 2
a2033 2
		    leftEdge,
		    (int) (y + (mePtr->height - imageHeight)/2),
d2315 1
d2319 1
d2323 1
d2325 3
a2327 1
    	*heightPtr = fmPtr->linespace;
d2329 4
d2334 1
d2336 1
d2338 31
a2368 1
    	    *widthPtr = Tk_TextWidth(tkfont, label, mePtr->labelLength);
d2370 7
a2376 1
    	    *widthPtr = 0;
@


1.14
log
@	* win/tkWinMenu.c (TkWinHandleMenuEvent): corrected reseting of
	service mode to only occur when it was set. [Bug #220948]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.13 2000/08/29 21:00:13 ericm Exp $
d484 1
a484 1
	    Tcl_DStringAppend(&itemString, p, next - p);
d493 1
a493 1
		Tcl_DStringAppend(&itemString, p, next - p);
d1719 1
a1719 1
		start - label, end - label);
@


1.13
log
@* win/tkWinMenu.c (DrawWindowsSystemBitmap): Use scratchDC
for determining the source's logical coordinates.  Patch from
[Bug: 6134 (Markus Oberhumer)].

* win/tkWinMenu.c (SetDefaults): Compute the indicatorDimensions[]
under Windows NT/2000 in the same way as under Windows 95/98.
Patch from [Bug: 6134 (Markus Oberhumer)].

* win/tkWinFont.c (GetScreenFont): Added a memset() to
pacify memory checkers.  Patch from [Bug: 6134 (Markus Oberhumer)].
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.12 2000/07/28 17:37:24 ericm Exp $
a1103 1
		Tcl_SetServiceMode(tsdPtr->oldServiceMode);
d1105 1
@


1.13.4.1
log
@        * Merged in updates from HEAD branch.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.14 2001/04/04 18:37:18 hobbs Exp $
d1104 1
a1105 1
		    Tcl_SetServiceMode(tsdPtr->oldServiceMode);
@


1.13.2.1
log
@	* generic/tk.decls:
	* generic/tkInt.decls:
	* generic/tkIntPlatDecls.h:
	* generic/tkPlatDecls.h:
	* generic/tkStubInit.c:
	* win/Makefile.in:
	* win/makefile.vc:
	* win/tkWin3d.c:
	* win/tkWinButton.c:
	* win/tkWinColor.c:
	* win/tkWinDraw.c:
	* win/tkWinFont.c:
	* win/tkWinGdi.c (new):
	* win/tkWinGdi.h (new):
	* win/tkWinImage.c:
	* win/tkWinInt.h:
	* win/tkWinMenu.c:
	* win/tkWinPixmap.c:
	* win/tkWinUtil.c (new):
	* win/tkWinWindow.c:
	* win/tkWinWm.c:
	* win/tkWinX.c:
	* win/winMain.c:
	* xlib/xgc.c:
	* xlib/X11/Xlib.h: first cut at Windows speedup improvements by
	Leo Schubert.  Needs to be streamlined, but the code is correct
	and passes all tests.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.13 2000/08/29 21:00:13 ericm Exp $
a17 1
#include "tkWinGdi.h"
a1073 1
		CkGraph_RegisterDeviceContext(itemPtr->hDC) ;
a1091 1
		CkGraph_UnRegisterDeviceContext(itemPtr->hDC) ;
d1438 2
a1439 5
#ifdef USE_CKGRAPH_IMP
    CkGraph_ClearDC(hdc);
#endif
    CkSetBkColor(hdc, gc->background);
    CkSetTextColor(hdc, gc->foreground);
d1441 2
a1442 2
    scratchDC = CkCreateCompatibleDC(hdc);
    bitmap = CkLoadBitmap(NULL, MAKEINTRESOURCE(bitmapID));
d1444 1
a1444 1
    CkSelectBitmap(scratchDC, bitmap);
d1470 1
a1470 1
    CkBitBlt(hdc, rectPtr->left + leftOffset, rectPtr->top + topOffset, ptSize.x,
d1472 2
a1473 2
    CkDeleteDC(scratchDC);
    CkDeleteBitmap(bitmap);
d2665 1
a2665 1
    scratchDC = CkCreateDC("DISPLAY", NULL, NULL, NULL);
d2674 2
a2675 2
    menuFont = CkCreateFontIndirect(&ncMetrics.lfMenuFont);
    CkSelectFont(scratchDC, menuFont);
a2685 4
#ifndef USE_CKGRAPH_IMP
    CkSelectFont(scratchDC, CkGetStockObject(SYSTEM_FONT));
#endif
    CkDeleteDC(scratchDC);
d2687 4
a2690 1
    CkDeleteFont(menuFont);
a2716 1
     /*Harhar*/
@


1.13.2.2
log
@sync with head
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.19 2002/01/17 03:35:01 dgp Exp $
d465 1
a465 1
	CONST char *p, *next;
d485 1
a485 1
	    Tcl_DStringAppend(&itemString, p, (int) (next - p));
d494 1
a494 1
		Tcl_DStringAppend(&itemString, p, (int) (next - p));
a916 1
		RecursivelyClearActiveMenu(menuPtr);
a1082 12
		} else {
		    /* On windows, menu entries should highlight even if they
		    ** are disabled. (I know this seems dumb, but it is the way
		    ** native windows menus works so we ought to mimic it.)
		    ** The ENTRY_PLATFORM_FLAG1 flag will indicate that the
		    ** entry should be highlighted even though it is disabled.
		    */
		    if (itemPtr->itemState & ODS_SELECTED) {
			mePtr->entryFlags |= ENTRY_PLATFORM_FLAG1;
		    } else {
			mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
		    }
d1107 1
a1108 1
		    Tcl_SetServiceMode(tsdPtr->oldServiceMode);
a1145 1
	    break;
a1177 4
	if (mePtr->state == ENTRY_ACTIVE) {
	    mePtr->state = ENTRY_NORMAL;
	}
	mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;
d1719 2
a1720 2
	CONST char *start = Tcl_UtfAtIndex(label, mePtr->underline);
	CONST char *end = Tcl_UtfNext(start);
d1725 1
a1725 1
		(int) (start - label), (int) (end - label));
d1898 1
d1912 1
a1916 4
    int textHeight, textWidth;
    int haveImage = 0, haveText = 0;
    int imageXOffset = 0, imageYOffset = 0;
    int textXOffset = 0, textYOffset = 0;
d1923 1
a1923 1
     * Work out what we will need to draw first.
d1926 1
a1928 71
        haveImage = 1;
    } else if (mePtr->bitmapPtr != NULL) {
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
	Tk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight);
	haveImage = 1;
    }
    if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
        if (mePtr->labelLength > 0) {
	    char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
	    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);
	    textHeight = fmPtr->linespace;
	    haveText = 1;
        }
    }
    
    /*
     * Now work out what the relative positions are.
     */

    if (haveImage && haveText) {
	int fullWidth = (imageWidth > textWidth ? imageWidth : textWidth);
	switch ((enum compound) mePtr->compound) {
	    case COMPOUND_TOP: {
		textXOffset = (fullWidth - textWidth)/2;
		textYOffset = imageHeight/2 + 2;
		imageXOffset = (fullWidth - imageWidth)/2;
		imageYOffset = -textHeight/2;
		break;
	    }
	    case COMPOUND_BOTTOM: {
		textXOffset = (fullWidth - textWidth)/2;
		textYOffset = -imageHeight/2;
		imageXOffset = (fullWidth - imageWidth)/2;
		imageYOffset = textHeight/2 + 2;
		break;
	    }
	    case COMPOUND_LEFT: {
		textXOffset = imageWidth + 2;
		textYOffset = 0;
		imageXOffset = 0;
		imageYOffset = 0;
		break;
	    }
	    case COMPOUND_RIGHT: {
		textXOffset = 0;
		textYOffset = 0;
		imageXOffset = textWidth + 2;
		imageYOffset = 0;
		break;
	    }
	    case COMPOUND_CENTER: {
		textXOffset = (fullWidth - textWidth)/2;
		textYOffset = 0;
		imageXOffset = (fullWidth - imageWidth)/2;
		imageYOffset = 0;
		break;
	    }
	    case COMPOUND_NONE: {break;}
	}
    } else {
	textXOffset = 0;
	textYOffset = 0;
	imageXOffset = 0;
	imageYOffset = 0;
    }
    
    /*
     * Draw label and/or bitmap or image for entry.
     */

    if (mePtr->image != NULL) {
d1932 2
a1933 2
		    imageWidth, imageHeight, d, leftEdge + imageXOffset,
	            (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
d1936 2
a1937 2
		    imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
d1940 1
d1942 5
a1946 6
    	XCopyPlane(menuPtr->display, bitmap, d,	gc, 0, 0, 
		(unsigned) imageWidth, (unsigned) imageHeight, 
		leftEdge + imageXOffset,
		(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);
    }
    if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {
a1947 1
	    int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
d1950 2
a1951 4
		    mePtr->labelLength, leftEdge + textXOffset, 
		    baseline + textYOffset);
	    DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, 
	            x + textXOffset, y + textYOffset,
d1963 2
a1964 2
		    leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
a2245 1
    int haveImage = 0, haveText = 0;
a2248 1
	haveImage = 1;
a2251 1
	haveImage = 1;
d2253 1
a2253 3
	*heightPtr = 0;
	*widthPtr = 0;
    }
a2254 4
    if (haveImage && (mePtr->compound == COMPOUND_NONE)) {
	/* We don't care about the text in this case */
    } else {
	/* Either it is compound or we don't have an image */
a2255 1
	    int textWidth;
a2256 1
	    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);
d2258 1
a2258 31
	    if ((mePtr->compound != COMPOUND_NONE) && haveImage) {
		switch ((enum compound) mePtr->compound) {
		    case COMPOUND_TOP:
		    case COMPOUND_BOTTOM: {
			if (textWidth > *widthPtr) {
			    *widthPtr = textWidth;
			}
			/* Add text and padding */
			*heightPtr += fmPtr->linespace + 2;
			break;
		    }
		    case COMPOUND_LEFT:
		    case COMPOUND_RIGHT: {
			if (fmPtr->linespace > *heightPtr) {
			    *heightPtr = fmPtr->linespace;
			}
			/* Add text and padding */
			*widthPtr += textWidth + 2;
			break;
		    }
		    case COMPOUND_CENTER: {
			if (fmPtr->linespace > *heightPtr) {
			    *heightPtr = fmPtr->linespace;
			}
			if (textWidth > *widthPtr) {
			    *widthPtr = textWidth;
			}
			break;
		    }
		    case COMPOUND_NONE: {break;}
		}
d2260 1
a2260 7
		/* We don't have an image or we're not compound */
		*heightPtr = fmPtr->linespace;
		*widthPtr = textWidth;
	    }
	} else {
	    /* An empty entry still has this height */
	    *heightPtr = fmPtr->linespace;
d2295 1
a2295 2
    if (mePtr->state == ENTRY_ACTIVE 
		|| (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)!=0 ) {
@


1.12
log
@* 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].
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.11 2000/07/06 03:17:44 mo Exp $
d1452 1
a1452 1
    DPtoLP(hdc, &ptOrg, 1);
d2718 1
a2718 1
    if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) {
@


1.11
log
@	* generic/tkFileFilter.c (AddClause): Cast to match function prototype.
	* win/stubs.c (_XInitImageFuncPtrs): Add return value for function.
	* win/tkWinButton.c (buttonStyles, ButtonBindProc, ComputeStyle):
	Remove unused declarations.
	* win/tkWinColor.c (GetColorByName, GetColorByValue): Remove unused
	function declarations.
	* win/tkWinDialog.c (TrySetDirectory): Remove unused function declaration.
	* win/tkWinEmbed.c (TkWinEmbeddedEventProc): Cast to match function prototype.
	* win/tkWinMenu.c (winMenuMutex, MenuExitProc): Remove unused declaration.
	* win/tkWinWindow.c (StackWindow): Remove unused declaration.
	* win/tkWinWm.c (ConfigureEvent): Remove unused declaration.
	* win/tkWinX.c (winXMutex): Remove unused declaration.
	* xlib/ximage.c (XCreateBitmapFromData): Cast to match function prototype.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.10 2000/05/16 17:57:32 ericm Exp $
d585 1
a585 1
	    flags |= MF_DISABLED;
@


1.10
log
@* 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].
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.9 2000/05/10 00:09:40 ericm Exp $
a84 2
TCL_DECLARE_MUTEX(winMenuMutex)

a149 1
static void		MenuExitProc _ANSI_ARGS_((ClientData clientData));
@


1.9
log
@	* doc/button.n: Added documentation for link relief.

	* tests/button.test: Added tests for link relief for buttons.

	* generic/tk.h (TK_CONFIG_LINK_OK): Added definition of
	TK_RELIEF_LINK, TK_OPTION_LINK_OK and TK_CONFIG_LINK_OK. [RFE: 4348]

	* generic/tk3d.c: Added support for link relief. [RFE: 4348]

	* mac/tkMacButton.c (TkpDisplayButton):
	* unix/tkUnixButton.c (TkpDisplayButton): Added support for link
	relief. [RFE: 4348]

	* generic/tkOldConfig.c (Tk_ConfigureWidget):
	* generic/tkConfig.c (DoObjConfig): Added understanding of link
	relief, which is allowed only for widgets that have
	TK_OPTION_LINK_OK or TK_CONFIG_LINK_OK set for the "-relief"
	option. [RFE: 4348]

	* generic/tkButton.c: Added TK_OPTION_LINK_OK to "-relief" option
	for buttons. [RFE: 4348]

	* win/tkWinWm.c (EX_TRANSIENT_STYLE): Removed WS_EX_TOOLWINDOW
	style bit, so that transient windows have full-size titlebars
	(like the tk_getOpenFile dialog).

	* 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
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.8 2000/04/13 20:51:55 ericm Exp $
d582 1
a582 1
	
d599 12
@


1.8
log
@* win/tkWinMenu.c: Corrected code that created separator items on
menus; originally, it requested that the system be responsible for
drawing those items, so it would ignore configuration items like
the widget background.  Now, we draw the separators ourselves (as
we do with every other kind of menu item already). [Bug: 1166].
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.7 2000/03/31 09:24:27 hobbs Exp $
d1387 1
a1387 1
    *heightPtr = fmPtr->linespace;
@


1.8.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
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.12 2000/07/28 17:37:24 ericm Exp $
d85 2
d152 1
d582 1
a582 1

d588 1
a588 1
	    flags |= MF_DISABLED | MF_GRAYED;
a600 12
	/*
	 * Set the SEPARATOR bit for separator entries.  This bit is not
	 * used by our internal drawing functions, but it is used by the
	 * system when drawing the system menu (we do not draw the system menu
	 * ourselves).  If this bit is not set, separator entries on the system
	 * menu will not be drawn correctly.
	 */

	if (mePtr->type == SEPARATOR_ENTRY) {
	    flags |= MF_SEPARATOR;
	}
	
d1387 1
a1387 1
    *heightPtr = fmPtr->linespace - (2 * fmPtr->descent);
@


1.8.2.2
log
@see ChangeLog for specific file details
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.13 2000/08/29 21:00:13 ericm Exp $
d1452 1
a1452 1
    DPtoLP(scratchDC, &ptOrg, 1);
d2718 1
a2718 1
    if (TkWinGetPlatformId() >= VER_PLATFORM_WIN32_WINDOWS) {
@


1.8.2.3
log
@	* win/tkWinMenu.c (TkWinHandleMenuEvent): corrected reseting of
	service mode to only occur when it was set. [Bug #220948]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.8.2.2 2001/04/04 07:57:18 hobbs Exp $
d1104 1
a1105 1
		    Tcl_SetServiceMode(tsdPtr->oldServiceMode);
@


1.7
log
@	* win/tkWinDialog.c: added unicode-aware open/save file dialogs

	* win/tkWinFont.c (TkpFontPkgInit): move private ref to platformId
	to TkWinGetPlatformId

	* win/tkWinMenu.c (SetDefaults): moved private use of versionInfo
	to TkWinGetPlatformId and removed all code for
	(versionInfo.dwMajorVersion < 4) (== Win32s)

	* win/tkWinX.c:
	* win/tkWin32Dll.c: moved TkWinGetPlatformId to tkWinX.c
	* win/tkWinInit.c: added TkWinXInit to TkpInit to ensure that its
	called for static Windows shells. [Bug: 3647]

	* win/tkWinInt.h:
	* win/tkWinX.c:
	* win/tkWinDraw.c (SetUpGraphicsPort):
	* win/tkWinScrlbr.c (UpdateScrollbar): removed use of tkpIsWin32s

	* win/tkWinInt.h (TkWinDCState struct): added bkmode value
	* win/tkWinDraw.c (TkWinGetDrawableDC, et al): added support for
	properly transparent dashed lines on Windows. [Bug: 4617]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.6 1999/09/15 22:35:42 hobbs Exp $
d573 5
a577 2
	if (mePtr->type == SEPARATOR_ENTRY) {
	    flags |= MF_SEPARATOR;
d579 35
a613 30
	    itemText = GetEntryText(mePtr);
	    if ((menuPtr->menuType == MENUBAR)
		    || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
		Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);
		lpNewItem = Tcl_DStringValue(&translatedText);
	    } else {
		lpNewItem = (LPCTSTR) mePtr;
		flags |= MF_OWNERDRAW;
	    }

    	    /*
    	     * Set enabling and disabling correctly.
    	     */

	    if (mePtr->state == ENTRY_DISABLED) {
		flags |= MF_DISABLED;
	    }
    	    
    	    /*
    	     * Set the check mark for check entries and radio entries.
    	     */
	    
	    if (((mePtr->type == CHECK_BUTTON_ENTRY)
		    || (mePtr->type == RADIO_BUTTON_ENTRY))
		    && (mePtr->entryFlags & ENTRY_SELECTED)) {
		flags |= MF_CHECKED;
	    }

	    if (mePtr->columnBreak) {
		flags |= MF_MENUBREAK;
d615 38
a652 51

	    itemID = (int) mePtr->platformEntryData;
	    if ((mePtr->type == CASCADE_ENTRY)
		    && (mePtr->childMenuRefPtr != NULL)
		    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
		HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr
		    ->platformData;
		if (childMenuHdl != NULL) {
		    itemID = (UINT) childMenuHdl;
		    flags |= MF_POPUP;
		}
		if ((menuPtr->menuType == MENUBAR) 
			&& !(mePtr->childMenuRefPtr->menuPtr->menuFlags
				& MENU_SYSTEM_MENU)) {
		    Tcl_DString ds;
		    TkMenuReferences *menuRefPtr;
		    TkMenu *systemMenuPtr = mePtr->childMenuRefPtr
			->menuPtr;

		    Tcl_DStringInit(&ds);
		    Tcl_DStringAppend(&ds,
			    Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
		    Tcl_DStringAppend(&ds, ".system", 7);

		    menuRefPtr = TkFindMenuReferences(menuPtr->interp,
			    Tcl_DStringValue(&ds));
		    
		    Tcl_DStringFree(&ds);

		    if ((menuRefPtr != NULL) 
			    && (menuRefPtr->menuPtr != NULL)
			    && (menuPtr->parentTopLevelPtr != NULL)
			    && (systemMenuPtr->masterMenuPtr
				    == menuRefPtr->menuPtr)) {
			HMENU systemMenuHdl = 
			    (HMENU) systemMenuPtr->platformData;
			HWND wrapper = TkWinGetWrapperWindow(menuPtr
				->parentTopLevelPtr);
			if (wrapper != NULL) {
			    DestroyMenu(systemMenuHdl);
			    systemMenuHdl = GetSystemMenu(wrapper, FALSE);
			    systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
			    systemMenuPtr->platformData = 
				(TkMenuPlatformData) systemMenuHdl;
			    if (!(systemMenuPtr->menuFlags 
				    & MENU_RECONFIGURE_PENDING)) {
				systemMenuPtr->menuFlags 
				    |= MENU_RECONFIGURE_PENDING;
				Tcl_DoWhenIdle(ReconfigureWindowsMenu,
					(ClientData) systemMenuPtr);
			    }
d656 4
a659 4
		if (mePtr->childMenuRefPtr->menuPtr->menuFlags 
			& MENU_SYSTEM_MENU) {
		    systemMenu++;
		}
@


1.6
log
@1999-09-14  Jeff Hobbs  <hobbs@@scriptics.com>

	* win/tkWinMenu.c: fix for stack overrun in GetTextFace [Bug: 909]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.5 1999/04/16 01:51:52 stanton Exp $
a76 3
static OSVERSIONINFO versionInfo;
				/* So we don't have to keep doing this */

d1527 1
a1527 2
		    && (menuPtr->disabledFgPtr != NULL)
		    && (versionInfo.dwMajorVersion >= 4)) {
a1542 7

	    if ((mePtr->state == ENTRY_DISABLED) 
		    && (menuPtr->disabledImageGC != None)
		    && (versionInfo.dwMajorVersion < 4)) {
		XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
			rect.left, rect.top, rect.right, rect.bottom);
	    }
d1597 18
a1614 21
	    || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {
	if (versionInfo.dwMajorVersion >= 4) {
	    COLORREF oldFgColor = gc->foreground;
	    
	    gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	    if (mePtr->accelPtr != NULL) {
		Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
			mePtr->accelLength, leftEdge + 1, baseline + 1);
	    }

	    if (mePtr->type == CASCADE_ENTRY) {
		RECT rect;

		rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1;
		rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1;
		rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1;
		rect.right = x + width;
		DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, 
			OBM_MNARROW, ALIGN_BITMAP_RIGHT);
	    }
	    gc->foreground = oldFgColor;
d1616 1
a1623 8
    if ((mePtr->state == ENTRY_DISABLED) 
	    && (menuPtr->disabledImageGC != None)
	    && (versionInfo.dwMajorVersion < 4)) {
	XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
		leftEdge, y, width - mePtr->labelWidth 
		- mePtr->indicatorSpace, height);
    }

a1632 6
	if ((mePtr->state == ENTRY_DISABLED) 
		&& (menuPtr->disabledImageGC != None)
		&& (versionInfo.dwMajorVersion < 4)) {
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
		    rect.left, rect.top, rect.right, rect.bottom);
	}
d2649 1
a2649 13


    versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);

    /*
     * If GetVersionEx fails, it means that the version info record
     * is too big for what is compiled. Should never happen, but if
     * it does, we are later than Windows 95 or NT 4.0.
     */

    if (!GetVersionEx(&versionInfo)) {
	versionInfo.dwMajorVersion = 4;
    }
a2660 1

d2667 4
a2670 10
    if (versionInfo.dwMajorVersion >= 4) {
	NONCLIENTMETRICS ncMetrics;

	ncMetrics.cbSize = sizeof(ncMetrics);
	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
		&ncMetrics, 0);
	menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
    } else {
	menuFont = GetStockObject(SYSTEM_FONT);
    }
d2714 1
a2714 1
    if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
@


1.5
log
@* Merged 8.1 branch into the main trunk
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
d2719 1
a2719 1
    GetTextFace(scratchDC, sizeof(menuFontDString), faceName);
@


1.5.6.1
log
@1999-09-21  Jeff Hobbs  <hobbs@@scriptics.com>

	* generic/tkFont.c: fixed processing of font options and error
	returned [Bug: 2075]

	* win/tkWinWm.c: fixed bug in 'wm deiconify' that raised the
	wrong toplevel, and changed it to not set focus on overridden
	toplevels

	* unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition [Bug: 2070]
	and fix to AIX-* to get ldAix right [Bug: 2624], fixed AIX
	version check and several other config fixes for AIX

	* mac/tkMacMenubutton.c:
	* unix/tkUnixMenubu.c: fixed permanently stippled menubutton image
	* win/tkWinButton.c: fixed possible pointer smash [Bug: 2733]

	* win/tkWinMenu.c: fix for stack overrun in GetTextFace [Bug: 909]

	* unix/tkUnixDraw.c: fixed header style for TkpDrawHighlightBorder

	* generic/tkCanvas.c: fixed GC error (bg <> fg) in tkCanvas.c
	(from code added to support TkpDrawHighlightBorder) [Bug: 2676]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.5 1999/04/16 01:51:52 stanton Exp $
d2719 1
a2719 1
    GetTextFace(scratchDC, LF_FACESIZE, faceName);
@


1.4
log
@* win/tkWinMenu.c (TkpDestroyMenu): Changed so modalMenuPtr is
cleared when it is being destroyed.
@
text
@d6 2
a7 1
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.3 1998/09/14 18:24:00 stanton Exp $
d16 3
a19 2
#include "tkMenu.h"
#include "tkWinInt.h"
d55 3
a57 1
static Tcl_HashTable commandTable;
d59 3
a61 3
static int inPostMenu;		/* We cannot be re-entrant like X Windows. */
static WORD lastCommandID;	/* The last command ID we allocated. */
static HWND menuHWND;		/* A window to service popup-menu messages
d63 1
a63 1
static int oldServiceMode;	/* Used while processing a menu; we need
d67 1
a67 1
static TkMenu *modalMenuPtr;	/* The menu we are processing inside the modal
d72 5
a78 2
static Tcl_HashTable winMenuTable;
				/* Need this to map HMENUs back to menuPtrs */
d84 1
a84 1
static char borderString[5];	/* The string indicating how big the border is */
d88 1
d133 1
a133 1
static char *		GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
d165 1
d201 2
d204 1
a204 1
    WORD curID = lastCommandID + 1;
d211 2
a212 2
    while (curID != lastCommandID) {
    	commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
d225 1
a225 1
    	lastCommandID = returnID;
d252 4
a255 1
    Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
d289 2
d305 1
a305 1
    hashEntryPtr = Tcl_CreateHashEntry(&winMenuTable, (char *) winMenuHdl,
d334 3
d361 2
a362 1
	    if (strcmp(searchEntryPtr->name, menuName) == 0) {
d380 2
a381 1
	hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
d389 2
a390 2
    if (menuPtr == modalMenuPtr) {
	modalMenuPtr = NULL;
d455 1
a455 1
    } else if (mePtr->imageString != NULL) {
d458 1
a458 1
    } else if (mePtr->bitmap != None) {
d461 1
a461 1
    } else if (mePtr->label == NULL || mePtr->labelLength == 0) {
d465 7
a471 2
	int size = mePtr->labelLength + 1;
	int i, j;
d480 1
a480 5
	for (i = 0; i < mePtr->labelLength; i++) {
	    if (mePtr->label[i] == '&') {
		size++;
	    }
	}
d482 3
a484 4
	if (mePtr->underline >= 0) {
	    size++;
	    if (mePtr->label[mePtr->underline] == '&') {
		size++;
d486 2
a487 9
	}

	if (mePtr->accelLength > 0) {
	    size += mePtr->accelLength + 1;
	}

	for (i = 0; i < mePtr->accelLength; i++) {
	    if (mePtr->accel[i] == '&') {
		size++;
d489 2
d492 5
a496 12

	itemText = ckalloc(size);
	
	if (mePtr->labelLength == 0) {
	    itemText[0] = 0;
	} else {
	    for (i = 0, j = 0; i < mePtr->labelLength; i++, j++) {
		if (mePtr->label[i] == '&') {
		    itemText[j++] = '&';
		}
		if (i == mePtr->underline) {
		    itemText[j++] = '&';
d498 2
a499 1
		itemText[j] = mePtr->label[i];
d501 1
a501 2
	    itemText[j] = '\0';
	}
d503 3
a505 11
	if (mePtr->accelLength > 0) {
	    strcat(itemText, "\t");
	    for (i = 0, j = strlen(itemText); i < mePtr->accelLength;
		    i++, j++) {
		if (mePtr->accel[i] == '&') {
		    itemText[j++] = '&';
		}
		itemText[j] = mePtr->accel[i];
	    }
	    itemText[j] = '\0';
	}
d534 2
a535 2
    char *itemText = NULL;
    LPCTSTR lpNewItem;
d540 2
a541 1

d570 1
d582 2
a583 1
		lpNewItem = itemText;
d593 1
a593 1
	    if (mePtr->state == tkDisabledUid) {
d624 1
d628 6
a633 7
		    char *systemMenuName = ckalloc(strlen(
			Tk_PathName(menuPtr->masterMenuPtr->tkwin))
			    + strlen(".system") + 1);

		    strcpy(systemMenuName, 
			    Tk_PathName(menuPtr->masterMenuPtr->tkwin));
		    strcat(systemMenuName, ".system");
d635 4
a638 1
			    systemMenuName);
a662 1
		    ckfree(systemMenuName);
d673 1
d719 2
d722 1
a722 1
    inPostMenu++;
d731 1
a731 1
	inPostMenu--;
d741 1
a741 1
	inPostMenu--;
d782 1
a782 1
	    menuHWND, &noGoawayRect);
d788 2
a789 2
    if (inPostMenu) {
	inPostMenu = 0;
d898 2
d904 2
a905 1
	    hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *pwParam);
d907 1
a907 1
		oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
d909 1
a909 1
		modalMenuPtr = menuPtr;
d915 1
a915 1
		if (!inPostMenu) {
d918 1
a918 1
 
d933 1
a933 1
		modalMenuPtr = NULL;
d943 1
a943 1
	    hashEntryPtr = Tcl_FindHashEntry(&commandTable,
d964 4
a967 2
		if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr 
			!= NULL)) {
d969 9
a977 8
			 strcmp(parentEntryPtr->name, 
				 Tk_PathName(menuPtr->tkwin)) != 0; 
			 parentEntryPtr = parentEntryPtr->nextCascadePtr) {

			/*
			 * Empty loop body.
			 */

d979 2
a980 3
		    if (parentEntryPtr->menuPtr
			    ->entries[parentEntryPtr->index]->state
			    != tkDisabledUid) {
d989 2
a990 2
		if ((code != TCL_OK) && (code != TCL_CONTINUE)
			&& (code != TCL_BREAK)) {
d1004 2
a1005 1
	    hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *plParam);
d1012 8
a1019 1
		    int underline = menuPtr->entries[i]->underline;
d1021 1
a1021 1
			    && (NULL != menuPtr->entries[i]->label)
d1023 2
a1024 2
			    == CharUpper((LPTSTR) (unsigned char) menuPtr
			    ->entries[i]->label[underline]))) {
d1045 1
a1045 1
		    itemPtr->itemWidth += 2 - indicatorDimensions[0];
d1047 6
a1052 1
		    itemPtr->itemWidth += 2 * menuPtr->activeBorderWidth;
d1066 2
d1074 1
a1074 1
		if (mePtr->state != tkDisabledUid) {
d1082 3
a1084 2
		Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
		TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, menuPtr->tkfont,
d1103 3
a1105 3
		Tcl_SetServiceMode(oldServiceMode);
		if (modalMenuPtr != NULL) {
		    RecursivelyClearActiveMenu(modalMenuPtr);
d1109 2
a1110 2
		if (*plParam != 0) {
		    hashEntryPtr = Tcl_FindHashEntry(&winMenuTable,
d1123 2
a1124 1
			    hashEntryPtr = Tcl_FindHashEntry(&commandTable,
d1127 2
a1128 1
				mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
d1133 1
a1133 1
		    if ((mePtr == NULL) || (mePtr->state == tkDisabledUid)) {
d1206 2
d1214 2
a1215 1
	hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
d1219 2
a1220 2
	hashEntryPtr = Tcl_CreateHashEntry(&winMenuTable, (char *) winMenuHdl,
		&newEntry);
d1292 5
a1296 1
	*widthPtr = indicatorDimensions[1] - menuPtr->borderWidth;
d1328 1
a1328 1
    } else if (mePtr->accel == NULL) {
d1331 2
a1332 1
	*widthPtr = Tk_TextWidth(tkfont, mePtr->accel, mePtr->accelLength);
d1422 1
a1422 1
    CONST RECT *rectPtr;		/* The rectangle to draw into */			
d1508 11
a1518 6
    if ((mePtr->type == CHECK_BUTTON_ENTRY || 
    	    mePtr->type == RADIO_BUTTON_ENTRY) 
    	    && mePtr->indicatorOn
	    && mePtr->entryFlags & ENTRY_SELECTED) {
	RECT rect;
	GC whichGC;
d1520 34
a1553 34
	if (mePtr->state != tkNormalUid) {
	    whichGC = gc;
	} else {
	    whichGC = indicatorGC;
	}

	rect.top = y;
	rect.bottom = y + mePtr->height;
	rect.left = menuPtr->borderWidth + menuPtr->activeBorderWidth + x;
	rect.right = mePtr->indicatorSpace + x;

	if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL)
		&& (versionInfo.dwMajorVersion >= 4)) {
	    RECT hilightRect;
	    COLORREF oldFgColor = whichGC->foreground;
	
	    whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
	    hilightRect.top = rect.top + 1;
	    hilightRect.bottom = rect.bottom + 1;
	    hilightRect.left = rect.left + 1;
	    hilightRect.right = rect.right + 1;
	    DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, 
		    &hilightRect, OBM_CHECK, 0);
	    whichGC->foreground = oldFgColor;
	}

	DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect, 
		OBM_CHECK, 0);

	if ((mePtr->state == tkDisabledUid) 
		&& (menuPtr->disabledImageGC != None)
		&& (versionInfo.dwMajorVersion < 4)) {
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
		    rect.left, rect.top, rect.right, rect.bottom);
d1598 5
d1606 2
a1607 2
    if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL)
	    && ((mePtr->accel != NULL)
d1613 2
a1614 2
	    if (mePtr->accel != NULL) {
		Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
d1632 2
a1633 2
    if (mePtr->accel != NULL) {
	Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel, 
d1637 1
a1637 1
    if ((mePtr->state == tkDisabledUid) 
d1654 1
a1654 1
	if ((mePtr->state == tkDisabledUid) 
d1693 1
d1699 3
a1701 2
    Tk_Draw3DPolygon(menuPtr->tkwin, d,
	    menuPtr->border, points, 2, 1, TK_RELIEF_RAISED);
d1735 4
d1740 1
a1740 1
    		gc, tkfont, mePtr->label, x + mePtr->indicatorSpace,
d1742 1
a1742 1
		mePtr->underline, mePtr->underline + 1);
d1804 2
a1805 2
		if (eventPtr->xkey.nchars > 0) {
		    for (i = 0; i < eventPtr->xkey.nchars; i++) {
d1931 2
a1932 1
    int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
d1935 4
d1956 1
a1956 1
    } else if (mePtr->bitmap != None) {
d1958 5
a1962 7

        Tk_SizeOfBitmap(menuPtr->display,
	        mePtr->bitmap, &width, &height);
    	XCopyPlane(menuPtr->display,
	    	mePtr->bitmap, d,
	    	gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
	    	(int) (y + (mePtr->height - height)/2), 1);
d1965 3
a1967 3
	    Tk_DrawChars(menuPtr->display, d, gc,
		    tkfont, mePtr->label, mePtr->labelLength,
		    leftEdge, baseline);
d1973 2
a1974 2
    if (mePtr->state == tkDisabledUid) {
	if (menuPtr->disabledFg == NULL) {
d2045 1
d2056 1
d2063 1
a2063 1
	Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
d2078 1
a2078 1
 *	interp->result contains an error message.
d2149 1
a2149 2
    if ((mePtr->state == tkActiveUid)
	    && !strictMotif) {
d2157 1
d2162 3
a2164 3
    	    if (strcmp(cascadeEntryPtr->name, 
    	    	    Tk_PathName(menuPtr->tkwin)) == 0) {
    	    	if (cascadeEntryPtr->state == tkDisabledUid) {
d2171 2
a2172 2
	if (((parentDisabled || (mePtr->state == tkDisabledUid)))
		&& (menuPtr->disabledFg != NULL)) {
d2188 4
a2191 5
	    
    bgBorder = mePtr->border;
    if (bgBorder == NULL) {
	bgBorder = menuPtr->border;
    }
d2195 3
a2197 4
	activeBorder = mePtr->activeBorder;
	if (activeBorder == NULL) {
	    activeBorder = menuPtr->activeBorder;
	}
d2200 1
a2200 1
    if (mePtr->tkfont == NULL) {
d2203 1
a2203 1
	tkfont = mePtr->tkfont;
d2266 3
a2268 2
    } else if (mePtr->bitmap != (Pixmap) NULL) {
    	Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
d2272 4
a2275 2
    	if (mePtr->label != NULL) {
    	    *widthPtr = Tk_TextWidth(tkfont, mePtr->label, mePtr->labelLength);
d2312 1
a2312 1
    if (mePtr->state == tkActiveUid) {
d2342 1
a2342 1
    Tk_Font tkfont;
d2347 1
d2353 3
a2355 1
    x = y = menuPtr->borderWidth;
d2370 5
a2374 2
    Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
    accelSpace = Tk_TextWidth(menuPtr->tkfont, "M", 1);
d2377 6
a2382 5
    	tkfont = menuPtr->entries[i]->tkfont;
    	if (tkfont == NULL) {
    	    tkfont = menuPtr->tkfont;
    	    fmPtr = &menuMetrics;
    	} else {
a2385 1
    	
d2394 1
a2394 1
			+ accelWidth + 2 * menuPtr->activeBorderWidth;
d2399 1
a2399 1
		    + 2 * menuPtr->borderWidth;
d2402 1
a2402 1
	    y = menuPtr->borderWidth;
d2450 1
a2450 1
	    menuPtr->entries[i]->height += 2 * menuPtr->activeBorderWidth + 1;
d2466 1
a2466 1
		+ accelWidth + 2 * menuPtr->activeBorderWidth;
d2471 1
a2471 2
	    + 2 * menuPtr->activeBorderWidth
	    + 2 * menuPtr->borderWidth;
d2474 1
a2474 1
    windowHeight += menuPtr->borderWidth;
d2600 4
a2603 1
    DestroyWindow(menuHWND);
d2610 39
a2648 1
 * TkpMenuInit --
d2663 3
a2665 1
TkpMenuInit()
d2667 1
a2667 2
    WNDCLASS wndClass;
    char sizeString[4];
a2672 1
    int i;
d2674 2
a2676 19
    Tcl_InitHashTable(&winMenuTable, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
 
    wndClass.style = CS_OWNDC;
    wndClass.lpfnWndProc = TkWinMenuProc;
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hInstance = Tk_GetHINSTANCE();
    wndClass.hIcon = NULL;
    wndClass.hCursor = NULL;
    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName = MENU_CLASS_NAME;
    RegisterClass(&wndClass);

    menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
	0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
d2695 11
a2705 4
    for (i = 0; ; i++) {
	if (tkMenuConfigSpecs[i].type == TK_CONFIG_END) {
	    break;
	}
d2707 2
a2708 39
	if ((strcmp(tkMenuConfigSpecs[i].dbName,
		"activeBorderWidth") == 0) ||
		(strcmp(tkMenuConfigSpecs[i].dbName, "borderWidth") == 0)) {
	    int borderWidth;

	    borderWidth = GetSystemMetrics(SM_CXBORDER);
	    if (GetSystemMetrics(SM_CYBORDER) > borderWidth) {
		borderWidth = GetSystemMetrics(SM_CYBORDER);
	    }
	    sprintf(borderString, "%d", borderWidth);
	    tkMenuConfigSpecs[i].defValue = borderString;
	} else if ((strcmp(tkMenuConfigSpecs[i].dbName, "font") == 0)) {
	    int pointSize;
	    HFONT menuFont;

	    scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
	    Tcl_DStringInit(&menuFontDString);

	    if (versionInfo.dwMajorVersion >= 4) {
		NONCLIENTMETRICS ncMetrics;

		ncMetrics.cbSize = sizeof(ncMetrics);
		SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
			&ncMetrics, 0);
		menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
	    } else {
		menuFont = GetStockObject(SYSTEM_FONT);
	    }
	    SelectObject(scratchDC, menuFont);
	    GetTextMetrics(scratchDC, &tm);
	    GetTextFace(scratchDC, sizeof(menuFontDString), faceName);
	    pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
		    72, GetDeviceCaps(scratchDC, LOGPIXELSY));
	    if (tm.tmWeight >= 700) {
		bold = 1;
	    }
	    if (tm.tmItalic) {
		italic = 1;
	    }
d2710 18
a2727 2
	    SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
	    DeleteDC(scratchDC);
d2729 2
a2730 17
	    DeleteObject(menuFont);
	    
	    Tcl_DStringAppendElement(&menuFontDString, faceName);
	    sprintf(sizeString, "%d", pointSize);
	    Tcl_DStringAppendElement(&menuFontDString, sizeString);

	    if (bold == 1 || italic == 1) {
		Tcl_DStringInit(&boldItalicDString);
		if (bold == 1) {
		    Tcl_DStringAppendElement(&boldItalicDString, "bold");
		}
		if (italic == 1) {
		    Tcl_DStringAppendElement(&boldItalicDString, "italic");
		}
		Tcl_DStringAppendElement(&menuFontDString, 
			Tcl_DStringValue(&boldItalicDString));
	    }
d2732 13
a2744 1
	    tkMenuConfigSpecs[i].defValue = Tcl_DStringValue(&menuFontDString);
d2746 2
d2771 65
d2837 2
@


1.3
log
@Replaced SCCS strings, fixed binary files
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id$
d367 4
@


1.2
log
@fixed bug in menus where bgerrors were not generated during menu callbacks
fixed memory leak in menu code
fixed Alt-key handling
@
text
@d11 1
a11 1
 * SCCS: @@(#) tkWinMenu.c 1.102 97/10/28 13:56:58
@


1.1
log
@Initial revision
@
text
@d4 1
a4 1
 *	This module implements the Mac-platform specific features of menus.
d323 3
a325 6
    if (NULL != winMenuHdl) {
	if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {
	    TkMenuEntry *searchEntryPtr;
	    Tcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);
	    char *menuName = Tcl_GetHashKey(tablePtr, 
		    menuPtr->menuRefPtr->hashEntryPtr);
d327 5
a331 7
	    for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
		    searchEntryPtr != NULL;
		    searchEntryPtr = searchEntryPtr->nextCascadePtr) {
		if (strcmp(searchEntryPtr->name,
			menuName) == 0) {
		    Tk_Window parentTopLevelPtr = searchEntryPtr
			    ->menuPtr->parentTopLevelPtr;
d333 16
a348 5
		    if (parentTopLevelPtr != NULL) {
			GetSystemMenu(TkWinGetWrapperWindow(parentTopLevelPtr),
				TRUE);
		    }
		    break;
d350 1
a351 2
	} else {
    	    DestroyMenu(winMenuHdl);
d353 12
a364 1
    	menuPtr->platformData = NULL;
d366 1
d549 1
a549 1
	height = Tk_Width(menuPtr->parentTopLevelPtr);
d604 18
a621 19
	    if (mePtr->type == CASCADE_ENTRY) {
		if ((mePtr->childMenuRefPtr != NULL)
			&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
		    HMENU childMenuHdl = 
			    (HMENU) mePtr->childMenuRefPtr->menuPtr
			    ->platformData;
		    if (childMenuHdl != NULL) {
			itemID = (UINT) childMenuHdl;
			flags |= MF_POPUP;
		    }
		    if ((menuPtr->menuType == MENUBAR) 
			    && !(mePtr->childMenuRefPtr->menuPtr->menuFlags
			    & MENU_SYSTEM_MENU)) {
			TkMenuReferences *menuRefPtr;
			TkMenu *systemMenuPtr = mePtr->childMenuRefPtr
				->menuPtr;
			char *systemMenuName = ckalloc(strlen(
				Tk_PathName(menuPtr->masterMenuPtr->tkwin))
				+ strlen(".system") + 1);
d623 26
a648 28
			strcpy(systemMenuName, 
				Tk_PathName(menuPtr->masterMenuPtr->tkwin));
			strcat(systemMenuName, ".system");
			menuRefPtr = TkFindMenuReferences(menuPtr->interp,
				systemMenuName);
			if ((menuRefPtr != NULL) 
				&& (menuRefPtr->menuPtr != NULL)
				&& (menuPtr->parentTopLevelPtr != NULL)
				&& (systemMenuPtr->masterMenuPtr
				== menuRefPtr->menuPtr)) {
			    HMENU systemMenuHdl = 
				    (HMENU) systemMenuPtr->platformData;
			    HWND wrapper = TkWinGetWrapperWindow(menuPtr
				    ->parentTopLevelPtr);
			    if (wrapper != NULL) {
				DestroyMenu(systemMenuHdl);
				systemMenuHdl = GetSystemMenu(
				    wrapper, FALSE);
				systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
				systemMenuPtr->platformData = 
					(TkMenuPlatformData) systemMenuHdl;
				if (!(systemMenuPtr->menuFlags 
					& MENU_RECONFIGURE_PENDING)) {
				    systemMenuPtr->menuFlags 
					    |= MENU_RECONFIGURE_PENDING;
				    Tcl_DoWhenIdle(ReconfigureWindowsMenu,
					    (ClientData) systemMenuPtr);
				}
a650 1
			ckfree(systemMenuName);
d652 1
a652 4
		    if (mePtr->childMenuRefPtr->menuPtr->menuFlags 
			    & MENU_SYSTEM_MENU) {
			systemMenu++;
		    }
d654 4
d900 12
a911 1
		    TkPreprocessMenu(menuPtr);
d924 14
a937 8
	    if (HIWORD(*pwParam) == 0) {
		hashEntryPtr = Tcl_FindHashEntry(&commandTable,
			(char *)LOWORD(*pwParam));
		if (hashEntryPtr != NULL) {
		    mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
		    if (mePtr != NULL) {
			TkMenuReferences *menuRefPtr;
			TkMenuEntry *parentEntryPtr;
d939 16
d956 1
a956 3
			 * We have to set the parent of this menu to be active
			 * if this is a submenu so that tearoffs will get the
			 * correct title.
a958 25
			menuPtr = mePtr->menuPtr;
    			menuRefPtr = TkFindMenuReferences(menuPtr->interp,
    	    			Tk_PathName(menuPtr->tkwin));
    			if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr 
				!= NULL)) {
    	    		    for (parentEntryPtr = menuRefPtr->parentEntryPtr;
    	    	    		    strcmp(parentEntryPtr->name, 
				    Tk_PathName(menuPtr->tkwin)) != 0; 
				    parentEntryPtr = parentEntryPtr->nextCascadePtr) {

				/*
				 * Empty loop body.
				 */

    	    		    }
    	    		    if (parentEntryPtr->menuPtr
    	    		    	    ->entries[parentEntryPtr->index]->state
    	    		    	    != tkDisabledUid) {
			    	TkActivateMenuEntry(parentEntryPtr->menuPtr, 
				    	parentEntryPtr->index);
			    }
    			}

		    	TkInvokeMenu(mePtr->menuPtr->interp,
				menuPtr, mePtr->index);
d960 6
a965 2
		    *plResult = 0;
		    returnResult = 1;
d967 10
d978 2
d1000 1
a1003 1
		returnResult = 1;
d1716 1
d1744 9
@


1.1.4.1
log
@initial tk8.1a2 version
@
text
@d4 1
a4 1
 *	This module implements the Windows-platform specific features of menus.
d6 1
a6 1
 * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
d11 1
a11 1
 * SCCS: @@(#) tkWinMenu.c 1.110 98/01/26 19:43:53
d15 2
a17 3
#include "tkMenu.h"

#include <string.h>
d77 1
a77 1
static int defaultBorderWidth;	/* The windows default border width. */
d125 1
a125 1
static TCHAR *		GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
a156 1
static void		SetDefaults _ANSI_ARGS_((int firstTime));
a317 1
    char *searchName;
d333 1
a333 3
		searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr,
			NULL);
		if (strcmp(searchName,
d413 1
a413 1
    } else if (mePtr->imagePtr != NULL) {
d416 1
a416 1
    } else if (mePtr->bitmapPtr != NULL) {
d419 1
a419 1
    } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
a424 4
	char *label = (mePtr->labelPtr == NULL) ? "" 
		: Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
	char *accel = (mePtr->accelPtr == NULL) ? "" 
		: Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
d434 1
a434 1
	    if (label[i] == '&') {
d441 1
a441 1
	    if (label[mePtr->underline] == '&') {
d451 1
a451 1
	    if (accel[i] == '&') {
d462 1
a462 1
		if (label[i] == '&') {
d468 1
a468 1
		itemText[j] = label[i];
d477 1
a477 1
		if (accel[i] == '&') {
d480 1
a480 1
		itemText[j] = accel[i];
d512 2
a513 2
    TCHAR *itemText = NULL;
    const TCHAR *lpNewItem;
a554 2
	    int columnBreak, state;

d568 1
a568 3
	    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
		    NULL, 0, &state);
	    if (state == ENTRY_DISABLED) {
d582 1
a582 3
	    Tcl_GetBooleanFromObj(NULL, mePtr->columnBreakPtr, 
		    &columnBreak);
	    if (columnBreak) {
d606 4
a906 1
			int code;
d917 10
a926 4
    			if ((menuRefPtr != NULL)
				&& (menuRefPtr->parentEntryPtr != NULL)) {
			    char *name;
			    int state;
a927 10
    	    		    for (parentEntryPtr = menuRefPtr->parentEntryPtr;
    	    	    		    ; 
				    parentEntryPtr = 
				    parentEntryPtr->nextCascadePtr) {
				name = Tcl_GetStringFromObj(
					parentEntryPtr->namePtr, NULL);
				if (strcmp(name, Tk_PathName(menuPtr->tkwin))
					== 0) {
				    break;
				}
d929 3
a931 5
			    Tcl_GetIndexFromObj(NULL, parentEntryPtr->menuPtr
				    ->entries[parentEntryPtr->index]
				    ->statePtr, tkMenuStateStrings, NULL, 
				    0, &state);
    	    		    if (state != ENTRY_DISABLED) {
d937 1
a937 1
		    	code = TkInvokeMenu(mePtr->menuPtr->interp,
a938 6
 			if (code != TCL_OK && code != TCL_CONTINUE
				&& code != TCL_BREAK) {
			    Tcl_AddErrorInfo(mePtr->menuPtr->interp, 
				    "\n    (menu invoke)");
			    Tcl_BackgroundError(mePtr->menuPtr->interp);
 			}
d957 1
a957 8
		    int underline;
		    char *label;

		    underline = menuPtr->entries[i]->underline;
		    if (menuPtr->entries[i]->labelPtr != NULL) {
			label = Tcl_GetStringFromObj(
				menuPtr->entries[i]->labelPtr, NULL);
		    }
d959 1
a959 1
			    && (NULL != menuPtr->entries[i]->labelPtr)
d961 2
a962 2
			    == CharUpper((LPTSTR) (unsigned char) 
			    label[underline]))) {
a975 2
		int hideMargin;

d982 2
a983 4
		Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr,
			&hideMargin);
		if (hideMargin) {
		    itemPtr->itemWidth += 2 - indicatorDimensions[1];
d985 1
a985 6
		    int activeBorderWidth;
		    
		    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
			    menuPtr->activeBorderWidthPtr, 
			    &activeBorderWidth);
		    itemPtr->itemWidth += 2 * activeBorderWidth;
a998 3
		int state;
		Tk_Font tkfont;

d1005 1
a1005 3
		Tcl_GetIndexFromObj(NULL, mePtr->statePtr, 
			tkMenuStateStrings, NULL, 0, &state);
		if (state != ENTRY_DISABLED) {
d1013 2
a1014 3
		tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
		Tk_GetFontMetrics(tkfont, &fontMetrics);
		TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont,
a1047 2
		    int state;

d1056 1
a1056 2
				mePtr = (TkMenuEntry *) 
					Tcl_GetHashValue(hashEntryPtr);
d1061 1
a1061 1
		    if (mePtr == NULL) {
d1064 1
a1064 7
			Tcl_GetIndexFromObj(NULL, mePtr->statePtr,
				tkMenuStateStrings, NULL, 0, &state);
			if (state == ENTRY_DISABLED) {
			    TkActivateMenuEntry(menuPtr, -1);
			} else {
			    TkActivateMenuEntry(menuPtr, mePtr->index);
			}
a1212 2
    int hideMargin;

d1214 1
a1214 2
    Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, &hideMargin);
    if (hideMargin) {
d1217 1
a1217 5
	int borderWidth;

	Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
		menuPtr->borderWidthPtr, &borderWidth);
	*widthPtr = indicatorDimensions[1] - borderWidth;
d1249 1
a1249 1
    } else if (mePtr->accelPtr == NULL) {
d1252 1
a1252 2
	char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
	*widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
d1342 1
a1342 1
    CONST RECT *rectPtr;		/* The rectangle to draw into */
d1428 35
a1462 18
    if ((mePtr->type == CHECK_BUTTON_ENTRY) 
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
	int indicatorOn;

	Tcl_GetBooleanFromObj(NULL, mePtr->indicatorOnPtr, &indicatorOn);

    	if (indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
	    RECT rect;
	    GC whichGC;
	    int state;
	    int borderWidth, activeBorderWidth;
	    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
		    NULL, 0, &state);
	    if (state != ENTRY_NORMAL) {
		whichGC = gc;
	    } else {
		whichGC = indicatorGC;
	    }
d1464 5
a1468 34
	    rect.top = y;
	    rect.bottom = y + mePtr->height;
	    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
		    menuPtr->borderWidthPtr, &borderWidth);
	    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
		    menuPtr->activeBorderWidthPtr, &activeBorderWidth);
	    rect.left = borderWidth + activeBorderWidth + x;
	    rect.right = mePtr->indicatorSpace + x;

	    if ((state == ENTRY_DISABLED)
		    && (menuPtr->disabledFgPtr != NULL)
		    && (versionInfo.dwMajorVersion >= 4)) {
		RECT hilightRect;
		COLORREF oldFgColor = whichGC->foreground;
	    
		whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
		hilightRect.top = rect.top + 1;
		hilightRect.bottom = rect.bottom + 1;
		hilightRect.left = rect.left + 1;
		hilightRect.right = rect.right + 1;
		DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, 
			&hilightRect, OBM_CHECK, 0);
		whichGC->foreground = oldFgColor;
	    }

	    DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect, 
		    OBM_CHECK, 0);

	    if ((state == ENTRY_DISABLED) 
		    && (menuPtr->disabledImageGC != None)
		    && (versionInfo.dwMajorVersion < 4)) {
		XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
			rect.left, rect.top, rect.right, rect.bottom);
	    }
a1512 6
    int state;
    char *accel;
    
    if (mePtr->accelPtr != NULL) {
	accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
    }
d1516 2
a1517 4
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL,
	    0, &state);
    if ((state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
	    && ((mePtr->accelPtr != NULL)
d1523 2
a1524 2
	    if (mePtr->accelPtr != NULL) {
		Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
d1542 2
a1543 2
    if (mePtr->accelPtr != NULL) {
	Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, 
d1547 1
a1547 1
    if ((state == ENTRY_DISABLED) 
d1564 1
a1564 1
	if ((state == ENTRY_DISABLED) 
a1602 1
    Tk_3DBorder border;
d1608 2
a1609 3
    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
    Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, 
	    TK_RELIEF_RAISED);
a1642 2
	char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);

d1644 1
a1644 1
    		gc, tkfont, label, x + mePtr->indicatorSpace,
d1825 1
a1825 2
    int activeBorderWidth;
    int leftEdge;
a1826 5
    int state;

    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
	    menuPtr->activeBorderWidthPtr, &activeBorderWidth);
    leftEdge = x + indicatorSpace + activeBorderWidth;
d1845 1
a1845 1
    } else if (mePtr->bitmapPtr != NULL) {
d1847 7
a1853 5
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
        Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
    	XCopyPlane(menuPtr->display, bitmap, d,	gc, 0, 0, (unsigned) width, 
		(unsigned) height, leftEdge,
		(int) (y + (mePtr->height - height)/2), 1);
d1856 3
a1858 3
	    char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, 
		    mePtr->labelLength, leftEdge, baseline);
d1864 2
a1865 4
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL,
	    0, &state);
    if (state == ENTRY_DISABLED) {
	if (menuPtr->disabledFgPtr == NULL) {
a1935 1
    Tk_3DBorder border;
a1945 1
    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
d1952 1
a1952 1
	Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
d1967 1
a1967 1
 *	the interp's result contains an error message.
a2032 1
    int state;
d2038 2
a2039 3
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL,
	    0, &state);
    if ((state == ENTRY_ACTIVE) && !strictMotif) {
a2046 1
	char *name;
d2051 3
a2053 3
	    name = Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
    	    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
    	    	if (state == ENTRY_DISABLED) {
d2060 2
a2061 2
	if (((parentDisabled || (state == ENTRY_DISABLED)))
		&& (menuPtr->disabledFgPtr != NULL)) {
d2077 5
a2081 4

    bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
	    (mePtr->borderPtr == NULL) ? menuPtr->borderPtr
	    : mePtr->borderPtr);
d2085 4
a2088 3
	activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
	    (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr
	    : mePtr->activeBorderPtr);
d2091 1
a2091 1
    if (mePtr->fontPtr == NULL) {
d2094 1
a2094 1
	tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
a2114 2
	int hideMargin;

d2119 1
a2119 2
	Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, &hideMargin);
	if (!hideMargin) {
d2157 2
a2158 3
    } else if (mePtr->bitmapPtr != NULL) {
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
    	Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
d2162 2
a2163 4
    	if (mePtr->labelPtr != NULL) {
	    char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);

    	    *widthPtr = Tk_TextWidth(tkfont, label, mePtr->labelLength);
d2200 1
a2200 5
    int state;

    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
	    NULL, 0, &state);
    if (state == ENTRY_ACTIVE) {
d2230 1
a2230 1
    Tk_Font menuFont, tkfont;
a2234 2
    int columnBreak;
    int activeBorderWidth, borderWidth;
d2240 1
a2240 3
    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin, 
	    menuPtr->borderWidthPtr, &borderWidth);
    x = y = borderWidth;
d2255 2
a2256 5
    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
    Tk_GetFontMetrics(menuFont, &menuMetrics);
    accelSpace = Tk_TextWidth(menuFont, "M", 1);
    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
	    menuPtr->activeBorderWidthPtr, &activeBorderWidth);
d2259 5
a2263 6
	if (menuPtr->entries[i]->fontPtr == NULL) {
	    tkfont = menuFont;
	    fmPtr = &menuMetrics;
	} else {
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
		    menuPtr->entries[i]->fontPtr);
d2267 2
a2268 4

	Tcl_GetBooleanFromObj(NULL, menuPtr->entries[i]->columnBreakPtr,
		&columnBreak);
	if ((i > 0) && columnBreak) {
d2276 1
a2276 1
			+ accelWidth + 2 * activeBorderWidth;
d2281 1
a2281 1
		    + 2 * borderWidth;
d2284 1
a2284 1
	    y = borderWidth;
d2332 1
a2332 1
	    menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;
d2348 1
a2348 1
		+ accelWidth + 2 * activeBorderWidth;
d2353 2
a2354 1
	    + 2 * activeBorderWidth + 2 * borderWidth;
d2357 1
a2357 1
    windowHeight += borderWidth;
d2490 1
a2490 39
 * TkWinGetMenuSystemDefault --
 *
 *	Gets the Windows specific default value for a given X resource
 *	database name.
 *
 * Results:
 *	Returns a Tcl_Obj * with the default value. If there is no
 *	Windows-specific default for this attribute, returns NULL.
 *	This object has a ref count of 0.
 *
 * Side effects:
 *	Storage is allocated.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TkWinGetMenuSystemDefault(
    Tk_Window tkwin,		/* A window to use. */
    char *dbName,		/* The option database name. */
    char *className)		/* The name of the option class. */
{
    Tcl_Obj *valuePtr = NULL;

    if ((strcmp(dbName, "activeBorderWidth") == 0) ||
	    (strcmp(dbName, "borderWidth") == 0)) {
	valuePtr = Tcl_NewIntObj(defaultBorderWidth);
    } else if (strcmp(dbName, "font") == 0) {
	valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString),
		-1);
    }

    return valuePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinMenuSetDefaults --
d2505 1
a2505 3
SetDefaults(
    int firstTime)		    /* Is this the first time this
				     * has been called? */
d2507 2
a2508 1
    char sizeString[TCL_INTEGER_SPACE];
d2514 1
a2515 2
    int pointSize;
    HFONT menuFont;
d2517 19
d2554 4
a2557 4
    defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);
    if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {
	defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
    }
d2559 39
d2599 2
a2600 5
    scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    if (!firstTime) {
	Tcl_DStringFree(&menuFontDString);
    }
    Tcl_DStringInit(&menuFontDString);
d2602 17
a2618 2
    if (versionInfo.dwMajorVersion >= 4) {
	NONCLIENTMETRICS ncMetrics;
d2620 1
a2620 32
	ncMetrics.cbSize = sizeof(ncMetrics);
	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
		&ncMetrics, 0);
	menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
    } else {
	menuFont = GetStockObject(SYSTEM_FONT);
    }
    SelectObject(scratchDC, menuFont);
    GetTextMetrics(scratchDC, &tm);
    GetTextFace(scratchDC, sizeof(menuFontDString), faceName);
    pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
	    72, GetDeviceCaps(scratchDC, LOGPIXELSY));
    if (tm.tmWeight >= 700) {
	bold = 1;
    }
    if (tm.tmItalic) {
	italic = 1;
    }

    SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
    DeleteDC(scratchDC);

    DeleteObject(menuFont);
    
    Tcl_DStringAppendElement(&menuFontDString, faceName);
    sprintf(sizeString, "%d", pointSize);
    Tcl_DStringAppendElement(&menuFontDString, sizeString);

    if (bold == 1 || italic == 1) {
	Tcl_DStringInit(&boldItalicDString);
	if (bold == 1) {
	    Tcl_DStringAppendElement(&boldItalicDString, "bold");
a2621 5
	if (italic == 1) {
	    Tcl_DStringAppendElement(&boldItalicDString, "italic");
	}
	Tcl_DStringAppendElement(&menuFontDString, 
		Tcl_DStringValue(&boldItalicDString));
a2644 23
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuInit --
 *
 *	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
TkpMenuInit()
{
    WNDCLASS wndClass;
a2645 19
    Tcl_InitHashTable(&winMenuTable, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
    wndClass.style = CS_OWNDC;
    wndClass.lpfnWndProc = TkWinMenuProc;
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hInstance = Tk_GetHINSTANCE();
    wndClass.hIcon = NULL;
    wndClass.hCursor = NULL;
    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName = MENU_CLASS_NAME;
    RegisterClass(&wndClass);

    menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
	0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
    SetDefaults(1);
@


1.1.4.2
log
@Merged 8.0.3 changes into 8.1
@
text
@d4 1
a4 1
 *	This module implements the Windows platform-specific features of menus.
d11 1
a11 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.3 1998/09/14 18:24:00 stanton Exp $
d326 22
a347 27
    if (winMenuHdl == NULL) {
	return;
    }

    if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {
	TkMenuEntry *searchEntryPtr;
	Tcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);
	char *menuName = Tcl_GetHashKey(tablePtr, 
		menuPtr->menuRefPtr->hashEntryPtr);

	/*
	 * Search for the menu in the menubar, if it is present, get the
	 * wrapper window associated with the toplevel and reset its
	 * system menu to the default menu.
	 */

	for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
	     searchEntryPtr != NULL;
	     searchEntryPtr = searchEntryPtr->nextCascadePtr) {
	    searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, NULL);
	    if (strcmp(searchName, menuName) == 0) {
		Tk_Window parentTopLevelPtr = searchEntryPtr
		    ->menuPtr->parentTopLevelPtr;

		if (parentTopLevelPtr != NULL) {
		    GetSystemMenu(TkWinGetWrapperWindow(parentTopLevelPtr),
			    TRUE);
a348 1
		break;
d350 2
d353 1
a353 12
    } else {
	Tcl_HashEntry *hashEntryPtr;
 
	/*
	 * Remove the menu from the menu hash table, then destroy the handle.
	 */

	hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
	if (hashEntryPtr != NULL) {
	    Tcl_DeleteHashEntry(hashEntryPtr);
	}
 	DestroyMenu(winMenuHdl);
a354 1
    menuPtr->platformData = NULL;
d541 1
a541 1
	height = Tk_Height(menuPtr->parentTopLevelPtr);
d602 44
a645 41
	    if ((mePtr->type == CASCADE_ENTRY)
		    && (mePtr->childMenuRefPtr != NULL)
		    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
		HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr
		    ->platformData;
		if (childMenuHdl != NULL) {
		    itemID = (UINT) childMenuHdl;
		    flags |= MF_POPUP;
		}
		if ((menuPtr->menuType == MENUBAR) 
			&& !(mePtr->childMenuRefPtr->menuPtr->menuFlags
				& MENU_SYSTEM_MENU)) {
		    TkMenuReferences *menuRefPtr;
		    TkMenu *systemMenuPtr = mePtr->childMenuRefPtr
			->menuPtr;
		    char *systemMenuName = ckalloc(strlen(
			Tk_PathName(menuPtr->masterMenuPtr->tkwin))
			    + strlen(".system") + 1);
		    menuRefPtr = TkFindMenuReferences(menuPtr->interp,
			    systemMenuName);
		    if ((menuRefPtr != NULL) 
			    && (menuRefPtr->menuPtr != NULL)
			    && (menuPtr->parentTopLevelPtr != NULL)
			    && (systemMenuPtr->masterMenuPtr
				    == menuRefPtr->menuPtr)) {
			HMENU systemMenuHdl = 
			    (HMENU) systemMenuPtr->platformData;
			HWND wrapper = TkWinGetWrapperWindow(menuPtr
				->parentTopLevelPtr);
			if (wrapper != NULL) {
			    DestroyMenu(systemMenuHdl);
			    systemMenuHdl = GetSystemMenu(wrapper, FALSE);
			    systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
			    systemMenuPtr->platformData = 
				(TkMenuPlatformData) systemMenuHdl;
			    if (!(systemMenuPtr->menuFlags 
				    & MENU_RECONFIGURE_PENDING)) {
				systemMenuPtr->menuFlags 
				    |= MENU_RECONFIGURE_PENDING;
				Tcl_DoWhenIdle(ReconfigureWindowsMenu,
					(ClientData) systemMenuPtr);
d648 5
a653 5
		    ckfree(systemMenuName);
		}
		if (mePtr->childMenuRefPtr->menuPtr->menuFlags 
			& MENU_SYSTEM_MENU) {
		    systemMenu++;
d897 1
a897 12
		    Tcl_Interp *interp;
		    int code;
 
		    interp = menuPtr->interp;
		    Tcl_Preserve((ClientData)interp);
		    code = TkPreprocessMenu(menuPtr);
		    if ((code != TCL_OK) && (code != TCL_CONTINUE)
			    && (code != TCL_BREAK)) {
			Tcl_AddErrorInfo(interp, "\n    (menu preprocess)");
			Tcl_BackgroundError(interp);
		    }
		    Tcl_Release((ClientData)interp);
d910 44
a953 28
	    if (HIWORD(*pwParam) != 0) {
		break;
	    }
	    hashEntryPtr = Tcl_FindHashEntry(&commandTable,
		    (char *)LOWORD(*pwParam));
	    if (hashEntryPtr == NULL) {
		break;
	    }
	    mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
	    if (mePtr != NULL) {
		TkMenuReferences *menuRefPtr;
		TkMenuEntry *parentEntryPtr;
		Tcl_Interp *interp;
		int code;

		/*
		 * We have to set the parent of this menu to be active
		 * if this is a submenu so that tearoffs will get the
		 * correct title.
		 */

		menuPtr = mePtr->menuPtr;
		menuRefPtr = TkFindMenuReferences(menuPtr->interp,
			Tk_PathName(menuPtr->tkwin));
		if ((menuRefPtr != NULL)
			&& (menuRefPtr->parentEntryPtr != NULL)) {
		    char *name;
		    int state;
d955 8
a962 18
		    for (parentEntryPtr = menuRefPtr->parentEntryPtr;
			 ; 
			 parentEntryPtr = 
			     parentEntryPtr->nextCascadePtr) {
			name = Tcl_GetStringFromObj(
			    parentEntryPtr->namePtr, NULL);
			if (strcmp(name, Tk_PathName(menuPtr->tkwin))
				== 0) {
			    break;
			}
		    }
		    Tcl_GetIndexFromObj(NULL, parentEntryPtr->menuPtr
			    ->entries[parentEntryPtr->index]
			    ->statePtr, tkMenuStateStrings, NULL, 
			    0, &state);
		    if (state != ENTRY_DISABLED) {
			TkActivateMenuEntry(parentEntryPtr->menuPtr, 
				parentEntryPtr->index);
d964 2
a966 10

		interp = menuPtr->interp;
		Tcl_Preserve((ClientData)interp);
		code = TkInvokeMenu(interp, menuPtr, mePtr->index);
		if (code != TCL_OK && code != TCL_CONTINUE
			&& code != TCL_BREAK) {
		    Tcl_AddErrorInfo(interp, "\n    (menu invoke)");
		    Tcl_BackgroundError(interp);
		}
		Tcl_Release((ClientData)interp);
a967 2
	    *plResult = 0;
	    returnResult = 1;
a994 1
			returnResult = 1;
d998 1
a1766 1
    int i;
a1793 9
		if (eventPtr->xkey.nchars > 0) {
		    for (i = 0; i < eventPtr->xkey.nchars; i++) {
			CallWindowProc(DefWindowProc,
				Tk_GetHWND(Tk_WindowId(tkwin)),
				WM_SYSCHAR,
				eventPtr->xkey.trans_chars[i],
				((scanCode << 16) | (1 << 29)));
		    }
		}
@


1.1.4.3
log
@merged 8.0.4 into 8.1
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.1.4.2 1998/09/30 02:19:35 stanton Exp $
d1823 2
a1824 2
		if (eventPtr->xkey.nbytes > 0) {
		    for (i = 0; i < eventPtr->xkey.nbytes; i++) {
@


1.1.4.4
log
@added ChangeLog
fixed bad merge
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.1.4.3 1998/10/06 03:27:36 stanton Exp $
d444 2
a445 1
	int i;
a449 2
	char *p, *next;
	Tcl_DString itemString;
d458 22
a479 1
	Tcl_DStringInit(&itemString);
d481 11
a491 15
	for (p = label, i = 0; *p != '\0'; i++, p = next) {
	    if (i == mePtr->underline) {
		Tcl_DStringAppend(&itemString, "&", 1);
	    }
	    if (*p == '&') {
		Tcl_DStringAppend(&itemString, "&", 1);
	    }
	    next = Tcl_UtfNext(p);
	    Tcl_DStringAppend(&itemString, p, next - p);
	}
        if (mePtr->accelLength > 0) {
	    Tcl_DStringAppend(&itemString, "\t", 1);
	    for (p = accel, i = 0; *p != '\0'; i++, p = next) {
		if (*p == '&') {
		    Tcl_DStringAppend(&itemString, "&", 1);
d493 1
a493 2
		next = Tcl_UtfNext(p);
		Tcl_DStringAppend(&itemString, p, next - p);
d495 2
a496 1
	} 	    
d498 11
a508 3
	itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);
	strcpy(itemText, Tcl_DStringValue(&itemString));
	Tcl_DStringFree(&itemString);
d543 1
a543 2
    Tcl_DString translatedText;
  
a571 1
	Tcl_DStringInit(&translatedText);
d585 1
a585 2
		Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);
		lpNewItem = Tcl_DStringValue(&translatedText);
a672 1
	Tcl_DStringFree(&translatedText);
d912 1
a912 1

@


1.1.4.5
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
@d11 1
a11 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.1.4.4 1998/11/20 02:36:27 stanton Exp $
d558 2
d574 3
a576 1
	    if (mePtr->state == ENTRY_DISABLED) {
d590 3
a592 1
	    if (mePtr->columnBreak) {
d941 1
d954 5
a958 2
		    if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]
			    ->state != ENTRY_DISABLED) {
d1015 2
d1023 3
a1025 1
		if (mePtr->hideMargin) {
d1047 1
d1056 3
a1058 1
		if (mePtr->state != ENTRY_DISABLED) {
d1102 2
d1118 1
a1118 1
		    if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
d1121 7
a1127 1
			TkActivateMenuEntry(menuPtr, mePtr->index);
d1276 2
d1279 2
a1280 1
    if (mePtr->hideMargin) {
d1501 5
a1505 1
    	if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
d1508 1
d1510 3
a1512 1
	    if (mePtr->state != ENTRY_NORMAL) {
d1527 1
a1527 1
	    if ((mePtr->state == ENTRY_DISABLED)
d1546 1
a1546 1
	    if ((mePtr->state == ENTRY_DISABLED) 
d1596 1
d1605 3
a1607 1
    if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
d1638 1
a1638 1
    if ((mePtr->state == ENTRY_DISABLED) 
d1655 1
a1655 1
	if ((mePtr->state == ENTRY_DISABLED) 
d1933 1
d1973 3
a1975 1
    if (mePtr->state == ENTRY_DISABLED) {
d2146 1
d2152 3
a2154 1
    if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
d2169 1
a2169 1
    	    	if (mePtr->state == ENTRY_DISABLED) {
d2176 1
a2176 1
	if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))
d2229 2
d2235 2
a2236 1
	if (!mePtr->hideMargin) {
d2320 5
a2324 1
    if (mePtr->state == ENTRY_ACTIVE) {
d2359 1
d2399 4
a2402 1
	if ((i > 0) && menuPtr->entries[i]->columnBreak) {
@


1.1.4.6
log
@* integrated tk8.0.4 changes.

* generic/tkBind.c: fixed deletion order bug where a crash would
result if a binding deleted "."
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id$
a602 1
		    Tcl_DString ds;
d606 3
a608 6

		    Tcl_DStringInit(&ds);
		    Tcl_DStringAppend(&ds,
			    Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
		    Tcl_DStringAppend(&ds, ".system", 7);

d610 1
a610 4
			    Tcl_DStringValue(&ds));
		    
		    Tcl_DStringFree(&ds);

d635 1
@


1.1.4.7
log
@
Tk 8.1 Muti-threading changes.

Moved static and global data elements into thread-local storage,
or introduced locks where not possible, as first stage of adding
thread safety to Tk.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.1.4.6 1998/11/25 21:16:42 stanton Exp $
a53 1

a59 1

d69 2
a73 5
static OSVERSIONINFO versionInfo;
				/* So we don't have to keep doing this */

TCL_DECLARE_MUTEX(winmenuMutex)

a2757 6

    Tcl_MutexLock(&winMenuMutex);


    Tcl_MutexUnlock(&winMenuMutex);

@


1.1.4.8
log
@Fixed Windows bugs encountered while building w/ threads enabled.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.1.4.7 1998/12/13 08:16:18 lfb Exp $
d55 1
a55 2
typedef struct ThreadSpecificData {
    Tcl_HashTable commandTable;
d57 3
a59 3
    int inPostMenu;		/* We cannot be re-entrant like X Windows. */
    WORD lastCommandID;	        /* The last command ID we allocated. */
    HWND menuHWND;		/* A window to service popup-menu messages
d61 2
a62 1
    int oldServiceMode;	        /* Used while processing a menu; we need
d66 1
a66 1
    TkMenu *modalMenuPtr;	/* The menu we are processing inside the modal
d71 1
a71 1
    Tcl_HashTable winMenuTable;
a72 2
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
d77 2
a86 1
TCL_DECLARE_MUTEX(winMenuMutex)
a198 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d200 1
a200 1
    WORD curID = tsdPtr->lastCommandID + 1;
d207 2
a208 2
    while (curID != tsdPtr->lastCommandID) {
    	commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,
d221 1
a221 1
    	tsdPtr->lastCommandID = returnID;
d248 1
a248 4
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
a281 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d296 1
a296 1
    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl,
a325 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d369 1
a369 2
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                (char *) winMenuHdl);
a702 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d704 1
a704 1
    tsdPtr->inPostMenu++;
d713 1
a713 1
	tsdPtr->inPostMenu--;
d723 1
a723 1
	tsdPtr->inPostMenu--;
d764 1
a764 1
	    tsdPtr->menuHWND, &noGoawayRect);
d770 2
a771 2
    if (tsdPtr->inPostMenu) {
	tsdPtr->inPostMenu = 0;
a879 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d884 1
a884 2
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                    (char *) *pwParam);
d886 1
a886 1
		tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
d888 1
a888 1
		tsdPtr->modalMenuPtr = menuPtr;
d894 1
a894 1
		if (!tsdPtr->inPostMenu) {
d912 1
a912 1
		tsdPtr->modalMenuPtr = NULL;
d922 1
a922 1
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
d983 1
a983 2
	    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                    (char *) *plParam);
d1081 3
a1083 3
		Tcl_SetServiceMode(tsdPtr->oldServiceMode);
		if (tsdPtr->modalMenuPtr != NULL) {
		    RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
d1087 2
a1088 2
 		if (*plParam != 0) {
		    hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
d1101 1
a1101 2
			    hashEntryPtr = Tcl_FindHashEntry(
                                    &tsdPtr->commandTable,
a1182 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d1189 1
a1189 2
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable, 
                (char *) winMenuHdl);
d1193 2
a1194 2
	hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, 
                (char *) winMenuHdl, &newEntry);
d2572 1
a2572 4
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    DestroyWindow(tsdPtr->menuHWND);
a2762 2
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
d2764 8
a2771 2
    Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);
d2784 1
a2784 1
    tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
@


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

* Integrated patches from 8.0.5b2
@
text
@a6 1
 * Copyright (c) 1998-1999 by Scriptics Corporation.
d11 1
a11 1
 * RCS: @@(#) $Id$
a386 4

    if (menuPtr == tsdPtr->modalMenuPtr) {
	tsdPtr->modalMenuPtr = NULL;
    }
@


1.1.4.10
log
@Added TkpThreadInit function for performing thread-specific
initialization of Menu module.  Only does real work on Windows.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkWinMenu.c,v 1.1.4.9 1999/02/11 04:13:51 stanton Exp $
d2776 1
a2776 1
 *	Sets up the process-wide variables used by the menu package.
d2782 2
a2783 1
 *	lastMenuID gets initialized.
d2795 2
a2813 26
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuThreadInit --
 *
 *	Sets up the thread-local hash tables used by the menu module.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Hash tables winMenuTable and commandTable are initialized.
 *
 *----------------------------------------------------------------------
 */

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

    Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);
@


1.1.4.11
log
@* doc/MeasureChar.3:
* doc/TextLayout.3:
* generic/tk.decls:
* generic/tkCanvText.c:
* generic/tkEntry.c:
* generic/tkFont.c:
* generic/tkListbox.c:
* generic/tkMessage.c:
* mac/tkMacFont.c:
* unix/tkUnixButton.c:
* unix/tkUnixFont.c:
* unix/tkUnixMenu.c:
* win/tkWinFont.c:
* win/tkWinMenu.c: Standardized text layout and font interfaces
so they are consistent with respect to byte versus character
oriented indices.  The layout functions all manipulate character
oriented values while the lower level measurement functions all
operate on byte oriented values.  This distinction was not clear
and so the functions were being used improperly in a number of
places.  [Bug: 1053, 747, 749, 1646]

* generic/tk.decls: Eliminated uses of C++ STL types string and
list from declarations.

* generic/tkFont.c: Changes to named fonts were not being
propagated in some cases. [Bug: 1144]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
a1735 2
	char *start = Tcl_UtfAtIndex(label, mePtr->underline);
	char *end = Tcl_UtfNext(start);
d1740 1
a1740 1
		start - label, end - label);
@


