diff --git a/docs/latex/wx/filesys.tex b/docs/latex/wx/filesys.tex index c4d472c679..3289835ec2 100644 --- a/docs/latex/wx/filesys.tex +++ b/docs/latex/wx/filesys.tex @@ -85,6 +85,22 @@ f = fs -> OpenFile("hello.htm"); // opens file 'subdir/folder/hello.htm' !! Returns actual path (set by \helpref{ChangePathTo}{wxfilesystemchangepathto}). + +\membersection{wxFileSystem::FindFirst}\label{wxfilesystemfindfirst} + +\func{wxString}{FindFirst}{\param{const wxString\& }{wildcard}, \param{int }{flags = 0}} + +Works like \helpref{wxFindFirstFile}{wxfindfirstfile}. Returns name of the first +filename (withing filesystem's current path) that matches {\it wildcard}. {\it flags} may be one of +wxFILE (only files), wxDIR (only directories) or 0 (both). + +\membersection{wxFileSystem::FindNext}\label{wxfilesystemfindnext} + +\func{wxString}{FindNext}{\void} + +Returns next filename that matches parameters passed to \helpref{FindFirst}{wxfilesystemfindfirst}. + + \membersection{wxFileSystem::OpenFile}\label{wxfilesystemopenfile} \func{wxFSFile*}{OpenFile}{\param{const wxString\& }{location}} diff --git a/docs/latex/wx/filesysh.tex b/docs/latex/wx/filesysh.tex index 1bc8655257..397cbd6ccd 100644 --- a/docs/latex/wx/filesysh.tex +++ b/docs/latex/wx/filesysh.tex @@ -104,6 +104,31 @@ Returns right location string extracted from {\it location}. Example : GetRightLocation("file:myzipfile.zip\#zip:index.htm") == "index.htm" + + + + +\membersection{wxFileSystemHandler::FindFirst}\label{wxfilesystemfindfirst} + +\func{virtual wxString}{FindFirst}{\param{const wxString\& }{wildcard}, \param{int }{flags = 0}} + +Works like \helpref{wxFindFirstFile}{wxfindfirstfile}. Returns name of the first +filename (withing filesystem's current path) that matches {\it wildcard}. {\it flags} may be one of +wxFILE (only files), wxDIR (only directories) or 0 (both). + +This method is only called if \helpref{CanOpen}{wxfilesystemhandlercanopen} returns TRUE. + +\membersection{wxFileSystemHandler::FindNext}\label{wxfilesystemfindnext} + +\func{virtual wxString}{FindNext}{\void} + +Returns next filename that matches parameters passed to \helpref{FindFirst}{wxfilesystemfindfirst}. + +This method is only called if \helpref{CanRead}{wxfilesystemhandlercanread} returns TRUE and FindFirst +returned non-empty string. + + + \membersection{wxFileSystemHandler::OpenFile}\label{wxfilesystemhandleropenfile} \func{virtual wxFSFile*}{OpenFile}{\param{wxFileSystem\& }{fs}, \param{const wxString\& }{location}} diff --git a/include/wx/filesys.h b/include/wx/filesys.h index 1d79fa851c..2753984d3e 100644 --- a/include/wx/filesys.h +++ b/include/wx/filesys.h @@ -3,6 +3,7 @@ // Purpose: class for opening files - virtual file system // Author: Vaclav Slavik // Copyright: (c) 1999 Vaclav Slavik +// RCS-ID: $Id$ // Licence: wxWindows Licence ///////////////////////////////////////////////////////////////////////////// @@ -93,6 +94,12 @@ class WXDLLEXPORT wxFileSystemHandler : public wxObject // Returns NULL if opening failed. // The location is always absolute path. + virtual wxString FindFirst(const wxString& spec, int flags = 0); + virtual wxString FindNext(); + // Finds first/next file that matches spec wildcard. flags can be wxDIR for restricting + // the query to directories or wxFILE for files only or 0 for either. + // Returns filename or empty string if no more matching file exists + protected: wxString GetProtocol(const wxString& location) const; // returns protocol ("file", "http", "tar" etc.) The last (most right) @@ -141,6 +148,40 @@ class WXDLLEXPORT wxFileSystem : public wxObject { DECLARE_DYNAMIC_CLASS(wxFileSystem) + public: + wxFileSystem() : wxObject() {m_Path = m_LastName = wxEmptyString; m_Handlers.DeleteContents(TRUE); m_FindFileHandler = NULL;} + + void ChangePathTo(const wxString& location, bool is_dir = FALSE); + // sets the current location. Every call to OpenFile is + // relative to this location. + // NOTE !! + // unless is_dir = TRUE 'location' is *not* the directory but + // file contained in this directory + // (so ChangePathTo("dir/subdir/xh.htm") sets m_Path to "dir/subdir/") + + wxString GetPath() const {return m_Path;} + + wxFSFile* OpenFile(const wxString& location); + // opens given file and returns pointer to input stream. + // Returns NULL if opening failed. + // It first tries to open the file in relative scope + // (based on ChangePathTo()'s value) and then as an absolute + // path. + + wxString FindFirst(const wxString& spec, int flags = 0); + wxString FindNext(); + // Finds first/next file that matches spec wildcard. flags can be wxDIR for restricting + // the query to directories or wxFILE for files only or 0 for either. + // Returns filename or empty string if no more matching file exists + + + static void AddHandler(wxFileSystemHandler *handler); + // Adds FS handler. + // In fact, this class is only front-end to the FS hanlers :-) + + static void CleanUpHandlers(); + // remove all items from the m_Handlers list + private: wxString m_Path; // the path (location) we are currently in @@ -151,33 +192,8 @@ class WXDLLEXPORT wxFileSystem : public wxObject // name of last opened file (full path) static wxList m_Handlers; // list of FS handlers - - public: - wxFileSystem() : wxObject() {m_Path = m_LastName = wxEmptyString; m_Handlers.DeleteContents(TRUE);} - - void ChangePathTo(const wxString& location, bool is_dir = FALSE); - // sets the current location. Every call to OpenFile is - // relative to this location. - // NOTE !! - // unless is_dir = TRUE 'location' is *not* the directory but - // file contained in this directory - // (so ChangePathTo("dir/subdir/xh.htm") sets m_Path to "dir/subdir/") - - wxString GetPath() const {return m_Path;} - - wxFSFile* OpenFile(const wxString& location); - // opens given file and returns pointer to input stream. - // Returns NULL if opening failed. - // It first tries to open the file in relative scope - // (based on ChangePathTo()'s value) and then as an absolute - // path. - - static void AddHandler(wxFileSystemHandler *handler); - // Adds FS handler. - // In fact, this class is only front-end to the FS hanlers :-) - - static void CleanUpHandlers(); - // remove all items from the m_Handlers list + wxFileSystemHandler *m_FindFileHandler; + // handler that succeed in FindFirst query }; diff --git a/include/wx/fs_zip.h b/include/wx/fs_zip.h index e3461634b8..53d866fd81 100644 --- a/include/wx/fs_zip.h +++ b/include/wx/fs_zip.h @@ -33,9 +33,20 @@ class WXDLLEXPORT wxZipFSHandler : public wxFileSystemHandler { public: + wxZipFSHandler(); virtual bool CanOpen(const wxString& location); virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); + virtual wxString FindFirst(const wxString& spec, int flags = 0); + virtual wxString FindNext(); ~wxZipFSHandler(); + + private: + // these vars are used by FindFirst/Next: + void *m_Archive; + wxString m_Pattern, m_BaseDir, m_ZipFile; + bool m_AllowDirs, m_AllowFiles; + + wxString DoFind(); }; diff --git a/src/common/filesys.cpp b/src/common/filesys.cpp index 65dfccc567..24e5687e6d 100644 --- a/src/common/filesys.cpp +++ b/src/common/filesys.cpp @@ -154,6 +154,13 @@ wxString wxFileSystemHandler::GetAnchor(const wxString& location) const return wxEmptyString; } + +wxString wxFileSystemHandler::FindFirst(const wxString& spec, int flags) { return wxEmptyString; } + +wxString wxFileSystemHandler::FindNext() { return wxEmptyString; } + + + //-------------------------------------------------------------------------------- // wxLocalFSHandler //-------------------------------------------------------------------------------- @@ -163,6 +170,8 @@ class wxLocalFSHandler : public wxFileSystemHandler public: virtual bool CanOpen(const wxString& location); virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); + virtual wxString FindFirst(const wxString& spec, int flags = 0); + virtual wxString FindNext(); }; @@ -182,6 +191,19 @@ wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& else return (wxFSFile*) NULL; } +wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags) +{ + wxString right = GetRightLocation(spec); + return wxFindFirstFile(right, flags); +} + +wxString wxLocalFSHandler::FindNext() +{ + return wxFindNextFile(); +} + + + //----------------------------------------------------------------------------- // wxFileSystem //----------------------------------------------------------------------------- @@ -201,46 +223,49 @@ void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir) for (i = m_Path.Length()-1; i >= 0; i--) if (m_Path[(unsigned int) i] == wxT('\\')) m_Path.GetWritableChar(i) = wxT('/'); // wanna be windows-safe - if (is_dir == FALSE) + if (is_dir) + { + if (m_Path.Length() > 0 && m_Path.Last() != wxT('/') && m_Path.Last() != wxT(':')) + m_Path << wxT('/'); + } + + else { for (i = m_Path.Length()-1; i >= 0; i--) - { + { if (m_Path[(unsigned int) i] == wxT('/')) - { + { if ((i > 1) && (m_Path[(unsigned int) (i-1)] == wxT('/')) && (m_Path[(unsigned int) (i-2)] == wxT(':'))) - { + { i -= 2; continue; } else - { + { pathpos = i; break; } } - else if (m_Path[(unsigned int) i] == wxT(':')) { - pathpos = i; - break; + else if (m_Path[(unsigned int) i] == wxT(':')) { + pathpos = i; + break; + } } - } if (pathpos == -1) - { + { for (i = 0; i < (int) m_Path.Length(); i++) - { + { if (m_Path[(unsigned int) i] == wxT(':')) - { - //m_Path << wxT('/'); + { m_Path.Remove(i+1); break; } } if (i == (int) m_Path.Length()) - m_Path = wxEmptyString; + m_Path = wxEmptyString; } else - { - if (m_Path[m_Path.Length()-1] != wxT('/')) - m_Path << wxT('/'); + { m_Path.Remove(pathpos+1); } } @@ -261,10 +286,11 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location) for (i = 0; i < ln; i++) { if (loc[(unsigned int) i] == wxT('\\')) loc.GetWritableChar(i) = wxT('/'); // wanna be windows-safe - if (!meta) switch (loc[(unsigned int) i]) - { - case wxT('/') : case wxT(':') : case wxT('#') : meta = loc[(unsigned int) i]; - } + if (!meta) + switch (loc[(unsigned int) i]) + { + case wxT('/') : case wxT(':') : case wxT('#') : meta = loc[(unsigned int) i]; + } } m_LastName = wxEmptyString; @@ -273,10 +299,10 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location) { node = m_Handlers.GetFirst(); while (node) - { + { wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData(); if (h->CanOpen(m_Path + location)) - { + { s = h->OpenFile(*this, m_Path + location); if (s) { m_LastName = m_Path + location; break; } } @@ -289,10 +315,10 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location) { node = m_Handlers.GetFirst(); while (node) - { + { wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData(); if (h->CanOpen(location)) - { + { s = h->OpenFile(*this, location); if (s) { m_LastName = location; break; } } @@ -303,6 +329,48 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location) } + +wxString wxFileSystem::FindFirst(const wxString& spec, int flags) +{ + wxNode *node; + wxString spec2(spec); + + m_FindFileHandler = NULL; + + for (int i = spec2.Length()-1; i >= 0; i--) + if (spec2[(unsigned int) i] == wxT('\\')) spec2.GetWritableChar(i) = wxT('/'); // wanna be windows-safe + + node = m_Handlers.GetFirst(); + while (node) + { + m_FindFileHandler = (wxFileSystemHandler*) node -> GetData(); + if (m_FindFileHandler -> CanOpen(m_Path + spec2)) + return m_FindFileHandler -> FindFirst(m_Path + spec2, flags); + node = node->GetNext(); + } + + node = m_Handlers.GetFirst(); + while (node) + { + m_FindFileHandler = (wxFileSystemHandler*) node -> GetData(); + if (m_FindFileHandler -> CanOpen(spec2)) + return m_FindFileHandler -> FindFirst(spec2, flags); + node = node->GetNext(); + } + + return wxEmptyString; +} + + + +wxString wxFileSystem::FindNext() +{ + if (m_FindFileHandler == NULL) return wxEmptyString; + else return m_FindFileHandler -> FindNext(); +} + + + void wxFileSystem::AddHandler(wxFileSystemHandler *handler) { m_Handlers.Append(handler); @@ -316,6 +384,8 @@ void wxFileSystem::CleanUpHandlers() } + + ///// Module: class wxFileSystemModule : public wxModule @@ -329,10 +399,10 @@ class wxFileSystemModule : public wxModule return TRUE; } virtual void OnExit() - { - wxFileSystemHandler::CleanUpStatics(); + { + wxFileSystemHandler::CleanUpStatics(); wxFileSystem::CleanUpHandlers(); - } + } }; IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule) diff --git a/src/common/fs_zip.cpp b/src/common/fs_zip.cpp index e7765395d5..a9939637d2 100644 --- a/src/common/fs_zip.cpp +++ b/src/common/fs_zip.cpp @@ -27,6 +27,13 @@ #include "wx/zipstrm.h" #include "wx/fs_zip.h" +/* Not the right solution (paths in makefiles) but... */ +#ifdef __BORLANDC__ +#include "../common/unzip.h" +#else +#include "unzip.h" +#endif + //-------------------------------------------------------------------------------- // wxZipFSHandler @@ -34,6 +41,23 @@ +wxZipFSHandler::wxZipFSHandler() : wxFileSystemHandler() +{ + m_Archive = NULL; + m_ZipFile = m_Pattern = m_BaseDir = wxEmptyString; + m_AllowDirs = m_AllowFiles = TRUE; +} + + + +wxZipFSHandler::~wxZipFSHandler() +{ + if (m_Archive) + unzClose((unzFile)m_Archive); +} + + + bool wxZipFSHandler::CanOpen(const wxString& location) { wxString p = GetProtocol(location); @@ -65,8 +89,91 @@ wxFSFile* wxZipFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& l -wxZipFSHandler::~wxZipFSHandler() +wxString wxZipFSHandler::FindFirst(const wxString& spec, int flags) { + wxString right = GetRightLocation(spec); + wxString left = GetLeftLocation(spec); + + if (right.Last() == wxT('/')) right.RemoveLast(); + + if (m_Archive) { + unzClose((unzFile)m_Archive); + m_Archive = NULL; + } + + if (GetProtocol(left) != "file") { + return wxEmptyString; + } + + switch (flags) { + case wxFILE : m_AllowDirs = FALSE, m_AllowFiles = TRUE; break; + case wxDIR : m_AllowDirs = TRUE, m_AllowFiles = FALSE; break; + default : m_AllowDirs = m_AllowFiles = TRUE; break; + } + + m_ZipFile = left; + m_Archive = (void*) unzOpen(m_ZipFile.fn_str()); + m_Pattern = right.AfterLast(wxT('/')); + m_BaseDir = right.BeforeLast(wxT('/')); + + if (m_Archive) { + if (unzGoToFirstFile((unzFile)m_Archive) != UNZ_OK) { + unzClose((unzFile)m_Archive); + m_Archive = NULL; + } + } + return DoFind(); } + + +wxString wxZipFSHandler::FindNext() +{ + if (!m_Archive) return wxEmptyString; + return DoFind(); +} + + + +wxString wxZipFSHandler::DoFind() +{ + static char namebuf[1024]; // char, not wxChar! + char *c; + wxString fn, dir, name; + wxString match = wxEmptyString; + bool wasdir; + + while (match == wxEmptyString) + { + unzGetCurrentFileInfo((unzFile)m_Archive, NULL, namebuf, 1024, NULL, 0, NULL, 0); + for (c = namebuf; *c; c++) if (*c == '\\') *c = '/'; + fn = namebuf; + if (fn.Last() == wxT('/')) { + fn.RemoveLast(); + wasdir = TRUE; + } + else wasdir = FALSE; + + name = fn.AfterLast(wxT('/')); + dir = fn.BeforeLast(wxT('/')); + + if (dir == m_BaseDir) { + if (m_AllowFiles && !wasdir && wxMatchWild(m_Pattern, name, FALSE)) + match = m_ZipFile + wxT("#zip:") + fn; + if (m_AllowDirs && wasdir && wxMatchWild(m_Pattern, name, FALSE)) + match = m_ZipFile + wxT("#zip:") + fn; + } + + if (unzGoToNextFile((unzFile)m_Archive) != UNZ_OK) { + unzClose((unzFile)m_Archive); + m_Archive = NULL; + break; + } + } + + return match; +} + + + #endif // wxUSE_FS_ZIP