Reimplemented wxFileName with m_relative field.

Adapted wxFileDialog to trailing slashes.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13038 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling 2001-12-16 12:07:44 +00:00
parent c04857dd6a
commit 353f41cb3b
4 changed files with 224 additions and 107 deletions

View File

@ -260,11 +260,12 @@ public:
static bool IsCaseSensitive( wxPathFormat format = wxPATH_NATIVE ); static bool IsCaseSensitive( wxPathFormat format = wxPATH_NATIVE );
// is this filename absolute? // is this filename absolute?
bool IsAbsolute( wxPathFormat format = wxPATH_NATIVE ); bool IsAbsolute() const
{ return !m_relative; }
// is this filename relative? // is this filename relative?
bool IsRelative( wxPathFormat format = wxPATH_NATIVE ) bool IsRelative() const
{ return !IsAbsolute(format); } { return m_relative; }
// Information about path format // Information about path format
@ -354,6 +355,9 @@ private:
// the file name and extension (empty for directories) // the file name and extension (empty for directories)
wxString m_name, wxString m_name,
m_ext; m_ext;
// is the path relative
bool m_relative;
}; };
#endif // _WX_FILENAME_H_ #endif // _WX_FILENAME_H_

View File

@ -48,7 +48,7 @@
*/ */
// what to test (in alphabetic order)? uncomment the line below to do all tests // what to test (in alphabetic order)? uncomment the line below to do all tests
#define TEST_ALL // #define TEST_ALL
#ifdef TEST_ALL #ifdef TEST_ALL
#define TEST_ARRAYS #define TEST_ARRAYS
#define TEST_CHARSET #define TEST_CHARSET
@ -828,7 +828,7 @@ static void TestFileNameConstruction()
printf("ERROR: fullname should be '%s'\n", fni.fullname); printf("ERROR: fullname should be '%s'\n", fni.fullname);
} }
bool isAbsolute = fn.IsAbsolute(fni.format); bool isAbsolute = fn.IsAbsolute();
printf("'%s' is %s (%s)\n\t", printf("'%s' is %s (%s)\n\t",
fullname.c_str(), fullname.c_str(),
isAbsolute ? "absolute" : "relative", isAbsolute ? "absolute" : "relative",
@ -5304,7 +5304,7 @@ int main(int argc, char **argv)
#endif // TEST_FILE #endif // TEST_FILE
#ifdef TEST_FILENAME #ifdef TEST_FILENAME
if ( 0 ) if ( 1 )
{ {
wxFileName fn; wxFileName fn;
fn.Assign("c:\\foo", "bar.baz"); fn.Assign("c:\\foo", "bar.baz");

View File

@ -32,9 +32,9 @@
or just or just
filename filename
(although :filename works as well). (although :filename works as well).
:::filename.ext is not yet supported. TODO.
Since the volume is just part of the file path, it is not Since the volume is just part of the file path, it is not
treated like a separate entity as it is done under DOS. treated like a separate entity as it is done under DOS and
VMS, it is just treated as another dir.
wxPATH_VMS: VMS native format, absolute file names have the form wxPATH_VMS: VMS native format, absolute file names have the form
<device>:[dir1.dir2.dir3]file.txt <device>:[dir1.dir2.dir3]file.txt
@ -225,6 +225,7 @@ void wxFileName::Assign( const wxFileName &filepath )
m_dirs = filepath.GetDirs(); m_dirs = filepath.GetDirs();
m_name = filepath.GetName(); m_name = filepath.GetName();
m_ext = filepath.GetExt(); m_ext = filepath.GetExt();
m_relative = filepath.IsRelative();
} }
void wxFileName::Assign(const wxString& volume, void wxFileName::Assign(const wxString& volume,
@ -233,18 +234,70 @@ void wxFileName::Assign(const wxString& volume,
const wxString& ext, const wxString& ext,
wxPathFormat format ) wxPathFormat format )
{ {
wxStringTokenizer tn(path, GetPathSeparators(format)); wxPathFormat my_format = GetFormat( format );
wxString my_path = path;
m_dirs.Clear(); m_dirs.Clear();
while ( tn.HasMoreTokens() )
if (!my_path.empty())
{ {
wxString token = tn.GetNextToken(); // 1) Determine if the path is relative or absolute.
switch (my_format)
{
case wxPATH_MAC:
m_relative = ( my_path[0u] == 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 <UP>, whereas under DOS, double
// slashes can be ignored: "\\\\" is the same as "\\".
if (m_relative)
my_path.Remove( 0, 1 );
break;
case wxPATH_VMS:
// TODO: what is the relative path format here?
m_relative = FALSE;
break;
case wxPATH_UNIX:
m_relative = ( my_path[0u] != wxT('/') );
break;
case wxPATH_DOS:
m_relative = ( (my_path[0u] != wxT('/')) && (my_path[0u] != wxT('\\')) );
break;
default:
wxFAIL_MSG( "error" );
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".
wxStringTokenizer tn( my_path, GetPathSeparators(my_format) );
// if the path starts with a slash, we do need the first empty dir while ( tn.HasMoreTokens() )
// entry to be able to tell later that it was an absolute path, but {
// otherwise ignore the double slashes wxString token = tn.GetNextToken();
if ( m_dirs.IsEmpty() || !token.IsEmpty() )
m_dirs.Add( token ); // 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 );
}
}
} }
m_volume = volume; m_volume = volume;
@ -276,7 +329,7 @@ void wxFileName::Assign(const wxString& fullpathOrig,
wxString volume, path, name, ext; wxString volume, path, name, ext;
// do some consistency checks in debug mode: the name should be really just // do some consistency checks in debug mode: the name should be really just
// the filename and the path should be realyl just a path // the filename and the path should be really just a path
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
wxString pathDummy, nameDummy, extDummy; wxString pathDummy, nameDummy, extDummy;
@ -649,7 +702,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
format = GetFormat(format); format = GetFormat(format);
// make the path absolute // make the path absolute
if ( (flags & wxPATH_NORM_ABSOLUTE) && !IsAbsolute() ) if ( (flags & wxPATH_NORM_ABSOLUTE) && m_relative )
{ {
if ( cwd.empty() ) if ( cwd.empty() )
{ {
@ -660,6 +713,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
curDir.AssignDir(cwd); curDir.AssignDir(cwd);
} }
#if 0
// the path may be not absolute because it doesn't have the volume name // the path may be not absolute because it doesn't have the volume name
// but in this case we shouldn't modify the directory components of it // but in this case we shouldn't modify the directory components of it
// but just set the current volume // but just set the current volume
@ -673,6 +727,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
curDir.Clear(); curDir.Clear();
} }
} }
#endif
} }
// handle ~ stuff under Unix only // handle ~ stuff under Unix only
@ -798,6 +853,8 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format)
{ {
m_dirs.Insert(wxT(".."), 0u); m_dirs.Insert(wxT(".."), 0u);
} }
m_relative = TRUE;
// we were modified // we were modified
return TRUE; return TRUE;
@ -833,56 +890,6 @@ bool wxFileName::IsCaseSensitive( wxPathFormat format )
return GetFormat(format) == wxPATH_UNIX; return GetFormat(format) == wxPATH_UNIX;
} }
bool wxFileName::IsAbsolute( wxPathFormat format )
{
// if we have no path, we can't be an abs filename
if ( m_dirs.IsEmpty() )
{
return FALSE;
}
format = GetFormat(format);
if ( format == wxPATH_UNIX )
{
const wxString& str = m_dirs[0u];
if ( str.empty() )
{
// the path started with '/', it's an absolute one
return TRUE;
}
// the path is absolute if it starts with a path separator or
// with "~" or "~user"
wxChar ch = str[0u];
return IsPathSeparator(ch, format) || ch == _T('~');
}
else // !Unix
{
// must have the drive
if ( m_volume.empty() )
return FALSE;
switch ( format )
{
default:
wxFAIL_MSG( _T("unknown wxPATH_XXX style") );
// fall through
case wxPATH_DOS:
return m_dirs[0u].empty();
case wxPATH_VMS:
// TODO: what is the relative path format here?
return TRUE;
case wxPATH_MAC:
return !m_dirs[0u].empty();
}
}
}
/* static */ /* static */
wxString wxFileName::GetVolumeSeparator(wxPathFormat format) wxString wxFileName::GetVolumeSeparator(wxPathFormat format)
{ {
@ -996,16 +1003,82 @@ wxString wxFileName::GetPath( bool add_separator, wxPathFormat format ) const
{ {
format = GetFormat( format ); format = GetFormat( format );
wxString ret; wxString fullpath;
size_t count = m_dirs.GetCount();
for ( size_t i = 0; i < count; i++ ) // the leading character
if ( format == wxPATH_MAC && m_relative )
{ {
ret += m_dirs[i]; fullpath += wxFILE_SEP_PATH_MAC;
if ( add_separator || (i < count) ) }
ret += wxFILE_SEP_PATH; else if ( format == wxPATH_DOS )
{
if (!m_relative)
fullpath += wxFILE_SEP_PATH_DOS;
}
else if ( format == wxPATH_UNIX )
{
if (!m_relative)
fullpath += wxFILE_SEP_PATH_UNIX;
}
// then concatenate all the path components using the path separator
size_t dirCount = m_dirs.GetCount();
if ( dirCount )
{
if ( format == wxPATH_VMS )
{
fullpath += wxT('[');
}
for ( size_t i = 0; i < dirCount; i++ )
{
// TODO: What to do with ".." under VMS
switch (format)
{
case wxPATH_MAC:
{
if (m_dirs[i] == wxT("."))
break;
if (m_dirs[i] != wxT("..")) // convert back from ".." to nothing
fullpath += m_dirs[i];
fullpath += wxT(':');
break;
}
case wxPATH_DOS:
{
fullpath += m_dirs[i];
fullpath += wxT('\\');
break;
}
case wxPATH_UNIX:
{
fullpath += m_dirs[i];
fullpath += wxT('/');
break;
}
case wxPATH_VMS:
{
if (m_dirs[i] != wxT("..")) // convert back from ".." to nothing
fullpath += m_dirs[i];
if (i == dirCount-1)
fullpath += wxT(']');
else
fullpath += wxT('.');
break;
}
default:
{
wxFAIL_MSG( "error" );
}
}
}
} }
return ret;
return fullpath;
} }
wxString wxFileName::GetFullPath( wxPathFormat format ) const wxString wxFileName::GetFullPath( wxPathFormat format ) const
@ -1026,50 +1099,82 @@ wxString wxFileName::GetFullPath( wxPathFormat format ) const
{ {
fullpath << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << m_volume; fullpath << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << m_volume;
} }
else // !UNC else if ( format == wxPATH_DOS || format == wxPATH_VMS )
{ {
fullpath << m_volume << GetVolumeSeparator(format); fullpath << m_volume << GetVolumeSeparator(format);
} }
// else ignore
} }
} }
// the leading character
if ( format == wxPATH_MAC && m_relative )
{
fullpath += wxFILE_SEP_PATH_MAC;
}
else if ( format == wxPATH_DOS )
{
if (!m_relative)
fullpath += wxFILE_SEP_PATH_DOS;
}
else if ( format == wxPATH_UNIX )
{
if (!m_relative)
fullpath += wxFILE_SEP_PATH_UNIX;
}
// then concatenate all the path components using the path separator // then concatenate all the path components using the path separator
size_t dirCount = m_dirs.GetCount(); size_t dirCount = m_dirs.GetCount();
if ( dirCount ) if ( dirCount )
{ {
// under Mac, we must have a path separator in the beginning of the
// relative path - otherwise it would be parsed as an absolute one
if ( format == wxPATH_MAC && m_dirs[0].empty() )
{
fullpath += wxFILE_SEP_PATH_MAC;
}
wxChar chPathSep = GetPathSeparators(format)[0u];
if ( format == wxPATH_VMS ) if ( format == wxPATH_VMS )
{ {
fullpath += _T('['); fullpath += wxT('[');
} }
for ( size_t i = 0; i < dirCount; i++ ) for ( size_t i = 0; i < dirCount; i++ )
{ {
// under VMS, we shouldn't have a leading dot // TODO: What to do with ".." under VMS
if ( i && (format != wxPATH_VMS || !m_dirs[i - 1].empty()) )
fullpath += chPathSep;
fullpath += m_dirs[i]; switch (format)
} {
case wxPATH_MAC:
if ( format == wxPATH_VMS ) {
{ if (m_dirs[i] == wxT("."))
fullpath += _T(']'); break;
} if (m_dirs[i] != wxT("..")) // convert back from ".." to nothing
else // !VMS fullpath += m_dirs[i];
{ fullpath += wxT(':');
// separate the file name from the last directory, notice that we break;
// intentionally do it even if the name and extension are empty as }
// this allows us to distinguish the directories from the file case wxPATH_DOS:
// names (the directories have the trailing slash) {
fullpath += chPathSep; fullpath += m_dirs[i];
fullpath += wxT('\\');
break;
}
case wxPATH_UNIX:
{
fullpath += m_dirs[i];
fullpath += wxT('/');
break;
}
case wxPATH_VMS:
{
if (m_dirs[i] != wxT("..")) // convert back from ".." to nothing
fullpath += m_dirs[i];
if (i == dirCount-1)
fullpath += wxT(']');
else
fullpath += wxT('.');
break;
}
default:
{
wxFAIL_MSG( "error" );
}
}
} }
} }
@ -1334,7 +1439,7 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume,
else else
{ {
// take everything up to the path separator but take care to make // take everything up to the path separator but take care to make
// tha path equal to something like '/', not empty, for the files // the path equal to something like '/', not empty, for the files
// immediately under root directory // immediately under root directory
size_t len = posLastSlash; size_t len = posLastSlash;
if ( !len ) if ( !len )

View File

@ -759,6 +759,9 @@ void wxFileCtrl::GoToParentDir()
{ {
if (m_dirName != wxT("/")) if (m_dirName != wxT("/"))
{ {
size_t len = m_dirName.Len();
if (m_dirName[len-1] == wxT('/'))
m_dirName.Remove( len-1, 1 );
wxString fname( wxFileNameFromPath(m_dirName) ); wxString fname( wxFileNameFromPath(m_dirName) );
m_dirName = wxPathOnly( m_dirName ); m_dirName = wxPathOnly( m_dirName );
if (m_dirName.IsEmpty()) m_dirName = wxT("/"); if (m_dirName.IsEmpty()) m_dirName = wxT("/");
@ -919,12 +922,17 @@ wxFileDialog::wxFileDialog(wxWindow *parent,
m_dialogStyle |= wxOPEN; m_dialogStyle |= wxOPEN;
m_dir = defaultDir; m_dir = defaultDir;
if ((m_dir.IsEmpty()) || (m_dir == wxT("."))) if ((m_dir.empty()) || (m_dir == wxT(".")))
{ {
char buf[200]; char buf[200];
m_dir = getcwd( buf, sizeof(buf) ); m_dir = getcwd( buf, sizeof(buf) );
} }
m_path = defaultDir;
size_t len = m_dir.Len();
if ((len > 1) && (m_dir[len-1] == wxT('/')))
m_dir.Remove( len-1, 1 );
m_path = m_dir;
m_path += wxT("/"); m_path += wxT("/");
m_path += defaultFile; m_path += defaultFile;
m_fileName = defaultFile; m_fileName = defaultFile;