;*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    60,132
        TITLE   WDHBUFUP.ASM -- Buffer Update Routine for Windows

;/*****************************************************************************
;*
;* SOURCE FILE NAME = WDHBUFUP.ASM
;*
;* DESCRIPTIVE NAME = Buffer Update Routine for Windows
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  Mainline routine for video buffer read, write,
;*              scroll functions.
;*
;*   LINKAGE:   Far Call from Base Video Subsystem (BVSCALLS.DLL)
;*
;* INPUT:       STACK FRAME on entry
;*
;* SS:SP  --->  bvsip           dw      BVS IP offset
;*              bvscs           dw      BVS CS selector
;*              parmn           dd      Function number (256)
;*              parmnm2         dd      Parameter block
;*              parmnm4         dd      Environment buffer
;*
;*
;* PARAMETER BLOCK FORMAT:
;*
;*   SIZE   DESCRIPTION
;*   ----   -----------
;*
;*   WORD   ParmLength (length of structure - 28 bytes)
;*   WORD   Flags
;*            Bit 0 = 0, do not update physical display buffer
;*            Bit 0 = 1, update physical display buffer if possible
;*            Bit 1 = 0, logical display buffer update not required
;*            Bit 1 = 1, update logical display buffer
;*            Bit 2 = 0, use attribute as is
;*            Bit 2 = 1, convert attribute to or from CGA format
;*            Bit 3 - 15 are reserved and must be OFF
;*
;*          NOTE:  If bit 0 and 1 are both ON then the LVB will
;*                 be written first before the PVB is updated.
;*                 This will ensure that video devices with
;*                 slower VRAM will benefit from this algorithm.
;*
;*                 The caller of BufferUpdate routine (BVS) must
;*                 serialize access to this routine to insure
;*                 that the LVB and the PVB will not get out of sync.
;*
;*   DWORD  AppDataAddr (address of application data)
;*   DWORD  AppCellAddr (address of character, attribute, or cell)
;*   WORD   Index (BufferUpdate sub-function to be performed)
;*            0 = Read cell types
;*                  Bit 0 = 0, single cell character
;*                             (occupies one cell on the screen)
;*                  Bit 0 = 1, double cell character
;*                             (occupies two cells on the screen)
;*                  Bit 1 = 0, leading (or only) cell
;*                  Bit 1 = 1, trailing cell
;*                  Bit 2 - 15 are reserved and must be OFF
;*            1 = Read characters from (Row, Col)
;*            2 = Read cells from (Row, Col)
;*            3 = Scroll (Row, Col) through (Row2, Col2) Up
;*            4 = Scroll (Row, Col) through (Row2, Col2) Down
;*            5 = Scroll (Row, Col) through (Row2, Col2) Left
;*            6 = Scroll (Row, Col) through (Row2, Col2) Right
;*            7 = Write cells to (Row, Col)
;*            8 = Write characters to (Row, Col)
;*            9 = Write characters with constant attr to (Row, Col)
;*           10 = Write repeat character to (Row, Col)
;*           11 = Write repeat attribute to (Row, Col)
;*           12 = Write repeat cell to (Row, Col)
;*   WORD   Row  (Starting row)
;*   WORD   Col  (Starting column)
;*   WORD   Row2 (Secondary row)
;*   WORD   Col2 (Secondary column)
;*   WORD   RepeatFactor (# of character cells or rows/columns)
;*   WORD   LogicalBufSel (logical buffer selector - LVB)
;*
;*
;* ENVIRONMENT BUFFER FORMAT:
;*
;*   SIZE   DESCRIPTION
;*   ----   -----------
;*   WORD   ModeDataOff (offset to mode data structure)
;*
;*
;* MODEDATA STRUCTURE FORMAT:
;*
;*   SIZE   DESCRIPTION
;*   ----   -----------
;*   WORD   Length (length of mode data structure - 34 bytes)
;*   BYTE   ModeType
;*            Bit 0 = 0, monochrome compatible
;*            Bit 0 = 1, other
;*            Bit 1 = 0, text mode
;*            Bit 1 = 1, graphics mode
;*            Bit 2 = 0, enable color burst
;*            Bit 2 = 1, disable color burst
;*            Bit 3 = 0, VGA compatible modes (0 - 13h)
;*            Bit 3 = 1, native mode
;*            Bit 4 - 15 are reserved
;*   BYTE   Color (number of colors as a power of 2)
;*   WORD   TextCols (number of text columns in current mode)
;*   WORD   TextRows (number of text rows in current mode)
;*   WORD   HorizRes (horizontal pel resolution)
;*   WORD   VertRes (vertical pel resolution)
;*   BYTE   AttrFormat (attribute format)
;*   BYTE   NAttributes (number of attributes in a character cell)
;*  DWORD   BufferAddr (32-bit physical address of PVB)
;*  DWORD   BufferLength (length of PVB in current mode)
;*  DWORD   FullBufSize (size of buffer required for screen save)
;*  DWORD   PartBufSize (size of buffer for popup save)
;*  DWORD   ExtDataAddr (extended mode data structure address)
;*
;* EXIT-NORMAL: AX = 0
;*
;* EXIT-ERROR:  AX = error code, ERROR_VIO_COL
;*                               ERROR_VIO_INVALID_LENGTH
;*                               ERROR_VIO_INVALID_PARMS
;*                               ERRPR_VIO_MODE
;*                               ERROR_VIO_ROW
;*                               ERROR_VIO_INTERNAL_RESOURCE
;*
;* EFFECTS:     All other registers are preserved
;*
;* INTERNAL REFERENCES: None
;*
;* EXTERNAL REFERENCES: ReadCellTypes           in XGAREAD.ASM
;*                      ReadCharStr             in XGAREAD.ASM
;*                      ReadCellStr             in XGAREAD.ASM
;*                      ScrollUp                in XGASCROL.ASM
;*                      ScrollDown              in XGASCROL.ASM
;*                      ScrollLeft              in XGASCROL.ASM
;*                      ScrollRight             in XGASCROL.ASM
;*                      WriteCellStr            in XGAWRITE.ASM
;*                      WriteCharStr            in XGAWRITE.ASM
;*                      WriteCharStrAttr        in XGAWRITE.ASM
;*                      WriteNChar              in XGAWRITE.ASM
;*                      WriteNAttr              in XGAWRITE.ASM
;*                      WriteNCell              in XGAWRITE.ASM
;*
;* FUNCTIONS    BUFFERUPDATE
;*              DummyLVBToPVB
;*              SetGenParms
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES  NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* PSEUDOCODE
;*
;*      Begin BufferUpdate
;*          Preset return code to ERROR_VIO_MODE
;*          If text mode
;*              Preset return code to ERROR_VIO_INVALID_LENGTH
;*              If correct parameter length
;*                  Preset return code to ERROR_VIO_INVALID_PARMS
;*                  If valid reserved flags     AND
;*                  If valid video buffer flags AND
;*                  If valid function number    AND
;*                  If valid index number
;*                      Call Read/Write/Scroll routines
;*                  Endif
;*              Endif
;*          Endif
;*      End BufferUpdate
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;*   03/25/89  @P1        D132    TPL, DCR 132 changes
;*   05/01/89  @C19       HM00550 CJJ, Clear carry flag for SetBuffAddr
;*                                routine,
;*   08/19/89  @S23       B706727 CJJ,TLB Save pssel in instance data,
;*   11/02/89  @D549      D549    CJJ, Seltable changes due to rangeless
;*                                sessions,
;*   01/22/90  @T52       D704    TPL, DCR 704 work
;*             @B55       B788870 WKB, Convert bytes to cell value for graphics
;*                                engine call
;*   04/11/91  D1348      D1348   NAKADA, Enable DBCS support in Vio-Window
;*   09/14/94  @95837             WKB, pmwinp.inc -> pmwinx.inc
;****************************************************************************/

        .xlist
        include bvscb.inc               ;BVS Control Blocks     @S23
        INCLUDE struc.inc               ; Structure macro
        INCLUDE error2.inc              ; Subsystem error equates
        INCLUDE vdhstruc.inc            ; Buffer update data structures
        INCLUDE vdhequ.inc              ; Buffer update equates
        .xlist

        EXTRN   ReadCellTypes    : NEAR ; 
        EXTRN   ReadCharStr      : NEAR ; VioReadCharStr
        EXTRN   ReadCellStr      : NEAR ; VioReadCellStr
        EXTRN   ScrollUp         : NEAR ; VioScrollUp
        EXTRN   ScrollDown       : NEAR ; VioScrollDn
        EXTRN   ScrollLeft       : NEAR ; VioScrollLt
        EXTRN   ScrollRight      : NEAR ; VioScrollRt
        EXTRN   WriteCellStr     : NEAR ; VioWriteCellStr
        EXTRN   WriteCharStr     : NEAR ; VioWriteCharStr
        EXTRN   WriteCharStrAttr : NEAR ; VioWriteCharStrAttr
        EXTRN   WriteNChar       : NEAR ; VioWriteNChar
        EXTRN   WriteNAttr       : NEAR ; VioWriteNAttr
        EXTRN   WriteNCell       : NEAR ; VioWriteNCell

        EXTRN   bvh_instance     : DWORD                                ;@T52

