Google
 

Trailing-Edge - PDP-10 Archives - bb-m836c-bm_tops20_v6_1_tools - tools/exec-mods/execce.mac
There are 5 other files named execce.mac in the archive. Click here to see a list.
; UPD ID= 273, SNARK:<6.1.EXEC>EXECCE.MAC.16,  28-Jun-85 16:05:06 by PRATT
;More TCO 6.1.1404:
;   Due to an aspect of the monitor, when the line is being read in 
;   image mode, and the terminal has pause on end-of-page set, and 
;   we continue to allow normal xon/xoff processing, the command editor
;   will pause at eop even though we have typed input on every line.
;   Fix this by removing the pause at eop setting and restore it if needed.
; UPD ID= 272, SNARK:<6.1.EXEC>EXECCE.MAC.15,  28-Jun-85 11:23:06 by PRATT
;More TCO 6.1.1404 - Fix SET EDIT MODE VMS not confirming properly
; UPD ID= 270, SNARK:<6.1.EXEC>EXECCE.MAC.14,  28-Jun-85 08:55:37 by PRATT
;   In VMS mode, ^B should act like up-arrow
;   Let user set a default VMS insert/overstrike mode, SED default is overstrike
;   SED mode was not terminating the string correctly in overstrike mode 
;   Make SET EDIT xxx legal
;   SET EDIT-xxx becomes invisible and will eventually go away
;   Make INFO COMMAND code say EDIT xxx
;   Fix INFO COMMAND code to say EDIT INT... instead of just INT...
; UPD ID= 267, SNARK:<6.1.EXEC>EXECCE.MAC.13,  25-Jun-85 15:59:13 by PRATT
;More TCO 6.1.1404 - Can't replace 1 instruction with 2 after skip insts.
; UPD ID= 266, SNARK:<6.1.EXEC>EXECCE.MAC.12,  25-Jun-85 12:57:44 by PRATT
;More TCO 6.1.1404:
;   In CEERET, CETTMD is garbage. Make it a real location in EXECPR
;   Whenever updating CETSAV for a new command, BLT the buffer to zero.
;   Fix some bugs for checking for end of CETSAV buffer
;   Don't blow up when trying to insert more than the CETSAV buffer holds
;   Exiting and quiting are indistinguishable, give indication of aborting 
;   Edited commands are not be saved, save them
; UPD ID= 263, SNARK:<6.1.EXEC>EXECCE.MAC.11,  24-Jun-85 14:42:35 by PRATT
;More TCO 6.1.1404 - Fix VMS mode help
; UPD ID= 260, SNARK:<6.1.EXEC>EXECCE.MAC.10,  21-Jun-85 12:45:15 by EVANS
;More TCO 6.1.1404 - Add RECALL; make  REDO and AGAIN invisible.
; UPD ID= 258, SNARK:<6.1.EXEC>EXECCE.MAC.9,  20-Jun-85 19:35:37 by PRATT
;Even more TCO 6.1.1404 - Fix problem with commands not being saved correctly
; UPD ID= 254, SNARK:<6.1.EXEC>EXECCE.MAC.8,  19-Jun-85 23:04:27 by PRATT
;More TCO 6.1.1404:
;   Be paranoid over updating the linked lists
;   Auto xon/xoff tty problems: remove ^S ^Q handling, leave page mode alone. 
;   Make certain memory to memory SOUTs use the ASOUT routine instead
;   Add SED and VMS line editing modes (works only for vt100's for now)
;   Let EMACs mode use arrow keys if vt100 style terminal
;   Remove non-DEC tty types, customers must add their own
;   Make commands table driven (more needs to be done)
;   Lots of cleanup, Make lots of JRST CEINC's become RET's
;   For alter-mode: when in insert mode, do the command if <cr> typed
;   Use RSCANs instead of STIs for executing the edited line
;   Do range checking so we don't overflow buffers (more needs to be done)
; UPD ID= 248, SNARK:<6.1.EXEC>EXECCE.MAC.7,  14-Jun-85 15:52:53 by EVANS
;More TCO 6.1.1404 - Don't save PCL subcommands to be in history.
; UPD ID= 245, SNARK:<6.1.EXEC>EXECCE.MAC.6,  10-Jun-85 09:15:05 by SANTIAGO
;More TCO 6.1.1404 - Don't let ^H be edit-interrupt character
; UPD ID= 222, SNARK:<6.1.EXEC>EXECCE.MAC.5,  10-Jun-85 08:43:00 by DMCDANIEL
;Take out copyrights, we do NOT own the command editor.
; UPD ID= 214, SNARK:<6.1.EXEC>EXECCE.MAC.4,   5-Jun-85 10:52:06 by EVANS
;More TCO 6.1.1404 - Add VT102 and VT200 terminals.
; UPD ID= 209, SNARK:<6.1.EXEC>EXECCE.MAC.3,  31-May-85 08:41:46 by EVANS
;More TCO 6.1.1404 - Fix extra line feeds in History from REDO and AGAIN.
; UPD ID= 208, SNARK:<6.1.EXEC>EXECCE.MAC.2,  24-May-85 14:18:46 by EVANS
;TCO 6.1.1404 - Bring all command editing routines into EXECCE, so command
;		editor can be assembled conditionally.


;TOPS20 'EXECUTIVE' COMMAND LANGUAGE - COMMAND EDITOR ROUTINES


;Digital does not support this product; it is provided only as a tool.

;Original command editor by Billy Brown @ UTEXAS-20
;Modified by others since (notably Ittai Hershman @ NYU)


	SEARCH EXECDE
	TTITLE EXECCE


DEFINE CESTG <
 TRVAR <CEPEOP,RVVFLG,CESVP,CEEOC,CADLFG,CEDUMB,CABKFG,CELPOS,CECPOS,CELPTR,CEDSEA,CENUMR,CEKBC>
 >

; ROUTINE TO SAVE CONTENTS OF COMMAND BUFFER FOR LATER EDITING
; THIS WILL RETURN +2 IF SUCCESSFUL SAVE, +1 IF NOT SUCCESSFUL


CSAVE::	CALL SAVACS      	;SAVE THE REGISTERS
	SKIPE CEBPTR		;THIS ONE NOT TO BE SAVED?
	 JRST CSAVE5		;QUIT NOW
	MOVE A,SBLOCK+.CMIOJ	;GET PRIMARY JFNS
	CAME A,[.PRIIN,,.PRIOU]	;A REAL, TYPED COMMAND?
	 JRST CSAVE5		;NOPE, DON'T SAVE IT
	SKIPE PCCIPF		;IF NOT PCL COMMAND, SAVE IT
	 JRST [	SKIPE PCLMID
		 JRST CSAVE5	;IF NOT THE CALLING COMMAND, DON'T SAVE
		SETOM PCLMID	;DON'T SAVE ANY MORE PCL COMMANDS
		JRST .+2 ]	;BUT DO SAVE THIS ONE
	SETZM PCLMID

	LDB A,[POINT 7,CBUF,6]	;CHECK IT OUT FIRST
	JUMPE A,CSAVE5		;DON'T SAVE EMPTY COMMANDS
	CAIN A,CR		;CR?
	 JRST CSAVE5		;YES, DON'T SAVE
	CAIN A,LF		;LF?
	 JRST CSAVE5		;YES, EMPTY COMMAND, DON'T SAVE

	MOVE A,[POINT 7,CBUF]	;POINT TO THE SOURCE
	CALL PIOFF		;NO INTERRUPTS RIGHT NOW
	MOVE B,CEFFL		;GET ADDRESS OF FIRST FREE LOCATION
	CAIL B,CESAVE		;DON'T WANT TO POINT OUTSIDE OF BUFFER
	 CAILE B,CEBFEN		; IF SO, WE ARE SMASHING THINGS
	  JRST CSAVER		;SMASHING THINGS
	CAME B,CE1ST		;ABOUT TO STOMP SOMEONE?
	 JRST CSAVE0		;NO
	HRRZ D,(B)		;GET ADDRESS OF NEXT ONE
	HRRZS (D)		;TIE IT OFF
	MOVEM D,CE1ST		;SAVE NEW ADDRESS
	CAIL D,CESAVE		;DON'T WANT TO POINT OUTSIDE OF BUFFER
	 CAILE D,CEBFEN		; IF SO, WE ARE SMASHING THINGS
	  JRST CSAVER		;SMASHING THINGS
	SOS CECNT		;DECREMENT THE COUNT
CSAVE0:	CALL PION		;OKAY FOR INTERRUPTS NOW
	HLL B,[POINT 7,0]	;POINT TO FIRST FREE SPOT
	AOS B			;LEAVE ROOM FOR THE HEADER
CSAVE1:	ILDB C,A		;GET NEXT BYTE
	CAIN C,CR		;END ON CR
	 SETZ C,
	CAIN C,LF		;END ON LINE FEED
	 SETZ C,

CSAVE2:	IDPB C,B		;STORE THE BYTE
	CALL PIOFF		;NO INTERRUPTS RIGHT NOW
	HRRZ D,B		;GET ADDRESS WE JUST STORED IN
	CAME D,CE1ST		;GOING OVER THE FIRST COMMAND?
	 JRST CSAVE3
	HRRZ D,(D)		;GET ADDRESS OF NEXT ONE
	HRRZS (D)		;TIE IT OFF
	MOVEM D,CE1ST		;SAVE NEW ADDRESS
	SOS CECNT		;DECREMENT THE COUNT
CSAVE3:	CALL PION		;OKAY FOR INTERRUPTS NOW
	HRRZ D,B		;GET ADDRESS AGAIN
	CAIE D,CEBFEN		;PAST THE BUFFER?
	 JRST CSAVE4		;NO
	MOVE B,[POINT 7,CESAVE]	;YES, RESET TO THE TOP
	JRST CSAVE2		;AND TRY AGAIN

CSAVE4:	JUMPN C,CSAVE1		;GET NEXT CHARACTER IF NOT THE END
	CALL PIOFF		;NO INTERRUPTS RIGHT NOW
	HRRZ A,B		;GET ADDRESS OF LAST BYTE
	AOS A			;BECOMES FIRST FREE LOCATION
	CAIL A,CEBFEN		;STILL IN THE BUFFER?
	 MOVEI A,CESAVE		;NO, WRAP AROUND
	EXCH A,CEFFL		;SAVE IT, A POINTS TO THE NEW BLOCK
	HRRM A,@CELAST		;LINK THIS ONE IN
	MOVE B,CELAST		;GET ADDRESS OF LAST ONE
	HRLZM B,(A)		;LINK FROM NEW ONE TO OLD ONE
	MOVEM A,CELAST		;UPDATE LAST COMMAND POINTER
	AOS CECNT		;INCREMENT COUNT
	CALL PION		;OKAY FOR INTERRUPTS NOW
	CALL RESACS		;RESTORE ACS
	SETOM CEBPTR		;MARK AS BEING SAVED
        RETSKP			; SUCCESSFUL SAVE

CSAVER:	ETYPE <%%Command editor problem: Pointers messed up, reseting them.%_>
	CALL PIOFF
	MOVEI A, CESAVE+2	;INITIALIZE THE COMMAND EDITOR
	MOVEM A, CESAVE		;
	MOVEM A, CEFFL		;INITIALIZE FREE SPACE POINTER
	MOVEI A, CESAVE		;INITIALIZE POINTER INTO TABLE
	MOVEM A, CE1ST		;
	MOVEM A, CELAST		;
	MOVEI A, 1		;INITIALIZE THE COMMAND COUNT
	MOVEM A, CECNT		;
	CALL PION
CSAVE5:	CALL RESACS		;RESTORE ACS
        RET			; COULDN'T SAVE COMMAND
;COMMAND LINE EDITOR

CEDITU::SETZM CEEOC		;CLEAR "EXITING" FLAG
	SETZM RVVFLG		;MAKE SURE HILITE FLAG IS OFF
	MOVEI A,.CTTRM		;GET OLD MODE WORD
	RFMOD
	MOVEM B,CETTMD		;SAVE THIS FOR CEERET AND CEQUIT
	MOVEI D,CEERET		;GET ADDRESS OF TTY CLEAN-UP ROUTINE
	MOVEM D,CERET		;MAKE SURE IT GETS CALLED ON ERROR
	TXZ B,TT%IGN		;MAKE SURE IT SEES TT%WAK BITS
	TXO B,TT%WAK		;WAKE ON EVERYTHING
	TXZ B,TT%ECO		;TURN OFF ECHOING
;	TXZ B,TT%PGM		;TURN OFF PAGING (^S, ^Q)
	TXZ B,TT%TAB		;SPACES INSTEAD OF TAB
	SFMOD
	STPAR
	MOVEI B,.MORXO		;GET SETTING OF PAUSE @ EOP
	MTOPR
	MOVEM C,CEPEOP		;SAVE IT
	MOVEI B,.MOXOF
	MOVEI C,.MOOFF		;NOW TURN IT OFF
	MTOPR
	MOVE B,[052525,,553125]	;PASS CR, ^I, FORMAT LF, NO NULLS
	MOVE C,[252525,,652400]	;FORMAT ESCAPE
	SFCOC
	MOVEI A,.FHJOB
	SETZ B,			;NO TERMINAL INTERRUPTS
	STIW
	 ERJMP CJERRE
	SETZM CELPOS		;INITIALIZE LINE NUMBER
	MOVE A,CELAST		;GET THE FIRST COMMAND POINTER
	MOVEM A,CELPTR		;INITIALIZE FOR CETOP
	SKIPE CEDSEA		;SEARCH MODE?
	 CALL CESRCH		;YES, SO BEGIN DEFFERENTLY
	SETZM CEDUMB		;ASSUME SMART TERMINAL
	MOVE A,CEFLAG		;GET EDITOR TYPE
	CAIN A,M.SED		;SED MODE ?
	 SETZM INSMOD		;YES - DEFAULT IS OVERSTRIKE
	MOVE B,CEVMSD		;GET DEFAULT INSERT/OVRSTRIKE MODE
	CAIN A,M.VMS		;VMS MODE ?
	 MOVEM B,INSMOD		;YES - SET DEFAULT MODE
	CAIN A,M.EMCS		;EMACS MODE?
	 JRST CEDIT1		;YES, SIMULATE UP CURSOR
	MOVE A,COJFN		;ALTER MODE, GET TERMINAL TYPE
	GTTYP
	SKIPN EEOLTB(B)		;IS IT SMART?
	 SETOM CEDUMB		;NO
	SETZM CADLFG		;INITIALIZE STUFF
	SETZM CABKFG
CEDIT1:	CALL CETOP		;SIMULATE INITIAL UP CURSOR
	CALL CEINC		;GO EDIT THE LINE
	RET
; SEARCH FOR INITIAL STRING -
;   CELPTR AND A CONTAINS POINTER TO FIRST COMMAND
;   CELPOS AND CELPTR UPDATED ON RETURN

CESRCH:	SKIPL CEDSEA		;SEARCH MODE OR NUMBER MODE
	 JRST CENUMM		;NUMBER MODE
	MOVE C,A		;BASE STRING HEADER
	MOVE B,[POINT 7,1(C)]	;BASE STRING BYTE POINTER
	MOVE A,[POINT 7,ATMBUF]	;POINT TO THE PREFIX STRING
	STCMP
	SKIPN A			;STRING ARE EQUAL?
	 RET			;YES, SO RETURN
	TXNE A,SC%SUB		;SUBSTRING?
	 RET			;YES, SO RETURN

; GO TO PREVIOUS LINE

	HLRZ A,@CELPTR		;TAKE THE LEFT HAND LINK
	SKIPN A			;CHECK FOR END OF LIST
	 JRST CESRCL		;END OF LIST
	AOS CELPOS		;INCREMENT THE LINE NUMBER
	MOVEM A,CELPTR		;UPDATE POINTER
	JRST CESRCH		;PROCESS THIS LINE

CESRCL:	MOVE A,CELAST		;END OF LIST, GO BACK TO THE FIRST LINE
	MOVEM A,CELPTR		;RESET THE POINTER
	SETZM CELPOS		;RESET LINE NUMBER
	TYPE <%Prefix not found - editing last command>
	RET


; NUMBER MODE

CENUMM:	SKIPGE C,CENUMR		;ONLY ALLOW POSITIVE NUMBERS
	 RET			;RETURN OTHERWISE POINTING AT CURRENT
CENUMA:	HLRZ A,@CELPTR		;TAKE THE LEFT HAND LINK
	SKIPN A			;CHECK FOR END OF LIST
	 JRST CENUML		;END OF LIST
	AOS CELPOS		;INCREMENT THE LINE NUMBER
	MOVEM A,CELPTR		;UPDATE POINTER
	SOJGE C,CENUMA		;CONTINUE IF MORE TO GO
	RET			;RETURN POINTING TO CURRENT LINE

CENUML:	TYPE <%Requested command line lost - positioning at first command>
	RET
CETOP:	CALL LM			;KEEP IT PRETTY
	CALL EEOLN		;ERRASE TO END OF LINE
	SETZM CETSAV		;CLEAR OUT 1ST LOCATION
	MOVE A,[CETSAV,,CETSAV+1] ;SET UP FOR THE BLT
	BLT A,CETSAV+CETBLN	;CLEAR TO END OF BUFFER
	MOVE A,CELPTR		;POINT TO THE CURRENT LINE
	AOS A			;SKIP PAST THE HEADER
	HLL A,[POINT 7,0]	;MAKE IT A POINTER
	MOVE B,[POINT 7,CETSAV]	;POINT TO THE TEMP BUFFER
CETOP0:	ILDB C,A		;GET NEXT BYTE
	HRRZ D,A		;CHECK FOR WRAP AROUND
	CAIE D,CEBFEN		;TOO FAR?
	 JRST CETOP1		;NO
	MOVE A,[POINT 7,CESAVE]	;YES, RESET THE POINTER
	JRST CETOP0		;AND START OVER

CETOP1:	IDPB C,B		;MOVE IT
	SKIPN C			;END ON NULL BYTE
	IFSKP.
	 HRRZ D,B		;CHECK FOR CETSAV OVERRUN
	 CAIGE D,CETSAV+CETBLN	;USED UP CETSAV YET?
	  JRST CETOP0		;NOPE, DO ANOTHER CHARACTER
	 SETO A,
	 ADJBP A,B		;DECREMENT POINTER
	 SETZ D,
	 DPB D,A		;PUT A NULL AT THE END
	ENDIF.
	SETZM CECPOS		;INITIALIZE POSITION
	MOVE A,[POINT 7,CETSAV]	;GET A POINTER TO IT
	MOVEM A,CEBPTR		;SAVE IT
	SKIPN CEDUMB		;WRITE LINE FOR DUMB TERMINALS
	 JRST CETOP2
	CALL CENUMB
	MOVE A,CEBPTR
	PSOUT
	TYPE <
>
CETOP2:	TYPE <    >		;MAKE ROOM FOR THE LINE NUMBER
	MOVE A,CEBPTR
	SKIPN CEDUMB		;EMACS OR SMART ALTER MODE?
	 PSOUT			;YES, WRITE IT OUT
	ETYPEC< TO THE BEGINNING
	CALL CENUMB		;WRITE THE NUMBER
	RET



CENUMB: MOVEI A,.CTTRM		;OUTPUT LINE# AS "DD:"
	MOVN B,CELPOS		;GET (NEGATIVE) LINE NUMBER
	JUMPE B,CENUM1		;DO CURRENT LINE DIFFERENT
	MOVE C,[NO%LFL!NO%OOV!NO%AST!FLD(3,NO%COL)!FLD(12,NO%RDX)]
        NOUT
	 JFCL
        ETYPE <:>
	RET			;ALL DONE

CENUM1:	ETYPE < **:>		;FOR CURRENT LINE
	RET
; GET THE NEXT INPUT CHARACTER

CEINC:	SKIPGE D,CEFLAG		;GET EDITOR TYPE
	 ERROR <No editor selected for command editing>
	SETZ P3,		;MAKE SURE COUNT IS ZERO
	HLRZ C,EDISP(D)		;GET DISPATCH ADR 
	CALL (C)		;GO GET A CHARACTER
	HRRZ C,EDISP(D)		;GET ADR TO GO TO
	CALL (C)		;GO HANDLE THE CHARACTER
	SKIPN CEEOC		;EXITING ?
	 JRST CEINC		;NO
	RET			;YES

;EDIT style command dispatch table

EDTCTB:	CR,,CEEXIT		;<CRLF> - EXIT AND DO COMMAND
	"E",,CEEXIT		;E - EXIT AND DO COMMAND
	.CHCNU,,CETOP		;^U - START OVER
	.CHLFD,,CEDOWN		;FL - NEXT LINE
	.CHESC,,CEUP		;ESC - PREVIOUS LINE
	.CHCNR,,CATYPE		;^R - RETYPE LINE
	"L",,CARTYP		;^L - TYPE LINE AND START OVER
	"P",,CATYPE		;P - RETYPE LINE
	"Q",,CEQUIT		;Q - ABORT
	.CHCNC,,CEQUIT		;^C - ABORT
	"D",,CADEL		;D - DELETE CHARACTERS
	"H",,CAHACK		;"H" - DELETE TO END, THEN INSERT
	"I",,CAINST		;"I" - ENTER INSERT MODE
	"R",,CADEIN		;"R" - REPLACE
	"W",,CAFORW		;"W" - MOVE OVER WORDS
	"X",,CAEXTN		;"X" - EXTEND LINE
	"Z",,CADELZ		;"Z" - DELETE WORDS
	":",,CACOLN	 	;DELETE REST OF LINE
	"\",,CETRAN		;"\" - TRANSPOSE PREVIOUS TWO CHARS
	.CHDEL,,CALEFT		;RUB - MOVE CURSOR LEFT
	" ",,CARIGH		;SPACE - MOVE CURSOR RIGHT
	.CHTAB,,CAEOLN		;TAB - MOVE TO END OF LINE
	"?",,CAHELP		;? - GIVE HELP MESSAGE
EDTCLN==.-EDTCTB


;Here with uppercase character in B

ACEDSP:	SETZ C,			;INIT THE INDEX
ACEDS0:	CAIGE C,EDTCLN		;DONE ?
	IFSKP.
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET        		;TRY AGAIN
	ENDIF.
	HLRZ A,EDTCTB(C)	;GET CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,ACEDS0		;BUMP INDEX AND LOOP
	HRRZ A,EDTCTB(C)	;GET DISPATCH ADDRESS
	CALL (A)		;AND GO THERE
	RET


;EDIT style "get a character routine"

ACEINP:	SETZ P3,		;ASSUME NO NUMERIC ARGUMENT
ACEIN0:	PBIN			;GET ALTER MODE COMMAND
	CAIL A,"0"		;BIGGER THAN 0?
	 CAILE A,"9"		;SMALLER THAT 9?
	  JRST ACEIN1		;NOT A NUMBER, OKAY
	IMULI P3,^D10		;NUMBER, UPDATE THE COUNT
	ADD P3,A		;ADD THIS ONE IN
	SUBI P3,"0"		;CONVERT TO BINARY
	JRST ACEIN0		;GET THE REST OF THE COMMAND

;Here make any lowercase characters become uppercase in ac B
ACEIN1:	MOVE B,A		;COPY CHARACTER
	CAIL B,"A"+40		;LESS THAN LC A
	 CAILE B,"Z"+40		;AND LESS THAN OR LC Z
	  SKIPA			;NOT LOWERCASE
	   SUBI B,40  		;MAKE LOWERCASE... UPPERCASE
	RET
;	HERE TO ENTER INSERT MODE

CAINST:	CALL CAFLSH		;FLUSH ANYTHING WE HAD GOING
CANST0:	PBIN			;GET NEXT CHARACTER
	CAIN A,.CHESC		;ESCAPE?
	 RET        		;YES, EXIT
	CAIN A,.CHTAB		;A TAB?
	 JRST CAINOK		;YES, LET IT PASS
	CAIN A,.CHCNC		;CONTROL C?
	 JRST CEQUIT		;YES, QUIT
	CAIN A,.CHCRT		;<CR>
	 JRST CEEXIT		;YES - GO DO IT
	CAIL A," "		;SOME CONTROL CODE?
	 CAIN A,.CHDEL		;OR RUBOUT?
	  SKIPA			;YES, ERROR
	   JRST CAINOK		;ITS OK
	CALL CEBELL		;ERROR, RING BELL
	JRST CANST0		;AND TRY AGAIN

CAINOK:	MOVE C,CEBPTR		;GET THE POINTER
	SKIPE CEDUMB		;DUMP TERMINAL?
	 PBOUT			;YES, DISPLAY THE CHARACTER
CAINS1:	ILDB B,C		;GET ONE THAT WAS THERE
	SKIPN CEDUMB		;SMART TERMINAL?
	 PBOUT			;YES, OUTPUT IT
	DPB A,C			;REPLACE IT
	JUMPE A,CAINS2		;EXIT AFTER A NULL BYTE
	MOVE A,B		;SET UP TO REINSERT THE ONE
	JRST CAINS1
CAINS2:	AOS CECPOS		;UPDATE OUR POSITION
	IBP CEBPTR		;AND OUR POINTER
	SKIPE CEDUMB		;SMART TERMINAL
	 JRST CAINST		;NO, GET SOME MORE
	ETYPES<TION THE CURSOR
	CALL CENUMB		;MOVE PAST THE LINE NUMBER
	MOVE A,COJFN		;POINT TO THE TERMINAL
	HRROI B,CETSAV		;POINT TO THE STRING
	MOVN C,CECPOS		;GET COUNT
	SKIPE C			;DON'T GO FOREVER HERE
	 SOUT			;MOVE PAST THE OLD CHARACTERS
	JRST CAINST		;DONE, GET SOME MORE


;	HERE TO DELETE N CHARACTERS

CADEL:	CALL ALTDEL		;DO ALTER MODE DELETE
	RET       		;DONE


;	HERE TO DELETE N CHARACTERS THEN INSERT TEXT

CADEIN:	CALL ALTDEL		;DO ALTER MODE DELETE
	CALL CAFLDE		;SIGNAL END OF DELETE
	JRST CAINST		;SO THE INSERT

;	ALTER MODE DELETE ROUTINE

ALTDEL:	MOVE A,CEBPTR
	ILDB B,A
	SKIPN B
	 RET
	CALL CAFLBK		;FLUSH BACKSPACE MARKER
	SKIPG P3		;ZERO OR BAD ARGUMENT?
	 MOVEI P3,1		;YES, MAKE IT THE DEFAULT
	SETZ C,			;NEW COUNTER
	SKIPE CEDUMB		;SMART TERMINAL
	 CALL CADELF		;NO, SIGNAL DELETE
	MOVE B,CEBPTR		;GET THE POINTER
ALTDL1:	ILDB A,B		;GET NEXT CHARACTER
	JUMPE A,ALTD1A		;END?
	AOS C			;NO, INCREMENT COUNT
	SKIPE CEDUMB		;SMART TERMINAL?
	 PBOUT			;NO, ECHO CHARACTER
	SOJG P3,ALTDL1
	JRST ALTDL2
ALTD1A:	SETO A,			;WENT TOO FAR, BACKUP POINTER
	ADJBP A,B
	MOVEM A,B
ALTDL2:	SKIPN C
	 RET
	MOVE A,CEBPTR
ALTDL3:	ILDB C,B		;GET FIRST CHARACTER
	IDPB C,A		;SAVE IN NEW POSITION
	JUMPN C,ALTDL3
	SKIPE CEDUMB		;SMART TERMINAL?
	 RET			;NO, DONE
ALTDL4:	MOVE A,CEBPTR		;REWRITE THE SCREEN
	PSOUT
	CALL EEOLN
	ETYPES<TION THE CURSOR
	CALL CENUMB		;MOVE PAST THE LINE NUMBER
	MOVE A,COJFN		;POINT TO THE TERMINAL
	HRROI B,CETSAV		;POINT TO THE STRING
	MOVN C,CECPOS		;GET COUNT
	SKIPE C			;DON'T GO FOREVER HERE
	 SOUT			;MOVE PAST THE OLD CHARACTERS
	RET
;	HERE TO RETYPE THE LINE

CATYPE:	CALL CAFLSH		;FLUSH EVERYTHING
	SKIPN CEDUMB		;SMART TERMINAL?
	 JRST CEDISP		;YES, THIS IS A JOB FOR EMACS
	MOVE A,CEBPTR		;FINISH THE LINE
	PSOUT
	ETYPE <
>				;GO TO NEW LINE
	JRST	CINST1		;WRITE IT OUT




;	HERE TO FINISH TYPING THE LINE AND START OVER

CARTYP:	CALL CAFLSH
	SETZM CECPOS		;RESET CHARACTER PSOITION
	SKIPN CEDUMB		;SMART TERMINAL?
	 JRST CARTP1		;YES
	MOVE A,CEBPTR		;FINISH THE LINE
	PSOUT
CARTP1:	MOVE A,[POINT 7,CETSAV]	;RESET POINTER
	MOVEM A,CEBPTR
	ETYPE <
>				;NEW LINE
	JRST CETOP2		;AND START OVER





;	HERE TO HACK AND INSERT

CAHACK:	CALL CAFLBK
	SKIPN CEDUMB		;SMART TERMINAL?
	JRST CAHAK1		;YES, DO IT THE EASY WAY
	CALL CADELF		;SIGNAL DELETE
	MOVE A,CEBPTR		;GET THE REST OF THE STRING
	PSOUT			;OUTPUT IT
	TYPE <\\>		;END OF DELETE
	SETZM CADLFG
CAHAK1:	SETZ A,			;CHOP OFF THE REST OF THE STRING
	MOVE B,CEBPTR		;GET COPY OF POINTER
	IDPB A,B		;CURSOR IS ONE POSITION PAST POINTER
	CALL EEOLN		;JUST IN CASE
	JRST CAINST		;START INSERTING

;	HERE TO MOVE OVER WORDS

CAFORW:	CALL CAFLSH
	SKIPG P3
	 MOVEI P3,1
CAFRW1:	CALL F.WORD		;GET COUNT TO NEXT WORD
	ADDM B,CECPOS		;UPDATE POSITION
	MOVN C,B		;GET NEGATIVE COUNT
	MOVE A,COJFN		;MOVE OVER
	MOVE B,CEBPTR
	SKIPE C
	 SOUT			;WRITE IT OUT
	MOVEM B,CEBPTR
	SOJG P3,CAFRW1
	RET



;	HERE TO DELETE N WORDS

CADELZ:	CALL CAFLBK
	PUSH P,CEBPTR		;SAVE THE POINTER
	SKIPG P3		;ZERO OR NO ARGUMENT?
	 MOVEI P3,1		;YES, MAKE IT THE DEFAULT
	SETZ D,			;KEEP COUNT HERE
CADLZ1:	CALL F.WORD		;GET COUNT TO NEXT WORD
	SUB D,B			;KEEP NEGATIVE COUNT
	ADJBP B,CEBPTR		;UPDATE POINTER
	MOVEM B,CEBPTR
	SOJG P3,CADLZ1
	SKIPE A,CEDUMB		;SMART TERMINAL?
	JRST CADLZ2		;NO.
	MOVE A,CEBPTR		;DESTINATION POINTER
	POP P,CEBPTR		;SOURCE POINTER
	JRST M.FIX		;FIX IT UP
CADLZ2:	CALL CADELF		;SIGNAL DELETE
	MOVE A,COJFN		;WRITE OUT DELETED STUFF
	MOVE B,(P)		;POINT TO DELETED STUFF
	MOVE C,D		;NUMBER OF CHARACTERS
	SKIPE C			;SKIP IF NONE
	 SOUT
	POP P,CEBPTR		;FIX THE POINTER
	MOVE A,CEBPTR
CADLZ3:	ILDB C,B		;GET FIRST CHARACTER
	IDPB C,A		;SAVE IN NEW POSITION
	JUMPN C,CADLZ3
	RET
;	HERE TO EXTEND THE LINE

CAEXTN:	CALL CAFLSH
	MOVE A,CEBPTR		;GET THE POINTER
	PSOUT			;WRITE IT OUT
	SETO B,			;BACKUP THE POINTER
	ADJBP B,A
	SETZ A,			;GET COUNT TOO
CAXTN1:	ILDB A,CEBPTR		;GET NEXT CHARACTER
	JUMPE A,CAXTN2
	AOS CECPOS		;UPDATE POSITION
	JRST CAXTN1
CAXTN2:	MOVEM B,CEBPTR		;SAVE NEW POINTER
	JRST CAINST		;GO TO INSERT MODE



;	HERE TO JUMP TO THE END OF A LINE

CAEOLN:	CALL CAFLSH
	MOVE A,CEBPTR		;GET POINTER
	PSOUT			;WRITE IT OUT
	SETO B,			;BACK IT UP
	ADJBP B,A
	SETZ A,			;GET COUNT TOO
CAEOL1:	ILDB A,CEBPTR		;GET NEXT CHARACTER
	JUMPE A,CAEOL2
	AOS CECPOS		;UPDATE POSITION
	JRST CAEOL1
CAEOL2:	MOVEM B,CEBPTR		;SAVE NEW POINTER
	RET



;	HERE TO DELETE THE REST OF THE LINE

CACOLN:	CALL CAFLBK
	SKIPN CEDUMB		;SMART TERMINAL?
	JRST CACLN1		;YES, SKIP THIS
	CALL CADELF		;SIGNAL DELETE
	MOVE A,CEBPTR		;GET POINTER
	PSOUT			;WRITE THE RESTO OF THE STRING
	TYPE <\\>		;SIGNAL NO MORE DELETE
	SETZM CADLFG
CACLN1:	SETZ A,			;CHOP OFF THE REST OF THE STRING
	MOVE B,CEBPTR		;GET COPY OF POINTER
	IDPB A,B		;CURSOR IS ONE POSITION PAST POINTER
	CALL EEOLN		;JUST IN CASE
	RET
;	HERE TO MOVE TO RIGHT

CARIGH:	CALL CAFLSH
	SKIPG P3		;ARGUMENT OK?
	 MOVEI P3,1		;FIX IT UP
CARIG1:	ILDB A,CEBPTR		;GET NEXT CHARACTER
	JUMPE A,CARIG2		;END OF LINE
	AOS CECPOS		;UPDATE POSITION
	PBOUT			;MOVE OVER
	SOJG P3,CARIG1		;DO THE REST
	RET

CARIG2:	SETO A,			;WENT TOO FAR
	ADJBP A,CEBPTR		;BACK UP
	MOVEM A,CEBPTR
	RET



;	HERE TO MOVE TO THE LEFT

CALEFT:	CALL CAFLDE
	SKIPN CECPOS		;BEGINNING OF LINE?
	 RET        		;YES, SKIP
	SKIPN P3		;NO ARGUMENT?
	 MOVEI P3,1		;MAKE IT A 1
	CAML P3,CECPOS		;ARGUMENT TOO BIG?
	 MOVE P3,CECPOS		;YES, TRIM IT DOWN
	SKIPE CEDUMB		;SMART TERMINAL
	 JRST CALFT1		;NO
	MOVN C,P3		;FIX THE POINTER
	ADJBP C,CEBPTR
	MOVEM C,CEBPTR
	MOVN A,P3		;FIX POSITION
	ADDM A,CECPOS
	JRST CINST1		;POSITION CURSOR

CALFT1:	CALL CABAKF		;SIGNAL BACK MOVEMENT
CALFT2:	LDB A,CEBPTR		;GET THIS CHARACTER
	PBOUT			;OUTPUT IT
	SETO B,			;MOVE THE POINTER BACK
	ADJBP B,CEBPTR		;BACK UP THE POINTER
	MOVEM B,CEBPTR
	SOS CECPOS
	SOJG P3,CALFT2		;DO THE REST
	RET
; ROUTINES TO PRINT \ AND \\ FOR DUMB TERMINAL ALTER MODE


CAFLSH:	CALL CAFLBK		;FLUSH OUT BACKSPACE CHARACTER
	CALL CAFLDE		;FLUSH OUT DELETE CHARACTER
	RET



CAFLBK:	SKIPN CEDUMB
	 RET
	SKIPN CABKFG		;WERE WE BACKSPACING?
	 RET			;NO, NOTHING TO DO
	SETZM CABKFG		;RESET THE FLAG
	TYPE <\>		;SIGNAL END OF BACKSPACE
	RET



CAFLDE:	SKIPN CEDUMB		;DUMB TERMINAL?
	 RET			;YES, RETURN
	SKIPN CADLFG		;WERE WE IN A DELETE?
	 RET			;NO
	SETZM CADLFG		;RESET FLAG
	TYPE <\\>		;SIGNAL END OF DELETE
	RET


CABAKF:	SKIPN CEDUMB
	 RET
	SKIPN CABKFG		;SET?
	ETYPE <\>		;NO, SIGNAL
	SETOM CABKFG		;SET BACKSPACE FLAG
	RET


CADELF:	SKIPN CEDUMB
	 RET
	SKIPN CADLFG		;SET?
	ETYPE <\\>		;NO, SIGNAL
	SETOM CADLFG		;SET DELETE FLAG
	RET

;	VMS MODE BEGINS HERE

;Here to dispatch given the uppercase character in B

VMSDSP:	MOVE D,A		;SAVE REAL CHAR
	SETZ C,			;INIT THE INDEX
VMSDS0:	CAIGE C,VMSCLN		;DONE ?
	IFSKP.
	 MOVE A,D		;GET REAL CHARACTER BACK
	 CAIL A," "		;SOME OTHER CONTROL CHARACTER?
	  JRST SEDINS		;INSERT THIS CHARACTER
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET       		;TRY AGAIN
	ENDIF.
	LDB A,[POINT 7,VMSCTB(C),17] ;GET THE CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,VMSDS0		;BUMP INDEX AND LOOP
	HRRZ B,VMSCTB(C)	;GET DISPATCH ADDRESS
	CALL (B)		;AND GO THERE
	RET

VMSCTB:	.CHCRT,,CEEXIT		;^M - EXIT AND DO EDITED COMMAND
	.CHCNA,,CINMOD		;^A - TOGGLE INSERT MODE
	.CHCNB,,CEUP		;^B - PREVIOUS COMMAND
	.CHCND,,CELEFT		;^D - LEFT
	.CHCNF,,CERIGH		;^F - RIGHT
	.CHCNE,,CEMEND		;^E - END OF LINE
	.CHBSP,,CEBEGN		;^H - BEGINNING OF LINE
	.CHTAB,,CINSRT		;^I - ALWAYS INSERT A TAB
	.CHLFD,,METARB		;^J - PREVIOUS WORD DELETE
	.CHCNC,,CEQUIT		;^C - ABORT
	.CHCNU,,VMSBBW	        ;^U - BACK TO BEGINNING OF WORD
	.CHCUN,,CVHELP	        ;^_ - HELP MESSAGE
	.CHCNR,,CEDISP	        ;^R - REDISPLAY LINE
	.CHCNO,,CRTLV		;^V - TAKE NEXT CHAR LITERALLY
	.CHESC,,VMSESC		;ESCAPE - GET NEXT FEW CHARACTERS
	.CHDEL,,CERUB		;DEL - DELETE CHAR AT LEFT OF CURSOR
VMSCLN==.-VMSCTB	        

;Here to delete from beginning of line to cursor

VMSBBW:	PUSH P,CEBPTR		;SAVE CURRENT POINTER
	CALL CEBEGN		;GO TO BEGINNING OF LINE
	POP P,B			;GET BACK THE POINTER
	MOVE A,CEBPTR		;DESTINATION IS BEGINNING OF BUFFER
	SETZ C,			;COPY UNTIL END OF STRING
	CALL ASOUT
	MOVE A,CEBPTR
	PSOUT
	CALL EEOLN		;CLEAR OLD EOL
	JRST CINST1

VMSESC:	CALL ECEINC		;GET NEXT CHARACTER
	CAIN B,"["		;GOT A BRACKET
	 JRST BRAKET		;YES - HANDLE IT
	MOVEI A,.PRIIN
	CFIBF			;CLEAR THE INPUT BUFFER
	CALL CEBELL		;NO, RING THE BELL
	RET

;	SED MODE BEGINS HERE

;Here to pick up a command character for SED mode

SEDINP:	STKVAR <ECHR,CVECHR,CEMODW>
	MOVEI A,.CTTRM		;ALLOW 8 BIT INPUT
	RFMOD			;GET THE MODE WORD
	MOVEM B,CEMODW		;SAVE IT
	TXZ B,TT%DAM		;BINARY MODE
	SFMOD
	HRROI A,[BYTE (7) 33,"=",33,"<",0] ;SET TERMINAL TO APPLICATIONS MODE
	PSOUT
	PBIN			;GET A CHAR
	CALL ACEIN1		;MAKE BOTH REAL CHARACTER AND UPPERCASE
	MOVEM B,CVECHR		;SAVE CONVERTED CHAR
	MOVEM A,ECHR		;SAVE REAL CHAR
	MOVE B,CEMODW		;RESTORE MODE WORD
	MOVEI A,.CTTRM
	SFMOD
	MOVE A,ECHR		;GET BACK THE CHARS
	MOVE B,CVECHR
	RET

;Here to reset some things on exiting the editor

VTEXIT:	HRROI A,[BYTE (7) 33,">",0] ;NO APPLICATIONS KEYPAD MODE
	CALL CECCOC
	SETZM SVSEDP		;CLEAR THE POINTER
	SETZM INSMOD		;CLEAR INSERT MODE
	RET

;Here to dispatch given the uppercase character in B

SEDDSP:	MOVE D,A		;SAVE REAL CHAR
	SETZ C,			;INIT THE INDEX
SEDDS0:	CAIGE C,SEDCLN		;DONE ?
	IFSKP.
	 MOVE A,D		;GET REAL CHARACTER BACK
	 CAIL A," "		;SOME OTHER CONTROL CHARACTER?
	  JRST SEDINS		;INSERT THIS CHARACTER
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET       		;TRY AGAIN
	ENDIF.
	LDB A,[POINT 7,SEDCTB(C),17] ;GET THE CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,SEDDS0		;BUMP INDEX AND LOOP
	HLRZ A,SEDCTB(C)	;GET FLAGS WORD
	TRNE A,SD%RST		;NEED RESET 1ST ?
	 CALL SDRST1		;YES
	HRRZ A,SEDCTB(C)	;GET DISPATCH ADDRESS
	CALL (A)		;AND GO THERE
	RET

;Here to determine whether overstrike mode or insert mode

SEDINS:	SKIPE INSMOD		;IN OVERSTRIKE MODE ?
	IFSKP. 
	 CALL OVRSTK		;YES
	ELSE.
	 CALL CINSRT		;NO - IN INSERT MODE
	ENDIF.
	RET

SD%RST==400000			;RESET "ENTER PARAM" BEFORE COMMAND XCTION

SEDCTB:	.CHCRT!SD%RST,,CEEXIT	;^M - EXIT AND DO EDITED COMMAND
	.CHBSP,,SEDRST		;BACKSPACE - RESET
	.CHLFD!SD%RST,,CEKILL	;LINEFEED - KILL TO END OF LINE
	.CHBEL,,SEDPUT		;^G - OUTPUT PICK BUFFER
	.CHCNV,,SEDPCK		;^V - PICK
	.CHVTB,,SDINSP		;^K - INSERT CHARACTER
	.CHCNW!SD%RST,,CEUP	;^W - EDIT PREVIOUS COMMAND
	.CHCNC!SD%RST,,CEQUIT	;^C - ABORT
	.CHDEL!SD%RST,,CERUB	;RUBOUT - DELETE CHAR AT LEFT OF CURSOR
	.CHFFD,,SEDKSP	        ;^L - DELETE CHARACTER AT CURSOR
	.CHCNF,,SEDKIL	        ;^F - KILL TO END OF LINE
	.CHCNU,,METAB 	        ;^U - BACK TO BEGINNING OF WORD
	.CHCUN,,CSHELP	        ;^_ - HELP MESSAGE
	.CHCNR,,CEDISP	        ;^R - REDISPLAY LINE
	.CHTAB,,NXTWRD	        ;TAB - FORWARD TO NEXT WORD
	.CHCNO!SD%RST,,CRTLV	;^O - TAKE NEXT CHAR LITERALLY
	.CHCNX!SD%RST,,CETRAN	;^X - TRANSPOSE CHARACTER
	.CHESC,,ESCDSP		;ESCAPE - GET NEXT FEW CHARACTERS
SEDCLN==.-SEDCTB	        


ESCCTB:	"[",,BRAKET		;LEFT SQUARE BRACKET
	"O",,KEYP.O		;"O"
ESCCLN==.-ESCCTB


BRKCTB:	"A"!SD%RST,,CEUP	;<ESC>[A - PREVIOUS COMMAND
	"B"!SD%RST,,CEDOWN	;<ESC>[B - NEXT LINE
	"C",,CERIGH	        ;<ESC>[C - CURSOR RIGHT
	"D",,CELEFT	        ;<ESC>[D - CURSOR LEFT
BRKCLN==.-BRKCTB


KPOCTB:	"P",,SEDENT		;ESCAPE O P == ENTER PARAMETER
	"M",,CINMOD		;ESCAPE O M == INSERT-MODE
	"A"!SD%RST,,CEUP  	;ESCAPE O A == PREVIOUS LINE
	"B"!SD%RST,,CEDOWN	;ESCAPE O B == NEXT LINE
	"C",,CERIGH		;ESCAPE O C == RIGHT
	"D",,CELEFT		;ESCAPE O D == LEFT
;These next few commands are normally lowercase (we converted them)
	"T",,CEBEGN		;ESCAPE O T == START-OF-LINE
	"V",,CEMEND		;ESCAPE O V == END-OF-LINE
	"N"!SD%RST,,METARB	;ESCAPE O N == ERASE-WORD
	"P"!SD%RST,,CETABI	;ESCAPE O P == REAL-TAB
	"U",,CEDISP		;ESCAPE O U == REDISPLAY LINE
	"S",,CSHELP		;ESCAPE O S == HELP
KPOCLN==.-KPOCTB


;Here to check for movement of the cursor as a parameter

CHKMOV:	SETZ P3,
	SKIPN B,SVSEDP		;GET SAVED PARAMETER POINTER
	 RET			;NONE - NO MOVEMENT
	MOVE A,CEBPTR		;GET CURRENT POINTER
	CALL SUBBP		;GET THE DIFFERENCE IN THE 2 POINTERS
	MOVE P3,A		;GET COUNT IN RIGHT AC
	JUMPE P3,CHKMV1		;NO MOVEMENT ?
	SKIPL P3		;GOING FORWARDS ?
	IFSKP.
	 MOVNS P3		;THE COUNT BECOMES POSITIVE
	 MOVE A,CEBPTR		;EXCHANGE THE SAVED AND THE NEW POINTERS
	 EXCH A,SVSEDP		
	 MOVEM A,CEBPTR	
	 MOVE A,CECPOS 		;EXCHANGE THE COUNTS
	 EXCH A,SVSEDC
	 MOVEM A,CECPOS
	ENDIF.
	RET

CHKMV1:	CALL SDRST1		;RESET PARAMETER
	SETO P3,		;FLAG IT
	RET			


;Here to kill line/characters
SEDKIL:	CALL CHKMOV		;CHECK MOVEMENT
	JUMPL P3,SDRDSP		;GO REDISPLAY CHARACTER (NO REVERSE VIDEO)
	JUMPE P3,SDKILL		;IF ZERO, KILL REST OF LINE
	SETO P2,		;SAVE THE KILL TEXT
SDKIL0:	STKVAR <SVCP>
	MOVE A,CEBPTR		;GET CURRENT POINTER
	MOVEM A,SVCP		;SAVE IT FOR LATER
	CALL SEDUPD		;UPDATE CURSOR POSITION BEFORE DOING CMD
	SKIPE P2		;SAVE THE TEXT ?
	CALL SEDSVK		;YES - SAVE TEXT THATS BEING KILLED
	MOVE A,SVCP  		;GET THE POINTER TO END OF KILL
	PSOUT			;TYPE IT OUT
	MOVE A,CEBPTR		;GET DESTINATION (BEGINNING OF KILL)
	MOVE B,SVCP    		;GET SOURCE IS END OF KILL
	SETZ C,			;COPY UNTIL END OF STRING
	CALL ASOUT
	CALL EEOLN		;CLEAR OLD EOL
	CALL SDRST1		
	JRST CINST1

;Here to delete space(s)
SEDKSP:	CALL CHKMOV		;CHECK MOVEMENT
	JUMPL P3,SDRDSP		;GO REDISPLAY CHARACTER (NO REVERSE VIDEO)
	JUMPE P3,CERMSP		;ONLY DO ONE ? YES - JUST DO DELETE CHAR
	SETZ P2,		;DO NOT SAVE TEXT BEFORE KILLING
	JRST SDKIL0		;GO KILL THE TEXT


;Here to save the text going into the kill buffer
; On return B/ updated CEBPTR

SEDSVK:	MOVEI C,CEKBLN*5
	CAML C,P3		;IF STRING IS TO LONG, TRUNCATE IT
	 MOVE C,P3		;IF STRING IS SHORT ENOUGH USE P3
	MOVE A,[POINT 7,CEKBUF] ;POINT TO KILL BUFFER
	MOVE B,CEBPTR		;ANY TO WHAT WE ARE KILLING
	SETZ D,	
	SOUT 
	SETZ C,			;CHOP OFF THE REST OF THE STRING
	IDPB C,A		;ADD A NULL TO THE END OF THE KILL BUFFER
	RET

SDKILL:	MOVEI P3,7777		;GET BIG NUMBER OF BYTES
	CALL SEDSVK		;SAVE TEXT THATS BEING KILLED
	MOVE B,CEBPTR		;GET COPY OF POINTER
	SETZ A,
SDKIL1:	ILDB D,B		;GET THIS BYTE 
	JUMPE D,SDKIL2		;DONE ON NULL
	DPB A,B		        ;CURSOR IS ONE POSITION PAST POINTER
	JRST SDKIL1		;ONWARD

SDKIL2:	CALL SDRST1		;RESET PARAMETER
	JRST EEOLN 		;CLEAR TO EOL


;Here to insert spaces
SDINSP:	CALL CHKMOV		;CHECK MOVEMENT
	JUMPL P3,SDRDSP		;GO REDISPLAY CHARACTER (NO REVERSE VIDEO)
	SKIPN P3 
	 SKIPA P3,[1]		;IF ZERO, MAKE IT 1
	CALL SEDUPD		;UPDATE CURSOR POSITION BEFORE DOING CMD
	MOVE A,CEBPTR
	CALL BUFFS		;LINE FROM CURRENT POS
	MOVE B,A		;SAVE BUFFERED STRING 
	MOVE D,P3		;GET THE COUNT
	MOVE A,CEBPTR
	MOVEI C,40		;GET A SPACE
SDIS1:	IDPB C,A		;DEPOSIT A SPACE
	SOJG D,SDIS1		;GO AROUND FOR ANOTHER
	SETZ C,			;STOP ON NULL (A&B ALREADY SET UP)
	CALL ASOUT		;MOVE REST OF STRING TO AFTER SPACES
	MOVE A,CEBPTR		;GET CURRENT POINTER AGAIN
	PSOUT			;TYPE THE LINE FROM CURRENT POS 
	CALL CINST1		;GO TYPE CORRECT POS
	JRST SDRST1



;Here to handle a pick
SEDPCK:	CALL CHKMOV		;CHECK FOR MOVEMENT
	JUMPL P3,SDRDSP		;GO REDISPLAY CHARACTER (NO REVERSE VIDEO)
	CALL SEDUPD		;UPDATE CURSOR POSITION TO SAVED POS
	SKIPN P3		;ZERO ?
	 MOVEI P3,7777		;YES - MAKE IT A BIG NUMBER
	MOVE C,[POINT 7,CEPBUF]	;SAVE IN THE PUT BUFFER
	MOVE D,CEBPTR
SDPK1:	ILDB B,D		;GET A CHARACTER
	IDPB B,C		;PUT IT IN THE PUT BUFFER
	JUMPE B,SDPK2		;DONE ON NULL
	SOJG P3,SDPK1		;GO AROUND FOR ANOTHER
SDPK2:	SETZ B,			;DEPOSIT A NULL AT THE END
	IDPB B,C
	JRST SDRST1		;ALL DONE


;Here to handle a PUT
SEDPUT:	CALL CHKMOV		;CHECK FOR MOVEMENT
	JUMPL P3,SDYANK		;GO HANDLE UNDELETE LINE
	JUMPN P3,SDPERR		;PARAMETER EXCEPT NULL LOSES
	MOVE A,[POINT 7,CEPBUF]	;GET POINTER TO PUT BUFFER
	CALL BCOUNT		;GET NUMBER OF CHARACTERS IN THERE
	MOVEM B,CEKBC		;SAVE IT
	JUMPE B,SDNPUT		;NO PUT BUFFER
	MOVE A,CEBPTR		;GET BUFFER POINTER
	CALL BUFFS		;SAVE THE END OF THE LINE
	MOVE B,A		;SAVE POINTER
	MOVE A,CEKBC		;GET COUNT
	ADJBP A,CEBPTR		;MAKE ROOM FOR THE KILLED TEXT
	SETZ C,			;END ON A ZERO BYTE
	CALL ASOUT		;MOVE END OF LINE OVER
	MOVE A,CEBPTR		;GET POINTER TO HOLE
	MOVE B,[POINT 7,CEPBUF]	;AND TO PUT BUFFER
SDPUT1:	ILDB C,B		;GET NEXT BYTE
	SKIPN C			;AT THE END?
	 JRST SDPUT2		;YES
	IDPB C,A		;NO, STORE IT
	JRST SDPUT1		;DO THE REST
SDPUT2:	MOVE A,CEBPTR		;GET POINTER TO REST OF STRING
	PSOUT			;UPDATE SCREEN
	CALL CINST1		;POSITION THE CURSOR
	JRST SDRST1		;ALL DONE

SDPERR:	MOVEI A,.PRIIN
	CFIBF			;CLEAR THE INPUT BUFFER
	CALL CEBELL
	TYPE <
?No parameters excepted for PUT at this time>
	JRST CEDISP		;GO REDISPLAY THE LINE

SDYANK:	CALL SDRST1		;RESET ENTER PARAMETER
	MOVE A,[POINT 7,CEKBUF]	;GET POINTER TO KILL BUFFER
	ILDB B,A		;GET 1ST CHARACTER IN IT
	JUMPN B,CEYANK		;IF NON-ZERO, THEN GOT KILL BUFFER
	MOVEI A,.PRIIN
	CFIBF			;CLEAR THE INPUT BUFFER
	CALL CEBELL
	TYPE <
?CLOSE buffer is empty>
	JRST CEDISP		;GO REDISPLAY THE LINE

SDNPUT:	CALL SDRST1		;RESET ENTER PARAMETER
	MOVEI A,.PRIIN
	CFIBF			;CLEAR THE INPUT BUFFER
	CALL CEBELL
	TYPE <
?PUT buffer is empty>
	JRST CEDISP		;GO REDISPLAY THE LINE

;Here to handle ENTER 

SEDENT:	MOVE A,CECPOS		;GET CHAR POS
	MOVEM A,SVSEDC		;SAVE IT
	MOVE A,CEBPTR		;GET THE CURRENT POINTER
	MOVEM A,SVSEDP		;SAVE SED PARAMETER POINTER
	ILDB D,A		;GET THE CHARACTER AT THE CURSOR
	SETOM RVVFLG		;NEXT CHARACTER IS REVERSE VIDEO
	RET

;Here to hi-lite the next character with reverse video

HILITE:	SAVEAC <A,B,C,D>
	MOVE D,A
	SETZM RVVFLG		;CLEAR THE REVERSE VIDEO FLAG
	HRROI A,[BYTE (7) 33,"[","7","m",0] ;REVERSE VIDEO
	CALL CECCOC
	MOVE A,D
	PBOUT
	HRROI A,[BYTE (7) 33,"[","0","m",0] ;NO REVERSE VIDEO ANYMORE
	CALL CECCOC
	RET

;Here to get rid of reversed video character

SDRDSP:	CALL SEDUPD
	RET


;Update cursor position before doing cmd

SEDUPD:	MOVE A,SVSEDP		;GET OLD POINTER AND UPDATE TO CURRENT
	MOVEM A,CEBPTR
	MOVE A,SVSEDC		;GET OLD POS AND UPDATE TO CURRENT
	MOVEM A,CECPOS
	CALL CINST1		;UPDATE CUROSR POS
	RET

;Here to reset entering parameters

SEDRST:	CALL SEDUPD		;UPDATE CURSOR POSITION 
SDRST1:	SETZM RVVFLG
	SETZM SVSEDC		;CLEAR THE POS
	SETZM SVSEDP		;CLEAR THE POINTER
	RET



ESCDSP:	CALL SEDINP		;GET NEXT CHARACTER
	SETZ C,			;INIT THE INDEX
ESCDS0:	CAIGE C,ESCCLN		;DONE ?
	IFSKP.
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET       		;TRY AGAIN
	ENDIF.
	LDB A,[POINT 7,ESCCTB(C),17] ;GET THE CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,ESCDS0		;BUMP INDEX AND LOOP
	HLRZ A,ESCCTB(C)	;GET FLAGS WORD
	TRNE A,SD%RST		;NEED RESET 1ST ?
	 CALL SDRST1		;YES
	HRRZ A,ESCCTB(C)	;GET DISPATCH ADDRESS
	CALL (A)		;AND GO THERE
	RET

KEYP.O:	CALL SEDINP		;GET NEXT CHARACTER
	SETZ C,			;INIT THE INDEX
KPODS0:	CAIGE C,KPOCLN		;DONE ?
	IFSKP.
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET         		;TRY AGAIN
	ENDIF.
	LDB A,[POINT 7,KPOCTB(C),17] ;GET THE CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,KPODS0		;BUMP INDEX AND LOOP
	HLRZ A,KPOCTB(C)	;GET FLAGS WORD
	TRNE A,SD%RST		;NEED RESET 1ST ?
	 CALL SDRST1		;YES
	HRRZ A,KPOCTB(C)	;GET DISPATCH ADDRESS
	CALL (A)		;AND GO THERE
	RET

BRAKET:	CALL SEDINP		;GET NEXT CHARACTER
	SETZ C,			;INIT THE INDEX
BRKDS0:	CAIGE C,BRKCLN		;DONE ?
	IFSKP.
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET       		;TRY AGAIN
	ENDIF.
	LDB A,[POINT 7,BRKCTB(C),17] ;GET THE CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,BRKDS0		;BUMP INDEX AND LOOP
	HLRZ A,BRKCTB(C)	;GET FLAGS WORD
	TRNE A,SD%RST		;NEED RESET 1ST ?
	 CALL SDRST1		;YES
	HRRZ A,BRKCTB(C)	;GET DISPATCH ADDRESS
	CALL (A)		;AND GO THERE
	RET

CETABI:	MOVEI A,.CHTAB		;INSERT A REAL TAB
	JRST CINSRT

CEINSP:	MOVEI A," "		;INSERT A SPACE
	JRST CINSRT

CINMOD:	SETCMM INSMOD		;TOGGLE INSERT MODE/OVERSTRIKE MODE
	RET


; HERE TO MOVE TO THE BEGINNING OF THE NEXT WORD

NXTWRD:	CALL WRDSKP		;GET DESTINATION
	ADDM B,CECPOS		;UPDATE POSITION
	JUMPE B,CEINC		;NO MOVEMENT, STOP
	MOVE C,B		;NUMBER OF CHARACTERS TO MOVE
	ADJBP B,CEBPTR		;UPDATE POINTER
	PUSH P,B		;SAVE IT
	SKIPN RVVFLG		;REVERSE VIDEO THIS CHARACTER ?
	IFSKP.
	 ILDB A,CEBPTR		;YES - GET POINTER
	 CALL HILITE	
	 SOS C			;ONE LESS TO OUTPUT
	ENDIF.
	MOVE B,CEBPTR		;START OF WHAT WE WANT TO TYPE
	MOVE A,COJFN		;PRIMARY OUTPUT
	SOUT			;PRINT OVER ONE WORD
	POP P,CEBPTR		;UPDATE POINTER
	RET


; SUBROUTINE TO RETURN NUMBER OF SPACES UNTIL START OF NEXT WORD
; UNLIKE F.WORD, IT WILL SKIP OVER SPACES, TABS, AND CERTAIN DELIMITERS

WRDSKP:	SETZ B,			;INITIALIZE COUNT
	MOVE C,CEBPTR		;GET LOCAL COPY OF POINTER
WDSKP0:	ILDB A,C		;GET THIS CHARACTER
	AOS B			;UPDATE COUNT
	JUMPE A,[RET]		;END OF LINE, QUIT
	CALL CHKCHR		;CHECK THE CHAR
	 JRST WDSKP0		;CHARACTER IS PART OF WORD
WDSKP1:	ILDB A,C		;AT DELIMITER, GET NEXT CHARACTER
	AOS B			;UPDATE COUNT
	JUMPE A,[RET]		;END OF LINE
	CALL CHKCHR		;CHECK THE CHAR
	 SOJA B,R		;AT BEGINNING OF NEW WORD 
	JRST WDSKP1		;STILL IN DELIMITER


;CHECK THE CHARACTER

CHKCHR:	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   RET
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   RET
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   RET
	RETSKP
;	EMACS MODE BEGINS HERE

;Here to pick up a command character for emacs mode

ECEINC:	STKVAR <CETYP,ECHR,CVECHR,CEMODW>
	MOVEM D,CETYP		;SAVE EDITOR TYPE
	MOVEI A,.CTTRM		;ALLOW 8 BIT INPUT
	RFMOD			;GET THE MODE WORD
	MOVEM B,CEMODW		;SAVE IT
	TXZ B,TT%DAM		;BINARY MODE
	SFMOD
	PBIN			;GET CHARACTER
	CALL ACEIN1		;MAKE BOTH REAL CHARACTER AND UPPERCASE
	MOVEM B,CVECHR		;SAVE CONVERTED CHAR
	MOVEM A,ECHR		;SAVE REAL CHAR
	MOVE B,CEMODW		;RESTORE MODE WORD
	MOVEI A,.CTTRM
	SFMOD
	MOVE A,ECHR		;GET BACK THE CHARS
	MOVE B,CVECHR
	RET


;Here to dispatch given the uppercase character in B

ECEDSP:	CALL ECDISP
	RET

ECDISP:	STKVAR <ECHR>
	MOVEM A,ECHR
	SKIPN CEMETA		;META KEY IN USE?
	 TRZ B,200		;NO, TRIM PARITY BIT
	MOVEI A,METAN1		;SETUP IN CASE OF META KEY
	TRZE B,200		;META KEY USED?
	 RET			;YES - SPECIAL DISPATCH
	SETZ C,			;INIT THE INDEX
ECEDS0:	CAIGE C,EMCCLN		;DONE ?
	IFSKP.
	 MOVE A,ECHR		;GET ACTUAL CHARACTER BACK
	 CAIL A," "		;SOME OTHER CONTROL CHARACTER?
	  JRST CINSRT		;INSERT THIS CHARACTER
	 CALL CEBELL		;YES - NO MATCH, RING THE BELL
	 RET         		;TRY AGAIN
	ENDIF.
	HLRZ A,EMCCTB(C)	;GET CHARACTER
	CAME A,B		;GOT A MATCH ?
	 AOJA C,ECEDS0		;BUMP INDEX AND LOOP
	HRRZ B,EMCCTB(C)	;GET DISPATCH ADDRESS
	CALL (B)		;GO THERE, CHARACTER IN A
	RET


EMCCTB:	CR,,CEEXIT		;^M - EXIT AND DO EDITED COMMAND
	.CHCNP,,CEUP		;^P - EDIT PREVIOUS COMMAND
	.CHBEL,,CEQUIT	        ;^G - ABORT
	.CHCNC,,CEQUIT	        ;^C - ABORT
	.CHDEL,,CERUB	        ;RUBOUT - DELETE CHAR AT LEFT OF CURSOR
	.CHCNB,,CELEFT	        ;^B - CURSOR LEFT
	.CHCNF,,CERIGH	        ;^F - CURSOR RIGHT
	.CHCNN,,CEDOWN	        ;^N - CURSOR DOWN
	.CHCND,,CERMSP	        ;^D - DELETE CHARACTER AT CURSOR
	.CHCNE,,CEMEND	        ;^E - MOVE TO END OF LINE
	.CHCNA,,CEBEGN	        ;^A - MOVE TO BEGINNING OF LINE
	.CHVTB,,CEKILL	        ;^K - KILL TO END OF LINE
	.CHCNT,,CETRAN	        ;^T - TRANSPOSE CHARACTERS
	.CHCNW,,METARB	        ;^W - SAME AS M-RUB
	.CHCNY,,CEYANK	        ;^Y - YANK KILL BUFFER
	.CHCUN,,CEHELP	        ;^_ - HELP MESSAGE
	.CHFFD,,CEDISP	        ;^L - REDISPLAY LINE
	.CHCNR,,CEDISP	        ;^R - REDISPLAY LINE
	.CHTAB,,CINSRT	        ;TAB - INSERT WITHOUT V
	.CHESC,,METAIN	        ;<ESC> - META PREFIX
;	.CHCNQ,,CRTLV	        ;^Q - TAKE NEXT CHAR LITERALLY
	.CHCNV,,CRTLV	        ;^V - TAKE NEXT CHAR LITERALLY
EMCCLN==.-EMCCTB	        


CRTLV:	PBIN			;GET THE CHARACTER
	JRST CINSRT		;PROCESS IT


; AN ESCAPE HAS BEEN ENTERED, GET THE NEXT COMMAND CHARACTER

METAIN:	PBIN			;GET THE NEXT WORD
METAN1:	CAIE A,"F"		;M-F - FORWARD TO END OF WORD
	 CAIN A,"f"
	  JRST METAF
	CAIE A,"B"		;M-B - BACK TO BEGINNING OF WORD
	 CAIN A,"b"
	  JRST METAB
	CAIE A,"D"		;M-D - DELETE TO END OF WORD
	 CAIN A,"d"
	  JRST METAD
	CAIN A,.CHDEL		;M-RUB - DELETE BACK TO START OF WORD
	 JRST METARB
	CAIN A,.CHESC		;M-ESC - STUFF COMMAND WITH <ESC>
	 JRST METAES
	CAIN A,"?"		;M-? - STUFF COMMAND WITH ?
	 JRST METAQU
	CAIN A,"["		;BRACKET ?
	 JRST METESC		;YES - ALLOW 
METAN2:	MOVEI A,.PRIIN
	CFIBF			;CLEAR THE INPUT BUFFER
	CALL CEBELL		;ERROR, RING BELL
	RET        		;TRY AGAIN


METESC:	MOVE A,COJFN		;GET TERMINAL TYPE
	GTTYP
	CAIN B,.TT100		;VT100 ?
	 JRST BRAKET		;YES - OKAY TO USE ARROW KEYS
	CAIN B,.TT102		;VT102 ?
	 JRST BRAKET		;YES - OKAY TO USE ARROW KEYS
	CAIN B,.TT125		;VT125 ?
	 JRST BRAKET		;YES - OKAY TO USE ARROW KEYS
	CAIN B,.TT131		;VT131 ?
	 JRST BRAKET		;YES - OKAY TO USE ARROW KEYS
	CAIN B,.TTK10		;GIGI ?
	 JRST BRAKET		;YES - OKAY TO USE ARROW KEYS
	CAIN B,.TTH19		;H19 ?
	 JRST BRAKET		;YES - OKAY TO USE ARROW KEYS
	JRST METAN2		;NO ARROW KEY ALLOWED

;Here on overstrike mode for insert character

OVRSTK:	MOVE C,CEBPTR		;GET THE POINTER
OVR1:	HRRZ B,C		;GET ADDRESS FIELD OF THE POINTER
	CAIGE B,CETSAV+CETBLN-1 ;ABOUT TO OVERFLOW THE BUFFER?
	IFSKP.
	 CALL CEBELL		;YES, RING BELL
	 JRST CINST1		;AND DON'T ACCEPT MORE INPUT
	ENDIF.
	ILDB B,C		;GET ONE THAT WAS THERE
	DPB A,C			;REPLACE IT
	SKIPE B			;WAS OLD ONE NULL ?
	IFSKP.
	 MOVE D,C		;DON'T INCREMENT CURRENT POINTER
	 IDPB B,D		;MAKE SURE THE NEXT BYTE IS ALSO NULL
	ENDIF.
	JUMPE A,CINST0		;EXIT AFTER A NULL BYTE
	PBOUT			;OUTPUT IT
	MOVE A,C		;GET CURRENT BYTE POINTER NOW
	PSOUT			;OUTPUT REST OF STRING
	MOVEM C,CEBPTR		;UPDATE POINTER
	AOS A,CECPOS		;UPDATE POSITION
	JRST CINST1		;GO UPDATE CURSOR



; HERE TO INSERT A CHARACTER INTO THE COMMAND LINE

CINSRT:	MOVE C,CEBPTR		;GET THE POINTER
CINST:	HRRZ B,C		;GET ADDRESS FIELD OF THE POINTER
	CAIGE B,CETSAV+CETBLN-1	;ABOUT TO OVERFLOW THE BUFFER?
	IFSKP.
	 CALL CEBELL		;YES, RING BELL
	 JRST CINST1		;AND DON'T ACCEPT MORE INPUT
	ENDIF.
	ILDB B,C		;GET ONE THAT WAS THERE
	DPB A,C			;REPLACE IT
	JUMPE A,CINST0		;EXIT AFTER A NULL BYTE
	PBOUT			;OUTPUT IT
	MOVE A,B		;SET UP TO REINSERT THE ONE
	JRST CINST
CINST0:	AOS A,CECPOS		;UPDATE EVERYTHING
	IBP CEBPTR

CINST1:	MOVE B,CEBPTR		;SEE WHAT WE'RE SUPPOSED TO POINT TO
	ILDB A,B		;IF WE'RE SUPPOSED TO BE AT THE END
	JUMPE A,R    		; OF THE LINE, WE'RE ALREADY THERE
	ETYPES<TION THE CURSOR
	CALL CENUMB		;MOVE PAST THE LINE NUMBER
	MOVE A,COJFN		;POINT TO THE TERMINAL
	HRROI B,CETSAV		;POINT TO THE STRING
	MOVN C,CECPOS		;GET COUNT
	SKIPE C			;DON'T GO FOREVER HERE
	 SOUT			;MOVE PAST THE OLD CHARACTERS
	RET




; MOVE THE CURSOR TO THE LEFT

CELEFT:	SKIPN CECPOS		;AT BEGINNING OF BUFFER?
	 RET          		;YES, DO NOTHING
	LDB C,CEBPTR		;GET CHARACTER WE ARE GOING TO
	SETO B,
	ADJBP B,CEBPTR		;DECR BYTE PTR
	MOVEM B,CEBPTR
	SOS CECPOS		;DECR CHARACTER POSITION
	CAIGE C," "		;SOME CONTROL CHARACTER?
	 JRST CINST1		;YES, DON'T MESS UP
	CALL CEBACK		;BACK UP
	RET
; ERASE LAST CHARACTER

CERUB:	SKIPN CECPOS		;AT BEGINNING OF BUFFER?
	 RET         		;YES, DON'T DO ANYTHING
	MOVE A,CEBPTR		;GET POINTER
	ILDB C,A		;SEE IF WE ARE AT END OF LINE
	SETO A,			;GET A -1
	ADJBP A,CEBPTR		;DECREMENT THE BYTE POINTER
	MOVEM A,CEBPTR		;SAVE IT
	SOS CECPOS		;AND DECREMENT CHARACTER POSITION
	JUMPN C,CERMSP		;IF NOT AT END OF LINE, RETYPE WHOLE THING
	ILDB B,A		;GET CHARACTER WE'RE DELETING
	CAIL B," "		;ARE WE DELETING A CONTROL CHARACTER
	IFSKP.			;YES...
	 CAIE B,.CHESC		;AND NOT ESCAPE (SINGLE CHARACTER)
	  CALL CEBACK		;YES, WE HAVE TO BACK UP OVER TWO CHARS
	ENDIF.			;
	CALL CEBACK		;BACK UP SOME
	JRST CEKILL		;AND KILL REST OF LINE




; MOVE THE CURSOR TO THE END OF THE LINE

CEMEND:	MOVE B,CEBPTR		;SEE IF WE'RE POINTING AT ZERO BYTE
	ILDB A,B
	JUMPE A,CEMND1		;AT END OF LINE, QUIT
	AOS CECPOS
	PBOUT			;MOVE OVER
	JRST CEMEND+1
CEMND1:	MOVNI C,1
	ADJBP C,B
	MOVEM C,CEBPTR		;MAKE BYTE POINTER AGREE WITH CURSOR
	RET
; MOVE THE CURSOR TO THE RIGHT

CERIGH:	MOVE B,CEBPTR		;SEE IF WE'RE POINTING AT ZERO BYTE
	ILDB A,B
	JUMPE A,CEINC		;AT END OF BUFFER, DO NOTHING
	SKIPE RVVFLG		;REVERSE VIDEO THIS CHARACTER ?
	IFSKP.
	 PBOUT			;NO - MOVE OVER
	ELSE.
	 CALL HILITE		;YES
	ENDIF.
	AOS CECPOS		;INCR CHARACTER POSITION
	IBP CEBPTR		;INCREMENT POINTER
	RET



; MOVE TO THE NEXT COMMAND LINE

CEDOWN:	HRRZ A,@CELPTR		;TAKE THE RIGHT HAND LINK
	SKIPN A			;CHECK FOR END OF LIST
	 JRST CEDWN1		;NOT AT END, SKIP THIS
	SOS CELPOS		;DECREMENT THE LINE NUMBER
	MOVEM A,CELPTR		;UPDATE POINTER
	JRST CETOP		;PROCESS THIS LINE

CEDWN1:	MOVE A,CE1ST		;END OF LIST, GO BACK TO THE FIRST LINE
	MOVEM A,CELPTR		;RESET THE POINTER
	MOVE A,CECNT		;GET RIGHT LINE NUMBER
	SOS A
	MOVEM A,CELPOS		;SET IT
	JRST CETOP		;PROCESS THIS LINE




; MOVE TO THE PREVIOUS COMMAND LINE

CEUP:	HLRZ A,@CELPTR		;TAKE THE LEFT HAND LINK
	SKIPN A			;CHECK FOR END OF LIST
	 JRST CEUP1		;NOT AT END
	AOS CELPOS		;INCREMENT THE LINE NUMBER
	MOVEM A,CELPTR		;UPDATE POINTER
	JRST CETOP		;PROCESS THIS LINE

CEUP1:	MOVE A,CELAST		;END OF LIST, GO BACK TO THE FIRST LINE
	MOVEM A,CELPTR		;RESET THE POINTER
	SETZM CELPOS		;RESET LINE NUMBER
	JRST CETOP		;PROCESS THIS LINE
; HERE TO DELETE THE CHARACTER AT THE CURSOR

CERMSP: MOVE B,CEBPTR		;GET DESTINATION POINTER
	MOVEI A,1
	ADJBP A,CEBPTR	        ;POINTER TO SOURCE
	LDB C,A		        ;ZERO BYTE?
	JUMPE C,R    	        ;YES, QUIT
	SETZ C,		        ;NO, MOVE THE TEXT
	SIN
	ETYPEA<T OVER
	CALL CENUMB		;WRITE THE LINE NUMBER
	HRROI A,CETSAV		;AND THE LINE
	PSOUT
	CALL EEOLN
	JRST CINST1		;POSITION THE CURSOR




; HERE TO MOVE THE CURSOR TO THE BEGINNING OF THE LINE

CEBEGN:	MOVEI A,CETSAV		;FIX POINTER
	HLL A,[POINT 7,0]
	MOVEM A,CEBPTR
	SETZM CECPOS		;RESET POINTER TO BEGINNING OF LINE
	ETYPEV< CURSOR TO BEGINNING
	CALL CENUMB		;WRITE THE LINE NUMBER
	RET




; HERE TO KILL EVERYTHING TO THE RIGHT OF THE CURSOR

CEKILL:	MOVE A,[POINT 7,CEKBUF] ;POINT TO KILL BUFFER
	MOVE B,CEBPTR		;ANY TO WHAT WE ARE KILLING
	MOVEI C,CEKBLN*5	;BUT ONLY SAVE 80 CHARS AT MOST
	SETZ D,			;AND ON ZERO BYTE
	SOUT      		;SAVE IT
	SETZ A,			;CHOP OFF THE REST OF THE STRING
	IDPB A,B		;ADD A NULL TO THE END OF THE KILL BUFFER
	MOVE B,CEBPTR		;GET COPY OF POINTER
	IDPB A,B		;CURSOR IS ONE POSITION PAST POINTER
	CALL EEOLN		;ERRASE IT FROM THE SCREEN
	RET

; HERE TO YANK THE KILL BUFFER

CEYANK:	MOVE A,[POINT 7,CEKBUF]	;GET POINTER TO KILL BUFFER
	CALL BCOUNT		;GET NUMBER OF CHARACTERS IN THERE
	MOVEM B,CEKBC		;SAVE IT
	MOVE A,CEBPTR		;GET BUFFER POINTER
	CALL BUFFS		;SAVE THE END OF THE LINE
	MOVE B,A		;SAVE POINTER
	MOVE A,CEKBC		;GET COUNT
	ADJBP A,CEBPTR		;MAKE ROOM FOR THE KILLED TEXT
	SETZ C,			;END ON A ZERO BYTE
	CALL ASOUT		;MOVE END OF LINE OVER
	MOVE A,CEBPTR		;GET POINTER TO HOLE
	MOVE B,[POINT 7,CEKBUF]	;AND TO KILLED TEXT
CEYNK1:	ILDB C,B		;GET NEXT BYTE
	SKIPN C			;AT THE END?
	 JRST CEYNK2		;YES
	IDPB C,A		;NO, STORE IT
	JRST CEYNK1		;DO THE REST
CEYNK2:	MOVE B,CEBPTR		;GET POINTER TO REST OF STRING
	MOVE A,COJFN		;PRIMARY OUTPUT
	SOUT			;UPDATE SCREEN
	  ERJMP KABOOM		;ABORT IF SOUT FAILS
	MOVE A,CEKBC		;GET LENGTH OF ADDED TEXT
	ADDM A,CECPOS		;UPDATE POSITION
	ADJBP A,CEBPTR		;MOVE TO END OF UNKILLED TEXT
	MOVEM A,CEBPTR		;SAVE UPDATED POINTER
	JRST CINST1		;POSITION THE CURSOR




; HERE TO SWAP THE CHARACTER AT THE CURSOR AND THE ONE BEFORE IT

CETRAN:	SKIPN CECPOS		;BEGINNING OF LINE?
	 RET       		;YES, SKIP
	MOVE B,CEBPTR
	ILDB A,B		;END OF LINE?
	JUMPE A,CEINC
	MOVE B,CEBPTR		;GET LOCAL POINTER
	MOVEI A,1		;SCOOT OVER ONE
	ADJBP A,B
	LDB C,A			;CHANGE THE CHARACTERS IN THE BUFFER
	LDB D,B
	DPB D,A
	DPB C,B
	ETYPEW<ITE THE LINE
	CALL CENUMB
	HRROI A,CETSAV
	PSOUT
	JRST CINST1		;POSITION CURSOR
; HERE TO MOVE TO THE BEGINNING OF THE NEXT WORD

METAF:	CALL F.WORD		;GET DESTINATION
	ADDM B,CECPOS		;UPDATE POSITION
	JUMPE B,CEINC		;NO MOVEMENT, STOP
	MOVE C,B		;NUMBER OF CHARACTERS TO MOVE
	ADJBP B,CEBPTR		;UPDATE POINTER
	PUSH P,B		;SAVE IT
	MOVE B,CEBPTR		;START OF WHAT WE WANT TO TYPE
	MOVE A,COJFN		;PRIMARY OUTPUT
	SOUT			;PRINT OVER ONE WORD
	POP P,CEBPTR		;UPDATE POINTER
	JRST CINST1		;MOVE CURSOR OVER



; HERE TO MOVE TO THE BEGINNING OF THE PREVIOUS WORD

METAB:	CALL B.WORD		;GET DESTINATION
	JUMPE B,CEINC		;SKIP IF NO MOVEMENT
	MOVNS B			;MAKE IT NEGATIVE
	MOVE C,B		;GET A COPY OF IT
	ADJBP C,CEBPTR		;UPDATE THE POINTER
	MOVEM C,CEBPTR
	ADDM B,CECPOS		;UPDATE POSITION
	JRST CINST1		;UPDATE CURSOR

METAB1:	PUSH P,B		;SAVE NUMBER OF CHARACTERS TO BACK UP
	CALL CEBACK		;BACK UP ONE
	POP P,B			;GET COUNT BACK
	AOJN B,METAB1		;DECREMENT COUNT
	RET       		;POSITION CURSOR



; HERE TO DELETE UP TO THE BEGINNING OF THE NEXT WORD

METAD:	CALL F.WORD		;GET DESTINATION
	MOVE A,B		;GET COPY OF OFFSET
	ADJBP A,CEBPTR		;POINTER TO DESTINATION
	JRST M.FIX		;MOVE EVERYTHING
; HERE TO DELETE BACK TO THE BEGINNING OF THE PREVIOUS (OR THIS) WORD

METARB:	SKIPN CECPOS		;Beginning of line?
	 RET       		;YES, AN ERROR...GET THE NEXT COMMAND
	MOVE A,CEBPTR		;GET POINTER
	ILDB B,A		;AT THE END OF THE LINE?
	PUSH P,B		;SAVE LAST CHARACTER
	CALL B.WORD		;GET DESTINATION
	MOVN D,B		;MAKE IT NEGATIVE
	MOVE A,D
	ADDM A,CECPOS		;FIX UP POSITION
	ADJBP A,CEBPTR		;GET DESTINATION POINTER
	EXCH A,CEBPTR		;FOOL M.FIX - WE ARE NOW A M-D
	POP P,B			;GET CHAR WE SAVED
METAR1:	JUMPE D,METAR2		;NEED TO MOVE THE CURSOR OVER
	PUSH P,A		;SAVE THE POINTER
	CALL CEBACK		;BACK UP
	POP P,A			;RESTORE THE POINTER
	AOJA D,METAR1
METAR2:	JUMPE B,CEKILL		;IF WE'RE AT EOL, JUST KILL IT




; HERE TO FIX THINGS UP AFTER METAD, METARB, OR ALTER MODE DELETE

M.FIX:	PUSH P,A		;A HAS END OF WORD TO STUFF IN KILL BUFFER
	MOVE B,CEBPTR		;B HAS START OF IT
	MOVE D,[POINT 7,CEKBUF]	;POINT TO KILL BUFFER
	CAMN A,B		;DOING ANYTHING?
	 JRST M.FIX3		;NO, DON'T LOOP FOREVER
M.FIX2:	ILDB C,B		;GET A CHARACTER OF DELETED STRING
	IDPB C,D		;SAVE IT IN THE KILL BUFFER
	CAME A,B		;SAVED ALL OF THE WORD YET?
	 JRST M.FIX2		;NO, DO NEXT CHARACTER
	SETZ C,			;GET A NULL BYTE
	IDPB C,D		;TIE OFF THE KILL BUFFER
M.FIX3:	POP P,B			;GET COPY OF DESTINATION POINTER
	SKIPN CEDUMB		;EMACS OR SMART ALTER?
	 PSOUT			;YES, OVERWRITE THE SCREEN
	CALL EEOLN		;CLEAN THINGS UP
	MOVE A,CEBPTR		;GET CURRENT POINTER
M.FIX1:	ILDB C,B		;GET FIRST CHARACTER
	IDPB C,A		;SAVE IN NEW POSITION
	JUMPN C,M.FIX1		;DONE?
	JRST CINST1		;POSITION THE CURSOR
; SUBROUTINE TO RETURN NUMBER OF SPACES UNTIL START OF NEXT WORD

F.WORD:	SETZ B,			;INITIALIZE COUNT
	MOVE C,CEBPTR		;GET LOCAL COPY OF POINTER
	ILDB A,C		;GET THIS CHARACTER
	JUMPE A,[RET]		;END OF LINE, QUIT
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST F.WRD2
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST F.WRD2
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST F.WRD2
F.WRD1:	ILDB A,C		;GET NEXT CHARACTER
	AOS B			;UPDATE COUNT
	JUMPE A,[RET]		;END OF LINE
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST F.WRD2
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST F.WRD2
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST F.WRD2
F.WRD2:	ILDB A,C		;GET NEXT CHARACTER
	AOS B			;INCREMENT COUNT
	JUMPE A,[RET]		;END OF LINE
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST F.WRD2
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST F.WRD2
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST F.WRD2
	RET			;YES, DONE.
; SUBROUTINE TO RETURN NUMBER OF SPACES UNTIL START OF PREVIOUS WORD

B.WORD:	SETZ B,			;INITIALIZE COUNT
	MOVE C,CEBPTR		;GET LOCAL COPY OF POINTER
	MOVE D,CECPOS		;LOCAL COPY OF POSITION
	JUMPE D,[RET]		;BEGINNING OF LINE, EXIT
	ILDB A,C		;GET THIS CHARACTER
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST B.WRD0
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST B.WRD0
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST B.WRD0
	JRST B.WRD1		;NO, IN THE MIDDLE OF A WORD
B.WRD0:	LDB A,CEBPTR		;GET WORD BEFORE THIS ONE
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST B.WRD2
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST B.WRD2
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST B.WRD2

;	CONTINUED ON NEXT PAGE
B.WRD1:	SETO A,			;BACKUP THE POINTER
	ADJBP A,C
	MOVE C,A
	LDB A,C			;GET NEXT ONE
	SOS D			;UPDATE COUNT
	AOS B			;UPDATE THIS TOO
	JUMPE D,[RET]		;CHECK FOR BEGINNING OF LINE
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST B.WRD2
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST B.WRD2
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST B.WRD2
	JRST B.WRD1
B.WRD2:	SETO A,			;BACKUP THE POINTER
	ADJBP A,C
	MOVE C,A
	LDB A,C			;GET NEXT CHARACTER
	SOS D			;UPDATE EVERYTHING
	AOS B
	JUMPE D,[RET]		;CHECK FOR BEGINNING OF LINE
	CAIL A,"0"
	 CAILE A,"9"
	  SKIPA
	   JRST B.WRD2
	CAIL A,"A"
	 CAILE A,"Z"
	  SKIPA
	   JRST B.WRD2
	CAIL A,"a"
	 CAILE A,"z"
	  SKIPA
	   JRST B.WRD2
	SOS B			;ADJUST IF NOT BEGINNING OF LINE
	RET			;ALL DONE

; HERE TO STICK AN ESCAPE OR QUESTION MARK ON THE END OF THE COMMAND

METAES:	SKIPA B,[.CHESC]	;STUFF ESCAPE WITH THE COMMAND
METAQU:	MOVEI B,"?"		;STUFF ? WITH THE COMMAND
METAEQ:	ILDB A,CEBPTR		;LOOK FOR THE END OF THE LINE
	JUMPE A,METEQ1
	JRST METAEQ		;TRY AGAIN
METEQ1:	MOVEI C,.CHCNR		;PUT A ^R IN FIRST SO EVERYTHING
	DPB C,CEBPTR		;IS ECHOED BY FIELD
	IDPB B,CEBPTR		;NOW STUFF THE NEW CHARACTER
	IDPB A,CEBPTR		;ADD A ZERO BYTE
	JRST CEEX2


; HERE WHEN BUFFER ABOUT TO OVERFLOW.  QUIT, INSTEAD OF MUNGING EXEC.
KABOOM:	MOVEI A,.PRIIN
	CFIBF			;CLEAR THE INPUT BUFFER
	CALL CEBELL		;GONG!
	TYPE <
?Buffer overflow, aborting command edit>
	JRST CEQUIT		;ABORT EDIT


; WHEN DONE, PASS THE EDITED COMMAND TO THE EXEC TO USE.
; NOTE THAT FOR A NORMAL RETURN (I.E. JUST CR) WE CAN'T JUST STUFF A ^R
; AT THE END OF THE BUFFER AND LET FIELD DO ALL THE DIRTY WORK OF ECHOING
; THE COMMAND, BECAUSE THERE IS NO WAY TO MAKE IT PRINT OUT A CARRIAGE RETURN
; AT THE END!!! SIGH, THUS THIS HACK...

CEEXIT:	ILDB A,CEBPTR		;FIRST FIND LAST CHARACTER IN LINE
	JUMPN A,CEEXIT
	SETO A,
	ADJBP A,CEBPTR		;POINT TO LAST CHARACTER
	LDB B,A
	CAIN B,.CHESC		;IS THE LAST CHAR AN ESCAPE?
	 JRST [	MOVEM A,CEBPTR	;IF SO, THEN USE METAES TO EXIT
		SETZ A,		;PUT A NULL IN A
		JRST METEQ1 ]
	SETOM NOPRMT		;DON'T PRINT PROMPT WHEN RSCANING BUFFER
	HRROI A,CETSAV		;GET THE COMMAND WE'RE GOING TO EXECUTE
	MOVEI B,LF		;PUT A LF AT THE END OF THE BUFFER
	DPB B,CEBPTR
	SETZ A,			;AND A NULL
	IDPB A,CEBPTR

CEEX2:	MOVEI A,.CTTRM
	CFIBF			;CLEAR THE INPUT BUFFER
	MOVE A,[POINT 7,CETSAV]	;POINT TO EDITED COMMAND
	RSCAN			;PUT STUFF IN RSCAN BUFFER
	 ERJMP CEEX3
	MOVEI A,.RSINI		;NOW GIVE TO THE EXEC TO USE
	RSCAN
	 ERJMP CEEX3
	CALL QUITR		;GO CLEAN UP
	ETYPE <
>
	RET

CEEX3:	ETYPE <?RSCAN failure when trying to execute the new command>
	SKIPA
CEQUIT:	ETYPE <%_[Aborting]>
	CALL QUITR		;DO THE CLEAN UP WORK
	MOVEI B,CR
	STI
	 ERJMP [ERROR <STI failure when trying to execute the new command>]
	SETZM CEBPTR		;MAKE SURE THE NEXT COMMAND IS SAVED
	RET

QUITR:	MOVE Q1,CEFLAG
	CAIN Q1,M.SED		;EDITOR IS SED ?
	 CALL VTEXIT		;YES - CLEAR APP KEYPAD MODE
	MOVEI Q1,ETTYMD		;LOAD EXEC TTY MODES
	CALL LTTYMD
	MOVEI A,.CTTRM 
	MOVE B,CETTMD		;RESTORE MODE WORD
	STPAR
	SFMOD
	MOVEI B,.MOXOF
	SKIPE C,CEPEOP		;GET OLD SETTING OF PAUSE @ EOP
	MTOPR			;AND SET IT
	SETOM CEEOC		;SET EXITING FLAG
	SETZM CEBPTR		;SAVE THIS COMMAND
	RET


;BEGIN ADDITION - MAKE SURE TTY GETS FIXED UP ON ERROR

CEERET:	MOVEI Q1, RERET		;PUT DEFAULT CLEANUP ROUTINE ADDRESS BACK
	MOVEM Q1, CERET	
	MOVEI Q1, ETTYMD	;NORMAL EXEC TTY MODES
	CALL LTTYMD		;FIX UP THE TTY
	MOVEI A,.CTTRM		;RESTORE OLD STPAR PARAMETERS TOO
	MOVE B,CETTMD		;GET JFN MODE WORD BACK
	STPAR			;PUT BACK THE CORRECT MODES
	JRST @CERET		;NOW GO DO DEFAULT CLEANUP

; ROUTINE TO REDISPLAY THE LINE

CEDISP:	TYPE <
>				;GO TO A NEW LINE
	CALL EEOLN		;JUST TO BE SURE
	CALL CENUMB		;DO THE LINE NUMBER
	HRROI A,CETSAV		;POINT TO COMMAND LINE
	PSOUT			;WRITE IT OUT
	JRST CINST1		;POSITION THE CURSOR


;Routine to send a bell to the terminal

CEBELL:	HRROI A,[BYTE (7) .CHBEL,0] ;SEND THE BELL
	CALL CECCOC
	RET

;Routine to set CCOC words, output a string, then reset the CCOC words

CECCOC:	STKVAR <SVSTG,<SVCCOC,2>>
	MOVEM A,SVSTG		;SAVE STRING POINTER
	MOVE A,COJFN		;REDO THE CCOC
	RFCOC
	DMOVEM B,SVCCOC		;SAVE MODE
	MOVE B,[525252,,525252]	;SEND ACTUAL CODE
	MOVE C,B
	SFCOC
	MOVE B,SVSTG		;GET STRING POINTER BACK
	SETZ C,
	SOUT			;OUTPUT IT
	DMOVE B,SVCCOC	
	SFCOC			;RESTORE MODE
	RET
; ROUTINE TO BACK THE CURSOR UP ONE PLACE

CEBACK:	MOVE A,COJFN		;GET THE TERMINAL TYPE
	RFMOD			;GET MODE WORD
	PUSH P,B		;SAVE IT
	TXZ B,TT%DAM		;NO TRANSLATION
	SFMOD
	GTTYP
	HRROI A,[ASCIZ //]	;ASSUME NORMAL TERMINAL
	CAIE B,^D16		;GET THE VT100 TYPES OUT OF THE WAY
	 CAIN B,^D33
	  HRROI A,[ASCIZ //]
	CAIE B,^D40
	 CAIN B,^D41
	  HRROI A,[ASCIZ //]	;VT200
	CAIN B,^D37		;VT102
	  HRROI A,[ASCIZ //]
	CAIN B,^D27		;BEEHIVES
	 HRROI A,[ASCIZ /D/]
	CAIN B,^D44		;DATAPOINTS
	 HRROI A,[ASCIZ //]
	PSOUT
	MOVE A,COJFN		;RESTORE MODE WORD
	POP P,B			;GET OLD MODE
	SFMOD			;DO IT
	RET



; ROUTINE TO ERRASE ALL CHARACTERS TO THE END OF LINE

EEOLN:	PUSH P,A		;SAVE THIS
	PUSH P,B		;THIS TOO
	MOVE A,COJFN		;CURRENT OUTPUT JFN
	RFMOD			;GET MODE WORD
	PUSH P,B		;SAVE IT
	TXZ B,TT%DAM		;NO TRANSLATION
	SFMOD
	GTTYP			;GET TERMINAL TYPE
	CAIG B,EOLNMX		;ALL WE KNOW ABOUT NOW
	SKIPN A,EEOLTB(B)	;GET STRING TO DUMP
	 JRST EEOLN2		;NONE - DO NOTHING
	TLNN A,-1		;STRING OR PNTR?
	 TLOA A,-1		;PNTR TO TEXT
	  HRROI A,EEOLTB(B)	;STRING - POINT TO IT INSTEAD
	PSOUT			;DUMP IT
EEOLN2:	MOVE A,COJFN		;RESTORE MODE WORD
	POP P,B			;GET OLD MODE
	SFMOD			;DO IT
	POP	P,B		;RESTORE THIS
	POP	P,A		;THIS TOO
	RET
;	ERASE TO END OF LINE TABLE

EEOLTB:	0				;0
	0				;1
	0				;2
	0				;3
	0              			;4 
	0                        	;5 
	0                           	;6 
	0                       	;7 
	0				;8
	0				;9
	BYTE (7)36,0			;10 VT05
	BYTE (7).CHESC,"K",0		;11 VT50
	0				;12 LA30
	0				;13 GT40
	0				;14 LA36
	BYTE (7) .CHESC,"K",0		;15 VT52
	BYTE(7).CHESC,"[","K",0		;16 VT100
	0				;17 LA38
	0				;18 LA120
	0                    		;19 
	0                    		;20 
	0                    		;21 
	0                    		;22 
	0                    		;23 
	0                    		;24 
	0                    		;25 
	0                    		;26 
	0                    		;27 
	0                    		;28 
	0                    		;29 
	0                    		;30 
	0				;31
	0				;32
	0				;33
	0				;34
	BYTE(7).CHESC,"[","K",0		;35 VT125
	BYTE(7).CHESC,"[","K",0		;36 GIGI
	BYTE(7).CHESC,"[","K",0         ;(37) VT102
	BYTE(7).CHESC,"[","K",0         ;(38) H19
	BYTE(7).CHESC,"[","K",0         ;(39) VT131
	BYTE(7).CHESC,"[","K",0         ;(40) VT200
REPEAT ^D10,<0>			;(41-50) (RESERVED FOR CUSTOMER)
REPEAT ^D10,<0>			;(51-60) (RESERVED FOR DIGITAL)
EOLNMX== .-EEOLTB-1

;ROUTINE TO TYPE A HELP MESSAGE WITH EDITORS

CSHELP:	HRROI B,[ASCIZ/HLP:EXEC-SED-KEYS.HLP/]
	CALL CEDHLP
	JRST CEDISP

CEHELP:	HRROI B,[ASCIZ/HLP:EXEC-EMACS-KEYS.HLP/]
	CALL CEDHLP
	JRST CEDISP

CVHELP:	HRROI B,[ASCIZ/HLP:EXEC-VMS-KEYS.HLP/]
	CALL CEDHLP
	JRST CEDISP

CAHELP:	HRROI B,[ASCIZ/HLP:EXEC-ALTER-KEYS.HLP/]
	CALL CEDHLP
	JRST CETOP


CEDHLP:	PUSH P,B
	CALL BLANK1		;CLEAR THE SCREEN
	POP P,B
	MOVX A,GJ%OLD+GJ%SHT+GJ%IFG ;OLD FILE ONLY, SHORT FORM
	CALL GTJFS		;GET HANDLE ON HELP FILE
	 ERROR <No help available, the help file was not found.>
	MOVEI Q1,CP%HEL		;SO "TYPE" LOGIC WILL KNOW IT'S US
	MOVE A,JBUFP		;GET POINTER TO JFN CELL
	HRRZM A,INIFH1
	HRRZM A,INIFH2		;COPY CODE NEEDS THIS
	CALL TYPE1		;FINISH COMMAND BY COPYING HELP FILE TO TERMINAL
	RET

;	COMMAND EDIT INTERRUPT ROUTINE

.CEPSI::SKIPN CLF		;AT COMMAND LEVEL?
	 DEBRK			;NO, DON'T DO THIS
	SKIPE .P		;DO WE HAVE A SAVED STACK POINTER?
	 MOVE P,.P		;YES, RESTORE IT
	CALL RLJFNS		;RELEASE PARSED JFN'S
	MOVE A,[POINT 7,CBUF]	;LOOK AT THE COMMAND BUFFER
	ILDB B,A		;GET THE NEXT CHARACTER
	JUMPN B,.-1		;KEEP LOOKING FOR A NULL
	SETO C,			;FOUND IT
	ADJBP C,A		;BACK UP ONE CHARACTER
	MOVEI A,.PRIIN		;LOOK AT THE TERMINAL
	SIBE			;ANYTHING THERE?
	 JRST [	MOVE A,C	;YES, ADD IT TO THE BUFFER
		MOVE B,[RD%RIE+^D80]
		SETZ C,		;NO PROMPT, QUIT WHEN TTY BUFFER IS EMPTY
		RDTTY		;GET IT
		 ETYPE <%_%%Can not find rest of command, Continuing>
		IDPB C,A	;ASCIZ THE STRING
		JRST .+1 ]	;READY TO GO NOW
	CALL CSAVE		;SAVE THE COMMAND IN PROGRESS
	 JFCL			;IGNORE THE ERROR
	CALL CEPSI1		;GO DO THE WORK
	MOVE A,LEV1PC		;GET THE RETURN ADDRESS
	HRRI A,CMDIN4		;CHANGE IT
	TXO A,PC%USR		;RETURN TO USER CODE
	MOVEM A,LEV1PC		;RESTORE FIXED PC
	DEBRK			;PARSE EDITED COMMAND

CEPSI1:	CESTG			;ASSURE CONSISTENT TRVAR
	SETZM CEDSEA		;INITIALIZE STUFF
	CALL CEDITU		;GO TO THE EDITOR
	RET
;	"SET INTERRUPT-CHARACTER (FOR COMMAND EDITOR TO) CHAR" COMMAND

.SCEIC::NOISE (for command editor to)
	STKVAR <ICHAR>		;CHARACTER TO INTERRUPT ON
	MOVEI B,CEICLS		;POINT TO THE LIST
	CALL FLDSKP		;GET THE CHARACTER
	 JRST [ ETYPE <%@?Character not available%_>
		RET ]
	HRRZ C,1(C)		;POINT TO THE STRING
	LDB B,[POINT 7,(C),13]	;GET THE CHARACTER
	TXZ B,1B29!1B30		;MAKE IT A CONTROL CHARACTER
	MOVEM B,ICHAR		;SAVE IT
	NOISE (for command editor)
	CONFIRM			;CONFIRM THE COMMAND
	SKIPL A,CEPSIC		;GET THE OLD CHARACTER
	 DTI			;IF ONE WAS ASSIGNED THEN DEASSIGN IT
	HRLZ A,ICHAR		;GET THE NEW ONE
	HLRZM A,CEPSIC		;SAVE IT
	HRRI A,CEDCHN		;SET THINGS UP ;CS4 use a symbol
	ATI			;ASSIGN NEW INTERRUPT CHARACTER
	RET			;DONE


.SNCEI::NOISE (for command editor)
	CONFIRM			;COMFIRM "SET NO INTERRUPT-CHARACTER"
	SKIPGE A,CEPSIC		;DO WE HAVE ONE?
	 RET			;NO, QUIT
	DTI			;WE HAD ONE, DEASSIGN IT
	SETOM CEPSIC		;SAY WE DON'T HAVE ONE
	RET			;DONE
;	COMMAND EDIT INTERRUPT CHARACTER LIST

CEICLS:	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^@.]>,,,Z1
Z1:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^A.]>,,,Z2
Z2:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^a.]>,,,Z3
Z3:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^B.]>,,,Z4
Z4:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^b.]>,,,Z5
Z5:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^D.]>,,,Z6
Z6:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^d.]>,,,Z7
Z7:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^G.]>,,,Z8
Z8:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^g.]>,,,Z9
Z9:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^K.]>,,,Z10
Z10:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^k.]>,,,Z11
Z11:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^N.]>,,,Z12
Z12:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^n.]>,,,Z13
Z13:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^P.]>,,,Z14
Z14:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^p.]>,,,Z15
Z15:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^Q.]>,,,Z16
Z16:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^q.]>,,,Z17
Z17:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^S.]>,,,Z18
Z18:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^s.]>,,,Z19
Z19:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^X.]>,,,Z20
Z20:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^x.]>,,,Z21
Z21:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^Y.]>,,,Z22
Z22:!	FLDDB. .CMTOK,CM%SDH,<POINT 7,[ASCIZ .^y.]>,<Control character
(typed as a two-character sequence)>


