;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = 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    Public: gen_nc_one_char
;*                      gen_nc_two_char
;*                      gen_nc_three_char
;*                      gen_nc_four_char
;*                      gen_nc_n_char
;*                      gen_nc_n_char
;*                      gen_nc_n_char
;*                      gen_nc_n_char
;*                      gen_cl_one_char
;*                      gen_cl_two_char
;*                      gen_cl_three_char
;*                      gen_cl_four_char
;*                      gen_cl_n_char
;*                      gen_cl_n_char
;*                      gen_cl_n_char
;*                      gen_cl_n_char
;*
;*
;*                if SPECIAL_CASE_DEV_ONC
;*                      dev_onc_one_char
;*                      dev_onc_two_char
;*                      dev_onc_three_char
;*                      dev_onc_four_char
;*                endif
;*
;*                if SPECIAL_CASE_DEV_TNC
;*                      dev_tnc_one_char
;*                      dev_tnc_two_char
;*                      dev_tnc_three_char
;*                      dev_tnc_four_char
;*                endif
;*
;*                if SPECIAL_CASE_DEV_TC
;*                      dev_tc_one_char
;*                      dev_tc_two_char
;*                      dev_tc_three_char
;*                      dev_tc_four_char
;*                endif
;*
;*                if SPECIAL_CASE_BM_OBWNC
;*                      bm_obwnc_one_char
;*                      bm_obwnc_two_char
;*                      bm_obwnc_three_char
;*                      bm_obwnc_four_char
;*                endif
;*
;*                if SPECIAL_CASE_BM_OWBNC
;*                      bm_owbnc_one_char
;*                      bm_owbnc_two_char
;*                      bm_owbnc_three_char
;*                      bm_owbnc_four_char
;*                endif
;*
;*                if SPECIAL_CASE_BM_TBNC
;*                      bm_tbnc_one_char
;*                      bm_tbnc_two_char
;*                      bm_tbnc_three_char
;*                      bm_tbnc_four_char
;*                endif
;*
;*                if SPECIAL_CASE_BM_TWNC
;*                      bm_twnc_one_char
;*                      bm_twnc_two_char
;*                      bm_twnc_three_char
;*                      bm_twnc_four_char
;*                endif
;*
;* 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]
;*   08/25/87                     Bob Grudem [bobgru] Added fixed pitch
;*                                entry point to consolidate it with the
;*                                proportional width case.
;*                                Bob Grudem [bobgru] Rewrote assignment
;*                                of bit-gathering and drawing functions.
;       Tue 25-Aug-1987 17:00:00 -by-  Bob Grudem [bobgru]
;       Rewrote assignment of bit-gathering and drawing functions.
;*
;*****************************************************************************/

        .xlist
        include cmacros.inc
INCL_GRE_CLIP           equ     1
INCL_FONTFILEFORMAT     equ     1
        include pmgre.inc
        include driver.inc
        include fontseg.inc
        include 8514.inc
        include 8514mem.inc
        include strblt8.inc
        .list

        externA SCREEN_CBSCAN

;       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


