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