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