;*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 = 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    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                     Written by Grudem
;*   10/14/87                     Bob Grudem [bobgru] Ported to Winthorn.  Total 
;*                                rewrite.
;*   01/07/88                     Bob Grudem [bobgru] Changed interface according 
;*                                to DCR 23694.
;*   02/07/91                     Bob Grudem [bobgru] Now validates border width, 
;*                                hddc, and options.  Called functions preserve 
;*                                DS:DI so segment loads are minimized.
;*   10/18/91                     Cliff Levesque [cliffl] Cleanup and convert 
;*                                to 386 and above flat model, protected mode
;*                                32 bit operation. Move draw_border_validate_parms,
;*                                draw_border_init,and draw_border_do_blts
;*                                inline in DrawBorder - MASM 6.0 - .
;*                                Move create_brush and do_blt inline within 
;*                                draw_border_do_blts - MASM 6.0 - .
;*
;*****************************************************************************/

        .386

        .xlist

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
INCL_GPIERRORS          equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1
OS2P_DEFD               equ     1

        include pmgre.inc
        include driver.inc
        include extern.inc
        include protos.inc

        .list

        .MODEL FLAT

        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA


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

;/*
;** This table maps the DB_ROP option bits onto PM 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

        .CODE

page

;/***************************************************************************
;*
;* FUNCTION NAME = DrawBorder
;*
;* DESCRIPTION   = Draw a border inside a rectangle, possibly filling the interior. 
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX,FLAGS
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EDX:EAX = 1      
;* RETURN-ERROR  = EDX:EAX = 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
;*            
;**************************************************************************/

                ASSUME  edi:PTR DDC

ALIGN 4
DrawBorder      PROC    SYSCALL USES EBX esi edi, hdc:DWORD, lprc:DWORD,
                                                cxBorder:DWORD, cyBorder:DWORD,
                                                clrBorder:DWORD, clrInterior:DWORD,
                                                flCmd:DWORD, hddc:DWORD, FunN:DWORD
                LOCAL   x1:DWORD, y1:DWORD,
                        x2:DWORD, y2:DWORD,
                        maxwidth:DWORD, maxheight:DWORD,
                        blt_rect:RECTL, rop:DWORD,
                        MyColors:BITBLTATTRS

        DebugMsg <DrawBorder CLIFFL>
        cld

        mov     edi,hddc
        mov     edx,edi
        ENTER_DRIVER2
        jc      db_exit_no_lock         ; EDX:EAX = 0 on error

        no_path_area db_exit,both

        ddc?    edi,<SURFACE>

        test    [edi].ddc_fb,DDC_PRESENT
        jz      no_bitmap_selected

draw_border_validate_parms:

        cmp     WORD PTR flCmd[2],0             ;validate flCmd
        jne     dbvp_invalid_option             ;no options up there
        mov     eax,flCmd                       ;get the option flags
        test    eax,DB_BAD_FLAGS                ;check all     flags at once
        jnz     dbvp_invalid_option             ;jump if flags bad
        and     eax,DB_ROP                      ;isolate rop requested
        jz      dbvp_border_widths              ;jump if DB_PATCOPY
        cmp     eax,DB_AREAMIXMODE              ;highest valid rop option
        jbe     dbvp_border_widths              ;jump if ok

dbvp_invalid_option:

        mov     eax,PMERR_INV_DRAW_BORDER_OPTION
        jmp     dbvp_save_error_code
ALIGN 4


dbvp_border_widths:

        mov     WORD PTR flCmd[2],ax            ;save preprocessed flags

        mov     eax,cxBorder                    ;validate border widths
        cmp     eax,10000h
        ja      dbvp_bad_length
        xchg    eax,ebx                         ;save a copy of low word

        mov     eax,cyBorder
        cmp     eax,10000h                      ;must be positive
        ja      dbvp_bad_length
        test    flCmd,DB_INTERIOR               ;if caller wants interior
        jnz     dbvp_rect                       ; then can't exit early
        or      eax,ebx                         ;if both widths are 0, then
        mov     eax,DB_SUCCESS                  ; exit successfully (having
        jz      dbvp_exit                       ; done nothing) -- carry is
        jmp     dbvp_rect                       ; clear
ALIGN 4

dbvp_bad_length:

        mov     eax,PMERR_INV_LENGTH_OR_COUNT
        jmp     dbvp_save_error_code
ALIGN 4

dbvp_bad_int:

        mov     eax,PMERR_INV_COORDINATE

dbvp_save_error_code:

        save_error_code

        stc
        jmp     dbvp_exit
ALIGN 4

