;*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.;
;*****************************************************************************/
        page    ,132

;/*****************************************************************************
;*
;* SOURCE FILE NAME = SMARTPRO.ASM
;*
;* DESCRIPTIVE NAME = Outputting proportional and fixed pitch characters.
;*                                                       
;*
;* VERSION      V2.0
;*
;* DATE         07/24/87
;*
;* DESCRIPTION  This module contains the routines for outputting proportion 
;*              and fixed pitch characters.                                 
;*                                                                          
;*              
;*              
;* FUNCTIONS    SmartPro
;*              
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   07/24/87                     Written by Walt Moore [waltm]
;*
;*****************************************************************************/
        
        .386

        .xlist

        OPTION  OLDMACROS

INCL_GRE_CLIP           equ     1
INCL_FONTFILEFORMAT     equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1

        include pmgre.inc
        include driver.inc
        include egafam.inc
        include strblt.inc
        include extern.inc
        include protos.inc

        .list

        .MODEL FLAT
    
        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA

        .CODE

        EXTERN  set_ega_opaque_mode:NEAR

;/*
;**       Special cases
;*/

SPECIAL_CASE_BM_OBBNC = 0                        ;Bitmap, opaque, black on black, non-clipped
SPECIAL_CASE_BM_OBWNC = 1                        ;Bitmap, opaque, black on white, non-clipped
SPECIAL_CASE_BM_OWBNC = 0                        ;Bitmap, opaque, white on black, non_clipped
SPECIAL_CASE_BM_OWWNC = 0                        ;Bitmap, opaque, white on white, non-clipped
SPECIAL_CASE_BM_TBNC  = 0                        ;Bitmap, transparent black, non-clipped
SPECIAL_CASE_BM_TWNC  = 0                        ;Bitmap, transparent white, non-clipped

SPECIAL_CASE_DEV_ONC  = 1                        ;Device, opaque, non-clipped
SPECIAL_CASE_DEV_TNC  = 1                        ;Device, transparent, non-clipped
;SPECIAL_CASE_DEV_OC  = 0                        ;Device, opaque, clipped (see notes below)
SPECIAL_CASE_DEV_TC   = 0                        ;Device, transparent, clipped

addsubedi macro addval,subval
        add     edi,addval
if subval
        sub     edi,subval
endif
endm        

;/*
;**       The following equates are used to index into the buffer
;**       of character widths, phases (x location), and offsets
;**       of the bits within the font.
;*/

base    equ     0

wwidth  equ     BYTE PTR 0
pphase  equ     BYTE PTR 1
cchar   equ     DWORD PTR -4

wwidth1 equ     BYTE PTR base - 0
pphase1 equ     BYTE PTR wwidth1 + 1
cchar1  equ     DWORD PTR wwidth1 - 4
                         
wwidth2 equ     BYTE PTR base - 8
pphase2 equ     BYTE PTR wwidth2 + 1
cchar2  equ     DWORD PTR wwidth2 - 4

wwidth3 equ     BYTE PTR base - 16
pphase3 equ     BYTE PTR wwidth3 + 1
cchar3  equ     DWORD PTR wwidth3 - 4

wwidth4 equ     BYTE PTR base - 24
pphase4 equ     BYTE PTR wwidth4 + 1
cchar4  equ     DWORD PTR wwidth4 - 4
page

;/*
;**--------------------------------Macro----------------------------------
;** upd_bm
;**
;**       upd_bm is the macro used for generating the destination update
;**       code for a bitmap.
;**
;**       Usage:
;**               upd_bm  ll
;**       Where
;**               ll      is the macro to invoke for the looping logic
;**-----------------------------------------------------------------------
;*/

upd_bm  macro   ll
if DRAW_ADJUST                                    ;;If last logic operation defined
        dec     edi                               ;;  did a stosb, adjust for it
endif
        add     edi,ss_next_scan
        ll
        endm

;/*
;**--------------------------------Macro----------------------------------
;** upd_dev
;**
;**       upd_dev is the macro used for generating the destination update
;**       code for the physical device
;**
;**       Usage:
;**               upd_dev ll
;**       Where
;**               ll      is the macro to invoke for the looping logic
;**-----------------------------------------------------------------------
;*/

upd_dev macro   ll
        addsubedi SCREEN_CBSCAN,DRAW_ADJUST
        ll
        endm
page

;/*
;**--------------------------------Macro----------------------------------;
;** n_char
;**
;**       n_char is a macro for generating the code required to process
;**       a destination character consisting of 5,6,7 or 8 source bytes
;**
;**       Usage:
;**               n_char  name,output,update,setup
;**       Where
;**
;**               name    the name of the procedure
;**               output  the macro which will generate the required
;**                       output logic
;**               update  the macro which will generate the required
;**                       destination update logic
;**               setup   if this parameter is given as "inline", then
;**                       setup code will be generated inline, else a
;**                       subroutine will be called to perform the
;**                       initialization.  This subroutine will be
;**                       created if not defined.
;**
;**       The macro will generate the loop_logic macro which is the
;**       macro used by all update macros for generating looping logic.
;**       It is defined as a macro so that devices which are interleaved
;**       can make multiple copies of it, possibly removing a jump.
;**-----------------------------------------------------------------------;
;*/

n_char  macro   name,output,update,setup
        local   genflag

;/*
;** n character looping logic macro
;*/

loop_logic      &macro
        inc     edx                               ;;Next scan of font
        dec     ss_height                         ;;Loop until all chars output
        jnz     name&_n_char_outer_loop
        pop     ebp                               ;;BP = frame pointer
        sub     edi,cell_adjust
        ret
        &endm

;/*
;** n character long looping logic macro
;*/

long_loop_logic &macro
        inc     edx                               ;;Next scan of font
        dec     ss_height                         ;;Loop until all chars output
        jz      name&_n_char_exit
        jmp     name&_n_char_outer_loop

        ALIGN   4

name&_n_char_exit:
        pop     ebp                               ;;BP = frame pointer
        sub     edi,cell_adjust
        ret
        &endm

;/*
;** n character setup logic
;*/

public  name&_n_char                              ;;make public
genflag=0                                         ;;assume out_of_line, already generated
ifidn <setup>,<inline>                            ;;if in_line
name&_n_char::                                    ;;  define procedure
  genflag = 01b                                   ;;  show code must be generated
else                                              ;;else
  ifndef n_char_setup                             ;;  if procedure not defined
    genflag = 11b                                 ;;    show proc must also be generated
  else                                            ;;  else
    ife $-n_char_setup                            ;;    it is defined on
      genflag = 11b                               ;;    pass 2 regardless of if we have
    endif                                         ;;    generated it
  endif                                           ;;
endif                                             ;;
if genflag                                        ;;if to generate setup
  if genflag and 10b                              ;;  if generating procedural version
public  n_char_setup                              ;;    make public for debugging
n_char_setup::                                    ;;    define start of setup proc
  endif                                           ;;  endif

        DebugMsg <n_char_setup SMARTPRO CLIFFL>

        mov     ss_height,eax                     ;;  save # scans in character
  if genflag and 10b                              ;;  if generating setup procedure
        pop     eax                               ;;    get return address
  endif                                           ;;  endif
        mov     ss_num_chars,cl                   ;;  save # of characters - 1
        push    ebp                               ;;  save frame pointer
        mov     ebp,pFont
        xchg    ebp,edx                           ;;  set buffer pointer
  if genflag and 10b                              ;;  if generating setup procedure
        jmp     eax                               ;;    dispatch to caller

        ALIGN   4

name&_n_char::                                    ;;    define actual procedure
        call    n_char_setup                      ;;    call setup code
  endif                                           ;;  endif
else                                              ;;else
name&_n_char::                                    ;;    define actual procedure

        call    n_char_setup                      ;;    call setup code
endif                                             ;;endif ;setup code


;/*
;** n character compilation logic
;*/

name&_n_char_outer_loop:
        xor     esi,esi                           ;;SI = char index
        mov     ch,ss_num_chars                  ;;Get # of characters - 1
        xchg    edx,edi                           ;;Index to next font scan in DI

name&_n_char_inner_loop:
        mov     ebx,[ebp][esi]+cchar             ;;BX = offset of bits
        mov     al,BYTE PTR [ebx][edi]
        mov     cl,BYTE PTR [ebp][esi]+wwidth    ;;CL = width
        shl     eax,cl
        sub     esi,8                             ;;--> next char
        dec     ch
        jnz     name&_n_char_inner_loop
        mov     ebx,[ebp][esi]+cchar             ;;BX = offset of bits
        mov     al,BYTE PTR [ebx][edi]
        mov     cl,BYTE PTR [ebp][esi]+pphase    ;;CL = phase
        shr     eax,cl
        xchg    edx,edi                           ;;DI = dest ptr
        output  <update>                          ;;Macro to do whatever for outputting
        endm
page

