;*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.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = WINATTRS.ASM
;*
;* DESCRIPTIVE NAME = Window Attributes functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         03/07/87
;*
;* DESCRIPTION  Window Attributes functions
;*
;* FUNCTIONS    SetStyleRatio
;*              GetStyleRatio
;*              SetLineOrigin
;*              GetLineOrigin
;*              RealizeFont
;*              SetPatternFont
;*              DeviceQueryFontAttributes
;*              GetPairKerningTable
;*              NotifyClipChange
;*              ErasePS
;*              GetCodePage
;*              SetCodePage
;*              DeviceQueryFonts
;*              NotifyTransformChange
;*              Death
;*              Resurrection
;*              GetDCOrigin
;*              DeviceSetDCOrigin
;*              DeviceInvalidateVisRegion
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   07/16/87                      Hock Lee [hockl] Modified for new DDI.
;*   10/05/87                      Hock Lee [hockl] Invalidated ddc_corr_rect
;*                                 when clip region changed.
;*   10/11/87                      Hock Lee [hockl] Changed to black default
;*                                 background color.
;*   10/28/87                      Hock Lee [hockl] Used current background color
;*   11/16/87                      Hock Lee [hockl] rewrote to use new bitblt.
;*   01/19/88                      Martin Picha [martinpi] Changed back to black
;*                                 for erasing screen as per DCR 23428.
;*   03/03/88                      Jeff Parsons [jeffpar] Added restore_textvram
;*                                 call.
;*   04/08/88                      Walt Moore [waltm] Corrected it.  Now logs
;*                                 an error if the high word of the code page
;*                                 is invalid, or no mapping vector is found.
;*                                 Now saves the code page regardless of whether
;*                                 the default font is selected in or not.  Fixed
;*                                 register trashing.
;*   05/13/88                      Hock Lee [hockl] Used SYSCLR_WINDOW for
;*                                 erasing screen as per DCR 23509.
;*   05/16/88                      Hock Lee [hockl] Clipped to all clipping
;*                                 primitives including clip path and user defined
;*                                 clip region!
;*   05/24/88                      Bob Grudem [bobgru] SYSCLR_WINDOW only used
;*                                 if color 0 hasn't been explicitly defined
;*   08/02/88                      Jeff Parsons [jeffpar] Death now relies on the
;*                                 physical_enable routine to perform the
;*                                 restore_textvram operation.  The return code
;*                                 from restore_textvram becomes the return code
;*                                 from physical_enable.
;*   10/08/88             DCR24139 Hock Lee [hockl] Implemented lazy vis region.
;*   10/22/88                      Bob Grudem [bobgru] Now does user bounds
;*                                 collection.
;*   12/12/88             DCR24229 Wes Rupel [wesleyr] Font Caching problems
;*                                 addressed
;*                                 to erase screen instead of black.
;*   11/26/92                      John Batty. Added DCAF changes.
;*   04/02/93               65029  If the DC has a palette loaded then palette
;*                                 index 0 should be used as the fill color.
;*****************************************************************************/

        .386

        OPTION  OLDSTRUCTS

        .MODEL FLAT,SYSCALL
        ASSUME  SS:FLAT, DS:FLAT, CS:FLAT, ES:FLAT

        .xlist

INCL_DDIMISC2           equ     1
INCL_WINSYS             equ     1
INCL_GRE_LINES          equ     1
INCL_GRE_CLIP           equ     1
INCL_GRE_BITMAPS        equ     1
INCL_GRE_FONTS          equ     1
INCL_GRE_DEVMISC        equ     1
INCL_GRE_DEVSUPPORT     equ     1
INCL_DDIBUNDLES         equ     1
INCL_FONTFILEFORMAT     equ     1
INCL_DDIMISC            equ     1
INCL_GPIREGIONS         equ     1

MASM_OUT_OF_MEMORY      equ     1
ifndef MASM_OUT_OF_MEMORY
INCL_GPIBITMAPS         equ     1
else
ROP_PATCOPY     EQU 0000000f0h
endif

INCL_DDICOMFLAGS        equ     1
        include pmgre.inc
DINCL_ENABLE            equ     1
DINCL_PAT_CACHE_DEFS    equ     1
DINCL_BITMAP            equ     1

        include driver.inc
        include extern.inc
        include protos.inc
        include fontseg.inc
        include assert.mac
        include tune.inc
        .list
page
.CODE

;/***************************************************************************
;*
;* FUNCTION NAME = SetStyleRatio
;*
;* DESCRIPTION   = sets the style stepping numbers in the DDC
;*
;*                 Registers Destroyed:
;*                       BX,CX,ES
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;* INPUT         = hdc     :DWORD,
;*                 pbRatio :DWORD,
;*                 hddc    :DWORD,
;*                 FunN    :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = 1
;* RETURN-ERROR  = DX:AX = 0
;*
;**************************************************************************/

ALIGN 4
SetStyleRatio   PROC SYSCALL USES EBX,
        hdc     :DWORD,
        pbRatio :DWORD,
        hddc    :DWORD,
        FunN    :DWORD

        mov     edx,hddc
        INVOKE  enter_driver                     ; pass in edx=hddc
        jc      ssr_exit_no_lock                 ; DX:AX = 0 on error

        mov     ebx,pbRatio
        mov     ax,[ebx]

        mov     ebx,hddc
        mov     word ptr [ebx].DDC.ddc_la.la_bStepX,ax
        .errnz  LINE_ATTRS.la_bStepY - LINE_ATTRS.la_bStepX - 1

        mov     eax,1
        INVOKE  leave_driver
ssr_exit_no_lock:
        ret
SetStyleRatio   ENDP

_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = GetStyleRatio
;*
;* DESCRIPTION   = gets the style stepping numbers from the DDC
;*
;*                 Registers Destroyed:
;*                       BX,CX,ES
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;* INPUT         = hdc     :DWORD,
;*                 lpRatio :DWORD,
;*                 hddc    :DWORD,
;*                 FunN    :DWORD
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = style state (DX = 0, AH = y step, AL = x step)
;* RETURN-ERROR  = DX:AX = -1
;*
;**************************************************************************/

ALIGN 4
GetStyleRatio  PROC SYSCALL USES EBX,
        hdc     :DWORD,
        lpRatio :DWORD,
        hddc    :DWORD,
        FunN    :DWORD

        mov     edx,hddc
        INVOKE  enter_driver
        mov     eax,-1                            ; assume error
        jc      gsr_exit_no_lock

        mov     ebx,hddc
        .errnz  LINE_ATTRS.la_bStepY - LINE_ATTRS.la_bStepX - 1

        mov     ax,word ptr [ebx].DDC.ddc_la.la_bStepX
        mov     ebx,lpRatio
        mov     [ebx],ax

        mov     eax,1
        INVOKE  leave_driver
gsr_exit_no_lock:
        ret
GetStyleRatio  ENDP
;/***************************************************************************
;*
;* FUNCTION NAME = SetLineOrigin
;*
;* DESCRIPTION   = sets the style state in the DDC
;*
;*                 Registers Destroyed:
;*                       BX,CX,ES
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;* INPUT         = lpXY     = new current position
;*                 Style.lo = style info
;*                 Style.hi = first pel info
;* OUTPUT        =
;*
;* RETURN-NORMAL = DX:AX = 1
;* RETURN-ERROR  = DX:AX = 0
;*
;**************************************************************************/

