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