/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
// attrib.c

#define INCL_DOS
#define INCL_PM
#include <os2.h>

#define INCL_DDICOMFLAGS
#define INCL_GRE_DEVMISC1
#define INCL_GRE_DEVSUPPORT
#define INCL_DDIMISC
#define INCL_DDIBUNDLES
#include <pmddi.h>

// c includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <builtin.h>

// driver includes
#define INCL_INNER_GRE
#include "def.h"
#include "driver.h"
#include "funcs.h"
#include "assert.h"


// --------------------------------------------------------------------------------------------------------------------
// only need one copy in memory of the attribute bundles that contain the default settings
// so pragma this static declaration onto a global data page in memory

#pragma data_seg( Global )

CHARBUNDLE DefaultCharBundle = {
        CLR_BLACK,                     // lColor
        CLR_WHITE,                     // lBackColor
        FM_OVERPAINT,                  // usMixMode
        BM_LEAVEALONE,                 // usBackMixMode
        0,                             // usSet
        3,                             // usPrecision
        {0x320000L,0x320000L},         // sizfxCell
        { 1, 0 },                      // ptlAngle
        { 0, 1 },                      // ptlShear
        1,                             // usDirection
        TA_NORMAL_HORIZ,               // usTextAlign
        0,                             // fxExtra
        0                              // fxBreakExtra
};



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

LONG ENGENTRY DeviceSetAttributes( HDC       hdc,
                                   ULONG     ulBType,
                                   ULONG     ulDefsMask,
                                   ULONG     flAttrsMask,
                                   PBUNDLE   pAttrs,
                                   PDDC      pddc,
                                   ULONG     ulFunction )
{
  REGREC          regrec;
  ULONG           ulException;
  LONG            lrc;
  PDCHARBUNDLE    pdcharbundle;
  PDLINEBUNDLE    pdlinebundle;
  PDAREABUNDLE    pdareabundle;
  PDMARKERBUNDLE  pdmarkerbundle;
  PDIMAGEBUNDLE   pdimagebundle;
  ULONG           ulDeviceSetAttr;
  ULONG           ulDefSet;
  ULONG           ulStatus;
  ULONG           ulDeviceBitmapHandle;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }

  ENTERDDC( pddc );

  if( ! flAttrsMask ) {
    // nothing to do
    lrc = TRUE;
    goto depart;
  }


  switch( ulBType ) {
  case PRIM_AREA:
    pdareabundle = (PDAREABUNDLE)pAttrs;
    ulDeviceSetAttr = 0;


    // assume that the fill pattern is not a bitmap used for filling
    // assume a normal, standard area fill pattern
    ulDefSet = 0;


    if( ABB_SET & flAttrsMask ) {

      // save a copy of the supplied area fill handle
      ulDefSet = pdareabundle->adef.defSet;

      // Check if the defSet is a bitmap handle.
      // The GRE identifies bitmap handles with a 0x0400 in the high-order word of the handle.
      // If it's a bitmap handle, then this bitmap will be used as the area fill pattern.

      if( 0x0400 == HIUSHORT( ulDefSet )) {
        // ulDefSet is a bitmap handle
        // GetDriverInfo is GRE-exported function that can
        // get the device-specified handle for this bitmap from the shadow DC
        ulDeviceBitmapHandle = GetDriverInfo( (HBITMAP) ulDefSet, 1L, pddc->hdcShadow );
        assert( (LONG)ulDeviceBitmapHandle != GPI_ALTERROR );

        // use the device bitmap handle on the call to shadow DC device set attributes because it is the
        // handle shadow DC device understands
        // be sure to set it back after the call
        pdareabundle->adef.defSet = ulDeviceBitmapHandle;

        flAttrsMask &= ~ABB_SET;
        ulDeviceSetAttr = ABB_SET;
      }
    }

    // device-level area fill set numbers are meaningless at this entry point, thus ABB_SET bit was masked off
    ulStatus = InnerGreSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, flAttrsMask, &pdareabundle->abnd, ulFunction );
    assert( ulStatus );

    // if there's a device-level bitmap fill pattern, then set it on the shadow dc with this call
    if( ulDeviceSetAttr ) {
      ulStatus = InnerGreDeviceSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, ulDeviceSetAttr, pAttrs, ulFunction );
      assert( ulStatus );
    }

    // clean up the dareabundle if it was modified above
    if( ulDefSet ) {
      pdareabundle->adef.defSet = ulDefSet;
    }
    lrc = TRUE;
    break;



  case PRIM_CHAR:
    pdcharbundle = (PDCHARBUNDLE)pAttrs;
    ulDeviceSetAttr = 0;

    if( CBB_SET & flAttrsMask ) {
      // device-level set numbers are meaningless at this entry point, thus CBB_SET bit was masked off
      flAttrsMask &= ~CBB_SET;
      // but I need to set this attribute at the device level
      ulDeviceSetAttr = CBB_SET;
    }

    // device-level set numbers are meaningless at this entry point, thus CBB_SET bit was masked off
    assert( !(flAttrsMask & CBB_SET) );
    ulStatus = InnerGreSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, flAttrsMask, &pdcharbundle->cbnd, ulFunction );
    assert( ulStatus );

    // however, if device-level attributes are spec'd, then set them on the shadow dc with this call
    if(  ulDeviceSetAttr) {
      ulStatus = InnerGreDeviceSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, ulDeviceSetAttr, pAttrs, ulFunction );
      assert( ulStatus );
    }
    lrc = TRUE;
    break;


  case PRIM_IMAGE:
    // image and line have no device-level handles; can just relay the call into the shadow dc set attributes
    pdimagebundle = (PDIMAGEBUNDLE)pAttrs;
    ulStatus = InnerGreSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, flAttrsMask, &pdimagebundle->ibnd, ulFunction );
    assert( ulStatus );
    break;

  case PRIM_LINE:
    // image and line have no device-level handles; can just relay the call into the shadow dc set attributes
    pdlinebundle = (PDLINEBUNDLE)pAttrs;
    ulStatus = InnerGreSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, flAttrsMask, &pdlinebundle->lbnd, ulFunction );
    assert( ulStatus );
    break;


  case PRIM_MARKER:
    pdmarkerbundle = (PDMARKERBUNDLE)pAttrs;
    ulDeviceSetAttr = 0;

    if( MBB_SET & flAttrsMask ) {
      // device-level set numbers are meaningless at this entry point, thus CBB_SET bit is masked off
      flAttrsMask &= ~MBB_SET;
      // but I need to set this attribute at the device level
      ulDeviceSetAttr = MBB_SET;
    }

    // device-level set numbers are meaningless at this entry point, thus CBB_SET bit was masked off
    assert( !(flAttrsMask & MBB_SET ));
    ulStatus = InnerGreSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, flAttrsMask, &pdmarkerbundle->mbnd, ulFunction );
    assert( ulStatus );

    // however, if device-level attributes are spec'd, then set them on the shadow dc with this call
    if(  ulDeviceSetAttr) {
      ulStatus = InnerGreDeviceSetAttributes( pddc->hdcShadow, ulBType, ulDefsMask, ulDeviceSetAttr, pAttrs, ulFunction );
      assert( ulStatus );
    }
    lrc = TRUE;
    break;

  default:
    assert( FALSE );
    break;
  }


depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}



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

LONG ENGENTRY DeviceGetAttributes( HDC       hdc,
                                   LONG      lPrimType,
                                   ULONG     ulAttrsMask,
                                   PBUNDLE   pAttrs,
                                   PDDC      pddc,
                                   ULONG     ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }
  ENTERDDC( pddc );


  lrc = GreDeviceGetAttributes( pddc->hdcShadow, lPrimType, ulAttrsMask, pAttrs );
  assert( lrc );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}

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

LONG ENGENTRY DeviceSetGlobalAttribute( HDC       hdc,
                                        LONG      lAttrType,
                                        LONG      lAttribute,
                                        ULONG     flOptions,
                                        PDDC      pddc,
                                        ULONG     ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  ULONG       lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }
  ENTERDDC( pddc );


  lrc = GreSetGlobalAttribute( pddc->hdcShadow, lAttrType, lAttribute, flOptions );
  assert( lrc );


depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}



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

LONG ENGENTRY GetPairKerningTable     ( HDC            hdc,
                                        LONG           cKernPairs,
                                        PKERNINGPAIRS  pKerningPairs,
                                        PDDC           pddc,
                                        ULONG          ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    // clean up here
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc );
    // error result
    lrc = FALSE;
    goto depart;
  }
  ENTERDDC( pddc );


  lrc = GreGetPairKerningTable( pddc->hdcShadow, cKernPairs, pKerningPairs );
  assert( lrc );

depart:
  EXITDDC( pddc );
  UNREGISTERHANDLER( regrec );
  return lrc;
}


