TEditSelectionOpsImpl.mesa
Paxton on June 6, 1983 1:47 pm
Maxwell, January 6, 1983 11:38 am
Plass, April 15, 1983 3:29 pm
Russ Atkinson, September 26, 1983 4:09 pm
DIRECTORY
Convert USING [Error, IntFromRope],
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],
Terminal,
TextFind USING [MalformedPattern],
TreeFind USING [CreateFromRope, Finder, Try, TryBackwards],
ViewerClasses USING [Viewer];
TEditSelectionOpsImpl: CEDAR PROGRAM
IMPORTS
Convert, MessageWindow, NodeProps, Rope, TEditInput, TEditLocks, TEditOps, TEditProfile, TEditRefresh, TEditSelection, Terminal, TextFind, TextNode, 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[];
count ← Convert.IntFromRope[sel ! Convert.Error => 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: BOOLEANFALSE,
id: SelectionId ← primary,
case: BOOLTRUE -- case => case of characters is significant -- ] = BEGIN
rope: Rope.ROPE = TEditOps.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: BOOLEANFALSE,
id: SelectionId ← primary,
case: BOOLTRUE -- case => case of characters is significant -- ] = BEGIN
IF ~DoFind[viewer, rope, findWhere, def, word, id, case] THEN {
MessageWindow.Append["Not found.", TRUE];
Terminal.BlinkBWDisplay[Terminal.Current[]];
RETURN } END;
DoFind: PUBLIC PROC [
viewer: ViewerClasses.Viewer,
rope: Rope.ROPE,
findWhere: FindWhere ← anywhere,
def, word: BOOLEANFALSE,
id: SelectionId ← primary,
case: BOOLTRUE -- 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.