-- file: IntIdleLoop.mesa -- edited by Brotz, January 19, 1982 3:53 PM -- edited by Levin, 13-Nov-80 16:28:30 DIRECTORY DMSTimeDefs USING [currentTime, HardwareTime, MapPackedTimeToTimeZoneString, PackedTime], dsD: FROM "DisplayDefs" USING [BlackenRectangle, ClearRectangle, erase, invert, PaintPicture, replace, ReplaceRectangle, ScreenXCoord, ScreenYCoord], Editor USING [MapCharIndexInLineToLeftX, MapCharIndexToLine], inD: FROM "InteractorDefs" USING [CaretState, CharIndex, LinePtr, MessageTextNbrPtr, realTimeClock, ScreenXCoord, ScreenYCoord, SetTime, TextHouseRefresher, ThumbLineNbrPtr, TOCTextNbrPtr], Inline USING [LongDivMod, LongMult], intCommon USING [cmTextNbr, cmThumbLineNbr, dmTextNbr, dmThumbLineNbr, lastMinuteSeconds, secondsLastChecked, target, timeHouse, timeMayBeBogus, tocThumbLineNbr], ProcessDefs USING [Yield], tsD: FROM "TOCSelectionDefs" USING [FirstSelectedEntry, TOCSelectionEmpty], vmD: FROM "VirtualMgrDefs" USING [CharIndex, FirstFreeTOCIndex, GetMessageSize, TOCHandle]; IntIdleLoop: MONITOR IMPORTS DMSTimeDefs, dsD, Editor, inD, intC: intCommon, Inline, ProcessDefs, tsD, vmD EXPORTS inD = BEGIN OPEN inD; -- Handles the IdleLoop and maintains the blinking caret. -- Global variables -- caretX: ScreenXCoord; caretY: ScreenYCoord; caretState: CaretState _ notVisible; caretLastUpdated: CARDINAL; -- nap: CONDITION; IdleLoop: PUBLIC PROCEDURE = -- Called by cursor tracking routines and any other routine that has time on its hands. -- Checks clock and calls procedures that must be activated at regular intervals, such as -- the time update for the top window and periodic mail checks. BEGIN DoTimeUpdate[]; -- Pause[]; ProcessDefs.Yield[]; UpdateDMandCMThumbLines[]; MaintainBlinkingCaret[]; END; -- of IdleLoop -- -- Pause: ENTRY PROCEDURE = INLINE -- causes the main Laurel process to give up control so that Pup and friends are happy. -- BEGIN -- WAIT nap; -- END; of Pause -- DoTimeUpdate: PROCEDURE = INLINE -- Updates the date-time-of-day string, and posts it in the time of day house. BEGIN pt: DMSTimeDefs.PackedTime = GetPackedTime[]; elapsedSeconds: CARDINAL; IF intC.timeMayBeBogus THEN {intC.timeMayBeBogus _ FALSE; SetTime[]; RETURN}; IF pt.lowbits = intC.secondsLastChecked THEN RETURN; intC.secondsLastChecked _ pt.lowbits; elapsedSeconds _ intC.secondsLastChecked - intC.lastMinuteSeconds; IF elapsedSeconds < 60 THEN RETURN; intC.lastMinuteSeconds _ intC.lastMinuteSeconds + 60 * (elapsedSeconds / 60); DMSTimeDefs.MapPackedTimeToTimeZoneString[pt, intC.timeHouse.text]; TextHouseRefresher[intC.timeHouse]; END; -- of DoTimeUpdate -- -- GetPackedTime is copied from TimeConvert to minimize swapping GetPackedTime: PRIVATE PROCEDURE RETURNS [DMSTimeDefs.PackedTime] = BEGIN ht: DMSTimeDefs.HardwareTime _ DMSTimeDefs.currentTime^; RETURN[[num[highbits: ht.highbits, lowbits: ht.lowbits]]]; END; -- of GetPackedTime -- -- Thumb line updating procedures UpdateThumbLineRecord: TYPE = RECORD [region: {toc, displayed, composed}, tlnp: ThumbLineNbrPtr, exists: BOOLEAN, length, start, end, selection: CARDINAL]; UpdateTOCThumbLine: PUBLIC PROCEDURE [tnp: TOCTextNbrPtr, key: CARDINAL] = -- Checks the TOC thumb line for a change in state and updates accordingly. BEGIN toc: vmD.TOCHandle = tnp.toc; updateThumbLineRecord: UpdateThumbLineRecord; updateThumbLineRecord _ UpdateThumbLineRecord [region: toc, tlnp: intC.tocThumbLineNbr, exists: toc # NIL, length: IF toc = NIL THEN 0 ELSE vmD.FirstFreeTOCIndex[toc, key] - 1, start: tnp.lines.linePair.index - 1, end: tnp.firstLineOffScreen.linePair.index - 1, selection: IF toc = NIL OR tsD.TOCSelectionEmpty[toc, key] THEN 0 ELSE tsD.FirstSelectedEntry[toc, key] - 1]; UpdateThumbLine[@updateThumbLineRecord]; END; -- of UpdateTOCThumbLine -- UpdateDMandCMThumbLines: PROCEDURE = -- Checks the DM and CM thumb lines for a change in state and updates accordingly. BEGIN updateThumbLineRecord: UpdateThumbLineRecord _ [region: displayed, tlnp: intC.dmThumbLineNbr, exists: , length: , start: , end: , selection: intC.target.start]; SetFromMNP: PROCEDURE[mnp: MessageTextNbrPtr] = BEGIN updateThumbLineRecord.start _ mnp.lines.firstCharIndex; updateThumbLineRecord.end _ mnp.firstLineOffScreen.firstCharIndex; updateThumbLineRecord.length _ IF (updateThumbLineRecord.exists _ mnp.haveMessage) THEN vmD.GetMessageSize[mnp.message] ELSE 0; END; -- of SetFrom MNP -- SetFromMNP[intC.dmTextNbr]; UpdateThumbLine[@updateThumbLineRecord]; updateThumbLineRecord.region _ composed; updateThumbLineRecord.tlnp _ intC.cmThumbLineNbr; SetFromMNP[intC.cmTextNbr]; UpdateThumbLine[@updateThumbLineRecord]; END; -- of UpdateDMandCMThumbLines -- UpdateThumbLine: PROCEDURE [utlr: POINTER TO UpdateThumbLineRecord] = -- Checks a thumb line for a change in state and updates accordingly. BEGIN OPEN utlr; quotient, remainder: CARDINAL; startX, endX, selectionX: ScreenXCoord; tlnp: ThumbLineNbrPtr _ utlr.tlnp; xRange: CARDINAL _ tlnp.rightX - tlnp.leftX; IF exists THEN BEGIN IF ~tlnp.exists OR tlnp.length # length OR tlnp.start # start OR tlnp.end # end OR (region # displayed AND tlnp.selection # selection) THEN BEGIN -- state changed and thumbable information exists tlnp.exists _ exists; tlnp.length _ length; tlnp.start _ start; tlnp.end _ end; tlnp.selection _ selection; IF length = 0 THEN BEGIN dsD.ClearRectangle[tlnp.leftX, tlnp.rightX, tlnp.topY + 1, tlnp.topY + 11]; dsD.BlackenRectangle[tlnp.leftX, tlnp.rightX, tlnp.topY + 5, tlnp.topY + 7]; tlnp.startX _ tlnp.leftX; tlnp.endX _ tlnp.leftX; tlnp.selectionX _ tlnp.leftX; END ELSE BEGIN [quotient, remainder] _ Inline.LongDivMod[Inline.LongMult[start, xRange], length]; startX _ quotient + tlnp.leftX + (IF remainder > 0 THEN 1 ELSE 0); [quotient, remainder] _ Inline.LongDivMod[Inline.LongMult[end, xRange], length]; endX _ quotient + tlnp.leftX + (IF remainder > 0 THEN 1 ELSE 0); IF region # displayed THEN BEGIN [quotient, remainder] _ Inline.LongDivMod[Inline.LongMult[selection, xRange], length]; selectionX _ quotient + tlnp.leftX + (IF remainder > 0 THEN 1 ELSE 0); END; IF startX + 8 > endX THEN BEGIN IF startX + 8 > tlnp.rightX THEN startX _ endX - 8 ELSE endX _ startX + 8; END; IF tlnp.startX # startX OR tlnp.endX # endX OR (region # displayed AND tlnp.selectionX # selectionX) THEN BEGIN OPEN dsD; IF region # displayed THEN PaintPicture[tlnp.selectionX, tlnp.topY+1, selectionThumbMark, erase]; ClearRectangle[tlnp.leftX, startX, tlnp.topY + 4, tlnp.topY + 8]; BlackenRectangle[tlnp.leftX, startX, tlnp.topY + 5, tlnp.topY + 7]; ReplaceRectangle[startX, endX, tlnp.topY + 4, tlnp.topY + 8, dottedLine]; ClearRectangle[endX, tlnp.rightX, tlnp.topY + 4, tlnp.topY + 8]; BlackenRectangle[endX, tlnp.rightX, tlnp.topY + 5, tlnp.topY + 7]; IF region # displayed THEN PaintPicture[selectionX, tlnp.topY + 1, selectionThumbMark, replace]; tlnp.startX _ startX; tlnp.endX _ endX; tlnp.selectionX _ selectionX; END; END; END; END ELSE IF tlnp.exists THEN BEGIN tlnp.exists _ FALSE; tlnp.startX _ tlnp.endX _ 0; dsD.ClearRectangle[tlnp.leftX, tlnp.rightX, tlnp.topY + 1, tlnp.topY + 11]; dsD.BlackenRectangle[tlnp.leftX, tlnp.rightX, tlnp.topY + 5, tlnp.topY + 7]; END; END; -- of UpdateThumbLine -- StartBlinkingCaret: PUBLIC PROCEDURE [x: ScreenXCoord, y: ScreenYCoord] = -- Notes time of call. Then places upper left corner of box containing caret at x,y. BEGIN StopBlinkingCaret[]; caretX _ x; caretY _ y; dsD.PaintPicture[caretX, caretY, caret, dsD.invert]; caretState _ black; caretLastUpdated _ realTimeClock^; END; -- of StartBlinkingCaret -- MaintainBlinkingCaret: PUBLIC PROCEDURE = -- Inverts caret at remembered x,y at appropriate time. BEGIN IF caretState = notVisible THEN RETURN; -- check if .3 seconds have elapsed since last caret inversion -- IF LOOPHOLE[realTimeClock^ - caretLastUpdated, CARDINAL] >= 9 THEN BEGIN -- one third second has elapsed since last update -- dsD.PaintPicture[caretX, caretY, caret, dsD.invert]; caretState _ IF caretState = black THEN white ELSE black; caretLastUpdated _ realTimeClock^; END; END; -- of MaintainBlinkingCaret -- StopBlinkingCaret: PUBLIC PROCEDURE = -- Restores caret picture to original state. BEGIN IF caretState = black THEN dsD.PaintPicture[caretX, caretY, caret, dsD.invert]; caretState _ notVisible; END; -- of StopBlinkingCaret -- SetCaretBlinking: PUBLIC PROCEDURE [charIndex: CharIndex, mnp: MessageTextNbrPtr] = BEGIN OPEN Editor; line: LinePtr; line _ MapCharIndexToLine[charIndex, mnp]; IF line # NIL THEN BEGIN caretX: ScreenXCoord _ MapCharIndexInLineToLeftX[charIndex, line, mnp.message] - 3; caretY: ScreenYCoord _ line.y + 9; StartBlinkingCaret[caretX, caretY]; END; END; -- of SetCaretBlinking -- -- Main body -- -- ProcessDefs.InitializeCondition[@nap, 1]; END. -- of IntIdleLoop --(635)\f1