/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Lexmark Corporation, 1989                                   */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = PRDGCONV
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdg_Convert
 *             prdg_FastConvert
 *             prdg_NotifyTransformChange
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                         /* Convert to C/SET2    CON3201       */
#define INCL_DOSPROCESS                 /* Convert to C/SET2    CON3201       */
#define INCL_DOSSEMAPHORES
#define INCL_GPITRANSFORMS
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_GPIERRORS
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPITRANSFORMS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_GPIERRORS

#define INCL_DDICOMFLAGS
#define INCL_DDIBUNDLES
#define INCL_DDIFONTSTRUCS
#define INCL_DDIDEFS
#define INCL_GRE_XFORMS
#define INCL_DDIMISC
#include <pmddi.h>
#undef INCL_DDICOMFLAGS
#undef INCL_DDIBUNDLES
#undef INCL_DDIFONTSTRUCS
#undef INCL_DDIDEFS
#undef INCL_GRE_XFORMS
#undef INCL_DDIMISC

#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

#include <prdconse.h>
#include <prddcone.h>

#define NO_SYS
#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL
#undef NO_SYS

#include <prdgextf.h>
#include <prdtextf.h>
#include <prdyextf.h>

/******************************************************************************/
/* Set up access to engine convert function                                   */
/******************************************************************************/
extern PFNL  da_Convert;
extern PFNL  da_NotifyTransformChange;

/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdg_Convert                                                   */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   PULONG     SourceXY;  Pointer to list of coordinates passed in           */
/*                         to be converted                                    */
/*   PULONG     TargetXY;  Pointer to list of coordinates returned            */
/*   SHORT     Source;    Flags describing the format of the source          */
/*                         source ...                                         */
/*   SHORT     Target;     ... and target coordinates (ie SHORT or          */
/*                         ULONG and World or Device)                         */
/*   SHORT     ncoord;    The number of coordinates to convert               */
/*   hanDC      DcH;       Handle to DC                                       */
/*   SHORT     Command;   Command word                                       */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function provides a common interface between the printer            */
/*   driver and the engine function GreConvert.  Each coordinate pair         */
/*   is converted into the correct format (ULONG) if necessary and            */
/*   passed to GreConvert.  The result of GreConvert is then                  */
/*   converted to the required format and stored.                             */
/*                                                                            */
/******************************************************************************/
#if 0
SHORT pascal prdg_Convert ( SourceXY, TargetXY, Source, Target,
                             ncoord, DcH, Command)

PULONG      SourceXY;
PULONG      TargetXY;
SHORT      Source;
SHORT      Target;
SHORT      ncoord;
hanDC       DcH;
SHORT      Command;
#endif

USHORT prdg_Convert ( PULONG SourceXY,                             /* CON3201 */
                      PULONG TargetXY,                             /* CON3201 */
                      USHORT Source,                               /* CON3201 */
                      USHORT Target,                               /* CON3201 */
                      USHORT ncoord,                               /* CON3201 */
                      hanDC  DcH,                                  /* CON3201 */
                      ULONG  Command )                             /* CON3201 */