.META::	NOISE <EXISTS ON TERMINAL>
	CONFIRM
	SETOM CEMETA
	RET



.NOMET::NOISE <EXISTS ON TERMINAL>
	CONFIRM
	SETZM CEMETA
	RET


.CESET::KEYWD $CESET		;POINT AT TABLE
	0
	JRST CERR
	HRRZS P3		;ONLY GET THE DISPATCH ADDRESS
	JRST (P3)		;GO THERE


$CESET:	TABLE
	T HISTORY,,.SEHST	;SET EDIT HISTORY n (COMMAND EDITOR)
	T INTERRUPT-CHARACTER,,.SCEIC ;SET INTERRUPT (COMMAND EDITOR)
	T MODE,,.CEDMO		;SET EDIT MODE (COMMAND EDITOR)
	TEND



;HERE FOR INFORMATION ABOUT COMMAND EDITOR

INFOCE::TYPE < SET EDIT MODE >
	MOVE A,CEFLAG
	CAIN A,M.EMCS		;EMACS MODE ?
	 TYPE <EMACS-STYLE-COMMANDS>
	CAIN A,M.SED
	 TYPE <SED-STYLE-COMMANDS>
	CAIN A,M.EDIT
	 TYPE <ALTER-STYLE-COMMANDS>
	CAIN A,M.VMS
	 TYPE <VMS-STYLE-COMMANDS>
	TYPE <
