;*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 = DRAWBORD.ASM
;*
;* DESCRIPTIVE NAME = This module contains code for the DrawBorder function. 
;*
;*
;* VERSION      V2.0
;*
;* DATE         05/27/87
;*
;* DESCRIPTION  
;*
;*      This subroutine draws the four edges of a rectangle border,
;*      and possibly fills the interior, based on the options described
;*      below.
;*
;*      The border and interior are always drawn using the pattern
;*      from the area attributes.  The colors of this pattern depend
;*      on the value of DB_AREAATTRS.:
;*
;*          If DB_AREAATTRS not given (default):
;*
;*              For any border, the pattern used will be the same as
;*              if a SetAttributes call for the area attributes was
;*              made with a foreground color of clrBorder and a back-
;*              ground color of clrInterior.
;*
;*              For any interior, the pattern used will be the same
;*              as if a SetAttributes call for the area attributes
;*              was made with a foreground color of clrInterior and
;*              a background color of clrBorder.
;*
;*          If DB_AREAATTRS given:
;*
;*              For any border, the pattern used will be the pattern
;*              as currently defined in the area attribute.
;*
;*              For any interior, the pattern used will be the same
;*              as if a SetAttributes call for the area attributes
;*              was made with the area attribute's background color
;*              being passed for the foreground color, and the area
;*              attribute's foreground color being passed as the
;*              background color.
;*
;*              If DB_INTERIOR is specified, the area contained within the
;*              given rectangle and not included within the borders (as given
;*              by cx,cy) will be drawn using the given mix mode.
;*
;*
;*      DB_PATCOPY
;*      DB_PATINVERT
;*      DB_DESTINVERT
;*      DB_AREAMIXMODE
;*              Determines the rop to be passed to Bitblt.
;*
;*      DB_INTERIOR
;*              In addition to any other option fill the frame's interior
;*              with clrInterior (or the current pattern background color,
;*              if DB_AREAATTRS).
;*
;*      DB_AREAATTRS
;*              Use the current pattern foreground color in place of
;*              clrBorder, and the current pattern background color
;*              in place of clrInterior (if DB_INTERIOR).
;*
;*      DB_STANDARD
;*      DB_DLGBORDER
;*              Ignored at this level (used by the window manager).
;*
;*
;*      The shapes of the edges drawn are shown below.
;*      The edges are drawn in numerical order.
;*
;*
;*                      +----+-----------------------+
;*                      |    |                          |
;*                      |    |                    III      |
;*                      |    |                          |
;*                      |    +------------------+----+
;*                      |    |                     |    |
;*                      |    |                     |    |
;*                      | IV |                     |    |
;*                      |    |                         V  |    |
;*                      |    |                     | II |
;*                      |    |                     |    |
;*                      |    |                     |    |
;*                      +----+------------------+    |
;*                      |                          |    |
;*                      |                            I  |    |
;*                      |                          |    |
;*                      +-----------------------+----+
;*
;* FUNCTIONS    Exported: DrawBorder
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   05/27/87                     Bob Grudem [bobgru] - Created
;*   ---------------------- DrawBorder----------------------------------
;*   02/07/88                     Bob Grudem [bobgru]
;*                                  Now validates border width, hddc, and
;*                                  options.  Called functions preserve
;*                                  DS:DI so segment loads are minimized.
;*   01/07/88                     Bob Grudem [bobgru]
;*                                  Changed interface according to DCR
;*                                  23694.
;*   10/14/87                     Bob Grudem [bobgru]
;*                                  Ported to Winthorn.  Total rewrite.
;*   06/11/87                     Bob Grudem [bobgru] Cleaned up comments.
;*   05/27/87                     Bob Grudem [bobgru] - Created DrawBorder
;*   -------------------draw_border_validate_parms----------------------
;*   04/17/88                     Bob Grudem [bobgru]
;*                                  Changed rop mapping from options as per
;*                                  DCR 23861.
;*   02/08/88                     Bob Grudem [bobgru]
;*                                  Created draw_border_validate_parms
;*   -------------------draw_border_init--------------------------------
;*   05/18/88                     Bob Grudem [bobgru]
;*                                  Added check for change of system colors.
;*   04/17/88                     Bob Grudem [bobgru]
;*                                  Changed rop mapping from options as per DCR
;*                                  23861.
;*   02/07/88                     Bob Grudem [bobgru]
;*                                  Totally rewrote for new DDC structure.
;*   12/09/87                     Hock Lee [hockl]
;*                                  Replaced ROP_PATCOPY_L and
;*                                  ROP_PATINVERT_L by ROP_PATCOPY and
;*                                  ROP_PATINVERT.
;*   10/14/87                     Bob Grudem [bobgru]
;*                                  Created draw_border_init
;*   -------------------draw_border_do_blts-----------------------------
;*   07/21/88                     Bob Grudem [bobgru]
;*                                  Now checks for error returned by
;*                                  create_brush.
;*   04/17/88                     Bob Grudem[bobgru]
;*                                  Calls to create_brush now take two
;*                                  colors.
;*   02/07/88                     Bob Grudem [bobgru]
;*                                  Border-color brush realized in one place
;*                                  at beginning, since there is now
;*                                  guaranteed to be at least one blt to do.
;*                                  Now preserves DI everywhere.
;*   06/11/87                     Bob Grudem [bobgru] - Cleaned up comments.
;*   05/27/87                     Bob Grudem [bobgru]
;*                                  Created draw_border_do_blts
;*   ---------------------------do_blt-------------------------------------
;*   02/07/88                     Bob Grudem [bobgru]
;*                                  Removed loading of DS, since DS is now
;*                                  preserved everywhere.
;*   06/11/87                     Bob Grudem [bobgru] - Cleaned up comments.
;*   05/27/87                     Bob Grudem [bobgru] - Created do_blt
;*   ------------------------create_brush-------------------------------
;*   07/21/88                     Bob Grudem [bobgru]
;*                                  Now checks for error returned by
;*                                  MakeBrushValid.
;*   04/17/88                     Bob Grudem[bobgru]
;*                                  Now takes two colors as parameters.
;*                                  Doesn't exit early if DB_PATINVERT.
;*   02/07/88                     Bob Grudem [bobgru]
;*                                  Totally rewrote for new DDC structure.
;*   10/14/87                     Bob Grudem [bobgru]
;*                                  Created create_brush
;*****************************************************************************/

        .xlist
        include cmacros.inc
