;*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 = SMARTFIX.ASM
;*
;* DESCRIPTIVE NAME = Fixed pitch character output
;*
;*
;* VERSION      V2.0
;*
;* DATE         04/05/88
;*
;* DESCRIPTION  This module contains the routines for outputting fixed
;*              pitch characters only.
;*
;* FUNCTIONS    Public: cached_font_strblt
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   04/05/88                     Author:  Mitchell McLain [gssc!mmm]
;*   05/06/88                     Mitchell McLain [gssc!mmm] Added in support
;*                                for proportional and ABC-spaced text.
;*   05/09/88                     Mitchell McLain [gssc!mmm] Added in support
;*                                for char_extra spacing and width vector.
;*   09/24/88                     Mitchell McLain [gssc!mmm] Fixed
;*                                proportional_display_loop to check for 0-width
;*                                characters.
;*   10/03/88                     Mitchell McLain [gssc!mmm] Now correctly masks
;*                                off insignficant X1 and Y1 bits to the 8514.
;*   08/27/90                     rajivg: added support for improved font cache.
;*   02/08/93              61121  Only display characters if the
;*                                X coordinate is between 0 and 7ff.
;*
;*
;*****************************************************************************/


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

        externNP    prepare_for_overlap

sBegin  Code
        assumes cs,Code

        externW  CodeData
        externW  CacheData

;/***************************************************************************
;*
;* FUNCTION NAME = cached_font_strblt
;*
;* DESCRIPTION   =
;*
;*     Overall logic for displaying text to the 8514 screen in a font that has
;*     been cached.  This is a separate path because accessing the hardware is
;*     nothing like accessing a bitmap, and the hardware can be used
;*     advantageously when displaying text to the screen.
;*
;*     Registers Destroyed:
;*           All
;*
;* INPUT         = Stack frame as defined in STRBLT8.INC
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

define_frame    cached_font_strblt
cBegin  <nogen>

        mov     al,accel                ;Save the actual state of the
        mov     bl,al                   ;  IS_OPAQUE flag since the
        and     al,IS_OPAQUE            ;  prepare_for_overlap code may
        or      wc_flags,al             ;  alter it
        mov     ah,excel                ;Only set text visible once a string
        and     ah,not TEXT_VISIBLE     ; is actually displayed
        mov     excel,ah

        test    bl,IS_OPAQUE            ;If transparent mode, then no
        jz      @F                      ;  special work is required
        test    bl,(HAVE_WIDTH_VECT or HAVE_CHAR_EXTRA) ; No extra work if
        jz      @F                      ;  no width vector and no char extra.
        call    prepare_for_overlap     ;Massive preprocessing required

@@:


;/*
;**  Here's how it's going to be done:
;**
;**    1. Set the hardware clip rectangle.
;**    2. Set the hardware colors for text and background.
;**    3. Set the second operand source plus background and foreground writing
;**       modes.
;**    4. Loop through the text string, using the copy rectangle hardware
;**       command to display text from the font cached in offscreen memory.
;**
;**
;**  Set the hardware clip rectangle, using the clip rectangle on the stack
;**
;**  The text clip rectangle is different than the normal PM clip rectangle
;**  in terms of which edges are inclusive and which are exclusive.  In PM,
;**  the left and bottom edges are inclusive and the top and right edges
;**  are exclusive.  The text path, however, is based on         code, and
;**  in         the top and left edges are inclusive and the bottom and
;**  right edges are exclusive.  Set up the hardware clip rectangle with
;**  that in mind.
;*/

        WaitQ   6                       ; Wait for room on the 8514 queue

        mov     ax,clip.rcs_pts1.pts_x  ; Left edge (inclusive)
        or      ax,XMIN_2DECODE
        .errnz   XMIN_2DECODE and 0000111111111111b
        outwQ   XMIN

        mov     ax,clip.rcs_pts1.pts_y  ; Top edge (inclusive)
        or      ax,YMIN_2DECODE
        .errnz   YMIN_2DECODE and 0000111111111111b
        outwQ   YMIN

        mov     ax,clip.rcs_pts2.pts_x
        dec     ax                      ; Right edge (exclusive)
        or      ax,XMAX_2DECODE
        .errnz   XMAX_2DECODE and 0000111111111111b
        outwQ   XMAX

        mov     ax,clip.rcs_pts2.pts_y
        dec     ax                      ; Bottom edge (exclusive)
        or      ax,YMAX_2DECODE
        .errnz   YMAX_2DECODE and 0000111111111111b
        outwQ   YMAX


