/*!
- @page overview_app wxApp overview
+@page overview_app wxApp Overview
- Classes: wxApp
+Classes: wxApp
- @li @ref overview_app_intro
- @li @ref overview_app_shutdown
+@li @ref overview_app_intro
+@li @ref overview_app_shutdown
- <hr>
+<hr>
- @section overview_app_intro Introduction
+@section overview_app_intro Introduction
- A wxWidgets application does not have a @e main procedure; the equivalent is the
- wxApp::OnInit member defined for a class derived from wxApp.
-
- @e OnInit will usually create a top window as a bare minimum.
- Unlike in earlier versions of wxWidgets, OnInit does not return a frame. Instead it
- returns a boolean value which indicates whether processing should continue (@true)
- or not (@false). You call wxApp::SetTopWindow to let wxWidgets know about the top window.
-
- Note that the program's command line arguments, represented by @e argc
- and @e argv, are available from within wxApp member functions.
-
- An application closes by destroying all windows. Because all frames must
- be destroyed for the application to exit, it is advisable to use parent
- frames wherever possible when creating new frames, so that deleting the
- top level frame will automatically delete child frames. The alternative
- is to explicitly delete child frames in the top-level frame's wxCloseEvent
- handler.
-
- In emergencies the wxExit function can be called to kill the
- application however normally the application shuts down automatically,
- see @ref overview_app_shutdown.
-
- An example of defining an application follows:
-
- @code
- class DerivedApp : public wxApp
- {
- public:
- virtual bool OnInit();
- };
-
- IMPLEMENT_APP(DerivedApp)
-
- bool DerivedApp::OnInit()
- {
- wxFrame *the_frame = new wxFrame(NULL, ID_MYFRAME, argv[0]);
- ...
- the_frame->Show(true);
- SetTopWindow(the_frame);
-
- return true;
- }
- @endcode
-
- Note the use of IMPLEMENT_APP(appClass), which allows wxWidgets to dynamically create
- an instance of the application object at the appropriate point in wxWidgets initialization.
- Previous versions of wxWidgets used to rely on the creation of a global application object,
- but this is no longer recommended, because required global initialization may not have
- been performed at application object construction time.
-
- You can also use DECLARE_APP(appClass) in a header file to declare the wxGetApp function
- which returns a reference to the application object. Otherwise you can only use the global
- @c wxTheApp pointer which is of type @c wxApp *.
-
-
-
- @section overview_app_shutdown Application shutdown
-
- The application normally shuts down when the last of its top level windows is
- closed. This is normally the expected behaviour and means that it is enough to
- call wxWindow::Close() in response to the @c "Exit" menu command if your program has a
- single top level window. If this behaviour is not desirable wxApp::SetExitOnFrameDelete
- can be called to change it.
-
- Note that such logic doesn't apply for the windows shown before the program enters the
- main loop: in other words, you can safely show a dialog from wxApp::OnInit and not be
- afraid that your application terminates when this dialog -- which is the last top level
- window for the moment -- is closed.
-
- Another aspect of the application shutdown is wxApp::OnExit
- which is called when the application exits but @e before wxWidgets cleans up
- its internal structures. You should delete all wxWidgets object that you
- created by the time OnExit finishes.
-
- In particular, do @b not destroy them from application class' destructor!
- For example, this code may crash:
-
- @code
- class MyApp : public wxApp
- {
- public:
- wxCHMHelpController m_helpCtrl;
- ...
- };
- @endcode
-
- The reason for that is that @c m_helpCtrl is a member object and is
- thus destroyed from MyApp destructor. But MyApp object is deleted after
- wxWidgets structures that wxCHMHelpController depends on were
- uninitialized! The solution is to destroy HelpCtrl in @e OnExit:
-
- @code
- class MyApp : public wxApp
- {
- public:
- wxCHMHelpController *m_helpCtrl;
- ...
- };
-
- bool MyApp::OnInit()
- {
- ...
- m_helpCtrl = new wxCHMHelpController;
- ...
- }
-
- int MyApp::OnExit()
- {
- delete m_helpCtrl;
- return 0;
- }
- @endcode
+A wxWidgets application does not have a @e main procedure; the equivalent is
+the wxApp::OnInit member defined for a class derived from wxApp.
+
+@e OnInit will usually create a top window as a bare minimum. Unlike in earlier
+versions of wxWidgets, OnInit does not return a frame. Instead it returns a
+boolean value which indicates whether processing should continue (@true) or not
+(@false). You call wxApp::SetTopWindow to let wxWidgets know about the top
+window.
+
+Note that the program's command line arguments, represented by @e argc and
+@e argv, are available from within wxApp member functions.
+
+An application closes by destroying all windows. Because all frames must be
+destroyed for the application to exit, it is advisable to use parent frames
+wherever possible when creating new frames, so that deleting the top level
+frame will automatically delete child frames. The alternative is to explicitly
+delete child frames in the top-level frame's wxCloseEvent handler.
+
+In emergencies the wxExit function can be called to kill the application
+however normally the application shuts down automatically, see
+@ref overview_app_shutdown.
+
+An example of defining an application follows:
+
+@code
+class DerivedApp : public wxApp
+{
+public:
+ virtual bool OnInit();
+};
+
+IMPLEMENT_APP(DerivedApp)
+
+bool DerivedApp::OnInit()
+{
+ wxFrame *the_frame = new wxFrame(NULL, ID_MYFRAME, argv[0]);
+ ...
+ the_frame->Show(true);
+ SetTopWindow(the_frame);
+
+ return true;
+}
+@endcode
+
+Note the use of IMPLEMENT_APP(appClass), which allows wxWidgets to dynamically
+create an instance of the application object at the appropriate point in
+wxWidgets initialization. Previous versions of wxWidgets used to rely on the
+creation of a global application object, but this is no longer recommended,
+because required global initialization may not have been performed at
+application object construction time.
+
+You can also use DECLARE_APP(appClass) in a header file to declare the wxGetApp
+function which returns a reference to the application object. Otherwise you can
+only use the global @c wxTheApp pointer which is of type @c wxApp*.
+
+
+@section overview_app_shutdown Application Shutdown
+
+The application normally shuts down when the last of its top level windows is
+closed. This is normally the expected behaviour and means that it is enough to
+call wxWindow::Close() in response to the "Exit" menu command if your program
+has a single top level window. If this behaviour is not desirable
+wxApp::SetExitOnFrameDelete can be called to change it.
+
+Note that such logic doesn't apply for the windows shown before the program
+enters the main loop: in other words, you can safely show a dialog from
+wxApp::OnInit and not be afraid that your application terminates when this
+dialog -- which is the last top level window for the moment -- is closed.
+
+Another aspect of the application shutdown is wxApp::OnExit which is called
+when the application exits but @e before wxWidgets cleans up its internal
+structures. You should delete all wxWidgets object that you created by the time
+OnExit finishes.
+
+In particular, do @b not destroy them from application class' destructor! For
+example, this code may crash:
+
+@code
+class MyApp : public wxApp
+{
+public:
+ wxCHMHelpController m_helpCtrl;
+ ...
+};
+@endcode
+
+The reason for that is that @c m_helpCtrl is a member object and is thus
+destroyed from MyApp destructor. But MyApp object is deleted after wxWidgets
+structures that wxCHMHelpController depends on were uninitialized! The solution
+is to destroy HelpCtrl in @e OnExit:
+
+@code
+class MyApp : public wxApp
+{
+public:
+ wxCHMHelpController *m_helpCtrl;
+ ...
+};
+
+bool MyApp::OnInit()
+{
+ ...
+ m_helpCtrl = new wxCHMHelpController;
+ ...
+}
+
+int MyApp::OnExit()
+{
+ delete m_helpCtrl;
+ return 0;
+}
+@endcode
*/
/*!
- @page overview_arc Archive formats such as zip
+@page overview_arc Archive Formats
- The archive classes handle archive formats such as zip, tar, rar and cab.
- Currently wxZip and wxTar classes are included.
+The archive classes handle archive formats such as zip, tar, rar and cab.
+Currently wxZip and wxTar classes are included.
- For each archive type, there are the following classes (using zip here
- as an example):
+For each archive type, there are the following classes (using zip here as an
+example):
- @li wxZipInputStream: input stream
- @li wxZipOutputStream: output stream
- @li wxZipEntry: holds the meta-data for an entry (e.g. filename, timestamp, etc.)
+@li wxZipInputStream: Input stream
+@li wxZipOutputStream: Output stream
+@li wxZipEntry: Holds meta-data for an entry (e.g. filename, timestamp, etc.)
- There are also abstract wxArchive classes that can be used to write code
- that can handle any of the archive types, see @ref overview_arc_generic.
+There are also abstract wxArchive classes that can be used to write code that
+can handle any of the archive types, see @ref overview_arc_generic.
- Also see wxFileSystem for a higher level interface that
- can handle archive files in a generic way.
+Also see wxFileSystem for a higher level interface that can handle archive
+files in a generic way.
- The classes are designed to handle archives on both seekable streams such
- as disk files, or non-seekable streams such as pipes and sockets
- (see @ref overview_arc_noseek).
+The classes are designed to handle archives on both seekable streams such as
+disk files, or non-seekable streams such as pipes and sockets (see
+@ref overview_arc_noseek).
- See also wxFileSystem.
+See also wxFileSystem.
- @li @ref overview_arc_create
- @li @ref overview_arc_extract
- @li @ref overview_arc_modify
- @li @ref overview_arc_byname
- @li @ref overview_arc_generic
- @li @ref overview_arc_noseek
+@li @ref overview_arc_create
+@li @ref overview_arc_extract
+@li @ref overview_arc_modify
+@li @ref overview_arc_byname
+@li @ref overview_arc_generic
+@li @ref overview_arc_noseek
- <hr>
+<hr>
- @section overview_arc_create Creating an archive
+@section overview_arc_create Creating an Archive
- Call wxArchiveOutputStream::PutNextEntry() to create each new entry in the archive,
- then write the entry's data.
- Another call to PutNextEntry() closes the current entry and begins the next.
- For example:
+Call wxArchiveOutputStream::PutNextEntry() to create each new entry in the
+archive, then write the entry's data. Another call to PutNextEntry() closes the
+current entry and begins the next. For example:
- @code
- wxFFileOutputStream out(_T("test.zip"));
- wxZipOutputStream zip(out);
- wxTextOutputStream txt(zip);
- wxString sep(wxFileName::GetPathSeparator());
+@code
+wxFFileOutputStream out(_T("test.zip"));
+wxZipOutputStream zip(out);
+wxTextOutputStream txt(zip);
+wxString sep(wxFileName::GetPathSeparator());
- zip.PutNextEntry(_T("entry1.txt"));
- txt << _T("Some text for entry1.txt\n");
+zip.PutNextEntry(_T("entry1.txt"));
+txt << _T("Some text for entry1.txt\n");
- zip.PutNextEntry(_T("subdir") + sep + _T("entry2.txt"));
- txt << _T("Some text for subdir/entry2.txt\n");
- @endcode
+zip.PutNextEntry(_T("subdir") + sep + _T("entry2.txt"));
+txt << _T("Some text for subdir/entry2.txt\n");
+@endcode
- The name of each entry can be a full path, which makes it possible to
- store entries in subdirectories.
+The name of each entry can be a full path, which makes it possible to store
+entries in subdirectories.
- @section overview_arc_extract Extracting an archive
+@section overview_arc_extract Extracting an Archive
- wxArchiveInputStream::GetNextEntry() returns a pointer to entry object containing the
- meta-data for the next entry in the archive (and gives away ownership).
+wxArchiveInputStream::GetNextEntry() returns a pointer to entry object
+containing the meta-data for the next entry in the archive (and gives away
+ownership).
- Reading from the input stream then returns the entry's data.
- Eof() becomes @true after an attempt has been made to read past the end of the entry's data.
+Reading from the input stream then returns the entry's data. Eof() becomes
+@true after an attempt has been made to read past the end of the entry's data.
- When there are no more entries, GetNextEntry() returns @NULL and sets Eof().
+When there are no more entries, GetNextEntry() returns @NULL and sets Eof().
- @code
- auto_ptr<wxZipEntry> entry;
+@code
+auto_ptr<wxZipEntry> entry;
- wxFFileInputStream in(_T("test.zip"));
- wxZipInputStream zip(in);
+wxFFileInputStream in(_T("test.zip"));
+wxZipInputStream zip(in);
- while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
- {
- // access meta-data
- wxString name = entry->GetName();
- // read 'zip' to access the entry's data
- }
- @endcode
+while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
+{
+ // access meta-data
+ wxString name = entry->GetName();
+ // read 'zip' to access the entry's data
+}
+@endcode
- @section overview_arc_modify Modifying an archive
+@section overview_arc_modify Modifying an Archive
- To modify an existing archive, write a new copy of the archive to a new file,
- making any necessary changes along the way and transferring any unchanged
- entries using wxArchiveOutputStream::CopyEntry().
+To modify an existing archive, write a new copy of the archive to a new file,
+making any necessary changes along the way and transferring any unchanged
+entries using wxArchiveOutputStream::CopyEntry().
- For archive types which compress entry data, CopyEntry() is likely to be
- much more efficient than transferring the data using Read() and Write()
- since it will copy them without decompressing and recompressing them.
+For archive types which compress entry data, CopyEntry() is likely to be much
+more efficient than transferring the data using Read() and Write() since it
+will copy them without decompressing and recompressing them.
- In general modifications are not possible without rewriting the archive,
- though it may be possible in some limited cases. Even then, rewriting the
- archive is usually a better choice since a failure can be handled without
- losing the whole archive. wxTempFileOutputStream can be helpful to do this.
+In general modifications are not possible without rewriting the archive, though
+it may be possible in some limited cases. Even then, rewriting the archive is
+usually a better choice since a failure can be handled without losing the whole
+archive. wxTempFileOutputStream can be helpful to do this.
- For example to delete all entries matching the pattern "*.txt":
+For example to delete all entries matching the pattern "*.txt":
- @code
- auto_ptr<wxFFileInputStream> in(new wxFFileInputStream(_T("test.zip")));
- wxTempFileOutputStream out(_T("test.zip"));
+@code
+auto_ptr<wxFFileInputStream> in(new wxFFileInputStream(_T("test.zip")));
+wxTempFileOutputStream out(_T("test.zip"));
- wxZipInputStream inzip(*in);
- wxZipOutputStream outzip(out);
+wxZipInputStream inzip(*in);
+wxZipOutputStream outzip(out);
- auto_ptr<wxZipEntry> entry;
+auto_ptr<wxZipEntry> entry;
- // transfer any meta-data for the archive as a whole (the zip comment
- // in the case of zip)
- outzip.CopyArchiveMetaData(inzip);
+// transfer any meta-data for the archive as a whole (the zip comment
+// in the case of zip)
+outzip.CopyArchiveMetaData(inzip);
- // call CopyEntry for each entry except those matching the pattern
- while (entry.reset(inzip.GetNextEntry()), entry.get() != NULL)
- if (!entry->GetName().Matches(_T("*.txt")))
- if (!outzip.CopyEntry(entry.release(), inzip))
- break;
+// call CopyEntry for each entry except those matching the pattern
+while (entry.reset(inzip.GetNextEntry()), entry.get() != NULL)
+ if (!entry->GetName().Matches(_T("*.txt")))
+ if (!outzip.CopyEntry(entry.release(), inzip))
+ break;
- // close the input stream by releasing the pointer to it, do this
- // before closing the output stream so that the file can be replaced
- in.reset();
+// close the input stream by releasing the pointer to it, do this
+// before closing the output stream so that the file can be replaced
+in.reset();
- // you can check for success as follows
- bool success = inzip.Eof() && outzip.Close() && out.Commit();
- @endcode
+// you can check for success as follows
+bool success = inzip.Eof() && outzip.Close() && out.Commit();
+@endcode
- @section overview_arc_byname Looking up an archive entry by name
+@section overview_arc_byname Looking Up an Archive Entry by Name
- Also see wxFileSystem for a higher level interface that is
- more convenient for accessing archive entries by name.
+Also see wxFileSystem for a higher level interface that is more convenient for
+accessing archive entries by name.
- To open just one entry in an archive, the most efficient way is
- to simply search for it linearly by calling wxArchiveInputStream::GetNextEntry()
- until the required entry is found. This works both for archives on seekable and
- non-seekable streams.
+To open just one entry in an archive, the most efficient way is to simply
+search for it linearly by calling wxArchiveInputStream::GetNextEntry() until
+the required entry is found. This works both for archives on seekable and
+non-seekable streams.
- The format of filenames in the archive is likely to be different
- from the local filename format. For example zips and tars use
- unix style names, with forward slashes as the path separator,
- and absolute paths are not allowed. So if on Windows the file
- "C:\MYDIR\MYFILE.TXT" is stored, then when reading the entry back
- wxArchiveEntry::GetName() will return "MYDIR\MYFILE.TXT".
- The conversion into the internal format and back has lost some information.
+The format of filenames in the archive is likely to be different from the local
+filename format. For example zips and tars use unix style names, with forward
+slashes as the path separator, and absolute paths are not allowed. So if on
+Windows the file "C:\MYDIR\MYFILE.TXT" is stored, then when reading the entry
+back wxArchiveEntry::GetName() will return "MYDIR\MYFILE.TXT". The conversion
+into the internal format and back has lost some information.
- So to avoid ambiguity when searching for an entry matching a local name,
- it is better to convert the local name to the archive's internal format
- and search for that:
+So to avoid ambiguity when searching for an entry matching a local name, it is
+better to convert the local name to the archive's internal format and search
+for that:
- @code
- auto_ptr<wxZipEntry> entry;
+@code
+auto_ptr<wxZipEntry> entry;
- // convert the local name we are looking for into the internal format
- wxString name = wxZipEntry::GetInternalName(localname);
+// convert the local name we are looking for into the internal format
+wxString name = wxZipEntry::GetInternalName(localname);
- // open the zip
- wxFFileInputStream in(_T("test.zip"));
- wxZipInputStream zip(in);
+// open the zip
+wxFFileInputStream in(_T("test.zip"));
+wxZipInputStream zip(in);
- // call GetNextEntry() until the required internal name is found
- do {
- entry.reset(zip.GetNextEntry());
- }
- while (entry.get() != NULL && entry->GetInternalName() != name);
+// call GetNextEntry() until the required internal name is found
+do
+{
+ entry.reset(zip.GetNextEntry());
+}
+while (entry.get() != NULL && entry->GetInternalName() != name);
- if (entry.get() != NULL) {
- // read the entry's data...
- }
- @endcode
+if (entry.get() != NULL)
+{
+ // read the entry's data...
+}
+@endcode
- To access several entries randomly, it is most efficient to transfer the
- entire catalogue of entries to a container such as a std::map or a
- wxHashMap then entries looked up by name can be opened using the
- wxArchiveInputStream::OpenEntry() method.
-
- @code
- WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
- ZipCatalog::iterator it;
- wxZipEntry *entry;
- ZipCatalog cat;
-
- // open the zip
- wxFFileInputStream in(_T("test.zip"));
- wxZipInputStream zip(in);
-
- // load the zip catalog
- while ((entry = zip.GetNextEntry()) != NULL) {
- wxZipEntry*& current = cat[entry->GetInternalName()];
- // some archive formats can have multiple entries with the same name
- // (e.g. tar) though it is an error in the case of zip
- delete current;
- current = entry;
- }
-
- // open an entry by name
- if ((it = cat.find(wxZipEntry::GetInternalName(localname))) != cat.end()) {
- zip.OpenEntry(*it->second);
- // ... now read entry's data
- }
- @endcode
-
- To open more than one entry simultaneously you need more than one
- underlying stream on the same archive:
-
- @code
- // opening another entry without closing the first requires another
- // input stream for the same file
- wxFFileInputStream in2(_T("test.zip"));
- wxZipInputStream zip2(in2);
- if ((it = cat.find(wxZipEntry::GetInternalName(local2))) != cat.end())
- zip2.OpenEntry(*it->second);
- @endcode
+To access several entries randomly, it is most efficient to transfer the entire
+catalogue of entries to a container such as a std::map or a wxHashMap then
+entries looked up by name can be opened using the
+wxArchiveInputStream::OpenEntry() method.
+@code
+WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
+ZipCatalog::iterator it;
+wxZipEntry *entry;
+ZipCatalog cat;
+
+// open the zip
+wxFFileInputStream in(_T("test.zip"));
+wxZipInputStream zip(in);
+
+// load the zip catalog
+while ((entry = zip.GetNextEntry()) != NULL)
+{
+ wxZipEntry*& current = cat[entry->GetInternalName()];
+ // some archive formats can have multiple entries with the same name
+ // (e.g. tar) though it is an error in the case of zip
+ delete current;
+ current = entry;
+}
+
+// open an entry by name
+if ((it = cat.find(wxZipEntry::GetInternalName(localname))) != cat.end())
+{
+ zip.OpenEntry(*it->second);
+ // ... now read entry's data
+}
+@endcode
+
+To open more than one entry simultaneously you need more than one underlying
+stream on the same archive:
+
+@code
+// opening another entry without closing the first requires another
+// input stream for the same file
+wxFFileInputStream in2(_T("test.zip"));
+wxZipInputStream zip2(in2);
+if ((it = cat.find(wxZipEntry::GetInternalName(local2))) != cat.end())
+ zip2.OpenEntry(*it->second);
+@endcode
+
+
+
+@section overview_arc_generic Generic Archive Programming
+
+Also see wxFileSystem for a higher level interface that can handle archive
+files in a generic way.
+
+The specific archive classes, such as the wxZip classes, inherit from the
+following abstract classes which can be used to write code that can handle any
+of the archive types:
+
+@li wxArchiveInputStream: Input stream
+@li wxArchiveOutputStream: Output stream
+@li wxArchiveEntry: Holds the meta-data for an entry (e.g. filename)
+
+In order to able to write generic code it's necessary to be able to create
+instances of the classes without knowing which archive type is being used.
+
+To allow this there is a class factory for each archive type, derived from
+wxArchiveClassFactory, that can create the other classes.
+
+For example, given wxArchiveClassFactory* factory, streams and entries can be
+created like this:
+
+@code
+// create streams without knowing their type
+auto_ptr<wxArchiveInputStream> inarc(factory->NewStream(in));
+auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
+
+// create an empty entry object
+auto_ptr<wxArchiveEntry> entry(factory->NewEntry());
+@endcode
+
+For the factory itself, the static member wxArchiveClassFactory::Find() can be
+used to find a class factory that can handle a given file extension or mime
+type. For example, given @e filename:
+
+@code
+const wxArchiveClassFactory *factory;
+factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
+
+if (factory)
+ stream = factory->NewStream(new wxFFileInputStream(filename));
+@endcode
+
+@e Find() does not give away ownership of the returned pointer, so it does not
+need to be deleted.
+
+There are similar class factories for the filter streams that handle the
+compression and decompression of a single stream, such as wxGzipInputStream.
+These can be found using wxFilterClassFactory::Find().
+
+For example, to list the contents of archive @e filename:
+
+@code
+auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));
+
+if (in->IsOk())
+{
+ // look for a filter handler, e.g. for '.gz'
+ const wxFilterClassFactory *fcf;
+ fcf = wxFilterClassFactory::Find(filename, wxSTREAM_FILEEXT);
+ if (fcf)
+ {
+ in.reset(fcf->NewStream(in.release()));
+ // pop the extension, so if it was '.tar.gz' it is now just '.tar'
+ filename = fcf->PopExtension(filename);
+ }
+
+ // look for a archive handler, e.g. for '.zip' or '.tar'
+ const wxArchiveClassFactory *acf;
+ acf = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
+ if (acf)
+ {
+ auto_ptr<wxArchiveInputStream> arc(acf->NewStream(in.release()));
+ auto_ptr<wxArchiveEntry> entry;
+
+ // list the contents of the archive
+ while ((entry.reset(arc->GetNextEntry())), entry.get() != NULL)
+ std::wcout << entry->GetName().c_str() << "\n";
+ }
+ else
+ {
+ wxLogError(_T("can't handle '%s'"), filename.c_str());
+ }
+}
+@endcode
- @section overview_arc_generic Generic archive programming
- Also see wxFileSystem for a higher level interface that
- can handle archive files in a generic way.
-
- The specific archive classes, such as the wxZip classes, inherit from
- the following abstract classes which can be used to write code that can
- handle any of the archive types:
-
- @li wxArchiveInputStream: input stream
- @li wxArchiveOutputStream: output stream
- @li wxArchiveEntry: holds the meta-data for an entry (e.g. filename)
-
- In order to able to write generic code it's necessary to be able to create
- instances of the classes without knowing which archive type is being used.
-
- To allow this there is a class factory for each archive type, derived from
- wxArchiveClassFactory, that can create the other classes.
-
- For example, given @e wxArchiveClassFactory* factory, streams and
- entries can be created like this:
-
- @code
- // create streams without knowing their type
- auto_ptr<wxArchiveInputStream> inarc(factory->NewStream(in));
- auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
-
- // create an empty entry object
- auto_ptr<wxArchiveEntry> entry(factory->NewEntry());
- @endcode
-
- For the factory itself, the static member wxArchiveClassFactory::Find().
- can be used to find a class factory that can handle a given file
- extension or mime type. For example, given @e filename:
-
- @code
- const wxArchiveClassFactory *factory;
- factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
-
- if (factory)
- stream = factory->NewStream(new wxFFileInputStream(filename));
- @endcode
-
- @e Find does not give away ownership of the returned pointer, so it
- does not need to be deleted.
-
- There are similar class factories for the filter streams that handle the
- compression and decompression of a single stream, such as wxGzipInputStream.
- These can be found using wxFilterClassFactory::Find().
-
- For example, to list the contents of archive @e filename:
-
- @code
- auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));
-
- if (in->IsOk())
- {
- // look for a filter handler, e.g. for '.gz'
- const wxFilterClassFactory *fcf;
- fcf = wxFilterClassFactory::Find(filename, wxSTREAM_FILEEXT);
- if (fcf) {
- in.reset(fcf->NewStream(in.release()));
- // pop the extension, so if it was '.tar.gz' it is now just '.tar'
- filename = fcf->PopExtension(filename);
- }
-
- // look for a archive handler, e.g. for '.zip' or '.tar'
- const wxArchiveClassFactory *acf;
- acf = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
- if (acf) {
- auto_ptr<wxArchiveInputStream> arc(acf->NewStream(in.release()));
- auto_ptr<wxArchiveEntry> entry;
-
- // list the contents of the archive
- while ((entry.reset(arc->GetNextEntry())), entry.get() != NULL)
- std::wcout << entry->GetName().c_str() << "\n";
- }
- else {
- wxLogError(_T("can't handle '%s'"), filename.c_str());
- }
- }
- @endcode
-
-
-
- @section overview_arc_noseek Archives on non-seekable streams
-
- In general, handling archives on non-seekable streams is done in the same
- way as for seekable streams, with a few caveats.
-
- The main limitation is that accessing entries randomly using
- wxArchiveInputStream::OpenEntry() is not possible, the entries can only be
- accessed sequentially in the order they are stored within the archive.
-
- For each archive type, there will also be other limitations which will
- depend on the order the entries' meta-data is stored within the archive.
- These are not too difficult to deal with, and are outlined below.
-
- @subsection overview_arc_noseek_entrysize PutNextEntry and the entry size
-
- When writing archives, some archive formats store the entry size before
- the entry's data (tar has this limitation, zip doesn't). In this case
- the entry's size must be passed to wxArchiveOutputStream::PutNextEntry()
- or an error occurs.
-
- This is only an issue on non-seekable streams, since otherwise the archive
- output stream can seek back and fix up the header once the size of the
- entry is known.
-
- For generic programming, one way to handle this is to supply the size
- whenever it is known, and rely on the error message from the output
- stream when the operation is not supported.
-
- @subsection overview_arc_noseek_weak GetNextEntry and the weak reference mechanism
-
- Some archive formats do not store all an entry's meta-data before the
- entry's data (zip is an example). In this case, when reading from a
- non-seekable stream, wxArchiveInputStream::GetNextEntry() can only return
- a partially populated wxArchiveEntry object - not all the fields are set.
-
- The input stream then keeps a weak reference to the entry object and
- updates it when more meta-data becomes available. A weak reference being
- one that does not prevent you from deleting the wxArchiveEntry object - the
- input stream only attempts to update it if it is still around.
-
- The documentation for each archive entry type gives the details
- of what meta-data becomes available and when. For generic programming,
- when the worst case must be assumed, you can rely on all the fields
- of wxArchiveEntry being fully populated when GetNextEntry() returns,
- with the the following exceptions:
-
- @li wxArchiveEntry::GetSize(): guaranteed to be available after the
- entry has been read to wxInputStream::Eof(), or wxArchiveInputStream::CloseEntry()
- has been called
-
- @li wxArchiveEntry::IsReadOnly(): guaranteed to be available after the end of
- the archive has been reached, i.e. after GetNextEntry() returns @NULL and
- Eof() is @true
-
- This mechanism allows wxArchiveOutputStream::CopyEntry() to always fully
- preserve entries' meta-data. No matter what order order the meta-data occurs
- within the archive, the input stream will always have read it before the output
- stream must write it.
-
- @subsection overview_arc_noseek_notifier wxArchiveNotifier
-
- Notifier objects can be used to get a notification whenever an input
- stream updates a wxArchiveEntry object's data via the weak reference mechanism.
-
- Consider the following code which renames an entry in an archive.
- This is the usual way to modify an entry's meta-data, simply set the
- required field before writing it with wxArchiveOutputStream::CopyEntry():
-
- @code
- auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
- auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
- auto_ptr<wxArchiveEntry> entry;
-
- outarc->CopyArchiveMetaData(*arc);
-
- while (entry.reset(arc->GetNextEntry()), entry.get() != NULL) {
- if (entry->GetName() == from)
- entry->SetName(to);
- if (!outarc->CopyEntry(entry.release(), *arc))
- break;
- }
-
- bool success = arc->Eof() && outarc->Close();
- @endcode
-
- However, for non-seekable streams, this technique cannot be used for
- fields such as wxArchiveEntry::IsReadOnly(), which are not necessarily set when
- wxArchiveInputStream::GetNextEntry() returns.
-
- In this case a wxArchiveNotifier can be used:
-
- @code
- class MyNotifier : public wxArchiveNotifier
- {
- public:
- void OnEntryUpdated(wxArchiveEntry& entry) { entry.SetIsReadOnly(false); }
- };
- @endcode
-
- The meta-data changes are done in your notifier's wxArchiveNotifier::OnEntryUpdated()
- method, then wxArchiveEntry::SetNotifier() is called before CopyEntry():
-
- @code
- auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
- auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
- auto_ptr<wxArchiveEntry> entry;
- MyNotifier notifier;
-
- outarc->CopyArchiveMetaData(*arc);
-
- while (entry.reset(arc->GetNextEntry()), entry.get() != NULL) {
- entry->SetNotifier(notifier);
- if (!outarc->CopyEntry(entry.release(), *arc))
- break;
- }
-
- bool success = arc->Eof() && outarc->Close();
- @endcode
-
- SetNotifier() calls OnEntryUpdated() immediately, then the input
- stream calls it again whenever it sets more fields in the entry. Since
- OnEntryUpdated() will be called at least once, this technique always
- works even when it is not strictly necessary to use it. For example,
- changing the entry name can be done this way too and it works on seekable
- streams as well as non-seekable.
+@section overview_arc_noseek Archives on Non-Seekable Streams
+
+In general, handling archives on non-seekable streams is done in the same way
+as for seekable streams, with a few caveats.
+
+The main limitation is that accessing entries randomly using
+wxArchiveInputStream::OpenEntry() is not possible, the entries can only be
+accessed sequentially in the order they are stored within the archive.
+
+For each archive type, there will also be other limitations which will depend
+on the order the entries' meta-data is stored within the archive. These are not
+too difficult to deal with, and are outlined below.
+
+@subsection overview_arc_noseek_entrysize PutNextEntry and the Entry Size
+
+When writing archives, some archive formats store the entry size before the
+entry's data (tar has this limitation, zip doesn't). In this case the entry's
+size must be passed to wxArchiveOutputStream::PutNextEntry() or an error
+occurs.
+
+This is only an issue on non-seekable streams, since otherwise the archive
+output stream can seek back and fix up the header once the size of the entry is
+known.
+
+For generic programming, one way to handle this is to supply the size whenever
+it is known, and rely on the error message from the output stream when the
+operation is not supported.
+
+@subsection overview_arc_noseek_weak GetNextEntry and the Weak Reference Mechanism
+
+Some archive formats do not store all an entry's meta-data before the entry's
+data (zip is an example). In this case, when reading from a non-seekable
+stream, wxArchiveInputStream::GetNextEntry() can only return a partially
+populated wxArchiveEntry object - not all the fields are set.
+
+The input stream then keeps a weak reference to the entry object and updates it
+when more meta-data becomes available. A weak reference being one that does not
+prevent you from deleting the wxArchiveEntry object - the input stream only
+attempts to update it if it is still around.
+
+The documentation for each archive entry type gives the details of what
+meta-data becomes available and when. For generic programming, when the worst
+case must be assumed, you can rely on all the fields of wxArchiveEntry being
+fully populated when GetNextEntry() returns, with the the following exceptions:
+
+@li wxArchiveEntry::GetSize(): Guaranteed to be available after the entry has
+ been read to wxInputStream::Eof(), or wxArchiveInputStream::CloseEntry()
+ has been called.
+@li wxArchiveEntry::IsReadOnly(): Guaranteed to be available after the end of
+ the archive has been reached, i.e. after GetNextEntry() returns @NULL and
+ Eof() is @true.
+
+This mechanism allows wxArchiveOutputStream::CopyEntry() to always fully
+preserve entries' meta-data. No matter what order order the meta-data occurs
+within the archive, the input stream will always have read it before the output
+stream must write it.
+
+@subsection overview_arc_noseek_notifier wxArchiveNotifier
+
+Notifier objects can be used to get a notification whenever an input stream
+updates a wxArchiveEntry object's data via the weak reference mechanism.
+
+Consider the following code which renames an entry in an archive. This is the
+usual way to modify an entry's meta-data, simply set the required field before
+writing it with wxArchiveOutputStream::CopyEntry():
+
+@code
+auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
+auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
+auto_ptr<wxArchiveEntry> entry;
+
+outarc->CopyArchiveMetaData(*arc);
+
+while (entry.reset(arc->GetNextEntry()), entry.get() != NULL)
+{
+ if (entry->GetName() == from)
+ entry->SetName(to);
+ if (!outarc->CopyEntry(entry.release(), *arc))
+ break;
+}
+
+bool success = arc->Eof() && outarc->Close();
+@endcode
+
+However, for non-seekable streams, this technique cannot be used for fields
+such as wxArchiveEntry::IsReadOnly(), which are not necessarily set when
+wxArchiveInputStream::GetNextEntry() returns.
+
+In this case a wxArchiveNotifier can be used:
+
+@code
+class MyNotifier : public wxArchiveNotifier
+{
+public:
+ void OnEntryUpdated(wxArchiveEntry& entry) { entry.SetIsReadOnly(false); }
+};
+@endcode
+
+The meta-data changes are done in your notifier's
+wxArchiveNotifier::OnEntryUpdated() method, then wxArchiveEntry::SetNotifier()
+is called before CopyEntry():
+
+@code
+auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
+auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
+auto_ptr<wxArchiveEntry> entry;
+MyNotifier notifier;
+
+outarc->CopyArchiveMetaData(*arc);
+
+while (entry.reset(arc->GetNextEntry()), entry.get() != NULL)
+{
+ entry->SetNotifier(notifier);
+ if (!outarc->CopyEntry(entry.release(), *arc))
+ break;
+}
+
+bool success = arc->Eof() && outarc->Close();
+@endcode
+
+SetNotifier() calls OnEntryUpdated() immediately, then the input stream calls
+it again whenever it sets more fields in the entry. Since OnEntryUpdated() will
+be called at least once, this technique always works even when it is not
+strictly necessary to use it. For example, changing the entry name can be done
+this way too and it works on seekable streams as well as non-seekable.
*/