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