;/*
;**     Set the text (foreground) and background colors, using the color
;**     information on the local frame.
;*/

        xor     ah,ah                   ; Insure contents of AH
        mov     al,byte ptr colors[BACKGROUND]
        outwQ   COLOR_0                 ; Set background color
        mov     al,byte ptr colors[FOREGROUND]
        outwQ   COLOR_1                 ; Set foreground color


;/*
;**     Set the hardware writing modes.
;**
;**         BG = opaque or transparent, depending on "accel" IS_OPAQUE bit
;**         FG = opaque, XOR or OR, depending on "accel" IS_XOR_TEXT and
;**              IS_OR_TEXT bits
;*/

        WaitQ   7                       ; Wait for room on the input queue

        mov     bl,accel

;/*
;**        Background
;*/

        mov     al,FUNC_S               ; Assume opaque background
        shr     bl,1                    ; Opaque?
        .errnz  IS_OPAQUE shr 1
        jc      @F                      ; Yes, it's opaque
        mov     al,FUNC_D               ; Force transparent background
@@:     or      al,FUNC_2OP_COL0        ; BG color source is COLOR 0
        .errnz  FUNC_2OP_COL0 and 011111b
        outwQ   FUNCTION_0              ; Background mode to 8514

;/*
;**        Foreground
;*/

        mov     al,FUNC_S_XOR_D         ; Assume XOR foreground
        shr     bl,1                    ; XOR?
        .errnz  IS_XOR_TEXT shr 2
        jc      @F                      ; Yes
        mov     al,FUNC_S_OR_D          ; Assume OR foreground
        shr     bl,1                    ; OR?
        .errnz  IS_OR_TEXT shr 3
        jc      @F                      ; Yes
        mov     al,FUNC_S               ; Force opaque foreground
@@:     or      al,FUNC_2OP_COL1        ; FG color source is COLOR_1
        .errnz  FUNC_2OP_COL1 and 011111b
        outwQ   FUNCTION_1

;/*
;**     Other hardware setup:
;**
;**         Enable all planes for writing
;**         Set pattern source to be copy rectangle read phase
;**         Set up height of character rectangles
;*/

        outwQ   WRITE_ENABLE,0ffh       ; Enable all planes for writing

        outwQ   MODE,(MODE_2DECODE+MD_PS_COPY);Pattern source copy rect.

        mov     ax,lfd.font_height
        dec     ax                      ; Board wants 1 less than height
        or      ax,LY_2DECODE           ; Bits for secondary decode command
        outwQ   LY                      ; Inform board of height


;/*
;**     The first order of business is to determine whether or not there
;**     is a width vector to deal with.  If so, make a local copy on the
;**     stack, so it's available in the display loops below.
;*/

        mov     al,accel
        test    al,HAVE_WIDTH_VECT
        jz      @F

        lds     si,lp_dx                ; DS:SI -> width vector
        assumes ds,nothing

        mov     bx,ss
        mov     es,bx                   ; SS -> stack
        assumes es,nothing

        mov     cx,count                ; Number of entries in the width vector
        sub     sp,cx                   ; Make room for local copy of the
        sub     sp,cx                   ;   width vector (in bytes).
        mov     bx,cx                   ; Save count
        mov     di,sp                   ; ES:DI -> local copy of width vector
        cld
rep     movsw                           ; Copy width vector

@@:


;/*
;**     Following are the loops that display the text.  There are three
;**     paths:
;**
;**         Fixed pitch text
;**         Proportional text
;**         ABC-spaced text
;**
;**     The fixed pitch path is intended to be the fastest possible,
;**     with every clock tick squeezed out, so system text will display
;**     as fast as possible.
;**
;**     The proportional path is not much slower than the fixed pitch
;**     patch, but in order to squeeze out those clock ticks in the
;**     fixed pitch path, it was broken out.
;**
;**     The ABC-spaced path is the slowest, because it has to deal with
;**     A spacing and C spacing that neither of the other two paths do.
;**
;**     Each of these paths in turn has a separate subpath that deals
;**     with extra character spacing and the presence of a width vector.
;*/