;/*
;**       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     word ptr -2

wwidth1 equ     byte ptr base - 0
pphase1 equ     byte ptr wwidth1 + 1
cchar1  equ     word ptr wwidth1 - 2

wwidth2 equ     byte ptr base - 4
pphase2 equ     byte ptr wwidth2 + 1
cchar2  equ     word ptr wwidth2 - 2

wwidth3 equ     byte ptr base - 8
pphase3 equ     byte ptr wwidth3 + 1
cchar3  equ     word ptr wwidth3 - 2

wwidth4 equ     byte ptr base - 12
pphase4 equ     byte ptr wwidth4 + 1
cchar4  equ     word ptr wwidth4 - 2
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     di                      ;;  did a stosb, adjust for it
endif
        add     di,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
        add     di,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

        assumes ds,nothing              ;;Set the assumptions now
        assumes es,nothing
        assumes ss,ss_variables

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

loop_logic      &macro
        inc     dx                      ;;Next scan of font
        dec     ss_height               ;;Loop until all chars output
        jnz     name&_n_char_outer_loop
        pop     bp                      ;;BP = frame pointer
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,cell_adjust
        ret
        &endm

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

long_loop_logic &macro
        inc     dx                      ;;Next scan of font
        dec     ss_height               ;;Loop until all chars output
        jz      name&_n_char_exit
        jmp     name&_n_char_outer_loop
name&_n_char_exit:
        pop     bp                      ;;BP = frame pointer
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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 proc near                  ;;  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 already 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 proc near                  ;;    define start of setup proc
  endif                                 ;;  endif
        call    get_column_width        ;;  Calculate the width of the column
        mov     ss_height,ax            ;;  save # scans in character
  if genflag and 10b                    ;;  if generating setup procedure
        pop     ax                      ;;    get return address
  endif                                 ;;  endif
        mov     ss_num_chars,cl         ;;  save # of characters - 1
        push    bp                      ;;  save frame pointer
        mov     bp,dx                   ;;  set buffer pointer
        xor     dx,dx                   ;;  index into font scan
  if genflag and 10b                    ;;  if generating setup procedure
        jmp     ax                      ;;    dispatch to caller
n_char_setup endp                       ;;    terminate the procedure
name&_n_char proc near                  ;;    define actual procedure
        call    n_char_setup            ;;    call setup code
  endif                                 ;;  endif
else                                    ;;else
name&_n_char proc near                  ;;    define actual procedure
        call    n_char_setup            ;;    call setup code
endif                                   ;;endif ;setup code

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

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

name&_n_char_inner_loop:
        mov     bx,[bp][si].cchar       ;;BX = offset of bits
        mov     al,[bx][di]
        mov     cl,[bp][si].wwidth      ;;CL = width
        shl     ax,cl
        sub     si,4                    ;;--> next char
        dec     ch
        jnz     name&_n_char_inner_loop
        mov     bx,[bp][si].cchar       ;;BX = offset of bits
        mov     al,[bx][di]
        mov     cl,[bp][si].pphase      ;;CL = phase
        shr     ax,cl
        xchg    dx,di                   ;;DI = dest ptr
        output  <update>                ;;Macro to do whatever for outputting
name&_n_char  endp
        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

        assumes ds,nothing              ;;Set the assumptions now
        assumes es,nothing
        assumes ss,ss_variables

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

loop_logic      &Macro
        dec     ss_height
        jnz     name&_four_char_loop
        pop     bp                      ;;BP = frame pointer
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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
name&_four_char_exit:
        pop     bp                      ;;BP = frame pointer
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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 proc near               ;;  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 already 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 proc near               ;;    define start of setup proc
  endif                                 ;;  endif
        call    get_column_width        ;;  Calculate the width of the column
        mov     ss_height,ax            ;;  save # scans in character
  if genflag and 10b                    ;;  if generating setup procedure
        pop     ax                      ;;    get return address
  endif                                 ;;  endif
        push    bp                      ;;  save frame pointer
        mov     bp,dx                   ;;  --> buffer
        mov     dl,[bp].wwidth3         ;;
        mov     dh,[bp].pphase4         ;;
        mov     ss_phases,dx            ;;
        mov     cl,[bp].wwidth1         ;;
        mov     ch,[bp].wwidth2         ;;
        mov     si,[bp].cchar4          ;;  4th character so we can lodsb
        mov     bx,[bp].cchar1          ;;
        mov     dx,[bp].cchar3          ;;
        mov     bp,[bp].cchar2          ;;
        sub     bx,si                   ;;  compute deltas
        sub     bp,si                   ;;
        sub     dx,si                   ;;
  if genflag and 10b                    ;;  if generating setup procedure
        jmp     ax                      ;;    dispatch to caller
four_char_setup endp                    ;;    terminate the procedure
name&_four_char proc near               ;;    define actual procedure
        call    four_char_setup         ;;    call setup code
  endif                                 ;;  endif
else                                    ;;else
name&_four_char proc near               ;;    define actual procedure
        call    four_char_setup         ;;    call setup code
endif                                   ;;endif ;setup code

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

name&_four_char_loop:
        mov     al,[si][bx]
        shl     ax,cl
        mov     al,ds:[si][bp]
        xchg    cl,ch
        shl     ax,cl
        xchg    cl,ch
        xchg    cx,ss_phases
        xchg    bx,dx
        mov     al,[si][bx]
        xchg    bx,dx
        shl     ax,cl
        lodsb
        xchg    cl,ch
        shr     ax,cl
        xchg    cl,ch
        xchg    cx,ss_phases
        output  <update>                ;;Macro to do whatever for outputting
name&_four_char endp
        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

        assumes ds,nothing              ;;Set the assumptions now
        assumes es,nothing
        assumes ss,ss_variables

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

loop_logic      &macro
        dec     ss_height
        jnz     name&_three_char_loop
        pop     bp
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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
name&_three_char_exit:
        pop     bp
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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 proc near              ;;  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 already 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 proc near              ;;    define start of setup proc
  endif                                 ;;  endif
        call    get_column_width        ;;  Calculate the width of the column
        mov     ss_height,ax            ;;  save # scans in character
  if genflag and 10b                    ;;  if generating setup procedure
        pop     ax                      ;;    get return address
  endif                                 ;;  endif
        push    bp
        mov     bp,dx                   ;;  BP = buffer
        mov     dl,[bp].wwidth1         ;;
        mov     dh,[bp].wwidth2         ;;
        mov     ch,[bp].pphase3         ;;
        mov     si,[bp].cchar3          ;;
        mov     bx,[bp].cchar2          ;;
        mov     bp,[bp].cchar1          ;;
        sub     bx,si                   ;;
        sub     bp,si                   ;;
  if genflag and 10b                    ;;  if generating setup procedure
        jmp     ax                      ;;    dispatch to caller
three_char_setup endp                   ;;    terminate the procedure
name&_three_char proc near              ;;    define actual procedure
        call    three_char_setup        ;;    call setup code
  endif                                 ;;  endif
else                                    ;;else
name&_three_char proc near              ;;    define actual procedure
        call    three_char_setup        ;;    call setup code
endif                                   ;;endif ;setup code

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

name&_three_char_loop:
        mov     al,ds:[si][bp]
        mov     cl,dl
        shl     ax,cl
        mov     al,[si][bx]
        mov     cl,dh
        shl     ax,cl
        lodsb
        mov     cl,ch
        shr     ax,cl
        output  <update>                ;;Macro to do whatever for outputting
name&_three_char endp
        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

        assumes ds,nothing              ;;Set the assumptions now
        assumes es,nothing
        assumes ss,ss_variables

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

loop_logic      &macro
        dec     dx
        jnz     name&_two_char_loop
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,cell_adjust
        ret
        &endm

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

long_loop_logic &macro
        dec     dx
        jz      name&_two_char_exit
        jmp     name&_two_char_loop
name&_two_char_exit:
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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 proc near                ;;  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 already 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 proc near                ;;    define start of setup proc
  endif                                 ;;  endif
        call    get_column_width        ;;  Calculate the width of the column
        xchg    bp,dx                   ;;  BP = buffer, DX = font height
        mov     cl,[bp].wwidth1         ;;
        mov     ch,[bp].pphase2         ;;
        mov     bx,[bp].cchar1          ;;
        mov     si,[bp].cchar2          ;;
        mov     bp,dx                   ;;  restore frame pointer
        xchg    ax,dx                   ;;  set DX = font height
        sub     bx,si                   ;;  delta between the characters
  if genflag and 10b                    ;;  if generating setup procedure
        ret                             ;;    dispatch to caller
two_char_setup endp                     ;;    terminate the procedure
name&_two_char proc near                ;;    define actual procedure
        call    two_char_setup          ;;    call setup code
  endif                                 ;;  endif
else                                    ;;else
name&_two_char proc near                ;;    define actual procedure
        call    two_char_setup          ;;    call setup code
endif                                   ;;endif ;setup code

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

name&_two_char_loop:
        mov     al,[bx][si]
        shl     ax,cl
        xchg    cl,ch
        lodsb
        shr     ax,cl
        xchg    cl,ch
        output  <update>                ;;Macro to do whatever for outputting
name&_two_char endp
        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

        assumes ds,nothing              ;;Set the assumptions now
        assumes es,nothing
        assumes ss,ss_variables

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

loop_logic      &macro
        dec     dx
        jnz     name&_one_char_loop
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,cell_adjust
        ret
        &endm

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

long_loop_logic &macro
        dec     dx
        jz      name&_one_char_exit
        jmp     name&_one_char_loop
name&_one_char_exit:
        add     di,ss_column_width      ;;Point to next char data column
        dec     di                      ;;Point to last byte in current column
        sub     di,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 proc near                ;;  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 already 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 proc near                ;;    define start of setup proc
  endif                                 ;;  endif
        call    get_column_width        ;;  Calculate the width of the column
        xchg    dx,bp                   ;;  BP --> character buffer
        mov     si,[bp].cchar1          ;;  DS:SI = char1
        mov     cl,[bp].pphase1         ;;
        xchg    dx,bp                   ;;  BP --> frame
        xchg    ax,dx                   ;;  DX = clipped_font_height
  if genflag and 10b                    ;;  if generating setup procedure
        ret                             ;;    dispatch to caller
one_char_setup endp                     ;;    terminate the procedure
name&_one_char proc near                ;;    define actual procedure
        call    one_char_setup          ;;    call setup code
  endif                                 ;;  endif
else                                    ;;else
name&_one_char proc near                ;;    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>
name&_one_char endp
        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----------------------------------;
;** 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      es:[di],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      es:[di],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      es:[di],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     es:[di],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     es:[di],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     es:[di],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,es:[di]
        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,es:[di]
        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 es:[di],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 es:[di],0FFh
DRAW_ADJUST     = 0                     ;;STOSB isn't used
        update
        endm

page

sBegin  Code
        assumes cs,Code

;/*
;**       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   word
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl
        dw      CodeOFFSET gen_cl


special_case_non_clip_tables    label   word
if SPECIAL_CASE_BM_TBNC eq 1
        dw      CodeOFFSET bm_tbnc
        dw      CodeOFFSET bm_tbnc
else
        dw      CodeOFFSET gen_nc
        dw      CodeOFFSET gen_nc
endif
if SPECIAL_CASE_BM_TWNC eq 1
        dw      CodeOFFSET bm_twnc
        dw      CodeOFFSET bm_twnc
else
        dw      CodeOFFSET gen_nc
        dw      CodeOFFSET gen_nc
endif
if SPECIAL_CASE_BM_OBBNC eq 1
        dw      CodeOFFSET bm_obbnc
else
        dw      CodeOFFSET gen_nc
endif
if SPECIAL_CASE_BM_OBWNC eq 1
        dw      CodeOFFSET bm_obwnc
else
        dw      CodeOFFSET gen_nc
endif
if SPECIAL_CASE_BM_OWBNC eq 1
        dw      CodeOFFSET bm_owbnc
else
        dw      CodeOFFSET gen_nc
endif
if SPECIAL_CASE_BM_OWWNC eq 1
        dw      CodeOFFSET bm_owwnc
else
        dw      CodeOFFSET gen_nc
endif


gen_nc  label   word
        dw      CodeOFFSET gen_nc_one_char
        dw      CodeOFFSET gen_nc_two_char
        dw      CodeOFFSET gen_nc_three_char
        dw      CodeOFFSET gen_nc_four_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char

gen_cl  label   word
        dw      CodeOFFSET gen_cl_one_char
        dw      CodeOFFSET gen_cl_two_char
        dw      CodeOFFSET gen_cl_three_char
        dw      CodeOFFSET gen_cl_four_char
        dw      CodeOFFSET gen_cl_n_char
        dw      CodeOFFSET gen_cl_n_char
        dw      CodeOFFSET gen_cl_n_char
        dw      CodeOFFSET gen_cl_n_char

if SPECIAL_CASE_BM_OBWNC eq 1
bm_obwnc label word
        dw      CodeOFFSET bm_obwnc_one_char
        dw      CodeOFFSET bm_obwnc_two_char
        dw      CodeOFFSET bm_obwnc_three_char
        dw      CodeOFFSET bm_obwnc_four_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
endif

if SPECIAL_CASE_BM_OWBNC eq 1
bm_owbnc label word
        dw      CodeOFFSET bm_owbnc_one_char
        dw      CodeOFFSET bm_owbnc_two_char
        dw      CodeOFFSET bm_owbnc_three_char
        dw      CodeOFFSET bm_owbnc_four_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
endif

if SPECIAL_CASE_BM_TBNC eq 1
bm_tbnc label word
        dw      CodeOFFSET bm_tbnc_one_char
        dw      CodeOFFSET bm_tbnc_two_char
        dw      CodeOFFSET bm_tbnc_three_char
        dw      CodeOFFSET bm_tbnc_four_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
endif

if SPECIAL_CASE_BM_TWNC eq 1
bm_twnc label word
        dw      CodeOFFSET bm_twnc_one_char
        dw      CodeOFFSET bm_twnc_two_char
        dw      CodeOFFSET bm_twnc_three_char
        dw      CodeOFFSET bm_twnc_four_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_n_char
        dw      CodeOFFSET gen_nc_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
;** dw 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 word

        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_opaque_color
        dw      CodeOFFSET  bm_opaque_color
        dw      CodeOFFSET  bm_opaque_color
        dw      CodeOFFSET  bm_opaque_color


non_clipped_drawing_functions label word

        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_trans_color
        dw      CodeOFFSET  bm_opaque_color
        dw      CodeOFFSET  bm_opaque_color
        dw      CodeOFFSET  bm_opaque_color
        dw      CodeOFFSET  bm_opaque_color


mono_non_clipped_drawing_functions      label word

        dw      CodeOFFSET  bm_trans_black
        dw      CodeOFFSET  bm_trans_black
        dw      CodeOFFSET  bm_trans_white
        dw      CodeOFFSET  bm_trans_white
        dw      CodeOFFSET  bm_opaque_black_on_black
        dw      CodeOFFSET  bm_opaque_black_on_white
        dw      CodeOFFSET  bm_opaque_white_on_black
        dw      CodeOFFSET  bm_opaque_white_on_white
        dw      8 dup (0)

clipped_table_size = $ - clipped_drawing_functions

xor_clipped_drawing_functions label word

        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_opaque_color
        dw      CodeOFFSET  xor_bm_opaque_color
        dw      CodeOFFSET  xor_bm_opaque_color
        dw      CodeOFFSET  xor_bm_opaque_color


xor_non_clipped_drawing_functions label word

        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_trans_color
        dw      CodeOFFSET  xor_bm_opaque_color
        dw      CodeOFFSET  xor_bm_opaque_color
        dw      CodeOFFSET  xor_bm_opaque_color
        dw      CodeOFFSET  xor_bm_opaque_color


xor_mono_non_clipped_drawing_functions  label word

        dw      CodeOFFSET  xor_bm_trans_black
        dw      CodeOFFSET  xor_bm_trans_black
        dw      CodeOFFSET  xor_bm_trans_white
        dw      CodeOFFSET  xor_bm_trans_white
        dw      CodeOFFSET  bm_opaque_white_on_black
        dw      CodeOFFSET  bm_opaque_white_on_white
        dw      CodeOFFSET  bm_opaque_black_on_black
        dw      CodeOFFSET  bm_opaque_black_on_white
        dw      8 dup (0)

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

        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_opaque_color
        dw      CodeOFFSET  or_bm_opaque_color
        dw      CodeOFFSET  or_bm_opaque_color
        dw      CodeOFFSET  or_bm_opaque_color


or_non_clipped_drawing_functions label word

        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_trans_color
        dw      CodeOFFSET  or_bm_opaque_color
        dw      CodeOFFSET  or_bm_opaque_color
        dw      CodeOFFSET  or_bm_opaque_color
        dw      CodeOFFSET  or_bm_opaque_color


or_mono_non_clipped_drawing_functions   label word

        dw      CodeOFFSET  or_bm_trans_black
        dw      CodeOFFSET  or_bm_trans_black
        dw      CodeOFFSET  bm_trans_white
        dw      CodeOFFSET  bm_trans_white
        dw      CodeOFFSET  bm_opaque_black_on_black
        dw      CodeOFFSET  bm_opaque_black_on_white
        dw      CodeOFFSET  bm_opaque_white_on_black
        dw      CodeOFFSET  bm_opaque_white_on_white
or_clipped_table_size = $ - or_clipped_drawing_functions
        .errnz  or_clipped_table_size - xor_clipped_table_size + 16

page

define_frame    SmartPro
cBegin  nogen
cEnd    nogen

;/***************************************************************************
;*
;* FUNCTION NAME = get_column_width
;*
;* DESCRIPTION   = 
;*                 
;*       Calculate the width of the data column being output in order to        
;*       correctly update the destination pointer.                              
;*                 
;*       Registers Preserved:           
;*             AX,BX,CX,DX,SI,DI,DS,ES,BP
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = ss_column_width set 
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  get_column_width        ; Debugging, of course.
get_column_width    proc    near
        push    ax
        push    cx

        xchg    bp,ss_p_frame           ;get frame pointer

        mov     al,1                    ; Assume mono bitmap
        cmp     num_planes,0ffh         ; Color bitmap?
        jne     gcw_done                ; No.

        mov     ah,ss_clip_mask
        xor     al,al                   ; Will be the column count
        mov     cx,8                    ; Will look at 8 bits in clip_mask

gcw_count_loop:
        shl     ah,1                    ; A bit to display?
        adc     al,0                    ; Increment count if so.
        loop    gcw_count_loop

gcw_done:
        cbw                             ; Count is a word
        mov     ss_column_width,ax      ; Save column width for cell_adjust

        xchg    bp,ss_p_frame           ; Restore frame pointer
        pop     cx
        pop     ax
        ret
get_column_width    endp
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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables
bm_opaque_white_on_white_clip:
        mov     al,0FFh

bm_trans_white_clip:
        and     al,ss_clip_mask

bm_trans_white:
        or      es:[di],al

DRAW_ADJUST     = 0                     ;STOSB isn't used
        upd_bm  <ret>                   ;Will generate the ret


xor_bm_trans_white:
        xor     es:[di],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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables
        
        public bm_opaque_black_on_black_clip ;!!!
bm_opaque_black_on_black_clip:
        mov     al,0FFh

bm_trans_black_clip:
        and     al,ss_clip_mask

bm_trans_black:
        not     al
        and     es:[di],al

DRAW_ADJUST     = 0                     ;STOSB isn't used
        upd_bm  <ret>                   ;Will generate the ret

or_bm_trans_black:
        not     al
        or      es:[di],al

DRAW_ADJUST     = 0                     ;STOSB isn't used
        upd_bm  <ret>                   ;Will generate the ret

xor_bm_trans_black:
        not     al
        xor     es:[di],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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

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,es:[di]
        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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

bm_opaque_white_on_white:
        mov     al,0FFh
        jmpnext

bm_opaque_black_on_black:
        xor     al,al
        jmpnext stop
        stosb

DRAW_ADJUST     = 1                     ;STOSB is used
        upd_bm  <ret>                   ;Will generate the ret
page

;/***************************************************************************
;*
;* PRIVATE 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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  bm_trans_color_fix
        public  bm_trans_color
bm_trans_color_fix:
        push    dx                      ;put return address on stack

bm_trans_color:
        push    ax
        push    cx
        push    di

        xchg    bp,ss_p_frame           ;get frame pointer
        mov     ah,ss_clip_mask

        cmp     num_planes,0ffh         ; Going to a color bitmap?
        je      btc_color_bitmap        ; Yes.

        and     ah,al
        not     ah                      ; 0s to fg bits; 1s to bg bits
        and     es:[di],ah              ; Clear fg bits in dest; leave alone bg
        mov     ch,byte ptr ss_colors[FOREGROUND]
        ror     ch,1                    ;see if this color plane is used
        jnc     btc_done
        or      es:[di],al              ; Turn on fg bits in destination
        jmp     btc_done

;/*
;**   Display the character data column to a color bitmap.
;**
;**       AH = clip mask
;**       AL = character column bit pattern left aligned
;*/

