;*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.;
;*****************************************************************************/
        PAGE     55,132
        TITLE    Color Conversions
        SUBTITLE Header
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CLRCONV.ASM
;*
;* DESCRIPTIVE NAME = Color convesion routines.
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/10/91
;*
;* DESCRIPTION  Color convesion 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
;*   11/10/91                     KEZ  Original
;*****************************************************************************/

        .386P
        .MODEL FLAT,SYSCALL
        assume CS:FLAT
;/*
;** Included files
;*/

INCL_NOBASEAPI     EQU 1
INCL_GPIPRIMITIVES EQU 1
OS2_NOPMAPI        EQU 1
INCL_SAADEFS       EQU 1
        INCLUDE PMGRE.INC

DINCL_BITMAP       EQU 1
DINCL_CLR_TBL      EQU 1
DINCL_ENABLE       EQU 1
        INCLUDE DRIVER.INC
        INCLUDE DISPLAY.INC
        INCLUDE EXTERN.INC
        INCLUDE PROTOS.INC


;/*
;** Data
;*/

        .DATA

;/*
;** 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 DWORD
        DWORD   FLAT:Def_clr_tbl_to_IPC
        DWORD   FLAT:User_clr_tbl_to_IPC
        DWORD   FLAT:My_RGB_to_IPC
        DWORD   FLAT:My_RGB_to_IPC
        .ERRNZ  DDC_RGB_MODE-00000100b
        .ERRNZ  DDC_LOG_CLR_TBL-00000010b

;/*
;** Public functions
;*/

        .CODE
_TUNE segment USE32 PUBLIC 'CODE'
; assume cs:FLAT
EXTERNDEF ctDefault                     :DWORD

        SUBTITLE ColorConvert
        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
;*
;* INPUT         = ESI --> DDC
;*                 EAX  =  Logical color (special, index, or rgb)
;*                 CL   =  BA_CLR_DEF or BA_CLR_BACK_DEF from ba_fb
;*                           (only one may be set)
;*
;* OUTPUT        = EAX  = IPC
;*                 'S' clear
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = EAX = INVALID_IPC
;*                 'S' set
;*                 Error logged
;*
;**************************************************************************/

ColorConvert PROC SYSCALL PUBLIC USES EBX
IFDEF FIREWALLS

        ddc?    ESI
        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 ; FIREWALLS

        TEST    CL,BA_CLR_DEF or BA_CLR_BACK_DEF
        JNZ     Have_a_def_color
        OR      EAX,EAX                 ; Possibly special color?
        JNS     Not_special_color       ;  Nope
        SUB     EAX,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     EAX,EAX
        .ERRNZ  SIZE_IPC-2
        XCHG    EAX,EBX
        MOVSX   EAX,aipcSpecial[EBX]
        JMP     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:
        MOVSX   EAX,ipcSysClrWindowText
        TEST    CL,BA_CLR_DEF
        JNZ     Color_convert_good_color
        MOVSX   EAX,ipcSysClrWindow
        JMP     Color_convert_good_color


;/*
;** 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:
        MOVZX   EBX,[ESI].DDC.ddc_fbClrTbl
        AND     EBX,DDC_RGB_MODE or DDC_LOG_CLR_TBL
        .ERRNZ  DDC_RGB_MODE-00000100b
        .ERRNZ  DDC_LOG_CLR_TBL-00000010b
        JMP     anpfnClrMap[2*EBX]               ; To the real handler


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

Def_clr_tbl_to_IPC::
        CMP     EAX,ctDefault+COLOR_TABLE.ct_iMax
        JA      Invalid_color_index              ; To big,     color index

Look_up_def_clr_tbl:
        ADD     EAX,EAX
        .ERRNZ  SIZE_IPC-2
        XCHG    EAX,EBX
        MOVSX   EAX,WORD ptr ctDefault+ct_aipc[EBX]
        JMP     Color_convert_chk_clr


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

User_clr_tbl_to_IPC::
        CMP     EAX,DEVCAPS_COLOR_INDEX
        JA      Invalid_color_index              ; To big,     color index
        MOV     EBX,[ESI].DDC.ddc_pClrTbl
        ADD     EAX,EAX
        .ERRNZ  SIZE_IPC-2
        XCHG    EAX,ESI
        MOVZX   ESI,WORD ptr [EBX]+ct_aipc[ESI]
        XCHG    EAX,ESI
        JMP     Color_convert_chk_clr


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

My_RGB_to_IPC::
        TEST    EAX,0FF000000h
        JS      Invalid_color_index              ; Special index was too negative
        JNZ     Invalid_color_data               ; RGB is bad
        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc                       ; Map EAX 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      EAX,EAX                 ; Set/clear 'S'
        JNS     Color_convert_good_color

Invalid_color_index:
        MOV     EAX,PMERR_INV_COLOR_INDEX
        JMP     CC_Log_error


Invalid_color_data:
        MOV     EAX,PMERR_INV_COLOR_DATA

CC_Log_error:
        PUSH    EBX                     ; This function preserves these
        PUSH    ECX                     ; registers
        save_error_code
        POP     ECX
        POP     EBX
        MOV     EAX,INVALID_IPC_DWORD   ; Invalid color
        OR      EAX,EAX                 ; Set 'S' to show invalid color

Color_convert_good_color:

        RET

ColorConvert ENDP

        SUBTITLE ipc_to_index
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = ipc_to_index
;*
;* DESCRIPTION   = Converts an IPC to a valid color index.  Scans color
;*                 tables to find the index if needed.
;*
;*                 Registers modified:
;*                   ECX EDX
;*
;* INPUT         = EBX --> DDC
;*                 EAX  =  IPC
;* OUTPUT        = EAX = Color index
;*
;* RETURN-NORMAL = EAX = Color index
;* RETURN-ERROR  = EAX = CLR_NOINDEX if no index exists
;*
;**************************************************************************/

