/*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.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDAATTS                                       */
/*                                                                    */
/*   Description     = Display Device Driver subroutines              */
/*                     SetTextAttributes,                             */
/*                     SetLineAttributes,                             */
/*                     SetMarkerAttributes,                           */
/*                     SetPatternAttributes                           */
/*                     SetImageAttributes.                            */
/*                                                                    */
/*   Function        = Each subroutine sets the attributes in the     */
/*                     appropriate bundle to either their default     */
/*                     or a given value.                              */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
/******************************************************************************/
/* CHANGE ACTIVITY:                                                           */
/*                                                                            */
/* FLAG RLSE  DATE  ORIGIN              COMMENTS                              */
/* ---- ---- ------ ------  --------------------------------------------------*/
/* @001 0205 930301 Change  Modified SetTextAttributes so the Code Page       */
/*                  Team    (along with the Char Set) can be checked to       */
/*                          see if a different font is required.              */
/*                          (Defect 62916 - BZ)                               */
/* @002      930603 Binar   The code for defect 52086 causes problems when    */
/*                 Graphics the caller wants the Background color unchanged.  */
/*                          Code already exists to handle the background      */
/*                          color so the troublesome code was removed.        */
/******************************************************************************/
#define INCL_DDICOMFLAGS
#define INCL_DDIMISC
#include <eddinclt.h>

#include <eddacone.h>
#include <eddccone.h>
#include <eddecone.h>
#include <eddhcone.h>
#include <eddtcone.h>

#include <eddaextf.h>
#include <eddcextf.h>
#include <eddgextf.h>
#include <eddtextf.h>

extern BOOL             DefaultTextSimulation;

extern DCHARBUNDLE      DefaultTextAttrs;
extern DLINEBUNDLE      DefaultLineAttrs;
extern DMARKERBUNDLE    DefaultMarkerAttrs;
extern DAREABUNDLE      DefaultPatternAttrs;
extern DIMAGEBUNDLE     DefaultImageAttrs;


/**********************************************************************/
/* Checks if usBackMix is valid. If it is it returns the background   */
/* mix value. If not, logs an error and returns BM_ERROR.             */
/**********************************************************************/
USHORT GetBackgroundMix(USHORT usBackMix)
{
   // @DMS this is a @@*^%#@!#$% useless function !!!!
   #ifndef   _8514
    switch ( usBackMix )
    {
        case BM_DEFAULT:
            return(DEFAULT_BACKGROUND_MIX);

        case BM_OR:
            return(BM_OR);

        case BM_OVERPAINT:
            return(BM_OVERPAINT);

        case BM_XOR:
            return(BM_XOR);

        case BM_LEAVEALONE:
            return(BM_LEAVEALONE);

        case BM_SRCTRANSPARENT:
            return(BM_SRCTRANSPARENT);

        case BM_DESTTRANSPARENT:
            return(BM_DESTTRANSPARENT);

        default:
            LogError(PMERR_INV_BACKGROUND_MIX_ATTR);
            return(BM_ERROR);
    }
   #else
    switch ( usBackMix )
    {
        case BM_DEFAULT:
        case BM_OR:
        case BM_OVERPAINT:
        case BM_XOR:
        case BM_LEAVEALONE:
        case BM_SRCTRANSPARENT:
        case BM_DESTTRANSPARENT:
           return(usBackMix);

        default:
            LogError(PMERR_INV_BACKGROUND_MIX_ATTR);
            return(BM_ERROR);
    }

       #endif
} /* GetBackgroundMix */


#ifdef TMP                                                  
/*====================================================================*/
/* structs for old code (16bit)                                       */
/*====================================================================*/
   typedef struct _CHARBUND16 {     /* cbnd */
      LONG      lColor;
      LONG      lBackColor;
      USHORT    usMixMode;
      USHORT    usBackMixMode;
      USHORT    usSet;
      USHORT    usPrecision;
      SIZEF     sizfxCell;
      POINTL    ptlAngle;
      POINTL    ptlShear;
      USHORT    usDirection;
//    USHORT    usTextAlign;    // These fields are not included in
//    FIXED     fxExtra;        //   16-bit structure
//    FIXED     fxBreakExtra;
   } CHARBUND16;
   typedef CHARBUND16 FAR *PCHARBUND16;

   typedef struct _CHARDE16 { /* cdef */
      ULONG      defSet;
      USHORT     fFlags;        // 2B instead of 4B for 16-bit struct
      USHORT     CodePage;      // ditto
      USHORT     charSpacing;   // ditto
   } CHARDE16;
   typedef CHARDE16 FAR *PCHARDE16;

   typedef struct _DCHARBUND16 { /* dcbnd */
      LONG       cAttr;
      LONG       cDefs;
      CHARBUND16 cbnd;
      CHARDE16   cdef;
   } DCHARBUND16;
   typedef DCHARBUND16 FAR *PDCHARBUND16;
#endif 

/**********************************************************************/
/* SetTextAttributes sets the text attributes to either a given value */
/* or their default value.                                            */
/* A flag is set in the DC instance data if the given attributes are  */
/* not supported.                                                     */
/*                                                                    */
/* To improve performance, the flag indicating if a text simulation   */
/* is required has been changed from a simple flag to a set of flags  */
/* indicating which CBB_ values require text simulations. These       */
/* flags can be set and reset by the individual parts of code that    */
/* change each attribute. A simulation is not required when they all  */
/* are unset (ie the flag has value 0). This should not break any     */
/* of the code that checks this as a flag.                            */
/*                                                                    */
/**********************************************************************/

ULONG SetTextAttributes (ULONG          DefMask,
                         ULONG          AttrMask,
                         PDCHARBUNDLE   Attributes)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG              PhyIndex;       /* Physical index              */
    USHORT             MixMode;        /* The mix mode to set         */
    PDCHARBUNDLE       NewAttrs;
    PDCHARBUNDLE       CurrentAttrs;   /* ptr to DC attrs structure   */
    ULONG              defSetOld;
    ULONG              defCodePageOld; /* Old Code Page          @001 */

#ifdef TMP                                                  
    DCHARBUNDLE        TempAttrs;