;/*
;**  Start of window specific code
;*/

        .xlist
        include pmwinx.inc              ;@95387
        include pmaviop.inc
        include wdhequ.inc              ; WDH Equates
        include bvsparms.inc            ; BVS Parameter Equates
        .list

        .386p                   ;@D549

        extrn   SecureSema4:NEAR
        extrn   ReleaseSema4:NEAR
        extrn   CharStr:NEAR
        extrn   WinScroll:NEAR

;/*
;**  End of window specific code
;*/

        PUBLIC  BUFFERUPDATE
        PUBLIC  DispTbl

WDHGSEG SEGMENT PARA PUBLIC 'DATA' USE16                                ;@T52
WDHGSEG ENDS                                                            ;@T52


R2CSEG  SEGMENT WORD    PUBLIC 'CODE' USE16     ;@D549
        ASSUME  CS:R2CSEG,DS:NOTHING,ES:NOTHING

DispTbl DW      OFFSET R2CSEG:ReadCellTypes ; 
        DW      OFFSET R2CSEG:ReadCharStr ; Read characters
        DW      OFFSET R2CSEG:ReadCellStr ; Read character/attribute 's
        DW      OFFSET R2CSEG:ScrollUp  ; Scroll window up
        DW      OFFSET R2CSEG:ScrollDown ; Scroll window down
        DW      OFFSET R2CSEG:ScrollLeft ; Scroll window left
        DW      OFFSET R2CSEG:ScrollRight ; Scroll window right
        DW      OFFSET R2CSEG:WriteCellStr ; Write character/attribute 's
        DW      OFFSET R2CSEG:WriteCharStr ; Write characters
        DW      OFFSET R2CSEG:WriteCharStrAttr ; Write characters with attr
        DW      OFFSET R2CSEG:WriteNChar ; Write character N times
        DW      OFFSET R2CSEG:WriteNAttr ; Write attribute N times
        DW      OFFSET R2CSEG:WriteNCell ; Write cell N times
        DW      OFFSET R2CSEG:DummyLVBToPVB ; Copy a rect of LVB to the PVB @P1

