TEditSelectionOpsImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Plass, March 21, 1985 12:54:53 pm PST
Russ Atkinson (RRA) January 22, 1986 11:59:50 pm PST
Doug Wyatt, August 7, 1986 3:32:26 pm PDT
DIRECTORY
Convert USING [Error, IntFromRope],
MessageWindow USING [Append, Blink, Clear],
NodeProps USING [GetProp],
Rope USING [Concat, IsEmpty, ROPE, Size, Substr],
TEditDocument USING [Selection, SelectionId, TEditDocumentData],
TEditInput USING [CloseEvent],
TEditInputExtras USING [interrupt],
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],
TEditSelectionOps USING [],
TextEdit USING [RefTextNode],
TextFind USING [MalformedPattern],
TextNode USING [EndPos, FirstChild, Location, LocWithin, Offset, Ref, RefTextNode],
TreeFind USING [CreateFromRope, Finder, Try, TryBackwards],
ViewerClasses USING [Viewer],
ViewerOps USING [BlinkDisplay];
TEditSelectionOpsImpl:
CEDAR
PROGRAM
IMPORTS Convert, MessageWindow, NodeProps, Rope, TEditInput, TEditInputExtras, TEditLocks, TEditOps, TEditProfile, TEditRefresh, TEditSelection, TextFind, TextNode, TreeFind, ViewerOps
EXPORTS TEditSelection, TEditSelectionOps
= BEGIN
ROPE: TYPE ~ Rope.ROPE;
Viewer: TYPE ~ ViewerClasses.Viewer;
SelectionId: TYPE ~ TEditDocument.SelectionId;
Selection: TYPE ~ TEditDocument.Selection;
CallWithSelAndDocAndTddLocks:
PUBLIC
PROC [viewer: Viewer, id: SelectionId ← primary,
proc:
PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection]] = {
IF viewer #
NIL
THEN
WITH viewer.data
SELECT
FROM
tdd: TEditDocument.TEditDocumentData => {
tSel: Selection ← NIL;
lockRef: TEditLocks.LockRef ← NIL;
Cleanup:
PROC = {
TEditSelection.UnlockSel[id];
IF lockRef # NIL THEN TEditLocks.UnlockDocAndTdd[tdd];
IF tSel # NIL THEN TEditSelection.Free[tSel]
};
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 => TEditSelection.pSel, secondary => TEditSelection.sSel, feedback => TEditSelection.fSel, ENDCASE => ERROR;
tSel ← TEditSelection.Alloc[];
TEditSelection.Copy[source: sel, dest: tSel];
proc[tdd, tSel]
};
Cleanup[];
};
};
ENDCASE;
};
ShowPosition:
PUBLIC
PROC[viewer: Viewer, skipCommentNodes:
BOOL ←
TRUE] = {
count: INT ← -1;
sel: ROPE ← TEditOps.GetSelContents[];
count ← Convert.IntFromRope[sel ! Convert.Error => CONTINUE];
IF count>=0
THEN ShowGivenPosition[viewer, count, skipCommentNodes]
ELSE {
MessageWindow.Append["Select character count for position.", TRUE];
MessageWindow.Blink[]
};
};
Position:
PUBLIC
PROC[viewer: Viewer] ~ {
ShowPosition[viewer: viewer, skipCommentNodes: TRUE];
};
ShowGivenPosition:
PUBLIC
PROC [viewer: Viewer, pos:
INT, skipCommentNodes:
BOOL ←
TRUE] = {
Exported to TEditSelectionOps (new for 6.0)
DoPosition:
PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection] = {
tiogaFile: BOOL ← (NodeProps.GetProp[tdd.text, $FromTiogaFile] = $Yes);
IF NOT tiogaFile THEN pos ← pos+1; -- hack to compensate for leading CR
tSel.start.pos ← tSel.end.pos ← TextNode.LocWithin[tdd.text, pos, 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];
};
targetOfLastSearch: ROPE ← NIL;
Find:
PUBLIC
PROC [viewer: Viewer,
findWhere: TEditSelection.FindWhere ← anywhere,
def, word:
BOOL ←
FALSE,
id: SelectionId ← primary,
case:
BOOL ←
TRUE
-- case => case of characters is significant --
] ~ {
rope: ROPE ← TEditOps.GetSelContents[];
IF Rope.IsEmpty[rope] THEN rope ← targetOfLastSearch ELSE targetOfLastSearch ← rope;
IF Rope.IsEmpty[rope]
THEN {
MessageWindow.Append["Select target for search.", TRUE];
MessageWindow.Blink[];
}
ELSE FindRope[viewer, rope, findWhere, def, word, id, case];
};
FindRope:
PUBLIC
PROC [viewer: Viewer, rope:
ROPE,
findWhere: TEditSelection.FindWhere ← anywhere,
def, word:
BOOL ←
FALSE,
id: SelectionId ← primary,
case:
BOOL ←
TRUE
-- case => case of characters is significant --
] = {
IF
NOT DoFind[viewer, rope, findWhere, def, word, id, case]
THEN {
target: ROPE ← rope;
IF Rope.Size[target]>50 THEN target ← Rope.Concat[Rope.Substr[target, 0, 47], "..."];
MessageWindow.Append[Rope.Concat[target, " not found."], TRUE];
ViewerOps.BlinkDisplay[];
}
ELSE MessageWindow.Clear[];
};
DoFind:
PUBLIC
PROC [viewer: Viewer, rope:
ROPE,
findWhere: TEditSelection.FindWhere ← anywhere,
def, word:
BOOL ←
FALSE,
id: SelectionId ← primary,
case:
BOOL ←
TRUE
-- case => case of characters is significant --
]
RETURNS [found:
BOOL] = {
finder: TreeFind.Finder ← NIL;
where: TextNode.RefTextNode;
first: TextNode.Ref;
start, at, atEnd: TextNode.Offset;
DoFindIt:
PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection] = {
SelectionVisibleInViewer:
PROC
RETURNS [
BOOL] = {
RETURN [tSel.viewer=viewer AND tSel.end.line IN [0..tdd.lineTable.lastLine]]
};
visible: BOOL ~ SelectionVisibleInViewer[];
interrupt: REF BOOL ~ TEditInputExtras.interrupt;
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: finder, first: first, start: start, interrupt: interrupt];
};
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: finder, first: first, len: start, interrupt: interrupt]
};
FromStart:
PROC = {
first ← TextNode.FirstChild[tdd.text]; start ← 0;
[found,where,at,atEnd,,] ← TreeFind.Try[finder: finder, first: first, start: start, interrupt: interrupt]
};
interrupt^ ← FALSE;
SELECT findWhere
FROM
forwards => Forward[];
backwards => Backward[];
anywhere => { Forward[]; IF NOT found THEN FromStart[] };
ENDCASE => ERROR;
IF NOT 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:
NOT case, word: word !
TextFind.MalformedPattern =>
IF ec=toobig
THEN
GOTO TooBig
since literal=TRUE, no other PatternErrorCode should occur
];
IF finder#NIL THEN CallWithSelAndDocAndTddLocks[viewer, id, DoFindIt];
EXITS
TooBig => {
MessageWindow.Append["Pattern too long", TRUE];
MessageWindow.Blink[];
};
};
END.