KiCad PCB EDA Suite
common.h File Reference

The common library. More...

#include <vector>
#include <functional>
#include <wx/confbase.h>
#include <wx/fileconf.h>
#include <wx/dir.h>
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/process.h>
#include <atomic>
#include <limits>
#include <memory>
#include <type_traits>
#include <typeinfo>
#include <macros.h>

Go to the source code of this file.

Classes

struct  std::hash< wxString >
 
struct  std::hash< wxPoint >
 
struct  std::less< wxPoint >
 

Namespaces

 std
 

Template specialization to enable wxStrings for certain containers (e.g. unordered_map)


 

Macros

#define USE_KICAD_WXSTRING_HASH
 
#define USE_KICAD_WXPOINT_LESS_AND_HASH
 Required to use wxPoint as key type in maps. More...
 

Functions

int ProcessExecute (const wxString &aCommandLine, int aFlags=wxEXEC_ASYNC, wxProcess *callback=NULL)
 Run a command in a child process. More...
 
wxString SearchHelpFileFullPath (const SEARCH_STACK &aSearchStack, const wxString &aBaseName)
 Return the help file's full path. More...
 
bool EnsureFileDirectoryExists (wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter=NULL)
 Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist. More...
 
const wxString ExpandEnvVarSubstitutions (const wxString &aString, PROJECT *aProject)
 Replace any environment variable & text variable references with their values. More...
 
wxString ExpandTextVars (const wxString &aSource, const std::function< bool(wxString *)> *aLocalResolver, const PROJECT *aProject, const std::function< bool(wxString *)> *aFallbackResolver=nullptr)
 Expand '${var-name}' templates in text. More...
 
const wxString ResolveUriByEnvVars (const wxString &aUri, PROJECT *aProject)
 Replace any environment and/or text variables in file-path uris (leaving network-path URIs alone). More...
 
std::ostream & operator<< (std::ostream &out, const wxSize &size)
 Helper function to print the given wxSize to a stream. More...
 
std::ostream & operator<< (std::ostream &out, const wxPoint &pt)
 Helper function to print the given wxPoint to a stream. More...
 
long long TimestampDir (const wxString &aDirPath, const wxString &aFilespec)
 A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/filename.cpp. More...
 

Detailed Description

The common library.

Definition in file common.h.

Macro Definition Documentation

◆ USE_KICAD_WXPOINT_LESS_AND_HASH

#define USE_KICAD_WXPOINT_LESS_AND_HASH

Required to use wxPoint as key type in maps.

Definition at line 163 of file common.h.

◆ USE_KICAD_WXSTRING_HASH

#define USE_KICAD_WXSTRING_HASH

Definition at line 151 of file common.h.

Function Documentation

◆ EnsureFileDirectoryExists()

bool EnsureFileDirectoryExists ( wxFileName *  aTargetFullFileName,
const wxString &  aBaseFilename,
REPORTER aReporter = NULL 
)

Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.

Parameters
aTargetFullFileNamethe wxFileName containing the full path and file name to modify. The path may be absolute or relative to aBaseFilename .
aBaseFilenamea full filename. Only its path is used to set the aTargetFullFileName path.
aReportera point to a REPORTER object use to show messages (can be NULL)
Returns
true if aOutputDir already exists or was successfully created.

Definition at line 283 of file common.cpp.

286 {
287  wxString msg;
288  wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
289 
290  // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
291  // already an absolute path) absolute:
292  if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
293  {
294  if( aReporter )
295  {
296  msg.Printf( _( "Cannot make path \"%s\" absolute with respect to \"%s\"." ),
297  aTargetFullFileName->GetPath(),
298  baseFilePath );
299  aReporter->Report( msg, RPT_SEVERITY_ERROR );
300  }
301 
302  return false;
303  }
304 
305  // Ensure the path of aTargetFullFileName exists, and create it if needed:
306  wxString outputPath( aTargetFullFileName->GetPath() );
307 
308  if( !wxFileName::DirExists( outputPath ) )
309  {
310  if( wxMkdir( outputPath ) )
311  {
312  if( aReporter )
313  {
314  msg.Printf( _( "Output directory \"%s\" created.\n" ), outputPath );
315  aReporter->Report( msg, RPT_SEVERITY_INFO );
316  return true;
317  }
318  }
319  else
320  {
321  if( aReporter )
322  {
323  msg.Printf( _( "Cannot create output directory \"%s\".\n" ), outputPath );
324  aReporter->Report( msg, RPT_SEVERITY_ERROR );
325  }
326 
327  return false;
328  }
329  }
330 
331  return true;
332 }
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
#define _(s)
Definition: 3d_actions.cpp:33

