;*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

;/*
;** 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
;*
;**************************************************************************/
ALIGN 4
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
;*
;**************************************************************************/

ALIGN 4
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 
;*
;**************************************************************************/
ALIGN 4
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                       
ALIGN 4

QCD_Log_error:
        save_error_code
        XOR     AX,ax    
        JMP     QCD_Exit                          
ALIGN 4

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 
;*
;**************************************************************************/

ALIGN 4
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                          
ALIGN 4

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 
;*
;**************************************************************************/

ALIGN 4
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
   
        SUBTITLE CreateLogColorTable
        PAGE +

;/***************************************************************************
;*
;* 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
;*
;**************************************************************************/

ALIGN 4
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                  
ALIGN 4

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

CLCT_Error:
        save_error_code
        XOR     EAX,EAX  
        JMP     CLCT_Exit                         
ALIGN 4

;/*
;** 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            
ALIGN 4

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

CLCT_Exit_OK_relay:
        JMP     CLCT_Exit_ok                      
ALIGN 4

CLCT_Bad_color:
        MOV     EAX,PMERR_INV_COLOR_DATA          
        JMP     CLCT_Error                        
ALIGN 4

CLCT_Bad_index:
        MOV     EAX,PMERR_INV_COLOR_INDEX         
        JMP     CLCT_Error                        
ALIGN 4

CLCT_Bad_start_index:
        MOV     EAX,PMERR_INV_COLOR_START_INDEX   
        JMP     CLCT_Error                        
ALIGN 4

CLCT_Bad_count:
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT     
        JMP     CLCT_Error                        
ALIGN 4

;/*
;** 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                      
ALIGN 4

;/*
;** 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?
ALIGN 4

@@:
        JMP     CLCT_Format_default              ; Use the default color table
ALIGN 4

;/*
;** 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                     
ALIGN 4

CLCT_Inv_len_or_cnt:
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT     

CLCT_Error_relay:
        JMP     CLCT_Error                               ; EAX = error code
ALIGN 4

;/*
;** 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                 
ALIGN 4

CLCT_Error_no_memory:
        MOV     EAX,PMERR_INSUFFICIENT_MEMORY     
        JMP     CLCT_Error                        
ALIGN 4

;/*
;** 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                  
ALIGN 4

;/*
;** 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
   
        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. 
;*
;**************************************************************************/

ALIGN 4
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                         
ALIGN 4

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                         
ALIGN 4

;/*
;** 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.
;*
;**************************************************************************/

ALIGN 4
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                         
ALIGN 4

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                    
ALIGN 4

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
   
        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.
;*
;**************************************************************************/

ALIGN 4
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                    
ALIGN 4

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
;*
;**************************************************************************/

ALIGN 4
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                    
ALIGN 4

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  RGBToNearestIndex,rgbColor        

QCI_Exit:
        INVOKE  leave_driver                     ; EAX = RGBOut

QCI_Final_exit:
        RET

QueryColorIndex ENDP
   
   
        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. 
;*
;**************************************************************************/

ALIGN 4
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                
ALIGN 4

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                
ALIGN 4

;/*
;** 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                        
ALIGN 4

;/*
;** 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
ALIGN 4

QueryRGBColor_exit:
        INVOKE  leave_driver                      

QRGB_Exit_no_lock:

        RET 

QueryRGBColor ENDP
   
        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
;*
;**************************************************************************/

ALIGN 4
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
;*
;**************************************************************************/

ALIGN 4
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
   
        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
;*
;**************************************************************************/

ALIGN 4
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

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
device_enter_driver PROC SYSCALL
        ret
device_enter_driver ENDP
        END
