Google
 

Trailing-Edge - PDP-10 Archives - BB-M836A-BM - tools/sed/sed.rno
There are 13 other files named sed.rno in the archive. Click here to see a list.
.ps 57 68 .autop
.VAR OLDTAB A B
.VAR NEWRUN A B
.IF NEWRUN
.HEADER BOTTOM
.ENDIF NEWRUN

.C;INSTALLATION MANUAL
.C;HOW TO ADAPT A TERMINAL TO THE SED SCREEN EDITOR
.C;AND OTHER USEFUL INFORMATION
.C;BY A CHRISTOPHER HALL
.C;June 1981

.S2
.C;MISCELLANEOUS INFORMATION

There are a number of assembly parameters at the beginning of the editor
program:

.s1 .lit
        MAXSIZ==^D1000  ;MAXIMUM FILE SIZE (BLOCKS) THAT CAN BE EDITED
        PCBSIZ==600     ;SIZE OF PICK AND CLOSE BUFFER
        NOBYTE==140     ;LENGTH OF LOOK-AHEAD WHEN SEARCHING FOR NULLS
        SQZVAL==100     ;NUMBER OF DELETE COMMANDS BETWEEN SQUEEZES
        XBFNUM==10      ;NUMBER OF EXECUTE BUFFERS
        XBFSIZ==14      ;SIZE OF EACH EXECUTE BUFFER
        TYPSIZ==40      ;SIZE OF TYPE BUFFER
.el .s1

None of these except MAXSIZ, XBFNUM, and XBFSIZ should need to be modified
unless the spirit moves you.

MAXSIZ depends on the amount of memory available to users on your system.
If SED tries to read in a file which is too large to fit in core it will
die horribly (without doing any damage), so set this parameter to
be as large as your memory can hold.

XBFNUM tells how many execute buffers there are, and XBFSIZ tells how
large each execute buffer is. The defaults are 8 buffers of 12 words (hence
60 characters) each. You have more or fewer, larger or smaller, buffers
(but there must be at least one).

Other switches you may want to set:

.s1 .lit
        TOPS10          1 if TOPS-10; 0 if TOPS-20
        FTKA10          1 if KA-10, else 0
        FTSFD           1 if you want SFD support, else 0
.el

If you set FTSFD, define SFDLVL to be the number of SFD levels you want.
Any number is permissable.

.S3
.c;ADAPTING SED TO A TERMINAL

All terminals which use the ASCII character set use the same codes
for the printing characters. That's the good news. The bad news
is that terminal control commands such as cursor movements and
screen control (clearing the screen, etc.) are done differently
almost everywhere, and the ability of a terminal to do things like
absolute cursor positioning, character highlighting, and other whiz-bang
features, varies even more. The more powerful an editor is, the more of
a demand it places on special terminal functions, and therefore the
more difficult it is to adapt a new terminal to use that editor.

SED is designed to be as powerful as it can get without becoming restricted
to a small class of terminals which are smart enough to run it, or needing
a large effort to write simulation subroutines to make it work with dumber
terminals.

Adapting SED to run on a new terminal must be done by a person who knows
MACRO assembly language. A handbook describing the terminal is also necessary,
unless you want to do a lot of guessing.

The program SEDECO (as in SED ECHO) can be used to figure out what character
sequences are sent by special terminal keys, and what effect sequences have
on the screen.

.S2
.c;THE GENERAL IDEA

Adapting SED to a terminal is a matter of setting up
a file which is loaded with SED.MAC.
This file contains two tables which handle incoming and outgoing
character sequences, two subroutines which perform cursor movement,
and perhaps some other routines to do things like setting up the terminal
or simulating functions which the terminal cannot do in hardware.

All of the files named SED??.MAC adapt SED to some terminal or other.
See SED.DIR to find out which file works with which terminal.

If your terminal already has a SED??.MAC file which works with it, your
job is done. Just load SED and edit.

Otherwise you will need to get out your terminal handbook and write
a driver. The file SEDX.MAC is a skeleton terminal file which you can
use as a template.

One of the two tables that needs to be set up (the terminal output table)
contains the character sequences which SED sends to the
terminal to get it to do interesting things (clearing the screen,
rolling, and so on), as well as some terminal-dependent values.
The other table (the terminal input table) maps sequences of characters
sent by the terminal into the values which SED uses internally to
represent its commands. Descriptions of the formats of these tables make
up the bulk of this document.

.S2
.c;OVERVIEW OF THE INSIDE OF SED

SED works as follows: when it receives a printing ASCII character (Octal
codes 40-176) from the terminal it puts it in the file and types it on
the screen.

Other characters (Octal 0-37 and 177) are used to signal that a command is
coming. SED converts the user type-in to an internal command code, and
dispatches on the code to perform the command. Any sequence of characters
which starts with a control character or RUBOUT can be mapped into any
command code. Establishing that relationship is part of the installer's
job, and this manual tells you how.

For example, when the user types the CURSOR-UP key the terminal sends, say,
the two characters "ESCAPE A" to the editor. SED must know that when it
receives an ESCAPE it should read the next character, and if that character
is an "A" it should dispatch to command 36, which is CURSOR-UP.

The internal command codes run from 0 to 61 or so (octal), one for each
command.

