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