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