The other half of the game is for SED to send the right character sequences
to the terminal to make it do interesting things, like clearing the screen,
absolute cursor positioning, or rolling the screen up or down. That
task will be handled first.

.PG
.C;THE TERMINAL OUTPUT TABLE

SED assumes that its terminals can do a number of special
functions. The codes to
do these functions are set up in the terminal output table.
Each entry in the table is one word long. Most entries are command sequences
or subroutine calls; some are flags or values.

The command sequence entries can be either a string of up to 5 characters
(which need not end with a null), the address of a longer string, or the
address of a subroutine. The subroutine can be used to output very long
sequences or to do more complex things
than just outputting characters. If your terminal does not have some
capability (like highlighting) put a CPOPJ in the table.

The format of the output command table is:

.s1 .lit
ITERML: CUP==0      ;CODE TO DO A CURSOR UP
        CDN==1      ;CODE TO DO A CURSOR DOWN
        CRG==2      ;CODE TO DO A CURSOR RIGHT
        CLF==3      ;CODE TO DO A CURSOR LEFT
        CHM==4      ;CODE TO DO A CURSOR HOME
        CPG==5      ;CLEAR TO END OF PAGE
        CLN==6      ;CLEAR TO END OF LINE
        RUP==7      ;ROLL SCREEN UP AND CLEAR NEW LINE *
        RLD==10     ;ROLL SCREEN DOWN AND CLEAR NEW LINE *
        PON==11     ;TURN HIGHLIGHTING ON
        POF==12     ;TURN HIGHLIGHTING OFF
        ILN==13     ;INSERT A BLANK LINE (0 IF NOT DEFINED)
        ISP==14     ;INSERT A SPACE (0 IF NOT DEFINED)
        DLN==15     ;DELETE A LINE  (0 IF NOT DEFINED)
        DSP==16     ;DELETE A CHARACTER (0 IF NOT DEFINED)
        MVB==17     ;MOVE TO BOTTOM OF PAGE *
        HCP==20     ;MOVE HOME AND CLEAR ENTIRE PAGE *
        PSC==21     ;ADDRESS OF ROUTINE TO POS'N TO (RW, CM)
        PSL==22     ;ADDRESS OF ROUTINE TO POS'N TO (T4, 1)
        LPP==23     ;NUMBER OF LINES PER PAGE
        CPL==24     ;NUMBER OF CHARACTERS PER LINE
        TCH==25     ;TERMINAL CHARACTERISTICS FLAGS
        RTE==26     ;ADDRESS OF ROUTINE TO CALL ON ENTRY
        RTX==27     ;ADDRESS OF ROUTINE TO CALL ON EXIT
        NUL==30     ;NUMBER OF NULLS TO OUTPUT,,NULL CHARACTER
        ITB==31     ;ADDRESS OF TERMINAL INPUT TABLE
        MAR==32     ;MARK TO PUT UP ON ENTER (IF NO HIGHLIGHTS)
.el .s1
*#These functions usually require more than one command to the terminal. For
example, MOVE TO BOTTOM might be done by HOME CURSOR-UP, or by
absolute positioning.
.s1
CURSOR MOVEMENTS

The cursor movements cause the cursor to move in the given direction
(or home).
.s1
CLEAR TO END OF LINE OR PAGE

Note that the clearing sequences are for clearing from the cursor position
to the end of the line or the screen, not the entire line or screen.
.s1
ROLLING THE SCREEN UP OR DOWN

Rolling the screen up means
moving every line on the screen up one line, eliminating the line
at the top, and adding a (blank) line at the bottom. Sometimes that
new bottom line will not be blank; it must then be cleared out. Rolling
down is similar. You can assume that the cursor is at the bottom of
the screen (top, for rolling down) while rolling is being done.
.s1
HIGHLIGHTING

Highlighting (which is often called "protection" in SED, for
historical reasons) means making a string of characters on the screen
stand out from the rest. Half intensity, blinking, and reverse video
are the most common ways of highlighting. The choice among these
is up to the implementor; blinking tends, however, to be annoying.
If your terminal does not have any highlighting, put CPOPJs in
table positions PON and POF and include the MAR table entry and MRK
terminal characteristic flag. Doing this
will cause a mark to be placed on the screen where the cursor used to be
when it is moved temporarily; it helps with the cursor movement commands.
.s1
INSERT OR DELETE LINES OR SPACES

Insert and delete lines or spaces are the sequences to do just that at the
terminal. Sending the insert line sequence will make a blank
line where the cursor is and move all lines beneath down. The bottom
line on the screen goes away. Delete line removes the line at the cursor
and moves every line beneath up. The bottom line on the screen is blank.
Insert space puts a space at the cursor position and moves the rest of the
line one character to the right. If a character goes off the right of the
screen, it is lost (the line does NOT wrap around). Delete character
removes the character at the cursor and moves the rest of the line one
character to the left.

IMPORTANT: if any of these four insert/delete sequences are undefined,
put a 0 in the table, not a CPOPJ.
.S1
CURSOR POSITIONING

Absolute cursor positioning is done differently by virtually every terminal.
The only thing the various algorithms have in common is the general format:
they begin with a sequence of characters which announces that absolute
positioning is being done. Then the row and column are output to the
terminal, encoded somehow. There are a million ways to encode the row and
column values.