INCL_WINCOMMON          equ                      1
INCL_GRE_BITMAPS        equ                      1
INCL_GRE_COLORTABLE     equ                      1
INCL_GPIBITMAPS         equ                      1
INCL_GPICONSTANTS       equ                      1
INCL_DDICOMFLAGS        equ                      1
INCL_DDIMISC            equ                      1
        include pmgre.inc
        include driver.inc
        include display.inc
        include njmp.mac
        .list

DB_ROP          equ     07h
DB_GOOD_FLAGS    =      DB_ROP or DB_INTERIOR or DB_AREAATTRS
DB_GOOD_FLAGS    =      DB_GOOD_FLAGS or DB_STANDARD or DB_DLGBORDER
DB_BAD_FLAGS     =      not DB_GOOD_FLAGS

DB_ERROR        equ     0
DB_SUCCESS      equ     1



        errcode <INV_RECT,INV_COORDINATE,INV_DRAW_BORDER_OPTION>
        errcode <BITMAP_NOT_SELECTED,INV_IN_PATH,INV_IN_AREA>
        errcode <INV_LENGTH_OR_COUNT>

        externFP Bitblt


sBegin  Data
        externB ddcInit
sEnd

sBegin  FarCode
        externNP PropagateSysClrChange
sEnd

sBegin  Code
        assumes cs,Code

        externW         CodeData

        externNP MakeBrushValid
        externNP enter_driver
        externNP leave_driver

