;************************************************************************
;* *
;* 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
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 <KBD> as jmp.l operand
MOVW #^H4EF9,-(A0) ; store <jmp.l>
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 #~<T$IMI>,@A5 ; restore image mode
BTST #B$SIL,D4 ; restore echo if B$SIL is clear
BNE 10$
ANDW #~<T$ECS>,@A5
10$: MOV A3,A2 ; set return pointer
ANDW #~<C.KIN!C.PTL>,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
;
; 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
;
; 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