;/*
;**--------------------------------Macro----------------------------------;
;** four_char
;**
;**       four_char is a macro for generating the code required to
;**       process a destination character consisting of 4 source bytes
;**
;**       Usage:
;**               four_char  name,output,update,setup
;**       Where
;**
;**               name    the name of the procedure
;**               output  the macro which will generate the required
;**                       output logic
;**               update  the macro which will generate the required
;**                       destination update logic
;**               setup   if this parameter is given as "inline", then
;**                       setup code will be generated inline, else a
;**                       subroutine will be called to perform the
;**                       initialization.  This subroutine will be
;**                       created if not defined.
;**
;**       The macro will generate the loop_logic macro which is the
;**       macro used by all update macros for generating looping logic.
;**       It is defined as a macro so that devices which are interleaved
;**       can make multiple copies of it, possibly removing a jump.
;**-----------------------------------------------------------------------;
;*/

four_char macro name,output,update,setup
        local   genflag


;/*
;** four character looping logic macro
;*/

loop_logic      &Macro
        dec     ss_height
        jnz     name&_four_char_loop
        pop     ebp                               ;;BP = frame pointer
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** four character long looping logic macro
;*/

long_loop_logic &Macro
        dec     ss_height
        jz      name&_four_char_exit
        jmp     name&_four_char_loop

        ALIGN   4

name&_four_char_exit:
        pop     ebp                               ;;BP = frame pointer
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** four character setup logic
;*/

public  name&_four_char                           ;;make public
genflag=0                                         ;;assume out_of_line, already generated
ifidn <setup>,<inline>                            ;;if in_line
name&_four_char::                                 ;;  define procedure
  genflag = 01b                                   ;;  show code must be generated
else                                              ;;else
  ifndef four_char_setup                          ;;  if procedure not defined
    genflag = 11b                                 ;;    show proc must also be generated
  else                                            ;;  else
    ife $-four_char_setup                         ;;    it is defined on
      genflag = 11b                               ;;    pass 2 regardless of if we have
    endif                                         ;;    generated it
  endif
endif
if genflag                                        ;;if to generate setup
  if genflag and 10b                              ;;  if generating procedural version
public  four_char_setup                           ;;    make public for debugging
four_char_setup::                                 ;;    define start of setup proc
  endif                                           ;;  endif
        
        DebugMsg <four_char_setup SMARTPRO CLIFFL>

        mov     ss_height,eax                     ;;  save # scans in character
  if genflag and 10b                              ;;  if generating setup procedure
        pop     eax                               ;;    get return address
  endif                                           ;;  endif
        push    ebp                               ;;  save frame pointer
        push    edi
        mov     edi,pFont
        mov     ebp,edx                           ;;  --> buffer
        mov     dl,BYTE PTR [ebp]+wwidth3        ;;
        mov     dh,BYTE PTR [ebp]+pphase4        ;;
        mov     ss_phases,edx                     ;;
        mov     cl,BYTE PTR [ebp]+wwidth1        ;;
        mov     ch,BYTE PTR [ebp]+wwidth2        ;;
        mov     esi,[ebp]+cchar4                  ;;  4th character so we can lodsb
        mov     ebx,[ebp]+cchar1                  ;;
        mov     edx,[ebp]+cchar3                  ;;
        mov     ebp,[ebp]+cchar2                  ;;
        sub     ebx,esi                           ;;  compute deltas
        sub     ebp,esi                           ;;
        sub     edx,esi                           ;;
        add     esi,edi
        pop     edi
  if genflag and 10b                              ;;  if generating setup procedure
        jmp     eax                               ;;    dispatch to caller

        ALIGN   4

name&_four_char::                                 ;;    define actual procedure
        call    four_char_setup                  ;;    call setup code
  endif                                           ;;  endif
else                                              ;;else
name&_four_char::                                 ;;    define actual procedure
        call    four_char_setup                  ;;    call setup code
endif                                             ;;endif ;setup code


;/*
;** four character compilation logic
;*/

name&_four_char_loop:
        mov     al,BYTE PTR [esi][ebx]
        shl     ax,cl
        mov     al,BYTE PTR [ebp][esi]
        xchg    cl,ch
        shl     eax,cl
        xchg    cl,ch
        xchg    ecx,ss_phases
        xchg    ebx,edx
        mov     al,BYTE PTR [esi][ebx]
        xchg    ebx,edx
        shl     eax,cl
        lodsb
        xchg    cl,ch
        shr     eax,cl
        xchg    cl,ch
        xchg    ecx,ss_phases
        output  <update>                          ;;Macro to do whatever for outputting
        endm
page

;/*
;**--------------------------------Macro----------------------------------;
;** three_char
;**
;**       three_char is a macro for generating the code required to
;**       process a destination character consisting of 3 source bytes
;**
;**       Usage:
;**               three_char  name,output,update,setup
;**       Where
;**
;**               name    the name of the procedure
;**               output  the macro which will generate the required
;**                       output logic
;**               update  the macro which will generate the required
;**                       destination update logic
;**               setup   if this parameter is given as "inline", then
;**                       setup code will be generated inline, else a
;**                       subroutine will be called to perform the
;**                       initialization.  This subroutine will be
;**                       created if not defined.
;**
;**       The macro will generate the loop_logic macro which is the
;**       macro used by all update macros for generating looping logic.
;**       It is defined as a macro so that devices which are interleaved
;**       can make multiple copies of it, possibly removing a jump.
;**-----------------------------------------------------------------------;
;*/

three_char macro name,output,update,setup
        local   genflag


;/*
;** three character looping logic macro
;*/

loop_logic      &macro
        dec     ss_height
        jnz     name&_three_char_loop
        pop     ebp
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** three character long looping logic macro
;*/

long_loop_logic &macro
        dec     ss_height
        jz      name&_three_char_exit
        jmp     name&_three_char_loop

        ALIGN   4

name&_three_char_exit:
        pop     ebp
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** three character setup logic
;*/

public  name&_three_char                          ;;make public
genflag=0                                         ;;assume out_of_line, already generated
ifidn <setup>,<inline>                            ;;if in_line
name&_three_char::                                ;;  define procedure
  genflag = 01b                                   ;;  show code must be generated
else                                              ;;else
  ifndef three_char_setup                         ;;  if procedure not defined
    genflag = 11b                                 ;;    show proc must also be generated
  else                                            ;;  else
    ife $-three_char_setup                        ;;    it is defined on
      genflag = 11b                               ;;    pass 2 regardless of if we have
    endif                                         ;;    generated it
  endif
endif
if genflag                                        ;;if to generate setup
  if genflag and 10b                              ;;  if generating procedural version
public  three_char_setup                          ;;    make public for debugging
three_char_setup::                                ;;    define start of setup proc
  endif                                           ;;  endif
        mov     ss_height,eax                     ;;  save # scans in character
  if genflag and 10b                              ;;  if generating setup procedure
        
        DebugMsg <three_char_setup SMARTPRO CLIFFL>

        pop     eax                               ;;    get return address
  endif                                           ;;  endif
        push    ebp
        push    edi
        mov     edi,pFont     
        mov     ebp,edx                           ;;  BP = buffer
        mov     dl,BYTE PTR [ebp]+wwidth1        ;;
        mov     dh,BYTE PTR [ebp]+wwidth2        ;;
        mov     ch,BYTE PTR [ebp]+pphase3        ;;
        mov     esi,[ebp]+cchar3                  ;;
        mov     ebx,[ebp]+cchar2                  ;;
        mov     ebp,[ebp]+cchar1                  ;;
        sub     ebx,esi                           ;;
        sub     ebp,esi                           ;;
        add     esi,edi
        pop     edi
  if genflag and 10b                              ;;  if generating setup procedure
        jmp     eax                               ;;    dispatch to caller

        ALIGN   4

name&_three_char::                                ;;    define actual procedure
        call    three_char_setup                 ;;    call setup code
  endif                                           ;;  endif
else                                              ;;else
name&_three_char::                                ;;    define actual procedure
        call    three_char_setup                 ;;    call setup code
endif                                             ;;endif ;setup code


;/*
;** three character compilation logic
;*/

name&_three_char_loop:
        mov     al,BYTE PTR [ebp][esi]
        mov     cl,dl
        shl     eax,cl
        mov     al,BYTE PTR [esi][ebx]
        mov     cl,dh
        shl     eax,cl
        lodsb
        mov     cl,ch
        shr     eax,cl
        output  <update>                          ;;Macro to do whatever for outputting
        endm
page

