Digital Alchemy Mercutio MDEF


 

DOCUMENTATION
* Overview
* FAQ
* Inside Mercutio(pdf)
* Internationalization
* Licensing Description
* Software License(pdf)

 
SOFTWARE
* Current version: 1.5.1
* Download Now!
* Release Notes
* Known Problems
* Version History

 
REGISTRATION
* Register!
* Registered Users

 
SUPPORT
* Technical Support
* Mailing Lists
* Report a Bug

 
SITE MAP

GetMenuScreen versions

This page documents the code changes in the GetMenuScreen routine that is used by the Mercutio MDEF to display popup menus. There have been three versions of GetMenuScreen:

  • Buggy version from Mercutio 1.3.4 and earlier that left the GDHandles unlocked.

  • Fixed version in 1.3.5b1 that saved and restored the handle state.

  • Optimized version in 1.5b2 that leaves the GDHandles alone (see below as to why this is safe in this case)


Mercutio 1.3.4 and earlier

This is the GetMenuScreen code used by Mercutio 1.3.4 and earlier.


FUNCTION GetMenuScreen (menuRect: rect): rect;
	VAR
		aGDevice: GDHandle;	{Handle to each screen's GDevice}
		maxGDevice: GDHandle;	{Handle to GDevice containing most of the menu}
		InterArea: longint;	{Menu rect/screen rect intersection area}
		MaxInterArea: longint;	{Maxiumum menu/screen intersection area}
		commonRect: rect;	{Intersection between the menu rect and the screen rect}
		ShareCommon: boolean;		{True if rects share common points}
		Environs: SysEnvRec;
		oe: osErr;
		returnRect: rect;	{result to pass back}
BEGIN
	oe := SysEnvirons(1, Environs);
	setRect(returnRect, 0, 0, 0, 0);
	IF (Environs.hasColorQD) THEN BEGIN
		MaxInterArea := 0;
		maxGDevice := NIL;
		aGDevice := GetDeviceList;
		WHILE (aGDevice <> NIL) DO BEGIN
		{Calculate the area of intersection}
			HLock(handle(aGDevice));
			ShareCommon := SectRect(menuRect, aGDevice^^.gdRect, commonRect);
			IF ShareCommon THEN BEGIN
				WITH commonRect DO
					InterArea := longint(longint(bottom - top) * (right - left));
				IF InterArea > MaxInterArea THEN {found a new maximum area}
					BEGIN
						returnRect := aGDevice^^.gdRect;
						maxGDevice := aGDevice;
						maxInterArea := InterArea;
					END;
				END;
			HUnLock(handle(aGDevice));
			aGDevice := GetNextDevice(aGDevice);
			END;
		IF maxGDevice = GetMainDevice THEN
			returnRect.top := returnRect.top + LMGetMBarHeight;
		END
	ELSE BEGIN
		returnRect := GetScreenRect;
		returnRect.top := returnRect.top + LMGetMBarHeight;
	END;
	GetMenuScreen := returnRect;
END;

Mercutio 1.3.5b1

This is the GetMenuScreen code used by Mercutio 1.3.5b1.


FUNCTION GetMenuScreen (menuRect: rect): rect;
	VAR
		aGDevice: GDHandle;	{Handle to each screen's GDevice}
		maxGDevice: GDHandle;	{Handle to GDevice containing most of the menu}
		InterArea: longint;	{Menu rect/screen rect intersection area}
		MaxInterArea: longint;	{Maxiumum menu/screen intersection area}
		commonRect: rect;	{Intersection between the menu rect and the screen rect}
		ShareCommon: boolean;		{True if rects share common points}
		Environs: SysEnvRec;
		oe: osErr;
		returnRect: rect;	{result to pass back}
		savedState: signedByte;
BEGIN
	oe := SysEnvirons(1, Environs);
	setRect(returnRect, 0, 0, 0, 0);
	IF (Environs.hasColorQD) THEN BEGIN
		MaxInterArea := 0;
		maxGDevice := NIL;
		aGDevice := GetDeviceList;
		WHILE (aGDevice <> NIL) DO BEGIN
				{Calculate the area of intersection}
				savedState := HGetState(handle(aGDevice));
				HLock(handle(aGDevice));
				ShareCommon := SectRect(menuRect, aGDevice^^.gdRect, commonRect);
				IF ShareCommon THEN BEGIN
						WITH commonRect DO
							InterArea := longint(longint(bottom - top) * (right - left));
						IF InterArea > MaxInterArea THEN {found a new maximum area}
							BEGIN
								returnRect := aGDevice^^.gdRect;
								maxGDevice := aGDevice;
								maxInterArea := InterArea;
							END;
					END;
				HSetState(handle(aGDevice), savedState);
				aGDevice := GetNextDevice(aGDevice);
			END;
		IF maxGDevice = GetMainDevice THEN
			returnRect.top := returnRect.top + LMGetMBarHeight;
		END
	ELSE BEGIN
		returnRect := GetScreenRect;
		returnRect.top := returnRect.top + LMGetMBarHeight;
	END;
	GetMenuScreen := returnRect;
END;

Mercutio 1.5b2

This is the GetMenuScreen code used by Mercutio 1.5b2 (and later). This is safe because this code always re-dereferences the handles, and never passes a pointer to the handle data into any routine that may move memory. If there we did call such a routine, we should restore the state saving code and lock the handle down.


FUNCTION GetMenuScreen (menuRect: rect): rect;
	VAR
		aGDevice: GDHandle;	{Handle to each screen's GDevice}
		maxGDevice: GDHandle;	{Handle to GDevice containing most of the menu}
		InterArea: longint;	{Menu rect/screen rect intersection area}
		MaxInterArea: longint;	{Maxiumum menu/screen intersection area}
		commonRect: rect;	{Intersection between the menu rect and the screen rect}
		ShareCommon: boolean;		{True if rects share common points}
		Environs: SysEnvRec;
		oe: osErr;
		returnRect: rect;	{result to pass back}
BEGIN
	oe := SysEnvirons(1, Environs);
	setRect(returnRect, 0, 0, 0, 0);
	IF (Environs.hasColorQD) THEN BEGIN
		MaxInterArea := 0;
		maxGDevice := NIL;
		aGDevice := GetDeviceList;
		WHILE (aGDevice <> NIL) DO BEGIN
				{Calculate the area of intersection}
				ShareCommon := SectRect(menuRect, aGDevice^^.gdRect, commonRect);
				IF ShareCommon THEN BEGIN
					WITH commonRect DO
						InterArea := longint(longint(bottom - top) * (right - left));
					IF InterArea > MaxInterArea THEN {found a new maximum area}
						BEGIN
							returnRect := aGDevice^^.gdRect;
							maxGDevice := aGDevice;
							maxInterArea := InterArea;
						END;
					END;
				aGDevice := GetNextDevice(aGDevice);
			END;
		IF maxGDevice = GetMainDevice THEN
			returnRect.top := returnRect.top + LMGetMBarHeight;
	END
	ELSE BEGIN
		returnRect := GetScreenRect;
		returnRect.top := returnRect.top + LMGetMBarHeight;
	END;
	GetMenuScreen := returnRect;
END;


Last modified by RMF at 18:59 PM on 02/26/1998. © Copyright 1996-2000, Digital Alchemy, All Rights Reserved.
This site was built on a Macintosh using BBEdit and CometPage.