mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-15 12:30:53 +00:00
962 lines
28 KiB
OpenEdge ABL
962 lines
28 KiB
OpenEdge ABL
|
{
|
|||
|
File: BuiltInVideoExtension.p
|
|||
|
|
|||
|
Contains: Built-in Video Monitors (cdev) Extension for IIci and IIsi.
|
|||
|
|
|||
|
Written by: Jim Straus/Mike Puckett
|
|||
|
|
|||
|
Copyright: <EFBFBD> 1989-1990 by Apple Computer, Inc., all rights reserved.
|
|||
|
|
|||
|
This file is used in these builds: Mac32 BigBang Sys606
|
|||
|
|
|||
|
Change History (most recent first):
|
|||
|
|
|||
|
<4> 1/23/91 stb BBM: change spParamData in SpBlock type from Ptr to a LONGINT;
|
|||
|
<3> 1/7/91 JDR (dba) Devices.p now has the Monitors extensions, so I've removed
|
|||
|
them from this file.
|
|||
|
<2> 12/14/90 dba <JDR> get rid of redundant RectPtr declaration, now in Types.p
|
|||
|
<1> 10/6/90 jmp Name change from VideoExtensionIIci.p to
|
|||
|
BuiltInVideoExtension.p. That<EFBFBD>s all!
|
|||
|
<11> 10/6/90 jmp Cleaned up changes I made on 10/2/90 -- no functionality
|
|||
|
changes; changed name of file from VideoExtensionIIci.p to
|
|||
|
BuiltInVideoExtension.p to reflect that it is used for more than
|
|||
|
just the IIci.
|
|||
|
<10> 10/4/90 JAL changed spStackPtr to spParamData to match change in Slots.p
|
|||
|
interface file.
|
|||
|
<9> 10/2/90 jmp NEEDED FOR 7.0: In version 4.4b2 of Monitors, I effectively
|
|||
|
removed the CodeValueOK code so that developers could have the
|
|||
|
entire LONGINT range of values. However, several third-party
|
|||
|
extensions were relying on Monitors reserving values 1-255 as
|
|||
|
error return values. So, in Monitors 4.4b3, I put the
|
|||
|
CodeValueOK code back in. This change, then, was made so that
|
|||
|
superUser vs. normalUser modes can be remembered across calls in
|
|||
|
the built-in extension (i.e., I added a call to NewHandle at
|
|||
|
startupMsg time, and a call to DisposHandle at okMsg/cancelMsg
|
|||
|
time).
|
|||
|
<8> 9/29/90 jmp NEEDED FOR 7.0: For version 4.4b2 of Monitors and later, this
|
|||
|
extension now always comes up; changing memory allocation for
|
|||
|
RBV is no longer considered an <EFBFBD>expert<EFBFBD> feature -- especially
|
|||
|
with the memory constraints imposed by System 7.0. This
|
|||
|
extension works on 6.0.x Systems as well.
|
|||
|
<7> 8/23/90 jmp Added MPW3.0 conditional for C2PStr. I<EFBFBD>m not sure which MPW
|
|||
|
objects SixPack or 7.0 are built with; I use MPW 3.2 myself.
|
|||
|
<6> 8/18/90 jmp NEEDED FOR SIXPACK: Cleaned up changes that were made on July
|
|||
|
3rd -- Get1Resource vs GetResource problem. Also, replaced the
|
|||
|
call of WeirdStatus to PBStatus, and brought GetTypesRsrc
|
|||
|
in-line (i.e., there is now no dependecy of this file on
|
|||
|
VideoExtensionIIci.a). I also fixed a problem in GetCardName
|
|||
|
that only occured when 32-bit addressing is activated (same
|
|||
|
change that was made to the NuMonitors.p source); this problem
|
|||
|
caused the built-in video radio buttons dialog to not show up.
|
|||
|
Finally, I fixed the window updating problems that were showing
|
|||
|
up under System 7.0.
|
|||
|
<5> 7/3/90 jmp I added to the comments for the previous fix (number <4>). No
|
|||
|
code changes were made. See the <5> comment block in the EDialog
|
|||
|
routine.
|
|||
|
<4> 7/3/90 DDG NEEDED FOR SIXPACK: Fixed resource reference problem.
|
|||
|
<3> 6/18/90 JBS NEEDED FOR SIXPACK-Merged ci/erickson extension with elsie
|
|||
|
resources
|
|||
|
<2> 1/3/90 CCH Change name of Gestalt interface file.
|
|||
|
<1.0> 8/3/89 JBS FOR 6.0.4 BUILD - Mac IIci Monitors extension code added to
|
|||
|
build.
|
|||
|
|
|||
|
To Do:
|
|||
|
}
|
|||
|
UNIT MNTR;
|
|||
|
|
|||
|
INTERFACE
|
|||
|
|
|||
|
USES
|
|||
|
GestaltEqu,
|
|||
|
Errors,
|
|||
|
Devices,
|
|||
|
Slots,
|
|||
|
Video,
|
|||
|
Start,
|
|||
|
QuickDraw,
|
|||
|
OSUtils,
|
|||
|
Desk,
|
|||
|
SysEqu,
|
|||
|
Menus,
|
|||
|
Windows,
|
|||
|
Dialogs,
|
|||
|
Lists,
|
|||
|
Fonts,
|
|||
|
Memory,
|
|||
|
Packages,
|
|||
|
PaletteMgr,
|
|||
|
Resources,
|
|||
|
ROMDefs,
|
|||
|
ToolUtils,
|
|||
|
Strings,
|
|||
|
PasLibIntf;
|
|||
|
|
|||
|
|
|||
|
{$D-} {No debug checking}
|
|||
|
{$R-} {Zap range checking again, in case USEd units set it}
|
|||
|
|
|||
|
CONST
|
|||
|
SlotCount = 15; {Maximum number of slots we deal with}
|
|||
|
|
|||
|
MonitorsMem = $C2E; {Monitors low memory global}
|
|||
|
|
|||
|
divLineItem = 1; {the items in our DITL}
|
|||
|
bwOnlyItem = 2; {the four radio buttons. Must be together and in order}
|
|||
|
fourItem = 3;
|
|||
|
sixteenItem = 4;
|
|||
|
twoFiftySixItem = 5;
|
|||
|
rect1Item = 6; {the various rectangles for max depths -- there<EFBFBD>s got to be}
|
|||
|
rect2Item = 7; { a better way!}
|
|||
|
rect3Item = 8;
|
|||
|
titleItem = 9;
|
|||
|
memoryItem = 10;
|
|||
|
|
|||
|
buttonDistance = 20; {how far the buttons are apart. Used to shrink the RECT resource}
|
|||
|
memRoundFactor = $8000; {size to round memory amounts by}
|
|||
|
|
|||
|
spFlagAll = 1; {flags that can be set for spParamData}
|
|||
|
spFlagOneSlot = 2;
|
|||
|
spFlagNext = 4;
|
|||
|
|
|||
|
cscSetDefault = 9; {csCode to the driver to get and set the video default}
|
|||
|
|
|||
|
rExtensionId = -4096; {use localID and baseID as calculated in code instead}
|
|||
|
rLocalId = -4080;
|
|||
|
|
|||
|
Mac2ID = $86;
|
|||
|
PortraitID = $81;
|
|||
|
IIGSID = $82;
|
|||
|
SEID = $87;
|
|||
|
|
|||
|
IDMask = $E7; {????}
|
|||
|
|
|||
|
numShow = 2; {localID to localID+numShow are the cards on which we should be}
|
|||
|
{visible; i.e. we won't show up ever on an Elsie or Eclipse.}
|
|||
|
|
|||
|
errorValue = 1; {returned in monitorValue when the extension can<EFBFBD>t be started up}
|
|||
|
|
|||
|
TYPE
|
|||
|
LongPtr = ^LONGINT;
|
|||
|
LongHdl = ^LongPtr;
|
|||
|
|
|||
|
QDGlobals = RECORD
|
|||
|
randSeed: LONGINT;
|
|||
|
screenBits: BitMap;
|
|||
|
arrow: Cursor;
|
|||
|
dkGray: Pattern;
|
|||
|
ltGray: Pattern;
|
|||
|
gray: Pattern;
|
|||
|
black: Pattern;
|
|||
|
white: Pattern;
|
|||
|
thePort: GrafPtr;
|
|||
|
END;
|
|||
|
QDGlobalsPtr = ^QDGlobals;
|
|||
|
|
|||
|
{
|
|||
|
August 15, 1990 jmp mod -- added this definition for ease of use with PBStatus,
|
|||
|
which is replacing the calls to WeirdStatus. (I.e., There<EFBFBD>s nothing weird
|
|||
|
about _Status except in the high-level glue, and who needs it anyway.)
|
|||
|
}
|
|||
|
VideoParamBlock = RECORD
|
|||
|
qLink: QElemPtr;
|
|||
|
qType: INTEGER;
|
|||
|
ioTrap: INTEGER;
|
|||
|
ioCmdAddr: Ptr;
|
|||
|
ioCompletion: ProcPtr;
|
|||
|
ioResult: OSErr;
|
|||
|
ioNamePtr: StringPtr;
|
|||
|
ioVRefNum: INTEGER;
|
|||
|
ioRefNum: INTEGER;
|
|||
|
csCode: INTEGER;
|
|||
|
csParam: Ptr;
|
|||
|
END;
|
|||
|
VideoParamBlockPtr = ^VideoParamBlock;
|
|||
|
|
|||
|
ScrnRecord = RECORD {'scrn' info for each screen}
|
|||
|
srDrvrHW: INTEGER; {spDrvrHW from slot decl mgr's device type}
|
|||
|
srSlot: INTEGER; {Slot number for the screen's video card}
|
|||
|
srDCtlDevBase: LONGINT; {Base address of card's memory}
|
|||
|
srMode: INTEGER; {sRsrcID for desired mode}
|
|||
|
srFlagMask: INTEGER; {$77FE}
|
|||
|
srFlags: INTEGER; {active, main screen, B/W or color}
|
|||
|
srColorTable: INTEGER; {Resource ID of desired 'clut'}
|
|||
|
srGammaTable: INTEGER; {Resource ID of desired 'gama'}
|
|||
|
srRect: Rect; {Device's rectangle, global coordinates}
|
|||
|
srCtlCount: INTEGER; {Number of control calls}
|
|||
|
END;
|
|||
|
ScrnRecordPtr = ^ScrnRecord;
|
|||
|
ScrnRecordHandle = ^ScrnRecordPtr;
|
|||
|
|
|||
|
ScrnRsrc = RECORD {Complete 'scrn' resource}
|
|||
|
count: INTEGER; {Number of screens configured here}
|
|||
|
scrnRecs: ARRAY[1..SlotCount] OF ScrnRecord; {Config for @ one}
|
|||
|
END;
|
|||
|
ScrnRsrcPtr = ^ScrnRsrc;
|
|||
|
ScrnRsrcHandle = ^ScrnRsrcPtr;
|
|||
|
|
|||
|
RectHandle = ^RectPtr;
|
|||
|
|
|||
|
VDDefaultRecord = RECORD
|
|||
|
csID: SignedByte;
|
|||
|
pad: SignedByte;
|
|||
|
END;
|
|||
|
GDDefaultRecPtr = ^VDDefaultRecord;
|
|||
|
|
|||
|
SPRAMRecord = RECORD
|
|||
|
boardID: INTEGER; {Apple-defined card identification}
|
|||
|
vendorUse1: SignedByte; {Byte with the default mode for screen devices}
|
|||
|
vendorUse2: SignedByte; {Unused by us}
|
|||
|
vendorUse3: SignedByte; {Unused by us}
|
|||
|
vendorUse4: SignedByte; {Unused by us}
|
|||
|
vendorUse5: SignedByte; {Unused by us}
|
|||
|
vendorUse6: SignedByte; {Unused by us}
|
|||
|
END;
|
|||
|
|
|||
|
FUNCTION Entry(message, {the action to handle}
|
|||
|
Item, {the DITL item or 0}
|
|||
|
numItems: INTEGER; {the number of the systems last item}
|
|||
|
monitorValue: LONGINT; {the value returned last time. defaults to zero}
|
|||
|
mDialog: DialogPtr; {the dialog pointer}
|
|||
|
theEvent: EventRecord; {the event that caused the message to happen}
|
|||
|
ScreenNum: INTEGER; {the number of the screen to affect}
|
|||
|
VAR Screens: ScrnRsrcHandle; {the screen resource to change if desired}
|
|||
|
VAR ScrnChanged: BOOLEAN {TRUE if we should clean up Screens}
|
|||
|
): LONGINT; {value to pass back in or error if negative}
|
|||
|
|
|||
|
IMPLEMENTATION
|
|||
|
|
|||
|
FUNCTION EDialog(message, {the action to handle}
|
|||
|
Item, {the DITL item or 0}
|
|||
|
numItems: INTEGER; {the number of the systems last item}
|
|||
|
monitorValue: LONGINT; {the value returned last time. defaults to zero}
|
|||
|
mDialog: DialogPtr; {the dialog pointer}
|
|||
|
theEvent: EventRecord; {the event that caused the message to happen}
|
|||
|
ScreenNum: INTEGER; {the number of the screen to affect}
|
|||
|
VAR Screens: ScrnRsrcHandle; {the screen resource to change if desired}
|
|||
|
VAR ScrnChanged: BOOLEAN {TRUE if we should clean up Screens}
|
|||
|
): LONGINT; FORWARD; {value to pass back in or error if negative}
|
|||
|
|
|||
|
FUNCTION Entry(message, {the action to handle}
|
|||
|
Item, {the DITL item or 0}
|
|||
|
numItems: INTEGER; {the number of the systems last item}
|
|||
|
monitorValue: LONGINT; {the value returned last time. defaults to zero}
|
|||
|
mDialog: DialogPtr; {the dialog pointer}
|
|||
|
theEvent: EventRecord; {the event that caused the message to happen}
|
|||
|
ScreenNum: INTEGER; {the number of the screen to affect}
|
|||
|
VAR Screens: ScrnRsrcHandle; {the screen resource to change if desired}
|
|||
|
VAR ScrnChanged: BOOLEAN {TRUE if we should clean up Screens}
|
|||
|
): LONGINT; {value to pass back in or error if negative}
|
|||
|
BEGIN
|
|||
|
Entry := EDialog(message, Item, numItems, monitorValue, mDialog, theEvent,
|
|||
|
ScreenNum, Screens, ScrnChanged);
|
|||
|
END;
|
|||
|
|
|||
|
{--------------------------------------------------------------------------------
|
|||
|
GetCardName - returns the name of the driver for a particular slot.
|
|||
|
}
|
|||
|
FUNCTION GetCardName(slotNum: INTEGER): STR255;
|
|||
|
CONST
|
|||
|
board = 0;
|
|||
|
drvrHWMask = 1;
|
|||
|
VAR
|
|||
|
sPB: SpBlock;
|
|||
|
name: Str255;
|
|||
|
BEGIN
|
|||
|
WITH sPB DO
|
|||
|
BEGIN
|
|||
|
spSlot := slotNum; { Start the sResource search from the top of the list }
|
|||
|
spID := 0; { (i.e, from 0+1 since 0 is invalid). }
|
|||
|
spExtDev := 0;
|
|||
|
|
|||
|
spTBMask := 0; { Look for board sResources [catBoard,typeBoard,0,0] }
|
|||
|
spCategory := catBoard; { only, set set mask to 0. }
|
|||
|
spCType := typeBoard;
|
|||
|
spDrvrSW := 0;
|
|||
|
spDrvrHW := 0;
|
|||
|
|
|||
|
spHwDev := 0;
|
|||
|
END;
|
|||
|
|
|||
|
name := 'XXX'; { Assume we will fail. }
|
|||
|
|
|||
|
IF SNextTypeSRsrc(@sPB) = noErr THEN
|
|||
|
BEGIN
|
|||
|
sPB.spID := sRsrcName;
|
|||
|
|
|||
|
IF SGetCString(@sPB) = noErr THEN
|
|||
|
name := C2PStr(Ptr(sPB.spResult))^
|
|||
|
END;
|
|||
|
|
|||
|
GetCardName := name;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
GetQDGlobals - return pointer to quickdraw globals
|
|||
|
}
|
|||
|
FUNCTION GetQDGlobals: QDGlobalsPtr;
|
|||
|
BEGIN
|
|||
|
{
|
|||
|
Get pointer to thePort, which is at offset zero from A5, and adjust
|
|||
|
it to point at the base of the quickdraw globals. We have to do
|
|||
|
this to reference quickdraw globals, because as a desk accessory
|
|||
|
we can't have any globals of our own.
|
|||
|
}
|
|||
|
|
|||
|
GetQDGlobals := QDGlobalsPtr(
|
|||
|
LongHdl(CurrentA5)^^ + Sizeof(GrafPtr) - Sizeof(QDGlobals));
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
DrawDivLine draws the line separating the extension from the rest of the options
|
|||
|
dialog. DrawLine, below, just draws a solid line.
|
|||
|
}
|
|||
|
PROCEDURE DrawDivLine(theWindow: WindowPtr; itemNo: INTEGER);
|
|||
|
VAR
|
|||
|
itemType: INTEGER;
|
|||
|
itemHandle: Handle;
|
|||
|
itemBox: Rect;
|
|||
|
savedPenState: PenState;
|
|||
|
BEGIN
|
|||
|
GetDItem(DialogPtr(theWindow), itemNo, itemType, itemHandle, itemBox);
|
|||
|
|
|||
|
GetPenState(savedPenState);
|
|||
|
PenNormal;
|
|||
|
FrameRect(itemBox);
|
|||
|
|
|||
|
PenMode(notPatBic);
|
|||
|
PenPat(GetQDGlobals^.gray);
|
|||
|
PaintRect(itemBox);
|
|||
|
|
|||
|
SetPenState(savedPenState);
|
|||
|
END;
|
|||
|
|
|||
|
PROCEDURE DrawLine(theWindow: WindowPTr; itemNo: INTEGER);
|
|||
|
VAR
|
|||
|
itemType: INTEGER;
|
|||
|
itemHandle: Handle;
|
|||
|
itemBox: Rect;
|
|||
|
BEGIN
|
|||
|
GetDItem(DialogPtr(theWindow), itemNo, itemType, itemHandle, itemBox);
|
|||
|
|
|||
|
PenNormal;
|
|||
|
FrameRect(itemBox);
|
|||
|
END;
|
|||
|
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
ID2Item converts a family member id into the control item in the dialog.
|
|||
|
There<EFBFBD>s got to be a better way to do this!
|
|||
|
}
|
|||
|
FUNCTION ID2Item(id: SignedByte): INTEGER;
|
|||
|
VAR
|
|||
|
temp: INTEGER;
|
|||
|
BEGIN
|
|||
|
ID2Item := BWOnlyItem; {a default value}
|
|||
|
temp := BAnd(id, $FF); {turn the signed byte into an integer}
|
|||
|
CASE temp OF
|
|||
|
$8E, $89, $8A, $8F: {all the 1 bit IDs for the various monitors supported}
|
|||
|
ID2Item := BWOnlyItem;
|
|||
|
$9E, $91, $9A, $9F: {all the 2 bit IDs for the various monitors supported}
|
|||
|
ID2Item := FourItem;
|
|||
|
$96, $81, $92, $97: {all the 4 bit IDs for the various monitors supported}
|
|||
|
ID2Item := SixteenItem;
|
|||
|
$86, $82, $87: {all the 8 bit IDs for the various monitors supported}
|
|||
|
ID2Item := TwoFiftySixItem;
|
|||
|
END;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
Item2ID converts a control item into the family member id.
|
|||
|
There<EFBFBD>s got to be a better way to do this.
|
|||
|
}
|
|||
|
FUNCTION Item2ID(Item: INTEGER; oldID: SignedByte): SignedByte;
|
|||
|
VAR
|
|||
|
base: INTEGER;
|
|||
|
BEGIN
|
|||
|
base := BAnd(oldID, IDMask); {mask to the base ID}
|
|||
|
IF base = $00 THEN
|
|||
|
base := $86; {if we have no base, assume High-Res Display}
|
|||
|
IF base = $81 THEN {handle Page Display specially. It can't have 8 bit mode}
|
|||
|
CASE Item OF
|
|||
|
BWOnlyItem:
|
|||
|
base := BOr(base, $08);
|
|||
|
FourItem:
|
|||
|
base := BOr(base, $10);
|
|||
|
SixteenItem:
|
|||
|
base := BOr(base, $00);
|
|||
|
TwoFiftySixItem:
|
|||
|
base := BOr(base, $00); {just in case}
|
|||
|
END
|
|||
|
ELSE
|
|||
|
CASE Item OF
|
|||
|
BWOnlyItem:
|
|||
|
base := BOr(base, $08);
|
|||
|
FourItem:
|
|||
|
base := BOr(base, $18);
|
|||
|
SixteenItem:
|
|||
|
base := BOr(base, $10);
|
|||
|
TwoFiftySixItem:
|
|||
|
base := BOr(base, $00);
|
|||
|
END;
|
|||
|
Item2ID := base;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
SetControl deselects all the radio buttons except for the item which is selected.
|
|||
|
}
|
|||
|
PROCEDURE SetControl(mDialog: DialogPtr; Item: INTEGER; numItems: INTEGER);
|
|||
|
VAR
|
|||
|
i: INTEGER;
|
|||
|
iType: INTEGER;
|
|||
|
iHandle: HANDLE;
|
|||
|
iBox: Rect;
|
|||
|
BEGIN
|
|||
|
Item := Item - numItems; {convert into our range of item numbers}
|
|||
|
FOR i := BWOnlyItem TO TwoFiftySixItem DO
|
|||
|
BEGIN
|
|||
|
GetDItem(mDialog, i + numItems, iType, iHandle, iBox);
|
|||
|
SetCtlValue(ControlHandle(iHandle), ord(i = Item)); {set to 1 if selected item, else 0}
|
|||
|
END;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
GetControl returns the item number of the radio button which is selected.
|
|||
|
}
|
|||
|
FUNCTION GetControl(mDialog: DialogPtr; numItems: INTEGER): INTEGER;
|
|||
|
VAR
|
|||
|
i: INTEGER;
|
|||
|
iType: INTEGER;
|
|||
|
iHandle: HANDLE;
|
|||
|
iBox: Rect;
|
|||
|
BEGIN
|
|||
|
GetControl := 0; {default case}
|
|||
|
FOR i := BWOnlyItem TO TwoFiftySixItem DO
|
|||
|
BEGIN
|
|||
|
GetDItem(mDialog, i + numItems, iType, iHandle, iBox);
|
|||
|
IF GetCtlValue(ControlHandle(iHandle)) <> 0 THEN
|
|||
|
GetControl := i;
|
|||
|
END;
|
|||
|
END;
|
|||
|
|
|||
|
FUNCTION GetDCEHand(gdHand: gdHandle): AuxDCEHandle;
|
|||
|
BEGIN
|
|||
|
GetDCEHand := AuxDCEHandle(GetDCtlEntry(gdHand^^.gdRefNum));
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
GetRefNum returns a slot number<EFBFBD>s driver refNum.
|
|||
|
}
|
|||
|
FUNCTION GetRefNum(Slot: INTEGER): INTEGER;
|
|||
|
VAR
|
|||
|
curGD: GDHandle;
|
|||
|
BEGIN
|
|||
|
GetRefNum := 0; {default case}
|
|||
|
curGD := GetDeviceList;
|
|||
|
WHILE (curGD <> NIL) DO
|
|||
|
BEGIN
|
|||
|
IF GetDCEHand(curGD)^^.dCtlSlot = Slot THEN
|
|||
|
BEGIN
|
|||
|
GetRefNum := curGD^^.gdRefNum;
|
|||
|
curGD := NIL; {to force us out of the loop}
|
|||
|
END
|
|||
|
ELSE
|
|||
|
curGD := GetNextDevice(curGD);
|
|||
|
END;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
GetVidDefault returns the family id for the currently selected family.
|
|||
|
}
|
|||
|
FUNCTION GetVidDefault(VAR Id: SignedByte; slot: INTEGER): OSErr;
|
|||
|
CONST
|
|||
|
cscGetDefaultMode = 9; {This should be removed when the Pascal Equates are updated.}
|
|||
|
VAR
|
|||
|
err: OSErr;
|
|||
|
defaultRec: VDDefaultRecord;
|
|||
|
vPB: VideoParamBlock;
|
|||
|
BEGIN
|
|||
|
{err := WeirdStatus(GetRefNum(slot), cscSetDefault, @defaultRec);}
|
|||
|
|
|||
|
vPB.ioRefNum := GetRefNum(slot);
|
|||
|
vPB.csCode := cscGetDefaultMode;
|
|||
|
vPB.csParam := Ptr(@defaultRec);
|
|||
|
|
|||
|
err := PBStatus(ParmBlkPtr(@vPB),false);
|
|||
|
|
|||
|
IF err = noErr THEN
|
|||
|
Id := defaultRec.csID
|
|||
|
ELSE
|
|||
|
Id := 0;
|
|||
|
|
|||
|
GetVidDefault := err;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
GetMemoryUsed determines the amount of memory used by video for a particular max
|
|||
|
depth. There<EFBFBD>s got to be a better way to do this!
|
|||
|
}
|
|||
|
FUNCTION GetMemoryUsed(item: INTEGER; slot: INTEGER): LONGINT;
|
|||
|
VAR
|
|||
|
id: SignedByte;
|
|||
|
size: LONGINT;
|
|||
|
factor: LONGINT;
|
|||
|
pageSize: LONGINT;
|
|||
|
BEGIN
|
|||
|
size := 0;
|
|||
|
GetMemoryUsed := 0;
|
|||
|
IF Gestalt(gestaltLogicalPageSize, pagesize) <> NoErr THEN
|
|||
|
pagesize := $00008000; {if no page size, assume 32k}
|
|||
|
IF GetVidDefault(id, slot) <> NoErr THEN
|
|||
|
Exit(GetMemoryUsed);
|
|||
|
CASE BAnd(id, IDMask) OF
|
|||
|
Mac2ID: {Mac II 12" monitor-640x480}
|
|||
|
CASE item OF
|
|||
|
BWOnlyItem:
|
|||
|
size := $00009600;
|
|||
|
FourItem:
|
|||
|
size := $00012C00;
|
|||
|
SixteenItem:
|
|||
|
size := $00025800;
|
|||
|
TwoFiftySixItem:
|
|||
|
size := $0004B000;
|
|||
|
END;
|
|||
|
PortraitID: {Portrait display-640x780}
|
|||
|
CASE item OF
|
|||
|
BWOnlyItem:
|
|||
|
size := $00010FE0;
|
|||
|
FourItem:
|
|||
|
size := $00021FC0;
|
|||
|
SixteenItem:
|
|||
|
size := $00043F80;
|
|||
|
TwoFiftySixItem:
|
|||
|
size := $00043F80;
|
|||
|
END;
|
|||
|
IIGSID: {IIGS 12" monitor-512x384}
|
|||
|
CASE item OF
|
|||
|
BWOnlyItem:
|
|||
|
size := $00006000;
|
|||
|
FourItem:
|
|||
|
size := $0000C000;
|
|||
|
SixteenItem:
|
|||
|
size := $00018000;
|
|||
|
TwoFiftySixItem:
|
|||
|
size := $00030000;
|
|||
|
END;
|
|||
|
SEID: {SE 9" monitor-512x342}
|
|||
|
CASE item OF
|
|||
|
BWOnlyItem:
|
|||
|
size := $00005580;
|
|||
|
FourItem:
|
|||
|
size := $0000A600;
|
|||
|
SixteenItem:
|
|||
|
size := $00015600;
|
|||
|
TwoFiftySixItem:
|
|||
|
size := $0002AC00;
|
|||
|
END;
|
|||
|
END;
|
|||
|
factor := size MOD pagesize;
|
|||
|
GetMemoryUsed := size + (pagesize - factor);
|
|||
|
END;
|
|||
|
|
|||
|
{sets the id for the selected family. Also sets the mode for restart}
|
|||
|
FUNCTION SetVidDefault(Id: SignedByte; depth: INTEGER; slot: INTEGER; VAR Screens: ScrnRsrcHandle; ScreenNum: INTEGER): OSErr;
|
|||
|
VAR
|
|||
|
err: OSErr;
|
|||
|
defaultRec: VDDefaultRecord;
|
|||
|
csParamPtr: Ptr;
|
|||
|
spBlk: spBlock;
|
|||
|
PRAMRec: SPRAMRecord;
|
|||
|
BEGIN
|
|||
|
defaultRec.csID := Id;
|
|||
|
csParamPtr := @defaultRec;
|
|||
|
err := Control(GetRefNum(slot), cscSetDefault, @csParamPtr);
|
|||
|
SetVidDefault := err;
|
|||
|
|
|||
|
spBlk.spSlot := slot;
|
|||
|
spBlk.spResult := LongInt(@PRAMRec);
|
|||
|
err := sReadPRAMRec(@spBlk);
|
|||
|
spBlk.spsPointer := @PRAMRec;
|
|||
|
PRAMRec.vendorUse1 := depth; {force to default mode}
|
|||
|
err := sPutPRAMRec(@spBlk);
|
|||
|
|
|||
|
Screens^^.scrnRecs[ScreenNum].srMode := depth; {force to default mode in scrn resource}
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
FindSlotStructfinds the video slot structure using the flags passed in
|
|||
|
(either all or only active).
|
|||
|
}
|
|||
|
FUNCTION FindSlotStruct(slot: INTEGER; VAR spBlk: spBlock; dataFlags: LongInt): OSErr;
|
|||
|
VAR
|
|||
|
err: OSErr;
|
|||
|
value: Ptr;
|
|||
|
BEGIN
|
|||
|
WITH spBlk DO {set up the fields for the slot manager call}
|
|||
|
BEGIN
|
|||
|
spParamData := dataFlags;
|
|||
|
spSlot := slot;
|
|||
|
spExtDev := 0;
|
|||
|
spCategory := catDisplay;
|
|||
|
spCType := typeVideo;
|
|||
|
spDrvrSW := drSwApple;
|
|||
|
spHWDev := 0;
|
|||
|
spTBMask := 1; {mask off hardware type field; match any vendor}
|
|||
|
END;
|
|||
|
err := SGetTypeSRsrc(@spBlk);
|
|||
|
|
|||
|
FindSlotStruct := err;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
NumFamilies finds the number of active and inactive video sResources.
|
|||
|
}
|
|||
|
FUNCTION NumFamilies(slot: INTEGER): INTEGER;
|
|||
|
VAR
|
|||
|
count: INTEGER;
|
|||
|
spBlk: spBlock;
|
|||
|
err: OSErr;
|
|||
|
BEGIN
|
|||
|
count := 0;
|
|||
|
err := NoErr;
|
|||
|
spBlk.spId := 0;
|
|||
|
WHILE (err = NoErr) DO
|
|||
|
BEGIN
|
|||
|
err := FindSlotStruct(slot, spBlk, spFlagAll+spFlagNext+spFlagOneSlot); {force to find invalid sRsrcs}
|
|||
|
IF err = NoErr THEN
|
|||
|
count := count + 1;
|
|||
|
END;
|
|||
|
IF count = 0 THEN {if we didn't find any, then there MUST be the active one}
|
|||
|
count := 1;
|
|||
|
|
|||
|
NumFamilies := count;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
GetActiveFamily gets the active member of the video family.
|
|||
|
}
|
|||
|
FUNCTION GetActiveFamily(slot: INTEGER): SignedByte;
|
|||
|
VAR
|
|||
|
spBlk: spBlock;
|
|||
|
err: OSErr;
|
|||
|
BEGIN
|
|||
|
GetActiveFamily := 0;
|
|||
|
spBlk.spId := 0;
|
|||
|
err := FindSlotStruct(slot, spBlk, spFlagNext+spFlagOneSlot);
|
|||
|
IF err = NoErr THEN
|
|||
|
GetActiveFamily := spBlk.spID;
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
SetMemUsed sets the string indicating the amount of memory that will be used/freed
|
|||
|
for a given selection.
|
|||
|
}
|
|||
|
PROCEDURE SetMemUsed(numItems, item: INTEGER; mDialog: DialogPtr; slot, localID: INTEGER);
|
|||
|
VAR
|
|||
|
iType: INTEGER;
|
|||
|
iHandle: HANDLE;
|
|||
|
iBox: Rect;
|
|||
|
defaultID: SignedByte;
|
|||
|
size: LONGINT;
|
|||
|
newText: STR255;
|
|||
|
titleText: STR255;
|
|||
|
BEGIN
|
|||
|
GetDItem(mDialog, MemoryItem + numItems, iType, iHandle, iBox);
|
|||
|
defaultID := GetActiveFamily(slot);
|
|||
|
size := GetMemoryUsed(Id2Item(defaultID), slot) - GetMemoryUsed(item - numItems, slot);
|
|||
|
IF size = 0 THEN
|
|||
|
newText := ''
|
|||
|
ELSE
|
|||
|
BEGIN
|
|||
|
NumToString(abs(size) DIV 1024, newText);
|
|||
|
IF size < 0 THEN
|
|||
|
BEGIN
|
|||
|
GetIndString(titleText, localID, 1);
|
|||
|
NewText := concat(titleText, newText);
|
|||
|
GetIndString(titleText, localID, 2);
|
|||
|
NewText := concat(newText, titleText);
|
|||
|
END
|
|||
|
ELSE
|
|||
|
BEGIN
|
|||
|
GetIndString(titleText, localID, 3);
|
|||
|
NewText := concat(titleText, newText);
|
|||
|
GetIndString(titleText, localID, 4);
|
|||
|
NewText := concat(newText, titleText);
|
|||
|
END;
|
|||
|
END;
|
|||
|
SetIText(iHandle, newText);
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
SetLine sets the item to our line drawing routine.
|
|||
|
}
|
|||
|
PROCEDURE SetLine(item, numItems: INTEGER; superUser: LONGINT; mDialog: DialogPtr);
|
|||
|
VAR
|
|||
|
iType: INTEGER;
|
|||
|
iHandle: HANDLE;
|
|||
|
iBox: Rect;
|
|||
|
BEGIN
|
|||
|
GetDItem(mDialog, item + numItems, iType, iHandle, iBox); {put in our line}
|
|||
|
|
|||
|
{
|
|||
|
Draw the divider line in gray (when in superuser mode) and the other lines
|
|||
|
solid.
|
|||
|
}
|
|||
|
IF item = divLineItem THEN
|
|||
|
BEGIN
|
|||
|
IF superUser = 1 THEN
|
|||
|
SetDItem(mDialog, item + numItems, iType, @DrawDivLine, iBox)
|
|||
|
END
|
|||
|
ELSE
|
|||
|
SetDItem(mDialog, item + numItems, iType, @DrawLine, iBox);
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
CenterRect centers a rectangle on another rectangle.
|
|||
|
}
|
|||
|
PROCEDURE CenterRect(VAR rectToCenter: Rect; rectToCenterOn: Rect);
|
|||
|
VAR
|
|||
|
ptToCenterTo: Point;
|
|||
|
oldCenter: Point;
|
|||
|
BEGIN
|
|||
|
WITH rectToCenterOn DO
|
|||
|
BEGIN
|
|||
|
ptToCenterTo.v := top + (bottom - top) DIV 2;
|
|||
|
ptToCenterTo.h := left + (right - left) DIV 2;
|
|||
|
END;
|
|||
|
WITH rectToCenter DO
|
|||
|
BEGIN
|
|||
|
oldCenter.v := top + (bottom - top) DIV 2;
|
|||
|
oldCenter.h := left + (right - left) DIV 2;
|
|||
|
END;
|
|||
|
OffsetRect(rectToCenter, ptToCenterTo.h - oldCenter.h, ptToCenterTo.v - oldCenter.v);
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
MyAlert performs an alert after moving the window over the control panel
|
|||
|
(front window).
|
|||
|
}
|
|||
|
FUNCTION MyAlert(alertID: INTEGER; filterProc: ProcPtr): INTEGER;
|
|||
|
VAR
|
|||
|
alertHand: AlertTHndl;
|
|||
|
r: Rect;
|
|||
|
mWindow: WindowPtr;
|
|||
|
savedPort: GrafPtr;
|
|||
|
BEGIN
|
|||
|
mWindow := FrontWindow;
|
|||
|
|
|||
|
InitCursor;
|
|||
|
alertHand := AlertTHndl(GetResource('ALRT', alertID));
|
|||
|
r := mWindow^.portRect;
|
|||
|
LocalToGlobal(r.topLeft);
|
|||
|
LocalToGlobal(r.botRight);
|
|||
|
CenterRect(alertHand^^.boundsRect, r);
|
|||
|
MyAlert := NoteAlert(alertID, filterProc);
|
|||
|
|
|||
|
{
|
|||
|
If I don<EFBFBD>t do the following, then the Monitors window doesn<EFBFBD>t get updated properly
|
|||
|
under System 7.0. I should probably clip around the area where the NoteAlert
|
|||
|
came up, but I<EFBFBD>m hoping that this code can be dumped. -- jmp
|
|||
|
}
|
|||
|
GetPort(savedPort);
|
|||
|
SetPort(mWindow);
|
|||
|
|
|||
|
InvalRect(mWindow^.portRect);
|
|||
|
SetPort(savedPort);
|
|||
|
END;
|
|||
|
|
|||
|
{---------------------------------------------------------------------------------
|
|||
|
EDialog is the main code.
|
|||
|
}
|
|||
|
FUNCTION EDialog(message, {the action to handle}
|
|||
|
item, {the DITL item or 0}
|
|||
|
numItems: INTEGER; {the number of the systems last item}
|
|||
|
monitorValue: LONGINT; {the value returned last time. defaults to zero}
|
|||
|
mDialog: DialogPtr; {the dialog pointer}
|
|||
|
theEvent: EventRecord; {the event that caused the message to happen}
|
|||
|
ScreenNum: INTEGER; {the number of the screen to affect}
|
|||
|
VAR Screens: ScrnRsrcHandle; {the screen resource to change if desired}
|
|||
|
VAR ScrnChanged: BOOLEAN {TRUE if we should clean up Screens}
|
|||
|
): LONGINT; {value to pass back in or error if negative}
|
|||
|
VAR
|
|||
|
iType: INTEGER;
|
|||
|
iHandle: HANDLE;
|
|||
|
iBox: Rect;
|
|||
|
err: OSErr;
|
|||
|
defaultID: SignedByte;
|
|||
|
itemFound: INTEGER;
|
|||
|
id: SignedByte;
|
|||
|
depth: INTEGER;
|
|||
|
num: INTEGER;
|
|||
|
rectHdl: RectHandle;
|
|||
|
theName: STR255;
|
|||
|
found: BOOLEAN;
|
|||
|
baseID: INTEGER;
|
|||
|
localID: INTEGER;
|
|||
|
theType: ResType;
|
|||
|
i: INTEGER;
|
|||
|
|
|||
|
disposeStorage: BOOLEAN; {true when time to dispose private storage}
|
|||
|
savedResFile: INTEGER; {for saving/restoring the current resFile}
|
|||
|
codeHandle: Handle; {for remembering handle to mntr resource}
|
|||
|
|
|||
|
BEGIN
|
|||
|
{
|
|||
|
Remember our entry point<EFBFBD>
|
|||
|
}
|
|||
|
codeHandle := Recoverhandle(@Entry);
|
|||
|
|
|||
|
{
|
|||
|
Scary stuff here!
|
|||
|
}
|
|||
|
GetResInfo(codeHandle, baseID, theType, theName);
|
|||
|
baseID := BAND(baseID, $FFE0);
|
|||
|
localID := baseID + $10;
|
|||
|
|
|||
|
{
|
|||
|
We<EFBFBD>ll determine dynamically whether storage needs to be thrown away
|
|||
|
this time or not.
|
|||
|
}
|
|||
|
disposeStorage := FALSE;
|
|||
|
|
|||
|
{
|
|||
|
Handle the messages<EFBFBD>
|
|||
|
}
|
|||
|
CASE message OF
|
|||
|
STARTUPMSG:
|
|||
|
BEGIN
|
|||
|
theName := GetCardName(Screens^^.scrnRecs[ScreenNum].srSlot);
|
|||
|
found := FALSE;
|
|||
|
|
|||
|
savedResFile := CurResFile;
|
|||
|
UseResFile(HomeResFile(codeHandle));
|
|||
|
|
|||
|
FOR i := localID TO (localID + numShow) DO
|
|||
|
BEGIN
|
|||
|
iHandle := Get1Resource('card',i);
|
|||
|
IF iHandle <> NIL THEN
|
|||
|
IF theName = StringHandle(iHandle)^^ THEN
|
|||
|
found := TRUE;
|
|||
|
END;
|
|||
|
UseResFile(savedResFile);
|
|||
|
|
|||
|
monitorValue := LONGINT(NewHandle(sizeof(INTEGER)));
|
|||
|
|
|||
|
IF monitorValue <> LONGINT(NIL) THEN
|
|||
|
BEGIN
|
|||
|
IF NOT found THEN
|
|||
|
disposeStorage := TRUE
|
|||
|
ELSE
|
|||
|
BEGIN
|
|||
|
num := NumFamilies(Screens^^.scrnRecs[ScreenNum].srSlot);
|
|||
|
rectHdl := RectHandle(GetResource('RECT', baseID));
|
|||
|
IF rectHdl <> NIL THEN
|
|||
|
BEGIN
|
|||
|
HNoPurge(Handle(rectHdl)); {so the resource won't be purged}
|
|||
|
rectHdl^^.top := rectHdl^^.top + (ButtonDistance * (4 - num));
|
|||
|
|
|||
|
Handle(monitorValue)^^ := item;
|
|||
|
END
|
|||
|
ELSE
|
|||
|
disposeStorage := TRUE;
|
|||
|
END;
|
|||
|
END;
|
|||
|
END;
|
|||
|
|
|||
|
INITMSG:
|
|||
|
BEGIN
|
|||
|
{
|
|||
|
Set the line separating us from the default controls.
|
|||
|
}
|
|||
|
SetLine(divLineItem, numItems, Handle(monitorValue)^^, mDialog);
|
|||
|
|
|||
|
{
|
|||
|
Find how many controls are showing and select the correct border rect.
|
|||
|
}
|
|||
|
CASE NumFamilies(Screens^^.scrnRecs[ScreenNum].srSlot) OF
|
|||
|
2:
|
|||
|
SetLine(rect1Item, numItems, Handle(monitorValue)^^, mDialog);
|
|||
|
3:
|
|||
|
SetLine(rect2Item, numItems, Handle(monitorValue)^^, mDialog);
|
|||
|
OTHERWISE
|
|||
|
SetLine(rect3Item, numItems, Handle(monitorValue)^^, mDialog);
|
|||
|
END;
|
|||
|
|
|||
|
{
|
|||
|
Select the approriate control. If we can't get the default, try for the active
|
|||
|
family member.
|
|||
|
}
|
|||
|
err := GetVidDefault(defaultID, Screens^^.scrnRecs[ScreenNum].srSlot);
|
|||
|
IF err <> noErr THEN
|
|||
|
defaultID := GetActiveFamily(Screens^^.scrnRecs[ScreenNum].srSlot);
|
|||
|
|
|||
|
itemFound := ID2Item(defaultID) + numItems;
|
|||
|
GetDItem(mDialog, itemFound, iType, iHandle, iBox);
|
|||
|
SetCtlValue(ControlHandle(iHandle), 1);
|
|||
|
|
|||
|
{
|
|||
|
Define the default control by appending message to the name of the active
|
|||
|
control.
|
|||
|
}
|
|||
|
defaultID := GetActiveFamily(Screens^^.scrnRecs[ScreenNum].srSlot);
|
|||
|
itemFound := ID2Item(defaultID) + numItems;
|
|||
|
GetDItem(mDialog, itemFound, iType, iHandle, iBox);
|
|||
|
GetCTitle(ControlHandle(iHandle), theName);
|
|||
|
theName := concat(theName, GetString(localID)^^);
|
|||
|
SetCTitle(ControlHandle(iHandle), theName);
|
|||
|
END;
|
|||
|
|
|||
|
HITMSG:
|
|||
|
BEGIN
|
|||
|
SetControl(mDialog, Item, numItems);
|
|||
|
SetMemUsed(numItems, Item, mDialog, Screens^^.scrnRecs[ScreenNum].srSlot, localID);
|
|||
|
END;
|
|||
|
|
|||
|
OKMSG:
|
|||
|
BEGIN
|
|||
|
itemFound := GetControl(mDialog, numItems);
|
|||
|
IF itemFound <> 0 THEN
|
|||
|
BEGIN
|
|||
|
err := GetVidDefault(defaultID, Screens^^.scrnRecs[ScreenNum].srSlot);
|
|||
|
id := Item2ID(itemFound, defaultID);
|
|||
|
IF (err = noErr) AND (id <> defaultID) THEN
|
|||
|
BEGIN
|
|||
|
depth := $80 + (itemFound - BWOnlyItem); {This is ugly, but still works.}
|
|||
|
err := SetVidDefault(id, depth, Screens^^.scrnRecs[ScreenNum].srSlot, Screens, ScreenNum);
|
|||
|
END;
|
|||
|
IF (err = noErr) AND (id <> GetActiveFamily(Screens^^.scrnRecs[ScreenNum].srSlot)) THEN
|
|||
|
BEGIN
|
|||
|
ScrnChanged := TRUE;
|
|||
|
Ptr(MonitorsMem)^ := BAnd(Ptr(MonitorsMem)^, BNot(BSL(1, ScreenNum)));
|
|||
|
err := MyAlert(localID, NIL);
|
|||
|
END;
|
|||
|
END;
|
|||
|
|
|||
|
disposeStorage := TRUE;
|
|||
|
END;
|
|||
|
|
|||
|
CANCELMSG:
|
|||
|
disposeStorage := TRUE;
|
|||
|
END;
|
|||
|
|
|||
|
{
|
|||
|
Common area for disposing of storage for <EFBFBD>superUser<EFBFBD> vs. <EFBFBD>normalUser<EFBFBD> flag. Note
|
|||
|
that if disposeStorage is TRUE at start, the monitorValue being set to errorValue
|
|||
|
is the right thing to do. Also, since the okMsg and cancelMsg are <EFBFBD>then end,<EFBFBD> setting
|
|||
|
monitorValue to an errorValue doesn<EFBFBD>t matter.
|
|||
|
}
|
|||
|
IF disposeStorage THEN
|
|||
|
BEGIN
|
|||
|
DisposHandle(Handle(monitorValue));
|
|||
|
monitorValue := errorValue;
|
|||
|
END;
|
|||
|
|
|||
|
{
|
|||
|
Return the result<EFBFBD>
|
|||
|
}
|
|||
|
EDialog := monitorValue;
|
|||
|
END;
|
|||
|
|
|||
|
END.
|
|||
|
|
|||
|
|