;/*
;**--------------------------------Macro----------------------------------;
;** two_char
;**
;**       two_char is a macro for generating the code required to
;**       process a destination character consisting of 2 source bytes
;**
;**       Usage:
;**               two_char  name,output,update,setup
;**       Where
;**
;**               name    the name of the procedure
;**               output  the macro which will generate the required
;**                       output logic
;**               update  the macro which will generate the required
;**                       destination update logic
;**               setup   if this parameter is given as "inline", then
;**                       setup code will be generated inline, else a
;**                       subroutine will be called to perform the
;**                       initialization.  This subroutine will be
;**                       created if not defined.
;**
;**       The macro will generate the loop_logic macro which is the
;**       macro used by all update macros for generating looping logic.
;**       It is defined as a macro so that devices which are interleaved
;**       can make multiple copies of it, possibly removing a jump.
;**-----------------------------------------------------------------------;
;*/

two_char macro name,output,update,setup
        local   genflag


;/*
;** two character looping logic macro
;*/

loop_logic      &macro
        dec     edx
        jnz     name&_two_char_loop
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** two character long looping logic macro
;*/

long_loop_logic &macro
        dec     edx
        jz      name&_two_char_exit
        jmp     name&_two_char_loop

        ALIGN   4

name&_two_char_exit:
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** two character setup logic
;*/

public  name&_two_char                            ;;make public
genflag=0                                         ;;assume out_of_line, already generated
ifidn <setup>,<inline>                            ;;if in_line
name&_two_char::                                  ;;  define procedure
  genflag = 01b                                   ;;  show code must be generated
else                                              ;;else
  ifndef two_char_setup                           ;;  if procedure not defined
    genflag = 11b                                 ;;    show proc must also be generated
  else                                            ;;  else
    ife $-two_char_setup                          ;;    it is defined on
      genflag = 11b                               ;;    pass 2 regardless of if we have
    endif                                         ;;    generated it
  endif
endif
if genflag                                        ;;if to generate setup
  if genflag and 10b                              ;;  if generating procedural version
public  two_char_setup                            ;;    make public for debugging
two_char_setup::                                  ;;    define start of setup proc
  endif                                           ;;  endif
        
        DebugMsg <two_char_setup SMARTPRO CLIFFL>

        xchg    ebp,edx                           ;;  BP = buffer, DX = font height
        mov     cl,BYTE PTR [ebp]+wwidth1        ;;
        mov     ch,BYTE PTR [ebp]+pphase2        ;;
        mov     ebx,[ebp]+cchar1                  ;;
        mov     esi,[ebp]+cchar2                  ;;

        and     esi,0ffff0000h
        jz      @F
ifdef FIREWALLS
        int 3
endif
@@:
        mov     esi,[ebp]+cchar2

        mov     ebp,edx                           ;;  restore frame pointer
        xchg    eax,edx                           ;;  set DX = font height
        sub     ebx,esi                           ;;  delta between the characters
        add     esi,pFont
  if genflag and 10b                              ;;  if generating setup procedure
        ret                                       ;;    dispatch to caller
name&_two_char::                                  ;;    define actual procedure
        call    two_char_setup                    ;;    call setup code
  endif                                           ;;  endif
else                                              ;;else
name&_two_char::                                  ;;    define actual procedure
        call    two_char_setup                    ;;    call setup code
endif                                             ;;endif ;setup code


;/*
;** two character compilation logic
;*/

name&_two_char_loop:
        mov     al,BYTE PTR [ebx][esi]
        shl     eax,cl
        xchg    cl,ch
        lodsb
        shr     eax,cl
        xchg    cl,ch
        output  <update>                          ;;Macro to do whatever for outputting
        endm
page

;/*
;**--------------------------------Macro----------------------------------;
;** one_char
;**
;**       one_char is a macro for generating the code required to
;**       process a destination character consisting of 1 source byte
;**
;**       Usage:
;**               one_char  name,output,update,setup
;**       Where
;**
;**               name    the name of the procedure
;**               output  the macro which will generate the required
;**                       output logic
;**               update  the macro which will generate the required
;**                       destination update logic.
;**               setup   if this parameter is given as "inline", then
;**                       setup code will be generated inline, else a
;**                       subroutine will be called to perform the
;**                       initialization.  This subroutine will be
;**                       created if not defined.
;**
;**       The macro will generate the loop_logic macro which is the
;**       macro used by all update macros for generating looping logic.
;**       It is defined as a macro so that devices which are interleaved
;**       can make multiple copies of it, possibly removing a jump.
;**-----------------------------------------------------------------------;
;*/

one_char macro name,output,update,setup
        local   genflag


;/*
;** one character looping logic macro
;*/

loop_logic      &macro
        dec     edx
        jnz     name&_one_char_loop
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** one character long looping logic macro
;*/

long_loop_logic &macro
        dec     edx
        jz      name&_one_char_exit
        jmp     name&_one_char_loop

        ALIGN   4

name&_one_char_exit:
        sub     edi,cell_adjust
        ret
        &endm


;/*
;** one character setup logic
;*/

public  name&_one_char                            ;;make public
genflag=0                                         ;;assume out_of_line, already generated
ifidn <setup>,<inline>                            ;;if in_line
name&_one_char::                                  ;;  define procedure
  genflag = 01b                                   ;;  show code must be generated
else                                              ;;else
  ifndef one_char_setup                           ;;  if procedure not defined
    genflag = 11b                                 ;;    show proc must also be generated
  else                                            ;;  else
    ife $-one_char_setup                          ;;    it is defined on
      genflag = 11b                               ;;    pass 2 regardless of if we have
    endif                                         ;;    generated it
  endif
endif
if genflag                                        ;;if to generate setup
  if genflag and 10b                              ;;  if generating procedural version
public  one_char_setup                            ;;    make public for debugging
one_char_setup::                                  ;;    define start of setup proc
  endif                                           ;;  endif

        DebugMsg <one_char_setup SMARTPRO CLIFFL>

        mov     esi,pFont
        xchg    edx,ebp                           ;;  BP --> character buffer
        add     esi,[ebp]+cchar1                  ;;  DS:SI = char1
        mov     cl,BYTE PTR [ebp]+pphase1        ;;
        xchg    edx,ebp                           ;;  BP --> frame
        xchg    eax,edx                           ;;  DX = clipped_font_height
  if genflag and 10b                              ;;  if generating setup procedure
        ret                                       ;;    dispatch to caller
name&_one_char::                                  ;;    define actual procedure
        call    one_char_setup                    ;;    call setup code
  endif                                           ;;  endif
else                                              ;;else
name&_one_char::                                  ;;    define actual procedure
        call    one_char_setup                    ;;    call setup code
endif                                             ;;endif ;setup code


;/*
;** one character compilation logic
;*/

name&_one_char_loop:
        lodsb                                     ;;char1
        shr     al,cl
        output  <update>
        endm
page

;/*
;**--------------------------------Macro----------------------------------;
;** clipped_output
;**
;**       clipped_output is the macro passed to the "x" character macros
;**       when the default subroutines are to be called for outputing a
;**       clipped character
;**
;**       Usage:
;**               clipped_output ll
;**       Where
;**               ll      is the macro to be invoked for generating
;**                       the looping logic.
;**-----------------------------------------------------------------------;
;*/

clipped_output macro x
        call    ss_draw_clipped
        x
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** non_clipped_output
;**
;**       non_clipped_output is the macro passed to the "x" character
;**       macros when the default subroutines are to be called for
;**       outputing a non-clipped character
;**
;**       Usage:
;**               non_clipped_output ll
;**       Where
;**              ll      is the macro to be invoked for generating
;**                       the looping logic.
;**-----------------------------------------------------------------------;
;*/

non_clipped_output macro x
        call    ss_draw
        x
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** ega_tnc
;**
;**       ega_tnc is a macro for generating the character drawing
;**       logic for transparent mode, non-clipped, ignoring colors, which
;**       only makes sense with hardware support of colors, as with the
;**       EGA.
;**
;**       Usage:
;**               ega_tnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

ega_tnc macro   update
        push    edx
        mov     dx,EGA_BASE + GRAF_DATA
        out     dx,al
        xchg    al,BYTE PTR [edi]
        pop     edx
DRAW_ADJUST = 0                                   ;stosb is not used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** ega_tc
;**
;**       ega_tc is a macro for generating the character drawing
;**       logic for transparent mode, clipped, ignoring colors, which
;**       only makes sense with hardware support of colors, as with the
;**       EGA.
;**
;**       Usage:
;**               ega_tc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

ega_tc  macro   update
        and     al,ss_clip_mask
        push    edx
        mov     dx,EGA_BASE + GRAF_DATA
        out     dx,al
        xchg    al,BYTE PTR [edi]
        pop     edx
DRAW_ADJUST = 0                                   ;stosb is not used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** ega_onc
;**
;**       ega_onc is a macro for generating the character drawing
;**       logic for opaque mode, non-clipped, ignoring colors, which
;**       only makes sense with hardware support of colors, as with the
;**       EGA.
;**
;**       Usage:
;**               ega_onc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

ega_onc macro   update
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** owwc
;**
;**       owwc  is a macro for generating the character drawing
;**       logic for opaque mode, white text, white background, clipped.
;**
;**       Usage:
;**               owwc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

