;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/

        PAGE     55,132

        TITLE    AVIO Support Functions
        SUBTITLE Header

;/*****************************************************************************
;*
;* SOURCE FILE NAME = CELLBLT.ASM
;*
;* DESCRIPTIVE NAME = Implementation of the driver interfaces for VIO/AVIO.
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/14/91
;*
;* DESCRIPTION
;*
;*  This module contains the entry points for the device driver code which
;*  supports Vio and AVio presentation spaces.  It invokes routines in the
;*  CellScan module which in turn invokes routines in the CellDraw module.
;*
;*
;*  All the character drawing work is funneled through the CharRect routine.
;*  CharRect establishes the stack frame used by the drawing and scanning
;*  routines, maps an LVB character rectangle into a pixel rectangle in
;*  screen coordinates, and then invokes DrawImageRect by way of
;*  enumerate_clip_rects.  DrawImageRect analyzes the clip rectangle it
;*  receives into a number of drawing regions characterized by the kinds of
;*  clipping required, and invokes the scanning routines in CELLSCAN.ASM to
;*  scan the LVB cells in those regions and get them drawn.  The scanning
;*  routines push on the stack a pseudocode description of the drawing
;*  actions necessary to materialize a portion of the image, and then invoke
;*  the drawing functions of CELLDRAW.ASM to interpret that pseudocode.
;*
;*
;* FUNCTIONS   CheckCodePage
;*             InvertTextCursor
;*             InvertSplitCursor
;*             CharStr
;*             UpdateCursor
;*             DeviceSetAVIOFont2
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   11/14/91                     KEZ  Original
;*   01/09/91                     added CLR2, only defined for non CGA
;*   07/27/93              70227  Unable to handle user defined fonts properly
;*****************************************************************************/


        .386P
        .MODEL FLAT,SYSCALL

        OPTION OLDSTRUCTS

;/*
;**Included files
;*/

INCL_DDICOMFLAGS    EQU 1
INCL_DOSERRORS      EQU 1
INCL_FONTFILEFORMAT EQU 1
INCL_GPIPRIMITIVES  EQU 1
INCL_GPIREGIONS     EQU 1
INCL_GRE_DCS        EQU 1
INCL_SAADEFS        EQU 1
        INCLUDE PMGRE.INC

DINCL_BITMAP        EQU 1
DINCL_ENABLE        EQU 1
        INCLUDE DRIVER.INC
        INCLUDE FONTSEG.INC
        INCLUDE EXTERN.INC
DINCL_VIOPS         EQU 1
        INCLUDE CELLBLT.INC
        INCLUDE PROTOS.INC

InvertClippedRect PROTO SYSCALL,
        hdc         :HDC,
        pDDC        :DWORD,
        afFunN      :WORD,
        lpBitmapBits:DWORD,
        wDestHeight :WORD,
        wDestBMWidth:WORD,
        wXCoord     :WORD,
        wYCoord     :WORD,
        wHeight     :WORD,
        wWidth      :WORD

;/*
;** AVIO handler data
;*/

        .DATA

CellBLTBlock cb_variables <>    ; Place to save some stuff that's used only
                                ; in AVIO handling code

;/*
;** Private functions
;*/

_AvioSupport SEGMENT DWORD PUBLIC FLAT 'CODE'

        SUBTITLE CheckCodePage
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = CheckCodePage
;*
;* DESCRIPTION   = This routine looks at the CellImageHeight and CodepageID fields
;*                 of a Vio presentation space (*pVioPS) and determines the
;*                 correct code page and cell size to use for drawing cell images.
;*                 The parameters pSelectors and pOffsets, respectively, are
;*                 offsets to tables of font selectors and a table of offsets
;*                 to code page mapping vector offsets. The two tables determine
;*                 how (A)Vio cells are drawn.  The entries in the tables
;*                 correspond to a base symbol set (0) and three loadable symbol
;*                 sets (1..3).
;*
;*                 On exit the selector and offset tables will be usable by the
;*                 (A)Vio drawing functions.  In particular the font selector and
;*                 mapping vector offset for the base symbol set will be coerced
;*                 to valid values.
;*
;*                 This routine is only called by CharRect and UpdateCursor.
;*
;*
;* INPUT         = C Prototype:
;*                   errVal _syscall CheckCodePage(VioPresentationSpace32 * pVioPS,
;*                                                 WORD                 * pSelectors,
;*                                                 WORD                 * pOffsets,
;*                                                 PVOID                * hDDC);
;*
;*                    where:
;*                      pVioPS     --> The desired VIO presentation space.
;*                      pSelectors --> Font definition.
;*                      pOffsets   --> Table of code page mapping vector offsets.
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

CheckCodePage PROC SYSCALL PUBLIC uses EBX EDI ESI,
                pVioPS    :DWORD,
                pSelectors:DWORD,
                pOffsets  :DWORD,
                hDDC      :DWORD

        LOCAL   cpidCodePage:DWORD

;/*
;** First we coerce the code page for the base symbol set to a valid id.  Note
;** that zero is a valid id.  It stands for the default code page as defined by
;** DosGetCtryInfo.  That default is interrogated during display initialization
;** and kept in the global constant default_vio_cpid.
;*/

        MOV     EBX,pVioPS
        MOVZX   EAX,[EBX].VioPresentationSpace32.viops_CodepageID
        OR      EAX,EAX
        JNZ     Non_default_CPID
        MOV     EAX,default_vio_cpid

        PUBLIC  Non_default_CPID

Non_default_CPID::
        MOV     cpidCodePage,EAX
        LEA     EBX,cpidCodePage
        INVOKE  Force_Valid_CP,EBX,pOffsets

;/*
;** !!! Call WinSetErrInfo when Force_Valid_CP returns a non-zero result.
;*/

        OR      EAX,EAX
        JZ      CCP_Continue
        MOV     EAX,ERROR_VIO_BAD_CP
        JMP     Err_Exit_CheckCodePage

        PUBLIC  CCP_Continue

CCP_Continue::
        MOV     EBX,pVioPS
        TEST    [EBX].VioPresentationSpace32.viops_CodepageID,0FFFFh
        JZ      Leave_null_CPID_alone

        MOV     EAX,cpidCodePage
        MOV     [EBX].VioPresentationSpace32.viops_CodepageID,AX

        PUBLIC  Leave_null_CPID_alone

Leave_null_CPID_alone::
        MOV     ESI,pVioPS

;/*
;** Whenever VioPresentationSpace32.viops_npmapfontsloaded is zero, we use the
;** code page map defined for the base symbol set.  The choice of the default
;** map is not critical since a null map reference will always be paired with a
;** null font selector, and hence won't cause any drawing. (See the
;** InterpretAttributes routine in CELLDRAW.ASM.)  A valid default is necessary
;** to make sure that the LVB scanning logic (see CELLSCAN.ASM) never fails.
;*/

        MOV     EBX,pOffsets
        MOV     EAX,[EBX]
        MOV     [EBX+4],EAX
        MOV     [EBX+8],EAX
        MOV     [EBX+12],EAX
;           MOV     ECX,[ESI].VioPresentationSpace32.viops_pMapFontsLoaded
        mov     EDI, hDDC                                               ;          
        mov     ECX, [EDI].DDC.ddc_MapFontsLoaded                       ;          

        JECXZ   Check_LCID_map2
        MOV     [EBX+4],ECX

        PUBLIC  Check_LCID_map2

Check_LCID_map2::
;           MOV     ECX,[ESI].VioPresentationSpace32.viops_pMapFontsLoaded+4
        mov     ECX, [EDI].DDC.ddc_MapFontsLoaded+4                     ;          

        JECXZ   Check_LCID_map3
        MOV     [EBX+8],ECX

        PUBLIC  Check_LCID_map3

Check_LCID_map3::
;           MOV     ECX,[ESI].VioPresentationSpace32.viops_pMapFontsLoaded+8
        mov     ECX, [EDI].DDC.ddc_MapFontsLoaded+8                     ;          

        JECXZ   LCID_aps_loaded
        MOV     [EBX+12],ECX

        PUBLIC  LCID_aps_loaded

LCID_aps_loaded::
;/*
;** Now we must decide what cell size to use.
;** do this by searching table of cell-sizes. Note that this table is ordered
;** by cell-size, width most-significant.
;*/

        MOVZX   EAX,[ESI].VioPresentationSpace32.viops_CellImageWidth
                                                ; EAX = width requested
        MOVZX   EDX,[ESI].VioPresentationSpace32.viops_CellImageHeight
                                                ; EDX = height requested
        MOV     ECX,cDevVioCells                         ; ECX = Cnt of avail sizes
        LEA     EBX,adDevVioCells                        ; EBX --> Table of sizes
        LEA     EDI,pDefVioFont                                  ; EDI --> The default result

        PUBLIC  Next_cellsize

Next_cellsize::
        CMP     EAX,[EBX].CellFont.cf_width      ; If requested width less than
        JB      Cellsize_decided                         ; width from table we're done
        CMP     EDX,[EBX].CellFont.cf_height     ; If requested height greater
        JB      Too_high                                         ; than height from table the
        MOV     EDI,EBX                         ; size is usable, but try to
                                                ; find larger

        PUBLIC  Too_high