btc_color_bitmap:
        mov     cl,8                    ; Always 8 source bits to worry about
        mov     ch,ah                   ; CH = clip mask
        mov     ah,byte ptr ss_colors[FOREGROUND]
        cmp     ch,0ffh                 ; Any clipping?
        jne     btc_clip_loop           ; Yes.

        xor     ch,ch                   ; CX = loop count

btc_loop:
        shl     al,1                    ; Foreground bit to carry flag?
        jnc     @F                      ; No, background pixel; do nothing.
        mov     es:[di],ah              ; Stuff foreground color
@@:     inc     di                      ; Next pixel
        loop    btc_loop
        jmp     short btc_done

btc_clip_loop:
        shl     ch,1                    ; Is this bit masked off?
        jnc     btc_drop_bit            ; Yes.

        shl     al,1                    ; Foregound bit to carry flag?
        jnc     @F                      ; No, background bit; do nothing.
        mov     es:[di],ah              ; Forground color to bitmap
@@:     inc     di                      ; Point to next byte in bitmap
        dec     cl                      ; One less bit to worry about
        jnz     btc_clip_loop
        jmp     short btc_done

btc_drop_bit:
        shl     al,1                    ; Drop the masked-off bit
        dec     cl                      ; One less bit to worry about
        jnz     btc_clip_loop