owwc    macro   update
        mov     al,ss_clip_mask
        or      BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** twc
;**
;**       twc is a macro for generating the character drawing
;**       logic for transparent mode, white text, clipped.
;**
;**       Usage:
;**               twc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

twc     macro   update
        and     al,ss_clip_mask
        or      BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** twnc
;**
;**       twnc is a macro for generating the character drawing
;**       logic for transparent mode, white text, non-clipped.
;**
;**       Usage:
;**               twnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

twnc    macro   update
        or      BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** obbc
;**
;**       obbc is a macro for generating the character drawing
;**       logic for opaque mode, black text, black background, clipped.
;**
;**       Usage:
;**               obbc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

obbc    macro   update
        mov     al,ss_clip_mask
        not     al
        and     BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** tbc
;**
;**       tbc is a macro for generating the character drawing
;**       logic for transparent mode, black text, clipped.
;**
;**       Usage:
;**               tbc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

tbc     macro   update
        and     al,ss_clip_mask
        not     al
        and     BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** tbnc
;**
;**       tbnc is a macro for generating the character drawing
;**       logic for transparent mode, black text, non-clipped.
;**
;**       Usage:
;**               tbnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

tbnc    macro   update
        not     al
        and     BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** obwc
;**
;**       obwc is a macro for generating the character drawing
;**       logic for opaque mode, black text, white background, clipped.
;**
;**       Usage:
;**               obwc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

obwc    macro   update
        not     al
        mov     ah,ss_clip_mask
        and     al,ah
        not     ah
        and     ah,BYTE PTR [edi]
        or      al,ah
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** owbc
;**
;**       owbc is a macro for generating the character drawing
;**       logic for opaque mode, white text, black background, clipped.
;**
;**       Usage:
;**               owbc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

owbc    macro   update
        mov     ah,ss_clip_mask
        and     al,ah
        not     ah
        and     ah,BYTE PTR [edi]
        or      al,ah
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** obwnc
;**
;**       obwnc is a macro for generating the character drawing
;**       logic for opaque mode, black text, white background, non-clipped.
;**
;**       Usage:
;**               obwnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

obwnc   macro   update
        not     al
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** owbnc
;**
;**       owbnc is a macro for generating the character drawing
;**       logic for opaque mode, white text, black background, non-clipped.
;**
;**       Usage:
;**               owbnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

owbnc   macro   update
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** obbnc
;**
;**       obbnc is a macro for generating the character drawing
;**       logic for opaque mode, black text, black background, non-clipped.
;**
;**       Usage:
;**               obbnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

obbnc   macro   update
        mov     byte ptr [edi],0
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm

;/*
;**--------------------------------Macro----------------------------------;
;** owwnc
;**
;**       owwnc is a macro for generating the character drawing
;**       logic for opaque mode, white text, white background, non-clipped.
;**
;**       Usage:
;**               owwnc update
;**       Where
;**               update  the macro which will generate the required
;**                       destination update logic.
;**-----------------------------------------------------------------------;
;*/

owwnc   macro   update
        mov     byte ptr [edi],0FFh
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        update
        endm
page

;/*
;**-----------------------------------------------------------------------;
;**
;**       The following tables are used to dispatch the various
;**       combinations of drawing required for foreground/background,
;**       opaque/transparent, device/bitmap, clipped/non-clipped text
;**
;**-----------------------------------------------------------------------;
;*/


special_case_clip_tables                         label DWORD

        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
if SPECIAL_CASE_DEV_TC eq 1
        DWORD   OFFSET dev_tc
        DWORD   OFFSET dev_tc
        DWORD   OFFSET dev_tc
        DWORD   OFFSET dev_tc
else
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
        DWORD   OFFSET gen_cl
endif
        DWORD   OFFSET dev_oc
        DWORD   OFFSET dev_oc
        DWORD   OFFSET dev_oc
        DWORD   OFFSET dev_oc


special_case_non_clip_tables                     label DWORD
if SPECIAL_CASE_BM_TBNC eq 1
        DWORD   OFFSET bm_tbnc
        DWORD   OFFSET bm_tbnc
else
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_BM_TWNC eq 1
        DWORD   OFFSET bm_twnc
        DWORD   OFFSET bm_twnc
else
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_BM_OBBNC eq 1
        DWORD   OFFSET bm_obbnc
else
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_BM_OBWNC eq 1
        DWORD   OFFSET bm_obwnc
else
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_BM_OWBNC eq 1
        DWORD   OFFSET bm_owbnc
else
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_BM_OWWNC eq 1
        DWORD   OFFSET bm_owwnc
else
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_DEV_TNC eq 1
        DWORD   OFFSET dev_tnc
        DWORD   OFFSET dev_tnc
        DWORD   OFFSET dev_tnc
        DWORD   OFFSET dev_tnc
else
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
endif
if SPECIAL_CASE_DEV_ONC eq 1
        DWORD   OFFSET dev_onc
        DWORD   OFFSET dev_onc
        DWORD   OFFSET dev_onc
        DWORD   OFFSET dev_onc
else
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
        DWORD   OFFSET gen_nc
endif


gen_nc  label   DWORD
        DWORD   OFFSET gen_nc_one_char
        DWORD   OFFSET gen_nc_two_char
        DWORD   OFFSET gen_nc_three_char
        DWORD   OFFSET gen_nc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char

gen_cl  label   DWORD
        DWORD   OFFSET gen_cl_one_char
        DWORD   OFFSET gen_cl_two_char
        DWORD   OFFSET gen_cl_three_char
        DWORD   OFFSET gen_cl_four_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
;/*
;**       This is a difficult enough mode of output that it is always
;**       "special-cased".  It actually goes through the generic handlers,
;**       but the entries in the first table below set up two passes
;**       through the functions in the second table.
;*/

dev_oc label DWORD
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop
        DWORD   OFFSET ega_oc_outer_loop_prop

        public  ega_oc
ega_oc label DWORD
        DWORD   OFFSET gen_cl_one_char
        DWORD   OFFSET gen_cl_two_char
        DWORD   OFFSET gen_cl_three_char
        DWORD   OFFSET gen_cl_four_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char

if SPECIAL_CASE_BM_OBWNC eq 1
bm_obwnc label DWORD
        DWORD   OFFSET bm_obwnc_one_char
        DWORD   OFFSET bm_obwnc_two_char
        DWORD   OFFSET bm_obwnc_three_char
        DWORD   OFFSET bm_obwnc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
endif

if SPECIAL_CASE_BM_OWBNC eq 1
bm_owbnc label DWORD
        DWORD   OFFSET bm_owbnc_one_char
        DWORD   OFFSET bm_owbnc_two_char
        DWORD   OFFSET bm_owbnc_three_char
        DWORD   OFFSET bm_owbnc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
endif

if SPECIAL_CASE_BM_TBNC eq 1
bm_tbnc label DWORD
        DWORD   OFFSET bm_tbnc_one_char
        DWORD   OFFSET bm_tbnc_two_char
        DWORD   OFFSET bm_tbnc_three_char
        DWORD   OFFSET bm_tbnc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
endif

if SPECIAL_CASE_BM_TWNC eq 1
bm_twnc label DWORD
        DWORD   OFFSET bm_twnc_one_char
        DWORD   OFFSET bm_twnc_two_char
        DWORD   OFFSET bm_twnc_three_char
        DWORD   OFFSET bm_twnc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
endif

if SPECIAL_CASE_DEV_ONC eq 1                     ;Device, opaque, non-clipped
dev_onc label DWORD
        DWORD   OFFSET dev_onc_one_char
        DWORD   OFFSET dev_onc_two_char
        DWORD   OFFSET dev_onc_three_char
        DWORD   OFFSET dev_onc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
endif

if SPECIAL_CASE_DEV_TNC eq 1                     ;Device, transparent, non-clipped
dev_tnc label   DWORD
        DWORD   OFFSET dev_tnc_one_char
        DWORD   OFFSET dev_tnc_two_char
        DWORD   OFFSET dev_tnc_three_char
        DWORD   OFFSET dev_tnc_four_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
        DWORD   OFFSET gen_nc_n_char
endif

if SPECIAL_CASE_DEV_TC eq 1                      ;Device, transparent, clipped
dev_tc label    DWORD
        DWORD   OFFSET dev_tc_one_char
        DWORD   OFFSET dev_tc_two_char
        DWORD   OFFSET dev_tc_three_char
        DWORD   OFFSET dev_tc_four_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
        DWORD   OFFSET gen_cl_n_char
endif