>
	TYPE < SET >		; REPORT THE INTERRUPT STUFF
	SKIPL A, CEPSIC		; ANY INTERRUPT CHARACTER SET?
	IFSKP.			; NO,
	  TYPE <NO EDIT INTERRUPT-CHARACTER (FOR COMMAND EDITOR)
>
	  RET			; SAY SO, AND RETURN
	ENDIF.
	TYPE <EDIT INTERRUPT-CHARACTER (TO) ^>
	ADDI A, 100		; MAKE IT A REAL CHARACTER
	PBOUT%			; AND OUTPUT IT
	TYPE < (FOR COMMAND EDITOR)
>
	RET



;THIS TELLS WHETHER TERMINAL META-KEY ENABLED - FOR "INFORMATION (ABOUT) TERMINAL"

IMETKY::MOVE A, TERMNL		; THIS TERMINAL?
	CAIN A, .CTTRM		; IF NOT, SKIP THIS
	SKIPN CEMETA		; META KEY ENABLED?
	IFSKP.
	  TYPE < TERMINAL META-KEY
>
	ENDIF.
	RET			; ALL DONE


;"SET COMMAND-EDIT-MODE" , USED BY COMMAND EDITOR

.CEDMO::NOISE <TO>
	KEYWD $CEDIT		;POINT AT EDITOR TABLE
	0
	JRST CERR
	HRRZS P3		;GET RID OF LEFT HALF
	MOVEM P3,CEFLAG		;SET MODE
	CAIN P3,M.VMS		;VMS MODE ?
	 JRST VMSDEF		;YES - ALLOW A DEFAULT MODE
	RET


