-- file: LaurelNub.Mesa
-- edited by Levin, April 14, 1981 4:22 PM
-- edited by Brotz, August 31, 1982 1:43 PM
-- edited by Schroeder: Wednesday Nov. 5, 1980 5:09 pm PST.
-- edited by Taft, May 10, 1983 6:08 PM

DIRECTORY
ccD: FROM "ChollaCmdDefs" USING [StartChollaMailProcess],
ControlDefs USING [GlobalFrame, Port],
CoreSwapDefs USING [PuntInfo],
displayCommon USING [bitmapInMDS, bitMapPtr, bitMapReady],
drD: FROM "LaurelDriverDefs" USING [CommandLineAction, InstallError,
PreStopInitialization, ProcessBugReport, ResumeNub],
dsD: FROM "DisplayDefs" USING [Bbt, bbtPtr, bmWidth, charBbtPtr, ClearRectangle,
CursorBitMap, cursorBM, lineHeight, machineFlavor, paint, pictureBbtPtr,
PutStringInBitMap, ReplaceRectangle, ScreenYCoord, SetCursor, source, yOrigin],
exD: FROM "ExceptionDefs" USING [DisplayException, installFailed, SysBug],
FrameDefs USING [GlobalFrame],
inD: FROM "InteractorDefs" USING [CaretIsBlinking, HousePtr, leftMargin, rightMargin,
ScreenTracker, ScreenYCoord, SetCaretBlinking, SetScreenParameters],
Inline USING [BITAND, HighHalf, LowHalf],
intCommon USING [audioEnabled, debuggerExtant, deleteCommandHouse,
displayCommandHouse, isCholla, mailFileBracketsHouse, mailFileCommandHouse,
newFormCommandHouse, newMailCommandHouse, newMailTune, numScanLines,
quitCommandHouse, retrieveHandle, target, tocTextNbr],
KeyDefs USING [Keys],
MiscDefs USING [WorryCallDebugger],
ProcessDefs USING [Yield],
RetrieveDefs USING [MailboxState, MBXState],
SegmentDefs USING [DefaultMDSBase, DefaultXMBase, HardDown, LongDataSegmentAddress,
MakeDataSegment],
Storage USING [Node, Prune],
String USING [AppendString];

LaurelNub: PROGRAM
IMPORTS ccD, disC: displayCommon, drD, dsD, exD, FrameDefs, inD, Inline,
intC: intCommon, MiscDefs, -- PerfDefs,-- ProcessDefs, RetrieveDefs, SegmentDefs,
Storage, String =

BEGIN
OPEN drD;


AllocateAndInitBitMap: PROCEDURE =
BEGIN
OPEN SegmentDefs;
dwtBankRegister: POINTER = LOOPHOLE[177740B + 11B];
wordsForBitMap: CARDINAL ← intC.numScanLines * dsD.bmWidth;
pagesForBitMap: CARDINAL ← (wordsForBitMap + 255) / 256;
[] ← Storage.Prune[];
disC.bitMapPtr ← LongDataSegmentAddress
[MakeDataSegment[IF disC.bitmapInMDS THEN DefaultMDSBase ELSE DefaultXMBase,
pagesForBitMap, HardDown]];
IF ~disC.bitmapInMDS AND dsD.machineFlavor # dmachine THEN
dwtBankRegister↑ ← Inline.HighHalf[disC.bitMapPtr] * 4;
END; -- of AllocateAndInitBitMap --


AllocateAndInitBbts: PROCEDURE =
-- Allocates and fills in constant fields of the BITBLT tables. Note: must be called AFTER
-- the last AllocateAndInitBitMap.
BEGIN OPEN dsD;

MakeBbt: PROCEDURE RETURNS [POINTER] =
-- Allocates SIZE[Bbt] words starting at an even address
BEGIN
p: POINTER ← Storage.Node[SIZE[Bbt] + 1];
RETURN[p + Inline.BITAND[p, 1]];
END; -- of Even --