btc_done:
        xchg    bp,ss_p_frame           ;restore bp and ss_p_frame

        pop     di
        pop     cx
        pop     ax

DRAW_ADJUST = 0
        upd_bm <ret>                    ;Will generate the ret
page

;/***************************************************************************
;*
;* PRIVATE 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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  or_bm_trans_color_fix
        public  or_bm_trans_color
or_bm_trans_color_fix:
        push    dx                      ;put return address on stack

or_bm_trans_color:
        push    ax
        push    cx
        push    di

        xchg    bp,ss_p_frame           ;get frame pointer

        mov     ch,ss_clip_mask
        cmp     num_planes,0ffh         ; Destined for a color bitmap?
        je      obtc_color_bitmap

        and     al,ch                   ; Mask off unaffected bits
        mov     ch,byte ptr ss_colors[FOREGROUND]
        ror     ch,1                    ; Are the foreground bits on?
        jnc     obtc_done               ; No.
        or      es:[di],al              ; Yes, turn on foreground bits.
        jmp     short obtc_done         ; Only have to do it once


;/*
;**   Display the character data column to a color bitmap.
;**
;**       AL = character column bit pattern left aligned
;**       CH = clip mask
;*/

obtc_color_bitmap:
        mov     cl,8                    ; Always 8 source bits to worry about
        mov     ah,byte ptr ss_colors[FOREGROUND]
        cmp     ch,0ffh                 ; Any clipping?
        jne     obtc_color_clip_loop    ; Yes.

        xor     ch,ch                   ; CX = loop count