;/*
;**  Here's what the board will need to know for each character of the text
;**  string to be displayed:
;**
;**    (X0,Y0) - location of character in the offscreen font cache
;**    The plane from which to read the character
;**    LX,LY   - the dimensions of the character cell (LY already sent to 8514)
;**    (X1,Y1) - where the character is to be displayed onscreen
;**    The command indicating what the board should do:
;**        Copy Rectangle
;**        Using fixed data
;**        Increment X and Y as command proceeds
;**        Access the planes during the write phase of the command
;**        Write four pixels at-a-time
;**        Enable write access to the planes
;*/


;/*
;**     At this point:
;**
;**         AL contains the "accel" flag bits
;**         SP -> local copy of width vector, if width vector exists
;*/

        mov     cx,count
        lds     si,lp_string            ; DS:SI -> our string
        assumes ds,nothing

        mov     es,CacheData
        assumes es,nothing

        test    al,FIXED_PITCH          ; Fixed pitch text?
        jnz     @F                      ; Yes
        jmp     cfs_not_fixed_pitch     ; No

@@:     test    al,(HAVE_WIDTH_VECT or HAVE_CHAR_EXTRA)
        jnz     cfs_fixed_extra_display


;/*
;**     Display fixed pitch text.  Do not account for extra character
;**     spacing or the width vector.  Just put the text on the screen
;**     as fast as possible.  Make it scream!
;*/

        lodsw                           ; First character of the string
        mov     bx,ax                   ; Use BX as an index
        shl     bx,3                    ; Index of HW_FONT_ENTRIES to use
        add     bx,offFont
        .errnz  (size HW_FONT_ENTRIES) - 8
        mov     ax,es:[bx].hwfe_Width ; This char's width is also font's
        dec     ax                      ; 8514 wants it minus 1
        outwQ   LX

        push    bp                      ; Save stack frame, freeing BP for use
        push    offFont                 ; save it on stack to retrieve it easily
        mov     di,y                    ; Destination Y of string
        mov     bp,x                    ; Destination X of string

        public  cfs_fixed_display_loop  ; For debugging
cfs_fixed_display_loop:
        WaitQ   6                       ; Wait for space in the queue

        outwQ   X0,es:[bx].hwfe_StartX
        outwQ   Y0,es:[bx].hwfe_StartY
        outwQ   READ_ENABLE,es:[bx].hwfe_Plane

                                        ; Defect #61121 (start)
        cmp     bp,0h                   ; Is X coord negative
        jl      get_next_char           ; yes
        mov     ax,XY_SIGNIFICANT       ; Calculate max positive X coord
        sub     ax,es:[bx].hwfe_Width
        cmp     bp,ax                   ; Is X coord beyond max
        jg      get_next_char           ; yes
                                        ; Defect #61121 (end)

        mov     ax,bp                   ; AX = destination X
;        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits.
        outwQ   X1                      ; Give board destination X of copy
        mov     ax,di                   ; AX = destination Y
        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits.
        outwQ   Y1                      ; Give board destination Y of copy
        outwQ   CMD_FLAGS,<CMD_C_CRECT+CMD_FV_FIX+CMD_DY+CMD_DX+CMD_MA_ACCESS+\
                           CMD_PA_FOUR+CMD_RW_W>; Draw the character

get_next_char:                          ; Defect #61121
        add     bp,es:[bx].hwfe_Width; Destination X of next character
        lodsw                           ; Get a character
        mov     bx,ax                   ; Use BX as an index
        shl     bx,3                    ; Index of HW_FONT_ENTRIES to use
        pop     ax                      ; pop into ax the offFont value
        push    ax
        add     bx,ax
        .errnz  (size HW_FONT_ENTRIES) - 8
        loop    cfs_fixed_display_loop

        pop     ax
        pop     bp                      ; Restore stack frame
        jmp     cfs_return


