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
Doug Wyatt, May 15, 1984 11:15:14 am PDT
DIRECTORY
Convert USING [Error, IntFromRope],
MessageWindow USING [Append, Blink],
NodeProps USING [GetProp],
Rope USING [Concat, ROPE, Size],
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],
TEditSelectionExtras USING [],
Terminal USING [BlinkBWDisplay, Current],
TextEdit USING [RefTextNode],
TextFind USING [MalformedPattern],
TextNode USING [EndPos, FirstChild, Location, LocWithin, Offset, Ref, RefTextNode],
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, TEditSelectionExtras
= BEGIN OPEN TEditDocument, TEditSelection;
Viewer: TYPE ~ ViewerClasses.Viewer;
CallWithSelAndDocAndTddLocks:
PUBLIC PROC [
viewer: 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
}
};
ShowPosition:
PUBLIC
PROC[viewer: Viewer, skipCommentNodes:
BOOL ←
TRUE] =
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, skipCommentNodes];
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;
Position:
PUBLIC
PROC[viewer: Viewer] ~ {
ShowPosition[viewer: viewer, skipCommentNodes: TRUE];
};
Find:
PUBLIC
PROC [viewer: 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 {
OPEN MessageWindow;
Append["Select target for search.", TRUE];
Blink[] };
FindRope[viewer, rope, findWhere, def, word, id, case];
END;
FindRope:
PUBLIC
PROC [
viewer: 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];
Terminal.BlinkBWDisplay[Terminal.Current[]];
RETURN } END;
DoFind:
PUBLIC
PROC [
viewer: 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.