;*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 Tables
        SUBTITLE Header

;/*****************************************************************************
;*
;* SOURCE FILE NAME = COLORTBL.ASM
;*
;* DESCRIPTIVE NAME = routines which interact with color tables
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/01/91
;*
;* DESCRIPTION  This file contains the routines which interact with color tables.
;*
;* FUNCTIONS  CalcRGBDistance
;*            RGBToNearestIndex
;*            QueryColorData
;*            RealizeColorTable
;*            UnrealizeColorTable
;*            CreateLogColorTable
;*            QueryLogColorTable
;*            QueryRealColors
;*            QueryNearestColor
;*            QueryColorIndex
;*            QueryRGBColor
;*            save_lct
;*            deselect_lct
;*            PropagateSysClrChange
;*            ResetLogColorTable
;*            device_enter_driver
;*
;* 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/1/91                      KEZ  Original
;*****************************************************************************/

        .386P
        .MODEL FLAT,SYSCALL

;/*
;** Included files
;*/

INCL_DDICOMFLAGS      EQU 1
INCL_DDIMISC          EQU 1
INCL_GPILOGCOLORTABLE EQU 1
INCL_GPIPRIMITIVES    EQU 1
INCL_GPIREGIONS       EQU 1
INCL_NOBASEAPI        EQU 1
INCL_NOCOMMON         EQU 1
INCL_WINSYS           EQU 1
OS2_NOPMAPI           EQU 1
        INCLUDE PMGRE.INC

DINCL_BITMAP          EQU 1
DINCL_CLR_TBL         EQU 1
DINCL_ENABLE          EQU 1
INCL_DDICOMFLAGS      EQU 1
DINCL_EXTENDEDCONTROL EQU 1
        INCLUDE DRIVER.INC
        INCLUDE EXTERN.INC
        INCLUDE PROTOS.INC
        INCLUDE ASSERT.MAC

;/*
;** Equates
;*/

BACKGND_WORD  EQU 0*2   ; Indicies for accessing rgbs and ipcs
FOREGND_WORD  EQU 7*2
BACKGND_DWORD EQU 0*4
FOREGND_DWORD EQU 7*4

LCOLOPT_REQUESTED EQU 2 ;!!! put into PMGPI.H !!!
EXTERNDEF ctDefault                     :DWORD

        .CODE

;;_TUNE segment USE32 PUBLIC 'CODE'
;/*
;** Private functions
;*/

        SUBTITLE CalcRGBDistance
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = CalcRGBDistance
;*
;* DESCRIPTION   = Calculate the differences between RGB values
;*
;*                 Registers Destroyed:
;*                       AX,CX,DX
;*
;* INPUT         = DL = Red         RGB color 1
;*                 AH = Green
;*                 AL = Blue
;*
;*                 DH = red         RGB color 2
;*                 CH = green
;*                 CL = blue
;*
;* OUTPUT        = EAX = (square of) distance apart in RGB space
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
CalcRGBDistance PROC SYSCALL PRIVATE uses EBX,

        SUB     AL,CL           ; Blue difference
        JNC     Positive_blue
        NEG     AL

Positive_blue:
        MOV     CL,AH           ; Save green before mult overwrites AH

;/*
;** Maximum difference is FF - 0 = FF, hence just in AL
;** Maximum square is FF * FF = FE01, it fits in AX
;*/

        MUL     AL              ; Square the difference
        MOVZX   EBX,AX          ; Save the difference so far

        MOV     AL,CL           ; Saved green value
        SUB     AL,CH           ; Green difference
        JNC     Positive_green
        NEG     AL

Positive_green:

;/*
;** Maximum difference is FF - 0 = FF, hence just in AL
;** Maximum square is FF * FF = FE01, it fits in AX
;*/

        MUL     AL              ; Square the difference
        CWDE
        ADD     EBX,EAX         ; Add to the total
        MOV     AL,DL
        SUB     AL,DH           ; Red difference
        JNC     Positive_red
        NEG     AL              ; Ensure diff is positive

Positive_red:

;/*
;** Maximum difference is FF - 0 = FF, hence just in AL
;** Maximum square is FF * FF = FE01, it fits in AX
;*/

        MUL     AL              ; Square the difference

;/*
;** Move the RGB distance into EAX
;*/

        CWDE
        ADD     EAX,EDI         ; Add the accumulated differences

        RET

CalcRGBDistance ENDP

        SUBTITLE RGBToNearestIndex
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = RGBToNearestIndex
;*
;* DESCRIPTION   = Converts an RGB to the nearest valid color index.  Scans
;*                 color tables to find the index with the smallest error.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,SI,DI
;*
;* INPUT         = DWORD RGB color for which index is desired.
;*                 EBX --> DDC
;*
;* OUTPUT        = EAX = Index for color closest to input color
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

RGBToNearestIndex PROC SYSCALL PRIVATE uses EDI ESI,
                RGBWanted:DWORD

        LOCAL   lBestError:DWORD,
                lBestIndex:DWORD

        MOV     WORD ptr lBestError+2,0FFFFh    ; Start with a big error
        MOV     lBestIndex,0                    ; Just in case!

IFDEF FIREWALLS

        TEST    [EBX].DDC.ddc_fbClrTbl,DDC_RGB_MODE
        assert  Z

@@:

ENDIF        ;FIREWALLS

;/*
;** Adjust system colors if necessary.
;*/

        ddc?    EBX
        MOV     EAX,[EBX].DDC.ddc_iSysClr
        CMP     EAX,ddcInit.ddc_iSysClr
        JE      @F
        MOV     ESI,EBX                         ; ESI --> DDC
        INVOKE  PropagateSysClrChange
@@:

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

        MOV     ESI,[EBX].DDC.ddc_pClrTbl        ; ESI --> Color table

;/*
;** Grab some color table info
;*/

        MOV     EDI,[ESI].COLOR_TABLE.ct_iMax    ; EDI = Max valid entry
        MOV     EBX,[ESI].COLOR_TABLE.ct_iMin    ; EBX = Min (start) entry
        assert  EBX,E,0
        MOV     ESI,[ESI].COLOR_TABLE.ct_npargb  ; ESI --> RGB array
        CLD

RNI_Scan_loop:

;/*
;** Load new quess.
;*/

        LODSW                                   ; AX = Green and blue
        MOV     DX,AX                           ; Save green and blue
        LODSW                                   ; AL = Current guess's red
        CMP     AX,-1                           ; This RGB may not be valid
        JE      RNI_End_loop                                     ; Just skip if not
        XCHG    DX,AX                           ; DL,AH,AL = R,G,B
        MOV     DH,BYTE ptr RGBWanted+2         ; DH = Red we want
        MOV     CX,WORD ptr RGBWanted                    ; CX = Green and blue
        INVOKE  CalcRGBDistance                                  ; Compares RGBs DL,AH,AL --
                                                ; DH,CH,CL
        CMP     EAX,lBestError
        JAE     RNI_End_loop

RNI_Its_better:
        MOV     lBestError,EAX                                   ; Save error
        MOV     lBestIndex,EBX                                   ; and index

RNI_End_loop:
        INC     EBX
        CMP     EBX,EDI
        JBE     RNI_Scan_loop

;/*
;** Get the index:
;*/
        MOV     EAX,lBestIndex                                   ; EAX = Index of best color

        RET

RGBToNearestIndex ENDP

;/*
;** Public functions
;*/

        SUBTITLE QueryColorData
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryColorData
;*
;* DESCRIPTION   = This function is called from the GRE's dispatch table in
;*                 response to a GreQueryColorData function call and
;*                 returns information about the currently available color
;*                 table and device colors.  Information will only be
;*                 returned for the number of elements supplied.  Any extra
;*                 elements supplied will be zeroed.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*
;* INPUT         = C Prototype:
;*                   BOOL _syscall QueryColorData(HDC   hdc,
;*                                                LONG  cArray,
;*                                                PLONG pArray,
;*                                                PVOID pInstance,
;*                                                ULONG lFunction);
;*
;*                    where:
;*                      All arguments are in accordance with the GreQueryColorData
;*                      function
;*
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  TRUE
;* RETURN-ERROR  =  FALSE
;*
;**************************************************************************/
QueryColorData PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc      :HDC,
                cArray   :LONG,
                pArray   :PLONG,
                pInstance:PVOID,
                lFunction:ULONG

        DebugMsg <QueryColorData,DISPATCH,KEZ>

        ddc?    pInstance
        MOV     ESI,pInstance
        MOV     EDX,ESI
        INVOKE  enter_driver
        JC      QCD_Exit_no_lock                 ; EAX = 0 on error
        CMP     cArray,10000h                    ; cArray must be <64K for now
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT    ; Indicate error
        JAE     QCD_Log_error                    ; Error - array too large
        MOV     ECX,cArray                       ; CX = Ct. of entries to copy
        OR      ECX,ECX
        JZ      QCD_Good_exit                    ; Nothing to copy
        MOV     EDI,pArray                       ; EDI --> destination array
        MOV     BL,[ESI].DDC.ddc_fbClrTbl        ; BL = Color table flags
        MOV     EAX,LCOLF_RGB                    ; Assume RGB mode
        TEST    BL,DDC_RGB_MODE
        JNZ     Return_color_mode                ; Mode is RGB
        MOV     ESI,[ESI].DDC.ddc_pClrTbl        ; ESI --> color table
        MOV     EAX,LCOLF_DEFAULT
        TEST    BL,DDC_LOG_CLR_TBL
        JZ      Return_color_mode                ; Mode is default color table
        MOV     EAX,LCOLF_INDRGB                 ; AH was trashed by the LAR!
        .ERRNZ  HIGH LCOLF_INDRGB                ; We assumed that all these
        .ERRNZ  HIGH LCOLF_DEFAULT               ; had the same MSB
        .ERRNZ  HIGH LCOLF_RGB
        .ERRNZ  HIGH LCOLF_PALETTE