M.EMCS==0	;EMACS MODE
M.EDIT==1	;EDIT/SOS/ALTER MODE
M.SED==2	;SED MODE
M.VMS==3	;VMS MODE

$CEDIT:	TABLE
	T ALTER-STYLE-COMMANDS,ONEWRD,M.EDIT
	T EMACS-STYLE-COMMANDS,ONEWRD,M.EMCS
	T SED-STYLE-COMMANDS,ONEWRD,M.SED
	T VMS-STYLE-COMMANDS,,M.VMS
	TEND


;Dispatch table for selected editor type. Order is based on M.xxxx values

EDISP:	XWD ECEINC,ECEDSP	;EMACS
	XWD ACEINP,ACEDSP	;EDIT/SOS STYLE MODE
	XWD SEDINP,SEDDSP	;SED MODE (USE SAME INPUT ROUTINE AS EMACS)
	XWD ECEINC,VMSDSP	;VMS MODE (USE SAME INPUT ROUTINE AS EMACS)
CEDSPL==.-CEDISP


;HERE TO SET DEFAULT VMS INSERT/OVERSTRIKE MODE

VMSDEF:	NOISE (WITH)
	KEYWD $INSOV		;POINT AT MODE TABLE
	T INSERT,ONEWRD,INSON 	;DEFAULT IS INSERT MODE
	JRST CERR
	HRRZS P3		;ONLY GET THE DISPATCH ADDRESS
	JRST (P3)		;GO THERE

