;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;******************************************************************************;
;    Module           : EDDHSUBR.ASM                                           ;
;                                                                              ;
;    Description      : cell scaning subroutines                               ;
;                       used for AVIO AI routines                              ;
;                                                                              ;
;    Created          : 03/04/92                                               ;
;    Author           : Eitaroh Kasamatsu (JL21221 at YMTVM6)                  ;
;                                                                              ;
;    Notes            :                                                        ;
;             - This ASM file is created based on EDDHAVIO.ASM SBCS            ;
;               version. To make more efficient to maintenance                 ;
;               modules, this ASM file has been devided into several           ;
;               files.                                                         ;
;                                                                              ;
;    History          :                                                        ;
;               Created, based on EDDHAVIO.ASM        (03/04/92,KASA)          ;
;                                                                              ;
;                       OCO Source Materials                                   ;
;                       XXXX-XXX                                               ;
;******************************************************************************;

INCL_GPIBITMAPS EQU     1
INCL_FONTFILEFORMAT     equ     1       ; to include pmfont.inc
include os2.inc
include eddinclt.inc

include eddhcone.inc
include eddhmacr.inc
include eddhtype.inc

?DF     equ     1       ; we dont want _TEXT segment defined
include cmacros.inc
include eddhavio.inc

;------------------------------------------------------------------------------;
; External access only for this module                                         ;
;------------------------------------------------------------------------------;
        ;None


_TEXT           segment dword use32 public 'CODE'
                assume  cs:FLAT, ds:FLAT, es:FLAT
;/********************************************************************/
;/* CheckDBCSEnv                                                     */
;/*                                                                  */
;/* This subroutine check whether the given byte value is in renge   */
;/* got by DosQueryDBCSEnv.                                          */
;/*                                                                  */
;/* Entry - pfdFont   : pointer to required FONTDETAILS              */
;/*         cellValue : cell value                                   */
;/*                                                                  */
;/*                                                                  */
;/* Exit  - EAX : 1 -- given value is in DBCSEnv renge               */
;/*               0 -- given value is not in DBCSEnv renge           */
;/*                                                                  */
;/* Registers: EBX,ESI,EDI,ES,DS   -- will be preserved              */
;/*            EAX                 -- will be changed                */
;/********************************************************************/
        align   4
cProc CheckDBCSEnv,<NEAR,PUBLIC>,<ebx,esi,edi,es,ds>
        parmD   pfdFont
        parmD   cellValue

cBegin

        mov     eax,pfdFont             ; 

env_see_parse_flag:
        movzx   edx,word ptr [eax].NLSParseFlag
                                        ; get this font's parse flag
        test    edx,NLSCA_MAP_DBCS      ; DBCSEnv vectors exist?
        jz short no_more_renge          ; no

prepare_check:
        mov     edx,[eax].pDBCSMap      ; EDX points to DBCSLeading tbl
        add     edx,MAX_NUM_DBCODEPOINTS ; EDX points to DBCSEnv vectors
        mov     ebx,cellValue           ; BL = cp byte
        mov     ecx,DBCSEvBufSiz        ; get DBCSEnv vectors size
        shr     ecx,1                   ; because 2byte pair (ECX = counter)

next_renge:
        mov     al,byte ptr [edx]       ; AL = lower limit of DBCSEnv
        mov     ah,byte ptr [edx+1]     ; AH = higher limit of DBCSEnv
        test    ax,0FFFFh               ; ax == 0?
        jz short no_more_renge          ; yes, renge array ended
        cmp     bl,al                   ; 
        jb short not_in_renge           ; BL is less than renge
        cmp     bl,ah                   ; 
        ja short not_in_renge           ; BL is greater than renge
        xor     eax,eax                 ; if reaches here, BL is in
        mov     eax,1                   ; renge, so indicate it's in
        jmp short ext_check_dbcsenv     ; renge

not_in_renge:
        add     edx,2                   ; points to next lower limit
        loop next_renge                 ; we exhausted renge array

no_more_renge:
        xor     eax,eax                 ; if reaches here, DL is not
                                        ; in renge, so indicate it's
                                        ; not in renge

ext_check_dbcsenv:

cEnd

;/********************************************************************/
;/* IniCheckCellType4                                                */
;/*                                                                  */
;/* This subroutine determines current cell type by scanning LVB     */
;/* backward.                                                        */
;/*                                                                  */
;/* Entry - pfdBaseFont : pFontDetails for base font                 */
;/*         pCharBuffer : position in char buffer                    */
;/*                                                                  */
;/* Exit  - EAX : Cell Type                                          */
;/*                  0 = SBCS Cell                                   */
;/*                  1 = DBCSLeading Cell                            */
;/*                  2 = DBCSTrailing Cell                           */
;/*                 -1 = Invalid DBCSLeading Cell                    */
;/*                 -2 = Invalid DBCSTrailing Cell                   */
;/*                                                                  */
;/*         ECX : low word  - Code Point to be used                  */
;/*               high word - Font No. to be used                    */
;/*         EDX : pFontDetails to be used                            */
;/*                                                                  */
;/*                                                                  */
;/* Summarised Logic is as follows:                                  */
;/*                                                                  */
;/* C :current cell                                                  */
;/* D :Cell which is not last cp of a char.(DBCSLeading/DBCSTrailing)*/
;/* X :Cell which is last cp of a char.    (SBCS/DBCSTrailing)       */
;/*                                                                  */
;/* Case (1)                                                         */
;/*                          given CharRect in LVB                   */
;/*          back scan +-------------------------                    */
;/*               <-   |                                             */
;/*          XD-- DDDDD|C                                            */
;/*           |       ||                                             */
;/*           +-------+|                                             */
;/*             even   |                                             */
;/*      (These cells  |                                             */
;/*    use same font.) |                                             */
;/*                    |                                             */
;/*                  left edge of CharRect                           */
;/*                                                                  */
;/*   In this case, current cell C is DBCSLeading or SBCS cell. So   */
;/*   we can start at this cell and determine its type by checking   */
;/*   whether the current cell C is in DBCSEv renge or not.          */
;/*                                                                  */
;/* Case (2)                                                         */
;/*                          given CharRect in LVB                   */
;/*          back scan +-------------------------                    */
;/*               <-   |                                             */
;/*         XDD-- DDDDD|C                                            */
;/*          |        ||                                             */
;/*          +--------+|                                             */
;/*            odd     |                                             */
;/*       (These cells |                                             */
;/*    use same font.) |                                             */
;/*                    |                                             */
;/*                    |                                             */
;/*                  left edge of CharRect                           */
;/*                                                                  */
;/*   In this case, current cell C is DBCSTrailing. So we can        */
;/*   construct DBCS codepoint with the current cell C and the cell  */
;/*   just left to the left edge of given CharRect.                  */
;/*                                                                  */
;/*                                                                  */
;/*   In this logic, we assume that DBCSLeading and DBCSTrailing     */
;/*   cells use same font. so if we encounter a cell which uses      */
;/*   different font from that of current font, we determine this    */
;/*   cell as the one which is last cp of a char.(SBCS/DBCSTrailing) */
;/*   So, if we come to call CheckDBCSEnv in this routine, the       */
;/*   current cell uses NLSCA_MBCS font. This font must have DBCS    */
;/*   Environment vectors.                                           */
;/*                                                                  */
;/* Registers: EBX,ESI,EDI,ES,DS         -- will be preserved        */
;/*            EAX,ECX,EDX               -- will be changed          */
;/********************************************************************/
        align   4
