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