#ifndef _AMIGAOS_HPP
#define _AMIGAOS_HPP 1
/*
**
** AmigaOS.hpp
**
** (c) 1998 Didier Levet
**
** AmigaOS class
**
** $Revision: 1.1 $
** $State: Exp $
** $Date: 1998/10/05 19:55:18 $
**
** $Log: AmigaOS.hpp $
** Revision 1.1  1998/10/05 19:55:18  kakace
** AmigaOS stubs (namespace emulation)
**
**
*/


//----------------------------------------------------------------------------------------------------
//============================================= INCLUDES =============================================
//----------------------------------------------------------------------------------------------------

/// Includes

#ifndef  _INCLUDE_STRING_H
#include <string.h>
#endif

#ifndef  CLIB_EXEC_PROTOS_H
#include <clib/exec_protos.h>
#endif

#ifndef  CLIB_DOS_PROTOS_H
#include <clib/dos_protos.h>
#endif

#ifndef  CLIB_INTUITION_PROTOS_H
#include <clib/intuition_protos.h>
#endif

#ifndef  CLIB_ICON_PROTOS_H
#include <clib/icon_protos.h>
#endif

#ifndef  CLIB_LOCALE_PROTOS_H
#include <clib/locale_protos.h>
#endif

#ifndef  CLIB_ASL_PROTOS_H
#include <clib/asl_protos.h>
#endif

#ifndef  _STRING_CLASS_HPP
#include "StringClass.hpp"
#endif

///


// These classes are used to emulate the "namespace" system for AmigaOS functions.
// Most functions are inlined, and some of them may contains bug fixes.


extern "ASM"
{
    void PutCharProc();
};


//----------------------------------------------------------------------------------------------------
//========================================== class ExecLib ===========================================
//----------------------------------------------------------------------------------------------------

struct ExecLib
{
    static STRING       RawDoFmt(STRING patternString, void *dataStream);

    static const Task * FindTask(STRING name = NULL)
                        {
                            return ::FindTask((UBYTE *) name);
                        }

    static BYTE         SetTaskPri(BYTE priority = 0)
                        {
                            return ::SetTaskPri( (Task *) ::FindTask(NULL), priority);
                        }

    //===== Private area =============================================================================

    private:

    static void         PutCharProc(register __d0 char c);

    static char fmt_buffer[350];        // Buffer for all "RawDoFmt" calls.
    static char *fmt_ptr;
};


//----------------------------------------------------------------------------------------------------
//=========================================== class DOSLib ===========================================
//----------------------------------------------------------------------------------------------------

struct DOSLib
{
    static int          GetProgramName(CString& progName);
    static int          NameFromLock(BPTR lock, CString& buffer);
    static int          NameFromFH(BPTR fileHandle, CString& buffer);
    static int          AddPart(CString& dirName, STRING fileName);
    static int          MatchPatternNoCase(const CString& pattern, STRING str);

    static LONG         IoErr()                     {return ::IoErr();}
    static LONG         SetIoErr(LONG errCode)      {return ::SetIoErr(errCode);}
    static BPTR         Output()                    {return ::Output();}
    static BPTR         GetProgramDir()             {return ::GetProgramDir();}
    static BPTR         CurrentDir(BPTR lock)       {return ::CurrentDir(lock);}

    // The following functions make use of CString objects so that modifying the returned
    // string can't change the original string.

    static CString      FilePart(STRING path)       {return ::FilePart( (STRPTR) path);}
    static CString      PathPart(STRING path)
                        {
                            CString s = path;
                            if (s != CString::EMPTY)
                            {
                                s[::PathPart(s) - s.string()] = '\0';
                            }
                            return s;
                        }

    static int          PrintFault(ULONG error, STRING header)          // V36
                        {
                            return ::PrintFault(error, (STRPTR) header);
                        }

    //===== Private area =============================================================================

    private:

    static LONG         GetProgramName(BPTR dummy, STRPTR name, LONG len)
                                                    {return :: GetProgramName(name, len);}

    static int          AutoExtend(BPTR handle, CString &buffer, ULONG step, LONG (*func)(BPTR, STRPTR, LONG));
};


//----------------------------------------------------------------------------------------------------
//======================================== class IntuitionLib ========================================
//----------------------------------------------------------------------------------------------------

struct IntuitionLib
{
    static LONG         EasyRequestArgs(Window *window, EasyStruct *easyStruct, ULONG *idcmpPtr, APTR args)
                        {
                            return ::EasyRequestArgs(window, easyStruct, idcmpPtr, args);
                        }
};


//----------------------------------------------------------------------------------------------------
//========================================= Special objects ==========================================
//----------------------------------------------------------------------------------------------------
//
// These classes are used to allocate/use/free AmigaOS related stuff in a manner that is compatible
// with exceptions. Once an object is passed to an instance of these classes (or when it is allocated
// by one of these instances), it becomes part of the instance. This means that this object will die
// when the instance will be deleted.
//----------------------------------------------------------------------------------------------------


//----------------------------------------------------------------------------------------------------
//=========================================== class CFile ============================================
//----------------------------------------------------------------------------------------------------

class CFile
{
    public:

        enum EMode{READWRITE = 1004, OLDFILE, NEWFILE};

        CFile() : fh(0)     {}
        ~CFile()            {if (fh != 0) ::Close(fh);}

        BPTR Open(STRING name, EMode accessMode)
        {
            return (fh = ::Open( (STRPTR) name, accessMode));
        }

        LONG Read(void *buffer, LONG length)
        {
            return ::Read(fh, buffer, length);
        }

        operator BPTR() const       {return fh;}

    protected:

        CFile(const CFile &);                   // Not implemented.
        CFile& operator =(const CFile &);       // Ditto.

        BPTR    fh;
};


