/*
**
** AmigaOS.cpp
**
** (c) 1998 Didier Levet
**
** Fonctions AmigaOS
**
** $Revision: 1.1 $
** $State: Exp $
** $Date: 1998/11/14 18:23:45 $
**
** $Log: AmigaOS.cpp $
** Revision 1.1  1998/11/14 18:23:45  kakace
** Initial revision
**
**
*/

#ifndef  _AMIGAOS_HPP
#include "AmigaOS.hpp"
#endif


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

//==================================================================================================
//
//   SYNOPSIS                                                                      ExecLib::RawDoFmt
//   string = ExecLib::RawDoFmt(patternString, dataStream)
//   STRING ExecLib::RawDoFmt(STRING, void *);
//
//   FUNCTION
//      Output several strings using a format string in a buffer, then returns the resulting string.
//
//   INPUTS
//   patternString - Pattern string.
//   dataStream    - Pointer to the arguments.
//
//   RESULT
//   string - Resulting string.
//
//   NOTES
//      This function check the buffer size before outputing any character. Thus, the resulting
//      string might be shorter than the one expected.
//
//   SEE ALSO
//
//   HISTORY
//
//==================================================================================================
/// ExecLib::RawDoFmt()

char  ExecLib::fmt_buffer[350];
char *ExecLib::fmt_ptr;

STRING ExecLib::RawDoFmt(STRING patternString, void *dataStream)
{
    fmt_buffer[sizeof(fmt_buffer) - 1] = '\0';      // Initialize the last character.
    fmt_ptr = fmt_buffer;                           // Initialize the output pointer.

    ::RawDoFmt((UBYTE *) patternString, dataStream, (void (*)()) PutCharProc, NULL);

    return fmt_buffer;
}


// ExecLib::PutCharProc()  [private]

void ExecLib::PutCharProc(register __d0 char ch)
{
    if (fmt_ptr - fmt_buffer < sizeof(fmt_buffer) - 1)
    {
        *fmt_ptr++ = ch;
    }
}
///


//----------------------------------------------------------------------------------------------------
//============================================== DOSLib ==============================================
//----------------------------------------------------------------------------------------------------
//
//  Most of the following functions take advantage of the extension feature of the CString objects.
//  Thus, we don't have to care about buffers size.

/// DOSLib::AddPart()
//----------------------------------------------------------------------------------------------------
//
//  Add a file name to the path given. This function is able to enlarge the path name buffer when
//  necessary.
//  Returns FALSE if ::AddPart() fails and if the buffer can't be enlarged (memory error).

int  DOSLib::AddPart(CString &dirName, STRING fileName)
{
    ULONG buff_size = dirName.extend(256);
    int   result = buff_size;                   // == FALSE if buff_size == 0

    if (fileName != NULL && buff_size > 0)
    {
        while ( (result = ::AddPart(dirName, (STRPTR) fileName, buff_size)) == FALSE)
        {
            buff_size += 256;
            if (dirName.extend(buff_size) < buff_size)
            {
                ::SetIoErr(ERROR_NO_FREE_STORE);
                break;
            }
        }
    }

    dirName.update();                           // Update the string's size.
    return result;
}
///
/// DOSLib::GetProgramName()
//----------------------------------------------------------------------------------------------------
int  DOSLib::GetProgramName(CString& progName)
{
    return AutoExtend(0, progName, 32, &DOSLib::GetProgramName);
}
///
/// DOSLib::NameFromLock()
//----------------------------------------------------------------------------------------------------
int  DOSLib::NameFromLock(BPTR lock, CString &buffer)
{
    return AutoExtend(lock, buffer, 256, &::NameFromLock);
}
///
/// DOSLib::NameFromFH()
//----------------------------------------------------------------------------------------------------
int  DOSLib::NameFromFH(BPTR fh, CString &buffer)
{
    return AutoExtend(fh, buffer, 256, &::NameFromFH);
}
///
/// DOSLib::MatchPatternNoCase()
//----------------------------------------------------------------------------------------------------

int  DOSLib::MatchPatternNoCase(const CString& pattern, STRING str)
{
    CString buffer(NULL, pattern.length() * 2 + 2);
    int  result = FALSE;

    if (buffer != CString::UNUSED && ::ParsePatternNoCase(pattern, buffer, buffer.buffsize()) >= 0)
    {
        result = ::MatchPatternNoCase(buffer, (STRPTR) str);
    }

    return result;
}
///

/// DOSLib::AutoExtend()            [PRIVATE]
//----------------------------------------------------------------------------------------------------
//
//  This function is used to call a DOS function that put some datas into a buffer. The buffer is
//  automatically enlarged when necessary.
//  Only returns TRUE when the datas have been copied successfully.

int  DOSLib::AutoExtend(BPTR handle, CString &buffer, ULONG step, LONG (*func)(BPTR, STRPTR, LONG))
{
    ULONG buff_size = buffer.extend(step);
    int  result = FALSE;

    if (buff_size > 0)
    {
        while ( (result = func(handle, buffer, buff_size)) != FALSE
               && DOSLib::IoErr() == ERROR_LINE_TOO_LONG)
        {
            buff_size += step;
            if (buffer.extend(buff_size) < buff_size)
            {
                ::SetIoErr(ERROR_NO_FREE_STORE);
                result = FALSE;
                break;
            }
        }
    }

    buffer.update();                            // Update the string's size.
    return result;
}
///

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

/// CMatch::First()
LONG CMatch::First(STRING pattern, AnchorPath *anchor)
{
    LONG result = ERROR_NO_FREE_STORE;

    if (anchor == NULL)
    {
        anchor = new AnchorPath;
    }

    if (anchor != NULL)
    {
        result = ::MatchFirst( (STRPTR) pattern, anchor);
        pAnchor = anchor;
        CloseMe = TRUE;
    }

    return result;
}
///


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

/// CDiskObject::Load()
DiskObject *CDiskObject::Load(STRING name)
{
    CString name_buffer;
    BPTR old_dir_lock;

    STRING prog_name = name;

    // As ToolTypes may be parsed when we start from either CLI or Workbench, we must handle all
    // cases. Thus, we set the current directory to the one where the icon should be, then we
    // get the program name which will be used as the icon's base name.

    old_dir_lock = DOSLib::CurrentDir(DOSLib::GetProgramDir());

    if (prog_name == NULL)
    {
        if (DOSLib::GetProgramName(name_buffer) != FALSE)
        {
            prog_name = name_buffer;
        }
    }

    if (prog_name != NULL)
    {
        release();                      // Releases the current DiskObject, if any.
        dobj = ::GetDiskObject( (UBYTE *) prog_name);
    }

    DOSLib::CurrentDir(old_dir_lock);
    return dobj;
}
///

