;************************************************************************ ;* * ;* LINE EDIT ROUTINE * ;* * ;************************************************************************ ;(C) Copyright 1984 John Waycott - All Rights Reserved ; ;Permission is granted to freely copy this program provided that: ; ; 1. The copyright notices in this program must remain intact. ; 2. The program or modifications thereof are not sold for profit. ; ;If you have modifications, bug reports or enhancements please let me know. ;My address is: ; ; John Waycott ; 6327 W Laredo St ; Chandler, Az 85224 ; (702) 961-0193 ; ;NOTE: The basic framework for this program was written several years ago ;when I was a rather inexperienced programmer and it probably shows in the ;code. A lot of silly tricks were used to keep the code size to a minimum. ;Good luck to anyone attempting to modify it. ; ;EDITLI causes the system to enter an "edit" mode for all line-oriented ;keyboard input. All of the VUE line-editing control characters are ;available. Control-K as the very first character of a line causes the ;last line entered to appear. ; ;This program is invoked in the system initialization file with: ; ; SYSTEM EDITLI.SYS/N ; ;Edit History: ; ;Revision Date Description ;-------- --------- ----------- ; 1.0(100) 16 Aug 84 Created ; 1.1(101) 10 May 85 Fixed inititalization so EDITLI works ; with other programs which fool with the ; monitor (e.g., TSASS, various CACHEs). ; 1.2(101) 20 May 85 Fixed problem with return from sys call ; skipping two bytes ; ; Flags in register D4: ; B$INS = 0 ; ^Q insert mode B$SIL = 1 ; Silent; set if KBD entered with echo ; suppressed. CH = 10 CI = 11 CK = 13 LF = 12 CL = 14 CR = 15 CQ = 21 VMAJOR = 1 VMINOR = 2 VSUB = 0 VEDIT = 101. VWHO = 0 SEARCH SYS SEARCH SYSSYM SEARCH TRM OBJNAM .SYS ; output name is EDITLI.SYS ASECT .=50 EM1010: ; address of EM1010 trap vector PSECT ; ;EDITLI: must point to the first byte of this program. ; EDITLI: PHDR -1,0,PH$REE!PH$REU TYPECR (C) Copyright 1984 John Waycott - All rights reserved MOV EM1010,A0 ; Get 1010 Emulation vector 20$: TST (A0)+ ; locate vector table BNE 20$ ADD #<4-2>*2,A0 ; get KBD routine address in A0 CLR D7 ; use D7 to prevent sign extension MOVW @A0,D7 MOV D7,A0 ; ; find the sequence ; CALL .... ; TSTB @A0 ; ; by looking for the TSTB @A0 instruction. The call is to TIN, which gets ; the next character from the terminal. ; 10$: CMPW (A0)+,#045020 ; is this the TSTB @A0 instruction? BNE 10$ ; ; replace the sequence with a JMP.L KBD instruction. We can do this ; because at this point, our routine can handle the keyboard input. ; LEA A6,KBD MOV A6,-(A0) ; store as jmp.l operand MOVW #^H4EF9,-(A0) ; store EXIT ; ; This is the KBD routine. Upon entry to this routine, A5 points to ; the terminal definition unit. A0 point to the JCB of the job. ; The keyboard routine has saved A0,A1,A3,A5,D1 on the stack. ; ; The system monitor handles the KBD call if: ; 1. the keyboard is in image or data mode ; 2. a command file is active, and the next line is not a :K ; 3. a terminal is attached. ; KBD: SAVE A4,D0,D2,D3,D4,D5 ; save remaining registers MOV T.ILB(A5),A3 ; set line buffer address MOV A3,A4 ; set addr of last byte in buffer ADD T.ILS(A5),A4 SUB #4,A4 ; less CRLF and NULL terminators CLRB @A4 ; insure reasonable data PUSH D1 MOVB #CQ,D1 ; force ^Q to revive any ^S set. TRMICP POP D1 CLR D4 ; clear flags MOVW #T$ECS,D7 ; set B$SIL if T$ECS is set. ANDW @A5,D7 BEQ 2$ BSET #B$SIL,D4 2$: ORW #T$IMI!T$ECS,@A5 ; set image mode, suppress echo 1$: TSTB T.STS(A5) ; wait until all output flushed. BMI 1$ MOVW T.POO(A5),D3 ; set beginning position. MOVW D3,D2 ; set current position. MOV A3,A2 ; set buffer pointer TIN CMPB D1,#CK BEQ ISCK CLRB @A2 ; not control-K - clear buffer BR NXT1 ISCK: CALL PAINT NXT: TIN ; get next character NXT1: TSTB @A0 ; check for interrupt JMI C CMPB D1,#127. ; check for DEL JEQ DEL CMPB D1,#40 ; printable? BLT CCHAR ; no BCALL PRINT BR NXT ; ; character is a control character ; CCHAR: ADD D1,D1 BEQ NXT LEA A6,10$[~D1] ; table jump to appropriate routine ADDW @A6,A6 CALL @A6 10$: BR NXT OFFSET A OFFSET RETURN OFFSET RETURN OFFSET D OFFSET RETURN OFFSET F OFFSET RETURN OFFSET H OFFSET F ; TAB always inserts. OFFSET J OFFSET RETURN OFFSET L OFFSET M OFFSET N OFFSET RETURN OFFSET RETURN OFFSET Q OFFSET R OFFSET RETURN OFFSET RETURN OFFSET U OFFSET V OFFSET W OFFSET RETURN OFFSET Y OFFSET Z OFFSET RETURN OFFSET RETURN OFFSET RETURN OFFSET RETURN OFFSET RETURN ; ; printable character. If printing over a TAB, insert the character. ; PRINT: CMPB @A2,#CI BEQ 5$ BTST #B$INS,D4 ; check for insert mode BEQ 10$ 5$: PUSHW D1 CLRB D1 ; insure space insert. CALL F RESTW D1 BNE 99$ 10$: CMP A2,A4 BEQ 99$ CALL OUTCH TSTB @A2 ; if at end of line, append a NULL BEQ 20$ MOVB D1,(A2)+ RTN 20$: MOVB D1,(A2)+ CLRB @A2 RTN 99$: MOVB #7,D1 CALL PUTC RETURN: RTN ; ; DEL - delete character ; DEL: CMP A2,A3 ; if at BOL, do nothing BEQ 99$ BTST #B$INS,D4 BEQ 20$ 10$: CALL H 15$: BCALL D JMP NXT 20$: TSTB @A2 BEQ 10$ CALL H CMPB @A2,#CI BEQ 15$ MOVB #40,@A2 BTST #B$SIL,D4 ; don't display if silent BNE 99$ TTYI BYTE ' ,CH,0,0 99$: JMP NXT ; ; delete word. ; V: CALL NXTWRD CMP A1,A2 BEQ D.X BR DELBCH ; ; delete character at cursor. ; D: TSTB @A2 BEQ D.X LEA A1,1(A2) DELBCH: PUSH A2 ; put current position on stack. CALL LASTP POP A6 ; put current position in A6. 10$: MOVB (A1)+,(A6)+ ; move block of bytes down. BNE 10$ CALL REDRAW ; redraw the line. D.X: RTN ; ; clear line ; Z: BCALL U BCALL Y RTN ; ; Delete to end of line. ; Y: CALL LASTP ; get last position. CLRB @A2 ; clear rest of line. CALL REDRAW ; redraw the line. RTN ; ; go to beginning of line ; U: BCALL H BNE U RTN ; ; backspace ; z-bit is set if beginning of line. ; H: CMP A2,A3 ; check if at beginning BEQ 99$ DEC A2 CALL BCK LCC #0 99$: RTN ; ; move to end of line ; N: BCALL L BNE N RTN ; ; forward space ; z-bit set if end of line. ; L: TSTB @A2 BEQ 99$ CALL FWD INC A2 LCC #0 99$: RTN ; ; Repaint line ; Entry PAINT is called when an up-arrow is first entered. ; It repaints the line and removes the CRLF. ; R: BCALL N TYPECR ^R CLR D3 ; clear beginning position CLRW D2 ; clear current position MOV A3,A2 PAINT: MOVB @A2,D1 BEQ 99$ CMPB @A2,#CR BEQ 99$ CMPB @A2,#LF BEQ 99$ CALL OUTCH INC A2 BR PAINT 99$: CLRB @A2 RTN ; ; interrupt - clear buffer and return ; C: CLRB @A3 BR DONE1 ; ; end of line - carraige return or line feed. ; ; If we have a carraige return, look to see if a line feed is the next ; character waiting. If so, discard it. This prevents a type-ahead ; problem when entering multiple lines, but does not allow a LF ; to be entered ater a CR before the computer is accepting input. M: TST T.ICC(A5) ; any type-ahead? BEQ 10$ ; no MOV T.IBF(A5),A6 ; yes - discard if LF CMPB @A6,#LF BNE 10$ TIN 10$: TSTB (A2)+ BNE 10$ MOVB #CR,-1(A2) BR DONE J: TSTB (A2)+ BNE J DEC A2 DONE: MOVB #LF,(A2)+ ; store final LF and NULL CLRB @A2 TST (SP)+ ; pop stack and echo CRLF CRLF MOVB #LF,JOBCMS+1(A0); store LF in upper byte of JOBCMS word 10$: ; ;If input is in upper case, convert the string to upper case ; MOVW @A5,D7 ANDW #T$ILC,D7 BNE DONE1 MOV A3,A2 20$: MOVB @A2,D1 BEQ DONE1 UCS MOVB D1,(A2)+ BR 20$ DONE1: ANDW #~,@A5 ; restore image mode BTST #B$SIL,D4 ; restore echo if B$SIL is clear BNE 10$ ANDW #~,@A5 10$: MOV A3,A2 ; set return pointer ANDW #~,JOBCMS(A0) ; clear :K or :P in cmd file REST A4,D0,D2,D3,D4,D5 REST A0,A1,A3,A5,D1 ; restore registers from sys call RTE ; return from system call ; ; Toggle insert mode ; Q: BCHG #B$INS,D4 MOVB #7,D1 CALL PUTC RTN ; ; insert a space or tab in the line. ; If D1 is CI * 2, insert tab. ; If no room in buffer, z-bit is cleared. ; F: MOV A2,A1 ; find end of line 10$: TSTB (A1)+ BNE 10$ CMP A1,A4 BLO 20$ LCC #0 ; clear z-bit - no room for insert RTN 20$: MOVB -(A1),1(A1) CMP A2,A1 BNE 20$ MOVB #40,@A2 ; insert space or tab CMPB D1,#CI_1 BNE 30$ MOVB #CI,D1 ; if tab insert, move past the tab. MOVB D1,(A2)+ CALL OUTCH ; output the tab 30$: CALL LASTP ; repaint the line CALL REDRAW LCC #4 ; return success. RTN ; ; Move cursor to beginning of word ; A: CALL H ; backspace BEQ 99$ ; at beginning of line ALF BEQ 20$ NUM BNE A 20$: CALL H BEQ 99$ ALF BEQ 20$ NUM BEQ 20$ CALL L 99$: RTN ; ; move to next word ; W: BCALL NXTWRD 10$: CMP A2,A1 BHIS 99$ CALL L BR 10$ 99$: RTN ; ; nxtwrd - point a1 to the next word in the line. ; NXTWRD: MOV A2,A1 ; save a2 10$: TSTB @A2 BEQ 99$ INC A2 ALF ; skip alphanumerics BEQ 10$ NUM BEQ 10$ 20$: TSTB @A2 BEQ 99$ CMP A2,A4 BEQ 99$ INC A2 ALF BEQ 99$ NUM BNE 20$ 99$: XCH A1,A2 ; restore a2 and set a1. RTN ;backspace the display. If backspace is over a character, simply output ;a control-H to do the backspace. If backspacing over a tab, calculate ; how many backspaces to actually do. ; BCK: CMPB @A2,#CI ; if not tab, backspace. BEQ 10$ MOVB #CH,D1 CALL PUTC DECW D2 ; decrement position RTN 10$: MOVW D3,D0 ; get beginning position count. MOV A3,A6 ; beginning of buffer CHKTB: CMP A6,A2 ; reached current character? BHIS CHKTBX ; yes CMPB (A6)+,#CI ; increment pos by tabstop if a tab. BEQ 10$ INC D0 BR CHKTB 10$: ADD #10,D0 ANDW #~7,D0 BR CHKTB CHKTBX: SUBW D2,D0 NEGW D0 MOVB #CH,D1 ; output backspaces. 10$: CALL PUTC DECW D2 DECW D0 BGT 10$ 99$: RTN ; ; move cursor forward. ; If forward over tab, compute new position and output necessary spaces. ; FWD: MOVW #1,D0 ; default count CMPB @A2,#CI BNE OUTCL 10$: MOVW D2,D0 ; get output position ANDW #7,D0 ; compute no. of spaces to output ADDW #-10,D0 NEGW D0 OUTCL: MOVB #CL,D1 10$: BCALL PUTC INCW D2 DECW D0 BGT 10$ RTN ; ;outch - output a character. Adjust output position stored in D2. ;If outputting a TAB, output spaces to tab position. ;posch - does same but dows not write char to terminal. Returns number ;of spaces moved in D7. ; OUTCH: BCALL POSCH ; set position CMPB D1,#CI ; if tab, output spaces, else BEQ 10$ BCALL PUTC RTN 10$: MOVB #40,D1 PUSHW D7 BCALL PUTC POPW D7 DECW D7 BGT 10$ RTN POSCH: MOVW #1,D7 CMPB D1,#CI BNE 99$ MOVW D2,D7 ANDW #7,D7 ADDW #-10,D7 NEGW D7 99$: ADDW D7,D2 RTN ; ; putc - output character in D1 to terminal if echo is not suppressed. ; PUTC: BTST #B$SIL,D4 BNE 99$ TTY 99$: RTN ; ;lastp - returns the screen position of the last character on the line in d0. ; LASTP: MOV A2,A6 MOVW D2,D0 ; save current position 10$: MOVB (A6)+,D1 BEQ 99$ CALL POSCH ; add to position BR 10$ 99$: XCH D2,D0 ; restore d2, d0 = last position. RTN ; ; redraw - redraw rest of line and clear end garbage. ; Called after a character or word delete. ; Upon entry, D2 contains current position, D0 contains the last position of ; the line before it was modified. ; The rest of the line is redrawn, and spaces are drawn to erase any garbage ; at the end. Finally, the cursor is backed up to the original position. ; REDRAW: SAVE A2,D2 CALL PAINT ; paint the new line 10$: CMPW D2,D0 ; at final position? BHIS GOBACK ; yes, go back again. MOVB #40,D1 ; no, output a space. CALL OUTCH BR 10$ GOBACK: REST A2,D2 ; restore original positions. 10$: CMPW D0,D2 ; back to original? BLOS 99$ ; yes, all done. MOVB #CH,D1 ; no, backspace. BCALL PUTC DECW D0 BR 10$ 99$: RTN END .