#endif 

    CurrentAttrs = &(pdc->DCICurTxtAts);

    if ( (DefMask == ALL_DEFAULTS) &&
         (AttrMask == ALL_DEFAULTS) )
    {
        /**************************************************************/
        /* This is the special case when called by reset DC           */
        /* in order to set all attributes to their defaults           */
        /**************************************************************/
        pdc->DCIChanged &= ~NOTDEFAULT_TextAttrs;

        memcpy( (PVOID)CurrentAttrs,
                (PVOID)&DefaultTextAttrs,
                sizeof(DCHARBUNDLE));

#ifdef DBCS                                                 
        /*============================================================*/
        /* Change codepage to that of enable-time of this DC          */
        /*   This is necessary to keep compatibility to ATLAS/VGA DBCS*/
        /*   driver, and some existing DBCS appl.    which assume it. */
        /*============================================================*/
        pdc->DCICodePage = pdc->DCIOriginalCodePage;
#endif 
        /**************************************************************/
        /* Set the simulation flags to their initial state.           */
        /**************************************************************/
        pdc->DCITextSim = DefaultTextSimulation;

        /**************************************************************/
        /* Get the font - if its changed                              */
        /* This sets up pointers in the instance data to the font,    */
        /* its metrics, header, codepage and its type.                */
        /**************************************************************/
        if (eddt_LocateFont() != OK)
        {
            return(ERROR_ZERO);
        }

        /**************************************************************/
        /* Set up the physical colour indices                         */
        /**************************************************************/
        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->cbnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCICharColatts.ForeColor = PhyIndex;

            PhyIndex = LogToPhyIndex(CurrentAttrs->cbnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCICharColatts.BackColor = PhyIndex;
        }

        return(OK);
    }

    /************************************************************@001**/
    /* Save the old Character Set and Code Page.                 @001 */
    /************************************************************@001**/
    defSetOld = CurrentAttrs->cdef.defSet;
    defCodePageOld = CurrentAttrs->cdef.CodePage;             /* @001 */

#ifdef TMP                                                  
    /*================================================================*/
    /* Temporary fix for DBCS postscript printer driver. (JS04702)    */
    /*  This 16-bit driver calls display driver to get character image*/
    /*  and DCHARBUNDLE struct is NOT properly thunked from 16-bit to */
    /*  32-bit.  (GRE32's problem?)                                   */
    /*================================================================*/
    if (Attributes->cAttr == sizeof(CHARBUND16))
      {                                /* if given is 16-bit struct   */
                                       /*  then setup local copy      */
#define ATTRIB16        ((PDCHARBUND16)Attributes)
        TempAttrs.cAttr = sizeof(CHARBUNDLE);
        TempAttrs.cDefs = sizeof(CHARDEFS);
        memcpy(&TempAttrs.cbnd, &ATTRIB16->cbnd, sizeof(CHARBUND16));
        TempAttrs.cbnd.usTextAlign =
          TempAttrs.cbnd.fxExtra =
          TempAttrs.cbnd.fxBreakExtra = 0;
                                       /* clear not-existing fields   */
        TempAttrs.cdef.defSet = ATTRIB16->cdef.defSet;
        TempAttrs.cdef.fFlags = ATTRIB16->cdef.fFlags;
        TempAttrs.cdef.CodePage = ATTRIB16->cdef.CodePage;
        TempAttrs.cdef.charSpacing = ATTRIB16->cdef.charSpacing;
#undef ATTRIB16                        /*                             */
        Attributes = &TempAttrs;       /*                             */
      }                                /* end of if:                  */
