
/*
 *@@sourcefile xwpimage.c:
 *      This file contains SOM code for the following XWorkplace classes:
 *
 *      --  XWPImageFile (WPImageFile subclass)
 *
 *@@somclass XWPImageFile img_
 *@@somclass M_XWPImageFile imgM_
 *@@added V1.0.1 (2003-01-25) [umoeller]
 */

/*
 *      Copyright (C) 2003 Ulrich M”ller.
 *
 *      This file is part of the XWorkplace source package.
 *      XWorkplace is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published
 *      by the Free Software Foundation, in version 2 as it comes in the
 *      "COPYING" file of the XWorkplace main distribution.
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 */

/*
 *  This file was generated by the SOM Compiler and Emitter Framework.
 *  Generated using:
 *      SOM Emitter emitctm: 2.41
 */

#ifndef SOM_Module_xwpimage_Source
#define SOM_Module_xwpimage_Source
#endif
#define XWPImageFile_Class_Source
#define M_XWPImageFile_Class_Source

#pragma strings(readonly)

/*
 *  Suggested #include order:
 *  1)  os2.h
 *  2)  C library headers
 *  3)  setup.h (code generation and debugging options)
 *  4)  headers in helpers\
 *  5)  at least one SOM implementation header (*.ih)
 *  6)  dlgids.h, headers in shared\ (as needed)
 *  7)  headers in implementation dirs (e.g. filesys\, as needed)
 *  8)  #pragma hdrstop and then more SOM headers which crash with precompiled headers
 */

#define INCL_DOSEXCEPTIONS
#define INCL_DOSPROCESS
#define INCL_DOSERRORS

#define INCL_GPI                // required for INCL_MMIO_CODEC
#define INCL_GPIBITMAPS         // required for INCL_MMIO_CODEC
#include <os2.h>

#define INCL_MCIOS2
#define INCL_MMIOOS2
#define INCL_MMIO_CODEC
#include <os2me.h>

// C library headers
#include <stdio.h>
#include <setjmp.h>             // needed for except.h

// generic headers
#include "setup.h"                      // code generation and debugging options

// headers in /helpers
#include "helpers\dosh.h"               // Control Program helper routines
#include "helpers\except.h"             // exception handling
#include "helpers\gpih.h"               // GPI helper routines
#include "helpers\mmpmh.h"              // MMPM/2 helpers
#include "helpers\stringh.h"            // string helper routines
#include "helpers\tree.h"               // red-black binary trees
#include "helpers\xstring.h"            // extended string helpers

// SOM headers which don't crash with prec. header files
#include "xwpimage.ih"

// XWorkplace implementation headers
#include "shared\common.h"              // the majestic XWorkplace include file
#include "shared\kernel.h"              // XWorkplace Kernel

#include "filesys\object.h"             // XFldObject implementation

#include "media\media.h"                // XWorkplace multimedia support

#pragma hdrstop                         // VAC++ keeps crashing otherwise

/* ******************************************************************
 *
 *   Global variables
 *
 ********************************************************************/

PCSZ            G_pcszImageFileFilter = NULL;

PMMFORMATINFO   G_aFormatInfos = NULL;
LONG            G_cFormatInfos = 0;

TREE            *G_FormatsTreeRoot;

/* ******************************************************************
 *
 *   XWPImageFile instance methods
 *
 ********************************************************************/

/*
 *@@ wpUnInitData:
 *
 */

SOM_Scope void  SOMLINK img_wpUnInitData(XWPImageFile *somSelf)
{
    XWPImageFileData *somThis = XWPImageFileGetData(somSelf);
    XWPImageFileMethodDebug("XWPImageFile","img_wpUnInitData");

    if (_pbMMImageHeader)
    {
        ShlFreeMem(_pbMMImageHeader);
        _pbMMImageHeader = NULL;
    }

    XWPImageFile_parent_WPImageFile_wpUnInitData(somSelf);
}

