KiCad PCB EDA Suite
common.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) 2014-2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.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 
30 #include <fctsys.h>
31 #include <eda_base_frame.h>
32 #include <base_struct.h>
33 #include <common.h>
34 #include <macros.h>
35 #include <base_units.h>
36 #include <reporter.h>
37 
38 #include <wx/process.h>
39 #include <wx/config.h>
40 #include <wx/utils.h>
41 #include <wx/stdpaths.h>
42 #include <wx/url.h>
43 
44 #include <pgm_base.h>
45 
46 using KIGFX::COLOR4D;
47 
48 
58 
59 #ifdef _WIN32
60 // a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
61 // when switching the locale to LC_NUMERIC, "C"
62 // It is used in class LOCALE_IO to hide a useless (in kicad) wxWidgets alert message
63 void KiAssertFilter( const wxString &file, int line,
64  const wxString &func, const wxString &cond,
65  const wxString &msg)
66 {
67  if( !msg.Contains( "Decimal separator mismatch" ) )
68  wxTheApp->OnAssertFailure( file, line, func, cond, msg );
69 }
70 #endif
71 
72 std::atomic<unsigned int> LOCALE_IO::m_c_count(0);
73 
74 // Note on Windows, setlocale( LC_NUMERIC, "C" ) works fine to read/write
75 // files with floating point numbers, but generates a overzealous wx alert
76 // in some cases (reading a bitmap for instance)
77 // So we disable alerts during the time a file is read or written
78 
80 {
81  // use thread safe, atomic operation
82  if( m_c_count++ == 0 )
83  {
84  // Store the user locale name, to restore this locale later, in dtor
85  m_user_locale = setlocale( LC_NUMERIC, nullptr );
86 #ifdef _WIN32
87  // Disable wxWidgets alerts
88  wxSetAssertHandler( KiAssertFilter );
89 #endif
90  // Switch the locale to C locale, to read/write files with fp numbers
91  setlocale( LC_NUMERIC, "C" );
92  }
93 }
94 
95 
97 {
98  // use thread safe, atomic operation
99  if( --m_c_count == 0 )
100  {
101  // revert to the user locale
102  setlocale( LC_NUMERIC, m_user_locale.c_str() );
103 #ifdef _WIN32
104  // Enaable wxWidgets alerts
105  wxSetDefaultAssertHandler();
106 #endif
107  }
108 }
109 
110 
111 wxSize GetTextSize( const wxString& aSingleLine, wxWindow* aWindow )
112 {
113  wxCoord width;
114  wxCoord height;
115 
116  {
117  wxClientDC dc( aWindow );
118  dc.SetFont( aWindow->GetFont() );
119  dc.GetTextExtent( aSingleLine, &width, &height );
120  }
121 
122  return wxSize( width, height );
123 }
124 
125 
126 bool EnsureTextCtrlWidth( wxTextCtrl* aCtrl, const wxString* aString )
127 {
128  wxWindow* window = aCtrl->GetParent();
129 
130  if( !window )
131  window = aCtrl;
132 
133  wxString ctrlText;
134 
135  if( !aString )
136  {
137  ctrlText = aCtrl->GetValue();
138  aString = &ctrlText;
139  }
140 
141  wxSize textz = GetTextSize( *aString, window );
142  wxSize ctrlz = aCtrl->GetSize();
143 
144  if( ctrlz.GetWidth() < textz.GetWidth() + 10 )
145  {
146  ctrlz.SetWidth( textz.GetWidth() + 10 );
147  aCtrl->SetSizeHints( ctrlz );
148  return true;
149  }
150 
151  return false;
152 }
153 
154 
155 void SelectReferenceNumber( wxTextEntry* aTextEntry )
156 {
157  wxString ref = aTextEntry->GetValue();
158 
159  if( ref.find_first_of( '?' ) != ref.npos )
160  {
161  aTextEntry->SetSelection( ref.find_first_of( '?' ), ref.find_last_of( '?' ) + 1 );
162  }
163  else
164  {
165  wxString num = ref;
166 
167  while( !num.IsEmpty() && ( !isdigit( num.Last() ) || !isdigit( num.GetChar( 0 ) ) ) )
168  {
169  if( !isdigit( num.Last() ) )
170  num.RemoveLast();
171  if( !isdigit( num.GetChar ( 0 ) ) )
172  num = num.Right( num.Length() - 1);
173  }
174 
175  aTextEntry->SetSelection( ref.Find( num ), ref.Find( num ) + num.Length() );
176 
177  if( num.IsEmpty() )
178  aTextEntry->SetSelection( -1, -1 );
179  }
180 }
181 
182 
183 void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter )
184 {
185  wxString tmp;
186 
187  for( unsigned ii = 0; ii < aText.Length(); ii++ )
188  {
189  if( aText[ii] == aSplitter )
190  {
191  aStrings.Add( tmp );
192  tmp.Clear();
193  }
194 
195  else
196  tmp << aText[ii];
197  }
198 
199  if( !tmp.IsEmpty() )
200  {
201  aStrings.Add( tmp );
202  }
203 }
204 
205 
206 int ProcessExecute( const wxString& aCommandLine, int aFlags, wxProcess *callback )
207 {
208  return wxExecute( aCommandLine, aFlags, callback );
209 }
210 
211 
213 {
214  static timestamp_t oldTimeStamp;
215  timestamp_t newTimeStamp;
216 
217  newTimeStamp = time( NULL );
218 
219  if( newTimeStamp <= oldTimeStamp )
220  newTimeStamp = oldTimeStamp + 1;
221 
222  oldTimeStamp = newTimeStamp;
223 
224  return newTimeStamp;
225 }
226 
227 
228 double RoundTo0( double x, double precision )
229 {
230  assert( precision != 0 );
231 
232  long long ix = KiROUND( x * precision );
233 
234  if ( x < 0.0 )
235  ix = -ix;
236 
237  int remainder = ix % 10; // remainder is in precision mm
238 
239  if( remainder <= 2 )
240  ix -= remainder; // truncate to the near number
241  else if( remainder >= 8 )
242  ix += 10 - remainder; // round to near number
243 
244  if ( x < 0 )
245  ix = -ix;
246 
247  return (double) ix / precision;
248 }
249 
250 
251 wxConfigBase* GetNewConfig( const wxString& aProgName )
252 {
253  wxConfigBase* cfg = 0;
254  wxFileName configname;
255  configname.AssignDir( GetKicadConfigPath() );
256  configname.SetFullName( aProgName );
257 
258  cfg = new wxFileConfig( wxT( "" ), wxT( "" ), configname.GetFullPath() );
259  return cfg;
260 }
261 
262 
264 {
265  wxFileName cfgpath;
266 
267  // http://docs.wxwidgets.org/3.0/classwx_standard_paths.html#a7c7cf595d94d29147360d031647476b0
268  cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
269 
270  // GetUserConfigDir() does not default to ~/.config which is the current standard
271  // configuration file location on Linux. This has been fixed in later versions of wxWidgets.
272 #if !defined( __WXMSW__ ) && !defined( __WXMAC__ )
273  wxArrayString dirs = cfgpath.GetDirs();
274 
275  if( dirs.Last() != ".config" )
276  cfgpath.AppendDir( ".config" );
277 #endif
278 
279  wxString envstr;
280 
281  // This shouldn't cause any issues on Windows or MacOS.
282  if( wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
283  {
284  // Override the assignment above with XDG_CONFIG_HOME
285  cfgpath.AssignDir( envstr );
286  }
287 
288  cfgpath.AppendDir( wxT( "kicad" ) );
289 
290  // Use KICAD_CONFIG_HOME to allow the user to force a specific configuration path.
291  if( wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
292  {
293  // Override the assignment above with KICAD_CONFIG_HOME
294  cfgpath.AssignDir( envstr );
295  }
296 
297  if( !cfgpath.DirExists() )
298  {
299  cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
300  }
301 
302  return cfgpath.GetPath();
303 }
304 
305 
307 {
311 #ifdef __WINDOWS__
312  Bracket_Windows = '%', // yeah, Windows people are a bit strange ;-)
313 #endif
315 };
316 
317 
318 //
319 // Stolen from wxExpandEnvVars and then heavily optimized
320 //
321 wxString KIwxExpandEnvVars(const wxString& str)
322 {
323  size_t strlen = str.length();
324 
325  wxString strResult;
326  strResult.Alloc(strlen);
327 
328  for ( size_t n = 0; n < strlen; n++ ) {
329  wxUniChar str_n = str[n];
330 
331  switch ( str_n.GetValue() ) {
332 #ifdef __WINDOWS__
333  case wxT('%'):
334 #endif // __WINDOWS__
335  case wxT('$'):
336  {
337  Bracket bracket;
338 #ifdef __WINDOWS__
339  if ( str_n == wxT('%') )
340  bracket = Bracket_Windows;
341  else
342 #endif // __WINDOWS__
343  if ( n == strlen - 1 ) {
344  bracket = Bracket_None;
345  }
346  else {
347  switch ( str[n + 1].GetValue() ) {
348  case wxT('('):
349  bracket = Bracket_Normal;
350  str_n = str[++n]; // skip the bracket
351  break;
352 
353  case wxT('{'):
354  bracket = Bracket_Curly;
355  str_n = str[++n]; // skip the bracket
356  break;
357 
358  default:
359  bracket = Bracket_None;
360  }
361  }
362 
363  size_t m = n + 1;
364  wxUniChar str_m = str[m];
365 
366  while ( m < strlen && (wxIsalnum(str_m) || str_m == wxT('_')) )
367  str_m = str[++m];
368 
369  wxString strVarName(str.c_str() + n + 1, m - n - 1);
370 
371 #ifdef __WXWINCE__
372  const bool expanded = false;
373 #else
374  // NB: use wxGetEnv instead of wxGetenv as otherwise variables
375  // set through wxSetEnv may not be read correctly!
376  bool expanded = false;
377  wxString tmp;
378  if (wxGetEnv(strVarName, &tmp))
379  {
380  strResult += tmp;
381  expanded = true;
382  }
383  else
384 #endif
385  {
386  // variable doesn't exist => don't change anything
387 #ifdef __WINDOWS__
388  if ( bracket != Bracket_Windows )
389 #endif
390  if ( bracket != Bracket_None )
391  strResult << str[n - 1];
392  strResult << str_n << strVarName;
393  }
394 
395  // check the closing bracket
396  if ( bracket != Bracket_None ) {
397  if ( m == strlen || str_m != (wxChar)bracket ) {
398  // under MSW it's common to have '%' characters in the registry
399  // and it's annoying to have warnings about them each time, so
400  // ignroe them silently if they are not used for env vars
401  //
402  // under Unix, OTOH, this warning could be useful for the user to
403  // understand why isn't the variable expanded as intended
404 #ifndef __WINDOWS__
405  wxLogWarning(_("Environment variables expansion failed: missing '%c' at position %u in '%s'."),
406  (char)bracket, (unsigned int) (m + 1), str.c_str());
407 #endif // __WINDOWS__
408  }
409  else {
410  // skip closing bracket unless the variables wasn't expanded
411  if ( !expanded )
412  strResult << (wxChar)bracket;
413  str_m = str[++m];
414  }
415  }
416 
417  n = m - 1; // skip variable name
418  str_n = str[n];
419  }
420  break;
421 
422  case wxT('\\'):
423  // backslash can be used to suppress special meaning of % and $
424  if ( n != strlen - 1 && (str[n + 1] == wxT('%') || str[n + 1] == wxT('$')) ) {
425  str_n = str[++n];
426  strResult += str_n;
427 
428  break;
429  }
430  //else: fall through
431 
432  default:
433  strResult += str_n;
434  }
435  }
436 
437  return strResult;
438 }
439 
440 
441 #include <ki_mutex.h>
442 const wxString ExpandEnvVarSubstitutions( const wxString& aString )
443 {
444  // wxGetenv( wchar_t* ) is not re-entrant on linux.
445  // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
446  static MUTEX getenv_mutex;
447 
448  MUTLOCK lock( getenv_mutex );
449 
450  // We reserve the right to do this another way, by providing our own member
451  // function.
452  return KIwxExpandEnvVars( aString );
453 }
454 
455 
456 const wxString ResolveUriByEnvVars( const wxString& aUri )
457 {
458  // URL-like URI: return as is.
459  wxURL url( aUri );
460  if( url.GetError() == wxURL_NOERR )
461  return aUri;
462 
463  // Otherwise, the path points to a local file. Resolve environment
464  // variables if any.
465  return ExpandEnvVarSubstitutions( aUri );
466 }
467 
468 
469 bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName,
470  const wxString& aBaseFilename,
471  REPORTER* aReporter )
472 {
473  wxString msg;
474  wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
475 
476  // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
477  // already an absolute path) absolute:
478  if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
479  {
480  if( aReporter )
481  {
482  msg.Printf( _( "Cannot make path \"%s\" absolute with respect to \"%s\"." ),
483  GetChars( aTargetFullFileName->GetPath() ),
484  GetChars( baseFilePath ) );
485  aReporter->Report( msg, REPORTER::RPT_ERROR );
486  }
487 
488  return false;
489  }
490 
491  // Ensure the path of aTargetFullFileName exists, and create it if needed:
492  wxString outputPath( aTargetFullFileName->GetPath() );
493 
494  if( !wxFileName::DirExists( outputPath ) )
495  {
496  if( wxMkdir( outputPath ) )
497  {
498  if( aReporter )
499  {
500  msg.Printf( _( "Output directory \"%s\" created.\n" ), GetChars( outputPath ) );
501  aReporter->Report( msg, REPORTER::RPT_INFO );
502  return true;
503  }
504  }
505  else
506  {
507  if( aReporter )
508  {
509  msg.Printf( _( "Cannot create output directory \"%s\".\n" ),
510  GetChars( outputPath ) );
511  aReporter->Report( msg, REPORTER::RPT_ERROR );
512  }
513 
514  return false;
515  }
516  }
517 
518  return true;
519 }
520 
521 
522 #ifdef __WXMAC__
523 wxString GetOSXKicadUserDataDir()
524 {
525  // According to wxWidgets documentation for GetUserDataDir:
526  // Mac: ~/Library/Application Support/appname
527  wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
528 
529  // Since appname is different if started via launcher or standalone binary
530  // map all to "kicad" here
531  udir.RemoveLastDir();
532  udir.AppendDir( wxT( "kicad" ) );
533 
534  return udir.GetPath();
535 }
536 
537 
538 wxString GetOSXKicadMachineDataDir()
539 {
540  return wxT( "/Library/Application Support/kicad" );
541 }
542 
543 
544 wxString GetOSXKicadDataDir()
545 {
546  // According to wxWidgets documentation for GetDataDir:
547  // Mac: appname.app/Contents/SharedSupport bundle subdirectory
548  wxFileName ddir( wxStandardPaths::Get().GetDataDir(), wxEmptyString );
549 
550  // This must be mapped to main bundle for everything but kicad.app
551  const wxArrayString dirs = ddir.GetDirs();
552  if( dirs[dirs.GetCount() - 3] != wxT( "kicad.app" ) )
553  {
554  // Bundle structure resp. current path is
555  // kicad.app/Contents/Applications/<standalone>.app/Contents/SharedSupport
556  // and will be mapped to
557  // kicad.app/Contents/SharedSupprt
558  ddir.RemoveLastDir();
559  ddir.RemoveLastDir();
560  ddir.RemoveLastDir();
561  ddir.RemoveLastDir();
562  ddir.AppendDir( wxT( "SharedSupport" ) );
563  }
564 
565  return ddir.GetPath();
566 }
567 #endif
568 
569 // add this only if it is not in wxWidgets (for instance before 3.1.0)
570 #ifdef USE_KICAD_WXSTRING_HASH
571 size_t std::hash<wxString>::operator()( const wxString& s ) const
572 {
573  return std::hash<std::wstring>{}( s.ToStdWstring() );
574 }
575 #endif
576 
577 
578 #ifdef USE_KICAD_WXPOINT_LESS
579 bool std::less<wxPoint>::operator()( const wxPoint& aA, const wxPoint& aB ) const
580 {
581  if( aA.x == aB.x )
582  return aA.y < aB.y;
583 
584  return aA.x < aB.x;
585 }
586 #endif
587 
588 
604 WX_FILENAME::WX_FILENAME( const wxString& aPath, const wxString& aFilename ) :
605  m_fn( aPath, aFilename ),
606  m_path( aPath ),
607  m_fullName( aFilename )
608 { }
609 
610 
611 void WX_FILENAME::SetFullName( const wxString& aFileNameAndExtension )
612 {
613  m_fullName = aFileNameAndExtension;
614 }
615 
616 
617 wxString WX_FILENAME::GetName() const
618 {
619  size_t dot = m_fullName.find_last_of( wxT( '.' ) );
620  return m_fullName.substr( 0, dot );
621 }
622 
623 
624 wxString WX_FILENAME::GetFullName() const
625 {
626  return m_fullName;
627 }
628 
629 
630 wxString WX_FILENAME::GetPath() const
631 {
632  return m_path;
633 }
634 
635 
636 wxString WX_FILENAME::GetFullPath() const
637 {
638  return m_path + wxT( '/' ) + m_fullName;
639 }
640 
641 
642 // Write locally-cached values to the wxFileName. MUST be called before using m_fn.
644 {
645  size_t dot = m_fullName.find_last_of( wxT( '.' ) );
646  m_fn.SetName( m_fullName.substr( 0, dot ) );
647  m_fn.SetExt( m_fullName.substr( dot + 1 ) );
648 }
649 
650 
652 {
653  resolve();
654 
655  if( m_fn.FileExists() )
656  return m_fn.GetModificationTime().GetValue().GetValue();
657 
658  return 0;
659 }
660 
661 
668 bool matchWild( const char* pat, const char* text, bool dot_special )
669 {
670  if ( !*text )
671  {
672  /* Match if both are empty. */
673  return !*pat;
674  }
675 
676  const char *m = pat,
677  *n = text,
678  *ma = NULL,
679  *na = NULL;
680  int just = 0,
681  acount = 0,
682  count = 0;
683 
684  if (dot_special && (*n == '.'))
685  {
686  /* Never match so that hidden Unix files
687  * are never found. */
688  return false;
689  }
690 
691  for (;;)
692  {
693  if (*m == '*')
694  {
695  ma = ++m;
696  na = n;
697  just = 1;
698  acount = count;
699  }
700  else if (*m == '?')
701  {
702  m++;
703  if (!*n++)
704  return false;
705  }
706  else
707  {
708  if (*m == '\\')
709  {
710  m++;
711  /* Quoting "nothing" is a bad thing */
712  if (!*m)
713  return false;
714  }
715  if (!*m)
716  {
717  /*
718  * If we are out of both strings or we just
719  * saw a wildcard, then we can say we have a
720  * match
721  */
722  if (!*n)
723  return true;
724  if (just)
725  return true;
726  just = 0;
727  goto not_matched;
728  }
729  /*
730  * We could check for *n == NULL at this point, but
731  * since it's more common to have a character there,
732  * check to see if they match first (m and n) and
733  * then if they don't match, THEN we can check for
734  * the NULL of n
735  */
736  just = 0;
737  if (*m == *n)
738  {
739  m++;
740  count++;
741  n++;
742  }
743  else
744  {
745 
746  not_matched:
747 
748  /*
749  * If there are no more characters in the
750  * string, but we still need to find another
751  * character (*m != NULL), then it will be
752  * impossible to match it
753  */
754  if (!*n)
755  return false;
756 
757  if (ma)
758  {
759  m = ma;
760  n = ++na;
761  count = acount;
762  }
763  else
764  return false;
765  }
766  }
767  }
768 }
769 
770 
775 #if wxUSE_DATETIME && defined(__WIN32__) && !defined(__WXMICROWIN__)
776 
777 // Convert between wxDateTime and FILETIME which is a 64-bit value representing
778 // the number of 100-nanosecond intervals since January 1, 1601 UTC.
779 //
780 // This is the offset between FILETIME epoch and the Unix/wxDateTime Epoch.
781 static wxInt64 EPOCH_OFFSET_IN_MSEC = wxLL(11644473600000);
782 
783 static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft)
784 {
785  wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
786  t /= 10000; // Convert hundreds of nanoseconds to milliseconds.
787  t -= EPOCH_OFFSET_IN_MSEC;
788 
789  *dt = wxDateTime(t);
790 }
791 
792 #endif // wxUSE_DATETIME && __WIN32__
793 
794 
804 long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec )
805 {
806  long long timestamp = 0;
807 
808 #if defined(__WIN32__)
809  // Win32 version.
810  // Save time by not searching for each path twice: once in wxDir.GetNext() and once in
811  // wxFileName.GetModificationTime(). Also cuts out wxWidgets' string-matching and case
812  // conversion by staying on the MSW side of things.
813  std::wstring filespec( aDirPath.t_str() );
814  filespec += '\\';
815  filespec += aFilespec.t_str();
816 
817  WIN32_FIND_DATA findData;
818  wxDateTime lastModDate;
819 
820  HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
821 
822  if( fileHandle != INVALID_HANDLE_VALUE )
823  {
824  do
825  {
826  ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
827  timestamp += lastModDate.GetValue().GetValue();
828  }
829  while ( FindNextFile( fileHandle, &findData ) != 0);
830  }
831 
832  FindClose( fileHandle );
833 #else
834  // POSIX version.
835  // Save time by not converting between encodings -- do everything on the file-system side.
836  std::string filespec( aFilespec.fn_str() );
837  std::string dir_path( aDirPath.fn_str() );
838 
839  DIR* dir = opendir( dir_path.c_str() );
840 
841  if( dir )
842  {
843  for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
844  {
845  if( !matchWild( filespec.c_str(), dir_entry->d_name, true ) )
846  continue;
847 
848  std::string entry_path = dir_path + '/' + dir_entry->d_name;
849  struct stat entry_stat;
850 
851  wxCRT_Lstat( entry_path.c_str(), &entry_stat );
852 
853  // Timestamp the source file, not the symlink
854  if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
855  {
856  char buffer[ PATH_MAX + 1 ];
857  ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
858 
859  if( pathLen > 0 )
860  {
861  buffer[ pathLen ] = '\0';
862  entry_path = dir_path + buffer;
863 
864  wxCRT_Lstat( entry_path.c_str(), &entry_stat );
865  }
866  }
867 
868  if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists()
869  timestamp += entry_stat.st_mtime * 1000;
870  }
871 
872  closedir( dir );
873  }
874 #endif
875 
876  return timestamp;
877 }
878 
879 
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: common.cpp:183
WX_FILENAME(const wxString &aPath, const wxString &aFilename)
Performance enhancements to file and directory operations.
Definition: common.cpp:604
wxString GetFullName() const
Definition: common.cpp:624
int ProcessExecute(const wxString &aCommandLine, int aFlags, wxProcess *callback)
Run a command in a child process.
Definition: common.cpp:206
~LOCALE_IO()
Definition: common.cpp:96
long timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
Definition: common.h:52
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:120
const wxString ResolveUriByEnvVars(const wxString &aUri)
Replace any environment variables in file-path uris (leaving network-path URIs alone).
Definition: common.cpp:456
Implementation of conversion functions that require both schematic and board internal units...
double RoundTo0(double x, double precision)
Round to the nearest precision.
Definition: common.cpp:228
wxString KIwxExpandEnvVars(const wxString &str)
Definition: common.cpp:321
wxConfigBase * GetNewConfig(const wxString &aProgName)
Create a new wxConfig so we can put configuration files in a more proper place for each platform...
Definition: common.cpp:251
boost::interprocess::interprocess_mutex MUTEX
Establish KiCad MUTEX choices here in this file: typedef MUTEX and typedef MUTLOCK.
Definition: ki_mutex.h:42
wxString m_path
Definition: common.h:411
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
void SetFullName(const wxString &aFileNameAndExtension)
Definition: common.cpp:611
const string & str
Definition: json11.cpp:596
This file contains miscellaneous commonly used macros and functions.
wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition: common.cpp:111
wxFileName m_fn
Definition: common.h:410
wxString GetPath() const
Definition: common.cpp:630
static std::atomic< unsigned int > m_c_count
Definition: common.h:187
void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
Definition: common.cpp:155
long long GetTimestamp()
Definition: common.cpp:651
timestamp_t GetNewTimeStamp()
Definition: common.cpp:212
void resolve()
Definition: common.cpp:643
bool EnsureTextCtrlWidth(wxTextCtrl *aCtrl, const wxString *aString)
Set the minimum pixel width on a text control in order to make a text string be fully visible within ...
Definition: common.cpp:126
const wxString ExpandEnvVarSubstitutions(const wxString &aString)
Replace any environment variable references with their values.
Definition: common.cpp:442
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn&#39;t yet exist...
Definition: common.cpp:469
Bracket
Definition: common.cpp:306
Base window classes and related definitions.
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/...
Definition: common.cpp:804
LOCALE_IO()
Definition: common.cpp:79
wxString GetName() const
Definition: common.cpp:617
wxString GetKicadConfigPath()
Return the user configuration path used to store KiCad&#39;s configuration files.
Definition: common.cpp:263
bool matchWild(const char *pat, const char *text, bool dot_special)
A copy of wxMatchWild(), which wxWidgets attributes to Douglas A.
Definition: common.cpp:668
bool operator()(const wxPoint &aA, const wxPoint &aB) const
Definition: common.cpp:579
boost::interprocess::scoped_lock< MUTEX > MUTLOCK
Definition: ki_mutex.h:43
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:92
see class PGM_BASE
wxString GetFullPath() const
Definition: common.cpp:636
The common library.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
size_t operator()(const wxString &s) const
Definition: common.cpp:571
Basic classes for most KiCad items.
wxString m_fullName
Definition: common.h:412
COLOR4D g_GhostColor
Global variables definitions.
Definition: common.cpp:57
std::string m_user_locale
Definition: common.h:191
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39