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

;/****************************************************************************
;*
;* SOURCE FILE NAME = AVIO.ASM
;*
;* DESCRIPTIVE NAME = Avio specific routines
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  This module contains routines that run at ring 2:
;*              Avio specific routines
;*
;* FUNCTIONS    AVIOSUBS
;*              VioAssociate
;*              VioCreatePS
;*              CreateAvio
;*              VioDestroyPS
;*              VioGetDeviceCellSize
;*              VioGetOrg
;*              VioQuerySetIds
;*              VioSetDeviceCellSize
;*              VioSetOrg
;*              VioShowPS
;*              VioGetPSAddress
;*              VioCreateLogFont
;*              VioDeleteSetId
;*              VioQueryFonts
;*              _NULLCHARRECT
;*              SetNLSbits
;*              HeadBounds
;*              PutDBCSs
;*              TailBounds
;*              PutDBCSinEnds
;*              Writes
;*              CheckDBCS
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES   GREENTRY4:FAR
;*                       GREENTRY5:FAR
;*                       GREENTRY6:FAR
;*                       GREENTRY8:FAR
;*                       DOSALLOCSEG:FAR
;*                       DOSFREESEG:FAR
;*                       DOSGETCP:FAR
;*                       DOSGETCTRYINFO:FAR
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   FLAG        APAR    CHANGE DESCRIPTION
;*   ----------  -----   --------------------------------------
;*   @Vr.mpppxx  xxxxx   xxxxxxx
;*   @P1         PTR6415 0300 890126 HDHVG all data to instance NSEG
;*   @P2         PTR6583 0300 890126 HDHVG alter initialisation of BVSCB for VDH
;*   @P3         PTR6584 0300 890126 HDHVG remove save of ds around DosFreeSeg
;*   @P4         PTR7442 0300 890918 HDRL  save FormatID/Reserved for IBMJapan
;*   @P5         AR06846 1.3  900921 TPL   do not return internal resource error
;*   @P6         MSD2061 1.3  910215 AN    set dbcs bits for common lvb format
;*               D1348   1348  2.0  910411 NAKADA    Enable DBCS in Window,
;*   @T83        AR12264 2.0  920221 TPL       Alloc the entire env buffer here
;*   @@SW        62978   2.1  930303 TPL   Increase # of PS from 32 to 128
;*
;******************************************************************************/


EXTRN   GREENTRY4:FAR
EXTRN   GREENTRY5:FAR
EXTRN   GREENTRY6:FAR
EXTRN   GREENTRY8:FAR
EXTRN   DOSALLOCSEG:FAR
EXTRN   DOSFREESEG:FAR
EXTRN   DOSGETCP:FAR
EXTRN   DOSGETCTRYINFO:FAR
EXTRN   AVIOCREATEPS:NEAR
EXTRN   AVIOASSOCIATE:NEAR
EXTRN   AVIODESTROYPS:NEAR
EXTRN   AVIOSETDEVICECELLSIZE:NEAR
EXTRN   AVIOSETORG:NEAR
EXTRN   AVIODELETESETID:NEAR
EXTRN   AVIOQUERYSETIDS:NEAR
EXTRN   AVIOQUERYFONTS:NEAR
EXTRN   ClearGreDat:NEAR                                                ;@T52
EXTRN   EngineCharRect:NEAR                                             ;@T52

EXTRN   bvh_instance:DWORD      ; BVH per process data                  ;@T52

Public  AVIOSUBS
Public  _NULLCHARRECT                                                   ;@T52
Public  VioAssociate
Public  VioCreatePS
Public  CreateAvio
Public  VioDeleteSetId
Public  VioDestroyPS
Public  VioGetDeviceCellSize
Public  VioGetOrg
Public  VioCreateLogFont
Public  VioQuerySetIds
Public  VioQueryFonts
Public  VioSetDeviceCellSize
Public  VioSetOrg
Public  VioShowPS
Public  VioGetPSAddress
.xlist
INCLUDE cmacros.inc

;/*
;** OS2 includes
;*/

INCL_NOCOMMOM equ 1
INCLUDE os2def.inc

INCL_ERRORS equ 1
INCLUDE BSEERR.INC

;/*
;** OS2P includes
;*/

INCLUDE pmwinx.inc              ;@95837

;INCL_WINP equ 1                ;@95837
INCL_AVIOP equ 1
;INCLUDE os2p.inc               ;@95837
INCLUDE pmaviop.inc             ;@95837


;/*
;** PMDDI includes
;*/

INCL_GRE_STRINGS equ 1
INCL_GRE_FONTS equ 1
INCL_GRE_SETID equ 1
INCLUDE pmddi.inc

INCLUDE bvscb.inc
INCL_ERRORS equ 1
INCLUDE struc.inc
INCLUDE BvsEQU.inc
INCLUDE wdhequ.inc                                                      ;@T83
.list

        public  __acrtused              ;Do not use C runtime           ;@T52