Too_high::
        ADD     EBX,sizeof CellFont                      ; Point to next entry
        LOOP    Next_cellsize                                    ; Iterate if more to try

        PUBLIC  Cellsize_decided

Cellsize_decided::
        MOV     EAX,[EDI].CellFont.cf_height     ; Set cell height in viops
                                                ; to chosen height
        MOV     [ESI].VioPresentationSpace32.viops_CellImageHeight,AX
        MOV     EAX,[EDI].CellFont.cf_width      ; Set cell-width in viops
                                                ; to chosen width
        MOV     [ESI].VioPresentationSpace32.viops_CellImageWidth,AX
        MOV     EAX,[EDI].CellFont.cf_ptr        ; Get pointer to font defn.

        PUBLIC  Store_base_font

Store_base_font::
        MOV     EBX,pSelectors
        MOV     [EBX],EAX
;/*
;** The selectors will be zero unless the corresponding
;** VioPresentationSpace32.viops_selfontsloaded value is non-zero and corresponds
;** to a font whose cell shape matches that selected above.
;*/

        XOR     EAX,EAX
        MOV     [EBX+4],EAX
        MOV     [EBX+8],EAX
        MOV     [EBX+12],EAX
        MOVZX   EAX,[ESI].VioPresentationSpace32.viops_CellImageWidth
        MOVZX   EDX,[ESI].VioPresentationSpace32.viops_CellImageHeight
;           MOV     ECX,[ESI].VioPresentationSpace32.viops_pFontsLoaded
        mov     EDI, hDDC                                                ;          
        mov     ECX,[EDI].DDC.ddc_FontsLoaded                            ;          
        JECXZ   Check_font2
        CMP     AX,[ECX].FOCAFONT.ff_fdDefinitions.fdh_xCellWidth
        JNE     Check_font2
        CMP     DX,[ECX].FOCAFONT.ff_fdDefinitions.fdh_yCellHeight
        JNE     Check_font2
        MOV     [EBX+4],ECX

        PUBLIC  Check_font2

Check_font2::
;           MOV     ECX,[ESI].VioPresentationSpace32.viops_pFontsLoaded[4]
        mov     ECX,[EDI].DDC.ddc_FontsLoaded[4]                        ;          
        JECXZ   Check_font3
        CMP     AX,[ECX].FOCAFONT.ff_fdDefinitions.fdh_xCellWidth
        JNE     Check_font3
        CMP     DX,[ECX].FOCAFONT.ff_fdDefinitions.fdh_yCellHeight
        JNE     Check_font3
        MOV     [EBX+8],ECX

        PUBLIC  Check_font3

Check_font3::
;           MOV     ECX,[ESI].VioPresentationSpace32.viops_pFontsLoaded[8]
        mov     ECX,[EDI].DDC.ddc_FontsLoaded[8]                        ;          
        JECXZ   Font_selectors_loaded
        CMP     AX,[ECX].FOCAFONT.ff_fdDefinitions.fdh_xCellWidth
        JNE     Font_selectors_loaded
        CMP     DX,[ECX].FOCAFONT.ff_fdDefinitions.fdh_yCellHeight
        JNE     Font_selectors_loaded
        MOV     [EBX+12],ECX

        PUBLIC  Font_selectors_loaded

Font_selectors_loaded::
;/*
;** If the cell height has changed since the last call, adjust the cursor
;** start/end lines to match the new cell size.
;*/

        CMP     DX,[ESI].VioPresentationSpace32.viops_CellHeightLatch
        JE      Exit_CheckCodePage
        MOV     [ESI].VioPresentationSpace32.viops_CellHeightLatch,DX
        DEC     EDX
        CMP     [ESI].VioPresentationSpace32.viops_TextCursorStartLine,DX
        JBE     Check_height_next
        MOV     [ESI].VioPresentationSpace32.viops_TextCursorStartLine,DX

        PUBLIC  Check_height_next

Check_height_next::
        CMP     [ESI].VioPresentationSpace32.viops_TextCursorEndLine,DX
        JBE     Check_height_done
        MOV     [ESI].VioPresentationSpace32.viops_TextCursorEndLine,DX

        PUBLIC  Check_height_done

Check_height_done::
        PUBLIC  Exit_CheckCodePage

Exit_CheckCodePage::
        XOR     EAX,EAX

        PUBLIC  Err_Exit_CheckCodePage

Err_Exit_CheckCodePage::

        RET

CheckCodePage ENDP

        SUBTITLE InvertTextCursor
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = InvertTextCursor
;*
;* DESCRIPTION   = Inverts a rectangle within the client rectangle to show or hide
;*                 the cursor.
;*
;* INPUT         = C Prototype:
;*                 VOID _syscall InvertTextCursor (HDC hdc,
;*                                                 PVOID pDDC,
;*                                                 PVOID lpBitmapBits,
;*                                                 SHORT wDestHeight,
;*                                                 SHORT wDestBMWidth,
;*                                                 SHORT wXCoord,
;*                                                 SHORT wYCoord,
;*                                                 SHORT wHeight,
;*                                                 SHORT wWidth);
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InvertTextCursor PROC SYSCALL PUBLIC,
                hdc         :HDC,
                pDDC        :DWORD,
                afFunN      :WORD,
                lpBitmapBits:DWORD,
                wDestHeight :WORD,
                wDestBMWidth:WORD,
                wXCoord     :WORD,
                wYCoord     :WORD,
                wHeight     :WORD,
                wWidth      :WORD

        LOCAL   fSomethingDrawn :WORD
        LOCAL   drBounds        :RECTL

        XOR     EAX,EAX
        MOV     fSomethingDrawn,AX

;/*
;** Find the bottom left corner
;*/

        MOV     ESI,pDDC
        MOV     ESI,[ESI].DDC.ddc_prddc
        MOV     EDX,[ESI].RDDC.rddc_ptsOrg.ptl_x
        MOV     EAX,[ESI].RDDC.rddc_ptsOrg.ptl_y
        AND     EDX,(not 7)                              ; In case the left window edge is
                                        ; not aligned on a BYTE boundary.
;/*
;** Now EDX/EAX contain the X/Y screen coordinates of our window origin.
;** We can map the coordinate parameters to the screen:
;*/

        MOVSX   EBX,wYCoord
        ADD     EAX,EBX                         ; EAX = Screen yBottom
        MOVSX   EBX,wXCoord
        ADD     EDX,EBX                         ; EDX = Screen xLeft
        MOVZX   EBX,wHeight
        MOVZX   ECX,wWidth
        ADD     EBX,EAX                         ; EBX = Screen yTop
        ADD     ECX,EDX                         ; ECX = Screen xRight

;/*
;** Now we'll build up the RECTL parameter for use with enumerate_clip_rects.
;*/

        MOV     drBounds.rcl_yBottom,EAX
        MOV     drBounds.rcl_xLeft,EDX
        MOV     drBounds.rcl_yTop,EBX
        MOV     drBounds.rcl_xRight,ECX
;/*
;** If either of the BOUNDs flags is set, we must accumulate bounds information
;** for this drawing action.
;*/

        MOV     DI,afFunN
        TEST    DI,COM_BOUND SHR 16 + COM_ALT_BOUND SHR 16
        JZ      Dont_accumulate_text_cursor_bounds
        MOV     ESI,pDDC
        MOV     EAX,drBounds.rcl_xLeft
        MOV     ECX,drBounds.rcl_xRight
        MOV     EBX,drBounds.rcl_yBottom
        MOV     EDX,drBounds.rcl_yTop
        DEC     EDX                             ; To make the rect inclusive
        DEC     ECX
        shl     edi,16
        INVOKE  InnerAccumulateBounds

        PUBLIC  Dont_accumulate_text_cursor_bounds

Dont_accumulate_text_cursor_bounds::
;/*
;** We can draw if the display device is visible or COM_DRAW bit is on
;** otherwise only do the bounds accumulation.
;*/

        TEST    afFunN,COM_DRAW                  SHR 16
        JZ      Exit_InvertTextCursor
        LEA     EBX,drBounds
;/*
;** Since enumerate_clip_rects will pass my ESI and EDI register values along
;** to InvertClippedRect, I use ESI to pass access to my stack frame.
;*/

        MOV     ESI,EBP
        MOV     ECX,RECTDIR_LFRT_BOTTOP-1        ; Favored direction
        MOV     EAX,pDDC
        INVOKE  enumerate_clip_rects,EAX,EBX,offset InvertClippedRect
;/*
;** If nothing was drawn we don't reset the display state.  That's not just
;** polite.  It's necessary to prevent interfering with full screen screen
;** groups.  When Winthorn is in the background, all the visible regions are
;** set empty, but drawing and device driver actions proceed normally.
;*/

        MOV     CX,fSomethingDrawn
        JCXZ    Exit_InvertTextCursor

        INVOKE  InnerCheckCursor        ; Actually a CheckCursor call

        INVOKE  SetDisplayDefaults

        PUBLIC  Exit_InvertTextCursor

Exit_InvertTextCursor::

        RET

