434 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			434 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| //
 | |
| // ARCHIVE.CPP
 | |
| //
 | |
| //  Source file for ArchiveLib 1.0
 | |
| //
 | |
| //  Copyright (c) Greenleaf Software, Inc. 1994
 | |
| //  All Rights Reserved
 | |
| //
 | |
| // CONTENTS
 | |
| //
 | |
| //  ALArchive::operator new()
 | |
| //  ALArchive::ALArchive()
 | |
| //  ALArchive::~ALArchive()
 | |
| //  ALArchive::CreateCompressionEngine()
 | |
| //  ALArchive::CreateStorageObject()
 | |
| //  ALArchive::AddWildCardFiles()
 | |
| //  ALArchive::MakeEntriesFromListBox()
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This file contains all the source code for class ALArchive.  ALArchive
 | |
| //  is a class derived from ALArchiveBase that knows how to create ALFile
 | |
| //  and ALMemory objects.  Remember that ALArchiveBase doesn't know how
 | |
| //  to create any kind of storage object, so we need derived classes to
 | |
| //  bind ourselves to certain types of objects.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //  May 23, 1994  1.0A  : First release
 | |
| //
 | |
| //
 | |
| #include "arclib.h"
 | |
| #pragma hdrstop
 | |
| 
 | |
| #include "archive.h"
 | |
| #include "grenengn.h"
 | |
| #include "copyengn.h"
 | |
| #include "filestor.h"
 | |
| #include "memstore.h"
 | |
| #include "wildcard.h"
 | |
| 
 | |
| //
 | |
| // void * ALArchive::operator new( size_t size )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  size  :  The number of bytes needed to create a new ALArchive object.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  A pointer to the newly allocated storage area, or 0 if no storage
 | |
| //  was available.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  When using a DLL, it is easy to create a dangerous situation when 
 | |
| //  creating objects whose ctor and dtor are both in the DLL.  The problem
 | |
| //  arises because when you create an object using new, the memory for
 | |
| //  the object will be allocated from the EXE.  However, when you destroy
 | |
| //  the object using delete, the memory is freed inside the DLL.  Since
 | |
| //  the DLL doesn't really own that memory, bad things can happen.
 | |
| //
 | |
| //  But, you say, won't the space just go back to the Windows heap regardless
 | |
| //  of who tries to free it?  Maybe, but maybe not.  If the DLL is using
 | |
| //  a subsegment allocation scheme, it might do some sort of local free
 | |
| //  before returning the space to the windows heap.  That is the point where
 | |
| //  you could conceivably cook your heap.
 | |
| //
 | |
| //  By providing our own version of operator new inside this class, we
 | |
| //  ensure that all memory allocation for the class will be done from
 | |
| //  inside the DLL, not the EXE calling the DLL.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| #if defined( AL_BUILDING_DLL )
 | |
| void AL_DLL_FAR * AL_PROTO ALArchive::operator new( size_t size )
 | |
| {
 | |
|   return ::new char[ size ];
 | |
| }
 | |
| #endif
 | |
| 
 | |
| //
 | |
| // ALArchive::ALArchive( const char *file_name )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  name  :  The name of the ALFile object that is going to hold the
 | |
| //           ALArchive.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing, this is a constructor.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This is one of two constructors for ALArchive.  (The other one 
 | |
| //  follows immediately in this source file.)  It is used
 | |
| //  when the archive you are working with or are going to create will
 | |
| //  reside in an ALFile object, which should be often.  It simply
 | |
| //  calls the constructor for the base class with the appropriately
 | |
| //  created ALFile object and returns.  It doesn't have to initialize
 | |
| //  any data members of its own, so life is really simple.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| AL_PROTO ALArchive::ALArchive( const char AL_DLL_FAR *file_name )
 | |
| : ALArchiveBase( new ALFile( file_name ), 1 )
 | |
| {
 | |
| }
 | |
| 
 | |
| //
 | |
| // ALArchive::ALArchive( ALStorage &so )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  so  : A storage object that will used as the storage for the archive.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing, this is a constructor.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This is one of two constructors for ALArchive.  (The other one 
 | |
| //  immediately precedes this function in the same source file.)  It is used
 | |
| //  when the archive you are working with or are going to create will
 | |
| //  reside in an object that you have already constructed.
 | |
| //  It doesn't have to initialize any data members of its own, so 
 | |
| //  all it does is call the base class constructor from an
 | |
| //  initializer list, and then return.
 | |
| //
 | |
| //  The storage object used for this archive is your responsibility to delete.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| AL_PROTO ALArchive::ALArchive( ALStorage AL_DLL_FAR &so )
 | |
| : ALArchiveBase( &so, 0 )
 | |
| {
 | |
| }
 | |
| 
 | |
| //
 | |
| // ALArchive::~ALArchive()
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing, destructor.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This destructor has an easy life of it, since it has no data
 | |
| //  members to clean up after.  Instead, it leaves all of the heavy
 | |
| //  lifting to the base class destructor.  In debug mode we at least
 | |