;/*
;** EAX has the current mode (format)
;*/

Return_color_mode:
        CLD                                      ; Return current color table
                                                 ; format
        STOSD
        .ERRNZ  QCD_LCT_FORMAT                   ; First DWORD
        DEC     ECX                              ; First down!
        JZ      QCD_Good_exit                    ; All done
        CMP     EAX,LCOLF_RGB                    ; RGB mode?
        JNE     Get_indices                      ;  Y - zero fill indices
        .ERRNZ  HIGH LCOLF_INDRGB                ; Once again, we assumed
        .ERRNZ  HIGH LCOLF_DEFAULT               ; these all had the same
        .ERRNZ  HIGH LCOLF_RGB                   ; value for the MSB
        .ERRNZ  HIGH LCOLF_PALETTE
        XOR     EAX,EAX
        STOSD                                    ; LO index is zero for RGB
                                                 ; mode
        DEC     ECX                              ; Another one bites the dust!
        JZ      QCD_Good_exit                    ; All done
        STOSD                                    ; HI index is zero for RGB
                                                 ; mode
        JMP     Get_options

QCD_Log_error:
        save_error_code
        XOR     AX,ax
        JMP     QCD_Exit

Get_indices:
        MOV     EAX,[ESI].COLOR_TABLE.ct_iMin    ; Minimum loaded color index
        STOSD
        .ERRNZ  QCD_LCT_LOINDEX-1                ; Second DWORD
        DEC     ECX                              ; Another one bites the dust!
        JZ      QCD_Good_exit                    ; No room for the maximum
                                                 ; index
        MOV     EAX,[ESI].COLOR_TABLE.ct_iMax    ; Maximum loaded color index
        STOSD
        .ERRNZ  QCD_LCT_HIINDEX-2                ; Third DWORD

Get_options:
        DEC     ECX                              ; And another one's down.
        JZ      QCD_Good_exit                    ;No room for the options

IFDEF FIREWALLS

        PUSH    ESI
        MOV     ESI,pInstance
        assert  BL,E,[ESI].DDC.ddc_fbClrTbl
        POP     ESI

ENDIF ; FIREWALLS

        XOR     EAX,EAX                          ; Clear the options
        BT      EBX,6                            ; A84210
        .ERRNZ  DDC_REALIZED-40h
        RCL     EAX,2                            ; 000000r0 r = realized bit
        .ERRNZ  LCOL_REALIZED-16
        BTC     EBX,0                            ; 00000r0p p = pure bit
        .ERRNZ  DDC_DITHER-1
        CMC
        RCL     EAX,1
        .ERRNZ  LCOL_PURECOLOR-4
        BT      EBX,5                            ; 000r0pR0 R = realizable bit
        .ERRNZ  DDC_REALIZABLE-20h
        RCL     EAX,2
        .ERRNZ  LCOL_REALIZABLE-2
        STOSD
        .ERRNZ  QCD_LCT_OPTIONS-3                ; Third DWORD

Zero_with_dec:
        DEC     ECX                              ; Zero will just fall through

Zero_extra_DWORDs:
        MOV     EAX,0
        REP     STOSD                            ; Stuff lots of zeros

QCD_Good_exit:
        MOV     EAX,1

QCD_Exit:
        INVOKE  leave_driver

QCD_Exit_no_lock:
        fw_zero <ECX>

        RET

QueryColorData ENDP

        SUBTITLE RealizeColorTable
        PAGE +
;/***************************************************************************
;*
;* FUNCTION NAME = RealizeColorTable
;*
;* DESCRIPTION   = This function is invoked from the GRE dispatch table in
;*                 response to a call to the GreRealizeColorTable function and
;*                 causes the system, if possible, to ensure that the device
;*                 physical color table is set to the closest possible match to
;*                 the logical color table.  We do not support realizable color
;*                 tables.  We do, however, track the realize bit passed in to
;*                 CreateLogColorTable.  If they have specified that the color
;*                 table is realizable and we're in color table mode, then we'll
;*                 return success and log a warning.  Otherwise, we're in RGB
;*                 mode or color table mode without the realize bit, in which
;*                 case we'll log the error.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*
;* INPUT         = C Prototype:
;*                   BOOL _syscall RealizeColorTable (HDC   hdc,
;*                                                    PVOID pInstance,
;*                                                    ULONG lFunction);
;*
;*                    where:
;*                       All arguments are as specified for the GreRealizeColorTable
;*                       function.
;*
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE
;* RETURN-ERROR  = FALSE
;*
;**************************************************************************/

RealizeColorTable PROC SYSCALL PUBLIC uses EBX,
                hdc      :HDC,
                pInstance:PVOID,
                FunN:ULONG

        DebugMsg <RealizeColorTable,DISPATCH,KEZ>

        ddc?    pInstance
        CLD
        MOV     EDX,pInstance
        INVOKE  enter_driver
        JC      RCT_Exit_no_lock        ; EAX = 0 on error
        no_path_area RCT_Exit,both      ; Not allowed in path or area
        MOV     EBX,pInstance
        TEST    [EBX].DDC.ddc_fbClrTbl,DDC_REALIZABLE
        JZ      RCT_Error                                ; Wasn't allowed to realize it
        OR      [EBX].DDC.ddc_fbClrTbl,DDC_REALIZED
        MOV     EAX,PMERR_REALIZE_NOT_SUPPORTED
        save_warning_code               ; Warning
        MOV     EAX,1                   ; Show success (1)
        JMP     RCT_Exit

RCT_Error:
        MOV     EAX,PMERR_COL_TABLE_NOT_REALIZABLE
        save_error_code
        XOR     EAX,EAX                 ; Return error
        .ERRNZ  $ - RCT_Exit

RCT_Exit:
        INVOKE  leave_driver

RCT_Exit_no_lock:

        RET

RealizeColorTable ENDP

        SUBTITLE UnrealizeColorTable
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = UnrealizeColorTable
;*
;* DESCRIPTION   = This function is invoked from the GRE dispatch table in
;*                 response to a call to the GreUnrealize ColorTable
;*                 function and is the reverse of RealizeColorTable.  It
;*                 causes the default physical palette to be reinstated.  If
;*                 a realize call has not been made, then an error will be
;*                 returned.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*
;* INPUT         = C Prototype:
;*                   BOOL _syscall UnrealizeColorTable (HDC   hdc,
;*                                                      PVOID pInstance,
;*                                                      ULONG lFunction);
;*
;*                    where:
;*                      All arguments are as specified for the GreUnrealizeColorTable
;*                      function.
;*
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE
;* RETURN-ERROR  = FALSE
;*
;**************************************************************************/

UnrealizeColorTable PROC SYSCALL PUBLIC uses EBX,
                hdc      :HDC,
                pInstance:PVOID,
                FunN:ULONG

        DebugMsg <UnrealizeColorTable,DISPATCH,KEZ>

        ddc?    pInstance
        CLD
        MOV     EDX,pInstance
        INVOKE  enter_driver
        JC      UCT_Exit_no_lock                        ; EAX = 0 on error

        no_path_area UCT_Exit,both

        MOV     EBX,pInstance
        MOV     EAX,1                                   ; Assume success
        TEST    [EBX].DDC.ddc_fbClrTbl,DDC_REALIZED
        JNZ     UCT_Update_flag
        MOV     EAX,PMERR_COL_TABLE_NOT_REALIZED
        save_error_code
        XOR     EAX,EAX                                 ; Indicate error

UCT_Update_flag:
        AND     [EBX].DDC.ddc_fbClrTbl,NOT DDC_REALIZED

UCT_Exit:
        INVOKE  leave_driver

UCT_Exit_no_lock:

        RET

UnrealizeColorTable ENDP
_TUNE segment USE32 PUBLIC 'CODE'
        SUBTITLE CreateLogColorTable
        PAGE +