;/****************************************************************************
;*
;* FUNCTION NAME = BUFFERUPDATE
;*
;* DESCRIPTION   =
;*
;*           This mainline routine checks all high level errors before
;*           control is transfer to the worker routine.
;*           On entry to each worker routine, the following registers
;*           are setup:
;*
;* INPUT     =   DS:SI -> Parameter block buffer
;*               ES:DI -> Mode data structure in the environment buffer
;*               SS:BP -> Parameter stack frame
;*
;*               All registers are preserved
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

BUFFERUPDATE PROC FAR


        sub     sp, bottomdest-PVB_Sel+2; Allocate storage for: PVB selector @P1
                                        ;                       Scroll parms
        push    bp                      ; Save caller's BP
        mov     bp, sp                  ; Establish parameter addressability
        pusha                           ; Save all registers
        push    ds                      ; 
        push    es                      ; 
        les     di, [bp].EnvBufParm     ; ES:DI -> environment buffer

IFDEF D1348
                                        ;/prepare the 2nd LVB for DBCS flag
        mov     ax,es:[di].env_lvbsize
        mov     [bp].j_lvbsize,ax
        mov     ax,es:[di].env_funcindx
        mov     [bp].j_funcindx,ax
        mov     [bp].j_dbcsstatus,0     ; clear bisecting flag

        mov     ax,es:[di].viops_CellByteSize
        mov     [bp].cellsize,ax

        mov     ax,word ptr es:[di].viops_lpNLSExt   ; get the pointer to nls exteded env.
        mov     word ptr [bp].lpNLSExt,ax
        mov     ax,word ptr es:[di+2].viops_lpNLSExt
        mov     word ptr [bp+2].lpNLSExt,ax

        mov     [bp].flgDBCS,0          ;/set dbcs flag
                                        ; 0         : there is no dbcs.
                                        ; otherwize : one or more dbcs exist(s).
        .if     <<es:[di].env_DBCSEvBuff>  ne 0> or
            or      [bp].flgDBCS,defaultDBCS
        .if     <<es:[di].env_DBCSEvBuff1> ne 0> or
        .if     <<es:[di].env_DBCSEvBuff2> ne 0> or
        .if     <<es:[di].env_DBCSEvBuff3> ne 0>
            or      [bp].flgDBCS,AvioDBCS
        .endif
ENDIF ;D1348

        push    WDHGSEG                                                 ;@T52
        pop     ds                      ; @S23
        lds     bx,ds:bvh_instance      ;                               ;@T52
        mov     [bx].wdhi_pssel,es      ; @S23 Save PS selector in instance data

        add     di, env_mdlen           ; ES:DI -> mode data structure
        mov     ax, ERROR_VIO_MODE      ; Preset invalid mode error

        lds     si, [bp].ParmBuf        ; DS:SI -> parameter buffer
IFDEF D1348
        mov     ax,[si].Flags
        mov     [bp].shadow_Flags,ax
ENDIF ;D1348
        mov     ax, ERROR_VIO_INVALID_LENGTH ; Preset error code
        .if     <[si].ParmLength ae LogicalBufSel+2> NEAR  ; Valid parm length? @P1
            mov     ax, ERROR_VIO_INVALID_PARMS ; Preset error code
            test    [si].Flags, RESERVED_FLAGS ; 
            .if     <z>                         AND ; Valid reserved flags?
            .if     <[bp].FuncNumHi e 0>        AND ; Correct function #?
            .if     <[bp].FuncNumLo e FUNC_NUM> AND ; 
            .if     <[si].FuncIndex be MAX_INDEX> ; Invalid index?

                sub     ax, ax          ; Clear return code
                push    ds
                push    si
                push    es
                push    di

                cld
                mov     bx, [si].FuncIndex
                shl     bx, 1           ; Word align jump table
                call    cs:DispTbl[bx]  ; Dispatch to handler

;/*
;**   Start of window specific code
;*/

                pop     di
                pop     es
                pop     si
                pop     ds

                .if     <zero ax>
                    mov     dx,[si].vp_index ;Get the subroutine index
                    sub     bx,bx

                    .if     <dl ae sx_ScrollUp> and
                    .if     <dl be sx_WriteNCell> ;Update window
                        Call    SecureSema4