__acrtused = 1                          ;  initialization code          ;@T52

avio3seg        equ     <R2CSEG>                                        ;@T52

cp_cpid EQU     parmn                   ;new code page id ;@@1;@@3
cp_parmoff EQU  parmn                   ;offset to the return data area ;@@1
cp_parmsel EQU  parmnm1                 ;selector to the return data area ;@@1

IFDEF D1348
WorldFormat     equ     70h             ; world format ID(common lvb format id)
DBCSFlag        equ     01h             ; dbcs bit
TrailByteFlag   equ     80h             ; dbcs trailing bit
                                        ; dbcs leading byte  : 01h in attr #3
                                        ; dbcs trailing byte : 81h in attr #3
lcid_mask       equ     00000011B
ENDIF ;D1348

avio3seg segment word Public 'code'                                     ;@T52
        Assume  cs:avio3seg,DS:NOTHING,ES:NOTHING

;/***************************************************************************
;*
;* FUNCTION NAME = AVIOSUBS
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;*                 SI    -  AVIO function code
;*
;* OUTPUT        = DS:BX -> BVHINSTANCE data
;*                 AX    -  Appropriate error code
;*                 All others are destroyed
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

AVIOSUBS Proc   FAR


        .if     <si ae 50h> and         ;range check function code
        .if     <si be 5Ch>
            sub     si,50h              ;normalise SI
            add     si,si               ;make SI an index to jump table
            push    ds                                                  ;@T52
            push    bx                                                  ;@T52
            call    cs:AvioTbl[si]
            pop     bx                                                  ;@T52
            pop     ds                                                  ;@T52
        .else
            mov     ax,error_vio_mode   ;SI function code out of range
        .endif
        ret

AVIOSUBS endp

;/*
;** AVIO function jump table :
;*/

AvioTbl dw      VioAssociate            ; 50h
        dw      VioCreatePS             ; 51h
        dw      VioDeleteSetId          ; 52h  Delete Logical Font
        dw      VioDestroyPS            ; 53h
        dw      VioGetDeviceCellSize    ; 54h
        dw      VioGetOrg               ; 55h
        dw      VioCreateLogFont        ; 56h
        dw      VioQuerySetIds          ; 57h
        dw      VioQueryFonts           ; 58h
        dw      VioSetDeviceCellSize    ; 59h
        dw      VioSetOrg               ; 5Ah
        dw      VioShowPS               ; 5Bh
        dw      VioGetPSAddress         ; 5Ch

