From: CRDGW2::CRDGW2::MRGATE::"SMTP::CUNYVM.CUNY.EDU::XLINHUCK%DDATHD21.BITNET" 2-NOV-1989 19:38
To: MRGATE::"ARISIA::EVERHART"

Date:     Thu,  2 Nov 89 18:43:35 +0200 (Central European Summertime)
From: [email-masked] (Volker Huck, TH Darmstadt, {06151}16-5152)
Subject:  European RSX SIGtape 1989
To: [email-masked]

Dear Glenn,

did you already receive the european RSX SIGtape? IF so I am sorry to tell
you that the most important program has an error. The source of MCE was
sent to The Hague via modem and there must have been some error. So I
was asked to put my source on the tape about one week ago. Unfortunately
it was too late then to correct it on your tape. So here is the file
MCE.MAC that I ask you to exchange on the SIGtape. MCE resides in directory
[265,2]. I also added two INI files MCEINI.DCL and MCEINI.MCR to this mail.

Thanks a lot and sorry for the mistake
Volker

=========================== MCE.MAC ========================================

        .TITLE    MCE - CLI-Commandline-Editor
;
        .IDENT    -V4.22a-      ; this identcode appears in MCE messages
;
        .ENABLE    LC
;
;       Copyright (c) 1987,1988,1989
;
;       J.H. Hamakers,
;       Asea Brown Boveri Industie b.v.
;       P.O.Box 113
;       3000 AC  Rotterdam
;       The Netherlands
;       Phone : +31 - 10 - 4078631
;
;       All rights reserved
;
;       This software may be copied and distributed ONLY
;       on a non profit basis and with the inclusion of
;       the above copyright statement.
;
;       PLEASE CONTACT ME FOR PROBLEMS OR SUGGESTIONS
;
;       +---------------------------------------------------+
;       | See MCEREL.DOC for information about this release |
;       +---------------------------------------------------+
;
; Test the ident of MCEPRE.MAC .....
;
        .IF NDF IDNPRE
ERROR ;MCE -- MCEPRE.MAC not compatible with this version of MCE.
ERROR ;       Please build again.
        .IFF
        .IF NE IDNPRE-4.
ERROR ;MCE -- MCEPRE.MAC not compatible with this version of MCE.
ERROR ;       Please build again.
        .ENDC
        .ENDC
;
        .SBTTL  MCE ----------- *** Macros, Constants, Variables etc. ***

;
; Psects used .....
;
        .PSECT  CODE ,I,RO
        .PSECT  IDATA,D,RW
        .PSECT  PDATA,D,RO
        .PSECT

;
; Macro calls .....
;
        .MCALL  DIR$    ,EXIT$S ,MRKT$S ,QIO$   ,SDIR$S
        .MCALL  SPWN$   ,SREX$S ,STSE$  ,STSE$S ,WTSE$

        .IF DF  FILE

        .MCALL  CSI$    ,CSI$1  ,CSI$2
        .MCALL  GET$S   ,CLOSE$ ,GMCR$  ,NMBLK$ ,OPEN$R
        .MCALL  FDBDF$  ,FDRC$A ,FDOP$A ,FSRSZ$

        .ENDC   ;FILE

        .IIF DF CLISUP!FILE             .MCALL  GCII$

        .IIF DF RTMESS!RTEXIT!TMOTIM    .MCALL  GLUN$S

        .IIF DF TMOTIM                  .MCALL  ASTX$S

        .IIF DF STATUS&TMOTIM           .MCALL  QIOW$S

;
; Local symbol definitions .....
;

CMDSIZ  = 78.
;
BELL    = 7
BKSP    = 10
LF      = 12
CR      = 15
ESC     = 33
BLNK    = 40
DEL     = 177
;
TI      = 1                     ; TI: LUN
INILUN  = 2                     ; MCEINI.xxx LUN
EFN     = 1                     ; Eventflag

        .IF DF  STATUS&TMOTIM

EFNAST  = 2                     ; Eventflag in TIMAST

        .ENDC   ;STATUS&TMOTIM

        .IIF NDF INSDEF    INSDEF = 0
        .IIF NDF INTDEF    INTDEF = 1
        .IIF NDF MAXFIF    MAXFIF = 22.
        .IIF NDF MINCHR    MINCHR = 1
        .IIF NDF OLDDEF    OLDDEF = 1
        .IIF NDF OVSDEF    OVSDEF = 0

        .IIF DF EDT     .IIF NDF EDTDEF    EDTDEF = 0
        .IIF DF EXTNPR  .IIF NDF PRMDEF    PRMDEF = 1
        .IIF DF STATUS  .IIF NDF STADEF    STADEF = 1

        .NLIST  BEX

        .MACRO  NEWLIN  Z
        .IF B Z
        .ASCII  <CR><LF>
        .IFF
        .ASCIZ  <CR><LF>
        .ENDC
        .ENDM   NEWLIN

;
; Stopfor/Waitfor I/O DPBs .....
;
; Normally we STOP for I/O. When MCE is aborted we WAIT for I/O.
; We use the WTSE$ directive here to copy the DIC-code to STOPIO.
; (See  EXAST:)
;
        .PSECT  PDATA

WAITIO: WTSE$

        .PSECT  IDATA

STOPIO: STSE$   EFN

;
; DBPs .....
;
        .IF DF  COMPND

SPAWN:  SPWN$   ,,,,,,,EXSTAT

        .IFF    ;COMPND

SPAWN:  SPWN$

        .ENDC   ;COMPND
;
        TASK    = SPAWN+S.PWTN          ; Taskname
        WAITFL  = SPAWN+S.PWEF          ; Event flag
$$$=.
=TASK

        .IF DF  CLISUP

        .RAD50  \CLI...\        ; Current CLI

        .IFF    ;CLISUP

        .RAD50  \MCR...\        ; Task for Systems without alternate CLI-Supp.

        .ENDC   ;CLISUP

=$$$

;
QIODIR: QIO$    ,TI,EFN,,IOSTAT
;
        ADR     = QIODIR+Q.IOPL         ; I/O Bufferaddress
        CODE    = QIODIR+Q.IOFN         ; I/O Functioncode
        LEN     = QIODIR+Q.IOPL+2       ; I/O length
                                        ; ( Also used for Spawn )
;
; File stuff .....
;

        .IF DF  FILE

        FSRSZ$  1               ; File storage region

        .PSECT  IDATA

;
; FDB for MCEINI files .....
;
FDBIN:  FDBDF$
        FDRC$A  ,CMDBUF ,CMDSIZ
        FDOP$A   INILUN ,FDSPT  ,NAMBLK ,FO.RD

;
; Descriptor dispatch table .....
;
FDSPT:  DEVL    ,DEV            ; Device string
FDIR:   DIRL    ,DIR            ; Directory string at startup
        0       ,0              ; No File name ( NAMBLK will be used )

;
; Descriptors .....
;
; Device descriptor in RW data section for it can be overwritten
;
DEV:    .ASCII    /LB:/         ; Device Name
DEVL = .-DEV
        .EVEN

        .PSECT  PDATA

        .IF DF  A$SV

DIR:    .ASCII  /[2,2]/

        .IFF    ;A$SV

DIR:    .ASCII  /[1,2]/

        .ENDC   ;A$SV

DIRL = .-DIR
        .EVEN

        .PSECT  IDATA

;
; Default startup filename block .....
;
; Default filename ( if no alternate CLI support ) is 'MCEINI.CMD'.
; Default device is SY: ( but superimposed by LB: in FDSPT ).
; SY: in the NAMBLK will be effective for files specified in the
; invoking MCR/DCL commandline. Specifying 'MCE XXX' thus results in
; file name 'SY0:XXX.CMD'.
; Note, that the filetype in NAMBLK will be overwritten by the CLI name.
; ( See GETCLI )
;
NAMBLK: NMBLK$  MCEINI ,CMD ,0 ,SY ,0
;
        FILTYP = NAMBLK+N.FTYP  ; Address of RAD-50 filetype

;
; CSI$ Control block .....
;
CSIBLK: CSI$                    ; Define CSI control block offsets
        .BLKB   C.SIZE
        .EVEN

        .ENDC   ;FILE

;
; Variable textstrings .....
;
; These textstrings are in RW Psects for they are dynamicly changed.
;

;
; - Pool information ...
;
POOLTX: .ASCII  /MCE -- Pool:/
POOLDT: .BLKB   18.

;
; - Startup text ...
;

        .IF DF  CLISUP

STRTXT: .ASCII  \MCE -- CLI-Commandline-Editor \

        .IFF    ;CLISUP

STRTXT: .ASCII  \MCE -- MCR-Commandline-Editor \

        .ENDC   ;CLISUP

IDENT:  .ASCII  \      \        ; Ident will be placed here

        .IIF DF A$SV    .ASCII \/ASV\

        .IIF DF VT2XX   .ASCII \/VT2\

        .IIF DF TDV2XX  .ASCII \/TDV\

        NEWLIN  Z

;
; - Help spawn string ...
;
HLPTXT: .ASCII  \HELP \

        .IIF DF HLPNEW  .ASCII  \/\

        .IIF DF A$SV    .ASCII  \ASV \

        .ASCII  \MCE\

HPAG0:  .ASCII  <0>\MCE\
HPAGE:  .ASCIZ  \ \

        .IF DF  COMPND

;
; - Terminating a compound commandline ...
;
EXSTMS: NEWLIN
        .ASCII  \MCE -- Terminated Compound Commandline, Exit status :\
EXSTDA: .ASCII  \     \
        NEWLIN
        .ASCII  \       --->\
EXSTML=.-EXSTMS

        .ENDC   ;COMPND

        .IF DF  STATUS

;
; - Statusline ...
;
STATX1: .ASCII  <ESC>"D"
        .ASCII  <ESC>"M"
STATX2: .ASCII  <ESC>"7"
        .ASCII  <ESC>"[1;23r"
        .ASCII  <ESC>"[24;1H"
        .ASCII  <ESC>"[7m"
STATX3: .ASCII  "MCE-"
IDENT2: .ASCII  "        FIFO:"
STALIR: .ASCII  "list/"
        .ASCII  "xx/"
        .ASCII  "xx/"
        .ASCII  "xx CMSZ:"
STACMD: .ASCII  "xx KEYP:"
STAKEY: .ASCII  "no  SVINT:"
STASVI: .ASCII  "xxx SVOLD:"
STASVR: .ASCII  "xxx TMO:"
STATMO: .ASCII  "no "
STALN3=.-STATX3
        .ASCII  <ESC>"[K"
        .ASCII  <ESC>"[m"
        .ASCII  <ESC>"8"
STALN2=.-STATX2
STALN1=.-STATX1

;
; - Statusline clear ..
;
STACLR: .ASCII  <ESC>"7"
        .ASCII  <ESC>"[1;24r"
        .ASCII  <ESC>"8"
        .ASCII  <ESC>"[J"
STACLN=.-STACLR

        .ENDC   ;STATUS

        .EVEN

        .PSECT  PDATA
;
; Permanent strings .....
;
BS:     .REPT   CMDSIZ          ; Backspace buffer for
        .ASCII  <BKSP>          ;   cursor positioning
        .ENDR                   ;
;
SCRCLR: .ASCII  <ESC>"[H"       ; Clear
        .ASCII  <ESC>"[J"       ;     screen
SCRCLL=.-SCRCLR                 ;

;
; - Various messages ...
;
BYETXT: .ASCIZ /BYE/
ENDTXT: NEWLIN                  ; Exit
EXITXT: .ASCIZ /MCE -- Exit/    ;   message
ERRTXT: NEWLIN
        .ASCIZ /MCE -- Internal command error/<BELL>
CRET:                           ; Only <CR><LF>
NOPOOL: NEWLIN
        .ASCIZ /MCE -- Pool exhausted - Install MCE with INC/<BELL>
TOOLON: NEWLIN
        .ASCIZ /MCE -- Command too long/<BELL>

        .IF DF  EDT

APLTXT: .ASCII  <ESC>/=/
EDTTXT: .ASCII  \HELP \

        .IIF DF HLPNEW  .ASCII  \/\

        .IIF DF A$SV    .ASCII  \ASV \

        .ASCIZ  \MCE KEYPAD\

