EditToolSearchImpl.mesa
Copyright Ó 1985, 1986, 1991, 1992 by Xerox Corporation. All rights reserved.
Michael Plass, March 28, 1985 9:01:55 am PST
Doug Wyatt, March 16, 1992 3:34 pm PST
Russ Atkinson (RRA) January 23, 1986 0:57:33 am PST
Alison Lee September 8, 1986 10:03:40 pm PDT
DIRECTORY
Atom USING [GetProp],
Buttons USING [Button, ButtonProc, SetDisplayStyle, ReLabel],
EditToolBuilder USING [BuildButton, BuildDataFieldPair, BuildLabel, BuildPair, BuildTriple, DataFieldButton, GetDataNode, HGap, ToMiddle, ToNext],
EditToolPrivate USING [ChangeState, CycleTriple, DoButton, FixPSel, Info, Pattern, PatternRep, mainToolInfo, editTool, Register, SavePSel, SearchDir, SearchWhere],
IO USING [PutFR, rope, int],
Labels USING [Set],
Menus USING [Menu, MenuProc, MenuEntry, FindEntry, CopyEntry, SetClientData],
MessageWindow USING [Append, Clear],
NodeProps USING [DoSpecs],
NodeStyleOps USING [StyleNameForNode],
Rope USING [Concat, ROPE],
TEditDocument USING [Selection],
TEditInput USING [CloseEvent, CommandProc],
TEditInputOps USING [CallWithLocks],
TEditOps USING [GetSelData, RememberCurrentPosition, SetTextContents],
TEditProfile USING [selectionCaret],
TEditRefresh USING [ScrollToEndOfSel],
TEditSelection USING [LockSel, UnlockSel, MakeSelection, SetSelLooks],
TextEdit,
TextFind,
TextNode USING [Root, FirstChild],
Tioga USING [Node, Location, Looks, noLooks],
TiogaFind USING [TargetFromNode, Search, Match],
ViewerClasses USING [Viewer],
ViewerOps USING [AddProp, BlinkDisplay, CreateViewer],
ViewerSpecs USING [openRightWidth],
ViewerTools USING [InhibitUserEdits];
EditToolSearchImpl: CEDAR PROGRAM
IMPORTS Atom, Buttons, EditToolBuilder, EditToolPrivate, IO, Labels, MessageWindow, Menus, NodeProps, NodeStyleOps, Rope, TEditOps, TextEdit, TextFind, TextNode, TEditInput, TEditInputOps, TEditProfile, TEditRefresh, TEditSelection, TiogaFind, ViewerOps, ViewerSpecs, ViewerTools
EXPORTS EditToolPrivate
= BEGIN OPEN EditToolPrivate, EditToolBuilder;
ROPE: TYPE ~ Rope.ROPE;
Node: TYPE ~ Tioga.Node;
Location: TYPE ~ Tioga.Location;
Report: PROC [msg: Rope.ROPE, blink: BOOLTRUE] ~ {
IF msg=NIL THEN MessageWindow.Clear[]
ELSE {
MessageWindow.Append[msg, TRUE];
IF blink THEN ViewerOps.BlinkDisplay[];
};
};
searchForwardAtom: LIST OF REF = Register[$SearchForward,SearchForwardOp];
SearchForwardOp: TEditInput.CommandProc = { Search[forwards,mainToolInfo] };
searchAnywhereAtom: LIST OF REF = Register[$SearchAnywhere,SearchAnywhereOp];
SearchAnywhereOp: TEditInput.CommandProc = { Search[anywhere,mainToolInfo] };
searchBackwardsAtom: LIST OF REF = Register[$SearchBackwards,SearchBackwardsOp];
SearchBackwardsOp: TEditInput.CommandProc = { Search[backwards,mainToolInfo] };
DoSearchMenuButton: PUBLIC Menus.MenuProc = {
SELECT mouseButton FROM
red => DoButton[searchForwardAtom];
yellow => DoButton[searchAnywhereAtom];
blue => DoButton[searchBackwardsAtom];
ENDCASE => ERROR;
};
CheckPSel: PUBLIC PROC [pSel: TEditDocument.Selection, typescriptOK: BOOL ¬ TRUE] RETURNS [ok: BOOL] = {
IF pSel#NIL AND pSel.viewer#NIL AND
(pSel.viewer.class.flavor=$Text OR
(typescriptOK AND pSel.viewer.class.flavor=$Typescript))
THEN RETURN [TRUE];
Report["Please make a text selection."];
RETURN [FALSE];
};
Search: PUBLIC PROC [whichDir: SearchDir, info: Info] = {
found: BOOL ~ TrySearch[whichDir, info];
Report[IF found THEN NIL ELSE "Not found.", TRUE];
};
TrySearch: PUBLIC PROC [whichDir: SearchDir, info: Info] RETURNS [found: BOOL ¬ FALSE] = {
IF info.ignoreText AND info.ignoreLooks AND info.ignoreFormat AND
info.ignoreStyle AND info.ignoreComment THEN {
Report["Pick one or more of text/looks/format/style/comment to match."];
RETURN;
};
TEditSelection.LockSel[primary, "TrySearch"];
{
ENABLE UNWIND => TEditSelection.UnlockSel[primary];
pSel: TEditDocument.Selection ¬ NIL;
pattern: Pattern ¬ NIL;
FixPSel[];
pSel ¬ TEditOps.GetSelData[];
IF ~CheckPSel[pSel] OR (pattern ¬ GetPattern[info])=NIL THEN GOTO Quit;
[found, info.subs] ¬ DoSearch[whichDir: whichDir,
pattern: pattern, interrupt: info.interrupt];
IF found THEN {
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[$DoSearch];
};
};
EXITS Quit => {};
};
TEditSelection.UnlockSel[primary];
};
matchFromWhere: ARRAY SearchWhere OF TiogaFind.Match
~ [anywhere: any, words: word, nodes: all];
GetPattern: PUBLIC PROC [info: EditToolPrivate.Info] RETURNS [Pattern] ~ {
node: Node ~ GetDataNode[info.targetArg];
nodeSize: INT ~ TextEdit.Size[node];
checkText: BOOL ~ NOT info.ignoreText;
checkLooks: BOOL ~ NOT info.ignoreLooks;
checkComment: BOOL ~ NOT info.ignoreComment;
checkFormat: BOOL ~ NOT info.ignoreFormat;
checkStyle: BOOL ~ NOT info.ignoreStyle;
target: TextFind.Target ¬ NIL;
comment: BOOL ¬ FALSE;
format: ATOM ¬ NIL;
style: ATOM ¬ NIL;
IF nodeSize=0 AND (checkText OR checkLooks) THEN {
Report["Please enter a search pattern in the \"Target:\" field."];
RETURN[NIL];
};
IF checkText THEN {
error: ROPE ¬ NIL;
target ¬ TiogaFind.TargetFromNode[node: node, pattern: NOT info.literal ! TextFind.Error => {
error ¬ IO.PutFR["Error: %g, at position %g.", IO.rope[reason], IO.int[index]]; CONTINUE }];
IF error#NIL THEN { Report[error]; RETURN[NIL] };
}
ELSE IF checkLooks THEN {
patternNode: Node ~ TextEdit.FromRope["**#**"];
patternLooks: Tioga.Looks ¬ Tioga.noLooks;
FOR i: INT IN [0..nodeSize) DO
looks: Tioga.Looks ~ TextEdit.FetchLooks[node, i];
IF i=0 THEN patternLooks ¬ looks
ELSE IF looks#patternLooks THEN {
Report["Search pattern has nonuniform looks; using looks from first char."];
EXIT;
};
ENDLOOP;
TextEdit.ChangeLooks[root: NIL, text: patternNode, add: patternLooks];
target ¬ TiogaFind.TargetFromNode[node: patternNode, pattern: TRUE];
};
IF node#NIL THEN {
IF checkComment THEN comment ¬ TextEdit.GetComment[node];
IF checkFormat THEN format ¬ TextEdit.GetFormat[node];
IF checkStyle THEN style ¬ NodeStyleOps.StyleNameForNode[node];
};
RETURN[NEW[PatternRep ¬ [target: target,
case: NOT info.ignoreCase, match: matchFromWhere[info.searchWhere],
checkLooks: checkLooks, looksExact: info.looksExact,
checkComment: checkComment, comment: comment,
checkFormat: checkFormat, format: format,
checkStyle: checkStyle, style: style]]];
};
DoSearch: PROC [whichDir: SearchDir, pattern: Pattern, interrupt: REF BOOL]
RETURNS
[found: BOOL ¬ FALSE, subs: TextFind.Subs ¬ NIL] ~ {
DoSearchLocked: PROC [root: Node, tSel: TEditDocument.Selection] = {
where: Node ¬ NIL;
at, atEnd: INT ¬ 0;
Try: PROC [dir: TextFind.Direction, loc1, loc2: Location] ~ {
pat: Pattern ~ pattern;
[node: where, matchStart: at, matchEnd: atEnd, subs: subs] ¬ TiogaFind.Search[
direction: dir, loc1: loc1, loc2: loc2,
target: pat.target, case: pat.case, match: pat.match,
checkLooks: pat.checkLooks, looksExact: pat.looksExact,
checkComment: pat.checkComment, comment: pat.comment,
checkFormat: pat.checkFormat, format: pat.format,
checkStyle: pat.checkStyle, style: pat.style,
styleProc: NodeStyleOps.StyleNameForNode,
interrupt: interrupt];
};
first: Location ~ [TextNode.FirstChild[root], 0];
loc1: Location ¬ tSel.start.pos;
loc2: Location ¬ tSel.end.pos;
loc1.where ¬ MIN[MAX[0, loc1.where], TextEdit.Size[loc1.node]];
loc2.where ¬ MIN[MAX[0, loc2.where+1], TextEdit.Size[loc2.node]];
IF interrupt#NIL THEN interrupt­ ¬ FALSE;
IF whichDir=backwards
THEN Try[backward, first, loc1]
ELSE Try[forward, loc2, [NIL, 0]];
IF where=NIL AND whichDir=anywhere AND NOT(interrupt#NIL AND interrupt­)
THEN Try[forward, first, [NIL, 0]];
IF where=NIL THEN RETURN ELSE found ¬ TRUE;
tSel.start.pos ¬ [where, at];
tSel.end.pos ¬ [where, MAX[0,atEnd-1]];
tSel.granularity ¬ IF pattern.target=NIL OR pattern.match=all THEN node
ELSE IF pattern.match=word THEN word ELSE char;
tSel.insertion ¬ IF TEditProfile.selectionCaret=before THEN before ELSE after;
TEditOps.RememberCurrentPosition[tSel.viewer];
TEditSelection.SetSelLooks[tSel];
TEditSelection.MakeSelection[new: tSel];
TEditInput.CloseEvent[];
TEditRefresh.ScrollToEndOfSel[tSel.viewer, FALSE];
};
TEditInputOps.CallWithLocks[DoSearchLocked, read]
};
SetUpRealText: PROC [info: EditToolPrivate.Info] = {
BuildRealSearchChoiceEntries[info]; ToNext[info.layout];
ignoringCase ¬ "IgnoreCase";
matchingCase ¬ "MatchCase";
matchingWords ¬ "MatchWords";
matchingAnywhere ¬ "MatchAnywhere";
matchingNodes ¬ "MatchNodes";
matchingLiterally ¬ "MatchLiterally";
matchingAsPattern ¬ "MatchPattern";
equalLooks ¬ "EqualLooksTest";
subsetLooks ¬ "SubsetLooksTest";
};
SetUpText: PROC [info: EditToolPrivate.Info] = {
BuildSearchChoiceEntries[info]; ToNext[info.layout];
ignoringCase ¬ "Ignore Case";
matchingCase ¬ "Match Case";
matchingWords ¬ "Match Words Only";
matchingAnywhere ¬ "Match Anywhere";
matchingNodes ¬ "Match Entire Nodes Only";
matchingLiterally ¬ "Match Literally";
matchingAsPattern ¬ "Match as Pattern";
equalLooks ¬ "Equal as Looks Test";
subsetLooks ¬ "Subset as Looks Test";
};
BuildSearchButtons: PUBLIC PROC [info: EditToolPrivate.Info, realNames: BOOL ¬ FALSE] = {
IF realNames THEN SetUpRealText[info] ELSE SetUpText[info];
BuildCaseEntry[info]; ToMiddle[info.layout];
BuildWhereEntry[info]; ToNext[info.layout];
BuildLitOrPatternEntry[info]; ToMiddle[info.layout];
BuildLooksMatchEntry[info];
};
equalLooks: Rope.ROPE;
subsetLooks: Rope.ROPE;
equalLooksAtom: LIST OF REF = Register[$EqualLooksTest,EqualLooksTestOp];
subsetLooksAtom: LIST OF REF = Register[$SubsetLooksTest,SubsetLooksTestOp];
LooksMatchButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.looksExact, equalLooksAtom,subsetLooksAtom];
};
EqualLooksTestOp: TEditInput.CommandProc = {
EqualLooksTest[mainToolInfo];
};
EqualLooksTest: PROC [info: Info] = {
OPEN info;
looksExact ¬ TRUE;
Labels.Set[looksMatchLabel,equalLooks];
};
SubsetLooksTestOp: TEditInput.CommandProc = {
SubsetLooksTest[mainToolInfo];
};
SubsetLooksTest: PROC [info: Info] = {
OPEN info;
looksExact ¬ FALSE;
Labels.Set[looksMatchLabel,subsetLooks];
};
BuildRealLooksMatchEntry: PROC [info: Info] = {
OPEN info;
looksExact ¬ FALSE;
[looksMatchLabel,] ¬ BuildPair[layout,LooksMatchButton,looksExact,"EqualLooksTest","SubsetLooksTest",info];
};
BuildLooksMatchEntry: PROC [info: Info] = {
OPEN info;
looksExact ¬ FALSE;
[looksMatchLabel,] ¬ BuildPair[layout,LooksMatchButton,looksExact,equalLooks,subsetLooks,info];
};
--------------------------
BuildEntry: PROC [name: Rope.ROPE, info:Info, proc: Buttons.ButtonProc, state: BOOL] RETURNS [new: Buttons.Button] = {
new ¬ BuildButton[info.layout, name, proc, info, FALSE, FALSE];
ViewerOps.AddProp[new, $DisableMBFeedback, $DisableMBFeedback];
SetButton[new, state, FALSE];
};
BuildRealSearchChoiceEntries: PROC [info: Info] = {
[] ¬ BuildLabel[info.layout, "Pick one or more: "];
HGap[info.layout];
info.textButton ¬ BuildEntry["MatchText", info, MatchTextButton, info.ignoreText ¬ FALSE];
info.looksButton ¬ BuildEntry["IgnoreLooks", info, MatchLooksButton, info.ignoreLooks ¬ TRUE];
info.formatButton ¬ BuildEntry["IgnoreFormat", info, MatchFormatButton, info.ignoreFormat ¬ TRUE];
EditToolBuilder.ToNext[info.layout];
EditToolBuilder.ToMiddle[info.layout];
info.styleButton ¬ BuildEntry["IgnoreStyle", info, MatchStyleButton, info.ignoreStyle ¬ TRUE];
info.commentButton ¬ BuildEntry["IgnoreComment", info, MatchCommentButton, info.ignoreComment ¬ TRUE];
};
BuildSearchChoiceEntries: PROC [info: Info] = {
[] ¬ BuildLabel[info.layout, "Pick one or more: "];
HGap[info.layout];
info.textButton ¬ BuildEntry["Text", info, MatchTextButton, info.ignoreText ¬ FALSE];
info.looksButton ¬ BuildEntry["Looks", info, MatchLooksButton, info.ignoreLooks ¬ TRUE];
info.formatButton ¬ BuildEntry["Format", info, MatchFormatButton, info.ignoreFormat ¬ TRUE];
info.styleButton ¬ BuildEntry["Style", info, MatchStyleButton, info.ignoreStyle ¬ TRUE];
info.commentButton ¬ BuildEntry["Comment", info, MatchCommentButton, info.ignoreComment ¬ TRUE];
};
SetButton: PROC [viewer: Buttons.Button, ignore: BOOL, paint: BOOL ¬ TRUE] = {
Buttons.SetDisplayStyle[viewer,
IF ignore THEN $BlackOnWhite ELSE $WhiteOnBlack, paint];
};
--------------------------
matchTextAtom: LIST OF REF = Register[$MatchText,MatchTextOp];
ignoreTextAtom: LIST OF REF = Register[$IgnoreText,IgnoreTextOp];
MatchTextButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.ignoreText, ignoreTextAtom, matchTextAtom];
};
MatchTextOp: TEditInput.CommandProc = { MatchText[mainToolInfo] };
MatchText: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.textButton, "MatchText", FALSE ];
SetButton[info.textButton, info.ignoreText ¬ FALSE];
};
IgnoreTextOp: TEditInput.CommandProc = { IgnoreText[mainToolInfo] };
IgnoreText: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.textButton, "IgnoreText", FALSE ];
SetButton[info.textButton, info.ignoreText ¬ TRUE];
};
--------------------------
matchLooksAtom: LIST OF REF = Register[$MatchLooks,MatchLooksOp];
ignoreLooksAtom: LIST OF REF = Register[$IgnoreLooks,IgnoreLooksOp];
MatchLooksButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.ignoreLooks, ignoreLooksAtom, matchLooksAtom];
};
MatchLooksOp: TEditInput.CommandProc = {
MatchLooks[mainToolInfo];
};
MatchLooks: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.looksButton, "MatchLooks", FALSE ];
SetButton[info.looksButton, info.ignoreLooks ¬ FALSE];
};
IgnoreLooksOp: TEditInput.CommandProc = {
IgnoreLooks[mainToolInfo];
};
IgnoreLooks: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.looksButton, "IgnoreLooks", FALSE ];
SetButton[info.looksButton, info.ignoreLooks ¬ TRUE];
};
--------------------------
matchFormatAtom: LIST OF REF = Register[$MatchFormat,MatchFormatOp];
ignoreFormatAtom: LIST OF REF = Register[$IgnoreFormat,IgnoreFormatOp];
MatchFormatButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.ignoreFormat, ignoreFormatAtom,matchFormatAtom]
};
MatchFormatOp: TEditInput.CommandProc = {
MatchFormat[mainToolInfo];
};
MatchFormat: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.formatButton, "MatchFormat", FALSE ];
SetButton[info.formatButton, info.ignoreFormat ¬ FALSE];
};
IgnoreFormatOp: TEditInput.CommandProc = {
IgnoreFormat[mainToolInfo];
};
IgnoreFormat: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.formatButton, "IgnoreFormat", FALSE ];
SetButton[info.formatButton, info.ignoreFormat ¬ TRUE];
};
matchStyleAtom: LIST OF REF = Register[$MatchStyle,MatchStyleOp];
ignoreStyleAtom: LIST OF REF = Register[$IgnoreStyle,IgnoreStyleOp];
MatchStyleButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.ignoreStyle, ignoreStyleAtom,matchStyleAtom]
};
MatchStyleOp: TEditInput.CommandProc = {
MatchStyle[mainToolInfo] };
MatchStyle: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.styleButton, "MatchStyle", FALSE ];
SetButton[info.styleButton, info.ignoreStyle ¬ FALSE] };
IgnoreStyleOp: TEditInput.CommandProc = {
IgnoreStyle[mainToolInfo] };
IgnoreStyle: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ mainToolInfo.styleButton, "IgnoreStyle", FALSE ];
SetButton[info.styleButton, info.ignoreStyle ¬ TRUE] };
matchCommentAtom: LIST OF REF = Register[$MatchComment,MatchCommentOp];
ignoreCommentAtom: LIST OF REF = Register[$IgnoreComment,IgnoreCommentOp];
MatchCommentButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.ignoreComment, ignoreCommentAtom,matchCommentAtom]
};
MatchCommentOp: TEditInput.CommandProc = {
MatchComment[mainToolInfo] };
MatchComment: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.commentButton, "MatchComment", FALSE ];
SetButton[info.commentButton, info.ignoreComment ¬ FALSE] };
IgnoreCommentOp: TEditInput.CommandProc = {
IgnoreComment[mainToolInfo] };
IgnoreComment: PROC [info: Info] = {
viewer: ViewerClasses.Viewer ¬ editTool;
menu: Menus.Menu ¬ viewer.menu;
menuEntry:Menus.MenuEntry ¬ Menus.CopyEntry[ Menus.FindEntry[ menu, "RealOps"] ];
menuClientData: REF ANY¬ Menus.SetClientData[ menuEntry, NIL ]; -- only way to query the clientData without affecting it.
data: REF BOOL ¬ NARROW[menuClientData];
usingRealNames: BOOL ¬ data­;
If using real names, must change the text in the button also, if not using real names then leave the text of the button the same.
IF usingRealNames THEN Buttons.ReLabel[ info.commentButton, "IgnoreComment", FALSE ];
SetButton[info.commentButton, info.ignoreComment ¬ TRUE] };
matchingLiterally: Rope.ROPE;
matchingAsPattern: Rope.ROPE;
matchLitAtom: LIST OF REF = Register[$MatchLiterally,MatchLitOp];
matchPatternAtom: LIST OF REF = Register[$MatchPattern,MatchPatternOp];
LiteralButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.literal, matchLitAtom,matchPatternAtom];
};
MatchLitOp: TEditInput.CommandProc = {
MatchLit[mainToolInfo];
};
MatchLit: PROC [info: Info] = {
OPEN info;
literal ¬ TRUE;
Labels.Set[literalLabel,matchingLiterally];
};
MatchPatternOp: TEditInput.CommandProc = {
MatchPattern[mainToolInfo];
};
MatchPattern: PROC [info: Info] = {
OPEN info;
literal ¬ FALSE;
Labels.Set[literalLabel,matchingAsPattern];
};
BuildLitOrPatternEntry: PROC [info: Info] = {
OPEN info;
literal ¬ TRUE;
[literalLabel,] ¬ BuildPair[layout,LiteralButton,literal,matchingLiterally,matchingAsPattern,info];
};
numDocRopes: NAT = 18;
docRopes: REF ARRAY [0..numDocRopes) OF Rope.ROPE ¬
NEW[ARRAY [0..numDocRopes) OF Rope.ROPE];
BuildPatternDocEntry: PUBLIC PROC [info: Info] = {
OPEN info.layout;
lines: CARDINAL = 25;
rope: Rope.ROPE;
arg: ViewerClasses.Viewer ¬ ViewerOps.CreateViewer[flavor: $Text, info: [parent: container,
border: FALSE, scrollable: TRUE,
wx: entryLeft, wy: heightSoFar,
ww: ViewerSpecs.openRightWidth-entryLeft-5,
wh: entryHeight*lines], paint: FALSE];
heightSoFar ¬ heightSoFar + entryHeight*lines;
FOR i:NAT IN [0..numDocRopes) DO
rope ¬ Rope.Concat[rope, docRopes[i]];
ENDLOOP;
TEditOps.SetTextContents[arg, rope];
};
numMiniDocRopes: NAT = 4;
miniDocRopes: REF ARRAY [0..numMiniDocRopes) OF Rope.ROPE ¬
NEW[ARRAY [0..numMiniDocRopes) OF Rope.ROPE];
miniDocStyle: Rope.ROPE ~ "
BeginStyle
(mini) \"for small comment\" {
 \"TimesRoman\" family
 8 pt size
 9 pt leading
 10 pt topIndent
 0 pt bottomIndent
 0 leftIndent
 5 pt rightIndent
 } StyleRule