{
#define TFUNC "prdg_Convert"
    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    SHORT        i;            /* Loop control variable              */
    WcsPoint      lcCoord;      /* A pair of coordinates stored as    */
                                /* long words used for passing and    */
                                /* returning values from the engine   */
                                /* function                           */
    DevPoint     *pTemp1;       /* CON3201 : temp pointer             */
    WcsPoint     *pTemp2;       /* CON3201 : temp pointer             */

    /**************************************************************************/
    /* Trace the input parameters                                             */
    /**************************************************************************/
    TRACE4(TFUNC, "SourceXY", SourceXY, 2);
    TRACE4(TFUNC, "TargetXY", TargetXY, 2);
    TRACE4(TFUNC, "Source", &Source, 1);
    TRACE4(TFUNC, "Target", &Target, 1);
    TRACE4(TFUNC, "ncoord", &ncoord, 1);
    TRACE4(TFUNC, "DcH", &DcH, 1);
    TRACE4(TFUNC, "Command", &Command, 1);

    /**************************************************************************/
    /* Convert each pair of co-ordinates separately.                          */
    /**************************************************************************/
    for (i = 0; i < ncoord; i++)
    {

        TRACE4(TFUNC, "SourceXY", SourceXY, 2);

        if (Source & COORD_WORD)
        {
            /******************************************************************/
            /* The source coordinates are in word format so cast them to long */
            /* words to pass them to the engine.                              */
            /******************************************************************/
         /* lcCoord.X = (LONG) (((DevPoint far *)SourceXY)->X); */
         /* lcCoord.Y = (LONG) (((DevPoint far *)SourceXY)->Y); */
            lcCoord.X = (LONG) (((DevPoint *)SourceXY)->X);        /* CON3201 */
            lcCoord.Y = (LONG) (((DevPoint *)SourceXY)->Y);        /* CON3201 */

            /******************************************************************/
            /* Increment the pointer to the list of coordinates to convert to */
            /* the next coordinate when the coordinates are word length.      */
            /******************************************************************/
         /* ++((DevPoint far *)SourceXY); */
            pTemp1   = ((DevPoint *)SourceXY);                     /* CON3201 */
            ++pTemp1;                                              /* CON3201 */
            SourceXY = (PULONG)pTemp1;                             /* CON3201 */
        }
        /*.. if (Source & COORD_WORD) ................................*/

        else
        {
            /******************************************************************/
            /* The source coordinates are in long word format so just assign  */
            /* them to lcCoord.                                               */
            /******************************************************************/
         /* lcCoord = *((WcsPoint far *)SourceXY); */
            lcCoord = *((WcsPoint *)SourceXY);                     /* CON3201 */

            /******************************************************************/
            /* Increment the pointer to the list of coordinates to convert to */
            /* the next coordinate when the coordinates are long word length. */
            /******************************************************************/
         /* ++((WcsPoint far *)SourceXY); */
            pTemp2   = ((WcsPoint *)SourceXY);                     /* CON3201 */
            ++pTemp2;                                              /* CON3201 */
            SourceXY = (PULONG)pTemp2;                             /* CON3201 */
        }
        /*.. else ! (Source & COORD_WORD) ............................*/

        TRACE4(TFUNC, "lcCoordXY", &lcCoord, 2);

        /**********************************************************************/
        /* If the COM_TRANSFORM bit is set then do the transform.  Call the   */
        /* engine convert function to do the conversion.  Use a mask on Source*/
        /* and Target to leave only the correct values (ie remove our         */
        /* COORD_WORD bit from it).  Ask the engine to convert one value only */
        /* and there is no need to pass pointer to DC Instance data becasue   */
        /* the function will be dealt with internally in the engine.  Ensure  */
        /* that the correct function number is passed for the engines dispatch*/
        /* table.                                                             */
        /**********************************************************************/
        if (Command & COM_TRANSFORM)
        {
            if ( !da_Convert ( DcH,
                               (ULONG)(Source & COORD_TYPE_MASK),
                               (ULONG)(Target & COORD_TYPE_MASK),
                            /* (WcsPoint far *)&lcCoord, */
                               (WcsPoint *)&lcCoord,               /* CON3201 */
                               1L,
                               0L,
                               NGreConvert) )
                return(ERROR_ZERO);
        }
        /*.. if (Command & COM_TRANSFORM) ............................*/

        TRACE4(TFUNC, "lcCoordXY", &lcCoord, 2);

        if (Target & COORD_WORD)
        {
            /******************************************************************/
            /* The target coordinates are in word format so cast the result   */
            /* from the engine function to assign it to the target.           */
            /******************************************************************/
            /* PD00703 : Check size of coordinates before converting to short */
            /******************************************************************/
            /* PD00767 : Correct check to allow -32768                        */
            /******************************************************************/
            if ( ( lcCoord.X <= 32767 ) && ( lcCoord.X >= -32768  ) &&
                 ( lcCoord.Y <= 32767 ) && ( lcCoord.Y >= -32768  )    )
            {
             /* ((DevPoint far *)TargetXY)->X = (INT)lcCoord.X; */
             /* ((DevPoint far *)TargetXY)->Y = (INT)lcCoord.Y; */
                ((DevPoint *)TargetXY)->X = (INT)lcCoord.X;        /* CON3201 */
                ((DevPoint *)TargetXY)->Y = (INT)lcCoord.Y;        /* CON3201 */
                /**************************************************************/
                /* Increment the pointer to the list of coordinates which are */
                /* being retruned when these coordinates are word length.     */
                /**************************************************************/
             /* ++((DevPoint far *)TargetXY); */
                pTemp1   = ((DevPoint *)TargetXY);                 /* CON3201 */
                ++pTemp1;                                          /* CON3201 */
                TargetXY = (PULONG)pTemp1;                         /* CON3201 */
            }
            else                                /* PD00703  coords too large          */
            {
                /**************************************************************/
                /* PD00703 : Log error when coordinate exceeds 32767          */
                /* PD00767 : or less than -32768                              */
                /**************************************************************/
                LOGERR(TFUNC,"Coord Overflow", &lcCoord, 1,
                                                    PMERR_COORDINATE_OVERFLOW);
                return((SHORT)ERROR_ZERO);
            }
         }
         /*.. if (Target & COORD_WORD) ...............................*/

         else
         {
            /******************************************************************/
            /* The target coordinates are in long word format so simply assign*/
            /* the coordinates from the engine to them.                       */
            /******************************************************************/
         /* (*(WcsPoint far *)TargetXY) = lcCoord; */
            (*(WcsPoint *)TargetXY) = lcCoord;                     /* CON3201 */

            TRACE4(TFUNC, "TargetXY", TargetXY, 2);

            /******************************************************************/
            /* Increment the pointer to the list of coordinates which are     */
            /* being retruned when these coordinates are long word length.    */
            /******************************************************************/
         /* ++((WcsPoint far *)TargetXY);     increment coord pointer */
            pTemp2   = ((WcsPoint *)TargetXY);                     /* CON3201 */
            ++pTemp2;                                              /* CON3201 */
            TargetXY = (PULONG)pTemp2;                             /* CON3201 */
        }
        /*.. else ! (Target & COORD_WORD) ............................*/

    }
    /*.. for (i = 0; i < ncoord; i++) ................................*/

    TRACE4(TFUNC, "Return OK", FNULL, 0);
    return((SHORT)OK);
}
#undef TFUNC


