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