$INSOV:	TABLE
	T INSERT,ONEWRD,INSON 	;DEFAULT IS INSERT MODE
	T OVERSTRIKE,ONEWRD,OVRON ;OVERSTRIKE MODE
	TEND

INSON:	SETOM CEVMSD		;INSERT MODE
	RET
OVRON:	SETZM CEVMSD		;OVERSTRIKE MODE
	RET



;HERE FOR SETTING UP COMMAND HISTORY

.SEHST::SKIPE SETNOF		; WAs "NO" SPECIFIED?
	JRST .SEHS1		; YES
	DECX <Decimal number of commands to remember> ; GET NUMBER
	 CMERRX			; BAD INPUT
	CAIG B, HSTMAX		; LARGER THAN MAX ALLOWED?
	JUMPG B, .SEHS2		; INPUT IS oK
	MOVEI A, HSTMAX+1	; GET MAX NUMBER
	ETYPE <?Number must be larger than zero but smaller than %1Q>
	RET
.SEHS1:	SETZ B,			; SET NO HISTORY
.SEHS2:	CONFIRM			; GET EOL
	PUSH P, B		; SAVE NEW VALUE
	SKIPN A, HSTCNT		; DO WE HAVE ANYTHING NOW?
	JRST .SEHS4		; NO, SO JUST GO ALLOCATE ANEW
	MOVEM A, HSTNUM		; SAVE THIS NUMBER FOR LATER