Older versions of SED contained pre-programmed cursor positioning routines,
but there came to be too many of them, and the implementation procedure
was very awkward. So now the implementor will need to write his own
cursor positioning routines (or copy them, if they already exist).

A number of routines have been stored in the file SED.POS. They can be
copied directly into your driver program, or as guides for writing new
routines.

Two types of cursor positioning routines are needed. One positions to the
row whose value is in accumulator RW and the column in AC CM. The other
positions to the start of the line given by AC T4. Simply write these routines
in the terminal-dependent file and put their addresses in slots PSC and
PSL of the terminal output table. The PSC and PSL slots MUST contain
subroutine addresses.
.s1
TERMINAL CHARACTERISTICS FLAGS

The terminal characteristics flags tell SED about certain
restrictions and shortcuts allowed or required by
the terminal. These operations have already been programmed, so the
only thing you need to do is to set the appropriate flags.

The following flags can be set up:

.s1 .lit
        LSD    LINEFEED AND CURSOR DOWN ARE THE SAME CHARACTER
        TBS    HARDWARE TABS EXIST (AND ARE PRE-SET)
        WRP    LONG LINES WRAP AROUND TO NEXT LINE OF SCREEN
        MRK    NO PROTECTED FIELDS; THUS, MARK NEEDED ON ENTER
        NEL    DON'T BOTHER RE-WRITING LAST LINE OF SCREEN
        NLP    SEND NULLS AFTER ABSOLUTE CURSOR POSITIONING
        SLW    SLOW TERMINAL: WRITE ERROR MSGS ON BOTTOM LINE
        NPG    DON'T SET TTY NO PAGE (^S AND ^Q REMAIN XOFF AND XON)
.el .s1
Explanations:

(LSD) LINEFEED is normally a command which clears out the line to which the
cursor moves. If it and CURSOR-DOWN are indistinguishable (both code 012,
say), then the LINEFEED command is disabled, and just the CURSOR-DOWN remains.

(TBS) If hardware tabs do not exist they must be simulated using CURSOR-RIGHT's.
Beware: a lot of terminals have hardware tabs, but they must be set up by
someone. If SED expects tabs but they are not set up it will go
bananas, so don't set the TBS flag for these terminals (or enable the tabs in
a terminal-specific entry subroutine).

(WRP) Lines too long for the screen will either lock on the right margin or
wrap around to the next line, depending on the terminal. The editor display
routine needs to know which will occur, or else long lines will not display
properly. Note: some terminals, such as the VT100 (in wrap mode) will wrap
before the 81st character is typed, rather than after the 80th. Do not set
the WRP flag for those terminals and they will work o.k.

(MRK) A protected field is one which SED wants to highlight. For
example, when you type ENTER SED will highlight the character at the
cursor position (by making it reverse video, for example). It's useful to
mark that cursor location, so if the terminal does not have any highlighting
features, the MRK flag indicates that a certain mark should be put at the
cursor location when ENTER is typed. The character code for that mark is
contained in the last word of this table (if MRK is not set that mark word
can be omitted).

(NEL) Make SED not care about keeping the bottom line of the screen
up to date. If your terminal is slow and has enough lines on the screen
that it can afford to give one away, then some re-write time can be saved by
setting the NEL flag.

(SLW) Causes error messages to be written on the bottom line of the screen.
The remainder of the screen is not affected (normally the whole screen
is erased and re-done). If your terminal is slow you can save a lot of
rewriting by setting the SLW flag.

(NLP) If your terminal needs to idle a while after positioning the cursor, set
the NLP flag, and set the NUL word of the table to the number of nulls to
send and the character to use.

(NPG) Some terminals that run at 9600 baud (and others) will send CONTROL-S
(XOFF) to the computer to tell it to stop transmitting and CONTROL-Q
(XON) to tell the computer to resume. SED cannot tell XOFF and
XON from DELETE-SPACES and ROLL-BACK-PAGES, so if the terminal persists in
sending XON's and XOFF's set the NPG flag and don't use CONTROL-S and
CONTROL-Q as editor commands.
.S1
ENTRY AND EXIT ROUTINES

If your terminal needs to be initialized (TABS set up, for example), write
a subroutine (in SEDX.MAC) to do whatever is necessary and put its address
in slot RTE. That routine will be called just before SED reads in the
file to be edited. Similarly for a routine to do things on exiting from SED,
in slot RTX. That routine is called just before exiting.
Use CPOPJ if no special action is desired.
.s1
NULLS

There are a number of situations where SED needs to delay and let
the terminal finish what it is doing. The most reliable delay tactic is
to send some nulls to the terminal. A null is any character which causes
no action from the terminal. 000 is the classic null, but beware: some
terminals or communication lines ignore 000's, and the desired delay
does not occur. Suggestions: RUBOUT (177) or CONTROL-F (006). Anyway, the
situations which need a delay are set up in the terminal characteristics
flags, described elsewhere, and the number of nulls to output for each
delay and the null character are defined in the NUL word of the terminal
output table. If no delay is ever required (the "usual" case) set the NUL
word to 0 and don't set any of the NL? characteristics flags.
.s1
NOTE