cProc IniCheckCellType4,<NEAR,PUBLIC>,<ebx,esi,edi,es,ds>
        parmD   pfdBaseFont
        parmD   pCharBuffer
        localD  pcbuff
        localD  currentFD
        localD  currentCP
        localW  currentFontNo
        localB  DBCSCellCount
cBegin

        mov     DBCSCellCount,0      ; initialize DBCSCellCount
        mov     eax,pCharBuffer      ; 
        mov     pcbuff,eax           ; 

ini_get_cell4:
        mov     ecx,dword ptr[eax]   ; ECX = current cell
        mov     currentCP,ecx        ; keep current cell value
        and     ecx,MFI_CHARMASK     ; 
        shr     ecx,16               ; 
        mov     currentFontNo,cx     ; 
        mov     edx,SIZE FONTDETAILS ; 
        imul    edx,ecx              ; 
        add     edx,pfdBaseFont      ; 
        or      edx,edx              ; pFontDetails not set or cleared?
        jz short @f                  ; not set or cleared.
        mov     eax,dword ptr [edx].pFocaFont
        or      eax,eax              ; pFocaFont null?
        jnz short ini_see_parse_flag4 ; no, so see parse flag
@@:
        sub     eax,eax              ; invalid font used. so use SBCS cp
        mov     edx,pfdBaseFont      ; with system fontdetails.
        mov     ecx,dword ptr[edx].ulDefCodepoint
        jmp ini_return_to_parent4    ; 

ini_see_parse_flag4:
        mov     currentFD,edx        ; save pfontdetails
        movzx   eax,word ptr [edx].NLSParseFlag
        test    eax,NLSCA_SBCS       ; SBCS parsing?
        jnz ini_parse_sbcs4          ; yes
        test    eax,NLSCA_DBCS       ; DBCS parsing?
        jz short ini_pre_check_before_backward4 ; no, MBCS parsing.

ini_parse_dl_or_dt4:
        mov     eax,pcbuff           ; It's DBCS font, so dl or dt
        sub     eax,AIxfer.pLVBFirst ; EAX holds num of byte from top
                                     ; of LVB
        jle short ini_parse_dl4      ; if top of LVB, it's dl.
        shr     eax,4                ; eax holds cell count from top of LVB
        and     al,01h               ; even count?
        jz short ini_parse_dl4       ; yes, so it's dl.
        jmp ini_parse_dt4            ; odd count, so it's dt.

ini_pre_check_before_backward4:
        mov     eax,pcbuff           ; 
        sub     eax,4                ; EAX = address of previous cell
        sub     eax,AIxfer.pLVBFirst ; reach to first LVB cell?
        jns short ini_go_one_step_backward4 ; no, so we can go backward
        jmp short ini_parse_sbcs_or_dl4  ; yes, so SBCS or DBCS Leading

ini_go_one_step_backward4:
        sub     pcbuff,4             ; do subtract pointer in LVB
        mov     eax,pcbuff           ; 

ini_get_previous_cell4:
        mov     eax,dword ptr[eax]   ; EAX = cell value
        mov     ecx,eax              ; get cell value
        and     ecx,MFI_CHARMASK     ; 
        shr     ecx,16               ; 
        cmp     cx,currentFontNo     ; use same font as current?
        jne short ini_non_dbcsev_detect4 ; 
        jmp short ini_call_checkdbcsenv4 ; now call CheckDBCSEnv

ini_call_checkdbcsenv4:
        push    eax                  ; cell Value
        push    currentFD            ; ptr to required fontdetails
        call    CheckDBCSEnv         ; determine whether the cell is
                                     ; in DBCSEnv renge or not
        add     esp,8                ; 
        or      eax,eax              ; the cell is in renge?
        jz short ini_non_dbcsev_detect4  ; no, detected char end pos
        inc     DBCSCellCount        ; yes, inc DBCSCellCount
        jmp short ini_pre_check_before_backward4 ; no, continue back scan

ini_non_dbcsev_detect4:
        mov     al,DBCSCellCount     ; 
        and     al,01h               ; DBCSCellCount = odd ?
        jnz ini_parse_dt4            ; odd, so current cell is
                                     ; DBCSTrailing

ini_parse_sbcs_or_dl4:               ; even, so current cell is SBCS
                                     ; or DBCSLeading
        push    currentCP            ; 
        push    currentFD            ; 
        call    CheckDBCSEnv         ; determine whether the cell is
                                     ; in DBCSEnv renge or not
        add     esp,8                ; 
        or      eax,eax              ; the cell is in renge?
        jz ini_parse_sbcs4           ; no, so it's SBCS cell

ini_parse_dl4:
        mov     eax,pCharBuffer      ; it seems dl, check more
        sub     eax,AIxfer.pLVBLast  ; last of LVB?
        jge ini_parse_sbcs4          ; last of LVB, treat this as SBCS cell
        mov     edx,currentFD        ; 
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        movzx   ecx,currentFontNo    ; 
        swap    ecx                  ; 
        or      ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp ini_inv_dl4              ; 

@@:     mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_FONTMASK    ; get font bits
        mov     eax,pCharBuffer      ; 
        mov     eax,dword ptr[eax+4] ; get DBCSTrailing cell
        and     eax,DBCS_FONTMASK    ; get font bits of dt
        cmp     ecx,eax              ; use same font No.?
        je short @f                  ; yes
        mov     ecx,currentCP        ; no, treat this SBCS
        and     ecx,MFI_CHARMASK     ; 
        jmp ini_is_sbcs4             ; 

@@:
        mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_CHARMASK    ; 
        shl     ecx,8                ; 
        mov     eax,pCharBuffer      ; 
        mov     eax,dword ptr[eax+4] ; 
        and     eax,MFI_CHARMASK     ; 
        or      ecx,eax              ; construct DBCS code point
        jmp ini_is_dl4               ; 

ini_parse_dt4:
        mov     edx,currentFD        ; It seems dt, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        mov     cx,currentFontNo     ; 
        swap    ecx                  ; 
        or      ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short ini_inv_dt4        ; 

@@:     mov     eax,pCharBuffer      ; 
        mov     eax,dword ptr[eax-4] ; get DBCSLeading cell
        and     eax,DBCS_FONTMASK    ; get font bits of dl
        mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_FONTMASK    ; get font bits
        cmp     ecx,eax              ; use same font No.?
        je short @f                  ; yes
        mov     ecx,currentCP        ; no, treat this SBCS
        and     ecx,MFI_CHARMASK     ; 
        jmp short ini_is_sbcs4       ; 

@@:     mov     eax,pCharBuffer      ; 
        mov     eax,dword ptr[eax-4] ; 
        and     eax,DBCS_CHARMASK    ; 
        shl     eax,8                ; 
        mov     ecx,currentCP        ; 
        and     ecx,MFI_CHARMASK     ; 
        or      ecx,eax              ; 
        jmp short ini_is_dt4         ; 