.SEHS3:	HLRZ C, HSTPTR		; GET ADDRESS OF PTR BLOCK
	ADD C, HSTCNT		; LOOK AT EACH STRING
	SUBI C, 1		; BASE 0. OFFSET CORRECTLY
	SKIPE A, (C)		; GET POINTER TO COMMAND STRING
	CALL STREM		;RETURN IF NOT NULL
	SOSE HSTCNT		; WORK UP THE LIST
	JRST .SEHS3		; UNTIL IT IS EXHAUSTED
	MOVE A, HSTNUM		; GET NUMBER OF WORDS TO RETURN
	HLRZ B, HSTPTR		; ADDRESS OF POINTER BLOCK
	CALL RETBUF		; RETURN IT
.SEHS4:	POP P, A		; GET NEW COUNT BACK
	MOVEM A, HSTCNT		; AND SAVE IT
	SKIPN A			; DON'T CALL ALLOCATION ROUTINE
	JRST R			; SKIP THIS
	CALL GTBUFX		; IF NON-ZERO, GET PERMANENT SPACE
	HRLZM A, HSTPTR		; SAVE ADDRESS OF POINTER BLOCK
	ADD A, HSTCNT		; POINT TO LAST ENTRY
	HRRM A, HSTPTR		; AND SAVE IT
	MOVN A, HSTCNT		; GET NUMBER OF WORDS TO CLEAR
	HRLZS A			; MOVE TO LEFT HALF
	HLR A, HSTPTR		; GET BASE ADDRESS BACK
	SETZM (A)		; CLEAR ALL WORDS TO ZERO
	AOBJN A, .-1		; UNTIL DONE
	SETZM HSTNUM		; ALWAYS RESET COMMAND COUNT
	RET			; AND RETURN