;EXTERNDEF ctDefault                     :DWORD
;/***************************************************************************
;*
;* FUNCTION NAME = CreateLogColorTable
;*
;* DESCRIPTION   = This function defines the entries of the logical color
;*                 table.  The Engine will perform the error checking for
;*                 CreateLogColorTable.  It may cause the color table to be
;*                 preset to the default values.
;*
;* INPUT         = C Prototype:
;*                   BOOL _syscall CreateLogColorTable (HDC   hdc,
;*                                                      ULONG flOptions,
;*                                                      LONG  lFormat,
;*                                                      LONG  lStart,
;*                                                      LONG  cCount,
;*                                                      PLONG pData,
;*                                                      PVOID pInstance,
;*                                                      ULONG lFunction);
;*
;*                    where:
;*                      All arguments are as specified for the GreCreateLogColorTable
;*                      function.
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE
;* RETURN-ERROR  = FALSE
;*
;**************************************************************************/

CreateLogColorTable PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc      :HDC,
                flOptions:ULONG,
                lFormat  :LONG,
                lStart   :LONG,
                cCount   :LONG,
                pData    :PLONG,
                pInstance:PVOID,
                FunN     :ULONG

        LOCAL   plNewData:DWORD
        LOCAL   pClrTbl:DWORD

        DebugMsg <CreateLogColorTable,DISPATCH,KEZ>

        ddc?    pInstance
        CLD
        MOV     ESI,pInstance
        MOV     EDX,ESI
        INVOKE  enter_driver
        JC      CLCT_Exit_no_lock                ; EAX = 0 on error

        no_path_area CLCT_Error,both,error

;/*
;** Validate all the arguments.  Option flags have been validated by GPI.
;** We will always log an error (warning) for the realize option.  If we
;** are asked to go to RGB mode with the realize option, we'll return an
;** error, else we'll just return it as a warning.
;*/

        XOR     EBX,EBX                          ; EBX is expected to be zero later
        MOV     EAX,PMERR_INV_COLOR_FORMAT
        CMP     lFormat,10000h                   ; Legitimate format?
        JAE     CLCT_Error
        TEST    flOptions,LCOL_REALIZABLE        ; Realizable?
        JZ      Logged_realize_warning
        MOV     EAX,PMERR_REALIZE_NOT_SUPPORTED
        CMP     lFormat,LCOLF_RGB
        JE      CLCT_Error                       ; Hard error
        save_warning_code                        ; Warning

Logged_realize_warning:
        MOV     ECX,lFormat                      ; Dispatch to the correct
        MOV     EDX,ECX                          ; format handler
        DEC     ECX
        JZ      CLCT_Format_logical
        .ERRNZ  LCOLF_INDRGB-1
        DEC     ECX
        JZ      CLCT_Format_logical
        .ERRNZ  LCOLF_CONSECRGB-2
        DEC     ECX
        JNZ     CLCT_Error
        .ERRNZ  LCOLF_RGB-3

;/*
;** Handle LCOLF_RGB mode
;*/

        MOV     BL,DDC_RGB_MODE

;/*
;** Handle LCOLF_DEFAULT. BL = DDC_RGB_MODE flag value or 0.
;**
;** We use this routine if entering RGB mode, or if LCOL_RESET given with a
;** count of 0.  If a color table is present, it is freed if needed.
;*/

CLCT_Format_default:
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JZ      Default_no_table
        MOV     ECX,[ESI].DDC.ddc_pClrTbl        ; Free the memory block
        DEC     [ECX].COLOR_TABLE.ct_cSave       ; containing the color table
        JNZ     Default_no_table
        INVOKE  private_free                     ; Free memory block

Default_no_table:
        MOV     [ESI].DDC.ddc_fbClrTbl,BL
        MOV     [ESI].DDC.ddc_pClrTbl,offset ctDefault
        JMP     CLCT_Common_exit

;/*
;** Yet another error handler
;*/

CLCT_Error:
        save_error_code
        XOR     EAX,EAX
        JMP     CLCT_Exit

;/*
;** Handle LCOLF_INDRGB and LCOLF_CONSECRGB
;**
;** Currently:     EBX = 0
;**                ECX = 0
;**                EDX = lFormat
;**                ESI --> ddc
;*/

CLCT_Format_logical:
        CMP     cCount,010000h                   ; Valid count?
        JAE     CLCT_Bad_count
        MOV     ECX,cCount
        TEST    flOptions,LCOL_SYSCOLORS
        JZ      Not_system_colors

Do_system_colors:
        JECXZ   CLCT_Exit_OK_relay               ; cCount is zero, nothing to do
        MOV     ESI,pData
        CMP     DL,LCOLF_CONSECRGB
        JE      Validate_sys_consecrgb

;/*
;** Do the SYSTEM INDRGB validation.  We want to make sure that all the
;** indices and RGB triplets are valid.
;*/

Validate_sys_indrgb:
        SHR     CX,1
        JC      CLCT_Bad_count

Validate_sys_indrgb_loop:
        LODSD                                    ; EAX = index
        SUB     EAX,MIN_SYSTEM_COLOR             ; Make it 0-based
        JB      CLCT_Bad_index
        CMP     EAX,SYSCLR_CSYSCOLORS
        JAE     CLCT_Bad_index
        LODSD
        ROL     EAX,8
        OR      AL,AL
        JNZ     CLCT_Bad_color
        LOOP    Validate_sys_indrgb_loop
;/*
;** The colors and indices seem to be valid.  Set the colors into the system
;** colors color tables.
;*/

        MOV     ESI,pData
        MOV     ECX,cCount
        SHR     ECX,1

Sys_indrgb_loop:
        LODSD                           ; EAX = index, ESI --> color
        XCHG    EAX,EDI                 ; EDI = index
        SUB     EDI,MIN_SYSTEM_COLOR    ; EDI = entry number
        LODSD                           ; EAX = color, ESI --> next index
        SHL     EDI,2                   ; EDI = 4 * entry number
        MOV     adrgbSpecial[EDI],EAX
        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc
        MOV     aipcSpecial[EDI],AX
        LOOP    Sys_indrgb_loop
        JMP     CLCT_Finish_sys_colors

;/*
;** Does this look like a good place for some of these?
;*/

CLCT_Exit_OK_relay:
        JMP     CLCT_Exit_ok

CLCT_Bad_color:
        MOV     EAX,PMERR_INV_COLOR_DATA
        JMP     CLCT_Error

CLCT_Bad_index:
        MOV     EAX,PMERR_INV_COLOR_INDEX
        JMP     CLCT_Error

CLCT_Bad_start_index:
        MOV     EAX,PMERR_INV_COLOR_START_INDEX
        JMP     CLCT_Error

CLCT_Bad_count:
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT
        JMP     CLCT_Error

;/*
;** Do the SYSTEM CONSECRGB validation.  We want to make sure that all the RGB
;** triplets are valid, and the range is valid.
;**
;*/

Validate_sys_consecrgb:
        MOV     EDI,lStart
        SUB     EDI,MIN_SYSTEM_COLOR
        JB      CLCT_Bad_start_index              ;error if edi < MIN_SYSTEM_COLOR
        MOV     EDX,SYSCLR_CSYSCOLORS
        SUB     EDX,EDI
        JBE     CLCT_Bad_start_index
        CMP     ECX,EDX
        JA      CLCT_Bad_count

Validate_sys_consecrgb_loop:

;/*
;** Make sure that the high-order byte of each index in the table is zero.
;**
;** At this point the registers contain:
;**    ECX --> Count of elements in table
;**    ESI --> Color table definition data
;**    EDI  =  Starting index (relative to MIN_SYSTEM_COLOR)
;*/

        LODSD
        ROL     EAX,8
        OR      AL,AL
        JNZ     CLCT_Bad_color                   ; Byte not zero
        LOOP    Validate_sys_consecrgb_loop      ; Check next one

;/*
;** The colors and range seem to be valid.  Set the colors into the system
;** color's color tables.
;*/

        LEA     EBX,aipcSpecial[EDI*2]
        LEA     EDI,adrgbSpecial[EDI*4]
        MOV     ECX,cCount
        MOV     ESI,pData

;/*
;** Upon entry to the loop, the following registers have the specified values:
;**   EBX --> IPC color table
;**   EDI --> RGB color table
;**   ESI --> Color table definition data
;*/

Sys_consecrgb_loop:
        LODSD                           ; Get color index
        STOSD                           ; Store it in RGB table
        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc              ; Convert it to IPC
        MOV     [EBX],AX                ; Store it in IPC table
        ADD     EBX,2                   ; Next index
        LOOP    Sys_consecrgb_loop

CLCT_Finish_sys_colors:

;/*
;** Update colors 0 and 7 in the default color table from the special system
;** colors.  We don't expect system colors to change very often.
;*/

CLCT_Exit_ok_sys_clr_change:
        MOV     EAX,drgbSysClrWindow
        MOV     adrgbDefault[BACKGND_DWORD],EAX
        MOV     ddcInit.ddc_ia.ia_ba.ba_clrBack,EAX
        MOV     ddcInit.ddc_pa.pa_ba.ba_clrBack,EAX
        MOV     ddcInit.ddc_la.la_ba.ba_clrBack,EAX
        MOV     ddcInit.ddc_ca.ca_ba.ba_clrBack,EAX
        MOV     ddcInit.ddc_ma.ma_ba.ba_clrBack,EAX

