//
// FILEATTR.CPP
//
//  Source file for ArchiveLib 1.0
//
//  Copyright (c) Greenleaf Software, Inc. 1994
//  All Rights Reserved
//
// CONTENTS
//
//  ALFileAttributes::operator new()
//  ALFileAttributes::ALFileAttributes()
//  ALFileAttributes::~ALFileAttributes()
//  ALFileAttributes::SetFromPackedAttributes()
//  ALFileAttributes::SetFromWin32Attributes()
//  ALFileAttributes::SetFromDosAttributes()
//  ALFileAttributes::PackedAttributes()
//  ALFileAttributes::GetDosAttributes()
//
// DESCRIPTION
//
//  This file contains all of the source to support the ALFileAttributes
//  class.  Even though this is in theory a standalone, independent class,
//  it really has not life of its own.  It always exists as a data
//  member embedded in ALStorage.  The only reason these functions aren't
//  member functions of ALStorage was simply to modularize things a bit.
//  As it is, it makes pretty good sense as a class of its own.
//
// REVISION HISTORY
//
//  May 25, 1994  1.0A  : First release
//

#include "arclib.h"
#pragma hdrstop

#include <dos.h>

#include "fileattr.h"

//
// void * ALFileAttributes::operator new( size_t size )
//
// ARGUMENTS:
//
//  size  :  The amount of storage that needs to be allocated for
//           this object.
//
// RETURNS
//
//  A pointer to the storage.
//
// DESCRIPTION
//
//  When using the DLL version of ArchiveLib, it is a good idea to
//  allocate the storage for objects from inside the DLL, since they
//  will be freed inside the DLL.  If we don't have the new operator
//  for a class, its storage will be allocated from the EXE before
//  the constructor code is called.  Then, when it is time to free
//  the storage, the delete operator will be called inside the DLL.
//  Not good, right?
//
//  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 25, 1994  1.0A  : First release
//

#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALFileAttributes::operator new( size_t size )
{
    return ::new char[ size ];
}
#endif

//
// ALFileAttributes::ALFileAttributes()
//
// ARGUMENTS:
//
//  None.
//
// RETURNS
//
//  Constructor, no return.
//
// DESCRIPTION
//
//  This is the only constructor for class ALFileAttributes.  It does
//  nothing more than set all of the bits to 0.  I was thinking that
//  it might be a good idea to set them to -1 instead, indicating that
//  they are presently in an unknown state.  I would want to set them
//  to 0 when I called Create(), and read them in when I call Open().
//  Just thinking out loud.
//
// REVISION HISTORY
//
//   May 25, 1994  1.0A  : First release
//

AL_PROTO ALFileAttributes::ALFileAttributes()
{
    miReadOnly = 0;
    miSystem = 0;
    miHidden = 0;
    miArchive = 0;
}

//
// ALFileAttributes::~ALFileAttributes()
//
// ARGUMENTS:
//
//  None.
//
// RETURNS
//
//  Destructor, no returns.
//
// DESCRIPTION
//
//  The destructor doesn't have to worry about freeing any dynamic
//  storage or anything like that, so it gets to do a great big nothing.
//
// REVISION HISTORY
//
//   May 25, 1994  1.0A  : First release
//

AL_PROTO ALFileAttributes::~ALFileAttributes()
{
}

//
// void ALFileAttributes::SetFromPackedAttributes( short int attributes )
//
// ARGUMENTS:
//
//  attributes  : A set of attributes that have been packed into a
//                short int using our internal bit ordering:
//
//                  X | X | X | X | A | H | S | R
//
// RETURNS
//
//  Nothing, a void function.
//
// DESCRIPTION
//
//  The packed format is how we actually store file attributes in an
//  archive.  When we read in the directory from an archive, we can
//  use this function to apply the packed attribute bits to a storage
//  object.  All it has to do is set the four bits internal to the
//  class.
//
// REVISION HISTORY
//
//   May 25, 1994  1.0A  : First release
//

void AL_PROTO ALFileAttributes::
SetFromPackedAttributes( short int attributes )
{
    miReadOnly = ( attributes & 1 ) != 0;
    miSystem = ( attributes & 2 ) != 0;
    miHidden = ( attributes & 4 ) != 0;
    miArchive = ( attributes & 8 ) != 0;
}

//
// void ALFileAttributes::SetFromWin32Attributes( DWORD win32_attributes )
//
// ARGUMENTS:
//
//  attributes  : The set of file attributes as defined for Win32s.
//                These are the attributes you get back from the
//                GetFileAttributes() function call.
//
// RETURNS
//
//  Nothing, a void function.
//
// DESCRIPTION
//
//  When the ALFile class opens a file under Win32s, it reads in
//  the file attributes with a call to GetFileAttributes.  It can then store
//  those file attributes in the ALFileAttributes member of ALStorage
//  by calling this function.
//
//  Converting the data to our internal format is simply a matter of picking
//  bits out of a DWORD.
//
// REVISION HISTORY
//
//   May 25, 1994  1.0A  : First release
//