ini_parse_sbcs4:
        mov     edx,currentFD        ; it seems sbcs, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_DBCS  ; use DBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; use invalid DBCS cp (i.e, 0)
        mov     cx,currentFontNo     ; 
        swap    ecx                  ; 
        jmp short ini_is_sbcs4       ; 

@@:     mov     ecx,currentCP        ; 
        and     ecx,MFI_CHARMASK     ; 
        jmp short ini_is_sbcs4       ; 

ini_is_dl4:                          ; yes, so it's DBCSLeading cell
        sub     eax,eax              ; 
        mov     eax,1                ; indicate DBCSLeading
        jmp short ini_return_to_parent4  ; then exit

ini_is_dt4:
        sub     eax,eax              ; 
        mov     eax,2                ; indicate DBCSTrailing
        jmp short ini_return_to_parent4  ; then exit

ini_is_sbcs4:
        sub     eax,eax              ; indicate SBCS
        jmp short ini_return_to_parent4  ; then exit

ini_inv_dl4:                         ; invalid DBCSLeading cell
        sub     eax,eax              ; 
        dec     eax                  ; 
        jmp short ini_return_to_parent4  ; then exit

ini_inv_dt4:
        sub     eax,eax              ; 
        sub     eax,2                ; 

ini_return_to_parent4:               ; then exit

cEnd


;/********************************************************************/
;/* IniCheckCellType2                                                */
;/*                                                                  */
;/* This subroutine determines current cell type by scanning LVB     */
;/* backward.                                                        */
;/*                                                                  */
;/* Entry - pfdBaseFont : pFontDetails for base font                 */
;/*         pCharBuffer : position in char buffer                    */
;/*                                                                  */
;/* Exit  - EAX : Cell Type                                          */
;/*                  0 = SBCS Cell                                   */
;/*                  1 = DBCSLeading Cell                            */
;/*                  2 = DBCSTrailing Cell                           */
;/*                 -1 = Invalid DBCSLeading Cell                    */
;/*                 -2 = Invalid DBCSTrailing Cell                   */
;/*                                                                  */
;/*         ECX : Code Point to be used                              */
;/*                                                                  */
;/* Summarised Logic is as follows:                                  */
;/*                                                                  */
;/* C :current cell                                                  */
;/* D :Cell which is not last cp of a char.(DBCSLeading/DBCSTrailing)*/
;/* X :Cell which is last cp of a char.    (SBCS/DBCSTrailing)       */
;/*                                                                  */
;/* Case (1)                                                         */
;/*                          given CharRect in LVB                   */
;/*          back scan +-------------------------                    */
;/*               <-   |                                             */
;/*          XD-- DDDDD|C                                            */
;/*           |       ||                                             */
;/*           +-------+|                                             */
;/*             even   |                                             */
;/*      (These cells  |                                             */
;/*    use same font.) |                                             */
;/*                    |                                             */
;/*                  left edge of CharRect                           */
;/*                                                                  */
;/*   In this case, current cell C is DBCSLeading or SBCS cell. So   */
;/*   we can start at this cell and determine its type by checking   */
;/*   whether the current cell C is in DBCSEv renge or not.          */
;/*                                                                  */
;/* Case (2)                                                         */
;/*                          given CharRect in LVB                   */
;/*          back scan +-------------------------                    */
;/*               <-   |                                             */
;/*         XDD-- DDDDD|C                                            */
;/*          |        ||                                             */
;/*          +--------+|                                             */
;/*            odd     |                                             */
;/*       (These cells |                                             */
;/*    use same font.) |                                             */
;/*                    |                                             */
;/*                    |                                             */
;/*                  left edge of CharRect                           */
;/*                                                                  */
;/*   In this case, current cell C is DBCSTrailing. So we can        */
;/*   construct DBCS codepoint with the current cell C and the cell  */
;/*   just left to the left edge of given CharRect.                  */
;/*                                                                  */
;/*                                                                  */
;/*   In this logic, we assume that DBCSLeading and DBCSTrailing     */
;/*   cells use same font. so if we encounter a cell which uses      */
;/*   different font from that of current font, we determine this    */
;/*   cell as the one which is last cp of a char.(SBCS/DBCSTrailing) */
;/*   So, if we come to call CheckDBCSEnv in this routine, the       */
;/*   current cell uses NLSCA_MBCS font. This font must have DBCS    */
;/*   Environment vectors.                                           */
;/*                                                                  */
;/* Registers: EBX,EDX,ESI,EDI,ES,DS     -- will be preserved        */
;/*            EAX,ECX                   -- will be changed          */
;/********************************************************************/
        align   4
cProc IniCheckCellType2,<NEAR,PUBLIC>,<ebx,edx,esi,edi,es,ds>
        parmD   pfdBaseFont
        parmD   pCharBuffer
        localD  pcbuff
        localD  currentCP
        localB  DBCSCellCount
cBegin

        mov     DBCSCellCount,0      ; initialize DBCSCellCount
        mov     eax,pCharBuffer      ; 
        mov     pcbuff,eax           ; 

ini_get_cell2:
        movzx   ecx,word ptr[eax]    ; ECX = current cell
        mov     currentCP,ecx        ; keep current cell value
        mov     edx,pfdBaseFont      ; system fontdetails

ini_see_parse_flag2:
        movzx   eax,word ptr [edx].NLSParseFlag
        test    eax,NLSCA_SBCS       ; SBCS parsing?
        jnz ini_parse_sbcs2          ; yes
        test    eax,NLSCA_DBCS       ; DBCS parsing?
        jz short ini_pre_check_before_backward2 ; no, MBCS parsing.

ini_parse_dl_or_dt2:
        mov     eax,pcbuff           ; It's DBCS font, so dl or dt
        sub     eax,AIxfer.pLVBFirst ; EAX holds num of byte from top
                                     ; of LVB
        jle short ini_parse_dl2      ; if top of LVB, it's dl.
        shr     eax,2                ; eax holds cell count from top of LVB
        and     al,01h               ; even count?
        jz short ini_parse_dl2       ; yes, so it's dl.
        jmp ini_parse_dt2            ; odd count, so it's dt.

ini_pre_check_before_backward2:
        mov     eax,pcbuff           ; 
        sub     eax,2                ; EAX = address of previous cell
        sub     eax,AIxfer.pLVBFirst ; reach to first LVB cell?
        jns short ini_go_one_step_backward2 ; no, so we can go backward
        jmp short ini_parse_sbcs_or_dl2  ; yes, so SBCS or DBCS Leading

ini_go_one_step_backward2:
        sub     pcbuff,2             ; do subtract pointer in LVB
        mov     eax,pcbuff           ; 

ini_get_previous_cell2:
        movzx   eax,word ptr[eax]    ; EAX = cell value

ini_call_checkdbcsenv2:
        push    eax                  ; cell Value
        push    pfdBaseFont          ; ptr to required fontdetails
        call    CheckDBCSEnv         ; determine whether the cell is
                                     ; in DBCSEnv renge or not
        add     esp,8                ; 
        or      eax,eax              ; the cell is in renge?
        jz short ini_non_dbcsev_detect2  ; no, detected char end pos
        inc     DBCSCellCount        ; yes, inc DBCSCellCount
        jmp short ini_pre_check_before_backward2 ; no, continue back scan