ALIGN 4
SetLineOrigin   PROC SYSCALL USES EBX,
        hdc     :DWORD,
        lpXY    :DWORD,
        Style   :DWORD,
        pddc    :DWORD, ;PDDC
        FunN    :DWORD

LOCAL   dTemp:DWORD

        mov     edx,pddc
        INVOKE  enter_driver
        jc      slo_exit_no_lock                 ; EAX = 0 on error

;/*
;** Clear the COM_AREA and COM_PATH bits from the FunN.hi.  The procedures
;** that call here already have taken the path cookie.
;*/

        mov     ebx,FunN
        and     ebx,NOT (COM_AREA or COM_PATH)
        mov     bx,NGreSetCurrentPosition

        INVOKE  SetCurrentPosition,
                hdc,
                lpXY,
                pddc,
                ebx   ;flags:NGreSetCurrentPosition



        or      eax,eax
        jz      slo_exit

        mov     ebx,pddc
        mov     ax,WORD PTR Style[0]             ; AL = mask pos, AH = error
        xchg    al,ah                             ; AL = error, AH = mask pos
        mov     word ptr [ebx].DDC.ddc_la.la_bError,ax
        .errnz  LINE_ATTRS.la_bMask - LINE_ATTRS.la_bError - 1
        and     [ebx].DDC.ddc_fb,not DDC_FIRST_PEL
        mov     ax,WORD PTR Style[2]
        or      ax,ax
        jz      slo_done
        or      [ebx].DDC.ddc_fb,DDC_FIRST_PEL
slo_done:
        mov     eax,1
slo_exit:
        INVOKE  leave_driver
slo_exit_no_lock:
        ret
SetLineOrigin ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = GetLineOrigin
;*
;* DESCRIPTION   = gets the style state and current position from the DDC
;*
;*                 Registers Destroyed:
;*                       BX,CX,ES
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;* INPUT         =  hdc     :DWORD
;*                  lpXY    :DWORD
;*                  pddc    :DWORD
;*                  FunN    :DWORD
;* OUTPUT        =
;*
;* RETURN-NORMAL = AX = AH = style error, AL = position in mask
;*                 DX = 0 => no first pel, 1 => first pel drawn.
;* RETURN-ERROR  =  DX:AX = -1
;*
;**************************************************************************/

ALIGN 4
GetLineOrigin   PROC SYSCALL USES ESI EDI EBX,
        hdc     :DWORD,
        lpXY    :DWORD,
        pddc    :DWORD,
        FunN    :DWORD


        mov     edx,pddc
        INVOKE  enter_driver
        mov     eax,-1                            ; assume error
        jc      glo_exit_no_lock

        mov     ebx,FunN
        mov     bx,NGreGetCurrentPosition

        INVOKE  GetCurrentPosition,
                hdc,
                lpXY,
                pddc,
                ebx   ;FunN.hi:NGreGetCurrentPosition

        mov     ebx,pddc
        movzx   eax,word ptr [ebx].DDC.ddc_la.la_bError
        .errnz  LINE_ATTRS.la_bMask - LINE_ATTRS.la_bError - 1
        xchg    al,ah                             ; AL = mask pos, AH = error
        test    [ebx].DDC.ddc_fb,DDC_FIRST_PEL   ; DX = first pel info
        jz      @F
        or      eax,010000h
@@:     INVOKE  leave_driver
glo_exit_no_lock:
        ret
GetLineOrigin   ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = RealizeFont
;*
;* DESCRIPTION   = Calls invalidate font cache
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*                 Registers Preserved:
;*                       SI,DI
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = 0
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
RealizeFont PROC SYSCALL USES ESI EDI EBX,
        hdc     :DWORD,
        Command :DWORD,
        LogFont :DWORD,
        EngFont :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

ifdef FONT_CACHING
        INVOKE  enter_driver_sem                 ; don't call back PMWIN!
        jc      rf_exit_no_lock                  ; EAX = 0 on error
        assert  WORD PTR Command[2],E,0
        cmp     WORD PTR Command[0],RF_DELETE_ENGINE_FONT and 0FFFFh
        jne     realizefont_exit
        mov     eax,EngFont
        mov     ebx,pddc
        ddc?    ebx
        INVOKE  invalidate_font_cache
realizefont_exit:
        INVOKE  leave_driver
rf_exit_no_lock:
endif
        mov     eax,0
        ret
RealizeFont ENDP
_TUNE ENDS

;/***************************************************************************
;*
;* FUNCTION NAME = SetPatternFont
;*
;* DESCRIPTION   = Deals with font selection/bitmap bits for patterns.  This
;*                 routine will not be called when the base pattern set is
;*                 selected.
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,DX,ES,FLAGS
;*
;* INPUT         = EBX -> ddc
;*                 EDX -> FOCAFONT, or SURFACE(BITMAP)
;*                 BP  =  attr index for characters
;*                 ESI -> DAREABUNDLE attribute bundle
;*                 PA_BITMAP_SRC and PA_COLOR_TRUTH bits clear in
;*                                        ddc->ddc_pa.pa_ba.ba_fb
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1
;* RETURN-ERROR  = AX = 0
;*                 error logged
;**************************************************************************/

ALIGN 4
SetPatternFont PROC SYSCALL USES ESI EDI ECX

        ddc?    ebx

        mov     eax,edx
;/*
;** Check whether we have a bitmap or a font.
;*/
        lea     esi,[esi].DAREABUNDLE.dabnd_adef
        ;now esi->AREADEFS

        cmp     [eax].SURFACE.sd_usId,SURFACE_IDENT     ;BITMAP ?
        .ERRNZ  SURFACE.sd_usId
        je      spf_bitmap                              ;YES
        jmp     spf_font
ALIGN 4

;/*
;** We have a font.  Set the codepage id, and get the codepage mapping
;** vector if needed.  Set the following flags if needed (* --> always set):
;**
;**       CA_MUST_MAP, CA_ABC_SPACING, CA_CHANGED (*), CA_USER_FONT (*)
;**       BA_REREALZE (*)
;**
;** Return errors in case of:
;**
;**       vector font
;**       huge font (> 64K)
;**       failure reading codepage mapping vector
;**
;** We need to set the flags to make the brush realization code do
;** something.  The PA_BITMAP_SRC and PA_COLOR_TRUTH bits have already
;** been cleared by the caller.
;**
;** We can ignore the offset to the font because we FIREWALLed it to be
;** zero, and all our code would fall apart if it wasn't.
;*/

spf_font:
ifdef FIREWALLS
        mov     [ebx].DDC.ddc_pa.pa_paus,INVALID_ADDRESS
endif

xyzzy   equ     CDEF_STRIKEOUT or CDEF_UNDERSCORE or CDEF_ITALIC or CDEF_BOLD
        test    [esi].AREADEFS.adef_fFlags,xyzzy
        jnz     spf_bad_font_attrs
        mov     esi,[esi].AREADEFS.adef_CodePage
        mov     ecx,[ebx].DDC.ddc_pa.pa_fs

        test    [edx].FOCAFONT.ff_fmMetrics.foca_fsTypeFlags,FM_TYPE_64K
        jnz     spf_huge_font

        test    [edx].FOCAFONT.ff_fmMetrics.foca_fsDefn,FM_DEFN_OUTLINE ; Vector Font
        jnz     spf_bad_font

        cmp     [edx].FOCAFONT.ff_fdDefinitions.fdh_fsChardef,FONTDEFCHAR3
        jne     @F
        or      ecx,CA_ABC_SPACE
