; MODULE: ZERRED 1 Line Editor ; AUTHOR: Rob Friefeld ; DATE: August 4, 1991 ; For ZERR 1.5C ; Simplified some code in this module. RDF ; ; For ZERR 1.5 ; Changed the name of this module to ZERRED (six characters) so ; that it can be '.REQUEST'ed from ZERR15.REL when linking. ; ; Changed to treat CMDLEN as an external Word. (Changed ZERRCMD.INC) ; Now works with all known PRL linkers. Joe Wright 14 Sept 90 ; ;========================================================================= ; ; D E F I N I T I O N S S E C T I O N ; ;========================================================================= ; EXTERNALS: ; LINE - Location of line buffer ; INS_FLAG - Insert/overwrite (00 or FF) ; BSP_FLAG - Destructive backspace ; CMD_LIST - List of commands keys ; CMDLEN - Length of command list ; CONOUT,CIN,CAPS - Using BDOS ; ZERRDEF.LIB ; LBUFWID - Size of line buffer (byte constant, recommend 0FFh) ; rcEXEC, rcABRT, rcCONT - defined editor return codes ; System Libraries ; EREOL ; ; ; ENTRY: Call EDIT ; RETURN: A = code ; rcEXEC = proceed (CR) ; rcABRT = quit (ESC) ; rcCONT = skip (TAB) include SYSDEF.LIB ; Standard definitions include ZERRDEF.LIB ; Common program modules defs public edit ;VLIB ext ereol ;ZERR16 ext line,ins_flag,bsp_flag,cmd_list,cmdlen ext conout,cin,caps ;========================================================================= ; ; M A I N C O D E S E C T I O N ; ;========================================================================= ; While editing ; HL -> current position in LINE buffer ; B = char count of line ; C = cursor position (0 .. count) ; DE = scratch ; Line is always 0 terminated ; Entry point edit: ld hl,line ; Init to start of line xor a ld b,a ; Char count = 0 ld c,a ; Cursor pos = 0 push hl ; Count up line already in buffer dec b edit1: inc b ; Line count accum in B cp (hl) ; A = 0 inc hl jr nz,edit1 edit2: pop hl call ptail ; Print the line from cursor position ;-------------------------------------------------------------------- ; EDIT COMMAND LOOP ; ; Get a char. If it is text, enter it. If it is a control, scan the ; CMD_LIST for a match. If found, compute offset into jump table and go. ; A "shifted" key (high bit set in table) is matched after the "meta-key" ; has been entered. ecmd: exx ; Main regs must be preserved ld hl,ecmd ; Save address so a return comes back here push hl no_match: exx ; Recover main regs call CIN ; Next key... exx ; Save main regs ld hl,meta_flag or (hl) ; Mask in possible shift flag ld (hl),0 ; Reset flag exx ; Recover main regs cp 20h jr c,control_key ; Not text cp del ; This control char > text chars jp c,enter ; Input text control_key: call menuinp ; Convert control char to cap exx ; Save main regs ld hl,cmd_list ; Scan command list ld bc,(cmdlen) ; Now an external Word (jww) cpir jr nz,no_match ld hl,cmd_vector ld a,(cmdlen) ; (jww) dec a sub c add a,a ld c,a add hl,bc ld c,(hl) inc hl ld b,(hl) push bc exx ; Recover main regs! ret ; Convert a control key entry to cap char ; menuinp: push af and 80h ; Keep high bit ld e,a pop af and 7fh call ucase or e ; Restore high bit ret ; Mark meta-key flag ; meta_key: ld a,10000000b ld (meta_flag),a ret meta_flag: db 0 cmd_vector: dw meta_key dw bspopt ; Backspace dw bsp dw fsp dw bwrd dw fwrd dw linend ; Line end or start dw linbeg dw linend1 dw delete dw delft dw delwrd dw delwlft dw dline dw deleol dw instog dw ctl_entry dw edexit ; CR dw esc_key dw tab_key dw delcmd_key ;-------------------------------------------------------------------- ; ON LINE ROUTINES, EDITING CURRENT LINE IN LINE BUFFER ; ; The command line is copied into the line buffer and edited there. ; WHILE ON LINE: ; B = CHAR COUNT (0..lbufwid) C = CURSOR POSITION (0..lbufwid) ; HL = MEM POINTER ; Backspace key ; Test bsp_flag for destructive v. non-destructive bspopt: ld a,(bsp_flag) or a jr nz,delft ; Cursor left ; Return Z = backspace not done, NZ = all OK bsp: xor a cp c ; Cursor pos ret z ; At start dec hl ; Back up in mem dec c ; If c->0, permit deletion anyway bspace: ld a,bs ; Back up on screen or a jp conout ; Forward space ; Return Z = not done fsp: ld a,(hl) or a ret z inc hl inc c jp pctl ; Screen advance by reprinting char ; Back word bwrd: call bsp ret z ; No where to go ld a,(hl) cp ' ' jr z,bwrd ; Backspace over blanks dec hl ; Now backspace until next wordsep call wrdsep inc hl jr nz,bwrd ret ; Forward word fwrd: call wrdsep ; Are we on a word separator? jr z,fwrd1 ; Yes call fsp ; No, advance until we find one jr fwrd fwrd1: call fsp ; Word sep found, advance 1 more space ld a,(hl) ; Are we on a blank? cp ' ' jr z,fwrd1 ; Don't quit on a blank ret ; Delete char left delft: call bsp ; Backspace and fall through to delete ; Delete char delete: call delmem ; In memory jp ptail ; Refresh screen from cursor position ; Delete word left delwlft: call bwrd ; Delete word right delwrd: call wrdsep ; On a word sep? jr z,delete ; Yes, kill it ld a,b cp c jr z,delete ; On last char of line delwrd1: call delmem ; Delete in mem, let screen catch up later jr delwrd ; Go until word sep found ; Delete to next command separator delcmd_key: ld a,(hl) cp cmdsep jr z,delete ; Yes, kill it ld a,b cp c jr z,delete ; On last char of line call delmem ; Delete in mem, let screen catch up later jr delcmd_key ; Go until word sep found ; Delete line dline: call linbeg ; Delete to eoln deleol: call ereol ; Clear on screen ld b,c ; Char count = current position ld (hl),0 ; Line terminator ret ; Insert/overwrite toggle instog: ld a,(ins_flag) ; Flag 0 -> owrt cpl ld (ins_flag),a ret ; Enter a control ctl_entry: call CIN and 1fh ; Enter a char enter: ex af,af' ; Save char ld a,b ; At eoln? cp c jr z,ovrwrt ; Yes, no need for insert mode ld a,(ins_flag) ; Which mode are we in? or a ; 0 = overwrite, nz = insert jr nz,insert ; Enter char in overwrite mode ovrwrt: ld a,c ; Cursor pos cp lbufwid-2 ret nc ; Line full AND at EOLN ovr1: ex af,af' ; Recover char ld (hl),a ; Put char in place call fsp ; Advance by printing it ld a,b ; Char count -> a cp c ret nc ; Inside line, no need to inc char count inc b ; ...else add to count ld (hl),0 ; ...and terminate ret ; Enter char in insert mode insert: ld a,b ; Line full? cp lbufwid-2 ret nc ; Make a hole in the line buffer at current position insmem: ld a,b ; Char count sub c ; A = # chars to eoln jr z,insert1 ; At end, don't need any space push hl exx ; Save on-line environment pop hl ld c,a ; Bc = # chars to move xor a ld b,a add hl,bc ; New EOLN ld d,h ; Now in DE ld e,l inc hl ld (hl),a ; Insure a line terminator dec hl ; Back up to.. dec hl ; ..current EOLN lddr ; Tail move exx ; Recover our starting position insert1: ex af,af' ; Recover new char ld (hl),a ; Place char in line call ptail ; Reprint entire line from here inc b ; Inc char count jp fsp ; Advance cursor ; Line end/start toggle linend: ; Go to soln or, if there, to eoln xor a or c jr nz,linbeg linend1: call fsp ; Print ahead until EOL jr nz,linend1 ret linbeg: call bsp ; Backspace until start jr nz,linbeg ret ; Compare current char to list of word separators wrdsep: push hl push bc ld bc,wrdseplen ld a,(hl) ld hl,wrdseps cpir pop bc pop hl ret wrdseps: db 0,tab,' ,;:.=' ; Punctuation word separators wrdseplen equ $ - wrdseps ; Delete current char from line delmem: ld (hl),0 ; Terminal 0 or char to be deleted ld a,b sub c ; A = (count-position) = chars from end ret z ; At eoln, no char dec b ret z ; Single char line dec a ret z ; On last char, just deleted it delmem1: inc a ; To move terminal 0 in push hl exx pop hl ld d,h ; Dest is current pos ld e,l inc hl ; Source, terminal 0 ld c,a ; Count, line tail ld b,0 ldir ; Block move exx ret ; Print line tail from cursor position, return to position ptail: push hl ; Save mem pos push bc ; Save screen pos call linend1 ; Print ahead to end of line call ereol ; Clean off danglers ld a,c ; End of line cursor pos pop bc pop hl sub c ; Current cursor pos ret z ; At end of line already ld e,a ptail2: call bspace ; Else back up to where we were dec e jr nz,ptail2 ret ;-------------------------------------------------------------------- ; Exit with return code edexit: pop af ; Lift ECMD from stack ld hl,line ; Update buffer ld a,rcExec ret esc_key: pop af ld a,rcAbrt ret tab_key: pop af ld a,rcCont ret ;-------------------------------------------------------------------- ; SUPPORT ROUTINES ; Print a char, turn a control char into a cap char pctl: push af cp 20h jr nc,pctl1 add a,'@' pctl1: call conout pop af ret ; Upcase char and convert controls ucase: cp ' ' jp nc,CAPS add a,'@' jp CAPS end ;END ZERR-ED.Z80