#if defined( AL_WIN32S )

void AL_PROTO ALFileAttributes::
SetFromWin32Attributes( DWORD win32_attributes )
{
    miReadOnly = ( win32_attributes & FILE_ATTRIBUTE_READONLY ) != 0;
    miSystem = ( win32_attributes & FILE_ATTRIBUTE_SYSTEM ) != 0;
    miHidden = ( win32_attributes & FILE_ATTRIBUTE_HIDDEN ) != 0;
    miArchive = ( win32_attributes & FILE_ATTRIBUTE_ARCHIVE ) != 0;
}

#endif

//
// void ALFileAttributes::SetFromDosAttributes( unsigned dos_attributes )
//
// ARGUMENTS:
//
//  attributes  : The set of file attributes as defined for MS-DOS.
//                These are the attributes you get back from the
//                _dos_getfileattr() function call.
//
// RETURNS
//
//  Nothing, a void function.
//
// DESCRIPTION
//
//  When the ALFile class opens a file under MS-DOS or Windows, it reads in
//  the file attributes with a call to _dos_getfileattr().  It can then store
//  those file attributes in the ALFileAttributes member of ALStorage
//  by calling this function.
//
//  Converting the data to our internal format is simply a matter of picking
//  bits out of an unsigned int
//
// REVISION HISTORY
//
//   May 25, 1994  1.0A  : First release
//

#if !defined( AL_WIN32S )

void AL_PROTO ALFileAttributes::SetFromDosAttributes( unsigned dos_attributes )
{
    miReadOnly = ( dos_attributes & _A_RDONLY ) != 0;
    miSystem = ( dos_attributes & _A_SYSTEM ) != 0;
    miHidden = ( dos_attributes & _A_HIDDEN ) != 0;
    miArchive = ( dos_attributes & _A_ARCH ) != 0;
}
#endif

//
// unsigned short int ALFileAttributes::PackedAttributes()
//
// ARGUMENTS:
//
//  None.
//
// RETURNS
//
//  An unsigned short int containing the four file attribute bits, packed
//  into the format we use to store file attributes in an archive:
//
//
//                  X | X | X | X | A | H | S | R
//
// DESCRIPTION
//
//  When it comes time to write an archive directory out to disk, we need
//  to store the file attributes in a consistent format.  This format
//  is our internal packed attribute format.  You can get the file attributes
//  in this packed attribute format with a call to this function.
//
// REVISION HISTORY
//
//   May 25, 1994  1.0A  : First release
//

unsigned short int AL_PROTO ALFileAttributes::PackedAttributes()
{
    int result = 0;

    result |= miReadOnly ? 1 : 0;
    result |= miSystem ? 2 : 0;
    result |= miHidden ? 4 : 0;
    result |= miArchive ? 8 : 0;
    return (unsigned short int ) result;
}

//
// unsigned short int ALFileAttributes::GetDosAttributes()
//
// ARGUMENTS:
//
//  None.
//
// RETURNS
//
//  The set of file attributes, packed into the order that MS-DOS
//  expects them for the _dos_setfileattr() function call.
//
// DESCRIPTION
//
//  When we are closing a file that we have to set the time stamp and
//  attributes for, this function is used to get the attributes.
//  Under MS-DOS at least.  All it needs to do is repack some bits
//  into the order that MS-DOS expects.
//
// REVISION HISTORY
//
//   May 26, 1994  1.0A  : First release
//

#if !defined( AL_WIN32S )

unsigned short int AL_PROTO ALFileAttributes::GetDosAttributes()
{
    int result = 0;
    result |= miReadOnly ? _A_RDONLY : 0;
    result |= miSystem ? _A_SYSTEM : 0;
    result |= miHidden ? _A_HIDDEN : 0;
    result |= miArchive ? _A_ARCH : 0;
    return (unsigned short int) result;
}
#endif //#if !defined( AL_WIN32S )

//
// DWORD ALFileAttributes::GetWin32Attributes()
//
// ARGUMENTS:
//
//  None.
//
// RETURNS
//
//  The set of file attributes, packed into the order that Win32s
//  expects them for the SetFileAttributes() function call.
//
// DESCRIPTION
//
//  When we are closing a file that we have to set the time stamp and
//  attributes for, this function is used to get the attributes.
//  Under Win32s at least.  All it needs to do is repack some bits
//  into the order that Win32s expects.
//
// REVISION HISTORY
//
//   May 26, 1994  1.0A  : First release
//

#if defined( AL_WIN32S )

DWORD AL_PROTO ALFileAttributes::GetWin32Attributes()
{
    DWORD result = 0;
    result |= miReadOnly ? FILE_ATTRIBUTE_READONLY : 0;
    result |= miSystem ? FILE_ATTRIBUTE_SYSTEM : 0;
    result |= miHidden ? FILE_ATTRIBUTE_HIDDEN : 0;
    result |= miArchive ? FILE_ATTRIBUTE_ARCHIVE : 0;
    return result;
}
#endif //#if !defined( AL_WIN32S )