;/*
;** The mono bit in the background IPC is alway correct, so we can simply pick
;** up the IPC and stuff it into all the appropriate places.
;*/

        MOV     AX,ipcSysClrWindow
        MOV     WORD ptr ctDefault+ct_aipc[BACKGND_WORD],AX
        MOV     ddcInit.ddc_ia.ia_ba.ba_ipcBack,AX
        MOV     ddcInit.ddc_pa.pa_ba.ba_ipcBack,AX
        MOV     ddcInit.ddc_la.la_ba.ba_ipcBack,AX
        MOV     ddcInit.ddc_ca.ca_ba.ba_ipcBack,AX
        MOV     ddcInit.ddc_ma.ma_ba.ba_ipcBack,AX

        MOV     EAX,drgbSysClrWindowText
        MOV     adrgbDefault[FOREGND_DWORD],EAX
        MOV     ddcInit.ddc_ia.ia_ba.ba_clr,EAX
        MOV     ddcInit.ddc_pa.pa_ba.ba_clr,EAX
        MOV     ddcInit.ddc_la.la_ba.ba_clr,EAX
        MOV     ddcInit.ddc_ca.ca_ba.ba_clr,EAX
        MOV     ddcInit.ddc_ma.ma_ba.ba_clr,EAX

;/*
;** Only the color portion of the foreground IPC is correct.  The mono portion
;** may not be correct.  To get around this, we will hold off stuffing the new
;** foreground color until after we have realized the new brush.  At that
;** point, we can pick the IPC up out of the brush and stuff it in all the
;** appropriate places, having let the normal color conversion code
;** (MakeColorsValid) worry about correct monochrome color mapping.
;**
;** Since the default DDC uses the default color table, we have to set the
;** color portion of the foreground IPC before making the call.
;*/

        MOV     AX,ipcSysClrWindowText
        MOV     WORD ptr ctDefault+ct_aipc[FOREGND_WORD],AX
        INC     ddcInit.ddc_iSysClr              ; Show system colors changed again

;/*
;** We need to realize the correct brush bits now.
;*/

        MOV     EBX,offset ddcInit.ddc_pa
        MOV     ESI,offset ddcInit
        OR      [ESI].DDC.ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID OR BA_CLR_BACK_INV
        XOR     CX,CX

        INVOKE  MakeBrushValid,EAX               ; argument unused

IFDEF FIREWALLS

        OR      EAX,EAX
        JS      Set_sys_clrs_brush_bad
        MOV     AL,ddcInit.ddc_pa.pa_ba.ba_fb
        TEST    AL,BA_REREALIZE OR BA_CLR_INVALID OR BA_CLR_BACK_INV
        JNZ     Set_sys_clrs_brush_bad
        AND     AL,BA_CLR_DEF or BA_CLR_BACK_DEF
        CMP     AL,BA_CLR_DEF or BA_CLR_BACK_DEF
        JE      Set_sys_clrs_brush_good

Set_sys_clrs_brush_bad:
        rip        text,<Setting System Colors Destroyed Default Brush>

Set_sys_clrs_brush_good:

ENDIF ; FIREWALLS

;/*
;** Now that DDC.ddc_pa.pa_ba.ba_ipc contains the correct mono bit, we need to
;** propagate this bit to the other foreground IPCs.
;*/

        MOV     AX,ddcInit.ddc_pa.pa_ba.ba_ipc
        MOV     ddcInit.ddc_ia.ia_ba.ba_ipc,AX
        MOV     ddcInit.ddc_la.la_ba.ba_ipc,AX
        MOV     ddcInit.ddc_ca.ca_ba.ba_ipc,AX
        MOV     ddcInit.ddc_ma.ma_ba.ba_ipc,AX
        MOV     ipcSysClrWindowText,AX
        MOV     WORD ptr ctDefault+ct_aipc[FOREGND_WORD],AX
        JMP     CLCT_Exit_ok

;/*
;** We will be partying on the user's color table, or just creating a default
;** color table.
;**
;** If the reset option was given and there is no data, then just use the
;** default table, with whatever control bits they passed in.  If the reset
;** option wasn't given, we were previously in RGB mode, and the count is
;** zero, use the default table.
;**
;** Currently:
;**                EBX  =  0
;**                ECX  =  cCount
;**                EDX  =  lFormat
;**                ESI --> ddc
;*/

Not_system_colors:
        OR      ECX,ECX
        JNZ     Count_aint_zero
        TEST    flOptions,LCOL_RESET             ; 0 + RESET => default table
        JNZ     @F
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_RGB_MODE
        JNZ     @F
        JMP     CLCT_Common_exit                 ; Maybe a little clean up?

@@:
        JMP     CLCT_Format_default              ; Use the default color table

;/*
;** We will never get into any of the code between here and common_exit with a
;** zero count for the number of elements to set.
;**
;** There will be data to be set into the color table.  We want to validate it
;** before we change anything.  That way, we can back out if we need to
;** without having to do major repairs.
;*/

Count_aint_zero:
        MOV     EDI,pData
        CMP     EDX,LCOLF_CONSECRGB
        MOV     EDX,LOGICAL_COLOR_TABLE_SIZE
        JE      Validate_consecrgb

;/*
;** Do the INDRGB validation.
;*/

        MOV     EAX,PMERR_INV_COLOR_INDEX
        SHR     ECX,1
        JC      CLCT_Inv_len_or_cnt
        MOV     EBX,PMERR_INV_COLOR_DATA

;/*
;** At this point the following registers have the specified values:
;**    EAX  =  Error code for invalid color index
;**    EBX  =  Error code for invalid color data
;**    ECX  =  Count of elements
;**    EDI --> pData
;**    EDX  =  Size of the logical color table
;**
;** We are dealing here with the INDRGB format, so validate the index and
;** color of each element.
;*/

Validate_INDRGB_loop:
        CMP     [EDI],EDX                                ; Index too great?
        JAE     CLCT_Error_relay                 ;  Y - Goodbye
        XCHG    EAX,EBX                 ;  N - Switch error codes
        CMP     BYTE ptr [EDI][7],0     ; This resolves to the high-order byte
                                        ; of the color, which should not have
                                        ; a value if it's legitimate.
        JNZ     CLCT_Error_relay                 ;  Not legitimate - Away with you!
        XCHG    EAX,EBX                 ;  Legit - Swap the error code back
        ADD     EDI,(sizeof DWORD)*2    ; Point to next element
        LOOP    Validate_INDRGB_loop             ; Do it again (it was so-o-o good!)
        JMP     Everything_OK

CLCT_Inv_len_or_cnt:
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT

CLCT_Error_relay:
        JMP     CLCT_Error                               ; EAX = error code

;/*
;** Do the CONSECRGB validation.
;**
;** At this point the following registers contain the specified values.
;**    ECX =   Number of elements in data
;**    EDI --> Color table definition data
;**    EDX =   Size of the logical color table
;*/

Validate_consecrgb:
        MOV     EAX,PMERR_INV_COLOR_START_INDEX ; Start index cannot be
        MOV     EBX,lStart                      ; greater than the size of the
        SUB     EDX,EBX                         ; logical table
        JBE     CLCT_Error_relay
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT   ; Count cannot, either
        CMP     ECX,EDX
        JA      CLCT_Error_relay
        MOV     EAX,PMERR_INV_COLOR_DATA

Validate_consecrgb_loop:
        CMP     BYTE ptr [EDI][3],0             ; High-order byte of color
        JNZ     CLCT_Error_relay                ; must be zero to be valid
        ADD     EDI,sizeof DWORD
        LOOP    Validate_consecrgb_loop         ; Do for all elements

;/*
;** No doubt about it.  We need to have a color table of our own now.  Kind of
;** like becoming 18 and needing your own apartment.
;*/

DRGB_SIZE  = 4
TABLE_SIZE = SIZE COLOR_TABLE+LOGICAL_COLOR_TABLE_SIZE*(DRGB_SIZE+SIZE_IPC)

Everything_OK:
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JNZ     Log_table_exists                 ; Already have a color table
        LEA     EBX,pClrTbl                      ; private_alloc wants
                                                 ; EBX --> Pointer to allocated
        MOV     EAX,TABLE_SIZE                   ; block and EAX = size
        INVOKE  private_alloc
        OR      ECX,ECX                          ; Check for error
        JNZ     CLCT_Error_no_memory             ;  Yep - handle it, Joe
        MOV     EDI,pClrTbl                      ;  Nope - Save it, Sam
        MOV     [ESI].DDC.ddc_pClrTbl,EDI        ; EDI --> color table

;/*
;** LCOL_RESET will initialize all the fields of the color table, so we don't
;** have to perform any initialization.
;*/

        OR      flOptions,LCOL_RESET             ; Must reset the table
        JMP     Have_my_own_table

CLCT_Error_no_memory:
        MOV     EAX,PMERR_INSUFFICIENT_MEMORY
        JMP     CLCT_Error

;/*
;** See if the existing table belongs to us alone (e.g. not saved).  If we
;** don't have exclusive access rights to it, we'll clone it.a
;*/