IFDEF D1348 ;DBCS BufferUpdate (bisecting DBCS character status)
                        mov     ax,[bp].j_dbcsstatus
                        mov     es:[bx].env_dbcsstatus,ax
ENDIF ;D1348

                        .if     <dl ae sx_WriteCellStr> ;Writing
                            .if     <dl e sx_WriteCellStr> ;Writing     ;@B55
                               mov     ax,[si].vp_repeatlength          ;@B55
                               shr     ax,1                             ;@B55
                               mov     [si].vp_repeatlength,ax          ;@B55
                            .endif                                      ;@B55
                            Call    CharStr
                        .else           ;Scrolling
                            Call    WinScroll
                        .endif

                        Call    ReleaseSema4
                        sub     ax,ax
                    .endif
                .endif

;/*
;**  End of window specific code
;*/

            .endif
        .endif

        mov     [bp-2], ax
        pop     es
        pop     ds
        popa
        pop     bp
        add     sp, bottomdest          ; Deallocate local storage

        ret     12

BUFFERUPDATE ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = DummyLVBToPVB
;*
;* DESCRIPTION   =
;*
;*      DummyLVBToPVB replaces the function LVBToPVB.  The LVBToPVB copies
;*      a rectangle from the LVB onto the PVB.  Since the LVB == PVB for
;*      the windowed VDH, this function is a NOP.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 0
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

                PUBLIC  DummyLVBToPVB                           ;@P1 begin
DummyLVBToPVB   PROC                                            ; 
                                                                ; 
        xor     ax,ax                   ; return good error code;
        ret                                                     ; 
                                                                ; 
DummyLVBToPVB   ENDP                                            ;@P1 end


