.title k11edi Command line editing .ident /3.52/ ; 18-Jul-86 12:00:29 Brian Nelson ; ; This code is used (currently) for the RSTS/E Command Line ; Editor (CLE.RTS) written by the above author, and for 5.1 ; of MINITAB. The encryption calls are for the RSTS/E CLE. .include /IN:K11MAC.MAC/ .enabl gbl .psect rwdata ,rw,d,lcl,rel,con .psect CLECTX ,rw,d,gbl,rel,con curpos: .word edipos curlen: .word edilen curcmd: .word edicmd maxsiz: .word edisiz clests: .word edists enckey: .word $enckey deckey: .word $deckey .psect $pdata ,ro,d,lcl,rel,con .psect $code ,i,ro,i,lcl,rel FALSE = 0 TRUE = 1 IN$MODE = 1 $DEBUG = 0 .iif ndf, $DEBUG, $DEBUG = 0 .MACRO ENCRYPT txt,key mov key ,-(sp) mov txt ,-(sp) call ENCRYPT .endm ENCRYPT .MACRO DECRYPT txt,key mov key ,-(sp) mov txt ,-(sp) call DECRYPT .endm DECRYPT .MACRO DEBUG txt,sts=1,docr=1 .if ne ,$DEBUG .if ne ,sts .save .psect $pdata $$ = . .if b , .ift .byte 15,12,0 .iff .asciz @txt@ .endc .even .restore mov #$$ ,-(sp) ; dump the text next please CALL mout ; to the terminal .globl mout ; perhaps .if nb , .ift .iif nb,docr, message .endc .endc .endc .endm DEBUG .enabl lsb kbredi::SAVE ; Save PRINT @r5 ; Prompt cmpb vttype ,#TTY ; Not a VT100 or VT2xx? bne 10$ ; No, try editing CALLS kbread ,<2(r5)> ; Hardcopy, use vanilla reads br 100$ ; Exit 10$: clr @curpos ; Assume at start of the line. clr @curlen ; No length mov 2(r5) ,r4 ; Buffer address clrb @r4 ; Insure starting with .ASCIZ 20$: CALL read1ch ; Read one character now mov r0 ,r3 ; Any data persent? beq 90$ ; Yes, treat as a control Z SCAN r3 ,#scanlst ; Look for a match asl r0 ; And dispatch jsr pc ,@scandsp(r0) ; Do it bcs 20$ ; Not done br 100$ ; Done ; 90$: mov #ER$EOF ,r0 ; Error, return END_OF_FILE clr r1 ; And no data 100$: UNSAVE ; Exit return .dsabl lsb .save .psect $pdata scanlst:.byte 'H&37 ,'E&37 ,'B&37 ,'U&37 ,'Z&37 ,CR ,LF .byte 'I&37 ,177 ,33 ,233 ,'R&37 ,'X&37 ,'C&37 .byte 'A&37 .byte 0 .even scandsp:.word INSCH .word SOL ,EOL ,PREV ,CTRLU ,EOF ,NOOP ,DONE .word NOOP ,DORUB ,DOESC ,DO220 ,RETYPE ,CANTYP ,CTRLC .word TOGGLE esclst: .byte 'A&137 ,'B&137 ,'C&137 ,'D&137 ,0 .even escdsp: .word NOOP .word PREV ,NEXT ,RIGHT ,LEFT $cc: .asciz /^C/ $cz: .asciz /^Z/ $bs: .byte 'H&37,0 $cr: .byte 15,0 $right: .asciz <33>/[C/ $left: .asciz <33>/[D/ $save: .asciz <33>/7/ $resto: .asciz <33>/8/ $ceol: .asciz <33>/[K/ $crlf: .byte CR,LF,0 .even .restore Doesc: DEBUG ; ... CALL read1ch ; Get next in esc seq Do220: DEBUG ; You know CALL read1ch ; Ditto mov r0 ,r3 ; Get the data beq 90$ ; Error Exit SCAN r3 ,#esclst ; Process the character asl r0 ; Convert to word offset jsr pc ,@escdsp(r0) ; Do it br 100$ ; Ok 90$: sec ; Failure on the READ 100$: return ; And Exit Noop: DEBUG ; ... sec ; Ignore return ; And Exit Insch: DEBUG ,FALSE ; ... sub #200 ,sp ; A temp buffer mov sp ,r2 ; A pointer to it tst r3 ; Null? beq 100$ ; Ignore cmp @curlen ,@maxsiz ; Too many chars? blo 10$ ; No CALL done ; Yes, exit br 100$ ; Bye 10$: inc @curlen ; Save this mov @curpos ,r1 ; Get the offset into line add r4 ,r1 ; Where to stuff the data tstb @r1 ; Already at end of line? beq 20$ ; Yes, we have the stop to stuff it bit #IN$MODE,@clests ; Insert or overstrike? bne 15$ ; Insert movb r3 ,(r1)+ ; Overstrike br 30$ ; Exit 15$: STRCPY r2 ,r1 ; No, so save the data now movb r3 ,(r1)+ ; And insert the new character STRCPY r1 ,r2 ; And put the trailing data back in. br 30$ ; Now for the echoing 20$: movb r3 ,(r1)+ ; Already at eol, insert clrb @r1 ; And insure .ASCIZ 30$: PRINT #$save ; Save cursor pos dec r1 ; Back to to the new character PRINT r1 ; Dump the data PRINT #$restore ; Put the cursor back now inc @curpos ; Move over one PRINT #$right ; Nove over on the display 100$: add #200 ,sp ; Pop buffer sec ; Not done return ; Exit .sbttl More line editing routines ; SOL Move to start of line (Control H) Sol: DEBUG ; ... tst @curpos ; Stop when at position 0 ble 100$ ; Done PRINT #$bs ; Move dec @curpos ; Fix position br sol ; Next please 100$: clr @curpos ; Insure correct sec ; Not done return ; Exit ; EOL Move to End of Line, Control E Eol: DEBUG ; ... STRLEN r4 ; Find string length 10$: cmp @curpos ,r0 ; End yet? bhis 100$ ; Yes PRINT #$right ; No inc @curpos ; Fix this br 10$ ; Next 100$: sec ; Not done return ; Exit gotoeol:STRLEN r4 ; Find string length 10$: cmp @curpos ,r0 ; End yet? bhis 100$ ; Yes inc @curpos ; Fix this br 10$ ; Next 100$: return ; Exit ; EOF Control Z on input .enabl lsb ; Temp Ctrlc: DEBUG ; ... PRINT #$cc ; Echo a control C br 100$ ; Common exit now Eof: DEBUG ; ... PRINT #$cz ; Echo a control Z 100$: mov #ER$EOF ,r0 ; Control Z clr r1 ; And return byte count of zero clc ; All done return ; Exit .dsabl lsb ; Done .enabl lsb .sbttl Carriage return (actually LF) processing ; Done. CR on input, store new line and bubble previous ones back Done: mov r5 ,-(sp) ; A scratch register we need DEBUG ; ... MESSAGE ; CR/LF STRLEN r4 ; Get byte count (we have CR or LF) mov r0 ,r1 ; Return it beq 90$ ; Nothing there, don't copy it. clr r2 ; The index mov lastcnt ,r3 ; Number of lines to do 10$: mov lastli(r2),r0 ; Look to find a free spot. tstb @r0 ; Empty? beq 60$ ; Yes add #2 ,r2 ; No, keep looking sob r3 ,10$ ; .... ; No room for command line. clr r2 ; The index mov r4 ,-(sp) ; Save it mov lastcnt ,r3 ; Number of lines to do dec r3 ; ... asl r3 ; See if this is same as last mov lastli(r3),r5 ; Current address inc r5 ; Skip the length mov r5 ,-(sp) ; Save DECRYPT r5,deckey ; Undo the old line STRLEN r4 ; Length cmpb -1(r5) ,r0 ; Same length bne 20$ ; No 15$: cmpb (r4)+ ,(r5)+ ; Check for string equality bne 20$ ; Not the same sob r0 ,15$ ; Same, check next 20$: mov (sp)+ ,r5 ; Restore old text pointer mov (sp)+ ,r4 ; Restore the current pointer ENCRYPT r5,enckey ; Restore the data asr r3 ; Restore r3 tst r0 ; Same ? bne 30$ ; No mov r3 ,@curcmd ; Yes, save index br 100$ ; Exit 30$: 40$: mov lastli(r2),r0 ; Counted string format mov lastli+2(r2),r1 ; Again movb (r1) ,(r0)+ ; Copy the string length beq 55$ ; Can't happen, but may as well check clr r5 ; Counter for the copy operation bisb (r1)+ ,r5 ; Copy the byte count 50$: movb (r1)+ ,(r0)+ ; Copy the string now sob r5 ,50$ ; Next 55$: add #2 ,r2 ; Move up sob r3 ,40$ ; Next please ; 60$: mov lastli(r2),r1 ; Copy the line at last STRLEN r4 ; Get the line length mov @maxsiz ,r3 ; For padding with spaces movb r0 ,(r1)+ ; Copy the length beq 80$ ; Nothing mov r4 ,r5 ; Source string mov r1 ,-(sp) ; Save text address 70$: movb (r5)+ ,(r1)+ ; Copy the data now dec r3 ; Keep track of remaining space beq 75$ ; No room left sob r0 ,70$ ; Next please 74$: movb #40 ,(r1)+ ; Now space fill the line sob r3 ,74$ ; Next please 75$: mov (sp)+ ,r1 ; Restore text address ENCRYPT r1,enckey ; Encode it 80$: asr r2 ; Set 'Current' Command index mov r2 ,@curcmd ; And save it br 100$ ; Exit 90$: movb #CR ,@r4 ; Return only a carriage return clrb 1(r4) ; .ASCIZ 100$: STRLEN r4 ; Get line length mov r0 ,r1 ; Where to return it. clr r0 ; No errors mov (sp)+ ,r5 ; Restore r5 clc ; All done return ; Exit .dsabl lsb ; PREV: Recall previous command line, UP-Arrow Key. Prev: DEBUG ; ... mov r5 ,-(sp) ; Save it 10$: mov @curcmd ,r2 ; Current command number blt 100$ ; Never been here. CALL sol ; Back up PRINT #$cr ; Start of line PRINT #$ceol ; Clear PRINT @r5 ; Prompt asl r2 ; We want addresses today mov lastli(r2),r2 ; At last tstb @r2 ; Anything to copy? bne 20$ ; Yes dec @curcmd ; No, back up again bge 10$ ; Ok clr @curcmd ; Reached the end br 100$ ; And exit 20$: clrb @r4 ; TO be safe clr r3 ; Get length next bisb (r2)+ ,r3 ; Do it beq 50$ ; Nothing? mov @maxsiz ,r0 ; Copy all for DES types mov r4 ,r5 ; A copy of the destination 30$: movb (r2)+ ,(r5)+ ; Copy it sob r0 ,30$ ; Next please DECRYPT r4,deckey ; Decode the data add r4 ,r3 ; Point to the real end of data clrb @r3 ; Insure .asciz PRINT r4 ; Echo it 50$: CALL gotoeol ; Move to end of the line STRLEN r4 ; Get length mov r0 ,@curlen ; And save it tst @curcmd ; Check for underflow ble 100$ ; Yes, exit dec @curcmd ; No, backup now. br 100$ ; Exit 90$: clrb @r4 ; Nothing, kill the buffer 100$: sec ; Not done yet mov (sp)+ ,r5 ; Restore this return ; Exit ; Control U: Erase entire line Ctrlu: DEBUG ; ... CALL sol ; Move to start of the line PRINT #$ceol ; Erase to the end of the line clrb @r4 ; No data left over clr @curlen ; No length sec ; Not done return ; Exit Right: DEBUG ; ... STRLEN r4 ; Get current length of the line cmp @curpos ,r0 ; Already at EOL? bhis 100$ ; Yes inc @curpos ; No, move over PRINT #$right ; Simple to do. 100$: sec ; Not done return ; Exit .sbttl Rubouts and move left ; DORUB: Erase character Dorub: DEBUG ,FALSE ; ... sub #200 ,sp ; Allocate a buffer again mov sp ,r3 ; And a pointer to such. tstb @r4 ; Is there ANYTHING in the line? beq 100$ ; No, it's a NO-OP tst @curpos ; Already at SOL (start of line)? bgt 10$ ; No clr @curpos ; Insure correct position clr @curlen ; Save this br 20$ ; Off to common code 10$: PRINT #$LEFT ; Go back one please dec @curpos ; Correct offset now dec @curlen ; Fix this up 20$: mov r4 ,r2 ; And move down add @curpos ,r2 ; Point to CURRENT character mov r2 ,r1 ; Again inc r1 ; Next position please STRCPY r3 ,r1 ; Make a temporary copy of the data STRCPY r2 ,r3 ; Move it down PRINT #$save ; Save cursor position PRINT #$ceol ; Erase to EOL PRINT r2 ; Dump buffer PRINT #$restore ; And go back 100$: add #200 ,sp ; Pop local buffer and Exit sec ; Not done return ; Exit ; Left: Move left one character Left: DEBUG ; ... tst @curpos ; Can we back up ? ble 100$ ; No dec @curpos ; Yes, backup a bit PRINT #$left ; And do so. 100$: sec ; Not done return ; Exit .sbttl Command recall and control R processing Next: DEBUG ; ... mov r5 ,-(sp) ; Save mov curcmd ,r2 ; Point to CURCMD tst @r2 ; Current command number blt 100$ ; Never been here. mov lastcnt ,-(sp) ; Get the recall buffer count dec (sp) ; ... cmp @r2 ,(sp)+ ; Can we move up? bge 100$ ; No inc @r2 ; Yes, move up. CALL sol ; Back up PRINT #$cr ; Start of line PRINT #$ceol ; Clear PRINT @r5 ; Prompt mov @r2 ,r2 ; Copy it. asl r2 ; We want addresses today mov lastli(r2),r2 ; At last tstb @r2 ; Anything to copy? beq 90$ ; No ; clrb @r4 ; TO be safe clr r3 ; Get length next bisb (r2)+ ,r3 ; Do it mov @maxsiz ,r0 ; Copy ALL for DES type routines mov r4 ,r5 ; A copy of the destination 30$: movb (r2)+ ,(r5)+ ; Copy it sob r0 ,30$ ; Next please DECRYPT r4,deckey ; Decode the data add r4 ,r3 ; Point to the real end of data clrb @r3 ; And force to .ASCIZ PRINT r4 ; Dump the data call gotoeol ; Fix internal pointers STRLEN r4 ; Get last line length mov r0 ,@curlen ; And save it mov lastcnt ,-(sp) ; Get the recall buffer count dec (sp) ; ... cmp @curcmd ,(sp)+ ; Poised at the last command? bne 100$ ; No dec @curcmd ; Fix so PREV works correctly. br 100$ ; Exit 90$: clrb @r4 ; Nothing, kill the buffer 100$: sec ; Not done yet mov (sp)+ ,r5 ; Restore return ; Exit Retype: DEBUG ; ... PRINT #$cr ; Start of line PRINT #$ceol ; Clear PRINT @r5 ; Prompt PRINT r4 ; Dump the buffer PRINT #$cr ; Back up again STRLEN @r5 ; Get a new poistion now add @curpos ,r0 ; Get to correct position beq 100$ ; Nothing (?) 10$: PRINT #$right ; Move over sob r0 ,10$ ; Simple 100$: sec ; Not yet done return ; Exit Cantyp: call clrcns ; Eat up console data sec ; Not done return ; Exit Toggle: mov #IN$MODE,r0 ; Toggle modes xor r0 ,@clests ; Do it sec ; Not done return ; Exit .end