-- EditToolSubsImpl.mesa
-- Edited by Paxton on 6-Feb-82 11:56:26
DIRECTORY
EditToolPrivate,
Buttons,
Convert,
EditNotify,
Inline,
IOStream,
UndoEvent,
Labels,
List,
Menus,
MessageWindow,
NodeAddrs,
Rope,
RopeEdit,
RopeReader,
RunReader,
TextEdit,
TextFind,
TextLooks,
TextLooksSupport,
TextNode,
TEditDocument,
TEditInputOps,
TEditOps,
TreeFind,
UserTerminal,
ViewerOps,
ViewerClasses,
ViewerMenus;
EditToolSubsImpl: PROGRAM
IMPORTS EditToolPrivate, Buttons, Convert, Inline, IOStream, Labels, List, MessageWindow, NodeAddrs,
Rope, TEditInputOps, TEditOps, TextEdit, TextFind, TextNode,
TreeFind, UserTerminal, ViewerOps
EXPORTS EditToolPrivate =
{ OPEN ViewerClasses, EditToolPrivate;
----------------------------
----------------------------
sourceButton: Buttons.Button;
sourceArg: PUBLIC ViewerClasses.Viewer; -- the viewer holding the source text
sourceArgAtom: ATOM = $EditToolReplaceBy;
SourceButton: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,sourceArgAtom]
ELSE [] ← SourceArgOp[] };
SourceArgOp: TEditOps.CommandProc = { DataFieldButton[sourceArg] };
BuildSourceEntry: PUBLIC PROC = {
[sourceButton,sourceArg] ← BuildDataFieldPair["Replace by:", SourceButton] };
----------------------------
doitButton: Buttons.Button;
yesButton: Buttons.Button;
noButton: Buttons.Button;
substituteButton: Buttons.Button;
replaceRope: Rope.Ref = "Replace!";
doitRope: Rope.Ref = "DoOne!";
subsRope: Rope.Ref = "Substitute!";
doallRope: Rope.Ref = "DoAll!";
BuildDoItEntries: PUBLIC PROC = {
yesButton ← Buttons.Create["Yes!", DoYes,
entryLeft, heightSoFar, 0, 0,
NIL, FALSE, container, FALSE];
yesButton.border ← FALSE;
noButton ← Buttons.Create["No!", DoNo,
entryLeft+gapSize*2+yesButton.ww, heightSoFar, 0, 0,
NIL, FALSE, container, FALSE];
noButton.border ← FALSE;
substituteButton ← Buttons.Create[subsRope, DoSubstitute,
entryLeft+gapSize*4+yesButton.ww+noButton.ww,
heightSoFar, 0, 0,
NIL, TRUE, container, FALSE]; -- notice that we fork Substitute's
substituteButton.border ← FALSE;
doitButton ← Buttons.Create[replaceRope, DoIt,
entryLeft+gapSize*6+yesButton.ww+noButton.ww+substituteButton.ww,
heightSoFar, 0, 0, NIL, FALSE, container, FALSE];
doitButton.border ← FALSE;
heightSoFar ← heightSoFar + entryHeight + entryVSpace;
};
----------------------------
operationButton: Buttons.Button;
operationLabel: Labels.Label;
doReplace: PUBLIC BOOLEAN ← TRUE;
replaceOperation: Rope.Ref = "Do Replace";
specifiedOperation: Rope.Ref = "Do Operations Specified Below";
doOpsAtom: ATOM = $EditToolDoOps;
doReplaceAtom: ATOM = $EditToolDoReplace;
OperationButton: Buttons.ButtonProc = {
IF mainEditTool THEN ChangeState[operationLabel,doReplace,doReplaceAtom,doOpsAtom]
ELSE IF doReplace THEN [] ← DoOpsOp[] ELSE [] ← DoReplaceOp[] };
DoOpsOp: TEditOps.CommandProc = {
doReplace ← FALSE;
Labels.Set[operationLabel, specifiedOperation];
Buttons.ReLabel[doitButton, doitRope];
Buttons.ReLabel[substituteButton, doallRope] };
DoReplaceOp: TEditOps.CommandProc = {
doReplace ← TRUE;
Labels.Set[operationLabel, replaceOperation];
Buttons.ReLabel[doitButton, replaceRope];
Buttons.ReLabel[substituteButton, subsRope] };
BuildOperationEntry: PUBLIC PROC = {
[operationLabel,operationButton] ←
BuildPair[OperationButton,doReplace,replaceOperation,specifiedOperation] };
----------------------------
----------------------------
initCapButton: Buttons.Button;
initCapLabel: Labels.Label;
forceInitCap: PUBLIC BOOLEAN ← TRUE;
forcingInitCap: Rope.Ref = "Capitalize like first replaced char";
ignoringInitCap: Rope.Ref = "Don't change replacement capitalization";
forceInitCapAtom: ATOM = $EditToolChangeInitCap;
ignoreInitCapAtom: ATOM = $EditToolLeaveInitCap;
InitCapButton: Buttons.ButtonProc = {
IF mainEditTool THEN
ChangeState[initCapLabel,forceInitCap,forceInitCapAtom,ignoreInitCapAtom]
ELSE IF forceInitCap THEN [] ← LeaveInitCapOp[] ELSE [] ← ChangeInitCapOp[] };
ChangeInitCapOp: TEditOps.CommandProc = {
forceInitCap ← TRUE;
Labels.Set[initCapLabel,forcingInitCap] };
LeaveInitCapOp: TEditOps.CommandProc = {
forceInitCap ← FALSE;
Labels.Set[initCapLabel,ignoringInitCap] };
BuildInitCapEntry: PUBLIC PROC = {
[initCapLabel,initCapButton] ←
BuildPair[InitCapButton,forceInitCap,forcingInitCap,ignoringInitCap] };
----------------------------
opsButton: Buttons.Button;
opsArg: ViewerClasses.Viewer;
opsAtom: ATOM = $EditToolOperations;
OpsButton: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,opsAtom]
ELSE [] ← OpsArgOp[] };
OpsArgOp: TEditOps.CommandProc = { DataFieldButton[opsArg] };
BuildOperationField: PUBLIC PROC = {
[opsButton,opsArg] ← BuildDataFieldPair["Operations:", OpsButton] };
GetOps: PROC RETURNS [list: LIST OF REF ANY] = { OPEN IOStream;
rope: Rope.Ref ← TextEdit.GetRope[GetDataNode[opsArg]];
h: Handle ← CreateInputStreamFromRope[rope];
item: REF ANY;
WHILE (item ← GetRefAny[h ! EndOfStream => { item ← NIL; CONTINUE}]) # NIL DO
WITH item SELECT FROM
x: ROPE => item ← LOOPHOLE[Rope.ToString[x], REF TEXT]; -- for now must convert ROPE to REF TEXT
ENDCASE;
list ← List.Nconc1[list, item];
ENDLOOP;
--h.Close[];
};
----------------------------
----------------------------
getopsButton: Buttons.Button;
setopButton: Buttons.Button;
getopButton: Buttons.Button;
BuildGetAndSetOpsEntries: PUBLIC PROC = {
getopsButton ← Buttons.Create["GetLastOps!", DoGetOps,
entryLeft, heightSoFar, 0, 0,
NIL, FALSE, container, FALSE];
getopsButton.border ← FALSE;
setopButton ← Buttons.Create["SetCom!", DoSetCom,
entryLeft+gapSize*2+getopsButton.ww, heightSoFar, 0, 0,
NIL, FALSE, container, FALSE];
setopButton.border ← FALSE;
getopButton ← Buttons.Create["GetCom!", DoGetCom,
entryLeft+gapSize*4+getopsButton.ww+setopButton.ww, heightSoFar, 0, 0,
NIL, FALSE, container, FALSE];
getopButton.border ← FALSE;
heightSoFar ← heightSoFar + entryHeight + entryVSpace;
};
DoGetOps: Buttons.ButtonProc = { ShowOps[TEditOps.GetRepeatSequence[]] };
-- this cannot be a registered TEdit atom since must reenter tedit monitor to get ops
ShowOps: PROC [list: LIST OF REF ANY] = { OPEN IOStream;
h: IOStream.Handle ← CreateOutputStreamToRope[];
doingChars: BOOLEAN ← FALSE;
nospace: BOOLEAN ← TRUE;
Space: PROC = {
IF doingChars THEN { -- end of string
PutChar[h, '"]; doingChars ← FALSE };
IF nospace THEN nospace ← FALSE ELSE PutChar[h,' ] };
AddChar: PROC [c: CHARACTER] = {
IF ~doingChars THEN { -- start of string
Space[]; PutChar[h, '"]; doingChars ← TRUE };
SELECT c FROM
'', '", '\\ => PutChar[h, '\\];
ENDCASE;
PutChar[h, c] };
{ ENABLE UNWIND => h.Close[];
FOR l: LIST OF REF ANY ← list, l.rest UNTIL l=NIL DO
WITH l.first SELECT FROM
x: ATOM => { Space[]; Put[h,atom[x]] };
x: REF INT => { Space[]; Put[h,int[x↑]] };
x: REF CHARACTER => AddChar[x↑];
x: ROPE => {
AddC: PROC [c: CHAR] RETURNS [BOOL] = {
AddChar[c]; RETURN [FALSE] };
[] ← Rope.Map[base: x, action: AddC] };
x: REF TEXT => {
FOR i: NAT IN [0..x.length) DO AddChar[x[i]]; ENDLOOP };
ENDCASE;
ENDLOOP;
IF doingChars THEN PutChar[h, '"];
TEditOps.SetTextContents[opsArg, GetOutputStreamRope[h]];
}};
debugCom: BOOLEAN ← FALSE;
SetCom: PROC [num: [0..9]] = {
list: LIST OF REF ANY ← GetOps[];
IF debugCom THEN ShowOps[list];
TEditOps.SetCommand[num,list];
};
DoSetCom: Buttons.ButtonProc = { OPEN IOStream;
-- this cannot be a registered TEdit atom since must reenter tedit monitor to get ops
rope: Rope.Ref ← TextEdit.GetRope[GetDataNode[comArg]];
h: Handle ← CreateInputStreamFromRope[rope];
num: INT ← GetInt[h ! Error => GOTO BadNum];
IF num ~IN [0..9] THEN GOTO BadNum;
SetCom[Inline.LowHalf[num]];
EXITS BadNum => { OPEN MessageWindow;
Append["Enter number from 0 to 9 in Command Number field", TRUE];
Blink[] } };
DoGetCom: Buttons.ButtonProc = { OPEN IOStream;
-- this cannot be a registered TEdit atom since must reenter tedit monitor to get ops
rope: Rope.Ref ← TextEdit.GetRope[GetDataNode[comArg]];
h: Handle ← CreateInputStreamFromRope[rope];
num: INT ← GetInt[h ! Error => GOTO BadNum];
IF num ~IN [0..9] THEN GOTO BadNum;
ShowOps[TEditOps.GetCommand[Inline.LowHalf[num]]];
EXITS BadNum => { OPEN MessageWindow;
Append["Enter number from 0 to 9 in Command Number field", TRUE];
Blink[] } };
----------------------------
comButton: Buttons.Button;
comArg: ViewerClasses.Viewer;
comNumAtom: ATOM = $EditToolCommandNumber;
ComNumButton: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,comNumAtom]
ELSE [] ← DoComNumOp[] };
DoComNumOp: TEditOps.CommandProc = { DataFieldButton[comArg] };
BuildComNumField: PUBLIC PROC = {
[comButton,comArg] ← BuildDataFieldPair["Command number [0..9]:", ComNumButton, 1];
TEditOps.SetTextContents[comArg, "1 "]; };
----------------------------
----------------------------
doItAtom: ATOM = $EditToolDoIt;
DoIt: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,doItAtom]
ELSE [] ← DoItOp[] };
DoItOp: TEditOps.CommandProc = {
pSel: TEditDocument.Selection;
params: LIST OF REF ANY;
IF doReplace THEN { DoReplace[]; RETURN };
IF (pSel ← TEditOps.GetSelData[])=NIL OR pSel.viewer=NIL OR pSel.viewer.class.flavor#$Text OR
(params ← GetOps[])=NIL THEN { UserTerminal.BlinkDisplay[]; RETURN };
IF mainEditTool THEN TEditOps.SneakyInterpret[pSel.viewer, params]
ELSE TEditOps.InterpretInput[pSel.viewer, params] };
tSel: PUBLIC TEditDocument.Selection ← NEW[TEditDocument.SelectionRec];
DoReplace: PROC = {
-- for now do it as a delete followed by a copy
-- to do the copy, must make source the secondary selection
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
tdd: TEditDocument.TEditDocumentData = NARROW[sourceArg.data];
node: TextNode.RefTextNode ← GetDataNode[sourceArg];
size: TextNode.Offset;
runs: TextLooks.Runs;
initCap: BOOLEAN;
IF pSel=NIL OR pSel.viewer=NIL OR pSel.viewer.class.flavor#$Text THEN {
UserTerminal.BlinkDisplay[]; RETURN };
SELECT looksChoice FROM
looksOnly => {
targetLooks: TextLooks.Looks ← GetDataLooks[targetArg,"Target"];
sourceLooks: TextLooks.Looks ← GetDataLooks[sourceArg,"Source"];
TEditInputOps.ChangeLooks[sourceLooks,targetLooks];
RETURN };
textOnly => IF node#NIL THEN {
runs ← node.runs; -- save source looks
TextEdit.SetLooks[node,GetSelInitLooks[pSel]] };
textAndLooks => NULL;
ENDCASE => ERROR;
initCap ← forceInitCap AND IsSelInitCap[pSel];
TEditOps.OpenRepeatSequence[];
TEditInputOps.Delete[];
IF (size ← TextEdit.Size[node]) = 0 THEN RETURN; -- no source
tSel.start.pos ← [node,0];
tSel.end.pos ← tSel.clickPoint ← [node,size];
tSel.granularity ← char;
tSel.viewer ← sourceArg;
tSel.data ← tdd;
tSel.insertion ← before;
TEditOps.SetSelData[tSel,FALSE];
TEditInputOps.Copy[];
IF looksChoice=textOnly AND node#NIL THEN node.runs ← runs; -- restore source
IF initCap AND IsSelInitLower[pSel] THEN TEditInputOps.Capitalise[firstCap];
};
GetSelInitLooks: PROC [pSel: TEditDocument.Selection] RETURNS [TextLooks.Looks] = {
node: TextNode.RefTextNode ← TextNode.NarrowToTextNode[pSel.start.pos.node];
loc: TextNode.Offset ← pSel.start.pos.where;
IF node=NIL OR loc=TextNode.NodeItself OR loc=TextEdit.Size[node]
THEN RETURN [TextLooks.noLooks];
RETURN [TextEdit.FetchLooks[node,loc]] };
IsSelInitCap: PROC [pSel: TEditDocument.Selection] RETURNS [BOOLEAN] = {
node: TextNode.RefTextNode ← TextNode.NarrowToTextNode[pSel.start.pos.node];
loc: TextNode.Offset ← pSel.start.pos.where;
IF node=NIL OR loc=TextNode.NodeItself OR loc=TextEdit.Size[node]
THEN RETURN [FALSE];
RETURN [TextEdit.FetchChar[node,loc] IN ['A..'Z]] };
IsSelInitLower: PROC [pSel: TEditDocument.Selection] RETURNS [BOOLEAN] = {
node: TextNode.RefTextNode ← TextNode.NarrowToTextNode[pSel.start.pos.node];
loc: TextNode.Offset ← pSel.start.pos.where;
IF node=NIL OR loc=TextNode.NodeItself OR loc=TextEdit.Size[node]
THEN RETURN [FALSE];
RETURN [TextEdit.FetchChar[node,loc] IN ['a..'z]] };
doYesAtom: ATOM = $EditToolDoYes;
DoYes: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,doYesAtom]
ELSE [] ← DoYesOp[] };
DoYesOp: TEditOps.CommandProc = { [] ← DoItOp[]; Search[TRUE] };
doNoAtom: ATOM = $EditToolDoNo;
DoNo: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,doNoAtom]
ELSE [] ← DoNoOp[] };
DoNoOp: TEditOps.CommandProc = { Search[TRUE] };
----------------------------
subsRangeButton: Buttons.Button;
subsRangeLabel: Labels.Label;
subsRange: PUBLIC [0..2] ← withinSel;
withinSelRope: Rope.Ref = "Within Selection Only";
afterSelRope: Rope.Ref = "After Selection Only";
entireDocRope: Rope.Ref = "In Entire Document";
withinSelAtom: ATOM = $EditToolSubInSel;
afterSelAtom: ATOM = $EditToolSubAfterSel;
entireDocAtom: ATOM = $EditToolSubEntireDoc;
BuildSubstituteEntry: PUBLIC PROC = {
[subsRangeLabel,subsRangeButton] ← BuildTriple[SubsRangeButton, withinSel,
withinSelRope, afterSelRope, entireDocRope] };
SubsRangeButton: Buttons.ButtonProc = {
IF mainEditTool THEN
CycleTriple[subsRangeLabel, subsRange, withinSelAtom, afterSelAtom, entireDocAtom]
ELSE SELECT subsRange FROM
withinSel => [] ← SubsAfterOp[];
afterSel => [] ← SubsEntireDocOp[];
entireDoc => [] ← SubsWithinOp[];
ENDCASE => ERROR };
SubsWithinOp: TEditOps.CommandProc = {
subsRange ← withinSel;
Labels.Set[subsRangeLabel,withinSelRope] };
SubsAfterOp: TEditOps.CommandProc = {
subsRange ← afterSel;
Labels.Set[subsRangeLabel,afterSelRope] };
SubsEntireDocOp: TEditOps.CommandProc = {
subsRange ← entireDoc;
Labels.Set[subsRangeLabel,entireDocRope] };
GetLooksAndPatternInfo: PUBLIC PROC [pattern: TextNode.RefTextNode]
RETURNS [pat: TextNode.RefTextNode,
ignoreLooks, lit: BOOLEAN,
searchLooks: TextLooks.Looks] = {
pat ← pattern; lit ← literal; searchLooks ← TextLooks.noLooks;
SELECT looksChoice FROM
looksOnly => {
size: TextNode.Offset = TextEdit.Size[pattern];
searchLooks ← IF size=0 THEN TextLooks.noLooks
ELSE TextEdit.FetchLooks[pattern,0];
FOR i: TextNode.Offset IN [1..size) DO
IF TextEdit.FetchLooks[pattern,i]#searchLooks THEN {
OPEN MessageWindow;
Append["Pattern does not have uniform looks.",TRUE];
Append[" Using looks from first char."];
Blink[]; EXIT };
ENDLOOP;
ignoreLooks ← lit ← FALSE;
pat ← TextEdit.FromRope["#*"];
TextEdit.SetLooks[pat,searchLooks] };
textOnly => ignoreLooks ← TRUE;
textAndLooks => ignoreLooks ← FALSE;
ENDCASE => ERROR };
doSubsAtom: ATOM = $EditToolSubstitute;
DoSubstitute: Buttons.ButtonProc = {
IF mainEditTool THEN TEditOps.InterpretAtom[button,doSubsAtom]
ELSE [] ← DoSubstituteOp[] };
DoSubstituteOp: TEditOps.CommandProc = {
finder: TreeFind.Finder;
first, last, selStart, selEnd: TextNode.Ref;
firstText, lastText: TextNode.RefTextNode;
lastWhere: TextNode.RefTextNode;
pattern: TextNode.RefTextNode;
start, lastLen: TextNode.Offset;
count: LONG INTEGER;
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
vwr: ViewerClasses.Viewer;
data: TEditDocument.TEditDocumentData;
insertion: TEditDocument.BeforeAfter;
granularity: TEditDocument.SelectionGrain;
ignoreLooks, lit: BOOLEAN;
searchLooks: TextLooks.Looks;
IF CheckPSel[pSel]=FALSE OR (pattern ← GetPatternNode[])=NIL THEN RETURN;
vwr ← pSel.viewer;
[pattern,ignoreLooks,lit,searchLooks] ← GetLooksAndPatternInfo[pattern];
SELECT subsRange FROM
withinSel => {
first ← pSel.start.pos.node;
last ← pSel.end.pos.node;
start ← pSel.start.pos.where;
lastLen ← pSel.end.pos.where };
afterSel => {
first ← pSel.end.pos.node;
last ← NIL;
start ← pSel.end.pos.where+1;
lastLen ← 0 };
entireDoc => {
first ← TextNode.Root[pSel.start.pos.node];
last ← NIL;
start ← 0;
lastLen ← 0 };
ENDCASE => ERROR;
data ← pSel.data;
insertion ← pSel.insertion;
granularity ← pSel.granularity;
selStart ← pSel.start.pos.node;
selEnd ← pSel.end.pos.node;
IF (firstText ← TextNode.NarrowToTextNode[selStart]) # NIL THEN
NodeAddrs.PutTextAddr[firstText,$Start,pSel.start.pos.where];
IF (lastText ← TextNode.NarrowToTextNode[selEnd]) # NIL THEN
NodeAddrs.PutTextAddr[lastText,$End,pSel.end.pos.where];
{ ENABLE TextFind.MalformedPattern => { OPEN MessageWindow;
Append[SELECT ec FROM
toobig => "Search pattern is too big",
endquote => "Search pattern incorrectly ends with quote",
boundary => "Search pattern incorrectly has | inside rather than at beginning or end",
ENDCASE => "Error in search pattern", TRUE];
Blink[];
GOTO Quit };
MakeSel: PROC [where: TextNode.RefTextNode, at, atEnd:TextNode.Offset] = {
tSel.start.pos ← [where,at];
tSel.end.pos ← [where,MAX[0,atEnd-1]];
tSel.granularity ← char;
tSel.viewer ← vwr;
tSel.data ← pSel.data;
tSel.insertion ← after;
TEditOps.SetSelData[tSel];
TEditOps.AutoScroll[FALSE];
};
DoSubs: PROC [where: TextNode.RefTextNode, at, atEnd, before, after: TextNode.Offset]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: TextNode.Offset] = {
len: TextNode.Offset ← atEnd-at;
size: TextNode.Offset ← TextEdit.Size[where];
initCap: BOOLEAN ← forceInitCap AND
at < size AND TextEdit.FetchChar[where,at] IN ['A..'Z];
initLooks: TextLooks.Looks;
IF interrupt THEN { continue ← FALSE; RETURN };
continue ← bumpCount ← TRUE;
SELECT looksChoice FROM
looksOnly => {
IF looksChoice=looksOnly AND ~word THEN {
[at,atEnd] ← Extend[TRUE,searchLooks,where,at,atEnd,last,lastLen];
len ← atEnd-at };
TextEdit.ChangeLooks[where,targetLooks,sourceLooks,
at,len,event];
from ← at+len; delta ← 0; RETURN };
textOnly => initLooks ← IF at < size THEN
TextEdit.FetchLooks[where,at] ELSE TextLooks.noLooks;
textAndLooks => NULL;
ENDCASE => ERROR;
--MakeSel[where,at,atEnd];
[] ← TextEdit.ReplaceByText[where,at,len,
sourceRope,sourceRuns,sourceStart,sourceLen,event];
IF initCap AND sourceLen > 0 AND TextEdit.FetchChar[where,at] IN ['a..'z] THEN
TextEdit.ChangeCaps[where,at,1,firstCap,event];
IF looksChoice=textOnly THEN
TextEdit.SetLooks[where,initLooks,at,sourceLen,event];
--TEditOps.PaintEdits[pSel];
from ← at+sourceLen; delta ← sourceLen-len };
DoOps: PROC [where: TextNode.RefTextNode, at, atEnd, before, after: TextNode.Offset]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: TextNode.Offset] = {
len: TextNode.Offset ← atEnd-at;
size: TextNode.Offset ← TextEdit.Size[where];
IF interrupt THEN { continue ← FALSE; RETURN };
MakeSel[where,at,atEnd];
IF where # lastWhere AND lastWhere # NIL THEN
NodeAddrs.RemTextAddr[lastWhere,$After];
lastWhere ← where;
NodeAddrs.PutTextAddr[where,$After,atEnd];
IF mainEditTool THEN TEditOps.SneakyInterpret[vwr, params]
ELSE TEditOps.InterpretInput[vwr, params];
delta ← NodeAddrs.GetTextAddr[where,$After]-atEnd;
from ← atEnd+delta; continue ← bumpCount ← TRUE };
source: TextNode.RefTextNode ← GetDataNode[sourceArg];
sourceStart, sourceLen, sourceEnd: TextNode.Offset;
sourceRope: Rope.Ref;
sourceRuns: TextLooks.Runs;
targetLooks, sourceLooks: TextLooks.Looks;
size: TextNode.Offset ← TextEdit.Size[source];
event: UndoEvent.Ref ← TEditOps.CurrentEvent[];
params: LIST OF REF ANY;
interrupt ← FALSE;
IF source # NIL THEN { sourceRope ← source.rope; sourceRuns ← source.runs };
sourceStart ← 0; sourceLen ← size; sourceEnd ← sourceStart+sourceLen;
finder ← TreeFind.Create[pattern,lit,word,ignoreLooks,ignoreCase];
IF ~doReplace THEN {
IF (params ← GetOps[])=NIL THEN {
UserTerminal.BlinkDisplay[]; RETURN }}
ELSE IF looksChoice=looksOnly THEN {
targetLooks ← GetDataLooks[targetArg,"Target"];
sourceLooks ← GetDataLooks[sourceArg,"Source"] };
TEditOps.OpenRepeatSequence;
count ← TreeFind.Apply[finder,first,
IF doReplace THEN DoSubs ELSE DoOps,
start,last,lastLen,looksExact];
};
-- update the selection
tSel.start.pos ← [selStart,
IF firstText=NIL THEN TextNode.NodeItself
ELSE NodeAddrs.GetTextAddr[firstText,$Start]];
tSel.end.pos ← tSel.clickPoint ← [selEnd,
IF lastText=NIL THEN TextNode.NodeItself
ELSE NodeAddrs.GetTextAddr[lastText,$End]];
IF firstText#NIL THEN NodeAddrs.RemTextAddr[firstText,$Start];
IF lastText#NIL THEN NodeAddrs.RemTextAddr[lastText,$End];
IF lastWhere#NIL THEN NodeAddrs.RemTextAddr[lastWhere,$After];
tSel.granularity ← granularity;
tSel.viewer ← vwr;
tSel.data ← data;
tSel.insertion ← insertion;
-- repaint
IF subsRange=withinSel THEN {
TEditOps.SetSelData[tSel,TRUE,FALSE];
TEditOps.PaintEdits[tSel] }
ELSE {
TEditOps.SetSelData[NIL]; -- clear it
ViewerOps.PaintViewer[vwr];
TEditOps.SetSelData[tSel] };
IF count > 0 THEN ViewerOps.SetNewVersion[vwr];
-- display the number of substitutions made
MessageWindow.Append[
Rope.Concat[Convert.ValueToRope[[signed[count,10]]],
IF count # 1 THEN " substitutions." ELSE " substitution."], TRUE];
EXITS Quit => RETURN;
};
RegisterSubs: PUBLIC PROC = {
TEditOps.Register[doSubsAtom, DoSubstituteOp];
TEditOps.Register[sourceArgAtom, SourceArgOp];
TEditOps.Register[opsAtom, OpsArgOp];
TEditOps.Register[comNumAtom, DoComNumOp];
TEditOps.Register[doItAtom, DoItOp];
TEditOps.Register[doYesAtom, DoYesOp];
TEditOps.Register[doNoAtom, DoNoOp];
TEditOps.Register[doOpsAtom, DoOpsOp];
TEditOps.Register[doReplaceAtom, DoReplaceOp];
TEditOps.Register[forceInitCapAtom, ChangeInitCapOp];
TEditOps.Register[ignoreInitCapAtom, LeaveInitCapOp];
TEditOps.Register[withinSelAtom, SubsWithinOp];
TEditOps.Register[afterSelAtom, SubsAfterOp];
TEditOps.Register[entireDocAtom, SubsEntireDocOp];
};
UnRegisterSubs: PUBLIC PROC = {
TEditOps.UnRegister[doSubsAtom];
TEditOps.UnRegister[sourceArgAtom];
TEditOps.UnRegister[opsAtom];
TEditOps.UnRegister[comNumAtom];
TEditOps.UnRegister[doItAtom];
TEditOps.UnRegister[doYesAtom];
TEditOps.UnRegister[doNoAtom];
TEditOps.UnRegister[doOpsAtom];
TEditOps.UnRegister[doReplaceAtom];
TEditOps.UnRegister[forceInitCapAtom];
TEditOps.UnRegister[ignoreInitCapAtom];
TEditOps.UnRegister[withinSelAtom];
TEditOps.UnRegister[afterSelAtom];
TEditOps.UnRegister[entireDocAtom];
};
}...