<<-- TEditSelectionOpsImpl.mesa Edited by Paxton on June 6, 1983 1:47 pm>> <> <> DIRECTORY Convert USING [Parse, Value], MessageWindow USING [Append, Blink], NodeProps USING [GetProp], Rope USING [Concat, ROPE, Size], TextEdit USING [RefTextNode], TextNode USING [EndPos, FirstChild, Location, LocWithin, Offset, Ref, RefTextNode], TEditDocument USING [Selection, SelectionId, TEditDocumentData], TEditInput USING [CloseEvent], TEditLocks USING [LockDocAndTdd, LockRef, UnlockDocAndTdd], TEditOps USING [GetSelContents, RememberCurrentPosition], TEditProfile USING [selectionCaret], TEditRefresh USING [ScrollToEndOfSel], TEditSelection USING [Alloc, Copy, Free, FindWhere, LockSel, MakeSelection, sSel, fSel, pSel, SetSelLooks, UnlockSel], TextFind USING [MalformedPattern], TreeFind USING [CreateFromRope, Finder, Try, TryBackwards], UserTerminal USING [BlinkDisplay], ViewerClasses USING [Viewer]; TEditSelectionOpsImpl: CEDAR PROGRAM IMPORTS Convert, MessageWindow, NodeProps, Rope, TextFind, TextNode, TEditInput, TEditLocks, TEditOps, TEditProfile, TEditRefresh, TEditSelection, UserTerminal, TreeFind EXPORTS TEditSelection = BEGIN OPEN TEditDocument, TEditSelection; CallWithSelAndDocAndTddLocks: PUBLIC PROC [ viewer: ViewerClasses.Viewer, id: SelectionId _ primary, proc: PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection]] = { Cleanup: PROC = { TEditSelection.UnlockSel[id]; IF lockRef # NIL THEN TEditLocks.UnlockDocAndTdd[tdd]; IF tSel # NIL THEN Free[tSel] }; tSel: Selection; lockRef: TEditLocks.LockRef; tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd # NIL THEN {ENABLE UNWIND => Cleanup[]; TEditSelection.LockSel[id, "CallWithSelAndDocAndTddLocks"]; lockRef _ TEditLocks.LockDocAndTdd[tdd, "CallWithSelAndDocAndTddLocks", read]; IF lockRef#NIL THEN { sel: Selection = SELECT id FROM primary => pSel, secondary => sSel, feedback => fSel, ENDCASE => ERROR; tSel _ Alloc[]; TEditSelection.Copy[source: sel, dest: tSel]; proc[tdd, tSel] }; Cleanup } }; Position: PUBLIC PROCEDURE [viewer: ViewerClasses.Viewer] = BEGIN count: INT _ -1; sel: Rope.ROPE _ TEditOps.GetSelContents[]; <<-- we'd like to use Convert.IntFromRope here, but the resultant>> <<-- fatal compiler errors in pass 5 wasted one afternoon already...>> IntFromRope: PROC [r: Rope.ROPE] RETURNS [i: INT] = BEGIN v: Convert.Value _ Convert.Parse[[rope[r]]].value; RETURN[NARROW[v, Convert.Value[signed]].signed]; END; count _ IntFromRope[sel ! ANY => CONTINUE]; IF count>=0 THEN BEGIN DoPosition: PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection] = { tiogaFile: BOOL _ (NodeProps.GetProp[tdd.text, $FromTiogaFile] = $Yes); IF ~tiogaFile THEN count _ count+1; -- hack to compensate for leading CR tSel.start.pos _ tSel.end.pos _ TextNode.LocWithin[tdd.text, count, 1, TRUE]; -- skip comment nodes tSel.end.pos.where _ MIN[tSel.end.pos.where+3, TextNode.EndPos[tSel.end.pos.node]]; tSel.start.pos.where _ MIN[tSel.end.pos.where, tSel.start.pos.where]; IF tSel.start.pos.where=tSel.end.pos.where AND tSel.start.pos.where > 0 THEN tSel.start.pos.where _ tSel.start.pos.where-1; tSel.granularity _ char; tSel.viewer _ viewer; tSel.data _ tdd; tSel.pendingDelete _ FALSE; tSel.insertion _ IF TEditProfile.selectionCaret=before THEN before ELSE after; TEditOps.RememberCurrentPosition[viewer]; TEditSelection.SetSelLooks[tSel]; TEditSelection.MakeSelection[new: tSel, selection: feedback]; TEditRefresh.ScrollToEndOfSel[viewer, FALSE, feedback]; -- sets bit to cause scroll after refresh }; CallWithSelAndDocAndTddLocks[viewer, feedback, DoPosition]; END ELSE { OPEN MessageWindow; Append["Select character count for position.", TRUE]; Blink[] }; END; Find: PUBLIC PROC [viewer: ViewerClasses.Viewer, findWhere: FindWhere _ anywhere, def, word: BOOLEAN _ FALSE, id: SelectionId _ primary, case: BOOL _ TRUE -- case => case of characters is significant -- ] = BEGIN rope: Rope.ROPE = TEditOps.GetSelContents[]; IF Rope.Size[rope]=0 THEN { MessageWindow.Append["Select target for search.", TRUE]; MessageWindow.Blink[] }; FindRope[viewer, rope, findWhere, def, word, id, case]; END; FindRope: PUBLIC PROC [ viewer: ViewerClasses.Viewer, rope: Rope.ROPE, findWhere: FindWhere _ anywhere, def, word: BOOLEAN _ FALSE, id: SelectionId _ primary, case: BOOL _ TRUE -- case => case of characters is significant -- ] = BEGIN IF ~DoFind[viewer, rope, findWhere, def, word, id, case] THEN { MessageWindow.Append["Not found.", TRUE]; TRUSTED {UserTerminal.BlinkDisplay[]}; RETURN } END; DoFind: PUBLIC PROC [ viewer: ViewerClasses.Viewer, rope: Rope.ROPE, findWhere: FindWhere _ anywhere, def, word: BOOLEAN _ FALSE, id: SelectionId _ primary, case: BOOL _ TRUE -- case => case of characters is significant -- ] RETURNS [found: BOOL] = BEGIN finder: TreeFind.Finder; where: TextNode.RefTextNode; first: TextNode.Ref; start, at, atEnd: TextNode.Offset; DoFindIt: PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection] = { visible: BOOL _ SelectionVisibleInViewer[]; Forward: PROC = { IF visible THEN { first _ tSel.end.pos.node; start _ tSel.end.pos.where+1 } ELSE { first _ tdd.lineTable.lines[0].pos.node; start _ tdd.lineTable.lines[0].pos.where }; [found,where,at,atEnd,,] _ TreeFind.Try[finder,first,start] }; Backward: PROC = { IF visible THEN { first _ tSel.start.pos.node; start _ tSel.start.pos.where } ELSE { first _ tdd.lineTable.lines[0].pos.node; start _ tdd.lineTable.lines[0].pos.where }; [found,where,at,atEnd,,] _ TreeFind.TryBackwards[finder,first,start] }; FromStart: PROC = { first _ TextNode.FirstChild[tdd.text]; start _ 0; [found,where,at,atEnd,,] _ TreeFind.Try[finder,first,start] }; SelectionVisibleInViewer: PROC RETURNS [BOOLEAN] = { RETURN [tSel.viewer=viewer AND tSel.end.line IN [0..tdd.lineTable.lastLine]] }; SELECT findWhere FROM forwards => Forward[]; backwards => Backward[]; anywhere => { Forward[]; IF ~found THEN FromStart[] }; ENDCASE => ERROR; IF ~found THEN RETURN; IF def THEN atEnd _ atEnd-1; -- skip the trailing : tSel.start.pos _ [where,at]; tSel.end.pos _ [where,MAX[0,atEnd-1]]; tSel.granularity _ IF word THEN word ELSE char; tSel.viewer _ viewer; tSel.data _ tdd; tSel.insertion _ IF TEditProfile.selectionCaret=before THEN before ELSE after; tSel.insertion _ after; tSel.pendingDelete _ FALSE; TEditOps.RememberCurrentPosition[viewer]; TEditSelection.SetSelLooks[tSel]; TEditSelection.MakeSelection[new: tSel, selection: id]; TEditInput.CloseEvent[]; TEditRefresh.ScrollToEndOfSel[viewer, FALSE, id]; }; found _ FALSE; IF Rope.Size[rope] = 0 THEN RETURN; IF def THEN rope _ Rope.Concat[rope,":"]; finder _ TreeFind.CreateFromRope[pattern: rope, literal: TRUE, ignoreCase: ~case, word: word ! TextFind.MalformedPattern => { MessageWindow.Append["Pattern too long",TRUE]; MessageWindow.Blink[]; GOTO Bad }]; CallWithSelAndDocAndTddLocks[viewer, id, DoFindIt]; EXITS Bad => NULL; END; END.