/*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 = PRDCCTAB
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS  prdc_CreateLogColorTable
 *            prdc_RealizeColorTable
 *            prdc_UnRealizeColorTable
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                    /* CON3201 */
#define INCL_DOSPROCESS            /* CON3201 */
#define INCL_DOSSEMAPHORES
#define INCL_GPILOGCOLORTABLE
#define INCL_GPIERRORS
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#include <os2.h>
#undef INCL_DOSPROCESS             /* CON3201 */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPILOGCOLORTABLE
#undef INCL_GPIERRORS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS

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

#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI

#include <prdccone.h>
#include <prddcone.h>

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

#include <prdcextf.h>
#include <prdconse.h>
#include <prdgextf.h>
#include <prdyextf.h>

/******************************************************************************/
/*  Set up access to the default color table                                  */
/******************************************************************************/
extern DefaultColorTableType  DefaultColorTable;

/******************************************************************************/
/*  FUNCTION: prdc_CreateLogcolorTable                                        */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  See "OS/2 Technical Reference: I/O Subsytems and Device Drivers"          */
/*                                                                            */
/*  hanDC   DcH;                                                              */
/*  ULONG   ArgOptions;                                                       */
/*  ULONG   ArgFormat;                                                        */
/*  ULONG   ArgStart;                                                         */
/*  ULONG   ArgCount;                                                         */
/*  PULONG  ArgData;                                                          */
/*  lpDCI   IData;                                                            */
/*  ULONG   FunN;                                                             */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function defines the entries in the logical color table.  There are a*/
/*  number of options which can be specified in ArgOptions and the format that*/
/*  the new values are to be supplied in is specified in ArgFormat.  The      */
/*  logical colors can either be supplied as a sequential sub-set of the      */
/*  logical color table (in which case they are simply loaded into the correct*/
/*  sequence of locations in the logical color table) or they can be supplied */
/*  as a set of indexes and logical colors (in which case they are loaded into*/
/*  the logical color table according to their indexes).  In the case of a    */
/*  monochrome printer the 0'th entry in the logical color table is mapped to */
/*  the default background color (white for a printer) along with any other   */
/*  entries with the same physical RGB values and all other entries are mapped*/
/*  to the default foreground color (black for a printer).                    */
/*                                                                            */
/*  CHANGES:                                                                  */
/*                                                                            */
/*  The scheme here is for a monochrome printer.  To take advantage of color  */
/*  printers a different mapping will have to be introduced between logical   */
/*  RGB values in the color table and the physical entries.  A subroutine to  */
/*  map logical RGB values to the physical values available on the device is a*/
/*  possibility.  Note however that it is desirable that the physical color   */
/*  produced by index 0 in the logical color table should be distinct from the*/
/*  physical colors produced by all the other indexes unless an index in the  */
/*  logical color table has exactly the same RGB value as index 0.  This is to*/
/*  ensure that two distinguishable colors are not mapped to the same color if*/
/*  this color is the background color - which index 0 is taken to be.        */
/******************************************************************************/
ULONG EXPENTRY prdc_CreateLogColorTable(  hanDC   DcH,
                                          ULONG   ArgOptions,
                                          ULONG   ArgFormat,
                                          ULONG   ArgStart,
                                          ULONG   ArgCount,
                                          PULONG  ArgData,
                                          lpDCI   IData,
                                          ULONG   FunN)