References _, REPORTER::Report(), RPT_SEVERITY_ERROR, and RPT_SEVERITY_INFO.

Referenced by DIALOG_GEN_FOOTPRINT_POSITION::CreateAsciiFiles(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), DIALOG_PLOT_SCHEMATIC::createPlotFileName(), DIALOG_EXPORT_SVG::ExportSVGFile(), DIALOG_GENDRILL::GenDrillAndMapFiles(), PLOT_CONTROLLER::OpenPlotfile(), and DIALOG_PLOT::Plot().

◆ ExpandEnvVarSubstitutions()

const wxString ExpandEnvVarSubstitutions ( const wxString &  aString,
PROJECT aProject 
)

Replace any environment variable & text variable references with their values.

Parameters
aString= a string containing (perhaps) references to env var
Returns
a string where env var are replaced by their value

Definition at line 255 of file common.cpp.

256 {
257  // wxGetenv( wchar_t* ) is not re-entrant on linux.
258  // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
259  static std::mutex getenv_mutex;
260 
261  std::lock_guard<std::mutex> lock( getenv_mutex );
262 
263  // We reserve the right to do this another way, by providing our own member function.
264  return KIwxExpandEnvVars( aString, aProject );
265 }
wxString KIwxExpandEnvVars(const wxString &str, const PROJECT *aProject)
Definition: common.cpp:116

References KIwxExpandEnvVars().

Referenced by FILENAME_RESOLVER::addPath(), FILENAME_RESOLVER::checkEnvVarPath(), S3D_PLUGIN_MANAGER::checkPluginName(), S3D_PLUGIN_MANAGER::checkPluginPath(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), FILENAME_RESOLVER::createPathList(), DIALOG_PLOT_SCHEMATIC::createPlotFileName(), DIALOG_EXPORT_SVG::ExportSVGFile(), DIALOG_GENDRILL::GenDrillAndMapFiles(), LIB_TABLE_ROW::GetFullURI(), WS_DATA_MODEL::MakeFullFileName(), TEXT_BUTTON_FILE_BROWSER::OnButtonClick(), DIALOG_GENDRILL::OnGenReportFile(), DIALOG_EXPORT_SVG::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT::OnOutputDirectoryBrowseClicked(), DIALOG_GEN_FOOTPRINT_POSITION::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT_SCHEMATIC::OnOutputDirectoryBrowseClicked(), DIALOG_GENDRILL::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT::Plot(), FILENAME_RESOLVER::ResolvePath(), ResolveUriByEnvVars(), FILENAME_RESOLVER::Set3DConfigDir(), S3D_CACHE::Set3DConfigDir(), FILENAME_RESOLVER::SetProject(), FILENAME_RESOLVER::ShortenPath(), and ERC_TESTER::TestTextVars().

◆ ExpandTextVars()

wxString ExpandTextVars ( const wxString &  aSource,
const std::function< bool(wxString *)> *  aLocalResolver,
const PROJECT aProject,
const std::function< bool(wxString *)> *  aFallbackResolver = nullptr 
)

Expand '${var-name}' templates in text.

The LocalResolver is given first crack at it, after which the PROJECT's resolver is called.

Definition at line 58 of file common.cpp.

62 {
63  wxString newbuf;
64  size_t sourceLen = aSource.length();
65 
66  newbuf.Alloc( sourceLen ); // best guess (improves performance)
67 
68  for( size_t i = 0; i < sourceLen; ++i )
69  {
70  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
71  {
72  wxString token;
73 
74  for( i = i + 2; i < sourceLen; ++i )
75  {
76  if( aSource[i] == '}' )
77  break;
78  else
79  token.append( aSource[i] );
80  }
81 
82  if( token.IsEmpty() )
83  continue;
84 
85  if( aLocalResolver && (*aLocalResolver)( &token ) )
86  {
87  newbuf.append( token );
88  }
89  else if( aProject && aProject->TextVarResolver( &token ) )
90  {
91  newbuf.append( token );
92  }
93  else if( aFallbackResolver && (*aFallbackResolver)( &token ) )
94  {
95  newbuf.append( token );
96  }
97  else
98  {
99  // Token not resolved: leave the reference unchanged
100  newbuf.append( "${" + token + "}" );
101  }
102  }
103  else
104  {
105  newbuf.append( aSource[i] );
106  }
107  }
108 
109  return newbuf;
110 }
VTBL_ENTRY bool TextVarResolver(wxString *aToken) const
Definition: project.cpp:66

