-- file: IntRefreshers.mesa
-- edited by Brotz, May 24, 1982 1:56 PM
-- edited by Schroeder, August 1, 1978 11:43 AM
-- edited by Levin, February 7, 1980 5:44 PM

DIRECTORY
Ascii USING [SP],
DiskKDDefs USING [CountFreeDiskPages],
displayCommon USING [bitMapReady],
dsD: FROM "DisplayDefs" USING [bmWidth, ClearRectangle, GetCharRightX,
GetStringWidth, lineHeight, paint, PaintPicture, PutCharInBitMap, PutStringInBitMap,
ScreenXCoord],
inD: FROM "InteractorDefs" USING [DisplayTOCEntry, DisplayTOCTail, HousePtr, LinePtr,
rightMargin, ScreenXCoord, ScrollDownTOC, TOCTextNbrPtr, UpdateTOCThumbLine],
Inline USING [DIVMOD],
intCommon USING [freePagesHouse, TOCRegion],
Process USING [Detach, MsecToTicks],
String USING [AppendString],
tsD: FROM "TOCSelectionDefs" USING [FirstSelectedEntry],
vmD: FROM "VirtualMgrDefs" USING [TOCIndex];

IntRefreshers: MONITOR
IMPORTS disC: displayCommon, DiskKDDefs, dsD, inD, Inline, intC: intCommon, Process,
String, tsD
EXPORTS inD =

BEGIN
OPEN inD;

freePageCount: CARDINAL ← 0;
freePageWakeup: CONDITION ← [timeout: Process.MsecToTicks[500]];


TextHouseRefresher: PUBLIC PROCEDURE [hp: HousePtr] =
-- Repaints one simple text house on the display screen, according to the parameters
-- contained in hp↑.
BEGIN
IF NOT disC.bitMapReady THEN RETURN;
dsD.ClearRectangle[hp.leftX, hp.rightX, hp.topY, hp.bottomY];
IF hp.usePicture THEN dsD.PaintPicture[hp.leftX, hp.topY, hp.picture, dsD.paint]
ELSE BEGIN
SELECT hp.fixedEdge FROM
left => hp.rightX ← hp.leftX + dsD.GetStringWidth[hp.text, hp.typeface];
right => hp.leftX ← hp.rightX - dsD.GetStringWidth[hp.text, hp.typeface];
ENDCASE;
[] ← dsD.PutStringInBitMap[hp.leftX, hp.topY, hp.text, hp.typeface];
END;
END; -- of TextHouseRefresher --


BracketsHouseRefresher: PUBLIC PROCEDURE [hp: HousePtr] =
-- Repaints one brackets command house on the display screen.
BEGIN
OPEN dsD;
curX, limX, x: ScreenXCoord;
i: CARDINAL;

ClearRectangle[hp.leftX, hp.rightX, hp.topY, hp.bottomY];
curX ← PutCharInBitMap[’{, hp.leftX, hp.topY, boldFace];
limX ← (IF hp.nextHouse = NIL OR hp.nextHouse.lineNumber # hp.lineNumber
THEN inD.rightMargin ELSE hp.nextHouse.leftX) - GetStringWidth[" } "L, boldFace];
-- space before bracket is for caret
IF GetStringWidth[hp.text, plainFace]+curX <= limX THEN
curX ← PutStringInBitMap[curX, hp.topY, hp.text, hp.typeface]
ELSE BEGIN
FOR i IN [0..5] DO
curX ← PutCharInBitMap[hp.text[i], curX, hp.topY, plainFace];
ENDLOOP;
curX ← x ← PutStringInBitMap[curX, hp.topY, "..."L, plainFace];
FOR i ← hp.text.length-1, i-1 DO
IF (x ← GetCharRightX[hp.text[i], x]) > limX THEN EXIT;
ENDLOOP;
FOR i IN [i + 1 .. hp.text.length - 1] DO
curX ← PutCharInBitMap[hp.text[i], curX, hp.topY, plainFace];
ENDLOOP;
END;
hp.rightX ← PutCharInBitMap[’}, curX, hp.topY, boldFace];
END; -- of BracketsHouseRefresher --


NullHouseRefresher: PUBLIC PROCEDURE [hp: HousePtr] =
-- Place-holder.
BEGIN
END; -- of NullHouseRefresher --


RefreshHouse: PUBLIC PROCEDURE [hp: HousePtr, text: STRING] =
-- Resets hp.text to text and calls hp.houseRefresher.
BEGIN
hp.text.length ← 0;
String.AppendString[hp.text, text];
hp.houseRefresher[hp];
END; -- of RefreshHouse --


TOCTextPainter: PUBLIC PROCEDURE [tnp: TOCTextNbrPtr, key: CARDINAL] =
-- Paints the TOC text neighborhood starting with the first selected entry.
BEGIN
endLineNumber: CARDINAL;
line: LinePtr;
index: vmD.TOCIndex;
IF ~tnp.haveToc THEN RETURN;
intC.TOCRegion.dcb.width ← 0;
index ← tsD.FirstSelectedEntry[tnp.toc, key];
IF index = 0 THEN index ← 1;
DisplayTOCTail[tnp, key, tnp.lines, index, 1];
IF tnp.nLines > 0 AND tnp.firstLineOffScreen.state = empty THEN
BEGIN -- scroll End of messages down to bottom line on screen.
endLineNumber ← 1;
FOR line ← tnp.lines, line.nextLine UNTIL line.state = end DO
endLineNumber ← endLineNumber + 1;
ENDLOOP;
ScrollDownTOC[tnp.lines.y + (tnp.nLines - endLineNumber) * dsD.lineHeight, tnp, key];
END;
IF tnp.nLines > 1 AND index > 1 AND tnp.lines.linePair.index = index
AND tnp.lines.state # end THEN
BEGIN -- try to scroll down one more entry for context.
prevNLines, nLines: CARDINAL;
[ , prevNLines] ← DisplayTOCEntry[tnp, key, index - 1, 0, NIL];
[ , nLines] ← DisplayTOCEntry[tnp, key, index, 0, NIL];
IF nLines + prevNLines < tnp.nLines THEN
ScrollDownTOC[tnp.lines.y + prevNLines * dsD.lineHeight, tnp, key];
END;
intC.TOCRegion.dcb.width ← dsD.bmWidth;
UpdateTOCThumbLine[tnp, key];
END; -- of TOCTextPainter --


FreePagesHouseRefresher: ENTRY PROCEDURE =
-- Repaints the free pages house with count on the display screen.
BEGIN
text: STRING = intC.freePagesHouse.text;
DO
count: CARDINAL ← DiskKDDefs.CountFreeDiskPages[];
IF count # freePageCount THEN
BEGIN
remainder: CARDINAL;
FOR i: CARDINAL DECREASING IN [0 .. 5) DO
[count, remainder] ← Inline.DIVMOD[count, 10];
text[i] ← ’0 + remainder;
IF count = 0 THEN
{FOR j: CARDINAL IN [0 .. i) DO text[j] ← Ascii.SP; ENDLOOP; EXIT};
ENDLOOP;
freePageCount ← count;
TextHouseRefresher[intC.freePagesHouse];
END;
WAIT freePageWakeup;
ENDLOOP;
END; -- of FreePagesHouseRefresher --


Process.Detach[FORK FreePagesHouseRefresher[]];


END. -- of IntRefreshers --