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