obtc_color_loop:
        shl     al,1                    ; Foreground bit to carry flag?
        jnc     @F                      ; No, background pixel; do nothing.
        mov     es:[di],ah              ; Stuff foreground color
@@:     inc     di                      ; Next pixel
        loop    obtc_color_loop
        jmp     short obtc_done

obtc_color_clip_loop:
        shl     ch,1                    ; Is this bit masked off?
        jnc     obtc_drop_bit           ; Yes.

        shl     al,1                    ; Foregound bit to carry flag?
        jnc     @F                      ; No, background bit; do nothing.
        or      es:[di],ah              ; Forground color to bitmap
@@:     inc     di                      ; Point to next byte in bitmap
        dec     cl                      ; One less bit to worry about
        jnz     obtc_color_clip_loop
        jmp     short obtc_done

obtc_drop_bit:
        shl     al,1                    ; Drop the masked-off bit
        dec     cl                      ; One less bit to worry about
        jnz     obtc_color_clip_loop

obtc_done:
        xchg    bp,ss_p_frame           ;restore bp and ss_p_frame

        pop     di
        pop     cx
        pop     ax

DRAW_ADJUST = 0
        upd_bm <ret>                    ;Will generate the ret


;/***************************************************************************
;*
;* PRIVATE 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
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  xor_bm_trans_color_fix
        public  xor_bm_trans_color
xor_bm_trans_color_fix:
        push    dx                      ;put return address on stack

xor_bm_trans_color:
        push    ax
        push    cx
        push    di

        xchg    bp,ss_p_frame           ;get frame pointer

        mov     ch,ss_clip_mask
        cmp     num_planes,0ffh         ; Going to a color bitmap?
        je      xbtc_color_bitmap       ; Yes.

        and     al,ch                   ; Mask off unaffected bits
        mov     ch,byte ptr ss_colors[FOREGROUND]
        ror     ch,1                    ; Are foreground bits on?
        jnc     xbtc_done               ; No.
        xor     es:[di],al              ; Yes, xor the bitmap.
        jmp     xbtc_done


;/*
;**   Display the character data column to a color bitmap.
;**
;**       AL = character column bit pattern left aligned
;**       CH = clip mask
;*/