/*
 *@@ wpQueryType:
 *      this WPFileSystem instance method returns the explicit
 *      types for this object as a const PSZ. Multiple types
 *      are separated with newline (\n) characters.
 *
 *      If no .TYPE EA is given, apparently this method calls
 *      M_WPFileSystem::wpclsQueryInstanceType to return
 *      default types for objects of a given data file class.
 *      WPDataFile returns an empty string there though, so
 *      for the majority of objects, this method returns an
 *      empty string as well.
 */

SOM_Scope PSZ  SOMLINK img_wpQueryType(XWPImageFile *somSelf)
{
    /* XWPImageFileData *somThis = XWPImageFileGetData(somSelf); */
    XWPImageFileMethodDebug("XWPImageFile","img_wpQueryType");

    return XWPImageFile_parent_WPImageFile_wpQueryType(somSelf);
}

/*
 *@@ wpQueryBitmapData:
 *      this WPImageFile method must return the file's contents
 *      as "bitmap data".
 *
 *      I don't think this method ever gets called by the
 *      core WPS code. This is a good thing because it's just
 *      crazy to keep several megabytes of bitmap data in instance
 *      memory for a few thousand image files just to support
 *      this method. It is also not clear to me who's responsible
 *      for cleaning up this data.
 */

SOM_Scope PBYTE  SOMLINK img_wpQueryBitmapData(XWPImageFile *somSelf,
                                               ULONG* pulSize)
{
    /* XWPImageFileData *somThis = XWPImageFileGetData(somSelf); */
    XWPImageFileMethodDebug("XWPImageFile","img_wpQueryBitmapData");

    return NULL;
}

/*
 *@@ LoadImageHeader:
 *      little helper to make sure we have the image
 *      header data loaded, but do this only once.
 *
 *      If this succeeds, we set the image header
 *      and cbPerRow instance members.
 *
 *@@added V1.0.1 (2003-01-29) [umoeller]
 */

PMMIMAGEHEADER LoadImageHeader(XWPImageFile *somSelf,
                               HMMIO hmmio)
{
    XWPImageFileData *somThis = XWPImageFileGetData(somSelf);

    // have we loaded this already?
    if (!_pbMMImageHeader)
    {
        // no:
        PMMIMAGEHEADER pmmih;
        if (pmmih = ShlAllocMem(sizeof(MMIMAGEHEADER), NULL))
        {
            if (!mmhLoadImageHeader(hmmio,
                                    pmmih,
                                    &_cbPerRow))
            {
                _pbMMImageHeader = (PBYTE)pmmih;
            }
            else
                ShlFreeMem(pmmih);
        }
    }

    return (PMMIMAGEHEADER)_pbMMImageHeader;
}

/*
 *@@ wpQueryBitmapHandle:
 *      this WPImageFile method must return the file's contents
 *      converted to a PM bitmap handle. It must be able create
 *      that bitmap in the size given by the caller in ulWidth
 *      and ulHeight.
 *
 *      Implementation of this method is required since the WPS
 *      appears to call this for folder background support. Also,
 *      this method gets called from WPImageFile::wpQueryHandleFromContents.
 *
 *      Apparently the WPS design assumes that this method should
 *      create a bitmap and no longer worry about it. It seems to
 *      be the responsibility of the caller to delete the bitmap
 *      whenever it wants to.
 *
 *@@added V1.0.1 (2003-01-29) [umoeller]
 */

