-- file: IntEditCom.Mesa -- edited by Horning, April 26, 1978 11:07 AM -- edited by Brotz, November 25, 1981 4:49 PM -- edited by Levin, July 9, 1980 1:23 PM -- edited by Taft, May 21, 1983 3:23 PM DIRECTORY Editor USING [RefreshSoThatFirstCharStartsLine, ResetInsertionBuffer, SwapMessageWithDeletionBuffer], exD: FROM "ExceptionDefs" USING [cantForward, DisplayException, noUndeletedEntries, totalMessageLengthTooBig, willReplaceMessage], inD: FROM "InteractorDefs" USING [AskUserToConfirm, CharIndex, House, HousePtr, MessageTextNbrPtr, TextHouseRefresher, TextSelection], intCommon USING [actionPoint, cForCopies, cmTextNbr, commandType, composedMessageEdited, deliverCommandHouse, deliverCommandVisible, editorType, newTargetSelection, pendingDeleteSetByControl, runCommandMode, source, target, tocTextNbr, user], lmD: FROM "LaurelMenuDefs" USING [HouseNumber], lsD: FROM "LaurelStateDefs" USING [ReleaseStateSegment, StateSegment, StateSegmentAddress, SwapInStateSegment, WriteStateSegment], prD: FROM "ProtectionDefs" USING [UnprotectAllFields], String USING [EquivalentString, WordsForString], tsD: FROM "TocSelectionDefs" USING [FirstSelectedAndUndeletedEntry, NextSelectedAndUndeletedEntry, TOCSelectionEmpty], vmD: FROM "VirtualMgrDefs" USING [AllocateDisplayMessageObject, CharIndex, ComposedMessage, ComposedMessagePtr, DisplayMessagePtr, FlushDisplayMessage, FreeVirtualMessageObject, GetMessageSize, InitComposedMessage, InsertRangeInMessage, InsertSubstringInMessage, LoadDisplayMessage, StartMessageInsertion, StopMessageInsertion, TOCHandle, TOCIndex, UnlockTOC, WaitForLock]; IntEditCom: PROGRAM IMPORTS Editor, exD, inD, intC: intCommon, lsD, prD, String, tsD, vmD EXPORTS inD, lmD = BEGIN OPEN inD, Editor; -- 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. -- Commands Section of the Editor Department -- Establishes the command structure of the editor. Handles keyboard and mouse input; -- interprets them. Establishes selections. -- 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). NewFormCommand: PUBLIC PROCEDURE [hp: HousePtr, confirmed: BOOLEAN] = -- Clears old composed message and initializes a new one to the standard composed message -- template. Refreshes display of the composed message. BEGIN toc: vmD.TOCHandle = intC.tocTextNbr.toc; key: CARDINAL _ 0; InitializeCM[hp, confirmed, newForm, NIL, 0]; END; -- of NewFormCommand -- ForwardCommand: PUBLIC PROCEDURE [hp: HousePtr, confirmed: BOOLEAN] = -- Clears old composed message and initializes a new one to the standard template for -- forwarded messages, followed by the entire displayed message (surrounded by dashed -- lines). Refreshes display of the composed message. BEGIN toc: vmD.TOCHandle = intC.tocTextNbr.toc; key: CARDINAL _ vmD.WaitForLock[toc]; IF tsD.TOCSelectionEmpty[toc, key] THEN {exD.DisplayException[exD.cantForward]; vmD.UnlockTOC[toc, key]; RETURN}; IF tsD.FirstSelectedAndUndeletedEntry[toc, key] = 0 THEN {exD.DisplayException[exD.noUndeletedEntries]; vmD.UnlockTOC[toc, key]; RETURN}; InitializeCM[hp, confirmed, forward, toc, key]; vmD.UnlockTOC[toc, key]; END; -- of ForwardCommand -- InitializeCM: PROC [hp: HousePtr, confirmed: BOOLEAN, kind: {newForm, forward}, toc: vmD.TOCHandle, key: CARDINAL] = BEGIN mnp: MessageTextNbrPtr = intC.cmTextNbr; oldMessageLength: CharIndex _ vmD.GetMessageSize[mnp.message]; composedMessage: vmD.ComposedMessagePtr; filler: STRING; newFormString: STRING = "Subject: Topic To: Recipients cc: CopiesTo, Message "L; forwardString: STRING = "Subject: Topic To: Recipients cc: CopiesTo CoveringMessage "L; separator: STRING = " --------------------------- "L; trailer: STRING = "------------------------------------------------------------ "L; IF ~confirmed AND intC.composedMessageEdited AND vmD.GetMessageSize[mnp.message] # 0 AND ~AskUserToConfirm[exD.willReplaceMessage] THEN RETURN; SwapMessageWithDeletionBuffer[mnp]; ResetInsertionBuffer[mnp]; composedMessage _ vmD.ComposedMessage[mnp.message]; IF intC.cForCopies THEN BEGIN newFormString[35] _ ':; newFormString[36] _ ' ; forwardString[35] _ ':; forwardString[36] _ ' ; END; IF kind = newForm THEN BEGIN vmD.InitComposedMessage[composedMessage, newFormString]; vmD.StartMessageInsertion[composedMessage, 50]; filler _ intC.user.name; END ELSE IF kind = forward THEN BEGIN vm: vmD.DisplayMessagePtr _ vmD.AllocateDisplayMessageObject[]; index: vmD.TOCIndex; vmSize, cmSize: CharIndex; limit: CharIndex = 62000; vmD.InitComposedMessage[composedMessage, forwardString]; FOR index _ tsD.FirstSelectedAndUndeletedEntry[toc, key], tsD.NextSelectedAndUndeletedEntry[toc, key, index] UNTIL index = 0 DO vmD.LoadDisplayMessage[toc, key, index, vm]; IF (vmSize _ vmD.GetMessageSize[vm]) + separator.length + trailer.length > (limit - (cmSize _ vmD.GetMessageSize[composedMessage])) THEN BEGIN exD.DisplayException[exD.totalMessageLengthTooBig]; vmD.FlushDisplayMessage[vm, key]; EXIT; END; vmD.StartMessageInsertion[composedMessage, cmSize]; [] _ vmD.InsertSubstringInMessage[composedMessage, separator, 0, separator.length]; vmD.StopMessageInsertion[composedMessage]; vmD.InsertRangeInMessage [cmSize + separator.length, composedMessage, [0, vmSize, vm]]; vmD.FlushDisplayMessage[vm, key]; ENDLOOP; vmD.FreeVirtualMessageObject[vm]; vmD.StartMessageInsertion[composedMessage, vmD.GetMessageSize[composedMessage]]; filler _ trailer; END; [] _ vmD.InsertSubstringInMessage[composedMessage, filler, 0, filler.length]; vmD.StopMessageInsertion[composedMessage]; intC.commandType _ get; intC.source _ TextSelection [mnp: mnp, start: 0, end: 0, point: 0, key: 0, mode: char, pendingDelete: FALSE]; intC.target _ TextSelection[mnp: mnp, start: 9, end: 16, point: 9, key: 0, mode: word, pendingDelete: intC.editorType = modeless]; intC.newTargetSelection _ TRUE; intC.actionPoint _ 0; intC.pendingDeleteSetByControl _ FALSE; IF mnp.protectedFieldPtr # NIL THEN prD.UnprotectAllFields[@mnp.protectedFieldPtr]; composedMessage.formatStart _ composedMessage.formatEnd _ 0; RefreshSoThatFirstCharStartsLine[firstChar: 0, firstLine: mnp.lines, mnp: mnp]; mnp.haveMessage _ TRUE; intC.runCommandMode _ FALSE; intC.composedMessageEdited _ FALSE; intC.deliverCommandHouse.text.length _ 0; intC.deliverCommandHouse.typeface _ italicFace; intC.deliverCommandHouse.callable _ FALSE; IF intC.deliverCommandVisible THEN TextHouseRefresher[intC.deliverCommandHouse]; END; -- of InitializeCM -- SwapInMenu: PUBLIC PROCEDURE [menuSegment: lsD.StateSegment] RETURNS [hp: HousePtr] = -- Swaps in the menu contained in menuSegment and locks it in memory. Sets all nextHouse -- pointers in the house list swapped in to be true pointers to the next House in the list. -- Returns a pointer to the head of the list. BEGIN h, nextHouse: HousePtr; h _ hp _ lsD.SwapInStateSegment[menuSegment]; DO h.text _ LOOPHOLE[h + SIZE[House], STRING]; nextHouse _ h + SIZE[House] + String.WordsForString[h.text.maxlength]; IF h.nextHouse = LOOPHOLE[0] THEN {h.nextHouse _ NIL; RETURN} ELSE h _ h.nextHouse _ nextHouse; ENDLOOP; END; -- of SwapInMenu -- ReleaseMenu: PUBLIC PROCEDURE [menuSegment: lsD.StateSegment] = -- Resets all pointers in the in the menuSegment to their canonical swapped out form: -- all nextHouse fields are set to 1 except for the last which is set to 0. Releases the -- menuSegment. BEGIN h, nextHouse: HousePtr; h _ lsD.StateSegmentAddress[menuSegment]; DO nextHouse _ h.nextHouse; IF nextHouse = NIL THEN {h.nextHouse _ LOOPHOLE[0]; EXIT} ELSE {h.nextHouse _ LOOPHOLE[1]; h _ nextHouse}; ENDLOOP; lsD.WriteStateSegment[menuSegment]; lsD.ReleaseStateSegment[menuSegment]; END; -- of ReleaseMenu -- MapHouseNumberToHousePtr: PUBLIC PROCEDURE [knownHp: HousePtr, knownHpNumber, number: lmD.HouseNumber] RETURNS [hp: HousePtr] = -- Returns a pointer to the number'th house (first cnp.houses is number 0) in the house list -- pointed to by knownHp. KnownHp's HouseNumber is knownHpNumber. This procedure -- should be used to set HousePtr's for houses that are relocated in segments. BEGIN hp _ knownHp; THROUGH [1 .. number - knownHpNumber] DO hp _ hp.nextHouse; ENDLOOP; END; -- of MapHouseNumberToHousePtr -- MapHouseTextToHousePtr: PUBLIC PROCEDURE [knownHp: HousePtr, s: STRING] RETURNS [hp: HousePtr] = -- Returns a pointer to the house in the house list started by knownHp whose text field -- matches "s". To obtain the HousePtr for a brackets house, use -- MapHouseTextToHousePtr[hp, textOfCommandHouse].nextHouse. BEGIN FOR hp _ knownHp, hp.nextHouse UNTIL hp = NIL OR String.EquivalentString[hp.text, s] DO ENDLOOP; END; -- of MapHouseTextToHousePtr -- END. -- of IntEditCom --z20461(529)\f1 3925v68V25v73V22v33V21v65V