#endif 
    /******************************************************************/
    /* Always copy everything from the cdef to our attributes         */
    /******************************************************************/
    CurrentAttrs->cdef = Attributes->cdef;

    /******************************************************************/
    /* Put the cdef flags in the high 16 bits of DCITextSim - the CBB_*/
    /* flags go in the lower 16 bits.                                 */
    /******************************************************************/
    pdc->DCITextSim = (pdc->DCITextSim & 0x0000ffff) |
                     ((Attributes->cdef.fFlags & (CDEF_BOLD       |
                                                  CDEF_ITALIC     |
                                                  CDEF_UNDERSCORE |
                                                  CDEF_STRIKEOUT  |
                                                  CDEF_OUTLINE)) << 16);

    /******************************************************************/
    /* Not using all the default values.  Record this in the DC data  */
    /* and check each attribute to see what needs to change.          */
    /******************************************************************/
    pdc->DCIChanged |= NOTDEFAULT_TextAttrs;

    /******************************************************************/
    /* Foreground colour                                              */
    /******************************************************************/
    if (AttrMask & CBB_COLOR)
    {
        /**************************************************************/
        /* Default value, or value passed                             */
        /**************************************************************/
        CurrentAttrs->cbnd.lColor = (DefMask & CBB_COLOR) ?
                                        DefaultTextAttrs.cbnd.lColor :
                                        Attributes->cbnd.lColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->cbnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCICharColatts.ForeColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Background Colour                                              */
    /******************************************************************/

    if (AttrMask & CBB_BACK_COLOR)
    {
        /**************************************************************/
        /* Default value, or value passed                             */
        /**************************************************************/
        CurrentAttrs->cbnd.lBackColor = (DefMask & CBB_BACK_COLOR) ?
                                        DefaultTextAttrs.cbnd.lBackColor :
                                        Attributes->cbnd.lBackColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->cbnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCICharColatts.BackColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Foreground Mix                                                 */
    /******************************************************************/

    if (AttrMask & CBB_MIX_MODE)
    {
        /**************************************************************/
        /* Default value, or value passed                             */
        /**************************************************************/
        MixMode = (DefMask & CBB_MIX_MODE) ?
                      DefaultTextAttrs.cbnd.usMixMode :
                      Attributes->cbnd.usMixMode;

        /**************************************************************/
        /* Check if MixMode is valid                                  */
        /**************************************************************/

        if (MixMode == 0)
        {
            CurrentAttrs->cbnd.usMixMode = DEFAULT_FOREGROUND_MIX;
        }
        else if (MixMode > 0 &&
                 MixMode < NO_OF_FOREGROUND_MIXES &&
                 MixMode != (USHORT)3)
        {
            CurrentAttrs->cbnd.usMixMode = MixMode;
        }
        else
        {
            LogError(PMERR_INV_MIX_ATTR);
            return(ERROR_ZERO);
        }
    }

    /******************************************************************/
    /* Background Mix                                                 */
    /******************************************************************/

    if (AttrMask & CBB_BACK_MIX_MODE)
    {

        /**************************************************************/
        /* Default value, or value passed                             */
        /**************************************************************/
        MixMode = (DefMask & CBB_BACK_MIX_MODE) ?
                      DefaultTextAttrs.cbnd.usBackMixMode :
                      Attributes->cbnd.usBackMixMode;

        /**************************************************************/
        /* Validate background mix mode.                              */
        /**************************************************************/
        MixMode = GetBackgroundMix(MixMode);
        if ( MixMode == (USHORT)BM_ERROR )
        {
             return(ERROR_ZERO);
        }
        else /* valid background mix */
        {
             CurrentAttrs->cbnd.usBackMixMode = MixMode;
        }
    }

    /******************************************************************/
    /* Character Set                                                  */
    /******************************************************************/

    if (AttrMask & CBB_SET)
    {
        /**************************************************************/
        /* See if the font is actually going to change                */
        /**************************************************************/
        NewAttrs = (DefMask & CBB_SET) ? &DefaultTextAttrs : Attributes;

        if (( CurrentAttrs->cdef.defSet != defSetOld ) ||      /* @001 */
            ( CurrentAttrs->cdef.CodePage != defCodePageOld )) /* @001 */
        {
            /**********************************************************/
            /* Free the currently selected font                       */
            /**********************************************************/
            if (pdc->CurrentFont.usFontID != (USHORT)(-1))
            {
                eddt_FreeCachedFont( pdc->CurrentFont.usFontID,
                                     pdc->CurrentFont.usCachedFontIndex);
            }

            /**********************************************************/
            /* Copy the new font set ID into the CHARBUNDLE.          */
            /**********************************************************/
            CurrentAttrs->cbnd.usSet = NewAttrs->cbnd.usSet;

            /**************************************************************/
            /* Get the font                                               */
            /* This sets up pointers in the instance data to the font,    */
            /* its metrics, header, codepage and its type.                */
            /**************************************************************/
            if (eddt_LocateFont() != OK)
            {
                return(ERROR_ZERO);
            }

            /**************************************************************/
            /* Text simulation required if the font is a vector font.     */
            /**************************************************************/
            if ( pdc->CurrentFont.pFocaFont->fmMetrics.fsDefn & FONT_IS_VECTOR )
            {
                pdc->DCITextSim |= CBB_SET;
            }
            else
            {
                pdc->DCITextSim &= ~CBB_SET;
            }
        }
    }

    /******************************************************************/
    /* Character Precision Mode                                       */
    /******************************************************************/

    if (AttrMask & CBB_MODE)
    {
        CurrentAttrs->cbnd.usPrecision = (DefMask & CBB_MODE) ?
                                   DefaultTextAttrs.cbnd.usPrecision :
                                   Attributes->cbnd.usPrecision;

        /**************************************************************/
        /* Text simulations required if the precision mode is not 1   */
        /**************************************************************/
        if (CurrentAttrs->cbnd.usPrecision != (USHORT)1)
        {
            pdc->DCITextSim |= CBB_MODE;
        }
        else
        {
            pdc->DCITextSim &= ~CBB_MODE;
        }
    }

    /******************************************************************/
    /* Character box size                                             */
    /******************************************************************/

    if (AttrMask & CBB_BOX)
    {
        CurrentAttrs->cbnd.sizfxCell = (DefMask & CBB_BOX) ?
                                   DefaultTextAttrs.cbnd.sizfxCell :
                                   Attributes->cbnd.sizfxCell;
    }

    /******************************************************************/
    /* Character Angle                                                */
    /******************************************************************/

    if (AttrMask & CBB_ANGLE)
    {
        CurrentAttrs->cbnd.ptlAngle = (DefMask & CBB_ANGLE) ?
                                  DefaultTextAttrs.cbnd.ptlAngle :
                                  Attributes->cbnd.ptlAngle;
    }

    /******************************************************************/
    /* Character Shear                                                */
    /******************************************************************/

    if (AttrMask & CBB_SHEAR)
    {
        CurrentAttrs->cbnd.ptlShear = (DefMask & CBB_SHEAR) ?
                                  DefaultTextAttrs.cbnd.ptlShear :
                                  Attributes->cbnd.ptlShear;
    }

    /******************************************************************/
    /* Character Direction                                            */
    /******************************************************************/

    if (AttrMask & CBB_DIRECTION)
    {
        CurrentAttrs->cbnd.usDirection = (DefMask & CBB_DIRECTION) ?
                                     DefaultTextAttrs.cbnd.usDirection :
                                     Attributes->cbnd.usDirection;

        /**************************************************************/
        /* Text simulations are required if the direction is not      */
        /* Left -> Right (which is also the default value)            */
        /**************************************************************/
        if ( (CurrentAttrs->cbnd.usDirection != CHDIRN_LEFTRIGHT) &&
             (CurrentAttrs->cbnd.usDirection != CHDIRN_DEFAULT) )
        {
            pdc->DCITextSim |= CBB_DIRECTION;
        }
        else
        {
            pdc->DCITextSim &= ~CBB_DIRECTION;
        }
    }

#ifdef EXTRA_SPACE
    /******************************************************************/
    /* DCR 25045: char extra and char break extra support.            */
    /******************************************************************/
    if (AttrMask & CBB_EXTRA)               /* Char break             */
    {
        CurrentAttrs->cbnd.fxExtra = (DefMask & CBB_EXTRA) ?
                                 DefaultTextAttrs.cbnd.fxExtra :
                                 Attributes->cbnd.fxExtra;

        /**************************************************************/
        /* If extra space is non-zero, then we return for simulation. */
        /* Note that the extra spacing is in FIXED point format, in   */
        /* world coordinates.                                         */
        /**************************************************************/
        if (CurrentAttrs->cbnd.fxExtra != 0)
        {
            pdc->DCITextSim |= CBB_EXTRA;
        }
        else
        {
            pdc->DCITextSim &= ~CBB_EXTRA;
        }
    }

    if (AttrMask & CBB_BREAK_EXTRA)            /* Char break extra    */
    {
        CurrentAttrs->cbnd.fxBreakExtra = (DefMask & CBB_BREAK_EXTRA) ?
                                      DefaultTextAttrs.cbnd.fxBreakExtra :
                                      Attributes->cbnd.fxBreakExtra;

        /**************************************************************/
        /* If extra space is non-zero, then we return for simulation. */
        /* Note that the extra spacing is in FIXED point format, in   */
        /* world coordinates.                                         */
        /**************************************************************/
        if (CurrentAttrs->cbnd.fxBreakExtra != 0)
        {
            pdc->DCITextSim |= CBB_BREAK_EXTRA;
        }
        else
        {
            pdc->DCITextSim &= ~CBB_BREAK_EXTRA;
        }
    }

#endif /* EXTRA_SPACE */

    /******************************************************************/
    /* DCR OS02028: Text Allignment                                   */
    /******************************************************************/
    if (AttrMask & CBB_TEXT_ALIGN)         /* Text allignment         */
    {
        CurrentAttrs->cbnd.usTextAlign = (DefMask & CBB_TEXT_ALIGN) ?
                                     DefaultTextAttrs.cbnd.usTextAlign :
                                     Attributes->cbnd.usTextAlign;

        /**************************************************************/
        /* Only text alignments of TA_LEFT and TA_BASE are supported  */
        /* (note if the character direction is CHDIRN_LEFTRIGHT:      */
        /* TA_NORMAL_HORIZ and TA_STANDARD_HORIZ equate to TA_LEFT,   */
        /* TA_NORMAL_VERT and TA_STANDARD_VERT equate to TA_BASE as   */
        /* other character directions require simulation we can       */
        /* accept these values as well.                               */
        /**************************************************************/
        if( ( (CurrentAttrs->cbnd.usTextAlign & 0xff) != TA_LEFT &&
              (CurrentAttrs->cbnd.usTextAlign & 0xff) != TA_NORMAL_HORIZ &&
              (CurrentAttrs->cbnd.usTextAlign & 0xff) != TA_STANDARD_HORIZ) ||
            ( (CurrentAttrs->cbnd.usTextAlign & 0xff00) != TA_BASE &&
              (CurrentAttrs->cbnd.usTextAlign & 0xff00) != TA_NORMAL_VERT &&
              (CurrentAttrs->cbnd.usTextAlign & 0xff00) != TA_STANDARD_VERT) )
        {
            pdc->DCITextSim |= CBB_TEXT_ALIGN;
        }
        else
        {
            pdc->DCITextSim &= ~CBB_TEXT_ALIGN;
        }
    }

    return(OK);
}






/**********************************************************************/
/* SetLineAttributes sets the line attributes to either a given value */
/* or their default value.                                            */
/* If the line type is changed then the line type mask and style      */
/* numbers are reset.                                                 */
/**********************************************************************/

ULONG SetLineAttributes (ULONG          DefMask,
                         ULONG          AttrMask,
                         PDLINEBUNDLE   Attributes)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG              PhyIndex;       /* Physical index              */
    USHORT             MixMode;        /* The mix mode to set         */
    LONG               GeomWidth;
    PDLINEBUNDLE       CurrentAttrs;   /* ptr to DC attrs structure   */


    CurrentAttrs = &(pdc->DCICurLinAts);

    if ( (DefMask == ALL_DEFAULTS) &&
         (AttrMask == ALL_DEFAULTS) )
    {
        /**************************************************************/
         /* this is the special case when called by reset DC           */
        /* in order to set all attributes to their defaults           */
        /**************************************************************/
        pdc->DCIChanged &= ~NOTDEFAULT_LineAttrs;

        memcpy( (PVOID)CurrentAttrs,
                (PVOID)&DefaultLineAttrs,
                sizeof(DLINEBUNDLE));

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->lbnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCILineColatts.ForeColor = PhyIndex;
        }

        return(OK);
    }

    /******************************************************************/
    /* Not using all the default values.  Record this in the DC data  */
    /* and check each attribute to see what needs to change.          */
    /******************************************************************/
    pdc->DCIChanged |= NOTDEFAULT_LineAttrs;

    /******************************************************************/
    /* copy the device bundle definitions field line type set.        */
    /******************************************************************/
    CurrentAttrs->ldef = Attributes->ldef;

    /******************************************************************/
    /* Foreground colour                                              */
    /******************************************************************/

    if (AttrMask & LBB_COLOR)
    {
        CurrentAttrs->lbnd.lColor = (DefMask & LBB_COLOR) ?
                                        DefaultLineAttrs.lbnd.lColor :
                                        Attributes->lbnd.lColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            /**********************************************************/
            /* Foreground colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->lbnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCILineColatts.ForeColor = PhyIndex;

//#ifdef LINESBG
//
// @002 - Richard Wooley, Binar Graphics
//
// This portion of code should NOT be here.  Situations are possible where
// the caller specified neither a default or a user defined background color.
// In this case, we get a bogus color which will fail during the LogToPhyIndex()
// call.  This will cause this function to fail and any other attributes the
// use specified will be ignored.  If the caller want the background color set,
// the background color code will be hit later to properly set the background color.
//
//            /**********************************************************/
//            /* Background Colour                                      */
//            /**********************************************************/
//
//            /**************************************************************/
//            /* Defect 52086 - We were not checking to see if the default  */
//            /* background color flag was ON. We would then use the bogus  */
//            /* color passed in and croak under certain circumstances.     */
//            /*                                                            */
//            /* Default value, or value passed                             */
//            /**************************************************************/
//            CurrentAttrs->lbnd.lBackColor = (DefMask & CBB_BACK_COLOR) ?
//                                             DefaultLineAttrs.lbnd.lBackColor :
//                                             Attributes->lbnd.lBackColor;
//
//            PhyIndex = LogToPhyIndex(CurrentAttrs->lbnd.lBackColor);
//            if (PhyIndex == CLR_NOPHYINDEX)
//            {
//                LogError(PMERR_INV_COLOR_ATTR);
//                return(ERROR_ZERO);
//            }
//            pdc->DCILineColatts.BackColor = PhyIndex;
//#endif /* LINESBG */
        }
    }

    /******************************************************************/
    /* Foreground Mix                                                 */
    /******************************************************************/

    if (AttrMask & LBB_MIX_MODE)
    {
        /**************************************************************/
        /* Default value, or value passed                             */
        /**************************************************************/
        MixMode = (DefMask & LBB_MIX_MODE) ?
                      DefaultLineAttrs.lbnd.usMixMode :
                      Attributes->lbnd.usMixMode;

        if (MixMode == 0)
        {
            CurrentAttrs->lbnd.usMixMode = DEFAULT_FOREGROUND_MIX;
        }
        else if (MixMode > 0 &&
                 MixMode < NO_OF_FOREGROUND_MIXES &&
                 MixMode != (USHORT)3)
        {
            CurrentAttrs->lbnd.usMixMode = MixMode;
        }
        else
        {
            LogError(PMERR_INV_MIX_ATTR);
            return(ERROR_ZERO);
        }
    }