ini_non_dbcsev_detect2:
        mov     al,DBCSCellCount     ; 
        and     al,01h               ; DBCSCellCount = odd ?
        jnz short ini_parse_dt2      ; odd, so current cell is
                                     ; DBCSTrailing

ini_parse_sbcs_or_dl2:               ; even, so current cell is SBCS
                                     ; or DBCSLeading
        push    currentCP            ; 
        push    pfdBaseFont          ; 
        call    CheckDBCSEnv         ; determine whether the cell is
                                     ; in DBCSEnv renge or not
        add     esp,8                ; 
        or      eax,eax              ; the cell is in renge?
        jz short ini_parse_sbcs2     ; no, so it's SBCS cell

ini_parse_dl2:
        mov     eax,pCharBuffer      ; it seems dl, check more
        sub     eax,AIxfer.pLVBLast  ; last of LVB?
        jge short ini_parse_sbcs2    ; last of LVB, treat this as SBCS cell
        mov     edx,pfdBaseFont      ; 
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        mov     ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp ini_inv_dl2              ; 

@@:
        mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_CHARMASK    ; 
        shl     ecx,8                ; 
        mov     eax,pCharBuffer      ; 
        movzx   eax,word ptr[eax+2]  ; 
        and     eax,DBCS_CHARMASK    ; 
        or      ecx,eax              ; construct DBCS code point
        jmp short ini_is_dl2         ; 

ini_parse_dt2:
        mov     edx,pfdBaseFont      ; It seems dt, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        mov     ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short ini_inv_dt2        ; 

@@:     mov     eax,pCharBuffer      ; 
        movzx   eax,word ptr[eax-2]  ; 
        and     eax,DBCS_CHARMASK    ; 
        shl     eax,8                ; 
        mov     ecx,currentCP        ; 
        and     ecx,DBCS_CHARMASK    ; 
        or      ecx,eax              ; 
        jmp short ini_is_dt2         ; 

ini_parse_sbcs2:
        mov     edx,pfdBaseFont      ; it seems sbcs, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_DBCS  ; use DBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; use invalid DBCS cp (i.e, 0)
        jmp short ini_is_sbcs2       ; 

@@:     mov     ecx,currentCP        ; 
        and     ecx,DBCS_CHARMASK    ; 
        jmp short ini_is_sbcs2       ; 

ini_is_dl2:                          ; yes, so it's DBCSLeading cell
        sub     eax,eax              ; 
        mov     eax,1                ; indicate DBCSLeading
        jmp short ini_return_to_parent2  ; then exit

ini_is_dt2:
        sub     eax,eax              ; 
        mov     eax,2                ; indicate DBCSTrailing
        jmp short ini_return_to_parent2  ; then exit

ini_is_sbcs2:
        sub     eax,eax              ; indicate SBCS
        jmp short ini_return_to_parent2  ; then exit

ini_inv_dl2:                         ; invalid DBCSLeading cell
        sub     eax,eax              ; 
        dec     eax                  ; 
        jmp short ini_return_to_parent2  ; then exit

ini_inv_dt2:
        sub     eax,eax              ; 
        sub     eax,2                ; 

ini_return_to_parent2:                   ; then exit

cEnd

;/********************************************************************/
;/* CheckCellType4                                                   */
;/*                                                                  */
;/* This subroutine determines current cell type.                    */
;/*                                                                  */
;/*                                                                  */
;/* Entry - pfdBaseFont : pFontDetails for base font                 */
;/*         pCharBuffer : position in char buffer                    */
;/*                                                                  */
;/* Exit  - EAX : Cell Type                                          */
;/*                  0 = SBCS Cell                                   */
;/*                  1 = DBCSLeading Cell                            */
;/*                 -1 = Invalid DBCSLeading Cell                    */
;/*                                                                  */
;/*         ECX : low word  - Code Point to be used                  */
;/*               high word - Font No. to be used                    */
;/*         EDX : pFontDetails to be used                            */
;/*                                                                  */
;/*                                                                  */
;/* Registers: EBX,ESI,EDI,ES,DS         -- will be preserved        */
;/*            EAX,ECX,EDX               -- will be changed          */
;/********************************************************************/
        align   4
cProc CheckCellType4,<NEAR,PUBLIC>,<ebx,esi,edi,es,ds>
        parmD   pfdBaseFont
        parmD   pCharBuffer
        localD  currentFD
        localD  currentCP
        localW  currentFontNo
cBegin

        mov     eax,pCharBuffer      ; 

get_cell4:
        mov     ecx,dword ptr[eax]   ; ECX = current cell
        mov     currentCP,ecx        ; keep current cell value
        and     ecx,MFI_CHARMASK     ; 
        shr     ecx,16               ; 
        mov     currentFontNo,cx     ; 
        mov     edx,SIZE FONTDETAILS ; 
        imul    edx,ecx              ; 
        add     edx,pfdBaseFont      ; 
        or      edx,edx              ; pFontDetails not set or cleared?
        jz short @f                  ; not set or cleared.
        mov     eax,dword ptr [edx].pFocaFont
        or      eax,eax              ; pFocaFont null?
        jnz short see_parse_flag4    ; no, so see parse flag
@@:
        sub     eax,eax              ; invalid font used. so use SBCS cp
        mov     edx,pfdBaseFont      ; with system fontdetails.
        mov     ecx,dword ptr[edx].ulDefCodepoint
        jmp return_to_parent4        ; 

see_parse_flag4:
        mov     currentFD,edx        ; save pfontdetails
        movzx   eax,word ptr [edx].NLSParseFlag
        test    eax,NLSCA_SBCS       ; SBCS parsing?
        jnz parse_sbcs4              ; yes
        test    eax,NLSCA_DBCS       ; DBCS parsing?
        jnz short parse_dl4          ; yes
                                     ; no, MBCS parsing

parse_sbcs_or_dl4:
                                     ; current cell is SBCS or dl
        push    currentCP            ; 
        push    currentFD            ; 
        call    CheckDBCSEnv         ; determine whether the cell is
                                     ; in DBCSEnv renge or not
        add     esp,8                ; 
        or      eax,eax              ; the cell is in renge?
        jz short parse_sbcs4         ; no, so it's SBCS cell

parse_dl4:
        mov     eax,pCharBuffer      ; it seems dl, check more
        sub     eax,AIxfer.pLVBLast  ; last of LVB?
        jge short parse_sbcs4        ; last of LVB, treat this as SBCS cell
        mov     edx,currentFD        ; 
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        movzx   ecx,currentFontNo    ; 
        swap    ecx                  ; 
        or      ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short inv_dl4            ; 

@@:     mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_FONTMASK    ; get font bits
        mov     eax,pCharBuffer      ; 
        mov     eax,dword ptr[eax+4] ; get DBCSTrailing cell
        and     eax,DBCS_FONTMASK    ; get font bits of dt
        cmp     ecx,eax              ; use same font No.?
        je short @f                  ; yes
        mov     ecx,currentCP        ; no, treat this SBCS
        and     ecx,MFI_CHARMASK     ; 
        jmp short is_sbcs4           ; 