Log_table_exists:
        MOV     EDI,[ESI].DDC.ddc_pClrTbl
        CMP     [EDI].COLOR_TABLE.ct_cSave,1
        JZ      Have_my_own_table
        LEA     EBX,pClrTbl                      ; private_alloc wants EBX --> pointer
        MOV     EAX,TABLE_SIZE                   ; to table and EAX = size
        INVOKE  private_alloc
        OR      ECX,ECX                          ; Error?
        JNZ     CLCT_Error_no_memory             ;  Y - So sad
        PUSH    EDI                              ;  N - Copy the old contents
        MOV     EDI,pClrTbl
        MOV     [ESI].DDC.ddc_pClrTbl,EDI
        POP     ESI
        MOV     ECX,TABLE_SIZE/2
    REP MOVSW
        SUB     ESI,TABLE_SIZE                   ; ESI = Old color table
        SUB     EDI,TABLE_SIZE                   ; EDI = New color table
        DEC     [ESI].COLOR_TABLE.ct_cSave       ; We don't want the old one
        MOV     [EDI].COLOR_TABLE.ct_cSave,1
        MOV     ESI,pInstance

Have_my_own_table:

;/*
;** We now have our very own color table set up ready to take whatever color
;** data that was passed.  We must now handle LCOL_RESET.
;*/

        MOV     AL,[ESI].DDC.ddc_fbClrTbl       ; Show we have a color table
                                                ; now
        AND     AL,NOT DDC_RGB_MODE
        OR      AL,DDC_LOG_CLR_TBL
        MOV     [ESI].DDC.ddc_fbClrTbl,AL
        TEST    flOptions,LCOL_RESET
        JZ      No_reset
        AND     AL,not (DDC_USER_CLR_0 or DDC_USER_CLR_7)
        MOV     [ESI].DDC.ddc_fbClrTbl,AL

CLCT_perform_reset:
        MOV     [EDI].COLOR_TABLE.ct_usId,CT_IDENT
        LEA     EAX,[EDI + ct_aipc + LOGICAL_COLOR_TABLE_SIZE * SIZE_IPC]
        MOV     [EDI].COLOR_TABLE.ct_npargb,EAX
        MOV     [EDI].COLOR_TABLE.ct_cSave,1
        MOV     [EDI].COLOR_TABLE.ct_iMin,0
        MOV     [EDI].COLOR_TABLE.ct_iMax,DEFAULT_COLOR_TABLE_SIZE - 1
        ADD     EDI,ct_aipc
        MOV     ESI,offset ctDefault+ct_aipc
        MOV     ECX,DEFAULT_COLOR_TABLE_SIZE
    REP MOVSW
        MOV     EAX,INVALID_IPC_DWORD
        MOV     ECX,LOGICAL_COLOR_TABLE_SIZE - DEFAULT_COLOR_TABLE_SIZE
    REP STOSW
        MOV     ECX,DEFAULT_COLOR_TABLE_SIZE
    REP MOVSD
        MOV     EAX,-1
        MOV     ECX,LOGICAL_COLOR_TABLE_SIZE - DEFAULT_COLOR_TABLE_SIZE
   REP  STOSD
        SUB     EDI,TABLE_SIZE                           ; EDI --> color table
        MOV     ESI,pInstance                            ; ESI = HDDC

No_reset:
        ddc?    ESI
        MOV     ECX,cCount
        JECXZ   CLCT_Common_exit_relay
        CMP     lFormat,LCOLF_CONSECRGB
        JNZ     Not_consecutive

;/*
;** Handle setting LCOLF_CONSECRGBs into the color table
;*/

        MOV     EAX,lStart                               ; Adjust the min and max
        MOV     EBX,EAX
        CMP     [EDI].COLOR_TABLE.ct_iMin,EBX
        JB      Have_my_min
        MOV     [EDI].COLOR_TABLE.ct_iMin,EBX

Have_my_min:
        ADD     EBX,ECX
        DEC     EBX
        CMP     [EDI].COLOR_TABLE.ct_iMax,EBX
        JG      Have_my_max                              ; COLOR_TABLE.ct_iMax might be -1
        MOV     [EDI].COLOR_TABLE.ct_iMax,EBX

Have_my_max:

;/*
;** If colors 0 or 7 are set by the caller, then we must track these so we
;** don't overwrite them when the system colors change.
;*/

        OR      EAX,EAX
        JNZ     Dont_have_index_0
        OR      [ESI].DDC.ddc_fbClrTbl,DDC_USER_CLR_0

Dont_have_index_0:
        CMP     EAX,7
        JG      Dont_have_index_7
        CMP     EBX,7
        JL      Dont_have_index_7
        OR      [ESI].DDC.ddc_fbClrTbl,DDC_USER_CLR_7

Dont_have_index_7:

;/*
;** Set up for the loop and then copy the data over.
;*/

        LEA     EBX,[EDI]+ct_aipc
        ADD     EAX,EAX
        ADD     EBX,EAX                 ; EBX --> IPC
        MOV     EDI,[EDI].COLOR_TABLE.ct_npargb
        ADD     EDI,EAX
        ADD     EDI,EAX                 ; EDI --> RGB
        MOV     ESI,pData                                ; ESI --> Input colors

Consecrgb_loop:
;DS:SI => input colors
        LODSD
        STOSD
        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc
        MOV     [EBX],AX
        INC     EBX
        INC     EBX
        LOOP    Consecrgb_loop

CLCT_Common_exit_relay:
        JMP     CLCT_Common_exit

;/*
;** Handle setting LCOLF_INDRGBs into the color table
;*/

Not_consecutive:
        SHR     ECX,1
        MOV     ESI,pData
        PUSH    EBP                             ; Need an extra register
        XOR     EBP,EBP

INDRGB_Loop:
        LODSD
        XCHG    EAX,EBX                         ; EBX = Index
        LODSD                                   ; EAX = Color
        CMP     [EDI].COLOR_TABLE.ct_iMin,EBX
        JB      Already_below
        MOV     [EDI].COLOR_TABLE.ct_iMin,EBX

Already_below:
        CMP     [EDI].COLOR_TABLE.ct_iMax,EBX
        JG      Already_above                                    ; COLOR_TABLE.ct_iMax might
                                                ; be -1
        MOV     [EDI].COLOR_TABLE.ct_iMax,EBX

Already_above:
        OR      EBX,EBX
        JNE     Not_index_0
        OR      EBP,DDC_USER_CLR_0

Not_index_0:
        CMP     EBX,7
        JNE     Not_index_7
        OR      EBP,DDC_USER_CLR_7

Not_index_7:
        PUSH    EDI
        MOV     EDI,[EDI].COLOR_TABLE.ct_npargb
        SHL     EBX,2
        ADD     EDI,EBX
        SHR     EBX,1
        STOSD
        POP     EDI
        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc
        MOV     WORD ptr [EDI]+ct_aipc[EBX],AX
        LOOP    INDRGB_Loop

        XCHG    EAX,EBP
        POP     EBP
        MOV     EBX,pInstance
        OR      [EBX].DDC.ddc_fbClrTbl,AL

;/*
;** We are almost done.  All we need to do is set the dither and realizable
;** bits, and invalidate all the colors of this DDC.
;*/

CLCT_Common_exit:
        ddc?    pInstance
        MOV     ESI,pInstance
        MOV     AL,[ESI].DDC.ddc_fbClrTbl
        AND     AL,not (DDC_DITHER or DDC_REALIZABLE)
        MOV     EBX,flOptions
        TEST    BL,LCOL_PURECOLOR
        JNZ     @F
        OR      AL,DDC_DITHER
@@:
        TEST    BL,LCOL_REALIZABLE
        JZ      @F
        OR      AL,DDC_REALIZABLE
@@:
        MOV     [ESI].DDC.ddc_fbClrTbl,AL
        OR      [ESI].DDC.ddc_ca.ca_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_la.la_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_ia.ia_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_ma.ma_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE

;/*
;** Caching causes a problem in that if the new IPCs match the old, and nothing
;** else changed, we won't pick up on the dithering flag changing.  We will
;** force a re-realization by indicating that the codepoint or font changed.
;*/

        OR      [ESI].DDC.ddc_pa.pa_fs,CA_CHANGED

CLCT_Exit_ok:
        MOV     EAX,1

CLCT_Exit:
        INVOKE  leave_driver

CLCT_Exit_no_lock:
        fw_zero <ECX>

        RET

CreateLogColorTable ENDP
_TUNE ENDS
        SUBTITLE QueryLogColorTable
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryLogColorTable
;*
;* DESCRIPTION   = Returns the logical color of the currently associated
;*                 device, one at a time.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall QueryLogColorTable (HDC   hdc,
;*                                                     ULONG flOptions,
;*                                                     LONG  lStart,
;*                                                     LONG  cArray,
;*                                                     PLONG pArray,
;*                                                     PVOID pInstance,
;*                                                     ULONG lFunction);
;*
;*                    where:
;*
;*                      All arguments are as specified for the GreQueryLogColorTable
;*                      function.
;*
;* OUTPUT        =  As specified for the GreQueryLogColorTable function.
;*
;* RETURN-NORMAL =  As specified for the GreQueryLogColorTable function.
;* RETURN-ERROR  =  As specified for the GreQueryLogColorTable function.
;*
;**************************************************************************/