;/*
;**
;**       Define the drawing logic tables.  These tables are used to
;**       fetch the address of the output function for the combination
;**       of foreground/background colors, opaque/transparent mode,
;**       and device/bitmap.
;**
;**       The tables are indexed as follows:
;**
;**         DEV/BM O/T FG BK  0;
;**           |     |   |  |
;**           |     |   |   ----------  background color (0/1)
;**           |     |   |
;**           |     |    -------------  foreground color (0/1)
;**           |     |
;**           |      -----------------  0 if transparent, 1 if opaque
;**           |
;**            ------------------------ 0 if a bitmap, 1 if the device
;**
;** There are 3 sets of drawing logic tables with the first being overwrite,
;** then xor, and finally or. Each set has three tables clipped, nonclipped,
;** and mono-nonclipped. Each of these tables are 32 bytes long making each
;** group 96 bytes long. These lengths are expected to be such and the
;** DWORD 0's should be left in place.
;*/

MASK_DEVBM      equ     00010000b
MASK_OT         equ     00001000b
MASK_FG         equ     00000100b
MASK_BK         equ     00000010b

MASK_DEV_ONC    equ     MASK_DEVBM or MASK_OT    ;MASK_BK, MASK_FG wildcards
MASK_DEV_TNC    equ     MASK_DEVBM                ;MASK_BK, MASK_FG wildcards
MASK_DEV_OC     equ     MASK_DEVBM or MASK_OT    ;MASK_BK, MASK_FG wildcards
MASK_DEV_TC     equ     MASK_DEVBM                ;MASK_BK, MASK_FG wildcards

MASK_BM_OBWNC   equ     MASK_OT or MASK_BK
MASK_BM_OWBNC   equ     MASK_OT or MASK_FG
MASK_BM_TBNC    equ     0                          ;MASK_BK is a wildcard
MASK_BM_TWNC    equ     MASK_FG                    ;MASK_BK is a wildcard

clipped_drawing_functions label DWORD

        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   4 dup (0)                          ;special case for opaque-clipped


non_clipped_drawing_functions label DWORD

        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_trans_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip


mono_non_clipped_drawing_functions               label DWORD

        DWORD   OFFSET  bm_trans_black
        DWORD   OFFSET  bm_trans_black
        DWORD   OFFSET  bm_trans_white
        DWORD   OFFSET  bm_trans_white
        DWORD   OFFSET  bm_opaque_black_on_black
        DWORD   OFFSET  bm_opaque_black_on_white
        DWORD   OFFSET  bm_opaque_white_on_black
        DWORD   OFFSET  bm_opaque_white_on_white
        DWORD   8 dup (0)

clipped_table_size = $ - clipped_drawing_functions

xor_clipped_drawing_functions label DWORD

        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   4 dup (0)                         ;these are a special case


xor_non_clipped_drawing_functions label DWORD

        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  xor_bm_trans_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip


xor_mono_non_clipped_drawing_functions           label DWORD

        DWORD   OFFSET  xor_bm_trans_black
        DWORD   OFFSET  xor_bm_trans_black
        DWORD   OFFSET  xor_bm_trans_white
        DWORD   OFFSET  xor_bm_trans_white
        DWORD   OFFSET  bm_opaque_white_on_black
        DWORD   OFFSET  bm_opaque_white_on_white
        DWORD   OFFSET  bm_opaque_black_on_black
        DWORD   OFFSET  bm_opaque_black_on_white
        DWORD   8 dup (0)

xor_clipped_table_size = $ - xor_clipped_drawing_functions
        .errnz  clipped_table_size - xor_clipped_table_size
        
or_clipped_drawing_functions label DWORD

        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   OFFSET ega_trans_clip
        DWORD   4 dup (0)                         ;these are a special case


or_non_clipped_drawing_functions label DWORD

        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  or_bm_trans_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET  bm_opaque_color
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_trans
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip
        DWORD   OFFSET ega_opaque_non_clip


or_mono_non_clipped_drawing_functions            label DWORD

        DWORD   OFFSET  or_bm_trans_black
        DWORD   OFFSET  or_bm_trans_black
        DWORD   OFFSET  bm_trans_white
        DWORD   OFFSET  bm_trans_white
        DWORD   OFFSET  bm_opaque_black_on_black
        DWORD   OFFSET  bm_opaque_black_on_white
        DWORD   OFFSET  bm_opaque_white_on_black
        DWORD   OFFSET  bm_opaque_white_on_white
or_clipped_table_size = $ - or_clipped_drawing_functions

        .errnz  or_clipped_table_size - xor_clipped_table_size + 32

page

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None
                        
;/***************************************************************************
;*
;* FUNCTION NAME = SmartPro 
;*
;* DESCRIPTION   = Contains the routines for outputting proportion
;*                 and fixed pitch characters.                                  
;*                                                                              
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

SmartPro PROC SYSCALL,          
  lp_DDC        :DWORD, 
  lp_DestDev    :DWORD,
  x             :DWORD,
  y             :DWORD,
  lp_clip_rect  :DWORD,
  lp_string     :DWORD,
  count         :DWORD,
  npAttrs       :DWORD,
  lp_dx         :DWORD,
  lp_opaque_rect:DWORD,
  eto_options   :DWORD 

        LOCAL   accel           :BYTE            
        LOCAL   excel           :BYTE            
        LOCAL   wc_flags        :BYTE            
        LOCAL   fbTranslate     :BYTE            
        LOCAL   colors          :DWORD           
        LOCAL   char_extra      :DWORD           
        LOCAL   num_null_pixels :DWORD           
        LOCAL   null_char_offset:DWORD           
        LOCAL   lhs             :DWORD           
        LOCAL   rhs             :DWORD           
        LOCAL   concat          :DWORD           
        LOCAL   pFont           :DWORD           
        LOCAL   lfd             :local_font_def
        LOCAL   clip            :RECTL
        LOCAL   text_bbox       :RECTL
        LOCAL   o_rect          :RECTL
        LOCAL   smart_flags            :BYTE
        LOCAL   special_bm_opaque_color:BYTE     
        LOCAL   num_planes             :BYTE     
        LOCAL   left_clip_mask         :BYTE     
        LOCAL   right_clip_mask        :BYTE     
        LOCAL   cell_adjust            :DWORD    
        LOCAL   buffer                 :DWORD    
        LOCAL   fix_total_bytes        :DWORD    
        LOCAL   next_scan              :DWORD    
        LOCAL   next_plane             :DWORD    
        LOCAL   next_scan_xor          :DWORD    
        LOCAL   opaque_routine         :DWORD    
        LOCAL   opaque_height          :DWORD    
        LOCAL   lp_surface             :DWORD    
        LOCAL   temp_off_lp_bits       :DWORD    
        LOCAL   scan_start             :DWORD    
        LOCAL   clipped_font_height    :DWORD    
        LOCAL   amt_clipped_on_top     :DWORD    
        LOCAL   clear_stack            :DWORD    
        LOCAL   min_stack              :DWORD    
        LOCAL   build_proc             :DWORD    
        LOCAL   phase                  :DWORD
        LOCAL   x2                     :DWORD
        LOCAL   inner_loop             :DWORD
        LOCAL   clipped_table          :DWORD    
        LOCAL   non_clipped_table      :DWORD    
        LOCAL   inner_byte_count       :DWORD    
        LOCAL   current_lhs            :DWORD    
        LOCAL   current_rhs            :DWORD    
        LOCAL   wc_opaque_lhs          :DWORD    
        LOCAL   wc_opaque_rhs          :DWORD    
        LOCAL   string_start_bias      :DWORD    
        LOCAL   ret_addr               :DWORD    
        LOCAL   unrolled_entry_point   :DWORD    
        LOCAL   vect_one_in_first      :DWORD    
        LOCAL   vect_two_in_first      :DWORD
        LOCAL   vect_one_in_middle     :DWORD
        LOCAL   vect_two_in_middle     :DWORD
        LOCAL   vect_one_in_last       :DWORD
        LOCAL   vect_two_in_last       :DWORD
        LOCAL   ret_addr_2             :DWORD
        LOCAL   ega_oc_saved_data      :DWORD



;/***************************************************************************
;*
;* PUBLIC ROUTINE   ega_oc_outer_loop_prop 
;*
;* DESCRIPTION   = 
;*                 
;*       Overall control logic for opaque clipped text to the EGA.
;*    
;*       For proportional text, this function stands in as bit gathering
;*       function (xxx_one_char, xxx_two_char, etc.). For fixed pitch text,
;*       this function supersedes the clipped bit gathering functions
;*       (xxx_one_in_first, xxx_two_in_last, etc.).  In either case, it sets
;*       up two passes through the appropriate generic bit gathering functions.
;*    
;*       Since the drawing function changes between passes, ss_draw_clipped
;*       must be set as needed here.
;*                 
;*       Registers Preserved:           
;*             CX,DX,DI,DS,ES           
;*       Registers Destroyed:           
;*             AX,BX,SI,BP              
;*                 
;* INPUT         = DS:     =  Font bits segment                
;*                 ES:DI  --> destination (ES = ScreenSelector)
;*                 DX      =  pointer to frame data            
;*                 CX      =  # of source characters - 1       
;*                 AX      =  Visible height                   
;* OUTPUT        = ES:DI  --> destination  
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  ega_oc_outer_loop_prop


        ALIGN   4

ega_oc_outer_loop_prop::

        mov     ebx,ecx                           ;create dispatch table index
        shl     ebx,1
        test    accel,IS_OR_TEXT                 
        jnz     ega_or_clipped_mode
        mov     ss_draw_clipped,OFFSET ega_opaque_clip_1
        test    accel,IS_XOR_TEXT
        jnz     ega_xor_clipped_mode

        push    eax                               ;save registers for second pass
        push    ebx
        push    ecx
        push    edx
        push    edi
        push    ebp                               ;prop code sometimes destroys this
        push    eax                               ;save regs destroyed inside call
        push    edx
        call    setup_ega_opaque_clip_magic
        pop     edx
        pop     eax

        call    ega_oc[ebx*2]                     ;do first pass

        mov     dx,EGA_BASE + SEQ_DATA
        mov     al,BYTE PTR colors[BACKGROUND]
        out     dx,al

        pop     ebp
        pop     edi                               ;restore registers for second pass
        pop     edx
        pop     ecx
        pop     ebx

;/*
;**       The next block of code determines if the second pass is
;**       necessary.
;**
;**       Note that the EGA has been programmed to allow writing only to
;**       the planes composing the background color. Since we're writing
;**       opaque text, all planes in the background color also in the
;**       foreground have been set by the first pass.  The second
;**       pass cleans up the background planes not in the foreground
;**       color.  If there aren't any, then skip the second pass.
;*/

        mov     eax,ss_colors
        xor     al,ah                             ;determine mismatching bits
        and     al,ah                             ;isolate those in the bk color
        pop     eax
        jz      ega_oc_outer_loop_skip_pass_2
