;*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    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = BUNDLE.ASM
;*
;* DESCRIPTIVE NAME = This file contains the routines which manage bitmaps.
;*
;*
;* VERSION      V2.0
;*
;* DATE         08/25/87
;*
;* DESCRIPTION   This file contains the routines which handle bundle attribute 
;*               calls
;*
;* FUNCTIONS    set_basic_attributes
;*              dsa_char
;*              dsa_marker
;*              dsa_pattern
;*              dsa_line
;*              DeviceSetAttributes         
;*              DeviceGetAttributes
;*              devicesetglobalattribute    
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   08/25/87                     Written by Hock Lee
;*   07/07/88                     Walt Moore [waltm] Delay mapping image data
;*                                foreground mix mode.
;*   10/09/91                     Cliff Levesque  [cliffl]
;*                                Convert to 32 bit operation.
;  Thu 07-Jul-1988 20:11:18                      -by- Walt Moore [waltm]
;   Delay mapping image data foreground mix mode.
;
;  Thu 09-Jun-1988 11:26:34                      -by- Walt Moore [waltm]
;   ptr 4633
;
;  Tue 02-Feb-1988 21:12:37                      -by- Walt Moore [waltm]
;   The big rewrite
;  Tue May 02 10:45:52 1989                      -by- Hock Lee [hockl]
; Made it return BOOL. (PTR SM83683)
;*
;*****************************************************************************/

        .286p
        .xlist
        include cmacros.inc
INCL_DDIBUNDLES         equ                      1
INCL_GRE_DEVMISC1       equ                      1
INCL_FONTFILEFORMAT     equ                      1
INCL_DDIMISC            equ                      1
INCL_GRE_DEVSUPPORT     equ                      1
INCL_WINSYS             equ                      1
        include pmgre.inc
        include driver.inc
        include fontseg.inc
        include display.inc
        include njmp.mac
        include assert.mac
        .list
        .286p

        errcode <INV_MIX_ATTR,INV_COLOR_ATTR,INV_LINE_TYPE_ATTR,INV_CHAR_MODE_ATTR>
        errcode <INV_CHAR_DIRECTION_ATTR,INV_BACKGROUND_MIX_ATTR,INV_BACKGROUND_COL_ATTR>
        errcode <INV_CHAR_ALIGN_ATTR>

        externFP SetCharFont
        externFP SetMarkerFont
        externFP SetPatternFont

        externA DEF_LOG_FORE_CLR
        externA DEF_LOG_BACK_CLR
        externA MIN_SPECIAL_COLOR

;/*
;**  We want some more convenient names for the basic attributes. We'll
;**  do all the error checking up front so it doesn't mess the code up
;**  all over the place.
;*/

BB_COLOR        equ     00000001b
BB_BACK_COLOR   equ     00000010b
BB_MIX          equ     00000100b
BB_BACK_MIX     equ     00001000b
BASIC_ATTR_MASK equ     BB_COLOR or BB_BACK_COLOR or BB_MIX or BB_BACK_MIX

        .errnz  BB_COLOR-LBB_COLOR
        .errnz  BB_BACK_COLOR-LBB_BACK_COLOR
        .errnz  BB_MIX-LBB_MIX_MODE
        .errnz  BB_BACK_MIX-LBB_BACK_MIX_MODE

        .errnz  BB_COLOR-CBB_COLOR
        .errnz  BB_BACK_COLOR-CBB_BACK_COLOR
        .errnz  BB_MIX-CBB_MIX_MODE
        .errnz  BB_BACK_MIX-CBB_BACK_MIX_MODE

        .errnz  BB_COLOR-MBB_COLOR
        .errnz  BB_BACK_COLOR-MBB_BACK_COLOR
        .errnz  BB_MIX-MBB_MIX_MODE
        .errnz  BB_BACK_MIX-MBB_BACK_MIX_MODE

        .errnz  BB_COLOR-ABB_COLOR
        .errnz  BB_BACK_COLOR-ABB_BACK_COLOR
        .errnz  BB_MIX-ABB_MIX_MODE
        .errnz  BB_BACK_MIX-ABB_BACK_MIX_MODE

        .errnz  BB_COLOR-IBB_COLOR
        .errnz  BB_BACK_COLOR-IBB_BACK_COLOR
        .errnz  BB_MIX-IBB_MIX_MODE
        .errnz  BB_BACK_MIX-IBB_BACK_MIX_MODE

bnd_temp        struc
bnd_lColor      dd      ?
bnd_lBackColor  dd      ?
bnd_usMix       dw      ?
bnd_usBackMix   dw      ?
bnd_temp        ends

        .errnz  bnd_lColor-lbnd_lColor
        .errnz  bnd_lBackColor-lbnd_lBackColor
        .errnz  bnd_usMix-lbnd_usMixMode
        .errnz  bnd_usBackMix-lbnd_usBackMixMode

        .errnz  bnd_lColor-cbnd_lColor
        .errnz  bnd_lBackColor-cbnd_lBackColor
        .errnz  bnd_usMix-cbnd_usMixMode
        .errnz  bnd_usBackMix-cbnd_usBackMixMode

        .errnz  bnd_lColor-mbnd_lColor
        .errnz  bnd_lBackColor-mbnd_lBackColor
        .errnz  bnd_usMix-mbnd_usMixMode
        .errnz  bnd_usBackMix-mbnd_usBackMixMode

        .errnz  bnd_lColor-pbnd_lColor
        .errnz  bnd_lBackColor-pbnd_lBackColor
        .errnz  bnd_usMix-pbnd_usMixMode
        .errnz  bnd_usBackMix-pbnd_usBackMixMode

        .errnz  bnd_lColor-ibmd_lColor
        .errnz  bnd_lBackColor-ibmd_lBackColor
        .errnz  bnd_usMix-ibmd_usMixMode
        .errnz  bnd_usBackMix-ibmd_usBackMixMode

dbnd_bnd equ    dlbnd_lbnd
        .errnz  dbnd_bnd-dlbnd_lbnd
        .errnz  dbnd_bnd-dabnd_abnd
        .errnz  dbnd_bnd-dcbnd_cbnd
        .errnz  dbnd_bnd-dibnd_ibnd
        .errnz  dbnd_bnd-dmbnd_mbnd

MAX_BUNDLE_TYPE equ     PRIM_IMAGE               ;Assume image is the last type
                .errnz  PRIM_IMAGE-5             ;in case they change it


sBegin  Data
        externB ddcInit
        externW anpabForeMix
        externW anpabBackMix

sEnd    Data