;/*
;**  this table maps the DB_ROP option bits onto         rops.
;**  The option DB_AREAMIXMODE causes the table my_rops to be
;**  used instead.
;*/

option_rops     label   byte
        db      0F0h                              ;** DB_PATCOPY
        db      05Ah                              ;** DB_PATINVERT
        db      055h                              ;** DB_DESTINVERT

        .errnz  DB_PATCOPY    - 0
        .errnz  DB_PATINVERT  - 1
        .errnz  DB_DESTINVERT - 2

my_rops         label   byte
        db      000h                              ;** DDx
        db      005h                              ;** DPon
        db      00Ah                              ;** DPna
        db      00Fh                              ;** Pn
        db      050h                              ;** PDna
        db      055h                              ;** Dn
        db      05Ah                              ;** DPx
        db      05Fh                              ;** DPan
        db      0A0h                              ;** DPa
        db      0A5h                              ;** DPxn
        db      0AAh                              ;** D
        db      0AFh                              ;** DPno
        db      0F0h                              ;** P
        db      0F5h                              ;** PDno
        db      0FAh                              ;** DPo
        db      0FFh                              ;** DDxn


page

;/***************************************************************************
;*
;* FUNCTION NAME = DrawBorder
;*
;* DESCRIPTION   = Draw a border inside a rectangle, possibly filling the           
;*                 interior.
;*              
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Calls:
;*                       draw_border_init
;*                       draw_border_do_blts
;*                       leave_driver
;*              
;* INPUT         = None
;* OUTPUT        = None
;*
;* RETURN-NORMAL = DX:AX = 1 
;* RETURN-ERROR  = DX:AX = 0 
;*                 BAD_OPTION
;*                     an invalid option bit was set
;*                 BAD_INTEGER
;*                     cxBorder, cyBorder, or any coordinate in *lprc not a 16-bit
;*                       integer sign-extended to 32 bits
;*                     cxBorder or cyBorder are negative
;*                 BAD_RECTANGLE
;*                     the points in the rectangle are misordered
;*                 others as returned by Bitblt
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

        check   DrawBorder,<hdc,prcl,cx,cy,clrFore,clrBack,flCmd,hddc,ulFunN>

cProc   DrawBorder,<FAR,PUBLIC,NODATA>,<si,di>

        parmD   hdc
        parmD   lprc                              ;** in DEVICE coordinates
        parmD   cxBorder                          ;**   ditto
        parmD   cyBorder                          ;**   ditto
        parmD   clrBorder
        parmD   clrInterior
        parmD   flCmd
        parmD   hddc
        parmD   FunN

        localW  x1                                ;** corners of rectangle to frame
        localW  y1
        localW  x2
        localW  y2

        localW  maxwidth                          ;** max width of top and bottom edges
        localW  maxheight                         ;** max height of right and left edges
        localV  blt_rect,%(size RECTL)
        localW  rop                               ;** make it easier to pass to bitblt

        localV  MyColors,%(size BITBLTATTRS)

cBegin
        fw_zero <ds,es>
        cld

        mov     ds,CodeData
        assumes ds,Data
        mov     di,hddc.lo
        mov     dx,di
        call    enter_driver
        jc      db_exit_no_lock                   ;**  DX:AX = 0 on error
        no_path_area db_exit,both
        ddc?    di,<SURFACE>
        test    [di].ddc_fb,DDC_PRESENT
        jz      no_bitmap_selected

        call    draw_border_validate_parms
        assumes es,nothing
        jc      db_set_exit_code                 ;** error already logged
        or      ax,ax                            ;** were borders widths both 0?
        jnz     db_exit                          ;** if yes, exit w/ AX = DB_SUCCESS

        call    draw_border_init

        call    draw_border_do_blts

db_set_exit_code:
        sbb     ax,ax                             ;** AX = 0 (ok), = -1 (error)
        inc     ax                                ;** AX = 1 (ok), =  0 (error)
        .errnz  DB_ERROR
        .errnz  DB_SUCCESS - 1
        jmp     short db_exit

no_bitmap_selected:
        mov     ax,PMERR_BITMAP_NOT_SELECTED
        save_error_code
        xor     ax,ax
db_exit:
        cwd
        call    leave_driver
db_exit_no_lock:
        fw_zero <cx,ds,es>
cEnd
page


;/***************************************************************************
;*
;* FUNCTION NAME = draw_border_validate_parms
;*
;* DESCRIPTION   = Validate as many parameters as possible.  The colors are   
;*                 left to Bitblt to validate later on.
;*
;*                 Registers Preserved:
;*                       DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,ES,FLAGS
;*                 Calls:
;*                       none
;*
;* INPUT         = SS:BP --> DrawBorder stack frame
;*                 DS:DI --> DDC
;* OUTPUT        = None
;*
;* RETURN-NORMAL = C = 0 if all parameters valid
;*                     AX = DB_SUCCESS if both widths zero
;*                     AX = 0 if at least one width is non-zero
;* RETURN-ERROR  = C = 1 if at least one parameter is in error
;*                     error will have been logged
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        public  draw_border_validate_parms
draw_border_validate_parms                       proc near

        cmp     flCmd.hi,0                         ;** validate flCmd
        jne     dbvp_invalid_option                ;** no options up there
        mov     ax,flCmd.lo                        ;** get the option flags
        test    ax,DB_BAD_FLAGS                    ;** check all     flags at once
        jnz     dbvp_invalid_option                ;** jump if flags bad
        and     ax,DB_ROP                          ;** isolate rop requested
        jz      dbvp_border_widths                 ;** jump if DB_PATCOPY
        cmp     ax,DB_AREAMIXMODE                  ;** highest valid rop option
        jbe     dbvp_border_widths                 ;** jump if ok
dbvp_invalid_option:
        mov     ax,PMERR_INV_DRAW_BORDER_OPTION
        jmp     short dbvp_save_error_code


dbvp_border_widths:
        mov     flCmd.hi,ax                        ;** save preprocessed flags

        mov     ax,cxBorder.lo                     ;** validate border widths
        or      ax,ax                              ;** must be positive
        js      dbvp_bad_length
        cwd
        cmp     dx,cxBorder.hi                     ;** must be 16-bit integer sign-
        jne     dbvp_bad_length                    ;**  extended to 32-bits
        xchg    ax,bx                              ;** save a copy of low word

        mov     ax,cyBorder.lo
        or      ax,ax                              ;** must be positive
        js      dbvp_bad_length
        cwd
        cmp     dx,cyBorder.hi                     ;** must be 16-bit integer sign-
        jne     dbvp_bad_length                    ;**  extended to 32-bits
        test    flCmd.lo,DB_INTERIOR               ;** if caller wants interior
        jnz     dbvp_rect                          ;**  then can't exit early
        or      ax,bx                              ;** if both widths are 0, then
        mov     ax,DB_SUCCESS                      ;**  exit successfully (having
        jz      dbvp_exit                          ;**  done nothing) -- carry is
        jmp     short dbvp_rect                    ;**  clear

dbvp_bad_length:
        mov     ax,PMERR_INV_LENGTH_OR_COUNT
        jmp     short dbvp_save_error_code

dbvp_bad_int:
        mov     ax,PMERR_INV_COORDINATE
dbvp_save_error_code:
        save_error_code
        stc
        jmp     short dbvp_exit

dbvp_rect:
        les     si,lprc                           ;** validate the rectangle
        assumes es,nothing

        mov     ax,es:[si].rcl_xRight.lo
        cwd
        cmp     dx,es:[si].rcl_xRight.hi ;** must be 16-bit integer sign-extended
        jne     dbvp_bad_int                      ;**   to 32-bits
        mov     x2,ax                             ;** save for building blt rects
        xchg    ax,bx                             ;** save in BX for computing x extent

        mov     ax,es:[si].rcl_yTop.lo
        cwd
        cmp     dx,es:[si].rcl_yTop.hi           ;** must be 16-bit integer sign-extended
        jne     dbvp_bad_int                     ;**   to 32-bits
        mov     y2,ax                            ;** save for building blt rects
        xchg    ax,cx                            ;** save in CX for computing y extent

        mov     ax,es:[si].rcl_xLeft.lo
        cwd
        cmp     dx,es:[si].rcl_xLeft.hi  ;** must be 16-bit integer sign-extended
        jne     dbvp_bad_int                      ;**   to 32-bits
        mov     x1,ax                             ;** save for building blt rects
        sub     bx,ax                             ;** compute x extent of rect

        mov     ax,es:[si].rcl_yBottom.lo
        cwd
        cmp     dx,es:[si].rcl_yBottom.hi ;** must be 16-bit integer sign-extended
        jne     dbvp_bad_int                      ;**   to 32-bits
        mov     y1,ax                             ;** save for building blt rects
        sub     cx,ax                             ;** compute y extent of rect

        mov     ax,bx                             ;** if either extent is negative then
        or      ax,cx                             ;** we have a degenerate rectangle
        mov     ax,PMERR_INV_RECT                 ;** prepare to exit with error
        js      dbvp_save_error_code              ;**     rect ==> no drawing needed


        sub     bx,cxBorder.lo                    ;** finish up a few dimension variables
        mov     maxwidth,bx
        sub     cx,cyBorder.lo
        mov     maxheight,cx
        xor     ax,ax                             ;** also clears carry

dbvp_exit:
        ret

draw_border_validate_parms                       endp


;/***************************************************************************
;*
;* FUNCTION NAME = draw_border_init
;*
;* DESCRIPTION   = Initialize frame variables. 
;*
;*                 Registers Preserved:
;*                       CX,DX,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,SI,FLAGS
;*                 Calls:
;*                       none
;*
;* INPUT         = SS:BP --> DrawBorder stack frame
;*                 DS:DI --> DDC
;*                 flCmd.hi = DB_PATCOPY, DB_PATINVERT, DB_DESTINVERT, or
;*                            DB_AREAMIXMODE
;* OUTPUT        = None
;*
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        public  draw_border_init
draw_border_init        proc                     near

;/*
;**  If the system colors SYSCLR_WINDOW or SYSCLR_WINDOWTEXT have changed
;**  recently, we need to update the colors in our DDC.
;*/

        mov     ax,ddcInit.ddc_iSysClr
        cmp     [di].ddc_iSysClr,ax
        je      db_init_sysclrs_ok
        mov     si,di                              ;** need DDC here
        cCall   PropagateSysClrChange
