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