;/*
;**       Set the return address variable in case we're fixed pitch.
;**       The first "errnz" is commented out because these subroutines are
;**       linked in from smartpro.asm.  The errnz should be alive there.
;*/

ega_not_or_clipped_mode:

        sub     ss_draw_clipped,2

ega_oc_invoke_pass_2:

        call    ega_oc[ebx*2] ;SEL 1-26-92:added *2   ;do second pass

ega_oc_outer_loop_chk_inner:

        test    excel,RES_EGA_INNER              ;is there a middle part to string?
        jz      ega_oc_outer_loop_exit           ;if no, skip EGA register setup
        call    set_ega_opaque_mode              ;else, prepare EGA for full opaque
        and     excel,not RES_EGA_INNER          ;prevent this at end of string

ega_oc_outer_loop_exit:

        ret
;/*
;**       Update ES:DI as would have been done by second pass, then check
;**       to see if EGA reprogramming is necessary for a non-clipped section
;**       of opaque text.
;*/

ega_oc_outer_loop_skip_pass_2:

        inc     edi                               ;update di for whoever follows
        jmp     ega_oc_outer_loop_chk_inner

        ALIGN   4


ega_or_clipped_mode:

        push    eax
        push    edx
        call    set_ega_opaque_mode              ;Incase it hasn't been done yet
        mov     al,ss_clip_mask
        mov     dx,EGA_BASE + GRAF_DATA
        out     dx,al
        pop     edx
        pop     eax
        mov     ss_draw_clipped,OFFSET ega_or_clipped
        jmp     ega_oc_invoke_pass_2

        ALIGN   4


ega_xor_clipped_mode:

        push    eax                               ;save registers for second pass
        push    ebx
        push    ecx
        push    edx
        push    edi
        push    ebp                               ;prop code sometimes destroys this

        push    eax                               ;Set background into the partial byte
        push    edx
        mov     dx,EGA_BASE + SEQ_DATA
        mov     al,MM_ALL
        out     dx,al
        mov     dl,GRAF_ADDR
        mov     ax,DR_SET shl 8 + GRAF_DATA_ROT
        out     dx,ax
        mov     ah,byte ptr ss_colors[BACKGROUND]
        mov     al,GRAF_SET_RESET
        out     dx,ax
        mov     ax,MM_ALL shl 8 + GRAF_ENAB_SR
        out     dx,ax
        mov     ah,ss_clip_mask
        mov     al,GRAF_BIT_MASK
        out     dx,ax
        pop     edx
        pop     eax
        call    ega_oc[ebx*2]  ;SEL 1-26-92:added *2 ;do first pass

        mov     al,byte ptr ss_colors[FOREGROUND]
        mov     dx,EGA_BASE + SEQ_DATA
        out     dx,al                             ;Second pass only where foreground = 1
        mov     dl,GRAF_ADDR
        mov     ax,GRAF_ENAB_SR                  ;No set/reset
        out     dx,ax
        mov     ax,DR_XOR shl 8 + GRAF_DATA_ROT
        out     dx,ax
        mov     ah,ss_clip_mask                  ;Last register output to just incase
        mov     al,GRAF_BIT_MASK
        out     dx,ax

        pop     ebp
        pop     edi                               ;restore registers for second pass
        pop     edx
        pop     ecx
        pop     ebx
        pop     eax
        jmp     ega_oc_invoke_pass_2

        ALIGN   4


        page