sBegin  Code
        assumes cs,Code

        externW  CodeData
        externNP xform_pattern_origin
        externNP enter_driver
        externNP enter_driver_sem
        externNP leave_driver

;/*
;**  ausAttrOffset contains the offsets to the basic attributes for
;**  each of the bundle attributes.
;*/

ausAttrOffset   label   word
        dw      ddc_la.la_ba
        .errnz  PRIM_LINE-1
        dw      ddc_ca.ca_ba
        .errnz  PRIM_CHAR-2
        dw      ddc_ma.ma_ba
        .errnz  PRIM_MARKER-3
        dw      ddc_pa.pa_ba
        .errnz  PRIM_AREA-4
        dw      ddc_ia.ia_ba
        .errnz  PRIM_IMAGE-5

;/*
;**  anpfnAttrProcs contains the processors for each of the basic
;**  attributes
;*/

anpfnAttrProcs  label   word                      ;Dispatch table for which
        dw      dsa_line                          ;  attribute we want to set
        .errnz  PRIM_LINE-1
        dw      dsa_char
        .errnz  PRIM_CHAR-2
        dw      dsa_marker
        .errnz  PRIM_MARKER-3
        dw      dsa_pattern
        .errnz  PRIM_AREA-4
        dw      dsa_image
        .errnz  PRIM_IMAGE-5

;/*
;**  acbSaveSize contains the number of bytes of attribute information
;**  in the ddc which must be saved to be able to recover from an error.
;*/

acbSaveSize     label   word                      ;Number of words of current attribute
        dw      LA_DSA_SAVE_LIM/2                 ; to save on stack for error recovery
        .errnz  PRIM_LINE-1
        dw      CA_DSA_SAVE_LIM/2
        .errnz  PRIM_CHAR-2
        dw      MA_DSA_SAVE_LIM/2
        .errnz  PRIM_MARKER-3
        dw      PA_DSA_SAVE_LIM/2
        .errnz  PRIM_AREA-4
        dw      IA_DSA_SAVE_LIM/2
        .errnz  PRIM_IMAGE-5
        .errnz  LA_DSA_SAVE_LIM and 1
        .errnz  CA_DSA_SAVE_LIM and 1
        .errnz  MA_DSA_SAVE_LIM and 1
        .errnz  PA_DSA_SAVE_LIM and 1
        .errnz  IA_DSA_SAVE_LIM and 1

MAX_SAVE_SIZE   equ     PA_DSA_SAVE_LIM
        .erre   PA_DSA_SAVE_LIM gt LA_DSA_SAVE_LIM
        .erre   PA_DSA_SAVE_LIM gt CA_DSA_SAVE_LIM
        .erre   PA_DSA_SAVE_LIM gt MA_DSA_SAVE_LIM
        .erre   PA_DSA_SAVE_LIM gt IA_DSA_SAVE_LIM


;/*
;**  afbDefClr is used to set the BA_CLR_INVALID, BA_CLR_BACK_INV,
;**  BA_CLR_DEF, BA_CLR_BACK_DEF, and BA_REREALIZE in the ba_fb flags.
;*/

afbDefClr       label   byte
        db      0
        db      BA_REREALIZE or BA_CLR_INVALID or BA_CLR_DEF
        .errnz  BB_COLOR-1
        db      BA_REREALIZE or BA_CLR_BACK_INV or BA_CLR_BACK_DEF
        .errnz  BB_BACK_COLOR-2
        db      BA_REREALIZE or BA_CLR_INVALID or BA_CLR_DEF or BA_CLR_BACK_INV or BA_CLR_BACK_DEF
        .errnz  (BB_COLOR or BB_BACK_COLOR)-3

;/*
;**  asBundleOffset contains the offset from the start of a bundle to the
;**  each of the basic attributes.  This is used by DeviceSetGlobalAttribute
;**  to synthesize a pointer to the stack to the attribute to be set.
;*/

acBundleOffset  label   word
        dw      -(dbnd_bnd.bnd_lColor)
        .errnz  BB_COLOR-1
        dw      -(dbnd_bnd.bnd_lBackColor)
        .errnz  BB_BACK_COLOR-2
        dw      -(dbnd_bnd.bnd_usMix)
        .errnz  BB_MIX-4
        dw      -(dbnd_bnd.bnd_usBackMix)
        .errnz  BB_BACK_MIX-8                     
page

;/***************************************************************************
;*
;* FUNCTION NAME = set_basic_attributes
;*
;* DESCRIPTION   = Sets basic attributes color, background color, mix     
;*                 mode, and background mix mode in the DC.
;*
;*                 Registers Preserved:
;*                       BX,CL,SI,DI,BP,DS,ES,
;*                 Registers Destroyed:
;*                       AX,CH,DX,FLAGS
;*                 
;* INPUT         = BX      =  ddc                                    
;*                 BP      =  Attribute index (a word index)         
;*                 CL      =  default mask (used only for colors)    
;*                 DI      =  attribute mask                         
;*                 ES:SI   =  bundle record                          
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL = AX = 1        
;*                 ZF cleared    
;* RETURN-ERROR  = AX = 0        
;*                 ZF set        
;*                 error logged  
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   set_basic_attributes,<PUBLIC,NEAR>       ;Public for debugging
cBegin

ifdef FIREWALLS
        ddc?    bx
        test    cl,not (BB_COLOR or BB_BACK_COLOR)
        jnz     sba_internal_error
        cmp     bp,(MAX_BUNDLE_TYPE*SIZE_WORD)-2
        ja      sba_internal_error
        test    bp,00000001b
        jz      @F
sba_internal_error:
        rip     text,<set_basic_attributes - internal error>
@@:
endif

;/*
;**  Set the ba_fb flags BA_CLR_INVALID, BA_CLR_BACK_INV, BA_CLR_DEF,
;**  and BA_CLR_BACK_DEF as appropriate.
;**
;**  We'll basically do a table lookup to get the bits to set/clear in
;**  the ba_fb word.
;*/

        add     bx,ausAttrOffset[bp]             ;--> attribute to change
        xor     ch,ch
        xchg    bx,cx                             ;CX --> ba_
        mov     bh,afbDefClr[bx]                 ;BH = defaults OR mask, BL = defs mask
        mov     ax,di
        and     ax,BB_COLOR or BB_BACK_COLOR
        xchg    ax,bx                             ;AH = defaults OR mask, AL = defs mask
        mov     bh,afbDefClr[bx]                 ;BH = non-defs OR mask (with some work)
        xchg    ax,cx                             ;CH = defaults OR mask, CL = defs mask
        xchg    ax,bx                             ;BX --> ba_, AH = non-defs mask
        mov     al,[bx].ba_fb
        or      al,ch                             ;Set INV, DEF bits for default colors
        or      al,ah                             ;Set INV bits for non-default colors
        and     ah,BA_CLR_DEF or BA_CLR_BACK_DEF
        xor     al,ah                             ;Clear def bits from non-defs mask
        mov     [bx].ba_fb,al