References PROJECT::TextVarResolver().

Referenced by WS_DRAW_ITEM_LIST::BuildFullText(), PCB_TEXT::GetShownText(), SCH_FIELD::GetShownText(), FP_TEXT::GetShownText(), SCH_TEXT::GetShownText(), and ResolveUriByEnvVars().

◆ operator<<() [1/2]

std::ostream& operator<< ( std::ostream &  out,
const wxSize &  size 
)

Helper function to print the given wxSize to a stream.

Used for debugging functions like EDA_ITEM::Show and also in unit testing fixtures.

Definition at line 412 of file common.cpp.

413 {
414  out << " width=\"" << size.GetWidth() << "\" height=\"" << size.GetHeight() << "\"";
415  return out;
416 }

◆ operator<<() [2/2]

std::ostream& operator<< ( std::ostream &  out,
const wxPoint &  pt 
)

Helper function to print the given wxPoint to a stream.

Used for debugging functions like EDA_ITEM::Show and also in unit testing fixtures.

Definition at line 419 of file common.cpp.

420 {
421  out << " x=\"" << pt.x << "\" y=\"" << pt.y << "\"";
422  return out;
423 }

◆ ProcessExecute()

int ProcessExecute ( const wxString &  aCommandLine,
int  aFlags = wxEXEC_ASYNC,
wxProcess *  callback = NULL 
)

Run a command in a child process.

Parameters
aCommandLineThe process and any arguments to it all in a single string.
aFlagsThe same args as allowed for wxExecute()
callbackwxProcess implementing OnTerminate to be run when the child process finishes
Returns
int - pid of process, 0 in case of error (like return values of wxExecute())

Definition at line 40 of file common.cpp.

41 {
42  return (int) wxExecute( aCommandLine, aFlags, callback );
43 }

Referenced by doPrintFile(), ExecuteFile(), GetAssociatedDocument(), OpenFile(), OpenPDF(), and SCH_EDIT_FRAME::WriteNetListFile().

◆ ResolveUriByEnvVars()

const wxString ResolveUriByEnvVars ( const wxString &  aUri,
PROJECT aProject 
)

Replace any environment and/or text variables in file-path uris (leaving network-path URIs alone).

Definition at line 268 of file common.cpp.

269 {
270  wxString uri = ExpandTextVars( aUri, nullptr, aProject );
271 
272  // URL-like URI: return as is.
273  wxURL url( uri );
274 
275  if( url.GetError() == wxURL_NOERR )
276  return uri;
277 
278  // Otherwise, the path points to a local file. Resolve environment variables if any.
279  return ExpandEnvVarSubstitutions( aUri, aProject );
280 }
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:255
wxString ExpandTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aLocalResolver, const PROJECT *aProject, const std::function< bool(wxString *)> *aFallbackResolver)
Expand '${var-name}' templates in text.
Definition: common.cpp:58

References ExpandEnvVarSubstitutions(), and ExpandTextVars().

Referenced by GetAssociatedDocument().

◆ SearchHelpFileFullPath()

wxString SearchHelpFileFullPath ( const SEARCH_STACK aSearchStack,
const wxString &  aBaseName 
)

Return the help file's full path.

Return the KiCad help file with path and extension. Help files can be html (.html ext) or pdf (.pdf ext) files. A <BaseName>.html file is searched and if not found, <BaseName>.pdf file is searched in the same path. If the help file for the current locale is not found, an attempt to find the English version of the help file is made. Help file is searched in directories in this order: help/<canonical name> like help/en_GB help/<short name> like help/en help/en

Parameters
aSearchStackcontains some possible base dirs that may be above the the one actually holding aBaseName. These are starting points for nested searches.
aBaseNameis the name of the help file to search for,

without extension

.

Returns
wxEmptyString is returned if aBaseName is not found, else the full path & filename.

Definition at line 68 of file searchhelpfilefullpath.cpp.