@@:

;/*
;** If the font is not in the default code page (850), then no mapping
;** is possible.  If the font is the default code page and a different
;** code page is to be used, get the mapping array.  If getting the
;** mapping array fails, return an error.
;*/

        cmp     [edx].FOCAFONT.ff_fmMetrics.foca_usCodePage,DEFAULTVIOCODEPAGE
        jne     spf_font_done
        cmp     esi,DEFAULTVIOCODEPAGE
        je      spf_font_done
        or      esi,esi                           ;0 = use the default in the font
        je      spf_font_done

;/*
;** Get the mapping vector for this code page.  Don't bother to get access
;** now since the access test has to be made at output time.
;*/

        push    ebx
        push    ecx

        INVOKE  Gre32Entry3,
                esi,            ;CPID
                0,              ; pddc
                NGreQueryCodePageVector

        pop     ecx
        pop     ebx


        mov     [ebx].DDC.ddc_pa.pa_paus,eax
        or      eax,eax
        jz      spf_exit_vect                     ;Error, return 0
        or      ecx,CA_MUST_MAP

spf_font_done:
        or      [ebx].DDC.ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        or      ecx,CA_CHANGED or CA_USER_FONT
        mov     [ebx].DDC.ddc_pa.pa_fs,ecx
        mov     eax,1
spf_exit_vect:
        jmp     spf_exit
ALIGN 4

;/*
;** Log the error and exit
;*/

spf_bad_font_attrs:
        mov     eax,PMERR_INV_PATTERN_SET_ATTR
        jmp     spf_error
ALIGN 4

spf_bad_font:
        mov     eax,PMERR_INV_PATTERN_SET_FONT
        jmp     spf_error
ALIGN 4

spf_huge_font:
        mov     eax,PMERR_HUGE_FONTS_NOT_SUPPORTED
spf_error:
        save_error_code
        mov     eax,0
        jmp     spf_exit
ALIGN 4



;/*
;** We have a bitmap to copy into the pattern attributes structure.
;** Before anything else, check that its handle is valid, that the
;** surface is indeed a bitmap, and that it is neither null nor huge.
;** Of all those checks, only null or huge bitmaps are considered
;** errors to be returned to the caller, the others being internal errors
;** worthy of rips.
;*/

spf_bitmap:
        mov     edi,eax                      ;move bitmap handle into index reg
ifdef FIREWALLS

;/*
;** Make sure the bitmap belongs to us.  If not, the engine is in error
;*/

        cmp     [edi].BITMAP.bm_sd.sd_usId,SURFACE_IDENT
        jne     spf_bad_handle
        test    [edi].BITMAP.bm_sd.sd_fb,SD_DEVICE
        jz      spf_bitmap_handle_ok

spf_bad_handle:
        rip     text,<A bad bitmap handle came into SetPatternFont>
        mov     eax,0
        jmp     spf_exit
ALIGN 4

spf_bitmap_handle_ok:
endif

;/*
;** Make sure that we have a handle to bits if the bitmap is non-null.
;** Exit with an error if the bitmap is null or huge.
;*/

        test    [edi].BITMAP.bm_sd.sd_fb,SD_NONNULL
        jz      spf_bad_font                          ;it's a null bitmap --> no bits
        test    [edi].BITMAP.bm_sd.sd_fb,SD_HUGE
        jnz     spf_bad_font                          ;it's a huge bitmap --> get out
ifdef FIREWALLS
        cmp     [edi].BITMAP.bm_sd.sd_pBits,0   ;must have non-null value
        jnz     spf_selector_ok

        rip     text,<A null bitmap selector came into SetPatternFont>
        mov     eax,0
        jmp     spf_exit
ALIGN 4
spf_selector_ok:
endif


;/*
;** Now that we believe the bitmap is valid, set up a call to copy the
;** bits based on whether it is in color or is monochrome.
;*/

        test    [edi].BITMAP.bm_sd.sd_fb,SD_COLOR
        jz      spf_mono_bitmap

        or      [ebx].DDC.ddc_pa.pa_fb,PA_BITMAP_SRC or PA_COLOR_TRUTH
        mov     esi,[ebx].DDC.ddc_pa.pa_abColor
        mov     cl,0ffh         ;device dependent
        jmp     spf_copy_bitmap_bits
ALIGN 4

spf_mono_bitmap:
        or      [ebx].DDC.ddc_pa.pa_fb,PA_BITMAP_SRC
        lea     esi,[ebx].DDC.ddc_pa.pa_abMask
        mov     cl,1


;/*
;** Set up the registers as follows:
;**
;**       AL     =  number of color planes
;**       AH     =  width in pels
;**       DS:BX --> DDC
;**       CX     =  number of bytes per scan
;**       DX     =  height in scans
;**       DS:SI --> destination of bits
;**       ES:DI --> source bits
;**
;** The width is truncated to 8 pels to make it fit in a byte.  It is only
;** needed to determine if the bitmap fills the entire pattern bits buffer.
;** The access macro is called to prevent GP faults (which will happen
;** without it!!).
;**
;** The brush realization code looks at the BA_REREALIZE and CA_CHANGED
;** bits in the pattern attributes to determine if the brush bits need
;** to be rerealized, so make sure we set these!
;*/

spf_copy_bitmap_bits:
        mov     eax,[edi].BITMAP.bm_sd.sd_cx      ;width of source bitmap
        mov     ah,al                              ;copy_bits... wants width here
        mov     al,cl                              ;  and wants plane cnt here
        mov     ecx,[edi].BITMAP.bm_sd.sd_cbScan  ;get bytes per scan line
        mov     edx,[edi].BITMAP.bm_sd.sd_cy      ;height of source bitmap
        mov     edi,[edi].BITMAP.bm_sd.sd_pBits  ;want EDI ptr to source bits
spf_copy_bits:
        INVOKE  copy_bits_to_pattern
        or      [ebx].DDC.ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        or      [ebx].DDC.ddc_pa.pa_fs,CA_CHANGED
        mov     eax,1

spf_exit:
        ret
SetPatternFont ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = DeviceQueryFontAttributes
;*
;* DESCRIPTION   = This obtains the metrics of the currently selected font.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = lpMetrics
;*                     A long pointer to a font metric block where the information
;*                     is to be returned.
;*                 iMetrics
;*                     The size of the data structure pointer at by lpMetrics
;*                 hdc
;*                     The DC handle.
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX   = 1 if the function executed successfully
;* RETURN-ERROR  = AX      = 0
;*
;*             ---------Pseudo-Code---------
;* short FAR DeviceQueryFontAttributes(iMetrics, lpMetrics, hdc, FunN)
;* {
;*   copy the metrics from current font handle in ddc
;*
;*   Copy(dst,src,nbytes)
;*   Copy(lpMetrics,
;*        &ddc->ddc_char_font->foca_szFamilyname,
;*        min(iMetrics,ddc->ddc_char_font->foca_ulSize));
;*
;*
;*   return success
;* }
;*
;**************************************************************************/


ALIGN 4
DeviceQueryFontAttributes PROC SYSCALL USES ESI EDI EBX,
        hdc             :DWORD,
        iMetrics        :DWORD,
        lpMetrics       :DWORD,
        pddc            :DWORD,
        FunN            :DWORD