;/*
;**     Display fixed pitch text.  Account for any extra character
;**     spacing plus the width vector (if present).
;*/

cfs_fixed_extra_display:
        WaitQ   -1                      ; Rewind WaitQ macro for outwQ LX
        lodsw                           ; First character of the string
        mov     bx,ax                   ; Use BX as an index
        shl     bx,3                    ; Index of HW_FONT_ENTRIES to use
        add     bx,offFont
        .errnz  (size HW_FONT_ENTRIES) - 8
        mov     ax,es:[bx].hwfe_Width ; This char's width is also font's
        dec     ax                      ; 8514 wants it minus 1
        outwQ   LX

        mov     di,x                    ; Destination X

        public  cfs_fixed_extra_display_loop ; For debugging
cfs_fixed_extra_display_loop:
        WaitQ   6                       ; Wait for space in the queue

        outwQ   X0,es:[bx].hwfe_StartX
        outwQ   Y0,es:[bx].hwfe_StartY
        outwQ   READ_ENABLE,es:[bx].hwfe_Plane
        lea     ax,[di+512]
        test    ax,not XY_SIGNIFICANT
        jnz     cfsf_skip_char          ; out of hardware addr range  PTR6256
        mov     ax,di
        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits
        outwQ   X1                      ; Give board destination X of copy
        mov     ax,y                    ; AX = destination Y
        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits
        outwQ   Y1                      ; Give board destination Y of copy
        outwQ   CMD_FLAGS,<CMD_C_CRECT+CMD_FV_FIX+CMD_DY+CMD_DX+CMD_MA_ACCESS+\
                           CMD_PA_FOUR+CMD_RW_W>; Draw the character
cfsf_skip_char:
        test    accel,HAVE_WIDTH_VECT
        jz      @F
        pop     ax                      ; Width from width vector
        add     di,ax
        jmp     short cfs_fixed_extra_added

@@:     add     di,es:[bx].hwfe_Width; Destination X of next character
        add     di,char_extra           ; add extra if need!
                                        ; not needed if WIDTH VECTOR.
cfs_fixed_extra_added:
        lodsw                           ; First character of the string
        mov     bx,ax                   ; Use BX as an index
        shl     bx,3                    ; Index of HW_FONT_ENTRIES to use
        add     bx,offFont
        .errnz  (size HW_FONT_ENTRIES) - 8
        loop    cfs_fixed_extra_display_loop

        jmp     cfs_return



        public  cfs_not_fixed_pitch     ; For debugging
cfs_not_fixed_pitch:
        test    al,ABC_FONT             ; ABC-spaced text?
        jnz     cfs_abc_text            ; Yes


;/*
;**     Display proportionally-spaced text.  Account for any extra
;**     character spacing as well as a width vector (if present).
;*/

        mov     di,x                    ; Destination X of string

        public  cfs_proportional_display_loop
cfs_proportional_display_loop:
        WaitQ   7                       ; Wait for space in the queue

        lodsw                           ; Get a character
        mov     bx,ax                   ; Use BX as an index
        shl     bx,3                    ; Index of HW_FONT_ENTRIES to use
        add     bx,offFont
        .errnz  (size HW_FONT_ENTRIES) - 8
        outwQ   X0,es:[bx].hwfe_StartX
        outwQ   Y0,es:[bx].hwfe_StartY
        outwQ   READ_ENABLE,es:[bx].hwfe_Plane
        mov     ax,es:[bx].hwfe_Width
        mov     bx,ax                   ; Save full width
        dec     ax                      ; 8514 wants width minus 1
        js      cfsp_skip_char          ; char has zero width
        outwQ   LX
        lea     ax,[di+512]
        test    ax,not XY_SIGNIFICANT
        jnz     cfsp_skip_char          ; out of hardware addr range  PTR6256
        mov     ax,di
        and     ax,XY_SIGNIFICANT       ; Mask off undefined bits
        outwQ   X1                      ; Give board destination X of copy
        mov     ax,y                    ; AX = destination Y
        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits
        outwQ   Y1                      ; Give board destination Y of copy
        outwQ   CMD_FLAGS,<CMD_C_CRECT+CMD_FV_FIX+CMD_DY+CMD_DX+CMD_MA_ACCESS+\
                           CMD_PA_FOUR+CMD_RW_W>