InvertTextCursor ENDP

        SUBTITLE InvertSplitCursor
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = InvertSplitCursor
;*
;* DESCRIPTION   =
;*
;*          This routine inverts the text cursor based on the information in the
;*          private portion of the PS structure (hVioWindow .. rgfShieldStates).
;*
;*          It detects split cursors (StartLine > EndLine) and breaks them into two
;*          inversion actions.  For splits, we assume that XLatch, YLatch,
;*          WidthLatch, and HeightLatch correspond to the complete vertical extent
;*          of a cell.  The latched StartLine and EndLine values are used to split
;*          that rectangle into the two inversion regions and the middle unchanged
;*          region.
;*
;*          For solid cursors XLatch, YLatch, WidthLatch, and HeightLatch directly
;*          define the image region to invert.
;*
;* INPUT         = C Prototype:
;*                    VOID _syscall InvertSplitCursor (HDC                    hdc,
;*                                          PVOID                  pDDC,
;*                                          BOOL                   afFunN,
;*                                          PVOID                  lpBitmapBits,
;*                                          SHORT                  wDestHeight,
;*                                          SHORT                  wDestBMWidth,
;*                                          VioPresentationSpace32 * pAVioPS);
;*
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InvertSplitCursor PROC SYSCALL PUBLIC uses EBX ESI,
                hdc         :DWORD,
                pDDC        :DWORD,
                afFunN      :WORD,
                lpBitmapBits:DWORD,
                wDestHeight :WORD,
                wDestBMWidth:WORD,
                pAVioPS     :DWORD

        LOCAL   wXCoord           :WORD
        LOCAL   wYCoord           :WORD
        LOCAL   wHeight           :WORD
        LOCAL   wWidth            :WORD
        LOCAL   wOrigin_Correction:WORD

        MOV     ESI,pAVioPS
        MOVSX   EAX,[ESI].VioPresentationSpace32.viops_PartialCellAdjust
        MOV     wOrigin_Correction,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_CursorStartLine
        CMP     AX,[ESI].VioPresentationSpace32.viops_CursorEndLine
        JBE     Solid_cursor

        PUBLIC  Split_cursor

Split_cursor::
;/*
;** First we invert the bottom half of the split.  That is, the rectangle from
;** StartLine to the bottom of the current cell.
;*/

        MOV     CX,[ESI].VioPresentationSpace32.viops_CellHeightLatch
        SUB     CX,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        ADD     BX,wOrigin_Correction
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertTextCursor,
                        hdc,
                        pDDC,
                        afFunN,
                        lpBitmapBits,
                        wDestHeight,
                        wDestBMWidth,
                        AX,
                        BX,
                        CX,
                        DX
;/*
;** Then we invert the top part of the split.  That is, from the top of
;** the cell to EndLine.
;*/

        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        ADD     BX,wOrigin_Correction
        ADD     BX,[ESI].VioPresentationSpace32.viops_CellHeightLatch
        MOV     CX,[ESI].VioPresentationSpace32.viops_CursorEndLine
        INC     CX
        SUB     BX,CX
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertTextCursor,
                        hdc,
                        pDDC,
                        afFunN,
                        lpBitmapBits,
                        wDestHeight,
                        wDestBMWidth,
                        AX,
                        BX,
                        CX,
                        DX
        JMP     Exit_InvertSplitCursor

        PUBLIC  Solid_cursor

Solid_cursor::
        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        ADD     BX,wOrigin_Correction
        MOV     CX,[ESI].VioPresentationSpace32.viops_HeightLatch
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertTextCursor,hdc,pDDC,afFunN,lpBitmapBits,wDestHeight,wDestBMWidth,AX,BX,CX,DX
        .ERRNZ  $-Exit_InvertSplitCursor

        PUBLIC  Exit_InvertSplitCursor

Exit_InvertSplitCursor::

        RET

InvertSplitCursor ENDP

;/*
;** Public functions
;*/

        SUBTITLE ScrollRect
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = ScrollRect
;*
;* DESCRIPTION   =
;*  This routine implements the ScrollRect call by falling into CharRect to
;*  redraw the rectangle which has been scrolled in the LVB.  Other device
;*  drivers may wish to split this work into two parts -- a screen-to-screen
;*  bitblt and a CharRect call to draw the tail region invalidated by the
;*  scrolling operation.  On the EGA that's slower than just redrawing the
;*  entire rectangle.  EGA memory is S-l-o-o-o-w!
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall ScrollRect (HDC hdc,
;*                                             VioPresentationSpace32 * pps,
;*                                             LPScrollRectRef        lpRectDesc,
;*                                             PVOID                  hddc,
;*                                             ULONG                  FunN);
;*
;*                 where:
;*                 All arguments are as specified for the GreScrollRect function.
;*
;*
;* OUTPUT        = As specified for the GreScrollRect function.
;*
;* RETURN-NORMAL = As specified for the GreScrollRect function.
;* RETURN-ERROR  = As specified for the GreScrollRect function.
;*
;**************************************************************************/

        OPTION  PROLOGUE:NONE
        OPTION  EPILOGUE:NONE

define_CharRect_frame ScrollRect


ScrollRect ENDP
        .ERRNZ  $-CharRect

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

        SUBTITLE CharRect
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = CharRect
;*
;* DESCRIPTION   =
;*         This routine displays a rectangle of character images in a VIO window
;*         according to the state of its presentation space and the cell rectangle
;*         defined by *lpRectDesc.  Its result will be zero for success, and an
;*         error code if a problem is detected.
;*
;*       Warnings: This code assumes the OrgRow and OrgCol fields in a presentation
;*                 space are never negative.  VIO and the Shield Layer must enforce
;*                 that discipline.
;*
;* INPUT         = C Prototype:
;*                   LONG _sycall CharRect (HDC hdc,
;*                                          VioPresentationSpace32 pps,
;*                                          LPGridRectRef        lpRectDesc,
;*                                          PVOID                hddc,
;*                                          ULONG                FunN);
;*
;*                    where:
;*                      All arguments are as specified in the GreCharRect function.
;*
;*
;* OUTPUT        = All arguments are as specified in the GreCharRect function.
;*
;* RETURN-NORMAL = As specified in the GreCharRect function.
;* RETURN-ERROR  = As specified in the GreCharRect function.
;*
;**************************************************************************/


define_CharRect_frame CharRect
        MOV     EDX,hddc

        ENTER_DRIVER2
        MOV     EAX,CE_INVALID_PRESENTATION_SPACE       ; Assume error
        JC      CR_Exit_no_lock
;/*
;** We save the current frame pointer in the bottom of the stack segment
;** to allow BP to be used as a work register in some of the scanning and
;** drawing routines.
;*/

        MOV     CellBLTBlock.cb_BPSaveSlot,EBP
;/*
;** I call CheckCodePage to coerce the CodepageID, CellImageHeight, and
;** CellImageWidth fields of the PS to valid and consistent values.  As a
;** side effect it also places the correct values in wSymbolSetSelectors
;** and wSymbolSetOffsets
;*/

        LEA     EAX,wSymbolSetSelectors
        LEA     EBX,wSymbolSetOffsets
;V2.1EKF00 INVOKE  CheckCodePage,lpPS,EAX,EBX
        INVOKE  CheckCodePage,lpPS,EAX,EBX,hddc         ;V2.1EKF00
        OR      EAX,EAX
        JZ      CR_Continue
        JMP     NoDisplayWork

        PUBLIC  CR_Continue

CR_Continue::
        MOV     EAX,wSymbolSetOffsets
        MOV     npcpmap,EAX
        MOV     ESI,lpPS                         ; Start looking at the presentation space
        MOV     AX,[ESI].VioPresentationSpace32.viops_CellImageHeight
        MOV     wCellHeight,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_CellImageWidth
        MOV     wCellWidth,AX
;/*
;** Here we examine the supplied DDC to see if it is a display device
;** (DDC_DEVICE) or something else.  We can draw with a display device
;** that is visible (DDC_VISIBLE), but not with a memory bitmap.
;*/

        MOV     ESI,hddc                                 ; Do we have a display device?

;/*
;** Check COM_DRAW bit
;*/

        MOVZX   ECX,[ESI].DDC.ddc_fb
        TEST    CL,DDC_DEVICE
        JZ      Not_A_Display_Device2
        AND     ECX,DDC_VISIBLE
        JZ      Bounds_only
        AND     CX,WORD ptr FunN+2               ; FunN - MSW is commands
        JNZ     Got_A_Display_Device2            ; skip draw
        .ERRNZ  COM_DRAW SHR 16 - DDC_VISIBLE

        PUBLIC  Not_A_Display_Device2

Not_A_Display_Device2::
        JMP     Drawing_Deferred

        PUBLIC  Bounds_only

Bounds_only::
;/*
;** We won't be drawing anything this time.  Note however that we still
;** must go through the coordinate transforms to calculate the bounds
;** rectangle.  The boolean variable fDontDraw indicates whether we'll
;** draw or not.
;*/

        MOV     fDontDraw,1
        JMP     Setup_for_drawing

        PUBLIC  Got_A_Display_Device2

Got_A_Display_Device2::
        CMP     fGrimReaper,0                                    ; Skip draw if dead
        JNZ     Not_A_Display_Device2
        MOV     fDontDraw,0

        PUBLIC  Setup_for_drawing