/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdg_FastConvert                                               */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   WcsPoint far *SourceXY;   Coordinates to be converted (in World)         */
/*   DevPoint far *TargetXY;   Coordinates returned (in Device)               */
/*   hanDC        DcH;         DC handle                                      */
/*   SHORT       Command;     Command word                                   */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function provides a fast conversion between one set of              */
/*   coordinates in World coordinates and their equivalent in Device          */
/*   coordinates.                                                             */
/*                                                                            */
/******************************************************************************/
#if 0
SHORT pascal prdg_FastConvert (SourceXY, TargetXY, DcH, Command)

WcsPoint far *SourceXY;
DevPoint far *TargetXY;
hanDC        DcH;
SHORT       Command;
#endif

USHORT prdg_FastConvert ( WcsPoint *SourceXY,
                          DevPoint *TargetXY,
                          hanDC     DcH,
                          ULONG     Command )

{
#define TFUNC "prdg_FastConvert"
    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    WcsPoint      lcCoord;      /* A pair of coordinates stored as    */
                                /* long words used for passing and    */
                                /* returning values from the engine   */
                                /* function                           */

    /**************************************************************************/
    /* Trace the input parameters                                             */
    /**************************************************************************/
    TRACE4(TFUNC, "SourceXY", SourceXY, 2);
    TRACE4(TFUNC, "TargetXY", TargetXY, 2);
    TRACE4(TFUNC, "DcH", &DcH, 1);
    TRACE4(TFUNC, "Command", &Command, 1);

    /**************************************************************************/
    /* Input coordinates are World so simply assign them to lcCoord           */
    /**************************************************************************/
    lcCoord.X = SourceXY->X;
    lcCoord.Y = SourceXY->Y;

    TRACE4(TFUNC, "lcCoordXY", &lcCoord, 2);

    /**************************************************************************/
    /* If the COM_TRANSFORM bit is set then do the transform.  Call the engine*/
    /* to do the convert function specifying the source coordinates as World  */
    /* and the target coordainates as Device and ask it to do only 1          */
    /* conversion.                                                            */
    /**************************************************************************/
    if (Command & COM_TRANSFORM)
    {
        if ( !da_Convert ( DcH,
                           CVTC_WORLD,
                           CVTC_DEVICE,
                        /* (WcsPoint far *)&lcCoord, */
                           (WcsPoint *)&lcCoord,                   /* CON3201 */
                           1L,
                           0L,
                           NGreConvert) )
            return(ERROR_ZERO);
    }
    /*.. if (Command & COM_TRANSFORM) ................................*/

    TRACE4(TFUNC, "lcCoordXY", &lcCoord, 2);

    /**************************************************************************/
    /* Target coordinates are Device so cast the result of the engine         */
    /* function.                                                              */
    /**************************************************************************/
    /* PD00525 : Check size of coordinates before converting to short type    */
    /**************************************************************************/
    /* PD00767 : Correct check to allow -32768                                */
    /**************************************************************************/
    if ( ( lcCoord.X <= 32767 ) && ( lcCoord.X >= -32768  ) &&
         ( lcCoord.Y <= 32767 ) && ( lcCoord.Y >= -32768  )    )
    {
        /**********************************************************************/
        /* Only update the target coordinates when they will fit in a Short   */
        /* variable.                                                          */
        /**********************************************************************/
        /* PD00767 : Change from USHORT to SHORT                              */
        /**********************************************************************/
        TargetXY->X = (SHORT)lcCoord.X;
        TargetXY->Y = (SHORT)lcCoord.Y;
    }
    else                                /* PD00589  coords too large          */
    {
        /**********************************************************************/
        /* PD00589 : Log error when coordinate exceeds 32767                  */
        /* PD00767 : or less than -32768                                      */
        /**********************************************************************/
        LOGERR(TFUNC,"Coord Overflow", &lcCoord, 1, PMERR_COORDINATE_OVERFLOW);
        return((SHORT)ERROR_ZERO);
    }


    TRACE4(TFUNC, "TargetXY", TargetXY, 2);

    TRACE4(TFUNC, "Return OK", FNULL, 0);
    return((SHORT)OK);
}
#undef TFUNC