69 {
70  wxArrayString subdirs;
71  wxArrayString altsubdirs;
72  SEARCH_STACK ss = aSStack;
73 
74  // It might already be in aSStack, but why depend on other code
75  // far away when it's so easy to add it again (to our copy) as the first place to look.
76 
77  // This is CMAKE_INSTALL_PREFIX unless DEFAULT_INSTALL_PATH was defined during
78  // build configuration:
79  ss.AddPaths( wxT( DEFAULT_INSTALL_PATH ), 0 );
80 
81 #if defined(__WXMAC__)
82  ss.AddPaths( GetOSXKicadMachineDataDir() );
83  ss.AddPaths( Pgm().GetExecutablePath(), 0 );
84 
85  // OS X packages can have the help files in
86  // /Library/Application\ Support/kicad/help,
87  // and in Contents/SharedSupport/help inside the
88  // bundle.
89  // Below we account for an international subdirectory.
90  subdirs.Add( "help" );
91  altsubdirs.Add( "Contents" );
92  altsubdirs.Add( "SharedSupport" );
93  altsubdirs.Add( "help" );
94 #endif
95 
96 #if ! defined(__WXMAC__) // && defined(__linux__)
97  // This is the executable path minus the trailing bin directory used on Windows and Linux.
98  wxFileName tmp( Pgm().GetExecutablePath(), wxEmptyString );
99  wxArrayString binDirs = tmp.GetDirs();
100 
101  if( !binDirs.IsEmpty() && binDirs[ binDirs.GetCount() - 1 ].CmpNoCase( wxT( "bin" ) ) == 0 )
102  tmp.RemoveLastDir();
103 
104  ss.AddPaths( tmp.GetPath(), 0 );
105 
106  // Based on kicad-doc.bzr/CMakeLists.txt, line 20, the help files are
107  // installed into "<CMAKE_INSTALL_PREFIX>/share/doc/kicad/help" for linux.
108  // This is ${KICAD_HELP} var in that CMakeLists.txt file.
109  // Below we account for an international subdirectory.
110  subdirs.Add( "share" );
111  subdirs.Add( "doc" );
112  subdirs.Add( "kicad" );
113  subdirs.Add( "help" );
114 
115  // Based on kicad-doc.bzr/CMakeLists.txt, line 35, the help files are
116  // installed into "<CMAKE_INSTALL_PREFIX>/doc/help" for Windows.
117  // This is ${KICAD_HELP} var in that CMakeLists.txt file.
118  // Below we account for an international subdirectory.
119  altsubdirs.Add( "doc" );
120  altsubdirs.Add( "help" );
121 #endif
122 
123  // If there's a KICAD environment variable set, always use that guy's path first.
124  if( !Pgm().GetKicadEnvVariable().IsEmpty() )
125  ss.AddPaths( Pgm().GetKicadEnvVariable(), 0 );
126 
127  /* Search for a help file.
128  * we *must* find a help file.
129  * so help is searched in directories in this order:
130  * help/<canonical name> like help/en_GB
131  * help/<short name> like help/en
132  * help/en
133  */
134 
135  wxLocale* i18n = Pgm().GetLocale();
136 
137  // We try to find help file in help/<canonical name>
138  // If fails, try to find help file in help/<short canonical name>
139  // If fails, try to find help file in help/en
140  wxArrayString locale_name_dirs;
141  locale_name_dirs.Add( i18n->GetCanonicalName() ); // canonical name like fr_FR
142 
143  // wxLocale::GetName() does not return always the short name
144  locale_name_dirs.Add( i18n->GetName().BeforeLast( '_' ) ); // short canonical name like fr
145  locale_name_dirs.Add( "en" ); // default (en)
146 
147 #if defined(DEBUG) && 1
148  ss.Show( wxString( __func__ ) );
149  wxLogTrace( tracePathsAndFiles, "%s: m_help_file:'%s'", __func__, aBaseName );
150 #endif
151 
152  wxLogTrace( tracePathsAndFiles, "Checking SEARCH_STACK for file %s", aBaseName );
153 
154  // Help files can be html (.html ext) or pdf (.pdf ext) files.
155  // Therefore, <BaseName>.html file is searched and if not found,
156  // <BaseName>.pdf file is searched in the same paths
157  wxString fn;
158 
159  for( unsigned ii = 0; ii < locale_name_dirs.GetCount(); ii++ )
160  {
161  subdirs.Add( locale_name_dirs[ii] );
162  altsubdirs.Add( locale_name_dirs[ii] );
163 
164  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".html" ), &altsubdirs );
165 
166  if( !fn.IsEmpty() )
167  {
168  // Prepend URI protocol since we will open in a browser
169  fn = wxT( "file://" ) + fn;
170  break;
171  }
172 
173  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".pdf" ), &altsubdirs );
174 
175  if( !fn.IsEmpty() )
176  break;
177 
178  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".html" ), &subdirs );
179 
180  if( !fn.IsEmpty() )
181  {
182  // Prepend URI protocol since we will open in a browser
183  fn = wxT( "file://" ) + fn;
184  break;
185  }
186 
187  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".pdf" ), &subdirs );
188 
189  if( !fn.IsEmpty() )
190  break;
191 
192  subdirs.RemoveAt( subdirs.GetCount() - 1 );
193  altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 );
194  }
195 
196  return fn;
197 }
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:102
wxString FindFileInSearchPaths(const SEARCH_STACK &aStack, const wxString &aFilename, const wxArrayString *aSubdirs)
Function FindFileInSearchPaths looks in "this" for aFilename, but first modifies every search path by...
void AddPaths(const wxString &aPaths, int aIndex=-1)
Function AddPaths insert or append path(s)

