-- file: IntBracketsCom.Mesa -- edited by Brotz, June 24, 1982 1:36 PM -- edited by Schroeder, December 2, 1980 9:59 AM -- edited by Levin, January 27, 1981 12:20 PM DIRECTORY AltoFile USING [CloseDirectory, DEfile, DirHandle, DVPtr, Enumerate, OpenDirectory, sysDirFP], Ascii USING [BS, ControlA, ControlW, CR, DEL, ESC, SP, TAB], Core USING [CacheEntry, localCacheHead], displayCommon USING [bitMapReady, charPropertyTable], dsD: FROM "DisplayDefs" USING [ChangeCursor, ClearRectangle, CursorShape, FaceType, GetCursor, GetStringWidth, GetVisibleCharWidth, PutCharInBitMap, PutStringInBitMap, ScreenXCoord, SetCursor, SlideRectangleHorizontally], Editor USING [cancelCode, ClearSourceSelection, insertDeletionCode, nextBracketStringCode, shiftedSelectionFlag], exD: FROM "ExceptionDefs" USING [ClearExceptionsRegion, confirmMessage, DisplayBothExceptionLines, DisplayException, DisplayExceptionLine, Exception, illegalCommand, pressToContinue], FrameDefs USING [IsBound], inD: FROM "InteractorDefs" USING [CharIndex, HousePtr, IdleLoop, KeyboardInputAcceptor, keyboardInputAcceptorPtr, maxBracketStringLength, MouseButton, realTimeClock, rightMargin, ScreenTracker, ScreenXCoord, StartBlinkingCaret, StopBlinkingCaret, TextSelection], Inline USING [BITAND, BITOR], intCommon USING [autoConfirm, cmTextNbr, commandMode, editorType, keystream, source], KeyDefs USING [Keys], ovD: FROM "OverviewDefs" USING [CharMask, LineBreakValue], Process USING [DisableTimeout], Storage USING [FreeString, String], StreamDefs USING [StreamHandle], String USING [AppendChar, AppendString, AppendSubString, EquivalentSubStrings, StringBoundsFault, SubString, SubStringDescriptor], vmD: FROM "VirtualMgrDefs" USING [CharIndex, GetMessageChar, GetMessageSize, VirtualMessagePtr]; IntBracketsCom: MONITOR IMPORTS AltoFile, Core, disC: displayCommon, dsD, Editor, exD, FrameDefs, inD, Inline, intC: intCommon, Process, Storage, String, vmD EXPORTS inD = BEGIN OPEN inD; -- Purpose: handles user interactions including the display, keyboard and -- mouse. This division gathers together commands and their arguments and is -- responsible for the display of all error messages. -- Global variables -- currentBracketsHouse: HousePtr _ NIL; currentBracketsX: ScreenXCoord; externalConfirmProc: PROCEDURE RETURNS [BOOLEAN] _ NIL; ConfirmBrackets: PUBLIC PROC [hp: HousePtr, acceptWhiteSpace: BOOLEAN _ FALSE, fileExtension: STRING _ NIL] RETURNS [confirmed: BOOLEAN] = -- Accepts keyboard input file name, sets hp.text to this file name, and displays -- it in its display position. Changes area of screen sensitive to mouse to -- reflect new brackets size. Returns Boolean value FALSE if brackets fill in -- is aborted, TRUE if completed. BEGIN aborted: BOOLEAN; dir: AltoFile.DirHandle _ NIL; dying: BOOLEAN _ FALSE; found: BOOLEAN _ FALSE; EnumProcess: PROCESS; EnumeratorCanRun: CONDITION; GetNextFileCanReturn: CONDITION; cacheEntry: Core.CacheEntry _ IF Core.localCacheHead = NIL THEN NIL ELSE Core.localCacheHead.firstEntry; getNextFileString: STRING; GetNextFile: ENTRY PROCEDURE [s: STRING] = BEGIN -- first cycle through the Alto Core file cache. UNTIL cacheEntry = NIL DO IF IsMatch[cacheEntry.name, s] THEN {cacheEntry _ cacheEntry.next; RETURN} ELSE cacheEntry _ cacheEntry.next; ENDLOOP; getNextFileString _ s; IF dir = NIL THEN BEGIN dir _ AltoFile.OpenDirectory[AltoFile.sysDirFP]; Process.DisableTimeout[@EnumeratorCanRun]; Process.DisableTimeout[@GetNextFileCanReturn]; EnumProcess _ FORK Enum; END ELSE NOTIFY EnumeratorCanRun; WAIT GetNextFileCanReturn; END; -- of GetNextFile -- Enum: PROCEDURE = BEGIN DO [] _ AltoFile.Enumerate[dir, CallBack]; IF dying THEN RETURN; IF ~found THEN StopGetNextFile[]; found _ FALSE; ENDLOOP; END; -- of Enum -- CallBack: ENTRY PROCEDURE [entry: AltoFile.DVPtr, name: STRING] RETURNS [BOOLEAN] = BEGIN IF dying THEN RETURN[TRUE]; IF entry.type # AltoFile.DEfile THEN RETURN[FALSE]; IF IsMatch[name, getNextFileString] THEN BEGIN found _ TRUE; NOTIFY GetNextFileCanReturn; WAIT EnumeratorCanRun; END; RETURN[dying]; END; -- of CallBack -- StopEnumerator: ENTRY PROCEDURE = BEGIN dying _ TRUE; NOTIFY EnumeratorCanRun; END; -- of StopEnumerator -- StopGetNextFile: ENTRY PROCEDURE = BEGIN NOTIFY GetNextFileCanReturn; WAIT EnumeratorCanRun; END; -- of StopGetNextFile -- IsMatch: PROCEDURE [file, s: STRING] RETURNS [BOOLEAN] = BEGIN ssd: String.SubStringDescriptor; IF file.length <= fileExtension.length THEN RETURN[FALSE]; ssd _ [file, file.length - fileExtension.length, fileExtension.length]; IF EquivPart[fileExtension, @ssd] THEN BEGIN ssd.length _ ssd.offset; ssd.offset _ 0; IF ~EquivPart[s, @ssd] THEN {s.length _ 0; String.AppendSubString[s, @ssd]; RETURN[TRUE]}; END; RETURN[FALSE]; END; -- of IsMatch -- EquivPart: PROCEDURE [s: STRING, part: String.SubString] RETURNS [BOOLEAN] = BEGIN ssd: String.SubStringDescriptor _ [s, 0, s.length]; RETURN[String.EquivalentSubStrings[@ssd, part]]; END; -- of EquivPart -- dsD.ChangeCursor[charArrow]; [aborted, hp.rightX] _ GetStringForBrackets [hp: hp, leftX: hp.leftX, rightX: hp.rightX, maxDeltaX: (IF hp.nextHouse = NIL OR hp.nextHouse.lineNumber # hp.lineNumber THEN inD.rightMargin ELSE hp.nextHouse.leftX) - hp.leftX, bracketFace: boldFace, displayChars: TRUE, initialDisplayString: hp.text, abortString: hp.text, outputString: hp.text, acceptWhiteSpace: acceptWhiteSpace, enumerate: IF fileExtension = NIL THEN NIL ELSE GetNextFile]; IF dir ~= NIL THEN BEGIN StopEnumerator[]; JOIN EnumProcess; AltoFile.CloseDirectory[dir]; END; dsD.ChangeCursor[hourGlass]; exD.ClearExceptionsRegion[]; RETURN[~aborted] END; -- of ConfirmBrackets -- Confirm: PUBLIC PROC [lineNumber: CARDINAL] RETURNS [confirmed: BOOLEAN] = -- Displays confirmation message on lineNumber of exception region, waits for -- confirmation input from user, displays exception if unexpected input -- received. BEGIN char: CHARACTER; keystream: StreamDefs.StreamHandle = intC.keystream; IF ~disC.bitMapReady THEN RETURN[FALSE]; IF intC.autoConfirm THEN RETURN[TRUE]; IF externalConfirmProc # NIL AND FrameDefs.IsBound[externalConfirmProc] THEN RETURN[externalConfirmProc[]]; SELECT (char _ ConfirmInner[lineNumber]) FROM Ascii.DEL, Editor.cancelCode, 'N, 'n => confirmed _ FALSE; Ascii.ESC, Ascii.SP, 'Y, 'y, Ascii.CR => confirmed _ TRUE; ENDCASE => BEGIN savedInputAcceptor: KeyboardInputAcceptor _ inD.keyboardInputAcceptorPtr^; ConfirmInputAcceptor: KeyboardInputAcceptor = {intC.keystream.putback[intC.keystream, char]}; confirmed _ FALSE; exD.DisplayBothExceptionLines[NIL, exD.illegalCommand, NIL, exD.pressToContinue]; keyboardInputAcceptorPtr^ _ ConfirmInputAcceptor; DO WHILE keystream.endof[keystream] DO IdleLoop[]; ENDLOOP; IF (char _ keystream.get[keystream]) = Ascii.DEL OR char = Editor.cancelCode THEN EXIT; ENDLOOP; keyboardInputAcceptorPtr^ _ savedInputAcceptor; END; exD.ClearExceptionsRegion[]; END; -- of Confirm -- ConfirmInner: PUBLIC PROC [lineNumber: CARDINAL] RETURNS [char: CHARACTER] = -- Displays confirmation message on lineNumber of exception region, waits for -- confirmation input from user, returns character typed by user. BEGIN cursorState: {black, white} _ white; cursorLastUpdated: CARDINAL; oldCursor: dsD.CursorShape _ dsD.GetCursor[].shape; keystream: StreamDefs.StreamHandle = intC.keystream; savedInputAcceptor: KeyboardInputAcceptor _ inD.keyboardInputAcceptorPtr^; ConfirmInputAcceptor: KeyboardInputAcceptor = {intC.keystream.putback[intC.keystream, char]}; HoldYellow: PROCEDURE RETURNS [char: CHARACTER] = BEGIN char _ Ascii.ESC; UNTIL MouseButton[middle, up] DO IdleLoop[]; IF ~keystream.endof[keystream] THEN char _ keystream.get[keystream]; IF MouseButton[left, down] OR MouseButton[right, down] THEN char _ IF intC.editorType = modeless THEN Editor.cancelCode ELSE Ascii.DEL; ENDLOOP; END; -- of HoldYellow -- keyboardInputAcceptorPtr^ _ ConfirmInputAcceptor; keystream.reset[keystream]; SELECT lineNumber FROM 0 => NULL; 1 => exD.DisplayException[exD.confirmMessage]; ENDCASE => exD.DisplayExceptionLine[exD.confirmMessage, lineNumber]; dsD.SetCursor[questionMark]; cursorLastUpdated _ realTimeClock^; DO SELECT TRUE FROM ~keystream.endof[keystream] => {char _ keystream.get[keystream]; EXIT}; MouseButton[middle, down] => {char _ HoldYellow[]; EXIT}; ENDCASE => BEGIN IdleLoop[]; IF LOOPHOLE[realTimeClock^ - cursorLastUpdated, CARDINAL] >= 9 THEN BEGIN IF cursorState = white THEN {cursorState _ black; dsD.SetCursor[invertQuestionMark]} ELSE {cursorState _ white; dsD.SetCursor[questionMark]}; cursorLastUpdated _ realTimeClock^; END; END; ENDLOOP; dsD.SetCursor[oldCursor]; keyboardInputAcceptorPtr^ _ savedInputAcceptor; END; -- of ConfirmInner -- AskUserToConfirm: PUBLIC PROCEDURE [exception: exD.Exception] RETURNS [confirmed: BOOLEAN] = -- Displays string corresponding to exception and the confirmation request -- message to user. Returns the user's answer. BEGIN exD.DisplayException[exception]; RETURN[Confirm[2]] END; -- of AskUserToConfirm -- GetStringForBrackets: PUBLIC PROCEDURE [hp: HousePtr, leftX, rightX: ScreenXCoord, maxDeltaX: CARDINAL, bracketFace: dsD.FaceType, displayChars: BOOLEAN, initialDisplayString, abortString, outputString: STRING, acceptWhiteSpace: BOOLEAN _ FALSE, enumerate: PROC [STRING] _ NIL] RETURNS [aborted: BOOLEAN, newRightX: ScreenXCoord] = -- Displays initialDisplayString in brackets. Accepts keyboard input and -- displays it appended to initialDisplayString. If abort (DEL or CANCEL), -- displays abortString in brackets and terminates. On termination (DEL or -- CANCEL or ESC (or DO)), puts the then displayed string in outputString. -- Returns the new right x position. BEGIN state: {fullString, dots}; s: STRING; limX, stringStartX, endOfDots: ScreenXCoord; keystream: StreamDefs.StreamHandle = intC.keystream; charWidth: CARDINAL; trailer: STRING _ " }"L; trailingWidth: CARDINAL = dsD.GetStringWidth[trailer, bracketFace]; i: CARDINAL; firstChar: BOOLEAN _ TRUE; savedInputAcceptor: KeyboardInputAcceptor _ inD.keyboardInputAcceptorPtr^; savedCommandMode: BOOLEAN _ intC.commandMode; FinishedWithBrackets: ERROR = CODE; BracketsInputAcceptor: KeyboardInputAcceptor = BEGIN TerminateBrackets: PROCEDURE [abort: BOOLEAN] = BEGIN IF (aborted _ abort) AND displayChars THEN PutStringInBrackets[abortString]; IF ~aborted OR outputString # abortString THEN BEGIN outputString.length _ 0; String.AppendString[outputString, IF aborted THEN abortString ELSE s]; END; ReplaceTrailerWithBracket[]; ERROR FinishedWithBrackets; END; AcceptNormalChar: PROCEDURE = BEGIN IF firstChar THEN MakeBracketsAndStringEmpty[]; String.AppendChar[s, char ! String.StringBoundsFault => GO TO Ignore]; IF displayChars THEN BEGIN charWidth _ dsD.GetVisibleCharWidth[char]; SELECT state FROM fullString => IF currentBracketsX + charWidth > limX THEN PutLongStringInBrackets[s] ELSE {SlideTrailer[charWidth]; PutCharInBitMap[char]}; dots => RefreshAfterDots[s]; ENDCASE; END; EXITS Ignore => NULL; END; -- of AcceptNormalChar -- StopBlinkingCaret[]; SELECT char FROM Editor.cancelCode, Ascii.DEL => TerminateBrackets[abort: TRUE]; Ascii.ControlW => BackWord[]; Ascii.ESC => TerminateBrackets[abort: FALSE]; Editor.nextBracketStringCode => BEGIN IF enumerate # NIL THEN {enumerate[s]; PutStringInBrackets[s]; firstChar _ TRUE}; SetBracketsCaretBlinking[]; RETURN; END; Ascii.CR, Ascii.SP, Ascii.TAB => IF acceptWhiteSpace THEN BEGIN IF char # Ascii.SP THEN char _ Inline.BITOR[char, ovD.LineBreakValue]; AcceptNormalChar[]; END ELSE TerminateBrackets[abort: FALSE]; Editor.shiftedSelectionFlag => BEGIN IF firstChar THEN MakeBracketsAndStringEmpty[]; InsertSourceSelection[]; END; Editor.insertDeletionCode => BEGIN IF firstChar THEN MakeBracketsAndStringEmpty[]; InsertLastDeletion[]; END; Ascii.BS, Ascii.ControlA => BackSpace[]; ENDCASE => AcceptNormalChar[]; firstChar _ FALSE; SetBracketsCaretBlinking[]; END; -- of BracketsInputAcceptor -- PutCharInBitMap: PROCEDURE [char: CHARACTER] = BEGIN currentBracketsX _ dsD.PutCharInBitMap[char, currentBracketsX, currentBracketsHouse.topY, plainFace]; END; -- of PutCharInBitMap -- PutStringInBitMap: PROCEDURE [s: STRING] = BEGIN FOR i: CARDINAL IN [0 .. s.length) DO PutCharInBitMap[s[i]]; ENDLOOP; END; -- of PutStringInBitMap -- GetVisibleStringWidth: PROCEDURE [s: STRING] RETURNS [width: CARDINAL] = BEGIN width _ 0; FOR i: CARDINAL IN [0 .. s.length) DO width _ width + dsD.GetVisibleCharWidth[s[i]]; ENDLOOP; END; -- of GetVisibleStringWidth -- SlideTrailer: PROCEDURE [amount: INTEGER] = INLINE BEGIN dsD.SlideRectangleHorizontally[currentBracketsX, currentBracketsX + trailingWidth, currentBracketsHouse.topY, currentBracketsHouse.bottomY, amount]; END; -- of SlideTrailer -- ReplaceTrailerWithBracket: PROCEDURE = BEGIN dsD.ClearRectangle[currentBracketsX, currentBracketsX + trailingWidth, currentBracketsHouse.topY, currentBracketsHouse.bottomY]; newRightX _ dsD.PutCharInBitMap['}, currentBracketsX, currentBracketsHouse.topY, bracketFace]; END; -- of ReplaceTrailerWithBracket -- MakeBracketsAndStringEmpty: PROCEDURE = BEGIN IF s.length > 0 THEN BEGIN s.length _ 0; SlideTrailer[stringStartX - currentBracketsX]; currentBracketsX _ stringStartX; state _ fullString; END; END; -- of MakeBracketsAndStringEmpty -- ResetBrackets: PROCEDURE = BEGIN dsD.ClearRectangle[leftX, currentBracketsX + trailingWidth, currentBracketsHouse.topY, currentBracketsHouse.bottomY]; currentBracketsX _ dsD.PutCharInBitMap ['{, leftX, currentBracketsHouse.topY, bracketFace]; END; -- of ResetBrackets -- RefreshAfterDots: PROCEDURE[s: STRING] = BEGIN x: ScreenXCoord _ endOfDots; FOR i _ s.length-1, i-1 DO IF (x _ dsD.GetVisibleCharWidth[s[i]] + x) > limX THEN EXIT; ENDLOOP; dsD.ClearRectangle[endOfDots, currentBracketsX + trailingWidth, currentBracketsHouse.topY, currentBracketsHouse.bottomY]; currentBracketsX _ endOfDots; FOR i IN [i + 1 .. s.length) DO PutCharInBitMap[s[i]]; ENDLOOP; [] _ dsD.PutStringInBitMap[currentBracketsX, currentBracketsHouse.topY, trailer, bracketFace]; END; -- of RefreshAfterDots -- PutLongStringInBrackets: PROCEDURE [s: STRING] = BEGIN ResetBrackets[]; FOR i IN [0..5] DO PutCharInBitMap[s[i]]; ENDLOOP; PutStringInBitMap["..."L]; endOfDots _ currentBracketsX; state _ dots; RefreshAfterDots[s]; END; -- of PutLongStringInBrackets -- PutShortStringInBrackets: PROCEDURE [s: STRING] = INLINE BEGIN ResetBrackets[]; PutStringInBitMap[s]; [] _ dsD.PutStringInBitMap[currentBracketsX, currentBracketsHouse.topY, trailer, bracketFace]; state _ fullString; END; -- of PutShortStringInBrackets -- PutStringInBrackets: PROCEDURE [s: STRING] = BEGIN IF stringStartX + GetVisibleStringWidth[s] > limX THEN PutLongStringInBrackets[s] ELSE PutShortStringInBrackets[s]; END; -- of PutStringInBrackets -- BackSpace: PROCEDURE = BEGIN IF s.length > 0 THEN BEGIN IF intC.editorType = modal OR (KeyDefs.Keys.FL4 = up AND KeyDefs.Keys.FR5 = up AND KeyDefs.Keys.Spare3 = up) THEN BEGIN -- just a backspace. char: CHARACTER _ s[s.length _ s.length - 1]; IF displayChars THEN BEGIN charWidth _ dsD.GetVisibleCharWidth[char]; SELECT state FROM fullString => BEGIN SlideTrailer[-charWidth]; currentBracketsX _ currentBracketsX - charWidth; END; dots => IF stringStartX + GetVisibleStringWidth[s] <= limX THEN BEGIN ResetBrackets[]; PutStringInBitMap[s]; [] _ dsD.PutStringInBitMap[currentBracketsX, currentBracketsHouse.topY, trailer, bracketFace]; state _ fullString; END ELSE RefreshAfterDots[s]; ENDCASE; END; END ELSE BackWord[]; -- modeless backword. END; END; -- of BackSpace -- BackWord: PROCEDURE = BEGIN -- First, back up over punctuation characters. UNTIL s.length = 0 DO SELECT disC.charPropertyTable[s[s.length - 1]] FROM punctuation, white => s.length _ s.length - 1; ENDCASE => EXIT; ENDLOOP; -- Then, back up over non-punctuation characters. UNTIL s.length = 0 DO SELECT disC.charPropertyTable[s[s.length - 1]] FROM punctuation, white => EXIT; ENDCASE => s.length _ s.length - 1; ENDLOOP; PutStringInBrackets[s]; END; -- of BackWord -- InsertSourceSelection: PROCEDURE = INLINE BEGIN selection: TextSelection _ intC.source; InsertFromMessage[selection.start, selection.end, selection.mnp.message]; Editor.ClearSourceSelection[]; END; -- of InsertSourceSelection -- InsertLastDeletion: PROCEDURE = INLINE BEGIN message: vmD.VirtualMessagePtr = intC.cmTextNbr.deletionBuffer; InsertFromMessage[0, vmD.GetMessageSize[message], message]; END; -- of InsertLastDeletion -- InsertFromMessage: PROCEDURE [start, end: CharIndex, message: vmD.VirtualMessagePtr] = BEGIN width: CARDINAL; string: STRING _ [maxBracketStringLength]; char: CHARACTER; end _ MIN[end, start + s.maxlength - s.length]; FOR i: CharIndex IN [start .. end) DO SELECT (char _ Inline.BITAND[vmD.GetMessageChar[message, i], ovD.CharMask]) FROM Ascii.CR, Ascii.SP, Ascii.TAB => IF acceptWhiteSpace THEN BEGIN IF char # Ascii.SP THEN char _ Inline.BITOR[char, ovD.LineBreakValue]; String.AppendChar[string, char]; END ELSE {keystream.putback[keystream, Ascii.ESC]; EXIT}; ENDCASE => String.AppendChar[string, char]; ENDLOOP; String.AppendString[s, string]; width _ GetVisibleStringWidth[string]; IF displayChars THEN SELECT state FROM fullString => IF currentBracketsX + width > limX THEN PutLongStringInBrackets[s] ELSE {SlideTrailer[width]; PutStringInBitMap[string]}; dots => RefreshAfterDots[s]; ENDCASE; END; -- of InsertFromMessage -- currentBracketsHouse _ hp; s _ Storage.String[outputString.maxlength]; String.AppendString[s, initialDisplayString]; limX _ leftX + maxDeltaX - trailingWidth; currentBracketsX _ rightX - trailingWidth; -- rightX may not equal leftX+maxDeltaX stringStartX _ dsD.GetStringWidth["{"L, bracketFace] + leftX; PutStringInBrackets[s]; keyboardInputAcceptorPtr^ _ BracketsInputAcceptor; intC.commandMode _ FALSE; SetBracketsCaretBlinking[]; ScreenTracker[brackets ! FinishedWithBrackets => CONTINUE]; currentBracketsHouse _ NIL; Storage.FreeString[s]; keyboardInputAcceptorPtr^ _ savedInputAcceptor; intC.commandMode _ savedCommandMode; END; -- of GetStringForBrackets -- SetBracketsCaretBlinking: PUBLIC PROCEDURE = -- Like StartBlinkingCaret, but works with the current caret in brackets. BEGIN IF currentBracketsHouse = NIL THEN ERROR; StartBlinkingCaret[currentBracketsX, (currentBracketsHouse.topY + currentBracketsHouse.bottomY) / 2]; END; -- of SetBracketsCaretBlinking -- SetExternalConfirmProc: PUBLIC PROCEDURE [proc: PROCEDURE RETURNS [BOOLEAN] ] = -- Allows a loaded program to redirect confirmation input and output. To cancel, call this -- procedure with argument NIL. BEGIN externalConfirmProc _ proc; END; -- of SetExternalConfirmProc -- END. -- of IntBracketsCom --z20461(529)\f1