Setup_for_drawing::
        MOV     EBX,[ESI].DDC.ddc_npsd                   ; EBX --> surface
        MOV     EAX,[EBX].SURFACE.sd_pBits       ; Copy far pointer to bits
        MOV     lpBitmapBits,EAX
        MOV     EAX,[EBX].SURFACE.sd_cx
        MOV     wDestWidth,AX
        MOV     EAX,[EBX].SURFACE.sd_cy
        MOV     wDestHeight,AX
        MOV     EAX,[EBX].SURFACE.sd_cbScan      ; Copy the width of the bit
        MOV     wDestBMWidth,AX                                  ; array in bytes.
        MOV     ESI,lpPS                                         ; Resume our scan of the
                                                ; Presentation Space.
        MOV     AX,[ESI].VioPresentationSpace32.viops_BufferRowCount
                                                ; Pick up the dimensions of
        MOV     wRowCount,AX                                     ; the logical video buffer
        MOV     AX,[ESI].VioPresentationSpace32.viops_BufferColumnCount
        MOV     wColCount,AX
        MOVZX   ECX,[ESI].VioPresentationSpace32.viops_CellByteSize
                                                ; Get the size of a buffer
        MOV     wCellSize,CX                    ; cell

        SHR     ECX,1                           ; Compute the shift factor
        MOV     wCellSizeShift,CX                        ; corresponding to the cell
                                                ; size.
                                                ; NB:  This particular trick
                                                ;      works only for sizes 2
                                                ;      (Vio) and 4 (AVio).
        SHL     AX,CL                           ; Calculate the width in bytes
        MOV     wLVBRowBytes,AX                                  ; of an LVB row.
        MOV     EAX,[ESI].VioPresentationSpace32.viops_pLVB
        MOV     seg_LVB,EAX
        TEST    fDontDraw,0FFFFh
        JZ      Drawing_permitted
        XOR     EAX,EAX
        JMP     Skip_Exclusion

        PUBLIC  Drawing_permitted

Drawing_permitted::
;/*
;** Certain flags in the rgfShieldStates field cause drawing actions to be
;** deferred.  Here we examine those flags.
;*/

        MOV     EAX,[ESI].VioPresentationSpace32.viops_rgfShieldStates
        TEST    EAX,fServeNobody
        JNZ     Drawing_Deferred
        AND     EAX,(fShieldCalling or fServeShieldOnly)
        CMP     EAX,fServeShieldOnly
        JNE     Drawing_Allowed

        PUBLIC  Drawing_Deferred

Drawing_Deferred::
        XOR     EAX,EAX
        JMP     NoDisplayWork

        PUBLIC  Drawing_Allowed

Drawing_Allowed::

;/*
;** Here we exclude the text cursor from the screen if it is visible and lies
;*/

        XOR     EAX,EAX
        TEST    [ESI].VioPresentationSpace32.viops_rgfShieldStates,fCursorShowing
        JZ      Skip_Exclusion
        MOV     EDI,lpRectDesc
        MOVZX   ECX,[ESI].VioPresentationSpace32.viops_CursorRow
        MOV     EBX,[EDI].GridRectRef.cellrect_StartRow
        CMP     ECX,EBX
        JL      Skip_Exclusion
        SUB     ECX,EBX
        CMP     ECX,[EDI].GridRectRef.cellrect_RectDepth
        JGE     Skip_Exclusion
        MOVZX   ECX,[ESI].VioPresentationSpace32.viops_CursorCol
        MOV     EBX,[EDI].GridRectRef.cellrect_StartColumn
        CMP     ECX,EBX
        JL      Skip_Exclusion
        SUB     ECX,EBX
        CMP     ECX,[EDI].GridRectRef.cellrect_RectWidth
        JGE     Skip_Exclusion
;/*
;** The text cursor lies within the rectangle we're to draw.
;** No need to actually remove the cursor from that rectangle,
;** since all we need do is redraw the cursor after we're finished
;** drawing.  Our drawing actions will obliterate the cursor anyway.
;*/

        MOV     EAX,1

        PUBLIC  Skip_Exclusion

Skip_Exclusion::
        MOV     fExcluding,AX
;/*
;** The following code calculates the pixel origin of the screen relative to
;** the image of the full logical video buffer.
;*/

;/*
;** First we calculate the height of the client rect in pixels.
;*/

        MOV     ESI,lpPS
        MOV     AX,[ESI].VioPresentationSpace32.viops_WindowHeight
        MUL     wCellHeight
        MOVZX   EBX,AX                          ; EBX = Window ht. in pixels
;/*
;** Then we retrieve the screen coordinates for the bottom left corner
;** of the client rectangle.
;*/

        PUSH    EDI
        MOV     EDI,hddc
        MOV     EDI,[EDI].DDC.ddc_prddc
        MOV     EDX,[EDI].RDDC.rddc_ptsOrg.ptl_x
        MOVSX   EAX,[ESI].VioPresentationSpace32.viops_PartialCellAdjust
        ADD     EAX,[EDI].RDDC.rddc_ptsOrg.ptl_y
        AND     EDX,(not 7)                              ; In case the left window edge is
        POP     EDI                     ; not aligned on a BYTE boundary.
;/*
;** Now EDX/EAX hold the X/Y coords of the bottom left corner of the window
;** client rectangle.
;*/
;/*
;** We transform the coordinates to have their origin at the top left corner of
;** the screen.
;*/

;/*
;** First we map  EDX/EAX to the top left corner of the window.
;*/

        ADD     EAX,EBX
;/*
;** Then adjust those coordinates to be relative to the top left corner of
;** the screen.
;*/

        MOVZX   EBX,wDestHeight
        SUB     EBX,EAX                 ; ptClientOrigin.ycoord
        MOV     ECX,EDX                 ; ptClientOrigin.xcoord

;/*
;** Now the Window Origin coordinates define the LVB cell drawn at the
;** bottom left corner of the window.  Also, those coordinates are relative
;** to the bottom left corner of the LVB.  To avoid changing lots of code
;** we map those coordinates so they refer to the cell which is drawn in
;** the top left corner of the window and we transform the coordinates to
;** be relative to the top left corner of the LVB.
;**
;** A future clean-up will eliminate the redundant mappings and transforms.
;*/

        MOV     AX,wRowCount                     ; Transform to top left origin.
        SUB     AX,[ESI].VioPresentationSpace32.viops_WindowOriginRow
        SUB     AX,[ESI].VioPresentationSpace32.viops_WindowHeight
                                                ; Map to the top left corner
                                                ; of the window image.
        MUL     wCellHeight                     ; Map relative to TL of screen
        SUB     AX,BX
        MOV     wVertLineOffset,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_WindowOriginColumn
        ColToPix AX
        SUB     AX,CX
        MOV     wHorzPixelOffset,AX
        PixToCol AX
        MOV     wDestColOffset,AX

;/*
;**Examine the rectangle descriptor
;*/

;/*
;** This code clips the rectangle descriptor to lie within the LVB and maps it
;** into a RECT descriptor relative to screen coordinates.  This is necessary
;** because the Vis Region clipping below only bounds the work to within the
;** window client region.  The Shield Layer code will guarantee that the
;** window's client rect won't extend beyond the image of the LVB.  No such
;** assumptions can be made for AVio support, however.  Thus the need for the
;** clipping action.
;**
;** Side Issue: AVio code which lets the client region get larger than the
;**             LVB image or which doesn't exercise discipline wrt the
;**             window origin will have to define a border color and
;**             paint the border region itself.
;*/

        LEA     EDI,drBounds                             ; Clear the Bounds rectangle
                                        ; to all zeroes.
        XOR     EAX,EAX                 ; !!! You are assuming that these
        CLD                             ; !!! will all be positive.  That
        MOV     ECX,(sizeof RECTL)/2             ; !!! seems       to me.
    REP STOSW                           ; !!! ..walt
        MOVZX   EDI,wDestHeight                          ; So we can flip the coords
                                        ; to have the origin at the
                                        ; bottom left.
        MOV     ESI,lpRectDesc
;/*
;** Here we're going to constrain the passed rectangle to lie within the
;** logical video buffer.  That is, cellrect_StartRow is coerced to the range
;** [0..wRowCount-1] and cellrect_RectDepth is coerced to the range
;** [0..wRowCount-cellrect_StartRow].
;*/

        XOR     EAX,EAX
;/*
;** cellrect_StartRow will define the bottom left cell of a
;** rectangle to be displayed, and it will be relative to the bottom left
;** corner of the logical video buffer.  For now we map and transform that
;** coordinate so that it denotes the top left cell of that rectangle and
;** is relative to the top left corner of the LVB.
;*/

        MOVZX   EBX,wRowCount                                            ; BL => TL origin
        SUB     EBX,[ESI].GridRectRef.cellrect_StartRow ; Map to TL corner of
                                                        ; the rectangle
        SUB     EBX,[ESI].GridRectRef.cellrect_RectDepth
        SMax    EBX
        MOV     ECX,[ESI].GridRectRef.cellrect_RectDepth
        SUB     ECX,EAX
        MOV     AX,wRowCount
        SUB     EAX,EBX
        SMin    ECX
        JG      VerticalMapping
        JMP     NoDisplayWork

        PUBLIC  VerticalMapping

