KiCad PCB EDA Suite
find.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2004-2018 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 /*
32  * Search a text (text, value, reference) within a component or
33  * search a component in libraries, a marker ...,
34  * in current sheet or whole the project
35  */
36 #include <fctsys.h>
37 #include <pgm_base.h>
38 #include <sch_draw_panel.h>
39 #include <confirm.h>
40 #include <kicad_string.h>
41 #include <gestfich.h>
42 #include <sch_edit_frame.h>
43 #include <base_units.h>
44 #include <trace_helpers.h>
45 #include <sch_view.h>
46 #include <general.h>
47 #include <class_library.h>
48 #include <lib_pin.h>
49 #include <sch_marker.h>
50 #include <sch_component.h>
51 #include <sch_sheet.h>
52 #include <sch_sheet_path.h>
53 #include <symbol_lib_table.h>
54 
55 #include <kicad_device_context.h>
56 
58 
59 
60 void SCH_EDIT_FRAME::OnFindDrcMarker( wxFindDialogEvent& event )
61 {
62  static SCH_MARKER* lastMarker = NULL;
63 
64  wxString msg;
65  SCH_SHEET_LIST schematic( g_RootSheet );
66  SCH_SHEET_PATH* sheetFoundIn = NULL;
67  bool wrap = ( event.GetFlags() & FR_SEARCH_WRAP ) != 0;
68  bool warpCursor = ( ( event.GetId() == wxEVT_COMMAND_FIND_CLOSE ) ||
69  !( event.GetFlags() & FR_NO_WARP_CURSOR ) );
70 
71  if( event.GetFlags() & FR_CURRENT_SHEET_ONLY )
72  {
73  sheetFoundIn = g_CurrentSheet;
74  lastMarker = (SCH_MARKER*) g_CurrentSheet->FindNextItem( SCH_MARKER_T, lastMarker, wrap );
75  }
76  else
77  {
78  lastMarker = (SCH_MARKER*) schematic.FindNextItem( SCH_MARKER_T, &sheetFoundIn,
79  lastMarker, wrap );
80  }
81 
82  if( lastMarker != NULL )
83  {
84  if( *sheetFoundIn != *g_CurrentSheet )
85  {
86  sheetFoundIn->LastScreen()->SetZoom( GetScreen()->GetZoom() );
87  *g_CurrentSheet = *sheetFoundIn;
89  }
90 
91  SetCrossHairPosition( lastMarker->GetPosition() );
92 
93 
94  CenterScreen( lastMarker->GetPosition(), warpCursor );
95 
96  msg.Printf( _( "Design rule check marker found in sheet %s at %s, %s" ),
97  sheetFoundIn->Path(),
98  MessageTextFromValue( m_UserUnits, lastMarker->GetPosition().x ),
99  MessageTextFromValue( m_UserUnits, lastMarker->GetPosition().y ) );
100  SetStatusText( msg );
101  }
102  else
103  {
104  SetStatusText( _( "No more markers were found." ) );
105  }
106 }
107 
108 
109 SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
110  bool aSearchHierarchy,
111  SCH_SEARCH_T aSearchType,
112  const wxString& aSearchText )
113 {
114  SCH_SHEET_PATH* sheet = NULL;
115  SCH_SHEET_PATH* sheetWithComponentFound = NULL;
116  SCH_ITEM* item = NULL;
117  SCH_COMPONENT* Component = NULL;
118  wxPoint pos;
119  bool notFound = true;
120  LIB_PIN* pin = nullptr;
121  SCH_SHEET_LIST sheetList( g_RootSheet );
122  EDA_ITEM* foundItem = nullptr;
123 
124  if( !aSearchHierarchy )
125  sheetList.push_back( *g_CurrentSheet );
126  else
127  sheetList.BuildSheetList( g_RootSheet );
128 
129  for( SCH_SHEET_PATHS_ITER it = sheetList.begin(); it != sheetList.end(); ++it )
130  {
131  sheet = &(*it);
132  item = (*it).LastDrawList();
133 
134  for( ; ( item != NULL ) && ( notFound == true ); item = item->Next() )
135  {
136  if( item->Type() != SCH_COMPONENT_T )
137  continue;
138 
139  SCH_COMPONENT* pSch = (SCH_COMPONENT*) item;
140 
141  if( aReference.CmpNoCase( pSch->GetRef( sheet ) ) == 0 )
142  {
143  Component = pSch;
144  sheetWithComponentFound = sheet;
145 
146  switch( aSearchType )
147  {
148  default:
149  case FIND_COMPONENT_ONLY: // Find component only
150  notFound = false;
151  pos = pSch->GetPosition();
152  foundItem = Component;
153  break;
154 
155  case FIND_PIN: // find a pin
156  pos = pSch->GetPosition(); // temporary: will be changed if the pin is found.
157  pin = pSch->GetPin( aSearchText );
158 
159  if( pin == NULL )
160  break;
161 
162  notFound = false;
163  pos += pin->GetPosition();
164  foundItem = Component;
165  break;
166 
167  case FIND_REFERENCE: // find reference
168  notFound = false;
169  pos = pSch->GetField( REFERENCE )->GetPosition();
170  foundItem = pSch->GetField( REFERENCE );
171  break;
172 
173  case FIND_VALUE: // find value
174  pos = pSch->GetPosition();
175 
176  if( aSearchText.CmpNoCase( pSch->GetField( VALUE )->GetShownText() ) != 0 )
177  break;
178 
179  notFound = false;
180  pos = pSch->GetField( VALUE )->GetPosition();
181  foundItem = pSch->GetField( VALUE );
182 
183  break;
184  }
185  }
186  }
187 
188  if( notFound == false )
189  break;
190  }
191 
192  if( Component )
193  {
194  sheet = sheetWithComponentFound;
195 
196  if( *sheet != *g_CurrentSheet )
197  {
198  sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() );
199  *g_CurrentSheet = *sheet;
201  }
202 
203  wxPoint delta;
204  pos -= Component->GetPosition();
205  delta = Component->GetTransform().TransformCoordinate( pos );
206  pos = delta + Component->GetPosition();
207 
208  SetCrossHairPosition( pos );
209  CenterScreen( pos, false );
210  }
211 
212  /* Print diag */
213  wxString msg_item;
214  wxString msg;
215 
216  switch( aSearchType )
217  {
218  default:
219  case FIND_COMPONENT_ONLY: msg_item = _( "component" ); break;
220  case FIND_PIN: msg_item.Printf( _( "pin %s" ), aSearchText ); break;
221  case FIND_REFERENCE: msg_item.Printf( _( "reference %s" ), aSearchText ); break;
222  case FIND_VALUE: msg_item.Printf( _( "value %s" ), aSearchText ); break;
223  case FIND_FIELD: msg_item.Printf( _( "field %s" ), aSearchText ); break;
224  }
225 
226  if( Component )
227  {
228  if( !notFound )
229  msg.Printf( _( "%s %s found" ), aReference, msg_item );
230  else
231  msg.Printf( _( "%s found but %s not found" ), aReference, msg_item );
232  }
233  else
234  msg.Printf( _( "Component %s not found" ), aReference );
235 
236  SetStatusText( msg );
237 
238  // highlight selection if foundItem is not null, or clear any highlighted selection
239  GetCanvas()->GetView()->HighlightItem( foundItem, pin );
240  GetCanvas()->Refresh();
241 
242  return item;
243 }
244 
245 
247 {
248  int mod_hash = Prj().SchSymbolLibTable()->GetModifyHash();
249 
250  // the cache is obsolete whenever any library changes.
251  if( mod_hash != m_foundItems.GetLibHash() )
252  {
254  m_foundItems.SetLibHash( mod_hash );
255  return true;
256  }
257  else if( m_foundItems.IsSearchRequired( aSearchCriteria ) )
258  return true;
259  else
260  return false;
261 }
262 
263 
264 void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
265 {
266  SCH_FIND_REPLACE_DATA searchCriteria;
268 
269  searchCriteria.SetFlags( aEvent.GetFlags() );
270  searchCriteria.SetFindString( aEvent.GetFindString() );
271  searchCriteria.SetReplaceString( aEvent.GetReplaceString() );
272 
273  if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
274  {
275  if( m_foundItems.GetCount() == 0 )
276  return;
277  }
278  else if( IsSearchCacheObsolete( searchCriteria ) )
279  {
280  if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 )
281  {
282  m_foundItems.Collect( searchCriteria, g_CurrentSheet );
283  }
284  else
285  {
286  m_foundItems.Collect( searchCriteria );
287  }
288  }
289  else
290  {
291  EDA_ITEM* currentItem = m_foundItems.GetItem( data );
292 
293  if( currentItem != NULL )
294  currentItem->SetForceVisible( false );
295 
297  }
298 
299  updateFindReplaceView( aEvent );
300 }
301 
302 
303 void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
304 {
305  SCH_ITEM* item;
306  SCH_SHEET_PATH* sheet;
307  SCH_SHEET_LIST schematic( g_RootSheet );
309  SCH_FIND_REPLACE_DATA searchCriteria;
310 
311  searchCriteria.SetFlags( aEvent.GetFlags() );
312  searchCriteria.SetFindString( aEvent.GetFindString() );
313  searchCriteria.SetReplaceString( aEvent.GetReplaceString() );
314  m_foundItems.SetReplaceString( aEvent.GetReplaceString() );
315 
316  if( IsSearchCacheObsolete( searchCriteria ) )
317  {
318  if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 )
319  {
320  m_foundItems.Collect( searchCriteria, g_CurrentSheet );
321  }
322  else
323  {
324  m_foundItems.Collect( searchCriteria );
325  }
326  }
327 
328  if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
329  {
330  while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
331  {
332  SCH_ITEM* undoItem = data.GetParent();
333 
334  // Don't save child items in undo list.
335  if( undoItem == NULL )
336  undoItem = item;
337 
338  sheet = schematic.GetSheetByPath( data.GetSheetPath() );
339 
340  wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );
341 
342  if( m_foundItems.ReplaceItem( sheet ) )
343  {
344  GetCanvas()->GetView()->Update( undoItem, KIGFX::ALL );
345  OnModify();
346  SaveUndoItemInUndoList( undoItem );
347  updateFindReplaceView( aEvent );
348  }
349 
351 
352  if( m_foundItems.PassedEnd() )
353  break;
354  }
355  }
356  else
357  {
358  item = (SCH_ITEM*) m_foundItems.GetItem( data );
359 
360  wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) );
361 
362  SCH_ITEM* undoItem = data.GetParent();
363 
364  if( undoItem == NULL )
365  undoItem = item;
366 
367  sheet = schematic.GetSheetByPath( data.GetSheetPath() );
368 
369  wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );
370 
371  if( m_foundItems.ReplaceItem( sheet ) )
372  {
373  GetCanvas()->GetView()->Update( undoItem, KIGFX::ALL );
374  OnModify();
375  SaveUndoItemInUndoList( undoItem );
376  updateFindReplaceView( aEvent );
377 
378  // A single replace is part of the search; it does not dirty it.
379  m_foundItems.SetForceSearch( false );
380  }
381 
383  }
384 
385  // End the replace if we are at the end if the list. This prevents an infinite loop if
386  // wrap search is selected and all of the items have been replaced with a value that
387  // still satisfies the search criteria.
388  if( m_foundItems.PassedEnd() )
389  aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND );
390 }
391 
392 
393 void SCH_EDIT_FRAME::updateFindReplaceView( wxFindDialogEvent& aEvent )
394 {
395  wxString msg;
396  SCH_SHEET_LIST schematic( g_RootSheet );
398  bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
399 
400  if( m_foundItems.GetItem( data ) != NULL )
401  {
402  wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText( MILLIMETRES ) );
403 
404  SCH_SHEET_PATH* sheet = schematic.GetSheetByPath( data.GetSheetPath() );
405 
406  wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) +
407  data.GetSheetPath() );
408 
409  SCH_ITEM* item = (SCH_ITEM*)m_foundItems.GetItem( data );
410 
411  // Make the item temporarily visible just in case it's hide flag is set. This
412  // has no effect on objects that don't support hiding. If this is a close find
413  // dialog event, clear the temporary visibility flag.
414  if( item )
415  {
416  if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
417  item->SetForceVisible( false );
418  else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() )
419  item->SetForceVisible( true );
420  }
421 
422  if( sheet->PathHumanReadable() != g_CurrentSheet->PathHumanReadable() )
423  {
424  sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() );
425  *g_CurrentSheet = *sheet;
427  SetScreen( sheet->LastScreen() );
428  sheet->LastScreen()->TestDanglingEnds();
429  }
430 
432  CenterScreen( data.GetPosition(), warpCursor );
433 
435 
436  if( aEvent.GetFlags() & FR_SEARCH_REPLACE )
437  aEvent.SetFlags( aEvent.GetFlags() | FR_REPLACE_ITEM_FOUND );
438  }
439  else
440  {
441  if( aEvent.GetFlags() & FR_SEARCH_REPLACE )
442  aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND );
443 
444  msg.Printf( _( "No item found matching %s." ), GetChars( aEvent.GetFindString() ) );
445  }
446 
447  *m_findReplaceStatus = msg;
448  SetStatusText( msg );
449 }
void OnFindDrcMarker(wxFindDialogEvent &event)
Definition: find.cpp:60
Class SCH_SHEET_LIST.
int GetLibHash() const
Class SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
wxString * m_findReplaceStatus
const wxChar *const traceFindReplace
Flag to enable find and replace debug tracing.
bool IsSearchRequired(const SCH_FIND_REPLACE_DATA &aFindReplaceData)
Function IsSearchRequired checks the current collector state against aFindReplaceData to see if a new...
SCH_SHEET_PATHS::iterator SCH_SHEET_PATHS_ITER
This file is part of the common library TODO brief description.
SCH_ITEM * FindNextItem(KICAD_T aType, SCH_SHEET_PATH **aSheetFound=NULL, SCH_ITEM *aLastItem=NULL, bool aWrap=true)
Function FindNextItem searches the entire schematic for the next schematic object.
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
SCH_ITEM * Next() const
Definition: sch_item.h:153
virtual void SetScreen(BASE_SCREEN *aScreen) override
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_marker.h:93
int CountSheets()
Count the number of sheets found in "this" sheet includeing all of the subsheets.
Definition: sch_sheet.cpp:606
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_field.cpp:550
SCH_FIND_COLLECTOR m_foundItems
List of find/replace items.
Find a component in the schematic.
Find an item by it's value field.
Used by the search event handler to let the dialog know that a replaceable item has been found.
LIB_PIN * GetPin(const wxString &number)
Find a symbol pin by number.
Wrap around the beginning or end of search list.
void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void DisplayCurrentSheet()
Draw the current sheet on the display.
Definition: hierarch.cpp:258
SCH_SHEET_PATH * GetSheetByPath(const wxString &aPath, bool aHumanReadable=true)
Function GetSheetByPath returns a sheet matching the path name in aPath.
Item needs to be redrawn.
Definition: view_item.h:61
void UpdateAllScreenReferences()
Function UpdateAllScreenReferences updates the reference and the m_Multi parameter (part selection) f...
Class SCH_FIND_COLLECTOR_DATA is used as a data container for the associated item found by the SCH_FI...
wxString GetShownText() const override
Returns the string actually shown after processing of the base text.
Definition: sch_field.cpp:115
void HighlightItem(EDA_ITEM *aItem, LIB_PIN *aPin=nullptr)
Definition: sch_view.cpp:191
Field Reference of part, i.e. "IC21".
Find a component pin in the schematic.
static const int delta[8][2]
Definition: solve.cpp:112
SCH_ITEM * FindComponentAndItem(const wxString &aReference, bool aSearchHierarchy, SCH_SEARCH_T aSearchType, const wxString &aSearchText)
Finds a component in the schematic and an item in this component.
Definition: find.cpp:109
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
void updateFindReplaceView(wxFindDialogEvent &aEvent)
Definition: find.cpp:393
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
wxString MessageTextFromValue(EDA_UNITS_T aUnits, int aValue, bool aUseMils)
Definition: base_units.cpp:125
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
void SetLibHash(int aHash)
void OnFindSchematicItem(wxFindDialogEvent &aEvent)
Find an item in the schematic matching the search criteria in aEvent.
Definition: find.cpp:264
#define VALUE
a helper to handle the real device context used in KiCad
void SetForceSearch(bool doSearch=true)
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:56
SCH_SHEET_PATH * g_CurrentSheet
With the new connectivity algorithm, many more places than before want to know what the current sheet...
wxString Path() const
Function Path the path uses the time stamps which do not changes even when editing sheet parameters a...
SCH_ITEM * GetItem(int ndx) const
void UpdateIndex()
Function UpdateIndex updates the list index according to the current find and replace criteria.
bool ReplaceItem(SCH_SHEET_PATH *aSheetPath=NULL)
Function ReplaceItem performs a string replace of the item at the current index.
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
TRANSFORM & GetTransform() const
Subclass of DIALOG_SCH_FIND_BASE, which is generated by wxFormBuilder.
void SetForceVisible(bool aEnable)
Function SetForceVisible is used to set and cleag force visible flag used to force the item to be dra...
Definition: base_struct.h:309
SCH_DRAW_PANEL * GetCanvas() const override
wxLogTrace helper definitions.
wxString GetSheetPath() const
virtual bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
Class SCH_SHEET_PATH.
bool IsSearchCacheObsolete(const SCH_FIND_REPLACE_DATA &aSearchCriteria)
Definition: find.cpp:246
Search the current sheet only.
void BuildSheetList(SCH_SHEET *aSheet)
Function BuildSheetList builds the list of sheets and their sheet path from aSheet.
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1539
void SaveUndoItemInUndoList(SCH_ITEM *aItem, bool aAppend=false)
Swap the cloned item in member variable m_undoItem with aItem and saves it to the undo list then swap...
const wxString GetRef(const SCH_SHEET_PATH *aSheet)
Return the reference for the given sheet path.
KIGFX::SCH_VIEW * GetView() const
wxPoint GetPosition() const override
Return the current draw object position.
Definition: lib_pin.h:432
Find a component field.
SCH_ITEM * FindNextItem(KICAD_T aType, SCH_ITEM *aLastItem=NULL, bool aWrap=false) const
Find the next schematic item in this sheet object.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:100
see class PGM_BASE
void SetReplaceString(const wxString &aReplaceString)
Update the replace string without changing anything else.
SCH_SEARCH_T
Schematic search type used by the socket link with Pcbnew.
Don't warp cursor to found item until the dialog is closed.
void Collect(SCH_FIND_REPLACE_DATA &aFindReplaceData, SCH_SHEET_PATH *aSheetPath=NULL)
Function Collect scans aSheetPath using this class's Inspector method for items matching aFindReplace...
Class SCH_FIND_REPLACE_DATA adds missing useful comparison and assignment operators to the wxFindRepl...
Find an item by it's reference designator.
Perform a search for a item that has replaceable text.
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
wxPoint GetPosition() const override
Function GetPosition.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:157
wxString GetText(EDA_UNITS_T aUnits)
Function GetText()
bool PassedEnd() const
Function PassedEnd tests if m_foundIndex is beyond the end of the list give the current find/replace ...
virtual void CenterScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
Definition for part library class.
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Set the screen cross hair position to aPosition in logical (drawing) units.
EDA_UNITS_T m_UserUnits
Definition: draw_frame.h:125
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Definition: sch_item.h:114
wxPoint GetPosition() const
SCH_SCREEN * LastScreen() const
Function LastScreen.
SCH_ITEM * GetParent() const
KICAD_T Type() const
Function Type()
Definition: base_struct.h:204
void OnFindReplace(wxFindDialogEvent &aEvent)
Perform a search and replace of text in an item in the schematic matching the search and replace crit...
Definition: find.cpp:303