;*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.;
;*****************************************************************************/
IFDEF D1348 ;DBCS bits handling routines

        PAGE    60,132
        TITLE   XGASUBS.ASM -- BufferUpdate SubRoutine for DBCS Code Page
;/*****************************************************************************
;*
;* SOURCE FILE NAME = XGASUBS.ASM
;*
;* DESCRIPTIVE NAME = BufferUpdate SubRoutine for DBCS Code Page 
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* DESCRIPTION  BUFFERUPDATE routines  
;*
;* FUNCTIONS    WriteCellStrWrld   
;*              WriteCharStrWrld   
;*              WriteCharStrAttrWrld
;*              WriteNCharWrld
;*              WriteNAttrWrld
;*              WriteNCellWrld
;*              ReadCharStrWrld
;*              ReadCellStrWrld
;*              MoveUpLeftWrld
;*              MoveDownRightWrld
;*              ReadCellTypesWrld
;*              UBCellToLVB3
;*              UBCharToLVB3
;*              UBCharAttToLVB3
;*              UBNCharToLVB3
;*              UBNAttToLVB3
;*              UBNCellToLVB3
;*              LVBCharToUB3
;*              LVBCellToUB3
;*              LVBCellToLVB3I
;*              LVBCellToLVB3D
;*              LVBCharTypeToUB3
;*
;* NOTES        NONE
;*             
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES   LocateBuffAddr  (in XGAREAD.ASM) 
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;*   04/11/91             D1348   NAKADA, Enable DBCS support in Vio-Window
;*****************************************************************************/

        .286c                           ; 286 protect mode instructions

        .xlist
        INCLUDE struc.inc               ; Structure macro
        INCLUDE pmwinx.inc              ; for check dbcs range
        INCLUDE pmaviop.inc             ; for check dbcs range
        INCLUDE vdhstruc.inc            ; Buffer update data structures
        INCLUDE vdhequ.inc              ; Buffer update equates
        .list

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

WrtCellStrTbl   dw      offset r2cseg:UBCellToLVB3
WrtCharStrTbl   dw      offset r2cseg:UBCharToLVB3
WrtCharStrAttTbl dw     offset r2cseg:UBCharAttToLVB3
WrtNCharTbl     dw      offset r2cseg:UBNCharToLVB3
WrtNAttrTbl     dw      offset r2cseg:UBNAttToLVB3
WrtNCellTbl     dw      offset r2cseg:UBNCellToLVB3

IFDEF MSKK
ReadCharStrTbl  dw      offset r2cseg:LVBCharToUB3
ReadCellStrTbl  dw      offset r2cseg:LVBCellToUB3
ENDIF ;MSKK

MoveUpLfTbl     dw      offset r2cseg:LVBCellToLVB3I
MoveDnRtTbl     dw      offset r2cseg:LVBCellToLVB3D
CellTypesTbl    dw      offset r2cseg:LVBCharTypeToUB3


