-- TEditEditingClassImpl.mesa Edited by McGregor on 14-Sep-81 11:06:19 DIRECTORY TextEdit USING [FetchChar, Offset, RefTextNode, Size], TextNode USING [FirstChild, LastChild, Location, NarrowToTextNode], TEditDocument USING [TEditDocumentData], TEditEditingClass, TEditInputOps USING [Delete, InsertChar], TEditSelection USING [MakeSelection, pSel, tSel], ViewerOps USING [PaintViewer], ViewerClasses USING [Viewer]; TEditEditingClassImpl: PROGRAM IMPORTS TextEdit, TextNode, TEditInputOps, TEditSelection, ViewerOps EXPORTS TEditEditingClass SHARES TEditEditingClass = BEGIN OPEN TEditEditingClass; Insert: PUBLIC PROC [self: ViewerClasses.Viewer, char: CHARACTER ← 0C, insertion: REF ANY, adr: DocAdr ← NIL, repaint: BOOLEAN ← TRUE] = BEGIN OPEN TEditSelection; IF pSel.viewer#self OR pSel.start.pos#adr↑ OR pSel.insertion#before OR pSel.granularity#point THEN BEGIN tSel.viewer ← self; tSel.insertion ← before; tSel.granularity ← point; tSel.start.pos ← tSel.end.pos ← adr↑; MakeSelection[primary, tSel]; -- finalised so that metrics are valid END; IF insertion # NIL THEN FOR lst: LIST OF CHARACTER ← NARROW[insertion], lst.rest UNTIL lst = NIL DO TEditInputOps.InsertChar[lst.first]; adr.where ← adr.where+1; ENDLOOP ELSE BEGIN TEditInputOps.InsertChar[char]; adr.where ← adr.where+1; END; IF repaint THEN ViewerOps.PaintViewer[self]; END; Get: PUBLIC PROC [self: ViewerClasses.Viewer, from, to: DocAdr ← NIL, advanceAdr: BOOLEAN ← TRUE] RETURNS [REF ANY]= BEGIN lst: LIST OF CHARACTER ← NIL; IF to.node#from.node THEN ERROR; -- not solving multi-node reads yet FOR i: TextEdit.Offset DECREASING IN [from.where..to.where) DO lst ← CONS[TextEdit.FetchChar[TextNode.NarrowToTextNode[from.node], i], lst]; ENDLOOP; IF advanceAdr THEN from.where ← to.where; RETURN[lst]; END; Delete: PUBLIC PROC [self: ViewerClasses.Viewer, from, to: DocAdr ← NIL, repaint: BOOLEAN ← TRUE] = BEGIN OPEN TEditSelection; tSel.viewer ← self; tSel.start.pos ← from↑; tSel.insertion ← before; tSel.granularity ← char; tSel.end.pos ← IF to=NIL THEN from↑ ELSE [to.node, to.where-1]; MakeSelection[primary, tSel]; -- finalised so that metrics are valid for Delete TEditInputOps.Delete[]; IF repaint THEN ViewerOps.PaintViewer[self]; -- no need to update fromAdr since virtual adr is unchanged END; Bounds: PUBLIC PROC [self: ViewerClasses.Viewer] RETURNS [top, bottom: DocAdr] = BEGIN OPEN TextNode; tdd: TEditDocument.TEditDocumentData ← NARROW[self.data]; firstChild: TextEdit.RefTextNode = NarrowToTextNode[FirstChild[tdd.text]]; lastChild: TextEdit.RefTextNode = NarrowToTextNode[LastChild[tdd.text]]; top ← NEW[TextNode.Location ← [firstChild, 0]]; bottom ← NEW[TextNode.Location ← [lastChild, TextEdit.Size[lastChild]-1]]; END; CompareAdr: PUBLIC PROC [self: ViewerClasses.Viewer, adr1, adr2: DocAdr ← NIL] RETURNS [Comparison] = BEGIN RETURN[SELECT TRUE FROM adr1.node#adr2.node => notEqual, -- not comparing nodes for now adr1.where=adr2.where => equal, adr1.where>adr2.where => greater, ENDCASE => less ]; END; AssignAdr: PUBLIC PROC [self: ViewerClasses.Viewer, from, into: DocAdr ← NIL] = BEGIN into↑ ← from↑; END; OutOfBoundsDocAdr: PUBLIC SIGNAL = CODE ; MoveAdr: PUBLIC PROC [self: ViewerClasses.Viewer, n: LONG INTEGER, adr: DocAdr ← NIL] = BEGIN adr.where ← adr.where+n; -- for now, assume addr must stay within the node IF adr.where<0 OR adr.where>TextEdit.Size[TextNode.NarrowToTextNode[adr.node]] THEN ERROR OutOfBoundsDocAdr; END; NewAdr: PUBLIC PROC [self: ViewerClasses.Viewer, adr: DocAdr ← NIL] RETURNS [DocAdr] = BEGIN newAdr: DocAdr ← NEW[TextNode.Location]; AssignAdr[self, adr, newAdr]; RETURN[newAdr]; END; END.