X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ba14d9861d043d53cc53ea70a2fab4146f7be9f3..a949e8fac2666418b2a6eb15e94959563cf8aad6:/src/common/filefn.cpp diff --git a/src/common/filefn.cpp b/src/common/filefn.cpp index 587a0582f5..4971630f26 100644 --- a/src/common/filefn.cpp +++ b/src/common/filefn.cpp @@ -68,13 +68,14 @@ #ifdef __UNIX__ #include #include + #include #endif #ifdef __WXPM__ #include #include "wx/os2/private.h" #endif -#if defined(__WINDOWS__) && !defined(__WXMICROWIN__) +#if defined(__WINDOWS__) && !defined(__WXMICROWIN__) && !defined(__WXWINE__) #if !defined( __GNUWIN32__ ) && !defined( __MWERKS__ ) && !defined(__SALFORDC__) #include #include @@ -104,7 +105,6 @@ #include #endif -#include "wx/setup.h" #include "wx/log.h" // No, Cygwin doesn't appear to have fnmatch.h after all. @@ -115,7 +115,7 @@ #ifdef __WINDOWS__ #include #include "wx/msw/mslu.h" - + // sys/cygwin.h is needed for cygwin_conv_to_full_win32_path() // // note that it must be included after @@ -123,7 +123,7 @@ #ifdef __CYGWIN__ #include #endif - #include + #ifndef __TWIN32__ #include #endif @@ -150,12 +150,11 @@ # include "FSpCompat.h" #endif -IMPLEMENT_DYNAMIC_CLASS(wxPathList, wxStringList) - // ---------------------------------------------------------------------------- // private globals // ---------------------------------------------------------------------------- +// MT-FIXME: get rid of this horror and all code using it static wxChar wxFileFunctionsBuffer[4*_MAXPATHLEN]; #if defined(__VISAGECPP__) && __IBMCPP__ >= 400 @@ -177,6 +176,32 @@ const off_t wxInvalidOffset = (off_t)-1; // implementation // ============================================================================ +#ifdef wxNEED_WX_UNISTD_H + +WXDLLEXPORT int wxStat( const wxChar *file_name, wxStructStat *buf ) +{ + return stat( wxConvFile.cWX2MB( file_name ), buf ); +} + +WXDLLEXPORT int wxAccess( const wxChar *pathname, int mode ) +{ + return access( wxConvFile.cWX2MB( pathname ), mode ); +} + +WXDLLEXPORT int wxOpen( const wxChar *pathname, int flags, mode_t mode ) +{ + return open( wxConvFile.cWX2MB( pathname ), flags, mode ); +} + +#endif + // wxNEED_WX_UNISTD_H + +// ---------------------------------------------------------------------------- +// wxPathList +// ---------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxPathList, wxStringList) + void wxPathList::Add (const wxString& path) { wxStringList::Add (WXSTRINGCAST path); @@ -257,7 +282,7 @@ wxString wxPathList::FindValidPath (const wxString& file) wxStrcpy(buf, wxFileFunctionsBuffer); wxChar *filename = (wxChar*) NULL; /* shut up buggy egcs warning */ - filename = IsAbsolutePath (buf) ? wxFileNameFromPath (buf) : (wxChar *)buf; + filename = wxIsAbsolutePath (buf) ? wxFileNameFromPath (buf) : (wxChar *)buf; for (wxNode * node = First (); node; node = node->Next ()) { @@ -268,7 +293,7 @@ wxString wxPathList::FindValidPath (const wxString& file) wxStrcat (wxFileFunctionsBuffer, wxT("/")); wxStrcat (wxFileFunctionsBuffer, filename); #ifdef __WINDOWS__ - Unix2DosFilename (wxFileFunctionsBuffer); + wxUnix2DosFilename (wxFileFunctionsBuffer); #endif if (wxFileExists (wxFileFunctionsBuffer)) { @@ -300,18 +325,16 @@ wxString wxPathList::FindAbsoluteValidPath (const wxString& file) bool wxFileExists (const wxString& filename) { + // we must use GetFileAttributes() instead of the ANSI C functions because + // it can cope with network (UNC) paths unlike them #if defined(__WIN32__) && !defined(__WXMICROWIN__) - // GetFileAttributes can copy with network paths unlike stat() DWORD ret = ::GetFileAttributes(filename); return (ret != (DWORD)-1) && !(ret & FILE_ATTRIBUTE_DIRECTORY); -#else - wxStructStat stbuf; - if ( !filename.empty() && wxStat (OS_FILENAME(filename), &stbuf) == 0 ) - return TRUE; - - return FALSE; -#endif +#else // !__WIN32__ + wxStructStat st; + return wxStat(filename, &st) == 0 && (st.st_mode & S_IFREG); +#endif // __WIN32__/!__WIN32__ } bool @@ -387,7 +410,7 @@ wxChar *wxRealPath (wxChar *path) { #ifdef __WXMSW__ static const wxChar SEP = wxT('\\'); - Unix2DosFilename(path); + wxUnix2DosFilename(path); #else static const wxChar SEP = wxT('/'); #endif @@ -405,7 +428,11 @@ wxChar *wxRealPath (wxChar *path) if (p[1] == wxT('.') && p[2] == wxT('.') && (p[3] == SEP || p[3] == wxT('\0'))) { wxChar *q; - for (q = p - 1; q >= path && *q != SEP; q--); + for (q = p - 1; q >= path && *q != SEP; q--) + { + // Empty + } + if (q[0] == SEP && (q[1] != wxT('.') || q[2] != wxT('.') || q[3] != SEP) && (q - 1 <= path || q[-1] != SEP)) { @@ -440,7 +467,7 @@ wxChar *wxCopyAbsolutePath(const wxString& filename) if (filename == wxT("")) return (wxChar *) NULL; - if (! IsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename))) { + if (! wxIsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename))) { wxChar buf[_MAXPATHLEN]; buf[0] = wxT('\0'); wxGetWorkingDirectory(buf, WXSIZEOF(buf)); @@ -569,7 +596,11 @@ wxChar *wxExpandPath(wxChar *buf, const wxChar *name) *--d = 0; value = wxGetenv(braces ? start + 1 : start); if (value) { - for ((d = start - 1); (*d++ = *value++) != 0;); + for ((d = start - 1); (*d++ = *value++) != 0;) + { + // Empty + } + d--; if (braces && *s) s++; @@ -593,7 +624,10 @@ wxChar *wxExpandPath(wxChar *buf, const wxChar *name) { /* ~user/filename */ register wxChar *nnm; register wxChar *home; - for (s = nm; *s && *s != SEP; s++); + for (s = nm; *s && *s != SEP; s++) + { + // Empty + } int was_sep; /* MATTHEW: Was there a separator, or NULL? */ was_sep = (*s == SEP); nnm = *s ? s + 1 : s; @@ -620,7 +654,10 @@ wxChar *wxExpandPath(wxChar *buf, const wxChar *name) *(d - 1) = SEP; } s = nm; - while ((*d++ = *s++) != 0); + while ((*d++ = *s++) != 0) + { + // Empty + } delete[] nm_tmp; // clean up alloc /* Now clean up the buffer */ return wxRealPath(buf); @@ -643,7 +680,7 @@ wxContractPath (const wxString& filename, const wxString& envname, const wxStrin wxStrcpy (dest, WXSTRINGCAST filename); #ifdef __WXMSW__ - Unix2DosFilename(dest); + wxUnix2DosFilename(dest); #endif // Handle environment @@ -669,11 +706,6 @@ wxContractPath (const wxString& filename, const wxString& envname, const wxStrin wxStrcpy(wxFileFunctionsBuffer, wxT("~")); if (user != wxT("")) wxStrcat(wxFileFunctionsBuffer, (const wxChar*) user); -#ifdef __WXMSW__ -// strcat(wxFileFunctionsBuffer, "\\"); -#else -// strcat(wxFileFunctionsBuffer, "/"); -#endif wxStrcat(wxFileFunctionsBuffer, dest + len); wxStrcpy (dest, wxFileFunctionsBuffer); } @@ -681,75 +713,27 @@ wxContractPath (const wxString& filename, const wxString& envname, const wxStrin return dest; } -// Return just the filename, not the path -// (basename) +// Return just the filename, not the path (basename) wxChar *wxFileNameFromPath (wxChar *path) { - if (path) - { - register wxChar *tcp; + wxString p = path; + wxString n = wxFileNameFromPath(p); - tcp = path + wxStrlen (path); - while (--tcp >= path) - { -#if defined(__WXMAC__) && !defined(__DARWIN__) - // Classic or Carbon CodeWarrior like - // Carbon with Apple DevTools is Unix like - if (*tcp == wxT(':')) - return tcp + 1; -#else - // Unix like or Windows - if (*tcp == wxT('/') || *tcp == wxT('\\')) - return tcp + 1; -#endif -#ifdef __VMS__ - if (*tcp == wxT(':') || *tcp == wxT(']')) - return tcp + 1; -#endif - } /* while */ -#if defined(__WXMSW__) || defined(__WXPM__) - // MSDOS like - if (wxIsalpha (*path) && *(path + 1) == wxT(':')) - return path + 2; -#endif - } - return path; + return path + p.length() - n.length(); } -wxString wxFileNameFromPath (const wxString& path1) +wxString wxFileNameFromPath (const wxString& path) { - if (path1 != wxT("")) - { - wxChar *path = WXSTRINGCAST path1 ; - register wxChar *tcp; + wxString name, ext; + wxFileName::SplitPath(path, NULL, &name, &ext); - tcp = path + wxStrlen (path); - while (--tcp >= path) - { -#if defined(__WXMAC__) && !defined(__DARWIN__) - // Classic or Carbon CodeWarrior like - // Carbon with Apple DevTools is Unix like - if (*tcp == wxT(':') ) - return wxString(tcp + 1); -#else - // Unix like or Windows - if (*tcp == wxT('/') || *tcp == wxT('\\')) - return wxString(tcp + 1); -#endif -#ifdef __VMS__ - if (*tcp == wxT(':') || *tcp == wxT(']')) - return wxString(tcp + 1); -#endif - } /* while */ -#if defined(__WXMSW__) || defined(__WXPM__) - // MSDOS like - if (wxIsalpha (*path) && *(path + 1) == wxT(':')) - return wxString(path + 2); -#endif + wxString fullname = name; + if ( !ext.empty() ) + { + fullname << wxFILE_SEP_EXT << ext; } - // Yes, this should return the path, not an empty string, otherwise - // we get "thing.txt" -> "". - return path1; + + return fullname; } // Return just the directory, or NULL if no directory @@ -922,7 +906,7 @@ wxString wxMacFSSpec2MacFilename( const FSSpec *spec ) // includes previously prepended path separator strcat(thePath, theFileName); } - + // create path string for return value wxString result( thePath ) ; #else @@ -947,26 +931,40 @@ wxString wxMacFSSpec2MacFilename( const FSSpec *spec ) return result ; } +#ifndef __DARWIN__ +// Mac file names are POSIX (Unix style) under Darwin +// therefore the conversion functions below are not needed + +static char sMacFileNameConversion[ 1000 ] ; +#endif void wxMacFilename2FSSpec( const char *path , FSSpec *spec ) { + OSStatus err = noErr ; #ifdef __DARWIN__ FSRef theRef; // get the FSRef associated with the POSIX path - (void) FSPathMakeRef((const UInt8 *) path, &theRef, NULL); + err = FSPathMakeRef((const UInt8 *) path, &theRef, NULL); // convert the FSRef to an FSSpec - (void) FSGetCatalogInfo(&theRef, kFSCatInfoNone, NULL, NULL, spec, NULL); + err = FSGetCatalogInfo(&theRef, kFSCatInfoNone, NULL, NULL, spec, NULL); #else - FSpLocationFromFullPath( strlen(path) , path , spec ) ; + if ( strchr( path , ':' ) == NULL ) + { + // try whether it is a volume / or a mounted volume + strncpy( sMacFileNameConversion , path , 1000 ) ; + sMacFileNameConversion[998] = 0 ; + strcat( sMacFileNameConversion , ":" ) ; + err = FSpLocationFromFullPath( strlen(sMacFileNameConversion) , sMacFileNameConversion , spec ) ; + } + else + { + err = FSpLocationFromFullPath( strlen(path) , path , spec ) ; + } #endif } #ifndef __DARWIN__ -// Mac file names are POSIX (Unix style) under Darwin -// therefore the conversion functions below are not needed - -static char sMacFileNameConversion[ 1000 ] ; wxString wxMac2UnixFilename (const char *str) { @@ -1085,16 +1083,16 @@ bool wxConcatFiles (const wxString& file1, const wxString& file2, const wxString& file3) { wxString outfile; - if ( !wxGetTempFileName("cat", outfile) ) + if ( !wxGetTempFileName( wxT("cat"), outfile) ) return FALSE; FILE *fp1 = (FILE *) NULL; FILE *fp2 = (FILE *) NULL; FILE *fp3 = (FILE *) NULL; // Open the inputs and outputs - if ((fp1 = wxFopen (OS_FILENAME( file1 ), wxT("rb"))) == NULL || - (fp2 = wxFopen (OS_FILENAME( file2 ), wxT("rb"))) == NULL || - (fp3 = wxFopen (OS_FILENAME( outfile ), wxT("wb"))) == NULL) + if ((fp1 = wxFopen ( file1, wxT("rb"))) == NULL || + (fp2 = wxFopen ( file2, wxT("rb"))) == NULL || + (fp3 = wxFopen ( outfile, wxT("wb"))) == NULL) { if (fp1) fclose (fp1); @@ -1139,10 +1137,10 @@ wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) if ( ::DosCopy(file2, file2, overwrite ? DCPY_EXISTING : 0) != 0 ) return FALSE; #else // !Win32 - wxStructStat fbuf; + wxStructStat fbuf; // get permissions of file1 - if ( wxStat(OS_FILENAME(file1), &fbuf) != 0 ) + if ( wxStat( file1.c_str(), &fbuf) != 0 ) { // the file probably doesn't exist or we haven't the rights to read // from it anyhow @@ -1173,6 +1171,7 @@ wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) // create file2 with the same permissions than file1 and open it for // writing + wxFile fileOut; if ( !fileOut.Create(file2, overwrite, fbuf.st_mode & 0777) ) return FALSE; @@ -1331,12 +1330,10 @@ bool wxPathExists(const wxChar *pszPathName) wxStructStat st; #ifndef __VISAGECPP__ - return wxStat(wxFNSTRINGCAST strPath.fn_str(), &st) == 0 && - ((st.st_mode & S_IFMT) == S_IFDIR); + return wxStat(pszPathName, &st) == 0 && ((st.st_mode & S_IFMT) == S_IFDIR); #else // S_IFMT not supported in VA compilers.. st_mode is a 2byte value only - return wxStat(wxFNSTRINGCAST strPath.fn_str(), &st) == 0 && - (st.st_mode == S_IFDIR); + return wxStat(pszPathName, &st) == 0 && (st.st_mode == S_IFDIR); #endif #endif // __WIN32__/!__WIN32__ @@ -1396,7 +1393,7 @@ wxString wxFindFirstFile(const wxChar *spec, int flags) } wxString result; - gs_dir->GetFirst(&result, wxFileNameFromPath((wxChar) spec), dirFlags); + gs_dir->GetFirst(&result, wxFileNameFromPath(wxString(spec)), dirFlags); if ( result.IsEmpty() ) { wxDELETE(gs_dir); @@ -1443,8 +1440,11 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) bool needsANSI = TRUE; #if !defined(HAVE_WGETCWD) || wxUSE_UNICODE_MSLU - wxCharBuffer c_buffer(sz); - char *cbuf = (char*)(const char*)c_buffer; + // This is not legal code as the compiler + // is allowed destroy the wxCharBuffer. + // wxCharBuffer c_buffer(sz); + // char *cbuf = (char*)(const char*)c_buffer; + char cbuf[_MAXPATHLEN]; #endif #ifdef HAVE_WGETCWD @@ -1529,7 +1529,9 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) } #endif // __DJGPP__ -#ifdef __CYGWIN__ +// MBN: we hope that in the case the user is compiling a GTK+/Motif app, +// he needs Unix as opposed to Win32 pathnames +#if defined( __CYGWIN__ ) && defined( __WINDOWS__ ) // another example of DOS/Unix mix (Cygwin) wxString pathUnix = buf; cygwin_conv_to_full_win32_path(pathUnix, buf); @@ -1545,15 +1547,11 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) wxString wxGetCwd() { - wxString str; - - // we can't create wxStringBuffer object inline: Sun CC generates buggy - // code in this case! - { - wxStringBuffer buf(str, _MAXPATHLEN); - wxGetWorkingDirectory(buf, _MAXPATHLEN); - } - + wxChar *buffer = new wxChar[_MAXPATHLEN]; + wxGetWorkingDirectory(buffer, _MAXPATHLEN); + wxString str( buffer ); + delete [] buffer; + return str; } @@ -1641,7 +1639,7 @@ bool wxFindFileInPath(wxString *pStr, const wxChar *pszPath, const wxChar *pszFi strFile += wxFILE_SEP_PATH; strFile += pszFile; - if ( FileExists(strFile) ) { + if ( wxFileExists(strFile) ) { *pStr = strFile; break; } @@ -1670,8 +1668,8 @@ void WXDLLEXPORT wxSplitPath(const wxChar *pszFileName, time_t WXDLLEXPORT wxFileModificationTime(const wxString& filename) { wxStructStat buf; - - wxStat(filename.fn_str(), &buf); + wxStat( filename, &buf); + return buf.st_mtime; } @@ -1682,10 +1680,12 @@ time_t WXDLLEXPORT wxFileModificationTime(const wxString& filename) bool wxIsWild( const wxString& pattern ) { - wxString tmp = pattern; - wxChar *pat = WXSTRINGCAST(tmp); - while (*pat) { - switch (*pat++) { + wxString tmp = pattern; + wxChar *pat = WXSTRINGCAST(tmp); + while (*pat) + { + switch (*pat++) + { case wxT('?'): case wxT('*'): case wxT('['): case wxT('{'): return TRUE; case wxT('\\'): @@ -1694,160 +1694,135 @@ bool wxIsWild( const wxString& pattern ) } } return FALSE; -}; - -bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special ) - -#if defined(HAVE_FNMATCH_H) -{ -// this probably won't work well for multibyte chars in Unicode mode? - if(dot_special) - return fnmatch(pat.fn_str(), text.fn_str(), FNM_PERIOD) == 0; - else - return fnmatch(pat.fn_str(), text.fn_str(), 0) == 0; } -#else -// #pragma error Broken implementation of wxMatchWild() -- needs fixing! +/* +* Written By Douglas A. Lewis +* +* The match procedure is public domain code (from ircII's reg.c) +*/ - /* - * WARNING: this code is broken! - */ +bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special ) { - wxString tmp1 = pat; - wxChar *pattern = WXSTRINGCAST(tmp1); - wxString tmp2 = text; - wxChar *str = WXSTRINGCAST(tmp2); - wxChar c; - wxChar *cp; - bool done = FALSE, ret_code, ok; - // Below is for vi fans - const wxChar OB = wxT('{'), CB = wxT('}'); - - // dot_special means '.' only matches '.' - if (dot_special && *str == wxT('.') && *pattern != *str) - return FALSE; + if (text.empty()) + { + /* Match if both are empty. */ + return pat.empty(); + } + + const wxChar *m = pat.c_str(), + *n = text.c_str(), + *ma = NULL, + *na = NULL, + *mp = NULL, + *np = NULL; + int just = 0, + pcount = 0, + acount = 0, + count = 0; + + if (dot_special && (*n == wxT('.'))) + { + /* Never match so that hidden Unix files + * are never found. */ + return FALSE; + } - while ((*pattern != wxT('\0')) && (!done) - && (((*str==wxT('\0'))&&((*pattern==OB)||(*pattern==wxT('*'))))||(*str!=wxT('\0')))) { - switch (*pattern) { - case wxT('\\'): - pattern++; - if (*pattern != wxT('\0')) - pattern++; - break; - case wxT('*'): - pattern++; - ret_code = FALSE; - while ((*str!=wxT('\0')) - && ((ret_code=wxMatchWild(pattern, str++, FALSE)) == 0)) - /*loop*/; - if (ret_code) { - while (*str != wxT('\0')) - str++; - while (*pattern != wxT('\0')) - pattern++; - } - break; - case wxT('['): - pattern++; - repeat: - if ((*pattern == wxT('\0')) || (*pattern == wxT(']'))) { - done = TRUE; - break; - } - if (*pattern == wxT('\\')) { - pattern++; - if (*pattern == wxT('\0')) { - done = TRUE; - break; - } - } - if (*(pattern + 1) == wxT('-')) { - c = *pattern; - pattern += 2; - if (*pattern == wxT(']')) { - done = TRUE; - break; - } - if (*pattern == wxT('\\')) { - pattern++; - if (*pattern == wxT('\0')) { - done = TRUE; - break; - } - } - if ((*str < c) || (*str > *pattern)) { - pattern++; - goto repeat; + for (;;) + { + if (*m == wxT('*')) + { + ma = ++m; + na = n; + just = 1; + mp = NULL; + acount = count; } - } else if (*pattern != *str) { - pattern++; - goto repeat; - } - pattern++; - while ((*pattern != wxT(']')) && (*pattern != wxT('\0'))) { - if ((*pattern == wxT('\\')) && (*(pattern + 1) != wxT('\0'))) - pattern++; - pattern++; - } - if (*pattern != wxT('\0')) { - pattern++, str++; - } - break; - case wxT('?'): - pattern++; - str++; - break; - case OB: - pattern++; - while ((*pattern != CB) && (*pattern != wxT('\0'))) { - cp = str; - ok = TRUE; - while (ok && (*cp != wxT('\0')) && (*pattern != wxT('\0')) - && (*pattern != wxT(',')) && (*pattern != CB)) { - if (*pattern == wxT('\\')) - pattern++; - ok = (*pattern++ == *cp++); + else if (*m == wxT('?')) + { + m++; + if (!*n++) + return FALSE; } - if (*pattern == wxT('\0')) { - ok = FALSE; - done = TRUE; - break; - } else if (ok) { - str = cp; - while ((*pattern != CB) && (*pattern != wxT('\0'))) { - if (*++pattern == wxT('\\')) { - if (*++pattern == CB) - pattern++; + else + { + if (*m == wxT('\\')) + { + m++; + /* Quoting "nothing" is a bad thing */ + if (!*m) + return FALSE; } - } - } else { - while (*pattern!=CB && *pattern!=wxT(',') && *pattern!=wxT('\0')) { - if (*++pattern == wxT('\\')) { - if (*++pattern == CB || *pattern == wxT(',')) - pattern++; + if (!*m) + { + /* + * If we are out of both strings or we just + * saw a wildcard, then we can say we have a + * match + */ + if (!*n) + return TRUE; + if (just) + return TRUE; + just = 0; + goto not_matched; + } + /* + * We could check for *n == NULL at this point, but + * since it's more common to have a character there, + * check to see if they match first (m and n) and + * then if they don't match, THEN we can check for + * the NULL of n + */ + just = 0; + if (*m == *n) + { + m++; + if (*n == wxT(' ')) + mp = NULL; + count++; + n++; + } + else + { + + not_matched: + + /* + * If there are no more characters in the + * string, but we still need to find another + * character (*m != NULL), then it will be + * impossible to match it + */ + if (!*n) + return FALSE; + if (mp) + { + m = mp; + if (*np == wxT(' ')) + { + mp = NULL; + goto check_percent; + } + n = ++np; + count = pcount; + } + else + check_percent: + + if (ma) + { + m = ma; + n = ++na; + count = acount; + } + else + return FALSE; } - } } - if (*pattern != wxT('\0')) - pattern++; - } - break; - default: - if (*str == *pattern) { - str++, pattern++; - } else { - done = TRUE; - } } - } - while (*pattern == wxT('*')) - pattern++; - return ((*str == wxT('\0')) && (*pattern == wxT('\0'))); -}; +} -#endif #ifdef __VISUALC__ #pragma warning(default:4706) // assignment within conditional expression