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-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2015 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 <wxstruct.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 
43 #include <pgm_base.h>
44 
45 using KIGFX::COLOR4D;
46 
47 
58 
59 
60 /* Class LOCALE_IO
61  * is a class that can be instantiated within a scope in which you are expecting
62  * exceptions to be thrown. Its constructor sets a "C" locale, to read/print files
63  * with fp numbers.
64  * Its destructor insures that the default locale is restored if an exception
65  * is thrown, or not.
66  */
67 
68 std::atomic<unsigned int> LOCALE_IO::m_c_count(0);
69 
71 {
72  // use thread safe, atomic operation
73  if( m_c_count++ == 0 )
74  {
75  // Store the user locale name, to restore this locale later, in dtor
76  m_user_locale = setlocale( LC_ALL, 0 );
77  // Switch the locale to C locale, to read/write files with fp numbers
78  setlocale( LC_ALL, "C" );
79  }
80 }
81 
83 {
84  // use thread safe, atomic operation
85  if( --m_c_count == 0 )
86  {
87  // revert to the user locale
88  setlocale( LC_ALL, m_user_locale.c_str() );
89  }
90 }
91 
92 
93 wxSize GetTextSize( const wxString& aSingleLine, wxWindow* aWindow )
94 {
95  wxCoord width;
96  wxCoord height;
97 
98  {
99  wxClientDC dc( aWindow );
100  dc.SetFont( aWindow->GetFont() );
101  dc.GetTextExtent( aSingleLine, &width, &height );
102  }
103 
104  return wxSize( width, height );
105 }
106 
107 
108 bool EnsureTextCtrlWidth( wxTextCtrl* aCtrl, const wxString* aString )
109 {
110  wxWindow* window = aCtrl->GetParent();
111 
112  if( !window )
113  window = aCtrl;
114 
115  wxString ctrlText;
116 
117  if( !aString )
118  {
119  ctrlText = aCtrl->GetValue();
120  aString = &ctrlText;
121  }
122 
123  wxSize textz = GetTextSize( *aString, window );
124  wxSize ctrlz = aCtrl->GetSize();
125 
126  if( ctrlz.GetWidth() < textz.GetWidth() + 10 )
127  {
128  ctrlz.SetWidth( textz.GetWidth() + 10 );
129  aCtrl->SetSizeHints( ctrlz );
130  return true;
131  }
132 
133  return false;
134 }
135 
136 
137 void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter )
138 {
139  wxString tmp;
140 
141  for( unsigned ii = 0; ii < aText.Length(); ii++ )
142  {
143  if( aText[ii] == aSplitter )
144  {
145  aStrings.Add( tmp );
146  tmp.Clear();
147  }
148 
149  else
150  tmp << aText[ii];
151  }
152 
153  if( !tmp.IsEmpty() )
154  {
155  aStrings.Add( tmp );
156  }
157 }
158 
159 
160 int ProcessExecute( const wxString& aCommandLine, int aFlags, wxProcess *callback )
161 {
162  return wxExecute( aCommandLine, aFlags, callback );
163 }
164 
165 
167 {
168  static time_t oldTimeStamp;
169  time_t newTimeStamp;
170 
171  newTimeStamp = time( NULL );
172 
173  if( newTimeStamp <= oldTimeStamp )
174  newTimeStamp = oldTimeStamp + 1;
175 
176  oldTimeStamp = newTimeStamp;
177 
178  return newTimeStamp;
179 }
180 
181 
182 double RoundTo0( double x, double precision )
183 {
184  assert( precision != 0 );
185 
186  long long ix = KiROUND( x * precision );
187 
188  if ( x < 0.0 )
189  ix = -ix;
190 
191  int remainder = ix % 10; // remainder is in precision mm
192 
193  if( remainder <= 2 )
194  ix -= remainder; // truncate to the near number
195  else if( remainder >= 8 )
196  ix += 10 - remainder; // round to near number
197 
198  if ( x < 0 )
199  ix = -ix;
200 
201  return (double) ix / precision;
202 }
203 
204 
205 wxConfigBase* GetNewConfig( const wxString& aProgName )
206 {
207  wxConfigBase* cfg = 0;
208  wxFileName configname;
209  configname.AssignDir( GetKicadConfigPath() );
210  configname.SetFullName( aProgName );
211 
212  cfg = new wxFileConfig( wxT( "" ), wxT( "" ), configname.GetFullPath() );
213  return cfg;
214 }
215 
216 
218 {
219  wxFileName cfgpath;
220 
221  // From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
222  // Unix: ~ (the home directory)
223  // Windows: "C:\Documents and Settings\username\Application Data"
224  // Mac: ~/Library/Preferences
225  cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
226 
227 #if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
228  wxString envstr;
229 
230  if( !wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) || envstr.IsEmpty() )
231  {
232  // XDG_CONFIG_HOME is not set, so use the fallback
233  cfgpath.AppendDir( wxT( ".config" ) );
234  }
235  else
236  {
237  // Override the assignment above with XDG_CONFIG_HOME
238  cfgpath.AssignDir( envstr );
239  }
240 #endif
241 
242  cfgpath.AppendDir( wxT( "kicad" ) );
243 
244  if( !cfgpath.DirExists() )
245  {
246  cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
247  }
248 
249  return cfgpath.GetPath();
250 }
251 
252 
253 #include <ki_mutex.h>
254 const wxString ExpandEnvVarSubstitutions( const wxString& aString )
255 {
256  // wxGetenv( wchar_t* ) is not re-entrant on linux.
257  // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
258  static MUTEX getenv_mutex;
259 
260  MUTLOCK lock( getenv_mutex );
261 
262  // We reserve the right to do this another way, by providing our own member
263  // function.
264  return wxExpandEnvVars( aString );
265 }
266 
267 bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName,
268  const wxString& aBaseFilename,
269  REPORTER* aReporter )
270 {
271  wxString msg;
272  wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
273 
274  // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
275  // already an absolute path) absolute:
276  if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
277  {
278  if( aReporter )
279  {
280  msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ),
281  GetChars( aTargetFullFileName->GetPath() ),
282  GetChars( baseFilePath ) );
283  aReporter->Report( msg, REPORTER::RPT_ERROR );
284  }
285 
286  return false;
287  }
288 
289  // Ensure the path of aTargetFullFileName exists, and create it if needed:
290  wxString outputPath( aTargetFullFileName->GetPath() );
291 
292  if( !wxFileName::DirExists( outputPath ) )
293  {
294  if( wxMkdir( outputPath ) )
295  {
296  if( aReporter )
297  {
298  msg.Printf( _( "Output directory '%s' created.\n" ), GetChars( outputPath ) );
299  aReporter->Report( msg, REPORTER::RPT_INFO );
300  return true;
301  }
302  }
303  else
304  {
305  if( aReporter )
306  {
307  msg.Printf( _( "Cannot create output directory '%s'.\n" ),
308  GetChars( outputPath ) );
309  aReporter->Report( msg, REPORTER::RPT_ERROR );
310  }
311 
312  return false;
313  }
314  }
315 
316  return true;
317 }
318 
319 
320 #ifdef __WXMAC__
321 wxString GetOSXKicadUserDataDir()
322 {
323  // According to wxWidgets documentation for GetUserDataDir:
324  // Mac: ~/Library/Application Support/appname
325  wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
326 
327  // Since appname is different if started via launcher or standalone binary
328  // map all to "kicad" here
329  udir.RemoveLastDir();
330  udir.AppendDir( wxT( "kicad" ) );
331 
332  return udir.GetPath();
333 }
334 
335 
336 wxString GetOSXKicadMachineDataDir()
337 {
338  return wxT( "/Library/Application Support/kicad" );
339 }
340 
341 
342 wxString GetOSXKicadDataDir()
343 {
344  // According to wxWidgets documentation for GetDataDir:
345  // Mac: appname.app/Contents/SharedSupport bundle subdirectory
346  wxFileName ddir( wxStandardPaths::Get().GetDataDir(), wxEmptyString );
347 
348  // This must be mapped to main bundle for everything but kicad.app
349  const wxArrayString dirs = ddir.GetDirs();
350  if( dirs[dirs.GetCount() - 3] != wxT( "kicad.app" ) )
351  {
352  // Bundle structure resp. current path is
353  // kicad.app/Contents/Applications/<standalone>.app/Contents/SharedSupport
354  // and will be mapped to
355  // kicad.app/Contents/SharedSupprt
356  ddir.RemoveLastDir();
357  ddir.RemoveLastDir();
358  ddir.RemoveLastDir();
359  ddir.RemoveLastDir();
360  ddir.AppendDir( wxT( "SharedSupport" ) );
361  }
362 
363  return ddir.GetPath();
364 }
365 #endif
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Function wxStringSplit splits aString to a string list separated at aSplitter.
Definition: common.cpp:137
int ProcessExecute(const wxString &aCommandLine, int aFlags, wxProcess *callback)
Function ProcessExecute runs a child process.
Definition: common.cpp:160
~LOCALE_IO()
Definition: common.cpp:82
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
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:182
wxConfigBase * GetNewConfig(const wxString &aProgName)
Function GetNewConfig.
Definition: common.cpp:205
time_t GetNewTimeStamp()
Definition: common.cpp:166
boost::interprocess::interprocess_mutex MUTEX
Establish KiCad MUTEX choices here in this file: typedef MUTEX and typedef MUTLOCK.
Definition: ki_mutex.h:42
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
This file contains miscellaneous commonly used macros and functions.
wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Function GetTextSize returns the size of aSingleLine of text when it is rendered in aWindow using wha...
Definition: common.cpp:93
static std::atomic< unsigned int > m_c_count
Definition: common.h:175
bool EnsureTextCtrlWidth(wxTextCtrl *aCtrl, const wxString *aString)
Function EnsureTextCtrlWidth sets the minimum pixel width on a text control in order to make a text s...
Definition: common.cpp:108
const wxString ExpandEnvVarSubstitutions(const wxString &aString)
Function ExpandEnvVarSubstitutions replaces any environment variable references with their values...
Definition: common.cpp:254
Base window classes and related definitions.
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Helper function EnsureFileDirectoryExists make aTargetFullFileName absolute and creates the path of t...
Definition: common.cpp:267
LOCALE_IO()
Definition: common.cpp:70
wxString GetKicadConfigPath()
Function GetKicadConfigPath.
Definition: common.cpp:217
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
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
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.
Basic classes for most KiCad items.
EDA_UNITS_T
Definition: common.h:143
COLOR4D g_GhostColor
Draw color for moving objects.
Definition: common.cpp:57
std::string m_user_locale
Definition: common.h:179
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39