-- file: IntExceptions.mesa -- edited by Brotz, December 9, 1980 2:45 PM -- edited by Levin, August 11, 1980 11:43 AM DIRECTORY dsD: FROM "DisplayDefs", displayCommon: FROM "DisplayCommon", exD: FROM "ExceptionDefs", ExceptionTableDefs, inD: FROM "InteractorDefs", Inline, intCommon: FROM "IntCommon", MiscDefs, SegmentDefs, Storage, String; IntExceptions: PROGRAM IMPORTS disC: displayCommon, dsD, ExceptionTableDefs, exD, inD, Inline, intC: intCommon, MiscDefs, SegmentDefs, Storage, String EXPORTS exD, inD SHARES inD = PUBLIC BEGIN OPEN exD, inD; -- Purpose: displays all exception messages. Text of the exceptions are contained within -- a table that is set up at install time. Exceptions are identified by their exception -- number (a CARDINAL) defined in ExceptionDefs. exceptionRegionDirty: PUBLIC BOOLEAN; -- exported variable. rightX: ARRAY [1 .. 2] OF ScreenXCoord _ [leftMargin, leftMargin]; recursionDepth: CARDINAL _ 0; SysBugSignal: SIGNAL [systemError: BOOLEAN] = CODE; SysBug: PROCEDURE [exception: Exception _ nil, message: STRING _ NIL] = -- Called when Laurel cannot proceed due to internal or user errors. When exception = nil -- and message = NIL, assumes that an internal error has occurred. Otherwise, -- assumes that a user error has occurred. BEGIN systemError: BOOLEAN = (exception = nil AND message = NIL); recursionDepth _ recursionDepth + 1; IF recursionDepth < 2 AND ~systemError THEN BEGIN DisplayExceptionOrStringOnLine[exception, message, 1]; DisplayExceptionLine[exD.cannotProceed, 2]; END; SIGNAL SysBugSignal[systemError]; END; -- of SysBug -- DisplayException: PROCEDURE [exception: Exception] = -- Displays error messages in the exceptions region. BEGIN -- Flashes screen, then displays one-line string in exception region. IF ~disC.bitMapReady THEN RETURN; ClearExceptionsRegion[]; DisplayExceptionLine[exception, 1]; FlashExceptionsRegion[]; END; -- of DisplayException -- DisplayExceptionString: PROCEDURE [string: STRING] = -- Displays error string in the exceptions region. BEGIN -- Flashes screen, then displays one-line string in exception region. IF ~disC.bitMapReady THEN RETURN; ClearExceptionsRegion[]; DisplayExceptionStringOnLine[string, 1]; FlashExceptionsRegion[]; END; -- of DisplayException -- DisplayExceptionLine: PROCEDURE [exception: Exception, lineNumber: CARDINAL] = -- Maps exception to its string and displays it on lineNumber of the exceptions region. BEGIN exceptionString: STRING _ [maxExceptionStringLength]; IF exception = exD.nil THEN exceptionString _ NIL ELSE GetExceptionString[exception, exceptionString]; DisplayExceptionStringOnLine[exceptionString, lineNumber]; END; -- of DisplayExceptionLine -- DisplayExceptionStringOnLine: PROCEDURE [exceptionString: STRING, lineNumber: CARDINAL] = -- Displays exceptionString on lineNumber of the exceptions region. BEGIN IF ~disC.bitMapReady THEN RETURN; ClearExceptionLine[lineNumber]; AppendStringToExceptionLine[exceptionString, lineNumber ! ExceptionLineOverflow => CONTINUE]; END; -- of DisplayExceptionStringOnLine -- AppendStringToExceptionLine: PROCEDURE [s: STRING, line: CARDINAL] = -- Appends s to the text already on line. May signal ExceptionLineOverflow with parameter -- i the index of the first character in s that doesn't fit on line. BEGIN firstUnusedIndex: CARDINAL; IF ~disC.bitMapReady THEN RETURN; IF s # NIL THEN BEGIN [firstUnusedIndex, rightX[line]] _ FillScreenWithWords [rightX[line], intC.exceptionsRegion.topY + line * dsD.lineHeight, rightMargin, 0, s]; exceptionRegionDirty _ TRUE; IF firstUnusedIndex # s.length THEN ERROR ExceptionLineOverflow[firstUnusedIndex]; END; END; -- of AppendStringToExceptionLine -- AppendExceptionToExceptionLine: PROCEDURE [exception: Exception, line: CARDINAL] = -- Appends exception to the text already on line. May signal ExceptionLineOverflow with -- parameter i being the the index of the first character in exception that doesn't fit on -- line. BEGIN exceptionString: STRING _ [maxExceptionStringLength]; IF exception = exD.nil THEN exceptionString _ NIL ELSE GetExceptionString[exception, exceptionString]; AppendStringToExceptionLine[exceptionString, line]; END; -- of AppendExceptionToExceptionLine -- AppendDecimalToExceptionLine: PROCEDURE [n: CARDINAL, line: CARDINAL] = -- Appends n to the text already on line. May signal ExceptionLineOverflow with parameter -- i being the index of the first character in n that doesn't fit on line. BEGIN nString: STRING = [6]; String.AppendNumber[nString, n, 10]; AppendStringToExceptionLine[nString, line]; END; -- of AppendDecimalToExceptionLine -- ExceptionLineOverflow: ERROR [i: CARDINAL] = CODE; -- Raised by AppendStringToExceptionLine (see above). DisplayExceptionOrStringOnLine: PROCEDURE [exception: Exception, string: STRING, lineNumber: CARDINAL] = -- Displays string if non-nil, otherwise exception on lineNumber of the exceptions region. BEGIN IF string = NIL OR string.length = 0 THEN DisplayExceptionLine[exception, lineNumber] ELSE DisplayExceptionStringOnLine[string, lineNumber]; END; -- of DisplayExceptionOrStringOnLine -- DisplayBothExceptionLines: PROCEDURE[string1: STRING, exception1: exD.Exception, string2: STRING, exception2: exD.Exception, flash: BOOLEAN _ TRUE] = -- Displays exception messages. Will use string1 if non-NIL and non-zero length, exception1 -- otherwise. Mutatis mutandis for string2. If flash, then will flash exceptions region. BEGIN DisplayExceptionOrStringOnLine[exception1, string1, 1]; DisplayExceptionOrStringOnLine[exception2, string2, 2]; IF flash THEN FlashExceptionsRegion[]; END; -- of DisplayBothExceptionLines -- -- Exception Table Code -- tableStart: CARDINAL; tableLength: CARDINAL; segments: DESCRIPTOR FOR ARRAY OF SegmentDefs.FileSegmentHandle; InitializeExceptions: PROCEDURE = -- Assumed to be called before BringInLaurelState BEGIN OPEN SegmentDefs; seg: FileSegmentHandle; nSegs, i: CARDINAL; [seg, tableStart] _ MiscDefs.DestroyFakeModule[LOOPHOLE[ExceptionTableDefs.ExceptionTable]]; nSegs _ seg.pages; segments _ DESCRIPTOR[Storage.Node[nSegs], nSegs]; FOR i IN [0..nSegs) DO segments[i] _ NewFileSegment[file: seg.file, base: seg.base+i, pages: 1, access: Read]; ENDLOOP; DeleteFileSegment[seg]; exceptionRegionDirty _ FALSE; END; -- of InitializeExceptions -- SetUpExceptionTable: PROCEDURE = -- Establishes proper table for Get/Append ExceptionString. BEGIN tableLength _ GetTableWord[tableStart]; IF intC.exceptionType = LaurelX THEN -- skip over Laurel table tableLength _ GetTableWord[tableStart _ tableStart+tableLength+1]; tableStart _ tableStart+1; END; -- of UseExceptionTable -- GetExceptionString: PROCEDURE [exception: Exception, exceptionString: STRING] = -- Fills in caller supplied exceptionString with text corresponding to exception. BEGIN exceptionString.length _ 0; AppendExceptionString[exception, exceptionString]; END; -- of GetExceptionString -- AppendExceptionString: PROCEDURE [exception: Exception, exceptionString: STRING] = -- Appends text corresponding to exception to end of caller supplied exceptionString. BEGIN OPEN SegmentDefs; segNo: CARDINAL; byte: [0..512]; seg: FileSegmentHandle; chars: POINTER TO PACKED ARRAY [0..512) OF CHARACTER; SetUpSegment: PROCEDURE = BEGIN seg _ segments[segNo]; SwapIn[seg]; chars _ FileSegmentAddress[seg]; END; IF exception >= tableLength THEN RETURN; -- bogus Exception number; treat as empty string [segNo, byte] _ Inline.DIVMOD[GetTableWord[tableStart+exception], 512]; SetUpSegment[]; UNTIL exceptionString.length = exceptionString.maxlength DO IF byte = 512 THEN BEGIN Unlock[seg]; segNo _ segNo+1; SetUpSegment[]; byte _ 0; END; IF chars[byte] = ExceptionTableDefs.endMarker THEN EXIT ELSE String.AppendChar[exceptionString, chars[byte]]; byte _ byte+1; ENDLOOP; Unlock[seg]; END; -- of AppendExceptionString -- GetTableWord: PRIVATE PROCEDURE[word: CARDINAL] RETURNS[val: CARDINAL] = BEGIN OPEN SegmentDefs; segNo: CARDINAL; seg: FileSegmentHandle; wordOffset: [0..256); [segNo, wordOffset] _ Inline.DIVMOD[word, 256]; seg _ segments[segNo]; SwapIn[seg]; val _ (FileSegmentAddress[seg]+wordOffset)^; Unlock[seg]; END; RealClearExceptionsRegion: PROCEDURE = -- Really clears the entire text area of the exceptions region. BEGIN IF ~disC.bitMapReady THEN RETURN; ClearExceptionLine[1]; ClearExceptionLine[2]; exceptionRegionDirty _ FALSE; END; -- of RealClearExceptionsRegion -- ClearExceptionLine: PROCEDURE [line: CARDINAL] = BEGIN IF ~disC.bitMapReady THEN RETURN; dsD.ClearRectangle [leftMargin, rightX[line], intC.exceptionsRegion.topY + line * dsD.lineHeight, intC.exceptionsRegion.topY + (line + 1) * dsD.lineHeight]; rightX[line] _ leftMargin; END; -- of ClearExceptionLine -- FlashExceptionsRegion: PROCEDURE = -- Flashes a rectangle within the exceptions region. BEGIN IF ~disC.bitMapReady THEN RETURN; THROUGH [1 .. 4] DO IF MouseButton[any, down] THEN RETURN; THROUGH [1 .. 2] DO dsD.InvertRectangle[leftMargin, rightMargin, intC.exceptionsRegion.topY+ dsD.lineHeight, intC.exceptionsRegion.topY + 3*dsD.lineHeight]; BusyWait[3]; ENDLOOP; ENDLOOP; END; -- of FlashExceptionsRegion -- BusyWait: PROCEDURE [duration: CARDINAL] = -- Waits for a period of (duration/26) seconds. -- Imperative that this procedure not WAIT or Yield. BEGIN startTime: CARDINAL = realTimeClock^; UNTIL LOOPHOLE[realTimeClock^ - startTime, CARDINAL] >= duration DO ENDLOOP; END; -- of BusyWait -- ExceptionsTracker: PROCEDURE [mnp: MessageTextNbrPtr, trackerType: TrackerType] = -- Tracks cursor within the Exceptions neighborhood. BEGIN -- ## of course this is not in a final state -- x: ScreenXCoord; y: ScreenYCoord; xOffset, yOffset: INTEGER; dsD.ChangeCursor[charArrow]; [ , xOffset, yOffset] _ dsD.GetCursor[]; DO x _ cursorX^ + xOffset; y _ cursorY^ + yOffset; IF ~(y IN [mnp.topY .. mnp.bottomY)) THEN RETURN; IdleLoop[]; AcceptKeyboardInput[]; ENDLOOP; END; -- of ExceptionsTracker -- END. -- of IntExceptions --z20461e1(529)\f1