dbvp_rect:

        mov     esi,lprc                ;validate the rectangle

        ASSUME  esi:PTR RECTL

        mov     eax,[esi].rcl_xRight
        mov     x2,eax                  ;save for building blt rects
        xchg    eax,ebx                 ;save in BX for computing x extent

        mov     eax,[esi].rcl_yTop
        mov     y2,eax                  ;save for building blt rects
        xchg    eax,ecx                 ;save in CX for computing y extent

        mov     eax,[esi].rcl_xLeft
        mov     x1,eax                  ;save for building blt rects
        sub     ebx,eax                 ;compute x extent of rect

        mov     eax,[esi].rcl_yBottom
        mov     y1,eax                  ;save for building blt rects
        sub     ecx,eax                 ;compute y extent of rect

        mov     eax,ebx                 ;if either extent is negative then
        or      eax,ecx                 ;we have a degenerate rectangle
        mov     eax,PMERR_INV_RECT      ;prepare to exit with error
        js      dbvp_save_error_code    ;bad rect ==> no drawing needed


        sub     ebx,cxBorder            ;finish up a few dimension variables
        mov     maxwidth,ebx
        sub     ecx,cyBorder
        mov     maxheight,ecx
        xor     eax,eax                 ;also clears carry

dbvp_exit:

        jc      db_set_exit_code        ;error already logged
        or      eax,eax                 ;were borders widths both 0?
        jnz     db_exit                 ;if yes, exit w/ AX = DB_SUCCESS

draw_border_init:

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

        mov     eax,ddcInit.ddc_iSysClr

        cmp     [edi].ddc_iSysClr,eax
        je      db_init_sysclrs_ok
        mov     esi,edi                         ;need DDC here
        INVOKE  PropagateSysClrChange

db_init_sysclrs_ok:

        movzx   ebx,WORD PTR flCmd[2]            ;get preprocessed flags
        cmp     ebx,DB_AREAMIXMODE
        je      db_init_use_current_mix

        mov     al,option_rops[ebx]
        jmp     db_init_check_areaattrs
ALIGN 4

db_init_use_current_mix:

        mov     bl,[edi].ddc_pa.pa_ba.ba_bmix
        mov     al,my_rops[ebx]

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

        movzx   eax,al
        mov     rop,eax                         ;save this first

        mov     eax,flCmd
        and     eax,DB_AREAATTRS or DB_INTERIOR
        cmp     eax,DB_AREAATTRS or DB_INTERIOR
        jne     @F
        mov     eax,[edi].ddc_pa.pa_ba.ba_clr
        mov     clrBorder,eax
        mov     eax,[edi].ddc_pa.pa_ba.ba_clrBack
        mov     clrInterior,eax
@@:

draw_border_do_blts:

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

        test    flCmd,DB_AREAATTRS      ;AREAATTRS option set?
        jnz     @F                      ;if yes, use pattern as is
        mov     eax,clrBorder           ;if no, set up attributes to get new
        mov     ebx,clrInterior         ;  brush

create_brush:

;/*
;** Set foreground color to EAX.
;** Set background color to EBX.
;*/

        mov     MyColors.bba_cSize,12
        mov     MyColors.bba_lColor,eax
        mov     MyColors.bba_lBackColor,ebx

        mov     esi,edi                         ;ESI --> DDC
        mov     cl,0FFh                         ;override colors
        push    edi
        INVOKE  MakeBrushValid, ADDR MyColors
        pop     edi
        or      eax,eax
        js      create_brush_error              ;jump if error (already logged)
        and     [edi].ddc_pa.pa_ba.ba_fb,not BA_REREALIZE
        jmp     create_brush_exit
ALIGN 4

create_brush_error:

        xor     eax,eax
        stc

create_brush_exit:

        jc      dbdb_exit_error_vect1   ;exit if error

@@:

        mov     esi,cxBorder            ;load commonly used values -- SI and DI
        mov     edi,cyBorder            ;  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     ecx,esi                 ;get horizontal border width
        add     ecx,ecx                 ; * 2
        mov     edx,edi                 ;get vertical border width
        add     edx,edx                 ; * 2
        mov     eax,x2                  ;compute x extent
        sub     eax,x1                  ; 
        cmp     eax,ecx                 ;is x extent less than 2*cxBorder?
        jle     dbdb_single_blt         ;if yes, it's really a single Bitblt
        mov     eax,y2                  ;compute y extent
        sub     eax,y1                  ; 
        cmp     eax,edx                 ;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     eax,x1
        mov     blt_rect.rcl_xLeft,eax
        mov     eax,y1
        mov     blt_rect.rcl_yBottom,eax
        mov     eax,x2
        mov     blt_rect.rcl_xRight,eax
        mov     eax,y2
        mov     blt_rect.rcl_yTop,eax

do_blt:

        xor     eax,eax                 ;generic null-parameter

        INVOKE  Bitblt, hdc,hdc,2,ADDR blt_rect,rop, 0, 0, hddc, FunN

        cmp     eax,1                   ;set carry if AX = 0

dbdb_exit_error_vect1:

        jmp     dbdb_exit
ALIGN 4


dbdb_multiple_blts:

;/*
;** Bottom edge
;*/

        or      edi,edi
        jz      dbdb_chk_right

        mov     eax,x1
        mov     blt_rect.rcl_xLeft,eax
        add     eax,maxwidth                    
        mov     blt_rect.rcl_xRight,eax
        mov     eax,y1
        mov     blt_rect.rcl_yBottom,eax
        add     eax,edi                         
        mov     blt_rect.rcl_yTop,eax

        xor     eax,eax                 ;generic null-parameter

        INVOKE  Bitblt, hdc,hdc,2,ADDR blt_rect,rop, 0, 0, hddc, FunN

        cmp     eax,1                   ;set carry if AX = 0

        jnc     dbdb_chk_right