;/*
;** Start of AVIO functions :
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = VioAssociate
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioAssociate Proc NEAR
        push    ds:[bx].ppbvs_pssel ;PresSpace Sel                      ;@T52
        push    0                ;Pres Space offset
        push    [bp].viohandle   ;AVio handle
        push    [bp].parmnm1     ;DC handle pt 1
        push    [bp].parmn       ;DC handle pt 2
        call    AVIOASSOCIATE
        ret
VioAssociate endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioCreatePS
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioCreatePS Proc NEAR
        mov     si,2                             ;get...
        mov     cx,0                             ;...
        mov     ax,1                             ;...next...
        .while  <cx b 128> and                   ;...                   ;@@SW
        .while  <nonzero ax>                     ;...free...            ;@T52
            mov     ax,[bx].addr_list[si]        ;...
            inc     cx                           ;...Avio...
            inc     si                           ;...
            inc     si                           ;...handle
        .endwhile
        .if     <zero ax>                        ;cx = handle           ;@T52
            mov     ax,error_vio_invalid_parms   ;preset error condition
            .if     <[bp].parmn eq 1> or
            .if     <[bp].parmn eq 3>            ;num attr ok
                .if     <[bp].parmnm2 be 255> and
                .if     <[bp].parmnm3 be 255>    ;width/depth ok
                    .if     <[bp].viohandle eq 0>;reserved ok
                        mov     ax,[bp].parmnm2  ;width
                        mul     [bp].parmnm3     ;depth
                        .if     <zero dx> and                           ;@T52
                        .if     <nonzero ax>     ;width * depth         ;@T52
                            .if     <ax be 4000h> and
                            .if     <[bp].parmn eq 3>
                                call    CreateAvio ;width*depth*numattr ok
                            .else
                                .if     <ax be 8000h> and
                                .if     <[bp].parmn eq 1>
                                    call    CreateAvio
                                .else
                                    mov     ax,error_vio_invalid_parms
                                .endif
                            .endif
                        .else
                            mov     ax,error_vio_invalid_parms
                        .endif
                    .endif
                .endif
            .endif
        .else
            mov     ax,error_vio_no_more_handles
        .endif
        ret

VioCreatePS endp

;/***************************************************************************
;*
;* FUNCTION NAME = CreateAvio
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;*                 CX    -  AVIO handle (index)
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

CreateAvio Proc NEAR


        .if     <[bx].ppbvs_gdtsel eq 0>  ;not yet initiallised         ;@T52
            mov     ax,ds:[bx].cmn_SISsel ;                             ;@T52
            mov     [bx].ppbvs_gdtsel,ax  ;System Info Seg GDT
            mov     ax,ds:[bx].cmn_LISsel ;                             ;@T52
            mov     [bx].ppbvs_ldtsel,ax  ;System Info Seg LDT
        .endif
        mov     di,ds                            ;save BVSNSEG
        lds     si,dword ptr [bp].parmnm4        ;get recipient for handle ...
        mov     ds:[si],cx                       ;...and put it in
        mov     si,cx                            ;get vio handle...
        add     si,si                            ;...adjust to make index...
        push    si                               ;...and save it
                                                 ; 
                                                 ;allocate PS seg
                                                 ; 
        mov     cx,size wdhenvironment                                  ;@T83
        push    cx                               ;length of PS + Shield/Gre Data
        mov     ds,di                            ;reset BVSNSEG
        push    ds                               ;recipient seg
        lea     ax,ds:[bx].ppbvs_pssel           ;recipient offset      ;@T52
        push    ax                                                      ;@T52
        push    2
        call    DosAllocSeg
        .if     <nonzero ax>                                            ;@T52
            mov    ds:[bx].ppbvs_pssel,0         ;alloc failed
        .else  near
            mov     ax,ds:[bx].ppbvs_pssel       ;alloc ok
            mov     ds:[bx].addr_list[si],ax     ; 
            mov     es,ax                        ;PS alloc ok , now init PS
            mov     al,0                         ; 
            sub     di,di
            rep     stosb
            mov     ax,[bp].parmnm3
            mov     es:[viops_BufferRowCount],ax                        ;@T52
            mov     ax,[bp].parmnm2
            mov     es:[viops_BufferColumnCount],ax                     ;@T52
            mov     ax,[bp].parmnm1              ;                       @P4A
            mov     es:[viops_FormatID],ax       ;                  @P4A;@T52
            mov     ax,[bp].viohandle            ;                       @P4A
            mov     es:[viops_Reserved],ax       ;                  @P4A;@T52
            mov     ax,[bp].parmn
            inc     ax
            mov     es:[viops_CellByteSize],ax                          ;@T52
            push    2
            push    es
            push    viops_CodepageID                                    ;@T52
            push    ds
            lea     ax,ds:[bx].Scratch_Area1                            ;@T52
            push    ax                                                  ;@T52
            call    DosGetCP
            .if     <es:[viops_CodepageID] eq 0>                        ;@T52

                mov     ds:[bx].wdhi_start_row,0                        ;@T52
                mov     word ptr ds:[bx].wdhi_start_row+2,0             ;@T52
                push    4                                               ;@T52
                push    ds                                              ;@T52
                lea     ax,ds:[bx].wdhi_start_row                       ;@T52
                push    ax                                              ;@T52
                push    ds                                              ;@T52
                lea     ax,ds:[bx].wdhi_start_col                       ;@T52
                push    ax                                              ;@T52
                push    ds                                              ;@T52
                lea     ax,ds:[bx].wdhi_length_width                    ;@T52
                push    ax                                              ;@T52
                call    DosGetCtryInfo
                mov     ax,ds:[bx].wdhi_start_col+2                     ;@T52
                .if     <zero ax>                                       ;@T52
                    mov     ax,850
                .endif
                mov     es:[viops_CodepageID],ax                        ;@T52
            .endif
                                                 ; 
                                                 ;Allocate LVB seg
                                                 ; 
            mov     ax,[bp].parmnm2              ;width
            mul     [bp].parmnm3                 ;depth
            mov     cx,[bp].parmn                ;num attr
            inc     cx
            mul     cx
            mov     ds:[bx].Scratch_Area2,ax
            push    ax                           ;length of LVB
            mov     si,ax                        ;save length for later
            push    es                           ;selector for LVB seg recipient
            push    viops_Sel_LogicalVideoBuffer ;offset to receive LVB seg
            push    2
            call    DosAllocSeg
            .if     <nonzero ax>                                        ;@T52
                mov    es:[viops_Sel_LogicalVideoBuffer],0 ;alloc failed;@T52
            .else  near
                sub     di,di                    ;LVB alloc ok , now init LVB
                mov     cx,si                    ; 
                mov     es,es:[viops_Sel_LogicalVideoBuffer]            ;@T52
                shr     cx,1
                .if     <[bp].parmn eq 1>        ;1 attr byte
                    mov     ax,0720h
                    rep     stosw
                .else                            ;3 attr bytes
                    shr     cx,1
                    .repeat
                        mov     ax,0720h
                        stosw
                        sub     ax,ax                                   ;@T52
                        stosw
                    .loop
                .endif
                mov     es,ds:[bx].ppbvs_pssel   ;                      ;@T52
                                                 ;Alloc BVSCB seg
                                                 ; 
                mov     cx,ds:[bx].cmn_bvscbsize ; computed length
                push    cx                       ; of BVSCB
                push    es
                push    viops_Sel_BVSControlBlock ;recipient address
                push    2
                call    DosAllocSeg
                .if     <nonzero ax>                                    ;@T52
                    mov    es:[viops_Sel_BVSControlBlock],0 ;alloc failed;@T52
                .else  near
                    sub     di,di                ; 
                    mov     cx,ds:[bx].cmn_bvscbsize ; BVSCB alloc ok,  ;@T52
                    mov     dx,cx                ; save bvscb size       @P2A
                    shr     cx,1                 ; now init it
                    mov     es,es:[viops_Sel_BVSControlBlock]           ;@T52
                                                 ;ds=PSCD,es=BVSCB       @P2A
                    sub     ax,ax
                    rep     stosw
                    mov     es:[bvs_bvssize],dx  ; size of bvscb    @P2A;@T52
                                                                        ;6@P2D
                    mov     es,ds:[bx].ppbvs_pssel                      ;@T52
                    mov     es:[viops_TextCursorVisible],1              ;@T52
                                                                        ;5@P2D
                    mov     es:[viops_rgfShieldStates],fHasTheFocus+fCursorIsOn ;@T52
                                                                        ;3@P2D
                    mov     ax,es:[viops_Sel_BVSControlBlock]      ;@P2M;@T52
                    mov     ds:[bx].ppbvs_bvssel,ax                ;@P2C;@T52
                    mov     ax,es:[viops_CellByteSize]        ;@P2M @P2C;@T52
                    mov     ds:[bx].cell_size,ax                        ;@P2C

;/*
;** go get an IC for the new PS
;*/

                    push    bx                                          ;@T52
                    push    es               ;PresSpace Sel
                    push    0                ;Pres Space offset
                    les     di,dword ptr [bp].parmnm4
                    push    es:[di]          ;AVio handle
                    call    AVIOCREATEPS
                    pop     bx                                          ;@T52
                    .if     <zero ax>                                   ;@T52
                        call    _NULLCHARRECT                           ;@T52
                        push    ds                                      ;@T52
                        mov     ds,[bx].ppbvs_pssel ;ds=PSCB
                        mov     ax,ds:[viops_CellImageHeight]           ;@T52
                        dec     ax
                        mov     ds:[viops_TextCursorStartLine],ax       ;@T52
                        mov     ds:[viops_TextCursorEndLine],ax         ;@T52
                        mov     ax,ds:[viops_CellImageWidth]            ;@T52
                        mov     ds:[viops_TextCursorWidth],ax           ;@T52
                        mov     ax,ds:[viops_BufferRowCount]            ;@T52
                        dec     ax
                        mov     ds:[viops_TextCursorRow],ax             ;@T52
                        sub     ax,ax
                        pop     ds                                      ;@T52
                    .endif
                .endif
            .endif
        .endif
        pop     si
        .if     <nonzero ax>                                            ;@T52
            .if     <ds:[bx].ppbvs_pssel ne 0>
                    mov     es,ds:[bx].ppbvs_pssel                      ;@T52
                    .if     <es:[viops_Sel_LogicalVideoBuffer] ne 0>    ;@T52
                            push    es:[viops_Sel_LogicalVideoBuffer]   ;@T52
                            call    DosFreeSeg          ;release LVB
                            .if     <es:[viops_Sel_BVSControlBlock] ne 0> ;@T52
                                    push    es:[viops_Sel_BVSControlBlock] ;@T52
                                    call    DosFreeSeg  ;release BVSCB
                            .endif
                    .endif
                    push    ds:[bx].ppbvs_pssel                         ;@T52
                    call    DosFreeSeg                  ;release PS
            .endif
            mov     ds:[bx].addr_list[si],0
        .endif
        ret