;/****************************************************************************
;*
;* FUNCTION NAME = SetGenParms
;*
;* DESCRIPTION   = Set general parameters used by all buffer update functions
;*
;*      SetGenParms sets up basic information relating to LVB substitution.
;*      The routine sets up the boundaries for the write based on whether
;*      the LVB has been superceeded by passed parameters.
;*
;* INPUT         = SS:BP - local data storage area
;*                 DS:SI - user passed parameter block
;*                 ES:DI - mode data structure
;*
;* OUTPUT       AX - index of right most row in LVB
;*              CX - index of bottom most column in LVB
;*              [bp].minrow - index of top most row in LVB (PVB coordinates)
;*              [bp].mincol - index of left most col in LVB (PVB coordinates)
;*              [bp].maxrow - index of bottom most row in LVB (PVB coordinates)
;*              [bp].maxcol - index of right most col in LVB (PVB coordinates)
;*              [bp].lvb_width - width of the LVB in cells
;*              [bp].lvb_height - height of the LVB in cells
;*
;*      CALLS   none
;*
;*      USES    AX,CX,DX,FLAGS
;*
;*      NOTES
;*
;*  PSEUDOCODE
;*
;*      PVB_SEL = 0
;*      LVB_SEL = parmLVB
;*      cellsize = VioPSCellByteSize
;*
;*      if (parmlength >= LVBHeight)
;*          mincol = parmLVBColOff
;*          maxcol = parmLVBWidth + mincol
;*          minrow = parmLVBRowOff
;*          maxrow = parmLVBHeight + minrow
;*          lvb_width = parmLVBWidth
;*          lvb_height = parmLVBHeight
;*          if (parmlength >= LVBAttrCount)
;*              if (parmAttrCount == 3)
;*                  cellsize = 4
;*              else
;*                  cellsize = 2
;*      else
;*          mincol = 0
;*          maxcol = modeCols - 1
;*          minrow = 0
;*          maxrow = modeRows - 1
;*          lvb_width = modeCols
;*          lvb_height = modeRows
;*          cellsize = modeattrcnt + 1
;*
;* RETURN-NORMAL = AX = 0
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

                PUBLIC  SetGenParms                             ;@P1 begin
SetGenParms     PROC

        mov     [bp].PVB_Sel,0          ; do not use PVB selector
        mov     ax, [si].LogicalBufSel  ; use LVB selector
        mov     [bp].LVB_Sel,ax         ; save the LVB selector

        mov     ax,es:viops_CellByteSize
        mov     [bp].cellsize,ax

        cmp     ds:[si].ParmLength,LVBFormatID  ; Did the caller specify LVB info?
        .if     <ae>                        ;   Yes, use callers information
            mov     cx,ds:[si].LVBColOff    ; (cx) = left most column
            mov     [bp].mincol,cx          ; store left most column
            mov     dx,ds:[si].LVBWidth     ; (dx) = number of columns
            mov     [bp].lvb_width,dx       ; store number of columns
            add     cx,dx                   ; (cx) = right most column + 1
            dec     cx                      ; (cx) = right most column
            mov     [bp].maxcol,cx          ; store right most column
            mov     ax,ds:[si].LVBRowOff    ; (ax) = top most row
            mov     [bp].minrow,ax          ; store top most row
            mov     dx,ds:[si].LVBHeight    ; (dx) = number of rows
            mov     [bp].lvb_height,dx      ; store number of rows
            add     ax,dx                   ; (ax) = bottom most row + 1
            dec     ax                      ; (ax) = bottom most row
            mov     [bp].maxrow,ax          ; store bottom most row
            cmp     ds:[si].ParmLength,LVBAttrCount + 1 ; Is the parm present?
            .if     <ae> and near           ;   Yes, attribute count is included
            cmp     word ptr ds:[si].LVBFormatID,WorldFMTATTR   ; Special format?
IFDEF D1348 ;support format ID 00h, attr count 3. (un-necessary ?)
            .if     <e> or near             ;   Yes, use three byte attributes
            cmp     word ptr ds:[si].LVBFormatID,ExtPSFMTATTR
ENDIF ;D1348
            .if     <e> near                ;   Yes, use three byte attributes
                mov     [bp].cellsize,WorldCellSize
            .else
                mov     [bp].cellsize,DefaultCellSize
            .endif
        .else                               ; Use default screen group information
            mov     [bp].mincol,0           ; store left most column
            mov     cx,es:[di].TextCols     ; (ax) = number of columns
            mov     [bp].lvb_width,cx       ; store number of columns
            dec     cx                      ; (ax) = right most column
            mov     [bp].maxcol,cx          ; store right most column
            mov     [bp].minrow,0           ; store top most row
            mov     ax,es:[di].TextRows     ; (ax) = number of rows
            mov     [bp].lvb_height,ax      ; store number of rows
            dec     ax                      ; (ax) = bottom most row
            mov     [bp].maxrow,ax          ; store bottom most row
            cmp     [bp].cellsize,ExtAttrib ; clear carry if extended attr @C19
        .endif

        ret

SetGenParms     ENDP                                            ;@P1 end

R2CSEG  ENDS
        END