INV:    .ASCII  <ESC>/[7m/
INVL    =.-INV
NOR:    .ASCII  <ESC>/[m/
NORL    =.-NOR
NUMTXT: .ASCII  <ESC>/>/

        .ENDC   ;EDT

        .IF DF  FILE

FLSTXT: NEWLIN
        .ASCIZ /MCE -- Filespecification syntax error/<BELL>
FILTXT: NEWLIN
        .ASCIZ /MCE -- File open error/<BELL>

        .ENDC   ;FILE

        .IF LT  MAXHLP-'A

;
; - This text is needed when MCE is not build together with a HELP-file ...
;
NOHTXT: NEWLIN
        .ASCII /MCE -- No information about number of HELP pages, /
        .ASCII /so cannot use NXT and PRV keys/
        NEWLIN
        .ASCII /       Generate MCE.HLP and MCE.TSK together with /
        .ASCII /MCEBLD.CMD/<BELL>
NOHLEN=.-NOHTXT

        .ENDC   ;MAXHLP-'A

;
; - RT: Messages ...
;
        .IF DF  RTEXIT

RTTXT:  NEWLIN
        .ASCII /MCE -- Started on a remote terminal (RT:) Exiting ...../<BELL>
        NEWLIN
RTTXTL=.-RTTXT

        .ENDC   ;RTEXIT

        .IF DF  RTMESS

RTTXT:  NEWLIN
        .ASCII /MCE -- ** WARNING ** Started on a remote terminal (RT:)/
        NEWLIN
        .ASCII /       If your local system is VMS with its commandline editor/
        NEWLIN
        .ASCII /       enabled please type "MCE EXIT"/<BELL>
        NEWLIN
RTTXTL=.-RTTXT

        .ENDC   ;RTMESS

        .IF DF  VT2XX

VT2ESQ: .ASCII  /[23~/          ; VT2XX <ESC> Picture
VT2ESL = .-VT2ESQ               ;

        .ENDC   ;VT2XX

        .EVEN

;
; Internal MCE command dispatch table .....
; ( See subroutine INTERN )
;
INTCMD:
        .ASCII  /CLEA/          ; Clear FIFO
        ICCLEA
        .ASCII  /CMSZ/          ; Minimum cmd size
        ICCMSZ
        .ASCII  /ECHO/          ; Echo commandline
        ICECHO
        .ASCII  /EXIT/          ; Task exit
        EXIT
        .ASCII  /FISZ/          ; FIFO maximum
        ICFISZ
        .ASCII  /FREE/          ; Free poolspace
        ICFREE
        .ASCII  /INSE/          ; Auto insert mode
        ICINSE
        .ASCII  /LIST/          ; FIFO is a list
        ICLIST
        .ASCII  /OVER/          ; Auto overstrike  mode
        ICOVER
        .ASCII  /PURG/          ; Delete all command translations
        ICPURG
        .ASCII  /RING/          ; FIFO is a ringbuffer
        ICRING
        .ASCII  /SVIN/          ; Save Internal commands on/off
        ICSVIN
        .ASCII  /SVOL/          ; Save Old commands on/off
        ICSVOL
        .ASCII  /VERS/          ; Version
        ICVERS

        .IF DF  EDT

        .ASCII  /KEYP/
        ICKEYP

        .ENDC   ;EDT

        .IF DF  EXTNPR

        .ASCII  /PROM/
        ICPROM

        .ENDC   ;EXTNPR

        .IF DF  FILE

        .ASCII  /CHAI/          ; Chain to other file (= READ)
        ICREAD
        .ASCII  /READ/          ; Read definition file 'MCE READ filespc'
        ICREAD
        .ASCII  /REPL/          ; Replace translations by new file
        ICREPL

        .ENDC   ;FILE

        .IF DF  STATUS

        .ASCII  /STAT/          ; Status line on/off
        ICSTAT

        .ENDC   ;STATUS

        0                       ; End of table marker

        .PSECT  IDATA
;
; Various variables and buffers .....
;
FREE:   .BLKW   2               ; Free memory listhead
IOSTAT: .BLKW   2               ; I/O Statusblock
MAXF:   MAXFIF                  ; FIFO size
MINC:   MINCHR                  ; Commandlength to be saved
POOL:   .BLKW   3               ; Pool information
PROMLF: DEFPR                   ; Point to default prompt with <LF><CR>
PROMPT: DEFPR+1                 ; Point to default prompt with <CR>

        .IF DF  COMPND

EXSTAT: .BLKW   8.              ; Exit status block

        .ENDC   ;COMPND

        .IF DF  EDT

SELSTR: 0                       ; Address of select start

        .ENDC   ;EDT

        .IF DF  TMOTIM!RTMESS!RTEXIT

GLUNB:  .BLKW   6.

        .ENDC   ;TMOTIM!RTMESS!RTEXIT

;
; Flags, buffers and other bytes .....
;
CHAR:   .BYTE   0               ; Input-character
ECHFLG: .BYTE   0               ; If ne : Echo commandline
INSFLG: .BYTE   INSDEF          ; If ne : Auto insert
                                ;         - change with MCE INSErt on/off
LEAFLG: .BYTE   0               ; If ne : Leave FIFO pointer     ( CTRL/X )
NEXFLG: .BYTE   0               ; If ne : Don't execute Command  ( CTRL/N )
NLOFLG: .BYTE   0               ; If ne : Don't load Command in Commandbuffer
OLDFLG: .BYTE   0               ; If ne : Old command , not edited
OVSFLG: .BYTE   OVSDEF          ; If ne : Auto overstike
                                ;         - change with MCE OVERstrike on/off
MODFLG: .BYTE   OVSDEF          ; If odd: Overstrike mode
                                ;         - change with ^A
PRIFLG: .BYTE   0               ; If ne : Commandbuffer being printout
RNGFLG: .BYTE   0               ; If ne : FIFO is a ringbuffer
                                ;         - change with MCE LIST/RING
SINFLG: .BYTE   INTDEF          ; If ne : Internal commands are saved
                                ;         - change with MCE SVINtern on/off
SOLFLG: .BYTE   OLDDEF          ; If ne : Old commands are saved
                                ;         - change with MCE SVOLd on/off

        .IF DF  EDT

EDTFLG: .BYTE   EDTDEF          ; If ne : EDT Mode active
                                ;         - change with MCE KEYPad on/off
GOLDFL: .BYTE   0               ; If ne : "GOLD" pushed
PSTBUF: .BLKB   CMDSIZ          ; Paste buffer
PSTLEN: .BYTE   0               ; Length of string in Paste buffer
SELFLG: .BYTE   0               ; if ne : Ansi-selective range active

        .ENDC   ;EDT

        .IF DF  EXTNPR

PRMFLG: .BYTE   PRMDEF          ; if ne : extended prompt

        .ENDC   ;EXTNPR

        .IF DF  FILE

FILINI: .BYTE   0               ; If ne : Startup file being processed
FILINP: .BYTE   0               ; If ne : File Input
FILREX: .BYTE   0               ; If ne : MCE Read or MCE Replace being
                                ;         processed
        .ENDC   ;FILE

        .IF DF  STATUS

STAFLG: .BYTE   STADEF          ; If ne : Status line is displayed
                                ;         - change with MCE STATus on/off

        .ENDC   ;STATUS

        .IF DF  TMOTIM

TMOCNT: .BYTE   TMOTIM          ; Counter for timeout
TT0FLG: .BYTE   0               ; If ne : TI: = TT0:

        .ENDC   ;TMOTIM

        .EVEN

;
; FIFO Buffer descriptors .....
;
FIFO:   0, FIFO                 ; Header FIFO Buffer
;
        F.1ST   = 0             ; Pointer to first entry
        F.LAST  = 2             ; Pointer to last entry
;
        FI.NXT  = 0             ; Pointer to next Entry
        FI.LEN  = 2             ; Length of entry
        FI.TXT  = 4             ; Text, terminated by binary 0
;
FIFCNT: .BYTE   0               ; Number of entries in FIFO
FIFPOI: .BYTE   0               ; Entry number
FIFPTR: 0                       ; Ptr to current Entry (for UP, DOWN keys)

;
; Translation buffer .....
; ( same entries as in FIFO )
;
TRNB:    0, TRNB                ; Header command definitions

;
; Terminal characteristics buffer .....
;
SFGMCB:
ANI:    .BYTE   TC.ANI,0        ; ANSI Terminal
HLD:    .BYTE   TC.HLD,0        ; Hold screen mode

        .IF DF  VT2XX!TDV2XX

TTP:    .BYTE   TC.TTP,0        ; Get terminal type

        .ENDC   ;VT2XX!TDV2XX

SFGMCL = .-SFGMCB

;
; Prompt area .....
;
        .BLKB   24.             ; Prompt buffer
        .EVEN
DEFPR:  .ASCII  <LF>            ;
        .ASCII  <CR>            ;
CMDBUF: .BLKB   CMDSIZ          ; Current buffer
CMDEND:
        .EVEN
SAVBUF: .BLKB   CMDSIZ          ; Save Buffer
RCLBUF: .BLKB   CMDSIZ          ; Recall Buffer
        .EVEN

        .IF DF  FILE

;
; MCR command line directive and buffer .....
;
GMCR:   GMCR$
;
        MCRLIN = GMCR+G.MCRB

        .ENDC   ;FILE

        .IF DF  CLISUP!FILE

;
; Buffer to receive CLI information .....
;
; Things taken from cli information are :
;
;  - CLI name to test if DCL    CLISUP
;  - CLI name as filetype       CLISUP&FILE
;  - Prompt                     CLISUP
;  - Current Directory          FILE
;
;
        CLIBSZ  = 50.
;
GCLI:   GCII$   CLIBUF,CLIBSZ
CLIBUF: .BLKB   CLIBSZ          ; Information buffer
;

        .ENDC   ;CLISUP!FILE

        .IF DF  CLISUP

        CLIPRM = CLIBUF+G.CIDP  ; CLI prompt
        CLINAM = CLIBUF+G.CICL  ; CLI name

        .ENDC   ;CLISUP

        .IF DF  FILE

        CLIUIC = CLIBUF+G.CICU  ; Current UIC
;
; Current directory string .....
;
CURDIR: .BLKB   40.

        .ENDC   ;FILE

; -------------------------------------------------------------------
; Command check buffers and flags ....
; The whole area is cleared so do not split.
;
CDSC:   0, 0                    ; Descriptor of whole remainder
PDSC:                           ; Descriptor of P0 .. P8
        .REPT    9.
        0, 0
        .ENDR
;
        PX.LEN  = 0             ; Bytecount
        PX.ADR  = 2             ; Address
        PX.SIZ  = 4             ; Length of an entry
;
CFETCH: .BYTE   0               ; Flag if Paramter fetched
OVMSG:  .BYTE   0               ; Send Overflow Message
CTSTAR: .BYTE   0               ; Find command with "*" enabled (ne 0)
TMPFLG: .BYTE   0               ; Temporary Flag: "*" encountered in compare
        .EVEN
CLL = .-CDSC                    ; Region to be cleared from CDSC
; -------------------------------------------------------------------

        .SBTTL  MCE - DSPTAB -- Jumptable

        .PSECT  PDATA
;
; JUMP TABLE
;
; This is the dispatch table for control characters.
; The table contains the addresses of the action routines for the
; different codes.
; When bit 0 of an address is set, the corresponding ctrl-key
; may not be superimposed by a definition.
;
DSPTAB:
        INSERT+1        ; SINGLE CHR.
        CHOVER          ; CTRL/A
        UP              ; CTRL/B
        CLRLIN          ; CTRL/C
        LEFT            ; CTRL/D
        ENDLIN          ; CTRL/E
        RIGHT           ; CTRL/F
        loop            ; CTRL/G
        BEGLIN          ; BS (CTRL/H)
        MOVWRD          ; HT (CTRL/I)
        DELEW           ; LF (CTRL/J)
        DELRL           ; CTRL/K
        loop            ; CTRL/L
        EXEC+1          ; CR (CTRL/M)
        SAVE            ; CTRL/N
        ESCAP+1         ; CTRL/O = SS3 8-bit ctrl. char. in 7-bit mode
                        ;  See note in release notes
                        ;
        loop            ; CTRL/P
        loop+1          ; CTRL/Q (XON)
        RETYPE          ; CTRL/R
        loop+1          ; CTRL/S (XOFF)
        DELAY           ; CTRL/T
        DELEL           ; CTRL/U
        DELRC           ; CTRL/V
        DELRW           ; CTRL/W
        EXELEA          ; CTRL/X
        EXIT            ; CTRL/Y
        loop            ; CTRL/Z
        ESCAP+1         ; ESC           (CTRL/[)
        loop            ; CTRL/\        (CTRL/|)
        loop            ; CTRL/]        (CTRL/})
        loop            ; CTRL/^        (CTRL/~)
        HELP            ; CTRL/?

        .IF DF  EDT

        .SBTTL  MCE - EDTTAB -- EDT-Key Jumptable
;
EDTTAB:
;
;       normal  gold     esc. sequ      key  EDT        GOLD EDT

        DELRC,  DELRC   ; ESC O l       ,   DELCHR      / UNDLCHR
        DELRW,  DELRW   ; ESC O m       -   DELWRD      / UNDLWRD
        SELECT, RESET   ; ESC O n       .   SELECT      / RESET
        loop,   loop    ; ESC O o
        BEGLIN, CLRLIN  ; ESC O p       0   BLINE       / OPENLINE
        MOVWRD, MOVWRD  ; ESC O q       1   WORD        / CHNGCAS
        ENDLIN, DELRL   ; ESC O r       2   EOL         / DELEOL
        loop,   loop    ; ESC O s       3   CHAR        / SPECIN
        loop,   loop    ; ESC O t       4   ADVANCE     / BOTTOM
        loop,   loop    ; ESC O u       5   BACKUP      / TOP
        CUT,    PASTE   ; ESC O v       6   CUT         / PASTE
        TRANSL, TRANSL  ; ESC O w       7   PAGE        / COMMAND
        PRINTC, SHVERS  ; ESC O x       8   SECTION     / FILL
        PRINTF, SHFREE  ; ESC O y       9   APPEND      / REPLACE
        GOLD,   GOLD    ; ESC O P      PF1  GOLD        / GOLD
        EDTHLP, EDTHLP  ; ESC O Q      PF2  HELP        / HELP
        RECALL, RECALL  ; ESC O R      PF3  FINDNXT     / FIND
        DELRL,  DELRL   ; ESC O S      PF4  DELLIN      / UNDLIN

        .ENDC   ;EDT

        .IF DF TDV2XX

        .SBTTL  MCE - TDVTAB -- TDV2230 Key table
;
TDVTAB:
;       Action routine    Key
;
        loop            ; F1
        loop            ; F2
        loop            ; F3
        loop            ; F4
        loop            ; F5
        loop            ; F6
        loop            ; F7

        .ENDC   ;TDV2XX

        .IF     DF      VT2XX

        .SBTTL  MCE - VT2TAB -- VT2XX Key table
;
; Entry:
;
;               Word 1 :   2 Ascii char. from esc-seq.
;               Word 2 :   Action routine address
;               Word 3 :   2 Ascii char. from key
;
        .MACRO  KEYVT2,ESC,ACT,KEY
        .ASCII  /ESC/
        .IF NB ACT
        ACT
        .IFF
        LOOP
        .ENDC
        .ASCII  /KEY/
        .ENDM
;
VT2TAB:
        KEYVT2  <1 >    ,RECALL ,<$F>   ; Find
        KEYVT2  <2 >    ,PASTE  ,<$I>   ; Insert here
        KEYVT2  <3 >    ,CUT    ,<$R>   ; Remove
        KEYVT2  <4 >    ,SELECT ,<$S>   ; Select
        KEYVT2  <5 >    ,PRVHLP ,<$P>   ; Prev. Screen
        KEYVT2  <6 >    ,NXTHLP ,<$N>   ; Next Screen
;
        KEYVT2  <17>    ,       ,<6 >   ; F6
        KEYVT2  <18>    ,       ,<7 >   ; F7
        KEYVT2  <19>    ,       ,<8 >   ; F8
        KEYVT2  <20>    ,       ,<9 >   ; F9
        KEYVT2  <21>    ,       ,<10>   ; F10
        KEYVT2  <23>    ,VT2ESC ,<11>   ; F11   ESC
        KEYVT2  <24>    ,BEGLIN ,<12>   ; F12   BS
        KEYVT2  <25>    ,DELEW  ,<13>   ; F13   LF
        KEYVT2  <26>    ,       ,<14>   ; F14
        KEYVT2  <28>    ,HELP   ,<15>   ; F15   HELP
        KEYVT2  <29>    ,EXECNW ,<16>   ; F16   DO
        KEYVT2  <31>    ,       ,<17>   ; F17
        KEYVT2  <32>    ,       ,<18>   ; F18
        KEYVT2  <33>    ,       ,<19>   ; F19
        KEYVT2  <34>    ,       ,<20>   ; F20
;
VT2LEN  =.-VT2TAB

        .ENDC   ;VT2XX

        .SBTTL
        .SBTTL  MCE ----------- *** Start of Code ***
        .SBTTL  MCE - START  -- INIT-Code
;
; Register usage
;
; R0    Scratch Pointer
; R1    Cursor in CMDBUF
; R2    First free byte in CMDBUF (End of Text)
; R3    Scratch
; R4    Scratch
; R5    Scratch Counter
;
        .PSECT CODE
;
START:
;
; TKB puts in R3 and R4 the Task identcode in RAD50 format from the
; .IDENT directive  or from the IDENT option in the TKB-CMD file.
; We use this to put in MCE's prompts ( See Multi-Tasker july 85 )
;
        MOV     #IDENT,R0       ; R0 => Version field address
        MOV     R3,R1           ; 1st 3 RAD50 char.
        CALL    $C5TA           ; Convert
        MOV     R4,R1           ; 2nd 3 RAD50 char.
        CALL    $C5TA           ; Convert

        .IF DF  STATUS

        MOV     #IDENT,R0       ; R0 => Version field address
        MOV     #IDENT2,R1      ; R1 => Version field address statusline
        MOV     #6,R2           ; R2 =  Counter
10$:
        MOVB    (R0)+,(R1)+     ; Copy
        SOB     R2,10$          ;   ident.

        .ENDC   ;STATUS

        SREX$S  #EXAST          ; Specify exit ast
        MOV     #FREE,R0        ; R0 => Free memory listhead
        CALL    $INIDM          ; Initialize Free Memory
        CALL    TERM            ; Get terminal info
        CALL    CLRBUF          ; Initialize CMDBUF buffer

        .IF NDF SILENT

        MOV     #STRTXT,R0      ; Print
        CALL    IOMSG           ;   Startup message

        .ENDC   ;SILENT

        .IF DF  TMOTIM!RTMESS!RTEXIT

        MOV     #GLUNB,R0       ; Buffer
        GLUN$S  #TI,R0          ; Get terminal information

        .IF DF  RTMESS!RTEXIT

        CMP     (R0),#"RT       ; Remote terminal ?
        BNE     20$             ;  No : => 20$
        MOV     #RTTXT,ADR      ; Print
        MOV     #RTTXTL,LEN     ; Print
        CALL    IOW             ;   RT message

        .IF DF  RTEXIT

        JMP     EXIT            ;

        .ENDC   ;RTEXIT

20$:

        .ENDC   ;RTMESS!RTEXIT

        .IF DF  TMOTIM

        CMP     (R0),#"TT       ; Normal terminal ?
        BNE     30$             ;  No : => 30$
        TSTB    2(R0)           ; TT0 ?
        BNE     30$             ;  No : => 30$
        INCB    TT0FLG          ; Set TT0: flag
30$:
        CALL    MARK            ; Marktime for timeout

        .ENDC   ;TMOTIM

        .ENDC   ;TMOTIM!RTMESS!RTEXIT

        .IF DF  FILE

        CALL    FILOP           ; Open MCEINI file

        .ENDC   ;FILE

        .SBTTL  MCE - RESTAR -- Get next Line,  Main-Loop
;
RESTAR:
        CLRB    NEXFLG          ; +
        CLRB    LEAFLG          ;  Clear flags
        CLRB    OLDFLG          ; -

        .IF DF  EDT

        CLR     SELSTR          ; Clear start of select
        CLRB    SELFLG          ; Clear ANSI-select flag
        CLRB    GOLDFL          ; Clear "GOLD"

        .ENDC   ;EDT

        CALL    TERM            ; Get terminal info

        .IF DF  FILE

        TSTB    FILINP          ; File Input ?
        BEQ     10$             ;  No  : => 10$
        CALL    FILREA          ; Goto EXEC1 if something read
10$:                            ;  then come back to RESTAR

        .ENDC   ;FILE

        MOV     #IO.ATT,CODE    ; Attach
        CALL    IO              ;    the terminal

        .IF DF  EDT

        TSTB    EDTFLG          ; EDT Keys enabled ?
        BEQ     20$             ;  No : => 20$
        MOV     #APLTXT,ADR     ; Aplication keypad
        MOV     #2,LEN          ; Length
        CALL    IOW             ; Write
20$:

        .ENDC   ;EDT

;
; Set our task default directory string to that of the terminal. We
; need to do that since the last command could have been a SET /DEF
; RSX11M does nothing with this directive so it doesn't have to be
; conditionalized
;
        SDIR$S  #SD.TI          ; Set task DDS to terminal DDS

        .IF DF  STATUS

        CALL    PRISTA          ; Print status line

        .ENDC   ;STATUS

        .SBTTL  MCE - PRIPRM -- Print the prompt
;
PRIPRM:
        MOV     #IO.CCO,CODE    ; Cancel <CTRL/O>
        MOV     PROMLF,ADR      ; Start of prompt buffer
        MOV     #CMDBUF+2,R3    ; Point behind prompt buffer ( Room for ESC[ )
        MOVB    #'[,-(R3)       ; Insert '[' ( Hold screen mode )
        MOVB    #ESC,-(R3)      ; Insert ESC ( Hold screen mode )

        .IF DF  CLISUP!FILE

        CALL    GETCLI          ; Get CLI information

        .ENDC   ;CLISUP!FILE

        .IF DF  CLISUP

        BCC     10$             ;  Success : => 10$
        MOV     #^RMCR,TASK     ; MCR... only
        BR      40$             ; Continue with default prompt
;
10$:
;
; Copy CLI prompt
;
        MOV     #CLIPRM,R0      ; R0 => CLI Prompt information
        MOVB    (R0)+,R4        ; Get length, advance to prompt string
        ADD     R4,R0           ; Point behind CLI prompt
        CLR     -(SP)           ; Reserve space
20$:
        MOVB    -(R0),(SP)      ; Save character
        CMPB    (SP),#CR        ; <CR> ?
        BEQ     30$             ;  Yes : => 30$
        CMPB    (SP),#LF        ; <LF> ?
        BEQ     30$             ;  Yes : => 30$
        MOVB    (SP),-(R3)      ; Copy character
30$:
        SOB     R4,20$          ; Next character
        TST     (SP)+           ; Flush space
        BR      50$             ; => 50$
40$:

        .ENDC   ;CLISUP

        MOVB    #'>,-(R3)       ; Default prompt
50$:
        BICB    INSFLG,MODFLG   ; Clear overstrike mode if Auto Insert
        BISB    OVSFLG,MODFLG   ; Set   overstrike mode if Auto Overstrike

        .IF DF  EXTNPR

        TSTB    PRMFLG          ; Extended prompt ?
        BEQ     70$             ;  No : => 70$

        .IF DF  EDT

        TSTB    EDTFLG          ; EDT mode active ?
        BEQ     60$             ;  No : => 60$

        .IF DF  STATUS

        TSTB    STAFLG          ; Status line ?
        BNE     60$             ;  Yes : => 60$

        .ENDC   ;STATUS

        MOVB    #':,-(R3)       ; Display EDT mode active
60$:

        .ENDC   ;EDT

        MOVB    #'+,-(R3)       ; Assume insert mode
        BITB    #1,MODFLG       ; Overstrike ?
        BEQ     70$             ;  No : => 70$
        MOVB    #'-,(R3)        ; Overstrike
70$:

        .ENDC   ;EXTNPR

        MOVB    #CR,-(R3)       ; Insert <CR>
        MOVB    #LF,-(R3)       ; Insert <LF>
        MOVB    #'/,-1(R3)      ; Insert '/' ( hold screen mode )
        MOVB    #ESC,-2(R3)     ; Insert <ESC> ( hold screen mode )
        MOV     #CMDBUF,LEN     ; Point behind prompt buffer
        SUB     R3,LEN          ; Length
        MOV     R3,PROMPT       ; +
        MOV     R3,PROMLF       ;  Adjust
        INC     PROMPT          ;     Pointers
        MOV     PROMLF,ADR      ; -
80$:
        TSTB    HLD+1           ; Hold screen mode ?
        BEQ     90$             ;  No : => 90$
        ADD     #4,LEN          ; Adjust length for Hold screen escseq.
        SUB     #2,ADR          ; Adjust address
90$:
        CALL    IO              ; Output prompt
;
; Clear edit buffer and setup R1 and R2 as pointers
;
        CALL    CLRBUF          ; Clear edit buffer

        .SBTTL  MCE - LOOP   -- Accept next Char. for input and dispatch it
;
LOOP:
        MOV     #IO.RST!TF.RNE,CODE
                                ; Accept one chr.
        MOV     #CHAR,ADR       ; 1 Character buffer
        MOV     #1,LEN          ; Length
        CALL    IO              ; Read 1 char
LOOP00:

        .IF DF  TMOTIM

        CMPB    IOSTAT,#IE.ABO  ; IO killed ? (time-out)
        BNE     30$             ;  No : => 30$
        MOV     #BYETXT,R0      ; Assume "BYE"
        TSTB    TT0FLG          ; Are we on TT0: ?
        BNE     10$             ;  Yes : => 10$
        MOV     #^RMCR,TASK     ; MCR...
        BR      20$             ; => 20$
10$:
        MOV     #EXITXT,R0      ; "MCE EXIT"
20$:
        CALL    GETBUF          ; Copy in CMDBUF
        CALL    DISPLY          ; Display
        JMP     EXEC            ; Execute "BYE" or "MCE EXIT" command
30$:

        .ENDC   ;TMOTIM

        MOVB    IOSTAT+1,R4     ; Test for branch table
        BIC     #177600,R4      ; Make 7-Bit ASCII
                                ; ( See note in release notes )
40$:
        CMPB    R4,#DEL         ; Delete ?
        BNE     50$             ;  No : => 50$
        JMP     DELEC           ; => Delete char.
50$:
        BIC     #177740,R4      ; IO.RST:  all ctrl-char in iostat
        MOV     R4,R3           ; Copy in R3
        ASL     R3              ; Word offset
        BIT     #1,DSPTAB(R3)   ; May be translated ?
        BEQ     60$             ;  Yes : => 60$
        MOV     DSPTAB(R3),R3   ; Take address
        BIC     #1,R3           ; Clear bit 0
        JMP     (R3)            ; Do action routine
60$:
;
; Check if to be translated
;
        MOVB    #'^,SAVBUF      ; Insert
        MOVB    R4,SAVBUF+1     ;   key
        BISB    #100,SAVBUF+1   ; Make ASCII
        CMPB    SAVBUF+1,#'_    ; "_" ?
        BNE     70$             ;  No : => 70$
        MOVB    #'?,SAVBUF+1    ; Make "?"
70$:
        ASL     R4              ; Word offset
        ADD     #DSPTAB,R4      ; Add table address
        MOV     #2,PDSC+PX.LEN  ; P0 Length = 2
PROCESS:
        MOV     #SAVBUF,PDSC+PX.ADR
                                ; P0 Address
        MOV     R2,-(SP)        ; Save R2
        CALL    FNDCMD          ; Find cmd
        MOV     (SP)+,R2        ; Restore R2
        BCS     10$             ;  No entry found : => 10$
        JMP     FUNC            ; Proccess it
10$:
        JMP     @(R4)           ; <== Dispatch

        .SBTTL
        .SBTTL    MCE ----------- *** Key actions ***
        .SBTTL    MCE - BEGLIN -- Begin of line
;
BEGLIN:

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     10$             ;  No :=> 10$
        MOV     #CMDBUF,R1      ; Cursor at pos 1
        CALL    DISPLY          ; Rewrite line
        JMP     LOOP            ; => LOOP

        .ENDC   ;EDT

10$:
        CALL    SPBACK          ; Back space one position
        BCC     10$             ; If CC not yet at the begin
        JMP     LOOP            ; => LOOP
;
;
        .SBTTL    MCE - CHOVER -- Flip between insert and overstrike mode
;
CHOVER:
        INCB    MODFLG          ; Change mode

        .IF DF  EXTNPR

        TSTB    PRMFLG          ; Extended prompt ?
        BEQ     20$             ;  No : => 20$
        MOV     PROMPT,R4       ; R4 => Prompt
        TSTB    (R4)+           ; R4 => Mode character
        MOVB    #'+,(R4)        ; Insert "+"
        BITB    #1,MODFLG       ; Overstrike ?
        BEQ     10$             ;  No : => 10$
        MOVB    #'-,(R4)        ; Insert "-"
10$:
        CALL    DISPLY          ; Rewrite line
20$:

        .ENDC   ;EXTNPR

        BR      LOOP1           ; => LOOP
;
;
        .SBTTL    MCE - DELEC  -- Delete left single char
;
DELEC:
        CALL    SPBACK          ; Back space one position
        BCS     LOOP1           ;  Error : => LOOP
        BR      DELCHR          ; => DELCHR
;
;
        .SBTTL    MCE - DELEL  -- Delete from start of line to cursor
;
DELEL:
        CMP     R1,#CMDBUF      ; At begin of buffer ?
        BLOS    60$             ;  Yes : => 60$
        MOV     #CMDBUF,R0      ; R0 => CMDBUF

        .IF DF  EDT

        TST     SELSTR          ; Selective range active ?
        BEQ     10$             ;  No : => 10$
        CMP     R1,SELSTR       ; Compare cursor with start of range
        BLO     10$             ;  Left of start : => 10$
        MOV     R1,SELSTR       ; Backup range

        .ENDC   ;EDT

10$:
        CMP     R1,R2           ; EOL ?
        BEQ     20$             ;  Yes : => 20$
        MOVB    (R1)+,(R0)+     ; Shift string left

        .IF DF  EDT

        TST     SELSTR          ; Selective range active ?
        BEQ     10$             ;  No : => 10$
        DEC     SELSTR          ; Backup range

        .ENDC   ;EDT

        BR      10$             ; => 10$
20$:
        MOV     R0,R2           ; End of text
30$:
        CMP     R0,#CMDEND      ; End of buffer ?
        BHIS    40$             ;  Yes : => 40$
        MOVB    #BLNK,(R0)+     ; Fill with blank
        BR      30$             ; => 30$
40$:
        CLRB    OLDFLG          ; No old command
        TSTB    ANI+1           ; Ansi Screen ?
        BNE     50$             ;  Yes : => 50$

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BNE     50$             ;  Yes : => 50$

        .ENDC   ;EDT

        MOV     PROMPT,ADR      ; +
        MOV     R1,LEN          ;  Rewrite line
        SUB     PROMPT,LEN      ;
        CALL    IOW             ; -
        MOV     #CMDBUF,LEN     ; +
        SUB     PROMPT,LEN      ;  Reposition cursor
        CALL    IO              ;
        MOV     #CMDBUF,R1      ; -
        BR      60$             ; => 60$
50$:
        MOV     #CMDBUF,R1      ; Reposition cursor
        CALL    DISPLY          ; Rewrite line
60$:
        BR      LOOP1           ; => LOOP
;
;
        .SBTTL    MCE - DELEW  -- Delete left single word
;
DELEW:
        CMP     R1,#CMDBUF      ; At begin of buffer ?
        BLOS    LOOP1           ;  Yes : => LOOP
        MOV     R1,-(SP)        ; Save cursor position
10$:
        DEC     R1              ; Cursor left
        CMP     R1,#CMDBUF      ; At begin of buffer ?
        BLOS    30$             ;  Yes : => 30$
        MOVB    -1(R1),R0       ; Get previous char
        CMPB    R0,#BLNK        ; Space ?
        BNE     20$             ;  No  : => 20$
        CMPB    R0,(R1)         ; Was previous one a space ?
        BEQ     10$             ;  Yes : => 10$, delete it
20$:
        CALL    SRWORD          ; Search word
        BCC     10$             ;
30$:
        MOV     (SP)+,R0        ; R0 = Initial cursor position
        MOV     R1,-(SP)        ; Save new cursor position
        BR      DELWRD          ; => Delwrd
;
;
        .SBTTL    MCE - DELRC  -- Delete right single char
;
DELRC:
        CMP     R1,R2           ; At EOL ?
        BHIS    LOOP1           ;  Yes : => LOOP
DELCHR:

        .IF DF  EDT

        TST     SELSTR          ; Selective range active ?
        BEQ     10$             ;  No : => 10$
        CMP     R1,SELSTR       ; Compare cursor with start of range
        BHI     10$             ;  Right of start
        DEC     SELSTR          ; Backup range
10$:

        .ENDC   ;EDT

        MOV     R1,R0           ; R0 => Cursor
20$:
        MOVB    1(R0),(R0)+     ; Shift string left
        CMP     R0,R2           ; At EOL ?
        BLOS    20$             ;  No : => 20$

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     30$             ;  No : => 30$
        DEC     R2              ; End of text
        CALL    DISPLY          ; Rewrite line
        BR      40$             ;
30$:

        .ENDC   ;EDT

        CALL    UPDATE          ; Rewrite line
        DEC     R2              ; End of text
40$:
        CLRB    OLDFLG          ; No old command
;
LOOP1:  JMP     LOOP            ; => LOOP
;
        .SBTTL    MCE - DELRL  -- Delete from cursor to eol
;
DELRL:
        MOV     R1,R0           ; R0 => Cursor
10$:
        CMP     R0,R2           ; EOL ?
        BHIS    20$             ;  Yes : => 20$
        CLRB    OLDFLG          ; No old command
        MOVB    #BLNK,(R0)+     ; Space
        BR      10$             ;
20$:

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     30$             ;  No : => 30$
        MOV     R1,R2           ; Cursor at EOL
        CALL    DISPLY          ; Rewrite line
        BR      40$             ;
30$:

        .ENDC   ;EDT

        CALL    UPDATE          ; Rewrite line
        MOV     R1,R2           ; Cursor at EOL
40$:
        BR      LOOP1           ; => LOOP
;
;
        .SBTTL    MCE - DELRW  -- Delete right single word
;
DELRW:
        CMP     R1,R2           ; At EOL ?
        BHIS    LOOP1           ;  Yes : => LOOP
        MOV     R1,-(SP)        ; Save cursor position
10$:
        MOVB    (R1)+,R0        ; Get char
        CMPB    R0,#BLNK        ; Space ?
        BNE     20$             ;  No  : => 20$
        CMPB    R0,(R1)         ; Is next one a space ?
        BEQ     30$             ;  Yes : => 30$, delete it
20$:
        CALL    SRWORD          ; Search word
        BCS     40$             ;
30$:
        CMP     R1,R2           ; At EOL ?
        BLO     10$             ;  No : => 10$
40$:
        MOV     R1,R0           ; R0 = Current cursor position
        MOV     (SP),R1         ; R1 = Initial cursor position

;
DELWRD:

        .IF DF  EDT

        TST     SELSTR          ; Selective range active ?
        BEQ     20$             ;  No : => 20$
        CMP     R0,SELSTR       ; Compare cursor with start of range
        BHI     10$             ;  Right of start : => 10$
        SUB     R0,SELSTR       ; Backup
        ADD     R1,SELSTR       ;     range
        BR      20$             ; => 20$
10$:
        CMP     R1,SELSTR       ; New cursor left of start range ?
        BHIS    20$             ;  No : => 20$
        MOV     R1,SELSTR       ; Update start of range
20$:

        .ENDC   ;EDT

        CMP     R0,R2           ; EOL ?
        BHIS    30$             ;  No  : => 30$
        MOVB    (R0),(R1)+      ; Shift down
        MOVB    #BLNK,(R0)+     ; Must be replaced by space
        BR      DELWRD          ; => DELWRD
30$:
        MOV     R1,R2           ; New end ptr
        MOV     (SP)+,R1        ; Restore cursor
        CLRB    OLDFLG          ; No old command
;
;
        .SBTTL    MCE - RETYPE -- Retype line
;
RETYPE:
        CALL    DISPLY          ; Write buffer
        BR      LOOP1           ; => LOOP
;
;
        .SBTTL    MCE - ENDLIN -- Jump to end of text
;
ENDLIN:

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     10$             ;  No : => 10$
        MOV     R2,R1           ; End of text
        CALL    DISPLY          ; Rewrite line
        BR      20$             ;
10$:

        .ENDC   ;EDT

        MOV     R1,ADR          ; +
        MOV     R2,LEN          ;  Write from cursor to end
        SUB     R1,LEN          ;
        BEQ     20$             ;
        CALL    IOW             ; -
        MOV     R2,R1           ; End of text
20$:
        BR      LOOP1           ; => LOOP
;
;
        .SBTTL    MCE - INSERT -- Insert one character
;
INSERT:
        CMP     R2,#CMDEND      ; Still Room ?
        BHIS    LOOP1           ;  No : => LOOP
        MOV     #CHAR,ADR       ; +
        MOV     #1,LEN          ;  Echo character
        CALL    IOW             ; -
        CLRB    OLDFLG          ; No old command
        BITB    #1,MODFLG       ; Overstrike ?
        BEQ     10$             ;  No : => 10$
        MOVB    CHAR,(R1)+      ; Overstrike
        CMP     R1,R2           ; At end ?
        BLOS    LOOP1           ;  No : => LOOP
        MOV     R1,R2           ; Increment end ptr
        BR      LOOP1           ; => LOOP
10$:
        INC     R2              ; No overstrike - shift
        MOV     R2,R0           ; R0 => EOL
20$:
        MOVB    -(R0),1(R0)     ; Shift string right
        CMP     R0,R1           ; At cursor ?
        BHI     20$             ;  No : => 20$
        MOVB    CHAR,(R1)+      ; Insert new character

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     30$             ;  No : => 30$
        CALL    DISPLY          ; Rewrite line
        BR      40$             ;
30$:

        .ENDC   ;EDT

        CALL    UPDATE          ; Rewrite line
40$:
        BR      LOOP1           ; => LOOP
;
;
        .SBTTL    MCE - MOVWRD -- Move word
;
MOVWRD:
        CMP     R1,R2           ; At EOL ?
        BLO     10$             ;  No => 10$
        MOV     #CMDBUF,R1      ; Set at begin
        BR      40$             ; => 40$
10$:
        MOVB    (R1)+,R0        ; Get char
        CMPB    R0,#BLNK        ; Space ?
        BNE     20$             ;  No  : => 20$
        CMPB    R0,(R1)         ; Is next one a space ?
        BEQ     30$             ;  Yes : => 30$
20$:
        CALL    SRWORD          ; Search word
        BCS     40$             ;
30$:
        CMP     R1,R2           ; At EOL ?
        BLO     10$             ;  No : => 10$
40$:
        CALL    DISPLY          ;
        JMP     LOOP            ; => LOOP

        .SBTTL
        .SBTTL  MCE ----------- *** Escape Sequences ***
        .SBTTL  MCE - ESCAP  -- Filter out Escape Sequences
;
ESCAP:
        .ENABL  LSB
;
        CALL    IO              ; Read next char
        MOVB    CHAR,R0         ; R0 = Character
        CMPB    R0,#'[          ; <ESC>[  ?
        BEQ     ESCAP           ;  Yes : => ESCAP
        CMPB    R0,#'O          ; <ESC>O  ?
        BEQ     ESCAP           ;  Yes : => ESCAP
        CMPB    R0,#'?          ; <ESC>?  ?
        BEQ     ESCAP           ;  Yes : => ESCAP
        CMPB    IOSTAT+1,#ESC   ; <ESC><ESC> ?
        BNE     10$             ;  No  : => 10$
        JMP     EXECNW          ; Execute no-wait
10$:
        CMPB    R0,#'A          ; <UP-ARROW> ?
        BNE     60$             ;  No  : => 60$
;
; UP-ARROW .....
;
        .SBTTL    MCE - UP     -- Older command
UP:
        MOV     FIFPTR,R5       ; Get Ptr of buffer
        BNE     20$             ;  Defined : => 20$
        TST     FIFO+F.1ST      ; Any entry ?
        BEQ     80$             ;  No  : => 80$
        MOV     FIFO+F.LAST,FIFPTR
                                ; Take
        MOVB    FIFCNT,FIFPOI   ;     newest entry
        BR      80$             ; => 80$
20$:
        MOV     #FIFO+F.1ST,R5  ; Find previous entry
30$:
        MOV     FI.NXT(R5),R5   ; Next
        BNE     40$             ;  Got one : => 40$
        TSTB    RNGFLG          ; Ringbuffer ?
        BEQ     80$             ;  No : => 80$
        CLRB    FIFPOI          ; None
        BR      50$             ; => 50$
40$:
        CMP     FI.NXT(R5),FIFPTR
                                ; Does this point to me ?
        BNE     30$             ;  No  : => 30$
        DECB    FIFPOI          ; One older
50$:
        MOV     R5,FIFPTR       ; Found - load
        BR      80$             ;            and display
;
60$:
        CMPB    R0,#'B          ; <DOWN-ARROW> ?
        BNE     110$            ;  No : => 110$
;
; DOWN-ARROW .....
;
        .SBTTL    MCE - DOWN   -- Newer command
;
DOWN:
        MOV     FIFPTR,R5       ; Get Ptr of buffer
        BNE     70$             ;  Defined : => 70$
        TST     FIFO+F.1ST      ; Any entry at all ?
        BEQ     80$             ;  No  : => 80$
        TSTB    RNGFLG          ; Ringbuffer ?
        BEQ     90$             ;  No : => 90$
        MOV     FIFO+F.1ST,FIFPTR
                                ; Take oldest
        MOVB    #1,FIFPOI       ; Oldest
        BR      80$             ; => 80$
70$:
        TST     FI.NXT(R5)      ; Goto next buffer if any
        BEQ     CLRLIN          ;  No more : => CLRLIN
        MOV     FI.NXT(R5),FIFPTR
                                ; Next
        INCB    FIFPOI          ; One newer
80$:

        .IF DF  EDT

        CLR     SELSTR          ; Clear start of select
        CLRB    SELFLG          ; Clear ANSI-select flag

        .ENDC   ;EDT

        CALL    GETFIF          ; Load CMDBUF from FIFO
        BR      100$            ; => 100$
;
; CLEAR LINE .....
;
        .SBTTL    MCE - CLRLIN -- Clear line
CLRLIN:
        CLRB    OLDFLG          ; Clear flag
        CALL    CLEAR           ; Clear FIFO pointers
90$:

        .IF DF  EDT

        CLR     SELSTR          ; Clear start of select
        CLRB    SELFLG          ; Clear ANSI-select flag

        .ENDC   ;EDT

        CALL    CLRBUF          ; Clear edit buffer
        CALL    DISPLY          ;   and display prompt
100$:

        .IF DF  STATUS

        CALL    PRIST1          ; Print status line

        .ENDC   ;STATUS

        BR      LOOP2           ; => LOOP
;
110$:
        CMPB    R0,#'C          ; <RIGHT-ARROW> ?
        BNE     130$            ;  No  : => 130$
;
; RIGHT-ARROW .....
;
        .SBTTL    MCE - RIGHT  -- Cursor right
;
RIGHT:
        CMP     R1,R2           ; End of text ?
        BHIS    LOOP2           ;  Yes : => LOOP
        MOV     R1,ADR          ; Rewrite
        MOV     #1,LEN          ;    Character
        CALL    IOW             ;     at Cursor position
        INC     R1              ; Shift cursor right

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     120$            ;  No : => 120$
        CALL    DISPLY          ; Rewrite line
120$:

        .ENDC   ;EDT

        BR      LOOP2           ; => LOOP
;
130$:
        CMPB    R0,#'D          ; <LEFT-ARROW> ?
        BNE     150$            ;  No : => 150$
;
; LEFT-ARROW .....
;
        .SBTTL    MCE - LEFT   -- Cursor left
;
LEFT:
        CALL    SPBACK          ; Cursor left one space

        .IF DF  EDT

        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     140$            ;  No : => 140$
        CALL    DISPLY          ; Rewrite line
140$:

        .ENDC   ;EDT

        BR      LOOP2           ; => LOOP
;
150$:

        .IF DF  EDT

;
; EDT-KEYS .....
;
        TSTB    EDTFLG          ; EDT Keys enabled ?
        BEQ     200$            ;  No : => 200$
        CMPB    R0,#'M          ; <ENTER> ?
        BNE     160$            ;  No  : => 160$
        JMP     EXEC            ; Execute
160$:
        CMPB    R0,#'P          ; +
        BLO     170$            ;  PFx range ?
        CMPB    R0,#'S          ;   No : => 170$
        BHI     170$            ; -
        ADD     #<'z-'l-'P>,R0  ; Relocate to table offset
        BR      180$            ; => 180$
170$:
        CMPB    R0,#'l          ; +
        BLO     200$            ;  Within Keypad range ?
        CMPB    R0,#'y          ;   No  : => 200$
        BHI     200$            ; -
        SUB     #'l,R0          ; Make
180$:
        ASL     R0              ;  dispatchtable
        ASL     R0              ;       offset
        TSTB    GOLDFL          ; Gold ?
        BEQ     190$            ;  No  : => 190$
        TST     (R0)+           ; Point to "GOLD" entry
        CLRB    GOLDFL          ; Clear "GOLD"
190$:
        JMP     @EDTTAB(R0)     ; Do EDT function
200$:

        .ENDC   ;EDT

;
; PF-KEYS .....
;
        SUB     #'P,R0          ; Any PFn key ?
        BLO     210$            ;  No : => VT2KEY
        CMP     R0,#'S-'P       ; > PF4 ?
        BLOS    220$            ;  Yes : => VT2KEY
210$:
        JMP     VT2KEY          ;
220$:
        MOV     R0,-(SP)        ; Save 0..3 for <PF1>..<PF4>
        MOV     #"PF,SAVBUF     ; "PF' in SAVBUF
        ADD     #'1,R0          ; Make ascii from PR-number
        MOV     R0,SAVBUF+2     ; Insert in SAVBUF
        MOV     #3,PDSC+PX.LEN  ; P0 Length
        MOV     #SAVBUF,PDSC+PX.ADR
                                ; P0 Address
        MOV     R2,-(SP)        ; Save R2
        CALL    FNDCMD          ; Find cmd
        MOV     (SP)+,R2        ; Restore R2
        MOV     (SP)+,R0        ; Restore R0
        BCC     FUNC            ;  Entry found : => FUNC
;
        MOV     R2,R1           ; Point to end of buffer
        ASL     R0              ; Word offset
        ADD     R0,PC           ; Branch
        BR      TRANSL          ; <PF1>
        BR      RECALL          ; <PF2>
        BR      PRINTC          ; <PF3>
;                               ; <PF4>
;       Fall through to PRINTF, adjacency assumed
;
        .DSABL  LSB

        .SBTTL    MCE - PRINTF -- <PF4> Print FIFO buffer
;
PRINTF:
;
; <PF4> Print FIFO .....
;
        CALL    PRIFIF          ; <PF4> Print whole FIFO
        BR      LOOP2           ; => LOOP
;
;
LOOP2:  JMP     LOOP            ; => LOOP
;
;
        .SBTTL    MCE - PRINTC -- <PF3> Print command buffer
;
PRINTC:
;
; <PF3> Print CMD Buffer
;
        CALL    PRICMD          ; Print command buffer
        BR      LOOP2           ; => LOOP
;
;
        .SBTTL    MCE - RECALL -- <PF2> Recall a command
;
RECALL:
;
; <PF2> - RECALL
;
        CALL    RECCMD          ; Recall Command

        .IF DF  STATUS

        CALL    PRIST1          ; Dispay status line

        .ENDC   ;STATUS

        BR      LOOP2           ; => LOOP
;
;
        .SBTTL    MCE - TRANSL -- <PF1> Translate a command
;
TRANSL:
;
; <PF1> Translate
;
        MOV     #CMDBUF,R0      ; R0 => CMDBUF
        CMP     R2,R0           ; Something in buffer ?
        BEQ     LOOP2           ;  No : => LOOP
        INCB    NLOFLG          ; Disable command load
        SUB     R0,R2           ; Calculate Length
        MOV     R2,LEN          ; Make length
        CALL    CMDCHK          ; Command Translation
        MOV     LEN,R2          ; Restore R2
        ADD     #CMDBUF,R2      ; Point
        MOV     R2,R1           ;   to end
        CALL    DISPLY          ; Write line
        CLRB    NLOFLG          ; Enable command load
        BR      LOOP2           ; => LOOP
;
;
        .SBTTL    MCE - FUNC   -- Exectute function key commands
;
FUNC:
        MOV     R1,R0           ; Find start of text
FUNCEX:
;
; Execute command in (R0)
;
        CALL    IOCR            ; Clear current line
        CALL    GETBUF          ; Load CMDBUF buffer
        MOV     #CMDBUF,R0      ; R0 => CMDBUF
        SUB     R0,R2           ; Calculate length
        MOV     R2,LEN          ; Save it
        CALL    DETACH          ; Detach terminal
        JMP     EXEC3           ; Execute without display

        .IF DF  VT2XX

        .IF LT  MAXHLP-'A

        .SBTTL    MCE - PRVHLP -- Previous screen
        .SBTTL    MCE - NXTHLP -- Next screen

PRVHLP:
NXTHLP:
        MOV     #NOHTXT,ADR     ; No help page
        MOV     #NOHLEN,LEN     ;
        CALL    IOW             ;   information
        JMP     RESTAR          ;

        .IFF    ;MAXHLP-'A
;
;
        .SBTTL    MCE - PRVHLP -- Previous screen
;
; Spawn "HELP MCE<page-1>"
;
PRVHLP:

        DECB    HPAGE           ; Previous screen
        CMPB    HPAGE,#'A       ; Low limit ?
        BHIS    10$             ;  No => 10$
        MOVB    #' ,HPAGE       ; Take
        CLRB    HPAG0           ;    main help
10$:
        BR      HELPGO          ; =>
;
;
        .SBTTL    MCE - NXTHLP -- Next screen
;
; Spawn "HELP MCE<page+1>"
;
NXTHLP:
;
        TSTB    HPAG0           ; Was main help last ?
        BNE     10$             ;  No : => 10$
        MOVB    #' ,HPAG0       ; Sub topics
        MOVB    #'A-1,HPAGE     ; Init for first subtopic
10$:
        INCB    HPAGE           ; Next screen
        CMPB    HPAGE,#MAXHLP   ; High limit ?
        BLOS    20$             ;  No => 20$
        MOVB    #MAXHLP,HPAGE   ; Take last help
20$:
        BR      HELPGO          ; =>

        .ENDC   ;MAXHLP-'A

        .ENDC   ;VT2XX
;
;
        .SBTTL    MCE - HELP   -- Help key
;
; <HELP> or <CTRL/?>  Spawn "HELP MCE "
;
HELP:
        MOVB    #' ,HPAGE       ; Take
        CLRB    HPAG0           ;    main help
HELPGO:
        CALL    CLRSCR          ; Clear screen
        MOV     #HLPTXT,R0      ; Move HELP MCE into Buffer
        BR      FUNCEX          ; => FUNCEX

        .IF DF  EDT

        .SBTTL    MCE - GOLD   -- "GOLD" Key
;
GOLD:
        INCB    GOLDFL          ; Set "GOLD" flag
        BR      LOOP2           ; => LOOP
;
;
        .SBTTL    MCE - SHVERS -- Version
;
SHVERS:
        MOV     #RESTAR,-(SP)   ; RESTAR as return address
        CALLR   ICVERS          ; Display Version
;
;
        .SBTTL    MCE - SHFREE -- Free pool
;
SHFREE:
        MOV     #RESTAR,-(SP)   ; RESTAR as return address
        CALLR   ICFREE          ; Display Free pool
;
;
        .SBTTL    MCE - EDTHLP -- Keypad Help
;
EDTHLP:
        TSTB    ANI+1           ; Ansi Screen ?
        BEQ     10$             ;  No : => 10$
        MOV     #SCRCLR,ADR     ; Clear
        MOV     #SCRCLL,LEN     ;    screen
        CALL    IOW             ;
10$:
        MOV     #EDTTXT,R0      ; EDT helptext
        BR      FUNCEX          ; => FUNCEX
;
;
        .SBTTL    MCE - SELECT -- Select key
;
SELECT:
        MOV     R1,SELSTR       ; Save of select address
        MOVB    ANI+1,SELFLG    ; Set Ansi-select flag
        BEQ     10$             ;  No Ansi : => 10$
        CALL    DISPLY          ;
10$:
        BR      LOOP3           ; => LOOP
;
;
        .SBTTL    MCE - RESET  -- Reset key
;
RESET:
        CLR     SELSTR          ; Clear start of select
        CLRB    SELFLG          ; Clear Ansi-select flag
        TSTB    ANI+1           ; Test Ansi-flag
        BEQ     10$             ;  No Ansi : => 10$
        CALL    DISPLY          ;
10$:
        BR      LOOP3           ; => LOOP
;
;
        .SBTTL    MCE - CUT    -- Put selective range in Paste buffer
;
CUT:
        TST     SELSTR          ; Range active ?
        BEQ     40$             ;  No : => 40$
        CMP     R1,SELSTR       ; Compare cursor with start of range
        BEQ     40$             ; - Equal => 40$
        BHI     10$             ; - Right => 10$
        MOV     R1,R4           ; R4 = Start
        MOV     SELSTR,R0       ; R0 = End
        BR      20$             ; => 20$
10$:
        MOV     SELSTR,R4       ; R4 = Start
        MOV     R1,R0           ; R0 = End
20$:
        MOV     R4,R1           ; R1 => Start
        MOV     #PSTBUF,R3      ; R3 => Save buffer
        CLRB    PSTLEN          ; Clear length
        MOV     R4,-(SP)        ; Save new cursor pos.
30$:
        MOVB    (R4)+,(R3)+     ; Copy character
        INCB    PSTLEN          ; Update length
        CMP     R4,R0           ; At the end ?
        BLO     30$             ;  No : => 30$
        CLR     SELSTR          ; Range not active
        CLRB    SELFLG          ; Clear Ansi-select flag
        JMP     DELWRD          ; Delete range
40$:
        BR      LOOP3           ; => LOOP
;
;
        .SBTTL    MCE - PASTE  -- Put Paste buffer in at cursor position
;
PASTE:
        CLR     R4              ; R4 = Counter
        BISB    PSTLEN,R4       ; R4 := length of PASTE string
        BEQ     60$             ;  Zero : => 60$
        MOV     #PSTBUF,R5      ; R5 => PSTBUF
        CLRB    OLDFLG          ; No old command
;
10$:
        CMP     R2,#CMDEND      ; Still Room ?
        BHIS    60$             ;  No : => 60$
        MOV     R5,ADR          ; +
        MOV     #1,LEN          ;  Echo character
        CALL    IOW             ; -
        BITB    #1,MODFLG       ; Overstrike ?
        BEQ     20$             ;  No : => 10$
;
        MOVB    (R5)+,(R1)+     ; Overstrike
        CMP     R1,R2           ; At end ?
        BLOS    40$             ;  No : => Loop
        MOV     R1,R2           ; Increment end ptr
        BR      40$             ; => Loop
20$:
        INC     R2              ; No overstrike - shift
        MOV     R2,R0           ; R0 => EOL
30$:
        MOVB    -(R0),1(R0)     ; Shift string right
        CMP     R0,R1           ; At cursor ?
        BHI     30$             ;  No : => 30$
        MOVB    (R5)+,(R1)+     ; Insert new character
40$:
        SOB     R4,10$          ;
;
        TSTB    SELFLG          ; ANSI-Select active ?
        BEQ     50$             ;  No : => 50$
        CALL    DISPLY          ; Rewrite line
        BR      60$             ;
50$:
        CALL    UPDATE          ; Rewrite line
60$:
;
LOOP3:  JMP     LOOP            ; => LOOP

        .ENDC   ;EDT

        .SBTTL  MCE - VT2KEY -- VT2xx Functionkeys
;
VT2KEY:

        .IF DF VT2XX

        CMPB    TTP+1,#T.V2XX   ; VT2xx ?
        BEQ     10$             ;  Yes : => 10$
        JMP     TDVKEY          ; => TDVKEY
10$:
;
; Check if function key  :
;
;               <ESC>[n~        n   1..6
;                 or
;               <ESC>[nn~       nn  17..34
;

        MOVB    CHAR,R0         ; R0 = character
        BIC     #177600,R0      ;
        CMPB    R0,#'1          ; +
        BLO     50$             ;  1..6 ?
        CMPB    R0,#'6          ;
        BHI     50$             ; -
        SWAB    R0              ; Char in highbyte
        BISB    #BLNK,R0        ; Lowbyte = space
        MOV     R0,-(SP)        ; Save it
        CALL    IO              ; Next char.
        MOVB    CHAR,R0         ; Take char.
        CMPB    R0,#'~          ; Tilde ?
        BEQ     20$             ;  Yes: => 20$
        CMPB    R0,#'0          ; +
        BLO     40$             ;  0..9 ?
        CMPB    R0,#'9          ;
        BHI     40$             ; -
        CLRB    (SP)            ; Clear byte
        BISB    R0,(SP)         ; Insert in word
        CALL    IO              ; Next char.
        CMPB    CHAR,#'~        ; Tilde ?
        BNE     40$             ;  No: => 40$
20$:
        MOV     (SP)+,R0        ; Retrieve word
        SWAB    R0              ; Adjust
        MOV     #VT2TAB,R4      ; R4 => VT2XX table
        MOV     #VT2LEN/6,R5    ; R5 =  Table length
30$:
        CMP     R0,(R4)+        ; Look for table entry
        BEQ     VT2FN           ;  Found : => VT2FN
        CMP     (R4)+,(R4)+     ; Next entry
        SOB     R5,30$          ; Try next
        JMP     LOOP            ;  Not found : => LOOP
40$:
        TST     (SP)+           ; Flush word
50$:
        JMP     LOOP00          ; => LOOP00
;
;
        .SBTTL  MCE - VT2FN  -- Check if VT2xx key to be translated
;
VT2FN:
;
; Check if to be translated
;
        MOVB    #'F,SAVBUF      ; Insert
        MOVB    2(R4),SAVBUF+1  ;   key
        MOVB    3(R4),SAVBUF+2  ;     ident
        MOV     #3,PDSC+PX.LEN  ; Assume P0 Length = 3
        CMPB    SAVBUF+2,#BLNK  ; Blank ?
        BNE     10$             ;  No : => 10$
        DEC     PDSC+PX.LEN     ; P0 Length = 2
10$:
        JMP     PROCESS         ; Go via table
;
;
        .SBTTL  MCE - VT2ESC -- Check for VT2XX <ESC><ESC>
;
; Typed VT2xx F11 (<ESC>) key; look for a second one
;
VT2ESC:
        CALL    IO              ; Next char
        CMPB    IOSTAT+1,#ESC   ; <ESC> ?
        BNE     20$             ;  No : => 20$
        MOV     #VT2ESQ,R4      ; R4 -> VT2XX ESC-SEQ.
        MOV     #VT2ESL,R5      ; R5 = Length
10$:
        CALL    IO              ; Next char.
        CMPB    CHAR,(R4)+      ; Match ?
        BNE     20$             ;  No : => 20$
        SOB     R5,10$          ; Next
        JMP     EXECNW          ; <ESC><ESC>
20$:
        JMP     LOOP            ;

        .ENDC   ;VT2XX

        .SBTTL  MCE - TDVTST -- TDV2230 Key support
;
TDVKEY:

        .IF DF TDV2XX

        CMPB    TTP+1,#200      ; TDV2XX ?
        BNE     10$             ;  No: => 10$
;
;       <ESC> O ...
;
; Test character is in the range of "T" - "Z" for F1..F7
;
        MOVB    CHAR,R4         ; R4 = Character
        BIC     #177600,R4      ;
        SUB     #'T,R4          ; Normalize
        BLT     10$             ;  Less then : => 10$
        CMPB    R4,#'Z-'T       ; In range ?
        BGT     10$             ;  No : => 10$
;
; Function ok: convert to string
;
        MOVB    #'F,SAVBUF      ; Insert
        MOVB    R4,R0           ;
        ADD     #'1,R0          ;     key  code
        MOVB    R0,SAVBUF+1     ;
;
        MOV     #2,PDSC+PX.LEN  ; P0 Length
        ASL     R4              ; Make word offset
        ADD     #TDVTAB,R4      ; Add table address
        JMP     PROCES          ;
10$:

        .ENDC   ;TDV2XX

        JMP     LOOP            ; => LOOP

        .SBTTL
        .SBTTL    MCE ----------- *** Command execution ***
        .SBTTL    MCE - DELAY  -- Detach and delay
;
DELAY:
        CALL    IOCRLF          ; Print <CR><LF>
        CALL    DETACH          ; Detach terminal
        MRKT$S  #EFN,#10.,#2    ; Wait
        DIR$    #STOPIO         ;     10 seconds
        JMP     RESTAR          ; => RESTAR
;
;
    .SBTTL    MCE - SAVE   -- Save command without execution
;
SAVE:
        INCB    NEXFLG          ; Don't execute
        BR      EXEC1           ; => EXEC1
;
    .SBTTL    MCE - EXELEA -- Execute and leave pointer
;
EXELEA:
        INCB    LEAFLG          ; Don't clear pointers
        BR      EXEC1           ; => EXEC1
;
;
    .SBTTL    MCE - EXECNW -- Execute command no-wait
;
EXECNW:
        CLR     WAITFL          ; Clear EVF
        BR      EXEC1           ; => EXEC1
;
;
    .SBTTL    MCE - EXEC   -- Execute command
;
EXEC:
        .ENABL  LSB

        MOV     #1,WAITFL       ; EVF = 1
EXEC1:
        CALL    IOCR            ; Print <CR>
        CALL    DETACH          ; Detach terminal
        SUB     #CMDBUF,R2      ; Calculate Length
        MOV     R2,LEN          ; Store
        CALL    SUPRES          ; Ignore leading blanks
        BCS     50$             ;  Empty ? => 50$
10$:
        TSTB    SOLFLG          ; Save old commands ?
        BNE     20$             ;  Yes : => 20$
        TSTB    OLDFLG          ; Old command ?
        BNE     30$             ;  Yes : => 30$
20$:
        CALL    LDFIF           ; Load into FIFO
30$:
        TSTB    LEAFLG          ; Leave pointers ?
        BNE     EXEC2           ;  Yes : => EXEC2
        CALL    CLEAR           ; Clear pointers
        TSTB    NEXFLG          ; Execute ?
        BNE     50$             ;  No : => 50$
EXEC2:
        CALL    CMDCHK          ; Check for command Translation
        BCS     50$             ; Nothing to execute
EXEC3:

        .IF DF  TMOTIM

        CLRB    TMOCNT          ; Disable timeouts (until next IO)

        .ENDC   ;TMOTIM

        CALL    SUPRR0          ; Ignore leading blanks ( Start at R0 )
        BCS     50$             ; If C set : Empty command
;
; R0  => First non blank character
; LEN =  Length of command
;
        CALL    INTERN          ; Internal command , BYE or LOG ?
        BCC     50$             ; If C clear: no command for CLI
        CALL    DOEXEC          ; Excute command in buffer CMDBUF
        TST     WAITFL          ; Wait ?
        BNE     40$             ;  Yes : => 40$
        INC     WAITFL          ; Make flag #1
        MRKT$S  WAITFL,#20.,#1  ; Allow task to run
40$:
        STSE$S  WAITFL          ; Stop until done
50$:
        JMP     RESTAR          ; => RESTAR

        .DSABL  LSB
;
;
        .SBTTL  MCE - EXAST  -- Task exit ast
;
EXAST:
;
; Change STOP to WAIT
;
        MOV     #IO.KIL,CODE    ;; Kill
        CALL    IO              ;;    pending read
        MOV     WAITIO,STOPIO   ;; Change DIC-code
        DIR$    #STOPIO         ;; Wait for I/O
;
;
        .SBTTL  MCE - EXIT   -- Task exit
;
EXIT:

        .IF NDF SILENT

        MOV     #ENDTXT,R0      ; Exit
        CALL    IOMSG           ;   message

        .ENDC   ;SILENT

;
        .SBTTL  MCE - EXITI  -- Immediate Task exit
;
EXITI:

        .IF DF  STATUS

        TSTB    ANI+1           ; Ansi Screen ?
        BEQ     10$             ;  No : => 10$
        MOV     #STACLR,ADR     ; Clear
        MOV     #STACLN,LEN     ;  Statusline
        CALL    IOW             ;
10$:

        .ENDC   ;STATUS

        CALL    DETACH          ; Detach terminal
        EXIT$S                  ; Exit

        .SBTTL
        .SBTTL  MCE ----------- *** Internal Command Handling ***
        .SBTTL  MCE - INTERN -- Check for internal commands

; Check if the command (AFTER translation) is BYE, LOG[out] or an
; internal command starting with the verb 'MCE '.
; To check for the special commands after translation offers the
; possibility to define any other string for exit/bye.
; (E.g.: LOGOF*F := BYE, BYE := LOGOUT )
; INTERN returns C set, if no internal command, i.e. the buffer R0 =>
; with length LEN has to be submitted to the CLI.
; C clear on return, if internal command found, no CLI submit.
;
MACRO  CMPBNE  Source,Char,Labl
        MovB    Source,R3
        BicB    #40,R3
        CmpB    R3,#''Char
        Bne     Labl
ENDM   CMPBNE
;
MACRO  CMPBEQ  Source,Char,Labl
        MovB    Source,R3
        BicB    #40,R3
        CmpB    R3,#''Char
        Beq     Labl
ENDM   CMPBEQ
;
INTERN:
;
; To be recognised as an internal command, at least 3 characters
; must be present.
; Internal commands trapped are:
; BYE        : the MCR RSX logout command
; LOG[OUT]   : the DCL RSX logout command
; MCE action : MCE internal actions
;
        CMP     LEN,#3          ; Length in range ?
        BLT     40$             ;  No : => 40$

        .IF DF  CLISUP

        CMP     CLINAM,#^RDCL   ; In DCL ?
        BNE     10$             ;  No : => 10$
        CMPBNE   (R0),L,10$     ; +
        CMPBNE  1(R0),O,10$     ;  LOG ?
        CMPBEQ  2(R0),G,20$     ; -
10$:

        .ENDC   ;CLISUP

        CMPBNE   (R0),B,30$     ; +
        CMPBNE  1(R0),Y,30$     ;  BYE ?
        CMPBNE  2(R0),E,30$     ; -
20$:
        MOV     #^RMCR,TASK     ; Force MCR...
        MOV     #BYETXT,R0      ; Command to spawn is "BYE"
        CALL    GETBUF          ; Copy in CMDBUF
        MOV     #CMDBUF,R0      ; R0 => CMDBUF
        MOV     #3,LEN          ; "BYE" = 3 char.
        CLR     WAITFL          ; Do not wait
        CALL    DOEXEC          ; Submit "BYE" to MCR...
        CALLR   EXITI           ; Immediate task exit
30$:
        CMPBNE   (R0),M,40$     ; +
        CMPBNE  1(R0),C,40$     ;  MCE ?
        CMPBEQ  2(R0),E,50$     ; -
40$:
        SEC                     ; No internal command trapped
        RETURN                  ;
;
; Internal command strings must not be less than 8 characters in length
; Ignore anything else
;
50$:
        MOV     #INTCMD,R1      ; Point to internal command table
        ADD     #3,R0           ; Point
        SUB     #3,LEN          ;    behind "MCE"
        CALL    SUPRR0          ; Suppress spaces
        BCS     150$            ; Empty => 150$
        CMP     LEN,#4          ; At least 4 characters left ?
        BLT     150$            ;  No : => 150$
        CLR     R3              ; +
        BISB    (R0)+,R3        ;
        SWAB    R3              ;
        BISB    (R0)+,R3        ;   R3 := Upcased 1st 2 characters
        SWAB    R3              ;
        BIC     #"  ,R3         ; -
        CLR     R4              ; +
        BISB    (R0)+,R4        ;
        SWAB    R4              ;
        BISB    (R0)+,R4        ;   R4 := Upcased 2nd 2 characters
        SWAB    R4              ;
        BIC     #"  ,R4         ; -
        SUB     #4,LEN          ;    behind "MCE XXXX"
60$:
;
; Look for Verb in Table .....
;
        TST     (R1)            ; End of table reached ?
        BEQ     150$            ;  Yes : => 150$
        CMP     R3,(R1)+        ; First 2 characters match ?
        BEQ     70$             ;  Yes : => 70$
        ADD     #4,R1           ; Point to next table entry
        BR      60$             ; Look ahead
70$:
        CMP     R4,(R1)+        ; Second 2 characters match ?
        BEQ     80$             ; If eq Yes: action verb match
        TST     (R1)+           ; Point to next table entry
        BR      60$             ; Look ahead
80$:
        CALL    @(R1)           ; EXECute internal command
;
        BCS     150$            ;  Not OK ? => 150$
        TSTB    SINFLG          ; Save internal command ?
        BNE     140$            ;  Yes : => 140$

        .IF DF  FILE

        TSTB    FILREX          ; Read or Replace being processed ?
        BNE     90$             ;  Yes : => 90$
        TSTB    FILINP          ; File input ?
        BNE     140$            ;  Yes : => 140$
90$:
        CLRB    FILREX          ; Clear flag

        .ENDC   ;FILE

        MOV     FIFO+F.1ST,R0   ; R0 => First entry
        BEQ     140$            ; No entries : => 140$
        MOV     FIFO+F.LAST,R2  ; R2 => Last entry
        CMP     R0,R2           ; 1st = last ?
        BEQ     120$            ;  Yes : => 120$
100$:
        CMP     FI.NXT(R0),R2   ; Next = Last ?
        BEQ     110$            ;  Yes : Delete this one
        MOV     FI.NXT(R0),R0   ; Next
        BR      100$            ; => 100$
110$:
        MOV     R0,FIFO+F.LAST  ; New last
        CLR     (R0)            ; Last
        MOV     #FREE,R0        ; R0 => Free listhead
        MOV     FI.LEN(R2),R1   ; R1 = Length
        CALL    $RLCB           ; Release block
        BR      130$            ; => 130$
120$:
        MOV     #FIFO+F.1ST,R0  ; R0 => Header
        CALL    FRENT           ; Free entry
130$:
        DECB    FIFCNT          ; One less
140$:
        CLC                     ; Success
        RETURN                  ;
150$:
        MOV     #ERRTXT,R0      ; Error
        CALLR   IOMSG           ;   Message

        .SBTTL  MCE - ICCLEA -- Clear
;
; Clear FIFO
;
ICCLEA:
;
        MOV     MAXF,-(SP)      ; Save maxFIFO
        CLR     MAXF            ; Clear
        CALL    CLEFIF          ;    FIFO
        MOV     (SP)+,MAXF      ; Restore maxFIFO
        RETURN                  ;
;
;
        .SBTTL  MCE - ICCMSZ -- Cmsz x
;
; CMD Size
;
ICCMSZ:
;
        MOV     #MINC,R5        ; R5 => Destination
        CALLR   VALUE           ;
;
;
        .SBTTL  MCE - ICECHO -- Echo on/off
;
; Echo On/Off
;
ICECHO:
;
        MOV     #ECHFLG,R3      ; R3 => Flag
        CALLR   ONOFF           ; => On / Off
;
;
        .SBTTL  MCE - ICFISZ -- Fisz x
;
; FIFO size
;
ICFISZ:
;
        MOV     #MAXF,R5        ; R5 => Destination
        CALL    VALUE           ; Get value
        BCC     10$             ;
        RETURN                  ;
10$:
        CALLR   CLEFIF          ; Clear fifo
;
;
        .SBTTL  MCE - ICFREE -- Free
;
; Free poolspace
;
ICFREE:
        MOV     #POOL,R5        ; Point to pool raw data buffer
        CLR     (R5)+           ; Clear number of fragments
        CLR     (R5)+           ; Clear total pool
        CLR     (R5)            ; Clear biggest hole
        MOV     FREE,R4         ; Get address of pool listhead
        BEQ     30$             ;  No blocks : => 30$
10$:
        TST     (R4)+           ; R4 => Size
        CMP     (R5),(R4)       ; This size > stored ?
        BHIS    20$             ;  No : => 20$
        MOV     (R4),(R5)       ; Set new max
20$:
        ADD     (R4),-(R5)      ; Add this space to total
        INC     -(R5)           ; Increment number of pool fragments
        CMP     (R5)+,(R5)+     ; Point R5 to end of raw data buffer
        MOV     -(R4),R4        ; Get addr of next block
        BNE     10$             ; If ne more to examine
30$:
        MOV     #POOLDT,R0      ; POOL message
        MOV     #3,R4           ; 3 words to convert
40$:
        MOV     (R5),R1         ; Binary value
        MOV     #20012,R2       ; Parms.
        CALL    $CBTA           ; Convert
        MOVB    #'.,(R0)+       ; Decimal
        MOVB    #':,(R0)+       ; Terminate
        TST     -(R5)           ; Next
        SOB     R4,40$          ;   word
;
        CLRB    -(R0)           ; ASCIZ
        MOV     #POOLTX,R0      ; R0 => Message
        CALLR   IOMSG           ; Write and return
;
;
        .SBTTL  MCE - ICINSE -- Auto Insert on/off
;
; Auto insert On/Off
;
ICINSE:
;
        MOV     #INSFLG,R3      ; R3 => Flag
        CALL    ONOFF           ; => On / Off
        BCS     10$             ;  Error : => 10$
        TSTB    (R3)            ; Set ?
        BEQ     10$             ;  No : => 10$
        CLRB    OVSFLG          ; Clear auto overstrike
10$:
        RETURN                  ;
;
        .IF DF  EDT

;
        .SBTTL  MCE - ICKEYP -- Keypad on/off
;
; Keypad On/Off
;
ICKEYP:
;
        MOV     #EDTFLG,R3      ; R3 => Flag
        CALLR   ONOFF           ; => On / Off

        .ENDC   ;EDT

;
        .SBTTL  MCE - ICLIST -- LIST
;
; FIFO is LIST
;
ICLIST:
;
        CLRB    RNGFLG          ; Indicate LIST
        RETURN                  ;
;
;
        .SBTTL  MCE - ICOVER -- Auto Overstrike on/off
;
; Auto overstrike On/Off
;
ICOVER:
;
        MOV     #OVSFLG,R3      ; R3 => Flag
        CALL    ONOFF           ; => On / Off
        BCS     10$             ;  Error : => 10$
        TSTB    (R3)            ; Set ?
        BEQ     10$             ;  No : => 10$
        CLRB    INSFLG          ; Clear auto insert
10$:
        RETURN                  ;

        .IF DF  EXTNPR

        .SBTTL  MCE - ICPROM -- Prompt on/off
;
; Prompt On/Off
;
ICPROM:
;
        MOV     #PRMFLG,R3      ; R3 => Flag
        CALLR   ONOFF           ; => On / Off

        .ENDC   ;PRMFLG

;
        .SBTTL  MCE - ICPURG -- Purge
;
; Delete current translation table
;
ICPURG:
;
        MOV     #TRNB+F.1ST,R0  ; Queue header for Transtation table
        CALL    FRENT           ; Delete table entry
        BCS     ICPURG          ; More entries ? : => ICPURG
        RETURN                  ;
;

        .IF DF  FILE

        .SBTTL  MCE - ICREAD -- Read
;
; read commands from file specified
;
ICREAD:
;
        MOV     R0,-(SP)        ; Save pointer
        TSTB    FILINP          ; Is a file open ?
        BEQ     10$             ; If eq no: just open new
;
; Close a file currently open, i.e. 'MCE READ' issued from
; inside a definition is equivalent to a 'MCE CHAIN' command
;
        CALL    FILCLO          ; Close current file
10$:
        MOV     (SP)+,R1        ; Point behind 'MCE XXXX'
        MOV     LEN,R2          ; Length of command
        CALL    GETFIL          ; Get new file name
        BCS     20$             ; Error => 20$
        CALL    FILOP1          ; Read file(s)
        INCB    FILREX          ; Read or Replace being processed
20$:
        CALLR   SUCCES          ; Always success

        .SBTTL  MCE - ICREPL -- Replace
;
ICREPL:
        MOV     R0,-(SP)        ; Save pointer
        CALL    ICPURG          ; Delete current translation table
        MOV     (SP)+,R0        ; Restore pointer
        BR      ICREAD          ;

        .ENDC   ;FILE

;
        .SBTTL  MCE - ICRING -- Ring
;
; FIFO is RING buffer
;
ICRING:
        MOVB    #1,RNGFLG       ; Indicate RING
        CALLR   SUCCES          ;
;

        .IF DF  STATUS

        .SBTTL  MCE - ICSTAT -- Status [ on/off ]
;
; Status
;
ICSTAT:
;
        CALL    DELSEA          ; Search for delimitor
        TST     LEN             ; Left ?
        BNE     30$             ;  Yes : => 30$
        CALL    STAFIL          ; Fill statusline
        MOV     #STATX3,ADR     ; Address
        MOV     #STALN3,LEN     ; Length
        CALLR   IOW             ;
30$:
        TSTB    ANI+1           ; ANSI Terminal ?
        BEQ     20$             ;  No : => 20$
        MOV     #STAFLG,R3      ; R3 => Flag
        MOVB    (R3),R2         ; Old status
        MOV     R2,-(SP)        ; Save it
        CALL    ONOFF           ; => On / Off
        MOV     (SP)+,R2        ; Restore
        BCS     20$             ;
        TSTB    STAFLG          ; Off ?
        BNE     20$             ;  No : => 20$
        TSTB    R2              ; Was it on ?
        BEQ     20$             ;  no : => 20$
        MOV     #STACLR,ADR     ; Address
        MOV     #STACLN,LEN     ; Length
        CALLR   IOW             ; Clear status line
20$:
        RETURN                  ;

        .ENDC   ;STATUS

;
        .SBTTL  MCE - ICSVIN -- Intern on/off
;
; Save internal commands On/Off
;
ICSVIN:
;
        MOV     #SINFLG,R3      ; R3 => Flag
        CALLR   ONOFF           ; => On / Off
;
;
        .SBTTL  MCE - ICSVOL -- Old commands on/off
;
; Save old commands On/Off
;
ICSVOL:
;
        MOV     #SOLFLG,R3      ; R3 => Flag
        CALLR   ONOFF           ; => On / Off
;
;
        .SBTTL  MCE - ICVERS -- Version
;
; Show version
;
ICVERS:
;
        MOV     #STRTXT,R0      ; Print
        CALLR   IOMSG           ;   Startup message

        .SBTTL  MCE - CLEFIF -- Clear Fifo
;
CLEFIF:
        CMPB    FIFCNT,MAXF     ; Maximum reached ?
        BLOS    10$             ;  No : => 10$
        CALL    CLFIFI          ; Release first entry
        BCS     CLEFIF          ; More ? : => CLEFIF
10$:
        CALLR   SUCCES          ;
;
;
        .SBTTL  MCE - DELSEA -- Delimitter search
;
DELSEA:
        TST     LEN             ; Length
        BEQ     20$             ; Zero : => 20$
10$:
        CMPB    (R0),#BLNK      ; Start with a Space ?
        BEQ     20$             ;  Yes : => 20$
        INC     R0              ; Next := First
        DEC     LEN             ; One less
        BNE     10$             ; Not empty : => 10$
20$:
        RETURN                  ;

        .SBTTL  MCE - ONOFF  -- Check for ON or OFF in command
;
; ON/OFF
;
;  R3 => Byte flag
;
ONOFF:
        CALL    DELSEA          ; Search for delimitor
        CALL    SUPRR0          ; Suppress
        BCS     NOSUCC          ;  Empty : => NOSUCC
        BICB    #40,(R0)        ; Upcase
        CMPB    (R0)+,#'O       ; 'O ?
        BNE     NOSUCC          ;  No : => NOSUCC
        BICB    #40,(R0)        ; Upcase
        CMPB    (R0),#'N        ; 'N ?
        BNE     30$             ;  No : => 30$
        INCB    (R3)            ; Set flag
        BR      SUCCES          ;
30$:
        CMPB    (R0)+,#'F       ; 'F ?
        BNE     NOSUCC          ;  No : => NOSUCC
        BICB    #40,(R0)        ; Upcase
        CMPB    (R0),#'F        ; 'F ?
        BNE     NOSUCC          ;  No : => NOSUCC
        CLRB    (R3)            ; Reset flag
;
SUCCES:
        CLC                     ; Succes
        RETURN                  ;
NOSUCC:
        SEC                     ; Not Succes
        RETURN                  ;
;
;
        .SBTTL  MCE - VALUE  -- Convert value of MCE XXXX nnn command
;
VALUE:
        CALL    DELSEA          ; Search for delimitor
        CALL    SUPRR0          ; Suppress
        BCS     NOSUCC          ;  Empty : => NOSUCC
        CALL    $CDTB           ; Convert
        TST     R1              ; Empty ?
        BEQ     NOSUCC          ;  Yes : => NOSUCC
        CMP     R1,#99.         ; Too large ?
        BHI     NOSUCC          ;  Yes : => NOSUCC
        MOV     R1,(R5)         ; Insert value
        BR      SUCCES          ;

        .SBTTL
        .SBTTL    MCE ----------- *** Subroutines ****
        .SBTTL    MCE - CLEAR  -- Clear flags and pointers
;
CLEAR:
;
        CLR     FIFPTR          ; Clear
        CLRB    FIFPOI          ;   pointers
        RETURN                  ;
;
;
        .SBTTL    MCE - CLFIFI -- Clear first entry of FIFO buffer
;
CLFIFI:
        MOV     #FIFO+F.1ST,R0  ; This header
        CALL    FRENT           ; Free entry from queue
        BCC     10$             ;  Empty : => 10$
        DECB    FIFCNT          ; Adjust count
10$:
        RETURN                  ;
;
;
        .SBTTL  MCE - CLRBUF -- Clear Buffer CMDBUF
;
CLRBUF:
        MOV     #CMDBUF,R1      ; R1 => CMDBUF
        MOV     R1,R2           ; R2 => CMDBUF
        MOV     #CMDSIZ,R5      ; R5 =  CMDSIZ
10$:
        MOVB    #BLNK,(R1)+     ; Reset CMDBUF to blank
        SOB     R5,10$          ; Go back if not the end
        MOV     R2,R1           ; R1 => CMDBUF
        RETURN                  ;
;
;
        .SBTTL  MCE - CLRSCR -- Clear Screen
;
CLRSCR:
        TSTB    ANI+1           ; Ansi Screen ?
        BEQ     10$             ;  No : => 10$
        MOV     #SCRCLR,ADR     ; Clear
        MOV     #SCRCLL,LEN     ;   screen
        CALLR   IOW             ;
10$:
        SEC                     ; Not cleared
        RETURN                  ;

        .SBTTL  MCE - CMDCHK -- Check for Command definition
;
; Check for Command definition
; or replace first command word by stuff defined in command buffer
; P1..P8 may also be replaced
;
;   R0  => Buffer
;   LEN =  Length
;
;
;
CMDCHK:
        MOV     R0,-(SP)        ; Save pointer in CMDBUF
        MOV     LEN,-(SP)       ; Save initial length
;
        MOV     #CDSC,R1        ; +
        MOV     #CLL/2,R2       ;
10$:                            ; Clear scratch buffer
        CLR     (R1)+           ;
        SOB     R2,10$          ; -
;
        MOV     R0,R1           ; R1 => Source Buffer
        MOV     LEN,R2          ; R2 =  Length
        MOV     #SAVBUF,R3      ; R3 => Destination Buffer
        MOV     #PDSC,R5        ; R5 => Current Parameter Descriptor
        MOV     R3,PX.ADR(R5)   ; Start of P0
20$:
;
; Store single char
;
        MOVB    (R1)+,R0        ; R0 = char
        CALL    CNVUPC          ; Convert and check for delimiter
        MOVB    R0,(R3)+        ; Store char in SAVBUF
        BCC     60$             ;  No delimiter found : => 60$
30$:
        CMPB    (R1),#BLNK      ; Another Space ?
        BNE     40$             ;  No : => 40$
        INC     R1              ; Next
        SOB     R2,30$          ;   Character
;
        BR      80$             ; End : => 80$
40$:
;
; To next Pn
;
        CMP     R5,#PDSC        ; Is this P0 ?
        BNE     50$             ;  No  : => 50$
        MOV     R3,CDSC+PX.ADR  ; Load start Address of remainder
        DEC     CDSC+PX.ADR     ; Point to space
50$:
        CMP     R5,#8.*PX.SIZ+PDSC
                                ; Already on P8 ?
        BHIS    60$             ;  Yes : => 60$, put it all there
        ADD     #PX.SIZ,R5      ; Next Parameter
        MOV     R3,PX.ADR(R5)   ; Start address
        BR      70$             ; Do not count
60$:
;
; No delimiter found
;
        INC     PX.LEN(R5)      ; Count char
70$:
        SOB     R2,20$          ; Next character
80$:
;
        MOV     R3,LEN          ; Calculate
        SUB     #SAVBUF,LEN     ;  Compressed length
        MOV     CDSC+PX.ADR,R2  ; Remainder Descriptor defined ?
        BEQ     90$             ;  No => 90$
        SUB     R2,R3           ; Calculate length
        MOV     R3,CDSC+PX.LEN  ; Store length
;
; Now everything is moved into SAVBUF
; Check if we define a new command ":=" in P1
;
90$:
        MOV     #PDSC+PX.SIZ,R2 ; R2 => P1 descr
        CMP     (R2)+,#2        ; Correct length ?
        BNE     100$            ;  No => 100$
        MOV     (R2),R2         ; R2 => string
        CMPB    (R2)+,#':       ; +
        BNE     100$            ;
        CMPB    (R2)+,#'=       ;   ":="
        BNE     100$            ; -
        CALL    NEWCMD          ; Match found
        SEC                     ; Nothing to execute
        BR      110$            ; =>
;
; Try find an entry in the commandbuffer with key P0
;
100$:
        CALL    FNDCMA          ; Check in table
        BCC     120$            ;  Entry found => 120$
        CLC                     ; Indicate success
110$:
        MOV     (SP)+,LEN       ; Restore initial length
        MOV     (SP)+,R0        ; Restore pointer in CMDBUF
        RETURN                  ;
120$:
;
; Entry found, R1 points to Text
;
        MOV     #CMDBUF,R2      ; R2 => Destination
130$:
;
; Assemble buffer CMDBUF
;
        MOVB    (R1)+,R0        ; Next char
        BEQ     150$            ;  All done : => 150$
        CMPB    R0,#''          ; Could it be 'Pn' ?
        BNE     140$            ;  No  : => 140$
        CALL    SUBST           ; Check it and substitute if necessary
        BCS     130$            ; Already substituted : => 130$
140$:
        MOVB    R0,(R2)+        ; Store character in CMDBUF
        BR      130$            ; Next char from CMD Buf
150$:
;
; Whole buffer moved to CMDBUF
;
        TSTB    CFETCH          ; Buffer already feched ?
        BLT     160$            ;  Yes : => 160$
        MOV     #CDSC,R1        ; This descriptor to append
        CALL    STORE           ; Store
160$:
;
; All done, execute new command
;
        MOV     #CMDBUF,R0      ; R0 => CMDBUF
        SUB     R0,R2           ; Calculate new length
        MOV     R2,LEN          ;  and store
        CMP     (SP)+,(SP)+     ; Flush pointer and length
        TSTB    OVMSG           ; Buffer overflow ?
        BEQ     170$            ;  No : => 170$
        MOV     #TOOLON,R0      ; Give
        CALL    IOMSG           ;   message
        SEC                     ; Not success
170$:
        RETURN                  ;

        .SBTTL  MCE - CNVUPC -- Convert to uppercase
;
; Convert to upper case, CC-C set if delimiter
;
CNVUPC:
        CMPB    R0,#'A+40       ; Convert to upper case
        BLO     10$             ;
        CMPB    R0,#'Z+40       ;
        BHI     10$             ;
        BICB    #40,R0          ; Convert to upper
10$:
        CMPB    R0,#BLNK        ; Delimter ?
        SEC                     ;
        BEQ     30$             ; Its a delimiter
20$:
        CLC                     ; Character within string
30$:
        RETURN                  ;

        .IF DF  STATUS

;
        .SBTTL  MCE - CONV   -- Convert 2 characters -> ASCII
;
CONV:
        MOV     #11012,R2       ; Convert 2 chars
        CALLR   $CBTA           ; Convert

        .ENDC   ;STATUS
;
;
        .SBTTL  MCE - DETACH -- Detach terminal
;
DETACH:

        .IF DF  EDT

        TSTB    EDTFLG          ; EDT Keys enabled ?
        BEQ     10$             ;  No : => 10$
        MOV     LEN,-(SP)       ; Save length
        MOV     #NUMTXT,ADR     ; Numeric keypad
        MOV     #2,LEN          ; Length
        CALL    IOW             ; Write
        MOV     (SP)+,LEN       ; Restore length
10$:

        .ENDC   ;EDT

        MOV     #IO.DET,CODE    ; Detach
        CALLR   IO              ;     the terminal
;
;
        .SBTTL  MCE - DISPLY -- Rewrite whole Line
;
DISPLY:
        TSTB    ANI+1           ; Ansi Screen ?
        BNE     20$             ;  Yes : => 20$
        CMP     ADR,PROMLF      ; Just new Line written ?
        BNE     10$             ;  No  : => 10$
        CMP     LEN,#2          ; Something written ?
        BLE     20$             ;  No  : => 20$
10$:
        MOV     PROMLF,ADR      ; Line with <LF><CR>
        BR      30$             ; => 30$
20$:
        MOV     PROMPT,ADR      ; Line with <CR>
30$:
        MOV     R2,LEN          ; Calculate
        SUB     ADR,LEN         ;       length
        MOV     R0,-(SP)        ; Save R0
        MOV     R2,R0           ; R0 => EOL
        MOVB    #ESC,(R0)+      ; Append
        MOVB    #'[,(R0)+       ;   Clear till EOL
        MOVB    #'K,(R0)+       ;       Esc sequence
        TSTB    ANI+1           ; Ansi Screen ?
        BEQ     40$             ;  No  : => 40$
        ADD     #3,LEN          ; Make Escseq visible
40$:

        .IF DF  EDT

        TST     SELSTR          ; Select active ?
        BEQ     70$             ;  No : => 70$
        CMP     R1,SELSTR       ; Compare cursor to start of sel range
        BEQ     70$             ;  - Equal => 70$
        MOV     R3,-(SP)        ; Save R3
        MOV     R4,-(SP)        ; Save R4
        BLO     50$             ;  - Cursor left of start
        MOV     SELSTR,R3       ; Start
        MOV     R1,R4           ; End
        BR      60$             ; => 60$
50$:
        MOV     R1,R3           ; Start
        MOV     SELSTR,R4       ; End
60$:
        CALL    WRISEL          ; Write selective range
        MOV     (SP)+,R4        ; Restore R4
        MOV     (SP)+,R3        ; Restore R3
70$:

        .ENDC   ;EDT

        CALL    IOW             ; Write
        MOVB    #BLNK,-(R0)     ; +
        MOVB    #BLNK,-(R0)     ;  Flush Escseq
        MOVB    #BLNK,-(R0)     ; -
        MOV     (SP)+,R0        ; Restore R0
        MOV     #BS,ADR         ; +
        MOV     R2,LEN          ;
        SUB     R1,LEN          ;  Restore Cursor
        BEQ     80$             ;
        CALLR   IO              ; -
80$:
        RETURN                  ;

        .SBTTL  MCE - DOEXEC -- Submit command to CLI
;
DOEXEC:
;
; R0  => First non blank character
; LEN =  Length of command
;

        .IF DF  COMPND

        MOV     R0,R3           ; R0 => start of command
        MOV     LEN,R4          ; R4 =  Length
        INC     WAITFL          ; Always wait
10$:
        MOV     R4,R1           ; R1 =  Length
        BEQ     60$             ; Empty : => 60$
        CLR     R2              ; Compute length here
20$:
        CMPB    (R3)+,#'&       ; Ampersand here ?
        BNE     30$             ;  No : => 30$
        CMPB    -2(R3),#BLNK    ; Preceeded by a space ?
        BEQ     40$             ;  Yes : => 40$
30$:
        INC     R2              ; Count command length
        SOB     R1,20$          ; End of story ?
;
        MOV     R2,LEN          ; Load new length
        DEC     WAITFL          ; Restore wait condition
        CALLR   DOEXE1          ; Process last or only command
40$:
        MOV     R2,LEN          ; Load new length
        INC     R2              ; Account for &-sign
        SUB     R2,R4           ; Compute unused string length
        BEQ     50$             ;  Empty ? Yes : => 50$
;
; Execute .....
;
        CALL    DOEXE1          ; Go execute it
        STSE$S  WAITFL          ; Stop for execution
        CMP     EXSTAT,#EX$SUC  ; Successfull ?
        BEQ     50$             ;  Yes : => 50$
;
; Message with exit status .....
;
        MOV     R0,-(SP)        ; Save R0
        MOV     LEN,-(SP)       ; Save Length
        MOV     #EXSTDA,R0      ; R0 => ASCII buffer
        MOV     EXSTAT,R1       ; R1 =  Value
        MOV     #27012,R2       ; R2 =  Parameters
        CALL    $CBTA           ; Convert to ASCII
        MOV     #EXSTMS,ADR     ;
        MOV     #EXSTML,LEN     ;
        CALL    IOW
        MOV     (SP)+,LEN       ; Restore Command length
        MOV     (SP)+,ADR       ; Restore Command pointer
        CALLR   IOW
50$:
        MOV     R3,R0           ; Set to unused string
        BR      10$             ; Go for next part
60$:
        RETURN                  ;

        .ENDC   ;COMPND

DOEXE1:
;
        .IF DF  COMPND

        CALL    SUPRR0          ; Suppress Leading spaces

        .ENDC   ;COMPND

        TSTB    ECHFLG          ; Echo ?
        BEQ     10$             ;  No : => 10$
        MOV     LEN,-(SP)       ; Save length
        CALL    IOCRLF          ; New line
        MOV     (SP),LEN        ; Get length
        MOV     R0,ADR          ; Address of command
        CALL    IOW             ; Write command
        CALL    IOCR            ; New line
        MOV     (SP)+,LEN       ; Restore length
10$:
;
; ***  EXECUTE COMMAND ***
;
        MOV     R0    ,SPAWN+S.PWCA
        MOV     LEN   ,SPAWN+S.PWCL
        DIR$    #SPAWN          ;
        RETURN                  ;

        .IF DF  FILE

;
        .SBTTL  MCE - FILCLO -- Close current MCEINI file
;
FILCLO:
        CLRB    FILINP          ; No file input
        CLOSE$  #FDBIN          ; Close inputfile
        TST     FDIR            ; Was it first default file ?
        BEQ     10$             ;  No : => 10$
        CALL    FILOP3          ; Open next file
        BCS     10$             ;
        CALLR   FILREA          ; If opened : => FILREA
10$:
        RETURN                  ;
;
;
        .SBTTL  MCE - FILOP  -- Open MCEINI file from MCR line
;
FILOP:  INCB    FILINI          ; Startup file
        CALL    GETMCR          ; Get MCR commandline (startup file)
        BCC     FILOP2          ;  OK : => FILOP2
        RETURN                  ;
;
;
        .SBTTL  MCE - FILOP1 -- Open MCEINI file
;
FILOP1:
        CLRB    FILINI          ; No startup
FILOP2:
        CALL    GETCLI          ; Get CLI info
        CALL    FILOP4          ; Open File LB:[1,2]xxx.CLI
        BCC     FILRET          ; Success
        TST     FDIR            ; Was it first default file ?
        BEQ     10$             ;  No : => 10$
        CALL    FILOP3          ; Open 'SY:xxx.CLI'
        BCC     FILRET          ;  Ok : => FILRET
        TSTB    FILINI          ; Startup ?
        BNE     FILRET          ;  Yes : => FILRET
10$:
        MOV     #FILTXT,R0      ; Error
        CALLR   IOMSG           ;   Message
;
FILOP3:
        CLR     FDIR            ; No directory descriptor
        MOV     #"SY,DEV        ; Try file 'SY:xxx.CLI'
FILOP4:
        CLRB    FILINP          ; Assume file can not be opened
        OPEN$R  #FDBIN          ; Open input file
        BCS     FILRET          ;  Not OK : => FILRET
        INCB    FILINP          ; Enable File Input
FILRET:
        RETURN                  ; Return
;
        .SBTTL  MCE - FILREA -- Read from MCEINI file
;
FILREA:
        GET$S   #FDBIN          ; Get a record
        BCC     10$             ;
        CALLR   FILCLO          ;  No more records : => Close file
10$:
        MOV     F.NRBD(R0),LEN  ; Length
        CALL    REPLHT          ; Replace TABs
        CALL    SUPRES          ; Ignore leading blanks
        BCS     FILREA          ;  Empty line : => FILREA
        TST     (SP)+           ; Do not return
        MOV     #1,WAITFL       ; Wait for execution of commands
        CALLR   EXEC2           ;   but execute directly

        .ENDC   ;FILE

        .SBTTL  MCE - FNDCMA -- Find entry in command table with "*"
        .SBTTL  MCE - FNDCMD -- Find entry in command table
;
;
;    Input    - PDSC of P0 defined
;             - CTSTAR .ne.0 to allow abreviated command if command
;               definition contains "*" (a la VMS)
;    Output   - CC-C set - no entry found
;               CC-C clr - entry found
;               R0 - to entry
;               R1 - to point to string after ":="
;               R2 - to previous entry (for remove and inserts)
;
FNDCMA:
        .ENABL  LSB

        MOVB    #1,CTSTAR       ; Enable abbrivations
        BR      10$             ;
FNDCMD:
        CLRB    CTSTAR          ; Ignore "*" in translation buffer
10$:
        MOV     #TRNB+F.1ST,R0  ; R0 => Translationbuffer
        MOV     R3,-(SP)        ; Save R3
        MOV     R1,-(SP)        ; Save R1
        CLR     -(SP)           ; For previous entry
20$:
        MOV     R0,(SP)         ; Save previous entry
        TST     FI.NXT(R0)      ; Any next entry ?
        BEQ     100$            ;  No : => 100$, end of list
        MOV     FI.NXT(R0),R0   ; Take next entry
        MOV     R0,R1           ; R1 => Entry
        ADD     #FI.TXT,R1      ; R1 => Text
        MOV     PDSC+PX.LEN,R3  ; Length to be compared
        BLE     100$            ;  Zero : => 100$
        MOV     PDSC+PX.ADR,R2  ; Start addr of P0
        TSTB    CTSTAR          ; Without abbreviation ?
        BEQ     80$             ;  Yes : => 80$
;
; Check for match, accepting any "*" in command defintion
;
        CLRB    TMPFLG          ; Reset Flag: "*" found in Cmd Translation
30$:
        CMPB    (R1),#'*        ; Check for "*" in translation buffer
        BNE     40$             ;  Not yet found : => 40$
        INCB    TMPFLG          ; Found, remember it
        INC     R1              ; Next char
40$:
        CMPB    (R1),#BLNK      ; End of translation buffer ?
        BEQ     60$             ;  Yes : => 60$, terminate compare
        CMPB    (R2)+,(R1)+     ; Equal ?
        BEQ     50$             ;  Yes : => 50$
        BGT     20$             ; NE and must come further down in list
        TSTB    TMPFLG          ; Passed entry - any "*" seen ?
        BNE     20$             ;  Yes : => 20$, continue search
        BR      100$            ; We passed alphabetical order : => 100$
50$:
        SOB     R3,30$          ; Next char
;
        CMPB    (R1),#BLNK      ; End of input string ?
        BEQ     70$             ;  Yes : => 70$
        CMPB    (R1),#'*        ; Next byte end ?
        BEQ     70$             ;  Yes : => 70$
60$:
        TSTB    TMPFLG          ; Abbreviation possible ?
        BEQ     20$             ;  No  : => 20$
70$:
        CMPB    (R1)+,#BLNK     ; End of string (or binary 0???) ?
        BHI     70$             ;  Not yet found : => 70$
        BR      90$             ; Point past key
;
; Check for match, ignoring any "*" in command defintion
;
80$:
        CMPB    (R2)+,(R1)+     ; Compare
        BGT     20$             ; NE and must come further down in list
        BLT     100$            ; Already passed alphabetical order
        SOB     R3,80$          ; Next
;
        CMPB    (R1)+,#BLNK     ; Followed by space ?
        BNE     100$            ;  No  : => 100$
90$:
        ADD     #3,R1           ; Skip ":= "
        CLC                     ; Successful
        MOV     (SP)+,R2        ; R2 => Previous entry
        TST     (SP)+           ; Flush old R1
        BR      110$            ;
100$:
        SEC                     ; Not found
        MOV     (SP)+,R2        ; R2 => Previous entry
        MOV     (SP)+,R1        ; Old R1
110$:
        MOV     (SP)+,R3        ; Restore R3
        RETURN                  ;

        .DSABL  LSB

        .SBTTL    MCE - FRENT  -- Free entry from queue
;
;  Header in R0.   CC-C clear if it was empty
;
FRENT:
        JSR     R5,.SAVR1       ; Save Regs
        MOV     F.1ST(R0),R2    ; Get entry if any
        CLC                     ; Assume empty
        BEQ     20$             ;  None : => 20$
        MOV     FI.NXT(R2),FI.NXT(R0)
                                ; Remove from head of queue
        BNE     10$             ; More entries
        MOV     R0,F.LAST(R0)   ; This was last one
10$:
        MOV     FI.LEN(R2),R1   ; R1 =  Length of entry
        MOV     #FREE,R0        ; R0 => Free memory list head
        CALL    $RLCB           ; Release memory block
        SEC                     ; Success
20$:
        RETURN                  ;
;
;
        .SBTTL  MCE - GETBUF -- Load Buffer into CMDBUF
;
; R0 points to source
;
GETBUF:
        MOV     #CMDBUF,R1      ; R1 => CMDBUF
        MOV     R1,R2           ; R1 => CMDBUF
        MOV     #CMDSIZ,R5      ; R5 =  CMDSIZ
10$:
        TSTB    PRIFLG          ; Print commandbuffer ?
        BEQ     30$             ;  No : => 30$
        CMPB    (R0),#':        ; Command definition ?
        BNE     30$             ;  No : => 30$
        CMPB    -1(R0),#BLNK    ; Space in front ?
        BNE     30$             ;  No : => 30$
        CMPB    1(R0),#'=       ; Equal sign behind ?
        BNE     30$             ;  No : => 30$
20$:
        MOVB    #BLNK,(R1)+     ; Insert spaces
        CMP     R1,#CMDBUF+12.  ;  At posision ?
        BLO     20$             ; No : => 20$
30$:
        MOVB    (R0)+,(R1)+     ; (R0) --> CMDBUF
        BEQ     50$             ;  Zero : => 50$
        CMPB    -1(R1),#BLNK    ; Blank ?
        BEQ     40$             ;  Yes : => 40$
        MOV     R1,R2           ; R2 => Behind last
40$:
        SOB     R5,10$          ; Go back if not the end
        BR      60$             ; => 60$
50$:
        MOVB    #BLNK,-1(R1)    ; Overprint 000 (.ASCIZ)
60$:
        MOV     R2,R1           ; Both at the end
        RETURN                  ;

        .IF DF  CLISUP!FILE
;
;
        .SBTTL  MCE - GETCLI -- Get CLI information
;
GETCLI:
        DIR$    #GCLI           ; Get CLI information
        BCS     10$             ; Error is C set

        .IF DF  CLISUP&FILE

        MOV     CLINAM,FILTYP   ; Use CLI name for file type

        .ENDC   ;CLISUP&FILE

        .IF DF  FILE

        CALL    $SAVAL          ; Save all registers
        MOV     #CURDIR,R2      ; R2 => Ascii Current directory
        MOV     CLIUIC,R3       ; Binary value from GCLI
        CLR     R4              ; Parameters ( No lea. zeroes, add separ. )
        CALL    .PPASC          ; Convert to ASCII
        MOV     R2,R1           ; Calculate
        MOV     #CURDIR,R2      ;    length
        SUB     R2,R1           ;       and point to Ascii
        CALL    .WDFDR          ; Write default UIC
        CLC

        .ENDC   ;FILE

10$:
        RETURN                  ;

        .ENDC   ;CLISUP!FILE
;
;
        .SBTTL    MCE - GETFIF -- Get FIFO Buffer, pointed to by FIFPTR
;
GETFIF:
        CLRB    OLDFLG          ; No old command
        MOV     FIFPTR,R0       ; Get Ptr
        BNE     10$             ;  Defined : => 10$
        MOV     #FIFPTR,R0      ; Null String
        BR      20$             ; => 20$
10$:
        INCB    OLDFLG          ; Old command
        ADD     #FI.TXT,R0      ; Get start of text
20$:
        CALL    GETBUF          ; Load buffer
        CALLR   DISPLY          ;  and display
;
;
        .IF DF  FILE            ;

        .SBTTL  MCE - GETFIL -- Get filespecification
        .SBTTL  MCE - GETMCR -- Get filespecification from MCR command
;
; This subroutine dequeues the command which invokes MCE (if any),
; and overrides the default startup file name (MCEINI.xxx) by
; file specified in the commandline.
; Command line syntax is : 'MCE file_specification'
;
        .ENABL LSB
GETMCR:
        DIR$    #GMCR           ; Get commandline
        BCS     20$             ;  Problem => 20$
        MOV     #MCRLIN,R1      ; Point to commandline
        MOV     $DSW,R2         ; Length of line
GETFIL:
;
; reset FDB file-name pointers
;
        MOV     #"LB,DEV        ; Reset default file volume
        MOV     #DIRL,FDIR      ; Restore pointer to default directory
        MOV     #FDSPT,FDBIN+F.DSPT
                                ; Reset DSPT pointer in FDB
        TST     R2              ; Any length ?
        BEQ     20$             ;  No : => 20$
10$:
        CMPB    #BLNK,(R1)+     ; Mnemonic delimiter ?
        BEQ     30$
        DEC     R2              ; Count remaining char
        BNE     10$             ; If eq: empty command
20$:
        CLC                     ; Success
        BR      50$             ;
30$:
        DEC     R2              ; Flush space
        CSI$1   #CSIBLK,R1,R2   ; Syntax check
        BCS     40$             ; Syntax error: ignore it
        CSI$2   R0,OUTPUT       ; Parse line into its com
        BCS     40$             ; No file: ignore it
;
; Now we have a file descriptor table inside the CSI parser block
; override the default DSPT pointing to MCEINI.CMD:
;
        MOV     #CSIBLK+C.DSDS,FDBIN+F.DSPT
                                ; New DSPT pointer
        CLR     FDIR            ; Indicate 'No more files'
        BR      50$             ; => 50$
40$:
        MOV     #FLSTXT,R0      ; Filespec
        CALL    IOMSG           ;     syntax error
        SEC                     ; Indicate error
50$:
        RETURN                  ;
        .DSABL  LSB

        .ENDC   ;FILE

        .SBTTL  MCE - IO     -- General I/O Routine
;
IO:

        .IF DF  TMOTIM

        MOVB    #TMOTIM,TMOCNT  ; Set new timeoutcount

        .ENDC   ;TMOTIM

        DIR$    #QIODIR         ; Do I/O
        DIR$    #STOPIO         ; Stop for I/O (or wait when aborted)
        RETURN                  ;
;
;
        .SBTTL  MCE - IOCR   -- Print <CR>
;
IOCR:
        MOV     #1,LEN          ; Length
        BR      IOCL            ; => IOCL
;
        .SBTTL  MCE - IOCRLF -- Print <CR><LF>
;
IOCRLF:
        MOV     #2,LEN          ; Length
IOCL:
        MOV     #IO.CCO,CODE    ; Cancel <CTRL/O>
        MOV     #CRET,ADR       ; Print <CR> ( <LF> )
        BR      IO              ; Go to IO
;
;
        .SBTTL  MCE - IOMSG  -- Print Message
;
; Print a Msg in (R0)
;
IOMSG:
        CALL    IOCRLF          ; Print <CR><LF>
        CALL    GETBUF          ; (R0) --> CMDBUF
        CALL    DISPLY          ; Write line
        CALLR   CLRBUF          ;
;
;
        .SBTTL  MCE - IOW    -- Write routine
;
IOW:
        MOV     #IO.WVB,CODE    ; write
        BR      IO              ; Go to IO
;
;
    .SBTTL    MCE - LDFIF  -- Load CMDBUF into FIFO Buffer
;
; R0  => First non blank character
; LEN =  Length of command
;
LDFIF:
        CALL    $SAVAL          ; Save Regs
        MOV     LEN,R5          ; R5 =  Length
        BEQ     40$             ;  Zero : => 40$
        CMP     R5,MINC         ; Save it ?
        BLO     40$             ;  No : => 40$
        MOV     R0,R4           ; R4 => Command
        MOV     R5,R1           ; R1 =  Length
        ADD     #FI.TXT+1,R1    ; Increment for header and 0 byte
        CMPB    FIFCNT,MAXF     ; Maximum reached ?
        BLO     20$             ;  No : => 20$
10$:
        CALL    CLFIFI          ; Release first entry
        BCC     40$             ; Nothing to release
20$:
        MOV     #FREE,R0        ; R0 => Free memory listhead
        CALL    $RQCB           ; Request core block
        BCS     10$             ; Nothing received yet - release more
        CLR     FI.NXT(R0)      ; No next entry
        MOV     R0,@FIFO+F.LAST ; Link to previous
        MOV     R0,FIFO+F.LAST  ; New last entry
        MOV     R1,FI.LEN(R0)   ; Total length
        ADD     #FI.TXT,R0      ; Point to text field
        MOV     R4,R1           ; Source text
30$:
        MOVB    (R1)+,(R0)+     ; Load
        SOB     R5,30$          ;   string
        CLRB    (R0)            ; End of string
        INCB    FIFCNT          ; Count
40$:
        RETURN                  ;

        .IF DF  TMOTIM

;
        .SBTTL  MCE - MARK   -- Next Marktime
MARK:
        MRKT$S  ,#60.,#2,#TIMAST;(;)
        RETURN                  ;(;)

        .ENDC   ;TMOTIM

        .SBTTL  MCE - NEWCMD -- Define new command or delete command
;
; Define new command in command buffer, or delete it
;
NEWCMD:
        TSTB    NLOFLG          ; Skip processing ?
        BNE     50$             ;  Yes : => 50$
        CALL    FNDCMD          ; Check if in table
        BCC     60$             ;  Yes : => 60$, release old entry
        TST     2*PX.SIZ+PDSC   ; P2 defined ?
        BNE     10$             ;  Yes : => 10$, must load
        TST     3*PX.SIZ+PDSC+PX.ADR
                                ; P3 with addr ?
        BEQ     50$             ;  No  : => 50$, delete only
10$:
;
; Insert new command
;
        MOV     R2,R3           ; R3 => Entry after which to insert
        MOV     LEN,R1          ; length of string
        BEQ     50$             ;   Zero : => 50$
        ADD     #FI.TXT+1,R1    ; With overhead and 0 byte
        MOV     #FREE,R0        ; R0 => Free memory listhead
        CALL    $RQCB           ; Request core block
        BCC     20$             ;  Ok : => 20$
        MOV     #NOPOOL,R0      ; No more Pool
        CALL    IOMSG           ; Give the message
        BR      50$             ; => 50$
20$:
        MOV     FI.NXT(R3),FI.NXT(R0)
                                ; Link to previous entry
        BNE     30$             ;
        MOV     R0,TRNB+F.LAST  ; We will be last one
30$:
        MOV     R0,FI.NXT(R3)   ;
        MOV     R1,FI.LEN(R0)   ; Total length
        ADD     #FI.TXT,R0      ; R0 => Start of text
        MOV     #SAVBUF,R1      ; R1 => Source
        MOV     LEN,R2          ; R2 =  Length
40$:
        MOVB    (R1)+,(R0)+     ; Copy
        SOB     R2,40$          ;  text
        CLRB    (R0)            ; Write delimiter
50$:
        RETURN                  ;
60$:
;
; Release old entry
;
        MOV     FI.NXT(R0),FI.NXT(R2)
                                ; Link remainder
        BNE     70$             ;  More entries : => 70$
        MOV     R2,TRNB+F.LAST  ; This was last one
70$:
        MOV     FI.LEN(R0),R1   ; R1 = Length
        MOV     R0,R2           ;
        MOV     #FREE,R0        ; R0 => Free memory listhead
        CALL    $RLCB           ; Release it
        BR      NEWCMD          ; Find more to release

        .IF DF  STATUS

;
        .SBTTL  MCE - OFFON  -- Depending on flag in R1 : Fill with ON or OFF
;
OFFON:
;
        MOVB    #'o,(R0)+       ; +
        TSTB    (R1)            ;
        BEQ     10$             ;
        MOVB    #'n,(R0)+       ;
        MOVB    #' ,(R0)+       ;
        RETURN
10$:
        MOVB    #'f,(R0)+       ;
        MOVB    #'f,(R0)+       ;
        RETURN                  ; -

        .ENDC   ;STATUS

    .SBTTL    MCE - PRICMD -- Print Cmd buffer and put pointer to end of queue
;
PRICMD:
        MOV     #TRNB+F.1ST, FIFPTR
                                ; Point to Translationbuffer
        INCB    PRIFLG          ; Flag Tarnslationbuffer print-out
        BR      PRIXXX          ; => PRIXXX
;
;
    .SBTTL    MCE - PRIFIF -- Print FIFO and put pointer to end of queue
;
PRIFIF:
        MOV     #FIFO+F.1ST,FIFPTR
                                ; Point to FIFO
PRIXXX:
        CALL    CLRSCR          ; Clear screen
        BCC     20$             ;  Cleared : => 20$
10$:
        CALL    IOCRLF          ; Blank line
20$:
        MOV     @FIFPTR,FIFPTR  ; Next PTR
        BEQ     30$             ;  Done : => 30$
        CALL    GETFIF          ; Display
        BR      10$             ; => 10$
30$:
        CLRB    PRIFLG          ; Flag commandbuffer print-out
        CALL    IOCRLF          ; Blank line
        CALL    CLRBUF          ; Clear edit buffer (FIFPTR already cleared)

        .IF DF  STATUS

        CALL    DISPLY          ;  and display prompt
        CALLR   PRISTA          ; Print status line

        .IFF    ;STATUS

        CALLR   DISPLY          ;  and display prompt

        .IFT    ;STATUS

        .SBTTL  MCE - PRISTA -- Print the status line
;
PRISTA:
        MOV     #STATX1,ADR     ; Print
        MOV     #STALN1,LEN     ;   The
        BR      PRIST2          ; Statusline
PRIST1:
        MOV     #STATX2,ADR     ; Print
        MOV     #STALN2,LEN     ;   The
        BR      PRIST2          ;     status line
PRIST2:
        CALL    STAFIL          ; Fill status record
        TSTB    STAFLG          ; Statusline wanted ?
        BEQ     10$             ;  No : => 10$
        CALLR   IOW             ;     Statusline
10$:
        RETURN                  ;

        .ENDC   ;STATUS

        .SBTTL  MCE - RECCMD -- Recall command from FIFO
;
; Recall Command from FIFO by key
;
RECCMD:
        CLR     -(SP)           ; Room for Pointer to FIFO entry
        MOVB    FIFPOI,R5       ; R5 = FIFO entry number
        MOV     FIFO+F.1ST,R4   ; R4 => Oldest Entry in FIFO
        BEQ     50$             ;  Empty : => 50$
        MOVB    #1,R5           ; Start above oldest
        TST     FIFPTR          ; Old pointer ?
        BNE     20$             ;  Defined : => 20$
        MOV     #CMDBUF,R1      ; R1 => Source Buffer
        MOV     #RCLBUF,R3      ; R3 => Destination Buffer
        SUB     R1,R2           ; R2 =  Length
        BLE     20$             ;  Zero : => 20$
10$:
;
; Store single char into Recall buffer
;
        MOVB    (R1)+,R0        ; R0 = next char
        CALL    CNVUPC          ; Convert
        MOVB    R0,(R3)+        ; Store char
        SOB     R2,10$          ; Next
        CLRB    (R3)            ; EOL
20$:
;
; Check next entry in FIFO
;
        MOV     #RCLBUF,R1      ; R1 => Source to Compare
        TSTB    (R1)            ; Search mask defined ?
        BEQ     50$             ;  No : => 50$
        MOV     R4,R3           ; R3 => Entry
        ADD     #FI.TXT,R3      ; R3 => Text of entry
30$:
        MOVB    (R3)+,R0        ; R0 = Next char
        BEQ     40$             ;  EOL : => 40$
        CALL    CNVUPC          ; Convert to uppercase
        CMPB    R0,(R1)+        ; Compare with source
        BNE     40$             ;  No match : => 40$
        TSTB    (R1)            ; EOL ?
        BNE     30$             ;  No : => 30$, Try next char
        MOV     R4,(SP)         ; Source exhausted - match found
        MOVB    R5,FIFPOI       ; Store FIFO entry number
40$:
        INCB    R5              ; One newer
        MOV     FI.NXT(R4),R4   ; R4 => Next entry
        BEQ     50$             ;  No more : => 50$
        CMP     R4,FIFPTR       ; Continue search ?
        BNE     20$             ;  Yes : => 20$
50$:
        MOV     (SP)+,FIFPTR    ; Pop Pointer to entry if any
        BNE     60$             ; Any pointer ? => 60$
        CLRB    FIFPOI          ;
60$:
        CALL    GETFIF          ; Load from FIFO (or delete CMDBUF buffer)
        RETURN                  ;

        .SBTTL  MCE - REPLHT -- Replace TABs
;
REPLHT:
;
        MOV     #CMDBUF,R0      ; R0 => CMDBUF
        MOV     LEN,R2          ; Length
        BEQ     30$             ;  Empty ? Yes : => 30$
10$:
        CMPB    (R0)+,#HT       ; TAB ?
        BNE     20$             ;  No : => 20$
        MOVB    #BLNK,-1(R0)    ; Replace by space
20$:
        SOB     R2,10$          ;
30$:
        RETURN                  ;
;
;
        .SBTTL    MCE - SPBACK -- Backspace 1 char.
;
SPBACK:
        CMP     R1,#CMDBUF      ; At begin of buffer ?
        BLOS    10$             ;  Yes : => 10$
        MOV     #BS,ADR         ; Write
        MOV     #1,LEN          ;    a
        CALL    IOW             ;       backspace
        DEC     R1              ; Shift cursor
        RETURN                  ;
10$:
        SEC                     ; Indicate cursur error
        RETURN                  ;
;
;
        .SBTTL    MCE - SRWORD -- Search for word
;
SRWORD:
        CMPB    R0,#'0          ; Digit ?
        BLO     10$             ;  No  : => 10$
        CMPB    R0,#'9          ; Digit ?
        BLO     20$             ;  Yes : => 20$
        CMPB    R0,#'_          ; Special char ?
        BEQ     20$             ;  Yes : => 20$
        BIC     #40,R0          ; Convert to uppercase
        CMPB    R0,#'A          ; Alphabetical ?
        BLO     10$             ;  No  : => 10$
        CMPB    R0,#'Z          ; Alphabetical ?
        BLOS    20$             ;  Yes : => 20$
10$:
        SEC                     ;
        RETURN
20$:
        CLC                     ;
        RETURN

        .IF DF  STATUS

;
        .SBTTL  MCE - STAFIL -- Fill status line
;
STAFIL:
;
        MOV     R1,-(SP)        ; Save R1
        MOV     R2,-(SP)        ; Save R2
        MOV     #STALIR,R0      ; +
        TSTB    RNGFLG          ;
        BEQ     10$             ;
        MOVB    #'r,(R0)+       ;
        MOVB    #'i,(R0)+       ;
        MOVB    #'n,(R0)+       ;
        MOVB    #'g,(R0)+       ;   Ring or List
        BR      20$             ;
10$:
        MOVB    #'l,(R0)+       ;
        MOVB    #'i,(R0)+       ;
        MOVB    #'s,(R0)+       ;
        MOVB    #'t,(R0)+       ; -
20$:
        TSTB    (R0)+           ; +
        MOV     MAXF,R1         ;   Maxfif
        CALL    CONV            ; -
        TSTB    (R0)+           ; +
        MOVB    FIFCNT,R1       ;   Fifcnt
        CALL    CONV            ; -
        TSTB    (R0)+           ; +
        MOVB    FIFPOI,R1       ;   Fifpoi
        CALL    CONV            ; -
        MOV     #STACMD,R0      ; +
        MOV     MINC,R1         ;   Minchr
        CALL    CONV            ; -

        .IF DF  EDT

        MOV     #STAKEY,R0      ; +
        MOV     #EDTFLG,R1      ;   Keypad
        CALL    OFFON           ; -

        .ENDC   ;EDT

        MOV     #STASVI,R0      ; +
        MOV     #SINFLG,R1      ;   Save internals
        CALL    OFFON           ; -
        MOV     #STASVR,R0      ; +
        MOV     #SOLFLG,R1      ;   Save old
        CALL    OFFON           ; -

        .IF DF  TMOTIM

        MOV     #STATMO,R0      ; +
        MOVB    TMOCNT,R1       ;    Time-out count
        MOV     #15012,R2       ;
        CALL    $CBTA           ; -

        .ENDC   ;TMOTIM

        MOV     (SP)+,R2        ; Restore R2
        MOV     (SP)+,R1        ; Restore R1
        RETURN                  ;

        .ENDC   ;STATUS

;
        .SBTTL  MCE - STORE  -- Append string with descriptor (R1) to CMDBUF
;
STORE:
;
;
        MOV     PX.LEN(R1),R5   ; R5 = Length
        BEQ     30$             ;  Empty : => 30$
        MOV     PX.ADR(R1),R1   ; R1 = Source Addr
10$:
        CMP     R2,#CMDEND      ; In range ?
        BLO     20$             ;  Yes : => 160
        DECB    OVMSG           ; Mark for Ovflw
        RETURN                  ;
20$:
        MOVB    (R1)+,(R2)+     ; Copy
        SOB     R5,10$          ;  characters
30$:
        RETURN
;
;
        .SBTTL  MCE - SUBST  -- Check and substitute if necessary
SUBST:
;
; Substitute Pn's
;
        JSR     R5,.SAVR1       ; Save Regs
        CMPB    (R1)+,#'P       ; Check next symbol
        BNE     10$             ;  No match : => 10$
        MOVB    (R1)+,R3        ; Get Parameter number
        SUB     #'0,R3          ; Decode
        BLE     10$             ;  Illegal : => 10$
        CMP     R3,#8.          ; In range ?
        BHI     10$             ;  No : => 10$
        CMPB    (R1)+,R0        ; Endmark ?
        BEQ     20$             ;  Yes : => 20$
10$:
        CLC                     ; Tell no substitution
        RETURN                  ;
20$:
;
; Substitution string found
;
        MOV     R1,2(SP)        ; Set up R1 after return
        ASL     R3              ; Param num
        ASL     R3              ;        times 4
        ADD     #PDSC,R3        ; R3 => Descriptor
        MOV     R3,R1           ;
        CALL    STORE           ; Load it
        MOV     R2,2*2(SP)      ; Load R2 after return
        DECB    CFETCH          ; Mark that parameter fetched
        SEC                     ; Tell substituted
        RETURN                  ;
;
;
        .SBTTL  MCE - SUPRES -- Suppress leading blanks
;
SUPRES:
;
        MOV     #CMDBUF,R0      ; R0 => CMDBUF
;
        .SBTTL  MCE - SUPRR0 -- Suppress leading blanks ( Start at R0 )
;
SUPRR0:
;
        TST     LEN             ; Empty ?
        BEQ     20$             ;  Yes : => 20$
10$:
        CMPB    (R0),#BLNK      ; Start with a Space ?
        BNE     30$             ;  No : => 30$
        INC     R0              ; Next := First
        DEC     LEN             ; One less
        BNE     10$             ; Not Empty : => 10$
20$:
        SEC                     ; Return
        RETURN                  ;
30$:
        CLC                     ; Success
        RETURN                  ;
;
;
        .SBTTL  MCE - TERM   -- Get terminal information
;
TERM:
        MOV     #SFGMCB,ADR     ; GMC Buffer
        MOV     #SFGMCL,LEN     ; GMC Bufferlength
        MOV     #SF.GMC,CODE    ; GMC Code

        .IF DF  STATUS

        CALL    IO              ; Do it
        TSTB    ANI+1           ; ANSI Terminal
        BNE     10$             ;  Yes : => 10$
        CLRB    STAFLG          ; No statusline possible
10$:
        RETURN                  ;

        .IFF    ;STATUS

        CALLR   IO              ; Do it

        .ENDC   ;STATUS

        .IF DF  TMOTIM

        .SBTTL  MCE - TIMAST -- TI: Time-out AST
;
; On timeout - log off (TT0: just exit)
;
TIMAST:
        TST     (SP)+           ;; Restore stack
        DECB    TMOCNT          ;; Timeout ?
        BLT     10$             ;; Should not have decremented
        BNE     20$             ;; Not yet
;
; Timed out - kill pending read
;
        MOV     #IO.KIL,CODE    ;; Kill
        CALL    IO              ;;    pending read
10$:
        CLRB    TMOCNT          ;;
20$:

        .IF DF  STATUS

        CALL    STAFIL          ;; Fill statusline
        TSTB    STAFLG          ;; Statusline wanted ?
        BEQ     30$             ;;  No : => 30$
        QIOW$S  #IO.WVB,#TI,#EFNAST,,,,<#STATX2,#STALN2,#0>
30$:

        .ENDC   ;STATUS

        CALL    MARK            ;; Mark time
        ASTX$S                  ;; Exit ast

        .ENDC   ;TMOTIM

;
;
        .SBTTL  MCE - UPDATE -- Update commandline
;
; Write from current Position to End of Line and reposition Cursor
;
UPDATE:
        MOV     R1,ADR          ; Address of Cursor
        MOV     R2,LEN          ; R2 => EOL
        SUB     R1,LEN          ; Length
        BEQ     10$             ;  Zero : => 10$
        CALL    IOW             ; Write rest of line
        MOV     #BS,ADR         ; Address backspaces
        CALLR   IO              ; Reposition Cursor
10$:
        RETURN                  ;

        .IF DF  EDT
;
        .SBTTL  MCE - WRISEL -- Write selective range
;
WRISEL:
;
;    | B U F F E R . . . . . . . . . . |clrlin|
;    ^                 ^      ^         ^      ^
;   ADR               R3     R4        R2     R0
;                    start   end
;                                      |      |
; LEN = length of buffer --------------+------+
;
        TSTB    ANI+1           ; Ansi Screen ?
        BEQ     10$             ;  No : => 10$
        MOV     LEN,-(SP)       ; Save length
        MOV     R3,LEN          ; Calculate
        SUB     ADR,LEN         ;    length to start of range
        SUB     LEN,(SP)        ; Update restlength
        CALL    IOW             ; Write
;
        MOV     #INV,ADR        ; Addres of inv esc seq.
        MOV     #INVL,LEN       ; Length
        CALL    IOW             ;
;
        MOV     R3,ADR          ; Address of range
        MOV     R4,LEN          ; Calculate
        SUB     R3,LEN          ;  length of range
        SUB     LEN,(SP)        ; Update restlength
        CALL    IOW             ;
;
        MOV     #NOR,ADR        ; Addres of inv esc seq.
        MOV     #NORL,LEN       ; Length
        CALL    IOW             ;
;
        MOV     R4,ADR          ; Address of rest
        MOV     (SP)+,LEN       ; Rest length
10$:
        RETURN                  ;

        .ENDC   ;EDT

        .END    START

============================ MCEINI.MCR =====================================

;
; MCEINI.MCR
; File for defining command(abbrevation)s for MCE V4.22a, CLI MCR
;
; Setting Up MCE
;
MCE KEYP ON
MCE STAT OFF
;
; Command Definitions
;
DEL := PIP 'P1'/SD
DELE := PIP 'P1'/LD/DE
E := EDT 'P1',SYS$LOGIN:EDTCOM.EDT
GDCL := MCE REPL SYS$LOGIN:MCEINI.DCL
GMCR := MCE REPL SYS$LOGIN:MCEINI.MCR
HM*CE := HELP /MCE 'P1'
LO*GOUT := BYE
SDCL := SET /DCL=TI:
SMCR := SET /MCR=TI:
SP*ACE := PIP 'P1'/FU
UIC := SET DEF 'P1'
USER := SHOW USER
WHO := SHOW DEFAULT

=================================== MCEINI.DCL ===============================

; MCEINI.CMD
; File for defining command(abbrevation)s for MCE V4.22a
;
; Setting up MCE
;
MCE KEYP ON
MCE STAT OFF
;
; Command Definitions
;
DEL    := DELETE 'P1'/CONF
DELE   := DELETE 'P1'/LO
E*DT   := EDIT/EDT/COMMAND=SYS$LOGIN:EDTCOM.EDT 'P1' 'P2' 'P3'
GDCL   := MCE REPL SYS$LOGIN:MCEINI.DCL
GMCR   := MCE REPL SYS$LOGIN:MCEINI.MCR
HM*CE  := HELP /MCE 'P1'
SDCL   := SET /DCL=TI:
SMCR   := SET /MCR=TI:
SP*ACE := DIR 'P1'/FU
UIC    := SET DEF 'P1' & SHOW DEFAULT
USER   := SHOW USER
WHO    := SHOW DEFAULT