CreateAvio endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioDestroyPS
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioDestroyPS Proc NEAR
        mov     es,ds:[bx].ppbvs_pssel                                  ;@T52
        push    bx                                                      ;@T52
        push    es               ;PresSpace Sel                         ;@T52
        push    0                ;Pres Space offset
        call    AVIODESTROYPS
        pop     bx                                                      ;@T52
        .if     <zero ax>                                               ;@T52
            mov     es,ds:[bx].ppbvs_pssel                              ;@T52
            push    es:[viops_Sel_LogicalVideoBuffer] ;release          ;@T52
            call    DosFreeSeg                   ;...LVB...
            .if     <zero ax>                    ;...and...             ;@T52
                mov     ax,es:[viops_Sel_BVSControlBlock] ;...          ;@T52
                push    ax                       ;...
                call    DosFreeSeg               ;...BVSCB...
                .if     <zero ax>                ;...and...             ;@T52
                    push    es                   ;...                   ;@T52
                    call    DosFreeSeg           ;...PS
                    .if     <zero ax>            ; if ok then copy
                        mov     si,[bp].viohandle;get VIO handle
                        add     si,si            ;make into index
                        mov     ds:[bx].addr_list[si],0;clear slot in BVSNSEG
                    .endif
                .endif
            .endif
        .endif
        ret
