EXPORT(sqInt) primitiveGetItemCmd(void) {
	CharParameter  aCharacter;
	MenuHandle menuHandle;
	sqInt menuHandleOop;
	sqInt anInteger;
	sqInt _return_value;

	menuHandleOop = interpreterProxy->stackValue(1);
	anInteger = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	menuHandle = ((MenuHandle) (interpreterProxy->positive64BitValueOf(menuHandleOop)));
	if (!(ioCheckMenuHandle(menuHandle))) {
		_return_value = interpreterProxy->success(0);
		if (interpreterProxy->failed()) {
			return null;
		}
		interpreterProxy->popthenPush(3, _return_value);
		return null;
	}
	aCharacter = 0;
	GetItemCmd(menuHandle,anInteger,&aCharacter);
	_return_value = interpreterProxy->integerObjectOf(aCharacter);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->popthenPush(3, _return_value);
	return null;
}
예제 #2
0
static SInt32 HandleMenuSelect(SInt32 menuAndItem, SubSysMenuHandle subSysMenus)
	// This routine is called from the tail patch on MenuSelect
	// to handle an actual menu command being returned.
	// menuAndItem was the result from the original MenuSelect, and
	// the result of this routine will be returned from our MenuSelect
	// patch.
	//
	// The basic idea is that, if the menu command was on
	// a system menu belong to us, we call the appropriate client
	// callback routine and return 0 so that the client sees
	// a null selection.  If the menu command doesn't belong to us,
	// we just return the value passed in.
{
	SInt32 result;
	SInt16 hitMenuID;
	UInt16 hitItem;
	ItemCount foundIndex;
	MenuRef foundMenuRef;
	
	// The system implementation of MenuSelect will return 0 if the hit item
	// is in a system menu.  Fortunately, the real hit item is still around
	// in the low memory global MenuDisable.  So we use if menuAndItem is zero.
	// 
	// One weird edge case is cancelling sticky menus.  If the user brings
	// down a sticky menu and never chooses anything, the sticky menu
	// will eventually time out.  But LMGetMenuDisable is still set to
	// the menu and item of the item over which the mouse was last moved.
	// So, we conditionalise our access to LMGetMenuDisable with a
	// call to LMGetTheMenu.  If LMGetTheMenu is 0, the operation was
	// cancelled and we should bail out without choosing the item
	// in LMGetMenuDisable.
	//
	// Also note that we assign result before doing this, so we only use
	// MenuDisable if it relates to a system menu and never return it from
	// this routine, and hence from our patch on MenuSelect.
	
	result = menuAndItem;	
	if (menuAndItem == 0) {
		if ( LMGetTheMenu() != 0 ) {
			menuAndItem = LMGetMenuDisable();
		}
	}
	
	hitMenuID = menuAndItem >> 16;
	hitItem   = menuAndItem & 0x0FFFF;
	
	// Search our list of system menus looking for a matching menu ID.
	// Start by looking for a root menu and, if that fails, look for
	// one of the sub-menus we attached to the root menus.
	//
	// If we find a matching menu, call the corresponding client with a
	// kSystemMenuActOnChosen message, and also set menuAndItem to 0 so
	// that the application never sees the menu choice.
	
	foundMenuRef = NULL;
	
	foundIndex = FindRootMenuByID(hitMenuID);
	if (foundIndex != kRootMenuNotFound) {
		foundMenuRef = (*gRootSysMenus)[foundIndex].theMenu;
	} else {
		ItemCount entryCount;
		ItemCount entryIndex;
		
		entryCount = CountSubSysMenus(subSysMenus);
		for (entryIndex = 0; entryIndex < entryCount; entryIndex++) {
			if (hitMenuID == (**(*subSysMenus)[entryIndex].childMenu).menuID) {
				foundIndex = (*subSysMenus)[entryIndex].rootMenuIndex;
				foundMenuRef = (*subSysMenus)[entryIndex].childMenu;
				assert(foundIndex < CountRootSysMenus());
				break;
			}
		}
	}
	if (foundIndex != kRootMenuNotFound) {
		Boolean enabled;
		CharParameter cmdOfHitItem;

		assert(ValidateSystemMenuRef(foundMenuRef));
		
		// Because we're using MenuDisable to get the actual item hit,
		// we'll often get false positives, hits on the menu title or
		// when the menu item is disabled.  Make sure we don't call the
		// client in these cases.

		// Item 0 is the title and is never enabled.  Items from 1 to 31
		// are controlled by the enableFlags field of the menu.  Items
		// above 31 are always assumed to be enabled.
		//
		// Note that I don't use IsMenuItemEnabled (introduced in Mac OS 8.5)
		// to access this information because it's a CFM-only routine.  It's
		// only relevant for items beyond 31, which is a corner case IMHO.

		// Also, items that are the root of sub-menus (ie their cmd is
		// hMenuCmd) can not be chosen.
		
		if (hitItem == 0) {
			enabled = false;
		} else if (hitItem <= 31) {
			enabled = (((**foundMenuRef).enableFlags & (1L << hitItem)) != 0);
		} else {
			enabled = true;
		}
		if (enabled) {
			GetItemCmd(foundMenuRef, hitItem, &cmdOfHitItem);
			enabled = (cmdOfHitItem != hMenuCmd);
		}
		if (enabled) {
			CallSingleClient(foundIndex, kSystemMenuActOnChosen, foundMenuRef, (void *) hitItem);
		}
		result = 0;
	}
	
	return result;
}