xbtc_color_bitmap:
        mov     cl,8                    ; Always 8 source bits to worry about
        mov     ah,byte ptr ss_colors[FOREGROUND]
        cmp     ch,0ffh                 ; Any clipping?
        jne     xbtc_color_clip_loop    ; Yes.

        xor     ch,ch                   ; CX = loop count

xbtc_color_loop:
        shl     al,1                    ; Foreground bit to carry flag?
        jnc     @F                      ; No, background pixel; do nothing.
        xor     es:[di],ah              ; Stuff foreground color
@@:     inc     di                      ; Next pixel
        loop    xbtc_color_loop
        jmp     short xbtc_done

xbtc_color_clip_loop:
        shl     ch,1                    ; Is this bit masked off?
        jnc     xbtc_drop_bit           ; Yes.

        shl     al,1                    ; Foreground bit to carry flag?
        jnc     @F                      ; No, background bit; do nothing
        xor     es:[di],ah              ; Xor the bitmap
@@:     inc     di                      ; Point to next bye in bitmap
        dec     cl                      ; One less bit to worry about
        jnz     xbtc_color_clip_loop
        jmp     short xbtc_done

xbtc_drop_bit:
        shl     al,1                    ; Drop the masked-off bit
        dec     cl                      ; One less bit to worry about
        jnz     obtc_color_clip_loop

xbtc_done:
        xchg    bp,ss_p_frame           ;restore bp and ss_p_frame

        pop     di
        pop     cx
        pop     ax

DRAW_ADJUST = 0
        upd_bm <ret>                    ;Will generate the ret

page

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

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  bm_opaque_color_fix
        public  bm_opaque_color
bm_opaque_color_fix:
        push    dx                      ;put return address on stack

bm_opaque_color:
        push    ax
        push    bx
        push    cx
        push    di

        xchg    bp,ss_p_frame           ;get frame pointer

        mov     bx,ss_colors            ; BH = BG color; BL = FG color
        .errnz  FOREGROUND
        mov     ch,ss_clip_mask
        cmp     num_planes,0ffh         ; Going to a color bitmap?
        je      boc_color_bitmap        ; Yes.

        mov     bl,special_bm_opaque_color ; Special format (get_device_data)
        shr     bl,1                    ;set C to inversion mask
        sbb     ah,ah
        and     ah,al                   ;AH = 1 where we want NOT background
        shr     bl,1                    ;set C to background color
        sbb     cl,cl                   ;AH = background color (00 or FF)
        xor     cl,ah                   ;AH = destination byte
        mov     ah,es:[di]
        xor     ah,cl
        and     ah,ch
        xor     es:[di],ah              ;output byte to mono bitmap
        jmp     boc_done

;/*
;** Display the character data column to a color bitmap.
;**
;**     AL = character column bit pattern left aligned
;**     BH = bg color
;**     BL = fg color
;**     CH = clip mask
;**     ES:DI -> first byte to touch
;*/

boc_color_bitmap:
        mov     cl,8                    ; 8 source bits (maybe masked)
        cmp     ch,0ffh                 ; Any clipping?
        jne     boc_color_clip_loop     ; Yes.

        xor     ch,ch                   ; CX = loop count

