;************************************************************************ ;* Copyright 1999, Caldera Thin Clients, Inc. * ;* This software is licenced under the GNU Public License. * ;* Please see LICENSE.TXT for further information. * ;* * ;* Historical Copyright * ;* * ;* * ;* * ;* Copyright (c) 1987, Digital Research, Inc. All Rights Reserved. * ;* The Software Code contained in this listing is proprietary to * ;* Digital Research, Inc., Monterey, California and is covered by U.S. * ;* and other copyright protection. Unauthorized copying, adaptation, * ;* distribution, use or display is prohibited and may be subject to * ;* civil and criminal penalties. Disclosure to others is prohibited. * ;* For the terms and conditions of software code use refer to the * ;* appropriate Digital Research License Agreement. * ;* * ;************************************************************************ include externs.a86 HORZ_OFF equ 2 cseg public text_blt public text_blt_special public txt_blt_op_branch public txt_blt_tran ega_seq_add equ 3c4h ;the ega sequencer add reg ega_seq_data equ 3c5h ;the ega sequencer data reg ega_wmapmask_reg equ 2 ;the write plane mask reg ega_graphic_add equ 3ceh ;the ega graphics add reg ega_graphic_data equ 3cfh ega_setres_reg equ 0 ;the ega plane set reset values ega_ensetres_reg equ 1 ;the ega plane set reset enable bits ega_datarot_reg equ 3 ;the ega data rotate register ega_rmapmask_reg equ 4 ;the ega plane read mask ega_mode_reg equ 5 ;the ega data source mode register ega_bitmask_reg equ 8 ;the ega bit mask register extrn txtblt_rep_rr:near extrn txtblt_tran_rr:near extrn txtblt_xor_rr_s:near extrn txtblt_itran_rr:near extrn txtblt_rep_rl:near extrn txtblt_tran_rl:near extrn txtblt_xor_rl_s:near extrn txtblt_itran_rl:near extrn box_plane_enable:near extrn box_ega_init:near ; Special effects masks. THICKEN equ 1h LIGHT equ 2h SKEW equ 4h UNDER equ 8h OUTLINE equ 10h SHADOW equ 20h ROTATE equ 0c0h ROT90 equ 040h ROT180 equ 080h ROT270 equ 0c0h ROTODD equ 040h ROTHIGH equ 080h SCALE equ 100h dseg public def_buf, txbuf1, txbuf2, buff_seg public sav_buf1, sav_buf2 public DELY ;font form height public FOFF ;pointer to font public FWIDTH ;form width of source form public FIR_CHR ;first ascii char in font public OFF_TBL ;pointer to font offset table public FONT_INF ;header for current font public fi_flags ;flags word for local font header extrn CONTRL:word extrn INTIN:word extrn PTSIN:word extrn FG_BP_1:word extrn NEXT_PAT:word extrn patmsk:word extrn patptr:word extrn SOLID:word extrn DITHER:word extrn DITHRMSK:word extrn X1:word extrn X2:word extrn Y1:word extrn Y2:word extrn SPECIAL:word extrn T_SCLSTS:word extrn MONO_STA:word extrn XACC_DDA:word extrn DDA_INC:word extrn WRT_MODE:word extrn TEXT_BP:word extrn MAP_COL:word extrn LN_MASK:word extrn plane_loop_count:byte if ( num_planes gt 1 ) and ( not segment_access ) extrn plane_port_tbl:byte extrn plane_read_tbl:byte endif extrn WEIGHT:word ;bolding ammount for char extrn L_OFF:word,R_OFF:word ;offsets for italic chars extrn CHAR_DEL:word ;additional width to add extrn DESTX:word,DESTY:word ;destination pixel address extrn ACTDELY:word ;form height after scale extrn CLIP:word ;clipping flag extrn XMN_CLIP:WORD,XMX_CLIP:WORD extrn YMN_CLIP:WORD,YMX_CLIP:WORD extrn FLIP_Y:word extrn width:word extrn rot_case:word font_inf rw 1 ;is the face number fi_point rw 1 fi_name rb 32 FIR_CHR rw 1 f_i_last rw 1 f_i_top rw 1 fi_ascen rw 1 fi_half rw 1 fi_desce rw 1 fi_botto rw 1 fi_mx_ch rw 1 fi_mx_ce rw 1 fi_l_off rw 1 fi_r_off rw 1 fi_thick rw 1 fi_ul_si rw 1 fi_light rw 1 fi_skew rw 1 fi_flags rw 1 off_htbl dw 0 seg_htbl dw 0 poff_tbl rw 0 OFF_TBL rd 1 FOFF rw 1 foff_seg rw 1 FWIDTH rw 1 DELY rw 1 fi_nxt_f rd 1 fi_fnt_s rw 1 rw 19h ; jn 10-28-87 def_buf rb 8*cell_size ;spare buffer txbuf1 dw offset def_buf txbuf2 dw offset def_buf+4*cell_size sav_buf1 dw offset def_buf sav_buf2 dw offset def_buf+4*cell_size buff_ptr dw offset def_buf buff_seg dw seg def_buf source_seg dw seg def_buf top_overhang dw 0 ; jn 10-29-87 tempdely dw 0 ;temporary char height storage foffindex dw 0 ;temporary char offset index isspace db 0 rt_hoff db 0 lt_hoff db 0 y_position rw 1 char_count rw 1 form_offset rw 1 form_width rw 1 JUST_DEL_WORD dw 0 JUST_DEL_WORD_REM dw 0 JUST_DEL_CHAR dw 0 JUST_DEL_CHAR_REM dw 0 JUST_DEL_SIGN dw 1 JUST_NEG dw 0 byte_mask_table db 11111111b db 01111111b db 00111111b db 00011111b db 00001111b db 00000111b db 00000011b db 00000001b db 00000000b text_ix db 0 ;text color index text_mode db 0 ;text write mode font_off dw 0 ;temp storage for font offset port_sel dw 0 pre_blt rw 1 post_blt rw 1 pre_blt_table dw pre_blt_0 dw pre_blt_90 dw pre_blt_180 dw pre_blt_270 post_blt_table dw post_blt_0 dw post_blt_90 dw post_blt_180 dw post_blt_270 line_table dw clr_skew_next_line_0 dw clr_skew_next_line_90 dw clr_skew_next_line_180 dw clr_skew_next_line_270 pixel_table dw clr_skew_next_pixel_0 dw clr_skew_next_pixel_90 dw clr_skew_next_pixel_180 dw clr_skew_next_pixel_270 public lt_hoff public rt_hoff public off_htbl public seg_htbl public poff_tbl public text_ix public JUST_NEG public buff_ptr public JUST_DEL_CHAR_REM public JUST_DEL_CHAR public font_off public line_table public tempdely public JUST_DEL_WORD public JUST_DEL_WORD_REM public foffindex public port_sel public pixel_table public text_mode public source_seg public JUST_DEL_SIGN public byte_mask_table cseg extrn chk_fnt:near extrn set_fnthdr:near extrn text_move:near extrn text_scale:near extrn text_italic:near extrn text_bold:near extrn text_grey:near extrn text_rotate:near extrn text_blit:near extrn clr_skew_next_line_0:near extrn clr_skew_next_line_90:near extrn clr_skew_next_line_180:near extrn clr_skew_next_line_270:near extrn clr_skew_next_pixel_0:near extrn clr_skew_next_pixel_90:near extrn clr_skew_next_pixel_180:near extrn clr_skew_next_pixel_270:near extrn double_table:word extrn d_gtext:near extrn ACT_SIZ:near extrn RECTFILL:near extrn CONCAT:near if (num_planes gt 1) and (not segment_access) extrn EGA_KLUG:near endif next_dest rw 1 next_source rw 1 rot_height rw 1 SPECIAL_CS rw 1 extrn txtblt_rep_rr:near extrn txtblt_tran_rr:near extrn txtblt_xor_rr_s:near extrn txtblt_itran_rr:near extrn txtblt_rep_rl:near extrn txtblt_tran_rl:near extrn txtblt_xor_rl_s:near extrn txtblt_itran_rl:near ; ;text blit branch table ; format three bits (rot dir ) (mode msb) (mode lsb) txt_blt_mode_table dw offset txt_blt_rep dw offset txt_blt_tran dw offset txt_blt_xor dw offset txt_blt_tran txt_blt_branch_table dw offset txtblt_rep_rr ;replace right source dw offset txtblt_tran_rr ;trans right source dw offset txtblt_tran_rr ;xor right source dw offset txtblt_itran_rr ;invtrans right source dw offset txtblt_rep_rl ;replace left source dw offset txtblt_tran_rl ;trans left source dw offset txtblt_tran_rl ;xor left source dw offset txtblt_itran_rl ;invtrans left source public rot_height public next_dest public txt_blt_branch_table public next_source public SPECIAL_CS ;**************************************************************** ; TEXT_BLT * ;**************************************************************** TEXT_BLT: ; If skewing and the writing mode is replace or reverse transparent, force the ; mode to transparent. In the latter case, substitute background color for ; the foreground. push bp mov ax, WRT_MODE test SPECIAL, SKEW ; skewed? jz text_blt_modeok cmp al, 0 ; replace mode? je text_blt_fudge_mode cmp al, 3 ; reverse transparent? jne text_blt_modeok mov dx, MAP_COL ; dx = background color mov TEXT_BP, dx text_blt_fudge_mode: mov al, 1 ; force to transparent mode text_blt_modeok: mov text_mode, al ; local writing mode mov bl, al xor bh, bh shl bx, 1 call txt_blt_mode_table[bx] mov dx, ega_graphic_data mov al, 0ffh out dx, al pop bp ret ;******************************* ; txt_blt_rep ; ;******************************* txt_blt_rep: mov bl, 0fh ;enable all planes to draw call box_plane_enable mov bx, TEXT_BP not bx xchg bh, bl and bh, 0fh ;set the planes with ix=0 to set/res mov bl, 00000000b ;set to no rotate and an replace op call box_ega_init mov dx, ega_graphic_add ;now set the planes to reset mov al, ega_setres_reg out dx, al mov dx, ega_graphic_data mov al, 0 out dx, al call text_blt_main ret ;******************************* ; txt_blt_tran ; ;******************************* txt_blt_tran: mov bx, TEXT_BP and bl, 0fh jz txt_blt_tran_NO_OR call box_plane_enable ;enable the planes to be drawn with 1's mov bh, 0 ;don't allow any planes to use set/res mov bl, 00010000b ;set to no rotate and an or op call box_ega_init push di call text_blt_main pop di txt_blt_tran_NO_OR: mov bx, TEXT_BP not bx and bl, 0fh jz txt_blt_tran_DONE call box_plane_enable mov dx, ega_graphic_add ;set up the writing mode to be applied mov al, ega_datarot_reg out dx, al mov dx, ega_graphic_data mov al, 00001000b ;set to no rotate with an and op out dx, al cmp WRT_MODE, 1 jz txt_blt_tran_LAST_OK mov text_mode, 1 ;set to tran mode call text_blt_main ret txt_blt_tran_LAST_OK: mov text_mode, 3 ;set to inv tran mode call text_blt_main txt_blt_tran_DONE: ret ;******************************* ; txt_blt_xor ; ;******************************* txt_blt_xor: mov bl, 0fh call box_plane_enable ;enable the planes to be drawn with 1's mov bh, 0 ;don't allow any planes to use set/res mov bl, 00011000b ;set to no rotate and an or op call box_ega_init call text_blt_main ret ;main entry into the text blit text_blt_main: ;clip the string in y direction mov dx,ega_graphic_add mov al, ega_bitmask_reg out dx, al ;init the regs to mask reg ; Handle special effects, rotation, and scaling separately. cmp SPECIAL, 0 je text_blt_normal jmp text_blt_special text_blt_normal: push bp mov top_overhang, 0 ; jn 10-29-87 xor ax, ax ;ax contains top offset mov dx, ACTDELY ;dx contains char height mov bp, DESTY ;bp char top y add mov cx, YMX_CLIP mov bx, bp add bx, dx ;find char bot y add dec bx cmp bx, cx ;is bot y lt clip boty jle text_blt_botlt ;if so test top clip cmp bp, cx ;is top y gt clip boty jg text_blt_notin ;if so discard string mov dx, bp mov bx, cx sub cx,dx mov dx, cx inc dx ;dx = new dely text_blt_botlt: ;the bottom of cell was above ;bottom of clip rectangle mov cx, YMN_CLIP cmp bp, cx ;is top y ge top clip jge text_blt_clpdn ;if so char is fully in mov bp, cx ;if any of string is in sub bx, cx ;topy = clip topy jl text_blt_notin inc bx ;bx is the new dely mov ax, dx sub ax, bx mov top_overhang, ax ; jn 10-29-87 mov dx, FWIDTH mul dx ;ax = font offset mov dx, bx ;ax = delta from top of cell jmps text_blt_clpdn text_blt_notin: pop bp ret text_blt_clpdn: call chk_fnt ; jn, 10-29-87 mov tempdely, dx ; save away new dely mov font_off, ax ; save it away mov DESTY, bp mov cx, CONTRL +6 ;get the intin count mov si, offset INTIN ;point at the string cmp CONTRL, 11 ;is this justified text jnz text_blt_normal_nojust add si, 4 ;index into the characters text_blt_normal_nojust: mov bx, DESTX mov di, XMN_CLIP text_clip_leftx: lodsw ; al = character ; jn 11-21-87 call set_fnthdr ; set the correct font header ; for this character mov isspace, al ; update space check push ax ; jn 11-21-87, save the char push dx ; jn 10-30-87 mov ax, ss:top_overhang mov dx, ss:FWIDTH mul dx add ax, ss:FOFF ; add in the font offset mov font_off, ax ; save it away pop dx pop ax ; restore char push si push ds sub ax, FIR_CHR ; offset by lowest ADE shl ax, 1 lds si, OFF_TBL ; ds:si -> font offset table add si, ax ; ds:si -> character offset ;11/6/86 DH ;added horizontal offset code here test ss:fi_flags, HORZ_OFF ;do we need to move to the left jz text_clip_leftx_nohorzoff push si ;save the char offset table ix mov si, ss:off_htbl add si, ax mov ax, [si] ;get the left offset mov ss:rt_hoff, ah ;save the offset on right xor ah, ah sub bx, ax ;mov the x left by offset ammount pop si text_clip_leftx_nohorzoff: ; lodsw mov dx, ax ; dx = offset into font lodsw sub ax, dx ; ax = character width pop ds pop si cmp bx, di ; clipped on the left? jge text_no_lxclip mov bp, bx add bp, ax dec bp ; bp = character ending x sub bp, di ; is the right edge in? jge text_clip_leftx_found cmp CONTRL, 11 ; is this justified text? jnz text_clip_leftx_notjust cmp isspace, 020h ; is the character a space? jne text_clip_just_nospace add ax, JUST_DEL_WORD ; yes: add in the word offset cmp JUST_DEL_WORD_REM, 0 ; need to add remainder? je text_clip_just_nospace add ax, JUST_DEL_SIGN ; add in remainder dec JUST_DEL_WORD_REM ; account for remainder jmps text_clip_just_done text_clip_just_nospace: add ax, JUST_DEL_CHAR ; add in character offset cmp JUST_DEL_CHAR_REM, 0 ; need to add remainder? je text_clip_just_done add ax, JUST_DEL_SIGN ; add in remainder dec JUST_DEL_CHAR_REM ; account for remainder text_clip_just_done: text_clip_leftx_notjust: add bx, ax ; no: point to next character test fi_flags, HORZ_OFF ; must we move left by right ammount jz text_clip_leftx_notjust_nohorz mov al, rt_hoff xor ah, ah sub bx, ax text_clip_leftx_notjust_nohorz: dec cx jz rtext_blt_notin jmp text_clip_leftx rtext_blt_notin: jmp text_blt_notin text_clip_leftx_found: inc bp ;the new width sub ax, bp add dx, ax ;the new startx mov bx, di ;the new dest x = clipx mov ax, bp ;the new width if 0 ; jn 11-10-87 dec ax ;width is off by one endif ; si = char pointer ; dx = first char source startx ; bx = first char dest startx ; ax = first char width ; cx = char count text_no_lxclip: push si push cx mov si, ax ;si = DELX = CHAR WIDTH mov bp, bx ;bp = DESTX push dx ;calculate dest address ;dest pointer = es:di mov ax, DESTY call concat ;get the dest pointer es:di mov ax, graph_plane mov es, ax ; init the segment register pop ax ;get the source startx back ;this is the main char out loop for text ;si = CHAR WIDTH ;bp = destx ;ax = sourcex text_blit_char_loop: ;calculate the right mask right mask = dh mov cx, 7 mov bx, bp add bx, si ;right x = DESTX+DELX dec bx mov dx, XMX_CLIP ;are we beyond the clip area cmp bx, dx jle right_clip_ok cmp bp, dx jle right_clip_last pop si pop si ;clear out the stack jmp text_blt_done right_clip_last: pop si mov si, 1 ;set char count = 1 left push si mov bx, dx sub dx, bp inc dx mov si, dx ;update the new width right_clip_ok: inc bx and bx, cx mov dh, byte_mask_table[bx] ;dh = right mask ;calculate the left mask ;left mask = dl mov bx, bp ;get dext x in bx and bx, cx mov dl, byte_mask_table[bx] not dl ;calculate rotate value ;rotate value = bh 0000drrr d=0 if right 1 if left rrr = count 0 - 7 mov ch, al and ch, cl ;mask off all but 3 lsbits mov bh, bl sub bh, ch ;if destx >= source x jns txt_blt_clc_height add bh, 16 ;get the left rotate index ;calculate the vertical loop count ;vertical loop count = cl txt_blt_clc_height: mov cx, tempdely ;calculate the middle byte count ;middle byte count = ch push ax sub bl, 8 ;left count max = 8-xposn neg bl mov ah, bh xor bh, bh push si sub si, bx ;delx - leftx jnc txt_blt_clc_middle or dl, dh ;if it is left only then must modify masks mov dh, 0ffh ;the right mask is now none xor bx, bx ;the next add delta is 0 mov ch, bl ;the middle count is 0 jmps txt_blt_op_branch txt_blt_clc_middle: mov bx, si shr bx, 1 shr bx, 1 shr bx, 1 ;divide out the low order bits mov ch, bl inc bl ;make it left + middle txt_blt_op_branch: pop si add bp, si ;add in the width to dest x and save pop si ;get the source x back shr si, 1 shr si, 1 shr si, 1 add si, font_off ;offset from the top cmp CONTRL, 11 ;is this justified text? jnz txt_blt_op_branch_notjust push di add di, bx ;get the current physical add mov bx, bp ;calculate the current scan line shr bx, 1 shr bx, 1 shr bx, 1 sub di, bx ;di = current scan line cmp isspace, 020h ;is this a space jnz txt_blt_op_branch_just_nospace add bp, JUST_DEL_WORD ;add in the word offset cmp JUST_DEL_WORD_REM, 0 ;done with extra space jz txt_blt_op_branch_just_nospace add bp, JUST_DEL_SIGN dec JUST_DEL_WORD_REM jmps txt_blt_op_branch_just_done txt_blt_op_branch_just_nospace: add bp, JUST_DEL_CHAR cmp JUST_DEL_CHAR_REM, 0 jz txt_blt_op_branch_just_done add bp, JUST_DEL_SIGN dec JUST_DEL_CHAR_REM txt_blt_op_branch_just_done: mov bx, di pop di push bp ;save the dest x shr bp, 1 shr bp, 1 shr bp, 1 add bx, bp jmps txt_blt_op_branch_just txt_blt_op_branch_notjust: push bp ;save the dest x add bx, di ;save the next di txt_blt_op_branch_just: push bx mov bp, FWIDTH mov bl, text_mode mov al, ah ;get the rotate flag and al, 8 shr al, 1 or bl, al xor bh, bh and ah, 11110111b ;mask off the rotate flag shl bx, 1 ;index in by words push ds mov ds, FOFF+2 call txt_blt_branch_table[bx] pop ds pop di ;get the new di pop bp ;get the new dest x pop cx ;get the char cnt pop si ;get the char ptr dec cx cmp cx, 0 ! jnz $ + 5 ! jmp text_blt_done lodsw ; get the next char call set_fnthdr push ax ; jn 11-21-87 push dx ; jn 10-29-87 mov ax, ss:top_overhang mov dx, ss:FWIDTH mul dx add ax, ss:FOFF mov ss:font_off, ax pop dx pop ax push si ; save the character pointer push cx ; save the character count push ds ;;DH 11/6/86 ;horizontal offset table code push ax ; save the character code mov dx, FIR_CHR sub al, dl shl ax, 1 lds si, OFF_TBL ; ds:si -> font offset table add si, ax test ss:fi_flags, HORZ_OFF jz text_blit_char_loop_nohorzoff mov dl, ss:rt_hoff ; get the right shift value mov bx, ss:off_htbl add bx, ax mov ax, [bx] ; get next char left shift mov ss:rt_hoff, ah ; save the right offset for char xor ah, ah mov dh, ah add ax, dx ; have total shift value mov dx, ax ; save delta ammount shr al, 1 shr al, 1 shr al, 1 ; get num of bytes to move back by mov bx, bp and bl, 7 ; if x & 7 + 1 < deltax & 7 mov bh, dl and bh, 7 cmp bh, bl jbe text_blit_char_loop_horzoff_ok inc al ; move back one more byte text_blit_char_loop_horzoff_ok: xor ah, ah sub di, ax sub bp, dx ;cliping should be retested here for left clip case text_blit_char_loop_nohorzoff: ;end of horizontal offset code ; pop ax mov ss:isspace, al ; save the character lodsw ; ax = offset to character mov dx, ax lodsw ;find the delx for char mov si, ax sub si, dx mov ax, dx pop ds jmp text_blit_char_loop ; All of the characters which can be output have been written. All that is ; left is to underline them, if requested. text_blt_done: test SPECIAL, UNDER jz text_exit ; done if no underline text_blt_do_under: push patptr push patmsk push NEXT_PAT push FG_BP_1 xor ax, ax mov NEXT_PAT, ax mov patmsk, ax mov patptr, offset SOLID test SPECIAL, LIGHT jz text_ul mov ax, DITHRMSK ; dither if lightened mov patmsk, ax mov ax, 24 add ax, offset DITHER mov patptr, ax text_ul: mov ax, TEXT_BP mov FG_BP_1, ax call RECTFILL pop FG_BP_1 pop NEXT_PAT pop patmsk pop patptr text_exit: pop bp ret ;**************************************************************** ; TEXT_BLT_SPECIAL * ;**************************************************************** text_blt_special: call chk_fnt ;make sure font is loaded ; Save the address of the appropriate pre- and post-blt routines (a function ; of rotation). mov bx, SPECIAL and bx, ROTATE mov cl, 5 shr bx, cl mov ax, pre_blt_table[bx] mov pre_blt, ax mov ax, post_blt_table[bx] mov post_blt, ax ; Perform preliminary clipping against the non-baseline axis of the text. push bp ; save for 'C' test SPECIAL, ROTODD jnz spec_odd_pre_clip ; Clip in the y direction. First, compare the cell against the clipping ; window bottom. xor ax, ax ; ax = offset to top in font mov dx, ACTDELY ; dx = character form height mov bp, DESTY ; bp = character cell top mov cx, YMX_CLIP mov bx, bp add bx, dx dec bx ; bx = character cell bottom cmp bx, cx ; is the cell bottom above jle spec_above_bottom ; the clip bottom? cmp bp, cx ; no: is the cell top above jg spec_reject ; the clip bottom? mov bx, cx ; bx = new cell bottom sub cx, bp mov dx, cx inc dx ; dx = new cell height ; At least part of the cell is above the bottom of the clipping rectangle. ; Check against the top of the clipping rectangle. spec_above_bottom: mov cx, YMN_CLIP cmp bp, cx ; is the cell top below the jge spec_clip_even_done ; clip top? mov bp, cx ; no: bp = new cell top sub bx, cx ; is the cell totally above jl spec_reject ; the clip top? inc bx ; no: bx = new cell height ; Calculate the new offset into the font. mov ax, dx sub ax, bx ; ax = font scan lines to skip mov dx, bx ; dx = cell height ; Save the clipping results. spec_clip_even_done: mov foffindex, ax ; save source lines to skip mov tempdely, dx ; save cell height mov y_position, bp ; save y position mov bp, DESTX ; bp = cell left x jmps spec_clip_done ; Trivial rejection exit point: abandon the text string. spec_reject: pop bp ret ; Clip in the x direction. First, compare the cell against the clipping ; window right edge. spec_odd_pre_clip: xor ax, ax ; ax = offset to top in font mov dx, ACTDELY ; dx = character form height mov bp, DESTX ; bp = character cell left mov cx, XMX_CLIP mov bx, bp add bx, dx dec bx ; bx = character cell right cmp bx, cx ; is the cell right left of jle spec_left_of_right ; the clip right? cmp bp, cx ; no: is the cell left left jg spec_reject ; of the clip right? mov bx, cx ; bx = new cell right sub cx, bp mov dx, cx inc dx ; dx = new cell "width" ; At least part of the cell is left of the right edge of the clipping ; rectangle. Check against the left edge of the clipping rectangle. spec_left_of_right: mov cx, XMN_CLIP cmp bp, cx ; is the cell left right of jge spec_clip_odd_done ; the clip left? mov bp, cx ; no: bp = new cell left sub bx, cx ; is the cell totally left of jl spec_reject ; the clip left? inc bx ; no: bx = new cell "width" ; Calculate the new offset into the font. mov ax, dx sub ax, bx ; ax = offset from form left mov dx, bx ; dx = cell "width" ; Save the clipping results. spec_clip_odd_done: mov form_offset, ax ; save offset from form left mov form_width, dx ; save visible width mov ax, DESTY mov y_position, ax ; save y position ; Prepare for the character output loop. spec_clip_done: mov ax, graph_plane mov es, ax ; init the segment register mov cx, CONTRL + 6 ; cx = number of characters mov char_count, cx ; save the character count mov si, offset INTIN ; ds:si -> string cmp CONTRL, 11 ; if "justified text" was jnz spec_char_loop ; requested, bump pointer add si, 4 ; by two words ; Top of the character output loop. Get the character, the offset ; into the font form, and the width of the character in the font. spec_char_loop: ;11/6/86 horizontal offset enhancement xor al, al mov lt_hoff, al mov rt_hoff, al ; lodsw ; get a character ; jn 11-21-87, let set_fnthdr call set_fnthdr ; modify the char mov isspace, al ; save the character push si ; save the character pointer push ds sub ax, FIR_CHR shl ax, 1 ; ax = index into offset table lds si, OFF_TBL add si, ax ; ds:si -> character offset ;11/6/86 horizontal offset enhancement test ss:fi_flags, HORZ_OFF jz spec_char_loop_nohorzoff mov bx, ss:off_htbl add bx, ax mov ax, [bx] ; get the horizontal offset data mov ss:lt_hoff, al mov ss:rt_hoff, ah spec_char_loop_nohorzoff: ; lodsw mov dx, ax ; dx = character offset lodsw ; ax = next character offset pop ds sub ax, dx jnz spec_char_isthere jmp spec_draw_done ; if char has width then draw it spec_char_isthere: mov si, ax ; si = character width mov ax, dx ; ax = offset into font form ; Point the destination to the temporary buffer. push bp ; save the cell left x push es mov es, buff_seg mov source_seg, es ; save for screen blt mov di, txbuf1 ; es:di -> temporary buffer mov buff_ptr, di ; If doubling, adjust the character buffer form width (bx). mov bx, si ; bx = character width test SPECIAL, SCALE jnz spec_calc_form_width add bx, CHAR_DEL ; add special extra width spec_calc_form_width: add bx, 7 shr bx, 1 shr bx, 1 shr bx, 1 ; bx = destination form width ; Move the character from the font form to the temporary buffer. call text_move ; Apply scaling, if necessary. test SPECIAL, SCALE jz spec_skew call text_scale ; The status of the registers when calling the special effects routines ; is as follows: ; bl = character buffer width, in bytes ; cx = height of the character cell ; dx = character width, in pixels ; es:di -> temporary character buffer ; Apply skewing, if necessary. spec_skew: mov cx, ACTDELY ; cx = total character height mov dx, si ; dx = offset to next char test SPECIAL, SKEW jz spec_bold call text_italic add si, L_OFF ; add left offset add si, R_OFF ; add right offset ; Apply bolding, if necessary. Bump the character width only if the font is ; not monospaced. spec_bold: test SPECIAL, THICKEN jz spec_grey call text_bold test MONO_STA, 0ffffh ; is this a monospaced font? jnz spec_grey add si, WEIGHT ; bump width add dx, WEIGHT ; bump offset to next char ; Apply lightening, if necessary. spec_grey: test SPECIAL, LIGHT jz spec_rotate call text_grey ; Rotate, if necessary. spec_rotate: test SPECIAL, ROTATE jz spec_done call text_rotate ; Special effects and attributes have been bound. spec_done: pop es pop bp ; get the screen dest x back ; Perform the necessary pre-blt operations, based on the rotation angle. ; Output the character and perform the necessary post-blt operations. call pre_blt jc spec_draw_done push bp push dx call text_blit pop dx pop bp call text_attr_just call post_blt ; Done with the character. Prepare for the next one. spec_draw_done: pop si dec char_count jz text_special_blit_done jmp spec_char_loop ; Subroutine to adjust for justified text. text_attr_just: cmp CONTRL, 11 ;is this justified text? jnz text_attr_just_done cmp isspace, 020h ;is this a space jnz text_attr_just_nospace add dx, JUST_DEL_WORD ;add in the word offset cmp JUST_DEL_WORD_REM, 0 ;done with extra space jz text_attr_just_nospace add dx, JUST_DEL_SIGN dec JUST_DEL_WORD_REM jmps text_attr_just_done text_attr_just_nospace: add dx, JUST_DEL_CHAR cmp JUST_DEL_CHAR_REM, 0 jz text_attr_just_done add dx, JUST_DEL_SIGN dec JUST_DEL_CHAR_REM text_attr_just_done: ret text_special_blit_done: test SPECIAL, SKEW jz text_special_blit_done_noskew add bp, R_OFF text_special_blit_done_noskew: jmp text_blt_done ;**************************************************************** ; PRE_BLT_0 * ; Input: none * ; Input/Output: * ; dx = offset to the next character * ; bp = destination x position * ; si = character width * ; Output: * ; carry flag: set if character is clipped out * ; char_count: number of characters to process * ; ax = source offset from left edge of form * ; di = bitmap address * ; Preserved: bx * ; Trashed: cx * ;**************************************************************** pre_blt_0: ; Find out if clipping is necessary on the left side. mov al, lt_hoff xor ah, ah sub bp, ax xor ax, ax ; ax = source offset from left mov di, bp add di, si dec di ; di = right edge of cell mov cx, XMN_CLIP cmp bp, cx ; out on the left? jge pre_0_right_clip mov ax, di sub ax, cx jl pre_0_no_draw ; Clipping is necessary on the left side. Do it. inc ax mov si, ax ; si = visible width mov ax, cx ; ax = left clip edge sub ax, bp sub dx, ax ; dx = distance to next char mov bp, cx ; bp = new left x (clip edge) ; Find out if clipping is necessary on the right side. pre_0_right_clip: mov cx, XMX_CLIP cmp di, cx ; clipped on the right side? jle pre_0_clip_done cmp bp, cx jg pre_0_all_clipped ; Clipping is necessary on the right side. Do it. sub cx, bp inc cx mov si, cx ; si = visible width ; Get the new bitmap address and return a status indicating that a character ; should be drawn. pre_0_clip_done: push ax push bx push dx mov bx, bp ; bx = new destination x mov ax, y_position call concat ; get new di pop dx pop bx pop ax clc ret ; No character will be drawn (clipped). Bump to the next position and return ; a status indicating clipped. pre_0_no_draw: call text_attr_just add bp, dx ; bp = next destination x stc ret ; No more characters can be drawn. Indicate that the last character has been ; processed. pre_0_all_clipped: mov char_count, 1 stc ret ;**************************************************************** ; PRE_BLT_90 * ; Input: * ; tempdely: form height * ; Input/Output: * ; y_position: screen y coordinate * ; dx = offset to the next character * ; Output: * ; carry flag: set if character is clipped out * ; char_count: number of characters to process * ; ax = source offset from left edge of form * ; si = character form "width" * ; di = bitmap address * ; Preserved: bx, bp * ; Trashed: cx * ;**************************************************************** pre_blt_90: ; Subtract the form height from the y position to obtain the screen y of the ; character's upper left corner. The offset to the next character must be ; similarly patched to return the y position for the next pass through. push bp mov al, lt_hoff xor ah, ah add y_position, ax mov bp, y_position mov si, tempdely ; si = character form "height" sub bp, si ; bp = upper left corner y mov y_position, bp sub dx, si ; Find out if clipping is necessary on the top. xor ax, ax ; ax = source offset from top mov di, bp add di, si dec di ; di = bottom edge of cell mov cx, YMN_CLIP cmp bp, cx ; out on top? jge pre_90_bottom_clip mov ax, di sub ax, cx jl pre_90_all_clipped ; if clipped, all are clipped ; Clipping is necessary on the top. Do it. inc ax mov si, ax ; si = visible "height" mov ax, cx sub ax, bp ; ax = source offset from top add dx, ax ; dx = distance to next char mov bp, cx ; bp = new top y (clip edge) mov y_position, bp ; save y position ; Find out if clipping is necessary on the bottom. pre_90_bottom_clip: mov cx, YMX_CLIP cmp di, cx ; clipped on the bottom? jle pre_90_clip_done cmp bp, cx jg pre_90_no_draw ; Clipping is necessary on the bottom. Do it. sub cx, bp inc cx mov si, cx ; si = visible "height" ; Get the new bitmap address and return a status indicating that a character ; should be drawn. pre_90_clip_done: mov foffindex, ax ; save source lines to skip mov tempdely, si ; save visible "height" mov ax, form_offset ; ax = source offset from left mov si, form_width ; si = visible width pop bp ; bp = destination x push ax push bx push dx mov bx, bp ; bx = new destination x mov ax, y_position call concat ; get new di pop dx pop bx pop ax clc ret ; No character will be drawn (clipped). Bump to the next position and return ; a status indicating clipped. pre_90_no_draw: pop bp call text_attr_just sub y_position, dx stc ret ; No more characters can be drawn. Indicate that the last character has been ; processed. pre_90_all_clipped: pop bp mov char_count, 1 stc ret ;**************************************************************** ; PRE_BLT_180 * ; Input: none * ; Input/Output: * ; bp = destination x position * ; si = character form width * ; Output: * ; carry flag: set if character is clipped out * ; char_count: number of characters to process * ; ax = source offset from left edge of form * ; dx = offset to the next character * ; di = bitmap address * ; Preserved: bx * ; Trashed: cx * ;**************************************************************** pre_blt_180: ; Subtract the form width from the destination x position so that the ; character will be placed correctly. The distance to the next character ; must also be updated. mov al, lt_hoff xor ah, ah add bp, ax sub bp, si mov dx, R_OFF add dx, L_OFF neg dx ; dx = offset to next ; Find out if clipping is necessary on the left side. xor ax, ax ; ax = source offset from left mov di, bp add di, si dec di ; di = right edge of cell mov cx, XMN_CLIP cmp bp, cx ; out on the left? jge pre_180_right_clip mov ax, di sub ax, cx jl pre_180_all_clipped ; Clipping is necessary on the left side. Do it. inc ax mov si, ax ; si = visible width mov ax, cx sub ax, bp ; ax = source offset from left add dx, ax ; dx = distance to next char mov bp, cx ; bp = new left x (clip edge) ; Find out if clipping is necessary on the right side. pre_180_right_clip: mov cx, XMX_CLIP cmp di, cx ; clipped on the right side? jle pre_180_clip_done cmp bp, cx jg pre_180_no_draw ; Clipping is necessary on the right side. Do it. sub cx, bp inc cx mov si, cx ; si = visible width ; Get the new bitmap address and return a status indicating that a character ; should be drawn. pre_180_clip_done: push ax push bx push dx mov bx, bp ; bx = new destination x mov ax, y_position call concat ; get new di pop dx pop bx pop ax clc ret ; No character will be drawn (clipped). Bump to the next position and return ; a status indicating clipped. pre_180_no_draw: call text_attr_just sub bp, dx ; bp = next destination x stc ret ; No more characters can be drawn. Indicate that the last character has been ; processed. pre_180_all_clipped: mov char_count, 1 stc ret ;**************************************************************** ; PRE_BLT_270 * ;**************************************************************** pre_blt_270: ; Get the character y position and the "height" (screen sense) of the ; character. push bp mov al, lt_hoff xor ah, ah sub y_position, ax mov bp, y_position mov si, tempdely ; si = character form "height" ; Find out if clipping is necessary on the top. xor ax, ax ; ax = source offset from top mov di, bp add di, si dec di ; di = bottom edge of cell mov cx, YMN_CLIP cmp bp, cx ; out on top? jge pre_270_bottom_clip mov ax, di sub ax, cx jl pre_270_no_draw ; don't draw if all clipped ; Clipping is necessary on the top. Do it. inc ax mov si, ax ; si = visible "height" mov ax, cx sub ax, bp ; ax = source offset from top sub dx, ax ; dx = distance to next char mov bp, cx ; bp = new top y (clip edge) mov y_position, bp ; save y position ; Find out if clipping is necessary on the bottom. pre_270_bottom_clip: mov cx, YMX_CLIP cmp di, cx ; clipped on the bottom? jle pre_270_clip_done cmp bp, cx jg pre_270_all_clipped ; if clipped, all are clipped ; Clipping is necessary on the bottom. Do it. sub cx, bp inc cx mov si, cx ; si = visible "height" ; Get the new bitmap address and return a status indicating that a character ; should be drawn. pre_270_clip_done: mov foffindex, ax ; save source lines to skip mov tempdely, si ; save visible "height" mov ax, form_offset ; ax = source offset from left mov si, form_width ; si = visible width pop bp ; bp = destination x push ax push bx push dx mov bx, bp ; bx = new destination x mov ax, y_position call concat ; get new di pop dx pop bx pop ax clc ret ; No character will be drawn (clipped). Bump to the next position and return ; a status indicating clipped. pre_270_no_draw: pop bp call text_attr_just add y_position, dx stc ret ; No more characters can be drawn. Indicate that the last character has been ; processed. pre_270_all_clipped: pop bp mov char_count, 1 stc ret ;**************************************************************** ; POST_BLT_0 * ; Input: * ; dx = offset to the next character * ; Input/Output: * ; bp = destination x position * ; Output: none * ; Preserved: ax, bx, cx, dx, si, di * ; Trashed: none * ;**************************************************************** post_blt_0: ; For no rotation, move to the right. mov al, rt_hoff xor ah, ah sub bp, ax add bp, dx ; bump to next character ret ;**************************************************************** ; POST_BLT_90 * ; Input: * ; dx = offset to the next character * ; Input/Output: * ; y_position: screen y position * ; Output: none * ; Preserved: ax, bx, cx, dx, si, di, bp * ; Trashed: none * ;**************************************************************** post_blt_90: ; For 90 degree rotation, move up. mov al, rt_hoff xor ah, ah add y_position, ax sub y_position, dx ; bump to next character ret ;**************************************************************** ; POST_BLT_180 * ; Input: * ; dx = offset to the next character * ; Input/Output: * ; bp = destination x position * ; Output: none * ; Preserved: ax, bx, cx, dx, si, di * ; Trashed: none * ;**************************************************************** post_blt_180: ; For 180 degree rotation, move to the left. mov al, rt_hoff xor ah, ah add bp, ax sub bp, dx ; bump to next character ret ;**************************************************************** ; POST_BLT_270 * ; Input: * ; dx = offset to the next character * ; Input/Output: * ; y_position: screen y position * ; Output: none * ; Preserved: ax, bx, cx, dx, si, di, bp * ; Trashed: none * ;**************************************************************** post_blt_270: ; For 270 degree rotation, move down. mov al, rt_hoff xor ah, ah sub y_position, ax add y_position, dx ; bump to next character ret