SOM_Scope BOOL32  SOMLINK img_wpQueryBitmapHandle(XWPImageFile *somSelf,
                                                  HBITMAP* phBitmap,
                                                  HPAL* phPalette,
                                                  ULONG ulWidth,
                                                  ULONG ulHeight,
                                                  ULONG ulFlags,
                                                  long lBackgroundColor,
                                                  BOOL* pbQuitEarly)
{
    BOOL    brc = FALSE;

    PBYTE   pbBitmapBits = NULL;
    HMMIO   hmmio = NULLHANDLE;

    CHAR    szFilename[CCHMAXPATH];

    XWPImageFileData *somThis = XWPImageFileGetData(somSelf);
    XWPImageFileMethodDebug("XWPImageFile","img_wpQueryBitmapHandle");

    _PmpfF(("entering"));

    if (    (phBitmap)
         && (_wpQueryFilename(somSelf, szFilename, TRUE))
       )
    {
        TRY_LOUD(excpt1)
        {
            APIRET  arc = ERROR_OPEN_FAILED;

            PSZ pszExt;

            if (pszExt = doshGetExtension(szFilename))
            {
                // try to find the ioproc that matches the extension
                ULONG   ul;
                nlsUpper(pszExt);

                _PmpfF(("[%s] got ext \"%s\"",
                        szFilename,
                        pszExt));

                for (ul = 0;
                     ul < G_cFormatInfos;
                     ++ul)
                {
                    if (!strcmp(G_aFormatInfos[ul].szDefaultFormatExt, pszExt))
                    {
                        CHAR szFourCC[5] = "1234";
                        memcpy(szFourCC, &G_aFormatInfos[ul].fccIOProc, sizeof(ULONG));

                        _PmpfF(("   %s (fcc: %s) matches",
                                G_aFormatInfos[ul].szDefaultFormatExt,
                                szFourCC));

                        // extension matches: try that fourcc
                        if (!(arc = mmhOpenImage(szFilename,
                                                 G_aFormatInfos[ul].fccIOProc,
                                                 &hmmio)))
                            // worked:
                            break;

                        _PmpfF(("       mmioOpen returned %d", arc));
                    }
                    else
                        _PmpfF(("   %s didn't match",
                                G_aFormatInfos[ul].szDefaultFormatExt));

                }
            }

            // arc is ERROR_OPEN_FAILED if we couldn't find that
            // extension, or the mmhOpenImage error code if open
            // didn't work for any; in those cases, still try
            // the default open
            if (    (!arc)
                 || (!(arc = mmhOpenImage(szFilename,
                                          0,
                                          &hmmio)))
               )
            {
                PMMIMAGEHEADER pmmihSelf;

                if (pmmihSelf = LoadImageHeader(somSelf,
                                                hmmio))
                {
                    // this sets _cbPerRow also

                    if (!(arc = mmhLoadImageBits(hmmio,
                                                 pmmihSelf,
                                                 _cbPerRow,
                                                 &pbBitmapBits)))
                    {
                        SIZEL   szlBitmap;
                        if (!(szlBitmap.cx = ulWidth))
                            szlBitmap.cx = pmmihSelf->mmXDIBHeader.BMPInfoHeader2.cx;
                        if (!(szlBitmap.cy = ulHeight))
                            szlBitmap.cy = pmmihSelf->mmXDIBHeader.BMPInfoHeader2.cy;
                        if (!(arc = mmhCreateBitmapFromBits(&szlBitmap,
                                                            &pmmihSelf->mmXDIBHeader.BMPInfoHeader2,
                                                            pbBitmapBits,
                                                            phBitmap)))
                        {
                            brc = TRUE;
                        }
                    }
                }
            }
        }
        CATCH(excpt1)
        {
        } END_CATCH();

        if (pbBitmapBits)
            DosFreeMem(pbBitmapBits);

        if (hmmio)
            G_mmioClose(hmmio, 0);
    }

    return brc;
}

/*
 *@@ wpQueryBitmapInfoHeader:
 *
 *
 *      Implementation of this method is required since the WPS
 *      appears to call this for folder background support. The
 *      WPS apparently expects this method to return a pointer
 *      to a BITMAPINFOHEADER2 structure.
 */

