-- file: IntEditCom.Mesa -- edited by Horning, April 26, 1978 11:07 AM -- edited by Brotz, April 8, 1981 11:40 AM -- edited by Levin, July 9, 1980 1:23 PM DIRECTORY Editor, exD: FROM "ExceptionDefs", inD: FROM "InteractorDefs", intCommon: FROM "IntCommon", lmD: FROM "LaurelMenuDefs", lsD: FROM "LaurelStateDefs", ovD: FROM "OverviewDefs", prD: FROM "ProtectionDefs", String, tsD: FROM "TocSelectionDefs", vmD: FROM "VirtualMgrDefs"; IntEditCom: PROGRAM IMPORTS Editor, exD, inD, intC: intCommon, lsD, prD, String, tsD, vmD EXPORTS inD, lmD = PUBLIC 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: 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 InitializeCM[hp, confirmed, newForm]; END; -- of NewFormCommand -- ForwardCommand: 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 fixedPart: vmD.TOCFixedPart; i: vmD.TOCIndex; IF tsD.TOCSelectionEmpty[] THEN {exD.DisplayException[exD.cantForward]; RETURN}; -- Check that there is at least one message to print. FOR i _ tsD.FirstSelectedEntry[], tsD.NextSelectedEntry[i] UNTIL i = 0 DO vmD.GetTOCFixedPart[i, @fixedPart]; IF ~fixedPart.deleted THEN EXIT; REPEAT FINISHED => {exD.DisplayException[exD.noUndeletedEntries]; RETURN}; ENDLOOP; InitializeCM[hp, confirmed, forward]; END; -- of ForwardCommand -- InitializeCM: PROCEDURE [hp: HousePtr, confirmed: BOOLEAN, kind: {newForm, forward}] = BEGIN mnp: MessageTextNbrPtr = intC.cmTextNbr; oldMessageLength: ovD.CharIndex _ vmD.GetMessageSize[mnp.message]; composeMessage: vmD.ComposeMessagePtr; 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]; composeMessage _ vmD.MapVirtualToComposeMessage[mnp.message]; IF intC.cForCopies THEN BEGIN newFormString[35] _ ':; newFormString[36] _ ' ; forwardString[35] _ ':; forwardString[36] _ ' ; END; IF kind = newForm THEN BEGIN vmD.InitComposeMessage[composeMessage, newFormString]; vmD.StartMessageInsertion[composeMessage, 50]; filler _ intC.user.name; END ELSE IF kind = forward THEN BEGIN fp: vmD.TOCFixedPart; vm: vmD.DisplayMessagePtr _ vmD.AllocateDisplayMessageObject[]; index: vmD.TOCIndex; vmSize, cmSize: ovD.CharIndex; limit: ovD.CharIndex = 62000; vmD.InitComposeMessage[composeMessage, forwardString]; FOR index _ tsD.FirstSelectedEntry[], tsD.NextSelectedEntry[index] UNTIL index = 0 DO vmD.GetTOCFixedPart[index, @fp]; IF fp.deleted THEN LOOP; IF vmD.VirtualizeMessage[index, vm] # ovD.ok OR (vmSize _ vmD.GetMessageSize[vm]) + separator.length + trailer.length > (limit - (cmSize _ vmD.GetMessageSize[composeMessage])) THEN {exD.DisplayException[exD.totalMessageLengthTooBig]; EXIT}; vmD.StartMessageInsertion[composeMessage, cmSize]; [] _ vmD.InsertSubstringInMessage[composeMessage, separator, 0, separator.length]; vmD.StopMessageInsertion[composeMessage]; InsertRangeInMess[cmSize + separator.length, composeMessage, [0, vmSize, vm]]; ENDLOOP; vmD.FreeVirtualMessageObject[vm]; vmD.StartMessageInsertion[composeMessage, vmD.GetMessageSize[composeMessage]]; filler _ trailer; END; [] _ vmD.InsertSubstringInMessage[composeMessage, filler, 0, filler.length]; vmD.StopMessageInsertion[composeMessage]; intC.commandType _ get; intC.source _ TextSelection [mnp: mnp, start: 0, end: 0, point: 0, mode: char, pendingDelete: FALSE]; intC.target _ TextSelection [mnp: mnp, start: 9, end: 16, point: 9, mode: word, pendingDelete: intC.editorType = modeless]; intC.newTargetSelection _ TRUE; intC.actionPoint _ 0; intC.pendingDeleteSetByControl _ FALSE; IF mnp.protectedFieldPtr # NIL THEN prD.UnprotectAllFields[@mnp.protectedFieldPtr]; SetHighWaterMark[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; TextHouseRefresher[intC.deliverCommandHouse]; END; -- of InitializeCM -- SwapInMenu: 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: 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: 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 -- InsertRangeInMess: PROCEDURE [targetIndex: ovD.CharIndex, targetMessage: vmD.ComposeMessagePtr, from: vmD.MessageRange] = -- ### Temporary KLUDGE to keep from losing virtual manager error messages. BEGIN errorC: ovD.ErrorCode _ vmD.InsertRangeInMessage[targetIndex, targetMessage, from]; IF errorC # ovD.ok THEN exD.SysBug[exD.insertionOverflow] END; InsertMessChar: PROCEDURE [cM: vmD.ComposeMessagePtr, char: CHARACTER] = -- ### Temporary KLUDGE to keep from losing virtual manager error messages. BEGIN errorC: ovD.ErrorCode _ vmD.InsertMessageChar[cM, char]; IF errorC # ovD.ok THEN exD.SysBug[exD.insertionOverflow] END; END. -- of IntEditCom --z20461(529)\f1 2650v68V25v73V22v33V21v65V