EditToolSubsImpl.mesa
Copyright Ó 1985, 1986, 1991, 1992, 1993 by Xerox Corporation. All rights reserved.
Michael Plass, February 25, 1991 4:25 pm PST
Russ Atkinson (RRA) June 18, 1985 5:07:32 pm PDT
Alison Lee September 8, 1986 10:21:02 pm PDT
Doug Wyatt, June 3, 1993 2:41 pm PDT
DIRECTORY
Atom USING [GetPName, GetProp],
Buttons USING [ButtonProc],
Char USING [XCHAR, Set, Narrow, Widen],
Convert USING [RopeFromInt],
EditToolBuilder USING [BuildButton, BuildDataFieldPair, BuildPair, BuildTriple, DataFieldButton, GetDataLooks, GetDataNode],
EditToolPrivate,
Labels USING [Set],
Menus USING [MenuProc],
MessageWindow USING [Append, Blink],
NodeAddrs USING [GetTextAddr, PutTextAddr, RemTextAddr],
NodeStyleOps USING [StyleNameForNode],
Rope USING [Concat, ROPE],
TEditDocument USING [BeforeAfter, Selection, SelectionGrain, SelectionRec, TEditDocumentData],
TEditInput USING [CommandProc, CurrentEvent, Interpret],
TEditInputOps USING [CheckReadonly],
TEditLocks USING [Lock],
TEditOps USING [GetSelData],
TEditRefresh USING [ScrollToEndOfSel],
TEditSelection USING [Deselect, LockSel, MakeSelection, pSel, SelectionRoot, UnlockDocAndPSel, UnlockSel],
TextEdit,
TextNode USING [Root],
Tioga,
TiogaFind,
ViewerClasses USING [Viewer];
EditToolSubsImpl: CEDAR PROGRAM
IMPORTS Atom, Char, Convert, EditToolBuilder, EditToolPrivate, Labels, MessageWindow, NodeAddrs, NodeStyleOps, Rope, TEditInput, TEditInputOps, TEditLocks, TEditOps, TEditRefresh, TEditSelection, TextEdit, TextNode, TiogaFind
EXPORTS EditToolPrivate
= BEGIN
Node: TYPE ~ Tioga.Node;
Viewer: TYPE ~ ViewerClasses.Viewer;
sourceArgAtom: LIST OF REF ~ EditToolPrivate.Register[$ReplaceBy,SourceArgOp];
clearSourceArgAtom: LIST OF REF ~ EditToolPrivate.Register[$ClearReplaceBy,ClearSourceArgOp];
SourceButton: Buttons.ButtonProc ~ {
EditToolPrivate.DoButton[sourceArgAtom, clearSourceArgAtom, mouseButton=red];
};
SourceArgOp: TEditInput.CommandProc ~ {
SourceArg[EditToolPrivate.mainToolInfo];
};
SourceArg: PROC [info: EditToolPrivate.Info] ~ {
EditToolPrivate.SavePSel[];
EditToolBuilder.DataFieldButton[info.sourceArg, FALSE];
};
ClearSourceArgOp: TEditInput.CommandProc ~ {
ClearSourceArg[EditToolPrivate.mainToolInfo];
};
ClearSourceArg: PROC [info: EditToolPrivate.Info] ~ {
EditToolPrivate.SavePSel[];
EditToolBuilder.DataFieldButton[info.sourceArg,TRUE];
};
BuildSourceEntry: PUBLIC PROC [info: EditToolPrivate.Info] ~ {
[,info.sourceArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Replacement:", SourceButton, info, 2];
};
BuildDoItEntries: PUBLIC PROC [info: EditToolPrivate.Info] ~ {
info.substituteButton ¬ EditToolBuilder.BuildButton[info.layout, "Substitute", DoSubstitute, info, TRUE];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Yes", DoYes, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "No", DoNo, info];
info.doitButton ¬ EditToolBuilder.BuildButton[info.layout, "Replace", DoIt, info];
[] ¬ EditToolBuilder.BuildButton[info.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;
specifiedOperation: Rope.ROPE;
doOperationsAtom: LIST OF REF ~ EditToolPrivate.Register[$DoOperations,DoOperationsOp];
doReplaceAtom: LIST OF REF ~ EditToolPrivate.Register[$DoReplace,DoReplaceOp];
OperationButton: Buttons.ButtonProc ~ {
EditToolPrivate.ChangeState[EditToolPrivate.mainToolInfo.doReplace,doReplaceAtom,doOperationsAtom];
};
DoOperationsOp: TEditInput.CommandProc ~ { DoOperations[EditToolPrivate.mainToolInfo] };
DoOperations: PROC [info: EditToolPrivate.Info] ~ {
info.doReplace ¬ FALSE;
Labels.Set[info.operationLabel, specifiedOperation];
};
DoReplaceOp: TEditInput.CommandProc ~ { DoRep[EditToolPrivate.mainToolInfo] };
DoRep: PROC [info: EditToolPrivate.Info] ~ {
info.doReplace ¬ TRUE;
Labels.Set[info.operationLabel, replaceOperation];
};
BuildOperationEntry: PUBLIC PROC [info: EditToolPrivate.Info, realNames: BOOL ¬ FALSE] ~ {
info.doReplace ¬ TRUE;
IF realNames THEN {
replaceOperation ¬ "DoReplace";
specifiedOperation ¬ "DoOperations";
}
ELSE {
replaceOperation ¬ "Do Replace";
specifiedOperation ¬ "Do Operations";
};
[info.operationLabel,] ¬ EditToolBuilder.BuildPair[info.layout,OperationButton,
info.doReplace,replaceOperation,specifiedOperation,info];
};
forcingInitCap: Rope.ROPE;
ignoringInitCap: Rope.ROPE;
forceInitCapAtom: LIST OF REF ~ EditToolPrivate.Register[$ChangeInitCap,ChangeInitCapOp];
ignoreInitCapAtom: LIST OF REF ~ EditToolPrivate.Register[$LeaveInitCap,LeaveInitCapOp];
InitCapButton: Buttons.ButtonProc ~ {
EditToolPrivate.ChangeState[EditToolPrivate.mainToolInfo.forceInitCap,
forceInitCapAtom,ignoreInitCapAtom];
};
ChangeInitCapOp: TEditInput.CommandProc ~ { ChangeInitCap[EditToolPrivate.mainToolInfo] };
ChangeInitCap: PROC [info: EditToolPrivate.Info] ~ {
info.forceInitCap ¬ TRUE;
Labels.Set[info.initCapLabel,forcingInitCap];
};
LeaveInitCapOp: TEditInput.CommandProc ~ { LeaveInitCap[EditToolPrivate.mainToolInfo] };
LeaveInitCap: PROC [info: EditToolPrivate.Info] ~ {
info.forceInitCap ¬ FALSE;
Labels.Set[info.initCapLabel,ignoringInitCap];
};
BuildInitCapEntry: PUBLIC PROC [info: EditToolPrivate.Info, realNames: BOOL ¬ FALSE] ~ {
info.forceInitCap ¬ TRUE;
IF realNames THEN {
forcingInitCap ¬ "ChangeInitCap";
ignoringInitCap ¬ "LeaveInitCap";
}
ELSE {
forcingInitCap ¬ "First cap like replaced";
ignoringInitCap ¬ "Don't change caps";
};
[info.initCapLabel,] ¬ EditToolBuilder.BuildPair[info.layout,InitCapButton,
info.forceInitCap,forcingInitCap,ignoringInitCap,info];
};
doSubsAtom: LIST OF REF ~ EditToolPrivate.Register[$DoSubstitute,DoSubstituteOp];
DoSubstitute: Buttons.ButtonProc ~ {
EditToolPrivate.DoButton[doSubsAtom];
};
DoSubstituteOp: TEditInput.CommandProc ~ {
DoSubstituteCom[EditToolPrivate.mainToolInfo];
};
DoSubstituteCom: PROC [info: EditToolPrivate.Info, countOnly: BOOL ¬ FALSE] ~ {
subsinfo: EditToolPrivate.SubsInfo ¬ NEW[EditToolPrivate.SubsInfoRec];
root: Node;
first, selStart, selEnd: Node;
firstText, lastText: Node;
lastWhere: Node;
pattern: EditToolPrivate.Pattern;
start: INT;
count: INT;
pSel: TEditDocument.Selection;
vwr: ViewerClasses.Viewer;
data: TEditDocument.TEditDocumentData;
insertion: TEditDocument.BeforeAfter;
granularity: TEditDocument.SelectionGrain;
source: Node ¬ EditToolBuilder.GetDataNode[info.sourceArg];
size: INT ¬ TextEdit.Size[source];
params: LIST OF REF ANY;
MakeSel: PROC [where: Node, at, atEnd: INT] ~ {
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: TiogaFind.ApplyProc ~ {
IF info.interrupt­ THEN { continue ¬ FALSE; RETURN };
continue ¬ bumpCount ¬ TRUE;
from ¬ matchEnd; delta ¬ 0
};
DoSubs: TiogaFind.ApplyProc ~ {
info.subs ¬ subs;
RETURN DoOneSubs[info, root, node, matchStart, matchEnd, subsinfo, vwr];
};
DoOps: TiogaFind.ApplyProc ~ {
len: INT ¬ matchEnd-matchStart;
size: INT ¬ TextEdit.Size[node];
IF info.interrupt­ THEN { continue ¬ FALSE; RETURN };
MakeSel[node,matchStart,matchEnd];
IF node # lastWhere AND lastWhere # NIL THEN
NodeAddrs.RemTextAddr[lastWhere,$After];
lastWhere ¬ node;
NodeAddrs.PutTextAddr[node,$After,matchEnd];
TEditInput.Interpret[vwr, params];
delta ¬ NodeAddrs.GetTextAddr[node,$After].location-matchEnd;
from ¬ matchEnd+delta; continue ¬ bumpCount ¬ TRUE;
};
subsinfo.event ¬ TEditInput.CurrentEvent[];
subsinfo.substitute ¬ TRUE;
TEditSelection.LockSel[primary, "DoSubstituteCom"];
EditToolPrivate.FixPSel[];
pSel ¬ TEditOps.GetSelData[];
IF (NOT countOnly AND NOT TEditInputOps.CheckReadonly[pSel])
OR (root ¬ TEditSelection.SelectionRoot[pSel])=NIL
OR CheckForSubs[info,pSel]=FALSE OR (pattern ¬ EditToolPrivate.GetPattern[info])=NIL
THEN { TEditSelection.UnlockSel[primary]; RETURN };
vwr ¬ pSel.viewer;
SELECT info.subsRange FROM
withinSel => {
first ¬ pSel.start.pos.node;
subsinfo.last ¬ pSel.end.pos.node;
start ¬ pSel.start.pos.where;
subsinfo.lastLen ¬ pSel.end.pos.where+1;
};
afterSel => {
first ¬ pSel.end.pos.node;
subsinfo.last ¬ NIL;
start ¬ pSel.end.pos.where+1;
subsinfo.lastLen ¬ 0;
};
entireDoc => {
first ¬ TextNode.Root[pSel.start.pos.node];
subsinfo.last ¬ NIL;
start ¬ 0;
subsinfo.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 ¬ selStart) # NIL THEN
NodeAddrs.PutTextAddr[firstText,$Start,tSel.start.pos.where];
IF (lastText ¬ selEnd) # NIL THEN
NodeAddrs.PutTextAddr[lastText,$End,tSel.end.pos.where+1];
info.interrupt­ ¬ FALSE;
IF source # NIL AND NOT countOnly AND info.doReplace THEN {
subsinfo.sourceFormat ¬ TextEdit.GetFormat[source];
IF NOT info.ignoreStyle THEN subsinfo.sourceStyle ¬ NodeStyleOps.StyleNameForNode[source];
subsinfo.sourceComment ¬ TextEdit.GetComment[source];
subsinfo.sourceNode ¬ source;
};
subsinfo.sourceLen ¬ size;
IF NOT countOnly AND NOT info.doReplace THEN { -- doing specified operations
IF (params ¬ EditToolPrivate.GetOps[info])=NIL THEN {
MessageWindow.Append["Specify operations to be performed.", TRUE];
MessageWindow.Blink[]; TEditSelection.UnlockDocAndPSel[root]; RETURN
}
}
ELSE IF info.doReplace AND info.ignoreText AND NOT info.ignoreLooks THEN {
subsinfo.targetLooks ¬ EditToolBuilder.GetDataLooks[info.targetArg,"\"Search for\" field"];
IF NOT countOnly THEN subsinfo.sourceLooks ¬ EditToolBuilder.GetDataLooks[info.sourceArg,"\"Replace by\" field"];
};
IF NOT countOnly THEN {
TEditSelection.Deselect[]; -- clear selection
};
IF NOT countOnly AND NOT info.doReplace THEN TEditSelection.LockSel[primary , "DoSubstituteCom"];
count ¬ TiogaFind.Apply[
proc: IF countOnly THEN CountOnly ELSE IF info.doReplace THEN DoSubs ELSE DoOps,
loc1: [first, start], loc2: [subsinfo.last, subsinfo.lastLen],
target: pattern.target, case: pattern.case, match: pattern.match,
checkLooks: pattern.checkLooks, looksExact: pattern.looksExact,
checkComment: pattern.checkComment, comment: pattern.comment,
checkFormat: pattern.checkFormat, format: pattern.format,
checkStyle: pattern.checkStyle, style: pattern.style,
styleProc: NodeStyleOps.StyleNameForNode
];
IF NOT countOnly AND NOT info.doReplace THEN TEditSelection.UnlockSel[primary];
update the selection
tSel.start.pos ¬ [selStart,
IF firstText=NIL THEN Tioga.NodeItself
ELSE NodeAddrs.GetTextAddr[firstText,$Start].location];
tSel.end.pos ¬ [selEnd,
IF lastText=NIL THEN Tioga.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 NOT 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];
{
Attempt to register in EditTool Cafeteria tray if the registry operation is available. This is deferred to this late because, only properly specified commands will be recorded.
cmdPtr: REF ANY ¬ Atom.GetProp[$CafeteriaTrayRegistryAtom, $EditToolAddToTray];
IF cmdPtr # NIL
THEN {
EditToolAddInterfaceProc: TYPE ~ PROC [operation: ATOM, opList: Rope.ROPE ¬ NIL]; -- same as EditToolCafeteria.EditToolAddInterfaceProc
addProcPtr: REF EditToolAddInterfaceProc ¬ NARROW[cmdPtr, REF EditToolAddInterfaceProc];
addProcPtr[$DoSubstitute,
IF NOT info.doReplace THEN EditToolBuilder.GetDataNode[info.opsArg].rope ELSE NIL];
}
};
};
CapClass: TYPE ~ {nil, upper, lower};
GetCapClass: PROC [node: Node, index: INT] RETURNS [CapClass ¬ nil] ~ {
x: Char.XCHAR ~ TextEdit.FetchChar[node, index];
IF Char.Set[x]=0 THEN SELECT Char.Narrow[x] FROM
IN ['A..'Z] => RETURN[upper];
IN ['a..'z] => RETURN[lower];
ENDCASE;
};
DoOneSubs: PROC [info: EditToolPrivate.Info, root: Node, dest: Node, destStart, destEnd: INT,
subsinfo: EditToolPrivate.SubsInfo, viewer: ViewerClasses.Viewer]
RETURNS [continue, bumpCount: BOOL ¬ FALSE, from, delta: INT ¬ 0] ~ {
destLen: INT ~ destEnd-destStart;
source: Node ~ subsinfo.sourceNode;
sourceSize: INT ~ TextEdit.Size[source];
initLooks: Tioga.Looks ¬ Tioga.noLooks;
event: Tioga.Event ~ subsinfo.event;
IF info.interrupt­ THEN { continue ¬ FALSE; RETURN };
continue ¬ bumpCount ¬ TRUE; from ¬ destEnd; delta ¬ 0;
IF NOT info.ignoreText THEN {
replacedCap, resultCap: CapClass ¬ nil;
replacedLooks: Tioga.Looks ¬ Tioga.noLooks;
resultStart, resultLen: INT ¬ 0;
IF destLen>0 THEN {
IF info.ignoreLooks THEN replacedLooks ¬ TextEdit.FetchLooks[dest, destStart];
IF info.forceInitCap THEN replacedCap ¬ GetCapClass[dest, destStart];
};
[resultStart, resultLen] ¬ TiogaFind.Replace[dest: dest, destStart: destStart, destLen: destLen,
source: source, pattern: NOT info.literal, subs: info.subs, event: event];
IF replacedCap#nil AND resultLen>0 THEN resultCap ¬ GetCapClass[dest, resultStart];
IF replacedCap#nil AND resultCap#nil AND replacedCap#resultCap THEN {
TextEdit.ChangeCaps[root: NIL, dest: dest, start: resultStart, len: 1,
how: IF replacedCap=upper THEN allCaps ELSE allLower, event: event]
};
IF info.ignoreLooks THEN {-- just changing the text, so now restore the looks
TextEdit.ChangeLooks[root: root, text: dest,
remove: Tioga.allLooks, add: replacedLooks,
start: resultStart, len: resultLen, event: event];
};
from ¬ resultStart+resultLen; delta ¬ resultLen-destLen;
}
ELSE IF NOT info.ignoreLooks THEN { -- looks only
TextEdit.ChangeLooks[root: root, text: dest,
remove: subsinfo.targetLooks, add: subsinfo.sourceLooks,
start: destStart, len: destLen, event: event];
};
IF NOT info.ignoreComment THEN TextEdit.PutComment[dest,
subsinfo.sourceComment, event];
IF NOT info.ignoreFormat THEN TextEdit.PutFormat[dest,
subsinfo.sourceFormat, event];
IF NOT info.ignoreStyle AND
NodeStyleOps.StyleNameForNode[dest] # subsinfo.sourceStyle THEN {
subsinfo.styleRope ¬ IF subsinfo.sourceStyle=NIL THEN NIL ELSE Atom.GetPName[subsinfo.sourceStyle];
TextEdit.ChangeStyle[dest, subsinfo.styleRope, event];
};
};
doItAtom: LIST OF REF ~ EditToolPrivate.Register[$DoIt, DoItOp];
DoIt: Buttons.ButtonProc ~ { EditToolPrivate.DoButton[doItAtom] };
DoItOp: TEditInput.CommandProc ~ { DoItCom[EditToolPrivate.mainToolInfo] };
DoItCom: PROC [info: EditToolPrivate.Info] ~ {
EditToolPrivate.FixPSel[];
IF info.doReplace THEN DoReplaceCom[info] ELSE EditToolPrivate.DoOpsCom[info];
};
tSel: PUBLIC TEditDocument.Selection ¬ NEW[TEditDocument.SelectionRec];
CheckForSubs: PROC [info: EditToolPrivate.Info, pSel: TEditDocument.Selection] RETURNS [ok: BOOL] ~ {
IF info.ignoreText AND info.ignoreLooks AND info.ignoreFormat
AND info.ignoreStyle AND info.ignoreComment THEN {
MessageWindow.Append["Pick one or more of text/looks/format/style/comment to replace.", TRUE];
MessageWindow.Blink[]; RETURN [FALSE];
};
IF NOT EditToolPrivate.CheckPSel[pSel] THEN RETURN [FALSE];
RETURN [TRUE];
};
DoReplaceCom: PROC [info: EditToolPrivate.Info] ~ {
subsinfo: EditToolPrivate.SubsInfo;
pSel: TEditDocument.Selection;
source: Node ¬ EditToolBuilder.GetDataNode[info.sourceArg];
where: Node;
root: Node;
at, atEnd, delta: INT;
TEditSelection.LockSel[primary, "DoReplaceCom"];
EditToolPrivate.FixPSel[];
pSel ¬ TEditOps.GetSelData[];
IF NOT TEditInputOps.CheckReadonly[pSel]
OR (root ¬ TEditSelection.SelectionRoot[pSel])=NIL
OR CheckForSubs[info,pSel]=FALSE
THEN { TEditSelection.UnlockSel[primary]; RETURN };
IF (where ¬ pSel.start.pos.node) # pSel.end.pos.node THEN {
MessageWindow.Append["Selection to replace must be within a single node.", TRUE];
MessageWindow.Blink[]; TEditSelection.UnlockSel[primary]; RETURN
};
at ¬ pSel.start.pos.where;
atEnd ¬ IF pSel.granularity=point THEN at ELSE pSel.end.pos.where+1;
subsinfo ¬ NEW[EditToolPrivate.SubsInfoRec];
subsinfo.event ¬ TEditInput.CurrentEvent[];
subsinfo.substitute ¬ FALSE;
subsinfo.sourceLen ¬ TextEdit.Size[source];
IF source # NIL THEN {
subsinfo.sourceFormat ¬ TextEdit.GetFormat[source];
subsinfo.sourceComment ¬ TextEdit.GetComment[source];
IF NOT info.ignoreStyle THEN subsinfo.sourceStyle ¬ NodeStyleOps.StyleNameForNode[source];
subsinfo.sourceNode ¬ source;
};
IF info.ignoreText AND NOT info.ignoreLooks THEN { -- looks only
subsinfo.targetLooks ¬ EditToolBuilder.GetDataLooks[info.targetArg,"\"Search for\" field"];
subsinfo.sourceLooks ¬ EditToolBuilder.GetDataLooks[info.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 [Tioga.Looks] ~ {
node: Node ¬ pSel.start.pos.node;
loc: INT ¬ pSel.start.pos.where;
IF node=NIL OR loc=Tioga.NodeItself OR loc=TextEdit.Size[node]
THEN RETURN [Tioga.noLooks];
RETURN [TextEdit.FetchLooks[node,loc]];
};
IsSelInitCap: PROC [pSel: TEditDocument.Selection] RETURNS [BOOL] ~ {
node: Node ¬ pSel.start.pos.node;
loc: INT ¬ pSel.start.pos.where;
IF node=NIL OR loc=Tioga.NodeItself OR loc=TextEdit.Size[node] THEN RETURN [FALSE];
RETURN [TextEdit.FetchChar[node,loc] IN [Char.Widen['A]..Char.Widen['Z]]];
};
IsSelInitLower: PROC [pSel: TEditDocument.Selection] RETURNS [BOOL] ~ {
node: Node ¬ pSel.start.pos.node;
loc: INT ¬ pSel.start.pos.where;
IF node=NIL OR loc=Tioga.NodeItself OR loc=TextEdit.Size[node] THEN RETURN [FALSE];
RETURN [TextEdit.FetchChar[node,loc] IN [Char.Widen['a]..Char.Widen['z]]];
};
doYesAtom: LIST OF REF ~ EditToolPrivate.Register[$DoYes,DoYesOp];
doYesBackAtom: LIST OF REF ~ EditToolPrivate.Register[$DoYesBack,DoYesBackOp];
DoYes: Buttons.ButtonProc ~ {
EditToolPrivate.DoButton[doYesAtom, doYesBackAtom, mouseButton=red];
};
DoYesOp: TEditInput.CommandProc ~ { DoYesCom[EditToolPrivate.mainToolInfo] };
DoYesCom: PROC [info: EditToolPrivate.Info] ~ {
DoItCom[info];
EditToolPrivate.Search[forwards,info];
};
DoYesBackOp: TEditInput.CommandProc ~ { DoYesBackCom[EditToolPrivate.mainToolInfo] };
DoYesBackCom: PROC [info: EditToolPrivate.Info] ~ {
DoItCom[info];
EditToolPrivate.Search[backwards,info];
};
doNoAtom: LIST OF REF ~ EditToolPrivate.Register[$DoNo,DoNoOp];
doNoBackAtom: LIST OF REF ~ EditToolPrivate.Register[$DoNoBack,DoNoBackOp];
DoNo: Buttons.ButtonProc ~ {
EditToolPrivate.DoButton[doNoAtom, doNoBackAtom, mouseButton=red];
};
DoNoOp: TEditInput.CommandProc ~ { DoNoCom[EditToolPrivate.mainToolInfo] };
DoNoCom: PROC [info: EditToolPrivate.Info] ~ {
EditToolPrivate.FixPSel[];
EditToolPrivate.Search[forwards,info];
};
DoNoBackOp: TEditInput.CommandProc ~ {
DoNoBackCom[EditToolPrivate.mainToolInfo];
};
DoNoBackCom: PROC [info: EditToolPrivate.Info] ~ {
EditToolPrivate.FixPSel[];
EditToolPrivate.Search[backwards,info];
};
doCountAtom: LIST OF REF ~ EditToolPrivate.Register[$DoCount,DoCountOp];
DoCount: Buttons.ButtonProc ~ {
EditToolPrivate.DoButton[doCountAtom];
};
DoCountOp: TEditInput.CommandProc ~ { DoCountCom[EditToolPrivate.mainToolInfo] };
DoCountCom: PROC [info: EditToolPrivate.Info] ~ { DoSubstituteCom[info,TRUE] };
withinSelRope: Rope.ROPE;
afterSelRope: Rope.ROPE;
entireDocRope: Rope.ROPE;
withinSelAtom: LIST OF REF ~ EditToolPrivate.Register[$SubstituteInSel,SubsWithinOp];
afterSelAtom: LIST OF REF ~ EditToolPrivate.Register[$SubstituteAfterSel,SubsAfterOp];
entireDocAtom: LIST OF REF ~ EditToolPrivate.Register[$SubstituteInEntireDoc,SubsEntireDocOp];
BuildSubstituteEntry: PUBLIC PROC [info: EditToolPrivate.Info, realNames: BOOL ¬ FALSE] ~ {
info.subsRange ¬ entireDoc;
IF realNames THEN {
withinSelRope ¬ "SubstituteInSel";
afterSelRope ¬ "SubstituteAfterSel";
entireDocRope ¬ "SubstituteInEntireDoc";
}
ELSE {
withinSelRope ¬ "Within Selection Only";
afterSelRope ¬ "After Selection Only";
entireDocRope ¬ "In Entire Document";
};
[info.subsRangeLabel,] ¬ EditToolBuilder.BuildTriple[info.layout, SubsRangeButton, ORD[info.subsRange], withinSelRope, afterSelRope, entireDocRope, info];
};
SubsRangeButton: Buttons.ButtonProc ~ {
EditToolPrivate.CycleTriple[ORD[EditToolPrivate.mainToolInfo.subsRange], withinSelAtom, afterSelAtom, entireDocAtom];
};
SubsWithinOp: TEditInput.CommandProc ~ { SubsWithin[EditToolPrivate.mainToolInfo] };
SubsWithin: PROC [info: EditToolPrivate.Info] ~ {
info.subsRange ¬ withinSel;
Labels.Set[info.subsRangeLabel,withinSelRope];
};
SubsAfterOp: TEditInput.CommandProc ~ { SubsAfter[EditToolPrivate.mainToolInfo] };
SubsAfter: PROC [info: EditToolPrivate.Info] ~ {
info.subsRange ¬ afterSel;
Labels.Set[info.subsRangeLabel,afterSelRope];
};
SubsEntireDocOp: TEditInput.CommandProc ~ { SubsEntireDoc[EditToolPrivate.mainToolInfo] };
SubsEntireDoc: PROC [info: EditToolPrivate.Info] ~ {
info.subsRange ¬ entireDoc;
Labels.Set[info.subsRangeLabel,entireDocRope];
};
END.