@@:
        mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_CHARMASK    ; 
        shl     ecx,8                ; 
        mov     eax,pCharBuffer      ; 
        mov     eax,dword ptr[eax+4] ; 
        and     eax,MFI_CHARMASK     ; 
        or      ecx,eax              ; construct DBCS code point
        jmp short is_dl4             ; 

parse_sbcs4:
        mov     edx,currentFD        ; it seems sbcs, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_DBCS  ; use DBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; use invalid DBCS cp (i.e, 0)
        mov     cx,currentFontNo     ; 
        swap    ecx                  ; 
        jmp short is_sbcs4           ; 

@@:     mov     ecx,currentCP        ; 
        and     ecx,MFI_CHARMASK     ; 
        jmp short is_sbcs4           ; 

is_dl4:                              ; yes, so it's DBCSLeading cell
        sub     eax,eax              ; 
        mov     eax,1                ; indicate DBCSLeading
        jmp short return_to_parent4  ; then exit

is_sbcs4:
        sub     eax,eax              ; indicate SBCS
        jmp short return_to_parent4  ; then exit

inv_dl4:                             ; invalid DBCSLeading cell
        sub     eax,eax              ; 
        dec     eax                  ; 

return_to_parent4:                   ; then exit

cEnd


;/********************************************************************/
;/* CheckCellType2                                                   */
;/*                                                                  */
;/* This subroutine determines current cell type.                    */
;/*                                                                  */
;/*                                                                  */
;/* Entry - pfdBaseFont : pFontDetails for base font                 */
;/*         pCharBuffer : position in char buffer                    */
;/*                                                                  */
;/* Exit  - EAX : Cell Type                                          */
;/*                  0 = SBCS Cell                                   */
;/*                  1 = DBCSLeading Cell                            */
;/*                 -1 = Invalid DBCSLeading Cell                    */
;/*                                                                  */
;/*         ECX : Code Point to be used                              */
;/*                                                                  */
;/* Registers: EBX,EDX,ESI,EDI,ES,DS     -- will be preserved        */
;/*            EAX,ECX                   -- will be changed          */
;/********************************************************************/
        align   4
cProc CheckCellType2,<NEAR,PUBLIC>,<ebx,edx,esi,edi,es,ds>
        parmD   pfdBaseFont
        parmD   pCharBuffer
        localD  currentCP
cBegin

        mov     eax,pCharBuffer      ; 

get_cell2:
        movzx   ecx,word ptr[eax]    ; ECX = current cell
        mov     currentCP,ecx        ; keep current cell value
        mov     edx,pfdBaseFont      ; system fontdetails

see_parse_flag2:
        movzx   eax,word ptr [edx].NLSParseFlag
        test    eax,NLSCA_SBCS       ; SBCS parsing?
        jnz short parse_sbcs2        ; yes
        test    eax,NLSCA_DBCS       ; DBCS parsing?
        jnz short parse_dl2          ; yes

parse_sbcs_or_dl2:
                                     ; current cell is SBCS or dl
        push    currentCP            ; 
        push    pfdBaseFont          ; 
        call    CheckDBCSEnv         ; determine whether the cell is
                                     ; in DBCSEnv renge or not
        add     esp,8                ; 
        or      eax,eax              ; the cell is in renge?
        jz short parse_sbcs2         ; no, so it's SBCS cell

parse_dl2:
        mov     eax,pCharBuffer      ; it seems dl, check more
        sub     eax,AIxfer.pLVBLast  ; last of LVB?
        jge short parse_sbcs2        ; last of LVB, treat this as SBCS cell
        mov     edx,pfdBaseFont      ; 
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        mov     ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short inv_dl2            ; 

@@:
        mov     ecx,currentCP        ; get cell value again
        and     ecx,DBCS_CHARMASK    ; 
        shl     ecx,8                ; 
        mov     eax,pCharBuffer      ; 
        movzx   eax,word ptr[eax+2]  ; 
        and     eax,DBCS_CHARMASK    ; 
        or      ecx,eax              ; construct DBCS code point
        jmp short is_dl2             ; 

parse_sbcs2:
        mov     edx,pfdBaseFont      ; it seems sbcs, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_DBCS  ; use DBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; use invalid DBCS cp (i.e, 0)
        jmp short is_sbcs2           ; 

@@:     mov     ecx,currentCP        ; 
        and     ecx,DBCS_CHARMASK    ; 
        jmp short is_sbcs2           ; 

is_dl2:                              ; yes, so it's DBCSLeading cell
        sub     eax,eax              ; 
        mov     eax,1                ; indicate DBCSLeading
        jmp short return_to_parent2  ; then exit

is_sbcs2:
        sub     eax,eax              ; indicate SBCS
        jmp short return_to_parent2  ; then exit

inv_dl2:                             ; invalid DBCSLeading cell
        sub     eax,eax              ; 
        dec     eax                  ; 

return_to_parent2:                   ; then exit

cEnd


;/********************************************************************/
;/* ExplisitCheckCellType4                                           */
;/*                                                                  */
;/* This subroutine determines current cell type by checking DBCS    */
;/* byte bit and DBCS 2nd byte bit.                                  */
;/*                                                                  */
;/* Entry - pfdBaseFont : pFontDetails for base font                 */
;/*         pCharBuffer : position in char buffer                    */
;/*                                                                  */
;/* Exit  - EAX : Cell Type                                          */
;/*                  0 = SBCS Cell                                   */
;/*                  1 = DBCSLeading Cell                            */
;/*                  2 = DBCSTrailing Cell                           */
;/*                 -1 = Invalid DBCSLeading Cell                    */
;/*                 -2 = Invalid DBCSTrailing Cell                   */
;/*                                                                  */
;/*         ECX : low word  - Code Point to be used                  */
;/*               high word - Font No. to be used                    */
;/*         EDX : pFontDetails to be used                            */
;/*                                                                  */
;/* Registers: EBX,ESI,EDI,ES,DS         -- will be preserved        */
;/*            EAX,ECX,EDX               -- will be changed          */
;/********************************************************************/
        align   4
cProc ExplisitCheckCellType4,<NEAR,PUBLIC>,<ebx,esi,edi,es,ds>
        parmD   pfdBaseFont
        parmD   pCharBuffer
        localW  currentFontNo
cBegin

        mov     edi,pfdBaseFont      ; 
        mov     esi,pCharBuffer      ; 

exp_get_cell4:                       ; no, it's four byte cell format
        mov     ecx,[esi]            ; EAX = current cell
        mov     ebx,ecx              ; keep current cell value
        and     ecx,MFI_CHARMASK     ; 
        shr     ecx,16               ; 
        mov     currentFontNo,cx     ; 
        mov     edx,SIZE FONTDETAILS ; 
        imul    edx,ecx              ; 
        add     edx,edi              ; 
        or      edx,edx              ; pFontDetails not set or cleared?
        jz short @f                  ; not set or cleared.
        mov     eax,dword ptr [edx].pFocaFont
        or      eax,eax              ; 
        jnz short exp_see_parse_flag4 ; 
