1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
30 #include <unistd.h> /* For isatty. */
33 #include <termios.h> /* For TIOCNOTTY. */
46 #include "termhooks.h"
47 #include "dispextern.h"
50 #include "blockinput.h"
51 #include "syssignal.h"
54 /* For now, don't try to include termcap.h. On some systems,
55 configure finds a non-standard termcap.h that the main build
58 #if defined HAVE_TERMCAP_H && 0
61 extern void tputs
P_ ((const char *, int, int (*)(int)));
62 extern int tgetent
P_ ((char *, const char *));
63 extern int tgetflag
P_ ((char *id
));
64 extern int tgetnum
P_ ((char *id
));
83 static void tty_set_scroll_region
P_ ((struct frame
*f
, int start
, int stop
));
84 static void turn_on_face
P_ ((struct frame
*, int face_id
));
85 static void turn_off_face
P_ ((struct frame
*, int face_id
));
86 static void tty_show_cursor
P_ ((struct tty_display_info
*));
87 static void tty_hide_cursor
P_ ((struct tty_display_info
*));
88 static void tty_background_highlight
P_ ((struct tty_display_info
*tty
));
89 static void clear_tty_hooks
P_ ((struct terminal
*terminal
));
90 static void set_tty_hooks
P_ ((struct terminal
*terminal
));
91 static void dissociate_if_controlling_tty
P_ ((int fd
));
92 static void delete_tty
P_ ((struct terminal
*));
94 #define OUTPUT(tty, a) \
95 emacs_tputs ((tty), a, \
96 (int) (FRAME_LINES (XFRAME (selected_frame)) \
100 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
101 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
103 #define OUTPUT_IF(tty, a) \
106 emacs_tputs ((tty), a, \
107 (int) (FRAME_LINES (XFRAME (selected_frame)) \
112 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
114 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
116 static int visible_cursor
;
118 /* Display space properties */
120 extern Lisp_Object Qspace
, QCalign_to
, QCwidth
;
122 /* Functions to call after suspending a tty. */
123 Lisp_Object Vsuspend_tty_functions
;
125 /* Functions to call after resuming a tty. */
126 Lisp_Object Vresume_tty_functions
;
128 /* Chain of all tty device parameters. */
129 struct tty_display_info
*tty_list
;
131 /* Nonzero means no need to redraw the entire frame on resuming a
132 suspended Emacs. This is useful on terminals with multiple
133 pages, where one page is used for Emacs and another for all
135 int no_redraw_on_reenter
;
137 /* Meaning of bits in no_color_video. Each bit set means that the
138 corresponding attribute cannot be combined with colors. */
142 NC_STANDOUT
= 1 << 0,
143 NC_UNDERLINE
= 1 << 1,
150 NC_ALT_CHARSET
= 1 << 8
155 /* The largest frame width in any call to calculate_costs. */
159 /* The largest frame height in any call to calculate_costs. */
163 /* Non-zero if we have dropped our controlling tty and therefore
164 should not open a frame on stdout. */
165 static int no_controlling_tty
;
167 /* Provided for lisp packages. */
169 static int system_uses_terminfo
;
173 extern char *tgetstr ();
175 static void term_clear_mouse_face ();
176 static void term_mouse_highlight (struct frame
*f
, int x
, int y
);
180 /* We aren't X windows, but we aren't termcap either. This makes me
181 uncertain as to what value to use for frame.output_method. For
182 this file, we'll define FRAME_TERMCAP_P to be zero so that our
183 output hooks get called instead of the termcap functions. Probably
184 the best long-term solution is to define an output_windows_nt... */
186 #undef FRAME_TERMCAP_P
187 #define FRAME_TERMCAP_P(_f_) 0
188 #endif /* WINDOWSNT */
191 #include <sys/fcntl.h>
194 /* Nonzero means mouse is enabled on Linux console. */
197 /* The id of the terminal device for which we have gpm support. */
200 /* These variables describe the range of text currently shown in its
201 mouse-face, together with the window they apply to. As long as
202 the mouse stays within this range, we need not redraw anything on
203 its account. Rows and columns are glyph matrix positions in
204 MOUSE_FACE_WINDOW. */
205 static int mouse_face_beg_row
, mouse_face_beg_col
;
206 static int mouse_face_end_row
, mouse_face_end_col
;
207 static int mouse_face_past_end
;
208 static Lisp_Object Qmouse_face_window
;
209 static int mouse_face_face_id
;
211 static int pos_x
, pos_y
;
212 static int last_mouse_x
, last_mouse_y
;
213 #endif /* HAVE_GPM */
215 /* Ring the bell on a tty. */
218 tty_ring_bell (struct frame
*f
)
220 struct tty_display_info
*tty
= FRAME_TTY (f
);
224 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
225 ? tty
->TS_visible_bell
227 fflush (tty
->output
);
231 /* Set up termcap modes for Emacs. */
234 tty_set_terminal_modes (struct terminal
*terminal
)
236 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
240 if (tty
->TS_termcap_modes
)
241 OUTPUT (tty
, tty
->TS_termcap_modes
);
244 /* Output enough newlines to scroll all the old screen contents
245 off the screen, so it won't be overwritten and lost. */
248 for (i
= 0; i
< FRAME_LINES (XFRAME (selected_frame
)); i
++)
252 OUTPUT_IF (tty
, tty
->TS_termcap_modes
);
253 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
254 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
256 fflush (tty
->output
);
260 /* Reset termcap modes before exiting Emacs. */
263 tty_reset_terminal_modes (struct terminal
*terminal
)
265 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
269 tty_turn_off_highlight (tty
);
270 tty_turn_off_insert (tty
);
271 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
272 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
273 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
274 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
275 /* Output raw CR so kernel can track the cursor hpos. */
278 fflush (tty
->output
);
282 /* Flag the end of a display update on a termcap terminal. */
285 tty_update_end (struct frame
*f
)
287 struct tty_display_info
*tty
= FRAME_TTY (f
);
289 if (!XWINDOW (selected_window
)->cursor_off_p
)
290 tty_show_cursor (tty
);
291 tty_turn_off_insert (tty
);
292 tty_background_highlight (tty
);
295 /* The implementation of set_terminal_window for termcap frames. */
298 tty_set_terminal_window (struct frame
*f
, int size
)
300 struct tty_display_info
*tty
= FRAME_TTY (f
);
302 tty
->specified_window
= size
? size
: FRAME_LINES (f
);
303 if (FRAME_SCROLL_REGION_OK (f
))
304 tty_set_scroll_region (f
, 0, tty
->specified_window
);
308 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
311 struct tty_display_info
*tty
= FRAME_TTY (f
);
313 if (tty
->TS_set_scroll_region
)
314 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1);
315 else if (tty
->TS_set_scroll_region_1
)
316 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
317 FRAME_LINES (f
), start
,
318 FRAME_LINES (f
) - stop
,
321 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
330 tty_turn_on_insert (struct tty_display_info
*tty
)
332 if (!tty
->insert_mode
)
333 OUTPUT (tty
, tty
->TS_insert_mode
);
334 tty
->insert_mode
= 1;
338 tty_turn_off_insert (struct tty_display_info
*tty
)
340 if (tty
->insert_mode
)
341 OUTPUT (tty
, tty
->TS_end_insert_mode
);
342 tty
->insert_mode
= 0;
345 /* Handle highlighting. */
348 tty_turn_off_highlight (struct tty_display_info
*tty
)
350 if (tty
->standout_mode
)
351 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
352 tty
->standout_mode
= 0;
356 tty_turn_on_highlight (struct tty_display_info
*tty
)
358 if (!tty
->standout_mode
)
359 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
360 tty
->standout_mode
= 1;
364 tty_toggle_highlight (struct tty_display_info
*tty
)
366 if (tty
->standout_mode
)
367 tty_turn_off_highlight (tty
);
369 tty_turn_on_highlight (tty
);
373 /* Make cursor invisible. */
376 tty_hide_cursor (struct tty_display_info
*tty
)
378 if (tty
->cursor_hidden
== 0)
380 tty
->cursor_hidden
= 1;
381 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
386 /* Ensure that cursor is visible. */
389 tty_show_cursor (struct tty_display_info
*tty
)
391 if (tty
->cursor_hidden
)
393 tty
->cursor_hidden
= 0;
394 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
396 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
401 /* Set standout mode to the state it should be in for
402 empty space inside windows. What this is,
403 depends on the user option inverse-video. */
406 tty_background_highlight (struct tty_display_info
*tty
)
409 tty_turn_on_highlight (tty
);
411 tty_turn_off_highlight (tty
);
414 /* Set standout mode to the mode specified for the text to be output. */
417 tty_highlight_if_desired (struct tty_display_info
*tty
)
420 tty_turn_on_highlight (tty
);
422 tty_turn_off_highlight (tty
);
426 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
427 frame-relative coordinates. */
430 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
432 struct tty_display_info
*tty
= FRAME_TTY (f
);
434 /* Detect the case where we are called from reset_sys_modes
435 and the costs have never been calculated. Do nothing. */
436 if (! tty
->costs_set
)
439 if (curY (tty
) == vpos
440 && curX (tty
) == hpos
)
442 if (!tty
->TF_standout_motion
)
443 tty_background_highlight (tty
);
444 if (!tty
->TF_insmode_motion
)
445 tty_turn_off_insert (tty
);
446 cmgoto (tty
, vpos
, hpos
);
449 /* Similar but don't take any account of the wasted characters. */
452 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
454 struct tty_display_info
*tty
= FRAME_TTY (f
);
456 if (curY (tty
) == row
457 && curX (tty
) == col
)
459 if (!tty
->TF_standout_motion
)
460 tty_background_highlight (tty
);
461 if (!tty
->TF_insmode_motion
)
462 tty_turn_off_insert (tty
);
463 cmgoto (tty
, row
, col
);
466 /* Erase operations */
468 /* Clear from cursor to end of frame on a termcap device. */
471 tty_clear_to_end (struct frame
*f
)
474 struct tty_display_info
*tty
= FRAME_TTY (f
);
476 if (tty
->TS_clr_to_bottom
)
478 tty_background_highlight (tty
);
479 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
483 for (i
= curY (tty
); i
< FRAME_LINES (f
); i
++)
486 clear_end_of_line (f
, FRAME_COLS (f
));
491 /* Clear an entire termcap frame. */
494 tty_clear_frame (struct frame
*f
)
496 struct tty_display_info
*tty
= FRAME_TTY (f
);
498 if (tty
->TS_clr_frame
)
500 tty_background_highlight (tty
);
501 OUTPUT (tty
, tty
->TS_clr_frame
);
511 /* An implementation of clear_end_of_line for termcap frames.
513 Note that the cursor may be moved, on terminals lacking a `ce' string. */
516 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
519 struct tty_display_info
*tty
= FRAME_TTY (f
);
521 /* Detect the case where we are called from reset_sys_modes
522 and the costs have never been calculated. Do nothing. */
523 if (! tty
->costs_set
)
526 if (curX (tty
) >= first_unused_hpos
)
528 tty_background_highlight (tty
);
529 if (tty
->TS_clr_line
)
531 OUTPUT1 (tty
, tty
->TS_clr_line
);
534 { /* have to do it the hard way */
535 tty_turn_off_insert (tty
);
537 /* Do not write in last row last col with Auto-wrap on. */
539 && curY (tty
) == FrameRows (tty
) - 1
540 && first_unused_hpos
== FrameCols (tty
))
543 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
546 fputc (' ', tty
->termscript
);
547 fputc (' ', tty
->output
);
549 cmplus (tty
, first_unused_hpos
- curX (tty
));
553 /* Buffer to store the source and result of code conversion for terminal. */
554 static unsigned char *encode_terminal_buf
;
555 /* Allocated size of the above buffer. */
556 static int encode_terminal_bufsize
;
558 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
559 Set CODING->produced to the byte-length of the resulting byte
560 sequence, and return a pointer to that byte sequence. */
563 encode_terminal_code (src
, src_len
, coding
)
566 struct coding_system
*coding
;
568 struct glyph
*src_end
= src
+ src_len
;
571 int nchars
, nbytes
, required
;
572 register int tlen
= GLYPH_TABLE_LENGTH
;
573 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
575 /* Allocate sufficient size of buffer to store all characters in
576 multibyte-form. But, it may be enlarged on demand if
577 Vglyph_table contains a string. */
578 required
= MAX_MULTIBYTE_LENGTH
* src_len
;
579 if (encode_terminal_bufsize
< required
)
581 if (encode_terminal_bufsize
== 0)
582 encode_terminal_buf
= xmalloc (required
);
584 encode_terminal_buf
= xrealloc (encode_terminal_buf
, required
);
585 encode_terminal_bufsize
= required
;
588 buf
= encode_terminal_buf
;
590 while (src
< src_end
)
592 /* We must skip glyphs to be padded for a wide character. */
593 if (! CHAR_GLYPH_PADDING_P (*src
))
595 g
= GLYPH_FROM_CHAR_GLYPH (src
[0]);
597 if (g
< 0 || g
>= tlen
)
599 /* This glyph doesn't has an entry in Vglyph_table. */
600 if (CHAR_VALID_P (src
->u
.ch
, 0))
601 buf
+= CHAR_STRING (src
->u
.ch
, buf
);
608 /* This glyph has an entry in Vglyph_table,
609 so process any alias before testing for simpleness. */
610 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
612 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
614 int c
= FAST_GLYPH_CHAR (g
);
616 if (CHAR_VALID_P (c
, 0))
617 buf
+= CHAR_STRING (c
, buf
);
624 /* We have a string in Vglyph_table. */
628 if (! STRING_MULTIBYTE (string
))
629 string
= string_to_multibyte (string
);
630 nbytes
= buf
- encode_terminal_buf
;
631 if (encode_terminal_bufsize
< nbytes
+ SBYTES (string
))
633 encode_terminal_bufsize
= nbytes
+ SBYTES (string
);
634 encode_terminal_buf
= xrealloc (encode_terminal_buf
,
635 encode_terminal_bufsize
);
636 buf
= encode_terminal_buf
+ nbytes
;
638 bcopy (SDATA (string
), buf
, SBYTES (string
));
639 buf
+= SBYTES (string
);
640 nchars
+= SCHARS (string
);
647 nbytes
= buf
- encode_terminal_buf
;
648 coding
->src_multibyte
= 1;
649 coding
->dst_multibyte
= 0;
650 if (SYMBOLP (coding
->pre_write_conversion
)
651 && ! NILP (Ffboundp (coding
->pre_write_conversion
)))
653 run_pre_write_conversin_on_c_str (&encode_terminal_buf
,
654 &encode_terminal_bufsize
,
655 nchars
, nbytes
, coding
);
656 nchars
= coding
->produced_char
;
657 nbytes
= coding
->produced
;
659 required
= nbytes
+ encoding_buffer_size (coding
, nbytes
);
660 if (encode_terminal_bufsize
< required
)
662 encode_terminal_bufsize
= required
;
663 encode_terminal_buf
= xrealloc (encode_terminal_buf
, required
);
666 encode_coding (coding
, encode_terminal_buf
, encode_terminal_buf
+ nbytes
,
667 nbytes
, encode_terminal_bufsize
- nbytes
);
668 return encode_terminal_buf
+ nbytes
;
672 /* An implementation of write_glyphs for termcap frames. */
675 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
677 unsigned char *conversion_buffer
;
678 struct coding_system
*coding
;
680 struct tty_display_info
*tty
= FRAME_TTY (f
);
682 tty_turn_off_insert (tty
);
683 tty_hide_cursor (tty
);
685 /* Don't dare write in last column of bottom line, if Auto-Wrap,
686 since that would scroll the whole frame on some terminals. */
689 && curY (tty
) + 1 == FRAME_LINES (f
)
690 && (curX (tty
) + len
) == FRAME_COLS (f
))
697 /* If terminal_coding does any conversion, use it, otherwise use
698 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
699 because it always return 1 if the member src_multibyte is 1. */
700 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
701 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
702 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
704 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
708 /* Identify a run of glyphs with the same face. */
709 int face_id
= string
->face_id
;
712 for (n
= 1; n
< len
; ++n
)
713 if (string
[n
].face_id
!= face_id
)
716 /* Turn appearance modes of the face of the run on. */
717 tty_highlight_if_desired (tty
);
718 turn_on_face (f
, face_id
);
721 /* This is the last run. */
722 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
723 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
724 if (coding
->produced
> 0)
727 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
728 if (ferror (tty
->output
))
729 clearerr (tty
->output
);
731 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
737 /* Turn appearance modes off. */
738 turn_off_face (f
, face_id
);
739 tty_turn_off_highlight (tty
);
746 tty_write_glyphs_with_face (f
, string
, len
, face_id
)
747 register struct frame
*f
;
748 register struct glyph
*string
;
749 register int len
, face_id
;
751 unsigned char *conversion_buffer
;
752 struct coding_system
*coding
;
754 struct tty_display_info
*tty
= FRAME_TTY (f
);
756 tty_turn_off_insert (tty
);
757 tty_hide_cursor (tty
);
759 /* Don't dare write in last column of bottom line, if Auto-Wrap,
760 since that would scroll the whole frame on some terminals. */
763 && curY (tty
) + 1 == FRAME_LINES (f
)
764 && (curX (tty
) + len
) == FRAME_COLS (f
))
771 /* If terminal_coding does any conversion, use it, otherwise use
772 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
773 because it always return 1 if the member src_multibyte is 1. */
774 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
775 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
776 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
778 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
780 /* Turn appearance modes of the face. */
781 tty_highlight_if_desired (tty
);
782 turn_on_face (f
, face_id
);
784 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
785 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
786 if (coding
->produced
> 0)
789 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
790 if (ferror (tty
->output
))
791 clearerr (tty
->output
);
793 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
797 /* Turn appearance modes off. */
798 turn_off_face (f
, face_id
);
799 tty_turn_off_highlight (tty
);
805 /* An implementation of insert_glyphs for termcap frames. */
808 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
811 struct glyph
*glyph
= NULL
;
812 unsigned char *conversion_buffer
;
813 unsigned char space
[1];
814 struct coding_system
*coding
;
816 struct tty_display_info
*tty
= FRAME_TTY (f
);
818 if (tty
->TS_ins_multi_chars
)
820 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
);
824 write_glyphs (f
, start
, len
);
828 tty_turn_on_insert (tty
);
832 space
[0] = SPACEGLYPH
;
834 /* If terminal_coding does any conversion, use it, otherwise use
835 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
836 because it always return 1 if the member src_multibyte is 1. */
837 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
838 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
839 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
841 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
845 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
848 conversion_buffer
= space
;
849 coding
->produced
= 1;
853 tty_highlight_if_desired (tty
);
854 turn_on_face (f
, start
->face_id
);
857 /* We must open sufficient space for a character which
858 occupies more than one column. */
859 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
861 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
866 /* This is the last glyph. */
867 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
869 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
872 if (coding
->produced
> 0)
875 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
876 if (ferror (tty
->output
))
877 clearerr (tty
->output
);
879 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
883 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
886 turn_off_face (f
, glyph
->face_id
);
887 tty_turn_off_highlight (tty
);
894 /* An implementation of delete_glyphs for termcap frames. */
897 tty_delete_glyphs (struct frame
*f
, int n
)
902 struct tty_display_info
*tty
= FRAME_TTY (f
);
904 if (tty
->delete_in_insert_mode
)
906 tty_turn_on_insert (tty
);
910 tty_turn_off_insert (tty
);
911 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
914 if (tty
->TS_del_multi_chars
)
916 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
);
921 for (i
= 0; i
< n
; i
++)
922 OUTPUT1 (tty
, tty
->TS_del_char
);
923 if (!tty
->delete_in_insert_mode
)
924 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
927 /* An implementation of ins_del_lines for termcap frames. */
930 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
932 struct tty_display_info
*tty
= FRAME_TTY (f
);
933 char *multi
= n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
934 char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
935 char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
937 register int i
= n
> 0 ? n
: -n
;
940 /* If the lines below the insertion are being pushed
941 into the end of the window, this is the same as clearing;
942 and we know the lines are already clear, since the matching
943 deletion has already been done. So can ignore this. */
944 /* If the lines below the deletion are blank lines coming
945 out of the end of the window, don't bother,
946 as there will be a matching inslines later that will flush them. */
947 if (FRAME_SCROLL_REGION_OK (f
)
948 && vpos
+ i
>= tty
->specified_window
)
950 if (!FRAME_MEMORY_BELOW_FRAME (f
)
951 && vpos
+ i
>= FRAME_LINES (f
))
956 raw_cursor_to (f
, vpos
, 0);
957 tty_background_highlight (tty
);
958 buf
= tparam (multi
, 0, 0, i
);
964 raw_cursor_to (f
, vpos
, 0);
965 tty_background_highlight (tty
);
967 OUTPUT (tty
, single
);
973 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
975 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
977 raw_cursor_to (f
, vpos
, 0);
978 tty_background_highlight (tty
);
980 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
981 tty_set_scroll_region (f
, 0, tty
->specified_window
);
984 if (!FRAME_SCROLL_REGION_OK (f
)
985 && FRAME_MEMORY_BELOW_FRAME (f
)
988 cursor_to (f
, FRAME_LINES (f
) + n
, 0);
993 /* Compute cost of sending "str", in characters,
994 not counting any line-dependent padding. */
997 string_cost (char *str
)
1001 tputs (str
, 0, evalcost
);
1005 /* Compute cost of sending "str", in characters,
1006 counting any line-dependent padding at one line. */
1009 string_cost_one_line (char *str
)
1013 tputs (str
, 1, evalcost
);
1017 /* Compute per line amount of line-dependent padding,
1018 in tenths of characters. */
1021 per_line_cost (char *str
)
1025 tputs (str
, 0, evalcost
);
1028 tputs (str
, 10, evalcost
);
1033 /* char_ins_del_cost[n] is cost of inserting N characters.
1034 char_ins_del_cost[-n] is cost of deleting N characters.
1035 The length of this vector is based on max_frame_cols. */
1037 int *char_ins_del_vector
;
1039 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1044 calculate_ins_del_char_costs (struct frame
*f
)
1046 struct tty_display_info
*tty
= FRAME_TTY (f
);
1047 int ins_startup_cost
, del_startup_cost
;
1048 int ins_cost_per_char
, del_cost_per_char
;
1052 if (tty
->TS_ins_multi_chars
)
1054 ins_cost_per_char
= 0;
1055 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1057 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1058 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1060 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1061 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1062 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1063 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1067 ins_startup_cost
= 9999;
1068 ins_cost_per_char
= 0;
1071 if (tty
->TS_del_multi_chars
)
1073 del_cost_per_char
= 0;
1074 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1076 else if (tty
->TS_del_char
)
1078 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1079 + string_cost (tty
->TS_end_delete_mode
));
1080 if (tty
->delete_in_insert_mode
)
1081 del_startup_cost
/= 2;
1082 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1086 del_startup_cost
= 9999;
1087 del_cost_per_char
= 0;
1090 /* Delete costs are at negative offsets */
1091 p
= &char_ins_del_cost (f
)[0];
1092 for (i
= FRAME_COLS (f
); --i
>= 0;)
1093 *--p
= (del_startup_cost
+= del_cost_per_char
);
1095 /* Doing nothing is free */
1096 p
= &char_ins_del_cost (f
)[0];
1099 /* Insert costs are at positive offsets */
1100 for (i
= FRAME_COLS (f
); --i
>= 0;)
1101 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1105 calculate_costs (struct frame
*frame
)
1107 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1109 if (FRAME_TERMCAP_P (frame
))
1111 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1112 register char *f
= (tty
->TS_set_scroll_region
1113 ? tty
->TS_set_scroll_region
1114 : tty
->TS_set_scroll_region_1
);
1116 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1120 /* These variables are only used for terminal stuff. They are
1121 allocated once for the terminal frame of X-windows emacs, but not
1124 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1125 X turns off char_ins_del_ok. */
1127 max_frame_lines
= max (max_frame_lines
, FRAME_LINES (frame
));
1128 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1130 if (char_ins_del_vector
!= 0)
1132 = (int *) xrealloc (char_ins_del_vector
,
1134 + 2 * max_frame_cols
* sizeof (int)));
1137 = (int *) xmalloc (sizeof (int)
1138 + 2 * max_frame_cols
* sizeof (int));
1140 bzero (char_ins_del_vector
, (sizeof (int)
1141 + 2 * max_frame_cols
* sizeof (int)));
1144 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1145 do_line_insertion_deletion_costs (frame
,
1146 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1147 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1150 do_line_insertion_deletion_costs (frame
,
1151 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1152 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1155 calculate_ins_del_char_costs (frame
);
1157 /* Don't use TS_repeat if its padding is worse than sending the chars */
1158 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1159 tty
->RPov
= string_cost (tty
->TS_repeat
);
1161 tty
->RPov
= FRAME_COLS (frame
) * 2;
1163 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1171 /* Termcap capability names that correspond directly to X keysyms.
1172 Some of these (marked "terminfo") aren't supplied by old-style
1173 (Berkeley) termcap entries. They're listed in X keysym order;
1174 except we put the keypad keys first, so that if they clash with
1175 other keys (as on the IBM PC keyboard) they get overridden.
1178 static struct fkey_table keys
[] =
1180 {"kh", "home"}, /* termcap */
1181 {"kl", "left"}, /* termcap */
1182 {"ku", "up"}, /* termcap */
1183 {"kr", "right"}, /* termcap */
1184 {"kd", "down"}, /* termcap */
1185 {"%8", "prior"}, /* terminfo */
1186 {"%5", "next"}, /* terminfo */
1187 {"@7", "end"}, /* terminfo */
1188 {"@1", "begin"}, /* terminfo */
1189 {"*6", "select"}, /* terminfo */
1190 {"%9", "print"}, /* terminfo */
1191 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1193 * "insert" --- see below
1195 {"&8", "undo"}, /* terminfo */
1196 {"%0", "redo"}, /* terminfo */
1197 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1198 {"@0", "find"}, /* terminfo */
1199 {"@2", "cancel"}, /* terminfo */
1200 {"%1", "help"}, /* terminfo */
1202 * "break" goes here, but can't be reliably intercepted with termcap
1204 {"&4", "reset"}, /* terminfo --- actually `restart' */
1206 * "system" and "user" --- no termcaps
1208 {"kE", "clearline"}, /* terminfo */
1209 {"kA", "insertline"}, /* terminfo */
1210 {"kL", "deleteline"}, /* terminfo */
1211 {"kI", "insertchar"}, /* terminfo */
1212 {"kD", "deletechar"}, /* terminfo */
1213 {"kB", "backtab"}, /* terminfo */
1215 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1217 {"@8", "kp-enter"}, /* terminfo */
1219 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1220 * "kp-multiply", "kp-add", "kp-separator",
1221 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1222 * --- no termcaps for any of these.
1224 {"K4", "kp-1"}, /* terminfo */
1226 * "kp-2" --- no termcap
1228 {"K5", "kp-3"}, /* terminfo */
1230 * "kp-4" --- no termcap
1232 {"K2", "kp-5"}, /* terminfo */
1234 * "kp-6" --- no termcap
1236 {"K1", "kp-7"}, /* terminfo */
1238 * "kp-8" --- no termcap
1240 {"K3", "kp-9"}, /* terminfo */
1242 * "kp-equal" --- no termcap
1254 {"&0", "S-cancel"}, /*shifted cancel key*/
1255 {"&9", "S-begin"}, /*shifted begin key*/
1256 {"*0", "S-find"}, /*shifted find key*/
1257 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1258 {"*4", "S-delete"}, /*shifted delete-character key*/
1259 {"*7", "S-end"}, /*shifted end key*/
1260 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1261 {"#1", "S-help"}, /*shifted help key*/
1262 {"#2", "S-home"}, /*shifted home key*/
1263 {"#3", "S-insert"}, /*shifted insert-character key*/
1264 {"#4", "S-left"}, /*shifted left-arrow key*/
1265 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1266 {"%c", "S-next"}, /*shifted next key*/
1267 {"%e", "S-prior"}, /*shifted previous key*/
1268 {"%f", "S-print"}, /*shifted print key*/
1269 {"%g", "S-redo"}, /*shifted redo key*/
1270 {"%i", "S-right"}, /*shifted right-arrow key*/
1271 {"!3", "S-undo"} /*shifted undo key*/
1274 static char **term_get_fkeys_address
;
1275 static KBOARD
*term_get_fkeys_kboard
;
1276 static Lisp_Object
term_get_fkeys_1 ();
1278 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1279 This function scans the termcap function key sequence entries, and
1280 adds entries to Vfunction_key_map for each function key it finds. */
1283 term_get_fkeys (address
, kboard
)
1287 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1288 errors during the call. The only errors should be from Fdefine_key
1289 when given a key sequence containing an invalid prefix key. If the
1290 termcap defines function keys which use a prefix that is already bound
1291 to a command by the default bindings, we should silently ignore that
1292 function key specification, rather than giving the user an error and
1293 refusing to run at all on such a terminal. */
1295 extern Lisp_Object
Fidentity ();
1296 term_get_fkeys_address
= address
;
1297 term_get_fkeys_kboard
= kboard
;
1298 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1306 char **address
= term_get_fkeys_address
;
1307 KBOARD
*kboard
= term_get_fkeys_kboard
;
1309 /* This can happen if CANNOT_DUMP or with strange options. */
1311 kboard
->Vlocal_function_key_map
= Fmake_sparse_keymap (Qnil
);
1313 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1315 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1317 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (sequence
),
1318 Fmake_vector (make_number (1),
1319 intern (keys
[i
].name
)));
1322 /* The uses of the "k0" capability are inconsistent; sometimes it
1323 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1324 We will attempt to politely accommodate both systems by testing for
1325 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1328 char *k_semi
= tgetstr ("k;", address
);
1329 char *k0
= tgetstr ("k0", address
);
1330 char *k0_name
= "f10";
1335 /* Define f0 first, so that f10 takes precedence in case the
1336 key sequences happens to be the same. */
1337 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (k0
),
1338 Fmake_vector (make_number (1), intern ("f0")));
1339 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (k_semi
),
1340 Fmake_vector (make_number (1), intern ("f10")));
1343 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (k0
),
1344 Fmake_vector (make_number (1), intern (k0_name
)));
1347 /* Set up cookies for numbered function keys above f10. */
1349 char fcap
[3], fkey
[4];
1351 fcap
[0] = 'F'; fcap
[2] = '\0';
1352 for (i
= 11; i
< 64; i
++)
1355 fcap
[1] = '1' + i
- 11;
1357 fcap
[1] = 'A' + i
- 20;
1359 fcap
[1] = 'a' + i
- 46;
1362 char *sequence
= tgetstr (fcap
, address
);
1365 sprintf (fkey
, "f%d", i
);
1366 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (sequence
),
1367 Fmake_vector (make_number (1),
1375 * Various mappings to try and get a better fit.
1378 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1379 if (!tgetstr (cap1, address)) \
1381 char *sequence = tgetstr (cap2, address); \
1383 Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), \
1384 Fmake_vector (make_number (1), \
1388 /* if there's no key_next keycap, map key_npage to `next' keysym */
1389 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1390 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1391 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1392 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1393 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1394 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1395 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1397 /* IBM has their own non-standard dialect of terminfo.
1398 If the standard name isn't found, try the IBM name. */
1399 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1400 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1401 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1402 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1403 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1404 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1405 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1406 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1407 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1408 #undef CONDITIONAL_REASSIGN
1415 /***********************************************************************
1416 Character Display Information
1417 ***********************************************************************/
1419 /* Avoid name clash with functions defined in xterm.c */
1421 #define append_glyph append_glyph_term
1422 #define produce_stretch_glyph produce_stretch_glyph_term
1425 static void append_glyph
P_ ((struct it
*));
1426 static void produce_stretch_glyph
P_ ((struct it
*));
1429 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1430 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1431 the character for which to produce glyphs; IT->face_id contains the
1432 character's face. Padding glyphs are appended if IT->c has a
1433 IT->pixel_width > 1. */
1439 struct glyph
*glyph
, *end
;
1442 xassert (it
->glyph_row
);
1443 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1444 + it
->glyph_row
->used
[it
->area
]);
1445 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1448 i
< it
->pixel_width
&& glyph
< end
;
1451 glyph
->type
= CHAR_GLYPH
;
1452 glyph
->pixel_width
= 1;
1453 glyph
->u
.ch
= it
->char_to_display
;
1454 glyph
->face_id
= it
->face_id
;
1455 glyph
->padding_p
= i
> 0;
1456 glyph
->charpos
= CHARPOS (it
->position
);
1457 glyph
->object
= it
->object
;
1459 ++it
->glyph_row
->used
[it
->area
];
1465 /* Produce glyphs for the display element described by IT. *IT
1466 specifies what we want to produce a glyph for (character, image, ...),
1467 and where in the glyph matrix we currently are (glyph row and hpos).
1468 produce_glyphs fills in output fields of *IT with information such as the
1469 pixel width and height of a character, and maybe output actual glyphs at
1470 the same time if IT->glyph_row is non-null. See the explanation of
1471 struct display_iterator in dispextern.h for an overview.
1473 produce_glyphs also stores the result of glyph width, ascent
1474 etc. computations in *IT.
1476 IT->glyph_row may be null, in which case produce_glyphs does not
1477 actually fill in the glyphs. This is used in the move_* functions
1478 in xdisp.c for text width and height computations.
1480 Callers usually don't call produce_glyphs directly;
1481 instead they use the macro PRODUCE_GLYPHS. */
1487 /* If a hook is installed, let it do the work. */
1488 xassert (it
->what
== IT_CHARACTER
1489 || it
->what
== IT_COMPOSITION
1490 || it
->what
== IT_STRETCH
);
1492 if (it
->what
== IT_STRETCH
)
1494 produce_stretch_glyph (it
);
1498 /* Nothing but characters are supported on terminal frames. For a
1499 composition sequence, it->c is the first character of the
1501 xassert (it
->what
== IT_CHARACTER
1502 || it
->what
== IT_COMPOSITION
);
1504 /* Maybe translate single-byte characters to multibyte. */
1505 it
->char_to_display
= it
->c
;
1507 if (it
->c
>= 040 && it
->c
< 0177)
1509 it
->pixel_width
= it
->nglyphs
= 1;
1513 else if (it
->c
== '\n')
1514 it
->pixel_width
= it
->nglyphs
= 0;
1515 else if (it
->c
== '\t')
1517 int absolute_x
= (it
->current_x
1518 + it
->continuation_lines_width
);
1520 = (((1 + absolute_x
+ it
->tab_width
- 1)
1525 /* If part of the TAB has been displayed on the previous line
1526 which is continued now, continuation_lines_width will have
1527 been incremented already by the part that fitted on the
1528 continued line. So, we will get the right number of spaces
1530 nspaces
= next_tab_x
- absolute_x
;
1536 it
->char_to_display
= ' ';
1537 it
->pixel_width
= it
->len
= 1;
1543 it
->pixel_width
= nspaces
;
1544 it
->nglyphs
= nspaces
;
1546 else if (SINGLE_BYTE_CHAR_P (it
->c
))
1548 if (unibyte_display_via_language_environment
1550 || !NILP (Vnonascii_translation_table
)))
1554 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1555 charset
= CHAR_CHARSET (it
->char_to_display
);
1556 it
->pixel_width
= CHARSET_WIDTH (charset
);
1557 it
->nglyphs
= it
->pixel_width
;
1563 /* Coming here means that it->c is from display table, thus we
1564 must send the code as is to the terminal. Although there's
1565 no way to know how many columns it occupies on a screen, it
1566 is a good assumption that a single byte code has 1-column
1568 it
->pixel_width
= it
->nglyphs
= 1;
1575 /* A multi-byte character. The display width is fixed for all
1576 characters of the set. Some of the glyphs may have to be
1577 ignored because they are already displayed in a continued
1579 int charset
= CHAR_CHARSET (it
->c
);
1581 it
->pixel_width
= CHARSET_WIDTH (charset
);
1582 it
->nglyphs
= it
->pixel_width
;
1589 /* Advance current_x by the pixel width as a convenience for
1591 if (it
->area
== TEXT_AREA
)
1592 it
->current_x
+= it
->pixel_width
;
1593 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1594 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1598 /* Produce a stretch glyph for iterator IT. IT->object is the value
1599 of the glyph property displayed. The value must be a list
1600 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1603 1. `:width WIDTH' specifies that the space should be WIDTH *
1604 canonical char width wide. WIDTH may be an integer or floating
1607 2. `:align-to HPOS' specifies that the space should be wide enough
1608 to reach HPOS, a value in canonical character units. */
1611 produce_stretch_glyph (it
)
1614 /* (space :width WIDTH ...) */
1615 Lisp_Object prop
, plist
;
1616 int width
= 0, align_to
= -1;
1617 int zero_width_ok_p
= 0;
1620 /* List should start with `space'. */
1621 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1622 plist
= XCDR (it
->object
);
1624 /* Compute the width of the stretch. */
1625 if ((prop
= Fplist_get (plist
, QCwidth
), !NILP (prop
))
1626 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, 0))
1628 /* Absolute width `:width WIDTH' specified and valid. */
1629 zero_width_ok_p
= 1;
1630 width
= (int)(tem
+ 0.5);
1632 else if ((prop
= Fplist_get (plist
, QCalign_to
), !NILP (prop
))
1633 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, &align_to
))
1635 if (it
->glyph_row
== NULL
|| !it
->glyph_row
->mode_line_p
)
1636 align_to
= (align_to
< 0
1638 : align_to
- window_box_left_offset (it
->w
, TEXT_AREA
));
1639 else if (align_to
< 0)
1640 align_to
= window_box_left_offset (it
->w
, TEXT_AREA
);
1641 width
= max (0, (int)(tem
+ 0.5) + align_to
- it
->current_x
);
1642 zero_width_ok_p
= 1;
1645 /* Nothing specified -> width defaults to canonical char width. */
1646 width
= FRAME_COLUMN_WIDTH (it
->f
);
1648 if (width
<= 0 && (width
< 0 || !zero_width_ok_p
))
1651 if (width
> 0 && it
->glyph_row
)
1653 Lisp_Object o_object
= it
->object
;
1654 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1657 if (!STRINGP (object
))
1658 object
= it
->w
->buffer
;
1659 it
->object
= object
;
1660 it
->char_to_display
= ' ';
1661 it
->pixel_width
= it
->len
= 1;
1664 it
->object
= o_object
;
1666 it
->pixel_width
= width
;
1667 it
->nglyphs
= width
;
1671 /* Get information about special display element WHAT in an
1672 environment described by IT. WHAT is one of IT_TRUNCATION or
1673 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1674 non-null glyph_row member. This function ensures that fields like
1675 face_id, c, len of IT are left untouched. */
1678 produce_special_glyphs (it
, what
)
1680 enum display_element_type what
;
1687 temp_it
.what
= IT_CHARACTER
;
1689 temp_it
.object
= make_number (0);
1690 bzero (&temp_it
.current
, sizeof temp_it
.current
);
1692 if (what
== IT_CONTINUATION
)
1694 /* Continuation glyph. */
1696 && INTEGERP (DISP_CONTINUE_GLYPH (it
->dp
))
1697 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it
->dp
))))
1699 glyph
= XINT (DISP_CONTINUE_GLYPH (it
->dp
));
1700 glyph
= spec_glyph_lookup_face (XWINDOW (it
->window
), glyph
);
1705 else if (what
== IT_TRUNCATION
)
1707 /* Truncation glyph. */
1709 && INTEGERP (DISP_TRUNC_GLYPH (it
->dp
))
1710 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it
->dp
))))
1712 glyph
= XINT (DISP_TRUNC_GLYPH (it
->dp
));
1713 glyph
= spec_glyph_lookup_face (XWINDOW (it
->window
), glyph
);
1721 temp_it
.c
= FAST_GLYPH_CHAR (glyph
);
1722 temp_it
.face_id
= FAST_GLYPH_FACE (glyph
);
1723 temp_it
.len
= CHAR_BYTES (temp_it
.c
);
1725 produce_glyphs (&temp_it
);
1726 it
->pixel_width
= temp_it
.pixel_width
;
1727 it
->nglyphs
= temp_it
.pixel_width
;
1732 /***********************************************************************
1734 ***********************************************************************/
1736 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1737 one of the enumerators from enum no_color_bit, or a bit set built
1738 from them. Some display attributes may not be used together with
1739 color; the termcap capability `NC' specifies which ones. */
1741 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1742 (tty->TN_max_colors > 0 \
1743 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1746 /* Turn appearances of face FACE_ID on tty frame F on.
1747 FACE_ID is a realized face ID number, in the face cache. */
1750 turn_on_face (f
, face_id
)
1754 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1755 long fg
= face
->foreground
;
1756 long bg
= face
->background
;
1757 struct tty_display_info
*tty
= FRAME_TTY (f
);
1759 /* Do this first because TS_end_standout_mode may be the same
1760 as TS_exit_attribute_mode, which turns all appearances off. */
1761 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
))
1763 if (tty
->TN_max_colors
> 0)
1765 if (fg
>= 0 && bg
>= 0)
1767 /* If the terminal supports colors, we can set them
1768 below without using reverse video. The face's fg
1769 and bg colors are set as they should appear on
1770 the screen, i.e. they take the inverse-video'ness
1771 of the face already into account. */
1773 else if (inverse_video
)
1775 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1776 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1777 tty_toggle_highlight (tty
);
1781 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1782 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1783 tty_toggle_highlight (tty
);
1788 /* If we can't display colors, use reverse video
1789 if the face specifies that. */
1792 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1793 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1794 tty_toggle_highlight (tty
);
1798 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1799 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1800 tty_toggle_highlight (tty
);
1805 if (face
->tty_bold_p
)
1807 if (MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1808 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1810 else if (face
->tty_dim_p
)
1811 if (MAY_USE_WITH_COLORS_P (tty
, NC_DIM
))
1812 OUTPUT1_IF (tty
, tty
->TS_enter_dim_mode
);
1814 /* Alternate charset and blinking not yet used. */
1815 if (face
->tty_alt_charset_p
1816 && MAY_USE_WITH_COLORS_P (tty
, NC_ALT_CHARSET
))
1817 OUTPUT1_IF (tty
, tty
->TS_enter_alt_charset_mode
);
1819 if (face
->tty_blinking_p
1820 && MAY_USE_WITH_COLORS_P (tty
, NC_BLINK
))
1821 OUTPUT1_IF (tty
, tty
->TS_enter_blink_mode
);
1823 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1824 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1826 if (tty
->TN_max_colors
> 0)
1830 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1833 p
= tparam (ts
, NULL
, 0, (int) fg
);
1838 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
1841 p
= tparam (ts
, NULL
, 0, (int) bg
);
1849 /* Turn off appearances of face FACE_ID on tty frame F. */
1852 turn_off_face (f
, face_id
)
1856 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1857 struct tty_display_info
*tty
= FRAME_TTY (f
);
1859 xassert (face
!= NULL
);
1861 if (tty
->TS_exit_attribute_mode
)
1863 /* Capability "me" will turn off appearance modes double-bright,
1864 half-bright, reverse-video, standout, underline. It may or
1865 may not turn off alt-char-mode. */
1866 if (face
->tty_bold_p
1868 || face
->tty_reverse_p
1869 || face
->tty_alt_charset_p
1870 || face
->tty_blinking_p
1871 || face
->tty_underline_p
)
1873 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
1874 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
1875 tty
->standout_mode
= 0;
1878 if (face
->tty_alt_charset_p
)
1879 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1883 /* If we don't have "me" we can only have those appearances
1884 that have exit sequences defined. */
1885 if (face
->tty_alt_charset_p
)
1886 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1888 if (face
->tty_underline_p
)
1889 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
1892 /* Switch back to default colors. */
1893 if (tty
->TN_max_colors
> 0
1894 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
1895 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
1896 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
1897 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
1898 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
1902 /* Return non-zero if the terminal on frame F supports all of the
1903 capabilities in CAPS simultaneously, with foreground and background
1904 colors FG and BG. */
1907 tty_capable_p (tty
, caps
, fg
, bg
)
1908 struct tty_display_info
*tty
;
1910 unsigned long fg
, bg
;
1912 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1913 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1916 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
1917 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
1918 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
1919 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
1920 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BLINK
, tty
->TS_enter_blink_mode
, NC_BLINK
);
1921 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ALT_CHARSET
, tty
->TS_enter_alt_charset_mode
, NC_ALT_CHARSET
);
1927 /* Return non-zero if the terminal is capable to display colors. */
1929 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
1931 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
1933 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1934 frame's terminal). This function always returns nil if TERMINAL
1935 is not on a tty device. */)
1937 Lisp_Object terminal
;
1939 struct terminal
*t
= get_tty_terminal (terminal
, 0);
1943 return t
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
1946 /* Return the number of supported colors. */
1947 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
1948 Stty_display_color_cells
, 0, 1, 0,
1949 doc
: /* Return the number of colors supported by the tty device TERMINAL.
1951 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1952 frame's terminal). This function always returns 0 if TERMINAL
1953 is not on a tty device. */)
1955 Lisp_Object terminal
;
1957 struct terminal
*t
= get_tty_terminal (terminal
, 0);
1959 return make_number (0);
1961 return make_number (t
->display_info
.tty
->TN_max_colors
);
1966 /* Save or restore the default color-related capabilities of this
1969 tty_default_color_capabilities (struct tty_display_info
*tty
, int save
)
1972 *default_orig_pair
, *default_set_foreground
, *default_set_background
;
1973 static int default_max_colors
, default_max_pairs
, default_no_color_video
;
1977 if (default_orig_pair
)
1978 xfree (default_orig_pair
);
1979 default_orig_pair
= tty
->TS_orig_pair
? xstrdup (tty
->TS_orig_pair
) : NULL
;
1981 if (default_set_foreground
)
1982 xfree (default_set_foreground
);
1983 default_set_foreground
= tty
->TS_set_foreground
? xstrdup (tty
->TS_set_foreground
)
1986 if (default_set_background
)
1987 xfree (default_set_background
);
1988 default_set_background
= tty
->TS_set_background
? xstrdup (tty
->TS_set_background
)
1991 default_max_colors
= tty
->TN_max_colors
;
1992 default_max_pairs
= tty
->TN_max_pairs
;
1993 default_no_color_video
= tty
->TN_no_color_video
;
1997 tty
->TS_orig_pair
= default_orig_pair
;
1998 tty
->TS_set_foreground
= default_set_foreground
;
1999 tty
->TS_set_background
= default_set_background
;
2000 tty
->TN_max_colors
= default_max_colors
;
2001 tty
->TN_max_pairs
= default_max_pairs
;
2002 tty
->TN_no_color_video
= default_no_color_video
;
2006 /* Setup one of the standard tty color schemes according to MODE.
2007 MODE's value is generally the number of colors which we want to
2008 support; zero means set up for the default capabilities, the ones
2009 we saw at init_tty time; -1 means turn off color support. */
2011 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2013 /* Canonicalize all negative values of MODE. */
2019 case -1: /* no colors at all */
2020 tty
->TN_max_colors
= 0;
2021 tty
->TN_max_pairs
= 0;
2022 tty
->TN_no_color_video
= 0;
2023 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2025 case 0: /* default colors, if any */
2027 tty_default_color_capabilities (tty
, 0);
2029 case 8: /* 8 standard ANSI colors */
2030 tty
->TS_orig_pair
= "\033[0m";
2032 tty
->TS_set_foreground
= "\033[3%p1%dm";
2033 tty
->TS_set_background
= "\033[4%p1%dm";
2035 tty
->TS_set_foreground
= "\033[3%dm";
2036 tty
->TS_set_background
= "\033[4%dm";
2038 tty
->TN_max_colors
= 8;
2039 tty
->TN_max_pairs
= 64;
2040 tty
->TN_no_color_video
= 0;
2046 set_tty_color_mode (f
, val
)
2050 Lisp_Object color_mode_spec
, current_mode_spec
;
2051 Lisp_Object color_mode
, current_mode
;
2053 extern Lisp_Object Qtty_color_mode
;
2054 Lisp_Object tty_color_mode_alist
;
2056 tty_color_mode_alist
= Fintern_soft (build_string ("tty-color-mode-alist"),
2063 if (NILP (tty_color_mode_alist
))
2064 color_mode_spec
= Qnil
;
2066 color_mode_spec
= Fassq (val
, XSYMBOL (tty_color_mode_alist
)->value
);
2068 if (CONSP (color_mode_spec
))
2069 color_mode
= XCDR (color_mode_spec
);
2074 current_mode_spec
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2076 if (CONSP (current_mode_spec
))
2077 current_mode
= XCDR (current_mode_spec
);
2079 current_mode
= Qnil
;
2080 if (INTEGERP (color_mode
))
2081 mode
= XINT (color_mode
);
2083 mode
= 0; /* meaning default */
2084 if (INTEGERP (current_mode
))
2085 old_mode
= XINT (current_mode
);
2089 if (mode
!= old_mode
)
2091 tty_setup_colors (FRAME_TTY (f
), mode
);
2092 /* This recomputes all the faces given the new color
2094 call0 (intern ("tty-set-up-initial-frame-faces"));
2099 #endif /* !WINDOWSNT */
2103 /* Return the tty display object specified by TERMINAL. */
2106 get_tty_terminal (Lisp_Object terminal
, int throw)
2108 struct terminal
*t
= get_terminal (terminal
, throw);
2110 if (t
&& t
->type
== output_initial
)
2113 if (t
&& t
->type
!= output_termcap
)
2116 error ("Device %d is not a termcap terminal device", t
->id
);
2124 /* Return an active termcap device that uses the tty device with the
2127 This function ignores suspended devices.
2129 Returns NULL if the named terminal device is not opened. */
2132 get_named_tty (name
)
2140 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
2142 if (t
->type
== output_termcap
2143 && !strcmp (t
->display_info
.tty
->name
, name
)
2144 && TERMINAL_ACTIVE_P (t
))
2152 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2153 doc
: /* Return the type of the tty device that TERMINAL uses.
2154 Returns nil if TERMINAL is not on a tty device.
2156 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2157 frame's terminal). */)
2159 Lisp_Object terminal
;
2161 struct terminal
*t
= get_terminal (terminal
, 1);
2163 if (t
->type
!= output_termcap
)
2166 if (t
->display_info
.tty
->type
)
2167 return build_string (t
->display_info
.tty
->type
);
2172 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2173 doc
: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2175 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2176 frame's terminal). This function always returns nil if TERMINAL
2177 is not on a tty device. */)
2179 Lisp_Object terminal
;
2181 struct terminal
*t
= get_terminal (terminal
, 1);
2183 if (t
->type
!= output_termcap
|| strcmp (t
->display_info
.tty
->name
, "/dev/tty"))
2189 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2190 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2191 This is used to override the terminfo data, for certain terminals that
2192 do not really do underlining, but say that they do. This function has
2193 no effect if used on a non-tty terminal.
2195 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2196 frame's terminal). This function always returns nil if TERMINAL
2197 is not on a tty device. */)
2199 Lisp_Object terminal
;
2201 struct terminal
*t
= get_terminal (terminal
, 1);
2203 if (t
->type
== output_termcap
)
2204 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2210 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2211 doc
: /* Suspend the terminal device TTY.
2213 The device is restored to its default state, and Emacs ceases all
2214 access to the tty device. Frames that use the device are not deleted,
2215 but input is not read from them and if they change, their display is
2218 TTY may be a terminal id, a frame, or nil for the terminal device of
2219 the currently selected frame.
2221 This function runs `suspend-tty-functions' after suspending the
2222 device. The functions are run with one arg, the id of the suspended
2225 `suspend-tty' does nothing if it is called on a device that is already
2228 A suspended tty may be resumed by calling `resume-tty' on it. */)
2232 struct terminal
*t
= get_tty_terminal (tty
, 1);
2236 error ("Unknown tty device");
2238 f
= t
->display_info
.tty
->input
;
2242 reset_sys_modes (t
->display_info
.tty
);
2244 delete_keyboard_wait_descriptor (fileno (f
));
2247 if (f
!= t
->display_info
.tty
->output
)
2248 fclose (t
->display_info
.tty
->output
);
2250 t
->display_info
.tty
->input
= 0;
2251 t
->display_info
.tty
->output
= 0;
2253 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2254 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2256 /* Run `suspend-tty-functions'. */
2257 if (!NILP (Vrun_hooks
))
2259 Lisp_Object args
[2];
2260 args
[0] = intern ("suspend-tty-functions");
2261 args
[1] = make_number (t
->id
);
2262 Frun_hook_with_args (2, args
);
2266 /* Clear display hooks to prevent further output. */
2267 clear_tty_hooks (t
);
2272 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2273 doc
: /* Resume the previously suspended terminal device TTY.
2274 The terminal is opened and reinitialized. Frames that are on the
2275 suspended terminal are revived.
2277 It is an error to resume a terminal while another terminal is active
2280 This function runs `resume-tty-functions' after resuming the terminal.
2281 The functions are run with one arg, the id of the resumed terminal
2284 `resume-tty' does nothing if it is called on a device that is not
2287 TTY may be a terminal id, a frame, or nil for the terminal device of
2288 the currently selected frame. */)
2292 struct terminal
*t
= get_tty_terminal (tty
, 1);
2296 error ("Unknown tty device");
2298 if (!t
->display_info
.tty
->input
)
2300 if (get_named_tty (t
->display_info
.tty
->name
))
2301 error ("Cannot resume display while another display is active on the same device");
2303 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2306 error ("Can not reopen tty device %s: %s", t
->display_info
.tty
->name
, strerror (errno
));
2308 if (strcmp (t
->display_info
.tty
->name
, "/dev/tty"))
2309 dissociate_if_controlling_tty (fd
);
2311 t
->display_info
.tty
->output
= fdopen (fd
, "w+");
2312 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
;
2314 add_keyboard_wait_descriptor (fd
);
2316 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2317 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2319 init_sys_modes (t
->display_info
.tty
);
2321 /* Run `suspend-tty-functions'. */
2322 if (!NILP (Vrun_hooks
))
2324 Lisp_Object args
[2];
2325 args
[0] = intern ("resume-tty-functions");
2326 args
[1] = make_number (t
->id
);
2327 Frun_hook_with_args (2, args
);
2337 /***********************************************************************
2339 ***********************************************************************/
2343 term_mouse_moveto (int x
, int y
)
2347 /* TODO: how to set mouse position?
2348 name = (const char *) ttyname (0);
2349 fd = open (name, O_WRONLY);
2350 SOME_FUNCTION (x, y, fd);
2353 last_mouse_y = y; */
2357 term_show_mouse_face (enum draw_glyphs_face draw
)
2359 struct window
*w
= XWINDOW (Qmouse_face_window
);
2363 struct frame
*f
= XFRAME (w
->frame
);
2364 struct tty_display_info
*tty
= FRAME_TTY (f
);
2366 if (/* If window is in the process of being destroyed, don't bother
2368 w
->current_matrix
!= NULL
2369 /* Recognize when we are called to operate on rows that don't exist
2370 anymore. This can happen when a window is split. */
2371 && mouse_face_end_row
< w
->current_matrix
->nrows
)
2373 /* write_glyphs writes at cursor position, so we need to
2374 temporarily move cursor coordinates to the beginning of
2375 the highlight region. */
2377 /* Save current cursor co-ordinates */
2378 save_y
= curY (tty
);
2379 save_x
= curX (tty
);
2381 /* Note that mouse_face_beg_row etc. are window relative. */
2382 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2384 int start_hpos
, end_hpos
, nglyphs
;
2385 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
2387 /* Don't do anything if row doesn't have valid contents. */
2388 if (!row
->enabled_p
)
2391 /* For all but the first row, the highlight starts at column 0. */
2392 if (i
== mouse_face_beg_row
)
2393 start_hpos
= mouse_face_beg_col
;
2397 if (i
== mouse_face_end_row
)
2398 end_hpos
= mouse_face_end_col
;
2401 end_hpos
= row
->used
[TEXT_AREA
];
2402 if (draw
== DRAW_NORMAL_TEXT
)
2403 row
->fill_line_p
= 1; /* Clear to end of line */
2406 if (end_hpos
<= start_hpos
)
2408 /* Record that some glyphs of this row are displayed in
2410 row
->mouse_face_p
= draw
> 0;
2412 nglyphs
= end_hpos
- start_hpos
;
2414 if (end_hpos
>= row
->used
[TEXT_AREA
])
2415 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2417 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2418 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
2419 + WINDOW_LEFT_EDGE_X (w
);
2421 cursor_to (f
, pos_y
, pos_x
);
2423 if (draw
== DRAW_MOUSE_FACE
)
2425 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2426 nglyphs
, mouse_face_face_id
);
2428 else /* draw == DRAW_NORMAL_TEXT */
2429 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2431 cursor_to (f
, save_y
, save_x
);
2436 term_clear_mouse_face ()
2438 if (!NILP (Qmouse_face_window
))
2439 term_show_mouse_face (DRAW_NORMAL_TEXT
);
2441 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2442 mouse_face_end_row
= mouse_face_end_col
= -1;
2443 Qmouse_face_window
= Qnil
;
2446 /* Find the glyph matrix position of buffer position POS in window W.
2447 *HPOS and *VPOS are set to the positions found. W's current glyphs
2448 must be up to date. If POS is above window start return (0, 0).
2449 If POS is after end of W, return end of last line in W.
2450 - taken from msdos.c */
2452 fast_find_position (struct window
*w
, int pos
, int *hpos
, int *vpos
)
2454 int i
, lastcol
, line_start_position
, maybe_next_line_p
= 0;
2455 int yb
= window_text_bottom_y (w
);
2456 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0), *best_row
= row
;
2460 if (row
->used
[TEXT_AREA
])
2461 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
2463 line_start_position
= 0;
2465 if (line_start_position
> pos
)
2467 /* If the position sought is the end of the buffer,
2468 don't include the blank lines at the bottom of the window. */
2469 else if (line_start_position
== pos
2470 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2472 maybe_next_line_p
= 1;
2475 else if (line_start_position
> 0)
2478 /* Don't overstep the last matrix row, lest we get into the
2479 never-never land... */
2480 if (row
->y
+ 1 >= yb
)
2486 /* Find the right column within BEST_ROW. */
2489 for (i
= 0; i
< row
->used
[TEXT_AREA
]; i
++)
2491 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
] + i
;
2494 charpos
= glyph
->charpos
;
2501 else if (charpos
> pos
)
2503 else if (charpos
> 0)
2507 /* If we're looking for the end of the buffer,
2508 and we didn't find it in the line we scanned,
2509 use the start of the following line. */
2510 if (maybe_next_line_p
)
2517 *hpos
= lastcol
+ 1;
2522 term_mouse_highlight (struct frame
*f
, int x
, int y
)
2524 enum window_part part
;
2529 if (NILP (Vmouse_highlight
)
2530 || !f
->glyphs_initialized_p
)
2533 /* Which window is that in? */
2534 window
= window_from_coordinates (f
, x
, y
, &part
, &x
, &y
, 0);
2536 /* Not on a window -> return. */
2537 if (!WINDOWP (window
))
2540 if (!EQ (window
, Qmouse_face_window
))
2541 term_clear_mouse_face ();
2543 w
= XWINDOW (window
);
2545 /* Are we in a window whose display is up to date?
2546 And verify the buffer's text has not changed. */
2547 b
= XBUFFER (w
->buffer
);
2549 && EQ (w
->window_end_valid
, w
->buffer
)
2550 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
2551 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
2553 int pos
, i
, nrows
= w
->current_matrix
->nrows
;
2554 struct glyph_row
*row
;
2555 struct glyph
*glyph
;
2557 /* Find the glyph under X/Y. */
2559 if (y
>= 0 && y
< nrows
)
2561 row
= MATRIX_ROW (w
->current_matrix
, y
);
2562 /* Give up if some row before the one we are looking for is
2564 for (i
= 0; i
<= y
; i
++)
2565 if (!MATRIX_ROW (w
->current_matrix
, i
)->enabled_p
)
2567 if (i
> y
/* all rows upto and including the one at Y are enabled */
2568 && row
->displays_text_p
2569 && x
< window_box_width (w
, TEXT_AREA
))
2571 glyph
= row
->glyphs
[TEXT_AREA
];
2572 if (x
>= row
->used
[TEXT_AREA
])
2577 if (!BUFFERP (glyph
->object
))
2583 /* Clear mouse face if X/Y not over text. */
2586 term_clear_mouse_face ();
2590 if (!BUFFERP (glyph
->object
))
2592 pos
= glyph
->charpos
;
2594 /* Check for mouse-face. */
2596 extern Lisp_Object Qmouse_face
;
2597 Lisp_Object mouse_face
, overlay
, position
, *overlay_vec
;
2598 int noverlays
, obegv
, ozv
;
2599 struct buffer
*obuf
;
2601 /* If we get an out-of-range value, return now; avoid an error. */
2602 if (pos
> BUF_Z (b
))
2605 /* Make the window's buffer temporarily current for
2606 overlays_at and compute_char_face. */
2607 obuf
= current_buffer
;
2614 /* Is this char mouse-active? */
2615 XSETINT (position
, pos
);
2617 /* Put all the overlays we want in a vector in overlay_vec. */
2618 GET_OVERLAYS_AT (pos
, overlay_vec
, noverlays
, NULL
, 0);
2619 /* Sort overlays into increasing priority order. */
2620 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2622 /* Check mouse-face highlighting. */
2623 if (!(EQ (window
, Qmouse_face_window
)
2624 && y
>= mouse_face_beg_row
2625 && y
<= mouse_face_end_row
2626 && (y
> mouse_face_beg_row
2627 || x
>= mouse_face_beg_col
)
2628 && (y
< mouse_face_end_row
2629 || x
< mouse_face_end_col
2630 || mouse_face_past_end
)))
2632 /* Clear the display of the old active region, if any. */
2633 term_clear_mouse_face ();
2635 /* Find the highest priority overlay that has a mouse-face
2638 for (i
= noverlays
- 1; i
>= 0; --i
)
2640 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2641 if (!NILP (mouse_face
))
2643 overlay
= overlay_vec
[i
];
2648 /* If no overlay applies, get a text property. */
2650 mouse_face
= Fget_text_property (position
, Qmouse_face
,
2653 /* Handle the overlay case. */
2654 if (!NILP (overlay
))
2656 /* Find the range of text around this char that
2657 should be active. */
2658 Lisp_Object before
, after
;
2662 before
= Foverlay_start (overlay
);
2663 after
= Foverlay_end (overlay
);
2664 /* Record this as the current active region. */
2665 fast_find_position (w
, XFASTINT (before
),
2666 &mouse_face_beg_col
,
2667 &mouse_face_beg_row
);
2670 = !fast_find_position (w
, XFASTINT (after
),
2671 &mouse_face_end_col
,
2672 &mouse_face_end_row
);
2673 Qmouse_face_window
= window
;
2676 = face_at_buffer_position (w
, pos
, 0, 0,
2677 &ignore
, pos
+ 1, 1);
2679 /* Display it as active. */
2680 term_show_mouse_face (DRAW_MOUSE_FACE
);
2682 /* Handle the text property case. */
2683 else if (!NILP (mouse_face
))
2685 /* Find the range of text around this char that
2686 should be active. */
2687 Lisp_Object before
, after
, beginning
, end
;
2690 beginning
= Fmarker_position (w
->start
);
2691 XSETINT (end
, (BUF_Z (b
) - XFASTINT (w
->window_end_pos
)));
2693 = Fprevious_single_property_change (make_number (pos
+ 1),
2695 w
->buffer
, beginning
);
2697 = Fnext_single_property_change (position
, Qmouse_face
,
2700 /* Record this as the current active region. */
2701 fast_find_position (w
, XFASTINT (before
),
2702 &mouse_face_beg_col
,
2703 &mouse_face_beg_row
);
2705 = !fast_find_position (w
, XFASTINT (after
),
2706 &mouse_face_end_col
,
2707 &mouse_face_end_row
);
2708 Qmouse_face_window
= window
;
2711 = face_at_buffer_position (w
, pos
, 0, 0,
2712 &ignore
, pos
+ 1, 1);
2714 /* Display it as active. */
2715 term_show_mouse_face (DRAW_MOUSE_FACE
);
2719 /* Look for a `help-echo' property. */
2722 extern Lisp_Object Qhelp_echo
;
2724 /* Check overlays first. */
2726 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
2728 overlay
= overlay_vec
[i
];
2729 help
= Foverlay_get (overlay
, Qhelp_echo
);
2734 help_echo_string
= help
;
2735 help_echo_window
= window
;
2736 help_echo_object
= overlay
;
2737 help_echo_pos
= pos
;
2739 /* Try text properties. */
2740 else if (NILP (help
)
2741 && ((STRINGP (glyph
->object
)
2742 && glyph
->charpos
>= 0
2743 && glyph
->charpos
< SCHARS (glyph
->object
))
2744 || (BUFFERP (glyph
->object
)
2745 && glyph
->charpos
>= BEGV
2746 && glyph
->charpos
< ZV
)))
2748 help
= Fget_text_property (make_number (glyph
->charpos
),
2749 Qhelp_echo
, glyph
->object
);
2752 help_echo_string
= help
;
2753 help_echo_window
= window
;
2754 help_echo_object
= glyph
->object
;
2755 help_echo_pos
= glyph
->charpos
;
2762 current_buffer
= obuf
;
2768 term_mouse_movement (FRAME_PTR frame
, Gpm_Event
*event
)
2770 /* Has the mouse moved off the glyph it was on at the last sighting? */
2771 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2773 frame
->mouse_moved
= 1;
2774 term_mouse_highlight (frame
, event
->x
, event
->y
);
2775 /* Remember which glyph we're now on. */
2776 last_mouse_x
= event
->x
;
2777 last_mouse_y
= event
->y
;
2783 /* Return the current position of the mouse.
2785 Set *f to the frame the mouse is in, or zero if the mouse is in no
2786 Emacs frame. If it is set to zero, all the other arguments are
2789 Set *bar_window to Qnil, and *x and *y to the column and
2790 row of the character cell the mouse is over.
2792 Set *time to the time the mouse was at the returned position.
2794 This clears mouse_moved until the next motion
2797 term_mouse_position (FRAME_PTR
*fp
, int insist
, Lisp_Object
*bar_window
,
2798 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2799 Lisp_Object
*y
, unsigned long *time
)
2803 *fp
= SELECTED_FRAME ();
2804 (*fp
)->mouse_moved
= 0;
2809 XSETINT (*x
, last_mouse_x
);
2810 XSETINT (*y
, last_mouse_y
);
2811 gettimeofday(&now
, 0);
2812 *time
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2815 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2817 If the event is a button press, then note that we have grabbed
2821 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
2827 result
->kind
= GPM_CLICK_EVENT
;
2828 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
2830 if (event
->buttons
& j
) {
2831 result
->code
= i
; /* button number */
2835 gettimeofday(&now
, 0);
2836 result
->timestamp
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2838 if (event
->type
& GPM_UP
)
2839 result
->modifiers
= up_modifier
;
2840 else if (event
->type
& GPM_DOWN
)
2841 result
->modifiers
= down_modifier
;
2843 result
->modifiers
= 0;
2845 if (event
->type
& GPM_SINGLE
)
2846 result
->modifiers
|= click_modifier
;
2848 if (event
->type
& GPM_DOUBLE
)
2849 result
->modifiers
|= double_modifier
;
2851 if (event
->type
& GPM_TRIPLE
)
2852 result
->modifiers
|= triple_modifier
;
2854 if (event
->type
& GPM_DRAG
)
2855 result
->modifiers
|= drag_modifier
;
2857 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
2860 if (event
->modifiers
& (1 << 0))
2861 result
->modifiers
|= shift_modifier
;
2864 if (event
->modifiers
& (1 << 2))
2865 result
->modifiers
|= ctrl_modifier
;
2867 /* 1 << KG_ALT || KG_ALTGR */
2868 if (event
->modifiers
& (1 << 3)
2869 || event
->modifiers
& (1 << 1))
2870 result
->modifiers
|= meta_modifier
;
2873 XSETINT (result
->x
, event
->x
);
2874 XSETINT (result
->y
, event
->y
);
2875 XSETFRAME (result
->frame_or_window
, f
);
2881 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
2883 struct frame
*f
= XFRAME (tty
->top_frame
);
2885 struct input_event ie
;
2893 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
2894 unsigned char buf
[6 * sizeof (short)];
2895 unsigned short *arg
= (unsigned short *) buf
+ 1;
2898 previous_help_echo_string
= help_echo_string
;
2899 help_echo_string
= Qnil
;
2901 /* Display mouse pointer */
2902 buf
[sizeof(short) - 1] = 2; /* set selection */
2904 arg
[0] = arg
[2] = (unsigned short) event
->x
+ gpm_zerobased
;
2905 arg
[1] = arg
[3] = (unsigned short) event
->y
+ gpm_zerobased
;
2906 arg
[4] = (unsigned short) 3;
2908 name
= (const char *) ttyname (0);
2909 fd
= open (name
, O_WRONLY
);
2910 ioctl (fd
, TIOCLINUX
, buf
+ sizeof (short) - 1);
2913 if (!term_mouse_movement (f
, event
))
2914 help_echo_string
= previous_help_echo_string
;
2916 /* If the contents of the global variable help_echo_string
2917 has changed, generate a HELP_EVENT. */
2918 if (!NILP (help_echo_string
)
2919 || !NILP (previous_help_echo_string
))
2926 term_mouse_click (&ie
, event
, f
);
2930 if (ie
.kind
!= NO_EVENT
)
2932 kbd_buffer_store_event_hold (&ie
, hold_quit
);
2937 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
2942 XSETFRAME (frame
, f
);
2946 gen_help_event (help_echo_string
, frame
, help_echo_window
,
2947 help_echo_object
, help_echo_pos
);
2954 DEFUN ("term-open-connection", Fterm_open_connection
, Sterm_open_connection
,
2956 doc
: /* Open a connection to Gpm. */)
2959 struct tty_display_info
*tty
= FRAME_TTY (SELECTED_FRAME ());
2960 Gpm_Connect connection
;
2962 connection
.eventMask
= ~0;
2963 connection
.defaultMask
= ~GPM_HARD
;
2964 connection
.maxMod
= ~0;
2965 connection
.minMod
= 0;
2968 /* We only support GPM on the controlling tty. */
2969 if (term_gpm
|| tty
->terminal
->id
> 1
2970 || Gpm_Open (&connection
, 0) < 0)
2975 gpm_tty
= tty
->terminal
->id
;
2976 reset_sys_modes (tty
);
2977 init_sys_modes (tty
);
2978 add_gpm_wait_descriptor (gpm_fd
);
2983 DEFUN ("term-close-connection", Fterm_close_connection
, Sterm_close_connection
,
2985 doc
: /* Close a connection to Gpm. */)
2988 delete_gpm_wait_descriptor (gpm_fd
);
2989 while (Gpm_Close()); /* close all the stack */
2993 #endif /* HAVE_GPM */
2996 /***********************************************************************
2998 ***********************************************************************/
3000 /* Initialize the tty-dependent part of frame F. The frame must
3001 already have its device initialized. */
3004 create_tty_output (struct frame
*f
)
3006 struct tty_output
*t
;
3008 if (! FRAME_TERMCAP_P (f
))
3011 t
= xmalloc (sizeof (struct tty_output
));
3012 bzero (t
, sizeof (struct tty_output
));
3014 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3016 f
->output_data
.tty
= t
;
3019 /* Delete the tty-dependent part of frame F. */
3022 delete_tty_output (struct frame
*f
)
3024 if (! FRAME_TERMCAP_P (f
))
3027 xfree (f
->output_data
.tty
);
3033 clear_tty_hooks (struct terminal
*terminal
)
3036 terminal
->cursor_to_hook
= 0;
3037 terminal
->raw_cursor_to_hook
= 0;
3038 terminal
->clear_to_end_hook
= 0;
3039 terminal
->clear_frame_hook
= 0;
3040 terminal
->clear_end_of_line_hook
= 0;
3041 terminal
->ins_del_lines_hook
= 0;
3042 terminal
->insert_glyphs_hook
= 0;
3043 terminal
->write_glyphs_hook
= 0;
3044 terminal
->delete_glyphs_hook
= 0;
3045 terminal
->ring_bell_hook
= 0;
3046 terminal
->reset_terminal_modes_hook
= 0;
3047 terminal
->set_terminal_modes_hook
= 0;
3048 terminal
->update_begin_hook
= 0;
3049 terminal
->update_end_hook
= 0;
3050 terminal
->set_terminal_window_hook
= 0;
3051 terminal
->mouse_position_hook
= 0;
3052 terminal
->frame_rehighlight_hook
= 0;
3053 terminal
->frame_raise_lower_hook
= 0;
3054 terminal
->fullscreen_hook
= 0;
3055 terminal
->set_vertical_scroll_bar_hook
= 0;
3056 terminal
->condemn_scroll_bars_hook
= 0;
3057 terminal
->redeem_scroll_bar_hook
= 0;
3058 terminal
->judge_scroll_bars_hook
= 0;
3059 terminal
->read_socket_hook
= 0;
3060 terminal
->frame_up_to_date_hook
= 0;
3062 /* Leave these two set, or suspended frames are not deleted
3064 terminal
->delete_frame_hook
= &delete_tty_output
;
3065 terminal
->delete_terminal_hook
= &delete_tty
;
3069 set_tty_hooks (struct terminal
*terminal
)
3071 terminal
->rif
= 0; /* ttys don't support window-based redisplay. */
3073 terminal
->cursor_to_hook
= &tty_cursor_to
;
3074 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3076 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3077 terminal
->clear_frame_hook
= &tty_clear_frame
;
3078 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3080 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3082 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3083 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3084 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3086 terminal
->ring_bell_hook
= &tty_ring_bell
;
3088 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3089 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3090 terminal
->update_begin_hook
= 0; /* Not needed. */
3091 terminal
->update_end_hook
= &tty_update_end
;
3092 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3094 terminal
->mouse_position_hook
= 0; /* Not needed. */
3095 terminal
->frame_rehighlight_hook
= 0; /* Not needed. */
3096 terminal
->frame_raise_lower_hook
= 0; /* Not needed. */
3098 terminal
->set_vertical_scroll_bar_hook
= 0; /* Not needed. */
3099 terminal
->condemn_scroll_bars_hook
= 0; /* Not needed. */
3100 terminal
->redeem_scroll_bar_hook
= 0; /* Not needed. */
3101 terminal
->judge_scroll_bars_hook
= 0; /* Not needed. */
3103 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3104 terminal
->frame_up_to_date_hook
= 0; /* Not needed. */
3106 terminal
->delete_frame_hook
= &delete_tty_output
;
3107 terminal
->delete_terminal_hook
= &delete_tty
;
3110 /* Drop the controlling terminal if fd is the same device. */
3112 dissociate_if_controlling_tty (int fd
)
3116 EMACS_GET_TTY_PGRP (fd
, &pgid
); /* If tcgetpgrp succeeds, fd is the ctty. */
3119 #if defined (USG) && !defined (BSD_PGRPS)
3121 no_controlling_tty
= 1;
3123 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3124 sigblock (sigmask (SIGTTOU
));
3125 fd
= emacs_open ("/dev/tty", O_RDWR
, 0);
3126 if (fd
!= -1 && ioctl (fd
, TIOCNOTTY
, 0) != -1)
3128 no_controlling_tty
= 1;
3132 sigunblock (sigmask (SIGTTOU
));
3134 /* Unknown system. */
3136 #endif /* ! TIOCNOTTY */
3142 static void maybe_fatal();
3144 /* Create a termcap display on the tty device with the given name and
3147 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3148 Otherwise NAME should be a path to the tty device file,
3151 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3153 If MUST_SUCCEED is true, then all errors are fatal. */
3156 init_tty (char *name
, char *terminal_type
, int must_succeed
)
3159 char **address
= &area
;
3160 char *buffer
= NULL
;
3161 int buffer_size
= 4096;
3162 register char *p
= NULL
;
3164 struct tty_display_info
*tty
= NULL
;
3165 struct terminal
*terminal
= NULL
;
3166 int ctty
= 0; /* 1 if asked to open controlling tty. */
3169 maybe_fatal (must_succeed
, 0, 0,
3170 "Unknown terminal type",
3171 "Unknown terminal type");
3176 if (!strcmp (name
, "/dev/tty"))
3179 /* If we already have a terminal on the given device, use that. If
3180 all such terminals are suspended, create a new one instead. */
3181 /* XXX Perhaps this should be made explicit by having init_tty
3182 always create a new terminal and separating terminal and frame
3183 creation on Lisp level. */
3184 terminal
= get_named_tty (name
);
3189 terminal
= create_terminal ();
3190 tty
= (struct tty_display_info
*) xmalloc (sizeof (struct tty_display_info
));
3191 bzero (tty
, sizeof (struct tty_display_info
));
3192 tty
->next
= tty_list
;
3195 terminal
->type
= output_termcap
;
3196 terminal
->display_info
.tty
= tty
;
3197 tty
->terminal
= terminal
;
3199 tty
->Wcm
= (struct cm
*) xmalloc (sizeof (struct cm
));
3203 set_tty_hooks (terminal
);
3209 #ifdef O_IGNORE_CTTY
3211 /* Open the terminal device. Don't recognize it as our
3212 controlling terminal, and don't make it the controlling tty
3213 if we don't have one at the moment. */
3214 fd
= emacs_open (name
, O_RDWR
| O_IGNORE_CTTY
| O_NOCTTY
, 0);
3217 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3218 defined on Hurd. On other systems, we need to explicitly
3219 dissociate ourselves from the controlling tty when we want to
3220 open a frame on the same terminal. */
3221 fd
= emacs_open (name
, O_RDWR
| O_NOCTTY
, 0);
3222 #endif /* O_IGNORE_CTTY */
3225 maybe_fatal (must_succeed
, buffer
, terminal
,
3226 "Could not open file: %s",
3227 "Could not open file: %s",
3232 maybe_fatal (must_succeed
, buffer
, terminal
,
3233 "Not a tty device: %s",
3234 "Not a tty device: %s",
3238 #ifndef O_IGNORE_CTTY
3240 dissociate_if_controlling_tty (fd
);
3243 file
= fdopen (fd
, "w+");
3244 tty
->name
= xstrdup (name
);
3245 terminal
->name
= xstrdup (name
);
3250 tty
->type
= xstrdup (terminal_type
);
3252 add_keyboard_wait_descriptor (fileno (tty
->input
));
3256 encode_terminal_bufsize
= 0;
3259 terminal
->mouse_position_hook
= term_mouse_position
;
3260 Qmouse_face_window
= Qnil
;
3264 initialize_w32_display ();
3266 /* XXX Can this be non-null? */
3269 tty
->name
= xstrdup (name
);
3270 terminal
->name
= xstrdup (name
);
3272 tty
->type
= xstrdup (terminal_type
);
3274 /* XXX not sure if this line is correct. If it is not set then we
3275 crash in update_display_1. */
3276 tty
->output
= stdout
;
3280 area
= (char *) xmalloc (2044); /* XXX this seems unused. */
3283 struct frame
*f
= XFRAME (selected_frame
);
3285 FrameRows (tty
) = FRAME_LINES (f
); /* XXX */
3286 FrameCols (tty
) = FRAME_COLS (f
); /* XXX */
3287 tty
->specified_window
= FRAME_LINES (f
); /* XXX */
3289 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0; /* XXX */
3290 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
; /* XXX */
3292 tty
->delete_in_insert_mode
= 1;
3295 terminal
->scroll_region_ok
= 0;
3297 /* Seems to insert lines when it's not supposed to, messing up the
3298 display. In doing a trace, it didn't seem to be called much, so I
3299 don't think we're losing anything by turning it off. */
3300 terminal
->line_ins_del_ok
= 0;
3301 terminal
->char_ins_del_ok
= 1;
3305 tty
->TN_max_colors
= 16; /* Required to be non-zero for tty-display-color-p */
3308 #else /* not WINDOWSNT */
3312 buffer
= (char *) xmalloc (buffer_size
);
3314 /* On some systems, tgetent tries to access the controlling
3316 sigblock (sigmask (SIGTTOU
));
3317 status
= tgetent (buffer
, terminal_type
);
3318 sigunblock (sigmask (SIGTTOU
));
3323 maybe_fatal (must_succeed
, buffer
, terminal
,
3324 "Cannot open terminfo database file",
3325 "Cannot open terminfo database file");
3327 maybe_fatal (must_succeed
, buffer
, terminal
,
3328 "Cannot open termcap database file",
3329 "Cannot open termcap database file");
3335 maybe_fatal (must_succeed
, buffer
, terminal
,
3336 "Terminal type %s is not defined",
3337 "Terminal type %s is not defined.\n\
3338 If that is not the actual type of terminal you have,\n\
3339 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3340 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3341 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3344 maybe_fatal (must_succeed
, buffer
, terminal
,
3345 "Terminal type %s is not defined",
3346 "Terminal type %s is not defined.\n\
3347 If that is not the actual type of terminal you have,\n\
3348 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3349 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3350 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3356 if (strlen (buffer
) >= buffer_size
)
3358 buffer_size
= strlen (buffer
);
3360 area
= (char *) xmalloc (buffer_size
);
3362 tty
->TS_ins_line
= tgetstr ("al", address
);
3363 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
3364 tty
->TS_bell
= tgetstr ("bl", address
);
3365 BackTab (tty
) = tgetstr ("bt", address
);
3366 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
3367 tty
->TS_clr_line
= tgetstr ("ce", address
);
3368 tty
->TS_clr_frame
= tgetstr ("cl", address
);
3369 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
3370 AbsPosition (tty
) = tgetstr ("cm", address
);
3371 CR (tty
) = tgetstr ("cr", address
);
3372 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
3373 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
3374 RowPosition (tty
) = tgetstr ("cv", address
);
3375 tty
->TS_del_char
= tgetstr ("dc", address
);
3376 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
3377 tty
->TS_del_line
= tgetstr ("dl", address
);
3378 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
3379 tty
->TS_delete_mode
= tgetstr ("dm", address
);
3380 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
3381 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
3382 Home (tty
) = tgetstr ("ho", address
);
3383 tty
->TS_ins_char
= tgetstr ("ic", address
);
3384 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
3385 tty
->TS_insert_mode
= tgetstr ("im", address
);
3386 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
3387 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
3388 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
3389 LastLine (tty
) = tgetstr ("ll", address
);
3390 Right (tty
) = tgetstr ("nd", address
);
3391 Down (tty
) = tgetstr ("do", address
);
3393 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do" */
3395 /* VMS puts a carriage return before each linefeed,
3396 so it is not safe to use linefeeds. */
3397 if (Down (tty
) && Down (tty
)[0] == '\n' && Down (tty
)[1] == '\0')
3400 if (tgetflag ("bs"))
3401 Left (tty
) = "\b"; /* can't possibly be longer! */
3402 else /* (Actually, "bs" is obsolete...) */
3403 Left (tty
) = tgetstr ("le", address
);
3405 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le" */
3406 tty
->TS_pad_char
= tgetstr ("pc", address
);
3407 tty
->TS_repeat
= tgetstr ("rp", address
);
3408 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
3409 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
3410 tty
->TS_standout_mode
= tgetstr ("so", address
);
3411 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
3412 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
3413 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
3414 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
3415 Up (tty
) = tgetstr ("up", address
);
3416 tty
->TS_visible_bell
= tgetstr ("vb", address
);
3417 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
3418 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
3419 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
3420 tty
->TS_set_window
= tgetstr ("wi", address
);
3422 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
3423 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
3424 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
3425 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
3426 tty
->TS_enter_blink_mode
= tgetstr ("mb", address
);
3427 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
3428 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
3429 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
3430 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
3432 MultiUp (tty
) = tgetstr ("UP", address
);
3433 MultiDown (tty
) = tgetstr ("DO", address
);
3434 MultiLeft (tty
) = tgetstr ("LE", address
);
3435 MultiRight (tty
) = tgetstr ("RI", address
);
3437 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3438 color because we can't switch back to the default foreground and
3440 tty
->TS_orig_pair
= tgetstr ("op", address
);
3441 if (tty
->TS_orig_pair
)
3443 tty
->TS_set_foreground
= tgetstr ("AF", address
);
3444 tty
->TS_set_background
= tgetstr ("AB", address
);
3445 if (!tty
->TS_set_foreground
)
3448 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
3449 tty
->TS_set_background
= tgetstr ("Sb", address
);
3452 tty
->TN_max_colors
= tgetnum ("Co");
3453 tty
->TN_max_pairs
= tgetnum ("pa");
3455 tty
->TN_no_color_video
= tgetnum ("NC");
3456 if (tty
->TN_no_color_video
== -1)
3457 tty
->TN_no_color_video
= 0;
3460 tty_default_color_capabilities (tty
, 1);
3462 MagicWrap (tty
) = tgetflag ("xn");
3463 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3464 the former flag imply the latter. */
3465 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
3466 terminal
->memory_below_frame
= tgetflag ("db");
3467 tty
->TF_hazeltine
= tgetflag ("hz");
3468 terminal
->must_write_spaces
= tgetflag ("in");
3469 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
3470 tty
->TF_insmode_motion
= tgetflag ("mi");
3471 tty
->TF_standout_motion
= tgetflag ("ms");
3472 tty
->TF_underscore
= tgetflag ("ul");
3473 tty
->TF_teleray
= tgetflag ("xt");
3476 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
3477 init_kboard (terminal
->kboard
);
3478 terminal
->kboard
->next_kboard
= all_kboards
;
3479 all_kboards
= terminal
->kboard
;
3480 terminal
->kboard
->reference_count
++;
3481 /* Don't let the initial kboard remain current longer than necessary.
3482 That would cause problems if a file loaded on startup tries to
3483 prompt in the mini-buffer. */
3484 if (current_kboard
== initial_kboard
)
3485 current_kboard
= terminal
->kboard
;
3486 term_get_fkeys (address
, terminal
->kboard
);
3489 /* Get frame size from system, or else from termcap. */
3492 get_tty_size (fileno (tty
->input
), &width
, &height
);
3493 FrameCols (tty
) = width
;
3494 FrameRows (tty
) = height
;
3497 if (FrameCols (tty
) <= 0)
3498 FrameCols (tty
) = tgetnum ("co");
3499 if (FrameRows (tty
) <= 0)
3500 FrameRows (tty
) = tgetnum ("li");
3502 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
3503 maybe_fatal (must_succeed
, NULL
, terminal
,
3504 "Screen size %dx%d is too small"
3505 "Screen size %dx%d is too small",
3506 FrameCols (tty
), FrameRows (tty
));
3508 #if 0 /* This is not used anywhere. */
3509 tty
->terminal
->min_padding_speed
= tgetnum ("pb");
3512 TabWidth (tty
) = tgetnum ("tw");
3515 /* These capabilities commonly use ^J.
3516 I don't know why, but sending them on VMS does not work;
3517 it causes following spaces to be lost, sometimes.
3518 For now, the simplest fix is to avoid using these capabilities ever. */
3519 if (Down (tty
) && Down (tty
)[0] == '\n')
3524 tty
->TS_bell
= "\07";
3526 if (!tty
->TS_fwd_scroll
)
3527 tty
->TS_fwd_scroll
= Down (tty
);
3529 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
3531 if (TabWidth (tty
) < 0)
3534 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3535 and newer termcap doc does not seem to say there is a default.
3536 if (!tty->Wcm->cm_tab)
3537 tty->Wcm->cm_tab = "\t";
3540 /* We don't support standout modes that use `magic cookies', so
3541 turn off any that do. */
3542 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
3544 tty
->TS_standout_mode
= 0;
3545 tty
->TS_end_standout_mode
= 0;
3547 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
3549 tty
->TS_enter_underline_mode
= 0;
3550 tty
->TS_exit_underline_mode
= 0;
3553 /* If there's no standout mode, try to use underlining instead. */
3554 if (tty
->TS_standout_mode
== 0)
3556 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
3557 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
3560 /* If no `se' string, try using a `me' string instead.
3561 If that fails, we can't use standout mode at all. */
3562 if (tty
->TS_end_standout_mode
== 0)
3564 char *s
= tgetstr ("me", address
);
3566 tty
->TS_end_standout_mode
= s
;
3568 tty
->TS_standout_mode
= 0;
3571 if (tty
->TF_teleray
)
3573 tty
->Wcm
->cm_tab
= 0;
3574 /* We can't support standout mode, because it uses magic cookies. */
3575 tty
->TS_standout_mode
= 0;
3576 /* But that means we cannot rely on ^M to go to column zero! */
3578 /* LF can't be trusted either -- can alter hpos */
3579 /* if move at column 0 thru a line with TS_standout_mode */
3583 /* Special handling for certain terminal types known to need it */
3585 if (!strcmp (terminal_type
, "supdup"))
3587 terminal
->memory_below_frame
= 1;
3588 tty
->Wcm
->cm_losewrap
= 1;
3590 if (!strncmp (terminal_type
, "c10", 3)
3591 || !strcmp (terminal_type
, "perq"))
3593 /* Supply a makeshift :wi string.
3594 This string is not valid in general since it works only
3595 for windows starting at the upper left corner;
3596 but that is all Emacs uses.
3598 This string works only if the frame is using
3599 the top of the video memory, because addressing is memory-relative.
3600 So first check the :ti string to see if that is true.
3602 It would be simpler if the :wi string could go in the termcap
3603 entry, but it can't because it is not fully valid.
3604 If it were in the termcap entry, it would confuse other programs. */
3605 if (!tty
->TS_set_window
)
3607 p
= tty
->TS_termcap_modes
;
3608 while (*p
&& strcmp (p
, "\033v "))
3611 tty
->TS_set_window
= "\033v%C %C %C %C ";
3613 /* Termcap entry often fails to have :in: flag */
3614 terminal
->must_write_spaces
= 1;
3615 /* :ti string typically fails to have \E^G! in it */
3616 /* This limits scope of insert-char to one line. */
3617 strcpy (area
, tty
->TS_termcap_modes
);
3618 strcat (area
, "\033\007!");
3619 tty
->TS_termcap_modes
= area
;
3620 area
+= strlen (area
) + 1;
3621 p
= AbsPosition (tty
);
3622 /* Change all %+ parameters to %C, to handle
3623 values above 96 correctly for the C100. */
3626 if (p
[0] == '%' && p
[1] == '+')
3632 tty
->specified_window
= FrameRows (tty
);
3634 if (Wcm_init (tty
) == -1) /* can't do cursor motion */
3636 maybe_fatal (must_succeed
, NULL
, terminal
,
3637 "Terminal type \"%s\" is not powerful enough to run Emacs",
3639 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3640 It lacks the ability to position the cursor.\n\
3641 If that is not the actual type of terminal you have, use either the\n\
3642 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
3643 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
3646 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3647 It lacks the ability to position the cursor.\n\
3648 If that is not the actual type of terminal you have,\n\
3649 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3650 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3651 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3652 # else /* TERMCAP */
3653 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3654 It lacks the ability to position the cursor.\n\
3655 If that is not the actual type of terminal you have,\n\
3656 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3657 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3658 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3659 # endif /* TERMINFO */
3664 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
3665 maybe_fatal (must_succeed
, NULL
, terminal
,
3666 "Could not determine the frame size",
3667 "Could not determine the frame size");
3669 tty
->delete_in_insert_mode
3670 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
3671 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
3673 tty
->se_is_so
= (tty
->TS_standout_mode
3674 && tty
->TS_end_standout_mode
3675 && !strcmp (tty
->TS_standout_mode
, tty
->TS_end_standout_mode
));
3677 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
3679 terminal
->scroll_region_ok
3681 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
3683 terminal
->line_ins_del_ok
3684 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
3685 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
3686 || (terminal
->scroll_region_ok
3687 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
3689 terminal
->char_ins_del_ok
3690 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
3691 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
3692 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
3694 terminal
->fast_clear_end_of_line
= tty
->TS_clr_line
!= 0;
3696 init_baud_rate (fileno (tty
->input
));
3699 /* The HFT system on AIX doesn't optimize for scrolling, so it's
3700 really ugly at times. */
3701 terminal
->line_ins_del_ok
= 0;
3702 terminal
->char_ins_del_ok
= 0;
3705 /* Don't do this. I think termcap may still need the buffer. */
3706 /* xfree (buffer); */
3708 /* Init system terminal modes (RAW or CBREAK, etc.). */
3709 init_sys_modes (tty
);
3712 #endif /* not WINDOWSNT */
3715 /* Auxiliary error-handling function for init_tty.
3716 Free BUFFER and delete TERMINAL, then call error or fatal
3717 with str1 or str2, respectively, according to MUST_SUCCEED. */
3720 maybe_fatal (must_succeed
, buffer
, terminal
, str1
, str2
, arg1
, arg2
)
3723 struct terminal
*terminal
;
3724 char *str1
, *str2
, *arg1
, *arg2
;
3730 delete_tty (terminal
);
3733 fatal (str2
, arg1
, arg2
);
3735 error (str1
, arg1
, arg2
);
3742 fatal (str
, arg1
, arg2
)
3743 char *str
, *arg1
, *arg2
;
3745 fprintf (stderr
, "emacs: ");
3746 fprintf (stderr
, str
, arg1
, arg2
);
3747 fprintf (stderr
, "\n");
3754 /* Delete the given tty terminal, closing all frames on it. */
3757 delete_tty (struct terminal
*terminal
)
3759 struct tty_display_info
*tty
;
3760 Lisp_Object tail
, frame
;
3763 /* Protect against recursive calls. Fdelete_frame in
3764 delete_terminal calls us back when it deletes our last frame. */
3765 if (terminal
->deleted
)
3768 if (terminal
->type
!= output_termcap
)
3771 tty
= terminal
->display_info
.tty
;
3774 FOR_EACH_FRAME (tail
, frame
)
3776 struct frame
*f
= XFRAME (frame
);
3777 if (FRAME_LIVE_P (f
) && (!FRAME_TERMCAP_P (f
) || FRAME_TTY (f
) != tty
))
3784 error ("Attempt to delete the sole terminal device with live frames");
3786 if (tty
== tty_list
)
3787 tty_list
= tty
->next
;
3790 struct tty_display_info
*p
;
3791 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
3795 /* This should not happen. */
3798 p
->next
= tty
->next
;
3802 /* reset_sys_modes needs a valid device, so this call needs to be
3803 before delete_terminal. */
3804 reset_sys_modes (tty
);
3806 delete_terminal (terminal
);
3816 delete_keyboard_wait_descriptor (fileno (tty
->input
));
3817 if (tty
->input
!= stdin
)
3818 fclose (tty
->input
);
3820 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
3821 fclose (tty
->output
);
3822 if (tty
->termscript
)
3823 fclose (tty
->termscript
);
3826 xfree (tty
->old_tty
);
3831 bzero (tty
, sizeof (struct tty_display_info
));
3837 /* Mark the pointers in the tty_display_info objects.
3838 Called by the Fgarbage_collector. */
3843 struct tty_display_info
*tty
;
3845 for (tty
= tty_list
; tty
; tty
= tty
->next
)
3848 mark_object (tty
->top_frame
);
3857 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
3858 doc
: /* Non-nil means the system uses terminfo rather than termcap.
3859 This variable can be used by terminal emulator packages. */);
3861 system_uses_terminfo
= 1;
3863 system_uses_terminfo
= 0;
3866 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions
,
3867 doc
: /* Functions to be run after suspending a tty.
3868 The functions are run with one argument, the terminal id to be suspended.
3869 See `suspend-tty'. */);
3870 Vsuspend_tty_functions
= Qnil
;
3873 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions
,
3874 doc
: /* Functions to be run after resuming a tty.
3875 The functions are run with one argument, the terminal id that was revived.
3876 See `resume-tty'. */);
3877 Vresume_tty_functions
= Qnil
;
3879 DEFVAR_BOOL ("visible-cursor", &visible_cursor
,
3880 doc
: /* Non-nil means to make the cursor very visible.
3881 This only has an effect when running in a text terminal.
3882 What means \"very visible\" is up to your terminal. It may make the cursor
3883 bigger, or it may make it blink, or it may do nothing at all. */);
3886 defsubr (&Stty_display_color_p
);
3887 defsubr (&Stty_display_color_cells
);
3888 defsubr (&Stty_no_underline
);
3889 defsubr (&Stty_type
);
3890 defsubr (&Scontrolling_tty_p
);
3891 defsubr (&Ssuspend_tty
);
3892 defsubr (&Sresume_tty
);
3894 defsubr (&Sterm_open_connection
);
3895 defsubr (&Sterm_close_connection
);
3897 staticpro (&Qmouse_face_window
);
3898 #endif /* HAVE_GPM */
3903 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3904 (do not change this comment) */