The ASCII backspace (CONTROL-H) is probably the best way to do a cursor left,
even if a separate command sequence exists. Likewise, LINEFEED is usually a
good way of rolling the screen up and clearing the new line.

.pg
.c;THE TERMINAL INPUT TABLE

The terminal input table maps sequences of characters arriving from the
terminal into the internal editor commands. The editor commands are described
below. If the ordering seems strange it is because the commands are organized
with regard to their position on the typewriter keyboard, and not
alphabetically.

.s1 .lit
INTERNAL   COMMAND     "USUAL"                 FUNCTION
  CODE                SEQUENCE

    1   INSERT-SPACES    ^A     add some spaces at the cursor
    2   SET-FILE         ^B     set up a new file for editing
    3   ABORT            ^C     exit, forgetting changes
    4   INSERT-LINES     ^D     add some blank lines at the cursor
    5   SEARCH-BACK      ^E     search from cursor to start of file
    6   DELETE-LINES     ^F     remove some lines at the cursor
    7   PUT              ^G     add text to the file
   10   CURSOR-LEFT      ^H     move the cursor to the left
   11   TAB              ^I     move cursor to the next tab stop
   12  *CLEAR-LINE       ^J     erase the line below the cursor
.EL
.IFNOT OLDTAB
.LIT
   13   SLIDE-LEFT       ^K     move viewing window to the left
   14   SLIDE-RIGHT      ^L     move viewing window to the right
   15   CARRIAGE-RETURN  ^M     good ol' ASCII carriage return
   16   SWITCH           ^N     set operating switches, etc.
   17   ENTER-CTRL-CHAR  ^O     make the next char typed a ctrl char
   20   PERCENT-GOTO     ^P     move window to a percent of the file
   21   ROLL-BACK-PAGES  ^Q     move window back some pages
   22   SEARCH-FORWARD   ^R     search from cursor to end of file
   23   DELETE-SPACES    ^S     remove some characters from a line
   24   ROLL-FORW-LINES  ^T     move window forward some lines
   25   BACKTAB          ^U     move cursor to the previous tab stop
   26   PICK             ^V     load buffer with text from the file
.EL
.ELSE OLDTAB
.LIT
   13   PICK             ^K     load buffer with text from the file
   14   SLIDE-LEFT       ^L     move viewing window to the left
   15   CARRIAGE-RETURN  ^M     good ol' ASCII carriage return
   16   BACKTAB          ^N     move cursor to the previous tab stop
   17   ENTER-CTRL-CHAR  ^O     make the next char typed a ctrl char
   20   PERCENT-GOTO     ^P     move window to a percent of the file
   21   ROLL-BACK-PAGES  ^Q     move window back some pages
   22   SEARCH-FORWARD   ^R     search from cursor to end of file
   23   DELETE-SPACES    ^S     remove some characters from a line
   24   ROLL-FORW-LINES  ^T     move window forward some lines
   25   SLIDE-RIGHT      ^U     move viewing window to the right
   26   SWITCH           ^V     set operating switches, etc.
.EL
.ENDIF OLDTAB
.LIT
   27   ROLL-BACK-LINES  ^W     move window back some lines
   30   EXECUTE          ^X     execute a sequence of commands
   31   ROLL-FORW-PAGES  ^Y     move window forward some pages
   32   EXIT             ^Z     save file and exit
   33   ENTER            ESCAPE set up an argument for a command
   34   CURSOR DOWN      ^\
   35   CURSOR RIGHT     ^]
   36   CURSOR UP        ^^
   37   CURSOR HOME      ^_

    0   RESET            RUBOUT rewrite cursor, line, or screen
   40   RECALL           (NONE) recall latest argument
   41   INSERT-MODE      (NONE) insert/replace toggle
   42   DELETE-CHARACTER (NONE) delete character to the left of cursor
   43   REAL-TAB         (NONE) type a TAB into the file
   44   MARK             (NONE) mark position for PICK or DELETE
   45  *LINE             (NONE) move to start or end of line
   46   CASE             (NONE) change case of character at cursor
   47   WINDOW           (NONE) set or clear split-screen window
   50  *ERASE-LINE       (NONE) erase from cursor to end of line
   51   (not used)
   52   UP-TAB           (NONE) move the cursor up six lines
   53   DOWN-TAB         (NONE) move the cursor down six lines
   54   RE-WRITE         (NONE) re-write the screen
   55   SAVE-FILE        (NONE) saves the current file
   56   HELP             (NONE) give on-line help
   57  *BEGIN-LINE       (NONE) move the cursor to beginning of line
   60  *END-LINE         (NONE) move the cursor to the end of line
   61   ERASE-WORD       (NONE) erases the word ending at the cursor
.EL .S1
Note: all values regarding characters are in octal in this manual.

.S1 .I0
*#The LINE command has been superceded by BEGIN-LINE and END-LINE,
and CLEAR-LINE has been superceded by ERASE-LINE. LINE and CLEAR-LINE
remain for compatability, but do not need to be implemented at a new
site.

For a fuller description of what these commands do, see the reference
manual, SED.DOC.

The command invoked by RUBOUT (octal 177) is set up in the -1 location
of the input table (ie, the word before the label). Nominally RUBOUT
invokes the RESET command, so that -1 word should contain 0.

