EditToolSubsImpl.mesa
Paxton on January 3, 1983 9:49 am
McGregor on August 30, 1982 2:40 pm
Russ Atkinson, September 26, 1983 6:00 pm
DIRECTORY
EditToolPrivate,
EditToolBuilder,
Buttons,
Convert,
EditNotify,
IO,
UndoEvent,
Labels,
List,
Menus,
MessageWindow,
NameSymbolTable,
NodeAddrs,
NodeProps,
NodeStyle,
Rope,
RopeEdit,
RopeReader,
RunReader,
TextEdit,
TextFind,
TextLooks,
TextLooksSupport,
TextNode,
TEditDisplay,
TEditDocument,
TEditHistory,
TEditInput,
TEditInputOps,
TEditLocks,
TEditOps,
TEditRefresh,
TEditSelection,
TEditTouchup,
TreeFind,
ViewerOps,
ViewerClasses,
ViewerMenus;
EditToolSubsImpl:
CEDAR PROGRAM
IMPORTS
EditToolPrivate, EditToolBuilder, --Buttons,-- Convert, Labels, MessageWindow, NodeAddrs, NameSymbolTable, NodeProps, NodeStyle, Rope, RopeReader, TEditOps, TextEdit, TextFind, TextNode, TextLooks, TEditInput, TEditInputOps, TEditLocks, TEditRefresh, TEditSelection, TreeFind
EXPORTS EditToolPrivate
SHARES Rope
= { OPEN ViewerClasses, EditToolBuilder, EditToolPrivate;
----------------------------
Offset: TYPE = TextNode.Offset;
----------------------------
sourceArgAtom: LIST OF REF = Register[$ReplaceBy,SourceArgOp];
clearSourceArgAtom: LIST OF REF = Register[$ClearReplaceBy,ClearSourceArgOp];
SourceButton: Buttons.ButtonProc = {
DoButton[sourceArgAtom, clearSourceArgAtom, mouseButton=red] };
SourceArgOp: TEditInput.CommandProc = { SourceArg[mainToolInfo] };
SourceArg: PROC [info: Info] = { SavePSel; DataFieldButton[info.sourceArg,FALSE] };
ClearSourceArgOp: TEditInput.CommandProc = { ClearSourceArg[mainToolInfo] };
ClearSourceArg: PROC [info: Info] = { SavePSel; DataFieldButton[info.sourceArg,TRUE] };
BuildSourceEntry:
PUBLIC
PROC [info: Info] = {
OPEN info;
[,sourceArg] ← BuildDataFieldPair[layout, "Replacement:", SourceButton, info, 2] };
----------------------------
replaceRope: Rope.ROPE = "Replace";
subsRope: Rope.ROPE = "Substitute";
BuildDoItEntries:
PUBLIC
PROC [info: Info] = {
OPEN info;
substituteButton ← BuildButton[layout, "Substitute", DoSubstitute, info, TRUE];
[] ← BuildButton[layout, "Yes", DoYes, info];
[] ← BuildButton[layout, "No", DoNo, info];
doitButton ← BuildButton[layout, "Replace", DoIt, info];
[] ← BuildButton[layout, "Count", DoCount, info];
};
DoSubstituteMenuButton:
PUBLIC Menus.MenuProc = {
DoSubstitute[NARROW[parent], clientData, mouseButton] };
DoYesMenuButton:
PUBLIC Menus.MenuProc = {
DoYes[NARROW[parent], clientData, mouseButton] };
DoNoMenuButton:
PUBLIC Menus.MenuProc = {
DoNo[NARROW[parent], clientData, mouseButton] };
DoItMenuButton:
PUBLIC Menus.MenuProc = {
DoIt[NARROW[parent], clientData, mouseButton] };
DoCountMenuButton:
PUBLIC Menus.MenuProc = {
DoCount[NARROW[parent], clientData, mouseButton] };
----------------------------
replaceOperation: Rope.ROPE = "Do Replace";
specifiedOperation: Rope.ROPE = "Do Operations";
doOperationsAtom: LIST OF REF = Register[$DoOperations,DoOperationsOp];
doReplaceAtom: LIST OF REF = Register[$DoReplace,DoReplaceOp];
OperationButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.doReplace,doReplaceAtom,doOperationsAtom] };
DoOperationsOp: TEditInput.CommandProc = { DoOperations[mainToolInfo] };
DoOperations:
PROC [info: Info] = {
OPEN info;
doReplace ← FALSE;
Labels.Set[operationLabel, specifiedOperation] };
DoReplaceOp: TEditInput.CommandProc = { DoRep[mainToolInfo] };
DoRep:
PROC [info: Info] = {
OPEN info;
doReplace ← TRUE;
Labels.Set[operationLabel, replaceOperation] };
BuildOperationEntry:
PUBLIC
PROC [info: Info] = {
OPEN info;
doReplace ← TRUE;
[operationLabel,] ← BuildPair[layout,OperationButton,
doReplace,replaceOperation,specifiedOperation,info] };
----------------------------
----------------------------
forcingInitCap: Rope.ROPE = "First cap like replaced";
ignoringInitCap: Rope.ROPE = "Don't change caps";
forceInitCapAtom: LIST OF REF = Register[$ChangeInitCap,ChangeInitCapOp];
ignoreInitCapAtom: LIST OF REF = Register[$LeaveInitCap,LeaveInitCapOp];
InitCapButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.forceInitCap,
forceInitCapAtom,ignoreInitCapAtom] };
ChangeInitCapOp: TEditInput.CommandProc = { ChangeInitCap[mainToolInfo] };
ChangeInitCap:
PROC [info: Info] = {
OPEN info;
forceInitCap ← TRUE;
Labels.Set[initCapLabel,forcingInitCap] };
LeaveInitCapOp: TEditInput.CommandProc = { LeaveInitCap[mainToolInfo] };
LeaveInitCap:
PROC [info: Info] = {
OPEN info;
forceInitCap ← FALSE;
Labels.Set[initCapLabel,ignoringInitCap] };
BuildInitCapEntry:
PUBLIC
PROC [info: Info] = {
OPEN info;
forceInitCap ← TRUE;
[initCapLabel,] ← BuildPair[layout,InitCapButton,
forceInitCap,forcingInitCap,ignoringInitCap,info] };
doSubsAtom: LIST OF REF = Register[$DoSubstitute,DoSubstituteOp];
DoSubstitute: Buttons.ButtonProc = {
DoButton[doSubsAtom] };
DoSubstituteOp: TEditInput.CommandProc = { DoSubstituteCom[mainToolInfo] };
DoSubstituteCom:
PROC [info: Info, countOnly:
BOOLEAN ←
FALSE] = {
OPEN info;
subsinfo: SubsInfo ← TextNode.pZone.NEW[SubsInfoRec];
root: TextNode.Ref;
{ OPEN subsinfo;
first, selStart, selEnd: TextNode.Ref;
firstText, lastText: TextNode.RefTextNode;
lastWhere: TextNode.RefTextNode;
pattern: TextNode.RefTextNode;
commentControl: TreeFind.CommentControl;
type: TextNode.TypeName;
style: NameSymbolTable.Name;
start: Offset;
count: LONG INTEGER;
pSel: TEditDocument.Selection;
vwr: ViewerClasses.Viewer;
data: TEditDocument.TEditDocumentData;
insertion: TEditDocument.BeforeAfter;
granularity: TEditDocument.SelectionGrain;
lit: BOOLEAN;
source: TextNode.RefTextNode ← GetDataNode[sourceArg];
size: Offset ← TextEdit.Size[source];
params: LIST OF REF ANY;
MakeSel:
PROC [where: TextNode.RefTextNode, at, atEnd:Offset] = {
tSel.start.pos ← [where,at];
tSel.end.pos ← [where,MAX[0,atEnd-1]];
tSel.granularity ← char;
tSel.viewer ← vwr;
tSel.data ← data;
tSel.insertion ← after;
TEditSelection.MakeSelection[new: tSel];
};
CountOnly:
PROC [where: TextNode.RefTextNode, at, atEnd, before, after: Offset]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: Offset] = {
IF interrupt^ THEN { continue ← FALSE; RETURN };
continue ← bumpCount ← TRUE;
from ← atEnd; delta ← 0 };
DoSubs:
PROC [where: TextNode.RefTextNode, at, atEnd, before, after: Offset]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: Offset] = {
varRope ← where.rope;
varRuns ← where.runs;
[continue, bumpCount, from, delta] ←
DoOneSubs[info, root, where, at, atEnd, subsinfo, vwr] };
DoOps:
PROC [where: TextNode.RefTextNode, at, atEnd, before, after: Offset]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: Offset] = {
len: Offset ← atEnd-at;
size: 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];
TEditInput.Interpret[vwr, params];
delta ← NodeAddrs.GetTextAddr[where,$After].location-atEnd;
from ← atEnd+delta; continue ← bumpCount ← TRUE };
event ← TEditInput.CurrentEvent[];
substitute ← TRUE;
TEditSelection.LockSel[primary, "DoSubstituteCom"];
FixPSel[];
pSel ← TEditOps.GetSelData[];
IF (~countOnly
AND ~TEditInputOps.CheckReadonly[pSel])
OR (root ← TEditSelection.SelectionRoot[pSel])=NIL
OR CheckForSubs[info,pSel]=FALSE OR (pattern ← GetPatternNode[info])=NIL
THEN { TEditSelection.UnlockSel[primary]; RETURN };
vwr ← pSel.viewer;
[pattern,lit,searchLooks,type,style,commentControl] ←
GetLooksAndPatternInfo[pattern,info];
SELECT subsRange
FROM
withinSel => {
first ← pSel.start.pos.node;
last ← pSel.end.pos.node;
start ← pSel.start.pos.where;
lastLen ← pSel.end.pos.where+1 };
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;
tSel^ ← pSel^;
[] ← TEditLocks.Lock[root, "DoSubstituteCom"];
IF (firstText ← TextNode.NarrowToTextNode[selStart]) #
NIL
THEN
NodeAddrs.PutTextAddr[firstText,$Start,tSel.start.pos.where];
IF (lastText ← TextNode.NarrowToTextNode[selEnd]) #
NIL
THEN
NodeAddrs.PutTextAddr[lastText,$End,tSel.end.pos.where+1];
interrupt^ ← FALSE;
IF source #
NIL
AND ~countOnly
AND doReplace
THEN {
sourceType ← source.typename;
IF ~ignoreStyle THEN sourceStyle ← NodeStyle.StyleNameForNode[source];
sourceComment ← source.comment;
sourceRope ← source.rope;
sourceRuns ← source.runs };
sourceLen ← size;
IF ~ignoreLooks
OR ~ignoreText
THEN
-- create a description of the pattern
finder ← TreeFind.Create[
pattern,lit,searchWhere=words,ignoreLooks,ignoreCase,searchWhere=nodes !
TextFind.MalformedPattern => { ReportPatternError[ec]; GOTO Quit }];
IF ~countOnly
AND ~doReplace
THEN {
-- doing specified operations
IF (params ← GetOps[info])=
NIL
THEN {
OPEN MessageWindow;
Append["Specify operations to be performed.", TRUE];
Blink[]; TEditSelection.UnlockDocAndPSel[root]; RETURN }}
ELSE
IF doReplace
AND ignoreText
AND ~ignoreLooks
THEN {
targetLooks ← GetDataLooks[targetArg,"\"Search for\" field"];
IF ~countOnly THEN sourceLooks ← GetDataLooks[sourceArg,"\"Replace by\" field"] };
IF ~countOnly
THEN {
TEditSelection.Deselect[]; -- clear selection
IF doReplace AND ~literal THEN rdr ← RopeReader.Create[] };
IF ~countOnly AND ~doReplace THEN TEditSelection.LockSel[primary , "DoSubstituteCom"];
count ← TreeFind.Apply[finder,first,
IF countOnly THEN CountOnly ELSE IF doReplace THEN DoSubs ELSE DoOps,
start,last,lastLen,looksExact,commentControl,~ignoreType,type,
~ignoreStyle,style,NodeStyle.StyleNameForNode];
IF ~countOnly AND ~doReplace THEN TEditSelection.UnlockSel[primary];
-- update the selection
tSel.start.pos ← [selStart,
IF firstText=NIL THEN TextNode.NodeItself
ELSE NodeAddrs.GetTextAddr[firstText,$Start].location];
tSel.end.pos ← [selEnd,
IF lastText=NIL THEN TextNode.NodeItself
ELSE MAX[NodeAddrs.GetTextAddr[lastText,$End].location,1]-1];
IF selStart=selEnd THEN tSel.end.pos.where ← MAX[tSel.start.pos.where, tSel.end.pos.where];
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;
IF ~countOnly THEN TEditSelection.MakeSelection[new: tSel]; -- restore selection
TEditSelection.UnlockDocAndPSel[root];
-- display the number of substitutions made
MessageWindow.Append[
Rope.Concat[Convert.RopeFromInt[count],
IF countOnly THEN IF count # 1 THEN " matches." ELSE " match."
ELSE IF count # 1 THEN " substitutions." ELSE " substitution."], TRUE];
EXITS Quit => { TEditSelection.UnlockDocAndPSel[root]; RETURN };
}};
DoOneSubs:
PROC [info: Info, root: TextNode.Ref, where: TextNode.RefTextNode, at, atEnd: Offset,
subsinfo: SubsInfo, viewer: ViewerClasses.Viewer]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: Offset] = { OPEN info, subsinfo;
len: Offset ← atEnd-at;
size: Offset ← TextEdit.Size[where];
initCap:
BOOLEAN ← forceInitCap
AND
at < size AND TextEdit.FetchChar[where,at] IN ['A..'Z];
initLower:
BOOLEAN ← forceInitCap
AND
at < size AND TextEdit.FetchChar[where,at] IN ['a..'z];
initLooks: TextLooks.Looks;
DoType:
PROC = {
IF ~ignoreType
AND where.typename # sourceType
THEN
TextEdit.ChangeType[where,sourceType,event,root];
};
DoStyle:
PROC = {
IF ~ignoreStyle
AND NodeStyle.StyleNameForNode[where] # sourceStyle
THEN {
styleRope ← NameSymbolTable.RopeFromName[sourceStyle];
TextEdit.ChangeStyle[where,styleRope,event,root] };
};
DoComment:
PROC = {
IF ~ignoreComment
AND where.comment # sourceComment
THEN
TextEdit.PutProp[where, "Comment",
IF sourceComment THEN NodeProps.true ELSE NodeProps.false, event, root];
};
IF interrupt^ THEN { continue ← FALSE; RETURN };
continue ← bumpCount ← TRUE; from ← atEnd; delta ← 0;
SELECT
TRUE
FROM
ignoreText
AND ~ignoreLooks => {
-- looks only
IF searchWhere=anywhere
AND substitute
THEN {
-- need to extend to include entire run
[at,atEnd] ← Extend[info,TRUE,searchLooks,where,at,atEnd,last,lastLen];
len ← atEnd-at };
TextEdit.ChangeLooks[root,where,targetLooks,sourceLooks,at,len,event];
from ← at+len;
DoType; DoStyle; DoComment;
RETURN };
ignoreLooks
AND ~ignoreText => initLooks ←
IF at < size
THEN
TextEdit.FetchLooks[where,at] ELSE TextLooks.noLooks;
ENDCASE;
IF ~ignoreText
OR ~ignoreLooks
THEN {
sLen: Offset ← sourceLen;
IF ~literal
THEN {
-- treat source as pattern
end, dest: Offset ← at+len; -- insert after the text to be deleted
litstart: Offset ← 0;
InsertLit:
PROC [after: Offset] = {
litlen: Offset ← after-litstart;
IF litlen <= 0 THEN RETURN;
[] ← TextEdit.ReplaceByText[root,where,dest,0,
sourceRope,sourceRuns,litstart,litlen,event];
dest ← dest+litlen };
RopeReader.SetPosition[rdr,sourceRope,0];
DO
-- read the source
char: CHAR ← RopeReader.Get[rdr ! RopeReader.ReadOffEnd => EXIT];
SELECT char
FROM
'' => {
-- treat next as literal
loc: Offset ← RopeReader.GetIndex[rdr]; -- after the quote
InsertLit[loc-1]; -- to take care of stuff up to the quote
litstart ← loc;
[] ← RopeReader.Get[rdr ! RopeReader.ReadOffEnd => EXIT] };
'< => {
-- read name, insert value
loc: Offset ← RopeReader.GetIndex[rdr]; -- after the <
at, atEnd, after: Offset;
addLooks: TextLooks.Looks;
IF ~ignoreLooks
THEN
-- read looks from the < at the start of the name
addLooks ← TextLooks.FetchLooks[sourceRuns, RopeReader.GetIndex[rdr]-1];
InsertLit[loc-1]; -- to take care of stuff up to the <
DO
-- read to >
IF RopeReader.Get[rdr ! RopeReader.ReadOffEnd =>
EXIT]
= '> THEN EXIT;
ENDLOOP;
after ← RopeReader.GetIndex[rdr]; -- after the >
IF nameRope =
NIL
THEN
nameRope ← TextNode.pZone.NEW[substr node Rope.RopeRep];
nameRope.size ← after-loc-1;
nameRope.base ← sourceRope;
nameRope.start ← loc;
[at,atEnd] ← TextFind.NameLoc[finder,nameRope];
atEnd ← MIN[atEnd,Rope.Size[varRope]];
IF at < atEnd
THEN {
len: Offset ← atEnd-at;
[] ← TextEdit.ReplaceByText[root,where,dest,0,varRope,varRuns,at,len,event];
IF ~ignoreLooks
THEN {
-- change the looks for the subpattern
remLooks: TextLooks.Looks = TextFind.NameLooks[finder, nameRope];
TextEdit.ChangeLooks[root,where,remLooks,addLooks,dest,len,event] };
dest ← dest+len };
litstart ← after;
LOOP };
ENDCASE;
ENDLOOP;
InsertLit[sourceLen];
sLen ← dest-end; -- the length of the replacement text
TextEdit.DeleteText[root,where,at,len,event]
-- delete last to keep selection addrs correct -- }
ELSE [] ← TextEdit.ReplaceByText[root,where,at,len,
sourceRope,sourceRuns,0,sourceLen,event];
IF initCap
AND sourceLen > 0
AND TextEdit.FetchChar[where,at]
IN ['a..'z]
THEN
TextEdit.ChangeCaps[root,where,at,1,allCaps,event]
ELSE IF initLower
AND sourceLen > 0
AND TextEdit.FetchChar[where,at]
IN ['A..'Z]
THEN
TextEdit.ChangeCaps[root,where,at,1,allLower,event];
IF ignoreLooks
THEN
-- just changing the text, so now restore the looks
TextEdit.SetLooks[root,where,initLooks,at,sLen,event];
from ← at+sLen; delta ← sLen-len };
DoType; DoStyle; DoComment };
----------------------------
----------------------------
doItAtom: LIST OF REF = Register[$DoIt,DoItOp];
DoIt: Buttons.ButtonProc = {
DoButton[doItAtom] };
DoItOp: TEditInput.CommandProc = { DoItCom[mainToolInfo] };
DoItCom:
PROC [info: Info] = {
FixPSel[];
IF info.doReplace THEN DoReplaceCom[info] ELSE DoOpsCom[info] };
tSel: PUBLIC TEditDocument.Selection ← NEW[TEditDocument.SelectionRec];
CheckForSubs:
PROC [info: Info, pSel: TEditDocument.Selection]
RETURNS [ok:
BOOLEAN] = {
OPEN info;
IF ignoreText
AND ignoreLooks
AND ignoreType
AND ignoreStyle
AND ignoreComment
THEN {
OPEN MessageWindow;
Append["Pick one or more of text/looks/type/style/comment to replace.", TRUE];
Blink[]; RETURN [FALSE] };
IF ~CheckPSel[pSel] THEN RETURN [FALSE];
RETURN [TRUE] };
DoReplaceCom:
PROC [info: Info] = {
OPEN info;
subsinfo: SubsInfo;
pSel: TEditDocument.Selection;
source: TextNode.RefTextNode ← GetDataNode[sourceArg];
where: TextNode.RefTextNode;
root: TextNode.Ref;
at, atEnd, delta: TextNode.Offset;
TEditSelection.LockSel[primary, "DoReplaceCom"];
FixPSel[];
pSel ← TEditOps.GetSelData[];
IF ~TEditInputOps.CheckReadonly[pSel]
OR (root ← TEditSelection.SelectionRoot[pSel])=NIL
OR CheckForSubs[info,pSel]=FALSE
THEN { TEditSelection.UnlockSel[primary]; RETURN };
IF (where ← TextNode.NarrowToTextNode[pSel.start.pos.node]) # pSel.end.pos.node
THEN {
OPEN MessageWindow;
Append["Selection to replace must be within a single node.", TRUE];
Blink[]; TEditSelection.UnlockSel[primary]; RETURN };
at ← pSel.start.pos.where;
atEnd ← pSel.end.pos.where+1;
subsinfo ← TextNode.pZone.NEW[SubsInfoRec];
{ OPEN subsinfo;
event ← TEditInput.CurrentEvent[];
substitute ← FALSE;
sourceLen ← TextEdit.Size[source];
IF source #
NIL
THEN {
sourceType ← source.typename;
IF ~ignoreStyle THEN sourceStyle ← NodeStyle.StyleNameForNode[source];
sourceComment ← source.comment;
sourceRope ← source.rope;
sourceRuns ← source.runs };
rdr ← RopeReader.Create[];
IF ignoreText
AND ~ignoreLooks
THEN {
-- looks only
targetLooks ← GetDataLooks[targetArg,"\"Search for\" field"];
sourceLooks ← GetDataLooks[sourceArg,"\"Replace by\" field"] };
tSel^ ← pSel^;
[] ← TEditLocks.Lock[root, "DoReplaceCom"];
TEditSelection.Deselect[]; -- remove the selection
delta ← DoOneSubs[info,root,
where,at,atEnd,subsinfo,tSel.viewer].delta;
tSel.end.pos.where ← tSel.end.pos.where + delta;
IF tSel.start.pos.node = tSel.end.pos.node
AND tSel.start.pos.where > tSel.end.pos.where
THEN {
tSel.end.pos.where ← tSel.start.pos.where;
tSel.granularity ← point;
tSel.insertion ← before };
TEditSelection.MakeSelection[new: tSel];
TEditRefresh.ScrollToEndOfSel[tSel.viewer, FALSE];
TEditSelection.UnlockDocAndPSel[root];
}};
GetSelInitLooks:
PROC [pSel: TEditDocument.Selection]
RETURNS [TextLooks.Looks] = {
node: TextNode.RefTextNode ← TextNode.NarrowToTextNode[pSel.start.pos.node];
loc: 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: 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: 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: LIST OF REF = Register[$DoYes,DoYesOp];
doYesBackAtom: LIST OF REF = Register[$DoYesBack,DoYesBackOp];
DoYes: Buttons.ButtonProc = {
DoButton[doYesAtom, doYesBackAtom, mouseButton=red] };
DoYesOp: TEditInput.CommandProc = { DoYesCom[mainToolInfo] };
DoYesCom: PROC [info: Info] = { DoItCom[info]; Search[forwards,info] };
DoYesBackOp: TEditInput.CommandProc = { DoYesBackCom[mainToolInfo] };
DoYesBackCom: PROC [info: Info] = { DoItCom[info]; Search[backwards,info] };
doNoAtom: LIST OF REF = Register[$DoNo,DoNoOp];
doNoBackAtom: LIST OF REF = Register[$DoNoBack,DoNoBackOp];
DoNo: Buttons.ButtonProc = {
DoButton[doNoAtom, doNoBackAtom, mouseButton=red] };
DoNoOp: TEditInput.CommandProc = { DoNoCom[mainToolInfo] };
DoNoCom: PROC [info: Info] = { FixPSel[]; Search[forwards,info] };
DoNoBackOp: TEditInput.CommandProc = { DoNoBackCom[mainToolInfo] };
DoNoBackCom: PROC [info: Info] = { FixPSel[]; Search[backwards,info] };
----------------------------
doCountAtom: LIST OF REF = Register[$DoCount,DoCountOp];
DoCount: Buttons.ButtonProc = {
DoButton[doCountAtom] };
DoCountOp: TEditInput.CommandProc = { DoCountCom[mainToolInfo] };
DoCountCom: PROC [info: Info] = { DoSubstituteCom[info,TRUE] };
----------------------------
withinSelRope: Rope.ROPE = "Within Selection Only";
afterSelRope: Rope.ROPE = "After Selection Only";
entireDocRope: Rope.ROPE = "In Entire Document";
withinSelAtom: LIST OF REF = Register[$SubstituteInSel,SubsWithinOp];
afterSelAtom: LIST OF REF = Register[$SubstituteAfterSel,SubsAfterOp];
entireDocAtom: LIST OF REF = Register[$SubstituteInEntireDoc,SubsEntireDocOp];
BuildSubstituteEntry:
PUBLIC
PROC [info: Info] = {
OPEN info;
subsRange ← entireDoc;
[subsRangeLabel,] ← BuildTriple[layout, SubsRangeButton, subsRange,
withinSelRope, afterSelRope, entireDocRope, info] };
SubsRangeButton: Buttons.ButtonProc = {
CycleTriple[mainToolInfo.subsRange, withinSelAtom, afterSelAtom, entireDocAtom] };
SubsWithinOp: TEditInput.CommandProc = { SubsWithin[mainToolInfo] };
SubsWithin:
PROC [info: Info] = {
OPEN info;
subsRange ← withinSel;
Labels.Set[subsRangeLabel,withinSelRope] };
SubsAfterOp: TEditInput.CommandProc = { SubsAfter[mainToolInfo] };
SubsAfter:
PROC [info: Info] = {
OPEN info;
subsRange ← afterSel;
Labels.Set[subsRangeLabel,afterSelRope] };
SubsEntireDocOp: TEditInput.CommandProc = { SubsEntireDoc[mainToolInfo] };
SubsEntireDoc:
PROC [info: Info] = {
OPEN info;
subsRange ← entireDoc;
Labels.Set[subsRangeLabel,entireDocRope] };
GetLooksAndPatternInfo:
PUBLIC
PROC [pattern: TextNode.RefTextNode, info: Info]
RETURNS [pat: TextNode.RefTextNode,
lit: BOOLEAN,
searchLooks: TextLooks.Looks,
type: TextNode.TypeName,
style: NameSymbolTable.Name,
commentControl: TreeFind.CommentControl] = { OPEN info;
pat ← pattern; lit ← literal; searchLooks ← TextLooks.noLooks;
IF ignoreText
AND ~ignoreLooks
THEN {
-- make a phony search pattern and get the looks
size: Offset = TextEdit.Size[pattern];
searchLooks ←
IF size=0
THEN TextLooks.noLooks
ELSE TextEdit.FetchLooks[pattern,0];
FOR i: Offset
IN [1..size)
DO
IF TextEdit.FetchLooks[pattern,i]#searchLooks
THEN {
OPEN MessageWindow;
Append["Search pattern does not have uniform looks.",TRUE];
Append[" Using looks from first char."];
Blink[]; EXIT };
ENDLOOP;
lit ← FALSE;
pat ← TextEdit.FromRope["#*"];
TextEdit.SetLooks[NIL,pat,searchLooks] };
type ← IF pattern # NIL THEN pat.typename ELSE TextNode.nullTypeName;
style ←
IF ignoreStyle
THEN NameSymbolTable.nullName
ELSE NodeStyle.StyleNameForNode[pattern];
commentControl ←
IF ignoreComment
THEN includeComments
ELSE IF pattern # NIL AND pattern.comment THEN commentsOnly
ELSE excludeComments;
};
}...