QueryLogColorTable PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc      :HDC,
                flOptions:ULONG,
                lStart   :LONG,
                cArray   :LONG,
                pArray   :PLONG,
                pInstance:PVOID,
                lFunction:ULONG

        LOCAL   nCount:DWORD

        DebugMsg <QueryLogColorTable,DISPATCH,KEZ>

        CLD
        MOV     EDI,pInstance                   ; EDI = DDC
        MOV     EDX,EDI
        INVOKE  enter_driver
        MOV     EAX,QLCT_ERROR                                   ; Assume error
        JC      QLCT_Exit_no_lock

;/*
;** Reject     options
;*/

        XOR     EBX,EBX                         ; EBX = 0
        MOV     nCount,EBX                                       ; nCount = 0
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT
        CMP     WORD ptr cArray+2,BX
        JNZ     QLCT_Error
        MOV     EAX,PMERR_INV_COLOR_START_INDEX
        CMP     WORD ptr lStart+2,BX
        JNZ     QLCT_Error
        MOV     EAX,PMERR_INV_COLOR_OPTIONS
        CMP     WORD ptr flOptions+2,BX
        JNZ     QLCT_Error
        TEST    WORD ptr flOptions,not LCOLOPT_INDEX
        JZ      No_obvious_errors

QLCT_Error:
        save_error_code
        MOV     EAX,QLCT_ERROR                                   ; -1
        JMP     QLCT_Exit

No_obvious_errors:

;/*
;** Make sure any color table is up to date with the system colors.
;*/

        MOV     EAX,[EDI].DDC.ddc_iSysClr
        CMP     EAX,ddcInit.ddc_iSysClr
        JE      @F
        INVOKE  PropagateSysClrChange

@@:

;/*
;** Return if in RGB mode
;*/

        MOV     EAX,QLCT_RGB                                     ; -2
        MOV     CL,[EDI].DDC.ddc_fbClrTbl        ; CL = DDC.ddc_fbClrTbl
        TEST    CL,DDC_RGB_MODE
        JNZ     QLCT_Exit

;/*
;** Locate logical color table
;*/

        MOV     ESI,[EDI].DDC.ddc_pClrTbl       ; ESI --> Color table

;/*
;** Determine the number of elements that fit in the return array
;*/

        MOV     ECX,cArray                                       ; ECX = Number requested
        JECXZ   Color_table_copied                       ; We're done if they asked
                                                ; for no entries

;/*
;** Determine the number that we could copy from the table.
;*/

        MOV     EAX,lStart                                       ; EAX = Logical Color Index
        MOV     EDX,[ESI].COLOR_TABLE.ct_iMax
        INC     EDX
        SUB     EDX,EAX                         ; EDX = Number to copy
        JBE     Color_table_copied                       ; Start index after end of
                                                ; table

;/*
;** Prepare to copy color table.
;*/

        MOV     EDI,pArray                                       ; EDI = Output buffer
        MOV     ESI,[ESI].COLOR_TABLE.ct_npargb          ; ESI = RGB colors

;/*
;** Advance to first index
;*/

        ADD     ESI,EAX                         ; 4 bytes per RGB entry
        ADD     ESI,EAX
        ADD     ESI,EAX
        ADD     ESI,EAX

;/*
;** Split to two loops
;*/

        TEST    WORD ptr flOptions,LCOLOPT_INDEX
        JNZ     Copy_with_index_loop

;/*
;** Limit the number we may return to the number we have.
;*/

        CMP     ECX,EDX
        JB      Count_is_low_enough
        MOV     ECX,EDX                         ; ECX = Number to copy

Count_is_low_enough:

;/*
;** Just copy the colors.
;*/

        MOV     EAX,ECX
        SHL     ECX,1                           ; Change DWORD cnt to WORD cnt
    REP MOVSW
        JMP     QLCT_Exit

;/*
;** Copy indices and colors.
;*/

Copy_with_index_loop:
        XCHG    ECX,EDX                         ; ECX = Max table entry
        SHR     EDX,1                           ; EDX = # of entries asked for

Index_loop:
        CMP     BYTE ptr [ESI][3],-1            ; Color not loaded if its
                                                ; index high-order byte is -1
        JZ      Skip_color
        STOSD                                   ; Store index
        MOVSD                                   ; Copy the RGB value
        ADD     nCount,2
        DEC     EDX                             ; We've filled another element
                                                ; in the users array.
        JZ      Color_table_copied                       ; Is it full Yet?
        SUB     ESI,4

Skip_color:
        ADD     ESI,4
        INC     EAX                             ; Advance index
        LOOP    Index_loop                                       ; Have we exhausted the table
                                                ; yet?

;/*
;** Return the number copied
;*/

Color_table_copied:
        MOV     EAX,nCount

QLCT_Exit:
        INVOKE  leave_driver

QLCT_Exit_no_lock:

        RET

QueryLogColorTable ENDP

        SUBTITLE QueryRealColors
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryRealColors
;*
;* DESCRIPTION   = Returns the RGB values of the distinct colors available
;*                 on the currently associated device, one at a time.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall QueryRealColors (HDC   hdc,
;*                                                  ULONG flOptions,
;*                                                  LONG  lStart,
;*                                                  LONG  cArray,
;*                                                  PLONG pArray,
;*                                                  PVOID pInstance,
;*                                                  ULONG lFunction);
;*
;*                    where:
;*                      All arguments are as specified for the GreQueryRealColors
;*                      function
;*
;* OUTPUT        = As specified for the GreQueryRealColors function.
;*
;* RETURN-NORMAL = As specified for the GreQueryRealColors function.
;* RETURN-ERROR  = As specified for the GreQueryRealColors function.
;*
;**************************************************************************/

QueryRealColors PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc      :HDC,
                flOptions:ULONG,
                lStart   :LONG,
                cArray   :LONG,
                pArray   :PLONG,
                pInstance:PVOID,
                lFunction:ULONG

        LOCAL   nCount    :DWORD
        LOCAL   nCountLeft:DWORD
        LOCAL   ColorFlags:DWORD

        CLD
        MOV     EDX,pInstance                   ; EDX --> Instance data
        INVOKE  enter_driver
        MOV     EAX,-1                          ; Assume error
        JC      QRC_Exit_no_lock

;/*
;** Validate the arguments.
;*/

        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT
        XOR     EBX,EBX                         ; EBX = 0
        CMP     WORD ptr cArray+2,BX
        JNZ     QRC_Error
        MOV     EAX,PMERR_INV_COLOR_OPTIONS
        CMP     WORD ptr flOptions+2,BX
        JNZ     QRC_Error
        TEST    WORD ptr flOptions,not (LCOLOPT_REALIZED + LCOLOPT_INDEX)
        JZ      QRC_Valid
        JMP     QRC_Error

QRC_Inv_start:
        MOV     AX,PMERR_INV_COLOR_START_INDEX
        .ERRNZ  $ - QRC_Error

QRC_Error:
        save_error_code
        MOV     EAX,GPI_ALTERROR
        JMP     QRC_Final_exit

QRC_Valid:
        MOV     nCount,EBX                       ; Initialize nCount

;/*
;** Get the count of colors we may return.
;*/

        MOV     ECX,cArray
        OR      ECX,ECX
        JZ      QRC_Exit
        TEST    WORD ptr flOptions,LCOLOPT_INDEX ; Do we return index
                                                 ;as well?
        JZ      Count_is_num_entry
        SHR     ECX,1                            ; ECX = Color Count

Count_is_num_entry:

;/*
;** Get the count of colors remaining
;*/

        assert  EBX,E,0
        CMP     lStart,010000h
        JAE     QRC_Inv_start
        MOV     EAX,lStart                       ; EAX = lStart
        MOV     EDX,DEVCAPS_COLORS
        SUB     EDX,EAX                          ; EDX = Count remaining
        JBE     QRC_Inv_start                    ; Start out of range

;/*
;** Limit the color count to the count remaining.
;*/

        CMP     ECX,EDX
        JB      QRC_Small_enough
        MOV     ECX,EDX                          ; ECX = Colors to copy

QRC_Small_enough:
        assert  ECX,NE,0
        MOV     nCountLeft,ECX

;/*
;** We can calculate the return value now.
;*/

        TEST    WORD ptr flOptions,LCOLOPT_INDEX
        JZ      Count_is_num_element
        SHL     ECX,1

Count_is_num_element:
        MOV     nCount,ECX

;/*
;** Get pointer to the RGB table.
;*/

        MOV     ESI,offset adrgbIndex
        SHL     EAX,2

IFDEF CLR2

;/*
;** The only choices are black and white.
;*/
        MOV     EDX,15
        MUL     EDX

ENDIF ; CLR2

        ADD     ESI,EAX

;/*
;** Do the copy loop
;*/

        MOV     EDI,pArray                       ; EDI = pArray
        MOV     EBX,pInstance                    ; EBX = DDC

