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