Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_1_19910112
-
6-1-exec/exechs.mac
There are no other files named exechs.mac in the archive.
;SRC:<6-1-EXEC>EXECHS.MAC.5, 18-Nov-85 11:05:57, Edit by KNIGHT
; Clean up CENUMB output
;SRC:<6-1-EXEC>EXECHS.MAC.4, 11-Nov-85 08:39:23, Edit by KNIGHT
; Never include / commands in history (edit moved from EXECSU)
;SRC:<6-1-EXEC>EXECHS.MAC.3, 7-Nov-85 16:32:38, Edit by KNIGHT
; Change prompt for current line
;SRC:<6-1-EXEC>EXECHS.MAC.2, 6-Nov-85 11:40:18, Edit by KNIGHT
; Make CENUMB type out command numbers the same as INFORMATION HISTORY
;[SU-SUSHI.ARPA]SHI:<6-1-EXEC>EXECHS.MAC.17, 15-Jul-85 16:43:30, Edit by BILLW
; change some "redo remembers" to "history"
; add STPOUT routine for typing STG style cursor control strings.
;<6-1-EXEC>EXECHS.MAC.15, 21-Jun-85 22:46:57, Edit by WHP4
; ^G acts like ^C in command editor at Stanford
;<6-1-EXEC>EXECHS.MAC.14, 18-May-85 17:44:43, Edit by FMF
; Don't smash needed pointers, be sure to call M.FIX after Meta-Rubout
;<6-1-EXEC>EXECHS.MAC.13, 18-May-85 17:34:50, Edit by FMF
; Fix bug where Meta-Rubout was looping forever (preserve D in call to CEBACK)
;<6-1-EXEC>EXECHS.MAC.12, 13-May-85 15:59:55, Edit by WHP4
; turn on PWSW so that we don't save passwords in history mech.
;<6-1-EXEC>EXECHS.MAC.11, 12-May-85 03:34:52, Edit by WHP4
;read jsys manual more carefully - +n, not -n in ac3 for SOUT in edit 10
;<6-1-EXEC>EXECHS.MAC.10, 12-May-85 03:24:15, Edit by WHP4
; need to print with SOUT to break on .STP when using strings from STG
;this should fix problem with DEL on AVT erasing screen, etc.
;<6-1-EXEC.CE>EXECHS.MAC.17, 3-May-85 23:53:07, Edit by FMF
;<6-1-EXEC.CE>EXECHS.MAC.16, 3-May-85 14:58:40, Edit by FMF
;<6-1-EXEC.CE>EXECHS.MAC.15, 3-May-85 14:55:26, Edit by FMF
; Another try at making METAR work right: be sure to count chars correctly
;<6-1-EXEC.CE>EXECHS.MAC.14, 3-May-85 14:22:18, Edit by FMF
; Make METAR's AOBJN pointer has a negative left half
; Decrement METAR's byte pointer after checking a character
;<6-1-EXEC.CE>EXECHS.MAC.13, 3-May-85 14:06:23, Edit by FMF
; Sigh, there was already a METAR0 (from METARB)
;<6-1-EXEC.CE>EXECHS.MAC.12, 3-May-85 14:02:20, Edit by FMF
;<6-1-EXEC.CE>EXECHS.MAC.11, 3-May-85 13:54:45, Edit by FMF
; M-S and M-R for search forward/backward for character
;<6-1-EXEC.CE>EXECHS.MAC.10, 23-Apr-85 19:04:11, Edit by WHP4
; sigh, put COMMAND-EDITOR subcommands table in alpha order
;<6-1-EXEC.CE>EXECHS.MAC.9, 23-Apr-85 18:51:30, Edit by WHP4
;<6-1-EXEC.CE>EXECHS.MAC.8, 23-Apr-85 18:14:07, Edit by WHP4
; add SET COMMAND-EDITOR EDIT-MODE, put back SOS mode
;<6-1-EXEC.CE>EXECHS.MAC.7, 10-Apr-85 17:15:13, Edit by WHP4
; fix capitalization, etc.
;<6-1-EXEC.CE>EXECHS.MAC.6, 29-Mar-85 20:35:38, Edit by WHP4
; change CALL FIELD to CALL FIELDX to follow changes elsewhere
;<6-EXEC>EXECHS.MAC.11, 5-Nov-84 01:33:23, Edit by ALMQUIST
; Use new Exectt module for terminal-type-dependent stuff so that this
; module is portable to other sites
; Fix bug in calculation of numeric arguments
; Make M-$ overwrite the current line
; Rewrite some CU fixes to M-$ that weren't quite right
;<6-EXEC>EXECHS.MAC.10, 11-Oct-84 21:26:43, Edit by ALMQUIST
; By default don't include references to PWDFLG, since Stanford Exec
; doesn't contain support for it anywhere else
; Fix (break?) Columbia-specific tty stuff so that this compiles at Stanford
; Copy ATICHR routine from Columbia so this will compile. This needs
; some sort of conditional to unbreak it at Columbia
;SNARK:<5.EXEC.US>EXECHS.MAC.9, 2-Mar-84 21:00:19, EMACSed by Sy.Bill
;CU146 Add VT102 tty
;SNARK:<5.EXEC.US>EXECHS.MAC.8, 24-Dec-83 00:00:26, EMACSed by Sy.Bill
;CU141 Add Viewpoint tty
;SNARK:<5.EXEC.US>EXECHS.MAC.6, 12-Oct-83 21:18:02, EMACSed by Sy.Bill
;CU135 Make REDO do WILDs in comparing the strings. Re-order FLDDBs
; so that CMCFM is before CMTXT. Reload function after confirm
; and do correct test for error.
;SNARK:<5.EXEC.US>EXECHS.MAC.5, 30-Sep-83 13:17:18, EMACSed by Sy.Bill
;CU133 Make sure we are NOINT when adding to history list.
;SNARK:<5.EXEC.US>EXECHS.MAC.4, 7-Sep-83 02:43:11, EMACSed by Sy.Bill
;CU129 Add Freedom-100 Terminal type
;SNARK:<5.EXEC.US>EXECHS.MAC.2, 17-Aug-83 00:39:39, EMACSed by Sy.Bill
;CU121 Don't expand % args when etypy'ing info history commands.
;SNARK:<5.EXEC.NEW>EXECHS.MAC.64, 30-Jun-83 04:12:16, EMACSed by Sy.Bill
;CU79 New help message for command editor.
;SNARK:<5.EXEC.NEW>EXECHS.MAC.61, 26-Jun-83 17:52:37, EMACSed by Sy.Bill
;CU79 Change "interrupt-character" to be "edit-character" a more
; mnemonic name. Fix problem with M-? causing zillions of weird
; things from happening, especially don't print two or three help
; messages.
;SNARK:<5.EXEC.NEW>EXECHS.MAC.60, 23-Jun-83 04:03:51, Edit by OC.CHRIS
;CU79 No funny M-ESC action if at left margin
;SNARK:<5.EXEC.NEW>EXECHS.MAC.59, 23-Jun-83 03:36:32, Edit by OC.CHRIS
;CU97 "Redefine (logical name) sys:" for editing logical name bodies
;SNARK:<5.EXEC.NEW>EXECHS.MAC.56, 22-Jun-83 12:31:40, EMACSed by Sy.Bill
;CU79 Make the editor work properly for terminals with parity set, don't
; read an extra CR in this case.
;SNARK:<5.EXEC.NEW>EXECHS.MAC.55, 18-Jun-83 10:03:17, EMACSed by Sy.Bill
;CU79 Don't make "/noedit" an invisible keyword
;<5.EXEC.NEW>EXECHS.MAC.52, 18-Jun-83 04:50:34, Edit by OC.CHRIS
;CU79 Change /noedit and /fast to /confirm and /noconfirm
;<5.EXEC.NEW>EXECHS.MAC.40, 14-Jun-83 18:01:00, Edit by OC.CHRIS
;CU79 REDO/FAST is like REDO/NOEDIT but doesn't require extra confirm
;<5.EXEC.NEW>EXECHS.MAC.37, 14-Jun-83 16:41:41, Edit by OC.CHRIS
;CU90 Canonical parsing for SET {NO} REDO INTERRUPT-CHARACTER
;SNARK:<5.EXEC.NEW>EXECHS.MAC.17, 13-Jun-83 20:18:21, EMACSed by Sy.Bill
;CU79 Change syntax to SET {NO} REDO instead of SET REDO {NO}.
; Repeat 0 SOS mode code.
; Remove SET REDO EDIT-MODE.
; Make SET NO REDO REMEMBERED (commands) disable interrupt char
; if present.
;SNARK:<5.EXEC.NEW>EXECHS.MAC.16, 10-Apr-83 18:16:42, EMACSed by Sy.Bill
;CU79 Fix problem in METESC when esc esc is typed when cursor is positioned
; on non-alphanumeric, the backword, forwardword stuff does not give
; the correct result. Try DIR (OF FILES)<esc><esc>.
;SNARK:<5.EXEC.NEW>EXECHS.MAC.6, 10-Apr-83 00:01:59, EMACSed by Sy.Bill
;CU79 New syntax:
; SET REDO {NO} REMEMBERS {n}
; SET REDO EDIT-MODE {EMACS | SOS}
; SET REDO INTERRUPT-CHARACTER
; INFORMATION PREVIOUS (COMMANDS) replaces HISTORY
;<PA0B.EXEC>EXECHS.MAC.3, 12-Mar-83 20:12:29, Edit by PA0B
;Parse EOL after "Redo -n"
;<PA0B.EXEC>EXECHS.MAC.2, 22-Feb-83 07:46:20, Edit by PA0B
;Turn on channel for editor interrupt character in C2CBUF, to allow
; "Redo /noedit ... CRLF ^Y"
;<PA0B.EXEC>EXECHS.MAC.1, 17-Jan-83 01:36:50, Edit by PA0B
;Created...The change number PA048 is used to denote changes I had to
;make to the UTEXAS code. The things I did were:
;
; - Rename CEFLAG => CEMODE to be more mneumonic
; - Use a macro to define the TRVAR for the editor (so I don't have
; to remember to change multiple TRVAR's)
; - Use SAVCMD instead of CSAVE
; - Rename CETSAV to CETBUF, and make it be a synonym for BUF0
; - Make CEBPTR a TRVAR, and ignore its use in the UTEXAS code as a
; flag like our LINSVD
; - Use HSTLST in place of references to CE1ST and CELAST
; - Use CMDNUM in place of CECNT - 1
; - Hack so that positive command numbers are absolute command numbers
; and negative ones are relative command numbers (UTEXAS code treated
; positive numbers as relative and didn't allow absolute
;
;----------------------------------------------------------------------
;
; New module for the command history stuff.
;
; Copyright (C) 1983, 1984 by Philip Almquist
; All rights reserved
;
; This module has been created to centralize the expanding mass
; of command history stuff in Clexec. Some of what appears here has
; been moved from other modules (mostly Execsu), and the editor and
; related stuff are new. The editor is based on the UTEXAS-20 editor
; by Billy Brown (which in turn claims to be based on the "Yale Exec
; Command Editor" by ???). The editor has been modified by Vince
; Fuller, Mike Blackwell, and myself. C2CBUF is a stripped down version
; of a routine used by Chris Ryland's command macro facility. The rest
; of the code is mine.
SEARCH EXECDE ;Get standard definitions, do TITLE,
TTITLE EXECHS ; get access to global symbols, etc.
IFNDEF CUSW,<CUSW==0> ;Assume not Columbia
IFN CUSW,<PWSW==1> ;If Columbia, include PWDFLG code
IFN STANSW,<PWSW==1> ;If Stanford, include PWDFLG code
IFNDEF PWSW,<PWSW==0> ;Assume no PWDFLG code
;PA048 Define storage used by command editor:
DEFINE CEDSTG,<
TRVAR <CADLFG,CEDUMB,CABKFG,CELPOS,CECPOS,CELPTR,CEBPTR,EDITFL,CETTMD,CEORIG>
>
CETBUF==BUF0 ;Command editor uses BUF0 as temp buffer
CETBSZ==1000 ;Size of buffer
;Special AC usage:
;
; Inside the editor, P3 is used as a global repeat count for
; commands.
; The command history is stored as a doubly-linked list of strings.
; Pointers to the head and tail of the list are stored in the Exec variable
; HSTLST. Storage is allocated dynamically in the Exec's permanant (XDICT)
; free pool. HSTLST is described in more detail later.
;
; The number of commands stored is controlled by the variable
; HISTSW, which contains an integer which is the number of commands to
; store (or zero if the command history facility is disabled). HISTSW
; is initialized by INITHS and can be changed via the "Set history n"
; and "Set no history" commands.
;
; HSTCNT contains an integer which is the number of commands
; actually stored. It may be less than HISTSW if not enough commands
; have been given to fill up the history. HSTCNT is used to determine
; when it is necessary to discard a command when adding a command to
; the history, and also to determine which direction to move around the
; list from the header for maximum efficiency in accessing a stored
; command.
;
; The variable CMDNUM is used to number the stored commands. It
; increases monotonically every time a command is issued (irregardless
; of whether the command history facility is enabled). The only exception
; to that rule is that commands containing passwords are not counted, but
; there are currently no commands at CMU that take a password as part of
; the first line of the command (at other places, "Login" and maybe a few
; others do). The reason for the bit about the commands with passwords is
; that the current command numbering scheme requires us to store every
; command that we number (since absolute numbers are converted to relative
; numbers). That could, of course, be changed.
;
; The last paragraph hinted that some things are not stored in the
; history. That is indeed correct. In particular:
;
; - Nothing is stored while HISTSW is equal to zero (ie, command history
; is disabled) even though CMDNUM is still incremented)
; - As stated above, any command line containing a password is not stored
; - Only the first line of a command is stored (ie, no subcommands).
; - Commands which are done inside of Take files or are DOCOMMAND'd by
; PCL commands are not stored.
;
; CMDNUM is not incremented for subcommands or for commands done in Take
; files or by DOCOMMAND in Pcl commands.
;
; The format of HSTLST is:
;
; tail (oldest record) pointer,,head (newest record) pointer
;
; The format of a history list entry is:
;
; +0/ previous pointer (or 0),,next pointer (or 0)
; +1/ size (in words) of the record
; +2/ command string (ASCIZ)
; +3/ .
; .
; +n/ .
;
; (These should probably be done with DEFSTR's someday...)
;Routine to initialize the command history system
;
INITHS::
SETZM HSTLST ;No entries in history list yet
SETZM HSTCNT ;Count of saved commands is zero
SETZM CMDNUM ;Current command is serial number 0
SETZM HISTSW ;Default to no history (for now)
SETZM CEMODE ;Default editing mode is Emacs
SETOM CEPSIC ;No interrupt character
SETZM CEMETA ;Assume no meta key
RET
;"History" - prints command history
.HISTO::NOISE <of commands>
MOVEI B,[FLDDB. .CMKEY,,$HISTO,,<all-recorded>,[
FLDDB. .CMNUM,CM%SDH,^D10,<Number of commands to print>,,]]
CALL FLDSKP ;Find out how many
ERROR <Length of history not specified>
CONFIRM
SKIPN HISTSW ;Is history stuff enabled?
ERROR <Command history facility is not enabled>
SKIPN HSTCNT ;Is there anything to print?
ERROR <No commands stored>
LDB D,[331100,,(C)] ;Good parse, see what got typed
CAIN D,.CMKEY ;All?
MOVE B,HSTCNT ;Yes, get number of entries
CAMLE B,HSTCNT ;Requested more than we have?
IFNSK. ;Yes
ETYPE <%%Insufficient history stored> ;CU79
ETYPE < - partial listing will be printed%_>
MOVE B,HSTCNT ;Print this many
ENDIF.
SKIPG B ;Request more than 0?
ERROR <Requested history length must be greater than 0>
MOVE A,HSTLST ;Get list header
MOVE D,CMDNUM ;Get the current command number
HSTLOP: HRROI C,2(A) ;Get address of string
CALL CENUMX ;Output command number
ETYPE <%3M%%_> ;CU121 Type the command
MOVE A,(A) ;Get next command
SOS D ;Decrement the command number
SOSLE B ;Done?
JRST HSTLOP ;No, do another
JRST CMDIN4 ;Yep, return to main command loop
$HISTO: TABLE
IFN CUSW,<
T all-recorded,,0
>;IFN CUSW
IFE CUSW,<
T ALL-RECORDED,,0
>;IFE CUSW
TEND
;"Redo" - re-executes a command from the history
$REDO: TABLE
IFN CUSW,<
T confirm,,0 ;CU79
T edit,,777777 ;(halfword -1)
IT fast,,1 ;CU79 1 means no edit and no extra confirm
T noconfirm,,1 ;CU79
T noedit,,0 ;CU79
>;IFN CUSW
IFE CUSW,<
T CONFIRM,,0
T EDIT,,777777 ;(halfword -1)
T NOCONFIRM,,1
IT NOEDIT,,0
>;IFE CUSW
TEND
.REDO:: CEDSTG ;Declare TRVAR's
NOISE <a previous command>
SETOM LINSVD ;Say already saved (so "Redo" commands are
; never saved)
SETOM CELPOS ;Default to relative command -1 (ie, most
; recent command)
MOVE B,REDOFL ;Get "Redo" defaults
MOVEM B,EDITFL ;Default whether or not to use editor
MOVEI B,[FLDDB. .CMSWI,,$REDO,,,[
FLDDB. .CMNUM,CM%SDH,^D10,<Absolute command number (positive)
or Relative command number (negative)>,,[
FLDDB. .CMCFM,CM%SDH,,,,[
FLDDB. .CMTXT,CM%SDH,,<Prefix of previous command (wildcards allowed)
or Confirm to reexecute the previous command>,,]]]]
CALL FLDSKP
CMERRX
LDB D,[331100,,(C)] ;Good parse, see what got typed
CAIE D,.CMSWI ;Switch?
JRST REDO0 ;No, go on
CALL GETKEY ;Get which one
HRREM P3,EDITFL ;Remember which switch we saw
MOVEI B,[FLDDB. .CMNUM,CM%SDH,^D10,<Absolute command number (positive)
or Relative command number (negative)>,,[
FLDDB. .CMCFM,CM%SDH,,,,[
FLDDB. .CMTXT,CM%SDH,,<Prefix of previous command (wildcards allowed)
or Confirm to reexecute the previous command>,,]]]
CALL FLDSKP
CMERRX
LOAD D,CM%FNC,.CMFNP(C) ;Good parse, see what got typed
REDO0: CAIN D,.CMTXT ;String?
JRST RDSRCH ;Yes, go handle it
CAIE D,.CMNUM ;Number?
JRST REDO2 ;No, better be confirmation
SKIPGE B ;Absolute command number given?
JRST REDO1 ;No, relative. Go confirm
SUB B,CMDNUM ;Yes, convert to relative
SOS B ;... (because current is relative -1)
REDO1: MOVEM B,CELPOS ;Store it
MOVEI B,[FLDDB. .CMCFM] ;Confirm the command
CALL FLDSKP ;...
CMERRX
MOVEI D,.CMCFM ;CU135 we just parsed a confirm....
REDO2: CAIE D,.CMCFM ;CU135 Confirm?
ERROR <Not confirmed>
SKIPN HISTSW ;Is history stuff enabled?
ERROR <Command history facility is not enabled>
SKIPL CELPOS ;Relative command number .gt. 0?
JRST CN2BGE ;Yes, user must have given an absolute number
; that was too big. Complain
MOVN A,CELPOS ;Get -(relative command number)
CAMLE A,HSTCNT ;Have enough history?
ERROR <The command history does not go back that far>
MOVE B,CELPOS ;Get back the relative command number
ADD B,CMDNUM ;Convert to absolute command number
AOS B ;...
EXCH B,CELPOS ;CELPOS needs absolute command number
LSH A,1 ;Multiply relative command number by 2
CAMLE A,HSTCNT ;Closer to the tail or the head of the history?
JRST REDO4 ;Closer to the tail
;Closer to head, fall thru...
;Here to run down the list starting at the head of the list. B contains
;the relative command number of the desired command:
HRRZ A,HSTLST ;Get pointer to list of stored commands
REDO3: AOSL B ;Found right command yet?
JRST REDO6 ;Yes
HRRZ A,(A) ;No, get next one
SKIPE A ;Internal error?
JRST REDO3 ;No, loop again
ERROR<Internal error in REDO3 - ran off end of list>
;Here to run down the list starting from the tail. Virtually identical
;to the above code, but sufficiently different that it would be hard to
;to merge the two cases:
REDO4: ADD B,HSTCNT ;Make B contain number of links away from
AOS B ; tail (when we get here it contains - the
; number away from the head of the list)
HLRZ A,HSTLST ;Get pointer to list tail
REDO5: SOSG B ;Found right command yet?
JRST REDO6 ;Yes
HLRZ A,(A) ;No, get next one
SKIPE A ;Check internal consistency
JRST REDO5 ;Ok, loop again
ERROR<Internal error in REDO5 - attempt to run off beginning of list>
;Here when we are supposed to match a given string:
RDSRCH: CONFIRM ;Confirm the command
SKIPN HISTSW ;Is history stuff enabled?
ERROR <Command history facility is not enabled>
REPEAT 0,< ;CU135
MOVE A,[POINT 7,ATMBUF] ;Get pointer to atom buffer
MOVE B,A ;Copy the pointer
DO. ;Compress out whitespace, raise lowercase
ILDB C,A ;Get a character
CAIL C,"a" ;Lowercase?
CAILE C,"z" ;...
TRNA ;No
SUBI C,40 ;Yes, raise it
CAIE C,.CHSPC ;Space
CAIN .CHTAB ; or tab?
LOOP. ;Yes, do next character
IDPB C,B ;No, significant, so keep it
JUMPE C,ENDLP. ;We're done if null
LOOP. ;Otherwise, go around again
OD.
>;CU135 END REPEAT 0
;CU135 Begin addition
; Scan the atom buffer to make sure it doesn't end with a "%". As
; long as it doesn't, add a "*".
MOVE A,[POINT 7,ATMBUF] ; point to the atom buffer
ILDB B,A ; get a char
JUMPN B,.-1 ; and loop until we hit the null
SETOM B ; backup by one
ADJBP B,A ; ...
LDB C,B ; get the character before the null
CAIE C,"%" ; all done if it is a special character
CAIN C,"*" ; already....
IFSKP. ; No, proceed to tie it off
MOVEI C,"*" ; with a star to match
DPB C,A ; the rest of the string
SETZM C ; and finally tie it
IDPB C,A ; off with a null
ENDIF.
;CU135 End addition
MOVE A,CMDNUM ;Get current command number
MOVEM A,CELPOS ;Save it
HRRZ C,HSTLST ;CU135 Get pointer to head of history list
MOVEM C,CELPTR ;CU135 Save it, too
SEALOP: ADDI C,2 ;CU135 Get pointer to text of history entry
HRLI C,440700 ;CU135 ...
MOVE B,[POINT 7,ATMBUF] ;Get pointer to atom buffer
MOVX A,.WLSTR ;CU135 function is wild match
WILD%
ERJMP [ERROR <WILD failed in SEALOP>]
JUMPE A,SESUCC ;CU135 a match, success!
REPEAT 0,< ;CU135
SEALO2: ILDB C,A ;Get a character from the history entry
CAIL C,"a" ;Lowercase?
CAILE C,"z" ;...
TRNA ;No
SUBI C,40 ;Yes, raise it
CAIE C,.CHSPC ;Space
CAIN C,.CHTAB ; or tab?
JRST SEALO2 ;Yes, get another character
ILDB D,B ;Get a character from the atom buffer
JUMPE D,SESUCC ;If null from atom buffer we're done
CAMN C,D ;Characters match?
JRST SEALO2 ;Yes, keep checking
>;CU135 END REPEAT 0
SOS CELPOS ;No, try next command. Decrement command
; number
HRRZ C,@CELPTR ;CU135 Get next history entry
MOVEM C,CELPTR ;CU135 Save it
JUMPN C,SEALOP ;CU135 If haven't fallen off end of list,
; go try this entry
ERROR <Unable to find a saved command with that prefix>
SESUCC: MOVE A,CELPTR ;Get address of winning entry
JRST REDO6 ;Go do it
;Here when we've found what we're looking for. A contains the address of
;the history record:
REDO6: SKIPL EDITFL ;CU79 Want to edit?
IFSKP. ;CU79 Yes
MOVEM A,D ;Save address of history record
HRROI A,CBUF ;Get pointer to CBUF
HRROI B,2(D) ;Get pointer to text of command
SETZ C, ;Terminate on null
SOUT% ;Copy command into CBUF in case ^G typed
ERJMP .+1 ; to editor later
MOVE A,D ;Get address of history record for command
MOVE B,CELPOS ;Get absolute command number for the entry
SETZ C, ;Start editing at beginning of the line
CALL CEDITU ;Go edit it
ELSE. ;Else just go retrieve command
HRROI A,2(A) ;Get pointer to text of command
CALL FAKTYP ;Set up the command
ENDIF.
SETZM CIPF ;Say no command in progress so that command
; will be given its right name and (more
; importantly) it will get saved in the
; history
;CU79 since FAKTYP was called a prompt was not issued and the terminal
;CU79 interrupt will not be enabled, enable it now.
HRLZ A,CEPSIC ;CU79 Get interrupt character's code
HRRI A,CEPCHN ;CU79 Get the channel to use
SKIPL A ;CU79 CEPSIC contains -1 (ie, none)
ATI% ;CU79 No, so assign interrupt
JRST REPARS ;Go parse it
;Here if user gave absolute command number and number was too big:
CN2BGE: ERROR <Command number too large - you have not issued that many commands>
;CU79 Set redo remembers n
;"Set history (of commands with length) n"
.SHIST::NOISE <number of commands>
DECX <Number of commands to store in the command history>
CMERRX
CONFIRM
CAIGE B,0
ERROR <Length must be greater than or equal to zero>
MOVEM B,HISTSW ;Store the new length
CAIN B,0 ;Length zero?
JRST SNHIS2 ;Yes, treat as "Set no history"
SUB B,HSTCNT ;Yes, compute - number of elements to remove
; from the current history list
MOVNM B,Q1 ;Invert sign and store in a safe place
JRST SNHIS3 ;Join "Set no history" code
; Set no redo remember
.SNHIS::NOISE <commands>
CONFIRM
SETZM HISTSW ;Flag history stuff is disabled
SNHIS2: SETOM CEPSIC ;CU79 get rid of character first
MOVE Q1,HSTCNT ;Get number of history records we currently
; have saved (and prepare to nuke them)
SNHIS3: SKIPG Q1 ;More to remove?
JRST CMDIN4 ;No, we're done
CALL RMVHST ;Yes, remove one entry
SOJA Q1,SNHIS3 ; and loop
; Info redo
.INRED::NOISE (status)
CONFIRM
SKIPE A,HISTSW ; get number of remembered commands
IFSKP.
ETYPE < Set no history%_>
ELSE.
ETYPE < Set history %1Q% (commands)%_>
ENDIF.
SKIPL A,CEPSIC ; get character
IFSKP.
ETYPE < Set no redo edit-character%_>
ELSE.
ADDI A,"A"-.CHCNA ;CU90 Convert to printing representation
ETYPE < Set redo edit-character ^%1\%%_> ;CU90
ENDIF.
RET
;"Set default redo"
.SDRED::MOVEI B,[FLDDB. .CMSWI,,$REDO,,,]
CALL FLDSKP ;Parse a switch
CMERRX
CALL GETKEY ;Get the data word
CONFIRM ;Finish it off
HRREM P3,REDOFL ;Save the value
RET ;All done
;CU79 "Info default redo"
IFN CUSW,<
.IDRED::HRROI 1,[ASCIZ/confirm/] ;CU79 assume "noedit" is the default
SKIPGE REDOFL
HRROI 1,[ASCIZ/edit/] ;if EDITFL = -1, then it's "edit"
SKIPLE REDOFL
HRROI 1,[ASCIZ/noconfirm/] ;CU79 if EDITFL = 1, don't confirm
ETYPE < Set default redo /%1M%%_> ;type it out
RET
>;IFN CUSW,
IFE CUSW,<
.IDRED::HRROI 1,[ASCIZ/CONFIRM/] ;CU79 assume "noedit" is the default
SKIPGE REDOFL
HRROI 1,[ASCIZ/EDIT/] ;if EDITFL = -1, then it's "edit"
SKIPLE REDOFL
HRROI 1,[ASCIZ/NOCONFIRM/] ;CU79 if EDITFL = 1, don't confirm
ETYPE < SET DEFAULT REDO /%1M%%_> ;type it out
RET
>;IFE CUSW
;CU1 modify format
; Set redo
; Set no redo
.CEDIT::NOISE <option>
KEYWD $CEDIT
0
JRST CERR
JRST 0(P3)
$CEDIT: TABLE
IFN CUSW,<
T edit-character,,.SCEIC
IT interrupt-character,,.SCEIC
T remembers,,.SHIST ;CU79
>;IFN CUSW
IFE CUSW,<
T EDIT-MODE,,.SCEDM
T ENTERED-ON-CHARACTER,,.SCEIC
IT INTERRUPT-CHARACTER,,.SCEIC
>;IFE CUSW
TEND
.CEDNO::KEYWD $CEDNO
0
JRST CERR
JRST 0(P3)
$CEDNO: TABLE
IFN CUSW,<
T edit-character,,.SNCEI
IT interrupt-character,,.SNCEI
t remembered,,.snhist ;CU79
>;IFN CUSW
IFE CUSW,<
T ENTER-EDITOR-CHARACTER,,.SNCEI
IT INTERRUPT-CHARACTER,,.SNCEI
>;IFE CUSW
TEND
IFE CUSW,<
;SET COMMAND-EDITOR EDIT-MODE (TO)
.SCEDM: NOISE (TO)
KEYWD $CEMOD
0
JRST CERR ;parsing error
JRST (P3) ;dispatch to proper function
$CEMOD: TABLE
T EMACS,,.SCEMA
T SOS-ALTER-MODE,,.SCSOS
TEND
.SCEMA: CONFIRM
SETZM CEMODE ;EMACS Mode
RET
.SCSOS: CONFIRM
SETOM CEMODE ;SOS/EDIT Mode
RET
>;IFE CUSW
;CU79 Set Redo Interrupt-Character
;"Set command-editor interrupt-character (to) char" command
.SCEIC: NOISE (to)
STKVAR <ICHAR> ;CHARACTER TO INTERRUPT ON
CALL ATICHR ;CU90 parse a character for ATI%
ERROR <Invalid terminal interrupt character> ;CU90
MOVEM A,ICHAR ;CU90 save it
NOISE (enters command editor)
CONFIRM ;CONFIRM THE COMMAND
SKIPN HISTSW ;CU79 is history enabled?
ERROR <Not remembering any commands - use "set history" first>
HRLZ A,ICHAR ;GET THE NEW ONE
HLRZM A,CEPSIC ;SAVE IT
RET ;DONE
.SNCEI: NOISE (for command editor)
CONFIRM ;COMFIRM "SET NO INTERRUPT-CHARACTER"
SETOM CEPSIC ;SAY WE DON'T HAVE ONE
RET ;DONE
;CU90 Begin addition - single character parsing routines
; This break mask when used with .CMUQS allows all characters except special
; editing characters.
brkall: brini. 0,0,0,0 ; Initialize the mask
brkch. (0,177) ; Break on everything
unbrk. (.chspc) ; except white space
unbrk. (.chtab)
exp w0.,w1.,w2.,w3.
; At this point let me suggest that there be a user interface to the comnd
; routine which matches a specified number of characters. Or maybe just one
; that matches a single arbitrary character...
;xx defines a keyword table entry, but differs from T macro in that the
; data may be only 18 bits wide (saves a word)
define xx (key,value,flags) <
ifb <flags>,<xwd [asciz @key@],value>
ifnb <flags>,<xwd [exp flags!cm%fw, asciz @key@],value>
>
ctrlkw==.chdel+1 ; larger than any single character
; indicates "CONTROL" keyword.
chrtbl: TABLE
xx b,"b",cm%inv
xx break,.chnul
xx c,"c",cm%inv
xx control,ctrlkw ; allow CONTROL "A"
xx d,"d",cm%inv
xx delete,.chcrb
xx e,"e",cm%inv
xx escape,.chesc
xx n,"n",cm%inv
xx null,.chnul
xx s,"s",cm%inv
xx space,.chspc
xx ^,"^",cm%inv
xx ^A,.chcna
xx ^B,.chcnb
xx ^C,.chcnc
xx ^D,.chcnd
xx ^E,.chcne
xx ^F,.chcnf
xx ^G,.chbel
xx ^H,.chbsp
xx ^I,.chtab
xx ^J,.chlfd
xx ^K,.chvtb
xx ^L,.chffd
xx ^M,.chcrt
xx ^N,.chcnn
xx ^O,.chcno
xx ^P,.chcnp
xx ^Q,.chcnq
xx ^R,.chcnr
xx ^S,.chcns
xx ^T,.chcnt
xx ^U,.chcnu
xx ^V,.chcnv
xx ^W,.chcnw
xx ^X,.chcnx
xx ^Y,.chcny
xx ^Z,.chcnz
xx ^\,.chcbs
xx ^^,.chccf
xx ^_,.chcun
TEND
; More than just characters that can be ATI'ed, it also is a table
; of characters you would want to ATI. CR, LF, SPACE, ESCAPE, DELETE
; are not present for this reason.
atitbl: TABLE
xx break,.chnul
xx control,ctrlkw ; allow CONTROL "A"
xx null,.chnul
xx ^,"^",cm%inv
xx ^A,.chcna
xx ^B,.chcnb
xx ^D,.chcnd
xx ^E,.chcne
xx ^F,.chcnf
xx ^G,.chbel
xx ^H,.chbsp
xx ^I,.chtab
xx ^J,.chlfd
xx ^K,.chvtb
xx ^L,.chffd
xx ^P,.chcnp
xx ^Q,.chcnq
xx ^R,.chcnr
xx ^S,.chcns
xx ^U,.chcnu
xx ^V,.chcnv
xx ^W,.chcnw
xx ^X,.chcnx
xx ^Y,.chcny
xx ^Z,.chcnz
TEND
ctbmsk: brini. keyb0.,keyb1.,keyb2.,keyb3. ; same as keyword
unbrk. "^"
unbrk. "_"
unbrk. "\"
exp w0.,w1.,w2.,w3.
;ATICHR - parses a single character which is reasonable for ATI%
;
; Returns
; +1: failure
; +2: success with character code in A
;
; This routine could be expanded to allow SP and DEL, but these
; have non-intuitive terminal interrupt codes, and aren't very likely
; choices anyway.
;
atichr::movei a,[flddb. .cmqst,cm%sdh,,<quoted control character>,,[
fldbk. .cmkey,,atitbl,<single control character or>,,ctbmsk]]
call prsone ; read the character
ret ; oops, single character parse failed
caig a,.tices ; characters up through ESC are ATI-able
cain a,.ticcc ; ^C probably couldn't hurt, but disallow
ret
caie a,.ticct ; make sure it's not ^T
cain a,.ticco ; or ^O, since we don't want those turned off
ret ; it's one of those, so reject it
caie a,.ticcm ; these would probably make bad journal-
cain a,.ticcj ; toggle characters
ret
retskp ; return failure
; ONECHR - parses a single character multiple ways
;
; Returns +1 on parse error, +2 on success with char in A
;
onechr::movei a,[flddb. .cmqst,cm%sdh,,<quoted control character>,,[
fldbk. .cmkey,,chrtbl,<single character or>,,ctbmsk]]
callret prsone
; a/ flddb
prsone: acvar <thechr,thefld>
movem a,thefld ; save the flddb to parse with
move b,thefld ; get back the flddbs to parse
call fldskp ; try and parse that
ifnsk. (callret onesch) ; failed, try one single character
load c,cm%fnc,.cmfnp(c) ; get the function
cain c,.cmqst ; a quoted string?
callret oneqst ; yes, verify and return
hrrz a,(b) ; else keyword, get data
cain a,ctrlkw ; special "CONTROL" keyword?
callret oneckw ; yes, proceed with second part
retskp ; else simply a char, return it
; Here to parse one single character using a break mask
onesch: movei b,[flddb. .cmuqs,,brkall,<a single character>]
call fldskp ; parse it
ret ; can't happen (proof left as an exercise)
move b,sblock+.cmptr ; this is the evil delimiter
ildb a,b
caie a,.chtab ; a tab?
cain a,.chspc ; or space?
jrst onesch ; yes, skip it
cain a,.chlfd ; make sure they didn't type some sort
ret ; of EOL character
caie a,.chffd ; formfeed is sometimes EOL
cain a,.chcrt
ret ; return failure if that's it
setzm thechr ; initialize this short string
dpb a,[point 7,thechr,6] ; deposit its one character
movei b,[flddb. .cmtok,,<point 7,thechr>]
call fldskp ; parse it as a token
ret ; shouldn't happen
ldb a,[point 7,thechr,6] ; get the character back
retskp ; and return
; here, verify that the quoted string was only one character long
oneqst: move b,[point 7,atmbuf] ; get a pointer to the character
ildb a,b ; first char is it
ildb c,b ; next char should be null
jumpe c,rskp ; yes, so return now
caie a,"^" ; is it possible they said "^X"
ret ; no, return failure
move a,c ; copy the second character
cail a,"a" ; now check for lower case and
caile a,"z" ; fold to upper case
skipa ; not lower case
trz a,40 ; is lower case, so make it upper
subi a,"A"-.CHCNA ; controlify it for them
ildb c,b ; and now check for the null
jumpn c,r ; no... sigh, fail then
retskp ; else return with the controlified char.
; here on CONTROL keyword, parse a single character in quotes
oneckw: movei b,[flddb. .cmqst,cm%sdh,,
<character in double quotes, or a single character>]
call fldskp ; get a quoted string
ifskp. ; got it...
call oneqst ; make sure it is in correct form
error <Not a single quoted character>
else.
call onesch ; it is not, parse a single character
ret ; that didn't work... fail return
cail a,"a" ; now check for lower case and
caile a,"z" ; fold to upper case
skipa ; not lower case
trz a,40 ; is lower case, so make it upper
endif.
subi a,"A"-.CHCNA ; otherwise controlify it
skipge a ; check for proper control character
error <Can't CONTROLify that character>
retskp ; and return it
endav.
;CU90 End addition
;Routine to maybe make the current contents of CBUF be the most recent history
;entry. Does nothing unless the user is keeping a history and the command
;is a top-level command (ie, we are not inside a PCL or a TAKE file or
;doing subcommands). May remove the oldest command in the history list
;if the new addition would otherwise overflow the history list.
;
;Takes:
; HISTSW/ 0 if user doesn't want a history
; HSTCNT/ Number of elements in the history list already
; CBUF/ Command string to be saved (ASCIZ)
;Returns:
; +1/ always (prints warning or does not return on error)
;Outputs:
; HSTCNT/ incremented if no element was removed from the list
; history list (HSTLST)/ updated to include new element
;Clobbers:
; A
;
SAVHST::
;First decide whether we want to save the command in SCBUF. Note: if
;we decide not to save the command in SCBUF we assume we don't want to
;save it in the history. The command is saved in SCBUF if:
;
; - it does not contain any fields that were not echoed (ie, passwords)
; - it contains non-whitespace characters
; - it was input from .PRIIN (intended to weed out DOCOMMAND's and TAKE files)
IFN NICSW,<
; - it does not begin with a slash
>;IFN NICSW
;
IFN PWSW,<
SKIPE PWDFLG ;Password on this line?
JRST SAVDON ;Yes, don't save this command
>;IFN PWSW
IFN NICSW,<
LDB A,[POINT 7,CBUF,6] ;[NIC1017] GET FIRST CHARACTER IN COMMAND BUFFER
CAIN A,"/" ;[NIC1017] IS IT THE EDIT CHARACTER?
JRST SAVDON ;[NIC1017] YES, SO IGNORE THIS COMMAND
>;IFN NICSW
HRROI A,CBUF ;Get pointer to command
CALL CKREAL ;Is there really a command to save?
JRST SAVDON ;No, return now
MOVE A,CIJFN ;Get input JFN
CAIE A,.PRIIN ;From terminal?
JRST SAVDON ;No, don't save
MOVE A,[CBUF,,SCBUF] ;Yes, get set to copy CBUF into SCBUF
BLT A,SCBUFE ;Do the copy
;Here if we decided the command was good enough to be saved in SCBUF. We
;now make additional checks to see if it should also be saved in the
;command history:
;
; - The command must be a top-level command (ie not a subcommand)
; - It must not have already been saved in the history
; - We must not be in a PCL command and parsing after a PROMPT statement
; - The command history facility must be turned on
;
SKIPE LINSVD ;This command already saved in the history?
JRST SAVDON ;Yes, don't try to save it again (this is
; the test that prevents the saving of
; subcommands)
;;This test doesn't work to detect that we are parsing after a PROMPT
;;statement if no PARSE EOL was done before the PROMPT (if a PARSE EOL
;;was done, we probably take the JRST above). PCL should be fixed to
;;make PROMPT do an implicit PARSE EOL if necessary...
;; MOVE A,TAKLEN ;Get current pointer to TAKE JFNS
;; CAILE A,1 ;Top of command stack?
;; JRST SAVDON ;No, don't save inside TAKE's and PCL's
SKIPN HISTSW ;Keeping a history?
JRST [ AOS CMDNUM ;No, but record one more command done anyway
JRST SAVDON ] ;All done
;...
CALL PIOFF ;CU133 don't allow interrupts
CALL SVALWS ;CU133 collect command line
CALL PION ;CU133 allow interrupts again
RET ;CU133 all done
;Enter here by falling through from above or from the command editor.
;We will now save the command in the history come hell or high water
;(unless the Exec is out of permanent free space)
SVALWS: AOS CMDNUM ;Record one more command done
PUSH P,B ;Save the AC's we'll use
PUSH P,C ;...
PUSH P,D ;...
MOVE A,HSTCNT ;Get number of history entries
CAML A,HISTSW ;Have enough already?
CALL RMVHST ;Yes, remove one
HRROI A,CBUF ;Get address of the command
CALL MKHREC ;Make a history record for it
JRST [ETYPE<%@ %%Insufficient space for history entry - proceeding%_>
SOS CMDNUM ;Don't think we have commands that we don't
JRST SAVHDN] ;Skip it
CALL ADDHST ;Make it the most recent in the history list
SAVHDN: POP P,D ;Restore the AC's
POP P,C ;...
POP P,B ;...
SAVDON: SETOM LINSVD ;Don't try to save this line again
RET
;Routine to do the same as the above routine except that it is called from
;the error handling code. It null-terminates CBUF and is generally more
;paranoid about the state of the word that the above routine.
SAVEHS::
JRST SAVHST ;Do nothing special...
;Routine to check whether what is pointed to by an asciz string is
;substantive enough to be considered a real command. It determines this
;by looking to see whether there are any characters in the command which
;are not whitespace (currently spaces and tabs).
;
;Takes:
; A/ pointer to string (-1,,address ok)
;Returns:
; +1/ don't save it
; +2/ save it
;Clobbers:
; A
CKREAL: CALL FIXPT ;Make it a nice byte pointer
SAVEAC <B>
CKLOOP: ILDB B,A ;Load a character
SKIPN B ;Null?
RET ;Yep, nothing of substance found
CAIE B,.CHSPC ;Space?
CAIN B,.CHTAB ; or tab?
JRST CKLOOP ;Get another character
CAIE B,.CHCRT ;CR?
CAIN B,.CHLFD ; or LF?
JRST CKLOOP ;Get another character
RETSKP ;Found something, say to save the line
;Routine to create a new new history entry.
;Takes:
; A/ byte pointer to command to be added (ASCIZ string)
;Returns:
; +1/ error (probably insufficient space)
; +2/ success
;Outputs:
; A/ address of history record
;Clobbers:
; B,C,D
MKHREC: STKVAR <STRADR>
MOVEM A,STRADR ;Save address of string
CALL BCOUNT ;Find out how many words we need to save string
ADDI A,2 ;Add 2 words for overhead
MOVX B,XDICT ;Say we want permanent space
CALL GETMEM ;Allocate it
RET
MOVEM A,1(B) ;Save size of block (for later disposal)
HRRZ A,STRADR ;Get address of command
HRLI A,440700 ;Make it a byte pointer
PUSH P,B ;Save address of the record for a minute
MOVEI B,2(B) ;Get destination of string.
HRLI B,440700 ;Make it a byte pointer
MKHLOP: ILDB C,A ;Get a character from the command
SKIPN C ;If a null
JRST MKHLO3 ;We're done, remove trailing whitespace
IDPB C,B ;Otherwise put it into the history record
JRST MKHLOP ;Do next character
MKHLO2: SETO C, ;Say one byte
ADJBP C,B ;Back up the destination byte pointer 1 byte
MOVEM C,B ;Put the byte pointer back
MKHLO3: LDB C,B ;Get a byte
CAIE C,15 ;CR?
CAIN C,12 ; or LF?
JRST MKHLO2 ;Strip from the history
;; CAIE C,40 ;Space?
;; CAIN C,11 ; or tab?
;; JRST MKHLO2 ;Yes, back up some more
CAIE C,33 ;<ESC>?
CAIN C,6 ; or ^F?
JRST MKHLO2 ;Yes, recognition are nasty so we'll nuke them
CAIE C,"?" ;Question mark?
CAIN C,22 ; or ^R?
JRST MKHLO2 ;Yes, not quite as nasty but nuke them anyway
CAIE C,.CHFFD ;Formfeed?
;; CAIN C,"," ;Comma seems to cause trouble, too (why?)
TRNA ;;
JRST MKHLO2 ; so strip it off, too
SETZ C, ;Deposit a null at the end
IDPB C,B ; of the string
POP P,A ;Get back address of the record
RETSKP
;Add a new element as the most recent element in the history list.
;Takes:
; A/ address of history element
; HSTLST/ address of oldest (tail),,address of newest (head)
; HSTCNT/ number of history entries
;Returns:
; +1 always
;Outputs:
; HSTCNT/ incremented
; HSTLST/ unchanged,,address of new element
; (previous first element)/ address of new element,,unchanged
;Clobbers:
; A,B
ADDHST: AOS HSTCNT ;Bump count of commands in the history
HRRZ B,HSTLST ;Get address of newest history entry
HRRM A,HSTLST ;New element is now at the beginning of list
HRRZM B,(A) ;Old first is now next of new element, and
; new element has no previous
SKIPE B ;If the list wasn't empty
HRLM A,(B) ; then previous of old first is new first
SKIPN B ;Else (if it was empty)
HRLM A,HSTLST ; then new element is also new tail
RET
;RMVHST - Removes the oldest element from the history list.
;RMVFST - Removes the newest element from the history list.
;Takes:
; HSTLST/ address of oldest (tail),,address of newest (head)
; HSTCNT/ number of history entries
;Returns:
; +1 always (does not return if underflow)
;Outputs:
; HSTCNT/ decremented
; HSTLST/ address of new tail element,,unchanged
; (previous first element)/ address of new element,,unchanged
RMVFST: SAVEAC <Z> ;Don't let RETMEM clobber CTCLF1 before
; .CEPSI or CEDESC do PION
SKIPA A,[-1] ;Flag this is RMVFST
RMVHST: SETZ A, ;Flag this is RMVHST
SOSGE HSTCNT ;Underflow?
JRST RMVUFL ;Yes
SKIPE A ;Is this RMVHST?
IFSKP. ;Yes,
HLRZ B,HSTLST ; get address of oldest history entry
ELSE. ;No,
HRRZ B,HSTLST ; get address of newest history entry
ENDIF.
JUMPE B,RMVUFL ;Check for underflow
MOVE C,B ;Save address of element to nuke
SKIPE A ;Is this RMVFST?
SOS CMDNUM ;Yes, set to absolute command number of newest
; command still stored
SKIPG HSTCNT ;Removing last element?
JRST [ SETZM HSTLST ;Yes, indicate list empty
JRST RMVH2 ] ;Dispose of the removed element
SKIPE A ;Is this RMVHST?
IFSKP. ;Yes
HLRZ B,(B) ;Get address of new last element
HRLM B,HSTLST ;Make tail pointer point at it
HLLZS (B) ;Zero new last element's next pointer
ELSE. ;No (from RMVFST)
HRRZ B,(B) ;Get address of new first element
HRRM B,HSTLST ;Make head pointer point to it
HRRZS (B) ;Zero new first element's previous pointer
ENDIF.
RMVH2: MOVE A,1(C) ;Get size of the block
MOVE B,C ;Get address of the block
MOVX C,XDICT ;Return it to permanent storage
CALL RETMEM ;...
RET
;Here on underflow of history list.
RMVUFL: ERROR <Internal error in RMVHST: history list underflow>
;Routine which takes a string pointer and acts as if the user had typed
;it in. It types the prompt, sticks the command into CBUF, and echos the
;command. The command is not confirmed unless the string has a CRLF at the
;end.
;
;Takes:
; 1/ byte pointer to string (-1,,address is ok)
;Returns:
; +1 always
;Outputs:
; See description above
FAKTYP: STKVAR <<CCSAV,2>,LINPTR> ;Saved CCOC words, saved pointer to
; line to be FAKTYP'd
MOVEM A,LINPTR ;Save pointer to string
SETO B, ;Flag we want the prompt typed
CALL C2CBUF ;Put the command into it
SKIPG EDITFL ;CU79 Is this /fast?
IFSKP. ;CU79 Yes
SKIPG CESCHK ;CU79 And not doing funny M-$ stuff?
CALL ADDCFM ;CU79 Yes, make this command confirm itself
ENDIF. ;CU79
MOVE A,COJFN ;Get output designator
RFCOC% ;Read CCOC words
DMOVEM B,CCSAV ;Save them
TXZE C,3B19 ;Don't echo <Esc>
SFCOC% ;...
MOVE A,COJFN ;Echo to standard output
;CU79 MOVE B,LINPTR ;Get back command line
MOVE B,CMPTR ;CU79 Use csb pointer in case doing /fast
;CU79 (i.e. extra confirm in buffer)
SETZ C, ;Terminate on null
SOUT% ;Echo the string
ERCAL CJERR
DMOVE B,CCSAV ;Get back saved CCOC words
TXNE C,3B19 ;Was <Esc> being echo'd before?
SFCOC% ;Yes, set it back
RET ;Go to CIN1 by way of our caller
; C2CBUF - Copies a string into CBUF; properly hacking the pointers so
; that COMND% believes it was typed in
; Called with:
; A/ pointer to the string
; B/ non-zero if we should type the prompt when we do the CMINI
; Returns with:
; command state block and buffer adjusted to contain the string
C2CBUF: TRVAR <CMNDBP,CMNDLN,PMTFLG,IOJSAV> ;Byte pointer to string to move,
; its length in (36 bit) words, and
; a place to save the arg in B, and
; a place for saving the .CMIOJ word
MOVEM A,CMNDBP ;Save pointer to command string
MOVEM B,PMTFLG ;Save print prompt flag
CALL CMDINI ;Set up SBLOCK (shouldn't be necessary, but is)
SKIPE PMTFLG ;Suppressing prompt?
IFSKP. ;Yes
MOVE A,CMIOJ ;Get .CMIOJ word from SBLOCK
MOVEM A,IOJSAV ;Save it
HRRI A,.NULIO ;Make output be .NULIO to
MOVEM A,CMIOJ ; suppress the prompt
ENDIF.
MOVX A,CMINI ;Do CMINI (don't call READY because it
MOVEM A,CMFNP ; destroys to many things
MOVEI B,FBLOCK ;SPECIFY FUNCTION BLOCK ADDRESS
CALL FIELDX ;TYPE THE PROMPT
SKIPE PMTFLG ;Did we suppress the prompt?
IFSKP. ;Yes
MOVE A,IOJSAV ;Get back saved .CMIOJ word
MOVEM A,CMIOJ ;Restore it
ENDIF.
MOVE A,CMNDBP ;Get back pointer to command
CALL BCOUNT ;Count length of string
MOVEM A,CMNDLN ;Save length in words
MOVE A,B ;Get length in bytes
MOVEM A,CMINC ;Save as count of unparsed characters
MOVEI B,CBUFL*5 ;Announce how much room for typein there is
SUB B,A ;The unparsed characters take up space
MOVEM B,CMCNT ;Save amount still free
SKIPGE CMCNT ;Negative amount of buffer still left?
ERROR <Internal error in C2CBUF: string will not fit in CBUF>
HRROI A,CBUF ;Get pointer to next field
MOVEM A,CMPTR ;Store it
HRL A,CMNDBP ;Get address of string to move
HRRI A,CBUF ;Make source,,destination
MOVEI B,CBUF ;Compute end for BLT
ADD B,CMNDLN ;...
BLT A,@B ;Move the string
RET ;All done
;PA048 Command editor interrupt character PSI routine
.CEPSI::MOVE A,[POINT 7,CBUF] ;LOOK AT THE COMMAND BUFFER
ILDB B,A ;GET THE NEXT CHARACTER
JUMPN B,.-1 ;KEEP LOOKING FOR A NULL
SETO C, ;FOUND IT
ADJBP C,A ;BACK UP ONE CHARACTER
MOVEI A,.PRIIN ;LOOK AT THE TERMINAL
SIBE ;ANYTHING THERE?
JRST [ MOVE A,C ;YES, ADD IT TO THE BUFFER
MOVE B,[RD%RIE+^D80]
SETZ C, ;NO PROMPT, QUIT WHEN TTY BUFFER IS EMPTY
RDTTY ;GET IT
ETYPE <%_%%Can not find rest of command, Continuing>
IDPB C,A ;ASCIZ THE STRING
JRST .+1 ] ;READY TO GO NOW
HRROI A,CBUF ;PA048 Point to command buffer
SETO C, ;PA048 Assume line was not empty
IFN PWSW,<
SKIPN PWDFLG ;PA048 Parsing a password line?
>;IFN PWSW
CALL CKREAL ;PA048 or line is entirely whitespace?
JRST [MOVE A,[SCBUF,,CBUF] ;PA048 Yes, edit saved command line
BLT A,CBUFE ;PA048 instead
IFN PWSW,<
SETZM PWDFLG ;PA048 Hopefully user won't type
; sensitive info into the editor
>;IFN PWSW
SETZ C, ;PA048 Always start editing at the beginning
; of the line for old saved commands
JRST .+1 ] ;PA048 ...
PUSH P,P ;SAVE THE STACK POINTER
CEDSTG ;PA048 Define TRVAR's for editor
TYPE <
> ;PA048 Put out a blank line here since we
; no longer do at the beginning of CEDITU
CALL PIOFF ;PA048 Don't allow ^C while history list munged
PUSH P,C ;PA048
CALL SVALWS ;PA048 Save CBUF in a temporary history entry
POP P,C ;PA048
HRRZ A,HSTLST ;PA048 Get pointer to most recent history entry
MOVE B,CMDNUM ;PA048 Get its command number
CALL CEDITU ;GO TO THE EDITOR
CALL RMVFST ;PA048 Remove the temporary entry from the
; history list (a permenent one will be made
; later by the normal methods by which such
; things are done)
CALL PION ;PA048 Allow ^C again
POP P,P ;FLUSH THE TRVARS
MOVE A,LEV3PC ;PA048 GET THE RETURN ADDRESS
HRRI A,REPARS ;CHANGE IT
TXO A,PC%USR ;RETURN TO USER CODE
MOVEM A,LEV3PC ;PA048 RESTORE FIXED PC
DEBRK ;PARSE EDITED COMMAND
;PA048 Entry from EXECSU after M-$ has been done
CEDESC::SETZM CESCHK ;Don't accidently come back here
MOVE A,CMPTR ;Get pointer to the rest of the input line
CALL FIXPT ;Make sure not -1,,foo pointer
MOVE B,CMINC ; and the number of unparsed characters
ADJBP B,A ;Make B point to end of the command
SETO A, ;Make A point to last character
ADJBP A,B ; of the command
LDB C,B ;Get last character in buffer
;CU79 CAIE C,.CHSPC ;A space?
MOVE A,B ;No, don't overwrite it
PUSH P,A ;Save good pointer
SETZ B, ;Get null
IDPB B,A ;Null-terminate the string
HRROI A,CBUF ;Get pointer to command
CALL BCOUNT ;Find out how long it is
MOVEM B,D ;Save length
MOVE A,[POINT 7,CEROCB] ;Get pointer to rest of command
DO. ;Loop
ILDB B,A ;Get a character
CAIE B,.CHSPC ;Space?
CAIN B,.CHTAB ; or tab?
AOJA D,TOP. ;Yes, want to position cursor past whitespace
OD.
POP P,A ;Get back pointer to end of string
HRROI B,CEROCB ;Get pointer to rest of command
SETZ C,
SKIPE CEROCB ;Anything there?
SOUT% ;Yes, append it to the end of the command
CEDSTG ;PA048 Define TRVAR's for editor
;; CALL LM ;PA048 Get to left margin
CALL PIOFF ;PA048 Don't allow ^C while history list munged
PUSH P,D ;PA048 Save column to start editing in
CALL SVALWS ;PA048 Save CBUF in a temporary history entry
HRRZ A,HSTLST ;PA048 Get pointer to most recent history entry
MOVE B,CMDNUM ;PA048 Get its command number
POP P,C ;PA048 Cursor position is length of stuff
; in CBUF after M-$ done
CALL CEDITU ;GO TO THE EDITOR
CALL RMVFST ;PA048 Remove the temporary entry from the
; history list (a permenent one will be made
; later by the normal methods by which such
; things are done)
CALL PION ;PA048 Allow ^C again
JRST REPARS ;Go execute command
; UTEXAS-20 COMMAND LINE EDITOR
;Takes:
; A/ Pointer to history entry of command to be edited
; B/ Absolute command number of command to be edited
; C/ Starting column number (0=beginning of line, n=column
; n (n > 0), and -1=end of line)
CEDITU: MOVEM A,CELPTR ;PA048 Point to command to be edited
MOVEM A,CEORIG ;PA048 Save a copy so we can find which
; we started out editing in CEABRT
MOVEM B,CELPOS ;PA048 Store its command number
MOVEM C,CECPOS ;PA048 Store starting column
MOVEI A,.CTTRM ;GET OLD MODE WORD
RFMOD
MOVEM B,CETTMD ;PA048 SAVE THIS FOR LATER
TXZ B,TT%IGN ;MAKE SURE IT SEES TT%WAK BITS
TXO B,TT%WAK ;WAKE ON EVERYTHING
TXZ B,TT%ECO ;TURN OFF ECHOING
TXZ B,TT%PGM ;TURN OFF PAGING (^S, ^Q)
TXZ B,TT%TAB ;SPACES INSTEAD OF TAB
SFMOD
STPAR
MOVE B,[052525,,553125] ;PASS CR, ^I, FORMAT LF, NO NULLS
MOVE C,[252525,,652400] ;FORMAT ESCAPE
SFCOC
MOVEI A,.FHJOB
SETZ B, ;NO TERMINAL INTERRUPTS
STIW
ERJMP [ETYPE <%%Can't set up terminal for editing - %?%%_> ;PA048
JRST CEABRT ] ;PA048 Pretend user typed ^G
SETZM CEDUMB ;ASSUME SMART TERMINAL
JRST CETNCR ;CU79 only EMACS mode
CETOP: TYPE <
> ;CR
SETZM CECPOS ;PA040 Reset current column (moved up
; above CETNCR from below)
CETNCR: ;PA048
MOVEI A,.CHCRT ;Make sure at left margin
PBOUT% ;...
CALL EEOLN ;ERRASE TO END OF LINE
MOVE A,CELPTR ;POINT TO THE CURRENT LINE
ADDI A,2 ;PA048 Skip past the header
HLL A,[POINT 7,0] ;MAKE IT A POINTER
MOVE B,[POINT 7,CETBUF] ;POINT TO THE TEMP BUFFER
SETZ D, ;PA048 Length is zero
CETOP0: ILDB C,A ;GET NEXT BYTE
AOS D ;PA048 Count one more
;PA048 HRRZ D,A ;CHECK FOR WRAP AROUND
;PA048 CAIE D,CEBFEN ;TOO FAR?
;PA048 JRST CETOP1 ;NO
;PA048 MOVE A,[POINT 7,CESAVE] ;YES, RESET THE POINTER
;PA048 JRST CETOP0 ;AND START OVER
CETOP1: IDPB C,B ;MOVE IT
SKIPE C ;END ON NULL BYTE
JRST CETOP0 ;DO THE REST
SOS D ;PA048 Don't count null in length
SKIPG A,CECPOS ;PA048 Absolute starting column requested?
IFSKP. ;PA048
CAMLE A,D ;PA048 Yes. Too big?
MOVEM D,CECPOS ;PA048 Yes, starting col is rightmost
ELSE. ;PA048
SKIPE CECPOS ;PA048 Want to start at beginning?
MOVEM D,CECPOS ;PA048 No, must want to start at end
ENDIF. ;PA048
MOVE A,CECPOS ;PA048 Get starting column
ADJBP A,[POINT 7,CETBUF] ;PA048 GET A POINTER TO IT
MOVEM A,CEBPTR ;SAVE IT
SKIPN CEDUMB ;WRITE LINE FOR DUMB TERMINALS
JRST CETOP2
CALL CENUMB
;;PA048 MOVE A,CEBPTR
HRROI A,CETBUF ;PA048
PSOUT
TYPE <
>
CETOP2: TYPE < > ;PA048 MAKE ROOM FOR THE LINE NUMBER
;;PA048 MOVE A,CEBPTR
HRROI A,CETBUF ;PA048
SKIPN CEDUMB ;EMACS OR SMART ALTER MODE?
PSOUT ;YES, WRITE IT OUT
MOVEI A,CR
PBOUT ;BACK TO THE BEGINNING
CALL CENUMB ;WRITE THE NUMBER
MOVE A,COJFN ;PA048 Get output jfn
HRROI B,CETBUF ;PA048 Get pointer to current line
MOVN C,CECPOS ;PA048 Get negative of current column
SKIPE C ;PA048 Unless column 0
SOUT% ;PA048 Move cursor to correct column
JRST CEINC ;GET COMMAND INPUT CHARACTER
CENUMX: SAVEAC <A,B,C> ;PA048 "History" enters here
MOVE A,COJFN ;PA048 Output to terminal
MOVE B,D ;PA048 Get command number
JRST CENUM2 ;PA048 Join common code
CENUMB:
IFN NICSW,<
ETYPE <[>
>;IFN NICSW
MOVEI A,.CTTRM ;OUTPUT LINE# AS "DD:"
;PA048 MOVN B,CELPOS ;GET (NEGATIVE) LINE NUMBER
MOVE B,CELPOS ;PA048 Get absolute command number
;PA048 JUMPE B,CENUM1 ;DO CURRENT LINE DIFFERENT
CAMN B,CMDNUM ;PA048 Current command?
JRST CENUM1 ;PA048 Yes, do differently
CENUM2: ;PA048
MOVE C,[NO%LFL!NO%OOV!NO%AST!FLD(3,NO%COL)!FLD(12,NO%RDX)]
NOUT
JFCL
IFN NICSW,<
ETYPE <]>
>;IFN NICSW
IFE NICSW,<
TYPE <: > ;PA048
>;IFE NICSW
RET ;ALL DONE
IFE NICSW,<
CENUM1: TYPE < **: > ;PA048 FOR CURRENT LINE
>;IFE NICSW
IFN NICSW,<
CENUM1: TYPE <***]> ;PA048 FOR CURRENT LINE
>;IFN NICSW
RET
; Get the next input character
CEINC:
IFN CUSW,<
JRST ECEINC ;CU79 Always emacs use, different commands
>;IFN CUSW
IFE CUSW,<
SKIPN CEMODE ;EMACS MODE?
JRST ECEINC ;YES, GO TO HANDLER
;NO, MUST BE ALTER MODE
SETZ P3, ;ASSUME NO NUMERIC ARGUMENT
ACEINC: PBIN ;GET ALTER MODE COMMAND
CAIL A,"0" ;BIGGER THAN 0?
CAILE A,"9" ;SMALLER THAT 9?
JRST ACEIN1 ;NOT A NUMBER, KEEP LOOKING
IMULI P3,^D10 ;NUMBER, UPDATE THE COUNT
ADD P3,A ;ADD THIS ONE IN
SUBI P3,"0" ;CONVERT TO BINARY
JRST ACEINC ;GET THE REST OF THE COMMAND
ACEIN1: CAIN A,CR ;^M - EXIT AND DO COMMAND
JRST CEEXIT
CAIE A,"E" ;E - EXIT AND DO COMMAND
CAIN A,"e"
JRST CEEXIT
CAIN A,.CHCNU ;^U - START OVER
JRST CETOP
CAIN A,.CHLFD ;FL - NEXT LINE
JRST CEDOWN
CAIN A,.CHESC ;ESC - PREVIOUS LINE
JRST CEUP
CAIN A,.CHCNR ;^R - RETYPE LINE
JRST CATYPE
CAIE A,"L" ;^L - TYPE LINE AND START OVER
CAIN A,"l"
JRST CARTYP
CAIE A,"P" ;P - RETYPE LINE
CAIN A,"p"
JRST CATYPE
CAIE A,"Q" ;Q - ABORT
CAIN A,"q"
JRST CEQUIT
CAIN A,.CHCNC ;^C - ABORT
JRST CEQUIT
CAIE A,"D" ;D - DELETE CHARACTERS
CAIN A,"d"
JRST CADEL
CAIE A,"H" ;"H" - DELETE TO END, THEN INSERT
CAIN A,"h"
JRST CAHACK
CAIE A,"I" ;"I" - ENTER INSERT MODE
CAIN A,"i"
JRST CAINST
; CONTINUED ON NEXT PAGE
CAIE A,"R" ;"R" - DELETE THEN INSERT
CAIN A,"r"
JRST CADEIN
CAIE A,"W" ;"W" - MOVE OVER WORDS
CAIN A,"w"
JRST CAFORW
CAIE A,"X" ;"X" - EXTEND LINE
CAIN A,"x"
JRST CAEXTN
CAIE A,"Z" ;"Z" - DELETE WORDS
CAIN A,"z"
JRST CADELZ
CAIN A,":" ;":" - DELETE REST OF LINE
JRST CACOLN
CAIN A,"\" ;"\" - TRANSPOSE PREVIOUS TWO CHARS
JRST CETRAN
CAIN A,.CHDEL ;RUB - MOVE CURSOR LEFT
JRST CALEFT
CAIN A," " ;SPACE - MOVE CURSOR RIGHT
JRST CARIGH
CAIN A,.CHTAB ;TAB - MOVE TO END OF LINE
JRST CAEOLN
CAIN A,"?" ;? - GIVE HELP MESSAGE
JRST CAHELP
CALL CEBELL ;ERROR, RING THE BELL
JRST CEINC ;TRY AGAIN
; HERE TO ENTER INSERT MODE
CAINST: CALL CAFLSH ;FLUSH ANYTHING WE HAD GOING
CANST0: PBIN ;GET NEXT CHARACTER
CAIN A,.CHESC ;ESCAPE?
JRST CEINC ;YES, EXIT
CAIN A,.CHTAB ;A TAB?
JRST CAINOK ;YES, LET IT PASS
CAIN A,.CHCNC ;CONTROL C?
JRST CEQUIT ;YES, QUIT
CAIL A," " ;SOME CONTROL CODE?
CAIN A,.CHDEL ;OR RUBOUT?
SKIPA ;YES, ERROR
JRST CAINOK ;ITS OK
CALL CEBELL ;ERROR, RING BELL
JRST CANST0 ;AND TRY AGAIN
CAINOK: MOVE C,CEBPTR ;GET THE POINTER
SKIPE CEDUMB ;DUMP TERMINAL?
PBOUT ;YES, DISPLAY THE CHARACTER
CAINS1: ILDB B,C ;GET ONE THAT WAS THERE
SKIPN CEDUMB ;SMART TERMINAL?
PBOUT ;YES, OUTPUT IT
DPB A,C ;REPLACE IT
JUMPE A,CAINS2 ;EXIT AFTER A NULL BYTE
MOVE A,B ;SET UP TO REINSERT THE ONE
JRST CAINS1
CAINS2: AOS CECPOS ;UPDATE OUR POSITION
IBP CEBPTR ;AND OUR POINTER
SKIPE CEDUMB ;SMART TERMINAL
JRST CAINST ;NO, GET SOME MORE
ETYPE <
> ;POSITION THE CURSOR
CALL CENUMB ;MOVE PAST THE LINE NUMBER
MOVE A,COJFN ;POINT TO THE TERMINAL
HRROI B,CETBUF ;POINT TO THE STRING
MOVN C,CECPOS ;GET COUNT
SKIPE C ;DON'T GO FOREVER HERE
SOUT ;MOVE PAST THE OLD CHARACTERS
JRST CAINST ;DONE, GET SOME MORE
; HERE TO DELETE N CHARACTERS
CADEL: CALL ALTDEL ;DO ALTER MODE DELETE
JRST CEINC ;DONE
; HERE TO DELETE N CHARACTERS THEN INSERT TEXT
CADEIN: CALL ALTDEL ;DO ALTER MODE DELETE
CALL CAFLDE ;SIGNAL END OF DELETE
JRST CAINST ;SO THE INSERT
; ALTER MODE DELETE ROUTINE
ALTDEL: MOVE A,CEBPTR
ILDB B,A
SKIPN B
RET
CALL CAFLBK ;FLUSH BACKSPACE MARKER
SKIPG P3 ;ZERO OR BAD ARGUMENT?
MOVEI P3,1 ;YES, MAKE IT THE DEFAULT
SETZ C, ;NEW COUNTER
SKIPE CEDUMB ;SMART TERMINAL
CALL CADELF ;NO, SIGNAL DELETE
MOVE B,CEBPTR ;GET THE POINTER
ALTDL1: ILDB A,B ;GET NEXT CHARACTER
JUMPE A,ALTD1A ;END?
AOS C ;NO, INCREMENT COUNT
SKIPE CEDUMB ;SMART TERMINAL?
PBOUT ;NO, ECHO CHARACTER
SOJG P3,ALTDL1
JRST ALTDL2
ALTD1A: SETO A, ;WENT TOO FAR, BACKUP POINTER
ADJBP A,B
MOVEM A,B
ALTDL2: SKIPN C
RET
MOVE A,CEBPTR
ALTDL3: ILDB C,B ;GET FIRST CHARACTER
IDPB C,A ;SAVE IN NEW POSITION
JUMPN C,ALTDL3
SKIPE CEDUMB ;SMART TERMINAL?
RET ;NO, DONE
ALTDL4: MOVE A,CEBPTR ;REWRITE THE SCREEN
PSOUT
CALL EEOLN
ETYPE <
> ;POSITION THE CURSOR
CALL CENUMB ;MOVE PAST THE LINE NUMBER
MOVE A,COJFN ;POINT TO THE TERMINAL
HRROI B,CETBUF ;POINT TO THE STRING
MOVN C,CECPOS ;GET COUNT
SKIPE C ;DON'T GO FOREVER HERE
SOUT ;MOVE PAST THE OLD CHARACTERS
RET
; HERE TO RETYPE THE LINE
CATYPE: CALL CAFLSH ;FLUSH EVERYTHING
SKIPN CEDUMB ;SMART TERMINAL?
JRST CEDISP ;YES, THIS IS A JOB FOR EMACS
MOVE A,CEBPTR ;FINISH THE LINE
PSOUT
ETYPE <
> ;GO TO NEW LINE
JRST CINST1 ;WRITE IT OUT
; HERE TO FINISH TYPING THE LINE AND START OVER
CARTYP: CALL CAFLSH
SETZM CECPOS ;RESET CHARACTER PSOITION
SKIPN CEDUMB ;SMART TERMINAL?
JRST CARTP1 ;YES
MOVE A,CEBPTR ;FINISH THE LINE
PSOUT
CARTP1: MOVE A,[POINT 7,CETBUF] ;RESET POINTER
MOVEM A,CEBPTR
ETYPE <
> ;NEW LINE
JRST CETOP2 ;AND START OVER
; HERE TO HACK AND INSERT
CAHACK: CALL CAFLBK
SKIPN CEDUMB ;SMART TERMINAL?
JRST CAHAK1 ;YES, DO IT THE EASY WAY
CALL CADELF ;SIGNAL DELETE
MOVE A,CEBPTR ;GET THE REST OF THE STRING
PSOUT ;OUTPUT IT
TYPE <\\> ;END OF DELETE
SETZM CADLFG
CAHAK1: SETZ A, ;CHOP OFF THE REST OF THE STRING
MOVE B,CEBPTR ;GET COPY OF POINTER
IDPB A,B ;CURSOR IS ONE POSITION PAST POINTER
CALL EEOLN ;JUST IN CASE
JRST CAINST ;START INSERTING
; HERE TO MOVE OVER WORDS
CAFORW: CALL CAFLSH
SKIPG P3
MOVEI P3,1
CAFRW1: CALL F.WORD ;GET COUNT TO NEXT WORD
ADDM B,CECPOS ;UPDATE POSITION
MOVN C,B ;GET NEGATIVE COUNT
MOVE A,COJFN ;MOVE OVER
MOVE B,CEBPTR
SKIPE C
SOUT ;WRITE IT OUT
MOVEM B,CEBPTR
SOJG P3,CAFRW1
JRST CEINC ;DONE
; HERE TO DELETE N WORDS
CADELZ: CALL CAFLBK
PUSH P,CEBPTR ;SAVE THE POINTER
SKIPG P3 ;ZERO OR NO ARGUMENT?
MOVEI P3,1 ;YES, MAKE IT THE DEFAULT
SETZ D, ;KEEP COUNT HERE
CADLZ1: CALL F.WORD ;GET COUNT TO NEXT WORD
SUB D,B ;KEEP NEGATIVE COUNT
ADJBP B,CEBPTR ;UPDATE POINTER
MOVEM B,CEBPTR
SOJG P3,CADLZ1
SKIPE A,CEDUMB ;SMART TERMINAL?
JRST CADLZ2 ;NO.
MOVE A,CEBPTR ;DESTINATION POINTER
POP P,CEBPTR ;SOURCE POINTER
JRST M.FIX ;FIX IT UP
CADLZ2: CALL CADELF ;SIGNAL DELETE
MOVE A,COJFN ;WRITE OUT DELETED STUFF
MOVE B,(P) ;POINT TO DELETED STUFF
MOVE C,D ;NUMBER OF CHARACTERS
SKIPE C ;SKIP IF NONE
SOUT
POP P,CEBPTR ;FIX THE POINTER
MOVE A,CEBPTR
CADLZ3: ILDB C,B ;GET FIRST CHARACTER
IDPB C,A ;SAVE IN NEW POSITION
JUMPN C,CADLZ3
JRST CEINC ;DONE
; HERE TO EXTEND THE LINE
CAEXTN: CALL CAFLSH
MOVE A,CEBPTR ;GET THE POINTER
PSOUT ;WRITE IT OUT
SETO B, ;BACKUP THE POINTER
ADJBP B,A
SETZ A, ;GET COUNT TOO
CAXTN1: ILDB A,CEBPTR ;GET NEXT CHARACTER
JUMPE A,CAXTN2
AOS CECPOS ;UPDATE POSITION
JRST CAXTN1
CAXTN2: MOVEM B,CEBPTR ;SAVE NEW POINTER
JRST CAINST ;GO TO INSERT MODE
; HERE TO JUMP TO THE END OF A LINE
CAEOLN: CALL CAFLSH
MOVE A,CEBPTR ;GET POINTER
PSOUT ;WRITE IT OUT
SETO B, ;BACK IT UP
ADJBP B,A
SETZ A, ;GET COUNT TOO
CAEOL1: ILDB A,CEBPTR ;GET NEXT CHARACTER
JUMPE A,CAEOL2
AOS CECPOS ;UPDATE POSITION
JRST CAEOL1
CAEOL2: MOVEM B,CEBPTR ;SAVE NEW POINTER
JRST CEINC ;DONE
; HERE TO DELETE THE REST OF THE LINE
CACOLN: CALL CAFLBK
SKIPN CEDUMB ;SMART TERMINAL?
JRST CACLN1 ;YES, SKIP THIS
CALL CADELF ;SIGNAL DELETE
MOVE A,CEBPTR ;GET POINTER
PSOUT ;WRITE THE RESTO OF THE STRING
TYPE <\\> ;SIGNAL NO MORE DELETE
SETZM CADLFG
CACLN1: SETZ A, ;CHOP OFF THE REST OF THE STRING
MOVE B,CEBPTR ;GET COPY OF POINTER
IDPB A,B ;CURSOR IS ONE POSITION PAST POINTER
CALL EEOLN ;JUST IN CASE
JRST CEINC ;ALL DONE
; HERE TO MOVE TO RIGHT
CARIGH: CALL CAFLSH
SKIPG P3 ;ARGUMENT OK?
MOVEI P3,1 ;FIX IT UP
CARIG1: ILDB A,CEBPTR ;GET NEXT CHARACTER
JUMPE A,CARIG2 ;END OF LINE
AOS CECPOS ;UPDATE POSITION
PBOUT ;MOVE OVER
SOJG P3,CARIG1 ;DO THE REST
JRST CEINC ;DONE
CARIG2: SETO A, ;WENT TOO FAR
ADJBP A,CEBPTR ;BACK UP
MOVEM A,CEBPTR
JRST CEINC ;DONE
; HERE TO MOVE TO THE LEFT
CALEFT: CALL CAFLDE
SKIPN CECPOS ;BEGINNING OF LINE?
JRST CEINC ;YES, SKIP
SKIPN P3 ;NO ARGUMENT?
MOVEI P3,1 ;MAKE IT A 1
CAML P3,CECPOS ;ARGUMENT TOO BIG?
MOVE P3,CECPOS ;YES, TRIM IT DOWN
SKIPE CEDUMB ;SMART TERMINAL
JRST CALFT1 ;NO
MOVN C,P3 ;FIX THE POINTER
ADJBP C,CEBPTR
MOVEM C,CEBPTR
MOVN A,P3 ;FIX POSITION
ADDM A,CECPOS
JRST CINST1 ;POSITION CURSOR
CALFT1: CALL CABAKF ;SIGNAL BACK MOVEMENT
CALFT2: LDB A,CEBPTR ;GET THIS CHARACTER
PBOUT ;OUTPUT IT
SETO B, ;MOVE THE POINTER BACK
ADJBP B,CEBPTR ;BACK UP THE POINTER
MOVEM B,CEBPTR
SOS CECPOS
SOJG P3,CALFT2 ;DO THE REST
JRST CEINC ;GET NEXT COMMAND
; ROUTINES TO PRINT \ AND \\ FOR DUMB TERMINAL ALTER MODE
CAFLSH: CALL CAFLBK ;FLUSH OUT BACKSPACE CHARACTER
CALL CAFLDE ;FLUSH OUT DELETE CHARACTER
RET
CAFLBK: SKIPN CEDUMB
RET
SKIPN CABKFG ;WERE WE BACKSPACING?
RET ;NO, NOTHING TO DO
SETZM CABKFG ;RESET THE FLAG
TYPE <\> ;SIGNAL END OF BACKSPACE
RET
CAFLDE: SKIPN CEDUMB ;DUMB TERMINAL?
RET ;YES, RETURN
SKIPN CADLFG ;WERE WE IN A DELETE?
RET ;NO
SETZM CADLFG ;RESET FLAG
TYPE <\\> ;SIGNAL END OF DELETE
RET
CABAKF: SKIPN CEDUMB
RET
SKIPN CABKFG ;SET?
ETYPE <\> ;NO, SIGNAL
SETOM CABKFG ;SET BACKSPACE FLAG
RET
CADELF: SKIPN CEDUMB
RET
SKIPN CADLFG ;SET?
ETYPE <\\> ;NO, SIGNAL
SETOM CADLFG ;SET DELETE FLAG
RET
>;IFE CUSW
; EMACS MODE BEGINS HERE
ECEINC: MOVEI P3,1 ;PA048 Default repeat count is one
ECEIN2: ;PA048 Enter here from argument (^U)
; handler, with P3 already set up
MOVEI A,.CTTRM ;ALLOW 8 BIT INPUT
RFMOD ;GET THE MODE WORD
PUSH P,B ;SAVE IT
TXZ B,TT%DAM ;BINARY MODE
SFMOD
PBIN ;GET EDIT CHARACTER
POP P,B ;RESTORE MODE WORD
PUSH P,A ;SAVE CHARACTER
MOVEI A,.CTTRM
SFMOD
POP P,A ;RESTORE CHARACTER
SKIPN CEMETA ;META KEY IN USE?
TRZ A,200 ;NO, TRIM PARITY BIT
TRZE A,200 ;META KEY USED?
JRST METAN1 ;YES, PROCESS IT
CAIN A,CR ;^M - EXIT AND DO EDITED COMMAND
JRST CECRLF ;PA048 Eat LF and then exit
CAIN A,.CHCNP ;^P - EDIT PREVIOUS COMMAND
JRST CEUP
IFE STANSW,<
CAIN A,.CHBEL ;PA048 ^G?
JRST CEABRT ;PA048 Yes, abort editing
>;IFE STANSW
IFN STANSW,<
CAIE A,.CHBEL ;^G? If so, act like ^C typed
>;IFN STANSW
CAIN A,.CHCNC ;PA048 ^C?
JRST CECTLC ;PA048 Yes, abort editing and goto ^C handler
CAIN A,.CHCNU ;PA048 ^U?
JRST CECTLU ;PA048 Go handle
CAIN A,.CHDEL ;RUBOUT - DELETE CHAR AT LEFT OF CURSOR
JRST CERUB ;EM74
CAIN A,.CHCNB ;^B - CURSOR LEFT
JRST CELEFT
CAIN A,.CHCNF ;^F - CURSOR RIGHT
JRST CERIGH
CAIN A,.CHCNN ;^N - CURSOR DOWN
JRST CEDOWN
CAIN A,.CHCND ;^D - DELETE CHARACTER AT CURSOR
JRST CERMSP
CAIN A,.CHCNE ;^E - MOVE TO END OF LINE
JRST CEMEND
CAIN A,.CHCNA ;^A - MOVE TO BEGINNING OF LINE
JRST CEBEGN
CAIN A,.CHVTB ;^K - KILL TO END OF LINE
JRST CECTLK ;PA048
CAIN A,.CHCNT ;^T - TRANSPOSE CHARACTERS
JRST CETRAN
CAIN A,.CHCNW ;^W - SAME AS M-RUB
JRST METARB
CAIN A,.CHCUN ;^_ - HELP MESSAGE
JRST CEHELP
CAIN A,.CHFFD ;PA048 ^L - Redisplay line
JRST CERDSP ;PA048 Rewrite line (on top of old line if
; terminal is smart enough)
CAIN A,.CHTAB ;TAB - INSERT WITHOUT V
JRST CINSRT
CAIN A,.CHESC ;<ESC> - META PREFIX
JRST METAIN
CAIE A,.CHCNQ ;^Q - TAKE NEXT CHAR LITERALLY
CAIN A,.CHCNV ;^V - TAKE NEXT CHAR LITERALLY
JRST CRTLV
CAIL A," " ;PA048 SOME OTHER CONTROL CHARACTER?
JRST CINSRT ;PA048 No, must be self-inserting
CALL CEBELL ;PA048 Yes, error. Beep at user
JRST CEINC ;PA048 Get another command
CRTLV: PBIN ;GET THE CHARACTER
JRST CINSRT ;PROCESS IT
; An escape has been entered, get the next command character
METAIN: PBIN ;GET THE NEXT WORD
METAN1: CAIE A,"F" ;M-F - FORWARD TO END OF WORD
CAIN A,"f"
JRST METAF
CAIE A,"B" ;M-B - BACK TO BEGINNING OF WORD
CAIN A,"b"
JRST METAB
CAIE A,"D" ;M-D - DELETE TO END OF WORD
CAIN A,"d"
JRST METAD
CAIE A,"S" ;M-S - SEARCH FORWARD FOR CHARACTER
CAIN A,"s"
JRST METAS
CAIE A,"R" ;M-R - SEARCH BACKWARD FOR CHARACTER
CAIN A,"r"
JRST METAR
CAIN A,.CHDEL ;M-RUB - DELETE BACK TO START OF WORD
JRST METARB
;CU79 CAIN A,.CHESC ;M-ESC - STUFF COMMAND WITH <ESC>
;CU79 JRST METAES
;CU79 Begin addition
CAIE A,.CHESC ;M-ESC?
IFSKP. ;Yes...
;; SKIPE CECPOS ;Are we at the left margin?
JRST METAES ;No, go do recognition
;; CALL CEBELL ;Yes, no recognition available here
;; JRST CEINC ;Go get another character
ENDIF.
;CU79 End addition
CAIN A,"?" ;M-? - STUFF COMMAND WITH ?
JRST METAQU
CAIN A,.CHCNC ;PA048 M-^C?
JRST CECTLC ;PA048 Yes, treat as ^C
CAIE A,"-" ;PA048 M-Minus?
CAIN A,.CHCNU ;PA048 or M-^U?
JRST CEAARG ;PA048 Yes, go do autoarg processing
CAIL A,"0" ;PA048 M-Digit?
CAILE A,"9" ;PA048 ...
TRNA ;PA048 No
JRST CEAARG ;PA048 Yes, go do autoarg processing
CALL CEBELL ;ERROR, RING BELL
JRST CEINC ;TRY AGAIN
;PA048 A M-digit command has been typed. Treat as autoarg:
CEAARG: JRST CECLU5 ;PA048
;PA048 A ^U has been typed. Read the argument and set up the
;count word P3:
CECTLU: MOVEI P3,4 ;PA048 Assume value of 4
CECLU2: PBIN ;PA048 Read another character
CAIE A,.CHCNU ;PA048 Another ^U?
IFSKP. ;PA048 Yes
IMULI P3,4 ;PA048 Multiply current repeat count
;PA048 by 4
JRST CECLU2 ;PA048 Loop some more
ENDIF. ;PA048
CAIN A,"-" ;PA048 Minus
JRST CECLU3 ;PA048 Yes, go handle number
CAIL A,"0" ;PA048 Digit?
CAILE A,"9" ;PA048 ...
IFSKP. ;PA048
JRST CECLU3 ;PA048 Yes, go handle number
ENDIF. ;PA048
JRST CECLU9 ;PA048 No, must be command. Go do it
;Here on a number after an arbitrary number or ^U's. We have to divide
;the current repeat count by 4, since the first ^U doesn't multiply the
;argument by 4 if there are numbers given. Then we have to get the
;number (the first character of which is in A) and multiply the repeat
;count by it:
CECLU3: IDIVI P3,4 ;PA048 Divide current repeat count by 4
; to forget first ^U
JRST CECLU5 ;PA048 Go handle number in A
;Here after we no longer have to worry about the initial ^U garbage
;(ie, we have seen a digit or a "-" and have done the hack to forget
;the initial ^U). Also enter here (at CECLU5) for autoarg (ie, M-digit
;and M-minus commands) processing:
CECLU4: PBIN% ;PA048 Get next character
CECLU5: CAIE A,"-" ;PA048 Minus?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, switch sign of repeat count
JRST CECLU4 ;PA048 Loop
ENDIF. ;PA048
CAIE A,.CHCNU ;PA048 ^U?
IFSKP. ;PA048
IMULI P3,4 ;PA048 Yes, multiply current repeat count
; by 4
JRST CECLU4 ;PA048 Loop
ENDIF. ;PA048
CAIL A,"0" ;PA048 Digit?
CAILE A,"9" ;PA048 ...
JRST CECLU9 ;PA048 No, we must be done
;Here to handle strings of digits. Accumulate number in D, and then
;multiply the repeat count by it after we've gotten the whole thing:
SUBI A,"0" ;PA048 Make it a number
MOVE D,A ;PA048 Initialize number accumulator
CECLU6: PBIN% ;PA048 Get another character
CAIL A,"0" ;PA048 Digit?
CAILE A,"9" ;PA048 ...
JRST CECLU7 ;PA048 No, go finish up
SUBI A,"0" ;PA048 Yes, make it a number
IMULI D,^D10 ;PA048 Accumulate number in D
ADDM A,D ;PA048 ...
JRST CECLU6 ;PA048 Go try for another digit
CECLU7: IMULM D,P3 ;PA048 Multiply repeat count by accumulated
; number
JRST CECLU5 ;PA048 Go read some more (next char to be
; processed is already in A)
;Here when we read something which we don't recognise. Assume it must be
;the actual command, so unread it and goto the command loop
CECLU9: MOVX A,.PRIIN ;PA048 Get source of input
BKJFN% ;PA048 Back up so we can reread command in
ERJMP .+1 ; binary mode
JRST ECEIN2 ;PA048 Go do command
; Here to insert a character into the command line
CINSRT: JUMPLE P3,CEINC ;PA048 Done on non-positive repeat count
MOVE D,A ;PA048 Save the character
CINSR0: MOVE C,CEBPTR ;PA048 Get the pointer
CINST: HRRZ B,C ;PA048 Get address field of the pointer
CAIGE B,CETBUF+CETBSZ-1 ;PA048 About to overflow the buffer
IFSKP. ;PA048
CALL CEBELL ;PA048 Yes, ring bell
JRST CINST1 ;PA048 Abort inserting
ENDIF. ;PA048
ILDB B,C ;GET ONE THAT WAS THERE
DPB A,C ;REPLACE IT
JUMPE A,CINST0 ;EXIT AFTER A NULL BYTE
;;PA048 PBOUT ;OUTPUT IT
MOVE A,B ;SET UP TO REINSERT THE ONE
JRST CINST
CINST0: AOS A,CECPOS ;UPDATE EVERYTHING
IBP CEBPTR
MOVE A,D ;PA048 Get back the character
PBOUT% ;PA048 Write the character
SOJG P3,CINSR0 ;PA048 Repeat if haven't done enough yet
MOVE A,CEBPTR ;PA048 Get pointer to rest of line
PSOUT% ;PA048 Write it
CINST1: MOVE B,CEBPTR ;EM74 See what we're supposed to point to
ILDB A,B ;EM74 If we're supposed to be at the end
JUMPE A,CEINC ;EM74 of the line, we're already there!
MOVEI A,CR
PBOUT ;POSITION THE CURSOR
CALL CENUMB ;MOVE PAST THE LINE NUMBER
MOVE A,COJFN ;POINT TO THE TERMINAL
HRROI B,CETBUF ;POINT TO THE STRING
MOVN C,CECPOS ;GET COUNT
SKIPE C ;DON'T GO FOREVER HERE
SOUT ;MOVE PAST THE OLD CHARACTERS
JRST CEINC ;DONE
; Move the cursor to the left
CELEFT: JUMPE P3,CEINC ;PA048 We're done if repeat count is zero
SKIPL P3 ;PA048 Negative repeat count?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make repeat count positive
JRST CERIGH ;PA048 Move cursor to the right
ENDIF. ;PA048
CAIG P3,1 ;PA048 Repeat count greater than one?
IFSKP. ;PA048
MOVE B,P3 ;PA048 Yes, get number of positions to move
MOVEI P3,1 ;PA048 Only move once
JRST METAB0 ;PA048 Join M-B code
ENDIF. ;PA048
;Here to move one position to the left:
SKIPN CECPOS ;AT BEGINNING OF BUFFER?
JRST CEINC ;YES, DO NOTHING
LDB C,CEBPTR ;GET CHARACTER WE ARE GOING TO
SETO B,
ADJBP B,CEBPTR ;DECR BYTE PTR
MOVEM B,CEBPTR
SOS CECPOS ;DECR CHARACTER POSITION
CAIGE C," " ;SOME CONTROL CHARACTER?
JRST CINST1 ;YES, DON'T MESS UP
CALL CEBACK ;BACK UP
JRST CEINC
;EM74 **** Begin ****
; Erase last character
CERUB: JUMPE P3,CEINC ;PA048 If repeat count is 0 we're done
SKIPL P3 ;PA048 Repeat count negative?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST CERMSP ;PA048 Treat as ^D
ENDIF. ;PA048
SKIPN CECPOS ;At beginning of buffer?
JRST CEINC ;Yep, don't do anything
CAIN P3,1 ;PA048 Repeat count is one?
IFSKP. ;PA048
MOVE B,P3 ;PA048 Get number of chars to back up
MOVEI P3,1 ;PA048 Do this only once
JRST METAR0 ;PA048 Join M-<del> code
ENDIF. ;PA048
;Here to delete exactly one character:
MOVE A,CEBPTR
ILDB C,A ;Get character to see if we're at EOL
SETO A,
ADJBP A,CEBPTR ;Decrement byte pointer
MOVEM A,CEBPTR
SOS CECPOS ;And decrement character position
JUMPN C,CERMSP ;If not at end of line, retype whole line
ILDB B,A ;CU79 Get character we're deleting
CAIL B," " ;CU79 Are we deleting a control character
IFSKP. ;CU79 yes...
CAIE B,.CHESC ;CU79 and not escape (single character)
CALL CEBACK ;CU79 Yes, we have to back up over two chars
ENDIF. ;CU79
CALL CEBACK ;Back up some
JRST CEKILL ;And nuke end of line
;EM74 **** End ****
; Move the cursor to the end of the line
CEMEND: MOVE B,CEBPTR ;SEE IF WE'RE POINTING AT ZERO BYTE
ILDB A,B
JUMPE A,CEMND1 ;AT END OF LINE, QUIT
AOS CECPOS
PBOUT ;MOVE OVER
JRST CEMEND+1
CEMND1: MOVNI C,1
ADJBP C,B
MOVEM C,CEBPTR ;MAKE BYTE POINTER AGREE WITH CURSOR
JRST CEINC
; Move the cursor to the right
CERIGH: JUMPE P3,CEINC ;PA048 We're done if repeat count is zero
SKIPL P3 ;PA048 Negative repeat count?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make repeat count positive
JRST CELEFT ;PA048 Move cursor to the left
ENDIF. ;PA048
CAIG P3,1 ;PA048 Repeat count greater than one?
IFSKP. ;PA048
MOVE B,P3 ;PA048 Yes, get number of positions to move
MOVEI P3,1 ;PA048 Only move once
JRST METAF0 ;PA048 Join M-F code
ENDIF. ;PA048
;Here to move one position to the right:
MOVE B,CEBPTR ;SEE IF WE'RE POINTING AT ZERO BYTE
ILDB A,B
JUMPE A,CEINC ;AT END OF BUFFER, DO NOTHING
PBOUT ;MOVE OVER
AOS CECPOS ;INCR CHARACTER POSITION
IBP CEBPTR ;INCREMENT POINTER
JRST CEINC
; Move to the next command line
CADOWN: MOVEI P3,1 ;PA048 In SOS the repeat count is always 1
CEDOWN: JUMPE P3,CETOP ;PA048 Done if repeat count 0
SKIPL P3 ;PA048 Repeat count negative?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST CEUP ;PA048 Treat as ^P
ENDIF. ;PA048
SOS P3 ;PA048 Decrement repeat count
HLRZ A,@CELPTR ;PA048 Get newer command line
SKIPN A ;CHECK FOR END OF LIST
JRST CEDWN1 ;NOT AT END, SKIP THIS
AOS CELPOS ;PA048 Increment THE LINE NUMBER
MOVEM A,CELPTR ;UPDATE POINTER
JRST CEDOWN ;PA048 Loop in case repeat count not 1
CEDWN1:
;PA048 MOVE A,CE1ST ;END OF LIST, GO BACK TO THE FIRST LINE
HLRZ A,HSTLST ;PA048 End of list, use oldest command
MOVEM A,CELPTR ;RESET THE POINTER
;PA048 MOVE A,CECNT ;GET RIGHT LINE NUMBER
;PA048 SOS A
MOVE A,CMDNUM ;PA048 Get current line number
SUB A,HSTCNT ;PA048 Comput command number of first entry
AOS A ;PA048 in history list
MOVEM A,CELPOS ;SET IT
JRST CEDOWN ;PA048 Loop in case repeat count not 1
; Move to the previous command line
CAUP: MOVEI P3,1 ;PA048 In SOS the repeat count is always 1
CEUP: JUMPE P3,CETOP ;PA048 Done if repeat count 0
SKIPL P3 ;PA048 Repeat count negative?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST CEDOWN ;PA048 Treat as ^N
ENDIF. ;PA048
SOS P3 ;PA048 Decrement repeat count
HRRZ A,@CELPTR ;PA048 TAKE THE LEFT HAND LINK
SKIPN A ;CHECK FOR END OF LIST
JRST CEUP1 ;NOT AT END
SOS CELPOS ;PA048 Decrement THE LINE NUMBER
MOVEM A,CELPTR ;UPDATE POINTER
JRST CEUP ;PA048 Loop in case argument was not 1
CEUP1:
;PA048 MOVE A,CELAST ;END OF LIST, GO BACK TO THE FIRST LINE
HRRZ A,HSTLST ;PA048 End of list, get newest command
MOVEM A,CELPTR ;RESET THE POINTER
;PA048 SETZM CELPOS ;RESET LINE NUMBER
MOVE A,CMDNUM ;PA048 Get right line number
MOVEM A,CELPOS ;PA048 Reset line number
JRST CEUP ;PA048 Loop in case argument was not 1
; Here to delete the character at the cursor
CERMSP: JUMPE P3,CEINC ;PA048 If repeat count is 0 we're done
SKIPL P3 ;PA048 Repeat count negative?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST CERUB ;PA048 Treat as <Del>
ENDIF. ;PA048
CAIG P3,1 ;PA048 Repeat count greater than one?
IFSKP. ;PA048
MOVE B,P3 ;PA048 Yes, get number of characters to delete
MOVEI P3,1 ;PA048 Delete them only once
JRST METAD0 ;PA048 Go join the M-D code
ENDIF. ;PA048
;Here if repeat count is one:
MOVE B,CEBPTR ;GET DESTINATION POINTER
MOVEI A,1
ADJBP A,CEBPTR ;POINTER TO SOURCE
LDB C,A ;ZERO BYTE?
JUMPE C,CEINC ;EM74 (Fix bug (check C, not A)) YES, QUIT
SETZ C, ;NO, MOVE THE TEXT
SIN
MOVEI A,CR
PBOUT ;START OVER
CALL CENUMB ;WRITE THE LINE NUMBER
HRROI A,CETBUF ;AND THE LINE
PSOUT
CALL EEOLN
JRST CINST1 ;POSITION THE CURSOR
; Here to move the cursor to the beginning of the line
CEBEGN: MOVEI A,CETBUF ;FIX POINTER
HLL A,[POINT 7,0]
MOVEM A,CEBPTR
SETZM CECPOS ;RESET POINTER TO BEGINNING OF LINE
MOVEI A,CR
PBOUT ;MOVE CURSOR TO BEGINNING
CALL CENUMB ;WRITE THE LINE NUMBER
JRST CEINC ;GET NEXT COMMAND
;PA048 Here on ^K command
CECTLK: SKIPLE P3 ;PA048 Argument strictly positive?
JRST CEKILL ;PA048 Yes, kill to end of line
MOVE B,CECPOS ;PA048 No, get number of chars to kill
JRST METAR0 ;PA048 Kill to beginning of line
; Here to kill everything to the right of the cursor
CEKILL: SETZ A, ;CHOP OFF THE REST OF THE STRING
MOVE B,CEBPTR ;GET COPY OF POINTER
IDPB A,B ;CURSOR IS ONE POSITION PAST POINTER
CALL EEOLN ;ERRASE IT FROM THE SCREEN
JRST CEINC ;GET NEXT COMMAND
; Here to swap the character at the cursor and the one before it
CATRAN: MOVEI P3,1 ;PA048 In SOS, arg is always 1
CETRAN: JUMPE P3,CEINC ;PA048 Done if repeat count zero
SKIPG P3 ;PA048 Repeat count negative?
JRST CETRA3 ;PA048 Yes, do differently
;Here if repeat count is positive:
SKIPN CECPOS ;BEGINNING OF LINE?
JRST CEINC ;YES, SKIP
MOVE B,CEBPTR
ILDB A,B ;END OF LINE?
JUMPE A,CEINC
CETRA2: MOVE B,CEBPTR ;GET LOCAL POINTER
MOVEI A,1 ;SCOOT OVER ONE
ADJBP A,B
MOVEM A,CEBPTR ;PA048 Save updated pointer
AOS CECPOS ;PA048 Move to the right
LDB C,A ;CHANGE THE CHARACTERS IN THE BUFFER
LDB D,B
DPB D,A
DPB C,B
SOJE P3,CETRA9 ;PA048 Done if repeat count exceeded
MOVE B,CEBPTR ;PA048
ILDB A,B ;PA048 End of line?
JUMPE A,CETRA9 ;PA048 Yes, we can do no more
JRST CETRA2 ;PA048 No, keep going
;PA048 Here if repeat count is negative:
CETRA3: MOVE A,CECPOS ;Get line position
CAIG A,1 ;Too close to the beginning of the line?
JRST CEINC ;Yes, skip
CETRA4: MOVE B,CEBPTR ;GET LOCAL POINTER
SETO A, ;SCOOT OVER ONE
ADJBP A,B
MOVEM A,CEBPTR ;PA048 Save updated pointer
SOS CECPOS ;PA048 Move to the left
LDB C,B ;CHANGE THE CHARACTERS IN THE BUFFER
LDB D,A
DPB D,B
DPB C,A
AOJE P3,CETRA9 ;PA048 Done if repeat count exceeded
MOVE A,CECPOS ;PA048 Get line position
CAIG A,1 ;PA048 Too close to the beginning?
JRST CETRA9 ;PA048 Yes, we can do no more
JRST CETRA4 ;PA048 No, keep going
;PA048 Here when done (repeat count hit zero or we ran into an end
;of the line):
CETRA9: ;PA048
MOVEI A,CR
PBOUT ;REWRITE THE LINE
CALL CENUMB
HRROI A,CETBUF
PSOUT
JRST CINST1 ;POSITION CURSOR
; Here to move to the beginning of the next word
METAF: JUMPE P3,CEINC ;PA048 Stop if repeat count is zero
SKIPL P3 ;PA048 Repeat count less than zero?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST METAB ;PA048 Go do a M-B
ENDIF. ;PA048
CALL F.WORD ;GET DESTINATION
;PA048 ^F with an argument greater than 1 enters here:
METAF0: ;PA048
ADDM B,CECPOS ;UPDATE POSITION
JUMPE B,CEINC ;NO MOVEMENT, STOP
MOVN C,B ;PA048, EM74 - Number of characters to move
ADJBP B,CEBPTR ;UPDATE POINTER
PUSH P,B ;EM74 And save it
MOVE B,CEBPTR ;EM74 Start of what we want to type
MOVE A,COJFN ;EM74
SOUT ;EM74 Print over one word
POP P,CEBPTR ;EM74 Update pointer
JRST CEINC ;EM74
; Here to move to the beginning of the previous word
METAB: JUMPE P3,CEINC ;PA048 Stop if repeat count is zero
SKIPL P3 ;PA048 Repeat count less than zero?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST METAF ;PA048 Go do a M-F
ENDIF. ;PA048
CALL B.WORD ;GET DESTINATION
;PA048 ^B with an argument greater than 1 joins here:
METAB0: ;PA048
JUMPE B,CEINC ;SKIP IF NO MOVEMENT
MOVNS B ;MAKE IT NEGATIVE
MOVE C,B ;GET A COPY OF IT
ADJBP C,CEBPTR ;UPDATE THE POINTER
MOVEM C,CEBPTR
ADDM B,CECPOS ;UPDATE POSITION
METAB1: PUSH P,B ;EM74 Save number of chars to back up
CALL CEBACK ;EM74 Back up one
POP P,B ;EM74
AOJN B,METAB1 ;EM74
JRST CEINC ;EM74
; Here to delete up to the beginning of the next word
METAD: JUMPE P3,CEINC ;PA048 Stop if repeat count is zero
SKIPL P3 ;PA048 Repeat count less than zero?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST METARB ;PA048 Go do a M-<Del>
ENDIF. ;PA048
CALL F.WORD ;GET DESTINATION
;PA048 ^D with an argument graeter than 1 joins here:
METAD0: ;PA048
MOVE A,B ;GET COPY OF OFFSET
ADJBP A,CEBPTR ;POINTER TO DESTINATION
JRST M.FIX ;MOVE EVERYTHING
; Here to delete back to the beginning of the previous (or this) word
METARB: JUMPE P3,CEINC ;PA048 Stop if repeat count is zero
SKIPL P3 ;PA048 Repeat count less than zero?
IFSKP. ;PA048
MOVNS P3 ;PA048 Yes, make it positive
JRST METAD ;PA048 Go do a M-D
ENDIF. ;PA048
CALL B.WORD ;GET DESTINATION
;PA048 <Del> with an argument greater than 1 enters here. So does
; ^K with a negative argument:
METAR0: ;PA048
MOVE A,CEBPTR ;PA048, EM74
ILDB D,A ;PA048, EM74 See if next char is end of line
PUSH P,D ;PA048, EM74 Save it
MOVN D,B ;MAKE IT NEGATIVE
MOVE A,D
ADDM A,CECPOS ;FIX UP POSITION
ADJBP A,CEBPTR ;GET DESTINATION POINTER
EXCH A,CEBPTR ;FOOL M.FIX - WE ARE NOW A M-D
PUSH P,D ;SAVE HOW MANY CHARS TO DELETE
PUSH P,A ;SAVE THE POINTER
METAR1: JUMPE D,METAR2 ;NEED TO MOVE THE CURSOR OVER
PUSH P,D ;SAVE LOOP COUNTER
CALL CEBACK ;BACK UP
POP P,D ;RESTORE LOOP COUNTER
AOJA D,METAR1
METAR2: POP P,A ;RESTORE THE POINTER
POP P,D ;GET BACK HOW MANY CHARS WE DELETED
POP P,B ;EM74 Get char we saved
JUMPE B,CEKILL ;EM74 If we were at EOL, just kill it
JRST M.FIX ;OTHERWISE DELETE THE CHARS
;M-S - Search forward for a character
METAS: JUMPE P3,CEINC ;Stop if repeat count is zero
SKIPL P3 ;Repeat count less than zero?
IFSKP. ;Yes...
MOVNS P3 ;Make it positive
JRST METAR ;And go do a M-R
ENDIF.
PBIN ;Get the character to search for
CAIL A,"a" ;Lowercase letter?
CAILE A,"z"
TRNA ;No
SUBI A,"a"-"A" ;Yes, make it uppercase
MOVE C,CEBPTR ;Get local copy of pointer
SETZ B, ;Zero the count of chars we moved past
METAS0: ILDB D,C ;Get the next char
IFE. D ;If it's a null
CALL CEBELL ;Feep the person
JRST CEINC ;And go try again for another command
ENDIF.
CAIL D,"a" ;Lowercase letter?
CAILE D,"z"
TRNA
SUBI D,"a"-"A" ;Yes, make it uppercase
AOS B ;Count another char we did
CAME A,D ;Do they match?
JRST METAS0 ;No, go get the next
SOJG P3,METAS0 ;Go until we find that many
JRST METAF0 ;And go forward that many chars
;M-R - Search backward for a character
METAR: JUMPE P3,CEINC ;Stop if repeat count is zero
SKIPL P3 ;Repeat count less than zero?
IFSKP. ;Yes...
MOVNS P3 ;Make it positive
JRST METAS ;And go do a M-S
ENDIF.
PBIN ;Get the character to search for
CAIL A,"a" ;Lowercase letter?
CAILE A,"z"
TRNA ;No
SUBI A,"a"-"A" ;Yes, make it uppercase
MOVE C,CEBPTR ;Get local copy of pointer
MOVN B,CECPOS ;Get -number of chars we're at
HRLZS B ;Make an AOBJN pointer for the position
IFE. B ;If already at the beginning
CALL CEBELL ;Feep the person
JRST CEINC ;And go back
ENDIF.
MTAR.0: LDB D,C ;Get the char we're pointing to
CAIL D,"a" ;Lowercase letter?
CAILE D,"z"
TRNA
SUBI D,"a"-"A" ;Yes, make it uppercase
CAMN A,D ;Do they match?
JRST MTAR.1 ;Yes, see if we're done
MTAR.2: SETO D, ;Want to decrement the pointer
ADJBP D,C ;Decrement it
MOVE C,D ;Get it in the right ac
AOBJN B,MTAR.0 ;Go on if there are more chars to do
CALL CEBELL ;Otherwise feep the person
JRST CEINC ;And go back
MTAR.1: SOJG P3,MTAR.2 ;Continue if we need more, check char count
HRRZS B ;Isolate the character count
AOS B ;Fudge to move back at least one char
JRST METAB0 ;And go back that many chars
; Here to fix things up after Metad, Metarb, or Alter mode delete
M.FIX: MOVE B,A ;GET COPY OF DESTINATION POINTER
SKIPN CEDUMB ;EMACS OR SMART ALTER?
PSOUT ;YES, OVERWRITE THE SCREEN
CALL EEOLN ;CLEAN THINGS UP
MOVE A,CEBPTR ;GET CURRENT POINTER
M.FIX1: ILDB C,B ;GET FIRST CHARACTER
IDPB C,A ;SAVE IN NEW POSITION
JUMPN C,M.FIX1 ;DONE?
JRST CINST1 ;POSITION THE CURSOR
; Subroutine to return number of spaces until start of next word
F.WORD: SAVEAC <P3> ;PA048 Don't clobber repeat count
SETZ B, ;INITIALIZE COUNT
MOVE C,CEBPTR ;GET LOCAL COPY OF POINTER
ILDB A,C ;GET THIS CHARACTER
JUMPE A,[RET] ;END OF LINE, QUIT
CALL SKPNAN ;PA048 Check if alphanumeric
JRST F.WRD2 ;EM74 It is
F.WRD1: ILDB A,C ;GET NEXT CHARACTER
AOS B ;UPDATE COUNT
JUMPE A,[RET] ;END OF LINE
CALL SKPNAN ;PA048 Alphanumeric?
JRST F.WRD2 ;EM74 Yes
JRST F.WRD1 ;EM74
F.WRD2: ILDB A,C ;GET NEXT CHARACTER
AOS B ;INCREMENT COUNT
JUMPE A,[RET] ;END OF LINE
CALL SKPNAN ;PA048 Alphanumeric?
JRST F.WRD2 ;EM74 Yes
SOJG P3,F.WRD1 ;PA048 Skip if repeat count still positive
RET ;No, DONE.
; Subroutine to return number of spaces until start of previous word
B.WORD: SAVEAC <P3> ;PA048 Don't clobber repeat count
SETZ B, ;INITIALIZE COUNT
MOVE C,CEBPTR ;GET LOCAL COPY OF POINTER
MOVE D,CECPOS ;LOCAL COPY OF POSITION
BWRD00: ;PA048
JUMPE D,[RET] ;BEGINNING OF LINE, EXIT
ILDB A,C ;GET THIS CHARACTER
CALL SKPNAN ;PA048 Alphanumeric?
JRST B.WRD0 ;EM74 Yes
JRST B.WRD1
B.WRD0: LDB A,CEBPTR ;GET CHARACTER BEFORE THIS ONE
CALL SKPNAN ;PA048 Alphanumeric?
JRST B.WRD2 ;EM74 Yes
B.WRD1: SETO A, ;BACKUP THE POINTER
ADJBP A,C
MOVE C,A
LDB A,C ;GET NEXT ONE
SOS D ;UPDATE COUNT
AOS B ;UPDATE THIS TOO
JUMPE D,[RET] ;CHECK FOR BEGINNING OF LINE
CALL SKPNAN ;PA048 Alphanumeric?
JRST B.WRD2 ;EM74 Yes
JRST B.WRD1 ;EM74 No
B.WRD2: SETO A, ;BACKUP THE POINTER
ADJBP A,C
MOVE C,A
LDB A,C ;GET NEXT CHARACTER
SOS D ;UPDATE EVERYTHING
AOS B
JUMPE D,[RET] ;CHECK FOR BEGINNING OF LINE
CALL SKPNAN ;PA048 Alphanumeric?
JRST B.WRD2 ;EM74 Yes
SOSG P3 ;PA048 Want to repeat some more?
IFSKP. ;PA048
SETO A, ;PA048 Yes
ADJBP A,C ;PA048 Back up the byte pointer one more
MOVEM A,C ;PA048 Save it
SOS D ;PA048 Remember column
JRST BWRD00 ;PA048 Loop
ENDIF. ;PA048
SOS B ;ADJUST IF NOT BEGINNING OF LINE
RET ;ALL DONE
;PA048 Subroutine which skips if a character is not alphanumeric
;
;Takes:
; A/ character
;Returns:
; +1/ character is alphanumeric
; +2/ otherwise
;Clobbers:
; No AC's
;
SKPNAN: CAIL A,"a" ;Lowercase letter?
CAILE A,"z" ; ...
TRNA ;No
RET ;Yes, return false
CAIL A,"A" ;Uppercase letter?
CAILE A,"Z" ; ...
TRNA ;No
RET ;Yes return false
CAIL A,"0" ;Digit?
CAILE A,"9" ; ...
RETSKP ;No, must be alphanumeric so return true
RET ;Yes, so return false
; Here to stick an Escape or question mark on the end of the command
METAES: SKIPGE P3 ;Argument negative?
JRST METAE2 ;Yes, handle differently
CAIN P3,0 ;Argument of zero
MOVEI P3,1 ;Use argument of one
REPEAT 0,<
CAIE P3,1 ;CU79 simple case?
IFSKP. ;CU79 yes..
LDB A,CEBPTR ;CU79 get char before cursor
CALL SKPNAN ;CU79 alphanumeric?
SKIPA ;CU79 yes...
JRST METAE3 ;CU79 no, skip this M-F, M-B stuff
ENDIF. ;CU79
>;REPEAT 0
PUSH P,P3 ;Save argument
MOVE B,CEBPTR ;Get a copy of current position pointer
ILDB A,B ;Advance it one
SKIPN A ;Got a null (ie, at end of line)?
IFSKP.
MOVEM B,CEBPTR ;No, save updated pointer
AOS CECPOS ;Update column, too. This hack makes us do
; the right thing if we start out on top of
; the first char of a word...
ENDIF.
MOVEI P3,1 ;First, back up a word
CALL B.WORD ;...
MOVNS B ;Negate amount to move backwards
ADDM B,CECPOS ;Update current column
ADJBP B,CEBPTR ;Update current char byte pointer
MOVEM B,CEBPTR ;Save updated pointer
POP P,P3 ;Get back argument
CALL F.WORD ;Compute how far to move forward
ADDM B,CECPOS ;Update current column
ADJBP B,CEBPTR ;Update current char byte pointer
MOVEM B,CEBPTR ;Save updated pointer
JRST METAE3 ;Go stick in <Esc> and go for it
METAE2: PUSH P,P3 ;Save the argument
MOVNS P3 ;Make argument positive
AOS P3 ;Add fudge factor
CALL B.WORD ;Compute amount to back up
MOVNS B ;Negate amount to move backwards
ADDM B,CECPOS ;Update current column
ADJBP B,CEBPTR ;Update current char byte pointer
MOVEM B,CEBPTR ;Save updated pointer
MOVEI P3,1 ;Now move to end of current word
CALL F.WORD ;Compute distance
ADDM B,CECPOS ;Update current column
ADJBP B,CEBPTR ;Update current char byte pointer
MOVEM B,CEBPTR ;Save updated pointer
POP P,P3 ;Get back argument
;Here with CEBPTR pointing to the place to deposit the <Esc>. Save
;the part of the command which is after the cursor position, deposit
;an <Esc> and a null at the cursor position, and go do the command:
METAE3:
MOVE B,CEBPTR ;CU79 Get copy of cursor pointer
ILDB A,B ;CU79 Get char under cursor
DO.
SKIPE A ;CU79 Null (ie, reached end of buffer)?
REPEAT 0,<
CALL SKPNAN ;CU79 or alphanumeric?
JRST ENDLP. ;CU79 Yes, go on
CAIE A,.CHSPC ;CU79 Space?
CAIE A,.CHTAB ;CU79 or tab?
JRST ENDLP. ;CU79 Yes, go on
CAIN A,"/" ;CU79 Slash is also ok (I think)
JRST ENDLP. ;CU79
>
CAIE A,")" ;CU79 Field suffix?
CAIN A,":" ;CU79
TRNA ;CU79
JRST ENDLP. ;CU79
MOVEM B,CEBPTR ;CU79 No, remember we moved forward
AOS CECPOS ;CU79 Remember where we are
ILDB A,B ;CU79 Move forward past punctuation
LOOP. ;CU79 And around again
OD. ;CU79
HRROI A,CEROCB ;Get pointer to place to save string
MOVE B,CEBPTR ;Get pointer to remainder of command
SETZ C,
SOUT% ;Save the rest of the command
MOVE A,CEBPTR ;Get back pointer to where to put <Esc>
MOVEI B,.CHESC ;Get an <Esc>
IDPB B,A ;Stash it at the end of the buffer
SETZ B, ;Then a null
IDPB B,A ;...
MOVEI A,2 ;We want to allow one reparse (because
MOVEM A,CESCHK ; we exit from the editor via REPARS)
CALL CEQUIT ;Go back to regular tty modes
HRROI A,CETBUF ;Get pointer to command line
SETZ B, ;Don't want prompt typed
CALL C2CBUF ;Copy line to atom buffer
RET ;Go do the command
; M-? Comes here
METAQU: SETZM EDITFL ; Don't do a confirm
MOVEI B,"?" ; STUFF ? WITH THE COMMAND
METAEQ: ILDB A,CEBPTR ; LOOK FOR THE END OF THE LINE
JUMPE A,METEQ1
JRST METAEQ ; TRY AGAIN
METEQ1: DPB B,CEBPTR ; STUFF THE NEW CHARACTER
IDPB A,CEBPTR ; ADD A ZERO BYTE
CALL CEQUIT ;Go back to regular tty modes
HRROI A,CETBUF ;Get pointer to command line
CALL FAKTYP ;Copy line to atom buffer and echo it
RET ;Go do the command
; Here when done. Stuff the edited command into the terminals input buffer
;CU79 On terminals which have parity set this code to read the LF does not
;CU79 work properly because the monitor will not add LF to a CR+PARITY.
;CU79 Allow this case by checking to see if a character is present before
;CU79 looking for the LF.
CECRLF: MOVX A,.PRIIN ;CU79 Check terminal for
SIBE% ;CU79 any characters present.
SKIPA ;CU79 yes, check it out for LF
JRST CEEXIT ;CU79 otherwise continue
PBIN% ;PA048 Read the LF
CAIN A,.CHLFD ;PA048 Really a LF
IFSKP. ;PA048 No (is this possible???)
MOVX A,.PRIIN ;PA048
BKJFN% ;PA048 Unread the character
ENDIF. ;PA048
CEEXIT: MOVEI C,CETBUF ;POINT TO CURRENT LINE
HRLI C,440700
;;PA048 MOVEI A,.CTTRM ;GET THE TERMINAL DESIGNATOR
;;PA048 CFIBF
CEEX2: ILDB B,C ;GET NEXT CHAR
JUMPE B,CEEX3 ;END ON A ZERO BYTE
;;PA048 STI ;STUFF IT
JRST CEEX2 ;DO THE REST
CEEX3:
MOVEI B,CR
;;PA048 STI
DPB B,C ;;PA048 Drop a CR on top of the nul
MOVEI B,.CHLFD ;;PA048 Then add
DPB B,C ;;PA048 a LF
SETZ B, ;;PA048 Load a null
IDPB B,C ;;PA048 Null-terminate the string
MOVEI A,CETBUF ;;PA048 Point to current line again
HRLI A,440700 ;;PA048 ...
SETZ B, ;;PA048 Don't type a prompt
CALL C2CBUF ;;PA048 Stick command in the command buffer
;; without echoing
TYPE <
> ;;PA048 Type a CRLF for neatness
CEQUIT: MOVEI Q1,ETTYMD ;LOAD EXEC TTY MODES
CALL LTTYMD
MOVEI A,.CTTRM ;RESTORE PAGE MODE IF WE NEED TO
MOVE B,CETTMD ;PA048 Get terminal modes
STPAR
;PA048 SETOM CEBPTR ;DON'T SAVE THIS
;PA048 ETYPE <
;PA048>
RET
;PA048 Here on ^G in Emacs or Q in SOS - forget about all editing, retype
; line which we started out editing, and quit
CEABRT: SETZM CESCHK ;CU79 Make sure we don't come back here
SETZM EDITFL ;CU79 Turn of /noconfirm or /edit action
CALL CEQUIT ;PA048 Fix TTY modes
MOVE A,CEORIG ;PA048 Get pointer to history entry we
; were editing
HRROI A,2(A) ;PA048 Get pointer to text of command
CALL FAKTYP ;PA048 Display it and copy it into CBUF
RET ;PA048 All done
;PA048 Here on ^C in either editor. Fixes tty modes and then simulates
;typein of a ^C (which, if ^C's are allowed, is handled by Exec's ^C
;handler since we've gotten ourselves out of binary mode)
CECTLC: CALL CEQUIT ;Fix tty modes
MOVEI A,.CTTRM ;Point at controlling tty
CFIBF% ;Clear typeahead
ERJMP .+1
; This does not work... Try
; "daytime<esc>^X<esc><esc>^C^X^C"
; MOVX B,.CHCNC ;Get ^C
; STI% ;"Type" it
MOVEI A,.FHSLF ;CU79 interrupt self
MOVX B,1B1 ;CU79 on ^C channel
IIC% ;CU79
ERJMP .+1 ;CU79
RET ;Return if ^C currently disabled
; Routine to redisplay the line
CERDSP: MOVEI A,.CHCRT ;PA048 Get CR
PBOUT% ;PA048 Get to beginning of line
SKIPE CEDUMB ;PA048 Go to new line only on stupid ttys
CEDISP: TYPE <
> ;PA048 (Use TYPE instead of ETYPE) for simple
; stuff) GO TO A NEW LINE
CALL EEOLN ;JUST TO BE SURE
CALL CENUMB ;DO THE LINE NUMBER
HRROI A,CETBUF ;POINT TO COMMAND LINE
PSOUT ;WRITE IT OUT
JRST CINST1 ;POSITION THE CURSOR
; Routine to send a bell to the terminal
CEBELL: MOVE A,COJFN ;REDO THE CCOC
RFCOC
PUSH P,B ;SAVE MODE
TLC B,1B32!1B33 ;SEND ACTUAL CODE
SFCOC
MOVEI B,.CHBEL ;SEND THE BELL
BOUT
POP P,B ;RESTORE
SFCOC
RET
; Routine to back the cursor up one place
CEBACK: MOVE A,COJFN ;GET THE TERMINAL TYPE
RFMOD ;GET MODE WORD
PUSH P,B ;SAVE IT
TXZ B,TT%DAM ;NO TRANSLATION
SFMOD
GTTYP
REPEAT 0,< ;Old way...
HRROI A,[ASCIZ //] ;ASSUME NORMAL TERMINAL
CAIE B,.TT100 ;GET THE VT100 TYPES OUT OF THE WAY
CAIN B,.TT125
HRROI A,[ASCIZ /[D/]
CAIN B,.TTK10 ;CU79
HRROI A,[ASCIZ /[D/]
CAIE B,.TTK10
CAIN B,.TTANS
HRROI A,[ASCIZ /[D/]
CAIN B,.TTAMB
HRROI A,[ASCIZ /[D/]
CAIN B,.TTB10 ;BEEHIVES
HRROI A,[ASCIZ /D/]
>;REPEAT 0
REPEAT 1,< ;New way...
CAIG B,NTTTYP ;Type number bigger than we know about?
SKIPN B,TTYPE1(B) ;Get address of table entry for this tty type
JRST EEOLN2 ;None - do nothing
SKIPN A,.CURBK(B) ;Get cursor backup sequence
JRST EEOLN2 ;None - do nothing
TLNE A,-1 ;String or 0,,address of string?
HRROI A,.CURBK(B) ;String - point to it instead
HRLI A,(<POINT 8,0>) ;Make 8-bit pointer
CEBAK2:
>;REPEAT 1
MOVE B,A ;use the string pointer we made
MOVE A,COJFN ;output to terminal
.STP==377 ;USED IN EXECTT
CALL STPOUT ;shove that string out
MOVE A,COJFN ;RESTORE MODE WORD
POP P,B ;GET OLD MODE
SFMOD ;DO IT
RET
CEBAK3: HRROI A,[ASCIZ //] ;No table entry, assume normal terminal
JRST CEBAK2
; Routine to errase all characters to the end of line
EEOLN: PUSH P,A ;SAVE THIS
PUSH P,B ;THIS TOO
MOVE A,COJFN ;CURRENT OUTPUT JFN
RFMOD ;GET MODE WORD
PUSH P,B ;SAVE IT
TXZ B,TT%DAM ;NO TRANSLATION
SFMOD
GTTYP ;GET TERMINAL TYPE
REPEAT 0,< ;Old way...
CAIG B,EOLNMX ;ALL WE KNOW ABOUT NOW
SKIPN A,EEOLTB(B) ;GET STRING TO DUMP
JRST EEOLN2 ;NONE - DO NOTHING
TLNN A,-1 ;STRING OR PNTR?
TLOA A,-1 ;PNTR TO TEXT
HRROI A,EEOLTB(B) ;STRING - POINT TO IT INSTEAD
>;REPEAT 0
REPEAT 1,< ;New way...
CAIG B,NTTTYP ;Type number bigger than we know about?
SKIPN B,TTYPE1(B) ;Get address of table entry for this tty type
JRST EEOLN2 ;None - do nothing
SKIPN A,.CUREL(B) ;Get clear-to-end-of-line sequence
JRST EEOLN2 ;None - do nothing
TLNE A,-1 ;String or 0,,address of string?
HRROI A,.CUREL(B) ;String - point to it instead
HRLI A,(<POINT 8,0>) ;Make 8-bit pointer
>;REPEAT 1
MOVE B,A ;use the string pointer we made
MOVE A,COJFN ;output to terminal
CALL STPOUT ;shove that string out
EEOLN2: MOVE A,COJFN ;RESTORE MODE WORD
POP P,B ;GET OLD MODE
SFMOD ;DO IT
POP P,B ;RESTORE THIS
POP P,A ;THIS TOO
RET
;STPOUT souts a STG style cursor control string to the termial. The
;problem is that we DONT want to output the termination character (.STP),
;as it can have undesireable side effects! This code assumes that the
;string is relatively short. (it counts characters one at a time...)
STPOUT: PUSH P,B
SETZB C,D
STPOU1: ILDB D,B ;get a character
CAIE D,.STP ;is it the terminator?
IFSKP.
POP P,B ;get back pointer to beginning of string
SOUT
RET
ENDIF.
SOJA C,STPOU1 ;increment count, step though string
; ERRASE TO END OF LINE TABLE
REPEAT 0,< ;No longer used
EEOLTB: 0 ;(0) Tty 33
0 ;(1) Tty 35
0 ;(2) Tty 37
0 ;(3) TI
0 ;(4)
0 ;(5)
0 ;(6)
0 ;(7)
0 ;(8) System default
0 ;(9) Ideal
BYTE(7) 36,0 ;(10) VT05
BYTE(7) .CHESC,"K",0 ;(11) VT50
0 ;(12) LA30
0 ;(13) GT40
0 ;(14) LA36
BYTE(7) .CHESC,"K",0 ;(15) VT52
BYTE(7) .CHESC,"[","K",0 ;(16) VT100
0 ;(17) LA38
0 ;(18) LA120
BYTE(7) .CHESC,"K",0 ;(19) Regent-20
BYTE(7) .CHESC,"I",0 ;(20) IBM 3101
0 ;(21)
0 ;(22)
;CU79 Columbia terminal types
BYTE(7) 33,"U",33,"U"-"@",0 ;(23) Concept-100
BYTE(7) .CHESC,"I",0 ;(24) Fox
BYTE(7) .CHCRB,0 ;(25) Datamedia 1520A
0 ;(26) Glass
BYTE(7) .CHESC,"K",0 ;(27) DM30xx (like VT52's)
BYTE(7) .CHESC,"K",0 ;(28) HP 26xx
BYTE(7) 13,0 ;(29) Infoton-Vista
[BYTE(7) .CHESC,"I",.CHDEL,.CHDEL,.CHDEL,.CHDEL,.CHDEL,0] ;(30) Bantam
BYTE(7) .CHESC,"K",0 ;(31) Heath-19
BYTE(7) .CHESC,"K",0 ;(32) Telray
BYTE(7) .CHESC,"t",0 ;CU129 (33) Freedom-100
BYTE(7) .CHESC,"K",0 ;CU141 (34) Viewpoint erase to EOL.
0 ;CU146 (35) VT125
0 ;CU146 (36) VK100
BYTE(7) .CHESC,"[","K",0 ;CU146 (37) VT102
EOLNMX== .-EEOLTB-1
>;REPEAT 0
; Routine to type a help message for Emacs mode
CEHELP: CALL BLANK1 ;CLEAR THE SCREEN
HRROI A,HLPMS0 ;CU79 get the help message
PSOUT
PBIN ;CU79 want next display?
CAIE A," " ;CU79 well?
IFSKP. ;CU79 yes...
CALL BLANK1 ;CU79 so blank the screen
HRROI A,HLPMS1 ;CU79 get next page
PSOUT ;CU79 and output it
ENDIF.
JRST CEDISP ;CU79 and redisplay the line
;CU79 New help message
HLPMS0: ASCIZ/
The following commands can be used while in the command editor:
RETURN Execute edited command
CTRL-C Exit from the command editor
CTRL-G Exit from the command editor, but enter the command
CTRL-N Edit the next (more recent) command line
CTRL-P Edit the previous command line
CTRL-F Move forward one character
CTRL-B Move back one character
CTRL-L Redisplay the command line
CTRL-E Move to the end of the line
CTRL-A Move to the beginning of the line
CTRL-T Swap the character at the cursor with the one before it
CTRL-D Delete the character at the cursor
CTRL-K Delete everything to the right of the cursor
CTRL-Q Quote the next character for insert
---MORE---/
HLPMS1: ASCIZ /
DELETE Delete the character to the left of the cursor
ESCAPE F Move to the beginning of the next word
ESCAPE B Move to the beginning of the previous word
ESCAPE D Delete up to the beginning of the next word
ESCAPE DELETE Delete back to the beginning of the previous word
ESCAPE S <char> Search forward for <char> (case insensitive)
ESCAPE R <char> Search backward for <char> (case insensitive)
ESCAPE ESCAPE Perform recognition on current word
ESCAPE ? Add a question mark to the end of the command and exit
Any other character will be inserted into the command before the cursor.
/
; ROUTINE TO TYPE HELP MESSAGE FOR ALTER MODE
CAHELP: CALL BLANK1 ;TRY TO BLANK THE SCREEN
HRROI A,ALTHLP ;POINT TO THE STRING
PSOUT ;WRITE IT OUT
JRST CETOP
ALTHLP: ASCIZ /
This is the Alter mode command editor.
Return Execute edited command
E Execute edited command
Q Return to command level
Line Feed Edit the next command line
Escape Edit the previous command line
Control-U Ignore editing up to now and start over
I Enter insert mode (exit with an escape)
nSPACE Move forward n characters
nRUB Move back n characters
nW Move forward n words
Tab Move to the end of the line
X Move to the end of the line and enter insert mode
Control-L Redisplay the command line, move cursor to beginning
Control-R Redisplay the command line, stay at current cursor position
P Redisplay the command line, stay at current cursor position
\ Swap the character at the cursor with the one before it
nD Delete n characters at the cursor
nR Delete n characters then enter insert mode
: Delete everything to the right of the cursor
H Delete the rest of the line and enter insert mode/
;CU79 Begin addition
;
; ADDCFM - add a confirm to the contents of the command buffer
;
; Returns +1 always, preserves all registers
;
addcfm: atsave ;save the temp cells
move a,cmptr ;get the pointer to next field to be parsed
tlc a,-1 ;fix up hrroi-style pointer
tlcn a,-1
hrli a,(point 7,)
move b,cminc ;and the number of characters left to parse
adjbp b,a ;make a byte pointer to the end of the string
ldb a,b ;get the last byte
caie a,.chlfd ;is it a linefeed?
cain a,.chcrt ;or carriage return?
ret ;yes, already confirmed so do nothing
cain a,.chffd ;formfeed?
ret ;yes, that confirms as well
movei a,.chcrt ;not confirmed, so get a carriage return
idpb a,b ;deposit it
movei a,.chlfd ;get a linefeed character
idpb a,b ;deposit on the end of the string
setz a, ;get a null
idpb a,b ;tie off the command buffer
movei a,2 ;we lengthened the buffer by two, so
addm a,cminc ; increment the character count appropriately
ret ;and return
;CU79 End addition
;CU97 Redefine (logical name) sys:
.redef::saveac <p1> ;command length goes here (can't use a stkvar)
stkvar <ln,<lnbody,100>>
noise (logical name)
strx <logical name to edit> ;parse a logical name
cmerrx
call bufff ;buffer it up
confirm ;get a confirm
movem a,ln ;save the pointer to the logical name
call bcount ;get its length
movei p1,^d14(b) ;calculate length of "define foo: (as) "
movei a,.lnsjb ;a/ want a job-wide logical definition
move b,ln ;b/ pointer to the logical name
hrroi c,lnbody ;c/ destination pointer
lnmst% ;get the logical name body
ifnsk. ;if not a job-wide logical...
movei a,.lnssy ;a/ want a system-wide logical
move b,ln ;b/ pointer to the logical name
hrroi c,lnbody ;c/ pointer to the destination
lnmst% ;get the logical name body
setzm lnbody ;not defined, so make body null
endif.
move a,[point 7,buf0] ;use buf0 as a temporary string buffer
movem a,cojfn ;divert etype output to buf0
move 1,ln ;1/ logical name string
hrroi 2,lnbody ;2/ logical name definition
etype <define %1\: (as) %2\> ;if you change this, update p1 above
call fixio ;restore cojfn
move a,[point 7,buf0] ;get a pointer to the command to edit
call mkhrec ;make a history record
error <EXEC free space exhausted>
call addhst ;add it to the history list
cedstg ;set up local variable context for ceditu
call pioff ;don't allow ^C while we much things around
hrrz a,hstlst ;a/ pointer to the history list entry
move b,cmdnum ;b/ the command number
move c,p1 ;c/ the column we want to start in
call ceditu ;call the command editor
call rmvfst ;remove the history list entry
call pion ;allow ^C again
;Since FAKTYP was called a prompt was not issued and the terminal
; interrupt will not be enabled, enable it now.
hrlz a,cepsic ;get interrupt character's code
hrri a,cepchn ;get the channel to use
skipl a ;CEPSIC contains -1 (ie, none)
ati% ;no, so assign interrupt
setzm cipf ;say no command in progress
jrst repars ;go fix things up and parse the command
;CU97 End addition
END