QRC_Loop:

;/*
;** Store the index first, if requested.
;*/

        TEST    WORD ptr flOptions,LCOLOPT_INDEX
        JZ      No_index
        MOV     AX,WORD ptr [ESI]
        MOV     DX,WORD ptr [ESI]+2
        INVOKE  rgb_to_ipc                       ; EAX = Our physical color
        INVOKE  ipc_to_index                     ; EAX = Index
        STOSD

No_index:

;/*
;** Copy the color.
;*/

        MOVSD

IFDEF CLR2

;/*
;** The only choices are black and white.
;*/

        ADD     ESI,14*4

ENDIF ; CLR2

        DEC     nCountLeft
        JNZ     QRC_Loop

QRC_Exit:
        MOV     EAX,nCount

QRC_Final_exit:
        INVOKE  leave_driver

QRC_Exit_no_lock:
        RET

QueryRealColors ENDP
_TUNE segment USE32 PUBLIC 'CODE'
        SUBTITLE QueryNearestColor
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryNearestColor
;*
;* DESCRIPTION   = Returns the nearest color available to the specified
;*                 color.  Both colors are specified as RGB.  Note that the
;*                 nearest color returned may not be present in the current
;*                 logical color table.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall QueryNearestColor (HDC   hdc,
;*                                                    ULONG flOptions,
;*                                                    LONG  rgbColorIn,
;*                                                    PVOID pInstance,
;*                                                    ULONG lFunction);
;*
;*                    where:
;*                      All arguments are as specified in the GreQueryNearestColor
;*                      function
;*
;* OUTPUT        = As specified in the GreQueryNearestColor function.
;*
;* RETURN-NORMAL = As specified in the GreQueryNearestColor function.
;* RETURN-ERROR  = As specified in the GreQueryNearestColor function.
;*
;**************************************************************************/

QueryNearestColor PROC SYSCALL PUBLIC uses EBX,
        hdc       :HDC,
        flOptions :ULONG,
        rgbColorIn:LONG,
        pInstance :PVOID,
        lFunction :ULONG

       DebugMsg <QueryNearestColor,DISPATCH,KEZ>

;/*
;** Validate the arguments.
;*/

        XOR     EBX,EBX                          ; EBX = 0
        MOV     EAX,PMERR_INV_COLOR_OPTIONS
        CMP     WORD ptr flOptions+2,BX          ; H-O word of options should
        JNZ     QNC_Error                        ; be zero
        TEST    WORD ptr flOptions,not LCOLOPT_REALIZED
        JNZ     QNC_Error
        MOV     EAX,PMERR_INV_RGBCOLOR           ; A valid RGB color does not
        CMP     BYTE ptr rgbColorIn[3],BL        ; have a value in its high-
        JZ      QNC_Valid                        ; order byte

QNC_Error:
        save_error_code

QNC_Exit_no_lock:
        MOV     EAX,-1
        JMP     QNC_Final_exit

QNC_Valid:

;/*
;** Do the work.
;*/

        MOV     EDX,pInstance                    ; EDX --> Instance data
        INVOKE  enter_driver
        JC      QNC_Exit_no_lock                 ; Error exit without
                                                 ; leave_driver

IFDEF CLR2

;/*
;** The only choices are black and white.  If R+G+B > 3/2 * 255 then return
;** white.  Otherwise return black.
;*/

        XOR     EDX,EDX
        MOVZX   EAX,WORD ptr rgbColorIn
        XCHG    AH,DL
        ADD     AX,DX   ; AX = sum of Green and Blue.
        ADD     AX,WORD ptr rgbColorIn+2         ; AX = sum of Red, Green, and Blue.
        CMP     AX,383  ; Least integer greater than 3/2 * 255
                                        ;  Carry is set if nearest is Black.
        SBB     AX,AX   ; EAX = -1 if black, EAX = 0 if white
        NOT     AX      ; EAX = 0 if black, EAX = -1 if white
        SHL     EAX,8
        MOV     AL,AH   ; EAX bits 0-23 = 0 if black, -1 if white

ELSE ; not CLR2

;/*
;** Get physical color
;*/

        MOV     AX,WORD ptr rgbColorIn                   ; EAX = RGB color
        MOV     DX,WORD ptr rgbColorIn+2
        INVOKE  rgb_to_ipc                               ; EAX = Physical color index

;/*
;** Look up its RGB color.
;*/

        AND     EAX,ipc_index_mask
        MOV     EBX,EAX
        SHL     EBX,2
        MOV     EAX,adrgbIndex[EBX]

ENDIF ; !CLR2

        INVOKE  leave_driver

QNC_Final_exit:
        RET

QueryNearestColor ENDP
        SUBTITLE QueryColorIndex
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryColorIndex
;*
;* DESCRIPTION   = This function is invoked from the GRE dispatch table in
;*                 response to a call to the GreQueryColorIndex function.
;*                 It returns the logical colr index that is closest to the
;*                 specified RGB color representation for the device.  If
;*                 the color index is RGB mode, the supplied RGB value is
;*                 returned.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall QueryColorIndex (HDC   hdc,
;*                                                  ULONG flOptions,
;*                                                  LONG  rgbColor,
;*                                                  PVOID pInstance,
;*                                                  ULONG lFunction);
;*
;*                    where:
;*                      All arguments are as specified in the GreQueryColorIndex
;*                      function
;*
;* OUTPUT        = As specified in the GreQueryColorIndex function
;*
;* RETURN-NORMAL = As specified in the GreQueryColorIndex function
;* RETURN-ERROR  = As specified in the GreQueryColorIndex function
;*
;**************************************************************************/

QueryColorIndex PROC SYSCALL PUBLIC uses EBX,
        hdc      :HDC,
        flOptions:ULONG,
        rgbColor :LONG,
        pInstance:PVOID,
        lFunction:ULONG

        DebugMsg <QueryColorIndex,DISPATCH,KEZ>

;/*
;** Validate the arguments.
;*/

        MOV     EAX,PMERR_INV_RGBCOLOR           ; Valid RGB colors don't have
        CMP     BYTE ptr rgbColor[3],0           ; anything in the high-order
        JNZ     QCI_Error                                        ; byte
        MOV     EAX,PMERR_INV_COLOR_OPTIONS      ; No valid options exist in
        TEST    flOptions,not LCOLOPT_REALIZED   ; Only valid option is
        JZ      QCI_Valid                        ; LCOLOPT_REALIZED

QCI_Error:
        save_error_code

QCI_Exit_no_lock:
        MOV     EAX,-1
        JMP     QCI_Final_exit

QCI_Valid:

;/*
;** Do it!
;*/

        MOV     EDX,pInstance                    ; EDX --> DDC
        INVOKE  enter_driver
        JC      QCI_Exit_no_lock                 ; Error exit without
                                                 ; leave_driver

;/*
;** Get physical color.
;*/

        MOV     EBX,pInstance                    ; EBX --> DDC
        MOV     EAX,rgbColor                     ; EAX = RGB color

;/*
;** Just return the input for RGB mode.
;*/

        TEST    BYTE ptr [EBX].DDC.ddc_fbClrTbl,DDC_RGB_MODE
        JNZ     QCI_Exit

;/*
;** Look up the index.
;*/

        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc                       ; EAX = Our physical color
        INVOKE  ipc_to_index                     ; EAX = Index
        CMP     EAX,10000h
        JB      QCI_Exit                         ; Index found

        INVOKE  FLAT:RGBToNearestIndex,rgbColor

QCI_Exit:
        INVOKE  leave_driver                     ; EAX = RGBOut

QCI_Final_exit:
        RET

QueryColorIndex ENDP

_TUNE ENDS

        SUBTITLE QueryRGBColor
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryRGBColor
;*
;* DESCRIPTION   = This function is invoked from the GRE dispatch table in
;*                 response to a call to the GreQueryRGBColor function and
;*                 returns the actual RGB color which will result from the
;*                 specified color index for the specified device.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall QueryRGBColor (HDC   hdc,
;*                                                ULONG flOptions,
;*                                                LONG  iColor,
;*                                                PVOID pInstance,
;*                                                ULONG lFunction);
;*
;*                    where:
;*                      All arguments are as specified for the GreQueryRGBColor
;*                      function
;*
;* OUTPUT        = As specified for the GreQueryRGBColor function.
;*
;* RETURN-NORMAL = As specified for the GreQueryRGBColor function.
;* RETURN-ERROR  = As specified for the GreQueryRGBColor function.
;*
;**************************************************************************/

QueryRGBColor PROC SYSCALL PUBLIC uses EBX ESI,
                hdc      :HDC,
                flOptions:ULONG,
                iColor   :LONG,
                pInstance:PVOID,
                lFunction:ULONG

        DebugMsg <QueryRGBColor,DISPATCH,KEZ>

;/*
;**!!! Must recognize color/mono for nearest color.
;*/

        MOV     ESI,pInstance                    ; ESI --> DDC
        MOV     EDX,ESI                          ; EDX --> DDC
        INVOKE  enter_driver
        MOV     EAX,-1                           ; Assume error
        JC      QRGB_Exit_no_lock