LOCAL   tm:FONTMETRICS


        mov     eax,0
        ret

DeviceQueryFontAttributes ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = GetPairKerningTable
;*
;* DESCRIPTION   =
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = hdc             :DWORD
;*                 Count           :DWORD
;*                 lpKernPairs     :DWORD
;*                 pddc            :DWORD
;*                 FunN            :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = 1
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
GetPairKerningTable PROC SYSCALL,
        hdc             :DWORD,
        Count           :DWORD,
        lpKernPairs     :DWORD,
        pddc            :DWORD,
        FunN            :DWORD


        PUSH    EBX
        ddc?    pddc
        mov     esi,pddc
        test    [esi].DDC.ddc_ca.ca_fs,CA_USER_FONT
        jz      gpkt_our_font

        POP     EBX
        mov     esp,ebp
        pop     ebp
        jmp     pfnDefGetPairKerningTable
ALIGN 4


gpkt_our_font:
        mov     eax,0                             ; assume success.
        cmp     WORD PTR Count[2],0
        jge     @F
        mov     eax,PMERR_INV_LENGTH_OR_COUNT
        save_error_code
        mov     eax,-1
@@:
        POP     EBX
        ret
GetPairKerningTable ENDP

_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = NotifyClipChange
;*
;* DESCRIPTION   = This function is called whenever the clip region intersected
;*                 with the visible region is changed. We always store the first
;*                 NUM_CLIP_RECTS in our ddc. If NCC_CLEANDC is set, the ddc is
;*                 no longer dirty.  This is required to implement lazy vis
;*                 region.
;*
;* INPUT         = hdc     :DWORD
;*                 prcl    :DWORD
;*                 crcl    :DWORD
;*                 Flags   :DWORD
;*                 pddc    :DWORD
;*                 FunN    :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

OPTION EPILOGUE:None
ALIGN 4
NotifyClipChange PROC SYSCALL,          ; USES ESI EDI done manually
        hdc     :DWORD,
        prcl    :DWORD,
        crcl    :DWORD,
        Flags   :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

LOCAL   RectBuffer[NUM_CLIP_RECTS]:RECTL
LOCAL   Control:RGNRECT

        push    ebx
        push    esi
        push    edi


        ddc?    pddc,<SURFACE>
        cld
;/*
;** This call only makes sense with the device locked, check it out!
;*/


        mov     edi,pddc                           ; ds:di --> ddc

;/*
;** get number of rectangles in the new region.
;*/

        assert  WORD PTR Flags[2],E,0
        assert  WORD PTR Flags[0],BE,NCC_CLEANDC
        test    WORD PTR Flags[0],NCC_CLEANDC    ; clear dc dirty bit?
        jz      @F                                 ;   no
ifdef FIREWALLS
        INVOKE  check_sem
        or      eax,eax
        jz      ncc_dev_is_locked
        rip     text,<NotifyClipChange called without LockDevice>
ncc_dev_is_locked:
        test    [edi].DDC.ddc_fbAbove,DDC_DIRTY_VISRGN
        jnz     ncc_dev_is_dirty
        DebugMsg <NotifyClipChange: DC is not dirty>
ncc_dev_is_dirty:
endif
        and     [edi].DDC.ddc_fbAbove,NOT DDC_DIRTY_VISRGN
        jmp     ncc_good_exit
ALIGN 4
@@:
        mov     ecx,crcl
        jecxz   got_a_rect                         ; 0 rect
        cmp     ecx,1                              ; 1 rect
        jne     get_all_rects

;/*
;** we have only one rect here which is our lpRect.
;*/

one_rects:

        mov     esi,prcl
got_a_rect:
        jmp     got_rects
ALIGN 4

;/*
;** we have more than one and at most NUM_CLIP_RECTS, get them all.
;*/

get_all_rects:

;/*
;** Get clip rectangles
;*/

        mov     eax,0
        mov     Control.rgnrc_ircStart,1
        mov     Control.rgnrc_crcReturned,eax
        mov     Control.rgnrc_crc,NUM_CLIP_RECTS
        mov     Control.rgnrc_ulDirection,RECTDIR_LFRT_BOTTOP

        INVOKE  PFNDefGetClipRects PTR pfnDefGetClipRects,
                hdc,
                0,                      ;lp_rect
                ADDR Control,           ;lp_ctrl
                ADDR RectBuffer,        ;lp_list
                0,                      ;pddcNull
                NGreGetClipRects        ;NGre...

ifdef FIREWALLS
        or      eax,eax
        jnz     get_clip_rects_ok
        rip     text,<GetClipRects returns error>
get_clip_rects_ok:
endif

        mov     ecx,crcl                          ;CX = num of clip rects

ifdef FIREWALLS
        cmp     ecx,Control.rgnrc_crcReturned
        je      clip_rects_ok
        cmp     ecx,NUM_CLIP_RECTS
        ja      clip_rects_ok
        rip     text,<GetClipRects returns error>
clip_rects_ok:
endif

        lea     esi,RectBuffer

;/*
;** ds:si = Clip Rects
;** es:di = ddc
;** cx = n clip rects
;** ddc_ncliprects is the number of clip rects (can be more than NUM_CLIP_RECTS)
;*/

got_rects:
        mov     eax,ecx
        add     edi,DDC.ddc_crcsClip
        stosd           ;eax=>[edi]
        jecxz   all_saved
        cmp     ecx,NUM_CLIP_RECTS
        jbe     save_rects                        ; 1 <= ecx <= NUM_CLIP_RECTS

;/*
;** we have too many rects here, save only the first NUM_CLIP_RECTS rects.
;*/

        mov     ecx,NUM_CLIP_RECTS               ; > NUM_CLIP_RECTS

;/*
;** store the clip rects
;*/

save_rects:
        mov     edi,[edi-DDC.ddc_crcsClip-4].DDC.ddc_prddc
        rddc?   edi
        add     edi,RDDC.rddc_arcsClip  ; SEL: these are RECTL'S NOW
        shl     ecx,2                             ; 4 sides per rectangle

save_rects_loop:
        rep     movsd
        .ERRNZ  ((4*SIZEOF DWORD) - (SIZEOF RDDC.rddc_arcsClip))


all_saved:
        mov     edi,pddc
        mov     al,[edi].DDC.ddc_fb
        or      al,DDC_CLIP_NOTIFY               ;Have been notified
        and     al,not DDC_VISIBLE               ;Assume nothing shows
        cmp     [edi].DDC.ddc_crcsClip,1
        jb      ncc_1701                          ;I'm a trekie
        test    al,DDC_PRESENT                    ;Do we have a surface?
        jz      ncc_1701                          ;  No, so it cannot be visible
        mov     ebx,[edi].DDC.ddc_npsd           ;  Yes, see if it is null
        test    [ebx].SURFACE.sd_fb,SD_NONNULL
        jz      ncc_1701
        or      al,DDC_VISIBLE
ncc_1701:
        mov     [edi].DDC.ddc_fb,al
ncc_good_exit:
        mov     eax,1

        pop     edi
        pop     esi
        pop     ebx
        mov     esp,ebp
        pop     ebp
        jmp     pfnDefNotifyClipChange
ALIGN 4
NotifyClipChange ENDP
_TUNE ENDS
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF

;/***************************************************************************
;*
;* FUNCTION NAME = ErasePS
;*
;* DESCRIPTION   = Erases the output media associated with the specified DC
;*                 handle to the color defined by SYSCLR_WINDOW.
;*
;*                 This operation is unaffected by the draw process control
;*                 bit and is subject to all clipping (i.e. clip path, viewing
;*                 limits, graphics field, clip region and vis region).
;*
;*                 In order to erase a media subjected only to environmental
;*                 clipping (i.e. clipping that is independent of any graphics
;*                 segments), the clip path and viewing limits must be reset
;*                 explicitly before the erase is issued.
;*
;* INPUT         =  hdc     :DWORD
;*                  pddc    :DWORD
;*                  FunN    :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1
;* RETURN-ERROR  = AX = 0
;*
;*                  -----------Pseudo-Code------
;* BOOL FAR PASCAL ErasePS(hdc,FunN)
;* {
;*   GreBitblt(0,2,{MINSHORT,MINSHORT,MAXSHORT,MAXSHORT},BLACKNESS,BLTMODE_ATTRS_PRES,
;*               {12,SYSCLR_WINDOW,SYSCLR_WINDOW},hdc);
;*
;*   return 1;
;* }
;*
;**************************************************************************/

ALIGN 4
ErasePS PROC SYSCALL USES ESI EDI EBX,
        hdc     :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

LOCAL   old_pa_fs:DWORD
LOCAL   old_pa_ch:BYTE
LOCAL   old_pa_fb:BYTE
LOCAL   old_bits[(SIZE_PATTERN*2)]:BYTE  
LOCAL   old_pColor:DWORD                                  
        DWORD_DIVISOR    EQU     4                        
        .ERRNZ  (SIZE_PATTERN * 2) AND (DWORD_DIVISOR-1)  

        cld
        mov     esi,pddc                          ; SI = ddc
        mov     edx,esi
        ENTER_DRIVER2
        jc      eps_exit_no_lock                 ; DX:AX = 0 on error

        no_path_area    erase_ps_exit,both

;/*
;** Save and set some goodies in ddc for BitBlt
;*/

        mov     al,PATSYM_SOLID                   ; set code point to solid
        xchg    al,[esi].DDC.ddc_pa.pa_ch
        xchg    al,old_pa_ch

        mov     eax,CA_CHANGED                    ; code point has changed
        xchg    eax,[esi].DDC.ddc_pa.pa_fs
        xchg    eax,old_pa_fs

        xor     al,al                             ; walt says so
        xchg    al,[esi].DDC.ddc_pa.pa_fb
        mov     old_pa_fb,al

;/*
;** If the pattern came from a bitmap, then we must save the bits
;** before calling Bitblt.  The change of codepoint to PATSYM_SOLID
;** will cause the color bits to be updated (i.e. the whole purpose of
;** if anyway).  Our only record of any bitmap bits set into a pattern
;** are the pattern bits themselves, so save 'em.
;*/

        test    al,PA_BITMAP_SRC
        jz      eps_pattern_bits_restorable

        test    al,PA_COLOR_TRUTH
        jz      eps_dont_save_abcolor
        INVOKE  alloc_brush
        or      eax,eax
        jnz     alloc_ok
        mov     eax,PMERR_INSUFFICIENT_MEMORY
        save_error_code
        xor     eax,eax
        jmp     erase_ps_exit
alloc_ok:
        mov     old_pColor,eax
        mov     edi,eax
        push    esi
        mov     esi,[esi].DDC.ddc_pa.pa_abColor
        INVOKE  copy_brush
        pop     esi

eps_dont_save_abcolor:
        mov     ecx,SIZE_PATTERN/DWORD_DIVISOR
eps_have_source:
        push    esi                               ;save pointer to DDC
        lea     esi,[esi].DDC.ddc_pa.pa_abMask  ;store source address in SI
        lea     edi,old_bits

        rep     movsd
        .ERRNZ  DWORD_DIVISOR - 4

        pop     esi                               ;restore pointer to DDC

eps_pattern_bits_restorable:

;/*
;** Clear screen to SYSCLR_WINDOW
;*/
        mov     edi,esp                           ; DI = old SP


        mov     eax,MAXSHORT
        push    eax                               ; TargY2
        push    eax                               ; TargX2
        mov     eax,0
        push    eax                               ; TargY1
        push    eax                               ; TargX1
        mov     ecx,esp                           ; BitBltParm in reverse stack order

;/*
;** lpAttrs
;**
;** If we are in indexed color mode and color 0 has been explicitly
;** redefined, then we will use color 0.           Otherwise, we will use
;** SYSCLR_WINDOW  (If color 0 hasn't been redefined, then it is
;** SYSCLR_WINDOW;  and, in RGB mode, color 0 cannot be redefined).
;** Defect 65029 - If the DC has a palette loaded then palette
;** index 0 should be used as the fill color.
;*/

        mov     eax,SYSCLR_WINDOW
        test    [esi].DDC.ddc_fbClrTbl,DDC_USER_CLR_0
        jnz     @F                                      ;          
        test    [esi].DDC.ddc_fbClrTbl,DDC_PALETTE      ;          
        jz      UseSYSCLR_WINDOW                        ;          
@@:                                                     ;          
        mov     eax,0                                   ;          
UseSYSCLR_WINDOW:                                       ;          
        push    eax                               ; background color
        push    eax                               ; foreground color
        push    12
        mov     ebx,esp                           ; Attrs in reverse order


        mov     edx,FunN
ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** We need to allow the DRAW bit and both the                       ;          
;** USER and SCREEN bound bits through to Bitblt.                    ;          
;** We do not accumulate GPI bounds for Erase PS.                    ;          
;*/                                                                  ;          
        and     edx,COM_DRAW or COM_ALT_BOUND or COM_SCR_BOUND       ;          
else  ; DCAF                                                         ;          
        and     edx,COM_DRAW or COM_ALT_BOUND
endif ; DCAF                                                         ;          
        or      edx,COM_TRANSFORM                ;The points are in device coords
        mov     dx,NGreBitblt

        INVOKE  Bitblt,
                hdc,                    ;hdc
                0,                      ;hdcSrc
                2,                      ;cPoints
                ecx,                    ;paptPoints pointer to array of (x,y) pairs
                ROP_PATCOPY,            ;lRop
                BLTMODE_ATTRS_PRES,     ;flOptions
                ebx,                    ;pBattrs
                pddc,                   ;pddc
                edx                     ;lFunction



        mov     esp,edi                           ; restore SP

;/*
;** Restore ddc goodies, do not destory EAX
;*/
        mov     bl,old_pa_ch
        mov     [esi].DDC.ddc_pa.pa_ch,bl

        mov     ebx,old_pa_fs
        or      ebx,CA_CHANGED                    ; code point has changed
        mov     [esi].DDC.ddc_pa.pa_fs,ebx

        mov     bl,old_pa_fb
        or      bl,BA_REREALIZE                  ; must redo pattern before using it
        mov     [esi].DDC.ddc_pa.pa_fb,bl

;/*
;** If we had to save the bits coming in, we'd better restore them
;** going out.
;*/

        test    bl,PA_BITMAP_SRC
        jz      erase_ps_exit

        test    bl,PA_COLOR_TRUTH
        jz      eps_dont_rstr_abcolor

        mov     esi,old_pColor
        mov     edi,[esi].DDC.ddc_pa.pa_abColor
        INVOKE  copy_brush

        mov     eax,esi
        INVOKE  free_brush