Normally the command with code n is invoked by typing CONTROL-n (for example,
SEARCH-BACKWARD by CONTROL-E). The commands which have internal codes above
octal 37 have no normal invocations. They were implemented after all the
control characters had been used up. If your terminal has some
user-defineable buttons on it you can make them invoke those commands. If
not, then if your terminal sends nulls (ASCII 000), then one of those
commands can be set up as CONTROL-SPACE.

The first thing to do is to figure out what input sequences from the terminal
should represent which commands. The decision is entirely arbitrary, but it
is a good idea to set up each command to be one keystroke (with or without
the control key depressed). Most often the control characters can be used to
represent the non-cursor movement commands. The sequences which define cursor
movement will be those which are sent when the cursor keys are pushed.
Undefined keys can be used in any manner you please.

The terminal input table is indexed by the character input from the terminal;
the values in the table are the internal commands. So if you want the user to
type a CONTROL-B and have a PUT occur, put 7 in word 2 of the table (the word
at the label is word 0).

The preceding discussion is adequate if each editor command is invoked by a
single control character from the terminal. However, if the terminal sends
two or more characters to represent a command things get a little more
complex. Suppose the cursor movement commands (UP, DOWN, RIGHT, LEFT, and
HOME) are invoked by ESCAPE something (like ESCAPE A for UP, ESCAPE H for
HOME, etc). Then word 33 of the table should contain a subtable pointer to
tell SED to read second character, and then how to interpret the
two-character sequence.

The 33rd word of the terminal input table would look like:

.s1 .lit
                -5,,SUBTAB
.EL .S1
This tells SED to read another character and go reference subtable SUBTAB
(which is 5 words long) to find out what to do. The subtable looks like:

.s1 .lit
        SUBTAB: 37,,"H"     ;ESCAPE H == HOME
                34,,"C"     ;ESCAPE C == CURSOR-UP
                35,,"B"     ;ESCAPE B == CURSOR-RIGHT
                36,,"A"     ;ESCAPE A == CURSOR-DOWN
                10,,"D"     ;ESCAPE D == CURSOR-LEFT
.EL

The general format of a subtable pointer is:

.s1 .lit
                -SIZE OF SUBTABLE ,, ADDRESS OF SUBTABLE
        or      -BIG NUMBER       ,, ADDRESS OF SUBTABLE
.EL .S1
In the latter case, the subtable must end with a zero word.

The subtable consists of one word for every sequence that begins with the
same character (in the above case, 5 words), plus maybe an extra zero word if
the second format above is used. Entries in the subtable are searched
sequentially from first to last, so any order is all right, but putting the
most expected commands first is a good idea.

Entries in a subtable can take two forms:

.s1 .lit
                INTERNAL COMMAND ,, CHARACTER
        or      SUBTABLE POINTER ,, CHARACTER
.el .s1
If CHARACTER is zero for either of these formats then any character input
will match. Otherwise characters not found in the subtable will cause an
ILLEGAL COMMAND message.

If your terminal's commands are all one or two characters long, then the
subtables will contain entries of the first form. When SED receives
the first character of the command it will point itself into the subtable;
when it receives the second it will set up the internal command which is in
the same word as that second character.

Now suppose the terminal sends a three-character sequence when some keys
are pressed. When SED receives the first character it goes to a subtable.
When it receives the second it should go to a sub-subtable, which tells
it to input a third character and then decide what the command is.

Since only the top-level table has room for the size of its subtable, all
sub-subtables must end in either a zero word or a word with a zero right
half. With the former case only characters explicitly set up in the table
will be recognized as legal; in the latter case, characters not found in the
table will be mapped into the command given by the left half of that word
whose right half is zero. Thus the subtable

.s1 .lit
        SUBTAB: 14,,"A"
                33,,"N"
                0
.el .s1
will map sequences ending in A to internal command 14, sequences ending in N
to command 33, and give an error for all others, whereas the subtable

.s1 .lit
        SUBTAB: 14,,"A"
                33,,0
.el .s1
will map the sequence ending in A to internal command 14 and all others
into internal command 33.
.s1
The sub-subtable

.s1 .lit
        SSBTAB: 33,,0
.el .s1
has the effect of ignoring the last character which has been input, since no
matter what that character is the sequence is mapped into code 33 (See the
example dealing with the ADM2 terminal).

Subtables can be stacked as deeply as desired; a command from the terminal
can be any number of characters at all.

As an example, say the terminal uses ESCAPE A for CURSOR-UP (ie, two
characters), ESCAPE $ + for CURSOR-HOME (three characters), and ESCAPE $ -
for ENTER. Then word 33 of the input table would contain

.s1 .lit
        -2,,SUBTAB      ;(ONLY 2 DIFFERENT 2-CHARACTER SEQUENCES)
.el .s1
The subtable would look like

.s1 .lit
        SUBTAB: 35,,"A"         ;ESCAPE A == CURSOR-UP
                SUBTB1,,"$"     ;ESCAPE $ NEEDS ONE MORE CHARACTER
.el .s1
And the sub-subtable,

