;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft 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.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CLRCONV.ASM
;*
;* DESCRIPTIVE NAME = Color conversion routines.
;*
;*
;* VERSION      V2.0
;*
;* DATE         07/10/87
;*
;* DESCRIPTION  Color conversion routines.
;*              
;* FUNCTIONS    ColorConvert
;*              ipc_to_index
;*                          
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   10/10/89                     Michael Kerekes [mikeke]
;*                                Changed to handle palettes.
;*   08/10/88                     Bob Grudem [bobgru] Now catches all
;*                                invalid negative indices less than
;*                                MIN_SPECIAL_COLOR.
;*   07/21/88                     Bob Grudem [bobgru] Now returns
;*                                INV_COLOR_DATA if an rgb value is bad.
;*   04/02/88                     Walt Moore [waltm] Changed to always
;*                                log an error if the IPC being returned
;*                                to the caller is invalid.  Before, we
;*                                were only returning an error if the
;*                                index was out of range.  Thus, if color
;*                                table index n was given and no value had
;*                                yet been assigned to index n, no error
;*                                would be logged.
;**************************************************************************/

        .286p
        .xlist
        include cmacros.inc
INCL_GPIPRIMITIVES      equ                      1
INCL_DDIMISC            equ                      1
INCL_GPIBITMAPS         equ                      1
INCL_GPILOGCOLORTABLE   equ                      1
        include pmgre.inc
DINCL_CLR_TBL           equ                      1
        include driver.inc
        include assert.mac
        include njmp.mac
        include palette.inc
        .list

        ??_out  clrconv

        errcode <INV_COLOR_INDEX,INV_COLOR_DATA>

        externA DEVCAPS_COLOR_INDEX
        externA MIN_SPECIAL_COLOR

sBegin  Data
        externB ctDefault
        externW aipcSpecial
        externW ipcSysClrWindowText
        externW ipcSysClrWindow
sEnd    Data

sBegin  Code
        assumes cs,Code

        externNP rgb_to_ipc
page

;/***************************************************************************
;*
;* FUNCTION NAME = ColorConvert 
;*
;* DESCRIPTION   = ColorConvert accepts a logical color and returns the device
;*                 dependent, physical representation of bits necessary to    
;*                 display the color closest to the specified color on the    
;*                 device.  This information will be used later by other      
;*                 driver routines.                                           
;*                                                                            
;*                 Registers Preserved:                                                             
;*                       BX,CX,SI,DI,DS                                                             
;*                 Registers Destroyed:                                                             
;*                       AX,DX,ES,FLAGS                                                             
;*                       Calls:
;*                           rgp_to_ipc
;*                                                                            
;* INPUT         = DS:SI --> DDC
;*                 DX:AX  =  Logical color (special, index, or rgb)
;*                 CL     =  BA_CLR_DEF or BA_CLR_BACK_DEF from ba_fb
;*                           (only one may be set)                                                                             
;*                                                                            
;* OUTPUT        = AX  = IPC          
;*                 'S' clear                                                                      
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = AX = INVALID_IPC 
;*                 'S' set           
;*                 Error logged      
;*
;**************************************************************************/


;/*
;** anpfnClrMap contains the address of the processors which will be
;** called to perform the specific color mapping, based on the color
;** mode currently set in the ddc.
;*/

anpfnClrMap     label   word
        dw      def_clr_tbl_to_ipc
        dw      user_clr_tbl_to_ipc
        dw      my_rgb_to_ipc
        dw      my_rgb_to_ipc
        .errnz  DDC_RGB_MODE-00000100b
        .errnz  DDC_LOG_CLR_TBL-00000010b

        assumes ds,Data
        assumes es,nothing

cProc   ColorConvert,<NEAR,PUBLIC,NONWIN>,<bx,di>
cBegin

ifdef FIREWALLS
        ddc?    si
        not     cl                                ;Can have one flag at most set
        test    cl,BA_CLR_DEF or BA_CLR_BACK_DEF
        not     cl                                ;Not doesn't alter flags
        jnz     @F
        rip     text,<ColorConvert called with more than one _DEF flag>
@@:
endif
        test    cl,BA_CLR_DEF or BA_CLR_BACK_DEF
        jnz     have_a_def_color
        inc     dx                               ;If negative, might be one of the
        jnz     not_special_color                ;  special colors
        sub     ax,MIN_SPECIAL_COLOR             ;Special color within range?
        jc      invalid_color_index              ;  No, error

;/*
;** The color is a SPECIAL color.  Look it up in aipcSpecial.
;*/
 
look_up_special_color:
        add     ax,ax
        .errnz  SIZE_IPC-2
        xchg    ax,bx
        mov     ax,aipcSpecial[bx]
        jmp     short color_convert_chk_clr

;/*
;** The color is a default color.  We can skip all the mapping stuff
;** and just return the correct default to the caller.  The defaults
;** can not be in error.
;*/