eps_dont_rstr_abcolor:
        mov     ecx,(SIZE_PATTERN)/DWORD_DIVISOR
        lea     edi,[esi].DDC.ddc_pa.pa_abMask


eps_have_dest:
        lea     esi,old_bits
        rep     movsd
        .ERRNZ  DWORD_DIVISOR - 4

erase_ps_exit:
        assert  eax,BE,1
        INVOKE  leave_driver
eps_exit_no_lock:
        ret
ErasePS ENDP
_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = GetCodePage
;*
;* DESCRIPTION   = This obtains the current code page.
;*
;* INPUT         = hdc     :DWORD
;*                 pddc    :DWORD
;*                 FunN    :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = current code page
;* RETURN-ERROR  = DX:AX = 0
;*
;*                     --------Pseudo-Code-----
;* LONG FAR PASCAL GetCodePage(hdc,FunN)
;* {
;*   return ddc_code_page;
;* }
;*
;**************************************************************************/

ALIGN 4
GetCodePage PROC SYSCALL USES EBX,
        hdc     :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

        mov     ebx,pddc
        mov     eax,[ebx].DDC.ddc_ca.ca_idCodePage
        fw_zero <ecx>
        ret
GetCodePage ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = SetCodePage
;*
;* DESCRIPTION   = This sets the code page to be used for the default font.
;*
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*
;* INPUT         = hdc             :DWORD
;*                 CodePage        :DWORD
;*                 pddc            :DWORD
;*                 FunN            :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1
;* RETURN-ERROR  = AX = 0
;*
;**************************************************************************/

ALIGN 4
SetCodePage PROC SYSCALL USES EBX,
        hdc             :DWORD,
        CodePage        :DWORD,
        pddc            :DWORD,
        FunN            :DWORD

        ddc?    pddc
        mov     edx,pddc
        INVOKE  enter_driver
        jc      scp_exit_no_lock                 ; DX:AX = 0 on error
        no_path_area    scp_exit,area

;/*
;** If the code page isn't the default code page, then make the call to
;** get the vector just to see if it is there.  If it is, then this is
;** a valid code page.  If not, its an error.  If it is a valid code
;** page, then if the default font is in use, we'll have to use it.
;**
;** The Engine (if written correctly) will validate the high word of
;** the code page and log any invalid code page error.
;*/

        mov     eax,INVALID_ADDRESS
        cmp     CodePage,DEFAULTVIOCODEPAGE
        je      scp_have_vector

scp_get_vector:

        INVOKE  Gre32Entry3,
                CodePage,       ;CPID
                0,              ;pddc
                NGreQueryCodePageVector
;/*
;** returns GPI_ERROR = 0 if error
;*/

        .ERRNZ  GPI_ERROR
        or      eax,eax
        jz      scp_exit                          ;Error logged by QueryCodePageVector

;/*
;** The code page is valid.  Save it.  If the default font is in use,
;** then we must use this vector for translation.
;*/

scp_have_vector:
        mov     ebx,pddc
        mov     ecx,CodePage
        mov     [ebx].DDC.ddc_ca.ca_idCodePage,ecx
        test    [ebx].DDC.ddc_ca.ca_fs,CA_USER_FONT
        jnz     scp_good_exit                     ;User font, don't use vector yet
        mov     [ebx].DDC.ddc_ca.ca_paus,eax
        mov     eax,[ebx].DDC.ddc_ca.ca_fs
        or      eax,CA_CHANGED or CA_MUST_MAP
        cmp     ecx,DEFAULTVIOCODEPAGE
        jne     scp_have_flags
        and     eax,NOT CA_MUST_MAP
scp_have_flags:
        mov     [ebx].DDC.ddc_ca.ca_fs,eax

scp_good_exit:
        mov     eax,1
scp_exit:
        INVOKE  leave_driver
scp_exit_no_lock:
        fw_zero <ecx>
        ret
SetCodePage ENDP
_TUNE ENDS
;/***************************************************************************
;*
;* FUNCTION NAME = DeviceQueryFonts
;*
;* DESCRIPTION   = Enumerates the fonts on a device. For each font on the device
;*                 the function returns the metrics of the the font
;*
;* INPUT         = lpFilter
;*                      The facename to match
;*
;*                 iMetrics
;*                     The number of bytes of each metrics structure in the
;*                     lpMetrics array.
;*
;*                 lpMetrics
;*                      A long pointer to an array of textmetric records
;*
;*                 lpiFonts
;*                      The number of fonts for which the application wants
;*                      metrics. The number the application received is returned
;*                      here.
;*                 All sizes are returned in world coordinates
;*                 In future we are going to have to back transform
;*                 the metrics of the font
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = ax =  The number of fonts the appl didn't get. This allows the
;*                       appl to find out how many fonts there are by setting
;*                       iFonts = 0.
;* RETURN-ERROR  = AX = -1
;*
;**************************************************************************/

ALIGN 4
DeviceQueryFonts PROC SYSCALL USES ESI EDI EBX,
        hdc             :DWORD,
        Options         :DWORD,
        lpFilter        :DWORD,
        lpMetrics       :DWORD,
        iMetrics        :DWORD,
        lpiFonts        :DWORD,
        pddc            :DWORD,
        FunN            :DWORD
LOCAL   tm:FONTMETRICS

        cld
        INVOKE  enter_driver_sem                 ; Do not do a VisRegionCallBack
        mov     eax,-1                            ; assume error
        jc      dgf_exit_no_lock

;/*
;** We don't have any fonts that we manage
;** so return 0 fonts left and 0 fonts returned
;*/

        mov     edi,lpiFonts
        mov     eax,0
        stosd

dqf_exit:
        INVOKE  leave_driver
dgf_exit_no_lock:
        fw_zero <ecx>
        ret
DeviceQueryFonts ENDP

_TUNE2 SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = NotifyTransformChange
;*
;* DESCRIPTION   =
;*         This function is called whenever the transform change.
;*         It must be fully recoverable so that it can back out all changes
;*         if it fails.  To be recoverable, every hooked function in the chain
;*         must do exactly the following:
;*
;*            1. Perform all necessary computation required by the new transform;
;*            2. If it fails for any reason, restore to old state and return
;*               error;
;*            3. Otherwise, make sure it can still recover to original state
;*               if the next function in chain fails;
;*            4. Call the next funcion in chain;
;*            5. If the call fails, goto step 2;
;*            6. Otherwise, commit all necessary changes and return success.
;*
;*          Registers Destroyed:
;*                AX,BX,CX,DX,ES
;*
;* INPUT         = hdc     :DWORD
;*                 Flags   :DWORD
;*                 lpData  :PULONG
;*                 pddc    :PDDC
;*                 FunN    :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1 for success
;* RETURN-ERROR  = EAX = 0
;*
;**************************************************************************/

ALIGN 4
NotifyTransformChange PROC SYSCALL USES ESI EDI EBX,
        hdc     :DWORD,
        Flags   :DWORD,
        lpData  :PULONG,
        pddc    :PDDC,
        FunN    :DWORD

LOCAL   new_ddc_ptsCurPos:POINTL
LOCAL   ptsPatOrg:POINTL
LOCAL   old_ddc_fb:BYTE

        cld
        mov     esi,pddc                          ; ds:si --> ddc
        mov     edx,esi
        INVOKE  enter_driver
        jc      ntc_exit_no_lock                 ; DX:AX = 0 on error