;/****************************************************************************
;*
;* FUNCTION NAME = WriteCellStrWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - user cells pointer
;*                 es:di - LVB pointer
;*                 cx    - cell length (in byte)
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WriteCellStrWrld   proc    near
public  WriteCellStrWrld

        jmp     cs:WrtCellStrTbl[0]

WriteCellStrWrld   endp


;/****************************************************************************
;*
;* FUNCTION NAME = WriteCharStrWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - user chars pointer    
;*                 es:di - LVB pointer           
;*                 cx    - char length (in byte) 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WriteCharStrWrld   proc    near
public  WriteCharStrWrld

        jmp     cs:WrtCharStrTbl[0]

WriteCharStrWrld   endp


;/****************************************************************************
;*
;* FUNCTION NAME = WriteCharStrAttrWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ah    - 1st attribute                  
;*                 dl    - 2nd attribute (if WorldFormat) 
;*                 dh    - system byte   (if WorldFormat)
;*                 ds:si - user chars pointer
;*                 es:di - LVB pointer
;*                 cx    - char length (in byte)
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WriteCharStrAttrWrld proc  near
public  WriteCharStrAttrWrld

        jmp     cs:WrtCharStrAttTbl[0]

WriteCharStrAttrWrld endp


;/****************************************************************************
;*
;* FUNCTION NAME = WriteNCharWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = al    - leading character or SBCS character 
;*                 ah    - trailing character                  
;*                 es:di - LVB pointer                         
;*                 cx    - char count                          
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WriteNCharWrld     proc    near
public  WriteNCharWrld

        jmp     cs:WrtNCharTbl[0]

WriteNCharWrld     endp


;/****************************************************************************
;*
;* FUNCTION NAME = WriteNAttrWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = al    - 1st attribute          
;*                 ds:si - 2nd attribute pointer               
;*                 es:di - LVB pointer                         
;*                 cx    - attr count                          
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WriteNAttrWrld     proc    near
public  WriteNAttrWrld

        jmp     cs:WrtNAttrTbl[0]

WriteNAttrWrld     endp


;/****************************************************************************
;*
;* FUNCTION NAME = WriteNCellWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = al    - character                                        
;*                 ah    - 1st attribute                                    
;*                 ds:si - Trailing byte character or 2nd attribute pointer 
;*                 es:di - LVB pointer                                      
;*                 cx    - cell count                                       
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WriteNCellWrld     proc    near
public  WriteNCellWrld

        jmp     cs:WrtNCellTbl[0]

WriteNCellWrld     endp


IFDEF MSKK

;/****************************************************************************
;*
;* FUNCTION NAME = ReadCharStrWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - LVB pointer                                      
;*                 es:di - user buffer pointer                              
;*                 cx    - char length (in byte) 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

ReadCharStrWrld    proc    near
public  ReadCharStrWrld

        jmp     cs:ReadCharStrTbl[0]

ReadCharStrWrld    endp
ENDIF ;MSKK

IFDEF MSKK

;/****************************************************************************
;*
;* FUNCTION NAME = ReadCellStrWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - LVB pointer                                      
;*                 es:di - user buffer pointer                              
;*                 cx    - cell length (in byte) / 2 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

ReadCellStrWrld    proc    near
public  ReadCellStrWrld

        jmp     cs:ReadCellStrTbl[0]

ReadCellStrWrld    endp
ENDIF ;MSKK


;/****************************************************************************
;*
;* FUNCTION NAME = MoveUpLeftWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - source LVB pointer                               
;*                 es:di - destination LVB pointer                          
;*                 cx    - cell length (in byte) / 2  
;*                 dx    - reserved                   
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

MoveUpLeftWrld     proc    near
public  MoveUpLeftWrld

        jmp     cs:MoveUpLfTbl[0]

MoveUpLeftWrld     endp

 
;/****************************************************************************
;*
;* FUNCTION NAME = MoveDownRightWrld
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - source LVB pointer                               
;*                 es:di - destination LVB pointer                          
;*                 cx    - cell length (in byte) / 2  
;*                 dx    - reserved                   
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

MoveDownRightWrld  proc    near
public  MoveDownRightWrld

        jmp     cs:MoveDnRtTbl[0]
 
MoveDownRightWrld  endp

;/****************************************************************************
;*
;* FUNCTION NAME = ReadCellTypesWrld
;*
;* DESCRIPTION   = support CheckCharType of DBCS 
;*
;* INPUT         = ds:si - source LVB pointer                               
;*                 es:di - destination LVB pointer                          
;*                 cx    - cell length (in byte) / 2  
;*                 dx    - reserved                   
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

ReadCellTypesWrld  proc    near
public  ReadCellTypesWrld

        jmp     cs:CellTypesTbl[0]

ReadCellTypesWrld  endp


;/****************************************************************************
;*
;* FUNCTION NAME = SetSystemByte
;*
;* DESCRIPTION   = 
;*
;*      maintain the DBCS and trail byte flags in the system byte.
;*      arguments are used to obtain the system byte to be modified.
;*
;* INPUT
;*         AL  -  Character to be Tested for lead byte range
;*         DH  -  Previous Character first byte of DBCS status
;*                (return value of previous macro invocation)
;* USES
;*         DX  -  to maintain the Lead/TrailByte State information
;*
;* RETURNS
;*         AX  -  [copied 2nd attribute (AL) and] New SystemByte (AH)
;*         DH  -  1 if character first byte of DBCS
;*
;* PSEUDO-CODE
;*
;*
;*     if( LeadingByte )
;*         ThisIsLeadByteFlag = 1
;*     if( PrevWasLeadByteFlag )
;*         ThisIsLeadByteFlag = 0
;*
;*     <process attribute>
;*
;*     system byte = ThisIsLeadByteFlag
;*     swap( ThisIsLeadByteFlag, PrevWasLeadByteFlag )
;*     system byte |= ThisIsLeadByteFlag
;*                 { which is true if PREV was lead byte }
;*
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

SetSystemByte macro  instruction

        xor     dl,dl           ; DL = 0
        push    ds
        push    si
        CheckLeadByte           ; Cy set if leading byte in AL
        pop     si
        pop     ds
        adc     dl,dl           ; DL = 1 if this was leading byte

        IFNB <instruction>
                &instruction    ; optional code to load AH (or AX)
        ENDIF
                                ; [AL = 2nd attr,] AH = system byte
        mov     ah,dl           ; set DBCS bit in system byte
        or      ah,dh           ; " " " if previous was lead_byte
        sub     dl,dh           ; dl = 0 if previous was leading byte already
        adc     dl,0
        xchg    dl,dh           ; save dl for next char, use dh now
        ror     dl,1            ; rotate to get tail_byte bit 0 into bit 7
        or      ah,dl           ; or TrailBYTE bit into system byte

        endm


Erase1  macro
        local   er1_end

        cmp     di,0                    ; first cell ?
        jbe     er1_end                 ; exit if yes

        test    byte ptr es:[di+3],TrailByteFlag
        jz      er1_end                 ; exit if not

        mov     byte ptr es:[di-4],CharBlank ; fill blank in this cell
        and     byte ptr es:[di-1],NOT DBCSFlag+TrailByteFlag ; and clear    ;@A04
                                                              ; trailbyte bit;@A04
        or      [bp].j_dbcsstatus,BisectDBCS_START

er1_end:
        endm

Erase1x macro
        local   er1x_end, er1x

        cmp     di,0                    ; first cell ?
        jbe     er1x_end                ; exit if yes

        push    ds                      ; save source selector
        mov     ds,[bp].j_dbcslvbsel    ; use DBCS flag LVB

        test    byte ptr ds:[di+1],TrailByteFlag
        jz      er1x                    ; exit if not

        mov     byte ptr es:[di-2],CharBlank ; copy blank into this cell
        and     byte ptr es:[di-1],NOT DBCSFlag+TrailByteFlag ; and clear    ;@A04
                                                              ; trailbyte bit;@A04
        or      [bp].j_dbcsstatus,BisectDBCS_START

er1x:
        pop     ds                      ; restore source selector
er1x_end:
        endm


Erase2  macro
        local   er2_end

        cmp     di,[bp].j_lvbsize       ; outside LVB
        jae     er2_end                 ; skip if yes

        test    byte ptr es:[di+3],TrailByteFlag
        jz      er2_end                 ; skip if not

        mov     byte ptr es:[di],CharBlank   ; copy blank into this cell
        and     byte ptr es:[di+3],NOT DBCSFlag+TrailByteFlag ; and clear    ;@A04
                                                              ; trailbyte bit;@A04
        or      [bp].j_dbcsstatus,BisectDBCS_LAST

er2_end:
        endm

Erase2x macro
        local   er2x_end, er2x

        cmp     di,[bp].j_lvbsize       ; outside LVB
        jae     er2x_end                ; skip if yes

        push    ds                      ; save source selector
        mov     ds,[bp].j_dbcslvbsel    ; use DBCS flag LVB

        test    byte ptr ds:[di+1],TrailByteFlag
        jz      er2x                    ; skip if not

        mov     byte ptr es:[di],CharBlank   ; copy blank into this cell
        and     byte ptr es:[di+1],NOT DBCSFlag+TrailByteFlag ; and clear    ;@A04
                                                              ; trailbyte bit;@A04
        or      [bp].j_dbcsstatus,BisectDBCS_LAST

er2x:
        pop     ds                      ; restore source selector
er2x_end:
        endm


Erase5  macro
        local   er5_end

        test    byte ptr [si+3],TrailByteFlag ; CF = 0
        jz      er5_end                 ; exit if not

        mov     al,CharBlank            ; AL = blank
        stc                             ; CF set if was trailing byte

er5_end:
        endm

Erase5x macro
        local   er5x_end

        push    ds                      ; save source selector
        mov     ds,[bp].j_dbcslvbsel    ; use DBCS flag LVB

        test    byte ptr ds:[si+1],TrailByteFlag ; CF = 0
        jz      er5x_end                ; exit if not

        mov     al,CharBlank            ; AL = blank
        stc                             ; CF set if was trailing byte

er5x_end:
        pop     ds                      ; restore source selector
        endm


Erase6  macro
        local   er6_end

        test    byte ptr [si+3],DBCSFlag; CF = 0
        jz      er6_end                 ; exit if not DBCS

        test    byte ptr [si+3],TrailByteFlag
        jnz     er6_end                 ; exit if trail byte

        mov     al,CharBlank            ; AL = blank
        stc                             ; CF set if was lead byte

er6_end:
        endm

Erase6x macro
        local   er6x_end

        push    ds                      ; save source selector
        mov     ds,[bp].j_dbcslvbsel    ; use DBCS flag LVB

        test    byte ptr ds:[si+1],DBCSFlag     ; CF = 0
        jz      er6x_end                ; exit if not DBCS

        test    byte ptr ds:[si+1],TrailByteFlag
        jnz     er6x_end                ; exit if trail byte

        mov     al,CharBlank            ; AL = blank
        stc                             ; CF set if was lead byte

er6x_end:
        pop     ds                      ; restore source selector
        endm


;/****************************************************************************
;*
;* FUNCTION NAME = UBCellToLVB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - user cells pointer                               
;*                 es:di - LVB pointer           
;*                 cx    - cell length (in byte) 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

UBCellToLVB3    PROC
        public  UBCellToLVB3

;*/
;** check to see whether we are about to overwrite to a trailing byte
;** and if so, erase preceding lead byte.
;*/

        Erase1

        shr     cx,2                    ; convert bytes to number of cell
        xor     dx,dx                   ; clear DH for use as flag in loop