sba_done_defaults:

;/*
;**  set foreground color
;*/

        test    di,BB_COLOR
        jz      sba_done_foreground

;/*
;**  Validate the index a little.   If the high byte is non-zero, then we
;**  can do a range check on the special colors.  If it is zero, we can't
;**  do anything until they try to use the color.
;*/

        mov     ax,es:[si].dbnd_bnd.bnd_lColor.lo
        mov     dx,es:[si].dbnd_bnd.bnd_lColor.hi
        mov     [bx].ba_clr.lo,ax
        mov     [bx].ba_clr.hi,dx
        or      dh,dh
        jz      sba_done_foreground
        inc     dx
        jnz     sba_invalid_color
        dec     dx
        cmp     ax,MIN_SPECIAL_COLOR
        jae     sba_done_foreground

sba_invalid_color:
        mov     dx,PMERR_INV_COLOR_ATTR
        jmp     short sba_log_error
sba_invalid_back_color:
        mov     dx,PMERR_INV_BACKGROUND_COL_ATTR
sba_log_error:
        xchg    ax,dx
        save_error_code
        xor     ax,ax
        jmp     sba_exit

sba_done_foreground:


;/*
;**  Set background color
;*/

        test    di,BB_BACK_COLOR
        jz      sba_done_background
        mov     ax,es:[si].dbnd_bnd.bnd_lBackColor.lo
        mov     dx,es:[si].dbnd_bnd.bnd_lBackColor.hi
        mov     [bx].ba_clrBack.lo,ax
        mov     [bx].ba_clrBack.hi,dx
        or      dh,dh
        jz      sba_done_background
        inc     dx
        jnz     sba_invalid_back_color
        dec     dx
        cmp     ax,MIN_SPECIAL_COLOR
        jb      sba_invalid_back_color
sba_done_background:


;/*
;**  Set foreground mix mode attribute.  There is no default mask bit
;**  for it.  If the range is invalid, report an error.
;*/

        test    di,BB_MIX
        jz      sba_done_fore_mix
        mov     dx,PMERR_INV_MIX_ATTR
        mov     ax,es:[si].dbnd_bnd.bnd_usMix.lo
        dec     ax                                ;DCR 22793 removed 0
        cmp     ax,FM_ONE
        jae     sba_log_error
        cmp     ax,3-1                            ;Reserved - underpaint
        je      sba_log_error
        cmp     bp,(PRIM_IMAGE-1)*2              ;Don't map image data mix mode
        je      have_fore_mix
        mov     dx,di
        mov     di,anpabForeMix[bp]
        xchg    ax,bx
        mov     bl,[di][bx]
        xchg    ax,bx
        mov     di,dx
have_fore_mix:
        mov     [bx].ba_bmix,al
sba_done_fore_mix:

;/*
;**  Set background mix mode attribute.  There is no default mask bit
;**  for it.  If the range is invalid, return an error.
;*/

        test    di,BB_BACK_MIX
        jz      sba_done_back_mix
        mov     dx,PMERR_INV_BACKGROUND_MIX_ATTR
        mov     ax,es:[si].dbnd_bnd.bnd_usBackMix.lo
        dec     ax                                ;DCR 22793 removed 0
        cmp     ax,BM_ONE               ;!!When BM_ are defined in pmgpi.h
        jae     sba_log_error           ;!!we will use it.
        cmp     ax,3-1                            ;Reserved - underpaint
        je      sba_log_error
have_back_mix:
        mov     dx,di
        mov     di,anpabBackMix[bp]
        xchg    ax,bx
        mov     bl,[di][bx]
        xchg    ax,bx
        mov     di,dx
        mov     [bx].ba_bkmix,al

sba_done_back_mix:
        mov     ax,1                              ;Show success

sba_exit:
        sub     bx,ausAttrOffset[bp]             ;--> to start of the ddc
        or      ax,ax                             ;Set/clear 'Z'
cEnd


;/***************************************************************************
;*
;* FUNCTION NAME = dsa_char
;*
;* DESCRIPTION   = This function is used to set the attributes for        
;*                 characters
;*                 
;*                 Registers Preserved:
;*                      BX,SI,DI,BP,DS,ES         CL if only basic attributes
;*                 Registers Destroyed:
;*                      AX,CH,DX,FLAGS            CL if other than basic attributes
;*                 Calls:
;*                      set_basic_attributes
;*
;* INPUT         = BX     --> ddc                                 
;*                 BP      =  Attribute index (a word index)      
;*                 CL      =  default mask (used only for colors) 
;*                 CH      =  basic attributes mask               
;*                 DI      =  attribute mask                      
;*                 ES:SI   =  bundle record                       
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL = AX = 1       
;* RETURN-ERROR  = AX = 0       
;*                 error logged 
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   dsa_char,<PUBLIC,NEAR>                    ;Public for debugging
cBegin
        ddc?    bx
        or      ch,ch
        jz      dsac_basics_set
        cCall   set_basic_attributes
        jnz     dsac_basics_set                  ;No errors so far
dsac_exit_no_adjust:                              ;Don't reset ddc pointer
        jmp     dsac_exit                         ;AX = return code

dsac_log_mode_error:
        mov     ax,PMERR_INV_CHAR_MODE_ATTR
        jmp     short dsac_log_error
dsac_log_dir_error:
        mov     ax,PMERR_INV_CHAR_DIRECTION_ATTR
        jmp     short dsac_log_error
dsac_log_align_error:
        mov     ax,PMERR_INV_CHAR_ALIGN_ATTR
dsac_log_error:
        save_error_code
        xor     ax,ax
        jmp     dsac_exit                         ;Need to fix up ddc pointer

;/*
;**  Process any other character, marker, or pattern attributes.  Take a
;**  quick out if none are to be set.
;*/

dsac_basics_set:
        mov     ax,1                              ;Assume nothing else will change
        test    di,CBB_MODE or CBB_DIRECTION or CBB_TEXT_ALIGN or CBB_SET or CBB_EXTRA or CBB_BREAK_EXTRA
        jz      dsac_exit_no_adjust              ;All done, take quick out, AX <> 0
        mov     cx,[bx].ddc_ca.ca_fs             ;Will be using this a lot