.s1 .lit
        SUBTB1: 37,,"+"         ;ESCAPE $ + == HOME
                33,,"-"         ;ESCAPE $ - == ENTER
                0               ;END OF TABLE
.EL .S2
.C;ADAPTING MORE THAN ONE TERMINAL

If SED is to be used on a number of terminals it is up to the
installation to figure out how to tell SED what kind of terminal it is
running on. SEDX.MAC has examples of how to ask the monitor about the
terminal type.

So find out the terminal type somehow,
then do the following: build all your terminal tables in
SEDX.MAC. Set up the location TERMNL with the addresses of the terminal
output tables, one after another. Put the address of a routine to execute on
entry in the first output table. That routine should do whatever is necessary
to pick the right terminal and get a value from 0 to N-1 (if there are N
terminals). Then set up the contents of TERMNL indexed by that value in
accumulator TM.

For example, say you have ONTEL, VT52 and VT100 terminals. Say the names
of their output tables are OONTEL, OVT52 and OVT100. Then make TERMNL
look like:

.s1 .lit
        TERMNL: OONTEL
                OVT52
                OVT100
.el .s1
In the "routine to execute on entry" word of OONTEL set up the address,
say, DECIDE. The DECIDE routine figures out what terminal the user is
on and gets an index. If the terminal is a VT52, DECIDE would want to
get the value 1. Say that value is in AC T1. Then the instruction

.s1 .lit
                MOVE    TM,TERMNL(T1)
.el .s1
would make SED use the right set of tables.

Another way to solve the problem is to have a number
of editor programs, each of which runs on its own terminal. The user would
run, say, SEDV on a VT52 and SEDO on an ONTEL. This is klugey, but simple.

.s2
.C;ADDING A NEW COMMAND TO THE EDITOR PROGRAM

If you're a MACRO programmer, it's easy to add a new command to SED.
Just write a routine to do whatever-it-is. End it with a JRST LOOP,
which will go get another command. Look at other routines to find
out how to read parameters, erase them from the screen, and all that.

Once the routine is written, hook it up as a command in the command table.
Add a word to the table which starts at CMDTBL. The left half of the word
is the place to go if that command is typed along with a parameter; the
right half is where to go if no parameter was typed.

The internal value of the command is its index in the table. If some
terminal character sequence maps into that value, the command will be
invoked.

You must also invent a two-character name for your command and put it
at the end of the CMDNAM command name table.

.pg
.C;EXAMPLE 1: HOW THE VT52 LIVES WITH SED

It would be helpful to look at a VT52 terminal manual while reading
this section, unless you want to take my word for the command sequences.

Note: these examples are examples only. They differ a little from the
actual terminal drivers in order to illustrate additional features. If
you want to know what the VT52 or ADM2 world is really like, see
SEDV52.MAC or SEDA2.MAC.

The VT52 terminal is described to SED in the file SEDV52.MAC (SED
is loaded with the command .LOAD SEDV52,SED). The first step is to set
up the editor's output sequences. Define the terminal output table, OVT52,
as the following:

.s1 .lit
OVT52:  BYTE (7) 33,"A"         ;CURSOR UP
        BYTE (7) 33,"B"         ; DOWN
        BYTE (7) 33,"C"         ; RIGHT
        BYTE (7) 10             ; LEFT
        BYTE (7) 33,"H"         ; HOME
        BYTE (7) 33,"J"         ;CLEAR TO END OF PAGE
        BYTE (7) 33,"K"         ;CLEAR TO END OF LINE
        BYTE (7) 12             ;ROLL UP AND CLEAR LINE
        BYTE (7) 33,"I"         ;ROLL DOWN AND CLEAR LINE
        CPOPJ                   ;PROTECT ON (NONE)
        CPOPJ                   ;PROTECT OFF
        0                       ;INSERT LINES (NONE)
        0                       ;INSERT SPACES (NONE)
        0                       ;DELETE LINES (NONE)
        0                       ;DELETE SPACES (NONE)
        BYTE (7) 33,"Y","7"," " ;MOVE TO BOTTOM
        BYTE (7) 33,"H",33,"J"  ;HOME AND CLEAR ENTIRE PAGE
        VT5PSC                  ;ROUTINE TO POSITION TO CHARACTER
        VT5PSL                  ;ROUTINE TO POSITION TO START OF LINE
        ^D24                    ;LINES PER PAGE
        ^D80                    ;CHARACTERS PER LINE
        MRK                     ;FLAGS
        VENTRY                  ;ROUTINE TO CALL ON ENTRY
        VEXIT                   ;ROUTINE TO CALL ON EXIT
        0,,0                    ;NO NULLS NEEDED
        IVT52                   ;ADDRESS OF INPUT TABLE
        "*"                     ;MARK TO DISPLAY ON ENTER
.el .s1

Roll up and clear can usually be done with a linefeed. On the VT52 roll down
automatically clears the line; on some other terminals the roll must be
followed by a clear to end of line.

There are no features like reverse video, blinking, or half intensity, so the
highlighting of the ENTER mark, the FENCE, and embedded CONTROL characters
cannot be done; hence the CPOPJ's.

There are no insert/delete character/line sequences on the VT52, so there
are four 0's in the table. SED will simulate the insert/delete action
in software.