#define TFUNC "prdg_NotifyXfrm Change"
/******************************************************************************/
/*                                                                            */
/*   FUNCTION: prdg_NotifyTransformChange                                     */
/*                                                                            */
/*   PARAMETERS:                                                              */
/*                                                                            */
/*   hanDC        DcH;         DC handle                                      */
/*   ULONG        Flags;       Information about Data                         */
/*   ULONG        Data;        Transformation matrix                          */
/*   lpDCI        DCIData;     Device context pointer                         */
/*   ULONG        FunN;        Command word and function number               */
/*                                                                            */
/*   DESCRIPTION:                                                             */
/*                                                                            */
/*   This function is called whenever the PageViewport transformation         */
/*   changes. The device driver updates the device coordinate                 */
/*   current position and pattern origin then calls the default               */
/*   handler to do the rest                                                   */
/*                                                                            */
/******************************************************************************/
#if 0
ULONG pascal far _loadds prdg_NotifyTransformChange(DcH,

                                            Flags,
                                            Data,
                                            DCIData,
                                            FunN)

hanDC DcH;
ULONG Flags;
ULONG Data;
lpDCI DCIData;
ULONG FunN;

#endif

ULONG prdg_NotifyTransformChange( hanDC DcH,                       /* CON3201 */
                                  ULONG Flags,                     /* CON3201 */
                                  ULONG Data,                      /* CON3201 */
                                  lpDCI DCIData,                   /* CON3201 */
                                  ULONG FunN)                      /* CON3201 */