;/*
;**  Process text spacings (I keep the values here in case we decide to
;**  do justification in the driver.  Then we may want to keep them in
;**  device units too.)
;*/

        .386
        test    di,CBB_EXTRA
        jz      short dsac_done_extra
        mov     eax,es:[si].dcbnd_cbnd.cbnd_fxExtra
        mov     [bx].ddc_ca.ca_fxExtra,eax
dsac_done_extra:
        test    di,CBB_BREAK_EXTRA
        jz      short dsac_done_break_extra
        mov     eax,es:[si].dcbnd_cbnd.cbnd_fxBreakExtra
        mov     [bx].ddc_ca.ca_fxBreakExtra,eax
dsac_done_break_extra:
        .286

;/*
;**  Process any text precision (they call it mode)
;*/

        test    di,CBB_MODE
        jz      dsac_done_mode
        and     cx,not CA_PREC_NOT_1             ;Assume precision 1
        mov     ax,es:[si].dcbnd_cbnd.cbnd_usPrecision
        dec     ax                                ;DCR 22793 removed CM_DEFAULT (0)
        cmp     ax,CM_MODE3                       ;Check for legal modes
        jae     dsac_log_mode_error                   ;It's illegal
        neg     ax                                ;'C' set if not mode 1
        sbb     ax,ax                             ;AX = FFFF if not mode 1
        and     ax,CA_PREC_NOT_1
        or      cx,ax
        .errnz  CM_MODE1-1                        ;It was decremented above
dsac_done_mode:

;/*
;**  Process any drawing direction
;*/

        test    di,CBB_DIRECTION
        jz      dsac_done_dir
        mov     ax,es:[si].dcbnd_cbnd.cbnd_usDirection
        dec     ax                                ;DCR 22793 removed CHDIRN_DEFAULT (0)
        cmp     ax,CHDIRN_BOTTOMTOP
        jae     dsac_log_dir_error
        and     cl,not CA_DIRECTION
        or      cl,al
        .errnz  CHDIRN_LEFTRIGHT-1
        .errnz  CHDIRN_TOPBOTTOM-2
        .errnz  CHDIRN_RIGHTLEFT-3
        .errnz  CHDIRN_BOTTOMTOP-4
        .errnz  CA_DIRECTION-00000011b
dsac_done_dir:

;/*
;**  Process any text align.
;*/

        test    di,CBB_TEXT_ALIGN
        jz      dsac_done_align
        mov     ax,es:[si].dcbnd_cbnd.cbnd_usTextAlign
        dec     al
        cmp     al,TA_STANDARD_HORIZ
        jae     dsac_log_align_error
        dec     ah
        cmp     ah,(TA_STANDARD_VERT shr 8)
        njae    dsac_log_align_error
        inc     al
        inc     ah
        mov     [bx].ddc_ca.ca_usTextAlign,ax

.errnz TA_NORMAL_HORIZ   - 0001h
.errnz TA_LEFT           - 0002h
.errnz TA_CENTER         - 0003h
.errnz TA_RIGHT          - 0004h
.errnz TA_STANDARD_HORIZ - 0005h
.errnz TA_NORMAL_VERT    - 0100h
.errnz TA_TOP            - 0200h
.errnz TA_HALF           - 0300h
.errnz TA_BASE           - 0400h
.errnz TA_BOTTOM         - 0500h
.errnz TA_STANDARD_VERT  - 0600h

dsac_done_align:

;/*
;**  Process any font change
;*/

CA_CLEAR = CA_VECTOR or CA_MUST_MAP    or CA_CHAR_EXTRA or CA_ABC_SPACE
CA_CLEAR = CA_CLEAR  or CA_FIXED_PITCH or CA_WIDTH_IS_8 or CA_STRIKEOUT
CA_CLEAR = CA_CLEAR  or CA_UNDERSCORE  or CA_ITALIC or CA_BOLD
CA_CLEAR = CA_CLEAR  or CA_USER_FONT

        mov     ax,1                              ;Assume no font change
        test    di,CBB_SET
        jz      dsac_save_flags

;/*
;**  Need ES:[SI] -> CHARDEFS temporarily.  Use indirection in case size of
;**  CHARBUNDLE changes.
;*/

        push    si
        add     si,es:[si].dcbnd_cAttr
        add     si,(SIZE dcbnd_cDefs + SIZE dcbnd_cAttr)


        and     cx,not CA_CLEAR
        mov     ax,es:[si].cdef_fFlags
        and     ax,(CDEF_STRIKEOUT+CDEF_UNDERSCORE+CDEF_ITALIC+CDEF_BOLD)
        add     ax,ax
        or      cx,ax
        .errnz  (CDEF_BOLD                        shl 1) - CA_BOLD
        .errnz  (CDEF_ITALIC                      shl 1) - CA_ITALIC
        .errnz  (CDEF_UNDERSCORE shl 1) - CA_UNDERSCORE
        .errnz  (CDEF_STRIKEOUT  shl 1) - CA_STRIKEOUT

        mov     dx,es:[si].cdef_defSet.sel
        mov     ax,es:[si].cdef_defSet.off
        pop     si                      ; ES:[SI] -> DCHARBUNDLE
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<A font pointer with a non-zero offset was encountered>
@@:
endif
        cmp     es:[si].dcbnd_cbnd.cbnd_usSet,LCID_DEFAULT
        je      dsac_have_font
        or      cx,CA_USER_FONT
dsac_have_font:
        mov     [bx].ddc_ca.ca_pFont.lo,ax
        mov     [bx].ddc_ca.ca_pFont.hi,dx

;/*
;**  Invoke the routine which deals with font selection.  The registers
;**  being passed are:
;**
;**        DS:BX --> ddc
;**        DX:AX  =  font handle / font pointer
;**        BP     =  attr index for characters
;**        CX     =  ca_fs
;**        ES:SI --> attribute bundle
;**
;**  We expect this routine to set BA_REREALIZE if it is appropriate.
;*/

        push    es
        call    SetCharFont                       ;AX = return code
        pop     es
        assumes es,nothing
dsac_save_flags:
        mov     [bx].ddc_ca.ca_fs,cx

dsac_exit:
cEnd