The next three commands are ones which probably cannot be done with one
terminal sequence; for example, home and clear page consists of the HOME
sequence followed by the CLEAR PAGE sequence. Moving to the bottom of the
screen can often be done with a HOME followed by a CURSOR UP; this will not
work on the VT52 since a CURSOR UP at the top of the screen will not put the
cursor at the bottom. So the sequence in the table is an absolute positioning
command.

The next two table locations give the addresses of routines to position the
cursor to row RW, column CM, and to the start of row T4. These routines
appear at the end of the terminal program.

The number of lines per page and of characters per line follow.

Then comes the word of flags, which indicate features which are missing and
must be simulated by SED. When ENTER is typed, the character at the
cursor position is highlighted. Since the VT52 does not have protected
(highlighted, right?) fields, the flag MRK tells SED to write a
certain mark at the cursor position. The code for that mark is given by
the next word of the table, and can be any printing character. That mark
word can be omitted if the MRK flag is not set.

There is a routine to execute on entry, VENTRY. It sets up the numeric keypad
so it sends different codes from the normal keyboard. This is so the ENTER
key can be used for INSERT-MODE. The exit routine, VEXIT, restores the
keypad to normal mode.

.S1

The VT52 has no problem with alphanumerics and most commands. However, ESCAPE
is used to signal cursor movement. Also, there are three unlabeled keys,
which send the sequences ESCAPE P, ESCAPE Q, and ESCAPE R; but no key to home
the cursor. So define the ESCAPE P key to be the ENTER command and ESCAPE R
to be HOME. The RECALL command can have the ESCAPE Q key. The INSERT-MODE
command is invoked by the key beneath CURSOR-LEFT, which sends ESCAPE ? M.
Thus all commands can be issued from the keyboard using one stroke each.

Note that the ESCAPE key on the terminal is never expected to
be used for commands.

.pg
The escape sequences are:

.s1 .lit
   CHARACTER(S)    COMMAND    EDITOR
   AFTER ESCAPE    DESIRED     CODE

        A       CURSOR RIGHT    35
        B       CURSOR LEFT     10
        C       CURSOR UP       36
        D       CURSOR DOWN     34
        H       HOME            37
        P       ENTER           33
        Q       RECALL          40
        R       HOME            37
        ? M     INSERT-MODE     41
.el .s1

The terminal input table contains value == location (ie, word 7 of the
table contains a 7, etc.) except for location 33 (ESCAPE). When an
ESCAPE is received SED wants to read the next character and
do different things depending on what that character is. So the
input table location 33 contains the negative length and the address of
the subtable which interprets the next character. The name of that
subtable is arbitrary.

If the character after the ESCAPE is not found in the subtable an
illegal command message is given. The subtable is searched sequentially,
so the more frequently expected commands, the cursor movements, appear
first.

The codes 34, 35, 36, and 37 are never expected to be received from the
terminal. So any value can be put in those words of the table; they
might as well be the usual values.

.s1 .lit
                 0                      ;COMMAND FOR RUBOUT (RESET)
IVT52:  EXP     40, 1, 2, 3, 4, 5, 6, 7 ;NOTHING SPECIAL
        EXP     10,11,12,13,14,15,16,17
        EXP     20,21,22,23,24,25,26,27
        EXP     30,31,32
        -10,,I.VT52     ;ESCAPE NEEDS A SUBTABLE
        EXP              34,35,36,37

I.VT52: 36,,"A"         ;ESCAPE A == UP
        34,,"B"         ;ESCAPE B == DOWN
        35,,"C"         ;ESCAPE C == RIGHT
        10,,"D"         ;ESCAPE D == LEFT
        33,,"P"         ;ESCAPE P == ENTER
        37,,"R"         ;ESCAPE R == HOME
        40,,"Q"         ;ESCAPE Q == RECALL
        IAVT52!SUB,,"?" ;ESCAPE ? M == INSERT-MODE

IAVT52: 41,,"M"
        0
.el
.pg
.C;EXAMPLE 2: HOW THE ADM2 LIVES WITH SED

The Systematics General ADM2 terminal is a good example of how detailed
things can get (Note: this example has been embellished to show off some
features. If you have an ADM2, see the file SEDA2.MAC).

The ADM2 terminal is described to the editor in the file SEDA2.MAC
(SED is loaded with the command .LOAD SEDA2,SED).
The terminal output table is pretty straightforward, the result
of reading the manual that comes with the ADM2.

