Portability fixes (now it compiles & runs fine on Solaris).
[bpt/emacs.git] / src / term.c
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
23
24 #include <config.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
28
29 #include <sys/file.h>
30
31 #include "lisp.h"
32 #include "systty.h" /* For emacs_tty in termchar.h */
33 #include "termchar.h"
34 #include "termopts.h"
35 #include "charset.h"
36 #include "coding.h"
37 #include "keyboard.h"
38 #include "frame.h"
39 #include "disptab.h"
40 #include "termhooks.h"
41 #include "dispextern.h"
42 #include "window.h"
43 #include "keymap.h"
44
45 /* For now, don't try to include termcap.h. On some systems,
46 configure finds a non-standard termcap.h that the main build
47 won't find. */
48
49 #if defined HAVE_TERMCAP_H && 0
50 #include <termcap.h>
51 #else
52 extern void tputs P_ ((const char *, int, int (*)(int)));
53 extern int tgetent P_ ((char *, const char *));
54 extern int tgetflag P_ ((char *id));
55 extern int tgetnum P_ ((char *id));
56 #endif
57
58 #include "cm.h"
59 #ifdef HAVE_X_WINDOWS
60 #include "xterm.h"
61 #endif
62 #ifdef MAC_OS
63 #include "macterm.h"
64 #endif
65
66 #ifndef O_RDWR
67 #define O_RDWR 2
68 #endif
69
70 static void turn_on_face P_ ((struct frame *, int face_id));
71 static void turn_off_face P_ ((struct frame *, int face_id));
72 static void tty_show_cursor P_ ((struct tty_display_info *));
73 static void tty_hide_cursor P_ ((struct tty_display_info *));
74
75 void delete_tty P_ ((struct tty_display_info *));
76 static void delete_tty_1 P_ ((struct tty_display_info *));
77
78
79 #define OUTPUT(tty, a) \
80 emacs_tputs ((tty), a, \
81 (int) (FRAME_LINES (XFRAME (selected_frame)) \
82 - curY (tty)), \
83 cmputc)
84
85 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
86 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
87
88 #define OUTPUT_IF(tty, a) \
89 do { \
90 if (a) \
91 emacs_tputs ((tty), a, \
92 (int) (FRAME_LINES (XFRAME (selected_frame)) \
93 - curY (tty) ), \
94 cmputc); \
95 } while (0)
96
97 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
98
99 /* Function to use to ring the bell. */
100
101 Lisp_Object Vring_bell_function;
102
103 /* Functions to call after a tty was deleted. */
104 Lisp_Object Vdelete_tty_after_functions;
105
106 /* Terminal characteristics that higher levels want to look at. */
107
108 struct tty_display_info *tty_list;
109
110 /* Nonzero means no need to redraw the entire frame on resuming a
111 suspended Emacs. This is useful on terminals with multiple
112 pages, where one page is used for Emacs and another for all
113 else. */
114 int no_redraw_on_reenter;
115
116 Lisp_Object Qframe_tty_name, Qframe_tty_type;
117
118 /* Hook functions that you can set to snap out the functions in this file.
119 These are all extern'd in termhooks.h */
120
121 void (*cursor_to_hook) P_ ((int, int));
122 void (*raw_cursor_to_hook) P_ ((int, int));
123 void (*clear_to_end_hook) P_ ((void));
124 void (*clear_frame_hook) P_ ((void));
125 void (*clear_end_of_line_hook) P_ ((int));
126
127 void (*ins_del_lines_hook) P_ ((int, int));
128
129 void (*delete_glyphs_hook) P_ ((int));
130
131 void (*ring_bell_hook) P_ ((void));
132
133 void (*reset_terminal_modes_hook) P_ ((void));
134 void (*set_terminal_modes_hook) P_ ((void));
135 void (*update_begin_hook) P_ ((struct frame *));
136 void (*update_end_hook) P_ ((struct frame *));
137 void (*set_terminal_window_hook) P_ ((int));
138 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
139 void (*write_glyphs_hook) P_ ((struct glyph *, int));
140 void (*delete_glyphs_hook) P_ ((int));
141
142 int (*read_socket_hook) P_ ((struct input_event *, int, int));
143
144 void (*frame_up_to_date_hook) P_ ((struct frame *));
145
146 /* Return the current position of the mouse.
147
148 Set *f to the frame the mouse is in, or zero if the mouse is in no
149 Emacs frame. If it is set to zero, all the other arguments are
150 garbage.
151
152 If the motion started in a scroll bar, set *bar_window to the
153 scroll bar's window, *part to the part the mouse is currently over,
154 *x to the position of the mouse along the scroll bar, and *y to the
155 overall length of the scroll bar.
156
157 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
158 row of the character cell the mouse is over.
159
160 Set *time to the time the mouse was at the returned position.
161
162 This should clear mouse_moved until the next motion
163 event arrives. */
164
165 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
166 Lisp_Object *bar_window,
167 enum scroll_bar_part *part,
168 Lisp_Object *x,
169 Lisp_Object *y,
170 unsigned long *time));
171
172 /* When reading from a minibuffer in a different frame, Emacs wants
173 to shift the highlight from the selected frame to the mini-buffer's
174 frame; under X, this means it lies about where the focus is.
175 This hook tells the window system code to re-decide where to put
176 the highlight. */
177
178 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
179
180 /* If we're displaying frames using a window system that can stack
181 frames on top of each other, this hook allows you to bring a frame
182 to the front, or bury it behind all the other windows. If this
183 hook is zero, that means the device we're displaying on doesn't
184 support overlapping frames, so there's no need to raise or lower
185 anything.
186
187 If RAISE is non-zero, F is brought to the front, before all other
188 windows. If RAISE is zero, F is sent to the back, behind all other
189 windows. */
190
191 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
192
193 /* Set the vertical scroll bar for WINDOW to have its upper left corner
194 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
195 indicate that we are displaying PORTION characters out of a total
196 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
197 have a scroll bar, create one for it. */
198
199 void (*set_vertical_scroll_bar_hook)
200 P_ ((struct window *window,
201 int portion, int whole, int position));
202
203
204 /* The following three hooks are used when we're doing a thorough
205 redisplay of the frame. We don't explicitly know which scroll bars
206 are going to be deleted, because keeping track of when windows go
207 away is a real pain - can you say set-window-configuration?
208 Instead, we just assert at the beginning of redisplay that *all*
209 scroll bars are to be removed, and then save scroll bars from the
210 fiery pit when we actually redisplay their window. */
211
212 /* Arrange for all scroll bars on FRAME to be removed at the next call
213 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
214 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
215
216 This should be applied to each frame each time its window tree is
217 redisplayed, even if it is not displaying scroll bars at the moment;
218 if the HAS_SCROLL_BARS flag has just been turned off, only calling
219 this and the judge_scroll_bars_hook will get rid of them.
220
221 If non-zero, this hook should be safe to apply to any frame,
222 whether or not it can support scroll bars, and whether or not it is
223 currently displaying them. */
224
225 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
226
227 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
228 Note that it's okay to redeem a scroll bar that is not condemned. */
229
230 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
231
232 /* Remove all scroll bars on FRAME that haven't been saved since the
233 last call to `*condemn_scroll_bars_hook'.
234
235 This should be applied to each frame after each time its window
236 tree is redisplayed, even if it is not displaying scroll bars at the
237 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
238 calling this and condemn_scroll_bars_hook will get rid of them.
239
240 If non-zero, this hook should be safe to apply to any frame,
241 whether or not it can support scroll bars, and whether or not it is
242 currently displaying them. */
243
244 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
245
246
247 /* Meaning of bits in no_color_video. Each bit set means that the
248 corresponding attribute cannot be combined with colors. */
249
250 enum no_color_bit
251 {
252 NC_STANDOUT = 1 << 0,
253 NC_UNDERLINE = 1 << 1,
254 NC_REVERSE = 1 << 2,
255 NC_BLINK = 1 << 3,
256 NC_DIM = 1 << 4,
257 NC_BOLD = 1 << 5,
258 NC_INVIS = 1 << 6,
259 NC_PROTECT = 1 << 7,
260 NC_ALT_CHARSET = 1 << 8
261 };
262
263 /* internal state */
264
265 /* The largest frame width in any call to calculate_costs. */
266
267 int max_frame_cols;
268
269 /* The largest frame height in any call to calculate_costs. */
270
271 int max_frame_lines;
272
273 /* A template for tty display methods, with common values
274 preinitialized. */
275 static struct display_method tty_display_method_template;
276
277 /* Frame currently being redisplayed; 0 if not currently redisplaying.
278 (Direct output does not count). */
279
280 FRAME_PTR updating_frame;
281
282 /* Provided for lisp packages. */
283
284 static int system_uses_terminfo;
285
286 char *tparam ();
287
288 extern char *tgetstr ();
289 \f
290
291 #ifdef WINDOWSNT
292 /* We aren't X windows, but we aren't termcap either. This makes me
293 uncertain as to what value to use for frame.output_method. For
294 this file, we'll define FRAME_TERMCAP_P to be zero so that our
295 output hooks get called instead of the termcap functions. Probably
296 the best long-term solution is to define an output_windows_nt... */
297
298 #undef FRAME_TERMCAP_P
299 #define FRAME_TERMCAP_P(_f_) 0
300 #endif /* WINDOWSNT */
301
302 void
303 ring_bell ()
304 {
305 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
306
307 if (!NILP (Vring_bell_function))
308 {
309 Lisp_Object function;
310
311 /* Temporarily set the global variable to nil
312 so that if we get an error, it stays nil
313 and we don't call it over and over.
314
315 We don't specbind it, because that would carefully
316 restore the bad value if there's an error
317 and make the loop of errors happen anyway. */
318
319 function = Vring_bell_function;
320 Vring_bell_function = Qnil;
321
322 call0 (function);
323
324 Vring_bell_function = function;
325 }
326 else if (!FRAME_TERMCAP_P (f))
327 (*ring_bell_hook) ();
328 else {
329 struct tty_display_info *tty = FRAME_TTY (f);
330 OUTPUT (tty, tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell);
331 }
332 }
333
334 void tty_set_terminal_modes (struct tty_display_info *tty)
335 {
336 OUTPUT_IF (tty, tty->TS_termcap_modes);
337 OUTPUT_IF (tty, tty->TS_cursor_visible);
338 OUTPUT_IF (tty, tty->TS_keypad_mode);
339 losecursor (tty);
340 }
341
342 void
343 set_terminal_modes ()
344 {
345 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
346 if (FRAME_TERMCAP_P (f))
347 tty_set_terminal_modes (FRAME_TTY (f));
348 else
349 (*set_terminal_modes_hook) ();
350 }
351
352 void tty_reset_terminal_modes (struct tty_display_info *tty)
353 {
354 turn_off_highlight (tty);
355 turn_off_insert (tty);
356 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
357 OUTPUT_IF (tty, tty->TS_cursor_normal);
358 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
359 OUTPUT_IF (tty, tty->TS_orig_pair);
360 /* Output raw CR so kernel can track the cursor hpos. */
361 current_tty = tty;
362 cmputc ('\r');
363 }
364
365 void
366 reset_terminal_modes ()
367 {
368 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
369 if (FRAME_TERMCAP_P (f))
370 tty_reset_terminal_modes (FRAME_TTY (f));
371 else if (reset_terminal_modes_hook)
372 (*reset_terminal_modes_hook) ();
373 }
374
375 void
376 update_begin (f)
377 struct frame *f;
378 {
379 updating_frame = f;
380 if (!FRAME_TERMCAP_P (f))
381 update_begin_hook (f);
382 }
383
384 void
385 update_end (f)
386 struct frame *f;
387 {
388 if (FRAME_TERMCAP_P (f))
389 {
390 struct tty_display_info *tty = FRAME_TTY (f);
391 if (!XWINDOW (selected_window)->cursor_off_p)
392 tty_show_cursor (tty);
393 turn_off_insert (tty);
394 background_highlight (tty);
395 }
396 else
397 update_end_hook (f);
398
399 updating_frame = NULL;
400 }
401
402 void
403 set_terminal_window (size)
404 int size;
405 {
406 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
407 if (FRAME_TERMCAP_P (f))
408 {
409 struct tty_display_info *tty = FRAME_TTY (f);
410 tty->specified_window = size ? size : FRAME_LINES (f);
411 if (FRAME_SCROLL_REGION_OK (f))
412 set_scroll_region (0, tty->specified_window);
413 }
414 else
415 set_terminal_window_hook (size);
416 }
417
418 void
419 set_scroll_region (start, stop)
420 int start, stop;
421 {
422 char *buf;
423 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
424 struct tty_display_info *tty = FRAME_TTY (f);
425
426 if (tty->TS_set_scroll_region)
427 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
428 else if (tty->TS_set_scroll_region_1)
429 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
430 FRAME_LINES (f), start,
431 FRAME_LINES (f) - stop,
432 FRAME_LINES (f));
433 else
434 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
435
436 OUTPUT (tty, buf);
437 xfree (buf);
438 losecursor (tty);
439 }
440
441 \f
442 static void
443 turn_on_insert (struct tty_display_info *tty)
444 {
445 if (!tty->insert_mode)
446 OUTPUT (tty, tty->TS_insert_mode);
447 tty->insert_mode = 1;
448 }
449
450 void
451 turn_off_insert (struct tty_display_info *tty)
452 {
453 if (tty->insert_mode)
454 OUTPUT (tty, tty->TS_end_insert_mode);
455 tty->insert_mode = 0;
456 }
457 \f
458 /* Handle highlighting. */
459
460 void
461 turn_off_highlight (struct tty_display_info *tty)
462 {
463 if (tty->standout_mode)
464 OUTPUT_IF (tty, tty->TS_end_standout_mode);
465 tty->standout_mode = 0;
466 }
467
468 static void
469 turn_on_highlight (struct tty_display_info *tty)
470 {
471 if (!tty->standout_mode)
472 OUTPUT_IF (tty, tty->TS_standout_mode);
473 tty->standout_mode = 1;
474 }
475
476 static void
477 toggle_highlight (struct tty_display_info *tty)
478 {
479 if (tty->standout_mode)
480 turn_off_highlight (tty);
481 else
482 turn_on_highlight (tty);
483 }
484
485
486 /* Make cursor invisible. */
487
488 static void
489 tty_hide_cursor (struct tty_display_info *tty)
490 {
491 if (tty->cursor_hidden == 0)
492 {
493 tty->cursor_hidden = 1;
494 OUTPUT_IF (tty, tty->TS_cursor_invisible);
495 }
496 }
497
498
499 /* Ensure that cursor is visible. */
500
501 static void
502 tty_show_cursor (struct tty_display_info *tty)
503 {
504 if (tty->cursor_hidden)
505 {
506 tty->cursor_hidden = 0;
507 OUTPUT_IF (tty, tty->TS_cursor_normal);
508 OUTPUT_IF (tty, tty->TS_cursor_visible);
509 }
510 }
511
512
513 /* Set standout mode to the state it should be in for
514 empty space inside windows. What this is,
515 depends on the user option inverse-video. */
516
517 void
518 background_highlight (struct tty_display_info *tty)
519 {
520 if (inverse_video)
521 turn_on_highlight (tty);
522 else
523 turn_off_highlight (tty);
524 }
525
526 /* Set standout mode to the mode specified for the text to be output. */
527
528 static void
529 highlight_if_desired (struct tty_display_info *tty)
530 {
531 if (inverse_video)
532 turn_on_highlight (tty);
533 else
534 turn_off_highlight (tty);
535 }
536 \f
537
538 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
539 frame-relative coordinates. */
540
541 void
542 cursor_to (vpos, hpos)
543 int vpos, hpos;
544 {
545 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
546 struct tty_display_info *tty;
547
548 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
549 {
550 (*cursor_to_hook) (vpos, hpos);
551 return;
552 }
553
554 tty = FRAME_TTY (f);
555
556 /* Detect the case where we are called from reset_sys_modes
557 and the costs have never been calculated. Do nothing. */
558 if (! tty->costs_set)
559 return;
560
561 if (curY (tty) == vpos
562 && curX (tty) == hpos)
563 return;
564 if (!tty->TF_standout_motion)
565 background_highlight (tty);
566 if (!tty->TF_insmode_motion)
567 turn_off_insert (tty);
568 cmgoto (tty, vpos, hpos);
569 }
570
571 /* Similar but don't take any account of the wasted characters. */
572
573 void
574 raw_cursor_to (row, col)
575 int row, col;
576 {
577 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
578 struct tty_display_info *tty;
579 if (! FRAME_TERMCAP_P (f))
580 {
581 (*raw_cursor_to_hook) (row, col);
582 return;
583 }
584 tty = FRAME_TTY (f);
585 if (curY (tty) == row
586 && curX (tty) == col)
587 return;
588 if (!tty->TF_standout_motion)
589 background_highlight (tty);
590 if (!tty->TF_insmode_motion)
591 turn_off_insert (tty);
592 cmgoto (tty, row, col);
593 }
594 \f
595 /* Erase operations */
596
597 /* clear from cursor to end of frame */
598 void
599 clear_to_end ()
600 {
601 register int i;
602
603 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
604 struct tty_display_info *tty;
605
606 if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
607 {
608 (*clear_to_end_hook) ();
609 return;
610 }
611 tty = FRAME_TTY (f);
612 if (tty->TS_clr_to_bottom)
613 {
614 background_highlight (tty);
615 OUTPUT (tty, tty->TS_clr_to_bottom);
616 }
617 else
618 {
619 for (i = curY (tty); i < FRAME_LINES (f); i++)
620 {
621 cursor_to (i, 0);
622 clear_end_of_line (FRAME_COLS (f));
623 }
624 }
625 }
626
627 /* Clear entire frame */
628
629 void
630 clear_frame ()
631 {
632 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
633 struct tty_display_info *tty;
634
635 if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
636 {
637 (*clear_frame_hook) ();
638 return;
639 }
640 tty = FRAME_TTY (f);
641 if (tty->TS_clr_frame)
642 {
643 background_highlight (tty);
644 OUTPUT (tty, tty->TS_clr_frame);
645 cmat (tty, 0, 0);
646 }
647 else
648 {
649 cursor_to (0, 0);
650 clear_to_end ();
651 }
652 }
653
654 /* Clear from cursor to end of line.
655 Assume that the line is already clear starting at column first_unused_hpos.
656
657 Note that the cursor may be moved, on terminals lacking a `ce' string. */
658
659 void
660 clear_end_of_line (first_unused_hpos)
661 int first_unused_hpos;
662 {
663 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
664 struct tty_display_info *tty;
665
666 if (clear_end_of_line_hook && ! FRAME_TERMCAP_P (f))
667 {
668 (*clear_end_of_line_hook) (first_unused_hpos);
669 return;
670 }
671
672 tty_clear_end_of_line (FRAME_TTY (f), first_unused_hpos);
673 }
674
675 void
676 tty_clear_end_of_line (struct tty_display_info *tty, int first_unused_hpos)
677 {
678 register int i;
679 /* Detect the case where we are called from reset_sys_modes
680 and the costs have never been calculated. Do nothing. */
681 if (! tty->costs_set)
682 return;
683
684 if (curX (tty) >= first_unused_hpos)
685 return;
686 background_highlight (tty);
687 if (tty->TS_clr_line)
688 {
689 OUTPUT1 (tty, tty->TS_clr_line);
690 }
691 else
692 { /* have to do it the hard way */
693 turn_off_insert (tty);
694
695 /* Do not write in last row last col with Auto-wrap on. */
696 if (AutoWrap (tty)
697 && curY (tty) == FrameRows (tty) - 1
698 && first_unused_hpos == FrameCols (tty))
699 first_unused_hpos--;
700
701 for (i = curX (tty); i < first_unused_hpos; i++)
702 {
703 if (TTY_TERMSCRIPT (tty))
704 fputc (' ', TTY_TERMSCRIPT (tty));
705 fputc (' ', TTY_OUTPUT (tty));
706 }
707 cmplus (tty, first_unused_hpos - curX (tty));
708 }
709 }
710 \f
711 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
712 store them at DST. Do not write more than DST_LEN bytes. That may
713 require stopping before all SRC_LEN input glyphs have been
714 converted.
715
716 We store the number of glyphs actually converted in *CONSUMED. The
717 return value is the number of bytes store in DST. */
718
719 int
720 encode_terminal_code (src, dst, src_len, dst_len, consumed)
721 struct glyph *src;
722 int src_len;
723 unsigned char *dst;
724 int dst_len, *consumed;
725 {
726 struct glyph *src_start = src, *src_end = src + src_len;
727 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
728 register GLYPH g;
729 unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
730 const unsigned char *buf;
731 int len;
732 register int tlen = GLYPH_TABLE_LENGTH;
733 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
734 int result;
735 struct coding_system *coding;
736
737 /* If terminal_coding does any conversion, use it, otherwise use
738 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
739 because it always return 1 if the member src_multibyte is 1. */
740 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
741 ? &terminal_coding
742 : &safe_terminal_coding);
743
744 while (src < src_end)
745 {
746 /* We must skip glyphs to be padded for a wide character. */
747 if (! CHAR_GLYPH_PADDING_P (*src))
748 {
749 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
750
751 if (g < 0 || g >= tlen)
752 {
753 /* This glyph doesn't has an entry in Vglyph_table. */
754 if (! CHAR_VALID_P (src->u.ch, 0))
755 {
756 len = 1;
757 buf = " ";
758 coding->src_multibyte = 0;
759 }
760 else
761 {
762 len = CHAR_STRING (src->u.ch, workbuf);
763 buf = workbuf;
764 coding->src_multibyte = 1;
765 }
766 }
767 else
768 {
769 /* This glyph has an entry in Vglyph_table,
770 so process any alias before testing for simpleness. */
771 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
772
773 if (GLYPH_SIMPLE_P (tbase, tlen, g))
774 {
775 /* We set the multi-byte form of a character in G
776 (that should be an ASCII character) at
777 WORKBUF. */
778 workbuf[0] = FAST_GLYPH_CHAR (g);
779 len = 1;
780 buf = workbuf;
781 coding->src_multibyte = 0;
782 }
783 else
784 {
785 /* We have a string in Vglyph_table. */
786 len = GLYPH_LENGTH (tbase, g);
787 buf = GLYPH_STRING (tbase, g);
788 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
789 }
790 }
791
792 result = encode_coding (coding, buf, dst, len, dst_end - dst);
793 len -= coding->consumed;
794 dst += coding->produced;
795 if (result == CODING_FINISH_INSUFFICIENT_DST
796 || (result == CODING_FINISH_INSUFFICIENT_SRC
797 && len > dst_end - dst))
798 /* The remaining output buffer is too short. We must
799 break the loop here without increasing SRC so that the
800 next call of this function starts from the same glyph. */
801 break;
802
803 if (len > 0)
804 {
805 /* This is the case that a code of the range 0200..0237
806 exists in buf. We must just write out such a code. */
807 buf += coding->consumed;
808 while (len--)
809 *dst++ = *buf++;
810 }
811 }
812 src++;
813 }
814
815 *consumed = src - src_start;
816 return (dst - dst_start);
817 }
818
819
820 void
821 write_glyphs (string, len)
822 register struct glyph *string;
823 register int len;
824 {
825 int produced, consumed;
826 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
827 struct tty_display_info *tty;
828 unsigned char conversion_buffer[1024];
829 int conversion_buffer_size = sizeof conversion_buffer;
830
831 if (write_glyphs_hook && ! FRAME_TERMCAP_P (f))
832 {
833 (*write_glyphs_hook) (string, len);
834 return;
835 }
836
837 tty = FRAME_TTY (f);
838
839 turn_off_insert (tty);
840 tty_hide_cursor (tty);
841
842 /* Don't dare write in last column of bottom line, if Auto-Wrap,
843 since that would scroll the whole frame on some terminals. */
844
845 if (AutoWrap (tty)
846 && curY (tty) + 1 == FRAME_LINES (f)
847 && (curX (tty) + len) == FRAME_COLS (f))
848 len --;
849 if (len <= 0)
850 return;
851
852 cmplus (tty, len);
853
854 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
855 the tail. */
856 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
857
858 while (len > 0)
859 {
860 /* Identify a run of glyphs with the same face. */
861 int face_id = string->face_id;
862 int n;
863
864 for (n = 1; n < len; ++n)
865 if (string[n].face_id != face_id)
866 break;
867
868 /* Turn appearance modes of the face of the run on. */
869 highlight_if_desired (tty);
870 turn_on_face (f, face_id);
871
872 while (n > 0)
873 {
874 /* We use a fixed size (1024 bytes) of conversion buffer.
875 Usually it is sufficient, but if not, we just repeat the
876 loop. */
877 produced = encode_terminal_code (string, conversion_buffer,
878 n, conversion_buffer_size,
879 &consumed);
880 if (produced > 0)
881 {
882 fwrite (conversion_buffer, 1, produced,
883 TTY_OUTPUT (tty));
884 if (ferror (TTY_OUTPUT (tty)))
885 clearerr (TTY_OUTPUT (tty));
886 if (TTY_TERMSCRIPT (tty))
887 fwrite (conversion_buffer, 1, produced,
888 TTY_TERMSCRIPT (tty));
889 }
890 len -= consumed;
891 n -= consumed;
892 string += consumed;
893 }
894
895 /* Turn appearance modes off. */
896 turn_off_face (f, face_id);
897 turn_off_highlight (tty);
898 }
899
900 /* We may have to output some codes to terminate the writing. */
901 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
902 {
903 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
904 encode_coding (&terminal_coding, "", conversion_buffer,
905 0, conversion_buffer_size);
906 if (terminal_coding.produced > 0)
907 {
908 fwrite (conversion_buffer, 1, terminal_coding.produced,
909 TTY_OUTPUT (tty));
910 if (ferror (TTY_OUTPUT (tty)))
911 clearerr (TTY_OUTPUT (tty));
912 if (TTY_TERMSCRIPT (tty))
913 fwrite (conversion_buffer, 1, terminal_coding.produced,
914 TTY_TERMSCRIPT (tty));
915 }
916 }
917
918 cmcheckmagic (tty);
919 }
920
921 /* If start is zero, insert blanks instead of a string at start */
922
923 void
924 insert_glyphs (start, len)
925 register struct glyph *start;
926 register int len;
927 {
928 char *buf;
929 struct glyph *glyph = NULL;
930 struct frame *f;
931 struct tty_display_info *tty;
932
933 if (len <= 0)
934 return;
935
936 f = (updating_frame ? updating_frame : XFRAME (selected_frame));
937
938 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (f))
939 {
940 (*insert_glyphs_hook) (start, len);
941 return;
942 }
943
944 tty = FRAME_TTY (f);
945
946 if (tty->TS_ins_multi_chars)
947 {
948 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
949 OUTPUT1 (tty, buf);
950 xfree (buf);
951 if (start)
952 write_glyphs (start, len);
953 return;
954 }
955
956 turn_on_insert (tty);
957 cmplus (tty, len);
958 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
959 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
960 while (len-- > 0)
961 {
962 int produced, consumed;
963 unsigned char conversion_buffer[1024];
964 int conversion_buffer_size = sizeof conversion_buffer;
965
966 OUTPUT1_IF (tty, tty->TS_ins_char);
967 if (!start)
968 {
969 conversion_buffer[0] = SPACEGLYPH;
970 produced = 1;
971 }
972 else
973 {
974 highlight_if_desired (tty);
975 turn_on_face (f, start->face_id);
976 glyph = start;
977 ++start;
978 /* We must open sufficient space for a character which
979 occupies more than one column. */
980 while (len && CHAR_GLYPH_PADDING_P (*start))
981 {
982 OUTPUT1_IF (tty, tty->TS_ins_char);
983 start++, len--;
984 }
985
986 if (len <= 0)
987 /* This is the last glyph. */
988 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
989
990 /* The size of conversion buffer (1024 bytes) is surely
991 sufficient for just one glyph. */
992 produced = encode_terminal_code (glyph, conversion_buffer, 1,
993 conversion_buffer_size, &consumed);
994 }
995
996 if (produced > 0)
997 {
998 fwrite (conversion_buffer, 1, produced,
999 TTY_OUTPUT (tty));
1000 if (ferror (TTY_OUTPUT (tty)))
1001 clearerr (TTY_OUTPUT (tty));
1002 if (TTY_TERMSCRIPT (tty))
1003 fwrite (conversion_buffer, 1, produced,
1004 TTY_TERMSCRIPT (tty));
1005 }
1006
1007 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
1008 if (start)
1009 {
1010 turn_off_face (f, glyph->face_id);
1011 turn_off_highlight (tty);
1012 }
1013 }
1014
1015 cmcheckmagic (tty);
1016 }
1017
1018 void
1019 delete_glyphs (n)
1020 register int n;
1021 {
1022 char *buf;
1023 register int i;
1024 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
1025 struct tty_display_info *tty = FRAME_TTY (f);
1026
1027 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (f))
1028 {
1029 (*delete_glyphs_hook) (n);
1030 return;
1031 }
1032
1033
1034 if (tty->delete_in_insert_mode)
1035 {
1036 turn_on_insert (tty);
1037 }
1038 else
1039 {
1040 turn_off_insert (tty);
1041 OUTPUT_IF (tty, tty->TS_delete_mode);
1042 }
1043
1044 if (tty->TS_del_multi_chars)
1045 {
1046 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1047 OUTPUT1 (tty, buf);
1048 xfree (buf);
1049 }
1050 else
1051 for (i = 0; i < n; i++)
1052 OUTPUT1 (tty, tty->TS_del_char);
1053 if (!tty->delete_in_insert_mode)
1054 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1055 }
1056 \f
1057 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1058
1059 void
1060 ins_del_lines (vpos, n)
1061 int vpos, n;
1062 {
1063 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
1064 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (f))
1065 {
1066 (*ins_del_lines_hook) (vpos, n);
1067 return;
1068 }
1069 else
1070 {
1071 struct tty_display_info *tty = FRAME_TTY (f);
1072 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1073 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1074 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1075
1076 register int i = n > 0 ? n : -n;
1077 register char *buf;
1078
1079 /* If the lines below the insertion are being pushed
1080 into the end of the window, this is the same as clearing;
1081 and we know the lines are already clear, since the matching
1082 deletion has already been done. So can ignore this. */
1083 /* If the lines below the deletion are blank lines coming
1084 out of the end of the window, don't bother,
1085 as there will be a matching inslines later that will flush them. */
1086 if (FRAME_SCROLL_REGION_OK (f)
1087 && vpos + i >= tty->specified_window)
1088 return;
1089 if (!FRAME_MEMORY_BELOW_FRAME (f)
1090 && vpos + i >= FRAME_LINES (f))
1091 return;
1092
1093 if (multi)
1094 {
1095 raw_cursor_to (vpos, 0);
1096 background_highlight (tty);
1097 buf = tparam (multi, 0, 0, i);
1098 OUTPUT (tty, buf);
1099 xfree (buf);
1100 }
1101 else if (single)
1102 {
1103 raw_cursor_to (vpos, 0);
1104 background_highlight (tty);
1105 while (--i >= 0)
1106 OUTPUT (tty, single);
1107 if (tty->TF_teleray)
1108 curX (tty) = 0;
1109 }
1110 else
1111 {
1112 set_scroll_region (vpos, tty->specified_window);
1113 if (n < 0)
1114 raw_cursor_to (tty->specified_window - 1, 0);
1115 else
1116 raw_cursor_to (vpos, 0);
1117 background_highlight (tty);
1118 while (--i >= 0)
1119 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1120 set_scroll_region (0, tty->specified_window);
1121 }
1122
1123 if (!FRAME_SCROLL_REGION_OK (f)
1124 && FRAME_MEMORY_BELOW_FRAME (f)
1125 && n < 0)
1126 {
1127 cursor_to (FRAME_LINES (f) + n, 0);
1128 clear_to_end ();
1129 }
1130 }
1131 }
1132 \f
1133 /* Compute cost of sending "str", in characters,
1134 not counting any line-dependent padding. */
1135
1136 int
1137 string_cost (str)
1138 char *str;
1139 {
1140 cost = 0;
1141 if (str)
1142 tputs (str, 0, evalcost);
1143 return cost;
1144 }
1145
1146 /* Compute cost of sending "str", in characters,
1147 counting any line-dependent padding at one line. */
1148
1149 static int
1150 string_cost_one_line (str)
1151 char *str;
1152 {
1153 cost = 0;
1154 if (str)
1155 tputs (str, 1, evalcost);
1156 return cost;
1157 }
1158
1159 /* Compute per line amount of line-dependent padding,
1160 in tenths of characters. */
1161
1162 int
1163 per_line_cost (str)
1164 register char *str;
1165 {
1166 cost = 0;
1167 if (str)
1168 tputs (str, 0, evalcost);
1169 cost = - cost;
1170 if (str)
1171 tputs (str, 10, evalcost);
1172 return cost;
1173 }
1174
1175 #ifndef old
1176 /* char_ins_del_cost[n] is cost of inserting N characters.
1177 char_ins_del_cost[-n] is cost of deleting N characters.
1178 The length of this vector is based on max_frame_cols. */
1179
1180 int *char_ins_del_vector;
1181
1182 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1183 #endif
1184
1185 /* ARGSUSED */
1186 static void
1187 calculate_ins_del_char_costs (f)
1188 FRAME_PTR f;
1189 {
1190 struct tty_display_info *tty = FRAME_TTY (f);
1191 int ins_startup_cost, del_startup_cost;
1192 int ins_cost_per_char, del_cost_per_char;
1193 register int i;
1194 register int *p;
1195
1196 if (tty->TS_ins_multi_chars)
1197 {
1198 ins_cost_per_char = 0;
1199 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1200 }
1201 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1202 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1203 {
1204 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1205 + string_cost (tty->TS_end_insert_mode))) / 100;
1206 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1207 + string_cost_one_line (tty->TS_pad_inserted_char));
1208 }
1209 else
1210 {
1211 ins_startup_cost = 9999;
1212 ins_cost_per_char = 0;
1213 }
1214
1215 if (tty->TS_del_multi_chars)
1216 {
1217 del_cost_per_char = 0;
1218 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1219 }
1220 else if (tty->TS_del_char)
1221 {
1222 del_startup_cost = (string_cost (tty->TS_delete_mode)
1223 + string_cost (tty->TS_end_delete_mode));
1224 if (tty->delete_in_insert_mode)
1225 del_startup_cost /= 2;
1226 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1227 }
1228 else
1229 {
1230 del_startup_cost = 9999;
1231 del_cost_per_char = 0;
1232 }
1233
1234 /* Delete costs are at negative offsets */
1235 p = &char_ins_del_cost (f)[0];
1236 for (i = FRAME_COLS (f); --i >= 0;)
1237 *--p = (del_startup_cost += del_cost_per_char);
1238
1239 /* Doing nothing is free */
1240 p = &char_ins_del_cost (f)[0];
1241 *p++ = 0;
1242
1243 /* Insert costs are at positive offsets */
1244 for (i = FRAME_COLS (f); --i >= 0;)
1245 *p++ = (ins_startup_cost += ins_cost_per_char);
1246 }
1247
1248 void
1249 calculate_costs (frame)
1250 FRAME_PTR frame;
1251 {
1252 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1253
1254 if (FRAME_TERMCAP_P (frame))
1255 {
1256 struct tty_display_info *tty = FRAME_TTY (frame);
1257 register char *f = (tty->TS_set_scroll_region
1258 ? tty->TS_set_scroll_region
1259 : tty->TS_set_scroll_region_1);
1260
1261 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1262
1263 tty->costs_set = 1;
1264
1265 /* These variables are only used for terminal stuff. They are
1266 allocated once for the terminal frame of X-windows emacs, but not
1267 used afterwards.
1268
1269 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1270 X turns off char_ins_del_ok. */
1271
1272 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1273 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1274
1275 if (char_ins_del_vector != 0)
1276 char_ins_del_vector
1277 = (int *) xrealloc (char_ins_del_vector,
1278 (sizeof (int)
1279 + 2 * max_frame_cols * sizeof (int)));
1280 else
1281 char_ins_del_vector
1282 = (int *) xmalloc (sizeof (int)
1283 + 2 * max_frame_cols * sizeof (int));
1284
1285 bzero (char_ins_del_vector, (sizeof (int)
1286 + 2 * max_frame_cols * sizeof (int)));
1287
1288
1289 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1290 do_line_insertion_deletion_costs (frame,
1291 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1292 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1293 f, f, 1);
1294 else
1295 do_line_insertion_deletion_costs (frame,
1296 tty->TS_ins_line, tty->TS_ins_multi_lines,
1297 tty->TS_del_line, tty->TS_del_multi_lines,
1298 0, 0, 1);
1299
1300 calculate_ins_del_char_costs (frame);
1301
1302 /* Don't use TS_repeat if its padding is worse than sending the chars */
1303 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1304 tty->RPov = string_cost (tty->TS_repeat);
1305 else
1306 tty->RPov = FRAME_COLS (frame) * 2;
1307
1308 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1309 }
1310 }
1311 \f
1312 struct fkey_table {
1313 char *cap, *name;
1314 };
1315
1316 /* Termcap capability names that correspond directly to X keysyms.
1317 Some of these (marked "terminfo") aren't supplied by old-style
1318 (Berkeley) termcap entries. They're listed in X keysym order;
1319 except we put the keypad keys first, so that if they clash with
1320 other keys (as on the IBM PC keyboard) they get overridden.
1321 */
1322
1323 static struct fkey_table keys[] =
1324 {
1325 {"kh", "home"}, /* termcap */
1326 {"kl", "left"}, /* termcap */
1327 {"ku", "up"}, /* termcap */
1328 {"kr", "right"}, /* termcap */
1329 {"kd", "down"}, /* termcap */
1330 {"%8", "prior"}, /* terminfo */
1331 {"%5", "next"}, /* terminfo */
1332 {"@7", "end"}, /* terminfo */
1333 {"@1", "begin"}, /* terminfo */
1334 {"*6", "select"}, /* terminfo */
1335 {"%9", "print"}, /* terminfo */
1336 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1337 /*
1338 * "insert" --- see below
1339 */
1340 {"&8", "undo"}, /* terminfo */
1341 {"%0", "redo"}, /* terminfo */
1342 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1343 {"@0", "find"}, /* terminfo */
1344 {"@2", "cancel"}, /* terminfo */
1345 {"%1", "help"}, /* terminfo */
1346 /*
1347 * "break" goes here, but can't be reliably intercepted with termcap
1348 */
1349 {"&4", "reset"}, /* terminfo --- actually `restart' */
1350 /*
1351 * "system" and "user" --- no termcaps
1352 */
1353 {"kE", "clearline"}, /* terminfo */
1354 {"kA", "insertline"}, /* terminfo */
1355 {"kL", "deleteline"}, /* terminfo */
1356 {"kI", "insertchar"}, /* terminfo */
1357 {"kD", "deletechar"}, /* terminfo */
1358 {"kB", "backtab"}, /* terminfo */
1359 /*
1360 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1361 */
1362 {"@8", "kp-enter"}, /* terminfo */
1363 /*
1364 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1365 * "kp-multiply", "kp-add", "kp-separator",
1366 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1367 * --- no termcaps for any of these.
1368 */
1369 {"K4", "kp-1"}, /* terminfo */
1370 /*
1371 * "kp-2" --- no termcap
1372 */
1373 {"K5", "kp-3"}, /* terminfo */
1374 /*
1375 * "kp-4" --- no termcap
1376 */
1377 {"K2", "kp-5"}, /* terminfo */
1378 /*
1379 * "kp-6" --- no termcap
1380 */
1381 {"K1", "kp-7"}, /* terminfo */
1382 /*
1383 * "kp-8" --- no termcap
1384 */
1385 {"K3", "kp-9"}, /* terminfo */
1386 /*
1387 * "kp-equal" --- no termcap
1388 */
1389 {"k1", "f1"},
1390 {"k2", "f2"},
1391 {"k3", "f3"},
1392 {"k4", "f4"},
1393 {"k5", "f5"},
1394 {"k6", "f6"},
1395 {"k7", "f7"},
1396 {"k8", "f8"},
1397 {"k9", "f9"}
1398 };
1399
1400 static char **term_get_fkeys_arg;
1401 static Lisp_Object term_get_fkeys_1 ();
1402
1403 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1404 This function scans the termcap function key sequence entries, and
1405 adds entries to Vfunction_key_map for each function key it finds. */
1406
1407 void
1408 term_get_fkeys (address)
1409 char **address;
1410 {
1411 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1412 errors during the call. The only errors should be from Fdefine_key
1413 when given a key sequence containing an invalid prefix key. If the
1414 termcap defines function keys which use a prefix that is already bound
1415 to a command by the default bindings, we should silently ignore that
1416 function key specification, rather than giving the user an error and
1417 refusing to run at all on such a terminal. */
1418
1419 extern Lisp_Object Fidentity ();
1420 term_get_fkeys_arg = address;
1421 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1422 }
1423
1424 static Lisp_Object
1425 term_get_fkeys_1 ()
1426 {
1427 int i;
1428
1429 char **address = term_get_fkeys_arg;
1430
1431 /* This can happen if CANNOT_DUMP or with strange options. */
1432 if (!initialized)
1433 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1434
1435 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1436 {
1437 char *sequence = tgetstr (keys[i].cap, address);
1438 if (sequence)
1439 Fdefine_key (Vfunction_key_map, build_string (sequence),
1440 Fmake_vector (make_number (1),
1441 intern (keys[i].name)));
1442 }
1443
1444 /* The uses of the "k0" capability are inconsistent; sometimes it
1445 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1446 We will attempt to politely accommodate both systems by testing for
1447 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1448 */
1449 {
1450 char *k_semi = tgetstr ("k;", address);
1451 char *k0 = tgetstr ("k0", address);
1452 char *k0_name = "f10";
1453
1454 if (k_semi)
1455 {
1456 if (k0)
1457 /* Define f0 first, so that f10 takes precedence in case the
1458 key sequences happens to be the same. */
1459 Fdefine_key (Vfunction_key_map, build_string (k0),
1460 Fmake_vector (make_number (1), intern ("f0")));
1461 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1462 Fmake_vector (make_number (1), intern ("f10")));
1463 }
1464 else if (k0)
1465 Fdefine_key (Vfunction_key_map, build_string (k0),
1466 Fmake_vector (make_number (1), intern (k0_name)));
1467 }
1468
1469 /* Set up cookies for numbered function keys above f10. */
1470 {
1471 char fcap[3], fkey[4];
1472
1473 fcap[0] = 'F'; fcap[2] = '\0';
1474 for (i = 11; i < 64; i++)
1475 {
1476 if (i <= 19)
1477 fcap[1] = '1' + i - 11;
1478 else if (i <= 45)
1479 fcap[1] = 'A' + i - 20;
1480 else
1481 fcap[1] = 'a' + i - 46;
1482
1483 {
1484 char *sequence = tgetstr (fcap, address);
1485 if (sequence)
1486 {
1487 sprintf (fkey, "f%d", i);
1488 Fdefine_key (Vfunction_key_map, build_string (sequence),
1489 Fmake_vector (make_number (1),
1490 intern (fkey)));
1491 }
1492 }
1493 }
1494 }
1495
1496 /*
1497 * Various mappings to try and get a better fit.
1498 */
1499 {
1500 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1501 if (!tgetstr (cap1, address)) \
1502 { \
1503 char *sequence = tgetstr (cap2, address); \
1504 if (sequence) \
1505 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1506 Fmake_vector (make_number (1), \
1507 intern (sym))); \
1508 }
1509
1510 /* if there's no key_next keycap, map key_npage to `next' keysym */
1511 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1512 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1513 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1514 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1515 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1516 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1517 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1518
1519 /* IBM has their own non-standard dialect of terminfo.
1520 If the standard name isn't found, try the IBM name. */
1521 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1522 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1523 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1524 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1525 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1526 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1527 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1528 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1529 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1530 #undef CONDITIONAL_REASSIGN
1531 }
1532
1533 return Qnil;
1534 }
1535
1536 \f
1537 /***********************************************************************
1538 Character Display Information
1539 ***********************************************************************/
1540
1541 static void append_glyph P_ ((struct it *));
1542
1543
1544 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1545 terminal frames if IT->glyph_row != NULL. IT->c is the character
1546 for which to produce glyphs; IT->face_id contains the character's
1547 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1548 1. */
1549
1550 static void
1551 append_glyph (it)
1552 struct it *it;
1553 {
1554 struct glyph *glyph, *end;
1555 int i;
1556
1557 xassert (it->glyph_row);
1558 glyph = (it->glyph_row->glyphs[it->area]
1559 + it->glyph_row->used[it->area]);
1560 end = it->glyph_row->glyphs[1 + it->area];
1561
1562 for (i = 0;
1563 i < it->pixel_width && glyph < end;
1564 ++i)
1565 {
1566 glyph->type = CHAR_GLYPH;
1567 glyph->pixel_width = 1;
1568 glyph->u.ch = it->c;
1569 glyph->face_id = it->face_id;
1570 glyph->padding_p = i > 0;
1571 glyph->charpos = CHARPOS (it->position);
1572 glyph->object = it->object;
1573
1574 ++it->glyph_row->used[it->area];
1575 ++glyph;
1576 }
1577 }
1578
1579
1580 /* Produce glyphs for the display element described by IT. *IT
1581 specifies what we want to produce a glyph for (character, image, ...),
1582 and where in the glyph matrix we currently are (glyph row and hpos).
1583 produce_glyphs fills in output fields of *IT with information such as the
1584 pixel width and height of a character, and maybe output actual glyphs at
1585 the same time if IT->glyph_row is non-null. See the explanation of
1586 struct display_iterator in dispextern.h for an overview.
1587
1588 produce_glyphs also stores the result of glyph width, ascent
1589 etc. computations in *IT.
1590
1591 IT->glyph_row may be null, in which case produce_glyphs does not
1592 actually fill in the glyphs. This is used in the move_* functions
1593 in xdisp.c for text width and height computations.
1594
1595 Callers usually don't call produce_glyphs directly;
1596 instead they use the macro PRODUCE_GLYPHS. */
1597
1598 void
1599 produce_glyphs (it)
1600 struct it *it;
1601 {
1602 /* If a hook is installed, let it do the work. */
1603 xassert (it->what == IT_CHARACTER
1604 || it->what == IT_COMPOSITION
1605 || it->what == IT_IMAGE
1606 || it->what == IT_STRETCH);
1607
1608 /* Nothing but characters are supported on terminal frames. For a
1609 composition sequence, it->c is the first character of the
1610 sequence. */
1611 xassert (it->what == IT_CHARACTER
1612 || it->what == IT_COMPOSITION);
1613
1614 if (it->c >= 040 && it->c < 0177)
1615 {
1616 it->pixel_width = it->nglyphs = 1;
1617 if (it->glyph_row)
1618 append_glyph (it);
1619 }
1620 else if (it->c == '\n')
1621 it->pixel_width = it->nglyphs = 0;
1622 else if (it->c == '\t')
1623 {
1624 int absolute_x = (it->current_x
1625 + it->continuation_lines_width);
1626 int next_tab_x
1627 = (((1 + absolute_x + it->tab_width - 1)
1628 / it->tab_width)
1629 * it->tab_width);
1630 int nspaces;
1631
1632 /* If part of the TAB has been displayed on the previous line
1633 which is continued now, continuation_lines_width will have
1634 been incremented already by the part that fitted on the
1635 continued line. So, we will get the right number of spaces
1636 here. */
1637 nspaces = next_tab_x - absolute_x;
1638
1639 if (it->glyph_row)
1640 {
1641 int n = nspaces;
1642
1643 it->c = ' ';
1644 it->pixel_width = it->len = 1;
1645
1646 while (n--)
1647 append_glyph (it);
1648
1649 it->c = '\t';
1650 }
1651
1652 it->pixel_width = nspaces;
1653 it->nglyphs = nspaces;
1654 }
1655 else if (SINGLE_BYTE_CHAR_P (it->c))
1656 {
1657 /* Coming here means that it->c is from display table, thus we
1658 must send the code as is to the terminal. Although there's
1659 no way to know how many columns it occupies on a screen, it
1660 is a good assumption that a single byte code has 1-column
1661 width. */
1662 it->pixel_width = it->nglyphs = 1;
1663 if (it->glyph_row)
1664 append_glyph (it);
1665 }
1666 else
1667 {
1668 /* A multi-byte character. The display width is fixed for all
1669 characters of the set. Some of the glyphs may have to be
1670 ignored because they are already displayed in a continued
1671 line. */
1672 int charset = CHAR_CHARSET (it->c);
1673
1674 it->pixel_width = CHARSET_WIDTH (charset);
1675 it->nglyphs = it->pixel_width;
1676
1677 if (it->glyph_row)
1678 append_glyph (it);
1679 }
1680
1681 /* Advance current_x by the pixel width as a convenience for
1682 the caller. */
1683 if (it->area == TEXT_AREA)
1684 it->current_x += it->pixel_width;
1685 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1686 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1687 }
1688
1689
1690 /* Get information about special display element WHAT in an
1691 environment described by IT. WHAT is one of IT_TRUNCATION or
1692 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1693 non-null glyph_row member. This function ensures that fields like
1694 face_id, c, len of IT are left untouched. */
1695
1696 void
1697 produce_special_glyphs (it, what)
1698 struct it *it;
1699 enum display_element_type what;
1700 {
1701 struct it temp_it;
1702
1703 temp_it = *it;
1704 temp_it.dp = NULL;
1705 temp_it.what = IT_CHARACTER;
1706 temp_it.len = 1;
1707 temp_it.object = make_number (0);
1708 bzero (&temp_it.current, sizeof temp_it.current);
1709
1710 if (what == IT_CONTINUATION)
1711 {
1712 /* Continuation glyph. */
1713 if (it->dp
1714 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1715 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1716 {
1717 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1718 temp_it.len = CHAR_BYTES (temp_it.c);
1719 }
1720 else
1721 temp_it.c = '\\';
1722
1723 produce_glyphs (&temp_it);
1724 it->pixel_width = temp_it.pixel_width;
1725 it->nglyphs = temp_it.pixel_width;
1726 }
1727 else if (what == IT_TRUNCATION)
1728 {
1729 /* Truncation glyph. */
1730 if (it->dp
1731 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1732 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1733 {
1734 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1735 temp_it.len = CHAR_BYTES (temp_it.c);
1736 }
1737 else
1738 temp_it.c = '$';
1739
1740 produce_glyphs (&temp_it);
1741 it->pixel_width = temp_it.pixel_width;
1742 it->nglyphs = temp_it.pixel_width;
1743 }
1744 else
1745 abort ();
1746 }
1747
1748
1749 \f
1750 /***********************************************************************
1751 Faces
1752 ***********************************************************************/
1753
1754 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1755 one of the enumerators from enum no_color_bit, or a bit set built
1756 from them. Some display attributes may not be used together with
1757 color; the termcap capability `NC' specifies which ones. */
1758
1759 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1760 (tty->TN_max_colors > 0 \
1761 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1762 : 1)
1763
1764 /* Turn appearances of face FACE_ID on tty frame F on. */
1765
1766 static void
1767 turn_on_face (f, face_id)
1768 struct frame *f;
1769 int face_id;
1770 {
1771 struct face *face = FACE_FROM_ID (f, face_id);
1772 long fg = face->foreground;
1773 long bg = face->background;
1774 struct tty_display_info *tty = FRAME_TTY (f);
1775
1776 /* Do this first because TS_end_standout_mode may be the same
1777 as TS_exit_attribute_mode, which turns all appearances off. */
1778 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1779 {
1780 if (tty->TN_max_colors > 0)
1781 {
1782 if (fg >= 0 && bg >= 0)
1783 {
1784 /* If the terminal supports colors, we can set them
1785 below without using reverse video. The face's fg
1786 and bg colors are set as they should appear on
1787 the screen, i.e. they take the inverse-video'ness
1788 of the face already into account. */
1789 }
1790 else if (inverse_video)
1791 {
1792 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1793 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1794 toggle_highlight (tty);
1795 }
1796 else
1797 {
1798 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1799 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1800 toggle_highlight (tty);
1801 }
1802 }
1803 else
1804 {
1805 /* If we can't display colors, use reverse video
1806 if the face specifies that. */
1807 if (inverse_video)
1808 {
1809 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1810 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1811 toggle_highlight (tty);
1812 }
1813 else
1814 {
1815 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1816 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1817 toggle_highlight (tty);
1818 }
1819 }
1820 }
1821
1822 if (face->tty_bold_p)
1823 {
1824 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1825 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1826 }
1827 else if (face->tty_dim_p)
1828 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1829 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1830
1831 /* Alternate charset and blinking not yet used. */
1832 if (face->tty_alt_charset_p
1833 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1834 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1835
1836 if (face->tty_blinking_p
1837 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1838 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1839
1840 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1841 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1842
1843 if (tty->TN_max_colors > 0)
1844 {
1845 char *p;
1846
1847 if (fg >= 0 && tty->TS_set_foreground)
1848 {
1849 p = tparam (tty->TS_set_foreground, NULL, 0, (int) fg);
1850 OUTPUT (tty, p);
1851 xfree (p);
1852 }
1853
1854 if (bg >= 0 && tty->TS_set_background)
1855 {
1856 p = tparam (tty->TS_set_background, NULL, 0, (int) bg);
1857 OUTPUT (tty, p);
1858 xfree (p);
1859 }
1860 }
1861 }
1862
1863
1864 /* Turn off appearances of face FACE_ID on tty frame F. */
1865
1866 static void
1867 turn_off_face (f, face_id)
1868 struct frame *f;
1869 int face_id;
1870 {
1871 struct face *face = FACE_FROM_ID (f, face_id);
1872 struct tty_display_info *tty = FRAME_TTY (f);
1873
1874 xassert (face != NULL);
1875
1876 if (tty->TS_exit_attribute_mode)
1877 {
1878 /* Capability "me" will turn off appearance modes double-bright,
1879 half-bright, reverse-video, standout, underline. It may or
1880 may not turn off alt-char-mode. */
1881 if (face->tty_bold_p
1882 || face->tty_dim_p
1883 || face->tty_reverse_p
1884 || face->tty_alt_charset_p
1885 || face->tty_blinking_p
1886 || face->tty_underline_p)
1887 {
1888 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1889 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1890 tty->standout_mode = 0;
1891 }
1892
1893 if (face->tty_alt_charset_p)
1894 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1895 }
1896 else
1897 {
1898 /* If we don't have "me" we can only have those appearances
1899 that have exit sequences defined. */
1900 if (face->tty_alt_charset_p)
1901 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1902
1903 if (face->tty_underline_p)
1904 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
1905 }
1906
1907 /* Switch back to default colors. */
1908 if (tty->TN_max_colors > 0
1909 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
1910 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
1911 || (face->background != FACE_TTY_DEFAULT_COLOR
1912 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
1913 OUTPUT1_IF (tty, tty->TS_orig_pair);
1914 }
1915
1916
1917 /* Return non-zero if the terminal on frame F supports all of the
1918 capabilities in CAPS simultaneously, with foreground and background
1919 colors FG and BG. */
1920
1921 int
1922 tty_capable_p (tty, caps, fg, bg)
1923 struct tty_display_info *tty;
1924 unsigned caps;
1925 unsigned long fg, bg;
1926 {
1927 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1928 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1929 return 0;
1930
1931 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
1932 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
1933 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
1934 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
1935 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
1936 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
1937
1938 /* We can do it! */
1939 return 1;
1940 }
1941
1942
1943 /* Return non-zero if the terminal is capable to display colors. */
1944
1945 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
1946 0, 1, 0,
1947 doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
1948 (display)
1949 Lisp_Object display;
1950 {
1951 struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
1952 return tty->TN_max_colors > 0 ? Qt : Qnil;
1953 }
1954
1955 /* Return the number of supported colors. */
1956 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
1957 Stty_display_color_cells, 0, 1, 0,
1958 doc: /* Return the number of colors supported by TTY on DISPLAY. */)
1959 (display)
1960 Lisp_Object display;
1961 {
1962 struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
1963 return make_number (tty->TN_max_colors);
1964 }
1965
1966 #ifndef WINDOWSNT
1967
1968 /* Save or restore the default color-related capabilities of this
1969 terminal. */
1970 static void
1971 tty_default_color_capabilities (struct tty_display_info *tty, int save)
1972 {
1973 static char
1974 *default_orig_pair, *default_set_foreground, *default_set_background;
1975 static int default_max_colors, default_max_pairs, default_no_color_video;
1976
1977 if (save)
1978 {
1979 if (default_orig_pair)
1980 xfree (default_orig_pair);
1981 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
1982
1983 if (default_set_foreground)
1984 xfree (default_set_foreground);
1985 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
1986 : NULL;
1987
1988 if (default_set_background)
1989 xfree (default_set_background);
1990 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
1991 : NULL;
1992
1993 default_max_colors = tty->TN_max_colors;
1994 default_max_pairs = tty->TN_max_pairs;
1995 default_no_color_video = tty->TN_no_color_video;
1996 }
1997 else
1998 {
1999 tty->TS_orig_pair = default_orig_pair;
2000 tty->TS_set_foreground = default_set_foreground;
2001 tty->TS_set_background = default_set_background;
2002 tty->TN_max_colors = default_max_colors;
2003 tty->TN_max_pairs = default_max_pairs;
2004 tty->TN_no_color_video = default_no_color_video;
2005 }
2006 }
2007
2008 /* Setup one of the standard tty color schemes according to MODE.
2009 MODE's value is generally the number of colors which we want to
2010 support; zero means set up for the default capabilities, the ones
2011 we saw at term_init time; -1 means turn off color support. */
2012 void
2013 tty_setup_colors (struct tty_display_info *tty, int mode)
2014 {
2015 /* Canonicalize all negative values of MODE. */
2016 if (mode < -1)
2017 mode = -1;
2018
2019 switch (mode)
2020 {
2021 case -1: /* no colors at all */
2022 tty->TN_max_colors = 0;
2023 tty->TN_max_pairs = 0;
2024 tty->TN_no_color_video = 0;
2025 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2026 break;
2027 case 0: /* default colors, if any */
2028 default:
2029 tty_default_color_capabilities (tty, 0);
2030 break;
2031 case 8: /* 8 standard ANSI colors */
2032 tty->TS_orig_pair = "\033[0m";
2033 #ifdef TERMINFO
2034 tty->TS_set_foreground = "\033[3%p1%dm";
2035 tty->TS_set_background = "\033[4%p1%dm";
2036 #else
2037 tty->TS_set_foreground = "\033[3%dm";
2038 tty->TS_set_background = "\033[4%dm";
2039 #endif
2040 tty->TN_max_colors = 8;
2041 tty->TN_max_pairs = 64;
2042 tty->TN_no_color_video = 0;
2043 break;
2044 }
2045 }
2046
2047 void
2048 set_tty_color_mode (f, val)
2049 struct frame *f;
2050 Lisp_Object val;
2051 {
2052 Lisp_Object color_mode_spec, current_mode_spec;
2053 Lisp_Object color_mode, current_mode;
2054 int mode, old_mode;
2055 extern Lisp_Object Qtty_color_mode;
2056 Lisp_Object tty_color_mode_alist;
2057
2058 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2059 Qnil);
2060
2061 if (INTEGERP (val))
2062 color_mode = val;
2063 else
2064 {
2065 if (NILP (tty_color_mode_alist))
2066 color_mode_spec = Qnil;
2067 else
2068 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
2069
2070 if (CONSP (color_mode_spec))
2071 color_mode = XCDR (color_mode_spec);
2072 else
2073 color_mode = Qnil;
2074 }
2075
2076 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2077
2078 if (CONSP (current_mode_spec))
2079 current_mode = XCDR (current_mode_spec);
2080 else
2081 current_mode = Qnil;
2082 if (INTEGERP (color_mode))
2083 mode = XINT (color_mode);
2084 else
2085 mode = 0; /* meaning default */
2086 if (INTEGERP (current_mode))
2087 old_mode = XINT (current_mode);
2088 else
2089 old_mode = 0;
2090
2091 if (mode != old_mode)
2092 {
2093 tty_setup_colors (FRAME_TTY (f), mode);
2094 /* This recomputes all the faces given the new color
2095 definitions. */
2096 call0 (intern ("tty-set-up-initial-frame-faces"));
2097 redraw_frame (f);
2098 }
2099 }
2100
2101 #endif /* !WINDOWSNT */
2102
2103 \f
2104
2105 struct tty_display_info *
2106 get_named_tty (name)
2107 char *name;
2108 {
2109 struct tty_display_info *tty = tty_list;
2110
2111 while (tty) {
2112 if ((tty->name == 0 && name == 0)
2113 || (name && tty->name && !strcmp (tty->name, name)))
2114 return tty;
2115 tty = tty->next;
2116 };
2117
2118 return 0;
2119 }
2120
2121 \f
2122
2123 DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0,
2124 doc: /* Return the name of the TTY device that FRAME is displayed on. */)
2125 (frame)
2126 Lisp_Object frame;
2127 {
2128 struct frame *f;
2129
2130 if (NILP (frame))
2131 {
2132 f = XFRAME (selected_frame);
2133 }
2134 else
2135 {
2136 CHECK_LIVE_FRAME (frame);
2137 f = XFRAME (frame);
2138 }
2139
2140 if (f->output_method != output_termcap)
2141 wrong_type_argument (Qframe_tty_name, frame);
2142
2143 if (FRAME_TTY (f)->name)
2144 return build_string (FRAME_TTY (f)->name);
2145 else
2146 return Qnil;
2147 }
2148
2149 DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0,
2150 doc: /* Return the type of the TTY device that FRAME is displayed on. */)
2151 (frame)
2152 Lisp_Object frame;
2153 {
2154 struct frame *f;
2155
2156 if (NILP (frame))
2157 {
2158 f = XFRAME (selected_frame);
2159 }
2160 else
2161 {
2162 CHECK_LIVE_FRAME (frame);
2163 f = XFRAME (frame);
2164 }
2165
2166 if (f->output_method != output_termcap)
2167 wrong_type_argument (Qframe_tty_type, frame);
2168
2169 if (FRAME_TTY (f)->type)
2170 return build_string (FRAME_TTY (f)->type);
2171 else
2172 return Qnil;
2173 }
2174
2175 \f
2176 /***********************************************************************
2177 Initialization
2178 ***********************************************************************/
2179
2180 struct tty_display_info *
2181 term_dummy_init (void)
2182 {
2183 if (initialized || tty_list)
2184 error ("tty already initialized");
2185
2186 tty_list = xmalloc (sizeof (struct tty_display_info));
2187 bzero (tty_list, sizeof (struct tty_display_info));
2188 tty_list->name = 0;
2189 tty_list->input = stdin;
2190 tty_list->output = stdout;
2191 tty_list->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2192 tty_list->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
2193 tty_list->kboard = initial_kboard;
2194 return tty_list;
2195 }
2196
2197
2198 struct tty_display_info *
2199 term_init (Lisp_Object frame, char *name, char *terminal_type)
2200 {
2201 char *area;
2202 char **address = &area;
2203 char *buffer = NULL;
2204 int buffer_size = 4096;
2205 register char *p;
2206 int status;
2207 struct frame *f = XFRAME (frame);
2208 struct tty_display_info *tty;
2209
2210 tty = get_named_tty (name);
2211 if (tty)
2212 {
2213 /* Return the previously initialized terminal, except if it is
2214 the dummy terminal created for the initial frame. */
2215 if (tty->type)
2216 return tty;
2217
2218 /* Free up temporary structures. */
2219 if (tty->Wcm)
2220 xfree (tty->Wcm);
2221 if (tty->display_method)
2222 xfree (tty->display_method);
2223 if (tty->kboard != initial_kboard)
2224 abort ();
2225 tty->kboard = 0;
2226 }
2227 else
2228 {
2229 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
2230 bzero (tty, sizeof (struct tty_display_info));
2231 tty->next = tty_list;
2232 tty_list = tty;
2233 }
2234
2235 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2236 Wcm_clear (tty);
2237
2238 /* Each termcap frame has its own display method. */
2239 tty->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
2240 bzero (tty->display_method, sizeof (struct display_method));
2241
2242 /* Initialize the common members in the new display method with our
2243 predefined template. */
2244 *tty->display_method = tty_display_method_template;
2245 f->display_method = tty->display_method;
2246
2247 /* Make sure the frame is live; if an error happens, it must be
2248 deleted. */
2249 f->output_method = output_termcap;
2250 if (! f->output_data.tty)
2251 abort ();
2252 f->output_data.tty->display_info = tty;
2253 if (name)
2254 {
2255 int fd;
2256 FILE *file;
2257 fd = emacs_open (name, O_RDWR, 0);
2258 if (fd < 0)
2259 {
2260 delete_tty (tty);
2261 error ("Could not open file: %s", name);
2262 }
2263 file = fdopen (fd, "w+");
2264 tty->name = xstrdup (name);
2265 tty->input = file;
2266 tty->output = file;
2267 }
2268 else
2269 {
2270 tty->name = 0;
2271 tty->input = stdin;
2272 tty->output = stdout;
2273 }
2274
2275 tty->type = xstrdup (terminal_type);
2276
2277 add_keyboard_wait_descriptor (fileno (tty->input));
2278
2279 #ifdef WINDOWSNT
2280 initialize_w32_display ();
2281
2282 Wcm_clear (tty);
2283
2284 area = (char *) xmalloc (2044);
2285
2286 FrameRows (tty) = FRAME_LINES (f);
2287 FrameCols (tty) = FRAME_COLS (f);
2288 tty->specified_window = FRAME_LINES (f);
2289
2290 tty->display_method->delete_in_insert_mode = 1;
2291
2292 UseTabs (tty) = 0;
2293 FRAME_SCROLL_REGION_OK (f) = 0;
2294
2295 /* Seems to insert lines when it's not supposed to, messing
2296 up the display. In doing a trace, it didn't seem to be
2297 called much, so I don't think we're losing anything by
2298 turning it off. */
2299 FRAME_LINE_INS_DEL_OK (f) = 0;
2300 FRAME_CHAR_INS_DEL_OK (f) = 1;
2301
2302 baud_rate = 19200;
2303
2304 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
2305 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
2306 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2307
2308 return tty;
2309 #else /* not WINDOWSNT */
2310
2311 Wcm_clear (tty);
2312
2313 buffer = (char *) xmalloc (buffer_size);
2314 status = tgetent (buffer, terminal_type);
2315 if (status < 0)
2316 {
2317 #ifdef TERMINFO
2318 if (name)
2319 {
2320 xfree (buffer);
2321 delete_tty (tty);
2322 error ("Cannot open terminfo database file");
2323 }
2324 else
2325 fatal ("Cannot open terminfo database file");
2326 #else
2327 if (name)
2328 {
2329 xfree (buffer);
2330 delete_tty (tty);
2331 error ("Cannot open termcap database file");
2332 }
2333 else
2334 fatal ("Cannot open termcap database file");
2335 #endif
2336 }
2337 if (status == 0)
2338 {
2339 #ifdef TERMINFO
2340 if (name)
2341 {
2342 xfree (buffer);
2343 delete_tty (tty);
2344 error ("Terminal type %s is not defined", terminal_type);
2345 }
2346 else
2347 fatal ("Terminal type %s is not defined.\n\
2348 If that is not the actual type of terminal you have,\n\
2349 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2350 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2351 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2352 terminal_type);
2353 #else
2354 if (name)
2355 {
2356 xfree (buffer);
2357 delete_tty (tty);
2358 error ("Terminal type %s is not defined", terminal_type);
2359 }
2360 else
2361 fatal ("Terminal type %s is not defined.\n\
2362 If that is not the actual type of terminal you have,\n\
2363 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2364 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2365 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2366 terminal_type);
2367 #endif
2368 }
2369
2370 #ifndef TERMINFO
2371 if (strlen (buffer) >= buffer_size)
2372 abort ();
2373 buffer_size = strlen (buffer);
2374 #endif
2375 area = (char *) xmalloc (buffer_size);
2376
2377 tty->TS_ins_line = tgetstr ("al", address);
2378 tty->TS_ins_multi_lines = tgetstr ("AL", address);
2379 tty->TS_bell = tgetstr ("bl", address);
2380 BackTab (tty) = tgetstr ("bt", address);
2381 tty->TS_clr_to_bottom = tgetstr ("cd", address);
2382 tty->TS_clr_line = tgetstr ("ce", address);
2383 tty->TS_clr_frame = tgetstr ("cl", address);
2384 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
2385 AbsPosition (tty) = tgetstr ("cm", address);
2386 CR (tty) = tgetstr ("cr", address);
2387 tty->TS_set_scroll_region = tgetstr ("cs", address);
2388 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
2389 RowPosition (tty) = tgetstr ("cv", address);
2390 tty->TS_del_char = tgetstr ("dc", address);
2391 tty->TS_del_multi_chars = tgetstr ("DC", address);
2392 tty->TS_del_line = tgetstr ("dl", address);
2393 tty->TS_del_multi_lines = tgetstr ("DL", address);
2394 tty->TS_delete_mode = tgetstr ("dm", address);
2395 tty->TS_end_delete_mode = tgetstr ("ed", address);
2396 tty->TS_end_insert_mode = tgetstr ("ei", address);
2397 Home (tty) = tgetstr ("ho", address);
2398 tty->TS_ins_char = tgetstr ("ic", address);
2399 tty->TS_ins_multi_chars = tgetstr ("IC", address);
2400 tty->TS_insert_mode = tgetstr ("im", address);
2401 tty->TS_pad_inserted_char = tgetstr ("ip", address);
2402 tty->TS_end_keypad_mode = tgetstr ("ke", address);
2403 tty->TS_keypad_mode = tgetstr ("ks", address);
2404 LastLine (tty) = tgetstr ("ll", address);
2405 Right (tty) = tgetstr ("nd", address);
2406 Down (tty) = tgetstr ("do", address);
2407 if (!Down (tty))
2408 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
2409 #ifdef VMS
2410 /* VMS puts a carriage return before each linefeed,
2411 so it is not safe to use linefeeds. */
2412 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
2413 Down (tty) = 0;
2414 #endif /* VMS */
2415 if (tgetflag ("bs"))
2416 Left (tty) = "\b"; /* can't possibly be longer! */
2417 else /* (Actually, "bs" is obsolete...) */
2418 Left (tty) = tgetstr ("le", address);
2419 if (!Left (tty))
2420 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
2421 tty->TS_pad_char = tgetstr ("pc", address);
2422 tty->TS_repeat = tgetstr ("rp", address);
2423 tty->TS_end_standout_mode = tgetstr ("se", address);
2424 tty->TS_fwd_scroll = tgetstr ("sf", address);
2425 tty->TS_standout_mode = tgetstr ("so", address);
2426 tty->TS_rev_scroll = tgetstr ("sr", address);
2427 tty->Wcm->cm_tab = tgetstr ("ta", address);
2428 tty->TS_end_termcap_modes = tgetstr ("te", address);
2429 tty->TS_termcap_modes = tgetstr ("ti", address);
2430 Up (tty) = tgetstr ("up", address);
2431 tty->TS_visible_bell = tgetstr ("vb", address);
2432 tty->TS_cursor_normal = tgetstr ("ve", address);
2433 tty->TS_cursor_visible = tgetstr ("vs", address);
2434 tty->TS_cursor_invisible = tgetstr ("vi", address);
2435 tty->TS_set_window = tgetstr ("wi", address);
2436
2437 tty->TS_enter_underline_mode = tgetstr ("us", address);
2438 tty->TS_exit_underline_mode = tgetstr ("ue", address);
2439 tty->TS_enter_bold_mode = tgetstr ("md", address);
2440 tty->TS_enter_dim_mode = tgetstr ("mh", address);
2441 tty->TS_enter_blink_mode = tgetstr ("mb", address);
2442 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
2443 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
2444 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
2445 tty->TS_exit_attribute_mode = tgetstr ("me", address);
2446
2447 MultiUp (tty) = tgetstr ("UP", address);
2448 MultiDown (tty) = tgetstr ("DO", address);
2449 MultiLeft (tty) = tgetstr ("LE", address);
2450 MultiRight (tty) = tgetstr ("RI", address);
2451
2452 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2453 color because we can't switch back to the default foreground and
2454 background. */
2455 tty->TS_orig_pair = tgetstr ("op", address);
2456 if (tty->TS_orig_pair)
2457 {
2458 tty->TS_set_foreground = tgetstr ("AF", address);
2459 tty->TS_set_background = tgetstr ("AB", address);
2460 if (!tty->TS_set_foreground)
2461 {
2462 /* SVr4. */
2463 tty->TS_set_foreground = tgetstr ("Sf", address);
2464 tty->TS_set_background = tgetstr ("Sb", address);
2465 }
2466
2467 tty->TN_max_colors = tgetnum ("Co");
2468 tty->TN_max_pairs = tgetnum ("pa");
2469
2470 tty->TN_no_color_video = tgetnum ("NC");
2471 if (tty->TN_no_color_video == -1)
2472 tty->TN_no_color_video = 0;
2473 }
2474
2475 tty_default_color_capabilities (tty, 1);
2476
2477 MagicWrap (tty) = tgetflag ("xn");
2478 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2479 the former flag imply the latter. */
2480 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
2481 FRAME_MEMORY_BELOW_FRAME (f) = tgetflag ("db");
2482 tty->TF_hazeltine = tgetflag ("hz");
2483 FRAME_MUST_WRITE_SPACES (f) = tgetflag ("in");
2484 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
2485 tty->TF_insmode_motion = tgetflag ("mi");
2486 tty->TF_standout_motion = tgetflag ("ms");
2487 tty->TF_underscore = tgetflag ("ul");
2488 tty->TF_teleray = tgetflag ("xt");
2489
2490 term_get_fkeys (address);
2491
2492 /* Get frame size from system, or else from termcap. */
2493 {
2494 int height, width;
2495 get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
2496 FrameCols (tty) = width;
2497 FrameRows (tty) = height;
2498 }
2499
2500 if (FrameCols (tty) <= 0)
2501 FrameCols (tty) = tgetnum ("co");
2502 if (FrameRows (tty) <= 0)
2503 FrameRows (tty) = tgetnum ("li");
2504
2505 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
2506 {
2507 if (initialized)
2508 {
2509 delete_tty (tty);
2510 error ("Screen size %dx%d is too small",
2511 FrameCols (tty), FrameRows (tty));
2512 }
2513 else
2514 {
2515 fatal ("Screen size %dx%d is too small",
2516 FrameCols (tty), FrameRows (tty));
2517 }
2518 }
2519
2520 #if 0 /* This is not used anywhere. */
2521 tty->display_method->min_padding_speed = tgetnum ("pb");
2522 #endif
2523
2524 TabWidth (tty) = tgetnum ("tw");
2525
2526 #ifdef VMS
2527 /* These capabilities commonly use ^J.
2528 I don't know why, but sending them on VMS does not work;
2529 it causes following spaces to be lost, sometimes.
2530 For now, the simplest fix is to avoid using these capabilities ever. */
2531 if (Down (tty) && Down (tty)[0] == '\n')
2532 Down (tty) = 0;
2533 #endif /* VMS */
2534
2535 if (!tty->TS_bell)
2536 tty->TS_bell = "\07";
2537
2538 if (!tty->TS_fwd_scroll)
2539 tty->TS_fwd_scroll = Down (tty);
2540
2541 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
2542
2543 if (TabWidth (tty) < 0)
2544 TabWidth (tty) = 8;
2545
2546 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2547 and newer termcap doc does not seem to say there is a default.
2548 if (!tty->Wcm->cm_tab)
2549 tty->Wcm->cm_tab = "\t";
2550 */
2551
2552 /* We don't support standout modes that use `magic cookies', so
2553 turn off any that do. */
2554 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
2555 {
2556 tty->TS_standout_mode = 0;
2557 tty->TS_end_standout_mode = 0;
2558 }
2559 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
2560 {
2561 tty->TS_enter_underline_mode = 0;
2562 tty->TS_exit_underline_mode = 0;
2563 }
2564
2565 /* If there's no standout mode, try to use underlining instead. */
2566 if (tty->TS_standout_mode == 0)
2567 {
2568 tty->TS_standout_mode = tty->TS_enter_underline_mode;
2569 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
2570 }
2571
2572 /* If no `se' string, try using a `me' string instead.
2573 If that fails, we can't use standout mode at all. */
2574 if (tty->TS_end_standout_mode == 0)
2575 {
2576 char *s = tgetstr ("me", address);
2577 if (s != 0)
2578 tty->TS_end_standout_mode = s;
2579 else
2580 tty->TS_standout_mode = 0;
2581 }
2582
2583 if (tty->TF_teleray)
2584 {
2585 tty->Wcm->cm_tab = 0;
2586 /* We can't support standout mode, because it uses magic cookies. */
2587 tty->TS_standout_mode = 0;
2588 /* But that means we cannot rely on ^M to go to column zero! */
2589 CR (tty) = 0;
2590 /* LF can't be trusted either -- can alter hpos */
2591 /* if move at column 0 thru a line with TS_standout_mode */
2592 Down (tty) = 0;
2593 }
2594
2595 /* Special handling for certain terminal types known to need it */
2596
2597 if (!strcmp (terminal_type, "supdup"))
2598 {
2599 FRAME_MEMORY_BELOW_FRAME (f) = 1;
2600 tty->Wcm->cm_losewrap = 1;
2601 }
2602 if (!strncmp (terminal_type, "c10", 3)
2603 || !strcmp (terminal_type, "perq"))
2604 {
2605 /* Supply a makeshift :wi string.
2606 This string is not valid in general since it works only
2607 for windows starting at the upper left corner;
2608 but that is all Emacs uses.
2609
2610 This string works only if the frame is using
2611 the top of the video memory, because addressing is memory-relative.
2612 So first check the :ti string to see if that is true.
2613
2614 It would be simpler if the :wi string could go in the termcap
2615 entry, but it can't because it is not fully valid.
2616 If it were in the termcap entry, it would confuse other programs. */
2617 if (!tty->TS_set_window)
2618 {
2619 p = tty->TS_termcap_modes;
2620 while (*p && strcmp (p, "\033v "))
2621 p++;
2622 if (*p)
2623 tty->TS_set_window = "\033v%C %C %C %C ";
2624 }
2625 /* Termcap entry often fails to have :in: flag */
2626 FRAME_MUST_WRITE_SPACES (f) = 1;
2627 /* :ti string typically fails to have \E^G! in it */
2628 /* This limits scope of insert-char to one line. */
2629 strcpy (area, tty->TS_termcap_modes);
2630 strcat (area, "\033\007!");
2631 tty->TS_termcap_modes = area;
2632 area += strlen (area) + 1;
2633 p = AbsPosition (tty);
2634 /* Change all %+ parameters to %C, to handle
2635 values above 96 correctly for the C100. */
2636 while (*p)
2637 {
2638 if (p[0] == '%' && p[1] == '+')
2639 p[1] = 'C';
2640 p++;
2641 }
2642 }
2643
2644 tty->specified_window = FrameRows (tty);
2645
2646 if (Wcm_init (tty) == -1) /* can't do cursor motion */
2647 if (name)
2648 {
2649 delete_tty (tty);
2650 error ("Terminal type \"%s\" is not powerful enough to run Emacs",
2651 terminal_type);
2652 }
2653 else {
2654 #ifdef VMS
2655 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2656 It lacks the ability to position the cursor.\n\
2657 If that is not the actual type of terminal you have, use either the\n\
2658 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2659 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2660 terminal_type);
2661 #else /* not VMS */
2662 # ifdef TERMINFO
2663 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2664 It lacks the ability to position the cursor.\n\
2665 If that is not the actual type of terminal you have,\n\
2666 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2667 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2668 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2669 terminal_type);
2670 # else /* TERMCAP */
2671 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2672 It lacks the ability to position the cursor.\n\
2673 If that is not the actual type of terminal you have,\n\
2674 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2675 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2676 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2677 terminal_type);
2678 # endif /* TERMINFO */
2679 #endif /*VMS */
2680 }
2681
2682 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
2683 {
2684 if (name)
2685 {
2686 delete_tty (tty);
2687 error ("The frame size has not been specified");
2688 }
2689 else
2690 fatal ("The frame size has not been specified");
2691 }
2692
2693 tty->delete_in_insert_mode
2694 = tty->TS_delete_mode && tty->TS_insert_mode
2695 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
2696
2697 tty->se_is_so = (tty->TS_standout_mode
2698 && tty->TS_end_standout_mode
2699 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
2700
2701 UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
2702
2703 FRAME_SCROLL_REGION_OK (f)
2704 = (tty->Wcm->cm_abs
2705 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
2706
2707 FRAME_LINE_INS_DEL_OK (f)
2708 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
2709 && (tty->TS_del_line || tty->TS_del_multi_lines))
2710 || (FRAME_SCROLL_REGION_OK (f)
2711 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
2712
2713 FRAME_CHAR_INS_DEL_OK (f)
2714 = ((tty->TS_ins_char || tty->TS_insert_mode
2715 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
2716 && (tty->TS_del_char || tty->TS_del_multi_chars));
2717
2718 FRAME_FAST_CLEAR_END_OF_LINE (f) = tty->TS_clr_line != 0;
2719
2720 init_baud_rate (fileno (TTY_INPUT (tty)));
2721 if (read_socket_hook) /* Baudrate is somewhat
2722 meaningless in this case */
2723 baud_rate = 9600;
2724
2725 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
2726 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
2727
2728 #ifdef AIXHFT
2729 /* The HFT system on AIX doesn't optimize for scrolling, so it's
2730 really ugly at times. */
2731 FRAME_LINE_INS_DEL_OK (f) = 0;
2732 FRAME_CHAR_INS_DEL_OK (f) = 0;
2733 #endif
2734
2735 #ifdef MULTI_KBOARD
2736 tty->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
2737 init_kboard (tty->kboard);
2738 tty->kboard->next_kboard = all_kboards;
2739 all_kboards = tty->kboard;
2740 /* Don't let the initial kboard remain current longer than necessary.
2741 That would cause problems if a file loaded on startup tries to
2742 prompt in the mini-buffer. */
2743 if (current_kboard == initial_kboard)
2744 current_kboard = tty->kboard;
2745 tty->kboard->reference_count++;
2746 #endif
2747
2748 /* Don't do this. I think termcap may still need the buffer. */
2749 /* xfree (buffer); */
2750
2751 /* Set the top frame to the first frame on this display. */
2752 tty->top_frame = frame;
2753
2754 /* Init system terminal modes (RAW or CBREAK, etc.). */
2755 init_sys_modes (tty);
2756
2757 return tty;
2758 #endif /* not WINDOWSNT */
2759 }
2760
2761 /* VARARGS 1 */
2762 void
2763 fatal (str, arg1, arg2)
2764 char *str, *arg1, *arg2;
2765 {
2766 fprintf (stderr, "emacs: ");
2767 fprintf (stderr, str, arg1, arg2);
2768 fprintf (stderr, "\n");
2769 fflush (stderr);
2770 exit (1);
2771 }
2772
2773 \f
2774
2775 DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0,
2776 doc: /* Delete all frames on the terminal named TTY, and close the device.
2777 If omitted, TTY defaults to the controlling terminal.
2778
2779 This function runs `delete-tty-after-functions' after closing the
2780 tty. The functions are run with one arg, the frame to be deleted. */)
2781 (tty)
2782 Lisp_Object tty;
2783 {
2784 struct tty_display_info *t;
2785 char *name = 0;
2786
2787 CHECK_STRING (tty);
2788
2789 if (SBYTES (tty) > 0)
2790 {
2791 name = (char *) alloca (SBYTES (tty) + 1);
2792 strncpy (name, SDATA (tty), SBYTES (tty));
2793 name[SBYTES (tty)] = 0;
2794 }
2795
2796 t = get_named_tty (name);
2797
2798 if (! t)
2799 error ("No such tty device: %s", name);
2800
2801 delete_tty (t);
2802 }
2803
2804 static int deleting_tty = 0;
2805
2806 void
2807 delete_tty (struct tty_display_info *tty)
2808 {
2809 Lisp_Object tail, frame;
2810 char *tty_name;
2811
2812 if (deleting_tty)
2813 /* We get a recursive call when we delete the last frame on this
2814 tty. */
2815 return;
2816
2817 deleting_tty = 1;
2818
2819 if (tty == tty_list)
2820 tty_list = tty->next;
2821 else
2822 {
2823 struct tty_display_info *p;
2824 for (p = tty_list; p && p->next != tty; p = p->next)
2825 ;
2826
2827 if (! p)
2828 /* This should not happen. */
2829 abort ();
2830
2831 p->next = tty->next;
2832 tty->next = 0;
2833 }
2834
2835 FOR_EACH_FRAME (tail, frame)
2836 {
2837 struct frame *f = XFRAME (frame);
2838 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
2839 {
2840 Fdelete_frame (frame, Qt);
2841 f->output_data.tty = 0;
2842 }
2843 }
2844
2845 reset_sys_modes (tty);
2846
2847 tty_name = tty->name;
2848 if (tty->type)
2849 xfree (tty->type);
2850
2851 if (tty->input)
2852 {
2853 delete_keyboard_wait_descriptor (fileno (tty->input));
2854 if (tty->input != stdin)
2855 fclose (tty->input);
2856 }
2857 if (tty->output && tty->output != stdout && tty->output != tty->input)
2858 fclose (tty->output);
2859 if (tty->termscript)
2860 fclose (tty->termscript);
2861
2862 if (tty->old_tty)
2863 xfree (tty->old_tty);
2864
2865 if (tty->Wcm)
2866 xfree (tty->Wcm);
2867
2868 if (tty->display_method)
2869 xfree (tty->display_method);
2870
2871 #ifdef MULTI_KBOARD
2872 if (tty->kboard && --tty->kboard->reference_count > 0)
2873 abort ();
2874 if (tty->kboard)
2875 delete_kboard (tty->kboard);
2876 #endif
2877
2878 bzero (tty, sizeof (struct tty_display_info));
2879 xfree (tty);
2880 deleting_tty = 0;
2881
2882 /* Run `delete-tty-after-functions'. */
2883 if (!NILP (Vrun_hooks))
2884 {
2885 Lisp_Object args[2];
2886 args[0] = intern ("delete-tty-after-functions");
2887 if (tty_name)
2888 {
2889 args[1] = build_string (tty_name);
2890 xfree (tty_name);
2891 }
2892 else
2893 args[1] = Qnil;
2894 Frun_hook_with_args (2, args);
2895 }
2896 }
2897
2898
2899 \f
2900
2901 /* Mark the pointers in the tty_display_info objects.
2902 Called by the Fgarbage_collector. */
2903 void
2904 mark_ttys ()
2905 {
2906 struct tty_display_info *tty;
2907 Lisp_Object *p;
2908 for (tty = tty_list; tty; tty = tty->next)
2909 {
2910 if (tty->top_frame)
2911 mark_object (tty->top_frame);
2912 }
2913 }
2914
2915
2916 \f
2917 void
2918 syms_of_term ()
2919 {
2920 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2921 doc: /* Non-nil means the system uses terminfo rather than termcap.
2922 This variable can be used by terminal emulator packages. */);
2923 #ifdef TERMINFO
2924 system_uses_terminfo = 1;
2925 #else
2926 system_uses_terminfo = 0;
2927 #endif
2928
2929 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2930 doc: /* Non-nil means call this function to ring the bell.
2931 The function should accept no arguments. */);
2932 Vring_bell_function = Qnil;
2933
2934 DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions,
2935 doc: /* Functions to be run after deleting a tty.
2936 The functions are run with one argument, the name of the tty to be deleted.
2937 See `delete-tty'. */);
2938 Vdelete_tty_after_functions = Qnil;
2939
2940 Qframe_tty_name = intern ("frame-tty-name");
2941 staticpro (&Qframe_tty_name);
2942
2943 Qframe_tty_type = intern ("frame-tty-type");
2944 staticpro (&Qframe_tty_type);
2945
2946 defsubr (&Stty_display_color_p);
2947 defsubr (&Stty_display_color_cells);
2948 defsubr (&Sframe_tty_name);
2949 defsubr (&Sframe_tty_type);
2950 defsubr (&Sdelete_tty);
2951
2952 Fprovide (intern ("multi-tty"), Qnil);
2953
2954 /* Initialize the display method template. */
2955
2956 /* Termcap-based displays don't support window-based redisplay. */
2957 tty_display_method_template.rif = 0;
2958
2959 }
2960
2961
2962
2963 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
2964 (do not change this comment) */