                     WHAT'S NEW IN ARCHIVELIB 2.0?
                     -----------------------------

Pkware support
--------------

You can now work with the PKWare ZIP archive format.  To work with PKZIP
archives, you need to create objects of type ALPkArchive.  ALPkArchive
has exactly the same member functions as ALGlArchive, so you can mix and
match these archive types freely.

ArchiveLib 2.0 doesn't support the following ZIP features:

*	Extraction of PKZIP 1.0 file formats.  In particular, PKZIP 1.0 used
    LZW compression to store files.  LZW compression is covered by a
    patent. You probably don't want to pay royalties on your product.

*	Encryption.  We need to sort out the export regulations on this
    before we attempt to add this to our product.

*	Disk spanning.  This is our number one feature for ArchiveLib 3.0.

OS/2 support
------------

ArchiveLib now comes with complete support for OS/2 console and PM
applications.  You can use BUILD.EXE to build examples using OS/2
libraries, from Borland and Microsoft.  The examples directory contains
a raft of examples named EX??CON.CPP, EX??CON.C and EX??PM.CPP that will
all work with OS/2.

Deflate engine
--------------

We have incorporated the ZLIB deflate engine written by Marc Adler and
Jean-loop Gailly into ArchiveLib.  These files, found in CPP_ZLIB,
implement the compression type needed to read and write ZIP files.  The
two engines are instantiated using the classes ALPkCompressor and
ALPkDecompressor.

The deflate algorithm creates two big buffers to compress data.  The
sliding window is a buffer with 2^(window_bits+2) bytes of storage.  In
other words, a window bits value of 15 means you need 128Kbytes for the
sliding buffer.

The second buffer is 2^(mem_level+9) bytes long.  So a mem_level of 8
will consume 128Kbytes.


New class hierarchy for archive
-------------------------------

The archive class hierarchy is somewhat simpler than it used to be.  The
abstract base class of ALArchive provides some infrastructure.  The two
classes derived from it are ALPkArchive and ALGlArchive.  They provide
the mechanism to create and manipulate the two different types of
archives.

New class hierarchy for compression engines
-------------------------------------------

In ArchiveLib 1.0, the ALCompressionEngine contained the code to both
compress and decompress.  In an effort to be more granular, compression
and decompression engines are now separated out into two base classes:
ALCompressor and ALDecompressor.  If you are just using archives, you
probably don't have to worry about this too much. However, if you are
using the engines in a standalone mode, you do need to worry about it.


Storage type binding done by entry list via toolkit
---------------------------------------------------

There is an architectural problem built in to ArchiveLib.  The problem
is how to decide which compression engines and storage objects to
include in your application.  In particular, it can be tough to decide
which engines to include when you are writing a routine that is going to
extract objects from an archive.  You might not know in advance what
type of objects are going to be in the archive, in which case you
probably should like in everything in sight.  On the other hand, you
might only be extracting files using the deflate engine.  If this is the
case, linking in memory objects and the Greenleaf compression engine is
a waste of time.

In ArchiveLib 1.0, storage object and engine linkage was accomplished by
deriving new types of archive objects.  class ALArchive was the default
class, and it linked in just about everything.

In ArchiveLib 2.0, linkage is performed by the ALEntryList object.  This
is a little more logical.  In addition, the linkage is more flexible,
and doesn't require derivation.  In a nutshell, when you create an
ALEntryList object, you give it a toolkit of storage objects, compression
engines, and decompression engines that it will use to do its job.  By
default, the toolkit contains all three compression engines, and two
storage object types.  This is accomplished by virtue of the default
value for the toolkit parameter in the ALEntryList constructor.  The
default value of FullTools() creates a toolkit with everything but the
kitchen sink.

To build a more slim and trim application, you can construct your
ALEntryList object with limited toolsets.  The ones we provide prebuilt
in the library include:

  *  PkTools(): File and memory storage objects, but only the deflate
     engines.  You would use this in an application that was not using
     Greenleaf's engine.

  *  PKCompressTools(): Same as above, but just the deflate compression
     engine.  A file that just creates Zip compatible archives could
     save space by excluding the decompression engine.

  *  PKDecompressTools(): Same as above, but just the deflate
     decompression engine.  Use this in an extraction only application.

Likewise, there are a corresponding set of toolkit builders known as
GlTools(), GlCompressTools(), and GLDecompressTools().

Finally, you can build your own toolkit in an argument to your
ALEntryList object.  Just throw in copies of all the
compression/decompression objects and storage objects you plan to use,
like this:

	ALEntryList list( ALFile() + ALGlCompressor() );

Yes, you use the '+' operator to connect all these guys together into a
toolkit.


Some header files and class names redone
----------------------------------------

