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