charBbtPtr ← MakeBbt[];
charBbtPtr↑ ←
[ptrs: IF dsD.machineFlavor = dmachine THEN long ELSE short,
sourcealt: FALSE,
destalt: dsD.machineFlavor # dmachine AND ~disC.bitmapInMDS,
func: paint + source,
unused: IF dsD.machineFlavor = dmachine THEN 0
ELSE Inline.HighHalf[disC.bitMapPtr],
dbca: Inline.LowHalf[disC.bitMapPtr],
dlx: , dty: , dw: , dh: ,
sbca: , sbmr: 1,
slx: 0, sty: 0,
dlbca: disC.bitMapPtr];

bbtPtr ← MakeBbt[];
bbtPtr↑ ←
[ptrs: IF dsD.machineFlavor = dmachine THEN long ELSE short,
sourcealt: dsD.machineFlavor # dmachine AND ~disC.bitmapInMDS,
destalt: dsD.machineFlavor # dmachine AND ~disC.bitmapInMDS,
func: ,
unused: IF dsD.machineFlavor = dmachine THEN 0
ELSE Inline.HighHalf[disC.bitMapPtr],
dbca: Inline.LowHalf[disC.bitMapPtr],
dlx: , dty: , dw: , dh: ,
sbca: Inline.LowHalf[disC.bitMapPtr], sbmr: dsD.bmWidth,
slx: , sty: ,
slbca: disC.bitMapPtr,
dlbca: disC.bitMapPtr];

pictureBbtPtr ← MakeBbt[];
pictureBbtPtr↑ ← charBbtPtr↑;

disC.bitMapReady ← TRUE;
END; -- of AllocateAndInitBbts --


CheckForDebuggerCall: PROCEDURE =
BEGIN
OPEN CoreSwapDefs, KeyDefs;
IF (intC.debuggerExtant
← PuntInfo↑ ~= NIL AND PuntInfo↑↑.pDebuggerFP ~= NIL)
AND Keys.Spare2 = down AND Keys.Spare3 = down THEN
BEGIN
debuggingCursor: dsD.CursorBitMap = [
001000B, 002400B, 005200B, 012500B, 025240B, 052540B, 025240B, 012740B,
005240B, 003760B, 000030B, 000014B, 000006B, 000003B, 000001B, 000000B ];
savedCursor: dsD.CursorBitMap ← dsD.cursorBM↑;
dsD.cursorBM↑ ← debuggingCursor;
MiscDefs.WorryCallDebugger["Get that bug!"L];
dsD.cursorBM↑ ← savedCursor;
END;
END; -- CheckForDebuggerCall --


InitializeLaurel: PROCEDURE =
BEGIN
installError: drD.InstallError;
commandInCommandLine: CommandLineAction;

ConfigureDisplay: PROCEDURE =
BEGIN
linesTotal: CARDINAL = intC.numScanLines/dsD.lineHeight;
linesAvailable: CARDINAL = linesTotal - (4+3+3+3);
-- Distribute available lines in the ratio TOC: 12, DM: 19, CM: 16.
-- (Those numbers are the actual values for a normal-size display.)
linesTOC: CARDINAL = (12*linesAvailable)/(12+19+16);
linesDM: CARDINAL = (19*linesAvailable)/(12+19+16);
linesCM: CARDINAL = linesAvailable - (linesTOC+linesDM);
inD.SetScreenParameters
[[4, -- mailCommandRegion
linesTOC, -- tocRegion
3, -- tocCommandRegion
linesDM, -- dmRegion
3, -- cmCommandRegion
linesCM, -- cmRegion
3]]; -- exceptionsRegion
END;

ProcessCommandLine: PROCEDURE [entryKind: CommandLineAction] =
BEGIN
inBoxState: RetrieveDefs.MBXState;

