<<-- TiogaSelectionOpsImpl.mesa Edited by Paxton on June 17, 1983 1:46 pm>> <> <> DIRECTORY Convert USING [Parse, Value], MessageWindow USING [Append, Blink], NodeProps USING [GetProp], Rope USING [Concat, ROPE, Size], TiogaNode USING [Location, Offset, Ref, RefTextNode], TiogaNodeOps USING [BranchChild, EndPos, LocWithin], TiogaDocument USING [Selection, SelectionId, TiogaDocumentData], TiogaInput USING [CloseEvent], TiogaLocks USING [LockDocAndTdd, LockRef, UnlockDocAndTdd], TiogaOps USING [GetSelContents, RememberCurrentPosition], TiogaProfile USING [selectionCaret], TiogaRefresh USING [ScrollToEndOfSel], TiogaSelection 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]; TiogaSelectionOpsImpl: CEDAR PROGRAM IMPORTS Convert, MessageWindow, NodeProps, Rope, TextFind, TiogaNodeOps, TiogaInput, TiogaLocks, TiogaOps, TiogaProfile, TiogaRefresh, TiogaSelection, UserTerminal, TreeFind EXPORTS TiogaSelection = BEGIN OPEN TiogaDocument, TiogaSelection; CallWithSelAndDocAndTddLocks: PUBLIC PROC [ viewer: ViewerClasses.Viewer, id: SelectionId _ primary, proc: PROC [tdd: TiogaDocument.TiogaDocumentData, tSel: Selection]] = { Cleanup: PROC = { TiogaSelection.UnlockSel[id]; IF lockRef # NIL THEN TiogaLocks.UnlockDocAndTdd[tdd]; IF tSel # NIL THEN Free[tSel] }; tSel: Selection; lockRef: TiogaLocks.LockRef; tdd: TiogaDocument.TiogaDocumentData ~ NARROW[viewer.data]; IF tdd # NIL THEN {ENABLE UNWIND => Cleanup[]; TiogaSelection.LockSel[id, "CallWithSelAndDocAndTddLocks"]; lockRef _ TiogaLocks.LockDocAndTdd[tdd, "CallWithSelAndDocAndTddLocks", read]; IF lockRef#NIL THEN { sel: Selection = SELECT id FROM primary => pSel, secondary => sSel, feedback => fSel, ENDCASE => ERROR; tSel _ Alloc[]; TiogaSelection.Copy[source: sel, dest: tSel]; proc[tdd, tSel] }; Cleanup } }; Position: PUBLIC PROCEDURE [viewer: ViewerClasses.Viewer] = BEGIN count: INT _ -1; sel: Rope.ROPE _ TiogaOps.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: TiogaDocument.TiogaDocumentData, 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 _ TiogaNodeOps.LocWithin[tdd.text, count, 1, TRUE]; -- skip comment nodes tSel.end.pos.where _ MIN[tSel.end.pos.where+3, TiogaNodeOps.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 TiogaProfile.selectionCaret=before THEN before ELSE after; TiogaOps.RememberCurrentPosition[viewer]; TiogaSelection.SetSelLooks[tSel]; TiogaSelection.MakeSelection[new: tSel, selection: feedback]; TiogaRefresh.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 = TiogaOps.GetSelContents[]; IF Rope.Size[rope]=0 THEN { OPEN MessageWindow; Append["Select target for search.", TRUE]; 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: TiogaNode.RefTextNode; first: TiogaNode.Ref; start, at, atEnd: TiogaNode.Offset; DoFindIt: PROC [tdd: TiogaDocument.TiogaDocumentData, 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 _ TiogaNodeOps.BranchChild[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 TiogaProfile.selectionCaret=before THEN before ELSE after; tSel.insertion _ after; tSel.pendingDelete _ FALSE; TiogaOps.RememberCurrentPosition[viewer]; TiogaSelection.SetSelLooks[tSel]; TiogaSelection.MakeSelection[new: tSel, selection: id]; TiogaInput.CloseEvent[]; TiogaRefresh.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.