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