;/***************************************************************************
;*
;* PUBLIC ROUTINE   ega_or_clipped 
;*
;* DESCRIPTION   =  Drawing routines for EGA, opaque mode, clipped    
;*
;*                  Registers Preserved:          
;*                        BX,CX,DX,SI,DI,DS,ES,BP 
;*                  Registers Destroyed:          
;*                        AX                      
;*
;* INPUT         =  AL = character to output    
;*                  ES:DI --> destination byte  
;*
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  ega_or_clipped


        ALIGN   4

ega_or_clipped::

        xchg    al,BYTE PTR [edi]

DRAW_ADJUST = 0                                   ;stosb is not used

        upd_dev <ret>                             ;will generate ret
page


;/***************************************************************************
;*
;* PUBLIC ROUTINES  ega_trans_clip   
;*                  ega_trans        
;*
;* DESCRIPTION   =  Drawing routines for EGA, transparent mode, clipped and    
;*                  non-clipped.                                               
;*                                                                             
;*                  Registers Preserved:         
;*                        BX,CX,DX,SI,DI,DS,ES,BP
;*                  Registers Destroyed:         
;*                        AX                     
;*
;* INPUT         = AL = character to output 
;*                 ES:DI --> destination byt
;*
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        ALIGN   4

ega_trans_clip::

        and     al,ss_clip_mask

ega_trans::

        push    edx
        mov     dx,EGA_BASE + GRAF_DATA
        out     dx,al
        xchg    al,BYTE PTR [edi]
        pop     edx

DRAW_ADJUST = 0                                   ;stosb is not used

        upd_dev <ret>                             ;will generate ret
page


;/***************************************************************************
;*
;* PUBLIC ROUTINES  bm_opaque_white_on_white_clip 
;*                  bm_trans_white_clip           
;*                  bm_trans_white                
;*                  xor_bm_trans_white            
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                     opaque, white on white, clipped    
;*                     transparent, white, clipped        
;*                     transparent, white, non-clipped    
;*                 
;*                 Registers Preserved:           
;*                       BX,CX,DX,SI,DI,DS,ES,BP  
;*                 Registers Destroyed:           
;*                       AX                       
;*
;* INPUT         = AL = character to output    
;*                 ES:DI --> destination byte  
;*                 
;*                 
;*
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        ALIGN   4

bm_opaque_white_on_white_clip:

        mov     al,0FFh

bm_trans_white_clip:

        and     al,ss_clip_mask

bm_trans_white::

        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm  <ret>                             ;Will generate the ret



xor_bm_trans_white::
        xor     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm  <ret>                             ;Will generate the ret


page


;/***************************************************************************
;*
;* PUBLIC ROUTINES  bm_opaque_black_on_black_clip 
;*                  bm_trans_black_clip           
;*                  bm_trans_black                
;*                  xor_bm_trans_black            
;*                  or_bm_trans_black             
;*
;* DESCRIPTION   = Standard bitmap drawing functions for:      
;*                                                             
;*                     opaque, black on black, clipped         
;*                     transparent, black, clipped             
;*                     transparent, black, non-clipped         
;*                 
;*                 Registers Preserved:          
;*                       BX,CX,DX,SI,DI,DS,ES,BP 
;*                 Registers Destroyed:          
;*                       AX                      
;*
;* INPUT         = AL = character to output   
;*                 ES:DI --> destination byte 
;*                 
;*                 
;*
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC bm_opaque_black_on_black_clip 


        ALIGN   4

bm_opaque_black_on_black_clip::

        mov     al,0FFh

bm_trans_black_clip:

        and     al,ss_clip_mask

bm_trans_black::

        not     al
        and     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm  <ret>                             ;Will generate the ret

or_bm_trans_black::

        not     al
        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm  <ret>                             ;Will generate the ret

xor_bm_trans_black::

        not     al
        xor     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm  <ret>                             ;Will generate the ret
page


;/***************************************************************************
;*
;* PUBLIC ROUTINES   bm_opaque_black_on_white        
;*                   bm_opaque_white_on_black        
;*
;* DESCRIPTION   =  Standard bitmap drawing functions for:     
;*                                                             
;*                      opaque, black on white, non-clipped    
;*                      opaque, white on black, non-clipped    
;*                 
;*                 Registers Preserved:              
;*                       BX,CX,DX,SI,DI,DS,ES,BP     
;*                 Registers Destroyed:              
;*                       AX                          
;*
;* INPUT         = AL = character to output  
;*                 ES:DI --> destination byte
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        ALIGN   4

bm_opaque_black_on_white::

        not     al

bm_opaque_white_on_black::

        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_bm  <ret>                             ;Will generate the ret
page


;/***************************************************************************
;*
;* PUBLIC ROUTINES  bm_opaque_black_on_white_clip    
;*                  bm_opaque_white_on_black_clip    
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                     opaque, black on white, clipped    
;*                     opaque, white on black, clipped    
;*                 
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = AL = character to output    
;*                 ES:DI --> destination byte  
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

bm_opaque_black_on_white_clip:

        not     al

bm_opaque_white_on_black_clip:

        mov     ah,ss_clip_mask
        and     al,ah
        not     ah
        and     ah,BYTE PTR [edi]
        or      al,ah
        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_bm  <ret>                             ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES   bm_opaque_white_on_white             
;*                   bm_opaque_black_on_black             
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                     opaque, white on white, non-clipped               
;*                     opaque, black on black, non-clipped               
;*                 
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = AL = character to output    
;*                 ES:DI --> destination byte  
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

bm_opaque_white_on_white::

        mov     al,0FFh
        jmp     jstop

        ALIGN   4


bm_opaque_black_on_black::

        xor     al,al
jstop:
        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_bm  <ret>                             ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES   bm_trans_color_fix                   
;*                   bm_trans_color                       
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      transparent, color                               
;*                                                        
;*                Entry points are for the fixed width code and proportional
;*                width code  respectively.
;*                                                        
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = (fixed):                              
;*                 AL = character to output              
;*                 DX = return address                   
;*                 ES:DI --> destination byte     
;*                 (prop):                        
;*                 AL = character to output       
;*                 ES:DI --> destination byte     
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  bm_trans_color_fix
        PUBLIC  bm_trans_color


        ALIGN   4

bm_trans_color_fix::

        push    edx                               ;put return address on stack

bm_trans_color::

        push    eax
        push    ecx
        push    edi

        xchg    ebp,ss_p_frame                    ;get frame pointer


        mov     ch,ss_clip_mask
        or      ch,ch
        mov     ah,al
        jz      bm_trans_color_no_clip

        mov     ah,ch
        and     ah,al
        mov     al,ah

bm_trans_color_no_clip:

        not     ah
        mov     cl,num_planes
        mov     ch,byte ptr ss_colors[FOREGROUND]

bm_trans_color_loop:

        and     BYTE PTR [edi],ah
        ror     ch,1                              ;see if this color plane is used
        jnc     bm_trans_color_set_byte
        or      BYTE PTR [edi],al

bm_trans_color_set_byte:

        add     edi,next_plane
        dec     cl
        jnz     bm_trans_color_loop

        xchg    ebp,ss_p_frame                    ;restore bp and ss_p_frame

        pop     edi
        pop     ecx
        pop     eax

DRAW_ADJUST = 0

        upd_bm <ret>                              ;Will generate the ret
page


;/***************************************************************************
;*
;* PUBLIC ROUTINES   or_bm_trans_color_fix                
;*                   or_bm_trans_color                    
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      transparent, color                               
;*                                                        
;*                Entry points are for the fixed width code and proportional
;*                width code respectively.
;*                                                        
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = (fixed):                              
;*                 AL = character to output              
;*                 DX = return address                   
;*                 ES:DI --> destination byte     
;*                 (prop):                        
;*                 AL = character to output       
;*                 ES:DI --> destination byte     
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  or_bm_trans_color_fix
        PUBLIC  or_bm_trans_color


        ALIGN   4

or_bm_trans_color_fix::

        push    edx                               ;put return address on stack

or_bm_trans_color::

        push    eax
        push    ecx
        push    edi

        xchg    ebp,ss_p_frame                    ;get frame pointer


        mov     ch,ss_clip_mask
        or      ch,ch
        mov     ah,al
        jz      or_bm_trans_color_no_clip

        mov     ah,ch
        and     ah,al
        mov     al,ah

or_bm_trans_color_no_clip:

        not     ah
        mov     cl,num_planes
        mov     ch,byte ptr ss_colors[FOREGROUND]

or_bm_trans_color_loop:

        ror     ch,1                              ;see if this color plane is used
        jnc     or_bm_trans_color_set_byte
        or      BYTE PTR [edi],al

or_bm_trans_color_set_byte:

        add     edi,next_plane
        dec     cl
        jnz     or_bm_trans_color_loop

        xchg    ebp,ss_p_frame                    ;restore bp and ss_p_frame

        pop     edi
        pop     ecx
        pop     eax

DRAW_ADJUST = 0

        upd_bm <ret>                              ;Will generate the ret
page


;/***************************************************************************
;*
;* PUBLIC ROUTINES   xor_bm_trans_color_fix               
;*                   xor_bm_trans_color                   
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      transparent, color                               
;*                                                        
;*                Entry points are for the fixed width code and proportional
;*                width code respectively.
;*                                                        
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = (fixed):                              
;*                 AL = character to output              
;*                 DX = return address                   
;*                 ES:DI --> destination byte     
;*                 (prop):                        
;*                 AL = character to output       
;*                 ES:DI --> destination byte     
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  xor_bm_trans_color_fix
        PUBLIC  xor_bm_trans_color


        ALIGN   4

xor_bm_trans_color_fix::

        push    edx                               ;put return address on stack

xor_bm_trans_color::

        push    eax
        push    ecx
        push    edi

        xchg    ebp,ss_p_frame                    ;get frame pointer


        mov     ch,ss_clip_mask
        or      ch,ch
        mov     ah,al
        jz      xor_bm_trans_color_no_clip

        mov     ah,ch
        and     ah,al
        mov     al,ah

xor_bm_trans_color_no_clip:

        not     ah
        mov     cl,num_planes
        mov     ch,byte ptr ss_colors[FOREGROUND]

xor_bm_trans_color_loop:

        ror     ch,1                              ;see if this color plane is used
        jnc     xor_bm_trans_color_set_byte
        xor     BYTE PTR [edi],al

xor_bm_trans_color_set_byte:

        add     edi,next_plane
        dec     cl
        jnz     xor_bm_trans_color_loop

        xchg    ebp,ss_p_frame                    ;restore bp and ss_p_frame

        pop     edi
        pop     ecx
        pop     eax

DRAW_ADJUST = 0

        upd_bm <ret>                              ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES   bm_opaque_color_fix             
;*                   bm_opaque_color                      
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      opaque, color                                    
;*                                                        
;*                                                        
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = AL = character to output             
;*                 ES:DI --> destination byte           
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        PUBLIC  bm_opaque_color_fix
        PUBLIC  bm_opaque_color


        ALIGN   4

bm_opaque_color_fix::

        push    edx                               ;put return address on stack

bm_opaque_color::

        push    eax
        push    ecx
        push    edx
        push    edi

        xchg    ebp,ss_p_frame                    ;get frame pointer

        mov     ch,ss_clip_mask
        mov     dh,num_planes
        mov     dl,special_bm_opaque_color

bm_opaque_color_partial:

        shr     dl,1                              ;set C to inversion mask
        sbb     ah,ah
        and     ah,al                             ;AH = 1 where we want NOT background
        shr     dl,1                              ;set C to background color
        sbb     cl,cl                             ;AH = background color (00 or FF)
        xor     cl,ah                             ;AH = destination byte
        mov     ah,BYTE PTR [edi]
        xor     ah,cl
        and     ah,ch
        xor     BYTE PTR [edi],ah                ;output byte to color plane
        add     edi,next_plane                    ;point to next color plane
        dec     dh
        jnz     bm_opaque_color_partial          ;handle next color plane

        xchg    ebp,ss_p_frame                    ;restore bp and ss_p_frame

        pop     edi
        pop     edx
        pop     ecx
        pop     eax

DRAW_ADJUST = 0

        upd_bm <ret>                              ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINE   ega_opaque_non_clip:            
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                     EGA opaque mode (color combination does not matter)   
;*                                                        
;*                                                        
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = AL = character to output             
;*                 ES:DI --> destination byte           
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  ega_opaque_non_clip


        ALIGN   4

ega_opaque_non_clip::

        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_dev <ret>                             ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINE   ega_opaque_clip_2                
;*                  ega_opaque_clip_1                
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      opaque, clipped                
;*                 Two passes are required for this mode of text output.     
;*                 Label ega_opaque_clip_x is the drawing function for pass x
;*                                                                           
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = AL = character to output             
;*                 ES:DI --> destination byte           
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  ega_opaque_clip_2
        PUBLIC  ega_opaque_clip_1


        ALIGN   4

ega_opaque_clip_2::

        not     al

ega_opaque_clip_1::

        xchg    al,BYTE PTR [edi]

DRAW_ADJUST     = 0                               ;STOSB is not used

        upd_dev <ret>                             ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINE   preset_pro_text                  
;*
;* DESCRIPTION   = Set any frame variables and stack locations (in the ring 2 
;*                 stack) required to output text with the current attributes.
;*                                                                            
;*                Registers Preserved:           
;*                      BX,CX,DX,SI,DI,DS,ES,BP  
;*                Registers Destroyed:           
;*                      AX                       
;*
;* INPUT         = BL = accel                           
;*                 AH = excel                           
;*                 SS = ring 2 stack                  
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        PUBLIC  preset_pro_text


        ALIGN   4

preset_pro_text::

        DebugMsg <preset_pro_text SMARTPRO CLIFFL>

        mov     ss_p_frame,ebp
        mov     ecx,next_scan
        mov     ss_next_scan,ecx
        mov     ecx,colors
        mov     ss_colors,ecx
;/*
;**       Accumulate foreground/background colors, opaque/transparent mode,
;**       and device/bitmap to determine which drawing functions will be
;**       used.
;*/

        and     ebx,IS_OPAQUE                     ;BL = 0000000 O/T

        errnz   IS_OPAQUE-00000001

        shr     cl,1
        rcl     bl,1                              ;BL = 000000 O/T FG

        errnz   FOREGROUND

        shr     ch,1                              ;BL = 00000 O/T FG BK
        rcl     bl,1

        errnz   BACKGROUND-FOREGROUND-1

        mov     dl,ah                             ;save the excel flag
        and     ah,IS_DEVICE
        or      bl,ah                             ;BL = 0000 DEV/BM O/T FG BK

        errnz   IS_DEVICE-00001000b

        shl     ebx,1                             ;BX = 00000000 000 DEV/BM O/T FG BK 0