VioDestroyPS endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioGetDeviceCellSize
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioGetDeviceCellSize Proc NEAR
        mov     ds,ds:[bx].ppbvs_pssel                                  ;@T52
        les     di,dword ptr [bp].parmn
        mov     ax,ds:[viops_CellImageWidth]                            ;@T52
        stosw
        les     di,dword ptr [bp].parmnm2
        mov     ax,ds:[viops_CellImageHeight]                           ;@T52
        stosw
        sub     ax,ax
        ret
VioGetDeviceCellSize endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioGetOrg
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioGetOrg Proc  Near
        mov     ds,ds:[bx].ppbvs_pssel                                  ;@T52
        les     di,dword ptr [bp].parmn          ;col
        mov     ax,ds:[viops_WindowOriginColumn]                        ;@T52
        stosw
        les     di,dword ptr [bp].parmnm2        ;row
        .if     <ds:[viops_WindowHeight] eq 0> and ;never associated    ;@T52
        .if     <ds:[viops_WindowOriginRow] eq 0>  ;.. or had a SetOrg. ;@T52
            sub     ax,ax
        .else
            mov     ax,ds:[viops_BufferRowCount]  ;adjust bottom left.. ;@T52
            sub     ax,ds:[viops_WindowHeight]    ;...relationship to.. ;@T52
            sub     ax,ds:[viops_WindowOriginRow] ;...be top left of LVB;@T52
        .endif
        stosw
        sub     ax,ax
        ret
VioGetOrg endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioQuerySetIds
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioQuerySetIds Proc NEAR
        push    ds:[bx].ppbvs_pssel ;PresSpace Sel
        push    0                ;Pres Space offset
        push    [bp].parmnm1                 ;number pt 1
        push    [bp].parmn                   ;number pt 2
        push    [bp].parmnm3                 ;types pt 1
        push    [bp].parmnm2                 ;types pt 2
        push    [bp].parmnm5                 ;names pt 1
        push    [bp].parmnm4                 ;names pt 2
        push    [bp].parmnm7                 ;LCIDS pt 1 (recipient addr)
        push    [bp].parmnm6                 ;LCIDS pt 2 (recipient addr)
        call    AVIOQUERYSETIDS
        ret
VioQuerySetIds endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioSetDeviceCellSize
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioSetDeviceCellSize Proc NEAR
        push    ds:[bx].ppbvs_pssel                                     ;@T52
        push    0                ;Pres Space offset
        push    [bp].parmn       ;requested cell image width
        push    [bp].parmnm1     ;requested cell image height
        call    AVIOSETDEVICECELLSIZE
        ret
VioSetDeviceCellSize endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioSetOrg
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioSetOrg Proc  NEAR
        mov     ds,ds:[bx].ppbvs_pssel                                  ;@T52
        mov     cx,[bp].parmn                    ;col
        sub     ax,ax
        .if     <cx b 0> or
        .if     <cx ae ds:[viops_BufferColumnCount]>                    ;@T52
            mov     ax,error_vio_col
        .endif
        .if     <zero ax>                                               ;@T52
            mov     dx,[bp].parmnm1              ;row
            .if     <dx ae 0> and
            .if     <dx b ds:[viops_BufferRowCount]>                    ;@T52
                push    ds               ;PresSpace Sel
                push    0                ;Pres Space offset
                push    dx               ;new org row
                push    cx               ;new org col
                call    AVIOSETORG
            .else
                mov     ax,error_vio_row
            .endif
        .endif
        ret