#ifdef LINESBG
    /******************************************************************/
    /* Background Colour                                              */
    /******************************************************************/
    if (AttrMask & LBB_BACK_COLOR)
    {
        CurrentAttrs->lbnd.lBackColor = (DefMask & LBB_BACK_COLOR) ?
                                   DefaultLineAttrs.lbnd.lBackColor :
                                   Attributes->lbnd.lBackColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->lbnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCILineColatts.BackColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Background Mix                                                 */
    /******************************************************************/
    if (AttrMask & LBB_BACK_MIX_MODE)
    {
        /**************************************************************/
        /* Default value, or value passed                             */
        /**************************************************************/
        MixMode = (DefMask & LBB_BACK_MIX_MODE) ?
                      DefaultLineAttrs.lbnd.usBackMixMode :
                      Attributes->lbnd.usBackMixMode;

        MixMode = GetBackgroundMix(MixMode);
        if ( MixMode == (USHORT)BM_ERROR )
        {
            return(ERROR_ZERO);
        }
        else /* valid background mix */
        {
            CurrentAttrs->lbnd.usBackMixMode = MixMode;
        }
    }
#endif /* LINESBG */

    /******************************************************************/
    /* Line Width                                                     */
    /******************************************************************/
    if (AttrMask & LBB_WIDTH)
    {
        CurrentAttrs->lbnd.fxWidth = (DefMask & LBB_WIDTH) ?
                                 DefaultLineAttrs.lbnd.fxWidth :
                                 Attributes->lbnd.fxWidth;
    }

    /******************************************************************/
    /* Geometric width                                                */
    /******************************************************************/
    if (AttrMask & LBB_GEOM_WIDTH)
    {
        GeomWidth = (DefMask & LBB_GEOM_WIDTH) ?
                DefaultLineAttrs.lbnd.lGeomWidth :
                Attributes->lbnd.lGeomWidth;

        if (GeomWidth < 0)
        {
            /**********************************************/
            /* Invalid Geometric width.                   */
            /**********************************************/
            LogError(PMERR_INV_GEOM_LINE_WIDTH_ATTR);
            return(ERROR_ZERO);
        }
        else
        {
            /**********************************************/
            /* Valid Geometric width.                     */
            /**********************************************/
            CurrentAttrs->lbnd.lGeomWidth = GeomWidth;
        }
    }

    /******************************************************************/
    /* Line Type                                                      */
    /******************************************************************/
    if (AttrMask & LBB_TYPE)
    {
        CurrentAttrs->lbnd.usType = (DefMask & LBB_TYPE) ?
                                DefaultLineAttrs.lbnd.usType :
                                Attributes->lbnd.usType;

        /**************************************************************/
        /* The line type mask and the style number must be reset.     */
        /**************************************************************/
        pdc->DCILinePatCnt = 0;
        pdc->StyleNumber = 0x0001ff00;
    }

    /******************************************************************/
    /* Line End                                                       */
    /******************************************************************/
    if (AttrMask & LBB_END)
    {
        CurrentAttrs->lbnd.usEnd = (DefMask & LBB_END) ?
                               DefaultLineAttrs.lbnd.usEnd :
                               Attributes->lbnd.usEnd;
    }

    /******************************************************************/
    /* Line Join                                                      */
    /******************************************************************/
    if (AttrMask & LBB_JOIN)
    {
        CurrentAttrs->lbnd.usJoin = (DefMask & LBB_JOIN) ?
                                DefaultLineAttrs.lbnd.usJoin :
                                Attributes->lbnd.usJoin;
    }

    return(OK);
}