db_init_sysclrs_ok:

        mov     bx,flCmd.hi                        ;** get preprocessed flags
        cmp     bx,DB_AREAMIXMODE
        je      db_init_use_current_mix

        mov     al,option_rops[bx]
        jmp     short db_init_check_areaattrs

db_init_use_current_mix:
        mov     bl,[di].ddc_pa.pa_ba.ba_bmix
        mov     al,my_rops[bx]


;/*
;**        If the DB_AREAATTRS option is set, use the colors in the
;**        pattern attributes in place of those passed in.  If both
;**        DB_AREAATTRS and DB_INTERIOR options are set, we'll have
;**        to realize a brush with the pattern foreground and background
;**        colors switched.  Since we won't ever use the colors passed
;**        in, we'll use that space for local storage of the colors
;**        we need.
;*/

db_init_check_areaattrs:
        xor     ah,ah
        mov     rop,ax                             ;** save this first

        mov     ax,flCmd.lo
        and     ax,DB_AREAATTRS or DB_INTERIOR
        cmp     ax,DB_AREAATTRS or DB_INTERIOR
        jne     @F
        mov     ax,[di].ddc_pa.pa_ba.ba_clr.lo
        mov     clrBorder.lo,ax
        mov     ax,[di].ddc_pa.pa_ba.ba_clr.hi
        mov     clrBorder.hi,ax
        mov     ax,[di].ddc_pa.pa_ba.ba_clrBack.lo
        mov     clrInterior.lo,ax
        mov     ax,[di].ddc_pa.pa_ba.ba_clrBack.hi
        mov     clrInterior.hi,ax