;/*
;** write cells.
;*/
        .repeat
            mov     bx,word ptr es:[di] ; Save for restoring the previous ;@A00
                                        ; cp & attr#1 for tail exception  ;@A00
            lodsw                       ; AL = char, AH = 1st attribute
            stosw                       ; write char and 1st attribute
            mov     ah,byte ptr ds:[si] ; get attr#2(including lcid)      ;@A00
            SetSystemByte <lodsw>       ; AL = 2nd attr, AH = system byte
            stosw                       ; store 2nd attr and system byte
        .loop

;/*
;** Check to see if the last char written was a lead byte, if so, erase
;*/
        .if     <bit dh and 1>          ; last char copied was lead byte
            mov     word ptr es:[di-4],bx ; Undo                          ;@A00
            shl     dh,1                                                  ;@A00
        .endif

;/*
;** Check if next cell contains a trail byte, if so, erase
;*/
        .if     <dh ne 2>               ; When dbcs 1st has been ignored, ;@A00
                                        ; forget the exception handling.  ;@A00
            Erase2
        .endif                                                            ;@A00

        ret
UBCellToLVB3    ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = UBCharToLVB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - user cells pointer                               
;*                 es:di - LVB pointer           
;*                 cx    - cell length (in byte) 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

UBCharToLVB3    PROC
        public  UBCharToLVB3