In ArchiveLib 1.0, ARCHIVE.H was used to define the Greenleaf archive
class.  Now we have two archiving classes, so this job is being done by
two different header files.  Note that the base class ALArchiveBase has
been renamed to ALArchive.  In 1.0, an ALArchive was a Greenleaf format
archive.  In 2.0, a Greenleaf format archive is an ALGlArchive.

Use PKARC.H to define and use Zip compaptible archives.  Use GLARC.H to
define and use Greenleaf proprietary archives.  ARC.H is used to define
the base archive class.

In 1.0, CMPENGN.H defined the base compression class, and GRENENGN.H
defined the Greenleaf proprietary compression class.  Now, the base
class is defined in ENGN.H, with derived classes showing up in PKENGN.H,
GLENGN.H, and COPYENGN.H.


Our header file, STORAGE.H, conflicts with an OLE 2.0 header file found
in Borland's 4.5 release.  The file has been renamed as STOR.H, which
means a few other header files had to have their contents renamed.
Since STOR.H is automatically included by ARCLIB.H, you should be able
to ignore this change.

Directory and build structure redone
------------------------------------

In order to cut back on ifdefs, ArchiveLib has partitioned as much
platform-specific code as possible into separate directories.  For
example, platform-specific user interface code is now found in
directories CPP_UI.TXT, CPP_UI.WIN, and CPP_UI.PM.  Similar partitioning
is done for File Systems, Yield functions, and Memory.

The default root directory for ArchiveLib is now AL200, to reflect the
new release number.

To make ArchiveLib a little more consistent with some of our other
products, the directory naming scheme for compilers has been slightly
modified.  The directories now being used are :

    Borland C++ 2.0 for OS/2       AL200\B20
    Borland C++ 3.1:               AL200\B31
    Borland C++ 4.0:               AL200\B40
    Borland C++ 4.5:               AL200\B45
    IBM CSET 2.0                   AL200\I20
    IBM Visual Age 3.0             AL200\I30
    Microsoft C++ 7.0:             AL200\C70
    Symantec C++ 7.x:              AL200\S7X
    Delphi 1.0                     AL200\DELPHI.16
    Visual Basic 3.0:              AL200\VB30
    Visual Basic 4.0 16 bit:       AL200\VB40.16
    Visual Basic 4.0 32 bit:       AL200\VB40.32
    Visual C++ 1.0/1.5:            AL200\V1X
    Visual C++ 2.x:                AL200\V2X
    Visual C++ 4.0:                AL200\V40
    Watcom 10.0:                   AL200\W10

New memory classes
------------------

We now have three memory based storage classes derived from the base
class ALMemoryBase. ALMemory uses standard calls to malloc(), calloc()
and realloc().  ALWinMemory() instead uses GlobalAlloc() and its ilk.
Finally, ALHugeMemroy use _farcalloc(), _halloc, and brethren.

BUILD.EXE updated
-----------------

With CommLib 5.1 we modified our BUILD.EXE program slightly.  Each library
directory now has its own naming scheme for BUILD.EXE and BUILD.INI.  For
example, in the Borland C++ 4.5 directory, these two files are now named
BUILDB45.EXE and BUILDB45.INI.

This change was made to help with future patches.  The patch program we
are using, RTPATCH, isn't happy when we have multiple copies of a file
with the same name.

With the initial release of ArchiveLib, we included a set of files with
the name MAKE*.BAT.  These files were used to build demo programs.  This
capability has been moved to BUILD*.EXE, so the batch files are now
gone.  BUILD*.EXE will now let you build a demo or example using the
library file of your choice.  To build demos, call BUILD*.EXE with the
-exe switch.  For example, to build all C examples with the Borland C++
4.0 Large Windows library, I would type this:

    BUILDB40 -exe LW ..\examples\ex??win.c


Debug libraries aren't being shipped
------------------------------------

Debug libraries take up a ton of disk space.  You usually can't use our
prebuilt versions of the debug libraries anyway, because your source
code path differs from ours.  Until we go to CD-ROM distribution, we
will just ship the release libraries.  However, you can quickly build
your own versions of the debug libraries using BUILD.EXE.


ALArchive::AddWildCardFiles() is gone!
--------------------------------------

Now this function is ALEntryList::AddWildCardFiles().  It's first
arg used to be an entry list, now its an archive.  When adding files
to the entry list, this function uses the default storage object and
compression engine recommended by the archive class.


Converting your 1.0 Programs
----------------------------

You should follow these steps to convert an ArchiveLib 1.0 program to
work with ArchiveLib 2.0:

1) If any of your modules include ARCHIVE.H, change the reference to
   GLARC.H. ARCHIVE.H no longer exists.  GLARC.H describes ALGlArchive,
   which is the archive compatible with Version 1.0 archives.

2) Replace every declaration of ALArchive with a declaration for
   ALGlArchive. ALArchive is now the base class for both Greenleaf and
   Zip compatible archives.  Replace any references to ALArchiveBase to
   ALArchive.

