-- TEditSelectionOpsImpl.mesa Edited by Paxton on June 6, 1983 1:47 pm
Last Edited by: Maxwell, January 6, 1983 11:38 am
Last Edited by: Plass, October 11, 1983 10:37 am
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
}
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.