@@:
        ret

draw_border_init        endp


;/***************************************************************************
;*
;* FUNCTION NAME = draw_border_do_blts
;*
;* DESCRIPTION   = Determines the coordinates of each segment of the border  
;*                 and makes the calls to Bitblt.  Calls create_brush to set
;*                 the pattern attributes as the caller requested.
;*
;*                 Registers Preserved:
;*                       DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,ES,FLAGS
;*                 Calls:
;*                       create_brush
;*                       do_blt
;*
;* INPUT         = DS:DI --> DDC
                   SS:BP --> DrawBorder stack frame
;* OUTPUT        = None
;*
;* RETURN-NORMAL = C = 0, if drawing was completed successfully 
;* RETURN-ERROR  = C = 1, if Bitblt returned error              
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        public  draw_border_do_blts
draw_border_do_blts     proc                     near

;/*
;**  Set the right flags and values in the DDC to get a new pattern
;**  the next time we call Bitblt.
;*/


        test    flCmd.lo,DB_AREAATTRS            ;** AREAATTRS option set?
        jnz     @F                               ;** if yes, use pattern as is
        mov     ax,clrBorder.lo                  ;** if no, set up attributes to get new
        mov     bx,clrBorder.hi                  ;**   brush
        mov     cx,clrInterior.lo
        mov     dx,clrInterior.hi
        call    create_brush
        jc      dbdb_exit_error_vect1            ;** exit if error