SOM_Scope PBYTE  SOMLINK img_wpQueryBitmapInfoHeader(XWPImageFile *somSelf)
{
    XWPImageFileData *somThis = XWPImageFileGetData(somSelf);
    XWPImageFileMethodDebug("XWPImageFile","img_wpQueryBitmapInfoHeader");

    if (!_pbMMImageHeader)
    {
        HMMIO   hmmio = NULLHANDLE;
        CHAR    szFilename[CCHMAXPATH];

        if (!_wpQueryFilename(somSelf, szFilename, TRUE))
            return FALSE;

        TRY_LOUD(excpt1)
        {
            APIRET  arc;

            if (!(arc = mmhOpenImage(szFilename,
                                     0, // fccIOProc,
                                     &hmmio)))
            {
                LoadImageHeader(somSelf,
                                hmmio);
            }
        }
        CATCH(excpt1)
        {
        } END_CATCH();

        if (hmmio)
            G_mmioClose(hmmio, 0);
    }

    if (_pbMMImageHeader)
        return (PBYTE)(&((PMMIMAGEHEADER)_pbMMImageHeader)->mmXDIBHeader.BMPInfoHeader2);

    return NULL;
}

/*
 *@@ wpReadImageFile:
 *
 *      I wonder why IBM made this method public because I do
 *      not think it ever gets called by WPS code.
 */

SOM_Scope BOOL32  SOMLINK img_wpReadImageFile(XWPImageFile *somSelf)
{
    /* XWPImageFileData *somThis = XWPImageFileGetData(somSelf); */
    XWPImageFileMethodDebug("XWPImageFile","img_wpReadImageFile");

    return (XWPImageFile_parent_WPImageFile_wpReadImageFile(somSelf));
}

/*
 *@@ wpSetBitmapData:
 *
 */

SOM_Scope BOOL32  SOMLINK img_wpSetBitmapData(XWPImageFile *somSelf,
                                              PBYTE pBitmapData,
                                              ULONG ulSize)
{
    /* XWPImageFileData *somThis = XWPImageFileGetData(somSelf); */
    XWPImageFileMethodDebug("XWPImageFile","img_wpSetBitmapData");

    return (XWPImageFile_parent_WPImageFile_wpSetBitmapData(somSelf,
                                                            pBitmapData,
                                                            ulSize));
}

/*
 *@@ wpWriteImageFile:
 *
 */

SOM_Scope BOOL32  SOMLINK img_wpWriteImageFile(XWPImageFile *somSelf)
{
    /* XWPImageFileData *somThis = XWPImageFileGetData(somSelf); */
    XWPImageFileMethodDebug("XWPImageFile","img_wpWriteImageFile");

    return (XWPImageFile_parent_WPImageFile_wpWriteImageFile(somSelf));
}


/* ******************************************************************
 *
 *   XWPImageFile class methods
 *
 ********************************************************************/

/*
 *@@ wpclsInitData:
 *      this M_WPObject class method gets called when a class
 *      is loaded by the WPS (probably from within a
 *      somFindClass call) and allows the class to initialize
 *      itself.
 */

SOM_Scope void  SOMLINK imgM_wpclsInitData(M_XWPImageFile *somSelf)
{
    /* M_XWPImageFileData *somThis = M_XWPImageFileGetData(somSelf); */
    M_XWPImageFileMethodDebug("M_XWPImageFile","imgM_wpclsInitData");

    M_XWPImageFile_parent_M_WPImageFile_wpclsInitData(somSelf);

    krnClassInitialized(G_pcszXWPImageFile);
}

/*
 *@@ wpclsQueryTitle:
 *      this M_WPObject class method tells the WPS the clear
 *      name of a class, which is shown in the third column
 *      of a Details view and also used as the default title
 *      for new objects of a class.
 */

SOM_Scope PSZ  SOMLINK imgM_wpclsQueryTitle(M_XWPImageFile *somSelf)
{
    /* M_XWPImageFileData *somThis = M_XWPImageFileGetData(somSelf); */
    M_XWPImageFileMethodDebug("M_XWPImageFile","imgM_wpclsQueryTitle");

    return "Image File"; // @@todo localize
}

