/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information.       */
/* Contact email: mac@aarongiles.com                     */
/*********************************************************/

#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif

//#include <Menus.h>
//#include <Types.h>

//  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//  xxx
//  xxx     Developer's Programming Interface for Mercutio Menu Definition Function
//  xxx            ©1992 Ramon M. Felciano, All Rights Reserved
//  xxx
//  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//
//  Ported to THINK C, 7 Mar 1993 by Aaron Giles
//  Updated constants for Mercutio 1.2, 19 May 1993 by Aaron Giles
//

static pascal Boolean IsCustomMenu(MenuHandle menu);

//	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//	x
//	x	PowerMenuKey is a replacement for the standard toolbox call MenuKey for use with the
//	x	Mercutio. Given the keypress message and modifiers parameters from a standard event, it
//	x	checks to see if the keypress is a key-equivalent for a particular menuitem. If you are currently
//	x	using custom menus (i.e. menus using Mercutio), pass the handle to one of these menus in
//	x	hMenu. If you are not using custom menus, pass in NIL or another menu, and PowerMenuKey will use the
//	x	standard MenuKey function to interpret the keypress.
//	x
//	x	As with MenuKey, PowerMenuKey returns the menu ID in high word of the result, and the menu
//	x	item in the low word.
//	x
//	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

#define customDefProcSig 'CUST'
#define areYouCustomMsg '**'
#define mMenuKeyMsg 'SK'

// MENU resource structures

typedef struct {
	char iconID;
	char keyEq;
	char mark;
	Style textStyle;
} stdItemData, *StdItemDataPtr;

// Menubar structures

typedef struct {
	short offsetToLastMenu;
	short HorizRtEdgeLastmenu;
	short dummy;
	struct {
		MenuHandle theMenu;
		short HorizRtEdge;
	} menuIDList[100];
} MBarRec, *MBarRecPtr;

// MenuKey result structure

typedef struct {
	union {
		long L;
		short menuID, itemNum;
	} match;
} menuMatch;


pascal Boolean IsCustomMenu(MenuHandle menu)
{
//	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//	x
//	x	IsCustomMenu returns true if hMenu is controlled by a custom MDEF. This relies on my
//	x	convention of returning the customDefProcSig constant in the rect parameter: this obtuse
//	x	convention should be unique enough that only my custom MDEFs behave this way.
//	x
//	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	Point zeroPoint = { 0, 0 };
	char state;
	Handle proc;
	Rect dummy;
	short dummyInt;
	MenuDefUPP mdef;

	proc = (*menu)->menuProc;
	state = HGetState(proc);
	HLock(proc);
	dummy.top = dummy.left = 0;
	mdef = (MenuDefUPP)NewRoutineDescriptor((ProcPtr)*proc, uppMenuDefProcInfo, kM68kISA);
	CallMenuDefProc(mdef, areYouCustomMsg, menu, &dummy, zeroPoint, &dummyInt);
	DisposeRoutineDescriptor(mdef);
	HSetState(proc, state);
	return *(long *)&dummy == customDefProcSig;
}

pascal long PowerMenuKey(long theMessage, short theModifiers, MenuHandle hMenu)
{
	Point thePoint = *(Point *)&theMessage;
	char state;
	Handle proc;
	Rect dummyRect;
	MenuDefUPP mdef;

	if (!hMenu || !IsCustomMenu(hMenu)) return MenuKey(theMessage & charCodeMask);
	else {
		proc = (*hMenu)->menuProc;
		state = HGetState(proc);
		HLock(proc);
		dummyRect.top = dummyRect.left = 0;
		mdef = (MenuDefUPP)NewRoutineDescriptor((ProcPtr)*proc, uppMenuDefProcInfo, kM68kISA);
		CallMenuDefProc(mdef, mMenuKeyMsg, hMenu, &dummyRect, thePoint, &theModifiers);
		DisposeRoutineDescriptor(mdef);
		HSetState(proc, state);
		return *(long *)&dummyRect;
	}
}