References SEARCH_STACK::AddPaths(), FindFileInSearchPaths(), Pgm(), and tracePathsAndFiles.

Referenced by COMMON_CONTROL::ShowHelp().

◆ TimestampDir()

long long TimestampDir ( const wxString &  aDirPath,
const wxString &  aFilespec 
)

A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/filename.cpp.

TimestampDir

This routine offers SIGNIFICANT performance benefits over using wxWidgets to gather timestamps from matching files in a directory.

Parameters
aDirPaththe directory to search
aFilespeca (wildcarded) file spec to match against
Returns
a hash of the last-mod-dates of all matching files in the directory

Definition at line 582 of file common.cpp.

583 {
584  long long timestamp = 0;
585 
586 #if defined( __WIN32__ )
587  // Win32 version.
588  // Save time by not searching for each path twice: once in wxDir.GetNext() and once in
589  // wxFileName.GetModificationTime(). Also cuts out wxWidgets' string-matching and case
590  // conversion by staying on the MSW side of things.
591  std::wstring filespec( aDirPath.t_str() );
592  filespec += '\\';
593  filespec += aFilespec.t_str();
594 
595  WIN32_FIND_DATA findData;
596  wxDateTime lastModDate;
597 
598  HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
599 
600  if( fileHandle != INVALID_HANDLE_VALUE )
601  {
602  do
603  {
604  ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
605  timestamp += lastModDate.GetValue().GetValue();
606  }
607  while ( FindNextFile( fileHandle, &findData ) != 0 );
608  }
609 
610  FindClose( fileHandle );
611 #else
612  // POSIX version.
613  // Save time by not converting between encodings -- do everything on the file-system side.
614  std::string filespec( aFilespec.fn_str() );
615  std::string dir_path( aDirPath.fn_str() );
616 
617  DIR* dir = opendir( dir_path.c_str() );
618 
619  if( dir )
620  {
621  for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
622  {
623  if( !matchWild( filespec.c_str(), dir_entry->d_name, true ) )
624  continue;
625 
626  std::string entry_path = dir_path + '/' + dir_entry->d_name;
627  struct stat entry_stat;
628 
629  if( wxCRT_Lstat( entry_path.c_str(), &entry_stat ) == 0 )
630  {
631  // Timestamp the source file, not the symlink
632  if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
633  {
634  char buffer[ PATH_MAX + 1 ];
635  ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
636 
637  if( pathLen > 0 )
638  {
639  struct stat linked_stat;
640  buffer[ pathLen ] = '\0';
641  entry_path = dir_path + buffer;
642 
643  if( wxCRT_Lstat( entry_path.c_str(), &linked_stat ) == 0 )
644  {
645  entry_stat = linked_stat;
646  }
647  else
648  {
649  // if we couldn't lstat the linked file we'll have to just use
650  // the symbolic link info
651  }
652  }
653  }
654 
655  if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists()
656  timestamp += entry_stat.st_mtime * 1000;
657  }
658  else
659  {
660  // if we couldn't lstat the file itself all we can do is use the name
661  timestamp += (signed) std::hash<std::string>{}( std::string( dir_entry->d_name ) );
662  }
663  }
664 
665  closedir( dir );
666  }
667 #endif
668 
669  return timestamp;
670 }
bool matchWild(const char *pat, const char *text, bool dot_special)
Performance enhancements to file and directory operations.
Definition: common.cpp:440

References matchWild().

Referenced by FP_CACHE::GetTimestamp(), and GPCB_FPL_CACHE::GetTimestamp().