/*
 *@@ wpclsQueryDefaultHelp:
 *      this M_WPObject class method returns the default help
 *      panel for objects of this class. This gets called
 *      from WPObject::wpQueryDefaultHelp if no instance
 *      help settings (HELPLIBRARY, HELPPANEL) have been
 *      set for an individual object. It is thus recommended
 *      to override this method instead of the instance
 *      method to change the default help panel for a class
 *      in order not to break instance help settings (fixed
 *      with 0.9.20).
 */

SOM_Scope BOOL  SOMLINK imgM_wpclsQueryDefaultHelp(M_XWPImageFile *somSelf,
                                                   PULONG pHelpPanelId,
                                                   PSZ pszHelpLibrary)
{
    /* M_XWPImageFileData *somThis = M_XWPImageFileGetData(somSelf); */
    M_XWPImageFileMethodDebug("M_XWPImageFile","imgM_wpclsQueryDefaultHelp");

    return M_XWPImageFile_parent_M_WPImageFile_wpclsQueryDefaultHelp(somSelf,
                                                                     pHelpPanelId,
                                                                     pszHelpLibrary);
}

/*
 *@@ wpclsQueryInstanceFilter:
 *      this M_WPFileSystem class method determines which file-system
 *      objects will be instances of a certain class according
 *      to a file filter.
 *
 *      We check with MMPM/2 what image file types are supported
 *      by IOProcs on the system and make all those extensions
 *      instances of us, EXCEPT *.BMP in order not to break WPBitmap.
 */

SOM_Scope PSZ  SOMLINK imgM_wpclsQueryInstanceFilter(M_XWPImageFile *somSelf)
{
    /* M_XWPImageFileData *somThis = M_XWPImageFileGetData(somSelf); */
    M_XWPImageFileMethodDebug("M_XWPImageFile","imgM_wpclsQueryInstanceFilter");

    if (    (!G_pcszImageFileFilter)
         && (xmmQueryStatus() == MMSTAT_WORKING)
         && (!mmhGetIOProcs(MMIO_MEDIATYPE_IMAGE,
                            &G_aFormatInfos,
                            &G_cFormatInfos))
       )
    {
        ULONG   ul;
        XSTRING str;
        xstrInit(&str, 0);
        for (ul = 0;
             ul < G_cFormatInfos;
             ++ul)
        {
            CHAR szExt[10] = "*.";

            nlsUpper(G_aFormatInfos[ul].szDefaultFormatExt);

            if (strcmp(G_aFormatInfos[ul].szDefaultFormatExt, "BMP"))
            {
                PSZ     p;
                ULONG   ulLen = strlcpy(szExt + 2,
                                        G_aFormatInfos[ul].szDefaultFormatExt,
                                        sizeof(szExt) - 2)
                                + 2;

                // make sure we add each extension only once
                // -- on the first loop, str.ulLength is 0
                // -- on the second loop, we have added "*.TIF";
                //    if we get another "*.TIF", p returns the
                //    first one... then make sure it's not the
                //    whole string
                if (    (!str.ulLength)
                     || (!(p = strstr(str.psz, szExt)))
                     || (    (p[ulLen] != '\0')
                          && (p[ulLen] != ',')
                        )
                   )
                {
                    if (str.ulLength)
                        xstrcatc(&str, ',');
                    xstrcat(&str, szExt, ulLen);
                }
            }
        }

        if (str.ulLength)
            G_pcszImageFileFilter = memcpy(malloc(str.ulLength + 1),
                                           str.psz,
                                           str.ulLength + 1);
            // never freed again

        xstrClear(&str);
    }

    if (G_pcszImageFileFilter)
    {
        _PmpfF(("G_pcszImageFileFilter: %s", G_pcszImageFileFilter));
        return (PSZ)G_pcszImageFileFilter;
    }

    return M_XWPImageFile_parent_M_WPImageFile_wpclsQueryInstanceFilter(somSelf);
}