| //  do *something*, which is just to verify that this is the correct
 | |
| //  type of object.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| AL_PROTO ALArchive::~ALArchive()
 | |
| {
 | |
|   AL_ASSERT( GoodTag(), "~ALArchive: attempt to delete invalid object" );
 | |
| }
 | |
| 
 | |
| //
 | |
| // ALCompressionEngine *ALArchive::CreateCompressionEngine( int engine_type )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  engine_type  : An integer from ALDEFS.H that defines the type of compression
 | |
| //                 to be created.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  A pointer to a newly created compression engine.  If things go bad,
 | |
| //  a value of 0 is possible.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  ALArchiveBase doesn't know how to create compression engines or
 | |
| //  storage objects.  That knowledge is left up to derived classes like
 | |
| //  this one.  When extracting objects from an archive, this class has
 | |
| //  to be able to create a compression engine with no more information
 | |
| //  than the integer engine type stored in the archive directory.
 | |
| //  This is where we do it.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| ALCompressionEngine AL_DLL_FAR *
 | |
| AL_PROTO ALArchive::CreateCompressionEngine( int engine_type )
 | |
| {
 | |
|   switch ( engine_type ) {
 | |
|   case AL_COMPRESSION_COPY :
 | |
|     return new ALCopyEngine();
 | |
|   case AL_COMPRESSION_GREENLEAF :
 | |
|     return new ALGreenleafEngine();
 | |
|     default :
 | |
|     mStatus.SetError( AL_UNKNOWN_COMPRESSION_TYPE,
 | |
|                      "Unknown compression type (%d) found in archive",
 | |
|                      engine_type );
 | |
|     break; //Break instead of return because of bogus warnings
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| //
 | |
| // ALStorage * ALArchive::CreateStorageObject( const char *name,
 | |
| //                                             int object_type )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  name        : The name of the storage object to be created.
 | |
| //
 | |
| //  object_type : The object type, from ALStorageType in STORAGE.H.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  A pointer to a newly storage object.  If things go bad,
 | |
| //  a value of 0 is possible.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  ALArchiveBase doesn't know how to create compression engines or
 | |
| //  storage objects.  That knowledge is left up to derived classes like
 | |
| //  this one.  When extracting objects from an archive, this class has
 | |
| //  to be able to create a storage object with no more information
 | |
| //  than the integer object type stored in the archive directory.
 | |
| //  This is where we do it.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| ALStorage AL_DLL_FAR * AL_PROTO
 | |
| ALArchive::CreateStorageObject( const char AL_DLL_FAR *name,
 | |
|                                int object_type )
 | |
| {
 | |
|   switch ( object_type ) {
 | |
|   case AL_MEMORY_OBJECT :
 | |
|     return new ALMemory( name );
 | |
|   case AL_FILE_OBJECT :
 | |
|     return new ALFile( name );
 | |
|     default :
 | |
|     mStatus.SetError( AL_UNKNOWN_STORAGE_OBJECT,
 | |
|                      "Unknown storage object type (%d) "
 | |
|                      "found in archive",
 | |
|                      object_type );
 | |
| 
 | |
|     break;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| // STATIC MEMBER FUNCTION
 | |
| //
 | |
| // int ALArchive::AddWildCardFiles(
 | |
| //                      ALEntryList & list,
 | |
| //                      const char *wild_spec = "*.*",
 | |
| //                      int traverse_flag  = 0,
 | |
| //                      short int compression_level = AL_GREENLEAF_LEVEL_2 )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  list              :  The list that is going to receive the newly created
 | |
| //                       ALEntry objects.
 | |
| //
 | |
| //  wild_spec         :  The wild card file spec to expand into a list of
 | |
| //                       files.  Note that this string can contain multiple
 | |
| //                       file specs, separated by commas or spaces.
 | |
| //
 | |
| //  traverse_flag     :  A flag to indicate whether wild card expansion
 | |
| //                       should traverse subdirectories.
 | |
| //
 | |
| //  compression_level :  The compression level that will be used to create
 | |
| //                       compression engines for the new entries.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  The number of entries created by the wild card expansion.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  It is handy to have a function that will create a bunch of ALEntry
 | |
| //  objects and add them to a list of your choosing.  We can't do this
 | |
| //  in the base class of ALArchiveBase, because it doesn't know anything
 | |
| //  about specific storage objects or compression engines.  So the
 | |
| //  logical place to turn is to this derived class, which does know about
 | |
| //  ALFile and ALMemory.  
 | |
| //
 | |
| //  The only bad thing here is that this is a static public functions, 
 | |
| //  so it is kind of confusing.  You might think that this ought to be
 | |
| //  a member function of ALEntryList.  The problem is, we don't want
 | |
| //  ALEntryList to know about specific engines or compression classes,
 | |
| //  because then they would get linked in to any application created
 | |
| //  with ArchiveLib.
 | |
| //
 | |
| //  So anyway, this function creates a bunch of new ALEntry objects,
 | |
| //  with the storage object being an instance of class ALFile, and the
 | |
| //  compression engine being an object of class ALGreenleafEngine.  It
 | |
| //  then adds the new ALEntry to the specified ALEntryList, so you don't
 | |
| //  have to do any work at all.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALArchive::AddWildCardFiles( ALEntryList AL_DLL_FAR & list,
 | |
|                             const char AL_DLL_FAR *wild_spec /* = "*.*" */,
 | |
|                             int traverse_flag /* = 0 */,
 | |
|                             short int compression_level /* = AL_GREENLEAF_LEVEL_2 */ )
 | |
| {
 | |
|   AL_ASSERT( wild_spec != 0, "AddWildCardFiles: null parameter for wild_spec" );
 | |
|   ALWildCardExpander files( wild_spec, traverse_flag );
 | |
|   int count = 0;
 | |
|   
 | |
|   char *new_name; ALEntry* dummy;
 | |
|   while ( ( new_name = files.GetNextFile() ) != 0 ) {
 | |
|     dummy = new ALEntry( list,
 | |
|                         new ALFile( new_name ),
 | |
|                         new ALGreenleafEngine( compression_level ) );
 | |
|     count++;
 | |
|   }
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| //
 | |
| // int ALArchive::MakeEntriesFromListBox( ALEntryList &list,
 | |
| //                                        HWND hDlg,
 | |
| //                                        int list_box /* = -1 */ )
 | |
| //
 | |
| // ARGUMENTS:
 | |
| //
 | |
| //  list     :  The list that is going to get the new entries.
 | |
| //
 | |
| //  hDlg     :  The handle of the dialog box that contains the list box
 | |
| //              control.  If you aren't using a dialog box, you can pass
 | |
| //              the handle of the list box control directly, and set
 | |
| //              the list_box parameter to -1.
 | |
| //
 | |
| //  list_box :  The id of the list box control in the dialog box.  If this
 | |
| //              parameter is set to -1, it means that hDlg doesn't refer
 | |
| //              to a dialog, it refers to the actual handle of a list box
 | |
| //              control.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  The number of new entries created from the list box.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This function goes through a list box, and picks out all the
 | |
| //  highlighted entries.  It creates a new ALEntry object for each
 | |
| //  of the marked entires, using ALFile and ALGreenleafEngine objects.
 | |
| //  For purposes of orthogonality, I  probably should have had a
 | |
| //  compression_level parameter here, but I neglected to include that.
 | |
| //  We could do it in the next release using a default parameter and
 | |
| //  nobody would even notice.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   May 23, 1994  1.0A  : First release
 | |
| //
 | |
| 
 | |
| #if defined( AL_WINDOWS_GUI )
 | |
| 
 | |
| int AL_PROTO ALArchive::
 | |
| MakeEntriesFromListBox( ALEntryList AL_DLL_FAR &list,
 | |
|                        HWND hDlg,
 | |
|                        int list_box /* = -1 */ )
 | |
| {
 | |
|   HWND window;
 | |
| 
 | |
|   if ( list_box != -1 )
 | |
|     window = GetDlgItem( hDlg, (short int) list_box );
 | |
|   else
 | |
|     window = hDlg;
 | |
|   int count = (WORD) SendMessage( window, LB_GETSELCOUNT, 0, 0L );
 | |
|   if ( count == LB_ERR )
 | |
|     return AL_GETSEL_ERROR;
 | |
|   int *items = new int[ count ];
 | |
|   if ( items == 0 )
 | |
|     return AL_CANT_ALLOCATE_MEMORY;
 | |
| #ifdef AL_FLAT_MODEL
 | |
|   if ( count != SendMessage( window, LB_GETSELITEMS, (short int) count, (LPARAM) items ) ) {
 | |
| #else
 | |
|     if ( count != SendMessage( window, LB_GETSELITEMS, (short int) count, (LPARAM)(int _far *)  items ) ) {
 | |
| #endif
 | |
|       delete items;
 | |
|       return AL_GETSEL_ERROR;
 | |
|     }
 | |
|     for ( WORD i = 0 ; i < (WORD) count ; i++ ) {
 | |
|       WORD length = (WORD) SendMessage( window, LB_GETTEXTLEN, (short int) items[ i ], 0L );
 | |
|       if ( length > 0 ) {
 | |
|         char *name = new char[ length + 1 ];
 | |
|         if ( name ) {
 | |
|           if ( SendMessage( window, LB_GETTEXT, (short int) items[ i ], (LPARAM)( (LPSTR) name ) ) >= 0 ) {
 | |
|             new ALEntry( list,
 | |
|                         new ALFile( name ),
 | |
|                         new ALGreenleafEngine() );
 | |
|           }
 | |
|           delete name;
 | |
|           SendMessage( window,
 | |
|                       LB_SETSEL,
 | |
|                       0,
 | |
|                       items[ i ] );
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     delete items;
 | |
|     return count;
 | |
|   }
 | |
| 
 | |
| #endif //#ifdef AL_WINDOWS_GUI
 |