{
    /**************************************************************************/
    /* Local variables                                                        */
    /**************************************************************************/
    WcsPoint ConvCoords[2];
    XFORM    xfm;
    PNOTIFYTRANSFORMDATA  dptr;


    prdm_EnterDriver(DCIData);
    ConvCoords[0] = DCIData->DCICurrPosWcs;
    ((PPOINTL)ConvCoords)[1] = DCIData->DCICurPtnAts->abnd.ptlRefPoint;

    /**************************************************************************/
    /* convert current position and pattern origin from world to device space */
    /**************************************************************************/
    if ( !da_Convert ( DcH,
                       CVTC_WORLD,
                       CVTC_DEVICE,
                    /* (WcsPoint far *)ConvCoords, */
                       (WcsPoint *)ConvCoords,                     /* CON3201 */
                       (ULONG)2,
                       (ULONG)0,
                       NGreConvert) )
    {
        prdm_LeaveDriver(DCIData);
        return(ERROR_ZERO);
    }

    /**************************************************************************/
    /* if the new device current position is bigger than 16 bits then we have */
    /* an error                                                               */
    /**************************************************************************/
/* CON3201
**  if ( (SELECTOROF(ConvCoords[0].X) &&
**       (SELECTOROF(ConvCoords[0].X) != -1)) ||
**       (SELECTOROF(ConvCoords[0].Y) &&
**       (SELECTOROF(ConvCoords[0].Y) != -1)) )
*/

/* CON3201 - changed from SELECTOROF to HIUSHORT because the condition was */
/*           always testing to true and giving us an error.  This is due   */
/*           to the way that SELECTOROF is defined                         */
    if ( (HIUSHORT(ConvCoords[0].X) &&
         (HIUSHORT(ConvCoords[0].X) != (USHORT)-1)) ||
         (HIUSHORT(ConvCoords[0].Y) &&
         (HIUSHORT(ConvCoords[0].Y) != (USHORT)-1)) )
    {
        prdm_LeaveDriver(DCIData);
        LOGERR(TFUNC, "Coordinate out of range", FNULL, 0,
                                            PMERR_COORDINATE_OVERFLOW);
        return(ERROR_ZERO);
    }


    /**************************************************************************/
    /* everything OK so copy new device coordinates to DC instance            */
    /**************************************************************************/
    DCIData->DCICurrPosDev.X = (SHORT)ConvCoords[0].X;
    DCIData->DCICurrPosDev.Y = (SHORT)ConvCoords[0].Y;
    DCIData->DCIPattOriDev.X = (SHORT)ConvCoords[1].X;
    DCIData->DCIPattOriDev.Y = (SHORT)ConvCoords[1].Y;

    /**************************************************************************/
    /* Current font coords have been invalidated ...                          */
    /**************************************************************************/
    DCIData->DCIStateFlags &= ~FONT_COORDS_VALID;

    /**************************************************************************/
    /* Get the new world-device transform matrix.  PD00073                    */
    /**************************************************************************/
    dptr = (PNOTIFYTRANSFORMDATA)Data;
    xfm =  dptr->xform;

    /**************************************************************************/
    /* Only rescale the character box if the world-device scaling is          */
    /* different.  Ignore origin changes.  Possibly ignore rotation &         */
    /* shearing.  PD00073                                                     */
    /**************************************************************************/
    if ( !( (DCIData->DCITransformFlags & MATRIX_UNITS) &&
                            (Flags & MATRIX_UNITS) ) )
        /**********************************************************************/
        /* Different scaling - rescale the charbox.                           */
        /**********************************************************************/
    {
      if ( prdg_MatrixScaleDifferent( DCIData->DCITransform, xfm ) )
      {
        /**********************************************************************/
        /* Need to rescale the Character Box.  Use old and new transforms to  */
        /* calculate new transform.  This subroutine will also be called by   */
        /* RestoreDC is a rescaling is required.                              */
        /**********************************************************************/
        prdt_RescaleCharBox( DCIData, DCIData->DCITransform, xfm );

      }
    }
    /**************************************************************************/
    /* Save the new world-device transformation matrix.  PD00073              */
    /**************************************************************************/
    DCIData->DCITransform = xfm;
    DCIData->DCITransformFlags = (SHORT)Flags;

    prdm_LeaveDriver(DCIData);
    return( da_NotifyTransformChange(DcH,
                                     Flags,
                                     Data,
                                     DCIData,
                                     FunN) );
}

#undef TFUNC
