X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5a3912f2aba8f5232315f7ca2206c50295ec21ea..f7ff39c6ac67b995c13900af1b6a4b32e8c7f9f2:/src/common/filename.cpp diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 062ddc41fb..17218d98d3 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -163,7 +163,8 @@ public: filename, // name mode == Read ? GENERIC_READ // access mask : GENERIC_WRITE, - 0, // no sharing + FILE_SHARE_READ | // sharing mode + FILE_SHARE_WRITE, // (allow everything) NULL, // no secutity attr OPEN_EXISTING, // creation disposition 0, // no flags @@ -311,84 +312,95 @@ void wxFileName::Assign(const wxString& volume, m_name = name; } -void wxFileName::SetPath( const wxString &path, wxPathFormat format ) +void wxFileName::SetPath( const wxString& pathOrig, wxPathFormat format ) { m_dirs.Clear(); - if ( !path.empty() ) + if ( pathOrig.empty() ) { - wxPathFormat my_format = GetFormat( format ); - wxString my_path = path; + // no path at all + m_relative = true; - // 1) Determine if the path is relative or absolute. - wxChar leadingChar = my_path[0u]; + return; + } - switch (my_format) - { - case wxPATH_MAC: - m_relative = leadingChar == wxT(':'); - - // We then remove a leading ":". The reason is in our - // storage form for relative paths: - // ":dir:file.txt" actually means "./dir/file.txt" in - // DOS notation and should get stored as - // (relative) (dir) (file.txt) - // "::dir:file.txt" actually means "../dir/file.txt" - // stored as (relative) (..) (dir) (file.txt) - // This is important only for the Mac as an empty dir - // actually means , whereas under DOS, double - // slashes can be ignored: "\\\\" is the same as "\\". - if (m_relative) - my_path.erase( 0, 1 ); - break; + format = GetFormat( format ); - case wxPATH_VMS: - // TODO: what is the relative path format here? - m_relative = false; - break; + // 0) deal with possible volume part first + wxString volume, + path; + SplitVolume(pathOrig, &volume, &path, format); + if ( !volume.empty() ) + { + m_relative = false; - default: - wxFAIL_MSG( _T("Unknown path format") ); - // !! Fall through !! + SetVolume(volume); + } - case wxPATH_UNIX: - // the paths of the form "~" or "~username" are absolute - m_relative = leadingChar != wxT('/') && leadingChar != _T('~'); - break; + // 1) Determine if the path is relative or absolute. + wxChar leadingChar = path[0u]; - case wxPATH_DOS: - m_relative = !IsPathSeparator(leadingChar, my_format); - break; + switch (format) + { + case wxPATH_MAC: + m_relative = leadingChar == wxT(':'); + + // We then remove a leading ":". The reason is in our + // storage form for relative paths: + // ":dir:file.txt" actually means "./dir/file.txt" in + // DOS notation and should get stored as + // (relative) (dir) (file.txt) + // "::dir:file.txt" actually means "../dir/file.txt" + // stored as (relative) (..) (dir) (file.txt) + // This is important only for the Mac as an empty dir + // actually means , whereas under DOS, double + // slashes can be ignored: "\\\\" is the same as "\\". + if (m_relative) + path.erase( 0, 1 ); + break; - } + case wxPATH_VMS: + // TODO: what is the relative path format here? + m_relative = false; + break; - // 2) Break up the path into its members. If the original path - // was just "/" or "\\", m_dirs will be empty. We know from - // the m_relative field, if this means "nothing" or "root dir". + default: + wxFAIL_MSG( _T("Unknown path format") ); + // !! Fall through !! - wxStringTokenizer tn( my_path, GetPathSeparators(my_format) ); + case wxPATH_UNIX: + // the paths of the form "~" or "~username" are absolute + m_relative = leadingChar != wxT('/') && leadingChar != _T('~'); + break; - while ( tn.HasMoreTokens() ) - { - wxString token = tn.GetNextToken(); + case wxPATH_DOS: + m_relative = !IsPathSeparator(leadingChar, format); + break; - // Remove empty token under DOS and Unix, interpret them - // as .. under Mac. - if (token.empty()) - { - if (my_format == wxPATH_MAC) - m_dirs.Add( wxT("..") ); - // else ignore - } - else - { - m_dirs.Add( token ); - } - } } - else // no path at all + + // 2) Break up the path into its members. If the original path + // was just "/" or "\\", m_dirs will be empty. We know from + // the m_relative field, if this means "nothing" or "root dir". + + wxStringTokenizer tn( path, GetPathSeparators(format) ); + + while ( tn.HasMoreTokens() ) { - m_relative = true; + wxString token = tn.GetNextToken(); + + // Remove empty token under DOS and Unix, interpret them + // as .. under Mac. + if (token.empty()) + { + if (format == wxPATH_MAC) + m_dirs.Add( wxT("..") ); + // else ignore + } + else + { + m_dirs.Add( token ); + } } } @@ -585,7 +597,7 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) } #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__) -#ifdef __WIN32__ + if ( dir.empty() ) { if ( !::GetTempPath(MAX_PATH, wxStringBuffer(dir, MAX_PATH + 1)) ) @@ -612,12 +624,6 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) path.clear(); } -#else // Win16 - if ( !::GetTempFileName(NULL, prefix, 0, wxStringBuffer(path, 1025)) ) - { - path.clear(); - } -#endif // Win32/16 #else // !Windows if ( dir.empty() ) @@ -945,11 +951,29 @@ bool wxFileName::Normalize(int flags, m_dirs.Add(dir); } + +#if defined(__WIN32__) && !defined(__WXWINCE__) && wxUSE_OLE + if ( (flags & wxPATH_NORM_SHORTCUT) ) + { + wxString filename; + if (GetShortcutTarget(GetFullPath(format), filename)) + { + // Repeat this since we may now have a new path + if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) ) + { + filename.MakeLower(); + } + m_relative = false; + Assign(filename); + } + } +#endif if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) ) { // VZ: expand env vars here too? + m_volume.MakeLower(); m_name.MakeLower(); m_ext.MakeLower(); } @@ -969,6 +993,81 @@ bool wxFileName::Normalize(int flags, return true; } +// ---------------------------------------------------------------------------- +// get the shortcut target +// ---------------------------------------------------------------------------- + +// WinCE (3) doesn't have CLSID_ShellLink, IID_IShellLink definitions. +// The .lnk file is a plain text file so it should be easy to +// make it work. Hint from Google Groups: +// "If you open up a lnk file, you'll see a +// number, followed by a pound sign (#), followed by more text. The +// number is the number of characters that follows the pound sign. The +// characters after the pound sign are the command line (which _can_ +// include arguments) to be executed. Any path (e.g. \windows\program +// files\myapp.exe) that includes spaces needs to be enclosed in +// quotation marks." + +#if defined(__WIN32__) && !defined(__WXWINCE__) && wxUSE_OLE +// The following lines are necessary under WinCE +// #include "wx/msw/private.h" +// #include +#include +#if defined(__WXWINCE__) +#include +#endif + +bool wxFileName::GetShortcutTarget(const wxString& shortcutPath, wxString& targetFilename, wxString* arguments) +{ + wxString path, file, ext; + wxSplitPath(shortcutPath, & path, & file, & ext); + + HRESULT hres; + IShellLink* psl; + bool success = FALSE; + + // Assume it's not a shortcut if it doesn't end with lnk + if (ext.Lower() != wxT("lnk")) + return FALSE; + + // create a ShellLink object + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, (LPVOID*) &psl); + + if (SUCCEEDED(hres)) + { + IPersistFile* ppf; + hres = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf); + if (SUCCEEDED(hres)) + { + WCHAR wsz[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, shortcutPath.mb_str(), -1, wsz, + MAX_PATH); + + hres = ppf->Load(wsz, 0); + if (SUCCEEDED(hres)) + { + wxChar buf[2048]; + psl->GetPath(buf, 2048, NULL, SLGP_UNCPRIORITY); + targetFilename = wxString(buf); + success = (shortcutPath != targetFilename); + + psl->GetArguments(buf, 2048); + wxString args(buf); + if (!args.IsEmpty() && arguments) + { + *arguments = args; + } + } + } + } + psl->Release(); + return success; +} +#endif + + // ---------------------------------------------------------------------------- // absolute/relative paths // ---------------------------------------------------------------------------- @@ -1055,8 +1154,8 @@ bool wxFileName::SameAs(const wxFileName& filepath, wxPathFormat format) const // get cwd only once - small time saving wxString cwd = wxGetCwd(); - fn1.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, cwd, format); - fn2.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, cwd, format); + fn1.Normalize(wxPATH_NORM_ALL | wxPATH_NORM_CASE, cwd, format); + fn2.Normalize(wxPATH_NORM_ALL | wxPATH_NORM_CASE, cwd, format); if ( fn1.GetFullPath() == fn2.GetFullPath() ) return true; @@ -1156,6 +1255,16 @@ wxString wxFileName::GetPathSeparators(wxPathFormat format) return seps; } +/* static */ +wxString wxFileName::GetPathTerminators(wxPathFormat format) +{ + format = GetFormat(format); + + // under VMS the end of the path is ']', not the path separator used to + // separate the components + return format == wxPATH_VMS ? wxString(_T(']')) : GetPathSeparators(format); +} + /* static */ bool wxFileName::IsPathSeparator(wxChar ch, wxPathFormat format) { @@ -1270,7 +1379,7 @@ wxString wxFileName::GetPath( int flags, wxPathFormat format ) const // normally the absolute file names start with a slash // with one exception: the ones like "~/foo.bar" don't // have it - if ( m_dirs[0u] != _T('~') ) + if ( m_dirs.IsEmpty() || m_dirs[0u] != _T('~') ) { fullpath += wxFILE_SEP_PATH_UNIX; } @@ -1530,22 +1639,16 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format ) // ---------------------------------------------------------------------------- /* static */ -void wxFileName::SplitPath(const wxString& fullpathWithVolume, - wxString *pstrVolume, - wxString *pstrPath, - wxString *pstrName, - wxString *pstrExt, - wxPathFormat format) +void +wxFileName::SplitVolume(const wxString& fullpathWithVolume, + wxString *pstrVolume, + wxString *pstrPath, + wxPathFormat format) { format = GetFormat(format); wxString fullpath = fullpathWithVolume; - // under VMS the end of the path is ']', not the path separator used to - // separate the components - wxString sepPath = format == wxPATH_VMS ? wxString(_T(']')) - : GetPathSeparators(format); - // special Windows UNC paths hack: transform \\share\path into share:path if ( format == wxPATH_DOS ) { @@ -1555,7 +1658,8 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume, { fullpath.erase(0, 2); - size_t posFirstSlash = fullpath.find_first_of(sepPath); + size_t posFirstSlash = + fullpath.find_first_of(GetPathTerminators(format)); if ( posFirstSlash != wxString::npos ) { fullpath[posFirstSlash] = wxFILE_SEP_DSK; @@ -1584,21 +1688,37 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume, } } + if ( pstrPath ) + *pstrPath = fullpath; +} + +/* static */ +void wxFileName::SplitPath(const wxString& fullpathWithVolume, + wxString *pstrVolume, + wxString *pstrPath, + wxString *pstrName, + wxString *pstrExt, + wxPathFormat format) +{ + format = GetFormat(format); + + wxString fullpath; + SplitVolume(fullpathWithVolume, pstrVolume, &fullpath, format); + // find the positions of the last dot and last path separator in the path size_t posLastDot = fullpath.find_last_of(wxFILE_SEP_EXT); - size_t posLastSlash = fullpath.find_last_of(sepPath); + size_t posLastSlash = fullpath.find_last_of(GetPathTerminators(format)); + // check whether this dot occurs at the very beginning of a path component if ( (posLastDot != wxString::npos) && - ((format == wxPATH_UNIX) || (format == wxPATH_VMS)) ) + (posLastDot == 0 || + IsPathSeparator(fullpath[posLastDot - 1]) || + (format == wxPATH_VMS && fullpath[posLastDot - 1] == _T(']'))) ) { - if ( (posLastDot == 0) || - (fullpath[posLastDot - 1] == sepPath[0u] ) ) - { - // under Unix and VMS, dot may be (and commonly is) the first - // character of the filename, don't treat the entire filename as - // extension in this case - posLastDot = wxString::npos; - } + // dot may be (and commonly -- at least under Unix -- is) the first + // character of the filename, don't treat the entire filename as + // extension in this case + posLastDot = wxString::npos; } // if we do have a dot and a slash, check that the dot is in the name part @@ -1891,25 +2011,25 @@ WX_DEFINE_EXPORTED_OBJARRAY(MacDefaultExtensionArray) ; MacDefaultExtensionArray gMacDefaultExtensions ; -static void MacEnsureDefaultExtensionsLoaded() +// load the default extensions +MacDefaultExtensionRecord gDefaults[] = { - if ( !gMacDefaultExtensionsInited ) - { - - // load the default extensions - MacDefaultExtensionRecord defaults[1] = - { - MacDefaultExtensionRecord( wxT("txt") , 'TEXT' , 'ttxt' ) , - - } ; - // we could load the pc exchange prefs here too + MacDefaultExtensionRecord( wxT("txt") , 'TEXT' , 'ttxt' ) , + MacDefaultExtensionRecord( wxT("tif") , 'TIFF' , '****' ) , + MacDefaultExtensionRecord( wxT("jpg") , 'JPEG' , '****' ) , +} ; - for ( size_t i = 0 ; i < WXSIZEOF( defaults ) ; ++i ) +static void MacEnsureDefaultExtensionsLoaded() +{ + if ( !gMacDefaultExtensionsInited ) { - gMacDefaultExtensions.Add( defaults[i] ) ; + // we could load the pc exchange prefs here too + for ( size_t i = 0 ; i < WXSIZEOF( gDefaults ) ; ++i ) + { + gMacDefaultExtensions.Add( gDefaults[i] ) ; + } + gMacDefaultExtensionsInited = true ; } - gMacDefaultExtensionsInited = true ; - } } bool wxFileName::MacSetTypeAndCreator( wxUint32 type , wxUint32 creator ) {