;*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   CGAWRITE.ASM -- CGA Buffer Write Routines

;/*****************************************************************************
;*
;* SOURCE FILE NAME = CGAWRITE.ASM
;*
;* DESCRIPTIVE NAME = CGA Buffer Write Routines 
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* DESCRIPTION  BUFFERUPDATE write routines    
;*
;* FUNCTIONS    WriteCellStr, WriteCharStr, WriteCharStrAttr,  
;*              WriteNChar, WriteNAttr, WriteNCell             
;*
;* NOTES        NONE
;*             
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES: LocateBuffAddr           (in CGAREAD.ASM)  
;*                      STOSB_SKIP_DI, _MOVSW, MOVSB_STOSB, _STOSW 
;*                      MOVSB_SKIP_DI                
;*                                                    
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;****************************************************************************/

        .286c                                     ; 286 protect mode instructions

        .xlist
        INCLUDE struc.inc                         ; Structure macro
        INCLUDE error2.inc                        ; Subsystem error equates
        INCLUDE vdhstruc.inc                      ; Buffer update data structures
        INCLUDE vdhequ.inc                        ; Buffer update equates
        .list

        EXTRN   LocateBuffAddr : NEAR             ; Determine target/source buffer
        EXTRN   _MOVSW         : FAR              ; Move words from DS:SI to ES:DI
        EXTRN   _STOSW         : FAR              ; Store words from DS:SI to ES:DI
        EXTRN   MOVSB_STOSB    : FAR              ; Move byte from DS:SI to ES:DI
                                                  ;   and store AL to ES:DI
        EXTRN   MOVSB_SKIP_DI  : FAR              ; Move byte DS:SI to ES:DI
        EXTRN   STOSB_SKIP_DI  : FAR              ; Store AL to ES:DI


R2CSEG  SEGMENT WORD    PUBLIC 'CODE'
        ASSUME  CS:R2CSEG,DS:NOTHING,ES:NOTHING

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     WriteCellStr                 
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler write cells  
;*                                                    
;* FUNCTION:    Process write cells sub-function.   
;*              The cells are written to the LVB and/or PVB  
;*              starting at the specified row, column location.  
;*              Line wrap occurs if the end of a line is reached. 
;*              Write function is terminated if the end of PVB or 
;*              LVB is reached.  The number of the char/attr cells 
;*              written is returned in the RepeatFactor field of 
;*              the paramter block.                  
;*                                                    
;* ENTRY POINT: WriteCellStr                          
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (target data buffer - LVB, PVB) 
;*   DWORD  Application data address  (source data buffer) 
;*   DWORD  Application data2 address (not used in this call) 
;*   WORD   Index (7)                                
;*   WORD   Starting row                               (target row)  
;*   WORD   Starting column                            (target column)  
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      LVB and/or PVB = new attributes    
;*              RepeatFactor = sum of char/attr pairs written  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     All                                   
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: LocateBuffAddr            (in CGAREAD.ASM)  
;*                      _MOVSW                        
;*                                                    
;****************************************************************************/

        PUBLIC  WriteCellStr
WriteCellStr    PROC    NEAR

        mov     bx, 1                              ; Set indicator for word move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off

;/*
;**   On exit from LocateBuffAddr:                     
;**     If PVB & LVB flags are set then BX = LVB selector   
;**        [bp].PVB_Sel = PVB selector 
;**     else BX = LVB or PVB selector  
;**                                                     
;**   If both PVB and LVB are selected then the input cells will be 
;**   written to the LVB first before the PVB is updated.   
;*/

        .if     <nc>                               ; Continue?
            shr     cx, 1                          ; Adjust for word move
            lds     si, [si].AppDataAddr           ; Setup source address
            mov     es, bx                         ; Setup destination selector
            mov     di, ax                         ; Setup destination offset
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                push    cx                         ; Save repeat factor and
                push    es                         ;   LVB destination address
                push    di                         ; 
                sub     bx, bx                     ; Go to LVB first
                call    _MOVSW                     ; Fill destination buffer
                mov     es, [bp].PVB_Sel           ; Setup PVB as destination
                pop     si                         ; 
                pop     ds                         ; DS:SI -> LVB
                pop     cx                         ; 
                mov     di, si                     ; ES:DI -> PVB
                inc     [bp].Retrace               ; Indicate retrace is required
            .endif                                 ; 
            mov     bx, [bp].Retrace               ; Pass retrace indicator
            call    _MOVSW                         ; Copy cell from DS:SI to ES:DI
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret                                        ; 