;/*
;**  check to see whether we are about to overwrite to a trailing byte
;**  and if so, erase preceding lead byte.
;*/

        Erase1

        xor     dx,dx                   ; clear DH for use as flag in loop

;/*
;** write characters
;*/
        .repeat
            mov     bl,byte ptr es:[di] ; Save for restoring the previous ;@A01
            lodsb                       ; copy char
            stosb
            xor     ah,ah               ; ignore attr#2(including lcid),  ;@A01
                                        ; which means using a default     ;@A01
                                        ; dbcs env. vector.               ;@A01
            inc     di                  ; skip 1st attribute
            SetSystemByte <mov ax,es:[di]>
                                        ; AL = 2nd attr, AH = system byte
            stosw                       ; store 2nd attr and system byte
        .loop

;/*
;** Check to see if the last char written was a lead byte, if so, erase
;*/
        .if     <bit dh and 1>          ; last char copied was lead byte
            mov     byte ptr es:[di-4],bl ; undo ; restore the prev. cp.  ;@A01
            shl     dh,1                                                  ;@A01
        .endif

;/*
;** Check if next cell contains a trail byte, if so, erase
;*/
        .if     <dh ne 2>               ; When dbcs 1st has been ignored, ;@A00
                                        ; forget the exception handling.  ;@A00
            Erase2
        .endif                                                            ;@A00

        ret
UBCharToLVB3    ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = UBCharAttToLVB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ah    - 1st attribute
;*                 dl    - 2nd attribute (if WorldFormat)
;*                 dh    - system byte   (if WorldFormat)
;*                 ds:si - user chars pointer
;*                 es:di - LVB pointer
;*                 cx    - char length (in byte)
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

UBCharAttToLVB3 PROC
        public  UBCharAttToLVB3

;/*
;**  check to see whether we are about to overwrite to a trailing byte
;**  and if so, erase preceding lead byte.
;*/
        Erase1

        mov     bl,ah                   ; BL = 1st attribute
        mov     bh,dl                   ; BH = 2nd attribute
        xor     dx,dx                   ; clear DH for use as flag in loop

;/*
;** write characters and attributes
;*/
        .repeat
            mov     ax,word ptr es:[di]              ; save for retrieve ;@A01
            mov     word ptr [bp].wSaveCpAttr1,ax                        ;@A01
            mov     ax,word ptr es:[di+2]                                ;@A01
            mov     word ptr [bp].wSaveAttr2Attr3,ax                     ;@A01
            lodsb                       ; char = AL
            mov     ah,bl               ; AH = first attribute
            stosw                       ; write char and 1st attribute
            mov     ah,bh               ; AH = attr #2(include lcid)    ;@A00
            SetSystemByte               ; output : AH = system byte
            mov     al,bh               ; AL = 2nd attribute
            stosw                       ; store 2nd attr and system byte
        .loop

;/*
;** Check to see if the last char written was a lead byte, if so, erase
;*/
        .if     <bit dh and 1>          ; last char copied was lead byte

            .if     <bit <word ptr [bp].shadow_Flags> and CGAAttr>       ;@A03
                mov     byte ptr es:[di-4],CharBlank                     ;@A03
                                            ; write a blank at           ;@A03
                                            ; the last character         ;@A03
                                                                         ;@A03
                and     byte ptr es:[di-1],NOT DBCSFlag+TrailByteFlag    ;@A04
                                            ; clear system byte          ;@A03
            .else                                                        ;@A03
                mov     ax,word ptr [bp].wSaveCpAttr1    ; retrieve      ;@A01
                mov     word ptr es:[di-4],ax                            ;@A01
                mov     ax,word ptr [bp].wSaveAttr2Attr3                 ;@A01
                mov     word ptr es:[di-2],ax                            ;@A01
                shl     dh,1                                             ;@A01
            .endif                                                       ;@A03
        .endif

