<<-- EditToolSubsImpl.mesa; Edited by Paxton on January 3, 1983 9:49 am>> <<-- Edited by McGregor on August 30, 1982 2:40 pm>> DIRECTORY EditToolPrivate, EditToolBuilder, Buttons, Convert, EditNotify, Inline, 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, UserTerminal, 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.ValueToRope[[signed[count,10]]], 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; tdd: TEditDocument.TEditDocumentData = NARROW[sourceArg.data]; 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; }; }...