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;
|