//----------------------------------------------------------------------------------------------------
//=========================================== class CMatch ===========================================
//----------------------------------------------------------------------------------------------------

class CMatch
{
    public:

        // Constructor. An AnchorPath structure may be passed to it and is adopted
        // by the object (the destructor will destroy it later).
        CMatch(AnchorPath *anchor = NULL) : pAnchor(anchor), CloseMe(FALSE) {}

        ~CMatch()
        {
            if (CloseMe != FALSE) ::MatchEnd(pAnchor);
            delete pAnchor;                     // Delete the AnchorPath structure.
        }

        // Matching initialization. If an AnchorPath structure is given, it is adopted
        // and it will be destroyed by the instance's destructor.
        LONG First(STRING pattern, AnchorPath *anchor = NULL);

        LONG Next()
        {
            return ::MatchNext(pAnchor);
        }

        // Accessor. A CMatch object can be used as an AnchorPath pointer.
        operator AnchorPath *() const   {return pAnchor;}

    protected:

        CMatch(const CMatch &);                 // Not implemented.
        CMatch& operator =(const CMatch &);     // Ditto.

        AnchorPath *pAnchor;
        int         CloseMe;                    // TRUE if First() has been run.
};


//----------------------------------------------------------------------------------------------------
//========================================= class CDOSObject =========================================
//----------------------------------------------------------------------------------------------------

class CDOSObject
{
    public:

        enum ETypes{FILEHANDLE, EXALLCONTROL, FIB, STDPKT, CLI, RDARGS};

        CDOSObject() : pAddr(NULL)          {}
        ~CDOSObject()                       {if (pAddr != NULL) ::FreeDosObject(iType, pAddr);}

        void *Allocate(ETypes type, TagItem *tags = NULL)
        {
            iType = type;
            return (pAddr = ::AllocDosObject(type, tags));
        }

        void *Allocate(ETypes type, Tag tag1, ...) {return Allocate(type, (TagItem *) &tag1);}

    protected:

        CDOSObject(const CDOSObject &);             // Not implemented.
        CDOSObject& operator =(const CDOSObject &); // Ditto.

        ETypes  iType;
        void   *pAddr;
};


//----------------------------------------------------------------------------------------------------
//========================================== class CRDArgs ===========================================
//----------------------------------------------------------------------------------------------------

class CRDArgs
{
    public:

        CRDArgs() : pArgs(NULL)     {}
        ~CRDArgs()                  {if (pArgs != NULL) ::FreeArgs(pArgs);}

        RDArgs *ReadArgs(STRING argTemplate, LONG *array, RDArgs *args = NULL)
        {
            return (pArgs = ::ReadArgs((STRPTR) argTemplate, array, args));
        }

    protected:

        CRDArgs(const CRDArgs &);                   // Not implemented.
        CRDArgs& operator =(const CRDArgs &);       // Ditto.

        RDArgs *pArgs;
};


//----------------------------------------------------------------------------------------------------
//=========================================== class CLock ============================================
//----------------------------------------------------------------------------------------------------

class CLock
{
    public:

        enum ETypes{WRITE = -1, EXCLUSIVE = -1, READ = -2, SHARED = -2};

        CLock() : lock(0)               {}
        ~CLock()                        {if (lock != 0) ::UnLock(lock);}

        CLock(const CLock& l)           {lock = ::DupLock(l.lock);}
        CLock& operator =(const CLock& l)
        {
            if (&l != this)
                lock = ::DupLock(l.lock);
            return *this;
        }

        operator BPTR() const   {return lock;}

        BPTR Lock(STRING name, ETypes type)
        {
            return (lock = ::Lock((STRPTR) name, type));
        }

        int  NameFromLock(CString& buffer) // V36
        {
            return DOSLib::NameFromLock(lock, buffer);
        }

    protected:

        BPTR lock;
};


//----------------------------------------------------------------------------------------------------
//======================================== class CDiskObject =========================================
//----------------------------------------------------------------------------------------------------

class CDiskObject
{
    public:

        CDiskObject() : dobj(NULL)      {}
        ~CDiskObject()                  {release();}

        DiskObject *Load(STRING name = NULL);

        STRING FindToolType(STRING typeName)
        {
            return (STRING) ::FindToolType( (UBYTE **) dobj->do_ToolTypes, (UBYTE *) typeName);
         // return (STRING) ::FindToolType( (STRPTR *) dobj->do_ToolTypes, (UBYTE *) typeName);
        }

    protected:

        CDiskObject(const CDiskObject &);               // Not implemented.
        CDiskObject& operator =(const CDiskObject &);   // Ditto.

        DiskObject *dobj;

        void release()                  {if (dobj != NULL) ::FreeDiskObject(dobj);}
};


//----------------------------------------------------------------------------------------------------
//======================================== class CFileRequest ========================================
//----------------------------------------------------------------------------------------------------

class CFileRequest
{
    public:

        CFileRequest() : fr(NULL)       {}
        ~CFileRequest()                 {if (fr != NULL) ::FreeAslRequest(fr);}

        FileRequester *Init(TagItem *tagList = NULL)
        {
            return (fr = (FileRequester *) ::AllocAslRequest(ASL_FileRequest, tagList));
        }

        FileRequester *Request(Tag tag1, ...)
        {
            return Request((TagItem *) &tag1);
        }

        FileRequester *Request(TagItem *tagList)
        {
            return (fr != NULL && ::AslRequest(fr, tagList) ? fr : NULL);
        }

    protected:

        CFileRequest(const CFileRequest &);             // Not implemented.
        CFileRequest& operator =(const CFileRequest &); // Ditto.

        FileRequester *fr;
};


//----------------------------------------------------------------------------------------------------

#endif  // !_AMIGAOS_HPP

