]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/filename.cpp
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / filename.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 // Copyright (C) 2003 John Dallaway
6 //
7 // This program is part of the eCos host tools.
8 //
9 // This program is free software; you can redistribute it and/or modify it 
10 // under the terms of the GNU General Public License as published by the Free 
11 // Software Foundation; either version 2 of the License, or (at your option) 
12 // any later version.
13 // 
14 // This program is distributed in the hope that it will be useful, but WITHOUT 
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
16 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
17 // more details.
18 // 
19 // You should have received a copy of the GNU General Public License along with
20 // this program; if not, write to the Free Software Foundation, Inc., 
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 //
23 // ----------------------------------------------------------------------------
24 //                                                                          
25 //####COPYRIGHTEND####
26
27 #ifdef __GNUG__
28 #pragma implementation "filename.h"
29 #endif
30
31 // Includes other headers for precompiled compilation
32 #include "ecpch.h"
33
34 #ifdef __BORLANDC__
35 #pragma hdrstop
36 #endif
37
38 #include "wx/filefn.h"
39 #include "wx/confbase.h" // For wxExpandEnvVars
40
41 #include "filename.h"
42
43 #ifdef __WXMSW__
44 //#include <direct.h>
45 //#include <dos.h>
46
47 #include <windows.h>
48 #include <shlwapi.h>
49
50 #include "wx/msw/winundef.h"
51 #ifndef __CYGWIN__
52 #ifdef CreateDirectory
53 #undef CreateDirectory
54 #endif
55 #ifdef ExpandEnvironmentStrings
56 #undef ExpandEnvironmentStrings
57 #endif
58 #ifdef GetCurrentDirectory
59 #undef GetCurrentDirectory
60 #endif
61 #ifdef SetCurrentDirectory
62 #undef SetCurrentDirectory
63 #endif
64 #ifdef GetTempPath
65 #undef GetTempPath
66 #endif
67 #endif
68
69 #else
70
71 // #include <dir.h>
72 #endif
73
74 #include <sys/stat.h>
75
76 #define wxTChar wxT
77
78 const wxChar ecFileName::cSep=wxFILE_SEP_PATH;
79
80 ecFileName::ecFileName(const wxChar* psz1,const wxChar* psz2):
81 wxString(psz1)
82 {
83     Normalize();
84     operator+=(psz2);
85 }
86
87 ecFileName::ecFileName(const wxChar* psz1,const wxChar* psz2,const wxChar* psz3):
88 wxString(psz1)
89 {
90     Normalize();
91     operator+=(psz2);
92     operator+=(psz3);
93 }
94
95 ecFileName::ecFileName(const wxChar* psz1,const wxChar* psz2,const wxChar* psz3,const wxChar* psz4):
96 wxString(psz1)
97 {
98     Normalize();
99     operator+=(psz2);
100     operator+=(psz3);
101     operator+=(psz4);
102 }
103
104 ecFileName::ecFileName(const wxChar* psz1,const wxChar* psz2,const wxChar* psz3,const wxChar* psz4,const wxChar* psz5):
105 wxString(psz1)
106 {
107     operator+=(psz2);
108     operator+=(psz3);
109     operator+=(psz4);
110     operator+=(psz5);
111 }
112
113 /*
114 ecFileName::~ecFileName()
115 {
116     // Unfortunately we can't do this since GetStringData is private in wxString.
117     // So for now, we may memory leaks since ~wxString is not virtual.
118     //GetStringData()->Unlock();
119 }
120 */
121
122 ecFileName operator+(const ecFileName& string1, const ecFileName& string2)
123 {
124     ecFileName s;
125     s.ConcatCopy(string1, string2);
126     return s;
127 }
128
129 ecFileName operator+(const ecFileName& string, const wxChar* lpsz)
130 {
131     if (lpsz == NULL)
132         return string;
133
134     ecFileName s;
135     s.ConcatCopy(string, wxString(lpsz));
136     return s;
137 }
138
139 ecFileName operator+(const wxChar* lpsz, const ecFileName& string)
140 {
141     if (lpsz == NULL)
142         return string;
143
144     ecFileName s;
145     s.ConcatCopy(wxString(lpsz), string);
146     return s;
147 }
148
149 ecFileName operator+(const ecFileName& string1, wxChar ch)
150 {
151     ecFileName s;
152     s.ConcatCopy(string1, wxString(ch));
153     return s;
154 }
155
156 ecFileName operator+(wxChar ch, const ecFileName& string)
157 {
158     ecFileName s;
159     s.ConcatCopy(wxString(ch), string);
160     return s;
161 }
162
163 const ecFileName& ecFileName::operator+=(const wxChar* lpsz)
164 {
165     if (lpsz == NULL)
166         return *this;
167
168     ConcatInPlace(wxString(lpsz));
169     return *this;
170 }
171
172 const ecFileName& ecFileName::operator+=(wxChar ch)
173 {
174     ConcatInPlace(wxString(ch));
175     return *this;
176 }
177
178 const ecFileName& ecFileName::operator+=(const ecFileName& string)
179 {
180     ConcatInPlace(string);
181     return *this;
182 }
183
184 void ecFileName::ConcatInPlace(const wxString& src)
185 {
186     ConcatCopy(* this, src);
187 }
188
189 void ecFileName::ConcatCopy(const wxString& src1,
190                             const wxString& src2)
191 {
192     int nSrc1Len = src1.Len();
193     int nSrc2Len = src2.Len();
194     int n=1;
195     int nNewLen = nSrc1Len + nSrc2Len;
196     if(nSrc1Len>0)
197     {
198         if(1==nSrc2Len && cSep==src2[0])
199         {
200             // Appending a single separator to a non-null string is a no-op
201             return;
202         } else {
203             // Count the intervening separators
204             n=(cSep==src1[nSrc1Len-1])+(cSep==src2[0]);
205             
206             switch(n){
207             case 0:
208                 (*this) = src1 + wxString(cSep) + src2;
209                 break;
210             case 1:
211                 (*this) = src1 + src2;
212                 break;
213             case 2:
214                 (*this) = src1 + src2.Mid(1);
215                 break;
216             }
217             return;
218         }
219     }
220 }
221
222 void ecFileName::Normalize()
223 {
224     // Remove any trailing seperator
225     int len = Len();
226     if (len > 0 && (*this)[(size_t)(len - 1)] == cSep)
227         (*this) = Mid(0, len - 1);
228 }
229
230
231 const ecFileName ecFileName::FullName() const
232 {
233 #ifdef __WXMSW__
234     TCHAR* pFile;
235     long dwSize=::GetFullPathName (*this, 0, NULL, &pFile);
236     if(dwSize>0){
237         wxString strCopy;
238         ::GetFullPathName (*this, 1+dwSize, strCopy.GetWriteBuf(1+dwSize), &pFile);
239         strCopy.UngetWriteBuf();
240         return strCopy;
241     } else {
242         return *this;
243     }
244 #else
245     return wxGetCwd() + wxString(cSep) + wxString(*this);
246 #endif
247 }
248
249 const ecFileName ecFileName::ShortName() const
250 {
251 #ifdef __WXMSW__
252     long dwSize=::GetShortPathName (*this, NULL, 0);
253     if(dwSize>0){
254         wxString strCopy;
255         ::GetShortPathName (*this, strCopy.GetWriteBuf(1+dwSize), 1+dwSize);
256         strCopy.UngetWriteBuf();
257         return strCopy;
258     } else {
259         return *this;
260     }
261 #else
262     return *this;
263 #endif
264 }
265
266 const ecFileName ecFileName::NoSpaceName() const// sans spaces
267 {
268 #ifndef __WXMSW__
269     return *this;
270 #else
271     // Only replace components with spaces with FAT names.
272     wxArrayString ar1,ar2;
273     const wxString str2(ShortName());
274     
275     size_t i,pcStart;
276     
277     unsigned int len = Len();
278     pcStart = 0;
279     for (i = 0; i < len; i++)
280     {
281         if(wxTChar('\\')==(*this)[i])
282         {
283             ar1.Add(this->Mid(pcStart, i - pcStart + 1));
284             pcStart = i + 1;
285         }
286     }
287     ar1.Add(this->Mid(pcStart, i - pcStart + 1));
288
289     len = str2.Len();
290     pcStart = 0;
291     for (i = 0; i < len; i++)
292     {
293         if(wxTChar('\\')==str2[i])
294         {
295             ar2.Add(str2.Mid(pcStart, i - pcStart + 1));
296             pcStart = i + 1;
297         }
298     }
299     ar2.Add(str2.Mid(pcStart, i - pcStart + 1));    
300     
301     wxASSERT(ar1.Count()==ar2.Count());
302     
303     wxString rc;
304     for(i=0;i<ar1.Count();i++){
305         rc+=(-1==ar1[i].Find(wxTChar(' ')))?ar1[i]:ar2[i];
306     }
307     return rc;
308 #endif
309 }
310
311 //
312 const ecFileName ecFileName::Tail() const
313 {
314     return AfterLast(cSep);
315 }
316
317 const ecFileName ecFileName::Head() const
318 {
319     return BeforeLast(cSep);
320 }
321
322 time_t ecFileName::LastModificationTime() const
323 {
324     return wxFileModificationTime(* this);
325     
326 #if 0
327     // GetFileAttributes is not available in Win95 so we test the water first
328     static HINSTANCE hInst=LoadLibrary(_T("kernel32.dll"));
329     wxASSERT(hInst);
330     
331 #ifdef _UNICODE
332 #define GETFILEATTRIBUTESNAME "GetFileAttributesExW"
333 #else
334 #define GETFILEATTRIBUTESNAME "GetFileAttributesExA"
335 #endif // !UNICODE
336     
337     typedef BOOL (WINAPI *GetFileAttributesP)(const wxChar*,GET_FILEEX_INFO_LEVELS,LPVOID);
338     
339     static GetFileAttributesP p=(GetFileAttributesP)GetProcAddress(hInst,GETFILEATTRIBUTESNAME);
340     if(p){
341         WIN32_FILE_ATTRIBUTE_DATA data;
342         
343         if((*p)(*this, GetFileExInfoStandard, (LPVOID)&data)){
344             return data.ftLastWriteTime;
345         }
346     } else {
347         HANDLE h=CreateFile(*this,0,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
348         FILETIME ft;
349         if(INVALID_HANDLE_VALUE!=h){
350             BOOL b=::GetFileTime(h,NULL,NULL,&ft);
351             ::CloseHandle(h);
352             if(b){
353                 return ft;
354             }
355         }
356     }
357     static FILETIME ftNull={0,0};
358     return ftNull;
359 #endif
360 }
361
362 /* TODO
363 bool ecFileName::SetFileAttributes(long dwFileAttributes) const
364 {
365 return ::SetFileAttributes (*this, dwFileAttributes)!=0;
366 }
367 */
368
369 bool ecFileName::Exists     () const
370 {
371     return IsFile() || IsDir() ;
372 }
373
374 bool ecFileName::IsDir      () const
375 {
376     return wxPathExists(* this);
377 }
378
379 bool ecFileName::IsFile     () const
380 {
381 #if defined(__WXMAC__)
382     struct stat stbuf;
383     if (filename && stat (wxUnix2MacFilename(filename), &stbuf) == 0 )
384         return TRUE;
385     return FALSE ;
386 #else
387     wxStructStat st;
388     if ((*this) != wxT("") && wxStat (wxFNSTRINGCAST fn_str(), &st) == 0 && (st.st_mode & S_IFREG))
389         return TRUE;
390
391     return FALSE;
392 #endif
393 }
394
395 bool ecFileName::IsReadOnly () const
396 {
397 #ifdef __WXMSW__
398     long a=GetFileAttributes(* this); return 0xFFFFFFFF!=a && (0!=(a&FILE_ATTRIBUTE_READONLY ));
399 #else
400     wxFAIL_MSG("ecFileName::IsReadOnly not supported on this platform.");
401     return FALSE;
402 #endif
403 }
404
405 bool ecFileName::SameFile(const ecFileName &o) const
406 {
407 #ifdef __WXMSW__
408     return 0==ShortName().CmpNoCase(o.ShortName());
409 #else
410     // On most other platforms, case is important.
411     return o == (*this);
412 #endif
413 }
414
415 ecFileName ecFileName::ExpandEnvironmentStrings(const wxChar* psz)
416 {
417     // wxExpandEnvVars is from confbase.h
418
419     ecFileName f = wxExpandEnvVars(psz);
420     return f;
421 }
422
423 const ecFileName& ecFileName::ExpandEnvironmentStrings()
424 {
425     *this=ecFileName::ExpandEnvironmentStrings(*this);
426     return *this;
427 }
428
429 #if 0
430 // Helper for Relative()  psz is in full format.
431 ecFileName ecFileName::Drive(const wxChar* psz)
432 {
433     if(wxIsalpha(psz[0])){
434         return psz[0];
435     } else if(cSep==psz[0]&&cSep==psz[1]){
436         wxChar *c=_tcschr(psz+2,cSep);
437         if(c){
438             c=_tcschr(c+1,cSep);
439             if(c){
440                 return wxString(psz,c-psz);
441             }
442         }
443     }
444     return _T("");
445 }
446 #endif
447
448 ecFileName ecFileName::Relative(const wxChar* compare,const wxChar* current)
449 {
450 #ifdef __WXMSW__
451     wxString rc;
452     bool b=(TRUE==PathRelativePathTo(rc.GetWriteBuf(1+MAX_PATH),current,FILE_ATTRIBUTE_DIRECTORY,compare,0));
453     rc.UngetWriteBuf();
454     return b?(ecFileName)rc:(ecFileName)compare;
455 #else
456     wxFAIL_MSG("ecFileName::Relative not implemented on this platform.");
457     return ecFileName();
458 #endif
459
460
461 const ecFileName& ecFileName::MakeRelative(const wxChar* pszRelativeTo)
462 {
463     *this=ecFileName::Relative(*this,pszRelativeTo);
464     return *this;
465 }
466
467
468 ecFileName ecFileName::GetCurrentDirectory()
469 {
470     ecFileName f;
471     f = wxGetCwd();
472     f.Normalize();
473
474     return f;
475 }
476
477
478 const ecFileName& ecFileName::Append(const wxChar* lpsz)
479 {
480     if (lpsz)
481         return *this;
482
483     //wxString::ConcatInPlace(lpsz);
484     wxString::Append(lpsz);
485     return *this;
486     
487 }
488
489 const ecFileName& ecFileName::Append(wxChar ch)
490 {
491     ConcatInPlace(wxString(ch));
492     return *this;
493 }
494
495 bool ecFileName::IsAbsolute() const
496 {
497     int nLength=Len();
498     const wxString& psz=*this;
499     return 
500         (nLength>0 && (cSep==psz[0]))|| // starts with '\'
501         (nLength>1 && (
502         (wxIsalpha(psz[0]) && wxTChar(':')==psz[1]) ||  // starts with [e.g.] "c:\"
503         (cSep==psz[0] && cSep==psz[1])));              // UNC
504 }
505
506 // TODO (?)
507 #if 0
508 // Return an array of filename pieces.  Plugs '\0's into 'this', which
509 // is therefore subsequently only usable as referenced by the returned array.
510 const wxChar* *ecFileName::Chop()
511 {
512     wxChar *c;
513     // Count the separators
514     int nSeps=0;
515     for(c=_tcschr(m_pchData,cSep);c;c=_tcschr(c+1,cSep)){
516         nSeps++;
517     }
518     const wxChar* *ar=new const wxChar*[2+nSeps]; // +1 for first, +1 for terminating 0
519     ar[0]=m_pchData;
520     int i=1;
521     for(c=_tcschr(m_pchData,cSep);c;c=_tcschr(c+1,cSep)){
522         ar[i++]=c+1;
523         *c=wxTChar('\0');
524     }
525     ar[i]=0;
526     return ar;
527 }
528 #endif
529
530 ecFileName ecFileName::GetTempPath()
531 {
532     ecFileName f;
533 #ifdef __WXMSW__
534 #ifdef _UNICODE
535     ::GetTempPathW(1+MAX_PATH,f.GetWriteBuf(1+MAX_PATH));
536 #else
537     ::GetTempPathA(1+MAX_PATH,f.GetWriteBuf(1+MAX_PATH));
538 #endif
539   f.UngetWriteBuf();
540 #elif defined(__WXGTK__)
541 #else
542     wxFAIL("ecFileName::GetTempPath() not implemented on this platform.");
543 #endif
544     f.Normalize();
545     return f;    
546 }
547
548 const ecFileName ecFileName::CygPath () const 
549 {
550 #ifdef __WXMSW__
551     ecFileName rc = ShortName();
552     if(wxIsalpha(rc[(size_t)0]) && wxTChar(':')==rc[(size_t)1])
553     {
554         // Convert c:\ to /cygdrive/c/
555         wxString s = wxString(wxT("/cygdrive/")) + wxString(rc[(size_t)0]) + rc.Mid(2);
556         rc = s;
557     }
558     size_t i;
559     for (i = 0; i < rc.Len(); i++)
560     {
561         if (rc[i] == wxTChar('\\'))
562             rc[i] = wxTChar('/');
563     }
564 #else
565     const ecFileName& rc = * this;
566 #endif
567
568     return rc;
569 }
570
571 bool ecFileName::CreateDirectory(bool bParentsToo,bool bFailIfAlreadyExists) const
572 {
573     if(bParentsToo)
574     {
575         // Create intermediate directories
576
577         // 'rest' will progressively have its separators replaced by underscores in order
578         // to find the next separator
579         wxString rest = * this;
580         size_t lastPos = 0;
581         int len = rest.Len();
582
583 #ifdef __WXMSW__
584         // If the path is a network path, ignore the first part of the path
585         if (len > 2 && (rest.GetChar(0) == wxT('\\') || rest.GetChar(0) == wxT('/')) && (rest.GetChar(1) == wxT('\\') || rest.GetChar(1) == wxT('/')))
586         {
587             rest.SetChar(0,wxT('_')); rest.SetChar(1,wxT('_'));
588             lastPos = rest.Find(cSep);
589             if (lastPos != -1 && lastPos >= 0)
590                 rest.SetChar(lastPos,wxT('_'));
591         }
592 #endif
593         
594         while (lastPos != -1)
595         {
596             lastPos = rest.Find(cSep);
597             if (lastPos != -1 && lastPos >= 0)
598             {
599                 rest[lastPos] = wxT('_'); // So we find the NEXT separator
600
601                 // don't attempt to create "C: or /"
602                 if (lastPos > 0 && (*this)[lastPos-1] == wxT(':'))
603                     continue;
604                 else if (lastPos == 0)
605                     continue;
606             }
607
608             // Fail if any of the dirs exist already
609             wxString str(this->Mid(0, lastPos));
610             bool alreadyExists = wxDirExists(str);
611             if (alreadyExists && bFailIfAlreadyExists)
612                 return FALSE;
613             
614             if (!alreadyExists)
615                 if (!wxMkdir(str))
616                     return FALSE;
617         }
618     }
619
620
621     return IsDir()? (!bFailIfAlreadyExists) : (TRUE==wxMkdir(*this));
622 }
623
624
625 const wxString ecFileName::Extension() const
626 {
627     wxString path, name, ext;
628
629     wxSplitPath(*this, & path, & name, & ext);
630     return ext;
631 }
632
633 const wxString ecFileName::Root() const
634 {
635     return wxPathOnly(*this);
636 }
637
638 ecFileName ecFileName::SetCurrentDirectory(const wxChar* pszDir)
639 {
640     const ecFileName strPwd=wxGetCwd();
641     if (::wxSetWorkingDirectory(pszDir))
642         return strPwd;
643     else
644         return wxT("");
645 }
646
647 bool ecFileName::RecursivelyDelete()
648 {
649     wxArrayString ar;
650     int i;
651     for(i=FindFiles(*this,ar)-1;i>=0;--i){
652         wxRemoveFile(ar[i]);
653     }
654     for(i=FindFiles(*this,ar,wxT("*.*"),TRUE,0)-1;i>=0;--i){
655         wxRmdir(ar[i]);
656     }
657     return TRUE==wxRmdir(*this);
658 }
659
660 // TODO: take account of dwExclude
661 int ecFileName::FindFiles (const wxString& pszDir,wxArrayString &ar,const wxString& pszPattern/*=wxT("*.*")*/,bool bRecurse/*=TRUE*/,long dwExclude/*=wxDIR_DIRS|wxDIR_HIDDEN*/)
662 {
663     ar.Clear();
664
665     // Scoping for wxDir
666     {
667         wxDir dir(pszDir);
668         
669         wxString fileName;
670         bool bMore = dir.GetFirst(& fileName, pszPattern, wxDIR_FILES);
671         while (bMore)
672         {
673             if (fileName != wxT(".") && fileName != wxT(".."))
674             {
675                 // Add full path
676                 ecFileName path(pszDir);
677                 path += (const wxChar*) fileName;
678                 ar.Add(path);
679             }
680             bMore = dir.GetNext(& fileName);
681         }
682     }
683
684     if (bRecurse)
685     {
686         // Since wxDir isn't rentrant, we need to gather all the directories
687         // first
688         wxArrayString ar2;
689
690         // Scoping
691         {
692             wxDir dir(pszDir);
693             
694             wxString fileName;
695             
696             bool bMore = dir.GetFirst(& fileName, wxT("*"), wxDIR_DIRS);
697             while (bMore)
698             {
699                 if (fileName != wxT(".") && fileName != wxT(".."))
700                 {
701                     // Add full path
702                     ecFileName path(pszDir);
703                     path += (const wxChar*) fileName;
704                     ar2.Add(path);
705                 }
706                 bMore = dir.GetNext(& fileName);
707             }
708         }
709
710         unsigned int i;
711         for (i = 0; i < ar2.Count(); i++)
712         {
713             wxString f(ar2[i]);
714             FindFiles(f, ar, pszPattern, bRecurse, dwExclude);
715         }
716     }
717
718     return ar.Count();
719 }
720
721 void ecFileName::ReplaceExtension(const wxString& newExt)
722 {
723     wxString ext = newExt;
724     if (ext[(unsigned) 0] == wxT('.'))
725         ext = ext.Mid(1);
726
727     wxStripExtension(* this);
728     this->wxString::Append(wxT("."));
729     this->wxString::Append(ext);
730 }