cfsp_skip_char:
        test    accel,HAVE_WIDTH_VECT
        jz      @F
        pop     ax                      ; Width from vector table
        add     di,ax                   ; Next X
        jmp     short cfs_proportional_added_extra

@@:     add     di,bx                   ; Add char width for next X
        add     di,char_extra           ; Note: do not add extra if width vector
cfs_proportional_added_extra:
        loop    cfs_proportional_display_loop

        jmp     cfs_return



;/*
;**     Display ABC-spaced text.  Account for any extra character
;**     spacing and the width vector (if present).
;*/

        public  cfs_abc_text            ; For debugging
cfs_abc_text:
        mov     di,x                    ; Destination X of string

        public  cfs_abc_display_loop
cfs_abc_display_loop:
        WaitQ   7                       ; Wait for space in the queue

        lodsw                           ; Get a character
        add     ax,ax                   ; * 2
        add     ax,ax                   ; * 4
        mov     bx,ax                   ; Use BX as an index
        add     ax,ax                   ; * 8
        add     bx,ax                   ; * 12
        add     bx,offFont
        .errnz  (size HW_ABC_FONT_ENTRIES) - 12

;/*
;**  Draw the character
;*/

        WaitQ   8
        add     di,es:[bx].hwabc_a_space; Add in left-side space
        mov     ax,es:[bx].hwabc_b_space; Character width
        dec     ax                      ; 8514 wants width minus 1
        js      @F                      ; Nothing displayed if zero width
        outwQ   LX                      ; Inform board of copy width
        outwQ   X0,es:[bx].hwabc_StartX
        outwQ   Y0,es:[bx].hwabc_StartY
        outwQ   READ_ENABLE,es:[bx].hwabc_Plane
        lea     ax,[di+512]
        test    ax,not XY_SIGNIFICANT
        jnz     @F                      ; out of hardware addr range   PTR6256
        mov     ax,di
        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits
        outwQ   X1                      ; Give board destination X of copy
        mov     ax,y                    ; AX = destination Y
        and     ax,XY_SIGNIFICANT       ; Mask off insignificant bits
        outwQ   Y1                      ; Give board destination Y of copy
        outwQ   CMD_FLAGS,<CMD_C_CRECT+CMD_FV_FIX+CMD_DY+CMD_DX+CMD_MA_ACCESS+\
                           CMD_PA_FOUR+CMD_RW_W> ; Copy from offscreen to on

@@:     test    accel,HAVE_WIDTH_VECT
        jz      @F
        sub     di,es:[bx].hwabc_a_space  ; subtract last a_space
        pop     ax                        ; Width from vector table
        add     di,ax
        jmp     short cfs_abc_added_extra

@@:     add     di,es:[bx].hwabc_b_space; Next X is this char's width

        add     di,es:[bx].hwabc_c_space  ;   plus right-side space
        add     di,char_extra             ; Account for extra spacing
cfs_abc_added_extra:                      ; Note: do not add extra if width vector
        nloop   cfs_abc_display_loop

        assumes es,nothing
        assumes ds,nothing

cfs_return:
        or      excel,TEXT_VISIBLE      ;Show something was displayed

        mov     al,wc_flags
        test    al,WC_SET_LR            ;If we stepped backwards, we'll
        jz      cfs_really_return       ;  have to restore the real lhs
        mov     bx,wc_opaque_lhs        ;  and rhs in case we have an
        mov     text_bbox.rcs_pts1.pts_x,bx ;  opaque rectangle.
        mov     bx,wc_opaque_rhs
        mov     text_bbox.rcs_pts2.pts_x,bx

cfs_really_return:
        and     al,IS_OPAQUE            ;Restore IS_OPAQUE incase prepare_for-
        or      accel,al                ;  overlap code cleared it, else the
                                        ;  opaque rectangle may overwrite our
                                        ;  text.
        retn                            ; The way out

cEnd    <nogen>
sEnd    Code
        end