@@:
        mov     si,cxBorder.lo                   ;** load commonly used values -- SI and DI
        mov     di,cyBorder.lo                   ;**   are preserved across call to do_blt


;/*
;**  Check for the case of a single BLT, where the border is thick
;**  enough to fill the entire rectangle.
;*/


        mov     cx,si                             ;** get horizontal border width
        add     cx,cx                             ;**  * 2
        mov     dx,di                             ;** get vertical border width
        add     dx,dx                             ;**  * 2
        mov     ax,x2                             ;** compute x extent
        sub     ax,x1                             ;**
        cmp     ax,cx                             ;** is x extent less than 2*cxBorder?
        jle     dbdb_single_blt                   ;** if yes, it's really a single Bitblt
        mov     ax,y2                             ;** compute y extent
        sub     ax,y1                             ;**
        cmp     ax,dx                             ;** is y extent greater than 2*cyBorder?
        jg      dbdb_multiple_blts                ;** if yes, then call Bitblt for each
                                                  ;**   segment of the border


;/*
;**  Single BLT - paint the whole rectangle the border color.
;*/

dbdb_single_blt:
        mov     ax,x1
        cwd
        mov     blt_rect.rcl_xLeft.lo,ax
        mov     blt_rect.rcl_xLeft.hi,dx
        mov     ax,y1
        cwd
        mov     blt_rect.rcl_yBottom.lo,ax
        mov     blt_rect.rcl_yBottom.hi,dx
        mov     ax,x2
        cwd
        mov     blt_rect.rcl_xRight.lo,ax
        mov     blt_rect.rcl_xRight.hi,dx
        mov     ax,y2
        cwd
        mov     blt_rect.rcl_yTop.lo,ax
        mov     blt_rect.rcl_yTop.hi,dx

        call    do_blt
dbdb_exit_error_vect1:
        jmp     dbdb_exit


dbdb_multiple_blts:


;/*
;**  Bottom edge
;*/

        or      di,di
        jz      dbdb_chk_right

        mov     ax,x1
        cwd
        mov     blt_rect.rcl_xLeft.lo,ax
        mov     blt_rect.rcl_xLeft.hi,dx
        add     ax,maxwidth                        
        cwd
        mov     blt_rect.rcl_xRight.lo,ax
        mov     blt_rect.rcl_xRight.hi,dx
        mov     ax,y1
        cwd
        mov     blt_rect.rcl_yBottom.lo,ax
        mov     blt_rect.rcl_yBottom.hi,dx
        add     ax,di                              
        cwd
        mov     blt_rect.rcl_yTop.lo,ax
        mov     blt_rect.rcl_yTop.hi,dx

        call    do_blt
        jnc     dbdb_chk_right
dbdb_exit_error_vect2:
        jmp     dbdb_exit


;/*
;**  Right edge
;*/

dbdb_chk_right:
        or      si,si
        jz      dbdb_chk_top

        mov     ax,x1
        add     ax,maxwidth                        
        cwd
        mov     blt_rect.rcl_xLeft.lo,ax
        mov     blt_rect.rcl_xLeft.hi,dx
        add     ax,si                              
        cwd
        mov     blt_rect.rcl_xRight.lo,ax
        mov     blt_rect.rcl_xRight.hi,dx
        mov     ax,y1
        cwd
        mov     blt_rect.rcl_yBottom.lo,ax
        mov     blt_rect.rcl_yBottom.hi,dx
        add     ax,maxheight                       
        cwd
        mov     blt_rect.rcl_yTop.lo,ax
        mov     blt_rect.rcl_yTop.hi,dx
        call    do_blt
        jc      dbdb_exit_error_vect2


;/*
;**  Top edge
;*/

dbdb_chk_top:
        or      di,di
        jz      dbdb_chk_left

        mov     ax,x1
        add     ax,si                              
        cwd
        mov     blt_rect.rcl_xLeft.lo,ax
        mov     blt_rect.rcl_xLeft.hi,dx
        add     ax,maxwidth                        
        cwd
        mov     blt_rect.rcl_xRight.lo,ax
        mov     blt_rect.rcl_xRight.hi,dx
        mov     ax,y1
        add     ax,maxheight                       
        cwd
        mov     blt_rect.rcl_yBottom.lo,ax
        mov     blt_rect.rcl_yBottom.hi,dx
        add     ax,di                              
        cwd
        mov     blt_rect.rcl_yTop.lo,ax
        mov     blt_rect.rcl_yTop.hi,dx

        call    do_blt
        jc      dbdb_exit_error_vect2


;/*
;**  Left edge
;*/

dbdb_chk_left:
        or      si,si
        jz      dbdb_chk_interior

        mov     ax,x1
        cwd
        mov     blt_rect.rcl_xLeft.lo,ax
        mov     blt_rect.rcl_xLeft.hi,dx
        add     ax,si                              
        cwd
        mov     blt_rect.rcl_xRight.lo,ax
        mov     blt_rect.rcl_xRight.hi,dx
        mov     ax,y1
        add     ax,di                              
        cwd
        mov     blt_rect.rcl_yBottom.lo,ax
        mov     blt_rect.rcl_yBottom.hi,dx
        add     ax,maxheight                       
        cwd
        mov     blt_rect.rcl_yTop.lo,ax
        mov     blt_rect.rcl_yTop.hi,dx

        call    do_blt
        jc      dbdb_exit


;/*
;**  Interior
;*/

dbdb_chk_interior:
        test    flCmd.lo,DB_INTERIOR
        jz      dbdb_exit

        mov     ax,x1
        add     ax,si                              
        cwd
        mov     blt_rect.rcl_xLeft.lo,ax
        mov     blt_rect.rcl_xLeft.hi,dx
        add     ax,maxwidth                        
        sub     ax,si                              
        cwd
        mov     blt_rect.rcl_xRight.lo,ax
        mov     blt_rect.rcl_xRight.hi,dx
        mov     ax,y1
        add     ax,di                              
        cwd
        mov     blt_rect.rcl_yBottom.lo,ax
        mov     blt_rect.rcl_yBottom.hi,dx
        add     ax,maxheight                       
        sub     ax,di                              
        cwd
        mov     blt_rect.rcl_yTop.lo,ax
        mov     blt_rect.rcl_yTop.hi,dx

        mov     ax,clrInterior.lo
        mov     bx,clrInterior.hi
        mov     cx,clrBorder.lo
        mov     dx,clrBorder.hi
        mov     di,hddc.lo
        call    create_brush
        jc      dbdb_exit                          ;** exit now if error
        call    do_blt