VerticalMapping::
        MOV     EAX,EBX                         ; Map the vertical bounds of
        MOVZX   EDX,wCellHeight                                  ; the cell rectangle to the
        MUL     EDX                             ; image rectangle.
        XCHG    ECX,EAX
        MOVZX   EDX,wCellHeight
        MUL     EDX
        MOVSX   EDX,wVertLineOffset
        SUB     ECX,EDX
        MOV     EDX,EDI
        SUB     EDX,ECX
        MOV     drBounds.rcl_yTop,EDX                    ; rect_y2 ... Top ...
        ADD     EAX,ECX
        MOV     EDX,EDI
        SUB     EDX,EAX
        MOV     drBounds.rcl_yBottom,EDX         ; rect_y1 ... Bottom ...
;/*
;** Here we coerce cellrect_StartColumn and cellrect_RectWidth so that
;** cellrect_StartColumn is in the range [0..wRowCount-1] and
;** cellrect_RectWidth is in to the range [0..wColCount-cellrect_StartColumn].
;*/

        XOR     EAX,EAX                                         ; Constrain
        MOV     EBX,[ESI].GridRectRef.cellrect_StartColumn ; the cell
        SMax    EBX                                             ; rectangle
        MOV     ECX,[ESI].GridRectRef.cellrect_RectWidth        ; horizontally
        SUB     ECX,EAX                                         ; to lie
        MOVZX   EAX,wColCount                                   ; within the
        SUB     EAX,EBX                                         ; LVB.
        SMin    ECX
        JG      HorizontalMapping
        JMP     NoDisplayWork

        PUBLIC  HorizontalMapping

HorizontalMapping::

IFNDEF CLR2   ; - Change to support non 8 pel wide AVIO
              ;                 characters
              ; CLR2 is only defined when building CGA driver.

        MOV     EAX,EBX                         ; ColToPix uses "MUL AX"
        ColToPix AX                            ; Map the horizontal bounds of
        MOVSX   EDX,wHorzPixelOffset            ; the cell rectangle to the
        SUB     EAX,EDX                         ; image rectangle.
        MOV     drBounds.rcl_xLeft,EAX          ; rect_x1... Left ...
        XCHG    EAX,ECX
        ColToPix AX
        ADD     ECX,EAX
        MOV     drBounds.rcl_xRight,ECX         ; rect_x2 ... Right ...

ELSE ; CLR2   - end followed by old code.

        ColToPix EBX                            ; Map the horizontal bounds of
        MOVZX   EAX,wHorzPixelOffset            ; the cell rectangle to the
        SUB     EBX,EAX                         ; image rectangle.
        MOV     drBounds.rcl_xLeft,EBX                   ; rect_x1... Left ...
        ColToPix ECX
        ADD     ECX,EBX
        MOV     drBounds.rcl_xRight,ECX                  ; rect_x2 ... Right ...

ENDIF ; CLR2
;/*
;** When we reach this point the image rectangle (drBounds) has been
;** calculated and clipped to lie within the image of the LVB.
;*/

        MOV     EDI,FunN
        TEST    EDI,(COM_BOUND+COM_ALT_BOUND)
        JZ      Dont_accumulate_charrect_bounds
        MOV     ESI,hddc
        MOV     EAX,drBounds.rcl_xLeft
        MOV     ECX,drBounds.rcl_xRight
        MOV     EBX,drBounds.rcl_yBottom
        MOV     EDX,drBounds.rcl_yTop
        DEC     EDX                             ; To make the rect inclusive
        DEC     ECX
        INVOKE  InnerAccumulateBounds

        PUBLIC  Dont_accumulate_charrect_bounds

Dont_accumulate_charrect_bounds::
        TEST    fDontDraw,0FFFFh
        JZ      Draw_the_char_rect
        XOR     EAX,EAX
        JMP     NoDisplayWork

        PUBLIC  Draw_the_char_rect

Draw_the_char_rect::
;/*
;** We set up fSomethingDrawn to detect whether we have a null visible region.
;** If so, the Winthorn screen group may not be active.
;*/

        XOR     EAX,EAX
        MOV     fSomethingDrawn,EAX

;/*
;** Now we call enumerate_clip_rects to drive the DrawImageRect routine.
;*/

        LEA     EBX,drBounds
        MOV     ESI,EBP                         ; To make our stack frame
                                                ; available.
        MOV     ECX,RECTDIR_LFRT_BOTTOP-1        ; Favored direction
        INVOKE  enumerate_clip_rects,hddc,EBX,offset DrawImageRect
        XOR     EAX,EAX
;/*
;** If nothing was drawn, don't do anything to the EGA registers.  That's
;** because the Winthorn screen group may be in the background.
;*/

        TEST    fSomethingDrawn,0FFFFFFFFh
        JZ      Null_visible_region
        PUSH    EAX
        INVOKE  SetDisplayDefaults               ; Revert to the default states assumed
                                        ; by the rest of the driver code.
        TEST    fExcluding,0FFFFh
        JZ      Cursor_wasnt_excluded
        MOV     ESI,lpPS
;/*
;** Note the CGA driver needs to OR this bit on in order to erase the cursor
;** when the cursor is moved by UpdateCursor
;*/

        OR      [ESI].VioPresentationSpace32.viops_rgfShieldStates,fCursorShowing
        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        MOV     CX,[ESI].VioPresentationSpace32.viops_HeightLatch
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertSplitCursor,
                        hdc,
                        hddc,
                        WORD ptr FunN+2,
                        lpBitmapBits,
                        wDestHeight,
                        wDestBMWidth,
                        lpPS

        PUBLIC  Cursor_wasnt_excluded

Cursor_wasnt_excluded::
        POP     EAX

        PUBLIC  NoDisplayWork

NoDisplayWork::
        PUBLIC  Null_visible_region

Null_visible_region::
        INVOKE  leave_driver

        PUBLIC  CR_Exit_no_lock

CR_Exit_no_lock::


        RET

CharRect ENDP

        SUBTITLE CharStr
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = CharStr
;*
;* DESCRIPTION   = This routines calls CharRectGlue as necessary to accomplish the
;*                 work defined by the lpStringDesc descriptor.
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall CharStr (HDC hdc,
;*                                          VioPresentationSpace32 * lpPS,
;*                                          LPGridRectRef          lpStrDesc,
;*                                          PVOID                  hddc,
;*                                          ULONG                  FunN);
;*
;*                    where:
;*                      All arguments are as specified for the GreCharStr function.
;*
;* OUTPUT        = As specified for the GreCharStr function.
;*
;* RETURN-NORMAL = As specified for the GreCharStr function.
;* RETURN-ERROR  = As specified for the GreCharStr function.
;*
;**************************************************************************/

CharStr PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc      :DWORD,                 ; A long pointer to the display context we'll be using.
                lpPS     :DWORD,
                lpStrDesc:DWORD,
                hddc     :DWORD,
                FunN     :DWORD                          ; Index for the desired driver
                                        ; function (presumably CharStr).

        LOCAL   wLVBRows  :WORD                          ; Dimensions of the LVB
        LOCAL   wLVBCols  :WORD
        LOCAL   wCellCount:WORD                          ; Length of the cell string
        LOCAL   SubRect   :GridRectRef           ; Subrectangle passed to CharRectangle


        MOV     EDX,hddc
        ENTER_DRIVER2
        MOV     EAX,CE_INVALID_PRESENTATION_SPACE       ; Assume error
        JC      CS_Exit_no_lock
        LEA     EDI,SubRect
        XOR     EAX,EAX
        MOV     ECX,(sizeof GridRectRef)/4
        CLD
    REP STOSD
        MOV     ESI,lpPS
        MOV     BX,[ESI].VioPresentationSpace32.viops_BufferRowCount
        MOV     wLVBRows,BX
        MOVZX   ECX,[ESI].VioPresentationSpace32.viops_BufferColumnCount
        MOV     wLVBCols,CX
        MOV     ESI,lpStrDesc
        MOV     EAX,[ESI].GridStringRef.cellstr_StartRow
        CMP     AX,BX
        JB      CS_Row_Inx_OK
        MOV     EAX,GRE_INVALIDROWINDEX
        JMP     CharStr_Error_Exit

        PUBLIC  CS_Row_Inx_OK

CS_Row_Inx_OK::
        MOV     SubRect.cellrect_StartRow,EAX
        MOV     EBX,[ESI].GridStringRef.cellstr_StartColumn
        CMP     EBX,ECX
        JB      CS_Col_Inx_OK
        MOV     EAX,GRE_INVALIDCOLUMNINDEX
        JMP     CharStr_Error_Exit

        PUBLIC  CS_Col_Inx_OK

CS_Col_Inx_OK::
        MOV     SubRect.cellrect_StartColumn,EBX
        MOV     ECX,[ESI].GridStringRef.cellstr_StringLength
        MOV     wCellCount,CX

;/*
;** The Code below partitions the designated string into three parts:
;**
;**   1.  A trailing string in the first row affected.
;**   2.  A sequence of middle rows which are also affected.
;**   3.  A leading string in the last row to be affected.
;**
;** In any particular call, some of these partitions may be empty.
;**
;** The common situation of having a string which fits completely in a
;** single row is handled as either a case 1 partition or a case 2 partition.
;*/

        OR      ECX,ECX                         ; Check for zero or negative
        JNS     Non_Negative_CS_Length
        MOV     EAX,GRE_NEGATIVELENGTH
        JMP     CharStr_Error_Exit

        PUBLIC  Non_Negative_CS_Length