VioSetOrg endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioShowPS
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioShowPS Proc  NEAR
        call    ClearGreDat
        mov     es,ds:[bx].ppbvs_pssel                                  ;@T52
        mov     ax,[bp].parmn                     ;offset in LVB
        .if     <ax l 0>
            mov     ax,error_vio_invalid_parms
        .else   near
            cwd
            div     es:[viops_BufferColumnCount] ;ax=start row, dx=start col ;@T52
            mov     cx,ax
            .if     <ax a es:[viops_BufferRowCount]>                    ;@T52
                mov     ax,error_vio_invalid_parms
            .else   near
                mov     ax,es:[viops_BufferRowCount] ;adjust for bottom..;@T52
                sub     ax,cx                     ;...left LVB origin
                mov     ds:[bx].wdhi_start_row,ax ;start row            ;@T52
                mov     ds:[bx].wdhi_start_col,dx ;start col            ;@T52
                mov     ax,[bp].parmnm1           ;width
                .if     <ax a es:[viops_BufferColumnCount]> or          ;@T52
                .if     <ax b 0>
                    mov     ax,error_vio_invalid_parms
                .else   near
                    mov     ds:[bx].wdhi_length_width,ax                ;@T52
                    mov     ax,[bp].parmnm2       ;depth
                    .if     <ax a ds:[bx].wdhi_start_row> or            ;@T52
                    .if     <ax b 0>
                        mov     ax,error_vio_invalid_parms
                    .else
                        sub     ds:[bx].wdhi_start_row,ax;normalise     ;@T52
                        mov     ds:[bx].wdhi_rect_height,ax             ;@T52

IFDEF D1348 ;BufferUpdate with dbcs bits handling
                        .if     <<byte ptr es:[viops_FormatID]> eq WorldFormat>
                            push    ax
                            push    bx
                            push    cx
                            push    dx
                            push    es
                            push    di
                            push    si
                            push    es
                            pop     ds
                            mov     cx,es:[viops_Sel_LogicalVideoBuffer]
                            mov     es,cx
                                                        ;(Depth-1)*ColCount+Width
                                                        ;= whole length
                            dec     ax                  ;dec Depth
                            mul     ds:[viops_BufferColumnCount]
                            add     ax,[bp].parmnm1     ;width
                            mov     cx,ax               ;set liner length

                            mov     ax,[bp].parmn       ;cell-offset in LVB
                            mul     ds:[viops_CellByteSize]
                            mov     di,ax               ;di=offset in byte

                            xor     ax,ax
                            push    cx
                            mov     cx,[bp].parmn       ;cell-offset in LVB
                            mov     bx,ds:[viops_CellByteSize]
                            .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
                            pop     cx
                            add     cx,ax

                            mov     ax,di               ;di=offset in byte
                            mov     si,ax

                            call    setNLSbits
                            pop     si
                            pop     di
                            pop     es
                            pop     dx
                            pop     cx
                            pop     bx
                            pop     ax
                        .endif
ENDIF ;D1348

                        call    EngineCharRect
                    .endif
                .endif
            .endif
        .endif
        ret
VioShowPS endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioGetPSAddress
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioGetPSAddress Proc NEAR
        mov     si,[bp].viohandle               ;get handle for PS
        add     si,si                           ;make it an index
        sub     ax,ax                           ;ps addr offset
        mov     dx,ds:[bx].addr_list[si]        ;get the PS seg for handle
        les     di, dword ptr [bp].parmn        ;get recipient address
        stosw                                   ;return offset to recipient
        mov     ax,dx
        stosw                                   ;return sel to recipient
        sub     ax,ax                           ;set good return code
        ret
VioGetPSAddress endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioCreateLogFont
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioCreateLogFont Proc NEAR
        mov     ds,ds:[bx].ppbvs_pssel                                  ;@T52
        mov     ax,[bp].parmnm2                  ;LCID value
        .if     <[bp].parmnm3 e 0> and
        .if     <ax ae 1> and
        .if     <ax be 3>
            push    word ptr ds:[viops_hConsoleDisplayContext+2] ;DCh pt 1 ;@T52
            push    word ptr ds:[viops_hConsoleDisplayContext] ;DCh pt 2   ;@T52
            inc     ax
            neg     ax                           ;put LCID 1..3 in range -2..-4
            push    -1                           ;hi part of LCID word
            push    ax                           ;lo part of LCID word
            push    [bp].parmnm1                 ;NAME selector
            push    [bp].parmn                   ;NAME offset
            push    [bp].parmnm5                 ;FONTMETRICS selector
            push    [bp].parmnm4                 ;FONTMETRICS offset
            push    0                            ;"cookie" parm pt 1
            push    0                            ;              pt 2
            push    seg_CreateLogicalFont        ;Engine function pt. 1
            push    off_CreateLogicalFont        ;Engine function pt. 2
            call    GREENTRY6
            .if     <zero ax>                                           ;@T52
                mov     ax,error_vio_see_error_log
            .else
                sub     ax,ax
            .endif
        .else
            mov     ax,error_vio_invalid_parms
        .endif
        ret
VioCreateLogFont endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioDeleteSetId
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioDeleteSetId Proc NEAR
        push    ds:[bx].ppbvs_pssel ;PresSpace Sel                      ;@T52
        push    0                ;Pres Space offset
        push    [bp].parmnm1     ;LCID value pt 1
        push    [bp].parmn       ;LCID value pt 2
        call    AVIODELETESETID
        ret