intC.mailFileBracketsHouse.houseRefresher[intC.mailFileBracketsHouse];
SELECT entryKind FROM
gmfOnly => SimulateCommandInHouse[intC.mailFileCommandHouse, TRUE];
checkOnly =>
BEGIN
inBoxState ← RetrieveDefs.MailboxState[intC.retrieveHandle];
IF ~(inBoxState = notEmpty OR inBoxState = badPwd) THEN
SimulateCommandInHouse[intC.quitCommandHouse, TRUE];
SimulateCommandInHouse[intC.mailFileCommandHouse, TRUE];
IF intC.tocTextNbr.haveToc AND inBoxState = notEmpty THEN
SimulateCommandInHouse[intC.newMailCommandHouse, FALSE];
END;
gnmAndStay =>
BEGIN
SimulateCommandInHouse[intC.mailFileCommandHouse, TRUE];
inBoxState ← RetrieveDefs.MailboxState[intC.retrieveHandle];
IF intC.tocTextNbr.haveToc AND inBoxState = notEmpty THEN
SimulateCommandInHouse[intC.newMailCommandHouse, FALSE];
END;
sendOnly =>
BEGIN
IF intC.mailFileBracketsHouse.text.length # 0 THEN
SimulateCommandInHouse[intC.mailFileCommandHouse, TRUE];
SimulateCommandInHouse[intC.newFormCommandHouse, TRUE];
END;
sendBug => ProcessBugReport[];
ENDCASE;
intC.audioEnabled ← (intC.newMailTune # NIL);
END; -- of ProcessCommandLine --

SimulateCommandInHouse: PROCEDURE [hp: inD.HousePtr, confirmed: BOOLEAN] =
-- Simulates command selection, including graying.
-- Will not work properly for picture houses.
BEGIN
dsD.ReplaceRectangle[hp.leftX, hp.rightX, hp.topY, hp.bottomY, lightGray];
[] ← dsD.PutStringInBitMap[hp.leftX, hp.topY, hp.text, boldFace];
hp.command[hp, confirmed];
dsD.ClearRectangle[hp.leftX, hp.rightX, hp.topY, hp.bottomY];
[] ← dsD.PutStringInBitMap[hp.leftX, hp.topY, hp.text, hp.typeface];
IF inD.CaretIsBlinking[] THEN inD.SetCaretBlinking[intC.target.point, intC.target.mnp];
END; -- of SimulateCommandInHouse --



-- ****************************
-- Initialization Code Proper
-- ****************************

[commandInCommandLine, installError] ← PreInit[];

AllocateAndInitBitMap[];
AllocateAndInitBbts[];
dsD.ClearRectangle
[inD.leftMargin, inD.rightMargin, dsD.yOrigin, dsD.yOrigin + intC.numScanLines];
IF installError = inLog THEN
BEGIN
intC.mailFileBracketsHouse.text.length ← 0;
String.AppendString[intC.mailFileBracketsHouse.text, "InstallErrors"L];
END;
ConfigureDisplay[];

-- report error from ReadLaurelProfile, if any

SELECT installError FROM
none => NULL;
inLog =>
BEGIN
SimulateCommandInHouse[intC.mailFileCommandHouse, TRUE];
SimulateCommandInHouse[intC.displayCommandHouse, TRUE];
SimulateCommandInHouse[intC.deleteCommandHouse, TRUE];
exD.DisplayException[exD.installFailed];
END;
ENDCASE => exD.SysBug[message: "Deep yoghurt."L];

ProcessDefs.Yield[]; -- let EtherProbe run

-- Now act on the command line switches.

IF installError = none THEN
BEGIN
IF intC.isCholla THEN ccD.StartChollaMailProcess[];
ProcessCommandLine[commandInCommandLine];
END
ELSE intC.isCholla ← FALSE;
ProcessDefs.Yield[]; -- let EtherProbe run
END; -- of InitializeLaurel --


-- This is where it all gets started...


PreInit: PORT RETURNS
[commandInCommandLine: CommandLineAction, installError: InstallError];

LOOPHOLE[PreInit, ControlDefs.Port].out ← @ResumeNub;
START LOOPHOLE[FrameDefs.GlobalFrame[PreStopInitialization], PROGRAM];
LOOPHOLE[ResumeNub, ControlDefs.Port].out ← @PreInit;
LOOPHOLE[ResumeNub, ControlDefs.Port].in ← PreStopInitialization;

[] ← PreInit[];

STOP;

-- START PerfDefs.AltoMesaPerfMonitor;
CheckForDebuggerCall[]; -- cannot be done before the STOP
InitializeLaurel[]; -- do the Laurel initialization
dsD.SetCursor[bullsEye];
inD.ScreenTracker[normal];

END. -- of LaurelNub --