Non_Negative_CS_Length::
        JG      Non_Empty_String                         ; string length.

        PUBLIC  CharStr_Done_Relay

CharStr_Done_Relay::
        JMP     CharStr_Done

        PUBLIC  Non_Empty_String

Non_Empty_String::
        OR      EBX,EBX                 ; If the string does not begin at
        JNZ     CS_FirstRow                              ; column zero, partition 1 is
                                        ; non-empty.
        CMP     CX,wLVBCols                              ; Ditto if the length is less than
        JGE     CS_Middle                                ; a full row.

        PUBLIC  CS_FirstRow

CS_FirstRow::

;/*
;** This code handles partition 1.
;*/

        MOV     EAX,1
        MOV     SubRect.cellrect_RectDepth,EAX
        MOVZX   EAX,wLVBCols                                     ; Width <- StringLength
        SUB     EAX,EBX                         ; Min RowLength - ColOffset
        SMin    ECX
        MOV     SubRect.cellrect_RectWidth,ECX
        SUB     wCellCount,CX
        LEA     EBX,SubRect
        INVOKE  CharRect,hdc,lpPS,EBX,hddc,FunN
        OR      EAX,EAX
        JZ      CS_Part1_Done_OK
        JMP     CharStr_Error_Exit

        PUBLIC  CS_Part1_Done_OK

CS_Part1_Done_OK::
        MOVZX   ECX,wCellCount                           ; Are we done?
        JECXZ   CharStr_Done_Relay               ; If not, adjust the rectangle
                                        ; descriptor to start in column 0 of
                                                 ; the next row.
        DEC     SubRect.cellrect_StartRow
        XOR     EAX,EAX
        MOV     SubRect.cellrect_StartColumn,EAX
        CMP     CX,wLVBCols                              ; Do we have at least a full row left?
        JL      CS_LastRow

        PUBLIC  CS_Middle

CS_Middle::

;/*
;** This code handles partition 2.
;*/

        MOV     EAX,ECX
        XOR     EDX,EDX
        MOVZX   EBX,wLVBCols
        DIV     EBX
        MOV     SubRect.cellrect_RectDepth,EAX
        MOV     SubRect.cellrect_RectWidth,EBX
        MUL     EBX
        SUB     ECX,EAX
        MOV     wCellCount,CX
        MOV     EAX,SubRect.cellrect_StartRow    ; Map cellrect_StartRow to the
        SUB     EAX,SubRect.cellrect_RectDepth   ; bottom left corner of the
        INC     EAX                             ; rectangle to be shown.
        MOV     SubRect.cellrect_StartRow,EAX
        LEA     EBX,SubRect
        INVOKE  CharRect,hdc,lpPS,EBX,hddc,FunN
        OR      EAX,EAX
        JZ      CS_Part2_Done_OK
        JMP     CharStr_Error_Exit

        PUBLIC  CS_Part2_Done_OK

CS_Part2_Done_OK::
        MOVZX   ECX,wCellCount                           ; Are we done?
        JECXZ   CharStr_Done                             ; If not, move StartRow down one
                                                 ; row to set up for partition 2.
        DEC     SubRect.cellrect_StartRow

        PUBLIC  CS_LastRow

CS_LastRow::

;/*
;** This code handles partition 3.
;*/

        MOV     SubRect.cellrect_RectWidth,ECX
        MOV     EAX,1
        MOV     SubRect.cellrect_RectDepth,EAX
        LEA     EBX,SubRect
        INVOKE  CharRect,hdc,lpPS,EBX,hddc,FunN
        OR      EAX,EAX
        JNZ     CharStr_Error_Exit

        PUBLIC  CharStr_Done

CharStr_Done::
        XOR     EAX,EAX

        PUBLIC  CharStr_Error_Exit

CharStr_Error_Exit::
        INVOKE  leave_driver

        PUBLIC  CS_Exit_no_lock

CS_Exit_no_lock::

        RET

CharStr ENDP

        SUBTITLE UpdateCursor
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = UpdateCursor
;*
;* DESCRIPTION   = This routine implements the functionality of GreUpdateCursor.
;*                 It adjusts the display as necessary to match the text cursor as
;*                 described in *lpPS.
;*
;* INPUT         = C Prototype:
;*                    ErrValue _syscall UpdateCursor(HDC hdc,
;*                                                   VioPresentationSpace32 * lpPS,
;*                                                   PVOID                  hddi,
;*                                                   ULONG                  FunN);
;*
;*                    where:
;*                      All argument are as specified for the GreUpdateCursor function.
;*
;*                  Return values:
;*                    As specified for the GreUpdateCursor function.
;*
;* OUTPUT        =  As specified for the GreUpdateCursor function.
;*
;* RETURN-NORMAL =  As specified for the GreUpdateCursor function.
;* RETURN-ERROR  =  As specified for the GreUpdateCursor function.
;*
;**************************************************************************/

UpdateCursor PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc :HDC,                       ; Handle for the device context to use
                lpPS:DWORD,                     ; Address of the Vio PS to use
                hddc:PVOID,                                      ; Handle for the Display Device Context
                FunN:ULONG                                       ; Index for the desired driver
                                                ; function (presumably
                                                ; UpdateCursor).

        LOCAL   wCellHeight :WORD

IFNDEF CLR2                             ;          
                                        ;          
        LOCAL   wCellWidth  :WORD       ;          
                                        ;          
ENDIF ; CLR2                            ;          

        LOCAL   lpBitmapBits:DWORD
        LOCAL   wDestWidth  :WORD
        LOCAL   wDestHeight :WORD
        LOCAL   wDestBMWidth:WORD
        LOCAL   wSymbolSelectors[4]:DWORD
        LOCAL   wSymbolOffsets[4]:DWORD


        MOV     ESI,hddc
        MOV     EDX,ESI
        ENTER_DRIVER2
        MOV     EAX,CE_INVALID_PRESENTATION_SPACE ; Assume error
        JC      UC_Exit_no_lock
        ddc?    ESI
;/*
;** First we call CheckCodePage to force lpPS->CellImageHeight to a valid
;** value.  wSymbolSelectors and wSymbolOffsets are necessary for the call and
;** irrelevant otherwise.
;*/

        LEA     EAX,wSymbolSelectors
        LEA     EBX,wSymbolOffsets
;V2.1EKF00 INVOKE  CheckCodePage,lpPS,EAX,EBX
        INVOKE  CheckCodePage,lpPS,EAX,EBX,hddc         ;V2.1EKF00

        OR      EAX,EAX
        JZ      UC_Continue
        JMP     UC_Badexit

        PUBLIC  UC_Continue

UC_Continue::
;/*
;** To prepare for display work we must retrieve information about where the
;** location of the screen bitmap and its dimensions.
;** Here we examine the supplied DDC to see if it is a display device
;** (DDC_DEVICE) or something else.
;*/

        MOVZX   ECX,[ESI].DDC.ddc_fb
        TEST    CL,DDC_DEVICE
        JZ      Cursor_updated
        AND     ECX,DDC_VISIBLE
        OR      ECX,NOT COM_DRAW SHR 16
        AND     WORD ptr FunN+2,CX               ; FunN - MSW is commands
        .ERRNZ  COM_DRAW SHR 16 - DDC_VISIBLE
        CMP     fGrimReaper,0                            ; Skip draw if dead
        JZ      @F
        AND     WORD ptr FunN+2,NOT COM_DRAW

@@:
        MOV     EBX,[ESI].DDC.ddc_npsd                   ; EBX -> Surface
        MOV     EAX,[EBX].SURFACE.sd_pBits       ; Copy far pointer to bits
        MOV     lpBitmapBits,EAX
        MOV     EAX,[EBX].SURFACE.sd_cx
        MOV     wDestWidth,AX
        MOV     EAX,[EBX].SURFACE.sd_cy
        MOV     wDestHeight,AX
        MOV     EAX,[EBX].SURFACE.sd_cbScan      ; Copy the width of the bit
        MOV     wDestBMWidth,AX                                  ; array in bytes.
;/*
;** Now we can examine the state of the text cursor fields in the VIO
;** presentation space.
;** First we compare the controlling fields of the PS against the snapshot we
;** keep in our private data.
;*/

        MOV     ESI,lpPS
        MOV     AX,[ESI].VioPresentationSpace32.viops_CellImageHeight
        MOV     wCellHeight,AX

IFNDEF CLR2
            ; CLR2 is only defined when building CGA driver

        MOV     AX,[ESI].VioPresentationSpace32.viops_CellImageWidth
                                                        ; Store char width for
        MOV     wCellWidth,AX                           ; ColToPix later on

ENDIF ; CLR2
;/*
;** Certain flags in the rgfShieldStates field cause drawing actions to be
;** deferred.  Here we examine those flags.
;*/

        MOV     EAX,[ESI].VioPresentationSpace32.viops_rgfShieldStates
        TEST    EAX,fServeNobody
        JZ      Check_for_Limited_Service
        JMP     Cursor_updated

        PUBLIC  Check_for_Limited_Service