;/*
;**       Now that we have an index into our tables of drawing functions,
;**       find out which table to use.  We use special tables for the
;**       nonclipped cases of device and monochrome bitmaps.  For color
;**       bitmaps, and all clipped cases, we'll get the drawing function
;**       from the general case table.
;*/

        mov     esi,ebx
        and     dl,IS_DEVICE                      ; are we using a bitmap
        jnz     preset_pro_no_x_or               ;no
        xor     edx,edx
        mov     cl,accel
        and     cl,(IS_OR_TEXT OR IS_XOR_TEXT)
        jz      preset_pro_no_x_or
        shr     cl,2

        .errnz  IS_XOR_TEXT-00000010b

        .errnz  IS_OR_TEXT -00000100b

        mov     edx,clipped_table_size
ifdef  JFIX        ;IBMJ
 shr edx,1
endif ;JFIX        ;IBMJ
        shl     edx,cl
        add     ebx,edx

preset_pro_no_x_or:

        mov     eax,non_clipped_drawing_functions[ebx*2]

        test    bl,MASK_DEVBM

        errnz   <MASK_DEVBM and 0FF00h>

        jnz     preset_pro_text_lookup_func
        cmp     num_planes,1
        jne     preset_pro_text_standard_func

        mov     eax,mono_non_clipped_drawing_functions[ebx*2]

preset_pro_text_lookup_func:

        mov     ebx,esi
        mov     esi,special_case_non_clip_tables[ebx*2]
        mov     edi,special_case_clip_tables[ebx*2]

preset_pro_text_have_func:

        mov     non_clipped_table,esi
        mov     clipped_table,edi
        mov     ss_draw,eax

        mov     eax,clipped_drawing_functions[ebx*2]
        mov     ss_draw_clipped,eax

        ret


preset_pro_text_standard_func:

        mov     esi,OFFSET gen_nc
        mov     edi,OFFSET gen_cl
        jmp     preset_pro_text_have_func

        ALIGN   4


        page

        PUBLIC  setup_ega_opaque_clip_magic


;/***************************************************************************
;*
;* PUBLIC ROUTINE setup_ega_opaque_clip_magic   
;*
;* DESCRIPTION   = 
;*
;*                 Registers Destroyed:             
;*                       AX, DX                     
;*                 Registers Preserved:             
;*                       BX, CX, SI, DI, BP, DS, ES 
;*
;* INPUT         = BP      = frame pointer 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        ALIGN   4

setup_ega_opaque_clip_magic::

        mov     dx,EGA_BASE + GRAF_ADDR
        mov     ax,DR_SET shl 8 + GRAF_DATA_ROT
        out     dx,ax

        mov     ah,ss_clip_mask
        mov     al,GRAF_BIT_MASK
        out             dx,ax

        mov     ah,BYTE PTR ss_colors[FOREGROUND]
        mov     al,GRAF_SET_RESET
        out             dx,ax

        xor     ah,BYTE PTR ss_colors[BACKGROUND]
        not     ah
        mov     al,GRAF_ENAB_SR
        out             dx,ax

        mov     dx,EGA_BASE + SEQ_DATA
        or      ah,BYTE PTR ss_colors[FOREGROUND]
        mov     al,ah
        out     dx,al

        ret

        page

;/*
;**
;**       The following cases are the general purpose routines for
;**       outputting the text.  They will call through the stack
;**       locations ss_draw and ss_draw_clipped to perform the
;**       actual output operations.
;**
;**       Following the general purpose routines are any special
;**       case routines.
;**
;*/


        ALIGN   4

        one_char        <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        two_char        <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        three_char      <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        four_char       <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        n_char          <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>

        ALIGN   4


        ALIGN   4

        one_char        <gen_cl>,<clipped_output>,<loop_logic>,<sub>

        ALIGN   4


        ALIGN   4

        two_char        <gen_cl>,<clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        three_char      <gen_cl>,<clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        four_char       <gen_cl>,<clipped_output>,<loop_logic>,<sub>

        ALIGN   4

        n_char          <gen_cl>,<clipped_output>,<loop_logic>,<sub>

if SPECIAL_CASE_DEV_ONC eq 1

        ALIGN   4

        one_char        <dev_onc>,<ega_onc>,<upd_dev loop_logic>,<inline>

        ALIGN   4

        two_char        <dev_onc>,<ega_onc>,<upd_dev loop_logic>,<inline>

        ALIGN   4

        three_char      <dev_onc>,<ega_onc>,<upd_dev loop_logic>,<inline>

        ALIGN   4

        four_char       <dev_onc>,<ega_onc>,<upd_dev loop_logic>,<sub>

        ALIGN   4

endif

if SPECIAL_CASE_DEV_TNC eq 1

        ALIGN   4

        one_char        <dev_tnc>,<ega_tnc>,<upd_dev loop_logic>,<inline>

        ALIGN   4

        two_char        <dev_tnc>,<ega_tnc>,<upd_dev loop_logic>,<inline>

        ALIGN   4

        three_char      <dev_tnc>,<ega_tnc>,<upd_dev loop_logic>,<inline>

        ALIGN   4

        four_char       <dev_tnc>,<ega_tnc>,<upd_dev loop_logic>,<sub>

        ALIGN   4


        ALIGN   4

endif

if SPECIAL_CASE_DEV_TC eq 1

        ALIGN   4

        one_char        <dev_tc>,<ega_tc>,<upd_dev loop_logic>,<sub>

        ALIGN   4


        ALIGN   4

        two_char        <dev_tc>,<ega_tc>,<upd_dev loop_logic>,<sub>

        ALIGN   4

        three_char      <dev_tc>,<ega_tc>,<upd_dev loop_logic>,<sub>

        ALIGN   4

        four_char       <dev_tc>,<ega_tc>,<upd_dev loop_logic>,<sub>

        ALIGN   4

endif

if SPECIAL_CASE_BM_OBWNC eq 1

        ALIGN   4

        one_char        <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        two_char        <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        three_char      <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        four_char       <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

endif

if SPECIAL_CASE_BM_OWBNC eq 1

        ALIGN   4

        one_char        <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        two_char        <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        three_char      <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        four_char       <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

endif

if SPECIAL_CASE_BM_TBNC eq 1

        ALIGN   4

        one_char        <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        two_char        <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        three_char      <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        four_char       <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

endif

if SPECIAL_CASE_BM_TWNC eq 1

        ALIGN   4

        one_char        <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        two_char        <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        three_char      <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

        four_char       <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>

        ALIGN   4

endif

SmartPro        ENDP

page
        end