;/*
;** Validate the arguments
;*/

        MOV     EAX,PMERR_INV_COLOR_OPTIONS
        CMP     WORD ptr flOptions+2,0                   ; No valid options in h-o-w
        JNZ     QRGB_Error
        TEST    WORD ptr flOptions,not LCOLOPT_REALIZED+LCOLOPT_REQUESTED
        JZ      QRGB_Valid

QRGB_Error:
        save_error_code

QRGB_Return_error:
        MOV     EAX,-1
        JMP     QueryRGBColor_exit

QRGB_Valid:

;/*
;** Handle the DISPLAYABLE RGB case.
;*/

        MOV     EAX,iColor                       ; EAX = Index
        TEST    flOptions,LCOLOPT_REQUESTED
        JNZ     Get_requested_color

;/*
;** Translate the index.
;*/

        XOR     ECX,ECX                          ; No defaults
        INVOKE  ColorConvert                     ; Get EAX = IPC
        JS      QRGB_Return_error

;/*
;** Convert the IPC into an RGB.
;*/

        AND     EAX,ipc_index_mask
        SHL     EAX,2
        MOV     EBX,EAX
        MOV     EAX,adrgbIndex[EBX]
        JMP     QueryRGBColor_exit

;/*
;** Handle the REQUESTED RGB case
;*/

Get_requested_color:
        CMP     EAX,0                            ; If negative, might be one of the
        JGE     Not_special_color                ; special colors
        SUB     EAX,MIN_SYSTEM_COLOR             ; Special color within range?
        JC      Invalid_color_index

;/*
;** The color is a SPECIAL color.  Look it up in adrgbSpecial.
;*/

        SHL     EAX,2
        XCHG    EAX,EBX                          ; EBX = Special color index
        MOV     EAX,adrgbSpecial[EBX]

Check_requested_color:
        TEST    EAX,0FF000000h                   ; Valid color?
        JZ      QueryRGBColor_exit               ;  Y - Exit

Invalid_color_index:
        MOV     EAX,PMERR_INV_COLOR_INDEX
        JMP     QRGB_Error

;/*
;** The color was not a special color.
;*/

Not_special_color:
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_RGB_MODE
        JNZ     Check_requested_color            ; Just return for RGB mode
        TEST    EAX,0FF000000h                   ; Valid color has nothing in
        JNZ     Invalid_color_index              ; high-order byte
        PUSH    EAX                              ; Save color
        INVOKE  PropagateSysClrChange
        POP     EAX
        MOV     EBX,[ESI].DDC.ddc_pClrTbl        ; EBX --> Color table
        CMP     EAX,[EBX].COLOR_TABLE.ct_iMax    ; Color index too high?
        JA      Invalid_color_index              ;  Y - Invalid
        SHL     EAX,2
        XCHG    EAX,ESI                          ; EAX --> DDC
                                                 ; ESI = Offset in color table
        ADD     ESI,[EBX].COLOR_TABLE.ct_npargb  ; ESI --> Color table entry
        MOV     EAX,[ESI]
        JMP     Check_requested_color            ; Make sure it's valid

QueryRGBColor_exit:
        INVOKE  leave_driver

QRGB_Exit_no_lock:

        RET

QueryRGBColor ENDP

_TUNE segment USE32 PUBLIC 'CODE'
        SUBTITLE save_lct
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = save_lct
;*
;* DESCRIPTION   = Increments the reference count for the user's color table.
;*
;*                 Registers Destroyed:
;*                       AX,BX,ES
;*
;* INPUT         = ESI --> DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

save_lct PROC SYSCALL PUBLIC uses EBX

        DebugMsg <save_lct,KEZ>

        ddc?    ESI

;/*
;** Just return if there is no user color table.
;*/

        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JZ      Save_LCT_done

;/*
;** Locate the table.
;*/

        MOV     EBX,[ESI].DDC.ddc_pClrTbl

;/*
;** Increment the reference count.
;*/

        INC     [EBX].COLOR_TABLE.ct_cSave

Save_LCT_done:

        RET

save_lct ENDP
        SUBTITLE deselect_lct
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = deselect_lct
;*
;* DESCRIPTION   = Frees a reference to a logical color table.  Decrements
;*                 the reference count and frees the memory if it hits
;*                 zero.
;*
;* INPUT         = ESI --> DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

deselect_lct PROC SYSCALL PUBLIC uses EBX

        DebugMsg <deselect_lct,KEZ>

        ddc?    ESI

;/*
;** Just return if there is no user color table.
;*/

        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JZ      Deselect_LCT_done

;/*
;** Locate the table.
;*/

        MOV     EBX,[ESI].DDC.ddc_pClrTbl       ; EBX --> Color table

;/*
;** Decrement the reference count.
;*/

        DEC     [EBX].COLOR_TABLE.ct_cSave
        JNZ     Dont_free_it
        MOV     ECX,EBX                         ; ECX --> Color table
        INVOKE  private_free

Dont_free_it:

;/*
;** Mark the flags to indicate there is no user table, since this might be part
;** of a ResetDC.
;*/

        AND     [ESI].DDC.ddc_fbClrTbl,not DDC_LOG_CLR_TBL
        MOV     [ESI].DDC.ddc_pClrTbl,offset ctDefault

Deselect_LCT_done:
        RET

deselect_lct ENDP
_TUNE ENDS

        SUBTITLE PropagateSysClrChange
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = PropagateSysClrChange
;*
;* DESCRIPTION   = Prepare the system to act correctly the next time it
;*                 needs to use a color after a system color has changed.
;*                 This subroutine is called only after at least one system
;*                 color has changed.  Since we can't know which color
;*                 changed, we must act as though all of them have.  Two
;*                 color table indices, 0 and 7, are by default set to
;*                 certain system colors.  If either of these system colors
;*                 change, and the default mapping is still in effect, then
;*                 the corresponding IPC (internal physical color) must be
;*                 updated from the default color table.  The default
;*                 mapping is in effect unless the user explicitly defined
;*                 the colors, indicated by the DDC_CLR_*_USERS bits being
;*                 set.  Furthermore, any attribute bundle which has a
;*                 system color selected into it must be updated.  We do
;*                 this lazily by marking the IPC as invalid, so that it
;*                 won't be re-realized until necessary.
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX
;*
;* INPUT         = ESI --> DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

PropagateSysClrChange PROC SYSCALL PUBLIC uses EDI

        DebugMsg <PropagateSysClrChange,KEZ>

        ddc?    ESI

;/*
;** Mark as invalid any attributes that use a system color.  Since it's
;** expensive to check them all, we'll just invalidate everything.
;**
;*/

        OR      [ESI].DDC.ddc_ca.ca_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_la.la_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_ia.ia_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE
        OR      [ESI].DDC.ddc_ma.ma_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE

        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JZ      PSCC_Exit

;/*
;** Copy index zero over unless it has been defined by the app.
;*/

        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_USER_CLR_0
        JNZ     PSCC_Checked_index_0
        MOV     EDI,[ESI].DDC.ddc_pClrTbl
        MOV     AX,WORD ptr ctDefault+ct_aipc[BACKGND_WORD]
        MOV     [EDI]+ct_aipc[BACKGND_WORD],AX
        MOV     EDI,[EDI].COLOR_TABLE.ct_npargb
        MOV     EAX,adrgbDefault[BACKGND_DWORD]
        MOV     [EDI][BACKGND_DWORD],EAX

PSCC_Checked_index_0:

;/*
;** Copy index seven over unless it has been defined by the app.
;*/

        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_USER_CLR_7
        JNZ     PSCC_Checked_index_7
        MOV     EDI,[ESI].DDC.ddc_pClrTbl
        MOV     AX,WORD ptr ctDefault+ct_aipc[FOREGND_WORD]
        MOV     [EDI]+ct_aipc[FOREGND_WORD],AX
        MOV     EDI,[EDI].COLOR_TABLE.ct_npargb
        MOV     EAX,adrgbDefault[FOREGND_DWORD]
        MOV     [EDI][FOREGND_DWORD],EAX

PSCC_Checked_index_7:

PSCC_Exit:
        MOV     EAX,ddcInit.ddc_iSysClr          ; Show up-to-date by setting iSysClr
        MOV     [ESI].DDC.ddc_iSysClr,EAX        ; to current system count
        OR      [ESI].DDC.ddc_fbBelow,DDC_DIRTY_ATTRS

        RET

PropagateSysClrChange ENDP
_TUNE segment USE32 PUBLIC 'CODE'
ResetLogColorTable PROC SYSCALL USES EDI,
        pddc:PDDC
        mov     edi,pddc
        and     [edi].DDC.ddc_fbClrTbl,not DDC_RGB_MODE
        mov     [edi].DDC.ddc_pClrTbl,OFFSET ctDefault
        ret
ResetLogColorTable ENDP
;_TUNE segment USE32 PUBLIC 'CODE'
device_enter_driver PROC SYSCALL
        ret
device_enter_driver ENDP
_TUNE ENDS
        END