have_a_def_color:
        mov     ax,ipcSysClrWindowText
        test    cl,BA_CLR_DEF
        njnz    cc_exit
        mov     ax,ipcSysClrWindow
        jmp     cc_exit

;/*
;** These errnz's are very important.  Since we take the good exit, we
;** rely on the "test" operation to clear 'S'.  Since we only allow
;** these two values as arguments, there should be no problem with this.
;*/

        .errnz  BA_CLR_DEF-00100000b
        .errnz  BA_CLR_BACK_DEF-00010000b

;/*
;** The color was not a special color.  Call the color conversion
;** routine to map the color into an ipc.
;*/

not_special_color:

        test    [si].ddc_fbBelow,DDC_PALETTE
        njnz    cc_custom_palette

        mov     bl,[si].ddc_fbClrTbl
        and     bx,DDC_RGB_MODE or DDC_LOG_CLR_TBL
        .errnz  DDC_RGB_MODE-00000100b
        .errnz  DDC_LOG_CLR_TBL-00000010b
        dec     dx                                ;Restore DX, set 'Z' as appropriate
        jmp     anpfnClrMap[bx]                   ;To the real handler


;/*
;** Process a convert call for the default color table
;*/

def_clr_tbl_to_ipc:
        jnz     invalid_color_index              ;DX <> 0, error
        cmp     ax,ctDefault.ct_iMax
        ja      invalid_color_index              ;To big,     color index
look_up_def_clr_tbl:
        add     ax,ax
        .errnz  SIZE_IPC-2
        xchg    ax,bx
        mov     ax,word ptr ctDefault.ct_aipc[bx]
        jmp     short color_convert_chk_clr


;/*
;** Process a convert call for a user-defined logical color table.
;*/

user_clr_tbl_to_ipc:
        jnz     invalid_color_index              ;DX <> 0, error
        cmp     ax,DEVCAPS_COLOR_INDEX
        ja      invalid_color_index              ;To big,     color index
        les     bx,[si].ddc_pClrTbl
        assumes es,nothing
        add     ax,ax
        .errnz  SIZE_IPC-2
        xchg    ax,si
        mov     si,es:[bx].ct_aipc[si]
        xchg    ax,si
        jmp     short color_convert_chk_clr


;/*
;** Process a convert call for RGB mode.
;*/

my_rgb_to_ipc:
        or      dh,dh
        js      invalid_color_index              ;Special index was too negative
        jnz     invalid_color_data               ;RGB is bad
        call    rgb_to_ipc                       ;Map DX:AX to an ipc, cannot fail

;/*
;** We could get an invalid IPC from a color table.  If so, we want to
;** log an error.
;*/

color_convert_chk_clr:
        or      ax,ax                             ;Set/clear 'S'
        jns     cc_exit
invalid_color_index:
        mov     ax,PMERR_INV_COLOR_INDEX
        jmp     short cc_log_error
invalid_color_data:
        mov     ax,PMERR_INV_COLOR_DATA
cc_log_error:
        push    bx                                ;This function preserves these
        push    cx                                ;  registers
        save_error_code
        pop     cx
        pop     bx
        mov     ax,INVALID_IPC                    ;Invalid color
        or      ax,ax                             ;Set 'S' to show invalid color

        jmp     short cc_exit


;/*
;** There is a palette in the ddc, which means the data we've been given
;** is in index mode.  If we get here, the index is positive.
;** Check the index against the range in the palette to prevent GP faulting
;** during table lookup.  Also check that the index is used in the palette.
;*/

cc_custom_palette:

        dec     dx                                ;Restore DX

;/*
;** If the palette index is not used, return PMERR_INV_COLOR_INDEX.
;*/

        mov     di,[si].ddc_npdevpal
        les     di,[di].devpal_pPalSeg
        assumes es,nothing

        cmp     ax,es:[di].palseg_usMax
        ja      invalid_color_index

        mov     bx,ax
        palOff  bx

;/*
;** If this is a memory DDC, then return the index as is.
;*/

        test    [si].ddc_fb,DDC_DEVICE
        jz      cc_exit

;/*
;** It's a device DDC, so map the index through the realization table.
;** If the palette has not been realized, index 0 will be returned (because
;** the realization table is initialized to 0).
;*/

        mov     al,es:[di+bx].palseg_apalclr.palclr_bCur

;/*
;** Common exit.
;*/

cc_exit:
        or      ah,ah                             ;set/clear sign bit

cEnd
page

ifdef FIREWALLS
        public  look_up_special_color
        public  have_a_def_color
        public  not_special_color
        public  def_clr_tbl_to_ipc
        public  look_up_def_clr_tbl
        public  user_clr_tbl_to_ipc
        public  my_rgb_to_ipc
        public  color_convert_chk_clr
        public  invalid_color_index
        public  invalid_color_data
        public  cc_log_error
        public  cc_custom_palette
        public  cc_exit
endif

sEnd
end