boc_color_no_clip_loop:
        mov     ah,bl                   ; Assume it's a foreground bit
        shl     al,1                    ; Is it a foreground bit?
        jc      @F                      ; Yes.
        mov     ah,bh                   ; No, use bg color.
@@:     mov     es:[di],ah              ; Write the pixel
        inc     di                      ; Next pixel
        loop    boc_color_no_clip_loop
        jmp     short boc_done

boc_color_clip_loop:
        shl     ch,1                    ; This bit masked off?
        jnc     boc_drop_bit            ; Yes.

        mov     ah,bl                   ; Assume it's a foreground pixel
        shl     al,1                    ; Forground bit?
        jc      @F                      ; Yes.
        mov     ah,bh                   ; No, use bg color.
@@:     mov     es:[di],ah              ; Turn on the bitmap pixel
        inc     di                      ; Point to next bitmap byte
        dec     cl                      ; One less source bit to worry about
        jnz     boc_color_clip_loop
        jmp     short boc_done


boc_drop_bit:
        shl     al,1                    ; Drop bit that's masked off
        dec     cl                      ; One less source bit to worry about
        jnz     boc_color_clip_loop

boc_done:
        xchg    bp,ss_p_frame           ;restore bp and ss_p_frame

        pop     di
        pop     cx
        pop     bx
        pop     ax

DRAW_ADJUST = 0
        upd_bm <ret>                    ;Will generate the ret
page

;/***************************************************************************
;*
;* PRIVATE ROUTINES  or_bm_opaque_color_fix
;*                   or_bm_opaque_color
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      opaque, color bitmaps only, OR mix mode
;*                                                        
;*                Registers Preserved:           
;*                      AX, BX, CX, DI, BP 
;*                Registers Destroyed:           
;*                      NONE
;*
;* INPUT         = AL = character to output             
;*                 ES:DI --> destination byte           
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  or_bm_opaque_color_fix
        public  or_bm_opaque_color
or_bm_opaque_color_fix:
        push    dx                      ;put return address on stack

or_bm_opaque_color:
        push    ax
        push    bx
        push    cx
        push    di

        xchg    bp,ss_p_frame           ;get frame pointer

        mov     bx,ss_colors            ; BH = BG color; BL = FG color
        .errnz  FOREGROUND
        mov     ch,ss_clip_mask

;/*
;** Display the character data column to a color bitmap.
;**
;**     AL = character column bit pattern left aligned
;**     BH = bg color
;**     BL = fg color
;**     CH = clip mask
;**     ES:DI -> first byte to touch
;*/

        mov     cl,8                    ; 8 source bits (maybe masked)
        cmp     ch,0ffh                 ; Any clipping?
        jne     or_boc_color_clip_loop     ; Yes.

        xor     ch,ch                   ; CX = loop count

or_boc_color_no_clip_loop:
        mov     ah,bl                   ; Assume it's a foreground bit
        shl     al,1                    ; Is it a foreground bit?
        jc      @F                      ; Yes.
        mov     ah,bh                   ; No, use bg color.
@@:     or      es:[di],ah              ; Write the pixel
        inc     di                      ; Next pixel
        loop    or_boc_color_no_clip_loop
        jmp     short or_boc_done

or_boc_color_clip_loop:
        shl     ch,1                    ; This bit masked off?
        jnc     or_boc_drop_bit         ; Yes.

        mov     ah,bl                   ; Assume it's a foreground pixel
        shl     al,1                    ; Forground bit?
        jc      @F                      ; Yes.
        mov     ah,bh                   ; No, use bg color.
@@:     or      es:[di],ah              ; Turn on the bitmap pixel
        inc     di                      ; Point to next bitmap byte
        dec     cl                      ; One less source bit to worry about
        jnz     or_boc_color_clip_loop
        jmp     short or_boc_done


or_boc_drop_bit:
        shl     al,1                    ; Drop bit that's masked off
        dec     cl                      ; One less source bit to worry about
        jnz     or_boc_color_clip_loop

or_boc_done:
        xchg    bp,ss_p_frame           ;restore bp and ss_p_frame

        pop     di
        pop     cx
        pop     bx
        pop     ax

DRAW_ADJUST = 0
        upd_bm <ret>                    ;Will generate the ret
        page

;/***************************************************************************
;*
;* PRIVATE ROUTINES  xor_bm_opaque_color_fix
;*                   xor_bm_opaque_color
;*
;* DESCRIPTION   = Standard bitmap drawing functions for: 
;*                                                        
;*                      opaque, color bitmaps only, XOR mix mode
;*                                                        
;*                Registers Preserved:           
;*                      AX, BX, CX, DI, BP 
;*                Registers Destroyed:           
;*                      NONE
;*
;* INPUT         = AL = character to output             
;*                 ES:DI --> destination byte           
;*                 
;* OUTPUT        = ES:DI --> same byte, next scan 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  xor_bm_opaque_color_fix
        public  xor_bm_opaque_color
xor_bm_opaque_color_fix:
        push    dx                      ;put return address on stack

xor_bm_opaque_color:
        push    ax
        push    bx
        push    cx
        push    di

        xchg    bp,ss_p_frame           ;get frame pointer

        mov     bx,ss_colors            ; BH = BG color; BL = FG color
        .errnz  FOREGROUND
        mov     ch,ss_clip_mask

;/*
;** Display the character data column to a color bitmap.
;**
;**     AL = character column bit pattern left aligned
;**     BH = bg color
;**     BL = fg color
;**     CH = clip mask
;**     ES:DI -> first byte to touch
;*/

        mov     cl,8                    ; 8 source bits (maybe masked)
        cmp     ch,0ffh                 ; Any clipping?
        jne     xor_boc_color_clip_loop     ; Yes.

        xor     ch,ch                   ; CX = loop count

