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 thing1thing2
285 > a bsecondthird 27
286 < c 15other
287 t last 5chance
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