Check_for_Limited_Service::
        AND     EAX,(fShieldCalling or fServeShieldOnly)
        CMP     EAX,fServeShieldOnly
        JNE     Service_Allowed
        JMP     Cursor_updated

        PUBLIC  Service_Allowed

Service_Allowed::
        MOV     EDI,ESI
        ADD     ESI,VioPresentationSpace32.viops_WindowOriginRow
        ADD     EDI,VioPresentationSpace32.viops_RowOrgLatch
        CLD
        MOV     CX,(VioPresentationSpace32.viops_XLatch-VioPresentationSpace32.viops_RowOrgLatch)/2
   REPE CMPSW
        MOV     ESI,lpPS
        JNE     Parameters_Changed
        JMP     Parameters_Unchanged

        PUBLIC  Parameters_Changed

Parameters_Changed::
;/*
;** The parameters have changed.  If the cursor is currently visible we need
;** to hide it.
;*/

        TEST    [ESI].VioPresentationSpace32.viops_rgfShieldStates,fCursorShowing
        JZ      Examine_Parameters
        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        MOV     CX,[ESI].VioPresentationSpace32.viops_HeightLatch
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertSplitCursor,
                        hdc,
                        hddc,
                        WORD ptr (FunN+2),
                        lpBitmapBits,
                        wDestHeight,
                        wDestBMWidth,
                        lpPS
        AND     [ESI].VioPresentationSpace32.viops_rgfShieldStates,NOT fCursorShowing

        PUBLIC  Examine_Parameters

Examine_Parameters::
;/*
;** Now we have to compute where the cursor will appear, given the new set of
;** parameters.  The first step is to copy the parameters to the private data
;** area, filtering them as we go.  We also compute the pixel location of the
;** text cursor.  That information is left in VioPresentationSpace.viops_XLatch, VioPresentationSpace.viops_YLatch, VioPresentationSpace.viops_Wi
;** and VioPresentationSpace32.viops_HeightLatch.
;*/

        MOV     AX,[ESI].VioPresentationSpace32.viops_TextCursorWidth
        OR      EAX,EAX
        JZ      Default_Cursor_Width

IFNDEF CLR2                             ; non CGA drivers

        CMP     AX,wCellWidth           ; Get current font width

ELSE ; !CLR2                            ; CGA driver

        CMP     EAX,SymbolImageWidth

ENDIF ; !CLR2                           ;

        JE      Cursor_Width_OK

        PUBLIC  Default_Cursor_Width

Default_Cursor_Width::

IFNDEF CLR2                             ; - non CGA drivers

        MOVZX   EAX,wCellWidth          ; Get current font width

ELSE ; !CLR2                            ; - CGA driver

        MOV     EAX,SymbolImageWidth

ENDIF ; !CLR2                           ;

        MOV     [ESI].VioPresentationSpace32.viops_TextCursorWidth,AX
                                        ; Store it in CursorWidth ;@D2C

        PUBLIC  Cursor_Width_OK

Cursor_Width_OK::
        MOV     [ESI].VioPresentationSpace32.viops_CursorWidth,AL
        MOV     [ESI].VioPresentationSpace32.viops_WidthLatch,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_TextCursorEndLine
        CMP     AX,wCellHeight
        JB      End_Line_OK
        MOV     AX,wCellHeight
        DEC     AX
        MOV     [ESI].VioPresentationSpace32.viops_TextCursorEndLine,AX

        PUBLIC  End_Line_OK

End_Line_OK::
        MOV     [ESI].VioPresentationSpace32.viops_CursorEndLine,AX
        MOV     BX,[ESI].VioPresentationSpace32.viops_TextCursorStartLine
        CMP     BX,wCellHeight
        JB      Start_Line_OK
        MOV     BX,wCellHeight
        DEC     BX
        MOV     [ESI].VioPresentationSpace32.viops_TextCursorStartLine,BX

        PUBLIC  Start_Line_OK

Start_Line_OK::
        MOV     [ESI].VioPresentationSpace32.viops_CursorStartLine,BX
        SUB     AX,BX
        JNS     Solid_cursor2
        MOV     AX,wCellHeight
        JMP     SHORT save_height

        PUBLIC  Solid_cursor2

Solid_cursor2::
        INC     AX

        PUBLIC  save_height

save_height::
        MOV     [ESI].VioPresentationSpace32.viops_HeightLatch,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_TextCursorRow
        CMP     AX,[ESI].VioPresentationSpace32.viops_BufferRowCount
        JB      Cursor_Row_OK
        MOV     AX,[ESI].VioPresentationSpace32.viops_BufferRowCount
        DEC     AX
        MOV     [ESI].VioPresentationSpace32.viops_TextCursorRow,AX

        PUBLIC  Cursor_Row_OK

Cursor_Row_OK::
        MOV     [ESI].VioPresentationSpace32.viops_CursorRow,AX
        MOV     CX,[ESI].VioPresentationSpace32.viops_WindowOriginRow
        MOV     [ESI].VioPresentationSpace32.viops_RowOrgLatch,CX
        SUB     AX,CX
        INC     AX
        MUL     wCellHeight
        MOV     BX,[ESI].VioPresentationSpace32.viops_CursorEndLine
        CMP     BX,[ESI].VioPresentationSpace32.viops_CursorStartLine
        JAE     Solid_cursor3
        SUB     AX,wCellHeight
        JMP     Save_Y_offset

        PUBLIC  Solid_cursor3

Solid_cursor3::
        DEC     AX
        SUB     AX,BX

        PUBLIC  Save_Y_offset

Save_Y_offset::
        MOV     [ESI].VioPresentationSpace32.viops_YLatch,AX
        MOV     AX,[ESI].VioPresentationSpace32.viops_TextCursorColumn
        CMP     AX,[ESI].VioPresentationSpace32.viops_BufferColumnCount
        JB      Cursor_Col_OK
        MOV     AX,[ESI].VioPresentationSpace32.viops_BufferColumnCount
        DEC     AX
        MOV     [ESI].VioPresentationSpace32.viops_TextCursorColumn,AX

        PUBLIC  Cursor_Col_OK

Cursor_Col_OK::
        MOV     [ESI].VioPresentationSpace32.viops_CursorCol,AX
        MOV     CX,[ESI].VioPresentationSpace32.viops_WindowOriginColumn
        MOV     [ESI].VioPresentationSpace32.viops_ColOrgLatch,CX
        SUB     AX,CX
        ColToPix AX
        MOV     [ESI].VioPresentationSpace32.viops_XLatch,AX

        PUBLIC  Parameters_Unchanged

Parameters_Unchanged::

;/*
;** When we get here the VioPresentationSpace32.viops_XLatch,
;** VioPresentationSpace32.viops_YLatch, VioPresentationSpace32.viops_WidthLatch,
;** and VioPresentationSpace32.viops_HeightLatch fields are synchronized with the
;** public cursor state fields.  Now we must decide whether the cursor should
;** be visible.  It must be visible if:
;**
;**       -- This window has the input focus
;**       -- the TextCursorVisible flag is non-zero
;**  and
;**       -- the fCursorIsOn flag is on.
;**
;** Otherwise it should not be visible.
;*/


        MOV     EAX,[ESI].VioPresentationSpace32.viops_rgfShieldStates
        TEST    EAX,fHasTheFocus
        JZ      Hide_The_Cursor
        MOV     EBX,[ESI].VioPresentationSpace32.viops_TextCursorVisible
        OR      BX,BX
        JZ      Hide_The_Cursor
        TEST    AX,fCursorIsOn
        JZ      Hide_The_Cursor
        TEST    AX,fCursorShowing
        JNZ     Cursor_updated
        OR      [ESI].VioPresentationSpace32.viops_rgfShieldStates,fCursorShowing
        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        MOV     CX,[ESI].VioPresentationSpace32.viops_HeightLatch
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertSplitCursor,
                        hdc,
                        hddc,
                        WORD ptr (FunN+2),
                        lpBitmapBits,
                        wDestHeight,
                        wDestBMWidth,
                        lpPS
        JMP     Cursor_updated

        PUBLIC  Hide_The_Cursor

Hide_The_Cursor::
        TEST    AX,fCursorShowing
        JZ      Cursor_updated
        AND     [ESI].VioPresentationSpace32.viops_rgfShieldStates,NOT fCursorShowing
        MOV     AX,[ESI].VioPresentationSpace32.viops_XLatch
        MOV     BX,[ESI].VioPresentationSpace32.viops_YLatch
        MOV     CX,[ESI].VioPresentationSpace32.viops_HeightLatch
        MOV     DX,[ESI].VioPresentationSpace32.viops_WidthLatch
        INVOKE  InvertSplitCursor,
                        hdc,
                        hddc,
                        WORD ptr (FunN+2),
                        lpBitmapBits,
                        wDestHeight,
                        wDestBMWidth,
                        lpPS
        errn$   Cursor_updated

        PUBLIC  Cursor_updated

Cursor_updated::
        XOR     EAX,EAX

        PUBLIC  UC_Badexit

UC_Badexit::
        MOV     ESI,hddc
        INVOKE  leave_driver

        PUBLIC  UC_Exit_no_lock

UC_Exit_no_lock::

        RET