{
#define TFUNC "prdc_CreateLogColorTable"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    USHORT        Size;                /* Size of color table needed after    */
                                       /* function                            */
    USHORT        Index;               /* Index into the color table          */
    USHORT        i;                   /* Loop counter                        */
/*  USHORT        Command;    */       /* CON3201                             */
    ULONG         Command;             /* command from FunN                   */
    lpColorTable  NewTable;            /* Pointer to the color table to be    */
                                       /* updated (may be a new table or the  */
                                       /* current one)                        */
    USHORT        Count;               /* Count of the number of colors       */
                                       /* supplied in the call                */
    lpDDTType     pDDT;                /* Pointer to DDT in PDB               */
    USHORT        Contrast;            /* index for contrast to RGB reset     */

    /**************************************************************************/
    /*  Trace the parameters                                                  */
    /**************************************************************************/
    TRACE8(TFUNC, "Options", &ArgOptions, 1);
    TRACE8(TFUNC, "Format", &ArgFormat, 1);
    TRACE8(TFUNC, "Start", &ArgStart, 1);
    TRACE8(TFUNC, "Count", &ArgCount, 1);
    TRACE8(TFUNC, "&Data", &ArgData, 1);
    TRACE8(TFUNC, "DcH", &DcH, 1);
    TRACE8(TFUNC, "FunN", &FunN, 1);

    /******************************************************************/
    /* Do entry processing                                            */
    /******************************************************************/
#ifdef PRD_TIMING
    DEKHOOK0(A,7,0D)
#endif
    GetCommand(IData);
    prdm_ValidatePath;
    prdm_ValidateArea;
    prdm_EnterDriver(IData);
    pDDT = &(IData->DCIPdbInstance->DDT);

    /**************************************************************************/
    /*  If the new mode is RGB then different approach is required            */
    /**************************************************************************/
    if (ArgFormat == LCOLF_RGB)
    {

        /**********************************************************************/
        /*  If there was a previous color table then free its memory and set */
        /*  the DCIColFormat to indicate indexes are RGB values and set the   */
        /*  size, low index and high index to the color table to 0 as it does*/
        /*  not exist in this mode.                                           */
        /*                                                                    */
        /*  PD00315 : Need to check to see if the memory has already been     */
        /*  freed...                                                          */
        /**********************************************************************/
        if ((IData->DCIColFormat != LCOLF_RGB) &&
            (IData->DCIColorTable != FNULL))
        {
            TRACE4(TFUNC, "Free Old Table", FNULL, 0);
            (VOID)prdg_FreeHeapItem(IData,
                                  IData->DCIColTabSize * sizeof(ColorTableType),
                                  (PUSHORT)IData->DCIColorTable);
            IData->DCIColorTable = FNULL; /* PD00315 : Null the pointer...    */
        }
        IData->DCIColFormat  = (USHORT)LCOLF_RGB;
        IData->DCIColTabSize = 0;
        IData->DCILowIndex   = 0;
        IData->DCIHighIndex  = 0;
        IData->DCIColOptions = ArgOptions;
        prdm_LeaveDriver(IData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,8D)
#endif
        return(OK);
    }
    else
    {
        if ((ArgFormat != LCOLF_INDRGB) && (ArgFormat != LCOLF_CONSECRGB))
        {
            LOGERR(TFUNC, "Invalid Format", FNULL, 0, PMERR_INV_COLOR_FORMAT);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,8D)
#endif
            return((ULONG)ERROR_ZERO);
        }

        /**********************************************************************/
        /*  Force a rest if changing to index mode                            */
        /**********************************************************************/
        if (IData->DCIColFormat == (USHORT)LCOLF_RGB)
            ArgOptions |= LCOL_RESET;
    }

    /**************************************************************************/
    /*  NewTable points to the table which is to be updated.  Assume it will  */
    /*  be the current table.                                                 */
    /**************************************************************************/
    NewTable = IData->DCIColorTable;

    /**************************************************************************/
    /*  Calculate the size of the color table required given the new data.    */
    /*  Count is the number of entries for the color table supplied by the    */
    /*  call so if the format of the supplied data is indexes and values the  */
    /*  number of entries will be half the number of arguments.               */
    /**************************************************************************/
    Count = (USHORT)ArgCount;
    if (ArgFormat == LCOLF_INDRGB)
    {
        Count /= 2;
    }
    TRACE4(TFUNC, "Count", &Count, 1);

    /**************************************************************************/
    /*  Take the current size as a starting point for the size calculations.  */
    /**************************************************************************/
    Size = IData->DCIColTabSize;

    /**************************************************************************/
    /*  If the table is to be reset to its default values use the default size*/
    /**************************************************************************/
    if (ArgOptions & LCOL_RESET)
    {
        Size = DEF_COL_TABLE_SIZE;
    }

    /**************************************************************************/
    /*  PD00255 : Handle the LCOL_REALIZABLE flag here...                     */
    /**************************************************************************/
    if (ArgOptions & LCOL_REALIZABLE)
        LOGWARNING(TFUNC, "Not Supported", FNULL, 0,
                   PMERR_REALIZE_NOT_SUPPORTED);

    /**************************************************************************/
    /*  If indexes and values have been supplied then step through all the    */
    /*  indexes supplied to find the largest (if it exceeds the size of the   */
    /*  current table)                                                        */
    /*                                                                        */
    /*  CODE1 : Put brackets around arm of IF when the following statement is */
    /*  a FOR loop.                                                           */
    /**************************************************************************/
    if (ArgFormat == LCOLF_INDRGB)
    {
        for (i = 0; i < Count; i++)
        {
            Index = (USHORT)ArgData[2 * i];
            if (Size <= Index)
                Size = Index + 1;
        }
    }

    /**************************************************************************/
    /*  If a consecutive sequence of color values has been supplied then the  */
    /*  maximum index is the start plus the length.  If this is larger than   */
    /*  the current table then take this for the size.                        */
    /*                                                                        */
    /*  PD00126 : check for negative ArgStart                                 */
    /**************************************************************************/
    if (ArgFormat == LCOLF_CONSECRGB)
    {
        if ((LONG)ArgStart < 0)
        {
            LOGERR(TFUNC, "Start index", &ArgStart, 1,PMERR_INV_COLOR_START_INDEX);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,8D)
#endif
            return(ERROR_ZERO);
        }
        if (Size < (USHORT)ArgCount + (USHORT)ArgStart)
            Size = (USHORT)ArgCount + (USHORT)ArgStart;
    }
    TRACE4(TFUNC, "Table Size", &Size, 1);

    /**************************************************************************/
    /*  Check that Size (= largest index) is within valid range               */
    /**************************************************************************/
    if (Size > MAX_COLOR_INDEX + 1)
    {
        LOGERR(TFUNC, "Color Table Size", &Size, 1, PMERR_INV_LENGTH_OR_COUNT);
        prdm_LeaveDriver(IData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,8D)
#endif
        return(ERROR_ZERO);
    }

    /**************************************************************************/
    /*  Allocate memory for new color table if required (ie if the the size   */
    /*  has changed or if the table has been reset)                           */
    /**************************************************************************/
    if (Size > IData->DCIColTabSize || ArgOptions & LCOL_RESET)
    {
        if (prdg_AllocHeapItem(IData, Size * sizeof(ColorTableType),
                                (PUSHORT *)&NewTable) != OK)
        {
            prdm_LeaveDriver(IData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,8D)
#endif
            return(ERROR_ZERO);
        }

        /**********************************************************************/
        /*  Set the logical RGBs in the new table to -1                       */
        /**********************************************************************/
        for (i = 0; i < Size; i++)
            NewTable[i].LogRGB = 0xFFFFFFFFL;

        /**********************************************************************/
        /*  Copy old table to new if required (it will not be necessary if the*/
        /*  table is to be set to its default value and it will not be        */
        /*  possible if the previous mode had RGB values as the indexes and no*/
        /*  color table).                                                     */
        /**********************************************************************/
        if (!(ArgOptions & LCOL_RESET) && IData->DCIColFormat != LCOLF_RGB)
        {
            for (i = 0; i < IData->DCIColTabSize; i++)
            {
                NewTable[i].LogRGB = IData->DCIColorTable[i].LogRGB;
            }
        }

        /**********************************************************************/
        /*  If a table had previously been established then free the memory it*/
        /*  occupied.                                                         */
        /*                                                                    */
        /*  PD00315 : Make sure the memory's there to free... check to see if */
        /*  the DCIColorTable is null.                                        */
        /**********************************************************************/
        if ((IData->DCIColFormat != LCOLF_RGB) &&
            (IData->DCIColorTable != FNULL))
        {
            TRACE4(TFUNC, "Free Old Table", FNULL, 0);
            (VOID)prdg_FreeHeapItem(IData,
                                  IData->DCIColTabSize * sizeof(ColorTableType),
                                  (PUSHORT)IData->DCIColorTable);
            IData->DCIColorTable = FNULL; /* PD00315 : Null the pointer.      */
        }
    }

    /**************************************************************************/
    /*  If reset to default values required then do so from the external      */
    /*  default color table.                                                  */
    /**************************************************************************/
    if (ArgOptions & LCOL_RESET)
    {
        TRACE4(TFUNC, "Default Reset", FNULL, 0);
        for (i = 0; i < DEF_COL_TABLE_SIZE; i++)
        {
            NewTable[i].LogRGB = DefaultColorTable[i];
        }
        if (Size == DEF_COL_TABLE_SIZE)
        {

            /******************************************************************/
            /*  Table has been reset to default so indicate this in           */
            /*  DCIColFormat.                                                 */
            /******************************************************************/
            IData->DCIColFormat = (USHORT)LCOLF_DEFAULT;
        }

        /**********************************************************************/
        /*  DCILowIndex and DCIHighIndex are the lowest and highest index of  */
        /*  colors in the color table excluding                               */
        /**********************************************************************/
        IData->DCILowIndex  = 0;
        IData->DCIHighIndex = DEF_COL_TABLE_SIZE - 1;
    }

    /**************************************************************************/
    /*  Set the format to show that it is not the default color table in      */
    /*  operation.                                                            */
    /**************************************************************************/
    if (ArgCount > 0)
        IData->DCIColFormat = (USHORT)LCOLF_INDRGB;

    /**************************************************************************/
    /*  Enter the values supplied in the call into the color table allowing   */
    /*  for the two possible formats they may be supplied in                  */
    /**************************************************************************/
    for (i = 0, Index = (USHORT)ArgStart; i < Count; i++, Index++)
    {
        if (ArgFormat == LCOLF_INDRGB)
        {

            /******************************************************************/
            /*  This is index and value format so find the index and use it to*/
            /*  enter the value                                               */
            /******************************************************************/
            Index = (USHORT)ArgData[2 * i];
            NewTable[Index].LogRGB = ArgData[2 * i + 1];
        }
        else
        {

            /******************************************************************/
            /*  The 'for' loop is set up to work in sequential value format so*/
            /*  this is a simple assignment                                   */
            /******************************************************************/
            NewTable[Index].LogRGB = ArgData[i];
        }

        /**********************************************************************/
        /*  Keep DCILowIndex and DCIHighIndex up to date                      */
        /**********************************************************************/
        if (Index > IData->DCIHighIndex)
            IData->DCIHighIndex = Index;
    }
    TRACE4(TFUNC, "Table", NewTable, 2 * Size);

    /**************************************************************************/
    /*  Calculate the physical RGBs for the device which correspond to the    */
    /*  logical values.                                                       */
    /**************************************************************************/
    TRACE4(TFUNC, "DevTable", pDDT->DDTDevColorTable->Colors, 8);
    TRACE4(TFUNC, "Calc Phys RGBs", FNULL, 0);
    if (pDDT->DDTMaxColors == DDT_TWO_COLORS)
    {

        /**********************************************************************/
        /*  On a monochrome printer index 0 in the color table is the reset   */
        /*  color.  All other indices have a contrast RGB unless they are the */
        /*  reset RGB.                                                        */
        /*                                                                    */
        /*  On a color printer this mapping should be changed to allow for all*/
        /*  the colors the device can produce.                                */
        /**********************************************************************/
        if (NewTable[0].LogRGB == RGB_BLACK)
        {
            NewTable[0].PhysRGB = pDDT->DDTDevColorTable->
                                                         Colors[PRD_FOREGROUND];
            Contrast = PRD_BACKGROUND;
        }
        else
        {
            NewTable[0].PhysRGB = pDDT->DDTDevColorTable->
                                                         Colors[PRD_BACKGROUND];
            Contrast = PRD_FOREGROUND;
        }
        for (i = 1; i < Size; i++)
            if (NewTable[i].LogRGB == RGB_WHITE)
                NewTable[0].PhysRGB = pDDT->DDTDevColorTable->
                                                         Colors[PRD_BACKGROUND];
            else
                if (NewTable[i].LogRGB == NewTable[0].LogRGB)
                    NewTable[i].PhysRGB = NewTable[0].PhysRGB;
                else
                    NewTable[i].PhysRGB = pDDT->DDTDevColorTable->
                                                               Colors[Contrast];
    }
    else
        if (pDDT->DDTMaxColors == DDT_EIGHT_COLORS )
        {

            for (i = 0; i < Size; i++)
                 NewTable[i].PhysRGB = pDDT->DDTDevColorTable->
                               Colors[prdc_RGBColorToPelBits(NewTable[i].LogRGB,
                               pDDT->DDTDevColorTable)];
        }

    TRACE4(TFUNC, "Table", NewTable, 2*Size);

    /**************************************************************************/
    /*  Include the new table in the DC Instance data                         */
    /**************************************************************************/
    IData->DCIColorTable = NewTable;
    IData->DCIColTabSize = Size;
    IData->DCIColOptions = ArgOptions;
    TRACE4(TFUNC, "Return OK", FNULL, 0);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,8D)