WriteCellStr    ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     WriteCharStr                 
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler write characters  
;*                                                    
;* FUNCTION:    Process write characters sub-function.   
;*              The characters are read from a user supplied  
;*              buffer which to be placed starting a the  
;*              specified row, column location within the PVB  
;*              and/or LVB.  Line wrap occurs if the end of a  
;*              line is reached.  Write function is terminated  
;*              if the end of PVB or LVB is reached.  The number 
;*              of characters written is returned in the  
;*              RepeatFacter field of the parameter block.  
;*                                                    
;* ENTRY POINT: WriteCharStr                          
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (target data buffer - LVB, PVB) 
;*   DWORD  Application data address  (source data buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (8)                                 
;*   WORD   Starting row                               (target row)   
;*   WORD   Starting column                            (target column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      PVB and/or LVB = new characters    
;*              RepeatFactor = number of characters written  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     AX, BX, DI, SI, DS, ES               
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: LocateBuffAddr           (in VDHREAD.ASM)  
;*                      MOVSB_SKIP_DI, _MOVSW       
;*                                                    
;****************************************************************************/

        PUBLIC  WriteCharStr
WriteCharStr    PROC    NEAR

        sub     bx, bx                             ; Set indicator for byte move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off
        .if     <nc>                               ; Continue?

;/*
;**    On exit from LocateBuffAddr:                     
;**      If PVB & LVB flags are set then BX = LVB selector   
;**         [bp].PVB_Sel = PVB selector 
;**      else BX = LVB or PVB selector  
;**                                                      
;**    If both PVB and LVB are selected then the input characters will 
;**    be written to the LVB first before the PVB is updated.  
;*/

            lds     si, [si].AppDataAddr           ; Setup source address
            mov     es, bx                         ; Setup destination selector
            mov     di, ax                         ; Setup destination offset
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                push    cx                         ; Save repeat factor, source
                push    si                         ;   and destination offset
                push    di                         ; 
                sub     bx, bx                     ; Go to LVB first
                call    MOVSB_SKIP_DI              ; Fill destination buffer
                mov     es, [bp].PVB_Sel           ; Setup PVB as destination
                pop     di                         ; ES:DI -> PVB
                pop     si                         ; DS:SI -> AppDataAddr
                pop     cx                         ; 
                inc     [bp].Retrace               ; Indicate retrace is required
            .endif                                 ; 
            mov     bx, [bp].Retrace               ; Pass retrace indicator
            call    MOVSB_SKIP_DI                  ; Copy cell from DS:SI to ES:DI
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret                                        ; 

WriteCharStr    ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     WriteCharStrAttr            
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler write characters  
;*                      with a constant attribute   
;*                                                    
;* FUNCTION:    Process write characters, attribute sub-function. 
;*              The characters and attribute are read from user  
;*              supplied buffers which will be placed starting  
;*              at the specified row, column location within the 
;*              PVB and/or LVB.  Line wrap occurs if the end of  
;*              a line is reached.  Write function is terminated 
;*              if the end of PVB or LVB is reached.  The number 
;*              of char/attr pairs written is returned in the  
;*              RepeatFacter field of the parameter block.  
;*                                                    
;* ENTRY POINT: WriteCharStrAttr                     
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (target data buffer - LVB, PVB) 
;*   DWORD  Application data address  (source data buffer)  
;*   DWORD  Application data2 address (source attribue buffer)  
;*   WORD   Index (9)                                 
;*   WORD   Starting row                               (target row)   
;*   WORD   Starting column                            (target column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      PVB and/or LVB = new characters    
;*              RepeatFactor = sum of char/attr pairs written  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     AX, BX, DI, SI, DS, ES               
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: LocateBuffAddr           (in VDHREAD.ASM)  
;*                      MOVSW_STOSB, _MOVSW         
;*                                                   
;****************************************************************************/

        PUBLIC  WriteCharStrAttr
WriteCharStrAttr        PROC                     NEAR

        sub     bx, bx                             ; Setup for byte read
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off
        .if     <nc>                               ; Continue?
 
;/*
;**    On exit from LocateBuffAddr:                     
;**      If PVB & LVB flags are set then BX = LVB selector   
;**         [bp].PVB_Sel = PVB selector 
;**      else BX = LVB or PVB selector  
;**                                                      
;**    If both PVB and LVB are selected then the input chars/attr will 
;**    be written to the LVB first before the PVB is updated.  
;*/

            mov     es, bx                         ; Setup destination selector
            mov     di, ax                         ; Setup destination offset
            lds     si, [si].AppCellAddr           ; Setup address to attribute
            lodsb                                  ; Get attribute
            lds     si, [bp].ParmBuf               ; Setup parameter buffer addr
            lds     si, [si].AppDataAddr           ; Setup source address
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                push    cx                         ; Save repeat factor and
                push    es                         ;   LVB destination address
                push    di                         ; 
            .endif                                 ; 
            mov     bx, [bp].Retrace               ; Pass retrace indicator
            call    MOVSB_STOSB                    ; Fill character/attribute
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                pop     si                         ; Use LVB is now source
                pop     ds                         ; 
                pop     cx                         ; 
                mov     es, [bp].PVB_Sel           ; Setup PVB as destination
                mov     di, si                     ; 
                inc     bx                         ; Retrace wait required
                call    _MOVSW                     ; Copy cell from LVB to PVB
            .endif                                 ; 
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret                                        ; 

WriteCharStrAttr        ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     WriteNChar                   
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler repeat characters  
;*                                                   
;* FUNCTION:    Process write character sub-function. 
;*              The characters are written to either PVB or LVB 
;*              starting at the specified row, column location. 
;*              Line wrap ocurrs if the end of a line is reached. 
;*              Write function is terminated if the end of PVB or 
;*              LVB is reached.  The number of characters written 
;*              is returned in the RepeatFacter field of the  
;*              parameter block.                     
;*                                                    
;* ENTRY POINT: WriteNChar                            
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (target data buffer - LVB, PVB) 
;*   DWORD  Application data address  (source character buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (10)                                
;*   WORD   Starting row                               (target row)   
;*   WORD   Starting column                            (target column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      PVB or LVB = new characters         
;*              RepeatFactor = number of characters written  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  None                                  
;*                                                    
;* EFFECTS:     AX, BX, DI, SI, DS, ES               
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: LocateBuffAddr           (in VDHREAD.ASM)  
;*                      STOSB_SKIP_DI, _MOVSW       
;*                                                    
;****************************************************************************/

        PUBLIC  WriteNChar
WriteNChar      PROC    NEAR

        sub     bx, bx                             ; Setup indicator for byte move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off
        .if     <nc>                               ; Continue?

;/*
;**    On exit from LocateBuffAddr:                     
;**      If PVB & LVB flags are set then BX = LVB selector   
;**         [bp].PVB_Sel = PVB selector 
;**      else BX = LVB or PVB selector  
;**                                                      
;**   If both PVB and LVB are selected then the input character will be
;**   repeatedly written to the LVB first before the PVB is updated.
;*/

            lds     si, [si].AppDataAddr           ; Setup source address
            mov     es, bx                         ; Setup destination selector
            mov     di, ax                         ; Setup destination offset
            lodsb                                  ; Get source character
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                push    cx                         ; Save repeat factor and
                push    di                         ;   destination offset
                sub     bx, bx                     ; Go to LVB first
                call    STOSB_SKIP_DI              ; Fill destination buffer
                mov     es, [bp].PVB_Sel           ; Setup PVB as destination
                pop     di                         ; ES:DI -> PVB
                pop     cx                         ; 
                inc     [bp].Retrace               ; Indicate retrace is required
            .endif                                 ; 
            mov     bx, [bp].Retrace               ; Pass retrace indicator
            call    STOSB_SKIP_DI                  ; Copy char from AL to ES:DI
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret                                        ; 

WriteNChar      ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     WriteNAttr                   
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler repeat attributes  
;*                                                    
;* FUNCTION:    Process repeat write attributes sub-function.  
;*              The attributes are written to either PVB or LVB  
;*              starting at the specified row, column location.  
;*              Line wrap occurs if the end of a line is reached. 
;*              Write function is terminated if the end of PVB or 
;*              LVB is reached.  The number of the attributes  
;*              written is returned in the RepeatFactor field  
;*              of the paramter block.               
;*                                                    
;* ENTRY POINT: WriteNAttr                            
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (target data buffer - LVB, PVB) 
;*   DWORD  Application data address  (source attribute buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (11)                                
;*   WORD   Starting row                               (target row)   
;*   WORD   Starting column                            (target column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      LVB and/or PVB = new attributes    
;*              RepeatFactor = number of attributes written  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     All                                   
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: LocateBuffAddr            (in VDHREAD.ASM)  
;*                      STOSB_SKIP_DI, _MOVSW       
;*                                                    
;****************************************************************************/

        PUBLIC  WriteNAttr
WriteNAttr      PROC    NEAR

        sub     bx, bx                             ; Set indicator for byte move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off

;/*
;**    On exit from LocateBuffAddr:                     
;**      If PVB & LVB flags are set then BX = LVB selector   
;**         [bp].PVB_Sel = PVB selector 
;**      else BX = LVB or PVB selector  
;**                                                      
;**   If both PVB and LVB are selected then the input attribute will be
;**   repeatedly written to the LVB first before the PVB is updated.
;*/

        .if     <nc>                               ; Continue?
            lds     si, [si].AppDataAddr           ; Setup source address
            mov     es, bx                         ; Setup destination selector
            mov     di, ax                         ; Setup destination offset
            lodsb                                  ; Get source attribute
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                push    cx                         ; Save repeat factor and
                push    di                         ;   destination offset
                inc     di                         ; 
                sub     bx, bx                     ; Go to LVB first
                call    STOSB_SKIP_DI              ; Fill destination buffer
                mov     es, [bp].PVB_Sel           ; Setup PVB as destination
                pop     di                         ; ES:DI -> PVB
                pop     cx                         ; 
                inc     [bp].Retrace               ; Indicate retrace is required
            .endif                                 ; 
            inc     di                             ; 
            mov     bx, [bp].Retrace               ; Pass retrace indicator
            call    STOSB_SKIP_DI                  ; Copy attr from AL to ES:DI
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret

WriteNAttr      ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     WriteNCell                   
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler repeat cells  
;*                                                    
;* FUNCTION:    Process write cells sub-function.   
;*              The cells are written to either PVB or LVB  
;*              starting at the specified row, column location.  
;*              Line wrap ocurrs if the end of a line is reached. 
;*              Write function is terminated if the end of PVB  
;*              or LVB is reached.  The number of cells writte
;*              is returned in the RepeatFacter field of the  
;*              parameter block.                     
;*                                                    
;* ENTRY POINT: WriteNCell                            
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (target data buffer - LVB, PVB) 
;*   DWORD  Application data address  (source cell buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (12)                                
;*   WORD   Starting row                               (target row)   
;*   WORD   Starting column                            (target column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      PVB or LVB = new characters         
;*              RepeatFactor = sum of char/attr pairs written  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     AX, BX, DI, SI, DS, ES               
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: LocateBuffAddr           (in VDHREAD.ASM)  
;*                      _STOSW, _MOVSW               
;*                                                    
;****************************************************************************/

        PUBLIC  WriteNCell
WriteNCell      PROC    NEAR

        sub     bx, bx                             ; Set indicator for byte move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off
        .if     <nc>                               ; Continue?

;/*
;**    On exit from LocateBuffAddr:                     
;**      If PVB & LVB flags are set then BX = LVB selector   
;**         [bp].PVB_Sel = PVB selector 
;**      else BX = LVB or PVB selector  
;**                                                      
;**   If both PVB and LVB are selected then the input cell will be
;**   repeatedly written to the LVB first before the PVB is updated.
;*/

            lds     si, [si].AppDataAddr           ; Setup source address
            mov     es, bx                         ; Setup destination selector
            mov     di, ax                         ; Setup destination offset
            lodsw                                  ; Get source character
            .if     <[bp].PVB_Sel a 0>             ; Write through request?
                push    cx                         ; Save repeat factor and
                push    es                         ;   LVB destination address
                push    di                         ; 
                sub     bx, bx                     ; Go to LVB first
                call    _STOSW                     ; Fill destination buffer
                pop     si                         ; Use LVB is now source
                pop     ds                         ; 
                pop     cx                         ; 
                mov     es, [bp].PVB_Sel           ; Setup PVB as destination
                mov     di, si                     ; 
                inc     [bp].Retrace               ; Indicate retrace is required
            .endif                                 ; 
            mov     bx, [bp].Retrace               ; Pass retrace indicator
            call    _STOSW                         ; Copy cell from LVB to PVB
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret                                        ; 

WriteNCell      ENDP

R2CSEG  ENDS
        END