dbdb_exit_error_vect2:

        jmp     dbdb_exit
ALIGN 4

;/*
;** Right edge
;*/

dbdb_chk_right:

        or      esi,esi
        jz      dbdb_chk_top

        mov     eax,x1
        add     eax,maxwidth                    
        mov     blt_rect.rcl_xLeft,eax
        add     eax,esi                         
        mov     blt_rect.rcl_xRight,eax
        mov     eax,y1
        mov     blt_rect.rcl_yBottom,eax
        add     eax,maxheight                   
        mov     blt_rect.rcl_yTop,eax

        xor     eax,eax                 ;generic null-parameter

        INVOKE  Bitblt, hdc,hdc,2,ADDR blt_rect,rop, 0, 0, hddc, FunN

        cmp     eax,1                   ;set carry if AX = 0

        jb      dbdb_exit_error_vect2

;/*
;** Top edge
;*/

dbdb_chk_top:

        or      edi,edi
        jz      dbdb_chk_left

        mov     eax,x1
        add     eax,esi                         
        mov     blt_rect.rcl_xLeft,eax
        add     eax,maxwidth                    
        mov     blt_rect.rcl_xRight,eax
        mov     eax,y1
        add     eax,maxheight                   
        mov     blt_rect.rcl_yBottom,eax
        add     eax,edi                         
        mov     blt_rect.rcl_yTop,eax

        xor     eax,eax                 ;generic null-parameter

        INVOKE  Bitblt, hdc,hdc,2,ADDR blt_rect,rop, 0, 0, hddc, FunN

        cmp     eax,1                   ;set carry if AX = 0

        jb      dbdb_exit_error_vect2

;/*
;** Left edge
;*/

dbdb_chk_left:

        or      esi,esi
        jz      dbdb_chk_interior

        mov     eax,x1
        mov     blt_rect.rcl_xLeft,eax
        add     eax,esi                         
        mov     blt_rect.rcl_xRight,eax
        mov     eax,y1
        add     eax,edi                         
        mov     blt_rect.rcl_yBottom,eax
        add     eax,maxheight                   
        mov     blt_rect.rcl_yTop,eax

        xor     eax,eax                 ;generic null-parameter

        INVOKE  Bitblt, hdc, hdc, 2, ADDR blt_rect,rop, 0, 0, hddc, FunN

        cmp     eax,1                   ;set carry if AX = 0

        jb      dbdb_exit

;/*
;** Interior
;*/

dbdb_chk_interior:

        test    flCmd,DB_INTERIOR
        jz      dbdb_exit

        mov     eax,x1
        add     eax,esi                         
        mov     blt_rect.rcl_xLeft,eax
        add     eax,maxwidth                    
        sub     eax,esi                         
        mov     blt_rect.rcl_xRight,eax
        mov     eax,y1
        add     eax,edi                         
        mov     blt_rect.rcl_yBottom,eax
        add     eax,maxheight                   
        sub     eax,edi                         
        mov     blt_rect.rcl_yTop,eax

        mov     eax,clrInterior
        mov     ebx,clrBorder
        mov     edi,hddc

create_brushx:

;/*
;** Set foreground color to EAX.
;** Set background color to EBX.
;*/

        mov     MyColors.bba_cSize,12
        mov     MyColors.bba_lColor,eax
        mov     MyColors.bba_lBackColor,ebx

        mov     esi,edi                         ;ESI --> DDC
        mov     cl,0FFh                         ;override colors
        push    edi
        INVOKE  MakeBrushValid, ADDR MyColors
        pop     edi
        or      eax,eax
        js      create_brush_errorx             ;jump if error (already logged)
        and     [edi].ddc_pa.pa_ba.ba_fb,not BA_REREALIZE
        jmp     create_brush_exitx
ALIGN 4

create_brush_errorx:

        xor     eax,eax
        stc

create_brush_exitx:

        jc      dbdb_exit               ;exit now if error

        xor     eax,eax                 ;generic null-parameter

        INVOKE  Bitblt, hdc, hdc, 2, ADDR blt_rect, rop, 0, 0, hddc, FunN

        cmp     eax,1                   ;set carry if AX = 0

dbdb_exit:

        mov     edi,hddc
        or      [edi].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        cmp     eax,1                   ;set carry if AX = 0

db_set_exit_code:

        sbb     eax,eax                 ;AX = 0 (ok), = -1 (error)
        inc     eax                     ;AX = 1 (ok), =  0 (error)

        .errnz  DB_ERROR
        .errnz  DB_SUCCESS - 1

        jmp     db_exit
ALIGN 4

no_bitmap_selected:

        mov     eax,PMERR_BITMAP_NOT_SELECTED

        save_error_code

        xor     eax,eax

db_exit:
        call    leave_driver

db_exit_no_lock:

        fw_zero <ecx>

                RET

DrawBorder      ENDP
end