3) The compression engine used to insert new compressed objects into
   archives is determined by the toolkit (new term) passed to your
   ALEntryList object on construction.  The default toolkit is the
   FullToolKit(), which will preferentially use the ZIP compressor.  If
   you need your archives to be compatible with AL 1.0 archives, you
   need to force your compression routines to use the Greenleaf
   compressor.  You can do this by modifying your ALEntryList
   constructor call to look like this:

      ALEntryList list( &monitor, GlTools() );

   Be sure to note that you might have created an entry list with no
   parameter to specify a monitor.  In this case, you need to pass a 0
   as the monitor argument.

   If you are explicitly using the greenleaf engine, change every
   reference to GRENENGN.H to GLENGN.H.

   C programmers have a new batch of constructors for ALEntryList, with
   each variation corresponding to a particular toolkit.  See the manual
   to figure out which one you need to be using.

4) AddWildCardFiles is a member function of the archive class in AL 1.0.
   In AL 2.0, this function is now a member function of the entry list
   class. Since the 1.0 function declaration was a static member of
   ALArchive, and took an ALEntryList as its first parameter, you can
   make the change using a fairly mechanical procedure.  Just eliminate
   any reference to the archive object used to call the function, then
   remove the list reference from the first parameter position.  Then
   take that same list reference, and set it to be the object used to
   call the function.

   For example:

   AL 1.0 call: archive.AddWildCardFiles( list, "input*.dat, *.bak" );

   Converted to 2.0: list.AddWildCardFiles( "input*.dat, *.bak" );

   Or:

   AL 1.0 call: ALArchive::AddWildCardFiles( list, "input*.dat, *.bak" );

   Converted to 2.0: list.AddWildCardFiles( "input*.dat, *.bak" );

   MakeEntriesFromListBox() has to undergo exactly the same
   transformation.

5) Under 1.0, the AddWildCardFiles() function also had some optional
   parameters that allow you to specify parameters used when creating
   the greenleaf compression engine.  In 2.0, the decision as to what
   parameters are used to create the engine is now under the control of
   the toolkit passed to the ALEntryList object when constructed.

   To create a toolkit that will use the parameters you want, you will
   need to make one more modification to the toolkit parameter passed to
   the entry constructor.  Just pass the desired compression level to
   the GlTools() function. A sample is shown here:

      ALEntryList list( &monitor, GlTools( AL_GREENLEAF_LEVEL_3 ) );

   After you have done that, just delete the compression level parameter
   from the call to AddWildCardFiles.

6) AL 1.0 has compression engines with the base class ALEngine.  AL 2.0
   has split these two up in the interests of modularity.  If you are
   constructing engines to perform compression or expansion by hand, you
   now have to decide which to use.  The new engine names are:

   ALCopyCompressor               COPYENGN.H
   ALCopyDecompressor             COPYENGN.H
   ALGlCompressor                 GLENGN.H
   ALGLDecompressor               GLENGN.H
   ALPkCompressor                 PKENGN.H
   ALPkDecompressor               PKENGN.H

   Be sure to included the appropriate header file when constructing the
   engine.

   This change means you will need to search through your code, looking
   for the type ALCompressionEngine, and change it to ALCompressor or
   ALDecompressor.  References to ALGreenleafEngine need to be changed
   to ALGlCompressor or ALGlDecompressor.  References to ALCopyEngine
   need to be changed to ALCopyCompressor or ALCopyDecompressor.

7) If you are creating ALEntry objects manually, you will have to
   account for a change in the parameters list.  In AL 1.0, ALEntry
   objects took a single ALCompressionEngine parameter.  AL 2.0 ALEntry
   lists take two pointers: the first a pointer to an ALCompressor, the
   second a pointer to an ALDecompressor.  Code that used to look like
   this:

   new ALEntry( list,
                new ALMemory( "buffer", buffer, strlen( buffer ) ),
                new ALGreenleafEngine );

   Now looks like this:

   new ALEntry( list,
                new ALMemory( "buffer", buffer, strlen( buffer )),
                new ALGlCompressor,
                new ALGlDecompressor );

8) If you are using compressed objects, you now have to pass the
   compressed object constructor, ALCompressedObject(), a pointer to a
   compressor, and a pointer to a decompressor.  The objects are now
   passed as pointers instead of references, as well.  This means you
   can pass a 0 for either of the engines, if your program won't be
   using it.

9) ALEntry objects used to have a single pointer to an engine, called
   mpCompressionEngine. Now there are two pointers, mpCompressor and
   mpDecompressor.

10) You can no longer get a copy of the MS-DOS file attributes using the
    member function GetDosAttributes().  Individual file attributes can
    now be read using these member functions:

        int ReadOnly();
        int System();
        int Hidden();
        int Archive();
        int Directory();

   If you want to get all the bits at once, you need to call member
   function PackedAttributes().

