; =====> BORDER.ASM ;*************************************** ;* TIPC Scheme Runtime Support * ;* Window Support Routines * ;* * ;* (C) Copyright 1985 by Texas * ;* Instruments Incorporated. * ;* All rights reserved. * ;* * ;* Date Written: 16 May 1985 * ;* Last Modification: * ;* 14 April 1986 : * ;* Make references to pagetabl * ;* call Memory Manager for use * ;* with extended/expanded mem. * ;* 26 Sept 1986 : * ;* added EGA support * ;* 13 May 1987 : * ;* Fixed Save/restore problem. * ;*************************************** page 60,132 include scheme.equ include pcmake.equ MSDOS equ 021h TI_CRT equ 049h IBM_CRT equ 010h DGROUP group data data segment word public 'DATA' assume DS:DGROUP extrn MAX_ROWS:byte,MAX_COLS:byte ; ___ __ __ ; + -| |- _|_ | -- | __| |__ | | (extra) map_tab db 0c5h,0b4h,0c3h,0c1h,0c2h,0c4h,0b3h,0d9h,0c0h,0bfh,0dah,0dah map_tabx equ $ trns_tab db 0dah,0c2h,0c3h,0c5h,0c3h,0c2h,0c2h,0c5h,0c3h,0c5h,0c5h db 0c2h,0bfh,0c5h,0b4h,0b4h,0c2h,0c2h,0c5h,0c5h,0b4h,0c5h db 0c3h,0c5h,0c0h,0c1h,0c3h,0c1h,0c5h,0c1h,0c3h,0c5h,0c5h db 0c5h,0b4h,0c1h,0d9h,0b4h,0c1h,0c5h,0c1h,0c5h,0b4h,0c5h db 0c3h,0b4h,0c3h,0b4h,0b3h,0c5h,0c5h,0c5h,0c3h,0b4h,0c5h db 0c2h,0c2h,0c1h,0c1h,0c5h,0c4h,0c2h,0c1h,0c5h,0c5h,0c5h m14_attr equ $ ;33-60 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < db 1,0,2,2,1,4,2,0,0,3,3,7,3,5,6,2,6,6,5,3,5,2,1,2,2,1,7,3 ;61-88 = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X db 2,6,1,2,2,0,3,0,0,0,3,1,0,4,0,0,1,1,3,0,3,0,2,0,1,3,1,1 ;89-116 Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t db 0,1,0,0,0,3,7,1,5,0,3,4,3,3,3,0,6,6,0,0,2,2,3,2,3,2,3,2 ;117-126 u v w x y z { | } ~ db 2,3,3,2,2,2,3,1,0,1 ;127-191 db 64 dup (0) ;192-197 db 5,2,0,0,0,4 ;198-218 db 20 dup (0) ;219-220 db 2,5 m16_attr equ $ ;33-60 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < db 3,1,4,4,4,7,4,2,2,6,6,11,6,9,9,4,10,10,9,6,9,4,2,4,4,3,10,6 ;61-88 = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X db 5,10,3,4,5,2,5,2,2,2,5,2,2,8,2,2,2,2,5,2,5,2,4,2,2,5,2,2 ;89-116 Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t db 2,2,2,2,2,3,12,2,9,2,6,7,6,6,6,2,10,11,2,2,5,5,6,5,6,5,6,4 ;117-126 u v w x y z { | } ~ db 5,5,5,5,5,5,6,2,2,3 db 64 dup (0) db 7,2,0,0,0,7 db 20 dup (0) db 2,7 public m18_attr m18_attr equ $ ;33-60 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < db 2,1,4,4,8,8,4,2,2,6,6,10,9,10,05,4,10,10,10,6,10,4,2,4,4,10,10,6 ;61-88 = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X db 9,06,2,4,4,2,6,2,2,2,6,2,2,8,2,2,2,2,6,2,6,2,4,2,2,6,2,2 ;89-116 Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t db 2,2,2,3,2,3,13,2,10,2,6,8,6,6,6,2,10,12,2,2,5,5,6,5,6,5,6,4 ;117-126 u v w x y z { | } ~ db 5,6,6,5,5,5,6,2,2,2 db 64 dup (0) db 10,4,0,0,0,8 db 20 dup (0) db 8,8 last_char db 0dbh extrn char_hgt:byte extrn vid_mode:word data ends XGROUP group PROGX PROGX segment byte public 'PROGX' assume CS:XGROUP ;************************************************************************ ;* Perform appropriate VIDEO I/O interrupt * ;* Any difference in register definition should be handled by * ;* the caller except where DH,DL contain row,col information. * ;************************************************************************ public crt_dsr crt_dsr proc far cmp PC_MAKE,TIPC jne ibm_dsr int TI_CRT ret ibm_dsr: xchg DH,DL ; Do this now instead of making special checks int IBM_CRT ; IBM's row,col is diff'rnt from TI's col,row ret crt_dsr endp ;************************************************************************ ;* Draw Border * ;************************************************************************ zb_args struc dw ? ; caller's BP dd ? ; return address (far linkage) dw ? ; return address (original) zb_line dw ? ; upper left corner line number zb_col dw ? ; upper left corner column number zb_nlines dw ? ; number of lines zb_ncols dw ? ; number of columns zb_battr dw ? ; border attributes zb_label dw ? ; pointer to label text zb_args ends public z%border z%border proc far push BP ; save caller's BP mov BP,SP ; output corners mov BL,byte ptr [BP].zb_battr ; load attribute bits mov DH,byte ptr [BP].zb_col ; load left column number mov DL,byte ptr [BP].zb_line ; load left line number dec DL dec DH mov AL,0DAh ; load upper left corner character call zcorner inc DH add DH,byte ptr [BP].zb_ncols mov AL,0BFh ; load upper right corner character call zcorner inc DL add DL,byte ptr [BP].zb_nlines mov AL,0D9h ; load lower right corner character call zcorner dec DH sub DH,byte ptr [BP].zb_ncols mov AL,0C0h ; load lower left corner character call zcorner ; output sides mov DH,byte ptr [BP].zb_col ; reload upper left column number mov DL,byte ptr [BP].zb_line ; and line number dec DH ; decrement column number mov CX,[BP].zb_nlines call zside ; draw the left hand border mov DH,byte ptr [BP].zb_col ; reload upper left column number mov DL,byte ptr [BP].zb_line ; and line number add DH,byte ptr [BP].zb_ncols ; add in line length mov CX,[BP].zb_nlines call zside ; draw the right hand border ; Output the top of the border mov DL,byte ptr [BP].zb_line ; load upper left row number dec DL jl z_no_top ; if row negative, skip write mov DH,byte ptr [BP].zb_col ; load upper left column number mov CX,[BP].zb_ncols call ztop ; Put the label in the top left corner of the border, if it'll fit mov BX,[BP].zb_label ; load pointer to the label's text cmp BX,0 ; if pointer NULL, no label je z_no_top ; jump, if NULL pointer mov DX,[BP].zb_ncols ; load window width xor CX,CX ; zero the character counter zb_loop: cmp byte ptr [BX],0 ; end of string? je zb_eos ; if end of string, jump inc CX ; increment the character count inc BX ; increment the character string pointer cmp CX,DX ; compare to window width jl zb_loop ; if label still shorter than window, loop zb_eos: jcxz z_no_top ; if no label, jump push CX ; save label length ; Write the label mov DL,byte ptr [BP].zb_line ; load upper left row number mov DH,byte ptr [BP].zb_col ; load upper left column number dec DL ; decrement row number xor BH,BH ; IBMism (page 0 for text-mode) mov AH,02h ; load "put cursor" code call CRT_DSR ; put cursor in upper left corner of border pop CX ; restore label's character count cmp PC_MAKE,TIPC jne ibm_cblk mov AH,011h ; load "write block of characters" code mov DX,DS ; load segment address mov BX,[BP].zb_label ; load label offset int TI_CRT ; write the label jmp short z_no_top ; ibm_cblk: mov AL,byte ptr [BP].zb_col add AL,CL cmp AL,MAX_COLS jle zb_sml ; jump if label length is OK sub AL,MAX_COLS sub CL,AL ; force label to remain within 80-col screen zb_sml: mov DI,[BP].zb_label ; load label offset lbl_loop: mov AH,0Eh ; Write ASCII Teletype mov AL,byte ptr [DI] mov BL,byte ptr [BP].zb_battr ; load attribute bits just in case xor BH,BH ; page # for alpha mode push CX push DI int IBM_CRT pop DI pop CX inc DI loop lbl_loop ; DECrement CX and jump if != 0 ; Output the bottom of the border z_no_top: mov BL,byte ptr [BP].zb_battr ; load attribute bits mov DL,byte ptr [BP].zb_line add DL,byte ptr [BP].zb_nlines mov DH,byte ptr [BP].zb_col ; load upper left column number mov CX,[BP].zb_ncols call ztop ; return to caller pop BP ; restore caller's BP ret ; return z%border endp ;************************************************************************ ;* Local Support: Draw a single character at cursor position * ;* * ;* Input Registers: AL - the character to be output * ;* BL - the character attributes for the write * ;* DH - column * ;* DL - row * ;* * ;* Registers Modified: AX,CX,SI,DI * ;************************************************************************ zcorner proc near ; draw a single corner character cmp DH,MAX_COLS jae zcornret cmp DL,MAX_ROWS jae zcornret push DX ; save cursor coordinates push AX ; save character to be output xor BH,BH ; page number (=0 for graphics mode also) mov AH,02h ; load "put cursor" code call CRT_DSR ; position the cursor ; read the character in this screen position ; ** This is tricky 'cause DH/DL are correct but ; ** will be swapped back (to incorrect) by CRT_DSR proc ; ** if using an IBM!!! cmp PC_MAKE,TIPC je no_swap xchg DH,DL xor BH,BH ; IBM display page no_swap: mov AH,08h call CRT_DSR ; see if it's one of the borderline characters call map_char mov SI,AX pop AX ; recover character to be output cmp SI,0 jl zcornput ; map corner to border character call map_char mov DL,map_tabx-map_tab-1 mul DL add SI,AX mov AL,trns_tab+[SI] ; output the corner character zcornput: mov AH,09h ; load "write character/attribute" code mov CX,1 ; number of characters = 1 xor BH,BH ; Display page for IBM text mode (=0) call CRT_DSR ; write it to the screen at cursor position pop DX ; restore cursor coordinates zcornret: ret ; return zcorner endp ;************************************************************************ ;* Local Support: Draw a border sides * ;* * ;* Input Registers: DH - column * ;* DL - row * ;* CX - number of rows * ;* * ;* Registers Modified: AX,CX,DL * ;************************************************************************ zside proc near cmp DH,MAX_COLS ; is column within the CRT's boundaries? jae zsideret ; if not, jump zside_lp: mov AL,0B3h ; load "|" border character push CX ; save line count push DX ; save next cursor position call zcorner ; output the border character pop DX ; restore current cursor position pop CX ; restore line counter inc DL ; increment the row number loop zside_lp ; loop until side is drawn zsideret: ret zside endp ;************************************************************************ ;* Local Support: Draw a border - Top or Bottom * ;* * ;* Input Registers: DH - column * ;* DL - row * ;* CX - number of columns * ;* * ;* Registers Modified: AX,CX * ;************************************************************************ ztop proc near cmp DL,MAX_ROWS ; is row within the CRT's boundaries? jae ztopret ; if not, jump ztop_lp: mov AL,0C4h ; load "-" border character push CX ; save line count push DX ; save next cursor position call zcorner ; output the border character pop DX ; restore current cursor position pop CX ; restore line counter inc DH ; increment the column number loop ztop_lp ; loop until top/bottom is drawn ztopret: ret ztop endp map_char proc near mov CX,map_tabx-map_tab mov DI,offset map_tab repne scasb mov AX,CX dec AX ret map_char endp ;************************************************************************ ;* Save Screen Contents * ;* * ;* Purpose: To save a rectangular region of the CRT in a string data * ;* object. * ;* * ;* Calling Sequence: save_scr(str_reg, ul_row, ul_col, n_rows, ncols) * ;* where str_reg - pointer to string data object * ;* which is to receive the screen * ;* contents * ;* ul_row - row number of the upper left * ;* corner of the region to be * ;* saved * ;* ul_col - column number of the upper left * ;* corner of the region to be * ;* saved * ;* n_rows - number of rows in the region to * ;* be saved * ;* n_cols - number of columns in the region * ;* to be saved * ;************************************************************************ sv_args struc dw ? ; caller's BP dw ? ; caller's ES dd ? ; return address (long) ; dw ? ; original return address (short) sv_str dw ? ; address of register pointing to string sv_ulrow dw ? ; upper left hand corner's row number sv_ulcol dw ? ; upper left hand corner's column number sv_nrow dw ? ; number of rows sv_ncol dw ? ; number of columns sv_args ends public save%scr save%scr proc far push ES push BP ; save the caller's BP register mov BP,SP ; and establish local addressability ; create a pointer to the string object mov BX,[BP].sv_str ; load address of register mov DI,[BX].C_disp ; load the string mov BX,[BX].C_page ; pointer %LoadPage ES,BX ; load string page's paragraph address ;;; mov ES,pagetabl+[BX] ; load string page's paragraph address add DI,BLK_OVHD ; advance pointer past string header ; store number of rows and columns into the first two bytes of the string mov AL,byte ptr [BP].sv_nrow stosb mov AL,byte ptr [BP].sv_ncol stosb ; adjust number of lines/columns for test conditions mov AX,[BP].sv_ulrow add [BP].sv_nrow,AX mov AX,[BP].sv_ulcol add [BP].sv_ncol,AX ; loop until all rows processed mov DL,byte ptr [BP].sv_ulrow rw_loop: mov DH,byte ptr [BP].sv_ulcol ; position cursor cl_loop: push DX ; save current position mov AH,02h ; load "put cursor" function id xor BH,BH ; IBMism (page number for cursor) call crt_dsr ; position the cursor ; read character/attributes at current screen position mov AH,08h ; load "read char/attribute" function id xor BH,BH ; IBMism (display page #) call crt_dsr ; read said ;******* cmp vid_mode,14 jl sav_01 ; not graphics modes cmp AL,0 ; don't bother with attributes if nul je sav_01 ; cmp AL,07fh ; is it above the first 128 characters ? ; jno sav_00 ; no cmp AL,0dah jbe sav_00 ; test AL,010h ; look for D0-DF ; je sav_00 xor AL,AL ; set to nul jmp sav_01 sav_00: call graph_attr ; mode 14,16, and 18 attribute function ;****** sav_01: stosw ; store char/attr into output string ; increment column number, test, branch pop DX inc DH cmp DH,byte ptr [BP].sv_ncol jl cl_loop ; increment row number, test, branch inc DL cmp DL,byte ptr [BP].sv_nrow jl rw_loop ; return to caller pop BP pop ES ret ; return to caller save%scr endp ;************************************************************************ ;* Restore Screen Contents * ;* * ;* Purpose: To restore a rectangular region of the CRT from a string * ;* data object. * ;* * ;* Calling Sequence: rest_scr(str_reg, ul_row, ul_col) * ;* where str_reg - pointer to string data object * ;* which contains the screen * ;* contents * ;* ul_row - row number of the upper left * ;* corner of the region to be * ;* restored * ;* ul_col - column number of the upper left * ;* corner of the region to be * ;* restored * ;************************************************************************ rs_args struc rs_nrow dw ? ; number of rows in saved data rs_ncol dw ? ; number of columns in saved data rs_BP dw ? ; caller's BP dw ? ; caller's ES dd ? ; return address (long) ; dw ? ; original return address (short) rs_str dw ? ; address of register pointing to string rs_ulrow dw ? ; upper left hand corner's row number rs_ulcol dw ? ; upper left hand corner's column number rs_mrow dw ? ; number of rows in new window rs_mcol dw ? ; number of columns in new window rs_args ends public rest%scr rest%scr proc far push ES push BP ; save the caller's BP register sub SP,offset rs_BP mov BP,SP ; and establish local addressability ; create a pointer to the string object mov BX,[BP].rs_str ; load address of register mov SI,[BX].C_disp ; load the string mov BX,[BX].C_page ; pointer %LoadPage ES,BX ; load string page's paragraph address ;;; mov ES,pagetabl+[BX] ; load string page's paragraph address add SI,BLK_OVHD ; advance pointer past string header ; recover number of rows and columns from screen object xor AX,AX lods byte ptr ES:[SI] add AX,[BP].rs_ulrow mov [BP].rs_nrow,AX lods byte ptr ES:[SI] add AX,[BP].rs_ulcol mov [BP].rs_ncol,AX ; adjust number of lines/columns for test conditions mov AX,[BP].rs_ulrow add [BP].rs_mrow,AX mov AX,[BP].rs_ulcol add [BP].rs_mcol,AX ; loop until all rows processed mov DL,byte ptr [BP].rs_ulrow xw_loop: mov DH,byte ptr [BP].rs_ulcol ; position cursor xl_loop: cmp DH,byte ptr [BP].rs_mcol ; column too long for new window? jge x_long ; if too long, jump push DX ; save current position mov AH,02h ; load "put cursor" function id xor BH,BH ; IBMism (page number/0 in graphic mode) call crt_dsr ; position the cursor ; read character/attributes at current screen position lods word ptr ES:[SI] ; fetch the character and attribute ;;;;;;;; cmp AL,20h ;;;;;;;; je x_sp ; if a space skip mov BL,AH ; and copy attribute to BL mov AH,09h ; load "write char/attribute" function id xor BH,BH ; IBMism (page number) mov CX,1 ; character count = 1 call crt_dsr ; read said ; increment column number, test, branch x_sp: pop DX ; recover the row/column coordinates x_more: inc DH ; increment the column number cmp DH,byte ptr [BP].rs_ncol ; more characters in this row? jl xl_loop ; if so, jump ; increment row number, test, branch inc DL ; increment the row number cmp DL,byte ptr [BP].rs_mrow ; check against new window boundary jge rs_fin ; if all rows filled, jump cmp DL,byte ptr [BP].rs_nrow ; check against saved data jl xw_loop ; if more lines, jump ; return to caller rs_fin: add SP,offset rs_BP ; deallocate local storage pop BP ; restore the caller's BP register pop ES ; restore the caller's ES register ret ; return to caller ; x_long: inc SI ; increment index into saved screen inc SI ; buffer jmp short x_more ; continue processing row rest%scr endp ;************************************************************************ ;* Graphics Character Attribute * ;* * ;* Purpose: To retrieve the attribute of a character on an IBM screen * ;* in a graphics mode, either 14 or 16. * ;* * ;************************************************************************ public graph_attr graph_attr proc near cmp AL,20h ; skip if a space je grphend cmp AL,00h ; skip if a null je grphend cmp AL,0dbh ; block character? je grphend push ES push SI push AX ; save character push DX ; save row and column xor AH,AH ; clear AH mov SI,AX ; use SI as an index sub SI,21h mov AL,DL ; row mul char_hgt ; pixels per character xor BX,BX mov BL,byte ptr m18_attr[SI] ; default mode 18 adjustment cmp vid_mode,18 ; are we in mode 18? je grph_02 ; yes, jump mov BL,byte ptr m16_attr[SI] ; default mode 16 adjustment cmp vid_mode,16 ; are we in mode 16? je grph_02 ; yes, jump mov BL,byte ptr m14_attr[SI] ; must be mode 14 grph_02: add AX,BX mov BX,80 ; 80 bytes per line mul BX pop DX ; restore the column xor DL,DL ; clear the row xchg DH,DL ; set AX to the row add AX,DX mov SI,AX ; put result in SI mov AX,0a000h ; load in graphics plane mov ES,AX xor CX,CX ; clear CX mov CH,01 mov AH,0 grph_03: call get_val shl CH,1 ; shift mask one bit to the left inc AH ; next plane cmp AH,3 jbe grph_03 pop AX ; retrieve character mov AH,CL ; set attribute byte pop SI pop ES grphend: ret graph_attr endp get_val proc near push AX ; save AH mov DX,3ceh ; port addr of sequencer mov AL,04h ; index to other map mask register out DX,AL ; set index register inc DX xchg AL,AH out DX,AL ; enable bank pop AX ; restore AH mov AL,ES:[SI] or AL,AL jz get_end or CL,CH ; set attribute bit get_end: ret get_val endp PROGX ends end