;HERE TO SAVE THE COMMANDS FOR COMMAND HISTORY


CMDHST::CALL CSAVE		; SAVE COMMAND FOR COMMAND EDITOR
	 SKIPA			; COULDN'T - DON'T DO THIS, EITHER
	SKIPN HSTCNT		; DOING HISTORY?
	 RET               	; NO, SKIP THIS
	LDB A, [POINT 7,CBUF,6] ; GET FIRST CHARACTER IN COMMAND BUFFER
	AOS HSTNUM		; BUMP COMMAND COUNTER
     	HRROI A, CBUF		; GET POINTER TO COMMAND INPUT
	CALL XBUFFS		; COPY IT TO PRV. PERMANENT FREE SPACE
	HRRZ B, HSTPTR		; LOOK AT CURRENT SLOT
	HLRZ C, HSTPTR		; GET BASE SLOT
	ADD C, HSTCNT		; POINT ONE PLACE PAST
	CAML B, C		; PAST END?
	HLR B, HSTPTR		; GET ADDRESS OF BASE, THEN
	HRRM B, HSTPTR		; AND SAVE IT
	EXCH A, (B)		; SAVE POINTER TO COMMAND
	SKIPE A			; ANYTHING THERE?
	CALL STREM		; YES, RETURN IT
	HRRZ B, HSTPTR		; GET BACK POINTER TO NEW COMMAND
	MOVE A, (B)		; GET BYTE POINTER TO COMMAND
	AOS HSTPTR		; POINT TO NEXT EMPTY SLOT