;/*
;** Check if next cell contains a trail byte, if so, erase
;*/
        .if     <dh ne 2>               ; When dbcs 1st has been ignored, ;@A00
                                        ; forget the exception handling.  ;@A00
            Erase2
        .endif                                                            ;@A00

        ret
UBCharAttToLVB3 ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = UBNCharToLVB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = al    - leading character or SBCS character 
;*                 ah    - trailing character                  
;*                 es:di - LVB pointer                         
;*                 cx    - char count                          
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

UBNCharToLVB3   PROC
        public  UBNCharToLVB3

;/*
;**  check to see whether we are about to overwrite to a trailing byte
;**  and if so, erase preceding lead byte.
;*/
        Erase1

        xor     dx,dx                   ; clear DX (system byte)

;/*
;** branch by DBCS character or SBCS character
;*/
        push    ax                      ; keep ah(trailing byte)
        xor     ah,ah                   ; can ignore lcid because of
                                        ; char code only
        push    ds
        push    si
        lds     si,[bp].lpNLSExt
        CheckLeadByte                   ; is it leading byte?
        pop     si
        pop     ds
        pop     ax

;/*
;** write DBCS characters
;*/
        .if     <c>                     ; yes
            shr     cx,1                ; CX = a pair of lead and trail byte
            pushf                       ; save frag whether DBCS bisect
            jcxz    @F
                                        ;     fix for starting from max point
            mov     dl,DBCSFlag         ; system byte
            mov     dh,TrailByteFlag OR DBCSFlag
            .repeat
                stosb                   ; copy leading character
                inc     di              ; skip attributes
                inc     di
                mov     byte ptr es:[di],dl     ; store leading system byte
                inc     di
                xchg    ah,al           ; flip lead/trail byte
                stosb                   ; copy trailing character
                inc     di              ; skip attributes
                inc     di
                mov     byte ptr es:[di],dh     ; store trailing system byte
                inc     di
                xchg    ah,al           ; flip lead/trail byte
            .loop

;/*
;** if the char count cause DBCS bisecting, store blank character
;*/
@@:
                                        ;     fix for starting from max point
            popf                        ; restore frag whether DBCS bisect
            .if     <c>                 ; last char is pointed to lead byte
                mov     al,CharBlank    ; last character is blank
                stosb                   ; copy blank character
                inc     di              ; skip attributes
                inc     di
;@A04           mov     dl,SBCS_BYTE    ; last system byte is SBCS flag
                and     dl,NOT DBCSFlag+TrailByteFlag                   ;@A04
                mov     byte ptr es:[di],dl     ; store system byte
                inc     di
            .endif

;/*
;** write SBCS characters
;*/
        .else short                     ; no
            .repeat
                stosb                   ; copy char
                inc     di              ; skip attributes
                inc     di
                mov     byte ptr es:[di],dl     ; store system
                inc     di
            .loop
        .endif

;/*
;** Check if next cell contains a trail byte, if so, erase
;*/
        Erase2

        ret
UBNCharToLVB3   ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = UBNAttToLVB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = al    - 1st attribute         
;*                 ds:si - 2nd attribute pointer               
;*                 es:di - LVB pointer                         
;*                 cx    - attr count                          
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

UBNAttToLVB3    PROC
        public  UBNAttToLVB3

;/*
;** set 1st attr to AL, 2nd attr to AH
;*/
        mov     ah,ds:[si]              ; ds:[si] = 2nd attribute

;/*
;** write attributes
;*/
        .repeat
            inc     di                  ; skip character
            stosw                       ; copy attribute
            inc     di                  ; skip system
        .loop

        ret
UBNAttToLVB3    ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = UBNCellToLVB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = al    - character                                        
;*                 ah    - 1st attribute                                    
;*                 ds:si - Trailing byte character or 2nd attribute pointer 
;*                 es:di - LVB pointer                                      
;*                 cx    - cell count                                       
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

UBNCellToLVB3   PROC
        public  UBNCellToLVB3

;/*
;**  check to see whether we are about to overwrite to a trailing byte
;**  and if so, erase preceding lead byte.
;*/
        Erase1

        mov     bl,byte ptr [si]        ; BL = Leading 2nd attribute
        xor     dx,dx                   ; clear DX (system byte)
        inc     si                      ; point trailing byte character
        inc     si

;/*
;** branch by DBCS character or SBCS character
;*/
        push    ds
        push    si
        xchg    ah,bl                   ; get attr#2(including lcid) to AH ;@A02
        CheckLeadByte                   ; is it leading byte?
        xchg    ah,bl                                                      ;@A02
        pop     si
        pop     ds