@@:
        sub     eax,eax              ; invalid font used. so use SBCS cp
        mov     edx,edi              ; with system fontdetails.
        mov     ecx,dword ptr[edx].ulDefCodepoint
        jmp exp_return_to_parent4    ; 

exp_see_parse_flag4:
        movzx   eax,word ptr [edx].NLSParseFlag
        test    eax,NLSCA_SBCS       ; 
        jnz exp_parse_sbcs4          ; 
        test    eax,NLSCA_DBCS       ; 
        jz short exp_check_dbcs_bits4

exp_parse_dl_or_dt4:
        mov     eax,esi              ; It's DBCS font, so dl or dt
        sub     eax,AIxfer.pLVBFirst ; EAX holds num of byte from top
                                     ; of LVB
        jle short exp_parse_dl4      ; if top of LVB, it's dl.
        shr     eax,4                ; eax holds cell count from top of LVB
        and     al,01h               ; even count?
        jz short exp_parse_dl4       ; yes, so it's dl.
        jmp short exp_parse_dt4      ; odd count, so it's dt.

exp_check_dbcs_bits4:
        mov     eax,ebx              ; restore cell value
        test    eax,DBCS_DTBIT4      ; DBCSTrailing?
        jnz short exp_parse_dt4      ; yes, so it's DBCSTrailing
        test    eax,DBCS_DBIT4       ; DBCS? (here DBCSLeading?)
        jnz short exp_parse_dl4      ; yes, so it's DBCSLeading
        jmp exp_parse_sbcs4          ; otherwise it's SBCS

exp_parse_dl4:
        mov     eax,esi              ; it seems dl, check more
        sub     eax,AIxfer.pLVBLast  ; last of LVB?
        jge exp_parse_sbcs4          ; last of LVB, treat this as SBCS cell
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        movzx   ecx,currentFontNo    ; 
        swap    ecx                  ; 
        or      ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp exp_inv_dl4              ; 

@@:     mov     ecx,ebx              ; get cell value again
        and     ecx,DBCS_FONTMASK    ; get font bits
        mov     eax,dword ptr[esi+4] ; get DBCSTrailing cell
        and     eax,DBCS_FONTMASK    ; get font bits of dt
        cmp     ecx,eax              ; use same font No.?
        je short @f                  ; yes
        mov     ecx,ebx              ; no, treat this SBCS
        and     ecx,MFI_CHARMASK     ; 
        jmp exp_is_sbcs4             ; 

@@:
        mov     ecx,ebx              ; get cell value again
        and     ecx,DBCS_CHARMASK    ; 
        shl     ecx,8                ; 
        mov     eax,dword ptr[esi+4] ; 
        and     eax,MFI_CHARMASK     ; 
        or      ecx,eax              ; construct DBCS code point
        jmp short exp_is_dl4         ; 

exp_parse_dt4:
        mov     eax,esi              ; it seems dt, check more
        sub     eax,AIxfer.pLVBFirst ; top  of LVB?
        jle short exp_parse_sbcs4    ; top of LVB, treat this as SBCS cell
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; 
        mov     cx,currentFontNo     ; 
        swap    ecx                  ; 
        or      ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short exp_inv_dt4        ; 

@@:     mov     eax,dword ptr[esi-4] ; get DBCSLeading cell
        and     eax,DBCS_FONTMASK    ; get font bits of dl
        mov     ecx,ebx              ; get cell value again
        and     ecx,DBCS_FONTMASK    ; get font bits
        cmp     ecx,eax              ; use same font No.?
        je short @f                  ; yes
        mov     ecx,ebx              ; no, treat this SBCS
        and     ecx,MFI_CHARMASK     ; 
        jmp short exp_is_sbcs4       ; 

@@:     mov     eax,dword ptr[esi-4] ; 
        and     eax,DBCS_CHARMASK    ; 
        shl     eax,8                ; 
        mov     ecx,ebx              ; 
        and     ecx,MFI_CHARMASK     ; 
        or      ecx,eax              ; 
        jmp short exp_is_dt4         ; 

exp_parse_sbcs4:
                                     ; it seems sbcs, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_DBCS  ; use DBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; use invalid DBCS cp (i.e, 0)
        mov     cx,currentFontNo     ; 
        swap    ecx                  ; 
        jmp short exp_is_sbcs4       ; 

@@:     mov     ecx,ebx              ; 
        and     ecx,MFI_CHARMASK     ; 
        jmp short exp_is_sbcs4       ; 

exp_is_dl4:                          ; yes, so it's DBCSLeading cell
        sub     eax,eax              ; 
        mov     eax,1                ; indicate DBCSLeading
        jmp short exp_return_to_parent4 ; then exit

exp_is_dt4:
        sub     eax,eax              ; 
        mov     eax,2                ; indicate DBCSTrailing
        jmp short exp_return_to_parent4 ; then exit

exp_is_sbcs4:                        ; 
        sub     eax,eax              ; indicate SBCS
        jmp short exp_return_to_parent4 ; then exit

exp_inv_dl4:                         ; invalid DBCSLeading cell
        sub     eax,eax              ; 
        dec     eax                  ; 
        jmp short exp_return_to_parent4 ; then exit

exp_inv_dt4:
        sub     eax,eax              ; 
        sub     eax,2                ; 

exp_return_to_parent4:               ; then exit

cEnd

;/********************************************************************/
;/* ExplisitCheckCellType2                                           */
;/*                                                                  */
;/* This subroutine determines current cell type by checking DBCS    */
;/* byte bit and DBCS 2nd byte bit.                                  */
;/*                                                                  */
;/* Entry - pfdBaseFont : pFontDetails for base font                 */
;/*         pCharBuffer : position in char buffer                    */
;/*                                                                  */
;/* Exit  - EAX : Cell Type 0 = SBCS Cell                            */
;/*                         1 = DBCSLeading Cell                     */
;/*                         2 = DBCSTrailing Cell                    */
;/*                        -1 = Invalid DBCSLeading Cell             */
;/*                        -2 = Invalid DBCSTrailing Cell            */
;/*         ECX : Code Point to be used                              */
;/*                                                                  */
;/* Registers: EBX,ESI,EDI,ES,DS         -- will be preserved        */
;/*            EAX,ECX                   -- will be changed          */
;/********************************************************************/
        align   4
cProc ExplisitCheckCellType2,<NEAR,PUBLIC>,<ebx,edx,esi,edi,es,ds>
        parmD   pfdBaseFont
        parmD   pCharBuffer
cBegin

        mov     edi,pfdBaseFont      ; 
        mov     esi,pCharBuffer      ; 

exp_get_cell2:
        movzx   ecx,word ptr [esi]   ; EAX = current cell
        mov     ebx,ecx              ; keep current cell value
        mov     edx,edi              ; system fontdetails

exp_see_parse_flag2:
        movzx   eax,word ptr [edx].NLSParseFlag
        test    eax,NLSCA_SBCS       ; 
        jnz exp_parse_sbcs2          ; 
        test    eax,NLSCA_DBCS       ; 
        jz short exp_check_dbcs_bits2