FDHST1:	ILDB C,A		; GET A BYTE
	JUMPE C, R		; FOUND NULL BEFORE CRLF - FINE.
	CAIE C,.CHCRT		; LOOK FOR CR
	CAIN D, .CHLFD		; OR A LF
	CAIA			;
	JRST FDHST1		; TRY AGAIN
	SETO C,			; BACK UP OVER IT
	ADJBP C,A		;
	SETZ A,			; AND DEPOSIT A NULL
	IDPB A,C		; ON TOP OF IT
	RET

; INFORMATION HISTORY

.INHST::MOVE A,HSTCNT		; GET NUMBER KEEPING
	JUMPE A,[ERROR<No history>] ; SAY ERROR
	ETYPE < History: %1Q%%_> ; OUTPUT IT
	MOVNS A			; MAKE IT NEGATIVE
	MOVSS A			; MOVE COUNT TO LH
	HRR A,HSTPTR		; GET ADDRESS OF NEXT EMPTY SLOT
	MOVE D,HSTNUM		; GET COMMAND COUNT
	SUB D,HSTCNT		; SUBTRACT DISPLAY NUMBER
	SKIPGE D		; IF NEGATIVE, MAKE ZERO
	SETZ D,			;
.INHS1:	HLRZ B,HSTPTR		; GET BASE ADDRESS OF BLOCK
	ADD B,HSTCNT		; FIND END OF BLOCK
	HRRZ C,A		; GET CURRENT PTR
	CAML C,B		; PAST LAST SLOT?
	 HLR A,HSTPTR		; GET BASE ADDRESS THEN
	SKIPN C,(A)		; GET A PTR
	 JRST .INHS2		; CHECK NEXT ONE
	AOS D			; INCR COMMAND COUNT
	ETYPE < [%4Q] %3M%%_>	; OUTPUT COMMAND
.INHS2:	AOBJN A,.INHS1		; CDR THROUGH LIST
	RET			; THEN RETURN



;HERE TO DO HISTORY COMMANDS

.REDO::PUSH P,[CMDIN4]		;FAKE RETURN ADDRESS
	SKIPN HSTCNT		;ANY COMMANDS?
	 ERROR <No history>	;
	MOVE A,P		;SAVE STACK PTR
	TRVAR <COMNUM,SAVEP>
	MOVEM A,SAVEP		;SO WE KNOW WHERE RETURN ADDR IS
	MOVEI B,[FLDDB. .CMNUM,CM%SDH,5+5,<Decimal command number>,,[
		   FLDDB. .CMQST,CM%SDH,,<Quoted imbedded string>,,[
		    FLDBK. .CMFLD,,,<Command string>,,FLDMSK,]]]
	CALL FLDSKP		;TRY TO PARSE THAT
	 CMERRX			;ERROR OR SOMETHING
	LDB D,[331100,,(C)]	;GET FUNCTION CODE
	CAIN D,.CMNUM		;GO HANDLE COMMAND NUMBER
	 JRST .DOHSN		;IF NUMBER ENTERED
	CAIN D,.CMFLD		;WAS IT A FIELD
	 JRST .DOHSF		;GO EAT IT UP THEN
	JRST .DOHSQ		;GO HANDLE QUOTED STRING

;HERE TO HANDLE COMMAND NUMBER
.DOHSN:	MOVE A,B		;SAVE COMMAND NUMBER
.DOHN1:	JUMPL A,[AOS A		;IF NEGATIVE, RELATIVE NUMBER
		 ADD A,HSTNUM	;MAKE IT ABSOLUTE
		 JRST .+1]	;AND CONTINUE
	MOVE B,HSTNUM		;GET CURRENT COMMAND NUMBER
	SUB B,HSTCNT		;GET SMALLEST COMMAND WE HAVE
	SKIPGE B		;IF NEGATIVE, MAKE ONE
	 SETZ B,		;STILL HAVE THIS ONE THEN
	AOS B			;BASE 1
	CAMG A,HSTNUM		;SMALLER THAN LARGEST WE HAVE
	 CAMGE A,B		;AND LARGER THAN SMALLEST WE HAVE
	   ERROR <Command not found> ;TELL HIM WHY
	SOS A			;BASE 0 THE COUNT
	IDIV A,HSTCNT		;DIVIDE BY NUMBER OF COMMANDS
	HLRZ A,HSTPTR		;GET BASE ADDRESS
	ADD A,B			;GET PROPER OFFSET
	MOVEM A,COMNUM		;SAVE COMMAND ADDRESS
	JRST .DOHS2		;GO PARSE FOR ARGS.

;HERE FOR AGAIN COMMAND
.AGAIN::PUSH P,[CMDIN4]		;FAKE RETURN ADDRESS
	SKIPN HSTCNT		;ANY COMMANDS?
	 ERROR <No history>	;]
	MOVE A,P		;SAVE STACK PTR
	TRVAR <COMNUM,SAVEP>
	MOVEM A,SAVEP		;SO WE KNOW WHERE RETURN ADDR IS
	MOVE A,HSTNUM		;GET CURRENT COMMAND NUMBER
	JRST .DOHN1		;CALCULATE COMMAND ADDRESS

;HERE TO HANDLE STRING FIELD
.DOHSF:	CALL DOHFCM		;LOOK UP COMMAND
	 ERROR <Command not found in list> ;COULDN'T FIND IT
	MOVEM D,COMNUM		;SAVE NUMBER
	JRST .DOHS2		;JOIN OTHERS

;HERE TO HANDLE A QUOTED STRING
.DOHSQ:	CALL DOHFIS		;LOOK UP IMBEDDED STRING IN COMMANDS
	 ERROR <Command not found in list> ;COULDN'T FIND IT
	MOVEM D,COMNUM		;SAVE NUMBER
	JRST .DOHS2		;JOIN OTHERS

;HERE TO FINISH UP PARSE
.DOHS2:	CONFIRM			;GET CRLF
	MOVE A,COMNUM		;GET COMMAND NUMBER SPECIFIED
	SKIPN B,(A)		;GET THE PTR ITSELF
	 ERROR <Command not found> ;NOTHING THERE. SAY SO
	HRROI A,CBUF		;COPY IT TO COMMAND BUFFER
	SETZ C,			;TILL NULL FOUND
	SOUT%
	MOVEI B, .CHCRT		;ADD CARRIAGE RETURN
	IDPB  B,A
	MOVEI B,.CHLFD		;ADD LINE FEED
	IDPB B,A		;]
	SETZ B,			;NOW ADD NULL
	IDPB B,A		;TIE IT OFF
	HRROI A,CBUF		;GET COMMAND PTR
	ETYPE < %1M>		;OUTPUT IT ALWAYS
	MOVEM A,CMPTR		;SAVE FOR INPUT LATER
	CALL BCOUNT		;COUNT CHARACTERS
	ADDM B,CMINC		;KEEP COUNT IN HERE
	MOVE A,SAVEP		;GET PTR TO RETURN LOC ON STACK
	MOVEI B,CIN42		;WHERE TO RETURN TO
	MOVEM B,(A)		;STUFF IT SO WE RETURN THERE
	RET			;GO DO IT

;HERE FOR RECALL - DISPLAYS THE COMMAND REQUESTED, AND WAITS FOR CONFIRM


.RECAL::PUSH P,[CMDIN4]		; FAKE RETURN ADDRESS
	SKIPN HSTCNT		; ANY COMMANDS?
	 ERROR <No history>	;
	MOVE A,P		; SAVE STACK PTR
	TRVAR <COMNUM,SAVEP>
	MOVEM A,SAVEP		; SO WE KNOW WHERE RETURN ADDR IS
	MOVEI B,[FLDDB. .CMNUM,CM%SDH,5+5,<Decimal command number>,,[
		   FLDDB. .CMQST,CM%SDH,,<Quoted imbedded string>,,[
		    FLDBK. .CMFLD,,,<Command string>,,FLDMSK,]]]
	CALL FLDSKP		; TRY TO PARSE THAT
	 CMERRX			; ERROR OR SOMETHING
	LDB D,[331100,,(C)]	; GET FUNCTION CODE
	CAIN D,.CMNUM		; GO HANDLE COMMAND NUMBER
	 JRST .REHSN		;IF NUMBER ENTERED
	CAIN D,.CMFLD		; WAS IT A FIELD
	 JRST .REHSF		; GO EAT IT UP THEN
	JRST .REHSQ		; GO HANDLE QUOTED STRING

;HERE TO HANDLE COMMAND NUMBER
.REHSN:	MOVE A,B		; SAVE COMMAND NUMBER
.REHN1:	JUMPL A,[AOS A		; IF NEGATIVE, RELATIVE NUMBER
		 ADD A,HSTNUM	; MAKE IT ABSOLUTE
		 JRST .+1]	; AND CONTINUE
	MOVE B,HSTNUM		; GET CURRENT COMMAND NUMBER
	SUB B,HSTCNT		; GET SMALLEST COMMAND WE HAVE
	SKIPGE B		; IF NEGATIVE, MAKE ONE
	 SETZ B,		; STILL HAVE THIS ONE THEN
	AOS B			; BASE 1
	CAMG A,HSTNUM		; SMALLER THAN LARGEST WE HAVE
	 CAMGE A,B		; AND LARGER THAN SMALLEST WE HAVE
	   ERROR <Command not found> ; TELL HIM WHY
	SOS A			; BASE 0 THE COUNT
	IDIV A,HSTCNT		; DIVIDE BY NUMBER OF COMMANDS
	HLRZ A,HSTPTR		; GET BASE ADDRESS
	ADD A,B			; GET PROPER OFFSET
	MOVEM A,COMNUM		; SAVE COMMAND ADDRESS

.REHS2:	CONFIRM			; GET CRLF
	MOVE A,COMNUM		; GET COMMAND NUMBER SPECIFIED
	SKIPN B,(A)		; GET THE PTR ITSELF
	 ERROR <Command not found> ; NOTHING THERE. SAY SO
	HRROI A,CBUF		; COPY IT TO COMMAND BUFFER
	SETZ C,			; TILL NULL FOUND
	SOUT%
	SETZ B,			; NOW ADD NULL
	IDPB B,A		; TIE IT OFF
	HRROI A,CBUF		; GET COMMAND PTR
	ETYPE < %1M>		; OUTPUT IT ALWAYS
	MOVEM A,CMPTR		; SAVE FOR INPUT LATER
	CALL BCOUNT		; COUNT CHARACTERS
	ADDM B,CMINC		; KEEP COUNT IN HERE
	MOVE A,SAVEP		; GET PTR TO RETURN LOC ON STACK
	MOVEI B,CIN42		; WHERE TO RETURN TO
	MOVEM B,(A)		; STUFF IT SO WE RETURN THERE
	RET			; GO DO IT

.REHSF:	CALL DOHFCM		; LOOK UP COMMAND
	 ERROR <Command not found in list> ; COULDN'T FIND IT
	MOVEM D,COMNUM		; SAVE NUMBER
	JRST .REHS2		; JOIN OTHERS

;HERE TO HANDLE A QUOTED STRING
.REHSQ:	CALL DOHFIS		; LOOK UP IMBEDDED STRING IN COMMANDS
	 ERROR <Command not found in list> ; COULDN'T FIND IT
	MOVEM D,COMNUM		; SAVE NUMBER
	JRST .REHS2		; JOIN OTHERS
;DOHFCM -- DO HISTORY FIND COMMAND
DOHFCM:	HLRZ C,HSTPTR		;GET BASE ADDRESS
	HRRZ D,HSTPTR		;GET CURRENT PTR
	ADD C,HSTCNT		;SPECIAL FIRST CASE CHECK
	CAML D,C		;PTR WITHIN RANGE?
	 HLRZ D,HSTPTR		;IF OVER RABLE, POINT TO FIRST
	MOVE Q1,D		;SAVE CURRENT PTR
	HLRZ C,HSTPTR		;GET BASE ADDR BACK
DOHFC1:	SOS D			;BACKUP TO PREVIOUS COMMAND
	CAMLE C,D		;IS PTR LESS THAN BASE?
	 JRST [ HLRZ D,HSTPTR	;GET CURRENT BASE ADDRESS
		ADD D,HSTCNT	;GET TO END OF BLOCK
		SOS D		;BACK UP TO LAST ENTRY
		JRST .+1]	;CONTINUE ON
	HRROI A,ATMBUF		;GET PTR TO INPUT STRING
	SKIPN B,(D)		;GET PTR TO COMMAND
	 JRST DOHFC2		;NOTHING, LOOK AT NEXT ONE
	STCMP%			;COMPARE
	SKIPE A			;TOTAL MATCH?
	 TXNE A,SC%SUB		;SUBSET MATCH?
	  RETSKP		;]
DOHFC2:	CAMN D,Q1		;HAVE WE LOOPED?
	 RET			;FAILURE RETURN
	JRST DOHFC1		;NO GOOD. LOOK AT NEXT

;DOHFIS -- DO HISTORY FIND IMBEDDED STRING
DOHFIS:	HLRZ C,HSTPTR		;GET BASE ADDRESS
	HRRZ D,HSTPTR		;GET CURRENT PTR
	ADD C,HSTCNT		;SPECIAL FIRST CASE CHECK
	CAML D,C		;PTR WITHIN RANGE?
	 HLRZ D,HSTPTR		;IF PAST TABLE, MOVE TO FIRST ENTRY
	MOVE Q1,D		;SAVE CURRENT PTR
	HLRZ C,HSTPTR		;GET BASE ADDR BACK
DOHFI1:	SOS D			;BACKUP TO PREVIOUS COMMAND
	CAMLE C,D		;IS PTR LESS THAN BASE?
	 JRST [ HLRZ D,HSTPTR	;GET CURRENT BASE ADDRESS
		ADD D,HSTCNT	;GET TO END OF BLOCK
		SOS D		;BACK UP TO LAST ENTRY
		JRST .+1]	;CONTINUE ON
	MOVE B,[POINT 7,ATMBUF]	;GET PTR TO INPUT PATTERN
	SKIPN A,(D)		;GET PTR TO COMMAND STRING
	 JRST DOHFI2		;NOTHING, LOOK AT NEXT ONE
	CALL DOHFND		;DO PATTERN MATCH
	  SKIPA			;NOT FOUND
	RETSKP			;SAY FOUND IT. ADDR OF COMMAND IN D
DOHFI2:	CAMN D,Q1		;HAVE WE LOOPED?
	 RET			;FAILURE RETURN
	JRST DOHFI1		;NO GOOD. LOOK AT NEXT

;DOHFND -- DO HISTORY FIND
;A/ PTR STRING TO SEARCH IN
;B/ PTR PATTERN TO FIND IN STRING
;RETURNS +1 NOT FOUND
;	 +2 A/ PTR TO START OF PATTERN IN STRING
DOHFND:	JUMPE A,R		;RETURN IF STRING ZERO
	JUMPE B,R		;RETURN IF PATTERN ZERO
	PUSH P,C		;AC TO SAVE PLACE IN STRING
	PUSH P,D		;AC WE USE TO POINT TO PATTERN
	PUSH P,Q1		;SAVE PLACES FOR CHARACTERS
	PUSH P,Q2		;
DOHFN1:	MOVE C,A		;SAVE PTR INTO STRING
	MOVE D,B		;GET NEW PTR TO PATTERN
DOHFN2:	ILDB Q1,A		;GET A CHARACTER FORM STRING
	ILDB Q2,D		;GET A CHARACTER FROM PATTERN
	JUMPE Q2,[MOVE A,C	;RESTORE SAVED STRING POSITION
		  AOS -4(P)	;GOOD RETURN. MATCH FOUND
		  JRST DOHFN4]	;POP AND RETURN
	JUMPE Q1,DOHFN4		;END OF STRING?
	CAMN Q1,Q2		;CHARACTERS MATCH?
	 JRST DOHFN2		;LOOP UNTIL MISMATCH
	JRST DOHFN1		;TRY PATTERN ON UPDATED STRING
DOHFN4:	POP P,Q2		;RESTORE ACS
	POP P,Q1
	POP P,D
	POP P,C
	RET

FLDMSK:	BRMSK. FLDB0.,FLDB1.,FLDB2.,FLDB3.,</-!;.@\_$,*>

END