KeyboardScan.Mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Last Edited by: Spreitzer, November 27, 1985 5:29:49 pm PST
Last tweaked by Mike Spreitzer on January 28, 1988 5:50:16 pm PST
Willie-s, March 23, 1992 2:46 pm PST
DIRECTORY MessageWindow, Rope, TEditDocument, TEditInput, TEditInputExtras, TEditInputOps, TEditOps, TEditRefresh, TEditSelection, TextEdit, TextNode, Tioga, TiogaFind, ViewerClasses, ViewerOps;
KeyboardScan: CEDAR PROGRAM
IMPORTS MessageWindow, Rope, TEditInput, TEditInputExtras, TEditOps, TEditRefresh, TEditSelection, TextEdit, TextNode, TiogaFind, ViewerOps
={
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
Location: TYPE = TextNode.Location;
Selection: TYPE = TEditDocument.Selection;
SelectionId: TYPE ~ TEditDocument.SelectionId;
record: BOOL ¬ TRUE;
ScanNull: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- =
{RETURN};
ScanStart: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- = {
NoteStart: PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection] = {
TEditSelection.Copy[source: tSel, dest: startSel];
RETURN};
TEditSelection.CallWithSelAndDocAndTddLocks[viewer, primary, NoteStart];
target ¬ NIL;
failTailLen ¬ 0;
findWhere ¬ forwards;
caseMatters ¬ FALSE;
RETURN};
ScanUpper: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- =
{case ¬ Upper};
ScanLower: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- =
{case ¬ Lower};
ScanForward: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- =
{findWhere ¬ forwards};
ScanBackward: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- =
{findWhere ¬ backwards};
ScanReverse: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- =
{SELECT findWhere FROM
forwards => {findWhere ¬ backwards; MessageWindow.Append["Leaping backwards", TRUE]};
backwards => {findWhere ¬ forwards; MessageWindow.Append["Leaping forwards", TRUE]};
ENDCASE => ERROR};
ScanToggleCase: PROC [viewer: Viewer ¬ NIL] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] --TEditInput.CommandProc-- = {
caseMatters ¬ NOT caseMatters;
MessageWindow.Append[IF caseMatters THEN "Case matters" ELSE "Case doesn't matter", TRUE]};
Case: TYPE = {Upper, Lower};
case: Case;
startSel: TEditDocument.Selection ~ TEditSelection.Create[];
findWhere: TEditSelection.FindWhere;
caseMatters: BOOL;
target, lastTarget: ROPE ¬ NIL;
failTailLen: NAT ¬ 0;
ScanTo: PROC [data: REF ANY, viewer: Viewer, param: REF ANY] RETURNS [recordAtom: BOOL, quit: BOOL] --TEditInputExtras.CommandClosureProc-- ~ {
parmRope: ROPE ~ NARROW[param];
raw: CHAR ~ IF parmRope.Length = 1 THEN parmRope.Fetch[0] ELSE ERROR;
goal: CHAR ~ IF raw NOT IN ['A .. 'Z] THEN raw ELSE SELECT case FROM
Upper => raw,
Lower => raw - 'A + 'a,
ENDCASE => ERROR;
newTarget: ROPE ~ target.Concat[Rope.FromChar[goal]];
target ¬ lastTarget ¬ newTarget;
IF failTailLen>0 THEN {failTailLen ¬ failTailLen+1; Bitch[target]}
ELSE IF NOT FindRope[viewer, newTarget, FALSE, findWhere, FALSE, FALSE, primary, caseMatters] THEN failTailLen ¬ 1;
RETURN [TRUE, TRUE]};
ScanRepeat: PROC [viewer: Viewer] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] = {
target ¬ lastTarget;
IF failTailLen>0 THEN Bitch[target]
ELSE IF NOT FindRope[viewer, target, TRUE, findWhere, FALSE, FALSE, primary, caseMatters] THEN failTailLen ¬ 1;
RETURN};
ScanShorten: PROC [viewer: Viewer] RETURNS [recordAtom: BOOL ¬ record, quit: BOOL ¬ TRUE] = {
oldLen: INT ~ target.Length;
IF oldLen>0 THEN target ¬ lastTarget ¬ target.Substr[len: oldLen-1];
IF oldLen<=1 THEN {
MessageWindow.Append["Empty search.", TRUE];
ViewerOps.BlinkDisplay[];
RETURN};
IF failTailLen>0 THEN failTailLen ¬ failTailLen-1;
IF failTailLen>0 THEN Bitch[target]
ELSE IF NOT FindRope[viewer, target, FALSE, findWhere, FALSE, FALSE, primary, caseMatters] THEN failTailLen ¬ 1;
RETURN};
FindRope: PUBLIC PROC [viewer: Viewer, rope: ROPE, moveOn: BOOL, findWhere: TEditSelection.FindWhere ¬ anywhere, def, word: BOOL ¬ FALSE, id: SelectionId ¬ primary, case: BOOL ¬ TRUE -- case => case of characters is significant --] RETURNS [found: BOOL] = {
IF (found ¬ DoFind[viewer, rope, moveOn, findWhere, def, word, id, case]) THEN MessageWindow.Clear[] ELSE Bitch[rope];
RETURN};
Bitch: PROC [target: 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[];
RETURN};
NormalizeLoc: PROC [loc: Location, dw: INT] RETURNS [Location] ~ {
IF loc.where=TextNode.NodeItself THEN loc.where ¬ 0;
loc.where ¬ MIN[loc.node.rope.Length, MAX[INT[0], loc.where + dw]];
RETURN [loc]};
DoFind: PUBLIC PROC [viewer: Viewer, rope: ROPE, moveOn: BOOL, findWhere: TEditSelection.FindWhere ¬ anywhere, def, word: BOOL ¬ FALSE, id: SelectionId ¬ primary, case: BOOL ¬ TRUE -- case => case of characters is significant --] RETURNS [found: BOOL] = {
where: TextNode.RefTextNode ¬ NIL;
first, last: Location;
at, atEnd: TextNode.Offset ¬ 0;
mv: INT ~ IF moveOn THEN 1 ELSE 0;
targLen: INT ~ rope.Length;
inViewer: BOOL ¬ FALSE;
targetNode: Tioga.Node;
DoFindIt: PROC [tdd: TEditDocument.TEditDocumentData, tSel: Selection] = {
interrupt: REF BOOL ~ TEditInput.interrupt;
FirstLoc: PROC [root: Tioga.Node] RETURNS [Location] ~ {
RETURN[[TextNode.FirstChild[root], 0]]
};
LastLoc: PROC [root: Tioga.Node] RETURNS [Location] ~ {
RETURN[TextNode.LastLocWithin[root]]
};
Forward: PROC = {
first ¬ NormalizeLoc[tSel.start.pos, mv];
[where, at, atEnd] ¬ TiogaFind.LiteralSearch[direction: forward, target: targetNode, case: FALSE, loc1: first, loc2: LastLoc[tdd.text], interrupt: interrupt];
};
Backward: PROC = {
first ¬ NormalizeLoc[tSel.start.pos, targLen-mv];
[where, at, atEnd] ¬ TiogaFind.LiteralSearch[direction: backward, target: targetNode, case: FALSE, loc1: FirstLoc[tdd.text], loc2: first, interrupt: interrupt]
};
FromStart: PROC = {
last ¬ NormalizeLoc[tSel.start.pos, targLen+mv];
[where, at, atEnd] ¬ TiogaFind.LiteralSearch[direction: forward, target: targetNode, case: FALSE, loc1: FirstLoc[tdd.text], loc2: LastLoc[tdd.text], interrupt: interrupt]
};
FromEnd: PROC = {
first ¬ [TextNode.LastWithin[tdd.text], 0];
first.where ¬ first.node.rope.Length;
last ¬ NormalizeLoc[tSel.start.pos, -mv];
[where, at, atEnd] ¬ TiogaFind.LiteralSearch[direction: backward, target: targetNode, case: FALSE, loc1: FirstLoc[tdd.text], loc2: LastLoc[tdd.text], interrupt: interrupt]
};
interrupt­ ¬ FALSE;
IF NOT (inViewer ¬ tSel.viewer=viewer) THEN RETURN;
SELECT findWhere FROM
backwards => { Backward[]; IF where = NIL THEN FromEnd[] };
forwards => { Forward[]; IF where = NIL THEN FromStart[] };
ENDCASE => ERROR;
IF where#NIL THEN {
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.insertion ¬ before;
tSel.pendingDelete ¬ FALSE;
tSel.viewer ¬ viewer;
tSel.data ¬ tdd;
}
ELSE {
TEditSelection.Copy[source: startSel, dest: tSel];
};
TEditOps.RememberCurrentPosition[viewer];
TEditSelection.SetSelLooks[tSel];
TEditSelection.MakeSelection[new: tSel, selection: id];
IF closeOnLeap THEN TEditInput.CloseEvent[];
TEditRefresh.ScrollToEndOfSel[viewer, FALSE, id];
};
found ¬ FALSE;
IF Rope.Size[rope] = 0 THEN RETURN;
IF def THEN rope ¬ Rope.Concat[rope,":"];
targetNode ¬ TextEdit.FromRope[rope];
TEditSelection.CallWithSelAndDocAndTddLocks[viewer, id, DoFindIt];
found ¬ where#NIL;
IF NOT inViewer THEN {
MessageWindow.Append["This can't happen!", TRUE];
MessageWindow.Blink[];
};
};
closeOnLeap: BOOL ¬ FALSE;
Start: PROC = {
TEditInput.Register[$ScanNull, ScanNull];
TEditInput.Register[$ScanStart, ScanStart];
TEditInput.Register[$ScanRepeat, ScanRepeat];
TEditInput.Register[$ScanShorten, ScanShorten];
TEditInput.Register[$ScanUpper, ScanUpper];
TEditInput.Register[$ScanLower, ScanLower];
TEditInput.Register[$ScanForward, ScanForward];
TEditInput.Register[$ScanBackward, ScanBackward];
TEditInput.Register[$ScanReverse, ScanReverse];
TEditInput.Register[$ScanToggleCase, ScanToggleCase];
TEditInputExtras.RegisterClosure[[$ScanTo, ScanTo, NIL]];
};
Start[];
}.