;/***************************************************************************
;*
;*
;* FUNCTION NAME = dsa_marker
;*
;* DESCRIPTION   = Sets marker attributes in the ddc. 
;*
;*                 Registers Preserved:
;*                       BX,CL,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,CH,DX,FLAGS
;*                 Calls:
;*                       set_basic_attributes
;*
;* INPUT         = BX     --> ddc                                  
;*                 BP      =  Attribute index (a word index)       
;*                 CL      =  default mask (used only for colors)  
;*                 CH      =  basic attributes mask                
;*                 DI      =  attribute mask                       
;*                 ES:SI   =  bundle record                        
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL = AX = 1       
;* RETURN-ERROR  = AX = 0       
;*                 error logged 
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   dsa_marker,<PUBLIC,NEAR>,<di>            ;Public for debugging
cBegin
        ddc?    bx

;/*
;**  We don't care about the marker cell size.  We don't do any scaling
;**  or support non-raster fonts, so we'll ignore it.  The code point
;**  can never be invalid since we use the default for any code point
;**  which isn't in the set.
;*/

        or      ch,ch
        jz      dsam_basics_set
        cCall   set_basic_attributes
        jz      dsam_exit_relay_z                ;AX = return code
dsam_basics_set:

;/*
;**  If we have a new code point, we'll have to save it.  We won't validate
;**  it until we use it when we have a good font, etc.
;*/

        test    di,MBB_SYMBOL
        jz      dsam_code_point_done
        mov     ax,es:[si].dmbnd_mbnd.mbnd_usSymbol
        mov     [bx].ddc_ma.ma_ch,al
        or      [bx].ddc_ma.ma_fs,CA_CHANGED
        or      [bx].ddc_ma.ma_ba.ba_fb,BA_REREALIZE
dsam_code_point_done:

;/*
;**  Process any font change.  We'll allow non-raster fonts which we'll
;**  just pass to the engine.
;*/

        mov     ax,1                              ;Assume no font change
        test    di,MBB_SET
dsam_exit_relay_z:
        jz      dsam_exit
        mov     cx,[bx].ddc_ma.ma_fs
        and     cx,not CA_CLEAR
        mov     di,si
        add     di,es:[si].dmbnd_cAttr
        add     di,(SIZE dmbnd_cDefs + SIZE dmbnd_cAttr)
        mov     ax,es:[di].mdef_fFlags
        and     ax,(CDEF_STRIKEOUT+CDEF_UNDERSCORE+CDEF_ITALIC+CDEF_BOLD)
        add     ax,ax
        or      cx,ax
        .errnz  (CDEF_BOLD                        shl 1) - CA_BOLD
        .errnz  (CDEF_ITALIC                      shl 1) - CA_ITALIC
        .errnz  (CDEF_UNDERSCORE shl 1) - CA_UNDERSCORE
        .errnz  (CDEF_STRIKEOUT  shl 1) - CA_STRIKEOUT

        or      cx,CA_USER_FONT                  ;Assume user font
        cmp     es:[si].dmbnd_mbnd.mbnd_usSet,LCID_DEFAULT
        je      dsam_use_default_font
        mov     ax,es:[di].mdef_defSet.off
        mov     dx,es:[di].mdef_defSet.sel
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<A font pointer with a non-zero offset was encountered>
@@:
endif
        or      dx,dx                             ;User font if non-zero
        jnz     dsam_have_font

dsam_use_default_font:
ifdef FIREWALLS
        test    es:[di].mdef_fFlags,1 ;!!! FNT_GENERIC
        jz      @F
        rip     text,<dsa_char - Default font was flagged FNT_GENERIC>
@@:
endif
        and     cx,not CA_USER_FONT
        mov     dx,ddcInit.ddc_ma.ma_pFont.sel
        mov     ax,ddcInit.ddc_ma.ma_pFont.off

dsam_have_font:
        mov     [bx].ddc_ma.ma_pFont.lo,ax
        mov     [bx].ddc_ma.ma_pFont.hi,dx

;/*
;**  Invoke the routine which deals with font selection.  The registers
;**  being passed are:
;**
;**        DS:BX --> ddc
;**        DX:AX  =  font handle / font pointer
;**        BP     =  attr index for characters
;**        CX     =  ma_fs
;**        ES:SI --> attribute bundle
;**
;**  We expect this routine to set BA_REREALIZE if it is appropriate.
;*/

        push    es
        call    SetMarkerFont                     ;AX = return code
        pop     es
        assumes es,nothing
        mov     [bx].ddc_ma.ma_fs,cx

dsam_exit:

cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = dsa_pattern
;*
;* DESCRIPTION   = Sets pattern attributes in the ddc. 
;*
;*                 Registers Preserved:
;*                       BX,CL,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,CH,DX,FLAGS
;*                 Calls:
;*                       dsa_marker
;*
;* INPUT         = BX     --> ddc                                 
;*                 BP      =  Attribute index (a word index)      
;*                 CL      =  default mask (used only for colors) 
;*                 CH      =  basic attributes mask               
;*                 DI      =  attribute mask                      
;*                 ES:SI   =  bundle record                       
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL = AX = 1        
;* RETURN-ERROR  = AX = 0        
;*                 error logged  
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   dsa_pattern,<PUBLIC,NEAR>                ;Public for debugging
cBegin
        ddc?    bx
        or      ch,ch
        jz      dsap_basics_set
        cCall   set_basic_attributes
        jz      jz_dsap_exit_relay               ;AX = return code
dsap_basics_set:

;/*
;**  If we have a new code point, we'll have to save it.  We won't validate
;**  it until we use it when we have a good font, etc.
;*/

        test    di,ABB_SYMBOL
        jz      dsap_code_point_done
        mov     ax,es:[si].dabnd_abnd.pbnd_usSymbol
        mov     [bx].ddc_pa.pa_ch,al
        or      [bx].ddc_pa.pa_fs,CA_CHANGED
        or      [bx].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
dsap_code_point_done:

;/*
;**  Process any pattern origin change.  If we have a change, make sure
;**  the new origin will be valid in device coordinates.  Since we saved
;**  the state of this attribute bundle, we can go ahead and save the new
;**  pattern origin in the ddc.  If we end up with an error, the bundle
;**  will be cleaned up for us.
;*/

        test    di,ABB_REF_POINT
        jz      dsap_done_ref_ptl
        mov     ax,es:[si].dabnd_abnd.pbnd_ptlRefPoint.ptl_x.lo
        mov     [bx].ddc_pa.pa_ptlOrg.ptl_x.lo,ax
        mov     ax,es:[si].dabnd_abnd.pbnd_ptlRefPoint.ptl_x.hi
        mov     [bx].ddc_pa.pa_ptlOrg.ptl_x.hi,ax
        mov     ax,es:[si].dabnd_abnd.pbnd_ptlRefPoint.ptl_y.lo
        mov     [bx].ddc_pa.pa_ptlOrg.ptl_y.lo,ax
        mov     ax,es:[si].dabnd_abnd.pbnd_ptlRefPoint.ptl_y.hi
        mov     [bx].ddc_pa.pa_ptlOrg.ptl_y.hi,ax
        or      [bx].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        xchg    bx,si                             ;DS:SI --> ddc
        save    <es,bx,cx>
        cCall   xform_pattern_origin
        xchg    bx,si
        or      ax,ax