exp_parse_dl_or_dt2:                 ; it's DBCS font, so dl or dt
        mov     eax,esi              ; 
        sub     eax,AIxfer.pLVBFirst ; EAX holds num of byte from top
                                     ; of LVB
        jle short exp_parse_dl2      ; if top of LVB, it's dl.
        shr     eax,2                ; eax holds cell count from top of LVB
        and     al,01h               ; even count?
        jz short exp_parse_dl2       ; yes, so it's dl.
        jmp short exp_parse_dt2      ; odd count, so it's dt.

exp_check_dbcs_bits2:
        mov     eax,ebx              ; restore cell value
        test    eax,DBCS_DTBIT2      ; DBCSTrailing?
        jnz short exp_parse_dt2      ; yes, so it's DBCSTrailing
        test    eax,DBCS_DBIT2       ; DBCS? (here DBCSLeading?)
        jnz short exp_parse_dl2      ; yes, so it's DBCSLeading
        jmp short exp_parse_sbcs2    ; otherwise it's SBCS

exp_parse_dl2:
        mov     eax,esi              ; it seems dl, check more
        sub     eax,AIxfer.pLVBLast  ; last of LVB?
        jge short exp_parse_sbcs2    ; last of LVB, treat this as SBCS cell
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        mov     ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short exp_inv_dl2        ; 

@@:     mov     ecx,ebx              ; 
        and     ecx,DBCS_CHARMASK    ; 
        shl     ecx,8                ; 
        movzx   eax,word ptr[esi+2]  ; 
        and     eax,DBCS_CHARMASK    ; 
        or      ecx,eax              ; 
        jmp short exp_is_dl2         ; 

exp_parse_dt2:
        mov     eax,esi              ; it seems dt, check more
        sub     eax,AIxfer.pLVBFirst ; top  of LVB?
        jle short exp_parse_sbcs2    ; top of LVB, treat this as SBCS cell
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_SBCS  ; use SBCS font?
        jz short @f                  ; no
        mov     ecx,dword ptr[edx].ulDefCodepoint ; use SBCS default cp
        jmp short exp_inv_dt2        ; 

@@:     movzx   eax,word ptr[esi-2]  ; 
        and     eax,DBCS_CHARMASK    ; 
        shl     eax,8                ; 
        mov     ecx,ebx              ; 
        and     ecx,DBCS_CHARMASK    ; 
        or      ecx,eax              ; 
        jmp short exp_is_dt2         ; 

exp_parse_sbcs2:
                                     ; it seems sbcs, check more
        movzx   eax,word ptr[edx].NLSFontFlag ; see font flag
        test    eax,NLSCA_FONT_DBCS  ; use DBCS font?
        jz short @f                  ; no
        sub     ecx,ecx              ; use invalid DBCS cp (i.e, 0)
        jmp short exp_is_sbcs2       ; 
@@:     mov     ecx,ebx              ; 
        and     ecx,DBCS_CHARMASK    ; 
        jmp short exp_is_sbcs2       ; 

exp_is_dl2:                          ; yes, so it's DBCSLeading cell
        sub     eax,eax              ; 
        mov     eax,1                ; indicate DBCSLeading
        jmp short exp_return_to_parent2 ; then exit

exp_is_dt2:
        sub     eax,eax              ; 
        mov     eax,2                ; indicate DBCSTrailing
        jmp short exp_return_to_parent2 ; then exit

exp_is_sbcs2:
        sub     eax,eax              ; indicate SBCS
        jmp short exp_return_to_parent2 ; then exit

exp_inv_dl2:                         ; invalid DBCSLeading cell
        sub     eax,eax              ; 
        dec     eax                  ; 
        jmp short exp_return_to_parent2 ; then exit

exp_inv_dt2:
        sub     eax,eax              ; 
        sub     eax,2                ; 

exp_return_to_parent2:                ; then exit

cEnd


;/********************************************************************/
;/* GetToBeDrawnRect                                                 */
;/*                                                                  */
;/* This subroutine checks whether the CharRect and current clipping */
;/* rectangle have intersect region or not. And if they have, this   */
;/* routine returns drawing area by LVB coords.                      */
;/*                                                                  */
;/*                                                                  */
;/* Entry - pAvioInfo : pointer to AvioInfo structure                */
;/* Entry - pClipRect : pointer to structure of current clipping     */
;/*                     rectangle                                    */
;/*       - lPoint0   : CharRect's point (x0,y0) (Screen coord)      */
;/*       - lPoint1   : CharRect's point (x1,y1) (Screen coord)      */
;/*                                                                  */
;/* Exit  - EAX       : (0= no error, FFFFFFFFh= no intersect)       */
;/*                                                                  */
;/* Registers: EBX,ECX,EDX,ESI,EDI,ES,DS     -- will be preserved    */
;/*            EAX                           -- will be changed      */
;/********************************************************************/
        align   4
cProc GetToBeDrawnRect,<NEAR,PUBLIC>,<ebx,ecx,edx,esi,edi,es,ds>
        parmD   pAvioInfo
        parmD   pClipRect
        parmD   lPoint0
        parmD   lPoint1
        localW  sClippedRectX0
        localW  sClippedRectX1
        localW  sClippedRectY0
        localW  sClippedRectY1
cBegin
        mov     ebx,pAvioInfo           ; to access faster
        mov     ecx,pClipRect           ; 
        mov     esi,lPoint0             ; 
        mov     edi,lPoint1             ; 

        ;/************************************************************/
        ;/* At first, We had better check that the CharRect and      */
        ;/* current clip rectangle have intersect region. If not,    */
        ;/* we will exit immediately.                                */
        ;/************************************************************/
        mov     eax,esi                 ; CharRect's left edge is right
        cmp     ax,[ecx].clip_x1        ; to left edge of clip rect?
        jg no_intersect                 ; yes, so no intersect region
        shr     eax,16                  ; CharRect's top edge is below
        cmp     ax,[ecx].clip_y1        ; to bottom edge of clip rect?
        jg no_intersect                 ; yes, so no intersect region
        mov     eax,edi                 ; CharRect's right edge is left
        cmp     ax,[ecx].clip_x0        ; to right edge of clip rect?
        jl no_intersect                 ; yes, so no intersect region
        shr     eax,16                  ; CharRect's bottom edge is
        cmp     ax,[ecx].clip_y0        ; above to top edge of clip
                                        ; rect?
        jl no_intersect                 ; yes, so no intersect region

        ;/************************************************************/
        ;/* CharRect and current clip rectangle have intersect       */
        ;/* region. Now we clip CharRect with current clip rectangle,*/
        ;/* and make clipped rectangle.                              */
        ;/************************************************************/
        mov     eax,esi                 ; compare left edge of CharRect
        cmp     ax,[ecx].clip_x0        ; and clip rect.
        jge short @f                    ; 
        mov     ax,[ecx].clip_x0        ; 
@@:
        mov     sClippedRectX0,ax       ; LF edge of clipped rect =
                                        ; max LF(CharRect, Clip rect)

        shr     eax,16                  ; compare top edge of
        cmp     ax,[ecx].clip_y0        ; CharRect and clip rect.
        jge short @f                    ; 
        mov     ax,[ecx].clip_y0        ; 