VioDeleteSetId endp

;/***************************************************************************
;*
;* FUNCTION NAME = VioQueryFonts
;*
;* DESCRIPTION   =
;*
;* INPUT         = DS:BX -> BVHINSTANCE data
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

VioQueryFonts Proc NEAR
        push    ds:[bx].ppbvs_pssel ;PresSpace Sel                      ;@T52
        push    0                   ;Pres Space offset
        push    [bp].parmnm1                 ;options pt 1
        push    [bp].parmn                   ;options pt 2
        push    [bp].parmnm3                 ;facename segment
        push    [bp].parmnm2                 ;facename offset
        push    [bp].parmnm5                 ;fonts pt 1
        push    [bp].parmnm4                 ;fonts pt 2
        push    [bp].parmnm7                 ;count pt 1
        push    [bp].parmnm6                 ;count pt 2
        push    [bp].parmnm9                 ;metrics pt 1
        push    [bp].parmnm8                 ;metrics pt 2
        push    [bp].(parmnm9 + 4)           ;remfonts pt 1
        push    [bp].(parmnm9 + 2)           ;remfonts pt 2
        call    AVIOQUERYFONTS
        ret
VioQueryFonts endp

;/*
;**                 Utility Subroutines
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = _NULLCHARRECT
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

_NULLCHARRECT Proc NEAR                                                 ;@T52

        Call    ClearGreDat                     ;advise...
        Call    EngineCharRect                  ;...to...
        ret                                     ;...PS
_NULLCHARRECT endp                                                      ;@T52

IFDEF D1348 ;BufferUpdate with dbcs bits handling

;/***************************************************************************
;*
;* FUNCTION NAME = SetNLSbits
;*
;* DESCRIPTION   =
;*
;*        +...LVB .....................................+
;*        .                                            .
;*        .       +-Showed PS -+-----------------------+
;*        . ??????|            |///////////////////////.
;*        +-------+            |///////////////////////.
;*        .///////|            |///////////////////////.
;*        .///////|            +-----------------------+
;*        .///////|            |                       .
;*        +-------+------------+                       .
;*        +............................................+
;*
;*      /// : DBCS bits in here should be handled to keep a
;*            valid dbcs attribute at the leftmost column in
;*            the next row.
;*
;*      ??? : Find the beginning of valid dbcs string.
;*            This process has been done prior to this routine
;*
;* INPUT         = DS = viops_*
;*                 ES = LVB
;*                 DI = offset in byte
;*                 CX = character count
;*                 AX = don't care
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Public  SetNLSbits
SetNLSbits  Proc NEAR

        Local_Bytes equ     2
        wLVBLimit   equ     ss:[bp][-2]

        enter   Local_Bytes,0           ;get storage for local variables

        mov     ax,ds:[viops_BufferColumnCount] ;set wLVBLimit
        mul     ds:[viops_BufferRowCount]
        mul     ds:[viops_CellByteSize]
        mov     word ptr wLVBLimit,ax

;/*
;**  Update LVB
;*/

        Call    HeadBounds
        xor     dx,dx                   ;clear the char counter
        .while  ncxz
            mov     al,es:[si]          ;get a code point in the cell
            add     si,4                ;skip attr#0,1,2
            mov     ah,es:[si-2]        ;get character set bits (attr#2)
            dec     cx                  ;adjust the loop counter (CX)
            inc     dx                  ;increment the char counter (DX)

            call    CheckDBCS
            .if     c                   ;if char have DBCS leading byte
                .if     < dx gt 1 >     ;SBCS Char Counter must be GT 1.
                    dec     dx          ;Adjust
                    call    Writes      ;Write the leading Hankaku String.
                .endif

                xor     dx,dx           ;clear the char counter (DX)
                .if     ncxz            ;& cx > 0
                    add     si,4
                    dec     cx          ;adjust the loop counter (CX)
                    call    PutDBCSs    ;write dbcs into LVB
                .else                                                   ;@A21
                    call    PutDBCSinEnds                               ;@A21
                .endif
            .endif                      ;End of DBCS Case
        .endwhile

        .if     < dx ne 0 >
            push    di
            call    Writes              ;Write SBCS char to LVB
            pop     di
        .endif

        leave
        ret
SetNLSbits  endp

;/*
;** OverWriting Handling
;** ES:DI - LVB
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = HeadBounds
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public  HeadBounds
HeadBounds Proc NEAR                        ;OverWriting of DBCS bisected
                                            ;leading in the biginning.
        cmp     di,4                        ;check start of screen or not ?
        .if     ae
            test    byte ptr es:[di+3],TrailByteFlag ;DBCS 2nd(trailing) ?
            .if     nz
                mov     byte ptr es:[di-4],20h  ;place a space
                and     byte ptr es:[di-1], Not (DBCSFlag+TrailByteFlag) ;off DBCS bits
            .endif
        .endif
        ret
HeadBounds endp

;/***************************************************************************
;*
;* FUNCTION NAME = HeadBounds
;*
;* DESCRIPTION   = Set DBCS bits(DBCS bit and DBCS trailing
;*                 bit)
;*
;* INPUT         = ES:DI = LVB
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public  PutDBCSs
PutDBCSs Proc

;/*
;** Set dbcs bit(s).
;** Copy the attr of leading byte to that of trailing.
;*/

                                                      ;/set dbcs leading byte bit
        and     byte ptr es:[di+3], not TrailByteFlag ;set dbcs trailing off
        or      byte ptr es:[di+3], DBCSFlag          ;set dbcs leading bit on

                                                      ;/set dbcs traling byte bit
        or      byte ptr es:[di+7], DBCSFlag+TrailByteFlag ;set dbcs bit and
                                                      ;dbcs trailing bit on
        add     di,8

        ret
PutDBCSs endp

;/***************************************************************************
;*
;* FUNCTION NAME = TailBounds
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public  TailBounds
TailBounds PROC NEAR                    ;Overwriting of Tail DBCS Widow
        cmp     di, word ptr wLVBLimit  ;check end of lvb or not ?
        .if     b
            test    byte ptr es:[di+3],TrailByteFlag ; Target Tail+1 is dbcs 2nd ?
            .if     nz
                mov     byte ptr es:[di],20h    ;place space to avoid a wrong
                                                ;display output of dbcs after
                                                ;the specified rectangle.
                and     byte ptr es:[di+3], Not (DBCSFlag+TrailByteFlag) ;off DBCS
                add     di,4
            .endif
        .endif
        ret
TailBounds ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = PutDBCSinEnds
;*
;* DESCRIPTION   = Set dbcs bit(s).
;*                 Copy the attr of leading byte to that of trailing.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public  PutDBCSinEnds
PutDBCSinEnds   Proc

        add     di,4

        cmp     di, word ptr wLVBLimit                ;check end of lvb or not ?
        .if     b
                                                      ;/set dbcs leading byte bit
            and     byte ptr es:[di-1], not TrailByteFlag  ;set dbcs trailing off
            or      byte ptr es:[di-1], DBCSFlag      ;set dbcs leading bit on
                                                      ;/set dbcs traling byte bit
            or      byte ptr es:[di+3], DBCSFlag+TrailByteFlag ;set dbcs bit and
                                                      ;dbcs trailing bit on
        .endif

        ret
PutDBCSinEnds   endp

;/***************************************************************************
;*
;* FUNCTION NAME = Writes
;*
;* DESCRIPTION   = Set SBCS bit
;*
;* INPUT         = ES:DI = LVB
;*                 DX = the count for SBCS characters
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Public  Writes
Writes  PROC                                ;SBCS write routine
        push    cx
        mov     cx,dx                       ;the number of SBCS characters
        .while  ncxz

            and     byte ptr es:[di+3], not (DBCSFlag+TrailByteFlag) ;off dbcs bits
            add     di,ds:[viops_CellByteSize]
            dec     cx
        .endwhile
        pop     cx
        ret
Writes  ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = CheckDBCS
;*
;* DESCRIPTION   = Check if input code point is DBCS leading
;*                 byte or not
;*
;* INPUT         = AL = Checked character        CF = 0 if SBCS
;*                      code point                  = 1 if DBCS leading
;*                 AH = attr #2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Public  CheckDBCS
CheckDBCS PROC  NEAR
        push    ds
        push    si
        push    cx
        push    dx
        push    bx
        xor     bh,bh
        mov     bl,ah
        and     bl,lcid_mask
        xchg    bx,ax
        mov     dx,size DBCSENVINFO
        mul     dx
        xchg    bx,ax

        clc
        mov     cx,DBCSEvBufSiz/2       ; set loop count

        lds     si,ds:[viops_lpNLSExt]  ; ds:si -> dbcs env. buffer

        mov     dx,ds:[bx+si]
DBCS_LOOP:
        cmp     dx,0
        jz      DBCS_END
        cmp     dl,al                   ; comp start value
        ja      DBCS_END                ; smaller than lower limit
        cmp     al,dh                   ; comp stop value
        jbe     DBCS_OK                 ; in range
DBCS_NO:
        inc     si                      ; see next vecter
        inc     si
        mov     dx,ds:[si]
        loop    DBCS_LOOP
DBCS_OK:
        stc
DBCS_END:
        pop     bx
        pop     dx
        pop     cx
        pop     si
        pop     ds
        ret
CheckDBCS endp

ENDIF ;D1348

avio3seg ends
        end