;/*
;** write DBCS cells
;*/
        .if     <c>                     ; yes
            shr     cx,1                ; CX = a pair of lead and trail byte
            pushf                       ; save frag whether DBCS bisect
            mov     bh,bl               ; BH = Leading 2nd attribute
            mov     bl,ah               ; BL = Leading 1st attribute
            mov     ah,al               ; AH = Leading character
            jcxz    @F                  ; 1990-08-02 updated
                                        ;     fix for starting from max point
            lodsb                       ; AL = Trailing character
            mov     dl,byte ptr ds:[si] ; DL = Trailing 1st attribute
            mov     dh,byte ptr ds:[si+1];DH = Trailing 2nd attribute
            .repeat
                xchg    al,ah           ; flip trail/lead byte character
                stosb                   ; copy leading char
                mov     es:[di],bx      ; store leading 1st attr and 2nd attr
                inc     di
                inc     di
                mov     byte ptr es:[di],DBCSFlag
                                        ; store leading system byte
                inc     di
                xchg    al,ah           ; flip lead/trail byte
                stosb                   ; copy trailing char
                mov     es:[di],dx      ; store trailing 1st attr and 2nd attr
                inc     di
                inc     di
                mov     byte ptr es:[di],TrailByteFlag OR DBCSFlag
                                        ; store leading system byte
                inc     di
            .loop

;/*
;** if the cell count cause DBCS bisecting, store attribute only.
;*/
@@:                                     ; 1990-08-02 updated
                                        ;     fix for starting from max point
            popf                        ; restore frag whether DBCS bisect
            .if     <c>                 ; last cell is pointed to lead byte
                mov     al,CharBlank    ; last character is blank
                mov     ah,bl           ; set 1st attribute
                stosw                   ; copy char and 1st attr
                mov     al,bh           ; set 2nd attribute
;@A04           mov     ah,SBCS_BYTE    ; last system byte is SBCS flag
                and     ah,NOT DBCSFlag+TrailByteFlag                   ;@A04
                stosw                   ; store 2nd attr and system byte
            .endif

;/*
;** write SBCS characters
;*/
        .else short                     ; no
            mov     bh,dh               ; copy system byte to BH
            .repeat
                stosw                   ; copy char and 1st attr
                mov     es:[di],bx      ; store 2nd attr and system byte
                inc di
                inc di
            .loop
        .endif

;/*
;** Check if next cell contains a trail byte, if so, erase
;*/
        Erase2

        ret
UBNCellToLVB3   ENDP


IFDEF MSKK
;/****************************************************************************
;*
;* FUNCTION NAME = LVBCharToUB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - LVB pointer                                      
;*                 es:di - user buffer pointer                              
;*                 cx    - char length (in byte)   
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

LVBCharToUB3    PROC
        public  LVBCharToUB3

;/*
;** Check if first cell to copy contains a trail byte, if so, erase
;*/
        mov     al,[si]                 ; AL = first character
        Erase5                          ; replace AL by blank if trail byte
        dec     cx                      ; count down this character

        .if     <ncxz>                  ; branch if only 1 char total
            stosb                       ; store character
            add     si,4                ; skip first cell point
            jmp short @F                ; jump into loop to do cx-1 iterations

            .repeat
                movsb                   ; copy character
                add     si,3            ; skip 3 attributes
@@:
            .loop

;/*
;** Check if last cell to copy contains lead byte, if so, erase
;** We check the source before copy, as then the following trail byte
;** is still attached and we can use the system byte TrailByteFlag to check.
;*/

            mov     al,[si]             ; last character
        .endif
        Erase6                          ; replace AL by blank if lead byte
        stosb                           ; store character

        ret
LVBCharToUB3    ENDP
ENDIF ;MSKK

IFDEF MSKK
;/****************************************************************************
;*
;* FUNCTION NAME = LVBCellToUB3
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - LVB pointer                                      
;*                 es:di - user buffer pointer                              
;*                 cx    - char length (in byte) / 2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

LVBCellToUB3    PROC
        public  LVBCellToUB3

        shr     cx,1                    ; convert to number of cell

;/*
;** Check if first cell to copy contains a trail byte, if so, erase
;*/
        mov     ax,[si]                 ; AL = first char, AH = 1st attr
        Erase5                          ; replace AL by blank if trail byte
        dec     cx                      ; count down this cell

        .if     <c> or                  ; branch if char was a trail byte
        .if     <ncxz>                  ; branch if this only cell to copy
            stosw                       ; store character and 1st attribute
            inc     si                  ; adjust source pointer
            inc     si

            lodsw                       ; AL = 2nd attr, AH = system byte
            .if     <c>                 ; branch if was not trail byte
                and     ah,NOT DBCSFlag+TrailByteFlag                   ;@A04
            .endif
            stosw                       ; store 2nd attr and system byte
            jcxz        @F              ; branch if this only cell to copy

            dec     cx
            add     cx,cx               ; word count
            rep     movsw               ; copy all except last cell.