@@:
        mov     sClippedRectY0,ax       ; TP edge of clipped rect =
                                        ; max TP(CharRect, Clip rect)

        mov     eax,edi                 ; compare right edge of
        cmp     ax,[ecx].clip_x1        ; CharRect and clip rect.
        jle short @f                    ; 
        mov     ax,[ecx].clip_x1        ; 
@@:
        mov     sClippedRectX1,ax       ; RT edge of clipped rect =
                                        ; min RT(CharRect, Clip rect)

        shr     eax,16                  ; compare bottom edge of
        cmp     ax,[ecx].clip_y1        ; CharRect and clip rect.
        jle short @f                    ; 
        mov     ax,[ecx].clip_y1        ; 
@@:
        mov     sClippedRectY1,ax       ; BT edge of clipped rect =
                                        ; min BT(CharRect, Clip rect)

        ;/************************************************************/
        ;/* We also calculate start/end row and start/end column     */
        ;/* in ClippedRect.                                          */
        ;/************************************************************/
        mov     al,AIxfer.bRow          ; initialize variables
        mov     AIxfer.bClppdRow,al     ; 
        mov     AIxfer.bClppdERow,al    ; 
        mov     al,AIxfer.bColumn       ; 
        mov     AIxfer.bClppdColumn,al  ; 
        mov     AIxfer.bClppdEColumn,al ; 

        mov     eax,esi                 ; AX = LF edge of CharRect
        dec     ax                      ; AX = 1 point LF from LF edge of
                                        ; CharRect
        movzx   cx,[ebx].bCellHeight    ; 
        swap    ecx                     ; 
        movzx   cx,[ebx].bCellWidth     ; 
        mov     dx,sClippedRectX0       ; DX = LF edge of clipped rect
add_cell_width_1:
        add     ax,cx                   ; RT edge of current cell is RT
        cmp     ax,dx                   ; to LF edge of clipped rect?
        jge short start_row             ; yes, go to get start row
        inc     AIxfer.bClppdColumn     ; next right column
        jmp short add_cell_width_1      ; 
start_row:
        swap    eax                     ; AX = TP edge of CharRect
        swap    ecx                     ; CX = cell height
        dec     ax                      ; AX = 1 point above from TP edge
                                        ; of CharRect
        mov     dx,sClippedRectY0       ; DX = TP edge of clipped rect
add_cell_height_1:
        add     ax,cx                   ; BT edge of current cell is
        cmp     ax,dx                   ; below to TP edge of clipped
                                        ; rect?
        jge short end_column            ; yes, go to get end column
        inc     AIxfer.bClppdRow        ; down next row
        jmp short add_cell_height_1
end_column:
        mov     eax,esi                 ; AX = LF edge of CharRect
        swap    ecx                     ; CX = cell width
        mov     dx,sClippedRectX1       ; DX = RT edge of clipped rect
add_cell_width_2:
        add     ax,cx                   ; 
        cmp     ax,dx                   ; LF edge of next cell is RT
                                        ; to RT edge of clipped rect?
        jg short end_row                ; yes,so current is end column
        inc     AIxfer.bClppdEColumn    ; no, go next column
        jmp short add_cell_width_2      ; 
end_row:
        swap    eax                     ; AX = TP edge of CharRect
        swap    ecx                     ; CX = cell height
        mov     dx,sClippedRectY1       ; DX = BT edge of clipped rect
add_cell_height_2:
        add     ax,cx                   ; 
        cmp     ax,dx                   ; TP edge of next cell is
                                        ; below to BT edge of clipped
                                        ; rect?
        jg short row_and_column_done     ; yes, clipped rect done
        inc     AIxfer.bClppdERow       ; go next row
        jmp short add_cell_height_2     ; 

row_and_column_done:
        mov     al,AIxfer.bClppdERow    ;calculate number of row
        sub     al,AIxfer.bClppdRow     ; 
        inc     al                      ; 
        mov     AIxfer.bNumOfRow,al     ; 
        mov     al,AIxfer.bClppdEColumn ;calculate number of column
        sub     al,AIxfer.bClppdColumn  ; 
        inc     al                      ; 
        mov     AIxfer.bNumOfColumn,al  ; 

calculate_y_addr_of_first_row:
        movzx   eax,[ebx].bCellHeight           ; load cell height
        mul     AIxfer.bClppdRow                ; 
        add     ax,[ebx].sYoffset               ; get Y in screen coordinate
        movzx   edx,sClippedRectY0              ; clipped rect Y0
        sub     edx,eax                         ; first row is clipped ?
        jle short full_cell_height_1            ; no
        mov     AIxfer.usFirstRowYAddr,dx       ; yes, so calculate dim2
        movzx   eax,[ebx].bCellHeight           ; 
        sub     eax,edx                         ; 
        dec     eax                             ; 
        mov     AIxfer.usFirstRowDim2,ax        ; 
        jmp short calculate_y_addr_of_next_row

full_cell_height_1:
        sub     edx,edx                         ; first row is not clipped,
        mov     AIxfer.usFirstRowYAddr,dx       ; so Y address is 0 (top of
        movzx   eax,[ebx].bCellHeight           ; cell) and dim2 is cell
        dec     eax                             ; height.
        mov     AIxfer.usFirstRowDim2,ax        ; 

calculate_y_addr_of_next_row:
        movzx   eax,[ebx].bCellHeight           ; 
        dec     eax                             ; 
        mov     AIxfer.usNextRowDim2,ax         ; 

calculate_y_addr_of_last_row:
        movzx   eax,[ebx].bCellHeight           ; 
        mov     edx,eax                         ; 
        mul     AIxfer.bClppdERow               ; 
        add     eax,edx                         ; 
        dec     eax                             ; 
        add     ax,[ebx].sYoffset               ; 
        sub     ax,sClippedRectY1               ; last row is clipped?
        jle short full_cell_height_2            ; no
        movzx   edx,AIxfer.bNumOfRow            ; if 1 row rect, we adjust dim2
        cmp     edx,1                           ; of first row.
        jne short not_one_row_rect              ; this is not 1 row rect.
        movzx   edx,AIxfer.usFirstRowDim2       ; this is 1 row rect, so adjust
        sub     edx,eax                         ; dim2 of first row.
        mov     AIxfer.usFirstRowDim2,dx        ; 
        jmp short region_done                   ; because will not use last row
                                                ; values

not_one_row_rect:
        movzx   edx,[ebx].bCellHeight           ; this is not 1 row rect, so
        sub     edx,eax                         ; calculate dim2 of last row.
        dec     edx                             ; 
        mov     AIxfer.usLastRowDim2,dx         ; 
        jmp short region_done                   ; 

full_cell_height_2:
        movzx   eax,[ebx].bCellHeight           ; last row is not clipped,
        dec     eax                             ; so set cell height as dim2.
        mov     AIxfer.usLastRowDim2,ax         ; 

region_done:
        sub     eax,eax                         ; indicate success
        jmp short rect_got_exit                 ; 

no_intersect:
        sub     eax,eax                 ; indicate no intersect
        dec     eax                     ;   region

rect_got_exit:

cEnd


_TEXT           ends

END