EndStyle
";
BuildMiniPatternDocEntry: PUBLIC PROC [info: Info] = {
OPEN info.layout;
rope: Rope.ROPE;
where: Node;
height: CARDINAL = numMiniDocRopes*10+3;
arg: ViewerClasses.Viewer ¬ ViewerOps.CreateViewer[flavor: $Text, info: [parent: container,
wx: entryLeft, wy: heightSoFar,
ww: ViewerSpecs.openRightWidth-entryLeft-5,
wh: height, border: FALSE, scrollable: FALSE], paint: FALSE];
heightSoFar ¬ heightSoFar + height;
FOR i:NAT IN [0..numMiniDocRopes) DO
rope ¬ Rope.Concat[rope, miniDocRopes[i]];
ENDLOOP;
TEditOps.SetTextContents[arg, rope];
where ¬ GetDataNode[arg];
TextEdit.PutProp[node: TextNode.Root[where], name: $StyleDef,
value: NodeProps.DoSpecs[$StyleDef, miniDocStyle]];
TextEdit.PutFormat[where, $mini];
ViewerTools.InhibitUserEdits[arg];
};
--------------------------
ignoringCase: Rope.ROPE;
matchingCase: Rope.ROPE;
ignoreCaseAtom: LIST OF REF = Register[$IgnoreCase,IgnoreCaseOp];
matchCaseAtom: LIST OF REF = Register[$MatchCase,MatchCaseOp];
CaseButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.ignoreCase, ignoreCaseAtom,matchCaseAtom];
};
IgnoreCaseOp: TEditInput.CommandProc = {
IgnoreCase[mainToolInfo];
};
IgnoreCase: PROC [info: Info] = {
OPEN info;
ignoreCase ¬ TRUE;
Labels.Set[caseLabel,ignoringCase];
};
MatchCaseOp: TEditInput.CommandProc = {
MatchCase[mainToolInfo];
};
MatchCase: PROC [info: Info] = {
OPEN info;
ignoreCase ¬ FALSE;
Labels.Set[caseLabel,matchingCase];
};
BuildCaseEntry: PROC [info: Info] = {
OPEN info;
ignoreCase ¬ FALSE;
[caseLabel,] ¬ BuildPair[layout,CaseButton,ignoreCase,ignoringCase,matchingCase,info];
};
matchingWords: Rope.ROPE;
matchingAnywhere: Rope.ROPE;
matchingNodes: Rope.ROPE;
matchWordsAtom: LIST OF REF = Register[$MatchWords,MatchWordsOp];
matchAnywhereAtom: LIST OF REF = Register[$MatchAnywhere,MatchAnywhereOp];
matchNodesAtom: LIST OF REF = Register[$MatchNodes,MatchNodesOp];
WhereButton: Buttons.ButtonProc = {
CycleTriple[ORD[mainToolInfo.searchWhere],
matchAnywhereAtom,matchWordsAtom,matchNodesAtom] };
MatchWordsOp: TEditInput.CommandProc = { MatchWords[mainToolInfo] };
MatchWords: PROC [info: Info] = {
OPEN info;
searchWhere ¬ words;
Labels.Set[wordLabel,matchingWords];
};
MatchNodesOp: TEditInput.CommandProc = { MatchNodes[mainToolInfo] };
MatchNodes: PROC [info: Info] = {
OPEN info;
searchWhere ¬ nodes;
Labels.Set[wordLabel,matchingNodes];
};
MatchAnywhereOp: TEditInput.CommandProc = {
MatchAnywhere[mainToolInfo];
};
MatchAnywhere: PROC [info: Info] = {
OPEN info;
searchWhere ¬ anywhere;
Labels.Set[wordLabel,matchingAnywhere];
};
BuildWhereEntry: PROC [info: Info] = {
OPEN info;
searchWhere ¬ anywhere;
[wordLabel,] ¬ BuildTriple[layout, WhereButton, ORD[searchWhere], matchingAnywhere, matchingWords, matchingNodes, info];
};
--------------------------
targetArgAtom: LIST OF REF = Register[$SearchFor,TargetArgOp];
clearTargetArgAtom: LIST OF REF = Register[$ClearSearchFor,ClearTargetArgOp];
TargetButton: Buttons.ButtonProc = {
DoButton[targetArgAtom, clearTargetArgAtom, mouseButton=red];
};
TargetArgOp: TEditInput.CommandProc = {
TargetArg[mainToolInfo];
};
TargetArg: PROC [info: Info] = {
SavePSel; DataFieldButton[info.targetArg,FALSE];
};
ClearTargetArgOp: TEditInput.CommandProc = {
ClearTargetArg[mainToolInfo];
};
ClearTargetArg: PROC [info: Info] = {
SavePSel; DataFieldButton[info.targetArg,TRUE];
};
BuildTargetEntry: PUBLIC PROC [info: Info] = {
OPEN info;
[,targetArg] ¬ BuildDataFieldPair[layout, "Target:", TargetButton, info, 2];
};
--------------------------
docRopes[0] ¬ "The following special symbols may be used in search patterns:
";
docRopes[1] ¬ " ' Match the next character in the pattern exactly.
";
docRopes[2] ¬ " ~ Match any character except the next one in the pattern.
";
docRopes[3] ¬ " # Match any single character.
";
docRopes[4] ¬ " * Match any sequence of characters.
";
docRopes[5] ¬ " @ Match any single alphanumeric character (letter or digit).
";
docRopes[6] ¬ " & Match any sequence of alphanumeric characters.
";
docRopes[7] ¬ " ~@ Match any single non-alphanumeric character.
";
docRopes[8] ¬ " ~& Match any sequence of non-alphanumeric characters.
";
docRopes[9] ¬ " % Match any single blank character.
";
docRopes[10] ¬ " $ Match any sequence of blank characters.
";
docRopes[11] ¬ " ~% Match any single non-blank character.
";
docRopes[12] ¬ " ~$ Match any sequence of non-blank characters.
";
docRopes[13] ¬ " | Match start or end of node.
";
docRopes[14] ¬ " { Mark start of resulting selection.
";
docRopes[15] ¬ " } Mark end of resulting selection.
";
docRopes[16] ¬ " < Mark start of named subpattern.
";
docRopes[17] ¬ " > Mark end of named subpattern.
";
miniDocRopes[0] ¬ "single character: # any; @ alpha; ~@ nonalpha; % blank; ~% nonblank;
";
miniDocRopes[1] ¬ "min sequence: * any; & alpha; ~& nonalpha; $ blank; ~$ nonblank;
";
miniDocRopes[2] ¬ "max sequence: ** any; && alpha; ~&~& nonalpha; $$ blank; ~$~$ nonblank;
";
miniDocRopes[3] ¬ "other: 'x = x; ~x = not x; | node boundary; { } selection; < > named subpattern
";
END.