;/*
;** Check if last cell to copy contains lead byte, if so, erase
;** We check the source before copy, as then the following trail byte
;** is still attached and we can use the system byte TrailByteFlag to check.
;*/

            mov     ax,[si]             ; AL = character, AH = attribute
        .endif
        Erase6                          ; replace AL by blank if lead byte
        stosw                           ; store character and attribute
        inc     si                      ; adjust source pointer
        inc     si
        lodsw                           ; get 2nd attribute and system byte
        .if     <c>                     ; branch if was not lead byte
            and     ah,NOT DBCSFlag+TrailByteFlag                       ;@A04
        .endif
        stosw                           ; store 2nd attribute and system byte

@@:
        ret
LVBCellToUB3    ENDP
ENDIF ;MSKK


;/****************************************************************************
;*
;* FUNCTION NAME = LVBCellToLVB3I
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - source LVB pointer                               
;*                 es:di - destination LVB pointer                          
;*                 cx    - cell length (in byte) / 2
;*                 dx    - reserved                  
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

LVBCellToLVB3I  PROC NEAR
        public  LVBCellToLVB3I

;/*
;**  Check if first source cell to copy contains a trail byte
;**  and if so, erase this DBCS character.
;*/
        .if     <si ae 4> and
        .if     <bit <byte ptr ds:[si+3]> and TrailByteFlag>
            mov     byte ptr ds:[si],CharBlank
                                        ; copy blank into this trailing char
            and     byte ptr ds:[si+3],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear trailing bit
            mov     byte ptr ds:[si-4],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr ds:[si-1],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear leading bit
            or      [bp].j_dbcsstatus,BisectDBCS_LEFT
        .endif

;/*
;**  check to see whether we are about to overwrite to a trailing byte
;**  and if so, erase preceding lead byte.
;*/
        .if     <di ae 4 > and
        .if     <bit <byte ptr es:[di+3]> and TrailByteFlag>
            mov     byte ptr es:[di-4],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr es:[di-1],NOT DBCSFlag+TrailByteFlag       ;@A04

                                        ; and clear leading bit
            or      [bp].j_dbcsstatus,BisectDBCS_LEFT
        .endif

;/*
;** move cells
;*/
        rep     movsw                   ; copy all remaining cells

;/*
;**  Check if last source cell to copy contains a lead byte
;**  and if so, erase this DBCS character and leading character stored.
;*/
        .if     <si b [bp].j_lvbsize> and
        .if     <bit <byte ptr ds:[si+3]> and TrailByteFlag>
            mov     byte ptr ds:[si],CharBlank
                                        ; copy blank into this trailing char
            and     byte ptr ds:[si+3],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear trailing bit
            mov     byte ptr ds:[si-4],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr ds:[si-1],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear leading bit
            mov     byte ptr es:[di-4],CharBlank
                                        ; copy blank into stored leading char
            and     byte ptr es:[di-1],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear stored leading bit
            or      [bp].j_dbcsstatus,BisectDBCS_RIGHT
        .endif

;/*
;** Check if next destination cell contains a trail byte, if so, erase
;*/
        .if     <di b [bp].j_lvbsize> and
        .if     <bit <byte ptr es:[di+3]> and TrailByteFlag>
            mov     byte ptr es:[di],CharBlank
                                        ; copy blank into this trailing char
            and     byte ptr es:[di+3],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear trailing bit
            or      [bp].j_dbcsstatus,BisectDBCS_RIGHT
        .endif

        ret
LVBCellToLVB3I  ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = LVBCellToLVB3D
;*
;* DESCRIPTION   = 
;*
;* INPUT         = ds:si - source LVB pointer                               
;*                 es:di - destination LVB pointer                          
;*                 cx    - cell length (in byte) / 2
;*                 dx    - reserved                  
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

LVBCellToLVB3D  PROC
        public  LVBCellToLVB3D

;/*
;** calculate the valid last cell pointer
;*/
        mov     ax,[bp].j_lvbsize
        .if     <ax eq 0FFFFh>          ; 64KB on AVIO
            sub     ax,3
        .else
            sub     ax,4
        .endif
        push    ax                      ; save valid last cell pointer

;/*
;**  Check if first source cell to copy contains a lead byte
;**  and if so, erase this DBCS character.
;*/
        .if     <si b ax> and
        .if     <bit <byte ptr ds:[si+5]> and TrailByteFlag>
            mov     byte ptr ds:[si-2],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr ds:[si+1],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear leading bit
            mov     byte ptr ds:[si+2],CharBlank
                                        ; copy blank into this trailing char
            and     byte ptr ds:[si+5],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear trailing bit
            or      [bp].j_dbcsstatus,BisectDBCS_RIGHT
        .endif

