1 06/25/79  - Writing Emacs Terminal Control Modules ("CTL"s)
  2 
  3 **This file is intended to be perused via dprint, print, or via an**
  4 **editor.  It is not intended to be perused with the help command**
  5 
  6 
  7 
  8 
  9 ^L
 10      Support of video (and printing) terminals in Emacs is accomplished
 11 via terminal-dependent modules known as "CTL"s (from the typical name,
 12 e.g., "super58.ctl" for a "super58" terminal).   There are about two
 13 dozen supplied CTLs.  They are kept in the directory >unb
 14 Emacs will attempt to locate an appropriate CTL in this directory at the
 15 time Emacs is entered; the decision as to which CTL will be made based
 16 upon the terminal type maintained by Multics, and optional Emacs control
 17 arguments.
 18 
 19      To support a type of terminal not supported by a supplied CTL, it is
 20 necessary to write a new CTL.  A CTL is written as a Lisp source program,
 21 name TTYTYPE.ctl.lisp, TTYTYPE being the name of the terminal type which
 22 will be supported.  If this terminal type is in your site's TTF (Terminal
 23 Type File), the name chosen should appear the same as appears in the TTF,
 24 except that the name of the CTL should be all lower case (Emacs will lower-case
 25 terminal types when looking for CTLs).
 26 
 27      CTLs are usually written by example from supplied CTLs.  Personnel
 28 with no knowledge of Lisp at all have achieved this successfully.  A
 29 relevant introduction to Lisp may be found in extensions.info in the Emacs
 30 documentation directory.  Once the CTL is written, it must be compiled
 31 before it can be used.  Compilation is performed via the Lisp compiler, lcp,
 32 which is kept in >unb.  A typical command line to compile
 33 a CTL might be
 34 
 35           lcp super58.ctl
 36 
 37 This will produce an object segment, super58ctl, which, when debugged, can be
 38 installed in the system library.  To use a CTL being debugged, invoke
 39 emacs with the "-ttp" control argument and the full pathname of the
 40 _^Hc_^Ho_^Hm_^Hp_^Hi_^Hl_^He_^Hd CTL:
 41 
 42           emacs -ttp >udd>Support>Jones>emacs_development>super58.ctl
 43 
 44 See emacs.info in the Emacs Documentation directory for the valid
 45 control arguments for managing terminal types.
 46 
 47               **************************************************
 48 
 49 
 50      The most effective method of writing a new CTL is to take one that
 51 was written for a similar terminal and modify it.  Almost all of the extant
 52 CTLs were written in this way.  The source for all supplied CTLs is kept
 53 in >>ldd>unb>s>bound_emacs_ctls_.s.archive.  The sources are Lisp source
 54 segments, generally one or two printed pages long.    Good starting points are
 55 
 56    o vip7200.ctl.lisp, typical of terminals that do not have the ability
 57      to insert or delete lines or characters.
 58 
 59    o vip7800.ctl.lisp, typical of terminals that do have these abilities.
 60      The two facilities are independent, either one, both, or neither
 61      may be present, although use of terminals without insert/delete
 62      lines at less than 300 baud may be found to be unacceptable.
 63 
 64      The interfaces (function definitions) in a CTL are standardized.  They
 65 have the same names in all CTLs.  The Emacs screen manager will call these
 66 interfaces anonymously after the appropriate CTL has been loaded.  The
 67 interface DCTL-init is called at Emacs start up time; it has the responsibility
 68 of setting various flags, and initializing the terminal.  It should
 69 contain the statements
 70 
 71  (setq idel-lines-availablep t)    if the terminal can insert/delete lines
 72  (setq idel-lines-availablep nil)  if it cannot
 73  (setq idel-chars-availablep t)    if the terminal can insert/delete characters
 74  (setq idel-chars-availablep nil)  if it cannot
 75  (setq screenheight N.)            Where N is the number of LINES on the screen
 76                                    (note the dot after the N).
 77  (setq screenlinelen M.)           Where M is _^Ho_^Hn_^He _^Hl_^He_^Hs_^Hs than_ the number
 78                                    of characters in a line on this terminal.
 79                                    Again, note the dot.
 80  (setq tty-type 'TYPENAME)         Where TYPENAME is a word like "super58"
 81                                    that identifies the terminal type.
 82 
 83      At the time DCTL-init is invoked, the variable "ospeed" is set to the
 84 speed of the communications line in _^Hc_^Hh_^Ha_^Hr_^Ha_^Hc_^Ht_^He_^Hr_^Hs _^Hp_^He_^Hr _^Hs_^He_^Hc_^Ho_^Hn_^Hd.
 85 This may be used to perform padding calculations.
 86 
 87      Also before DCTL-init is invoked, the variable "given-tty-type" is set to
 88 the name by which the CTL was loaded with the ".ctl" suffix stripped.  This
 89 variable can be used in DCTL-init (and elsewhere) to enable and use different
 90 features of a terminal dependent on the name used to reference that terminal.
 91 
 92      The following functions are available to the CTL writer:
 93 
 94           o Rtyo takes one argument, a number (fixnum), and outputs
 95             that number as ASCII data. For instance, (Rtyo 141) will
 96             output an "a", and (Rtyo 33) will output an ESC.
 97 
 98           o Rprinc takes one argument, a character string, and outputs
 99             it.  For instance, (Rprinc "]I") outputs a right bracket and
100             an I.
101 
102 Both of these functions buffer their output until the Emacs screen manager
103 deems it appropriate to dump this buffer.  This will always be done at
104 the end of any redisplay at all, and after DCTL-init is called.
105 
106      The CTL writer must maintain the values of the special (global) variables
107 X and Y as the zero-originned screen position where the cursor was left.
108 In return, he or she gets to inspect these variables to do positioning
109 optimization.
110 
111      The CTL writer must provide the following interfaces to be called by
112 the Emacs screen manager:
113 
114      o DCTL-init  - (of no arguments) - Must set the flags listed above,
115        initialize the terminal (if necessary), clear the terminal screen,
116        and leave the cursor at position (0, 0) (home).
117 
118      o DCTL-position-cursor - (of two arguments, a new X position and
119        a new Y position) - Move the terminal's cursor to the given
120        position, if not there already. Position 0, 0 is defined as the
121        upper left hand corner of the screen.  This function must check
122        the variables X and Y, and output no characters if the cursor is
123        known to already be at the desired position.  Otherwise, it must
124        use the values of X and Y to determine what type of motion is necessary,
125        output characters to move the cursor, and update X and Y to the input
126        parameters (the delay of the buffered output is not an issue).
127 
128        Typically, DCTL-position-cursor will determine which is the optimal
129        movement based upon the relative positions of the cursor and the desired
130        position.  For terminals that have many forms of cursor movement,
131        some combination of backspaces, linefeeds, and carriage returns
132        may be adequate to effect some forms of cursor movement. Sometimes
133        the sequences generated by the "arrow buttons" on the terminal
134        may be used for relative positioning.  Just about all terminals
135        include some form of absolute positioning.  The choice of optimal
136        cursor positioning should be based upon which will output the fewest
137        characters to effect the desired move.  See hp2645.ctl.lisp for an
138        example of a very well optimized cursor positioner.
139 
140        One useful trick in the writing of DCTL-position-cursor is the use of
141        recursion.  See adds980.ctl.lisp for an example.  If you choose to use
142        terminal tabs, then your DCTL-init must set them, and you must take
143        care not to clear them.  No supplied CTLs (other than the extremely
144        special-case printing terminal controller) use tabs.
145 
146      o DCTL-display-char-string (of one argument, a character string to
147        be displayed).  Must output this character string to the terminal
148        at the current assumed cursor position.  The string is guaranteed
149        to contain no control or other non-printing characters,  and each
150        character in it is guaranteed to take up one and only one print
151        position.  Be careful to update cursor position after printing
152        the string; the lisp function "stringlength" may be used to ascertain
153        the length/printing length of the string.
154 
155      o DCTL-kill-line - (of no arguments) - Clear the line from the current
156        assumed cursor position to the end of the line, and, importantly,
157        _^Hl_^He_^Ha_^Hv_^He the cursor at that original assumed position.  Most
158        video terminals have a clear-to-end-of-line feature; it should be
159        used here if available.  Some terminals do not, yet this function
160        must be provided anyway.  The machinations for "simulating" clear
161        to end of line are moderately arcane; see adm3a.ctl.lisp for an
162        example of clearing to end of line by overwriting with blanks.
163        Performance of this technique at 300 baud is generally completely
164        unacceptable, rendering such terminals unfit for use with Emacs
165        (or any other display editor) at that speed.
166 
167      o DCTL-clear-rest-of-screen - (of no arguments) - Clear the screen
168        from the current assumed cursor position to the end. Leave the cursor
169        where it was supplied.  Some terminals have a "clear whole screen"
170        function, but not clear to end of screen.  For the time being, this
171        will do, although we may use the added functionality in the future.
172        If your terminal does not even have a clear-whole-screen function,
173        it is probably not worth using with Emacs.  If you choose to use tabs
174        in cursor positioning, be wary of clearing them via this function.
175 
176      We have just listed all the required functions.  Some terminals require
177 control sequences to change "modes" between normal Multics operation and
178 operation within Emacs.  (For example, a terminal might be switched between
179 line-at-a-time transmission and character-at-a-time transmission.)  Yet other
180 terminals might use features during the operation of Emacs which should be
181 disbaled/reset when using Multics.  (For example, the VT100 uses "scroll"
182 regions to simulate insert/delete lines.  However, if a scroll region exists,
183 it will make parts of the screen unusable when using Multics.)  It is possible
184 and quite common to switch between Multics and Emacs by using the ATTN key and
185 the "pi" command.  In this case, the terminal will be in the wrong mode at
186 various times.  If the terminal for which you are writing a CTL exhibits this
187 behavior, you should add the following statements to DCTL-init:
188 
189  (setq DCTL-prologue-availablep t) to specify that certain functions must be
190                                    performed each time Emacs "mode" is entered
191                                    from Multics "mode".
192  (setq DCTL-epilogue-availablep t) to specify that certain functions must be
193                                    performed each time Multics "mode" is
194                                    entered from Emacs "mode".
195 
196 In addition, you must then supply the following two functions:
197 
198      o DCTL-prologue - (of no arguments) - Perform any operations which are
199        required when Emacs "mode" is entered from Multics "mode".  This
200        function will be invoked immediately after DCTL-init is called and
201        after Emacs is reentered after a QUIT via either the "pi" or "start"
202        commands.
203 
204      o DCTL-epilogue - (of no arguments) - Perform any operations which are
205        required when Multics "mode" is to be entered from Emacs "mode".  This
206        function will be invoked immediately before Emacs is exited when the
207        ^X^C (quit-the-editor) command is invoked and immediately before Emacs
208        is suspended when the ^Z^Z (quit) command is invoked or the ATTN key is
209        hit on the terminal.
210 
211      If you have stated that insert/delete lines is available, via setting the
212 flag idel-lines-availablep to t, you must supply the following two functions.
213 If you set this flag to nil, you need not write these functions:
214 
215      o DCTL-insert-lines - (of one argument, a number of lines to be
216        inserted) - Open up the given number of lines on the screen.
217        There will be guaranteed to be that many blank lines (created by
218        DCTL-delete-lines) at the bottom of the screen at the time this
219        function is invoked.  The cursor will be at position 0 of some
220        line at the time DCTL-insert-lines is invoked.  It must push
221        the contents of that line "down" the supplied number of lines,
222        leaving the cursor in the same place, the line the cursor is on
223        and the n-1 succeeding lines blank.
224 
225      o DCTL-delete-lines - (of one argument, a number of lines to be
226        deleted) - Delete from the screen the supplied number of lines,
227        starting with the line the cursor is on on down.  The cursor is to
228        be left in the same place it was given.  That many blank lines
229        will be assumed to be pulled up on the bottom of the screen.
230 
231      If the flag idel-chars-availablep is set t, indicating that insertion
232 and deletion of characters is available, the following two functions must
233 be supplied:
234 
235      o DCTL-insert-char-string - (of one argument, a character string
236        to be inserted at the current assumed cursor position).  The
237        character string supplied is to be inserted at the current
238        cursor position.  All characters at, and to the right of the
239        current cursor position are to be pushed over to the right.  There
240        will be guaranteed to be only blanks on the screen in the region
241        which will be "pushed off".  The cursor is to be left (and updated
242        as being at) the end (after the last character) of the string inserted.
243 
244      o DCTL-delete-chars - (of one argument, the number of characters
245        to be deleted). The supplied number of characters, starting with the
246        character at the cursor and on to the right, are to be physically
247        deleted from the screen.  All characters to the right of these
248        characters are to be moved that many positions to the left.  That many
249        blanks will be assumed to be moved in from the right edge.  The cursor
250        is to be left where it was supplied.
251 
252      Writing a CTL usually involves editing an existant one, trying it,
253 modifying it, and iterating until it is solid.  One will use the "-ttp"
254 control argument many times to switch back and forth between "printing
255 terminal mode" and the new CTL when logged in from the terminal on which the
256 CTL is being developed.  For terminals with insert/delete features,
257 it may be convenient to debug the CTL first without these features (claim
258 they are not there in the DCTL-init), and add them later.  Similarly,
259 one is encouraged to write "more optimal" DCTL-position-cursor's once
260 one has one that works at all, for the convenience of editing the CTL with
261 Emacs substantially reduces the effort of improving it.
262 
263      For some terminals, padding may be necessary for some operations at some
264 or all line speeds.  If terminal behavior appears random, or garbage is left
265 on the screen after a ^L or ^K, this may be the problem.  Check the manual
266 for your terminal about padding requirements.  It may be convenient to define
267 a function called DCTL-pad, which takes a number of microseconds or
268 milliseconds as an argument, and issues enough pad characters ((Rtyo 0)
269 or (Rtyo 177) are common, check your terminal manual for what your terminal
270 expects) to perform this padding.  The variable "ospeed" gives the line
271 speed in characters per second, for use in such calculations.  Getting
272 the padding right may involve quite a bit of tinkering on some terminals;
273 one proven method in cases where padding is felt to be a problem is to specify
274 a very large amount of padding (e.g., a second) and cut it down until it works.
275 See dd4000.ctl.lisp for an example of terminal padding.
276 
277               **************************************************
278 
279      The Lisp special forms _^Hc_^Ho_^Hn_^Hd and _^Hd_^Ho are used heavily in CTLs and
280 not documented in extensions.info.  Emacs environment macros (do-forever,
281 if, etc) should not be used in CTLs, thus the native Lisp forms are necessary.
282 Here are the descriptions of cond and do:
283 
284      (cond ((= this that) (thing1)(thing2))
285            ((> a b)(second)(third) 27)
286            ((< c 15)(other))
287            (t (last 5)(chance)))
288 
289 means:
290 
291    "If this equals that, call thing1 of no arguments, then call thing2 of
292     no arguments, and return as the value of the cond the value returned
293     by thing2.  OTHERWISE, if a is greater than b, call "second" with
294     no arguments, then call "third", and return 27 as a value. YET
295     OTHERWISE, if c is less than 15 (all numbers octal), return the value
296     obtained by applying "other" to no arguments.  If none of the above
297     are true, call "last" with an argument of 5, and then return the value
298     obtained by calling "chance" with no arguments."
299 
300 "cond" is very much like PL/I's
301 
302     if ( .... ) then do;
303          .....
304     end;
305     else if ( .... ) then do;
306          .....
307     end;
308     else if ( .... ) then do;
309          .....
310     end;
311     else do;
312          .....
313     end;
314 
315 The format of Lisp "do" used in CTL's to iterate is of this form:
316 
317    (do VARIABLE INITIAL-VALUE REPEAT-VALUE TEST form1 form2 form3.. )
318 
319 It is identically equivalent to PL/I's
320 
321    do VARIABLE = INITIAL-VALUE
322       repeat REPEAT-VALUE
323       while (^ TEST);
324 
325       form1;form2; ...
326    end;
327 
328 which, itself, is equivalent to
329 
330      VARIABLE = INITIAL-VALUE;
331 l:   if TEST then go to e;
332      form1;form2;...
333      VARIABLE = REPEAT-VALUE;
334      go to l;
335 e:   ;
336 
337 The variable VARIABLE is locally defined inside the "do".  It may be used
338 in the forms inside the "do", in the "end test" TEST, and in the repeat
339 value REPEAT-VALUE.
340 
341 (END)