-- file: EditorTypein.Mesa -- last edited by Horning, February 16, 1978 3:24 PM -- last edited by Brotz, October 1, 1982 4:43 PM -- last edited by Spitzen, May 16, 1978 2:57 PM -- last edited by Korb, November 7, 1979 9:57 AM. Modeless editor changes. -- last edited by Taft, May 6, 1983 5:37 PM DIRECTORY Ascii USING [BS, ControlA, ControlW, DEL, ESC], dsD: FROM "DisplayDefs" USING [GetCharBreakProp], Editor USING [cancelCode, CommandType, Deleter, DeUnderlineSelection, insertDeletionCode, MakeCharIndexVisible, nextCode, RefreshFromFirstChange, ResetBuffers, ResetInsertionBuffer, ShiftKey], inD: FROM "InteractorDefs" USING [CharIndex, MessageTextNbrPtr, TextSelection, TextSelectionPtr], Inline USING [BITAND], intCommon USING [actionPoint, commandType, editorType, keystream, newTargetSelection, target], ovD: FROM "OverviewDefs" USING [CharMask], prD: FROM "ProtectionDefs" USING [FindUnprotectedSubrange], StreamDefs USING [StreamHandle], vmD: FROM "VirtualMgrDefs" USING [AppendMessageChar, CharIndex, ComposedMessage, ComposedMessagePtr, DeleteRangeInMessage, GetMessageChar, GetMessageSize, InsertMessageChar, MessageRange, StartMessageInsertion, StopMessageInsertion, UnAppendMessageChar]; EditorTypein: PROGRAM IMPORTS dsD, Editor, Inline, intC: intCommon, prD, vmD EXPORTS Editor = BEGIN OPEN Editor, inD; -- Editor Department of the Interactor Division -- Implements the editor for the composed message. Commands are: Insert, Append, Replace, -- Delete, Undo, Redo. Other operations (which are not commands per se) are selection, -- scrolling, and command aborting. -- Selection convention: a range is represented by a nonempty half open interval; a point is -- represented by an empty half open interval; selection beyond the message end is -- represented by the point [messageLength .. messageLength). AcceptTypeIn: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr, char: CHARACTER] = -- Insert text at target.point. BEGIN -- Long set of locals to AcceptTypeIn: InsertChar: PROCEDURE = -- Globals: char -- char is inserted in mnp.message and mnp.scratchBuffer and displayed on screen. Screen -- is reformatted as necessary. BEGIN insertionCount: CARDINAL _ 1; vmD.StartMessageInsertion[composedMessage, target.point]; DO vmD.InsertMessageChar[composedMessage, char]; vmD.AppendMessageChar[mnp.insertionBuffer, char]; IF ~keystream.endof[keystream] THEN char _ keystream.get[keystream] ELSE EXIT; SELECT char FROM Ascii.ESC, Ascii.DEL, Ascii.BS, Ascii.ControlA, Ascii.ControlW => {keystream.putback[keystream, char]; EXIT}; cancelCode, insertDeletionCode, nextCode => IF modalEditor THEN insertionCount _ insertionCount + 1 ELSE {keystream.putback[keystream, char]; EXIT}; ENDCASE => insertionCount _ insertionCount + 1; ENDLOOP; vmD.StopMessageInsertion[composedMessage]; RefreshFromFirstChange[target.point, 0, insertionCount, mnp]; target.point _ target.point + insertionCount; SELECT commandType^ FROM delete => commandType^ _ replace; insert, replace => NULL; ENDCASE => commandType^ _ insert; END; -- of InsertChar -- BackSpaceWord: PROCEDURE = -- Backspaces over one word. BEGIN LoopOverChars: PROCEDURE [isAlphaNumeric: BOOLEAN] = BEGIN mChar: CHARACTER; UNTIL target.point = terminus DO mChar _ vmD.GetMessageChar[composedMessage, target.point - 1]; IF (dsD.GetCharBreakProp[Inline.BITAND[mChar, ovD.CharMask]] = alphaNumeric) = isAlphaNumeric THEN RETURN; BackSpaceChar[]; nChars _ nChars + 1; ENDLOOP; END; -- of LoopOverChars -- nChars: CARDINAL _ 0; terminus: CharIndex _ FindBackSpaceTerminus[]; -- First, back up over white space characters. LoopOverChars[TRUE]; -- Then, back up over non-white space characters. LoopOverChars[FALSE]; RefreshFromFirstChange[target.point, nChars, 0, mnp]; END; -- of BackSpaceWord -- BackSpaceChar: PROCEDURE = -- Perform all actions required by backspace except for screen refresh. BEGIN char: CHARACTER; insertionSize: CARDINAL = vmD.GetMessageSize[mnp.insertionBuffer]; IF insertionSize = 0 THEN BEGIN commandType^ _ delete; char _ vmD.GetMessageChar[mnp.message, target.point - 1]; vmD.StartMessageInsertion[mnp.deletionBuffer, 0]; vmD.InsertMessageChar[mnp.deletionBuffer, char]; vmD.StopMessageInsertion[mnp.deletionBuffer]; END ELSE BEGIN vmD.UnAppendMessageChar[mnp.insertionBuffer]; IF insertionSize = 1 THEN commandType^ _ IF vmD.GetMessageSize[mnp.deletionBuffer] = 0 THEN noCommand ELSE delete; END; vmD.DeleteRangeInMessage [from: vmD.MessageRange[target.point - 1, target.point, composedMessage]]; target.point _ target.point - 1; actionPoint^ _ MIN[actionPoint^, target.point]; END; -- of BackSpaceChar -- BackSpaceCharAndRefresh: PROCEDURE = BEGIN IF target.point = FindBackSpaceTerminus[] THEN RETURN; BackSpaceChar[]; RefreshFromFirstChange[target.point, 1, 0, mnp]; END; -- of BackSpaceChar -- ForwardSpaceWord: PROCEDURE = -- Forwardspaces over one word. BEGIN LoopOverChars: PROCEDURE [isAlphaNumeric: BOOLEAN] = BEGIN mChar: CHARACTER; UNTIL target.point+nChars >= terminus DO mChar _ vmD.GetMessageChar[composedMessage, target.point]; IF (dsD.GetCharBreakProp[Inline.BITAND[mChar, ovD.CharMask]] = alphaNumeric) = isAlphaNumeric THEN RETURN; ForwardSpaceChar[]; nChars _ nChars + 1; ENDLOOP; END; -- of LoopOverChars -- nChars: CARDINAL _ 0; terminus: CharIndex _ FindForwardSpaceTerminus[]; -- First, forward space over white space characters. LoopOverChars[TRUE]; -- Then, forward space over non-white space characters. LoopOverChars[FALSE]; RefreshFromFirstChange[target.point, nChars, 0, mnp]; END; -- of ForwardSpaceWord -- ForwardSpaceChar: PROCEDURE = -- Perform all actions required by forwardspace except for screen refresh. BEGIN insertionSize: CARDINAL = vmD.GetMessageSize[mnp.insertionBuffer]; IF insertionSize = 0 THEN commandType^ _ delete; vmD.AppendMessageChar [mnp.deletionBuffer, vmD.GetMessageChar[mnp.message, target.point]]; vmD.DeleteRangeInMessage [from: vmD.MessageRange[target.point, target.point + 1, composedMessage]]; END; -- of ForwardSpaceChar -- ForwardSpaceCharAndRefresh: PROCEDURE = BEGIN IF target.point >= FindForwardSpaceTerminus[] THEN RETURN; ForwardSpaceChar[]; RefreshFromFirstChange[target.point, 1, 0, mnp]; END; -- of ForwardSpaceChar -- FindBackSpaceTerminus: PROCEDURE RETURNS [ci: CharIndex] = BEGIN range: vmD.MessageRange; ci _ IF modalEditor THEN actionPoint^ ELSE 0; IF mnp.protectedFieldPtr = NIL THEN RETURN; range _ [ci, target.point, composedMessage]; prD.FindUnprotectedSubrange[pfp: mnp.protectedFieldPtr, rangePtr: @range, fixStart:FALSE]; RETURN[range.start]; END; -- of FindBackSpaceTerminus -- FindForwardSpaceTerminus: PROCEDURE RETURNS [ci: CharIndex] = BEGIN range: vmD.MessageRange; ci _ vmD.GetMessageSize[composedMessage]; IF mnp.protectedFieldPtr = NIL THEN RETURN; range _ [target.point, ci, composedMessage]; prD.FindUnprotectedSubrange[pfp: mnp.protectedFieldPtr, rangePtr: @range, fixStart: TRUE]; RETURN[range.end]; END; -- of FindForwardSpaceTerminus -- -- End of procedures local to AcceptTypeIn & start of its main code. -- Initialization. target: TextSelectionPtr _ @intC.target; actionPoint: POINTER TO CharIndex _ @intC.actionPoint; commandType: POINTER TO CommandType _ @intC.commandType; topCharIndex: CharIndex _ mnp.lines.firstCharIndex; composedMessage: vmD.ComposedMessagePtr = vmD.ComposedMessage[mnp.message]; modalEditor: BOOLEAN _ (intC.editorType = modal); keystream: StreamDefs.StreamHandle = intC.keystream; PrepareForTypeIn[mnp]; [] _ MakeCharIndexVisible[target.point, mnp]; DO -- read char and dispatch SELECT char FROM Ascii.ESC, Ascii.DEL => EXIT; Ascii.ControlW => IF ~modalEditor AND ShiftKey[down] THEN ForwardSpaceWord[] ELSE BackSpaceWord[]; Ascii.BS, Ascii.ControlA => IF ~modalEditor AND ShiftKey[down] THEN ForwardSpaceCharAndRefresh[] ELSE BackSpaceCharAndRefresh[]; cancelCode, insertDeletionCode, nextCode => IF modalEditor THEN InsertChar[] ELSE EXIT; ENDCASE => InsertChar[]; target.start _ target.end _ target.point; [] _ MakeCharIndexVisible[target.point, mnp]; IF keystream.endof[keystream] THEN RETURN; char _ keystream.get[keystream]; ENDLOOP; -- read char and dispatch keystream.putback[keystream, char]; END; -- of AcceptTypeIn -- PrepareForTypeIn: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] = -- Resets primary selection and handles pending delete properly. BEGIN target: TextSelectionPtr _ @intC.target; IF intC.newTargetSelection THEN BEGIN -- We are beginning a new typein sequence. intC.newTargetSelection _ FALSE; IF target.pendingDelete THEN {Deleter[mnp]; ResetInsertionBuffer[mnp]} ELSE BEGIN ResetBuffers[mnp]; DeUnderlineSelection[target, target]; target^ _ TextSelection [mnp, (intC.actionPoint _ target.point), target.point, target.point, 0, char, FALSE]; END; END; END; -- of PrepareForTypeIn -- END. -- of EditorTypein --z20638(529)