;/*
;**  check to see whether we are about to overwrite to a leading byte
;**  and if so, erase next trail byte.
;*/
        pop     ax                      ; restore valid last cell pointer
        .if     <di b ax > and
        .if     <bit <byte ptr es:[di+5]> and TrailByteFlag>
            mov     byte ptr es:[di+2],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr es:[di+5],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear leading bit
            or      [bp].j_dbcsstatus,BisectDBCS_RIGHT
        .endif

;/*
;** move cells
;*/
        rep     movsw                   ; copy all remaining cells

;/*
;**  Check if last source cell to copy contains a trail byte
;**  and if so, erase this DBCS character and trailing character stored.
;*/
        .if     <si ge 2> and
        mov     al,byte ptr ds:[si+1]
        and     al,(TrailByteFlag or DBCSFlag)
        .if     <al eq DBCSFlag>
            mov     byte ptr ds:[si-2],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr ds:[si+1],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear leading bit
            mov     byte ptr ds:[si+2],CharBlank
                                        ; copy blank into this trailing char
            and     byte ptr ds:[si+5],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear trailing bit
            mov     byte ptr es:[di+2],CharBlank
                                        ; copy blank into stored trailing char
            and     byte ptr es:[di+5],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear stored trailing bit
            or      [bp].j_dbcsstatus,BisectDBCS_LEFT
        .endif

;/*
;** Check if next destination cell contains a lead byte, if so, erase
;*/
        .if     <di ge 2> and
        mov     al,byte ptr es:[di+1]
        and     al,(TrailByteFlag or DBCSFlag)
        .if     <al eq DBCSFlag>
            mov     byte ptr es:[di-2],CharBlank
                                        ; copy blank into this leading char
            and     byte ptr es:[di+1],NOT DBCSFlag+TrailByteFlag       ;@A04
                                        ; and clear trailing bit
            or      [bp].j_dbcsstatus,BisectDBCS_LEFT
        .endif

        ret
LVBCellToLVB3D  ENDP


;/****************************************************************************
;*
;* FUNCTION NAME = LVBCharTypeToUB3
;*
;* DESCRIPTION   = support CheckCharType of DBCS 
;*
;* INPUT         = ds:si - LVB pointer                                      
;*                 es:di - user buffer pointer 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

TypeSBCS        equ     0
TypeDBCSLead    equ     2
TypeDBCSTrail   equ     3


LVBCharTypeToUB3 PROC
        public  LVBCharTypeToUB3

        mov     ah,byte ptr ds:[si+3]   ; get system byte
                                                                        ;@A05 start
        test    ah, (TrailByteFlag or DBCSFlag)
        .if     z   near                    ; check whether it is a real SBCS
            push    es
            push    ds
            push    di

            push    ds
            pop     es
            push    si
            pop     di

            lds     bx, [bp].EnvBufParm     ; DS:BX -> environment buffer
            mov     ax,di
            mov     cx, ds:[bx].viops_CellByteSize
            shr     cl,1
            shr     ax,cl
            mov     cx,ax                   ; set the number of bytes before
                                            ; the specified position.
            mov     bx, ds:[bx].viops_CellByteSize
            xor     ax,ax
            .if     <cx a 0>
                mov     ax,cx           ;save
                .repeat                 ;keep the upper compatible
                                        ;for dbcs applications.
                                        ;Avio must ensure all
                                        ;of dbcs bits are valid.
                    test    byte ptr es:[di+3], DBCSFlag+TrailByteFlag
                    jnz     @F
                    sub     di,bx
                .loop
            @@:
                .if     <bit <byte ptr es:[di+3]> and <NOT TrailByteFlag>> and
                .if     <nonzero cx>
                    sub     di,bx       ;this is the dbcs leading byte
                    dec     cx
                .endif
                sub     ax,cx
            .endif
            add     cx,ax
            inc     cx                  ;include the specified position itself

            .repeat
                mov     ah,byte ptr es:[di+2]   ; AH : attr#2(including lcid)
                mov     al,byte ptr es:[di]     ; AL : char code point
                inc     di                      ; skip char
                inc     di                      ; skip 1st attribute
                SetSystemByte <mov ax,es:[di]>  ; get 2nd attr & 3rd attr
                stosw                           ; store 2nd attr and system byte
            .loop

            pop     di
            pop     ds
            pop     es

        .endif
                                                                        ;@A05 end
        and     ah,(TrailByteFlag or DBCSFlag)

        mov     al,TypeSBCS             ; default SBCS
        .if     <ah eq DBCSFlag>
            mov     al,TypeDBCSLead     ; leading byte
        .elseif <ah eq <TrailByteFlag or DBCSFlag>>
            mov     al,TypeDBCSTrail    ; trailing byte
        .endif

        xor     ah,ah
        stosw                           ; store character type

        ret
LVBCharTypeToUB3 ENDP




R2CSEG  ENDS
ENDIF ;D1348
        END