;/*
;** we can skip all these if we are changing transform from unit to unit,
;** i.e. no transform change!!!
;*/

        mov     al,[esi].DDC.ddc_fb
        mov     old_ddc_fb,al
        or      al,DDC_UNIT_XFORM
        cmp     Flags,MATRIX_UNITS+MATRIX_SIMPLE
        je      @F
        and     al,not DDC_UNIT_XFORM
@@:
        mov     [esi].DDC.ddc_fb,al 
        or      [esi].DDC.ddc_ca.ca_ba.ba_fb,BA_XFORM_CHANGE or BA_REREALIZE
        or      [esi].DDC.ddc_pa.pa_ba.ba_fb,BA_XFORM_CHANGE or BA_REREALIZE
        or      [esi].DDC.ddc_la.la_ba.ba_fb,BA_XFORM_CHANGE or BA_REREALIZE
        or      [esi].DDC.ddc_ia.ia_ba.ba_fb,BA_XFORM_CHANGE or BA_REREALIZE
        or      [esi].DDC.ddc_ma.ma_ba.ba_fb,BA_XFORM_CHANGE or BA_REREALIZE

;/*
;** update screen position
;** world position remain the same
;*/

update_screen_position:
        mov     ebx,[esi].DDC.ddc_prddc
        push    [ebx].RDDC.rddc_ptlWorldPos.ptl_y
        push    [ebx].RDDC.rddc_ptlWorldPos.ptl_x
        mov     ebx,esp

        ; ESI = DDC
        INVOKE  convert_world_screen,
                ebx,    ; lp_point
                1


        pop     new_ddc_ptsCurPos.ptl_x
        pop     new_ddc_ptsCurPos.ptl_y
        assert  eax,E,ecx
        jecxz   ntc_restore     ; back up all changes

;/*
;** make sure pick window is valid in device coordinates
;*/
        INVOKE  recalc_correlate_rect
        jecxz   ntc_restore                       ; back up all changes

;/*
;** make sure pattern origin is valid in new coordinate space
;*/

        mov     eax,[esi].DDC.ddc_pa.pa_ptsOrg.ptl_x
        mov     ptsPatOrg.ptl_x,eax
        mov     eax,[esi].DDC.ddc_pa.pa_ptsOrg.ptl_y
        mov     ptsPatOrg.ptl_y,eax
        INVOKE  xform_pattern_origin
        or      eax,eax
        jz      ntc_restore_pattern

;/*
;** we call the next in chain only if we are sure we can do this transform
;*/

        INVOKE  PFNDefNotifyTransformChange PTR pfnDefNotifyTransformChange,
                hdc,
                Flags,
                lpData,
                pddc,
                FunN

        or      eax,eax
        jnz     ntc_doit

;/*
;** something went wrong, we have to back up all changes
;*/

ntc_restore_pattern:
        mov     eax,ptsPatOrg.ptl_x
        mov     [esi].DDC.ddc_pa.pa_ptsOrg.ptl_x,eax
        mov     eax,ptsPatOrg.ptl_y
        mov     [esi].DDC.ddc_pa.pa_ptsOrg.ptl_y,eax

ntc_restore:
        ddc?    esi
        mov     al,old_ddc_fb
        or      al,DDC_CORR_INV                   ; invalidate ddc_corr_rect
        mov     [esi].DDC.ddc_fb,al               ; restore flags
        mov     eax,0
        jmp     ntc_exit
ALIGN 4

;/*
;** everything is golden, complete the call
;*/

ntc_doit:
        or      [esi].DDC.ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        mov     esi,[esi].DDC.ddc_prddc
        rddc?   esi
        lea     edi,[esi].RDDC.rddc_ptsCurPos
        lea     esi,new_ddc_ptsCurPos
        movsd
        movsd
        .errnz  (sizeof POINTL)-8
        assert  eax,E,1

ntc_exit:
        INVOKE  leave_driver
ntc_exit_no_lock:
        fw_zero <ecx>
        ret
NotifyTransformChange ENDP
_TUNE2 ENDS
;/***************************************************************************
;*
;* FUNCTION NAME = Death
;*
;* DESCRIPTION   = This function is used to provide notification of a screen group
;*                 switch into another screen group.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 for success
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
Death PROC SYSCALL USES EBX,
        hdc     :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

ifdef FIREWALLS
        cmp     fGrimReaper,0
        je      not_dead_yet
        rip     text,<Death warmed over - Cannot kill me twice>
not_dead_yet:
endif
        INVOKE  physical_disable

        mov     eax,1
        fw_zero <ecx>
        ret
Death ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = Resurrection
;*
;* DESCRIPTION   = This function is used to provide notification of a screen group
;*                 switch back from another screen group.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 if VRAM completely restored, 2 if not.
;* RETURN-ERROR  = AX = 0 unrecoverable error
;*
;*                      -------Pseudo-Code-----
;* BOOL FAR PASCAL Resurrection(hdc,cbDirty,pbDirty,FunN)
;* {
;*   LockDevice();       // prevent screen I/O
;*   setup screen hardware;
;*   DeathFlag = 0;
;*   UnlockDevice();
;*   return 1;
;* }
;**************************************************************************/

ALIGN 4
Resurrection PROC SYSCALL USES EBX,
        hdc     :DWORD,
        cbDirty :DWORD,
        pbDirty :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

ifdef DCAF                                                           ;          
LOCAL   rclSinglePel : RECTL                                         ;          
endif ;DCAF                                                          ;          

        mov     edx,pddc
        INVOKE  enter_driver
        jnc     @F

;/*
;** cannot recover from here!
;*/

        rip     text,<Resurrection: Oops! you live once only>
        mov     eax,PMERR_INV_HDC
        save_unrecoverable_code                   ; die in peace
        mov     eax,0
        jmp     res_exit_no_lock
ALIGN 4
@@:

;/*
;** Invalidate any pattern cache
;*/

        mov     idBrushCache,PAT_CACHE_INVALID

;/*
;** initialize screen hardware
;*/

        INVOKE  physical_enable,
                0,
                cbDirty
                                                  ;returns 0 if VRAM was restored
        push    eax                               ;save return code

ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** If the VRAM was successfully restored (EAX=0) then the DCAF      ;          
;** screen bounds can remain as they are (we don't have to           ;          
;** retransmit the whole screen).                                    ;          
;** However, the DCAF controller does not display the PM session     ;          
;** until it receives some PM data. Therefore in this case we        ;          
;** add a single pel to the active SCAs to ensure that some data is  ;          
;** sent.                                                            ;          
;**                                                                  ;          
;** If the VRAM has not been restored (EAX=1) then we know the       ;          
;** whole screen is about to be redrawn, so we set the DCAF          ;          
;** screen bounds NOW to be a single rectangle the size of the       ;          
;** screen. This improves redraw performance.                        ;          
;*/                                                                  ;          
        or      eax,eax                                              ;          
        jz      set_one_pel                                          ;          
        INVOKE SetFullScreenBounds                                   ;          
        jmp     short dcaf_bounds_set                                ;          
                                                                     ;          