#endif
    prdm_LeaveDriver(IData);
    return(OK);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdc_RealizeColorTable (not supported)                          */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/******************************************************************************/
ULONG EXPENTRY prdc_RealizeColorTable( hanDC  DcH,
                                       lpDCI  DCIData,
                                       ULONG  FunN)

{
#define TFUNC "prdc_RealizeColorTable"

    TRACE8(TFUNC, "DcH", &DcH, 1);
    TRACE8(TFUNC, "FunN", &FunN, 1);

    /**************************************************************************/
    /*  Color table cannot be realized.                                       */
    /*                                                                        */
    /*  PD00255 : Change from a warning to an error.  Also changed error being*/
    /*  reported to reflect OS/2 documentation.                               */
    /**************************************************************************/
    LOGERR(TFUNC, "Not Supported", FNULL, 0, PMERR_COL_TABLE_NOT_REALIZABLE);
    return(ERROR_ZERO);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdc_UnRealizeColorTable (not supported)                        */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/******************************************************************************/
ULONG EXPENTRY prdc_UnRealizeColorTable( hanDC   DcH,
                                         lpDCI   DCIData,
                                         ULONG   FunN)

{
#define TFUNC "prdc_UnRealizeColorTable"

    TRACE8(TFUNC, "DcH", &DcH, 1);
    TRACE8(TFUNC, "FunN", &FunN, 1);

    /**************************************************************************/
    /*  Color table cannot be unrealized.                                     */
    /*                                                                        */
    /*  PD00255 : Removed LOGWARNING statement as there are no documented     */
    /*  errors to report under these circumstances.                           */
    /**************************************************************************/
    return(OK);
}
#undef TFUNC
