KiCad PCB EDA Suite
Loading...
Searching...
No Matches
search_stack.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 CERN
5 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <search_stack.h>
22#include <string_utils.h>
23#include <trace_helpers.h>
24#include <wx/tokenzr.h>
25#include <wx/log.h>
26
27
28#if defined(_WIN32)
29 #define PATH_SEPS wxT( ";\r\n" )
30#else
31 #define PATH_SEPS wxT( ":;\r\n" ) // unix == linux | mac
32#endif
33
34
35int SEARCH_STACK::Split( wxArrayString* aResult, const wxString& aPathString )
36{
37 wxStringTokenizer tokenizer( aPathString, PATH_SEPS, wxTOKEN_STRTOK );
38
39 while( tokenizer.HasMoreTokens() )
40 {
41 wxString path = tokenizer.GetNextToken();
42
43 aResult->Add( path );
44 }
45
46 return aResult->GetCount();
47}
48
49
50// Convert aRelativePath to an absolute path based on aBaseDir
51static wxString base_dir( const wxString& aRelativePath, const wxString& aBaseDir )
52{
53 wxFileName fn = aRelativePath;
54
55 if( !fn.IsAbsolute() && !!aBaseDir )
56 {
57 wxASSERT_MSG( wxFileName( aBaseDir ).IsAbsolute(),
58 wxT( "Must pass absolute path in aBaseDir" ) );
59 fn.MakeRelativeTo( aBaseDir );
60 }
61
62 return fn.GetFullPath();
63}
64
65
67 const wxString& aFullFilename, const wxString& aBaseDir )
68{
69 wxFileName fn = aFullFilename;
70 wxString filename = aFullFilename;
71
72 unsigned pathlen = fn.GetPath().Len(); // path len, used to find the better (shortest)
73 // subpath within defaults paths
74
75 for( unsigned kk = 0; kk < GetCount(); kk++ )
76 {
77 fn = aFullFilename;
78
79 // Search for the shortest subpath within 'this':
80 if( fn.MakeRelativeTo( base_dir( (*this)[kk], aBaseDir ) ) )
81 {
82 if( fn.GetPathWithSep().StartsWith( wxT("..") ) ) // Path outside KiCad libs paths
83 continue;
84
85 if( pathlen > fn.GetPath().Len() ) // A better (shortest) subpath is found
86 {
87 filename = fn.GetPathWithSep() + fn.GetFullName();
88 pathlen = fn.GetPath().Len();
89 }
90 }
91 }
92
93 return filename;
94}
95
96
97void SEARCH_STACK::RemovePaths( const wxString& aPaths )
98{
99 bool isCS = wxFileName::IsCaseSensitive();
100 wxArrayString paths;
101
102 Split( &paths, aPaths );
103
104 for( unsigned i=0; i<paths.GetCount(); ++i )
105 {
106 wxString path = paths[i];
107
108 if( Index( path, isCS ) != wxNOT_FOUND )
109 {
110 Remove( path );
111 }
112 }
113}
114
115
116void SEARCH_STACK::AddPaths( const wxString& aPaths, int aIndex )
117{
118 bool isCS = wxFileName::IsCaseSensitive();
119 wxArrayString paths;
120
121 Split( &paths, aPaths );
122
123 // appending all of them, on large or negative aIndex
124 if( unsigned( aIndex ) >= GetCount() )
125 {
126 for( unsigned i=0; i<paths.GetCount(); ++i )
127 {
128 wxString path = paths[i];
129
130 if( wxFileName::IsDirReadable( path )
131 && Index( path, isCS ) == wxNOT_FOUND )
132 {
133 Add( path );
134 }
135 }
136 }
137
138 // inserting all of them:
139 else
140 {
141 for( unsigned i=0; i<paths.GetCount(); ++i )
142 {
143 wxString path = paths[i];
144
145 if( wxFileName::IsDirReadable( path )
146 && Index( path, isCS ) == wxNOT_FOUND )
147 {
148 Insert( path, aIndex );
149 aIndex++;
150 }
151 }
152 }
153}
154
155
156#if 1 // this function is too convoluted for words.
157
158const wxString SEARCH_STACK::LastVisitedPath( const wxString& aSubPathToSearch )
159{
160 wxString path;
161
162 // Initialize default path to the main default lib path
163 // this is the second path in list (the first is the project path).
164 unsigned pcount = GetCount();
165
166 if( pcount )
167 {
168 unsigned ipath = 0;
169
170 if( (*this)[0] == wxGetCwd() )
171 ipath = 1;
172
173 // First choice of path:
174 if( ipath < pcount )
175 path = (*this)[ipath];
176
177 // Search a sub path matching this SEARCH_PATH
178 if( !IsEmpty() )
179 {
180 for( ; ipath < pcount; ipath++ )
181 {
182 if( (*this)[ipath].Contains( aSubPathToSearch ) )
183 {
184 path = (*this)[ipath];
185 break;
186 }
187 }
188 }
189 }
190
191 if( path.IsEmpty() )
192 path = wxGetCwd();
193
194 return path;
195}
196#endif
197
198
199#if defined( DEBUG )
200void SEARCH_STACK::Show( const wxString& aPrefix ) const
201{
202 wxLogTrace( tracePathsAndFiles, "%s SEARCH_STACK:", aPrefix );
203
204 for( unsigned i = 0; i < GetCount(); ++i )
205 {
206 wxLogTrace( tracePathsAndFiles, " [%2u]:%s", i, TO_UTF8( ( *this )[i] ) );
207 }
208}
209#endif
const wxString LastVisitedPath(const wxString &aSubPathToSearch=wxEmptyString)
A quirky function inherited from old code that seems to serve particular needs in the UI.
static int Split(wxArrayString *aResult, const wxString &aPathString)
Separate aPathString into individual paths.
void AddPaths(const wxString &aPaths, int aIndex=-1)
Insert or append path(s).
void RemovePaths(const wxString &aPaths)
Remove the given path(s) from the library path list.
wxString FilenameWithRelativePathInSearchList(const wxString &aFullFilename, const wxString &aBaseDir)
Return the shortest possible path which can be use later to find a full path from this SEARCH_STACK.
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
#define PATH_SEPS
static wxString base_dir(const wxString &aRelativePath, const wxString &aBaseDir)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::string path
wxLogTrace helper definitions.