/**********************************************************************/
/* SetMarkerAttributes sets the marker attributes to either a given   */
/* value or their default value.                                      */
/* As the marker values in the default set are non contiguous a       */
/* mapping is applied, where necessary, to ensure contiguity.         */
/**********************************************************************/

ULONG SetMarkerAttributes (ULONG          DefMask,
                           ULONG          AttrMask,
                           PDMARKERBUNDLE Attributes)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG              PhyIndex;       /* Physical index              */
    USHORT             MixMode;
    PDMARKERBUNDLE     CurrentAttrs;   /* ptr to DC attrs structure   */


    CurrentAttrs = &(pdc->DCICurMrkAts);

    if ( (DefMask == ALL_DEFAULTS) &&
         (AttrMask == ALL_DEFAULTS) )
    {
        /**************************************************************/
        /* this is the special case when called by reset DC           */
        /* in order to set all attributes to their defaults           */
        /**************************************************************/
        if ( (pdc->DCICurMrkAts.mbnd.usSymbol !=
                                   DefaultMarkerAttrs.mbnd.usSymbol) ||
             (pdc->DCICurMrkAts.mbnd.usSet !=
                                       DefaultMarkerAttrs.mbnd.usSet) )
        {
            pdc->DCIChanged = (BOOL)(~NOTDEFAULT_MarkAttrs &
                               (pdc->DCIChanged | NEW_MARKER_SYMBOL));
        }
        else
        {
            pdc->DCIChanged &= ~NOTDEFAULT_MarkAttrs;
        }

        memcpy( (PVOID)&(pdc->DCICurMrkAts),
                (PVOID)&DefaultMarkerAttrs,
                sizeof(DMARKERBUNDLE));

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            /**********************************************************/
            /* Foreground Colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->mbnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIMarkColatts.ForeColor = PhyIndex;

            /**********************************************************/
            /* Background Colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->mbnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIMarkColatts.BackColor = PhyIndex;
        }

        return(OK);
    }

    /******************************************************************/
    /* Not using all the default values.  Record this in the DC data  */
    /* and check each attribute to see what needs to change.          */
    /******************************************************************/
    pdc->DCIChanged |= NOTDEFAULT_MarkAttrs;

    /**************************************************************/
    /* Copy the device bundle definitions fields. The fields are  */
    /* the marker set/font, flags and code page (for font).       */
    /**************************************************************/
    CurrentAttrs->mdef = Attributes->mdef;

    /******************************************************************/
    /* Foreground Colour                                              */
    /******************************************************************/
    if (AttrMask & MBB_COLOR)
    {
        CurrentAttrs->mbnd.lColor = (DefMask & MBB_COLOR) ?
                                DefaultMarkerAttrs.mbnd.lColor :
                                Attributes->mbnd.lColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->mbnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIMarkColatts.ForeColor = PhyIndex;
        }

    }

    /******************************************************************/
    /* Background Colour                                              */
    /******************************************************************/
    if (AttrMask & MBB_BACK_COLOR)
    {
        CurrentAttrs->mbnd.lBackColor = (DefMask & MBB_BACK_COLOR) ?
                                    DefaultMarkerAttrs.mbnd.lBackColor :
                                    Attributes->mbnd.lBackColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->mbnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIMarkColatts.BackColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Foreground Mix                                                 */
    /******************************************************************/
    if (AttrMask & MBB_MIX_MODE)
    {
        MixMode = (DefMask & MBB_MIX_MODE) ?
                DefaultMarkerAttrs.mbnd.usMixMode :
                Attributes->mbnd.usMixMode;

        if (MixMode == 0)
        {
            CurrentAttrs->mbnd.usMixMode = DEFAULT_FOREGROUND_MIX;
        }
        else if (MixMode > 0 &&
                 MixMode < NO_OF_FOREGROUND_MIXES &&
                 MixMode != (USHORT)3)
        {
            CurrentAttrs->mbnd.usMixMode = MixMode;
        }
        else
        {
            LogError(PMERR_INV_MIX_ATTR);
            return(ERROR_ZERO);
        }
    }

    /******************************************************************/
    /* Background Mix                                                 */
    /******************************************************************/
    if (AttrMask & MBB_BACK_MIX_MODE)
    {
        MixMode = (DefMask & MBB_BACK_MIX_MODE) ?
              DefaultMarkerAttrs.mbnd.usBackMixMode :
              Attributes->mbnd.usBackMixMode;

        MixMode = GetBackgroundMix(MixMode);
        if ( MixMode == (USHORT)BM_ERROR )
        {
            return(ERROR_ZERO);
        }
        else /* valid background mix */
        {
            CurrentAttrs->mbnd.usBackMixMode = MixMode;
        }
    }

    /******************************************************************/
    /* Marker Set                                                     */
    /******************************************************************/
    if (AttrMask & MBB_SET)
    {
        CurrentAttrs->mbnd.usSet = (DefMask & MBB_SET) ?
                               DefaultMarkerAttrs.mbnd.usSet :
                               Attributes->mbnd.usSet;


        pdc->DCIChanged |= NEW_MARKER_SYMBOL;

        /******************************************************/
        /* Check if simulations are required to output marker */
        /* note: these tests are done on the mdef fields      */
        /* rather than the mbnd fields - this is not an error!*/
        /******************************************************/
        pdc->DCIMarkerSimReq = (BOOL)
          ((pdc->DCICurMrkAts.mdef.fFlags &
             (CDEF_BOLD   | CDEF_STRIKEOUT |
              CDEF_ITALIC | CDEF_UNDERSCORE))    ||
          (pdc->DCICurMrkAts.mdef.defSet &&
             (((PFOCAFONT)pdc->DCICurMrkAts.mdef.defSet)->
                             fmMetrics.fsDefn & FONT_IS_VECTOR)));
    }

    /******************************************************************/
    /* Marker Symbol                                                  */
    /******************************************************************/
    if (AttrMask & MBB_SYMBOL)
    {
        CurrentAttrs->mbnd.usSymbol = (DefMask & MBB_SYMBOL) ?
                                  DefaultMarkerAttrs.mbnd.usSymbol :
                                  Attributes->mbnd.usSymbol;

        pdc->DCIChanged |= NEW_MARKER_SYMBOL;
    }

    /******************************************************************/
    /* Marker Cell Size                                               */
    /******************************************************************/
    if (AttrMask & MBB_BOX)
    {
        CurrentAttrs->mbnd.sizfxCell = (DefMask & MBB_BOX) ?
                                   DefaultMarkerAttrs.mbnd.sizfxCell :
                                   Attributes->mbnd.sizfxCell;
    }


    return(OK);
}