jz_dsap_exit_relay:
        jz      dsap_exit                         ;Error occured
dsap_done_ref_ptl:

;/*
;**  Process any font change.  We only allow bitmaps and raster fonts
;*/

        test    di,ABB_SET
        jz      dsap_have_font
        and     [bx].ddc_pa.pa_fs,not (CA_CLEAR)
        and     [bx].ddc_pa.pa_fb,not (PA_BITMAP_SRC or PA_COLOR_TRUTH)
        or      [bx].ddc_pa.pa_fs,CA_CHANGED
        or      [bx].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        cmp     es:[si].dabnd_abnd.pbnd_usSet,LCID_DEFAULT
        je      dsap_have_font
        push    si
        add     si,es:[si].dabnd_cAttr
        mov     dx,es:[si][SIZE dabnd_cDefs + SIZE dabnd_cAttr].adef_defSet.sel
        mov     ax,es:[si][SIZE dabnd_cDefs + SIZE dabnd_cAttr].adef_defSet.off
        pop     si
        or      dx,dx                             ;User font if non-zero
        jz      dsap_have_font                    ;Its the default
        mov     [bx].ddc_pa.pa_pFont.lo,ax
        mov     [bx].ddc_pa.pa_pFont.hi,dx


;/*
;**  Invoke the routine which deals with font selection for patterns
;**
;**        DS:BX --> ddc
;**        DX:AX  =  font handle / font pointer / bitmap handle
;**        BP     =  attr index for characters
;**        ES:SI --> attribute bundle
;*/
 
        push    es
        call    SetPatternFont                    ;AX = return code
        pop     es
        assumes es,nothing
        jmp     short dsap_exit

dsap_have_font:
        mov     ax,1                              ;Assume no font change

dsap_exit:
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = dsa_image
;*
;* DESCRIPTION   = There are only the basic attributes for image data,  
;*               = so we can just use the set_basic_attributes function.
;*                 
;*                 Registers Preserved:
;*                       BX,CL,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,CH,DX,FLAGS
;*                 Calls:
;*                       set_basic_attributes
;*
;* INPUT         = BX     --> ddc                                 
;*                 BP      =  Attribute index (a word index)      
;*                 CL      =  default mask (used only for colors) 
;*                 CH      =  basic attributes mask               
;*                 DI      =  attribute mask                      
;*                 ES:SI   =  bundle record                       
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL = AX = 1       
;* RETURN-ERROR  = AX = 0       
;*                 error logged 
;**************************************************************************/

dsa_image       equ     set_basic_attributes
page

;/***************************************************************************
;*
;* FUNCTION NAME = dsa_line
;*
;* DESCRIPTION   = Sets line attributes in the ddc.                                 
;*
;*                 Registers Preserved:
;*                       BX,CL,SI,DI,BP,DS,ES
;*                
;*                 Registers Destroyed:
;*                       AX,CH,DX,FLAGS
;*
;*                 Calls:
;*                       set_basic_attributes
;*
;* INPUT         = BX     --> ddc
;*                 BP      =  Attribute index (a word index)
;*                 CL      =  default mask (used only for colors)
;*                 CH      =  basic attributes mask
;*                 DI      =  attribute mask
;*                 ES:SI   =  bundle record
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1   
;* RETURN-ERROR  = AX = 0       
;*                 error logged  
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   dsa_line,<PUBLIC,NEAR>                    ;Public for debugging
cBegin
        ddc?    bx
        or      ch,ch
        jz      dsal_basics_set                  ;No basic attributes will change
        cCall   set_basic_attributes
        jz      dsal_exit                         ;Had an error, AX = 0
dsal_basics_set:

;/*
;**  If a line type is being set, validate it and set it if valid.
;*/

        test    di,LBB_TYPE
        jz      dsal_check_width
        mov     ax,es:[si].dlbnd_lbnd.lbnd_usType
        dec     ax                                ;DCR 22793 removed LINETYPE_DEFAULT (0)
        cmp     ax,LINETYPE_ALTERNATE
        jb      dsal_line_type_ok
        mov     ax,PMERR_INV_LINE_TYPE_ATTR
        save_error_code
        xor     ax,ax
        jmp     short dsal_exit

dsal_line_type_ok:
        mov     [bx].ddc_la.la_usType,ax;Need to reset the line style!!!!!

dsal_check_width:
        test    di,LBB_WIDTH
        jz      dsa_line_done

;/*
;**  Move the high portion of the line width into the line bundle.  Since
;**  the line width is fixed point, the lower word is not relevant.
;*/

        mov     ax,es:[si].dlbnd_lbnd.lbnd_fxWidth.hi ; Set line width
        mov     [bx].ddc_la.la_sWidth,ax
dsa_line_done:
        mov     ax,1                              ;Show success
dsal_exit:

cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSetAttributes  
;*
;* DESCRIPTION   = Sets selected attributes in the DC.  The current                
;*                 attributes for the given bundle will be saved in case
;*                 an error is encountered and restored if one actually
;*                 occurs.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*
;*                 Calls:
;*                       dsa_line
;*                       dsa_character
;*                       dsa_marker
;*                       dsa_pattern
;*                       dsa_image
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 
;* RETURN-ERROR  = AX = 0     
;*                 error logged
;**************************************************************************/

        check   DeviceSetAttributes,<hdc,ulType,flDefs,flAttrs,pBundle,hddc,ulFunN>

        assumes ds,nothing
        assumes es,nothing

cProc   DeviceSetAttributes,<PUBLIC,FAR,NODATA>,<di,si>
        parmD   hdc
        parmD   BType
        parmD   DefsMask
        parmD   AttrsMask
        parmD   lpAttrs
        parmD   hddc
        parmD   FunN
        localV  abTemp,MAX_SAVE_SIZE
cBegin

ifdef FIREWALLS

        fw_zero <es,ds>
        ddc?    hddc

;/*
;**  If the bundle type is invalid, the Engine screwed up.  If the default
;**  mask contains anything other than BB_COLOR or BB_BACK_COLOR, it should
;**  be considered an error (at least for this release).
;**  The high word of the attributes mask should be zero
;*/

        cmp     DefsMask.hi,0
        jne     dsa_internal_error
        test    DefsMask.lo,not (BB_COLOR or BB_BACK_COLOR)
        jz      @F
