; Screen driver for Heath-19 ; by Harold F. Bower and Bridger Mitchell ; 26 September 1986 ; .title 'H19SCRN bg ii Screen Driver' ; ; M80 or ZAS Z80 assembler. ; FALSE equ 0 TRUE equ NOT FALSE ; ;..... ;Particular features of Heath-19 code: ; ; H19 sends a stream consisting of successive chars, with ESC sequences ; preceeding any change in reverse/normal video and graphics/normal ; character set. Several upgrade modes support a "native" mode with ; the 2-character ESC - char sequence replaced by 1 8-bit character. ; This code automatically detects and supports both modes FROM the ; terminal, and always sends in 7-bit mode TO the terminal, for complete ; compatibility. ; Consta equ 0 Conin equ 0 Conout equ 0 Outch equ 0 Puts equ 0 Bwrch equ 0 Bflush equ 0 ; ; ascii equates ; BELL EQU 07H BS EQU 08H CR EQU 0DH LF EQU 0AH ESC EQU 1BH SPACE EQU 20H DEL EQU 7FH ; ; CUT command characters ; HOME EQU 'H' ;home the cursor MARK EQU 'X' ;set a mark PASTE EQU 'P'-40H ;paste region at cursor CANCEL EQU 'C'-40H ;cancel cut command ; ; TERMINAL-SPECIFIC EQUATES ; ; ; Cursor movement controls for Heath-19/89 ;----------------------------------------- ;=== WordStar-like ; WSLFT EQU 'S'-40H WSRIT EQU 'D'-40H WSUP EQU 'E'-40H WSDWN EQU 'X'-40H WSINS EQU 'V'-40H WSDEL EQU 'Y'-40H ; ;=== ESCape sequence arguments ; LEFT EQU 'D' RIGHT EQU 'C' UP EQU 'A' DOWN EQU 'B' INSERT EQU 'L' DELETE EQU 'M' ; ; ; Heath-19 screen parameters ; NCOLS EQU 80 NROWS EQU 25 NROW24 EQU 24 ;# rows excluding status line ; SCRSIZ EQU NCOLS*NROWS CRBIAS equ 20H ; Bias for cursor positioning ; ; Heath-19 Escape argument characters ; CLRSCR equ 'E' ; Clear screen & Home cursor GRON equ 'F' ; Graphics mode on GROFF equ 'G' ; Graphics mode off REVON equ 'p' ; Reverse video mode on REVOF equ 'q' ; Reverse video mode off SNDPAG equ '#' ; Send lines 1-24 from screen SND25 equ ']' ; Send line 25 from screen SNDCUR equ 'n' ; Send Cursor position as ; ; Flag bits in status register ; TOSCR$ equ 0 ; Send to screen GRAPH$ equ 1 ; Graphics sequence active REV$ equ 2 ; Reverse video sequence active ESCMOD equ 3 ; ESCape sequence ; ;========================= ; org 3F80H ; Module name sector ; ; db 'Heath 19/89 26 Sept 86',0 ; ;------------------------- ; org 4000H ; ;------------------------------------------------------------ ; Start: ; ; Start of Screen Module. Assemble to run at 4000h. ; ;***** MODULE ENTRY HEADER ; ; EXTERNAL ADDRESSES, supplied by loader ; JJcons: jp Consta ; BIOS constat JJconi: jp Conin ; BIOS conin JJouta: jp Outch ; A to conout, preserving BC,DE,HL JJputs: jp Puts ; HL-string to conout, NUL/bit-7 term. ; preserving BC,DE,HL JJbrdc: jp 0000 ; Buffered read char from cut-swp JJbwrc: jp Bwrch ; Buffered write char to cut-swp JJbflu: jp Bflush ; Flush (write) buffer ; ; INTERNAL ENTRY POINTS ; Savscr: jp Savpag ; Save screen Resscr: jp Respag ; Restore saved screen Lastnb: jp Lstnbl ; Last non-blank char in rows 1-24 Dmpchr: jp Retnch ; Return next screen char Dmpcur: jp Retncu ; Return buffer cursor Dmpatt: jp Retnat ; Return next screen attribute Setmrk: jp Stmrks ; Set region marks, move cursor Cutrg: jp Docut ; Cut region Pastrg: jp Dopaste ; Paste region Ininpd: jp Ininot ; Initialize jotpad Putnpd: jp Putnch ; Put char to jotpad ; ;======================================== ; Ininot: ; << Generic >> ; ; Initiate Jotpad - clear screen, print banner. ; ld hl,zbanner jr JJputs ; ;======================================== ; Retncu: ; << Generic >> ; ; Return buffer cursor as row/col. ; ; RET: D = binary row, E= binary col ; L = ascii row, H = ascii col (for shld ...) ; ld hl,(bcursor) ; ; Convert offset to col/row. ; EXIT: D = binary row, E = binary col ; H = ascii col, L = ascii row <-- NOTE ORDER ; Off2cr: ld b,0 ; Convert to row,col ld de,-NCOLS Off2c1: add hl,de jr nc,Off2c2 inc b ; Increment row count jr Off2c1 Off2c2: ld de,NCOLS add hl,de ld a,l ; Col ld e,a ; Binary col in E ld d,b ; Binary row in D add a,CRBIAS ; + bias ld h,a ; H = ascii col ld a,b ; Row add a,CRBIAS ; + bias ld l,a ; L = ascii row ret ; ;======================================== ; Dopaste: ; <> ; ; Paste the last-cut region onto active screen at the current cursor. ; For H-19, only use lines 1-24 due to scroll problem in line 25, ; and to not paste to the last character position in line 24 for the ; same reason. ; ; 1. Get previously-cut region from external routine ; 2. Send chars to screen, avoiding boundary overflows. ; ; 'savpag' not needed if terminal supports 'send cursor address' ; ; call Savpag ; Get current screen, ; in order to find cursor ld b,4 ; Read 4 data bytes Dopas0: push bc call JJbrdc pop bc djnz Dopas0 ; ld b,a ; 4th byte is # rows push bc call Crs2hl ; current cursor's row/col to hl pop bc ; ; Loop over rows ; Prowlp: push bc push hl ld e,l ; E = col no. push de call Stcrshl ; Set cursor at H,L Pcollp: call JJbrdc ; Read char from cut-swp cp CR jr z,Prend ld c,a ; Save char pop de ; Check for off screen ld a,e cp NCOLS inc e push de ; row/col to stack call c,Sendc ; to conout, unless off edge jr Pcollp ; Prend: pop de ; Clear row/col pop hl pop bc inc h ; Bump row ld a,h ; Check for off bottom of screen cp NROW24 ; Use NROWS if 25th line scrolls jr nc,Pxit djnz Prowlp Pxit: xor a ret ; ;======================================== ; Docut: ; << Generic >> ; ; Cut rectangular region defined by keypresses. ; 1. Parse keypresses to move cursor and mark corners. ; Highlight region as cursor is moved. ; ; NOTE: The last char in row 24 of the Heath-19 is not ; marked due to scroll effects if line wrap is ON. ; ; 2. Send the marked region, row-wise to external routine. ; Append CR after each row. ; ; Data structure is: ; size (word) ; # columns (byte) ; # rows (byte) ; row 1 ; CR ; row 2 ; CR ; .... ; xor a ld (mrkcnt),a ;init for next time ; ; Set ctcols = # cols, ctrows = # rows ; (assumes mark2 is SE of mark1) ; Cornrs: ld de,(mark1) ld hl,(mark2) ld a,h ; # rows = 1 + mark2row - mark1row inc a sub d ld h,a ld a,l ; # cols = 1 + mark2col -mark1col inc a sub e ld l,a ld (ctcols),hl ; ; Cut rectangle [mark1...mark2] & copy to buffer ; Append CR at end of each row ; ex de,hl push hl ; Mark1 call Wrpara ; Write parameters pop hl ; Mark1 call Rc2off ; Convert to screen addr ld a,(ctrows) ; Get # rows ld b,a ; ; write the cut region to external buffer ; DCrwlp: push bc ; (+1 push hl ; (+2 ld de,buf ; Fetch from screen buffer add hl,de ; ; write 1 row of cut region to external buffer ; ld a,(ctcols) ld b,a ; B = # cols call Bwrthl ld c,CR ; Append CR to each row call JJbwrc ; pop hl ; (+1 pop bc ; (+0 ld de,NCOLS ; Bump to next row add hl,de djnz DCrwlp ; and loop jp JJbflu ; Flush the write buffer ; ; Write parameters: size, # cols, # rows to swp file ; DE contains CTCOLS on entry ; Wrpara: ld b,d ; # rows ld d,0 inc e ; +1 for CR ld hl,0 ; accum. Wrpar0: add hl,de djnz Wrpar0 ld (ctsize),hl ld b,4 ; Write 4 bytes of parameters ld hl,ctsize ; ; Buffered write B chars at HL ; Bwrthl: push bc push hl ld c,(hl) call JJbwrc pop hl pop bc inc hl djnz Bwrthl ret ; ;======================================== ; Lstnbl: ; << Generic >> ; ; Find last non-blank line (1-24 only) in current scr buffer. ; Graphics characters are considered blanks. 8-bit values ; (reverse video) are masked to see if they are valid chars. ; If B = 0FF, save screen first. ; ; RETURN: H = row, L = col of last non-blank char in rows 1-24 ; inc b call z,Savpag ld bc,NROW24*100H+NCOLS ; B=# rows, C=# cols ld de,buf ld hl,0 Lstlp: ld a,(de) and 7FH ; Turn off any reverse video cp SPACE+1 ; Don't count cntl chars or SPACE jr c,Lst1 cp DEL ; or DEL or graphics 8-bit jr nc,Lst1 ld (savrc),hl Lst1: inc de inc l dec c jr nz,Lstlp ; Loop over cols inc h ld l,c ; 0 ld c,NCOLS djnz Lstlp ; Loop over rows savrc equ $+1 ld hl,0000 ; HL = last non-blank ret ; ;------------- Generic Support Routines -------------- ; Xring: ld c,BELL ; ; send C to screen, exit Z, no CY ; Sendc: ld a,c ; send A to screen, exit Z, no CY ; (this will scroll, however!) ; Send: call JJouta xor a ; Z, no CY ret ; ;============================================ ; E N D O F G E N E R I C C O D E ;============================================ ; Putnch: ; << Specific >> ; (Was generic til cursor controls added) ; ; Put char in A to jotpad (screen) ; Convert CR to CRLF, DEL to rubout, 8-bit codes ; to ESC-n sequences. ; cp CR ld hl,zcrlf ; Convert CR to CR,LF jp z,JJputs cp DEL ld hl,zrub jp z,JJputs bit 7,a ; 8-bit code? jr nz,Wrt8th ; cp WSLFT ; Use WS-like commands? jr z,Wrtlef cp WSRIT jr z,Wrtrit cp WSUP jr z,Wrtup cp WSDWN jr z,Wrtdwn cp WSDEL jr z,Wrtdel cp WSINS jp nz,JJouta ; ...fall thru ld a,'L' ; ESC code for Insert line jr DoWrt ; Wrtlef: ld a,'D' ; ESC code for Left curs jr DoWrt ; Wrtrit: ld a,'C' ; ESC code for Right curs jr DoWrt ; Wrtdwn: ld a,'B' ; ESC code for Down curs jr DoWrt ; Wrtup: ld a,'A' ; ESC code for Up curs jr DoWrt ; Wrtdel: ld a,'M' ; ESC code for Delete line ; ...and fall thru... Wrt8th: and 7FH ; Mask 8th bit and send as ESC-n DoWrt: jp Jptesc ; ;=========================================== ; Stmrks: ; << Specific >> ; ; Move cursor and set marks. Return CY clear until exit. ; NOTE: For Heath-19, the last character in line 24 is ; NOT highlighted since that causes the entire ; screen to scroll if Line Wrap is ON. ; ; 1. move cursor, until: ; 2. 'X' = set 1st mark ; turn on hiliting, set mark, keep cursor at mark ; 3. move cursor right/down only ; 4. 'X' = set 2nd mark ; turn off hiliting, set 2nd mark ; exit CY (done) ; 5. cntl-C = CANCEL. ; turn off hilighting, set CY, exit ; ; cp ESC jr nz,Stmrk0 ; Continue if not Escape ld a,0FFH ; ..else set flag ld (mrkesc),a xor a ; Return for next char ret ; Stmrk0: bit 7,a ; Is it an 8-bit command? jr nz,Stmrk1 ; ..do short jump if so. push af ld a,(mrkesc) ; Is this ESC argument? or a ld a,0 ; (always reset flag) ld (mrkesc),a jr z,Stmrk2 ; Jump if not ESC argument pop af Stmrk1: and 7FH ; Mask MSB in case 8-bit code cp LEFT ; ..process argument characters jp z,Goleft cp UP jp z,Goup cp RIGHT jp z,Gort cp DOWN jp z,Godn xor a ; Clear for next char.. ret ; ..if not one of these ; Stmrk2: pop af cp CANCEL jr z,Abort cp WSLFT jp z,Goleft cp WSUP jp z,Goup cp WSRIT jp z,Gort cp WSDWN jp z,Godn cp CR jr z,StmrkA and 5FH ; Convert to Ucase cp MARK jr z,StmrkA cp HOME jr z,Gohome xor a ;no action ret ; StmrkA: ld hl,mrkcnt ;if no mark yet set ld a,(hl) or a ld (hl),1 jr z,Mk1 ;..set mark1 call Mk2 ;else set mark2 Mrkxit: xor a ld (mrkcnt),a ;init for next time scf ;CY = all done ret ; abort: call Normal ;restore normal video ld a,CANCEL jr Mrkxit ; ;------------------------------------------- ; ; Set 1st mark, turn on rev. video, don't move cursor ; Mk1: call Crs2hl ld (mark1),hl ld (mark2),hl ld (curcol),hl ; L -> curcol, H -> currow push hl call Revers ; Reverse video on ; ; Set single character under cursor to reverse video ; pop hl ; Mark1 ld a,1 ; Reverse 1 char ld (colct),a ld (rowct),a push hl call Showro pop hl jp Stcrshl ; Set cursor to start ; ; Set 2nd mark, restore normal video, set CY ; Mk2: call Crs2hl ld (mark2),hl call Normal ; Restore normal video scf ; CY = all done ret ; ;-------------------------------------------- ; Home cursor if no mark yet set ; Gohome: ld c,'H' ; Convert to video driver's cntl char jr Ckmcnt ; ; Move cursor up one line if no mark yet set ; Goup: ld c,'A' ; 7-bit code for UP jr Ckmcnt ; ; Move cursor left if no mark yet set ; Goleft: ld a,'D' ; 7-bit code for LEFT Mvcurs: ld c,a Ckmcnt: ld a,(mrkcnt) ; Send cursor-move char or a ret nz ; ..unless mark1 already set ld a,c jp Jptesc ; ..else send ESC then char in A ; ; Move cursor right setting reverse video if mark already set ; Gort: ld a,'C' ; 7-bit code for RIGHT call Jptesc ; Position cursor ld a,(mrkcnt) or a ; Quit here if no mark set ret z ; ; Hilite marked column if not already at right limit ; Set cur at toprow, next col ; Send partial column ; colcnt++ ; Gort1: ld hl,mark2 ld a,NCOLS-2 cp (hl) ; Ring bell if already in last column Jcring: jp c,Xring inc (hl) ; Bump 2nd mark-row ld hl,curcol inc (hl) ; Bump column ld l,(hl) ld a,(mark1+1) ; Top row ld h,a ; H = row, L = col to hilite rowct equ $+1 ld b,00 ; ; Loop over each row in cut region ; Gorlp: push bc push hl ; Save binary row/col ld a,1 ; Display 1 char in each row call Showhi pop hl pop bc inc h ; Next row djnz Gorlp ld hl,colct ; Prepare to bump col cnt & exit jr Inrmbs ; ; Move cursor down setting reverse video if mark set ; Godn: ld a,'B' ; 7-bit code for DOWN call Jptesc ; Move cursor down ld a,(mrkcnt) or a ret z ; quit here if no marks ; ; Set reverse video on marked row if not already at bottom ; set cur at next row, left col ; send partial row ; rowcnt++ ; Godn1: ld hl,mark2+1 ; Row ld a,NROWS-2 cp (hl) ; Ring bell if on bottom line jr c,Jcring inc (hl) ; Bump 2nd mark-col ld hl,currow ; Bump row inc (hl) ld h,(hl) ld a,(mark1) ; Left col ld l,a ; H = row, L = col for row to hilite call Showro ; Display 1 cut row ld hl,rowct ; Bump row cnt Inrmbs: inc (hl) ; and exit ld hl,(curcol) jp Stcrshl ; ;-------------- ; Fetch A chars at H=binary row, L=binary col from buffer. ; Put chars to screen, setting REVERSE VIDEO attribute. ; All registers used. ; ; ENTER: H = binary row, L= binary col ; EXIT: CY flag clear ; Showro: colct equ $+1 ld a,00 ; Showhi: push af ld a,h ; Are we on bottom line? cp NROWS-2 jr nz,Show1 ; ..jump if not pop af push af ; Restore char count add a,l ; ..add to start column cp NCOLS ; Will it end in last column? jr c,Show1 ; ..jump if not pop af dec a ; Else let it end in next-to-last jr z,Show2 ; ..Quit if char cnt = 0 push af Show1: push hl call Stcrshl ; Set cursor to start marked area pop hl call Rc2off ; Convert cursor to offset ld de,buf ; ..add buffer start address add hl,de pop af ; # chars ld b,a Showlp: ld c,(hl) ; Fetch char from buffer push hl push bc call Sendc ; Put to screen pop bc pop hl inc hl djnz Showlp Show2: or a ; Clear CY ret ; ;======================================== ; Retnch: ; << Specific >> ; ; Return next screen char from buffer. ; ; ENTER: D = row, E = col ; B = FF ==> read screen ; C = FF ==> set bufptr ; EXIT: A = char, CY set if good ; DE -> row,col of next char, HL -> buf of next char ; CY clear if out of range ; ; This routine can be called to get successive chars from ; buffer as long as caller preserves hl,de and sets b=c=0. ; xor a call Stdump ret nc ld a,(hl) ; Get char inc hl ; bump bufptr ret ; ;-------------------- ; ; ret: NC if out of range ; else hl-> buffer char ; Stdump: inc b jr nz,Stdum0 push bc ; B = FF ==> Read screen push de push hl call Savpag pop hl pop de pop bc Stdum0: inc c jr nz,Conv4 ; ; ENTER: D = row, E = col ; SET: HL -> buffer address, CY set, preserve DE ; RETURN: CY clear if error (off screen) ; ld a,d ; C = FF ==> set bufptr cp NROWS jr nc,ConBAD ld a,e cp NCOLS jr c,ConvOK ConBAD: xor a ; Out of range, ret NC ret ; ConvOK: push de ; Preserve col/row ex de,hl call Rc2off ; Convert to Offset in HL ld de,buf ; ..from buffer base add hl,de pop de ; ..restore col/row ; ..fall thru.. Conv4: inc de ; Bump col ld a,e cp NCOLS ret c ld e,0 ; End of row, set col = 0 inc d ; and bump row ld a,d cp NROWS ret ; NC if out of range ; ;======================================== ; Retnat: ; << Specific >> ; ; Return next screen attribute from buffer. ; NUL FUNCTION for Heath-19. ; ; ENTER: D = row, E = col ; B = FF ==> read screen ; C = FF ==> set bufptr ; EXIT: A = attr, CY set if good ; DE -> row,col of next char, HL -> buf of next char ; RETURN: CY clear if out of range ; xor a ; Clear CY ret ; ;======================================== ; Savpag: ; << Specific >> ; ; Save screen to buffer. ; ;; ld hl,Zheath ; If needed, put in ANSI mode ;; call JJputs call Getcu ; Get ASCII row/col cursor ld (colrow),hl call Get124 jr Get25 ; ; Get lines 1-24 ; Get124: ld a,SNDPAG ; Tell terminal to send 1-24 call Jptesc ld hl,buf call Getrgn ld (ptr25),hl ret ; ; Get 25th line ; Get25: ld hl,z25on ; Turn on status line call JJputs ld a,SND25 ; Tell terminal to send row 25 call Jptesc ld hl,(ptr25) ; ...fall thru... ; ; Get region to the HL buffer ; Getrgn: ld c,0 Getplp: push hl push bc call JJconi ; Get a char pop bc pop hl cp ESC ; Is this an escape? jr z,Getpl1 cp CR ; Is this the end? ret z bit ESCMOD,c ; Was last char=ESC? jr nz,Getpl2 ; ..jump if so bit GRAPH$,c jr z,Getplr ; Jump if not graphic sub 5FH ; make binary res 7,a ; 5E-->7FH ld (hl),a ; Getplr: bit REV$,c jr z,Getpl0 ; Jump if not reverse video set 7,a Getpl0: ld (hl),a inc hl ; Bump ptr.. jr Getplp ; ..loop ; Getpl1: set ESCMOD,c ; Flag next as argument jr Getplp ; Getpl2: cp REVON jr z,Ron cp REVOF jr z,Roff cp GRON jr z,Gon cp GROFF jr nz,Getpl3 ; Reset esc & loop res GRAPH$,c jr Getpl3 ; Ron: set REV$,c jr Getpl3 ; Roff: res REV$,c jr Getpl3 ; Gon: set GRAPH$,c Getpl3: res ESCMOD,c jr Getplp ; ;======================================== ; Respag: ; << Specific >> ; ; Restore saved screen from buffer. ; NOTE: For the Heath-19, the last position in row 24 ; is NOT restored since that causes the entire ; screen to scroll if Line Wrap is ON. ; ld a,CLRSCR ; Clear screen call Jptesc call put124 ; Restore rows 1 thru 24.. call put25 ; ..and 25 ld hl,zcurs ; Restore cursor call JJputs call Nogrph ; Finish with graphics OFF.. jp Normal ; ..and return to normal video ; ; To screen, line 25 ; Put25: ld hl,y0row ; Set cursor position for.. ld (hl),NROWS-1+CRBIAS ; ..row 25, col 0 dec hl ; Point to string start dec hl call JJputs ; Position cursor ld a,1 ; Send 1 line ld hl,(ptr25) jr Putsc1 ; ; To screen, lines 1-24 ; Put124: ld hl,y0row ; Set cursor position for.. ld (hl),1-1+CRBIAS ; ..First row, col 0 dec hl ; Point to string start dec hl call JJputs ; Position cursor ld hl,buf ld a,24 ; Send 24 lines Putsc1: ld c,0 ; Normal video, no graphics ; Putlp: ld (lincnt),a ; Store number of lines left ld b,NCOLS ; ..set # of chars per line ld a,(y0row) cp NROW24-1+CRBIAS ; If this is line 24... jr nz,Putlp0 dec b ; ..don't write in last position Putlp0: push hl ; Save buffer address call Sndprc ; Send processed char.. call Send ; ..to screen pop hl inc hl djnz Putlp0 ; Loop on line push hl ld hl,y0curs ; Return to left col at each line end call JJputs pop hl ld a,(lincnt) dec a ; Any more lines? jr z,PutlpZ ; ..jump if not push af push hl ld hl,y0row ; Position to next line down inc (hl) ; ..by bumping cursor address dec hl ; Back to string start dec hl call JJputs ; ..and position pop hl pop af jr Putlp ; PutlpZ: ld (ptr25),hl call Ptgrof jp Normal ; Set screen to normal ; ; Process character sending appropriate ESCape sequences ; and setting flags. ; Sndprc: ld a,(hl) push af bit 7,a ; Check for reverse video jr z,Sndpr0 ; ..jump if not call Putrev pop af and 7FH ; Restore char masking MSB push af jr Sndpr1 ; Sndpr0: bit REV$,c ; See of flag on.. call nz,Ptroff ; ..and reset if so pop af push af ; Sndpr1: cp ' ' jr c,Putgph ; Jump if graphic cp DEL ; 7FH is also graphic jr z,Putgph bit GRAPH$,c call nz,Ptgrof pop af ret ; Putgph: bit GRAPH$,c call z,Ptgron pop af add a,5FH ; Make printable char and 7FH ; ..mask off MSB ret ; ; Set to reverse video mode if necessary ; Putrev: bit REV$,c ret nz ; ..already there, return ; ..else fall thru.. ; ; Update the flag ; Putron: set REV$,c Revers: ld a,REVON ; Turn on reverse video jr Jptesc ; Ptroff: res REV$,c Normal: ld a,REVOF ; Turn off reverse vidso jr Jptesc ; Ptgron: set GRAPH$,c ld a,GRON ; Turn on graphics jr Jptesc ; Ptgrof: res GRAPH$,c Nogrph: ld a,GROFF ; Turn off graphics Jptesc: push af ; Send ESCape followed by char in A ld a,ESC call Send pop af jp Send ; ;---------- Cursor Conversion Routines ---------- ; ; Convert binary row/col to relative offset ; Enter: H=binary row, L=binary col ; Exit: HL = Binary offset (HL = row * NCOLS + col) ; Uses: BC, DE, HL ; Rc2off: ld b,h ; B = row ld c,l ; C = col ld hl,0 inc b ld de,NCOLS jr Rc2bot Rc2of0: add hl,de ; Rows * NCOLS Rc2bot: djnz Rc2of0 add hl,bc ; Add col ret ; ;============ Cursor Positioning Routines ============== ; ; Set cursor on screen. ; Enter: H=binary row, L = binary col ; Stcrshl: call Rc2off ; ...fall thru... ; ; Set cursor on screen by direct cursor addressing. ; Enter: HL = cursor offset relative to 0000 ; Stcrs: call Off2cr ; Convert from offset to ascii col/row ld (colrow),hl ; Put ascii col/row into string ld hl,zcurs ; Send set-cursor string jp JJputs ; ;------------- ; ; Get current cursor position. ; Exit: H=binary row, L=binary col ; Uses: A, HL ; Crs2hl: call Getcu ; Get cursor by querying terminal ld a,h ; Convert ASCII to binary.. ld h,l ; ..and reverse order sub CRBIAS ld l,a ld a,h sub CRBIAS ld h,a ld (bcursor),hl ; Save it ret ; ;------------- ; ; Get cursor position, checking for 8-bit mode ; Exit: HL Contains ASCII H=col, L=row ; Uses: A, HL ; Getcu: ld a,SNDCUR call Jptesc call JJconi bit 7,a ; If 8-bit mode, skip call z,JJconi call JJconi ; Get row ld l,a push hl call JJconi ; Get col pop hl ld h,a ret ; ;****************************************** ; ; DATA AREA ; ; cut-region data ; ctsize: dw 0 ; (# cols + 1) * (# rows) ; ctcols: db 0 ; # cols in cut region (excl. CR), A PAIR ctrows: db 0 ; # rows ; ptr25: dw 00 ; Pointer to 25th line lincnt: db 0 ; Line counter for put-page ; ; mark-region data ; mrkcnt: db 0 ; curcol: db 0 ; A PAIR currow: db 0 ; mark1: dw 0 ; Binary row,col of upperleft mark mark2: dw 0 ; Lower right mark ; mrkesc: db 0 ; Flag for ESC sensing ; ZRUB: DB BS,SPACE,BS+80H ; Rub-out previous char ; ;**************************************** ; ; TERMINAL-SPECIFIC data ; Heath-19 ; ; ...Cursor lead-in and command strings ; zcurs: db ESC,'Y' ; Set cursor to.. colrow: db ' ' ; row,col - modified in-line db 0 ; Must have following NUL ; y0curs: db ESC,'Y' ; Working positioning sequence y0row: db 20H,20H!80H ; Cursor at line nn, col 0 ; z25on: db ESC,'x','1'!80H ; enable 25th line ; ; ...Other sequences for Heath-19 ; ;z8bits: db ESC,'e','C'!80H ; UNUSED. Put in 8-bit mode ; zheath: db ESC,'[','?','2','h' ; Enter Heath mode ; ;================================ ; ; NOTEPAD BANNER ; ; 1. Clear screen. ; 2. Remind user of usage, to extent space is available. ; zbanner: db ESC,CLRSCR ; Clear screen HEATH-19-SPECIFIC ; db 'JOT: = exit, ' db '^V = ins line, ^Y = del line',CR,LF db ' ^E - up, ^X - down, ' db '^S - left, ^D - right' ; zcrlf: db CR,LF!80H ; codlen equ $-start ; Length of code ; ;++++++++++++++++++++++++++++++ ; ; SCREEN BUFFER STRUCTURE ; ; The rest of the 4K block is available for the screen image and other data. ; xbreq equ 2 + nrows*ncols ; ; put buffer at end of 4K area, to just fit ; bstart equ [start + 400H] + [3*400h-xbreq] ; short equ start+codlen-bstart xfree equ - short ; IF [SHORT] defb '[07]Code overflows buffer!' ENDIF ; ; addresses: ; bcursor equ bstart ; Cursor location in saved screen buf equ bcursor+2 ; Start of screen buffer ; ; Buffer uses (25 lines x 80 chars) ; bufend equ buf+NROWS*NCOLS ; ; end JJcons