.s1 .lit
OADM2:  BYTE (7) 13             ;CURSOR UP
        BYTE (7) 12             ; DOWN
        BYTE (7) 14             ; RIGHT
        BYTE (7) 10             ; LEFT
        BYTE (7) 36             ; HOME
        BYTE (7) 33,"Y"         ;CLEAR TO END OF PAGE
        BYTE (7) 33,"T"         ;CLEAR TO END OF LINE
        BYTE (7) 12             ;ROLL UP AND CLEAR LINE
        0                       ;ROLL DOWN AND CLEAR LINE
        BYTE (7) 33,")"         ;PROTECT ON
        BYTE (7) 33,"("         ;PROTECT OFF
        BYTE (7) 33,"E"         ;INSERT A BLANK LINE
        BYTE (7) 33,"Q"         ;INSERT A SPACE
        BYTE (7) 33,"R"         ;DELETE LINE
        BYTE (7) 33,"W"         ;DELETE SPACE
        BYTE (7) 36,13          ;MOVE TO BOTTOM
        BYTE (7) 36,33,"Y"      ;HOME AND CLEAR ENTIRE PAGE
        ADMPSC                  ;ROUTINE TO POSITION TO CHARACTER
        ADMPSL                  ;ROUTINE TO POSITION TO START OF LINE
        ^D24                    ;LINES PER PAGE
        ^D80                    ;CHARACTERS PER LINE
        WRP!LSD!NLP             ;WRAPAROUND, LF=DOWN, NO ROLL DOWN
        CPOPJ                   ;ROUTINE TO CALL ON ENTRY (NONE)
        CPOPJ                   ;ROUTINE TO CALL ON EXIT  (NONE)
        2,,6                    ;SEND 2 ^F'S AS NULLS
        IADM2                   ;ADDRESS OF TERMINAL INPUT TABLE
.el .s1

The terminal cannot roll the screen down, so there is a CPOPJ in
the table and the NRD flag is set.

The ADM2 has sequences for inserting and deleting, so SED can
use them. Rewriting only a line or two on an insert or delete, instead
of most of the screen, can really speed things up.

The ADM2 uses a LINEFEED as the CURSOR-DOWN character, so the LINEFEED
command has been disabled by the LSD flag.

Long lines will wrap around to the next line, so the WRP flag is set.

After absolute positioning a little delay is needed, to set the NLP flag
and define the NUL word to say that two CONTROL-F's will be sent as nulls.

There is no MAR word since highlighting (protection) exists (in the
guise of half intensity), so no special mark is needed.

.s2

The ADM2 has a row of 16 undefined buttons which send the codes CONTROL-A @
CARRIAGE-RETURN through CONTROL-A O CARRIAGE-RETURN, which can be used for
any homeless commands. Which is a good thing, since the terminal uses
CONTROL-K and CONTROL-L for cursor movement, and ESCAPE is not echoed
properly. So SLIDE-LEFT, SLIDE-RIGHT and ENTER will be set up as three
of those undefined buttons. INSERT-SPACES must also be defined as one of
those buttons, since CONTROL-A now signals that the two characters
following it must be inspected. For symmetry, put DELETE-SPACES in the
buttons too, and define two more of them to be RECALL and INSERT-MODE.

To add insult to injury, the HOME character is 36, not 37.

The CONTROL-A sequences are:

.s1 .lit
    CHARACTER      COMMAND    EDITOR
     AFTER ^A      DESIRED     CODE

        @       INSERT-SPACES    1
        A       DELETE-SPACES   23
        B       SLIDE-LEFT      13
        C       SLIDE-RIGHT     14
        M       INSERT-MODE     41
        N       RECALL          40
        O       ENTER           33
.el .s1
Each of these is followed by a CARRIAGE-RETURN, making each a
three-character sequence.

Now for the terminal input table itself. There is a subtable
pointer in word 1, for CONTROL-A. Words 13 and 14 contain
cursor movements, and word 36 contains the HOME command.
Otherwise the table is normal.

The subtable contains a number of addresses of other subtables,
since after finding the proper second character, SED wants
to pick up the CARRIAGE-RETURN.

Each of the sub-subtables indicates that any character is acceptable
(given by the 0 in the right half), and maps the three character
sequence received into the proper editor command.

Thus if the user types a SLIDE-LEFT command (third undefined button from
the left), the terminal sends CONTROL-A B CARRIAGE-RETURN to the
editor. SED receives the CONTROL-A, is directed to the
subtable, receives the B, is directed to sub-subtable IA3ADM,
receives the CARRIAGE-RETURN and maps the sequence into the
internal SLIDE-LEFT command, code octal 13.

The codes 23, 33, 34, 35, and 37 are undefined at the moment. They can
be anything, but it is probably best to give them their usual meanings.
So a DELETE-SPACES can be invoked by the user typing either button F2 or
_^S. A little redundancy doesn't hurt.

.S1 .lit
        0                               ;COMMAND FOR RUBOUT (RESET)
IADM2:  40
        -7,,IAADM2      ;^A NEEDS A SUBTABLE
        EXP            2, 3, 4, 5, 6, 7
        EXP     10,11,12,36,35,15,16,17 ;^K AND ^L ALTERED
        EXP     20,21,22,23,24,25,26,27
        EXP     30,31,32,33,34,35,37,37 ;36 IS HOME

IAADM2: IA1ADM,,"@"     ;^A @ CR == ^A
        IA2ADM,,"A"     ;^A A CR == ^S
        IA3ADM,,"B"     ;^A B CR == ^K
        IA4ADM,,"C"     ;^A C CR == ^L
        IA7ADM,,"M"     ;^A M CR == INSERT MODE
        IA8ADM,,"N"     ;^A N CR == RECALL
        IA9ADM,,"O"     ;^A O CR == ENTER

IA1ADM: "A"-100,,0
IA2ADM: "S"-100,,0
IA3ADM: "K"-100,,0
IA4ADM: "L"-100,,0
IA7ADM: 41,,0
IA8ADM: 40,,0
IA9ADM: 33,,0
.el