dsa_internal_error:
        rip     text,<DeviceSetAttributes - Invalid mask encountered>
@@:
        cmp     AttrsMask.hi,0
        jne     dsa_internal_error
        cmp     BType.hi,0
        jne     dsa_bad_type
        cmp     BType.lo,0
        je      dsa_bad_type
        cmp     BType.lo,MAX_BUNDLE_TYPE
        jbe     @F
dsa_bad_type:
        rip     text,<DeviceSetAttributes - Invalid bundle type>
@@:
endif

;/*
;**  Save the current attributes on the stack so we can recover from
;**  an error.
;*/

        mov     ds,CodeData
        assumes ds,Data
        mov     dx,hddc.lo
        call    enter_driver_sem
        jc      dsa_exit_no_lock                 ; DX:AX = 0 on error
        mov     bx,hddc.lo
        or      [bx].ddc_fbBelow,DDC_DIRTY_ATTRS

        mov     ax,ss
        mov     es,ax
        assumes es,nothing
        mov     si,BType.lo
        dec     si
        add     si,si                             ;Indexing into words
        mov     BType.lo,si                       ;Will need it later

;/*
;**  Don't need to do save if only default attributes will be set since
;**  default attributes cannot fail.  I want the attributes masks to be
;**  mutually exclusive.
;*/

        mov     ax,AttrsMask.lo                  ;A bit in the DefsMask is only valid
        and     ax,DefsMask.lo                    ;  if same bit is set in AttrsMask
        mov     DefsMask.lo,ax
        xor     ax,AttrsMask.lo
        jz      dsa_save_done
        mov     cx,acbSaveSize[si]               ;# bytes to move
        mov     si,ausAttrOffset[si]             ;Offset into ddc of attributes
        add     si,bx                             ;Add in start of ddc
        lea     di,abTemp
        cld
        rep     movsw
dsa_save_done:
;/*
;**  Invoke the correct attribute processor to do our dirty work for us.
;/*

        mov     cx,DefsMask.lo
        mov     di,ax
        or      al,cl
        and     al,BASIC_ATTR_MASK
        mov     ch,al
        les     si,lpAttrs
        assumes es,nothing
        push    bp
        mov     bp,BType.lo
        call    anpfnAttrProcs[bp]               ;Return code will be returned in AX
        pop     bp
        or      ax,ax
        jnz     dsa_all_done

;/*
;**  An error occurred.  The saved attributes must be restored.
;*/

        or      di,di
        jz      dsa_all_done                      ;Attributes were not saved
        mov     es,CodeData
        assumes es,nothing
        mov     si,BType.lo
        mov     cx,acbSaveSize[si]               ;# bytes to move
        mov     di,ausAttrOffset[si]             ;Offset into ddc of attributes
        add     di,bx                             ;Add in start of ddc
        lea     si,abTemp
        cld
        rep     movs word ptr es:[di], word ptr ss:[si]

dsa_all_done:
        call    leave_driver
        cwd
dsa_exit_no_lock:
        fw_zero <es,cx>
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSetGlobalAttribute   
;*
;* DESCRIPTION   = This function sets the five individual primitive               
;*                 attributes to the specified value, in the pen, pattern,
;*                 character, image and marker bundles.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,FLAGS
;*
;*                 Calls:
;*                       set_basic_attributes
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 
;* RETURN-ERROR  = EAX = 0      
;*                 error logged 
;**************************************************************************/

;/*
;**  abAttrsMasks is used to turn the AttributeType parameter into a
;**  bit index which can then be passed to set_basic_attributes
;*/

abAttrsMasks    label   byte

        db      BB_COLOR
        .errnz  ATYPE_COLOR-1
        db      BB_BACK_COLOR
        .errnz  ATYPE_BACK_COLOR-2
        db      BB_MIX
        .errnz  ATYPE_MIX_MODE-3
        db      BB_BACK_MIX
        .errnz  ATYPE_BACK_MIX_MODE-4

        check   DeviceSetGlobalAttribute,<hdc,ulType,ulAttr,flCmd,hddc,ulFunN>

        assumes ds,nothing
        assumes es,nothing

cProc   DeviceSetGlobalAttribute,<PUBLIC,FAR,NODATA>,<di,si>
        parmD   hdc
        parmD   AttributeType
        parmD   Attribute
        parmD   Options
        parmD   hddc
        parmD   FunN
cBegin

ifdef FIREWALLS
        fw_zero <es,ds>
        ddc?    hddc
        cmp     AttributeType.hi,0
        jne     dsga_error
        mov     ax,AttributeType.lo
        dec     ax
        cmp     ax,ATYPE_BACK_MIX_MODE
        jb      @F
dsga_error:
        rip     text,<DeviceSetGlobalAttribute - Invalid attribute type>
@@:
endif

        mov     ds,CodeData
        assumes ds,Data
        mov     dx,hddc.lo
        call    enter_driver
        njc     dsga_exit_no_lock                ; DX:AX = 0 on error
        mov     bx,hddc.lo
        or      [bx].ddc_fbBelow,DDC_DIRTY_ATTRS
        push    bp                                ;We'll be using BP soon
        mov     si,AttributeType.lo
        dec     si
        mov     cl,abAttrsMasks[si]              ;Get the mask for the attribute
        xor     ch,ch
        xor     di,di
        test    Options.lo,GATTR_DEFAULT
        jnz     dsga_set_first_attr              ;Defaults cannot fail
        xchg    di,cx                             ;Not default, it's user defined

;/*
;**  Now we get a little slimey.  We can simply adjust the pointer passed
;**  to set_basic_attributes so that when the attribute field is accessed,
;**  it will reference our stack parameter.
;*/

        add     si,si                             ;Indexing into words
        mov     si,acBundleOffset[si]
        lea     si,Attribute[si]                 ;Add efective address of offset
        mov     ax,ss
        mov     es,ax                             ;--> phoney bundle record
        assumes es,nothing

;/*
;**  Save the current attributes on the stack so we can recover from
;**  an error.  We only have to save one attribute bundle, and only
;**  the basic attributes in it.  If the set succeeds for the first
;**  attribute bundle, it will succeed for all of them.  If we are
;**  setting the defaults, we don't save this stuff since defaults
;**  can never fail.
;*/

        push    [bx].ddc_ia.ia_ba.ba_clr.lo
        push    [bx].ddc_ia.ia_ba.ba_clr.hi
        push    [bx].ddc_ia.ia_ba.ba_clrBack.lo
        push    [bx].ddc_ia.ia_ba.ba_clrBack.hi
        push    word ptr [bx].ddc_ia.ia_ba.ba_bReserved
        .errnz  ba_fb-ba_bReserved-1

