
//***************************************************
// Generalised Bitmap Module C++ adapter for GBM plugins
//
// Requires: GBM.DLL version 1.35 or higher (with multipage support)
//
// Copyright (C) 2006-2008 Heiko Nitzsche
//
//   This software is provided 'as-is', without any express or implied
//   warranty.  In no event will the author be held liable for any damages
//   arising from the use of this software.
//
//   Permission is granted to anyone to use this software for any purpose,
//   including commercial applications, and to alter it and redistribute it
//   freely, subject to the following restrictions:
//
//   1. The origin of this software must not be misrepresented; you must not
//      claim that you wrote the original software. If you use this software
//      in a product, an acknowledgment in the product documentation would be
//      appreciated but is not required.
//   2. Altered source versions must be plainly marked as such, and must not be
//      misrepresented as being the original software.
//   3. This notice may not be removed or altered from any source distribution.
//
//***************************************************

#ifdef __IBMCPP__
  #pragma strings( readonly )
#endif

#include "os2defs.h"
#include <string.h>
#include "GbmAccessor.hpp"

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

GbmAccessor::GbmAccessor() throw (GbmAccessorException)
    : moduleName(NULL),
      moduleHandle(NULLHANDLE)
{
    // load GBM.DLL via LIBPATH lookup

    if (! init("GBM"))
    {
        throw GbmAccessorException();
    }
}

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

GbmAccessor::GbmAccessor(const char * dllPath) throw (GbmAccessorException)
    : moduleName(NULL),
      moduleHandle(NULLHANDLE)
{
    // load GBM.DLL via absolute path
    if (! init(dllPath))
    {
        throw GbmAccessorException();
    }
}

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

GbmAccessor::~GbmAccessor()
{
    delete [] moduleName;
    moduleName = NULL;

    if (moduleHandle != NULLHANDLE)
    {
        fn_Gbm_deinit();
        DosFreeModule(moduleHandle);
        moduleHandle = NULLHANDLE;
    }
}

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

const char * GbmAccessor::getModuleName() const
{
    return moduleName;
}

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

BOOLEAN GbmAccessor::init(const char * dllPath)
{
    if (dllPath == NULL)
    {
        return FALSE;
    }

    // load GBM.DLL
    UCHAR  loadError[201] = "";
    APIRET rc             = 0;

    /* load the module */
    rc = DosLoadModule((PSZ)loadError,
                       sizeof(loadError)-1,
                       (PSZ)dllPath,
                       &moduleHandle);
    if (rc == 0)
    {
        const int moduleNameLength = strlen(dllPath);
        moduleName = new char[moduleNameLength+1];
        strcpy(moduleName, dllPath);

        // as _System exported functions
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_version", (PFN *) &fn_Gbm_version);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_init"   , (PFN *) &fn_Gbm_init);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_deinit" , (PFN *) &fn_Gbm_deinit);

        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_io_open"  , (PFN *) &fn_Gbm_io_open);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_io_create", (PFN *) &fn_Gbm_io_create);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_io_close" , (PFN *) &fn_Gbm_io_close);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_io_lseek" , (PFN *) &fn_Gbm_io_lseek);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_io_read"  , (PFN *) &fn_Gbm_io_read);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_io_write" , (PFN *) &fn_Gbm_io_write);

        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_query_n_filetypes", (PFN *) &fn_Gbm_query_n_filetypes);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_guess_filetype"   , (PFN *) &fn_Gbm_guess_filetype);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_query_filetype"   , (PFN *) &fn_Gbm_query_filetype);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_read_header"      , (PFN *) &fn_Gbm_read_header);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_read_palette"     , (PFN *) &fn_Gbm_read_palette);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_read_data"        , (PFN *) &fn_Gbm_read_data);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_write"            , (PFN *) &fn_Gbm_write);
        rc |= DosQueryProcAddr(moduleHandle, 0L, "Gbm_err"              , (PFN *) &fn_Gbm_err);

        if (rc)
        {
            delete [] moduleName;
            moduleName = NULL;
            DosFreeModule(moduleHandle);
            moduleHandle = NULLHANDLE;
            return FALSE;
        }

        // optional functions that have default operation
        rc = DosQueryProcAddr(moduleHandle, 0L, "gbm_read_imgcount", (PFN *) &fn_Gbm_read_imgcount);
        if (rc)
        {
            fn_Gbm_read_imgcount = NULL;
        }

        fn_Gbm_init();
        return TRUE;
    }
    moduleHandle = NULLHANDLE;
    return FALSE;
}

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

int GbmAccessor::Gbm_version() const
{
    return fn_Gbm_version();
}

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

int GbmAccessor::Gbm_io_open(const char *fn, int mode) const
{
    return fn_Gbm_io_open(fn, mode);
}

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

int GbmAccessor::Gbm_io_create(const char *fn, int mode) const
{
    return fn_Gbm_io_create(fn, mode);
}

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

void GbmAccessor::Gbm_io_close(int fd) const
{
    fn_Gbm_io_close(fd);
}

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

long GbmAccessor::Gbm_io_lseek(int fd, long  pos, int whence) const
{
    return fn_Gbm_io_lseek(fd, pos, whence);
}

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

int GbmAccessor::Gbm_io_read(int fd, void *buf, int len) const
{
    return fn_Gbm_io_read(fd, buf, len);
}

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

int  GbmAccessor::Gbm_io_write(int fd, const void *buf, int len) const
{
    return fn_Gbm_io_write(fd, buf, len);
}

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

GBM_ERR GbmAccessor::Gbm_query_n_filetypes(int *n_ft) const
{
    return fn_Gbm_query_n_filetypes(n_ft);
}

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

GBM_ERR GbmAccessor::Gbm_guess_filetype(const char *fn, int *ft) const
{
    return fn_Gbm_guess_filetype(fn, ft);
}

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

GBM_ERR GbmAccessor::Gbm_query_filetype(int ft, GBMFT *gbmft) const
{
    return fn_Gbm_query_filetype(ft, gbmft);
}

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

GBM_ERR GbmAccessor::Gbm_read_imgcount(const char *fn, int fd, int ft, int *pimgcnt) const
{
    if (fn_Gbm_read_imgcount != NULL)
    {
        return fn_Gbm_read_imgcount(fn, fd, ft, pimgcnt);
    }
    return 1; // simulate old behaviour (GBM versions before 1.35)
}

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

GBM_ERR GbmAccessor::Gbm_read_header(const char *fn, int fd, int ft, GBM *gbm, const char *opt) const
{
    return fn_Gbm_read_header(fn, fd, ft, gbm, opt);
}

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

GBM_ERR GbmAccessor::Gbm_read_palette(int fd, int ft, GBM *gbm, GBMRGB *gbmrgb) const
{
    return fn_Gbm_read_palette(fd, ft, gbm, gbmrgb);
}

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

GBM_ERR GbmAccessor::Gbm_read_data(int fd, int ft, GBM *gbm, byte *data) const
{
    return fn_Gbm_read_data(fd, ft, gbm, data);
}

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

GBM_ERR GbmAccessor::Gbm_write(const char *fn, int fd, int ft, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt) const
{
    return fn_Gbm_write(fn, fd, ft, gbm, gbmrgb, data, opt);
}

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

const char * GbmAccessor::Gbm_err(GBM_ERR rc) const
{
    return fn_Gbm_err(rc);
}


