]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/filename.cpp
tried to fix layout of label-less static box sizers
[wxWidgets.git] / src / common / filename.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/filename.cpp
3// Purpose: wxFileName - encapsulates a file path
4// Author: Robert Roebling, Vadim Zeitlin
5// Modified by:
6// Created: 28.12.2000
7// RCS-ID: $Id$
8// Copyright: (c) 2000 Robert Roebling
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "filename.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34#endif
35
36#include "wx/filename.h"
37#include "wx/tokenzr.h"
38#include "wx/config.h" // for wxExpandEnvVars
39#include "wx/utils.h"
40
41// ============================================================================
42// implementation
43// ============================================================================
44
45// ----------------------------------------------------------------------------
46// wxFileName construction
47// ----------------------------------------------------------------------------
48
49void wxFileName::Assign( const wxFileName &filepath )
50{
51 m_ext = filepath.GetExt();
52 m_name = filepath.GetName();
53 m_dirs = filepath.GetDirs();
54}
55
56void wxFileName::Assign( const wxString& path,
57 const wxString& name,
58 const wxString& ext,
59 wxPathFormat format )
60{
61 wxStringTokenizer tn(path, GetPathSeparators(format),
62 wxTOKEN_RET_EMPTY_ALL);
63 bool first = TRUE;
64 m_dirs.Clear();
65 while ( tn.HasMoreTokens() )
66 {
67 wxString token = tn.GetNextToken();
68
69 // If the path starts with a slash, we need the first
70 // dir entry to be an empty for later reassembly.
71 if (first || !token.IsEmpty())
72 m_dirs.Add( token );
73
74 first = FALSE;
75 }
76
77 m_ext = ext;
78 m_name = name;
79}
80
81void wxFileName::Assign(const wxString& fullpath,
82 wxPathFormat format)
83{
84 wxString path, name, ext;
85 SplitPath(fullpath, &path, &name, &ext, format);
86
87 Assign(path, name, ext, format);
88}
89
90void wxFileName::Assign(const wxString& path,
91 const wxString& fullname,
92 wxPathFormat format)
93{
94 wxString name, ext;
95 SplitPath(fullname, NULL /* no path */, &name, &ext, format);
96
97 Assign(path, name, ext, format);
98}
99
100void wxFileName::Clear()
101{
102 m_dirs.Clear();
103 m_name =
104 m_ext = wxEmptyString;
105}
106
107/* static */
108wxFileName wxFileName::FileName(const wxString& file)
109{
110 return wxFileName(file);
111}
112
113/* static */
114wxFileName wxFileName::DirName(const wxString& dir)
115{
116 wxFileName fn;
117 fn.AssignDir(dir);
118 return fn;
119}
120
121// ----------------------------------------------------------------------------
122// existence tests
123// ----------------------------------------------------------------------------
124
125bool wxFileName::FileExists()
126{
127 return wxFileName::FileExists( GetFullPath() );
128}
129
130bool wxFileName::FileExists( const wxString &file )
131{
132 return ::wxFileExists( file );
133}
134
135bool wxFileName::DirExists()
136{
137 return wxFileName::DirExists( GetFullPath() );
138}
139
140bool wxFileName::DirExists( const wxString &dir )
141{
142 return ::wxDirExists( dir );
143}
144
145// ----------------------------------------------------------------------------
146// CWD and HOME stuff
147// ----------------------------------------------------------------------------
148
149void wxFileName::AssignCwd()
150{
151 AssignDir(wxFileName::GetCwd());
152}
153
154/* static */
155wxString wxFileName::GetCwd()
156{
157 return ::wxGetCwd();
158}
159
160bool wxFileName::SetCwd()
161{
162 return wxFileName::SetCwd( GetFullPath() );
163}
164
165bool wxFileName::SetCwd( const wxString &cwd )
166{
167 return ::wxSetWorkingDirectory( cwd );
168}
169
170void wxFileName::AssignHomeDir()
171{
172 AssignDir(wxFileName::GetHomeDir());
173}
174
175wxString wxFileName::GetHomeDir()
176{
177 return ::wxGetHomeDir();
178}
179
180void wxFileName::AssignTempFileName( const wxString &prefix )
181{
182 wxString fullname;
183 if ( wxGetTempFileName(prefix, fullname) )
184 {
185 Assign(fullname);
186 }
187 else // error
188 {
189 Clear();
190 }
191}
192
193// ----------------------------------------------------------------------------
194// directory operations
195// ----------------------------------------------------------------------------
196
197bool wxFileName::Mkdir( int perm )
198{
199 return wxFileName::Mkdir( GetFullPath(), perm );
200}
201
202bool wxFileName::Mkdir( const wxString &dir, int perm )
203{
204 return ::wxMkdir( dir, perm );
205}
206
207bool wxFileName::Rmdir()
208{
209 return wxFileName::Rmdir( GetFullPath() );
210}
211
212bool wxFileName::Rmdir( const wxString &dir )
213{
214 return ::wxRmdir( dir );
215}
216
217// ----------------------------------------------------------------------------
218// path normalization
219// ----------------------------------------------------------------------------
220
221bool wxFileName::Normalize(wxPathNormalize flags,
222 const wxString& cwd,
223 wxPathFormat format)
224{
225 // the existing path components
226 wxArrayString dirs = GetDirs();
227
228 // the path to prepend in front to make the path absolute
229 wxFileName curDir;
230
231 format = GetFormat(format);
232
233 // make the path absolute
234 if ( (flags & wxPATH_NORM_ABSOLUTE) && !IsAbsolute() )
235 {
236 if ( cwd.empty() )
237 curDir.AssignCwd();
238 else
239 curDir.AssignDir(cwd);
240 }
241
242 // handle ~ stuff under Unix only
243 if ( (format == wxPATH_UNIX) && (flags & wxPATH_NORM_TILDE) )
244 {
245 if ( !dirs.IsEmpty() )
246 {
247 wxString dir = dirs[0u];
248 if ( !dir.empty() && dir[0u] == _T('~') )
249 {
250 curDir.AssignDir(wxGetUserHome(dir.c_str() + 1));
251
252 dirs.RemoveAt(0u);
253 }
254 }
255 }
256
257 if ( curDir.IsOk() )
258 {
259 wxArrayString dirsNew = curDir.GetDirs();
260 size_t count = dirs.GetCount();
261 for ( size_t n = 0; n < count; n++ )
262 {
263 dirsNew.Add(dirs[n]);
264 }
265
266 dirs = dirsNew;
267 }
268
269 // now deal with ".", ".." and the rest
270 m_dirs.Empty();
271 size_t count = dirs.GetCount();
272 for ( size_t n = 0; n < count; n++ )
273 {
274 wxString dir = dirs[n];
275
276 if ( flags && wxPATH_NORM_DOTS )
277 {
278 if ( dir == wxT(".") )
279 {
280 // just ignore
281 continue;
282 }
283
284 if ( dir == wxT("..") )
285 {
286 if ( m_dirs.IsEmpty() )
287 {
288 wxLogError(_("The path '%s' contains too many \"..\"!"),
289 GetFullPath().c_str());
290 return FALSE;
291 }
292
293 m_dirs.Remove(m_dirs.GetCount() - 1);
294 continue;
295 }
296 }
297
298 if ( flags & wxPATH_NORM_ENV_VARS )
299 {
300 dir = wxExpandEnvVars(dir);
301 }
302
303 if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) )
304 {
305 dir.MakeLower();
306 }
307
308 m_dirs.Add(dir);
309 }
310
311 if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) )
312 {
313 // VZ: expand env vars here too?
314
315 m_name.MakeLower();
316 m_ext.MakeLower();
317 }
318
319 return TRUE;
320}
321
322// ----------------------------------------------------------------------------
323// filename kind tests
324// ----------------------------------------------------------------------------
325
326bool wxFileName::SameAs( const wxFileName &filepath, wxPathFormat format)
327{
328 wxFileName fn1 = *this,
329 fn2 = filepath;
330
331 // get cwd only once - small time saving
332 wxString cwd = wxGetCwd();
333 fn1.Normalize(wxPATH_NORM_ALL, cwd, format);
334 fn2.Normalize(wxPATH_NORM_ALL, cwd, format);
335
336 if ( fn1.GetFullPath() == fn2.GetFullPath() )
337 return TRUE;
338
339 // TODO: compare inodes for Unix, this works even when filenames are
340 // different but files are the same (symlinks) (VZ)
341
342 return FALSE;
343}
344
345/* static */
346bool wxFileName::IsCaseSensitive( wxPathFormat format )
347{
348 // only DOS filenames are case-sensitive
349 return GetFormat(format) != wxPATH_DOS;
350}
351
352bool wxFileName::IsRelative( wxPathFormat format )
353{
354 return !IsAbsolute(format);
355}
356
357bool wxFileName::IsAbsolute( wxPathFormat format )
358{
359 wxChar ch = m_dirs.IsEmpty() ? _T('\0') : m_dirs[0u][0u];
360
361 // the path is absolute if it starts with a path separator or, only for
362 // Unix filenames, with "~" or "~user"
363 return IsPathSeparator(ch, format) ||
364 (GetFormat(format) == wxPATH_UNIX && ch == _T('~') );
365}
366
367/* static */
368wxString wxFileName::GetPathSeparators(wxPathFormat format)
369{
370 wxString seps;
371 switch ( GetFormat(format) )
372 {
373 case wxPATH_DOS:
374 // accept both as native APIs do
375 seps << wxFILE_SEP_PATH_UNIX << wxFILE_SEP_PATH_DOS;
376 break;
377
378 default:
379 wxFAIL_MSG( _T("unknown wxPATH_XXX style") );
380 // fall through
381
382 case wxPATH_UNIX:
383 seps = wxFILE_SEP_PATH_UNIX;
384 break;
385
386 case wxPATH_MAC:
387 seps = wxFILE_SEP_PATH_MAC;
388 break;
389 }
390
391 return seps;
392}
393
394/* static */
395bool wxFileName::IsPathSeparator(wxChar ch, wxPathFormat format)
396{
397 return GetPathSeparators(format).Find(ch) != wxNOT_FOUND;
398}
399
400bool wxFileName::IsWild( wxPathFormat format )
401{
402 // FIXME: this is probably false for Mac and this is surely wrong for most
403 // of Unix shells (think about "[...]")
404 return m_name.find_first_of(_T("*?")) != wxString::npos;
405}
406
407// ----------------------------------------------------------------------------
408// path components manipulation
409// ----------------------------------------------------------------------------
410
411void wxFileName::AppendDir( const wxString &dir )
412{
413 m_dirs.Add( dir );
414}
415
416void wxFileName::PrependDir( const wxString &dir )
417{
418 m_dirs.Insert( dir, 0 );
419}
420
421void wxFileName::InsertDir( int before, const wxString &dir )
422{
423 m_dirs.Insert( dir, before );
424}
425
426void wxFileName::RemoveDir( int pos )
427{
428 m_dirs.Remove( (size_t)pos );
429}
430
431// ----------------------------------------------------------------------------
432// accessors
433// ----------------------------------------------------------------------------
434
435void wxFileName::SetFullName(const wxString& fullname)
436{
437 SplitPath(fullname, NULL /* no path */, &m_name, &m_ext);
438}
439
440wxString wxFileName::GetFullName() const
441{
442 wxString fullname = m_name;
443 if ( !m_ext.empty() )
444 {
445 fullname << wxFILE_SEP_EXT << m_ext;
446 }
447
448 return fullname;
449}
450
451wxString wxFileName::GetPath( bool add_separator, wxPathFormat format ) const
452{
453 format = GetFormat( format );
454
455 wxString ret;
456 size_t count = m_dirs.GetCount();
457 for ( size_t i = 0; i < count; i++ )
458 {
459 ret += m_dirs[i];
460 if ( add_separator || (i < count) )
461 ret += wxFILE_SEP_PATH;
462 }
463
464 return ret;
465}
466
467wxString wxFileName::GetFullPath( wxPathFormat format ) const
468{
469 return GetPathWithSep() + GetFullName();
470}
471
472wxPathFormat wxFileName::GetFormat( wxPathFormat format )
473{
474 if (format == wxPATH_NATIVE)
475 {
476#if defined(__WXMSW__) || defined(__WXPM__)
477 format = wxPATH_DOS;
478#elif defined(__WXMAC__)
479 format = wxPATH_MAC;
480#else
481 format = wxPATH_UNIX;
482#endif
483 }
484 return format;
485}
486
487// ----------------------------------------------------------------------------
488// path splitting function
489// ----------------------------------------------------------------------------
490
491void wxFileName::SplitPath(const wxString& fullpath,
492 wxString *pstrPath,
493 wxString *pstrName,
494 wxString *pstrExt,
495 wxPathFormat format)
496{
497 format = GetFormat(format);
498
499 // find the positions of the last dot and last path separator in the path
500 size_t posLastDot = fullpath.find_last_of(wxFILE_SEP_EXT);
501 size_t posLastSlash = fullpath.find_last_of(GetPathSeparators(format));
502
503 if ( (posLastDot != wxString::npos) && (format == wxPATH_UNIX) )
504 {
505 if ( (posLastDot == 0) ||
506 (fullpath[posLastDot - 1] == wxFILE_SEP_PATH_UNIX) )
507 {
508 // under Unix, dot may be (and commonly is) the first character of
509 // the filename, don't treat the entire filename as extension in
510 // this case
511 posLastDot = wxString::npos;
512 }
513 }
514
515 if ( (posLastDot != wxString::npos) && (posLastDot < posLastSlash) )
516 {
517 // the dot is part of the path, not the start of the extension
518 posLastDot = wxString::npos;
519 }
520
521 // now fill in the variables provided by user
522 if ( pstrPath )
523 {
524 if ( posLastSlash == wxString::npos )
525 {
526 // no path at all
527 pstrPath->Empty();
528 }
529 else
530 {
531 // take all until the separator
532 *pstrPath = fullpath.Left(posLastSlash);
533 }
534 }
535
536 if ( pstrName )
537 {
538 // take all characters starting from the one after the last slash and
539 // up to, but excluding, the last dot
540 size_t nStart = posLastSlash == wxString::npos ? 0 : posLastSlash + 1;
541 size_t count = posLastDot == wxString::npos
542 ? wxString::npos
543 : posLastDot - posLastSlash - 1;
544
545 *pstrName = fullpath.Mid(nStart, count);
546 }
547
548 if ( pstrExt )
549 {
550 if ( posLastDot == wxString::npos )
551 {
552 // no extension
553 pstrExt->Empty();
554 }
555 else
556 {
557 // take everything after the dot
558 *pstrExt = fullpath.Mid(posLastDot + 1);
559 }
560 }
561}