dsga_set_first_attr:
        mov     bp,(PRIM_IMAGE-1)*SIZE_WORD ;--> first attribute to change
        .errnz  MAX_BUNDLE_TYPE-PRIM_IMAGE

dsga_set_next_attr:
        call    set_basic_attributes
        jz      dsga_error_occured
        dec     bp
        dec     bp
        jg      dsga_set_next_attr               ;If this far, AX = 1
        js      dsga_attributes_set

;/*
;**  The last bundle is the linebundle.  We aren't allowed to change its
;**  background color or mix mode, because it didn't have any in old versions.
;*/

        .errnz  PRIM_LINE-1
        xor     dx,dx
        or      dl,cl
        or      dx,di
        test    dx,(LBB_BACK_COLOR OR LBB_BACK_MIX_MODE)
        jz      short dsga_set_next_attr

dsga_attributes_set:

;/*
;**  We need to clean the saved basic attributes off the stack if we
;**  pushed them.  If the defaults mask is zero, then we did not save
;**  the attributes.
;*/

        or      cl,cl
        jnz     dsga_exit
        add     sp,5*SIZE_WORD                    ;Remove saved basic attributes
        jmp     short dsga_exit

dsga_error_occured:
ifdef FIREWALLS
        cmp     bp,(PRIM_IMAGE-1)*SIZE_WORD
        je      @F                                ;Should only have this error
                                                  ;  on first attribute set
        rip     text,<DeviceSetGlobalAttribute - Error occured after first attribute set>
@@:
endif

;/*
;**  We know we saved the parameters since default cannot fail.
;*/

        pop     word ptr [bx].ddc_ia.ia_ba.ba_bReserved
        .errnz  ba_fb-ba_bReserved-1
        pop     [bx].ddc_ia.ia_ba.ba_clrBack.hi
        pop     [bx].ddc_ia.ia_ba.ba_clrBack.lo
        pop     [bx].ddc_ia.ia_ba.ba_clr.hi
        pop     [bx].ddc_ia.ia_ba.ba_clr.lo

dsga_exit:                                        ;AX = return code
        pop     bp
        call    leave_driver
        cwd
dsga_exit_no_lock:
        fw_zero <es,cx>

cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceGetAttributes 
;*
;* DESCRIPTION   = Get the current attributes.  Although a [TYPE]BUNDLE is           
;*                 returned, this function only returns the foreground and
;*                 background colours.
;*                                                                                            
;*                 BType    - type of bundle wanted (PRIM_*) (e.g. PRIM_CHAR)
;*                                                                                            
;*                 TheMask  - the mask indicated what the caller wants returned.
;*                            Only valid masks are xBB_COLOR AND xBB_BACK_COLOR
;*                            where xe{LCMAI} (e.g. CBB_COLOR)
;*                                                                                            
;*                 lpAttrrs - long pointer to a *BUNDLE structure (e.g. CHARBUNDLE)
;*                                                                                             
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                
;*                 Registers Destroyed:
;*                       BX,CX,ES
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  DX:AX = BOOL 
;* RETURN-ERROR  =  DX:AX = BOOL 
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

        check   DeviceGetAttributes,<hdc,ulType,flAttrs,pBundle,hddc,ulFunN>
        check   GetAttributes,<hdc,ulType,flAttrs,pBundle,hddc,ulFunN>

cProc   DeviceGetAttributes,<PUBLIC,FAR,NODATA>,<di,si>
        parmD   hdc
        parmD   BType
        parmD   TheMask
        parmD   lpAttrs
        parmD   hddc
        parmD   FunN
cBegin

ifdef FIREWALLS                                   ;Callable only from engine.

        fw_zero <es,ds>
        ddc?    hddc
        mov     ax,TheMask.hi
        or      ax,BType.hi
        jnz     dga_firewall_error
        test    TheMask.lo,not (BB_COLOR or BB_BACK_COLOR)
        jnz     dga_firewall_error
        mov     cx,BType.lo
        jcxz    dga_firewall_error
        cmp     cx,MAX_BUNDLE_TYPE
        jbe     @f
dga_firewall_error:
        rip     text,<DeviceGetAttributes - bad parameters>

@@:
endif
        mov     ds,CodeData
        assumes ds,Data
        mov     dx,hddc.lo
        call    enter_driver
        xor     ax,ax                             ; assume error
        jc      dga_exit_no_lock

        mov     bx,BType.lo
        .errnz  PRIM_LINE-1
        dec     bx
        add     bx,bx
        mov     bx,ausAttrOffset[bx]
        add     bx,hddc.lo

        les     di,lpAttrs
        assumes es,nothing

        mov     dl,[bx].ba_fb
        mov     cx,TheMask.lo                     ;CH = 0

;/*
;**  Return either the current foreground color or the default foreground
;**  color if asked for.  The default must be return as a system color
;**  index because they might be in index color table mode in which case
;**  an RGB triplet is useless.
;*/

        test    cl,BB_COLOR
        jz      dga_done_foreground_color
        mov     ax,[bx].ba_clr.lo
        mov     si,[bx].ba_clr.hi
        test    dl,BA_CLR_DEF
        jz      @F
        or      ch,BB_COLOR                       ;Show default color
        mov     ax,SYSCLR_WINDOWTEXT and 0FFFFh
        mov     si,SYSCLR_WINDOWTEXT shr 16
@@:
        mov     es:[di].bnd_lColor.lo,ax
        mov     es:[di].bnd_lColor.hi,si
dga_done_foreground_color:

;/*
;**  Return either the current background color or the default background
;**  color if asked for.
;*/

        test    cl,BB_BACK_COLOR
        jz      dga_no_background_color ;Did not ask for foreground color
        mov     ax,[bx].ba_clrBack.lo
        mov     si,[bx].ba_clrBack.hi
        test    dl,BA_CLR_BACK_DEF
        jz      @F
        or      ch,BB_BACK_COLOR                 ;Show default color
        mov     ax,SYSCLR_WINDOW and 0FFFFh
        mov     si,SYSCLR_WINDOW shr 16
@@:
        mov     es:[di].bnd_lBackColor.lo,ax
        mov     es:[di].bnd_lBackColor.hi,si
dga_no_background_color:


        call    leave_driver
        mov     ax,1                              ;Return success
dga_exit_no_lock:
        cwd
        fw_zero <es,ds>
cEnd


sEnd    Code
end