dbdb_exit:
        mov     di,hddc.lo
        or      [di].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        cmp     ax,1                               ;** set carry if AX = 0
        ret

draw_border_do_blts     endp


;/***************************************************************************
;*
;* FUNCTION NAME = do_blt
;*
;* DESCRIPTION   = Shovel parameters to BitBlt. 
;*              
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,flags
;*                 Calls:
;*                       Bitblt
;*
;*
;* INPUT         = SS:BP --> DrawBorder's stack frame
;*                 Destination rectangle for Bitblt has been determined, and placed
;*                 in the blt_rect structure.
;* OUTPUT        = AX = Bitblt return code
;*                                         
;* RETURN-NORMAL = C  = 0 if no error      
;* RETURN-ERROR  = C  = 1 if error         
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

        public  do_blt
do_blt  proc    near

        xor     ax,ax                             ;** generic null-parameter
        lea     bx,blt_rect
        farPtr  Cnt,ax,2
        farPtr  Mix,ax,rop
        farPtr  Styl,ax,ax
        farPtr  lpAttrs,ax,ax
        farPtr  lpPts,ss,bx
        farPtr  MyFunN,(FunN.hi),off_Bitblt
        check   Bitblt,<hdc,hdcSrc,cptl,pbbp,lMix,flCmd,pbba,hddc,ulFunN>
        cCall   Bitblt,<hdc,hdc,Cnt,lpPts,Mix,Styl,lpAttrs,hddc,MyFunN>
        cmp     ax,1                              ;** set carry if AX = 0
        ret

do_blt  endp


;/***************************************************************************
;*
;* FUNCTION NAME = create_brush
;*
;* DESCRIPTION   = Calls MakeBrushValid to convert the pattern bits to the    
;*                 requested colors.
;*              
;*                 Registers Preserved:
;*                       BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,ES,FLAGS
;*                 Calls:
;*                       MakeBrushValid
;*
;* INPUT         = AX = low word of brush foreground color
;*                 BX = high word of brush foreground color
;*                 CX = low word of brush background color
;*                 DX = high word of brush background color
;*                 SS:BP --> DrawBorder stack frame
;*                 DS:DI --> DDC
;* OUTPUT        = None
;*
;* RETURN-NORMAL = carry bit clear  
;* RETURN-ERROR  = carry bit set    
;*                 AX = 0           
;*                 error logged     
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        public  create_brush
create_brush    proc    near

;/*
;**  Set foreground color to BX:AX.
;**  Set background color to DX:CX.
;*/


        mov     MyColors.bba_cSize.lo,12
        mov     MyColors.bba_cSize.hi,0
        mov     MyColors.bba_lColor.lo,ax
        mov     MyColors.bba_lColor.hi,bx
        mov     MyColors.bba_lBackColor.lo,cx
        mov     MyColors.bba_lBackColor.hi,dx

        mov     si,di                              ;** DS:SI --> DDC
        mov     cl,0FFh                            ;** override colors
        lea     ax,MyColors
        farPtr  NewColors,ss,ax
        push    di
        cCall   MakeBrushValid,<NewColors>
        pop     di
        or      ax,ax
        js      create_brush_error                ;** jump if error (already logged)
        and     [di].ddc_pa.pa_ba.ba_fb,not BA_REREALIZE
        jmp     short create_brush_exit
create_brush_error:
        xor     ax,ax
        stc
create_brush_exit:
        ret

create_brush    endp

sEnd    Code
end