ipc_to_index PROC SYSCALL PUBLIC uses EBX EDI ESI

        DebugMsg <ipc_to_index,KEZ>

        TEST    [EBX].DDC.ddc_fbClrTbl,DDC_RGB_MODE
        JZ      Not_RGB_mode
        AND     EAX,MM_ALL                                       ; The EGA has accel. bits
        SHL     EAX,2                           ; EAX = 4 * IPC
        MOV     EDI,EAX                         ; EDI = 4 * IPC
        MOV     EAX,adrgbIndex[EDI]                      ; EAX = RBG color
                                                ;       corresponding to IPC
        JMP     Return_this_index


Not_RGB_mode:

;/*
;** Locate the logical color table.
;*/

        MOV     ESI,[EBX].DDC.ddc_pClrTbl       ; ESI --> Color table
        TEST    BYTE ptr [EBX].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JZ      Dont_validate
        PUSH    EAX
        MOV     EAX,[EBX].DDC.ddc_iSysClr                ; EAX = Index of current
                                                ;       system color
        CMP     EAX,ddcInit.ddc_iSysClr
        JE      @F
        XCHG    EBX,ESI                         ; EBX --> Color table,
                                                ; ESI --> DDC
        INVOKE  PropagateSysClrChange
        XCHG    EBX,ESI                         ; EBX --> DDC
                                                ; ESI --> Color table
@@:
        POP     EAX                             ; EAX = RGB color for IPC

Dont_validate:

;/*
;** Locate the IPC in the table.
;*/

        MOV     ECX,[ESI].COLOR_TABLE.ct_iMax
        INC     ECX                             ; ECX = Size of table
        LEA     EDI,[ESI]+ct_aipc                        ; EDI --> IPC array
        CLD
  REPNZ SCASW
        JZ      Found_a_match

;/*
;** Check for MONO bit match, if monochrome.
;*/

        MOV     EDI,[EBX].DDC.ddc_npsd                   ; EDI --> Surface definition
        TEST    [EDI].SURFACE.sd_fb,SD_COLOR     ; No match if color
        JNZ     No_match_at_all

;/*
;** Look for an ON bit.
;*/

        MOV     ECX,[ESI].COLOR_TABLE.ct_iMax
        INC     ECX                             ; ECX = Size of table
        LEA     EDI,[ESI]+ct_aipc                        ; EDI --> IPC array
        MOV     EDX,EDI                         ; EDX --> IPC array
        TEST    EAX,MONO_BIT
        JZ      Look_for_OFF_loop

Look_for_ON_loop:
        ADD     EDX,2
        TEST    WORD ptr [EDI],MONO_BIT
        MOV     EDI,EDX                         ; EDI --> Element in IPC array
        LOOPZ   Look_for_ON_loop
        JNZ     Found_a_match

No_match_at_all:
        MOV     EAX,CLR_NOINDEX                                  ; Indicate no index found
        JMP     Return_this_index


;/*
;** Look for an OFF bit.
;*/

Look_for_OFF_loop:
        ADD     EDX,2
        TEST    WORD ptr [EDI],MONO_BIT
        MOV     EDI,EDX
        LOOPNZ  Look_for_OFF_loop
        JNZ     No_match_at_all

;/*
;** Calculate the index.
;*/

Found_a_match:
        SUB     EDI,ESI
        SUB     EDI,ct_aipc + 2
        MOV     EAX,EDI                         ; EDI = 2 * index
        SHR     EAX,1                           ; EAX = Index

Return_this_index:

        RET

ipc_to_index ENDP

_TUNE ENDS
        END