UpdateCursor ENDP


        SUBTITLE DeviceSetAVIOFont2
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSetAVIOFont2
;*
;* DESCRIPTION   =
;*       This routine binds a loaded font to one of the extended LCID's for an
;*       AVIO presentation space (1..3).  The font to be loaded must be fixed
;*       pitch and must match the cell width and height requirements of the the
;*       current device.  Its result will be TRUE if the binding was successfully
;*       constructed and FALSE otherwise.
;*
;*      Side Effects: A successful binding will involve altering entries in the
;*                   VioPresentationSpace32.viops_selFontsLoaded and
;*                   VioPresentationSpace32.viops_npMapFontsLoaded arrays of the
;*                   AVio presentation space corresponding to hdc.
;*
;*      Warnings: If lpFattr is NULL the default codepage of the font is used.
;*
;* INPUT         = C Prototype:
;*                   BOOL _syscall DeviceSetAVIOFont2 (HDC   hdc,
;*                                                     LONG  lpFattr,
;*                                                     ULONG FontDef,
;*                                                     ULONG inxLCID,
;*                                                     HDDC  hddc,
;*                                                     ULONG inxFn);
;*             where:
;*             All arguments are as specified for the GreDeviceSetAVIOFont function
;*
;* OUTPUT        = As specified for the GreDeviceSetAVIOFont function.
;*
;* RETURN-NORMAL = As specified for the GreDeviceSetAVIOFont function.
;* RETURN-ERROR  = As specified for the GreDeviceSetAVIOFont function.
;*
;**************************************************************************/

DeviceSetAVIOFont2 PROC SYSCALL PUBLIC USES EBX,
                hdc    :DWORD,
                pFattr :DWORD,
                FontDef:DWORD,
                inxLCID:DWORD,
                hDDC   :DWORD,
                inxFn  :DWORD

        LOCAL   lpAVioPS    :DWORD
;V2.1EKF00 LOCAL   cpidCodePage:WORD
        LOCAL   cpidCodePage:DWORD              ;V2.1EKF00
        LOCAL   npCPMap     :DWORD
        LOCAL   inx         :WORD

;/*
;** First we map HDC to lpAVioPS, the address for the AVIO PS.  We do this by
;** calling GreGetHandle for slot 1 and then validating the returned value by
;** calling VioGetPSAddress, which will return zero if it is a valid PS address.
;*/

        INVOKE  Gre32Entry4,hdc,AVIO_PS_HANDLE_INDEX,0,NGreGetHandle
        OR      EAX,EAX
        JNZ     DSAF_50
        MOV     EAX,PMERR_INV_HDC
        JMP     Error_exit_DeviceSetAVIOFont2

        PUBLIC  DSAF_50

DSAF_50::
        MOV     EDX,EAX

;V2.1EKF00        EXTERN  ring3_VioGetPSAddress:NEAR
;V2.1EKF00        INVOKE  Vga32CallBack,OFFSET ring3_VioGetPSAddress

        MOV     lpAVioPS,EAX
        OR      EAX,EAX                         ; lpAVioPS non-null?
        JNZ     DSAF_100                                         ; then continue
        MOV     EAX,PMERR_INV_HDC                        ; else error
        JMP     Error_exit_DeviceSetAVIOFont2

        PUBLIC  DSAF_100

DSAF_100::
;/*
;** Next we examine the FontDef parameter to see if it defines a usable font
;** segment.
;*/

        MOV     EAX,FontDef
        OR      EAX,EAX
        JNZ     Non_null_fontdef
;/*
;** A null FontDef means that we should clear out the VioPS info for the
;** specified LCID.
;*/

        MOV     npCPMap,EAX
        JMP     Verify_the_LCID_index

        PUBLIC  Bad_FontDef

Bad_FontDef::
        MOV     EAX,PMERR_FONT_NOT_LOADED
        JMP     Error_exit_DeviceSetAVIOFont2

        PUBLIC  Non_null_fontdef

Non_null_fontdef::
        MOV     ESI,FontDef                                      ; Offset must be zero!
        OR      ESI,ESI
        TEST    [ESI].FOCAFONT.ff_fmMetrics.foca_fsTypeFlags,1 ; Fixed pitch
                                                                ; font?
        JZ      Inv_font_attrs
;/*
;** The image shape for the font must match the default cell shape or the
;** alternate (small) cell shape.
;*/

;                  MOV     AX,[ESI].FOCAFONT.ff_fdDefinitions.fdh_xCellWidth
;                  movzx   eax,ax
;                  MOV     BX,[ESI].FOCAFONT.ff_fdDefinitions.fdh_yCellHeight
;                  movzx   ebx,bx
;                  CMP     EBX,adDevCapsData[DEF_HEIGHT_OFFSET]
;                  JNE     Try_alternate_cell_shape
;                  CMP     EAX,adDevCapsData[DEF_WIDTH_OFFSET]
;                  JE      Acceptable_cell_shape
;          
;                  PUBLIC  Try_alternate_cell_shape
;          
;                                    
;                  CMP     EBX,adDevCapsData[ALT_HEIGHT_OFFSET]
;                  JNE     Inv_font_attrs
;                  CMP     EAX,adDevCapsData[ALT_WIDTH_OFFSET]
;                  JE      Acceptable_cell_shape

;Start new code for           
        mov     ax,[ESI].FOCAFONT.ff_fdDefinitions.fdh_xCellWidth      ; get requested cell-width
        movzx   eax,ax
        mov     dx,[ESI].FOCAFONT.ff_fdDefinitions.fdh_yCellHeight     ; get requested cell-height
        movzx   edx,dx

        mov     ecx,cDevVioCells         ; get count of available sizes
        lea     ebx,adDevVioCells        ; point to first entry in table

dsaf_230:
        cmp     eax,es:cf_width[ebx]      ; if requested width less than...       vcb
        jb      Inv_font_attrs          ; ...width from table it isn't in...      vcb
                                        ; ...the table                            vcb
        ja      dsaf_250                ; if it's greater then try the next one   vcb

        cmp     edx,es:cf_height[ebx]   ; if requested height matches then...     vcb
        je      Acceptable_cell_shape   ; ...found it                             vcb
        jb      Inv_font_attrs          ; if it's less then it isn't in table     vcb

dsaf_250:
        add     ebx,size CellFont        ; move to next entry                     vcb
        loop    dsaf_230                ; iterate                                 vcb
;End new code for           

        PUBLIC  Inv_font_attrs

Inv_font_attrs::
        MOV     EAX,PMERR_INV_FONT_ATTRS

        PUBLIC  Error_exit_DeviceSetAVIOFont2

Error_exit_DeviceSetAVIOFont2::
        save_error_code
        XOR     EAX,EAX
        JMP     Exit_DeviceSetAVIOFont2

;/*
;** Now we construct a reference to the code page mapping vector for this font.
;*/

        PUBLIC  Acceptable_cell_shape

Acceptable_cell_shape::
        MOV     AX,[ESI].FOCAFONT.ff_fmMetrics.foca_usCodePage ; Set font's
                                                                ; codepage
;/*
;** Use the logical font codepage if it is available.  Because we may be
;** simulating the old DeviceSetAVIOFont the pFattr parameter may be NULL.
;*/

        MOV     EBX,pFattr
        OR      EBX,EBX
        JZ      DSAF_codepage_set
        MOV     AX,[EBX].FATTRS.fat_usCodePage

        PUBLIC  DSAF_codepage_set

DSAF_codepage_set::
;                  MOV     cpidCodePage,AX
        MOV     cpidCodePage,EAX                        ;          
        LEA     EBX,cpidCodePage
        LEA     ECX,npCPMap
        INVOKE  Force_Valid_CP,EBX,ECX
        OR      EAX,EAX
        JZ      DSAF_300
        MOV     EAX,ERROR_VIO_BAD_CP
        JMP     Error_exit_DeviceSetAVIOFont2

        PUBLIC  DSAF_300

DSAF_300::

;/*
;** Check the range of the LCID index
;*/

        PUBLIC  Verify_the_LCID_index

Verify_the_LCID_index::
        PUBLIC  DSAF_400

DSAF_400::
        MOV     ESI,inxLCID
        NOT     ESI
        DEC     ESI
        CMP     ESI,CNT_LOADABLE_LCIDS
        JB      DSAF_500
        MOV     EAX,PMERR_INV_SETID
        JMP     Error_exit_DeviceSetAVIOFont2

        PUBLIC  DSAF_500

DSAF_500::

;/*
;** All OK.  Store the font selector and the mapping offset.
;*/

;        mov     edi,lpAVioPS
        mov     edi,hDDC                                                ;          
        SHL     ESI,1
        MOV     EAX,FontDef
;       MOV     [edi].VioPresentationSpace32.viops_pFontsLoaded[esi],EAX
        mov     [edi].DDC.ddc_FontsLoaded[esi], EAX                     ;           
        MOV     EAX,npCPMap
;       MOV     [edi].VioPresentationSpace32.viops_pMapFontsLoaded[esi],EAX
        mov     [edi].DDC.ddc_MapFontsLoaded[esi], EAX                  ;          
        MOV     EAX,1

        PUBLIC  Exit_DeviceSetAVIOFont2

Exit_DeviceSetAVIOFont2::


        RET

DeviceSetAVIOFont2 ENDP

_AvioSupport ENDS

        END