set_one_pel:                                                         ;          
        xor     eax,eax          ; A zero will be useful             ;          
        mov     rclSinglePel.rcl_xLeft,eax                           ;          
        mov     rclSinglePel.rcl_yBottom,eax                         ;          
        mov     rclSinglePel.rcl_xRight,eax                          ;          
        mov     rclSinglePel.rcl_yTop,eax                            ;          
                                                                     ;          
        INVOKE  AccumulateScreenBound, ADDR rclSinglePel             ;          
dcaf_bounds_set:                                                     ;          
endif ;DCAF                                                          ;          

        pop     eax                               ;get code from restore_textvram
        inc     eax                               ;return either 1 or 2
                                                  ;(2 implies we couldn't restore VRAM)
resurrect_exit:
        INVOKE  leave_driver
res_exit_no_lock:
        fw_zero <ecx>
        ret
Resurrection ENDP
_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = GetDCOrigin
;*
;* DESCRIPTION   = Copies the DC origin from the DC to the given location.
;*
;* INPUT         = DWORD hdc
;*                 DWORD *lpXY
;*                 DWORD pddc
;*                 DWORD FunN
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

ALIGN 4
GetDCOrigin PROC SYSCALL USES ESI EDI EBX,
        hdc     :DWORD,
        lpXY    :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

        ddc?    pddc
        mov     esi,pddc
        mov     edx,esi
        INVOKE  enter_driver
        jc      gdco_exit_no_lock                ; DX:AX = 0 on error

        mov     edi,lpXY                         ; point ES:DI to X and Y values
        mov     esi,[esi].DDC.ddc_prddc
        lea     esi,[esi].RDDC.rddc_ptsOrg
        .errnz  SIZE POINTL - 8
        cld
        movsd
        movsd
        mov     eax,1
        INVOKE  leave_driver
gdco_exit_no_lock:
        fw_zero <ecx>
        ret
GetDCOrigin ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSetDCOrigin
;*
;* DESCRIPTION   = Sets the DDC origin of the specified device context.  Note that
;*                 the device origin is 0,0 when the device context is created.
;*
;*                 Note: DC origins at all saved levels of the DDC will be changed
;*                       at restore time.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = hdc     :DWORD
;*                 lpXY    :DWORD
;*                 pddc    :DWORD
;*                 FunN    :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 for success
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
DeviceSetDCOrigin PROC SYSCALL USES ESI EBX,
        hdc     :DWORD,
        lpXY    :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

        ddc?    pddc

;/*
;** This call only makes sense with the device locked, check it out!
;*/

        mov     ebx,lpXY

        mov     eax,[ebx].POINTL.ptl_x
ifdef FIREWALLS
        cwd     ;doesn't change eax
        cmp     dx,WORD PTR [ebx].POINTL.ptl_x[2]
        je      @F
        rip     text,<SetDCOrigin - invalid integer>
@@:
endif

        xchg    ecx,eax
        mov     eax,[ebx].POINTL.ptl_y
ifdef FIREWALLS
        cwd
        cmp     dx,WORD PTR [ebx].POINTL.ptl_y[2]
        je      @F
        rip     text,<SetDCOrigin - invalid integer>
@@:
endif
        mov     ebx,pddc

;/*
;** Put new X origin into the ddc.  If delta X mod SIZE_PATTERN is 0,
;** the the pattern doesn't have to be rerealized.
;*/

        mov     esi,[ebx].DDC.ddc_prddc
        rddc?   esi
        xchg    ecx,[esi].RDDC.rddc_ptsOrg.ptl_x
        sub     ecx,[esi].RDDC.rddc_ptsOrg.ptl_x
        jz      sdco_done_x
        sub     [esi].RDDC.rddc_ptsCurPos.ptl_x,ecx  
        test    ecx,SIZE_PATTERN-1               ;Test modulo pattern size
        jz      sdco_done_x
        sub     [ebx].DDC.ddc_pa.pa_ptsOrg.ptl_x,ecx
        or      [ebx].DDC.ddc_pa.pa_ba.ba_fb,BA_REREALIZE
sdco_done_x:

;/*
;** The Y brush origin is always handled at output time, so we don't have
;** to realize the pattern.
;*/

        rddc?   esi
        xchg    eax,[esi].RDDC.rddc_ptsOrg.ptl_y
        sub     eax,[esi].RDDC.rddc_ptsOrg.ptl_y
        sub     [esi].RDDC.rddc_ptsCurPos.ptl_y,eax     
        sub     [ebx].DDC.ddc_pa.pa_ptsOrg.ptl_y,eax

;/*
;** invalidate ddc_corr_rect
;*/

        or      [ebx].DDC.ddc_fb,DDC_CORR_INV
        mov     eax,1
        fw_zero <ecx>
        ret
DeviceSetDCOrigin ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceInvalidateVisRegion
;*
;* DESCRIPTION   = When the display driver is entered for any calls requiring a
;*                 valid  total clipping it must call pmwin to update vis region
;*                 if the DC is dirty.
;*                 This enables lazy vis region calculations in PM.
;*
;*                 This function must be called in a Lock/UnlockDevice bracket.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES
;*
;* INPUT         = lprghdc is a long pointer to an array of structures of the
;*                 form.
;*                         typedef struct {
;*                             HDC   hDC;   ; a handle to a device context
;*                             ULONG pddc;  ; unused by pmwin, filled in by engine.
;*                         } DC_BLOCK;
;*
;*                 Count is the number of elements in the array
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 for success
;* RETURN-ERROR  = NONE
;*
;*                    ---------Pseudo-Code------
;* DeviceInvalidateVisRegion(hdc, count, lprghdc, pddc, FunN)
;* {
;*     /* must be serialized in pmwin */
;*     SemCheck(Device);
;*     for ( ; count; count--)
;*     {
;*       if (lprghdc[count].pddc.hi == HDDC_IDENT &&
;*           lprghdc[count].pddc->ddc_ident == DC_IDENTIFIER)
;*            lprghdc[count].pddc->ddc_flags |= DDC_DIRTY;
;*     }
;* }
;*
;**************************************************************************/

ALIGN 4
DeviceInvalidateVisRegion PROC SYSCALL USES ESI EDI EBX,
        hdc     :DWORD,
        Count   :DWORD,
        lprghdc :DWORD,
        pddc    :DWORD,
        FunN    :DWORD

;/*
;** This call only makes sense with the device locked, check it out!
;*/

ifdef FIREWALLS
        INVOKE  check_sem
        or      eax,eax
        jz      @F
        rip     text,<DeviceInvalidateVisRegion called without LockDevice>
@@:
endif

        mov     ecx,Count
        jecxz   divr_good_exit                     ; CX = count

        mov     edi,lprghdc                        ; ES:DI = lprghdc

divr_ddc_loop:

        cmp     [edi].DC_BLOCK.ivr_hddc,0
        je      divr_next_ddc

;/*
;** check out the ddc identifier
;*/

        mov     ebx,[edi].DC_BLOCK.ivr_hddc       ; BX = pddc
        cmp     [ebx].DDC.ddc_usId,DDC_IDENT
        jnz     divr_next_ddc                      ; not a DDC

;/*
;** mark the ddc as dirty
;*/

        or      [ebx].DDC.ddc_fbAbove,DDC_DIRTY_VISRGN

divr_next_ddc:
        add     edi,SIZE DC_BLOCK
        loop    divr_ddc_loop                      ; do next ddc

divr_good_exit:
        mov     eax,1
        ret
DeviceInvalidateVisRegion ENDP
_TUNE ENDS
        end
