1 /* Functions related to terminal devices.
2    Copyright (C) 2005-2021 Free Software Foundation, Inc.
3 
4 This file is part of GNU Emacs.
5 
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
10 
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
18 
19 #include <config.h>
20 
21 #include "lisp.h"
22 #include "character.h"
23 #include "frame.h"
24 #include "termchar.h"
25 #include "termhooks.h"
26 #include "keyboard.h"
27 
28 #if HAVE_STRUCT_UNIPAIR_UNICODE
29 # include <errno.h>
30 # include <linux/kd.h>
31 # include <sys/ioctl.h>
32 #endif
33 
34 /* Chain of all terminals currently in use.  */
35 struct terminal *terminal_list;
36 
37 /* The first unallocated terminal id.  */
38 static int next_terminal_id;
39 
40 /* The initial terminal device, created by initial_term_init.  */
41 struct terminal *initial_terminal;
42 
43 static void delete_initial_terminal (struct terminal *);
44 
45 /* This setter is used only in this file, so it can be private.  */
46 static void
tset_param_alist(struct terminal * t,Lisp_Object val)47 tset_param_alist (struct terminal *t, Lisp_Object val)
48 {
49   t->param_alist = val;
50 }
51 
52 
53 
54 void
ring_bell(struct frame * f)55 ring_bell (struct frame *f)
56 {
57   if (!NILP (Vring_bell_function))
58     {
59       Lisp_Object function;
60 
61       /* Temporarily set the global variable to nil
62 	 so that if we get an error, it stays nil
63 	 and we don't call it over and over.
64 
65 	 We don't specbind it, because that would carefully
66 	 restore the bad value if there's an error
67 	 and make the loop of errors happen anyway.  */
68 
69       function = Vring_bell_function;
70       Vring_bell_function = Qnil;
71 
72       call0 (function);
73 
74       Vring_bell_function = function;
75     }
76   else if (FRAME_TERMINAL (f)->ring_bell_hook)
77     (*FRAME_TERMINAL (f)->ring_bell_hook) (f);
78 }
79 
80 void
update_begin(struct frame * f)81 update_begin (struct frame *f)
82 {
83   if (FRAME_TERMINAL (f)->update_begin_hook)
84     (*FRAME_TERMINAL (f)->update_begin_hook) (f);
85 }
86 
87 void
update_end(struct frame * f)88 update_end (struct frame *f)
89 {
90   if (FRAME_TERMINAL (f)->update_end_hook)
91     (*FRAME_TERMINAL (f)->update_end_hook) (f);
92 }
93 
94 /* Specify how many text lines, from the top of the window,
95    should be affected by insert-lines and delete-lines operations.
96    This, and those operations, are used only within an update
97    that is bounded by calls to update_begin and update_end.  */
98 
99 void
set_terminal_window(struct frame * f,int size)100 set_terminal_window (struct frame *f, int size)
101 {
102   if (FRAME_TERMINAL (f)->set_terminal_window_hook)
103     (*FRAME_TERMINAL (f)->set_terminal_window_hook) (f, size);
104 }
105 
106 /* Move cursor to row/column position VPOS/HPOS.  HPOS/VPOS are
107    frame-relative coordinates.  */
108 
109 void
cursor_to(struct frame * f,int vpos,int hpos)110 cursor_to (struct frame *f, int vpos, int hpos)
111 {
112   if (FRAME_TERMINAL (f)->cursor_to_hook)
113     (*FRAME_TERMINAL (f)->cursor_to_hook) (f, vpos, hpos);
114 }
115 
116 /* Similar but don't take any account of the wasted characters.  */
117 
118 void
raw_cursor_to(struct frame * f,int row,int col)119 raw_cursor_to (struct frame *f, int row, int col)
120 {
121   if (FRAME_TERMINAL (f)->raw_cursor_to_hook)
122     (*FRAME_TERMINAL (f)->raw_cursor_to_hook) (f, row, col);
123 }
124 
125 /* Erase operations.  */
126 
127 /* Clear from cursor to end of frame.  */
128 void
clear_to_end(struct frame * f)129 clear_to_end (struct frame *f)
130 {
131   if (FRAME_TERMINAL (f)->clear_to_end_hook)
132     (*FRAME_TERMINAL (f)->clear_to_end_hook) (f);
133 }
134 
135 /* Clear entire frame.  */
136 
137 void
clear_frame(struct frame * f)138 clear_frame (struct frame *f)
139 {
140   if (FRAME_TERMINAL (f)->clear_frame_hook)
141     (*FRAME_TERMINAL (f)->clear_frame_hook) (f);
142 }
143 
144 /* Clear from cursor to end of line.
145    Assume that the line is already clear starting at column first_unused_hpos.
146 
147    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
148 
149 void
clear_end_of_line(struct frame * f,int first_unused_hpos)150 clear_end_of_line (struct frame *f, int first_unused_hpos)
151 {
152   if (FRAME_TERMINAL (f)->clear_end_of_line_hook)
153     (*FRAME_TERMINAL (f)->clear_end_of_line_hook) (f, first_unused_hpos);
154 }
155 
156 /* Output LEN glyphs starting at STRING at the nominal cursor position.
157    Advance the nominal cursor over the text.  */
158 
159 void
write_glyphs(struct frame * f,struct glyph * string,int len)160 write_glyphs (struct frame *f, struct glyph *string, int len)
161 {
162   if (FRAME_TERMINAL (f)->write_glyphs_hook)
163     (*FRAME_TERMINAL (f)->write_glyphs_hook) (f, string, len);
164 }
165 
166 /* Insert LEN glyphs from START at the nominal cursor position.
167 
168    If start is zero, insert blanks instead of a string at start */
169 
170 void
insert_glyphs(struct frame * f,struct glyph * start,int len)171 insert_glyphs (struct frame *f, struct glyph *start, int len)
172 {
173   if (len <= 0)
174     return;
175 
176   if (FRAME_TERMINAL (f)->insert_glyphs_hook)
177     (*FRAME_TERMINAL (f)->insert_glyphs_hook) (f, start, len);
178 }
179 
180 /* Delete N glyphs at the nominal cursor position. */
181 
182 void
delete_glyphs(struct frame * f,int n)183 delete_glyphs (struct frame *f, int n)
184 {
185   if (FRAME_TERMINAL (f)->delete_glyphs_hook)
186     (*FRAME_TERMINAL (f)->delete_glyphs_hook) (f, n);
187 }
188 
189 /* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
190 
191 void
ins_del_lines(struct frame * f,int vpos,int n)192 ins_del_lines (struct frame *f, int vpos, int n)
193 {
194   if (FRAME_TERMINAL (f)->ins_del_lines_hook)
195     (*FRAME_TERMINAL (f)->ins_del_lines_hook) (f, vpos, n);
196 }
197 
198 /* Return the terminal object specified by TERMINAL.  TERMINAL may
199    be a terminal object, a frame, or nil for the terminal device of
200    the current frame.  If TERMINAL is neither from the above or the
201    resulting terminal object is deleted, return NULL.  */
202 
203 static struct terminal *
decode_terminal(Lisp_Object terminal)204 decode_terminal (Lisp_Object terminal)
205 {
206   struct terminal *t;
207 
208   if (NILP (terminal))
209     terminal = selected_frame;
210   t = (TERMINALP (terminal)
211        ? XTERMINAL (terminal)
212        : FRAMEP (terminal) ? FRAME_TERMINAL (XFRAME (terminal)) : NULL);
213   return t && t->name ? t : NULL;
214 }
215 
216 /* Like above, but throw an error if TERMINAL is not valid or deleted.  */
217 
218 struct terminal *
decode_live_terminal(Lisp_Object terminal)219 decode_live_terminal (Lisp_Object terminal)
220 {
221   struct terminal *t = decode_terminal (terminal);
222 
223   if (!t)
224     wrong_type_argument (Qterminal_live_p, terminal);
225   return t;
226 }
227 
228 /* Like decode_terminal, but ensure that the resulting terminal object refers
229    to a text-based terminal device.  */
230 
231 struct terminal *
decode_tty_terminal(Lisp_Object terminal)232 decode_tty_terminal (Lisp_Object terminal)
233 {
234   struct terminal *t = decode_live_terminal (terminal);
235 
236   return (t->type == output_termcap || t->type == output_msdos_raw) ? t : NULL;
237 }
238 
239 /* Return an active (not suspended) text-based terminal device that uses
240    the tty device with the given NAME, or NULL if the named terminal device
241    is not opened.  */
242 
243 struct terminal *
get_named_terminal(const char * name)244 get_named_terminal (const char *name)
245 {
246   struct terminal *t;
247 
248   eassert (name);
249 
250   for (t = terminal_list; t; t = t->next_terminal)
251     {
252       if ((t->type == output_termcap || t->type == output_msdos_raw)
253           && !strcmp (t->display_info.tty->name, name)
254           && TERMINAL_ACTIVE_P (t))
255         return t;
256     }
257   return NULL;
258 }
259 
260 /* Allocate basically initialized terminal.  */
261 
262 static struct terminal *
allocate_terminal(void)263 allocate_terminal (void)
264 {
265   return ALLOCATE_ZEROED_PSEUDOVECTOR (struct terminal, glyph_code_table,
266 				       PVEC_TERMINAL);
267 }
268 
269 /* Create a new terminal object of TYPE and add it to the terminal list.  RIF
270    may be NULL if this terminal type doesn't support window-based redisplay.  */
271 
272 struct terminal *
create_terminal(enum output_method type,struct redisplay_interface * rif)273 create_terminal (enum output_method type, struct redisplay_interface *rif)
274 {
275   struct terminal *terminal = allocate_terminal ();
276   Lisp_Object terminal_coding, keyboard_coding;
277 
278   terminal->next_terminal = terminal_list;
279   terminal_list = terminal;
280   terminal->type = type;
281   terminal->rif = rif;
282   terminal->id = next_terminal_id++;
283 
284   terminal->keyboard_coding = xmalloc (sizeof (struct coding_system));
285   terminal->terminal_coding = xmalloc (sizeof (struct coding_system));
286 
287   /* If default coding systems for the terminal and the keyboard are
288      already defined, use them in preference to the defaults.  This is
289      needed when Emacs runs in daemon mode.  */
290   keyboard_coding =
291     find_symbol_value (intern ("default-keyboard-coding-system"));
292   if (NILP (keyboard_coding)
293       || EQ (keyboard_coding, Qunbound)
294       || NILP (Fcoding_system_p (keyboard_coding)))
295     keyboard_coding = Qno_conversion;
296   terminal_coding =
297     find_symbol_value (intern ("default-terminal-coding-system"));
298   if (NILP (terminal_coding)
299       || EQ (terminal_coding, Qunbound)
300       || NILP (Fcoding_system_p (terminal_coding)))
301     terminal_coding = Qundecided;
302 
303   setup_coding_system (keyboard_coding, terminal->keyboard_coding);
304   setup_coding_system (terminal_coding, terminal->terminal_coding);
305 
306   return terminal;
307 }
308 
309 /* Low-level function to close all frames on a terminal, remove it
310    from the terminal list and free its memory.  */
311 
312 void
delete_terminal(struct terminal * terminal)313 delete_terminal (struct terminal *terminal)
314 {
315   Lisp_Object tail, frame;
316 
317   /* Protect against recursive calls.  delete_frame calls the
318      delete_terminal_hook when we delete our last frame.  */
319   if (!terminal->name)
320     return;
321   xfree (terminal->name);
322   terminal->name = NULL;
323 
324   /* Check for live frames that are still on this terminal.  */
325   FOR_EACH_FRAME (tail, frame)
326     {
327       struct frame *f = XFRAME (frame);
328       if (FRAME_LIVE_P (f) && f->terminal == terminal)
329         {
330 	  /* Pass Qnoelisp rather than Qt.  */
331           delete_frame (frame, Qnoelisp);
332         }
333     }
334 
335   delete_terminal_internal (terminal);
336 }
337 
338 void
delete_terminal_internal(struct terminal * terminal)339 delete_terminal_internal (struct terminal *terminal)
340 {
341   struct terminal **tp;
342 
343   for (tp = &terminal_list; *tp != terminal; tp = &(*tp)->next_terminal)
344     if (! *tp)
345       emacs_abort ();
346   *tp = terminal->next_terminal;
347 
348   xfree (terminal->keyboard_coding);
349   terminal->keyboard_coding = NULL;
350   xfree (terminal->terminal_coding);
351   terminal->terminal_coding = NULL;
352 
353   if (terminal->kboard && --terminal->kboard->reference_count == 0)
354     {
355       delete_kboard (terminal->kboard);
356       terminal->kboard = NULL;
357     }
358 }
359 
360 DEFUN ("delete-terminal", Fdelete_terminal, Sdelete_terminal, 0, 2, 0,
361        doc: /* Delete TERMINAL by deleting all frames on it and closing the terminal.
362 TERMINAL may be a terminal object, a frame, or nil (meaning the
363 selected frame's terminal).
364 
365 Normally, you may not delete a display if all other displays are suspended,
366 but if the second argument FORCE is non-nil, you may do so. */)
367   (Lisp_Object terminal, Lisp_Object force)
368 {
369   struct terminal *t = decode_terminal (terminal);
370 
371   if (!t)
372     return Qnil;
373 
374   if (NILP (force))
375     {
376       struct terminal *p = terminal_list;
377       while (p && (p == t || !TERMINAL_ACTIVE_P (p)))
378 	p = p->next_terminal;
379 
380       if (!p)
381 	error ("Attempt to delete the sole active display terminal");
382     }
383 
384   if (NILP (Vrun_hooks))
385     ;
386   else if (EQ (force, Qnoelisp))
387     pending_funcalls
388       = Fcons (list3 (Qrun_hook_with_args,
389 		      Qdelete_terminal_functions, terminal),
390 	       pending_funcalls);
391   else
392     safe_call2 (Qrun_hook_with_args, Qdelete_terminal_functions, terminal);
393 
394   if (t->delete_terminal_hook)
395     (*t->delete_terminal_hook) (t);
396   else
397     delete_terminal (t);
398 
399   return Qnil;
400 }
401 
402 
403 DEFUN ("frame-terminal", Fframe_terminal, Sframe_terminal, 0, 1, 0,
404        doc: /* Return the terminal that FRAME is displayed on.
405 If FRAME is nil, the selected frame is used.
406 
407 The terminal device is represented by its integer identifier.  */)
408   (Lisp_Object frame)
409 {
410   struct terminal *t = FRAME_TERMINAL (decode_live_frame (frame));
411 
412   if (!t)
413     return Qnil;
414   else
415     {
416       Lisp_Object terminal;
417       XSETTERMINAL (terminal, t);
418       return terminal;
419     }
420 }
421 
422 DEFUN ("terminal-live-p", Fterminal_live_p, Sterminal_live_p, 1, 1, 0,
423        doc: /* Return non-nil if OBJECT is a terminal which has not been deleted.
424 Value is nil if OBJECT is not a live display terminal.
425 If object is a live display terminal, the return value indicates what
426 sort of output terminal it uses.  See the documentation of `framep' for
427 possible return values.  */)
428   (Lisp_Object object)
429 {
430   struct terminal *t = decode_terminal (object);
431 
432   if (!t)
433     return Qnil;
434 
435   switch (t->type)
436     {
437     case output_initial: /* The initial frame is like a termcap frame. */
438     case output_termcap:
439       return Qt;
440     case output_x_window:
441       return Qx;
442     case output_w32:
443       return Qw32;
444     case output_msdos_raw:
445       return Qpc;
446     case output_ns:
447       return Qns;
448     case output_pgtk:
449       return Qpgtk;
450     case output_haiku:
451       return Qhaiku;
452     default:
453       emacs_abort ();
454     }
455 }
456 
457 DEFUN ("terminal-list", Fterminal_list, Sterminal_list, 0, 0, 0,
458        doc: /* Return a list of all terminal devices.  */)
459   (void)
460 {
461   Lisp_Object terminal, terminals = Qnil;
462   struct terminal *t;
463 
464   for (t = terminal_list; t; t = t->next_terminal)
465     {
466       XSETTERMINAL (terminal, t);
467       terminals = Fcons (terminal, terminals);
468     }
469 
470   return terminals;
471 }
472 
473 DEFUN ("terminal-name", Fterminal_name, Sterminal_name, 0, 1, 0,
474        doc: /* Return the name of the terminal device TERMINAL.
475 It is not guaranteed that the returned value is unique among opened devices.
476 
477 TERMINAL may be a terminal object, a frame, or nil (meaning the
478 selected frame's terminal). */)
479   (Lisp_Object terminal)
480 {
481   struct terminal *t = decode_live_terminal (terminal);
482 
483   return t->name ? build_string (t->name) : Qnil;
484 }
485 
486 
487 
488 /* Set the value of terminal parameter PARAMETER in terminal D to VALUE.
489    Return the previous value.  */
490 
491 static Lisp_Object
store_terminal_param(struct terminal * t,Lisp_Object parameter,Lisp_Object value)492 store_terminal_param (struct terminal *t, Lisp_Object parameter, Lisp_Object value)
493 {
494   Lisp_Object old_alist_elt = Fassq (parameter, t->param_alist);
495   if (NILP (old_alist_elt))
496     {
497       tset_param_alist (t, Fcons (Fcons (parameter, value), t->param_alist));
498       return Qnil;
499     }
500   else
501     {
502       Lisp_Object result = Fcdr (old_alist_elt);
503       Fsetcdr (old_alist_elt, value);
504       return result;
505     }
506 }
507 
508 
509 DEFUN ("terminal-parameters", Fterminal_parameters, Sterminal_parameters, 0, 1, 0,
510        doc: /* Return the parameter-alist of terminal TERMINAL.
511 The value is a list of elements of the form (PARM . VALUE), where PARM
512 is a symbol.
513 
514 TERMINAL can be a terminal object, a frame, or nil (meaning the
515 selected frame's terminal).  */)
516   (Lisp_Object terminal)
517 {
518   return Fcopy_alist (decode_live_terminal (terminal)->param_alist);
519 }
520 
521 DEFUN ("terminal-parameter", Fterminal_parameter, Sterminal_parameter, 2, 2, 0,
522        doc: /* Return TERMINAL's value for parameter PARAMETER.
523 TERMINAL can be a terminal object, a frame, or nil (meaning the
524 selected frame's terminal).  */)
525   (Lisp_Object terminal, Lisp_Object parameter)
526 {
527   CHECK_SYMBOL (parameter);
528   return Fcdr (Fassq (parameter, decode_live_terminal (terminal)->param_alist));
529 }
530 
531 DEFUN ("set-terminal-parameter", Fset_terminal_parameter,
532        Sset_terminal_parameter, 3, 3, 0,
533        doc: /* Set TERMINAL's value for parameter PARAMETER to VALUE.
534 Return the previous value of PARAMETER.
535 
536 TERMINAL can be a terminal object, a frame or nil (meaning the
537 selected frame's terminal).  */)
538   (Lisp_Object terminal, Lisp_Object parameter, Lisp_Object value)
539 {
540   return store_terminal_param (decode_live_terminal (terminal), parameter, value);
541 }
542 
543 #if HAVE_STRUCT_UNIPAIR_UNICODE
544 
545 /* Compute the glyph code table for T.  */
546 
547 static void
calculate_glyph_code_table(struct terminal * t)548 calculate_glyph_code_table (struct terminal *t)
549 {
550   Lisp_Object glyphtab = Qt;
551   enum { initial_unipairs = 1000 };
552   int entry_ct = initial_unipairs;
553   struct unipair unipair_buffer[initial_unipairs];
554   struct unipair *entries = unipair_buffer;
555   struct unipair *alloced = 0;
556 
557   while (true)
558     {
559       int fd = fileno (t->display_info.tty->output);
560       struct unimapdesc unimapdesc = { entry_ct, entries };
561       if (ioctl (fd, GIO_UNIMAP, &unimapdesc) == 0)
562 	{
563 	  glyphtab = Fmake_char_table (Qnil, make_fixnum (-1));
564 	  for (int i = 0; i < unimapdesc.entry_ct; i++)
565 	    char_table_set (glyphtab, entries[i].unicode,
566 			    make_fixnum (entries[i].fontpos));
567 	  break;
568 	}
569       if (errno != ENOMEM)
570 	break;
571       entry_ct = unimapdesc.entry_ct;
572       entries = alloced = xrealloc (alloced, entry_ct * sizeof *alloced);
573     }
574 
575   xfree (alloced);
576   t->glyph_code_table = glyphtab;
577 }
578 #endif
579 
580 /* Return the glyph code in T of character CH, or -1 if CH does not
581    have a font position in T, or nil if T does not report glyph codes.  */
582 
583 Lisp_Object
terminal_glyph_code(struct terminal * t,int ch)584 terminal_glyph_code (struct terminal *t, int ch)
585 {
586 #if HAVE_STRUCT_UNIPAIR_UNICODE
587   /* Heuristically assume that a terminal supporting glyph codes is in
588      UTF-8 mode if and only if its coding system is UTF-8 (Bug#26396).  */
589   if (t->type == output_termcap
590       && t->terminal_coding->encoder == encode_coding_utf_8)
591     {
592       /* As a hack, recompute the table when CH is the maximum
593 	 character.  */
594       if (NILP (t->glyph_code_table) || ch == MAX_CHAR)
595 	calculate_glyph_code_table (t);
596 
597       if (! EQ (t->glyph_code_table, Qt))
598 	return char_table_ref (t->glyph_code_table, ch);
599     }
600 #endif
601 
602   return Qnil;
603 }
604 
605 /* Initial frame has no device-dependent output data, but has
606    face cache which should be freed when the frame is deleted.  */
607 
608 static void
initial_free_frame_resources(struct frame * f)609 initial_free_frame_resources (struct frame *f)
610 {
611   eassert (FRAME_INITIAL_P (f));
612   free_frame_faces (f);
613 }
614 
615 /* Create the bootstrap display terminal for the initial frame.
616    Returns a terminal of type output_initial.  */
617 
618 struct terminal *
init_initial_terminal(void)619 init_initial_terminal (void)
620 {
621   if (initialized || terminal_list || tty_list)
622     emacs_abort ();
623 
624   initial_terminal = create_terminal (output_initial, NULL);
625   initial_terminal->name = xstrdup ("initial_terminal");
626   initial_terminal->kboard = initial_kboard;
627   initial_terminal->delete_terminal_hook = &delete_initial_terminal;
628   initial_terminal->delete_frame_hook = &initial_free_frame_resources;
629   initial_terminal->defined_color_hook = &tty_defined_color; /* xfaces.c */
630   /* Other hooks are NULL by default.  */
631 
632   return initial_terminal;
633 }
634 
635 /* Deletes the bootstrap terminal device.
636    Called through delete_terminal_hook. */
637 
638 static void
delete_initial_terminal(struct terminal * terminal)639 delete_initial_terminal (struct terminal *terminal)
640 {
641   if (terminal != initial_terminal)
642     emacs_abort ();
643 
644   delete_terminal (terminal);
645   initial_terminal = NULL;
646 }
647 
648 void
syms_of_terminal(void)649 syms_of_terminal (void)
650 {
651 
652   DEFVAR_LISP ("ring-bell-function", Vring_bell_function,
653     doc: /* Non-nil means call this function to ring the bell.
654 The function should accept no arguments.  */);
655   Vring_bell_function = Qnil;
656 
657   DEFVAR_LISP ("delete-terminal-functions", Vdelete_terminal_functions,
658     doc: /* Special hook run when a terminal is deleted.
659 Each function is called with argument, the terminal.
660 This may be called just before actually deleting the terminal,
661 or some time later.  */);
662   Vdelete_terminal_functions = Qnil;
663 
664   DEFSYM (Qterminal_live_p, "terminal-live-p");
665   DEFSYM (Qdelete_terminal_functions, "delete-terminal-functions");
666   DEFSYM (Qrun_hook_with_args, "run-hook-with-args");
667 
668   defsubr (&Sdelete_terminal);
669   defsubr (&Sframe_terminal);
670   defsubr (&Sterminal_live_p);
671   defsubr (&Sterminal_list);
672   defsubr (&Sterminal_name);
673   defsubr (&Sterminal_parameters);
674   defsubr (&Sterminal_parameter);
675   defsubr (&Sset_terminal_parameter);
676 
677   Fprovide (intern_c_string ("multi-tty"), Qnil);
678 }
679