xor_boc_color_no_clip_loop:
        mov     ah,bl                   ; Assume it's a foreground bit
        shl     al,1                    ; Is it a foreground bit?
        jc      @F                      ; Yes.
        mov     ah,bh                   ; No, use bg color.
@@:     xor     es:[di],ah              ; Write the pixel
        inc     di                      ; Next pixel
        loop    xor_boc_color_no_clip_loop
        jmp     short xor_boc_done

xor_boc_color_clip_loop:
        shl     ch,1                    ; This bit masked off?
        jnc     xor_boc_drop_bit        ; Yes.

        mov     ah,bl                   ; Assume it's a foreground pixel
        shl     al,1                    ; Forground bit?
        jc      @F                      ; Yes.
        mov     ah,bh                   ; No, use bg color.
@@:     xor     es:[di],ah              ; Turn on the bitmap pixel
        inc     di                      ; Point to next bitmap byte
        dec     cl                      ; One less source bit to worry about
        jnz     xor_boc_color_clip_loop
        jmp     short xor_boc_done


xor_boc_drop_bit:
        shl     al,1                    ; Drop bit that's masked off
        dec     cl                      ; One less source bit to worry about
        jnz     xor_boc_color_clip_loop

xor_boc_done:
        xchg    bp,ss_p_frame           ;restore bp and ss_p_frame

        pop     di
        pop     cx
        pop     bx
        pop     ax

DRAW_ADJUST = 0
        upd_bm <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:           
;*                      DX,BP,DS,ES          
;*                Registers Destroyed:           
;*                      AX,BX,CX,SI,DI,FLAGS     
;*
;* INPUT         = BL = accel                           
;*                 AH = excel                           
;*                 SS = ring 2 stack                  
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing
        assumes ss,ss_variables

        public  preset_pro_text
preset_pro_text proc    near

ifdef   FIREWALLS

;/*
;**       This routine should be called only when text is going to an
;**       offscreen bitmap.
;*/

        test    ah,IS_DEVICE            ; Going to the screen?
        jz      @F                      ; No (which is good).
        rip     text,<preset_pro_text called for onscreen text, a no-no.>
@@:
endif

        mov     ss_p_frame,bp
        mov     cx,next_scan
        mov     ss_next_scan,cx
        mov     cx,colors
        mov     ss_colors,cx

;/*
;**       Accumulate foreground/background colors, and opaque/transparent
;**       mode to determine which drawing functions will be used.
;*/

        and     bx,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
        shl     bx,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 monochrome bitmaps.  For color bitmaps, and
;**       all clipped cases, we'll get the drawing function from the
;**       general case table.
;*/

        mov     si,bx
        xor     dx,dx
        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     dx,clipped_table_size
        shl     dx,cl
        add     bx,dx

preset_pro_no_x_or:
        mov     ax,non_clipped_drawing_functions[bx]
        cmp     num_planes,1            ; Going to a mono bitmap?
        jne     preset_pro_text_standard_func ; No.

        mov     ax,mono_non_clipped_drawing_functions[bx]

preset_pro_text_lookup_func:
        mov     bx,si
        mov     si,special_case_non_clip_tables[bx]
        mov     di,special_case_clip_tables[bx]

preset_pro_text_have_func:
        mov     non_clipped_table,si
        mov     clipped_table,di
        mov     ss_draw,ax

        mov     ax,clipped_drawing_functions[bx]
        mov     ss_draw_clipped,ax

        ret


preset_pro_text_standard_func:
        mov     si,CodeOFFSET gen_nc
        mov     di,CodeOFFSET gen_cl
        jmp     short preset_pro_text_have_func

preset_pro_text endp
        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.
;*/

        one_char        <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>
        two_char        <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>
        three_char      <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>
        four_char       <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>
        n_char          <gen_nc>,<non_clipped_output>,<loop_logic>,<sub>

        one_char        <gen_cl>,<clipped_output>,<loop_logic>,<sub>
        two_char        <gen_cl>,<clipped_output>,<loop_logic>,<sub>
        three_char      <gen_cl>,<clipped_output>,<loop_logic>,<sub>
        four_char       <gen_cl>,<clipped_output>,<loop_logic>,<sub>
        n_char          <gen_cl>,<clipped_output>,<loop_logic>,<sub>

if SPECIAL_CASE_BM_OBWNC eq 1
        one_char        <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>
        two_char        <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>
        three_char      <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>
        four_char       <bm_obwnc>,<obwnc>,<upd_bm loop_logic>,<sub>
endif

if SPECIAL_CASE_BM_OWBNC eq 1
        one_char        <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>
        two_char        <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>
        three_char      <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>
        four_char       <bm_owbnc>,<owbnc>,<upd_bm loop_logic>,<sub>
endif

if SPECIAL_CASE_BM_TBNC eq 1
        one_char        <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>
        two_char        <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>
        three_char      <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>
        four_char       <bm_tbnc>,<tbnc>,<upd_bm loop_logic>,<sub>
endif

if SPECIAL_CASE_BM_TWNC eq 1
        one_char        <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>
        two_char        <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>
        three_char      <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>
        four_char       <bm_twnc>,<twnc>,<upd_bm loop_logic>,<sub>
endif
page
sEnd    Code
        end