/**********************************************************************/
/* SetPatternAttributes sets the pattern attributes to either a given */
/* value or their default value.                                      */
/* The pattern reference point is stored in AI co-ordinates in the    */
/* DC instance data and is updated as necessary.                      */
/* The current pattern symbol is stored as a bitmap in the DC instance*/
/* data and is changed if necessary.                                  */
/**********************************************************************/

ULONG SetPatternAttributes (ULONG          DefMask,
                            ULONG          AttrMask,
                            PDAREABUNDLE   Attributes)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG              PhyIndex;       /* Physical index              */
    USHORT             MixMode;
    PDAREABUNDLE       CurrentAttrs;   /* ptr to DC attrs structure   */


    CurrentAttrs = &(pdc->DCICurPtnAts);

    if ( (DefMask == ALL_DEFAULTS) &&
         (AttrMask == ALL_DEFAULTS) )
    {
        /**************************************************************/
        /* this is the special case when called by reset DC           */
        /* in order to set all attributes to their defaults           */
        /**************************************************************/
        if ( (pdc->DCICurPtnAts.abnd.usSymbol !=
                                  DefaultPatternAttrs.abnd.usSymbol) ||
             (pdc->DCICurPtnAts.abnd.usSet !=
                                      DefaultPatternAttrs.abnd.usSet) )
        {
            pdc->DCIChanged = (BOOL)(~NOTDEFAULT_PtrnAttrs &
                              (pdc->DCIChanged | NEW_PATTERN_SYMBOL));
        }
        else
        {
            pdc->DCIChanged &= ~NOTDEFAULT_PtrnAttrs;
        }

        memcpy( (PVOID)CurrentAttrs,
                (PVOID)&DefaultPatternAttrs,
                sizeof(DAREABUNDLE));

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            /**********************************************************/
            /* Foreground Colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->abnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIPattColatts.ForeColor = PhyIndex;

            /**********************************************************/
            /* Background Colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->abnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIPattColatts.BackColor = PhyIndex;

        }

        return(OK);
    }


    /******************************************************************/
    /* Not using all the default values.  Record this in the DC data  */
    /* and check each attribute to see what needs to change.          */
    /******************************************************************/
    pdc->DCIChanged |= NOTDEFAULT_PtrnAttrs;

    /******************************************************************/
    /* Foreground Colour                                              */
    /******************************************************************/
    if (AttrMask & ABB_COLOR)
    {
        CurrentAttrs->abnd.lColor = (DefMask & ABB_COLOR) ?
                                DefaultPatternAttrs.abnd.lColor :
                                Attributes->abnd.lColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->abnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIPattColatts.ForeColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Background Colour                                              */
    /******************************************************************/
    if (AttrMask & ABB_BACK_COLOR)
    {
        CurrentAttrs->abnd.lBackColor = (DefMask & ABB_BACK_COLOR) ?
                                    DefaultPatternAttrs.abnd.lBackColor :
                                    Attributes->abnd.lBackColor;
        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->abnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }

            pdc->DCIPattColatts.BackColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Foreground Mix                                                 */
    /******************************************************************/
    if (AttrMask & ABB_MIX_MODE)
    {
        MixMode = (DefMask & ABB_MIX_MODE) ?
              DefaultPatternAttrs.abnd.usMixMode :
              Attributes->abnd.usMixMode;

        if (MixMode == 0)
        {
            CurrentAttrs->abnd.usMixMode = DEFAULT_FOREGROUND_MIX;
        }
        else if (MixMode > 0 &&
                 MixMode < NO_OF_FOREGROUND_MIXES &&
                 MixMode != (USHORT)3)
        {
            CurrentAttrs->abnd.usMixMode = MixMode;
        }
        else
        {
            LogError(PMERR_INV_MIX_ATTR);
            return(ERROR_ZERO);
        }
    }

    /******************************************************************/
    /* BAckground Mix                                                 */
    /******************************************************************/
    if (AttrMask & ABB_BACK_MIX_MODE)
    {
        MixMode = (DefMask & ABB_BACK_MIX_MODE) ?
              DefaultPatternAttrs.abnd.usBackMixMode :
              Attributes->abnd.usBackMixMode;

        MixMode = GetBackgroundMix(MixMode);

        if (MixMode == (USHORT)BM_ERROR)
        {
            return(ERROR_ZERO);
        }
        else /* valid background mix */
        {
            CurrentAttrs->abnd.usBackMixMode = MixMode;
        }
    }

    /******************************************************************/
    /* Pattern Set                                                    */
    /******************************************************************/
    if (AttrMask & ABB_SET)
    {
        /******************************************************/
        /* Copy the device bundle definitions fields. The     */
        /* fields are the pattern set/font/bitmap, flags and  */
        /* code page (for fonts). Actually these are only     */
        /* used the set value is non-zero.                    */
        /******************************************************/
        if (DefMask & ABB_SET)
        {
            CurrentAttrs->abnd.usSet = DefaultPatternAttrs.abnd.usSet;

            CurrentAttrs->adef = DefaultPatternAttrs.adef;
        }
        else
        {
            /**********************************************************/
            /* The pattern must be either the default set, a font or  */
            /* a bitmap.                                              */
            /*                                                        */
            /* If it is a font, we must check that it is a bitmap     */
            /* font, not a vector font.                               */
            /*                                                        */
            /* If it is a font the defset field will either contain a */
            /* value between 1 and 254 (an LCID for an AI format      */
            /* font) or a pointer to a FocaFont.                      */
            /*                                                        */
            /* If it is a bitmap the defset field will contain a far  */
            /* pointer to the bitmap list entry.                      */
            /*                                                        */
            /* We therefore have the problem that if we have a        */
            /* pointer, it could be to a font or a bitmap.  I would   */
            /* imagine that somewhere in the AREABUNDLE there is a    */
            /* bit to tell us this, but it does not seem to be        */
            /* documented.  We therefore work it out ourselves by     */
            /* looking at the first ULONG (4 bytes) of the structure. */
            /* For a FocaFont this is defined to be 0xFFFFFFFE, and   */
            /* for a bitmap this will be a pointer to the actual      */
            /* bitmap bits (which won't be 0xFFFFFFFE!).              */
            /*                                                        */
            /**********************************************************/
            if (CurrentAttrs->abnd.usSet != Attributes->abnd.usSet)
            {
              if ((ULONG)Attributes->abnd.usSet != 0)
              {
#ifdef TMP                                                  
                /*----------------------------------------------------*/
                /* If defSet is NULL, we will assume usSet should be  */
                /* a bitmap LCID and get its handle from engine.      */
                /* (See set_pattern_from_font() in EDDAPTMK.C)        */
                /*----------------------------------------------------*/
                if (Attributes->adef.defSet != NULL)
                {
#endif 
                  if ( ( (ULONG)Attributes->adef.defSet <= MAX_LCID)  ||
                       (*(PULONG)Attributes->adef.defSet == 0xFFFFFFFEL) )
                  {
                      /**************************************************/
                      /* Pattern is from a font, check it is not a      */
                      /* vector font.                                   */
                      /**************************************************/
                      if (((PFOCAFONT)(Attributes->adef.defSet))->
                                             fmMetrics.fsDefn & FONT_IS_VECTOR)
                      {
                          /**********************************************/
                          /* Only Bitmap fonts can be set as a pattern  */
                          /**********************************************/
                          LogError(PMERR_INV_PATTERN_SET_ATTR);
                          return(ERROR_ZERO);
                      }
                  }
#ifdef TMP                                                  
                }
#endif 
              }

              CurrentAttrs->abnd.usSet = Attributes->abnd.usSet;
              CurrentAttrs->adef = Attributes->adef;
              pdc->DCIChanged |= NEW_PATTERN_SYMBOL;
            }
        }
    }

    /******************************************************************/
    /* Pattern Symbol                                                 */
    /******************************************************************/
    if (AttrMask & ABB_SYMBOL)
    {
        if (DefMask & ABB_SYMBOL)
        {
          if (CurrentAttrs->abnd.usSymbol !=
                                     DefaultPatternAttrs.abnd.usSymbol)
          {
            CurrentAttrs->abnd.usSymbol = DefaultPatternAttrs.abnd.usSymbol;
            pdc->DCIChanged |= NEW_PATTERN_SYMBOL;
          }
        }
        else
        {
          if (CurrentAttrs->abnd.usSymbol != Attributes->abnd.usSymbol)
          {
            CurrentAttrs->abnd.usSymbol = Attributes->abnd.usSymbol;
            pdc->DCIChanged |= NEW_PATTERN_SYMBOL;
          }
        }
    }

    /******************************************************************/
    /* Pattern Origin                                                 */
    /******************************************************************/
    if (AttrMask & ABB_REF_POINT)
    {
        CurrentAttrs->abnd.ptlRefPoint = (DefMask & ABB_REF_POINT) ?
                                    DefaultPatternAttrs.abnd.ptlRefPoint :
                                    Attributes->abnd.ptlRefPoint;

        /**************************************************************/
        /* Copy Pattern Reference Point from DCICurPtnAts ( held in   */
        /* world coords ) to DCIPattOrigin ( held in AI coords ).     */
        /* However, we convert it to device coordinates here so that  */
        /* the overflow detection performed by eddg_Convert works     */
        /* OK.                                                        */
        /**************************************************************/
        if ( OK != eddg_Convert (
             (PULONG) &(pdc->DCICurPtnAts.abnd.ptlRefPoint),
             (PULONG) &(pdc->DCIPatternOrigin),
             COORD_WORLD,
             COORD_DEVICE_WORD,
             1,
             COM_TRANSFORM) )
        {
            return (ERROR_ZERO);
        }

        /**************************************************************/
        /* We now convert the pattern origin from device coordinates  */
        /* to AI coordinates. We do not need to worry about           */
        /* overflow because the pattern origin is used MOD the        */
        /* pattern width.                                             */
        /* We also make an adjustment to the Y coordinate because     */
        /* Winthorn refers to the top of the pattern whereas the      */
        /* AI refers to the bottom. We can do this by adding 1        */
        /* (adding 1 is the same as subtracting (pat_height-1).       */
        /**************************************************************/
        pdc->DCIPatternOrigin.Y = pdc->DCIConvFactor -
                                     pdc->DCIPatternOrigin.Y + (USHORT)1;
        pdc->DCIPatternOrigin.X +=pdc->DCIOrigin.X;
    }


    return(OK);
}







/**********************************************************************/
/* SetImageAttributes sets the image attributes to either a given     */
/* value or their default value.                                      */
/**********************************************************************/

ULONG SetImageAttributes (ULONG          DefMask,
                          ULONG          AttrMask,
                          PDIMAGEBUNDLE  Attributes)


{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG              PhyIndex;       /* Physical index              */
    USHORT             MixMode;
    PDIMAGEBUNDLE      CurrentAttrs;   /* ptr to DC attrs structure   */


    CurrentAttrs = &(pdc->DCICurImgAts);

    if ( (DefMask == ALL_DEFAULTS) &&
         (AttrMask == ALL_DEFAULTS) )
    {
        /**************************************************************/
        /* this is the special case when called by reset DC           */
        /* in order to set all attributes to their defaults           */
        /**************************************************************/
        pdc->DCIChanged &= ~NOTDEFAULT_ImagAttrs;

        memcpy( (PVOID)CurrentAttrs,
                (PVOID)&DefaultImageAttrs,
                sizeof(DIMAGEBUNDLE));

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            /**********************************************************/
            /* Foreground Colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->ibnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIImagColatts.ForeColor = PhyIndex;

            /**********************************************************/
            /* Background Colour                                      */
            /**********************************************************/
            PhyIndex = LogToPhyIndex(CurrentAttrs->ibnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIImagColatts.BackColor = PhyIndex;
        }
        return(OK);
    }

    /******************************************************************/
    /* Not using all the default values.  Record this in the DC data  */
    /* and check each attribute to see what needs to change.          */
    /******************************************************************/

    pdc->DCIChanged |= NOTDEFAULT_ImagAttrs;

    /******************************************************************/
    /* Foreground Colour                                              */
    /******************************************************************/
    if (AttrMask & IBB_COLOR)
    {
        CurrentAttrs->ibnd.lColor = (DefMask & IBB_COLOR) ?
                                DefaultImageAttrs.ibnd.lColor :
                                Attributes->ibnd.lColor;
        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->ibnd.lColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_COLOR_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIImagColatts.ForeColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Background Colour                                              */
    /******************************************************************/
    if (AttrMask & IBB_BACK_COLOR)
    {
        CurrentAttrs->ibnd.lBackColor = (DefMask & IBB_BACK_COLOR) ?
                                    DefaultImageAttrs.ibnd.lBackColor :
                                    Attributes->ibnd.lBackColor;

        /**************************************************************/
        /* We can only calculate the correct physical colors if there */
        /* is a bitmap selected into the DC.  (Selecting a bitmap     */
        /* into the DC will cause the physical colors to be           */
        /* recalculated).                                             */
        /**************************************************************/
        if (pdc->DCISelListEntry != NULL)
        {
            PhyIndex = LogToPhyIndex(CurrentAttrs->ibnd.lBackColor);
            if (PhyIndex == CLR_NOPHYINDEX)
            {
                LogError(PMERR_INV_BACKGROUND_COL_ATTR);
                return(ERROR_ZERO);
            }
            pdc->DCIImagColatts.BackColor = PhyIndex;
        }
    }

    /******************************************************************/
    /* Foreground Mix                                                 */
    /******************************************************************/
    if (AttrMask & IBB_MIX_MODE)
    {
        MixMode = (DefMask & IBB_MIX_MODE) ?
              DefaultImageAttrs.ibnd.usMixMode :
              Attributes->ibnd.usMixMode;

        if (MixMode == 0)
        {
            CurrentAttrs->ibnd.usMixMode = DEFAULT_FOREGROUND_MIX;
        }
        else if (MixMode > 0 &&
                 MixMode < NO_OF_FOREGROUND_MIXES &&
                 MixMode != (USHORT)3)
        {
            CurrentAttrs->ibnd.usMixMode = MixMode;
        }
        else
        {
            LogError(PMERR_INV_MIX_ATTR);
            return(ERROR_ZERO);
        }
    }

    /******************************************************************/
    /* Background Mix                                                 */
    /******************************************************************/
    if (AttrMask & IBB_BACK_MIX_MODE)
    {
        MixMode = (DefMask & IBB_BACK_MIX_MODE) ?
              DefaultImageAttrs.ibnd.usBackMixMode :
              Attributes->ibnd.usBackMixMode;

        MixMode = GetBackgroundMix(MixMode);
        if (MixMode == (USHORT)BM_ERROR )
        {
            return(ERROR_ZERO);
        }
        else /* valid background mix */
        {
            CurrentAttrs->ibnd.usBackMixMode = MixMode;
        }
    }


    return(OK);
}
