(tty_cursor_hidden): New variable.
[bpt/emacs.git] / src / term.c
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001
3 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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, 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 #include "termchar.h"
29 #include "termopts.h"
30 #include "lisp.h"
31 #include "charset.h"
32 #include "coding.h"
33 #include "keyboard.h"
34 #include "frame.h"
35 #include "disptab.h"
36 #include "termhooks.h"
37 #include "dispextern.h"
38 #include "window.h"
39
40 /* For now, don't try to include termcap.h. On some systems,
41 configure finds a non-standard termcap.h that the main build
42 won't find. */
43
44 #if defined HAVE_TERMCAP_H && 0
45 #include <termcap.h>
46 #else
47 extern void tputs P_ ((const char *, int, int (*)(int)));
48 extern int tgetent P_ ((char *, const char *));
49 extern int tgetflag P_ ((char *id));
50 extern int tgetnum P_ ((char *id));
51 #endif
52
53 #include "cm.h"
54 #ifdef HAVE_X_WINDOWS
55 #include "xterm.h"
56 #endif
57 #ifdef macintosh
58 #include "macterm.h"
59 #endif
60
61 static void turn_on_face P_ ((struct frame *, int face_id));
62 static void turn_off_face P_ ((struct frame *, int face_id));
63 static void tty_show_cursor P_ ((void));
64 static void tty_hide_cursor P_ ((void));
65
66 #define max(a, b) ((a) > (b) ? (a) : (b))
67 #define min(a, b) ((a) < (b) ? (a) : (b))
68
69 #define OUTPUT(a) \
70 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
71 #define OUTPUT1(a) tputs (a, 1, cmputc)
72 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
73
74 #define OUTPUT_IF(a) \
75 do { \
76 if (a) \
77 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) \
78 - curY), cmputc); \
79 } while (0)
80
81 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
82
83 /* Function to use to ring the bell. */
84
85 Lisp_Object Vring_bell_function;
86
87 /* Terminal characteristics that higher levels want to look at.
88 These are all extern'd in termchar.h */
89
90 int must_write_spaces; /* Nonzero means spaces in the text
91 must actually be output; can't just skip
92 over some columns to leave them blank. */
93 int min_padding_speed; /* Speed below which no padding necessary */
94
95 int line_ins_del_ok; /* Terminal can insert and delete lines */
96 int char_ins_del_ok; /* Terminal can insert and delete chars */
97 int scroll_region_ok; /* Terminal supports setting the
98 scroll window */
99 int scroll_region_cost; /* Cost of setting a scroll window,
100 measured in characters */
101 int memory_below_frame; /* Terminal remembers lines
102 scrolled off bottom */
103 int fast_clear_end_of_line; /* Terminal has a `ce' string */
104
105 /* Nonzero means no need to redraw the entire frame on resuming
106 a suspended Emacs. This is useful on terminals with multiple pages,
107 where one page is used for Emacs and another for all else. */
108
109 int no_redraw_on_reenter;
110
111 /* Hook functions that you can set to snap out the functions in this file.
112 These are all extern'd in termhooks.h */
113
114 void (*cursor_to_hook) P_ ((int, int));
115 void (*raw_cursor_to_hook) P_ ((int, int));
116 void (*clear_to_end_hook) P_ ((void));
117 void (*clear_frame_hook) P_ ((void));
118 void (*clear_end_of_line_hook) P_ ((int));
119
120 void (*ins_del_lines_hook) P_ ((int, int));
121
122 void (*change_line_highlight_hook) P_ ((int, int, int, int));
123 void (*reassert_line_highlight_hook) P_ ((int, int));
124
125 void (*delete_glyphs_hook) P_ ((int));
126
127 void (*ring_bell_hook) P_ ((void));
128
129 void (*reset_terminal_modes_hook) P_ ((void));
130 void (*set_terminal_modes_hook) P_ ((void));
131 void (*update_begin_hook) P_ ((struct frame *));
132 void (*update_end_hook) P_ ((struct frame *));
133 void (*set_terminal_window_hook) P_ ((int));
134 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
135 void (*write_glyphs_hook) P_ ((struct glyph *, int));
136 void (*delete_glyphs_hook) P_ ((int));
137
138 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
139
140 void (*frame_up_to_date_hook) P_ ((struct frame *));
141
142 /* Return the current position of the mouse.
143
144 Set *f to the frame the mouse is in, or zero if the mouse is in no
145 Emacs frame. If it is set to zero, all the other arguments are
146 garbage.
147
148 If the motion started in a scroll bar, set *bar_window to the
149 scroll bar's window, *part to the part the mouse is currently over,
150 *x to the position of the mouse along the scroll bar, and *y to the
151 overall length of the scroll bar.
152
153 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
154 row of the character cell the mouse is over.
155
156 Set *time to the time the mouse was at the returned position.
157
158 This should clear mouse_moved until the next motion
159 event arrives. */
160
161 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
162 Lisp_Object *bar_window,
163 enum scroll_bar_part *part,
164 Lisp_Object *x,
165 Lisp_Object *y,
166 unsigned long *time));
167
168 /* When reading from a minibuffer in a different frame, Emacs wants
169 to shift the highlight from the selected frame to the mini-buffer's
170 frame; under X, this means it lies about where the focus is.
171 This hook tells the window system code to re-decide where to put
172 the highlight. */
173
174 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
175
176 /* If we're displaying frames using a window system that can stack
177 frames on top of each other, this hook allows you to bring a frame
178 to the front, or bury it behind all the other windows. If this
179 hook is zero, that means the device we're displaying on doesn't
180 support overlapping frames, so there's no need to raise or lower
181 anything.
182
183 If RAISE is non-zero, F is brought to the front, before all other
184 windows. If RAISE is zero, F is sent to the back, behind all other
185 windows. */
186
187 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
188
189 /* Set the vertical scroll bar for WINDOW to have its upper left corner
190 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
191 indicate that we are displaying PORTION characters out of a total
192 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
193 have a scroll bar, create one for it. */
194
195 void (*set_vertical_scroll_bar_hook)
196 P_ ((struct window *window,
197 int portion, int whole, int position));
198
199
200 /* The following three hooks are used when we're doing a thorough
201 redisplay of the frame. We don't explicitly know which scroll bars
202 are going to be deleted, because keeping track of when windows go
203 away is a real pain - can you say set-window-configuration?
204 Instead, we just assert at the beginning of redisplay that *all*
205 scroll bars are to be removed, and then save scroll bars from the
206 fiery pit when we actually redisplay their window. */
207
208 /* Arrange for all scroll bars on FRAME to be removed at the next call
209 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
210 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
211
212 This should be applied to each frame each time its window tree is
213 redisplayed, even if it is not displaying scroll bars at the moment;
214 if the HAS_SCROLL_BARS flag has just been turned off, only calling
215 this and the judge_scroll_bars_hook will get rid of them.
216
217 If non-zero, this hook should be safe to apply to any frame,
218 whether or not it can support scroll bars, and whether or not it is
219 currently displaying them. */
220
221 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
222
223 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
224 Note that it's okay to redeem a scroll bar that is not condemned. */
225
226 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
227
228 /* Remove all scroll bars on FRAME that haven't been saved since the
229 last call to `*condemn_scroll_bars_hook'.
230
231 This should be applied to each frame after each time its window
232 tree is redisplayed, even if it is not displaying scroll bars at the
233 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
234 calling this and condemn_scroll_bars_hook will get rid of them.
235
236 If non-zero, this hook should be safe to apply to any frame,
237 whether or not it can support scroll bars, and whether or not it is
238 currently displaying them. */
239
240 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
241
242 /* Hook to call in estimate_mode_line_height, if any. */
243
244 int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
245
246
247 /* Strings, numbers and flags taken from the termcap entry. */
248
249 char *TS_ins_line; /* "al" */
250 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
251 char *TS_bell; /* "bl" */
252 char *TS_clr_to_bottom; /* "cd" */
253 char *TS_clr_line; /* "ce", clear to end of line */
254 char *TS_clr_frame; /* "cl" */
255 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
256 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
257 lines above scroll region, lines below it,
258 total lines again) */
259 char *TS_del_char; /* "dc" */
260 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
261 char *TS_del_line; /* "dl" */
262 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
263 char *TS_delete_mode; /* "dm", enter character-delete mode */
264 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
265 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
266 char *TS_ins_char; /* "ic" */
267 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
268 char *TS_insert_mode; /* "im", enter character-insert mode */
269 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
270 char *TS_end_keypad_mode; /* "ke" */
271 char *TS_keypad_mode; /* "ks" */
272 char *TS_pad_char; /* "pc", char to use as padding */
273 char *TS_repeat; /* "rp" (2 params, # times to repeat
274 and character to be repeated) */
275 char *TS_end_standout_mode; /* "se" */
276 char *TS_fwd_scroll; /* "sf" */
277 char *TS_standout_mode; /* "so" */
278 char *TS_rev_scroll; /* "sr" */
279 char *TS_end_termcap_modes; /* "te" */
280 char *TS_termcap_modes; /* "ti" */
281 char *TS_visible_bell; /* "vb" */
282 char *TS_cursor_normal; /* "ve" */
283 char *TS_cursor_visible; /* "vs" */
284 char *TS_cursor_invisible; /* "vi" */
285 char *TS_set_window; /* "wi" (4 params, start and end of window,
286 each as vpos and hpos) */
287
288 /* Value of the "NC" (no_color_video) capability, or 0 if not
289 present. */
290
291 static int TN_no_color_video;
292
293 /* Meaning of bits in no_color_video. Each bit set means that the
294 corresponding attribute cannot be combined with colors. */
295
296 enum no_color_bit
297 {
298 NC_STANDOUT = 1 << 0,
299 NC_UNDERLINE = 1 << 1,
300 NC_REVERSE = 1 << 2,
301 NC_BLINK = 1 << 3,
302 NC_DIM = 1 << 4,
303 NC_BOLD = 1 << 5,
304 NC_INVIS = 1 << 6,
305 NC_PROTECT = 1 << 7,
306 NC_ALT_CHARSET = 1 << 8
307 };
308
309 /* "md" -- turn on bold (extra bright mode). */
310
311 char *TS_enter_bold_mode;
312
313 /* "mh" -- turn on half-bright mode. */
314
315 char *TS_enter_dim_mode;
316
317 /* "mb" -- enter blinking mode. */
318
319 char *TS_enter_blink_mode;
320
321 /* "mr" -- enter reverse video mode. */
322
323 char *TS_enter_reverse_mode;
324
325 /* "us"/"ue" -- start/end underlining. */
326
327 char *TS_exit_underline_mode, *TS_enter_underline_mode;
328
329 /* "ug" -- number of blanks left by underline. */
330
331 int TN_magic_cookie_glitch_ul;
332
333 /* "as"/"ae" -- start/end alternate character set. Not really
334 supported, yet. */
335
336 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
337
338 /* "me" -- switch appearances off. */
339
340 char *TS_exit_attribute_mode;
341
342 /* "Co" -- number of colors. */
343
344 int TN_max_colors;
345
346 /* "pa" -- max. number of color pairs on screen. Not handled yet.
347 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
348
349 int TN_max_pairs;
350
351 /* "op" -- SVr4 set default pair to its original value. */
352
353 char *TS_orig_pair;
354
355 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
356 1 param, the color index. */
357
358 char *TS_set_foreground, *TS_set_background;
359
360 int TF_hazeltine; /* termcap hz flag. */
361 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
362 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
363 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
364 non-blank position. Must clear before writing _. */
365 int TF_teleray; /* termcap xt flag: many weird consequences.
366 For t1061. */
367
368 int TF_xs; /* Nonzero for "xs". If set together with
369 TN_standout_width == 0, it means don't bother
370 to write any end-standout cookies. */
371
372 int TN_standout_width; /* termcap sg number: width occupied by standout
373 markers */
374
375 static int RPov; /* # chars to start a TS_repeat */
376
377 static int delete_in_insert_mode; /* delete mode == insert mode */
378
379 static int se_is_so; /* 1 if same string both enters and leaves
380 standout mode */
381
382 /* internal state */
383
384 /* The largest frame width in any call to calculate_costs. */
385
386 int max_frame_width;
387
388 /* The largest frame height in any call to calculate_costs. */
389
390 int max_frame_height;
391
392 /* Number of chars of space used for standout marker at beginning of line,
393 or'd with 0100. Zero if no standout marker at all.
394 The length of these vectors is max_frame_height.
395
396 Used IFF TN_standout_width >= 0. */
397
398 static char *chars_wasted;
399 static char *copybuf;
400
401 /* nonzero means supposed to write text in standout mode. */
402
403 int standout_requested;
404
405 int insert_mode; /* Nonzero when in insert mode. */
406 int standout_mode; /* Nonzero when in standout mode. */
407
408 /* Size of window specified by higher levels.
409 This is the number of lines, from the top of frame downwards,
410 which can participate in insert-line/delete-line operations.
411
412 Effectively it excludes the bottom frame_height - specified_window_size
413 lines from those operations. */
414
415 int specified_window;
416
417 /* Frame currently being redisplayed; 0 if not currently redisplaying.
418 (Direct output does not count). */
419
420 FRAME_PTR updating_frame;
421
422 /* Provided for lisp packages. */
423
424 static int system_uses_terminfo;
425
426 /* Flag used in tty_show/hide_cursor. */
427
428 static int tty_cursor_hidden;
429
430 char *tparam ();
431
432 extern char *tgetstr ();
433 \f
434
435 #ifdef WINDOWSNT
436 /* We aren't X windows, but we aren't termcap either. This makes me
437 uncertain as to what value to use for frame.output_method. For
438 this file, we'll define FRAME_TERMCAP_P to be zero so that our
439 output hooks get called instead of the termcap functions. Probably
440 the best long-term solution is to define an output_windows_nt... */
441
442 #undef FRAME_TERMCAP_P
443 #define FRAME_TERMCAP_P(_f_) 0
444 #endif /* WINDOWSNT */
445
446 void
447 ring_bell ()
448 {
449 if (!NILP (Vring_bell_function))
450 {
451 Lisp_Object function;
452
453 /* Temporarily set the global variable to nil
454 so that if we get an error, it stays nil
455 and we don't call it over and over.
456
457 We don't specbind it, because that would carefully
458 restore the bad value if there's an error
459 and make the loop of errors happen anyway. */
460
461 function = Vring_bell_function;
462 Vring_bell_function = Qnil;
463
464 call0 (function);
465
466 Vring_bell_function = function;
467 }
468 else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
469 (*ring_bell_hook) ();
470 else
471 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
472 }
473
474 void
475 set_terminal_modes ()
476 {
477 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
478 {
479 OUTPUT_IF (TS_termcap_modes);
480 OUTPUT_IF (TS_cursor_visible);
481 OUTPUT_IF (TS_keypad_mode);
482 losecursor ();
483 }
484 else
485 (*set_terminal_modes_hook) ();
486 }
487
488 void
489 reset_terminal_modes ()
490 {
491 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
492 {
493 if (TN_standout_width < 0)
494 turn_off_highlight ();
495 turn_off_insert ();
496 OUTPUT_IF (TS_end_keypad_mode);
497 OUTPUT_IF (TS_cursor_normal);
498 OUTPUT_IF (TS_end_termcap_modes);
499 OUTPUT_IF (TS_orig_pair);
500 /* Output raw CR so kernel can track the cursor hpos. */
501 /* But on magic-cookie terminals this can erase an end-standout
502 marker and cause the rest of the frame to be in standout, so
503 move down first. */
504 if (TN_standout_width >= 0)
505 cmputc ('\n');
506 cmputc ('\r');
507 }
508 else if (reset_terminal_modes_hook)
509 (*reset_terminal_modes_hook) ();
510 }
511
512 void
513 update_begin (f)
514 struct frame *f;
515 {
516 updating_frame = f;
517 if (!FRAME_TERMCAP_P (f))
518 update_begin_hook (f);
519 }
520
521 void
522 update_end (f)
523 struct frame *f;
524 {
525 if (FRAME_TERMCAP_P (f))
526 {
527 if (!XWINDOW (selected_window)->cursor_off_p)
528 tty_show_cursor ();
529 turn_off_insert ();
530 background_highlight ();
531 standout_requested = 0;
532 }
533 else
534 update_end_hook (f);
535
536 updating_frame = NULL;
537 }
538
539 void
540 set_terminal_window (size)
541 int size;
542 {
543 if (FRAME_TERMCAP_P (updating_frame))
544 {
545 specified_window = size ? size : FRAME_HEIGHT (updating_frame);
546 if (scroll_region_ok)
547 set_scroll_region (0, specified_window);
548 }
549 else
550 set_terminal_window_hook (size);
551 }
552
553 void
554 set_scroll_region (start, stop)
555 int start, stop;
556 {
557 char *buf;
558 struct frame *sf = XFRAME (selected_frame);
559
560 if (TS_set_scroll_region)
561 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
562 else if (TS_set_scroll_region_1)
563 buf = tparam (TS_set_scroll_region_1, 0, 0,
564 FRAME_HEIGHT (sf), start,
565 FRAME_HEIGHT (sf) - stop,
566 FRAME_HEIGHT (sf));
567 else
568 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
569
570 OUTPUT (buf);
571 xfree (buf);
572 losecursor ();
573 }
574
575 \f
576 static void
577 turn_on_insert ()
578 {
579 if (!insert_mode)
580 OUTPUT (TS_insert_mode);
581 insert_mode = 1;
582 }
583
584 void
585 turn_off_insert ()
586 {
587 if (insert_mode)
588 OUTPUT (TS_end_insert_mode);
589 insert_mode = 0;
590 }
591 \f
592 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
593 In these terminals, output is affected by the value of standout
594 mode when the output is written.
595
596 These functions are called on all terminals, but do nothing
597 on terminals whose standout mode does not work that way. */
598
599 void
600 turn_off_highlight ()
601 {
602 if (TN_standout_width < 0)
603 {
604 if (standout_mode)
605 OUTPUT_IF (TS_end_standout_mode);
606 standout_mode = 0;
607 }
608 }
609
610 static void
611 turn_on_highlight ()
612 {
613 if (TN_standout_width < 0)
614 {
615 if (!standout_mode)
616 OUTPUT_IF (TS_standout_mode);
617 standout_mode = 1;
618 }
619 }
620
621 static void
622 toggle_highlight ()
623 {
624 if (standout_mode)
625 turn_off_highlight ();
626 else
627 turn_on_highlight ();
628 }
629
630
631 /* Make cursor invisible. */
632
633 static void
634 tty_hide_cursor ()
635 {
636 if (tty_cursor_hidden == 0)
637 {
638 tty_cursor_hidden = 1;
639 OUTPUT_IF (TS_cursor_invisible);
640 }
641 }
642
643
644 /* Ensure that cursor is visible. */
645
646 static void
647 tty_show_cursor ()
648 {
649 if (tty_cursor_hidden)
650 {
651 tty_cursor_hidden = 0;
652 OUTPUT_IF (TS_cursor_normal);
653 OUTPUT_IF (TS_cursor_visible);
654 }
655 }
656
657
658 /* Set standout mode to the state it should be in for
659 empty space inside windows. What this is,
660 depends on the user option inverse-video. */
661
662 void
663 background_highlight ()
664 {
665 if (TN_standout_width >= 0)
666 return;
667 if (inverse_video)
668 turn_on_highlight ();
669 else
670 turn_off_highlight ();
671 }
672
673 /* Set standout mode to the mode specified for the text to be output. */
674
675 static void
676 highlight_if_desired ()
677 {
678 if (TN_standout_width >= 0)
679 return;
680 if (!inverse_video == !standout_requested)
681 turn_off_highlight ();
682 else
683 turn_on_highlight ();
684 }
685 \f
686 /* Handle standout mode for terminals in which TN_standout_width >= 0.
687 On these terminals, standout is controlled by markers that
688 live inside the terminal's memory. TN_standout_width is the width
689 that the marker occupies in memory. Standout runs from the marker
690 to the end of the line on some terminals, or to the next
691 turn-off-standout marker (TS_end_standout_mode) string
692 on other terminals. */
693
694 /* Write a standout marker or end-standout marker at the front of the line
695 at vertical position vpos. */
696
697 static void
698 write_standout_marker (flag, vpos)
699 int flag, vpos;
700 {
701 if (flag
702 || (TS_end_standout_mode && !TF_teleray && !se_is_so
703 && !(TF_xs && TN_standout_width == 0)))
704 {
705 cmgoto (vpos, 0);
706 cmplus (TN_standout_width);
707 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
708 chars_wasted[curY] = TN_standout_width | 0100;
709 }
710 }
711 \f
712 /* External interface to control of standout mode.
713 Call this when about to modify line at position VPOS
714 and not change whether it is highlighted. */
715
716 void
717 reassert_line_highlight (highlight, vpos)
718 int highlight;
719 int vpos;
720 {
721 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
722 if (! FRAME_TERMCAP_P (f))
723 {
724 (*reassert_line_highlight_hook) (highlight, vpos);
725 return;
726 }
727 if (TN_standout_width < 0)
728 /* Handle terminals where standout takes affect at output time */
729 standout_requested = highlight;
730 else if (chars_wasted && chars_wasted[vpos] == 0)
731 /* For terminals with standout markers, write one on this line
732 if there isn't one already. */
733 write_standout_marker (inverse_video ? !highlight : highlight, vpos);
734 }
735
736 /* Call this when about to modify line at position VPOS
737 and change whether it is highlighted. */
738
739 void
740 change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
741 int new_highlight, vpos, y, first_unused_hpos;
742 {
743 standout_requested = new_highlight;
744 if (! FRAME_TERMCAP_P (updating_frame))
745 {
746 (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
747 return;
748 }
749
750 cursor_to (vpos, 0);
751
752 if (TN_standout_width < 0)
753 background_highlight ();
754 /* If line starts with a marker, delete the marker */
755 else if (TS_clr_line && chars_wasted[curY])
756 {
757 turn_off_insert ();
758 /* On Teleray, make sure to erase the SO marker. */
759 if (TF_teleray)
760 {
761 cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4);
762 OUTPUT ("\033S");
763 curY++; /* ESC S moves to next line where the TS_standout_mode was */
764 curX = 0;
765 }
766 else
767 cmgoto (curY, 0); /* reposition to kill standout marker */
768 }
769 clear_end_of_line_raw (first_unused_hpos);
770 reassert_line_highlight (new_highlight, curY);
771 }
772 \f
773
774 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
775 frame-relative coordinates. */
776
777 void
778 cursor_to (vpos, hpos)
779 int vpos, hpos;
780 {
781 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
782
783 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
784 {
785 (*cursor_to_hook) (vpos, hpos);
786 return;
787 }
788
789 /* Detect the case where we are called from reset_sys_modes
790 and the costs have never been calculated. Do nothing. */
791 if (chars_wasted == 0)
792 return;
793
794 hpos += chars_wasted[vpos] & 077;
795 if (curY == vpos && curX == hpos)
796 return;
797 if (!TF_standout_motion)
798 background_highlight ();
799 if (!TF_insmode_motion)
800 turn_off_insert ();
801 cmgoto (vpos, hpos);
802 }
803
804 /* Similar but don't take any account of the wasted characters. */
805
806 void
807 raw_cursor_to (row, col)
808 int row, col;
809 {
810 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
811 if (! FRAME_TERMCAP_P (f))
812 {
813 (*raw_cursor_to_hook) (row, col);
814 return;
815 }
816 if (curY == row && curX == col)
817 return;
818 if (!TF_standout_motion)
819 background_highlight ();
820 if (!TF_insmode_motion)
821 turn_off_insert ();
822 cmgoto (row, col);
823 }
824 \f
825 /* Erase operations */
826
827 /* clear from cursor to end of frame */
828 void
829 clear_to_end ()
830 {
831 register int i;
832
833 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
834 {
835 (*clear_to_end_hook) ();
836 return;
837 }
838 if (TS_clr_to_bottom)
839 {
840 background_highlight ();
841 OUTPUT (TS_clr_to_bottom);
842 bzero (chars_wasted + curY,
843 FRAME_HEIGHT (XFRAME (selected_frame)) - curY);
844 }
845 else
846 {
847 for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
848 {
849 cursor_to (i, 0);
850 clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame)));
851 }
852 }
853 }
854
855 /* Clear entire frame */
856
857 void
858 clear_frame ()
859 {
860 struct frame *sf = XFRAME (selected_frame);
861
862 if (clear_frame_hook
863 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
864 {
865 (*clear_frame_hook) ();
866 return;
867 }
868 if (TS_clr_frame)
869 {
870 background_highlight ();
871 OUTPUT (TS_clr_frame);
872 bzero (chars_wasted, FRAME_HEIGHT (sf));
873 cmat (0, 0);
874 }
875 else
876 {
877 cursor_to (0, 0);
878 clear_to_end ();
879 }
880 }
881
882 /* Clear to end of line, but do not clear any standout marker.
883 Assumes that the cursor is positioned at a character of real text,
884 which implies it cannot be before a standout marker
885 unless the marker has zero width.
886
887 Note that the cursor may be moved. */
888
889 void
890 clear_end_of_line (first_unused_hpos)
891 int first_unused_hpos;
892 {
893 if (FRAME_TERMCAP_P (XFRAME (selected_frame))
894 && chars_wasted != 0
895 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
896 write_glyphs (&space_glyph, 1);
897 clear_end_of_line_raw (first_unused_hpos);
898 }
899
900 /* Clear from cursor to end of line.
901 Assume that the line is already clear starting at column first_unused_hpos.
902 If the cursor is at a standout marker, erase the marker.
903
904 Note that the cursor may be moved, on terminals lacking a `ce' string. */
905
906 void
907 clear_end_of_line_raw (first_unused_hpos)
908 int first_unused_hpos;
909 {
910 register int i;
911
912 if (clear_end_of_line_hook
913 && ! FRAME_TERMCAP_P ((updating_frame
914 ? updating_frame
915 : XFRAME (selected_frame))))
916 {
917 (*clear_end_of_line_hook) (first_unused_hpos);
918 return;
919 }
920
921 /* Detect the case where we are called from reset_sys_modes
922 and the costs have never been calculated. Do nothing. */
923 if (chars_wasted == 0)
924 return;
925
926 first_unused_hpos += chars_wasted[curY] & 077;
927 if (curX >= first_unused_hpos)
928 return;
929 /* Notice if we are erasing a magic cookie */
930 if (curX == 0)
931 chars_wasted[curY] = 0;
932 background_highlight ();
933 if (TS_clr_line)
934 {
935 OUTPUT1 (TS_clr_line);
936 }
937 else
938 { /* have to do it the hard way */
939 struct frame *sf = XFRAME (selected_frame);
940 turn_off_insert ();
941
942 /* Do not write in last row last col with Auto-wrap on. */
943 if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
944 && first_unused_hpos == FRAME_WIDTH (sf))
945 first_unused_hpos--;
946
947 for (i = curX; i < first_unused_hpos; i++)
948 {
949 if (termscript)
950 fputc (' ', termscript);
951 putchar (' ');
952 }
953 cmplus (first_unused_hpos - curX);
954 }
955 }
956 \f
957 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
958 store them at DST. Do not write more than DST_LEN bytes. That may
959 require stopping before all SRC_LEN input glyphs have been
960 converted.
961
962 We store the number of glyphs actually converted in *CONSUMED. The
963 return value is the number of bytes store in DST. */
964
965 int
966 encode_terminal_code (src, dst, src_len, dst_len, consumed)
967 struct glyph *src;
968 int src_len;
969 unsigned char *dst;
970 int dst_len, *consumed;
971 {
972 struct glyph *src_start = src, *src_end = src + src_len;
973 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
974 register GLYPH g;
975 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
976 int len;
977 register int tlen = GLYPH_TABLE_LENGTH;
978 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
979 int result;
980 struct coding_system *coding;
981
982 /* If terminal_coding does any conversion, use it, otherwise use
983 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
984 because it always return 1 if the member src_multibyte is 1. */
985 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
986 ? &terminal_coding
987 : &safe_terminal_coding);
988
989 while (src < src_end)
990 {
991 /* We must skip glyphs to be padded for a wide character. */
992 if (! CHAR_GLYPH_PADDING_P (*src))
993 {
994 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
995
996 if (g < 0 || g >= tlen)
997 {
998 /* This glyph doesn't has an entry in Vglyph_table. */
999 if (! CHAR_VALID_P (src->u.ch, 0))
1000 {
1001 len = 1;
1002 buf = " ";
1003 coding->src_multibyte = 0;
1004 }
1005 else
1006 {
1007 len = CHAR_STRING (src->u.ch, workbuf);
1008 buf = workbuf;
1009 coding->src_multibyte = 1;
1010 }
1011 }
1012 else
1013 {
1014 /* This glyph has an entry in Vglyph_table,
1015 so process any alias before testing for simpleness. */
1016 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
1017
1018 if (GLYPH_SIMPLE_P (tbase, tlen, g))
1019 {
1020 /* We set the multi-byte form of a character in G
1021 (that should be an ASCII character) at
1022 WORKBUF. */
1023 workbuf[0] = FAST_GLYPH_CHAR (g);
1024 len = 1;
1025 buf = workbuf;
1026 coding->src_multibyte = 0;
1027 }
1028 else
1029 {
1030 /* We have a string in Vglyph_table. */
1031 len = GLYPH_LENGTH (tbase, g);
1032 buf = GLYPH_STRING (tbase, g);
1033 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
1034 }
1035 }
1036
1037 result = encode_coding (coding, buf, dst, len, dst_end - dst);
1038 len -= coding->consumed;
1039 dst += coding->produced;
1040 if (result == CODING_FINISH_INSUFFICIENT_DST
1041 || (result == CODING_FINISH_INSUFFICIENT_SRC
1042 && len > dst_end - dst))
1043 /* The remaining output buffer is too short. We must
1044 break the loop here without increasing SRC so that the
1045 next call of this function starts from the same glyph. */
1046 break;
1047
1048 if (len > 0)
1049 {
1050 /* This is the case that a code of the range 0200..0237
1051 exists in buf. We must just write out such a code. */
1052 buf += coding->consumed;
1053 while (len--)
1054 *dst++ = *buf++;
1055 }
1056 }
1057 src++;
1058 }
1059
1060 *consumed = src - src_start;
1061 return (dst - dst_start);
1062 }
1063
1064
1065 void
1066 write_glyphs (string, len)
1067 register struct glyph *string;
1068 register int len;
1069 {
1070 int produced, consumed;
1071 struct frame *sf = XFRAME (selected_frame);
1072 struct frame *f = updating_frame ? updating_frame : sf;
1073 unsigned char conversion_buffer[1024];
1074 int conversion_buffer_size = sizeof conversion_buffer;
1075
1076 if (write_glyphs_hook
1077 && ! FRAME_TERMCAP_P (f))
1078 {
1079 (*write_glyphs_hook) (string, len);
1080 return;
1081 }
1082
1083 turn_off_insert ();
1084 tty_hide_cursor ();
1085
1086 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1087 since that would scroll the whole frame on some terminals. */
1088
1089 if (AutoWrap
1090 && curY + 1 == FRAME_HEIGHT (sf)
1091 && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (sf)))
1092 len --;
1093 if (len <= 0)
1094 return;
1095
1096 cmplus (len);
1097
1098 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1099 the tail. */
1100 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1101
1102 while (len > 0)
1103 {
1104 /* Identify a run of glyphs with the same face. */
1105 int face_id = string->face_id;
1106 int n;
1107
1108 for (n = 1; n < len; ++n)
1109 if (string[n].face_id != face_id)
1110 break;
1111
1112 /* Turn appearance modes of the face of the run on. */
1113 highlight_if_desired ();
1114 turn_on_face (f, face_id);
1115
1116 while (n > 0)
1117 {
1118 /* We use a fixed size (1024 bytes) of conversion buffer.
1119 Usually it is sufficient, but if not, we just repeat the
1120 loop. */
1121 produced = encode_terminal_code (string, conversion_buffer,
1122 n, conversion_buffer_size,
1123 &consumed);
1124 if (produced > 0)
1125 {
1126 fwrite (conversion_buffer, 1, produced, stdout);
1127 if (ferror (stdout))
1128 clearerr (stdout);
1129 if (termscript)
1130 fwrite (conversion_buffer, 1, produced, termscript);
1131 }
1132 len -= consumed;
1133 n -= consumed;
1134 string += consumed;
1135 }
1136
1137 /* Turn appearance modes off. */
1138 turn_off_face (f, face_id);
1139 turn_off_highlight ();
1140 }
1141
1142 /* We may have to output some codes to terminate the writing. */
1143 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1144 {
1145 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1146 encode_coding (&terminal_coding, "", conversion_buffer,
1147 0, conversion_buffer_size);
1148 if (terminal_coding.produced > 0)
1149 {
1150 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
1151 if (ferror (stdout))
1152 clearerr (stdout);
1153 if (termscript)
1154 fwrite (conversion_buffer, 1, terminal_coding.produced,
1155 termscript);
1156 }
1157 }
1158
1159 cmcheckmagic ();
1160 }
1161
1162 /* If start is zero, insert blanks instead of a string at start */
1163
1164 void
1165 insert_glyphs (start, len)
1166 register struct glyph *start;
1167 register int len;
1168 {
1169 char *buf;
1170 struct glyph *glyph = NULL;
1171 struct frame *f, *sf;
1172
1173 if (len <= 0)
1174 return;
1175
1176 if (insert_glyphs_hook)
1177 {
1178 (*insert_glyphs_hook) (start, len);
1179 return;
1180 }
1181
1182 sf = XFRAME (selected_frame);
1183 f = updating_frame ? updating_frame : sf;
1184
1185 if (TS_ins_multi_chars)
1186 {
1187 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1188 OUTPUT1 (buf);
1189 xfree (buf);
1190 if (start)
1191 write_glyphs (start, len);
1192 return;
1193 }
1194
1195 turn_on_insert ();
1196 cmplus (len);
1197 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1198 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1199 while (len-- > 0)
1200 {
1201 int produced, consumed;
1202 unsigned char conversion_buffer[1024];
1203 int conversion_buffer_size = sizeof conversion_buffer;
1204
1205 OUTPUT1_IF (TS_ins_char);
1206 if (!start)
1207 {
1208 conversion_buffer[0] = SPACEGLYPH;
1209 produced = 1;
1210 }
1211 else
1212 {
1213 highlight_if_desired ();
1214 turn_on_face (f, start->face_id);
1215 glyph = start;
1216 ++start;
1217 /* We must open sufficient space for a character which
1218 occupies more than one column. */
1219 while (len && CHAR_GLYPH_PADDING_P (*start))
1220 {
1221 OUTPUT1_IF (TS_ins_char);
1222 start++, len--;
1223 }
1224
1225 if (len <= 0)
1226 /* This is the last glyph. */
1227 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1228
1229 /* The size of conversion buffer (1024 bytes) is surely
1230 sufficient for just one glyph. */
1231 produced = encode_terminal_code (glyph, conversion_buffer, 1,
1232 conversion_buffer_size, &consumed);
1233 }
1234
1235 if (produced > 0)
1236 {
1237 fwrite (conversion_buffer, 1, produced, stdout);
1238 if (ferror (stdout))
1239 clearerr (stdout);
1240 if (termscript)
1241 fwrite (conversion_buffer, 1, produced, termscript);
1242 }
1243
1244 OUTPUT1_IF (TS_pad_inserted_char);
1245 if (start)
1246 {
1247 turn_off_face (f, glyph->face_id);
1248 turn_off_highlight ();
1249 }
1250 }
1251
1252 cmcheckmagic ();
1253 }
1254
1255 void
1256 delete_glyphs (n)
1257 register int n;
1258 {
1259 char *buf;
1260 register int i;
1261
1262 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1263 {
1264 (*delete_glyphs_hook) (n);
1265 return;
1266 }
1267
1268 if (delete_in_insert_mode)
1269 {
1270 turn_on_insert ();
1271 }
1272 else
1273 {
1274 turn_off_insert ();
1275 OUTPUT_IF (TS_delete_mode);
1276 }
1277
1278 if (TS_del_multi_chars)
1279 {
1280 buf = tparam (TS_del_multi_chars, 0, 0, n);
1281 OUTPUT1 (buf);
1282 xfree (buf);
1283 }
1284 else
1285 for (i = 0; i < n; i++)
1286 OUTPUT1 (TS_del_char);
1287 if (!delete_in_insert_mode)
1288 OUTPUT_IF (TS_end_delete_mode);
1289 }
1290 \f
1291 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1292
1293 void
1294 ins_del_lines (vpos, n)
1295 int vpos, n;
1296 {
1297 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1298 char *single = n > 0 ? TS_ins_line : TS_del_line;
1299 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1300 struct frame *sf;
1301
1302 register int i = n > 0 ? n : -n;
1303 register char *buf;
1304
1305 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1306 {
1307 (*ins_del_lines_hook) (vpos, n);
1308 return;
1309 }
1310
1311 sf = XFRAME (selected_frame);
1312
1313 /* If the lines below the insertion are being pushed
1314 into the end of the window, this is the same as clearing;
1315 and we know the lines are already clear, since the matching
1316 deletion has already been done. So can ignore this. */
1317 /* If the lines below the deletion are blank lines coming
1318 out of the end of the window, don't bother,
1319 as there will be a matching inslines later that will flush them. */
1320 if (scroll_region_ok && vpos + i >= specified_window)
1321 return;
1322 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
1323 return;
1324
1325 if (multi)
1326 {
1327 raw_cursor_to (vpos, 0);
1328 background_highlight ();
1329 buf = tparam (multi, 0, 0, i);
1330 OUTPUT (buf);
1331 xfree (buf);
1332 }
1333 else if (single)
1334 {
1335 raw_cursor_to (vpos, 0);
1336 background_highlight ();
1337 while (--i >= 0)
1338 OUTPUT (single);
1339 if (TF_teleray)
1340 curX = 0;
1341 }
1342 else
1343 {
1344 set_scroll_region (vpos, specified_window);
1345 if (n < 0)
1346 raw_cursor_to (specified_window - 1, 0);
1347 else
1348 raw_cursor_to (vpos, 0);
1349 background_highlight ();
1350 while (--i >= 0)
1351 OUTPUTL (scroll, specified_window - vpos);
1352 set_scroll_region (0, specified_window);
1353 }
1354
1355 if (TN_standout_width >= 0)
1356 {
1357 register int lower_limit
1358 = (scroll_region_ok
1359 ? specified_window
1360 : FRAME_HEIGHT (sf));
1361
1362 if (n < 0)
1363 {
1364 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1365 lower_limit - vpos + n);
1366 bzero (&chars_wasted[lower_limit + n], - n);
1367 }
1368 else
1369 {
1370 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1371 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1372 lower_limit - vpos - n);
1373 bzero (&chars_wasted[vpos], n);
1374 }
1375 }
1376 if (!scroll_region_ok && memory_below_frame && n < 0)
1377 {
1378 cursor_to (FRAME_HEIGHT (sf) + n, 0);
1379 clear_to_end ();
1380 }
1381 }
1382 \f
1383 /* Compute cost of sending "str", in characters,
1384 not counting any line-dependent padding. */
1385
1386 int
1387 string_cost (str)
1388 char *str;
1389 {
1390 cost = 0;
1391 if (str)
1392 tputs (str, 0, evalcost);
1393 return cost;
1394 }
1395
1396 /* Compute cost of sending "str", in characters,
1397 counting any line-dependent padding at one line. */
1398
1399 static int
1400 string_cost_one_line (str)
1401 char *str;
1402 {
1403 cost = 0;
1404 if (str)
1405 tputs (str, 1, evalcost);
1406 return cost;
1407 }
1408
1409 /* Compute per line amount of line-dependent padding,
1410 in tenths of characters. */
1411
1412 int
1413 per_line_cost (str)
1414 register char *str;
1415 {
1416 cost = 0;
1417 if (str)
1418 tputs (str, 0, evalcost);
1419 cost = - cost;
1420 if (str)
1421 tputs (str, 10, evalcost);
1422 return cost;
1423 }
1424
1425 #ifndef old
1426 /* char_ins_del_cost[n] is cost of inserting N characters.
1427 char_ins_del_cost[-n] is cost of deleting N characters.
1428 The length of this vector is based on max_frame_width. */
1429
1430 int *char_ins_del_vector;
1431
1432 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1433 #endif
1434
1435 /* ARGSUSED */
1436 static void
1437 calculate_ins_del_char_costs (frame)
1438 FRAME_PTR frame;
1439 {
1440 int ins_startup_cost, del_startup_cost;
1441 int ins_cost_per_char, del_cost_per_char;
1442 register int i;
1443 register int *p;
1444
1445 if (TS_ins_multi_chars)
1446 {
1447 ins_cost_per_char = 0;
1448 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1449 }
1450 else if (TS_ins_char || TS_pad_inserted_char
1451 || (TS_insert_mode && TS_end_insert_mode))
1452 {
1453 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1454 + string_cost (TS_end_insert_mode))) / 100;
1455 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1456 + string_cost_one_line (TS_pad_inserted_char));
1457 }
1458 else
1459 {
1460 ins_startup_cost = 9999;
1461 ins_cost_per_char = 0;
1462 }
1463
1464 if (TS_del_multi_chars)
1465 {
1466 del_cost_per_char = 0;
1467 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1468 }
1469 else if (TS_del_char)
1470 {
1471 del_startup_cost = (string_cost (TS_delete_mode)
1472 + string_cost (TS_end_delete_mode));
1473 if (delete_in_insert_mode)
1474 del_startup_cost /= 2;
1475 del_cost_per_char = string_cost_one_line (TS_del_char);
1476 }
1477 else
1478 {
1479 del_startup_cost = 9999;
1480 del_cost_per_char = 0;
1481 }
1482
1483 /* Delete costs are at negative offsets */
1484 p = &char_ins_del_cost (frame)[0];
1485 for (i = FRAME_WIDTH (frame); --i >= 0;)
1486 *--p = (del_startup_cost += del_cost_per_char);
1487
1488 /* Doing nothing is free */
1489 p = &char_ins_del_cost (frame)[0];
1490 *p++ = 0;
1491
1492 /* Insert costs are at positive offsets */
1493 for (i = FRAME_WIDTH (frame); --i >= 0;)
1494 *p++ = (ins_startup_cost += ins_cost_per_char);
1495 }
1496
1497 void
1498 calculate_costs (frame)
1499 FRAME_PTR frame;
1500 {
1501 register char *f = (TS_set_scroll_region
1502 ? TS_set_scroll_region
1503 : TS_set_scroll_region_1);
1504
1505 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1506
1507 scroll_region_cost = string_cost (f);
1508
1509 /* These variables are only used for terminal stuff. They are allocated
1510 once for the terminal frame of X-windows emacs, but not used afterwards.
1511
1512 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1513 X turns off char_ins_del_ok.
1514
1515 chars_wasted and copybuf are only used here in term.c in cases where
1516 the term hook isn't called. */
1517
1518 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1519 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1520
1521 if (chars_wasted != 0)
1522 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1523 else
1524 chars_wasted = (char *) xmalloc (max_frame_height);
1525
1526 if (copybuf != 0)
1527 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1528 else
1529 copybuf = (char *) xmalloc (max_frame_height);
1530
1531 if (char_ins_del_vector != 0)
1532 char_ins_del_vector
1533 = (int *) xrealloc (char_ins_del_vector,
1534 (sizeof (int)
1535 + 2 * max_frame_width * sizeof (int)));
1536 else
1537 char_ins_del_vector
1538 = (int *) xmalloc (sizeof (int)
1539 + 2 * max_frame_width * sizeof (int));
1540
1541 bzero (chars_wasted, max_frame_height);
1542 bzero (copybuf, max_frame_height);
1543 bzero (char_ins_del_vector, (sizeof (int)
1544 + 2 * max_frame_width * sizeof (int)));
1545
1546 if (f && (!TS_ins_line && !TS_del_line))
1547 do_line_insertion_deletion_costs (frame,
1548 TS_rev_scroll, TS_ins_multi_lines,
1549 TS_fwd_scroll, TS_del_multi_lines,
1550 f, f, 1);
1551 else
1552 do_line_insertion_deletion_costs (frame,
1553 TS_ins_line, TS_ins_multi_lines,
1554 TS_del_line, TS_del_multi_lines,
1555 0, 0, 1);
1556
1557 calculate_ins_del_char_costs (frame);
1558
1559 /* Don't use TS_repeat if its padding is worse than sending the chars */
1560 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1561 RPov = string_cost (TS_repeat);
1562 else
1563 RPov = FRAME_WIDTH (frame) * 2;
1564
1565 cmcostinit (); /* set up cursor motion costs */
1566 }
1567 \f
1568 struct fkey_table {
1569 char *cap, *name;
1570 };
1571
1572 /* Termcap capability names that correspond directly to X keysyms.
1573 Some of these (marked "terminfo") aren't supplied by old-style
1574 (Berkeley) termcap entries. They're listed in X keysym order;
1575 except we put the keypad keys first, so that if they clash with
1576 other keys (as on the IBM PC keyboard) they get overridden.
1577 */
1578
1579 static struct fkey_table keys[] =
1580 {
1581 "kh", "home", /* termcap */
1582 "kl", "left", /* termcap */
1583 "ku", "up", /* termcap */
1584 "kr", "right", /* termcap */
1585 "kd", "down", /* termcap */
1586 "%8", "prior", /* terminfo */
1587 "%5", "next", /* terminfo */
1588 "@7", "end", /* terminfo */
1589 "@1", "begin", /* terminfo */
1590 "*6", "select", /* terminfo */
1591 "%9", "print", /* terminfo */
1592 "@4", "execute", /* terminfo --- actually the `command' key */
1593 /*
1594 * "insert" --- see below
1595 */
1596 "&8", "undo", /* terminfo */
1597 "%0", "redo", /* terminfo */
1598 "%7", "menu", /* terminfo --- actually the `options' key */
1599 "@0", "find", /* terminfo */
1600 "@2", "cancel", /* terminfo */
1601 "%1", "help", /* terminfo */
1602 /*
1603 * "break" goes here, but can't be reliably intercepted with termcap
1604 */
1605 "&4", "reset", /* terminfo --- actually `restart' */
1606 /*
1607 * "system" and "user" --- no termcaps
1608 */
1609 "kE", "clearline", /* terminfo */
1610 "kA", "insertline", /* terminfo */
1611 "kL", "deleteline", /* terminfo */
1612 "kI", "insertchar", /* terminfo */
1613 "kD", "deletechar", /* terminfo */
1614 "kB", "backtab", /* terminfo */
1615 /*
1616 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1617 */
1618 "@8", "kp-enter", /* terminfo */
1619 /*
1620 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1621 * "kp-multiply", "kp-add", "kp-separator",
1622 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1623 * --- no termcaps for any of these.
1624 */
1625 "K4", "kp-1", /* terminfo */
1626 /*
1627 * "kp-2" --- no termcap
1628 */
1629 "K5", "kp-3", /* terminfo */
1630 /*
1631 * "kp-4" --- no termcap
1632 */
1633 "K2", "kp-5", /* terminfo */
1634 /*
1635 * "kp-6" --- no termcap
1636 */
1637 "K1", "kp-7", /* terminfo */
1638 /*
1639 * "kp-8" --- no termcap
1640 */
1641 "K3", "kp-9", /* terminfo */
1642 /*
1643 * "kp-equal" --- no termcap
1644 */
1645 "k1", "f1",
1646 "k2", "f2",
1647 "k3", "f3",
1648 "k4", "f4",
1649 "k5", "f5",
1650 "k6", "f6",
1651 "k7", "f7",
1652 "k8", "f8",
1653 "k9", "f9",
1654 };
1655
1656 static char **term_get_fkeys_arg;
1657 static Lisp_Object term_get_fkeys_1 ();
1658
1659 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1660 This function scans the termcap function key sequence entries, and
1661 adds entries to Vfunction_key_map for each function key it finds. */
1662
1663 void
1664 term_get_fkeys (address)
1665 char **address;
1666 {
1667 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1668 errors during the call. The only errors should be from Fdefine_key
1669 when given a key sequence containing an invalid prefix key. If the
1670 termcap defines function keys which use a prefix that is already bound
1671 to a command by the default bindings, we should silently ignore that
1672 function key specification, rather than giving the user an error and
1673 refusing to run at all on such a terminal. */
1674
1675 extern Lisp_Object Fidentity ();
1676 term_get_fkeys_arg = address;
1677 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1678 }
1679
1680 static Lisp_Object
1681 term_get_fkeys_1 ()
1682 {
1683 int i;
1684
1685 char **address = term_get_fkeys_arg;
1686
1687 /* This can happen if CANNOT_DUMP or with strange options. */
1688 if (!initialized)
1689 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1690
1691 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1692 {
1693 char *sequence = tgetstr (keys[i].cap, address);
1694 if (sequence)
1695 Fdefine_key (Vfunction_key_map, build_string (sequence),
1696 Fmake_vector (make_number (1),
1697 intern (keys[i].name)));
1698 }
1699
1700 /* The uses of the "k0" capability are inconsistent; sometimes it
1701 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1702 We will attempt to politely accommodate both systems by testing for
1703 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1704 */
1705 {
1706 char *k_semi = tgetstr ("k;", address);
1707 char *k0 = tgetstr ("k0", address);
1708 char *k0_name = "f10";
1709
1710 if (k_semi)
1711 {
1712 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1713 Fmake_vector (make_number (1), intern ("f10")));
1714 k0_name = "f0";
1715 }
1716
1717 if (k0)
1718 Fdefine_key (Vfunction_key_map, build_string (k0),
1719 Fmake_vector (make_number (1), intern (k0_name)));
1720 }
1721
1722 /* Set up cookies for numbered function keys above f10. */
1723 {
1724 char fcap[3], fkey[4];
1725
1726 fcap[0] = 'F'; fcap[2] = '\0';
1727 for (i = 11; i < 64; i++)
1728 {
1729 if (i <= 19)
1730 fcap[1] = '1' + i - 11;
1731 else if (i <= 45)
1732 fcap[1] = 'A' + i - 20;
1733 else
1734 fcap[1] = 'a' + i - 46;
1735
1736 {
1737 char *sequence = tgetstr (fcap, address);
1738 if (sequence)
1739 {
1740 sprintf (fkey, "f%d", i);
1741 Fdefine_key (Vfunction_key_map, build_string (sequence),
1742 Fmake_vector (make_number (1),
1743 intern (fkey)));
1744 }
1745 }
1746 }
1747 }
1748
1749 /*
1750 * Various mappings to try and get a better fit.
1751 */
1752 {
1753 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1754 if (!tgetstr (cap1, address)) \
1755 { \
1756 char *sequence = tgetstr (cap2, address); \
1757 if (sequence) \
1758 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1759 Fmake_vector (make_number (1), \
1760 intern (sym))); \
1761 }
1762
1763 /* if there's no key_next keycap, map key_npage to `next' keysym */
1764 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1765 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1766 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1767 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1768 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1769 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1770 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1771
1772 /* IBM has their own non-standard dialect of terminfo.
1773 If the standard name isn't found, try the IBM name. */
1774 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1775 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1776 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1777 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1778 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1779 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1780 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1781 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1782 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1783 #undef CONDITIONAL_REASSIGN
1784 }
1785
1786 return Qnil;
1787 }
1788
1789 \f
1790 /***********************************************************************
1791 Character Display Information
1792 ***********************************************************************/
1793
1794 static void append_glyph P_ ((struct it *));
1795
1796
1797 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1798 terminal frames if IT->glyph_row != NULL. IT->c is the character
1799 for which to produce glyphs; IT->face_id contains the character's
1800 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1801 1. */
1802
1803 static void
1804 append_glyph (it)
1805 struct it *it;
1806 {
1807 struct glyph *glyph, *end;
1808 int i;
1809
1810 xassert (it->glyph_row);
1811 glyph = (it->glyph_row->glyphs[it->area]
1812 + it->glyph_row->used[it->area]);
1813 end = it->glyph_row->glyphs[1 + it->area];
1814
1815 for (i = 0;
1816 i < it->pixel_width && glyph < end;
1817 ++i)
1818 {
1819 glyph->type = CHAR_GLYPH;
1820 glyph->pixel_width = 1;
1821 glyph->u.ch = it->c;
1822 glyph->face_id = it->face_id;
1823 glyph->padding_p = i > 0;
1824 glyph->charpos = CHARPOS (it->position);
1825 glyph->object = it->object;
1826
1827 ++it->glyph_row->used[it->area];
1828 ++glyph;
1829 }
1830 }
1831
1832
1833 /* Produce glyphs for the display element described by IT. The
1834 function fills output fields of IT with pixel information like the
1835 pixel width and height of a character, and maybe produces glyphs at
1836 the same time if IT->glyph_row is non-null. See the explanation of
1837 struct display_iterator in dispextern.h for an overview. */
1838
1839 void
1840 produce_glyphs (it)
1841 struct it *it;
1842 {
1843 /* If a hook is installed, let it do the work. */
1844 xassert (it->what == IT_CHARACTER
1845 || it->what == IT_COMPOSITION
1846 || it->what == IT_IMAGE
1847 || it->what == IT_STRETCH);
1848
1849 /* Nothing but characters are supported on terminal frames. For a
1850 composition sequence, it->c is the first character of the
1851 sequence. */
1852 xassert (it->what == IT_CHARACTER
1853 || it->what == IT_COMPOSITION);
1854
1855 if (it->c >= 040 && it->c < 0177)
1856 {
1857 it->pixel_width = it->nglyphs = 1;
1858 if (it->glyph_row)
1859 append_glyph (it);
1860 }
1861 else if (it->c == '\n')
1862 it->pixel_width = it->nglyphs = 0;
1863 else if (it->c == '\t')
1864 {
1865 int absolute_x = (it->current_x
1866 + it->continuation_lines_width);
1867 int next_tab_x
1868 = (((1 + absolute_x + it->tab_width - 1)
1869 / it->tab_width)
1870 * it->tab_width);
1871 int nspaces;
1872
1873 /* If part of the TAB has been displayed on the previous line
1874 which is continued now, continuation_lines_width will have
1875 been incremented already by the part that fitted on the
1876 continued line. So, we will get the right number of spaces
1877 here. */
1878 nspaces = next_tab_x - absolute_x;
1879
1880 if (it->glyph_row)
1881 {
1882 int n = nspaces;
1883
1884 it->c = ' ';
1885 it->pixel_width = it->len = 1;
1886
1887 while (n--)
1888 append_glyph (it);
1889
1890 it->c = '\t';
1891 }
1892
1893 it->pixel_width = nspaces;
1894 it->nglyphs = nspaces;
1895 }
1896 else if (SINGLE_BYTE_CHAR_P (it->c))
1897 {
1898 /* Coming here means that it->c is from display table, thus we
1899 must send the code as is to the terminal. Although there's
1900 no way to know how many columns it occupies on a screen, it
1901 is a good assumption that a single byte code has 1-column
1902 width. */
1903 it->pixel_width = it->nglyphs = 1;
1904 if (it->glyph_row)
1905 append_glyph (it);
1906 }
1907 else
1908 {
1909 /* A multi-byte character. The display width is fixed for all
1910 characters of the set. Some of the glyphs may have to be
1911 ignored because they are already displayed in a continued
1912 line. */
1913 int charset = CHAR_CHARSET (it->c);
1914
1915 it->pixel_width = CHARSET_WIDTH (charset);
1916 it->nglyphs = it->pixel_width;
1917
1918 if (it->glyph_row)
1919 append_glyph (it);
1920 }
1921
1922 /* Advance current_x by the pixel width as a convenience for
1923 the caller. */
1924 if (it->area == TEXT_AREA)
1925 it->current_x += it->pixel_width;
1926 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1927 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1928 }
1929
1930
1931 /* Get information about special display element WHAT in an
1932 environment described by IT. WHAT is one of IT_TRUNCATION or
1933 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1934 non-null glyph_row member. This function ensures that fields like
1935 face_id, c, len of IT are left untouched. */
1936
1937 void
1938 produce_special_glyphs (it, what)
1939 struct it *it;
1940 enum display_element_type what;
1941 {
1942 struct it temp_it;
1943
1944 temp_it = *it;
1945 temp_it.dp = NULL;
1946 temp_it.what = IT_CHARACTER;
1947 temp_it.len = 1;
1948 temp_it.object = make_number (0);
1949 bzero (&temp_it.current, sizeof temp_it.current);
1950
1951 if (what == IT_CONTINUATION)
1952 {
1953 /* Continuation glyph. */
1954 if (it->dp
1955 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1956 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1957 {
1958 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1959 temp_it.len = CHAR_BYTES (temp_it.c);
1960 }
1961 else
1962 temp_it.c = '\\';
1963
1964 produce_glyphs (&temp_it);
1965 it->pixel_width = temp_it.pixel_width;
1966 it->nglyphs = temp_it.pixel_width;
1967 }
1968 else if (what == IT_TRUNCATION)
1969 {
1970 /* Truncation glyph. */
1971 if (it->dp
1972 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1973 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1974 {
1975 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1976 temp_it.len = CHAR_BYTES (temp_it.c);
1977 }
1978 else
1979 temp_it.c = '$';
1980
1981 produce_glyphs (&temp_it);
1982 it->pixel_width = temp_it.pixel_width;
1983 it->nglyphs = temp_it.pixel_width;
1984 }
1985 else
1986 abort ();
1987 }
1988
1989
1990 /* Return an estimation of the pixel height of mode or top lines on
1991 frame F. FACE_ID specifies what line's height to estimate. */
1992
1993 int
1994 estimate_mode_line_height (f, face_id)
1995 struct frame *f;
1996 enum face_id face_id;
1997 {
1998 if (estimate_mode_line_height_hook)
1999 return estimate_mode_line_height_hook (f, face_id);
2000 else
2001 return 1;
2002 }
2003
2004
2005 \f
2006 /***********************************************************************
2007 Faces
2008 ***********************************************************************/
2009
2010 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2011 one of the enumerators from enum no_color_bit, or a bit set built
2012 from them. Some display attributes may not be used together with
2013 color; the termcap capability `NC' specifies which ones. */
2014
2015 #define MAY_USE_WITH_COLORS_P(ATTR) \
2016 (TN_max_colors > 0 \
2017 ? (TN_no_color_video & (ATTR)) == 0 \
2018 : 1)
2019
2020 /* Turn appearances of face FACE_ID on tty frame F on. */
2021
2022 static void
2023 turn_on_face (f, face_id)
2024 struct frame *f;
2025 int face_id;
2026 {
2027 struct face *face = FACE_FROM_ID (f, face_id);
2028 long fg = face->foreground;
2029 long bg = face->background;
2030
2031 /* Do this first because TS_end_standout_mode may be the same
2032 as TS_exit_attribute_mode, which turns all appearances off. */
2033 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
2034 {
2035 if (TN_max_colors > 0)
2036 {
2037 if (fg >= 0 && bg >= 0)
2038 {
2039 /* If the terminal supports colors, we can set them
2040 below without using reverse video. The face's fg
2041 and bg colors are set as they should appear on
2042 the screen, i.e. they take the inverse-video'ness
2043 of the face already into account. */
2044 }
2045 else if (inverse_video)
2046 {
2047 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2048 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2049 toggle_highlight ();
2050 }
2051 else
2052 {
2053 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2054 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2055 toggle_highlight ();
2056 }
2057 }
2058 else
2059 {
2060 /* If we can't display colors, use reverse video
2061 if the face specifies that. */
2062 if (inverse_video)
2063 {
2064 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2065 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2066 toggle_highlight ();
2067 }
2068 else
2069 {
2070 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2071 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2072 toggle_highlight ();
2073 }
2074 }
2075 }
2076
2077 if (face->tty_bold_p)
2078 {
2079 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
2080 OUTPUT1_IF (TS_enter_bold_mode);
2081 }
2082 else if (face->tty_dim_p)
2083 if (MAY_USE_WITH_COLORS_P (NC_DIM))
2084 OUTPUT1_IF (TS_enter_dim_mode);
2085
2086 /* Alternate charset and blinking not yet used. */
2087 if (face->tty_alt_charset_p
2088 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
2089 OUTPUT1_IF (TS_enter_alt_charset_mode);
2090
2091 if (face->tty_blinking_p
2092 && MAY_USE_WITH_COLORS_P (NC_BLINK))
2093 OUTPUT1_IF (TS_enter_blink_mode);
2094
2095 if (face->tty_underline_p
2096 /* Don't underline if that's difficult. */
2097 && TN_magic_cookie_glitch_ul <= 0
2098 && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
2099 OUTPUT1_IF (TS_enter_underline_mode);
2100
2101 if (TN_max_colors > 0)
2102 {
2103 char *p;
2104
2105 if (fg >= 0 && TS_set_foreground)
2106 {
2107 p = tparam (TS_set_foreground, NULL, 0, (int) fg);
2108 OUTPUT (p);
2109 xfree (p);
2110 }
2111
2112 if (bg >= 0 && TS_set_background)
2113 {
2114 p = tparam (TS_set_background, NULL, 0, (int) bg);
2115 OUTPUT (p);
2116 xfree (p);
2117 }
2118 }
2119 }
2120
2121
2122 /* Turn off appearances of face FACE_ID on tty frame F. */
2123
2124 static void
2125 turn_off_face (f, face_id)
2126 struct frame *f;
2127 int face_id;
2128 {
2129 struct face *face = FACE_FROM_ID (f, face_id);
2130
2131 xassert (face != NULL);
2132
2133 if (TS_exit_attribute_mode)
2134 {
2135 /* Capability "me" will turn off appearance modes double-bright,
2136 half-bright, reverse-video, standout, underline. It may or
2137 may not turn off alt-char-mode. */
2138 if (face->tty_bold_p
2139 || face->tty_dim_p
2140 || face->tty_reverse_p
2141 || face->tty_alt_charset_p
2142 || face->tty_blinking_p
2143 || face->tty_underline_p)
2144 {
2145 OUTPUT1_IF (TS_exit_attribute_mode);
2146 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
2147 standout_mode = 0;
2148 }
2149
2150 if (face->tty_alt_charset_p)
2151 OUTPUT_IF (TS_exit_alt_charset_mode);
2152 }
2153 else
2154 {
2155 /* If we don't have "me" we can only have those appearances
2156 that have exit sequences defined. */
2157 if (face->tty_alt_charset_p)
2158 OUTPUT_IF (TS_exit_alt_charset_mode);
2159
2160 if (face->tty_underline_p
2161 /* We don't underline if that's difficult. */
2162 && TN_magic_cookie_glitch_ul <= 0)
2163 OUTPUT_IF (TS_exit_underline_mode);
2164 }
2165
2166 /* Switch back to default colors. */
2167 if (TN_max_colors > 0
2168 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2169 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2170 || (face->background != FACE_TTY_DEFAULT_COLOR
2171 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2172 OUTPUT1_IF (TS_orig_pair);
2173 }
2174
2175
2176 /* Return non-zero if the terminal is capable to display colors. */
2177
2178 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2179 0, 1, 0,
2180 "Return non-nil if TTY can display colors on FRAME.")
2181 (frame)
2182 Lisp_Object frame;
2183 {
2184 return TN_max_colors > 0 ? Qt : Qnil;
2185 }
2186
2187
2188
2189 \f
2190 /***********************************************************************
2191 Initialization
2192 ***********************************************************************/
2193
2194 void
2195 term_init (terminal_type)
2196 char *terminal_type;
2197 {
2198 char *area;
2199 char **address = &area;
2200 char buffer[2044];
2201 register char *p;
2202 int status;
2203 struct frame *sf = XFRAME (selected_frame);
2204
2205 #ifdef WINDOWSNT
2206 initialize_w32_display ();
2207
2208 Wcm_clear ();
2209
2210 area = (char *) xmalloc (2044);
2211
2212 if (area == 0)
2213 abort ();
2214
2215 FrameRows = FRAME_HEIGHT (sf);
2216 FrameCols = FRAME_WIDTH (sf);
2217 specified_window = FRAME_HEIGHT (sf);
2218
2219 delete_in_insert_mode = 1;
2220
2221 UseTabs = 0;
2222 scroll_region_ok = 0;
2223
2224 /* Seems to insert lines when it's not supposed to, messing
2225 up the display. In doing a trace, it didn't seem to be
2226 called much, so I don't think we're losing anything by
2227 turning it off. */
2228
2229 line_ins_del_ok = 0;
2230 char_ins_del_ok = 1;
2231
2232 baud_rate = 19200;
2233
2234 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2235 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2236 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2237
2238 return;
2239 #else /* not WINDOWSNT */
2240
2241 Wcm_clear ();
2242
2243 status = tgetent (buffer, terminal_type);
2244 if (status < 0)
2245 {
2246 #ifdef TERMINFO
2247 fatal ("Cannot open terminfo database file");
2248 #else
2249 fatal ("Cannot open termcap database file");
2250 #endif
2251 }
2252 if (status == 0)
2253 {
2254 #ifdef TERMINFO
2255 fatal ("Terminal type %s is not defined.\n\
2256 If that is not the actual type of terminal you have,\n\
2257 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2258 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2259 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2260 terminal_type);
2261 #else
2262 fatal ("Terminal type %s is not defined.\n\
2263 If that is not the actual type of terminal you have,\n\
2264 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2265 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2266 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2267 terminal_type);
2268 #endif
2269 }
2270 #ifdef TERMINFO
2271 area = (char *) xmalloc (2044);
2272 #else
2273 area = (char *) xmalloc (strlen (buffer));
2274 #endif /* not TERMINFO */
2275 if (area == 0)
2276 abort ();
2277
2278 TS_ins_line = tgetstr ("al", address);
2279 TS_ins_multi_lines = tgetstr ("AL", address);
2280 TS_bell = tgetstr ("bl", address);
2281 BackTab = tgetstr ("bt", address);
2282 TS_clr_to_bottom = tgetstr ("cd", address);
2283 TS_clr_line = tgetstr ("ce", address);
2284 TS_clr_frame = tgetstr ("cl", address);
2285 ColPosition = NULL; /* tgetstr ("ch", address); */
2286 AbsPosition = tgetstr ("cm", address);
2287 CR = tgetstr ("cr", address);
2288 TS_set_scroll_region = tgetstr ("cs", address);
2289 TS_set_scroll_region_1 = tgetstr ("cS", address);
2290 RowPosition = tgetstr ("cv", address);
2291 TS_del_char = tgetstr ("dc", address);
2292 TS_del_multi_chars = tgetstr ("DC", address);
2293 TS_del_line = tgetstr ("dl", address);
2294 TS_del_multi_lines = tgetstr ("DL", address);
2295 TS_delete_mode = tgetstr ("dm", address);
2296 TS_end_delete_mode = tgetstr ("ed", address);
2297 TS_end_insert_mode = tgetstr ("ei", address);
2298 Home = tgetstr ("ho", address);
2299 TS_ins_char = tgetstr ("ic", address);
2300 TS_ins_multi_chars = tgetstr ("IC", address);
2301 TS_insert_mode = tgetstr ("im", address);
2302 TS_pad_inserted_char = tgetstr ("ip", address);
2303 TS_end_keypad_mode = tgetstr ("ke", address);
2304 TS_keypad_mode = tgetstr ("ks", address);
2305 LastLine = tgetstr ("ll", address);
2306 Right = tgetstr ("nd", address);
2307 Down = tgetstr ("do", address);
2308 if (!Down)
2309 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2310 #ifdef VMS
2311 /* VMS puts a carriage return before each linefeed,
2312 so it is not safe to use linefeeds. */
2313 if (Down && Down[0] == '\n' && Down[1] == '\0')
2314 Down = 0;
2315 #endif /* VMS */
2316 if (tgetflag ("bs"))
2317 Left = "\b"; /* can't possibly be longer! */
2318 else /* (Actually, "bs" is obsolete...) */
2319 Left = tgetstr ("le", address);
2320 if (!Left)
2321 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2322 TS_pad_char = tgetstr ("pc", address);
2323 TS_repeat = tgetstr ("rp", address);
2324 TS_end_standout_mode = tgetstr ("se", address);
2325 TS_fwd_scroll = tgetstr ("sf", address);
2326 TS_standout_mode = tgetstr ("so", address);
2327 TS_rev_scroll = tgetstr ("sr", address);
2328 Wcm.cm_tab = tgetstr ("ta", address);
2329 TS_end_termcap_modes = tgetstr ("te", address);
2330 TS_termcap_modes = tgetstr ("ti", address);
2331 Up = tgetstr ("up", address);
2332 TS_visible_bell = tgetstr ("vb", address);
2333 TS_cursor_normal = tgetstr ("ve", address);
2334 TS_cursor_visible = tgetstr ("vs", address);
2335 TS_cursor_invisible = tgetstr ("vi", address);
2336 TS_set_window = tgetstr ("wi", address);
2337
2338 TS_enter_underline_mode = tgetstr ("us", address);
2339 TS_exit_underline_mode = tgetstr ("ue", address);
2340 TN_magic_cookie_glitch_ul = tgetnum ("ug");
2341 TS_enter_bold_mode = tgetstr ("md", address);
2342 TS_enter_dim_mode = tgetstr ("mh", address);
2343 TS_enter_blink_mode = tgetstr ("mb", address);
2344 TS_enter_reverse_mode = tgetstr ("mr", address);
2345 TS_enter_alt_charset_mode = tgetstr ("as", address);
2346 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2347 TS_exit_attribute_mode = tgetstr ("me", address);
2348
2349 MultiUp = tgetstr ("UP", address);
2350 MultiDown = tgetstr ("DO", address);
2351 MultiLeft = tgetstr ("LE", address);
2352 MultiRight = tgetstr ("RI", address);
2353
2354 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2355 color because we can't switch back to the default foreground and
2356 background. */
2357 TS_orig_pair = tgetstr ("op", address);
2358 if (TS_orig_pair)
2359 {
2360 TS_set_foreground = tgetstr ("AF", address);
2361 TS_set_background = tgetstr ("AB", address);
2362 if (!TS_set_foreground)
2363 {
2364 /* SVr4. */
2365 TS_set_foreground = tgetstr ("Sf", address);
2366 TS_set_background = tgetstr ("Sb", address);
2367 }
2368
2369 TN_max_colors = tgetnum ("Co");
2370 TN_max_pairs = tgetnum ("pa");
2371
2372 TN_no_color_video = tgetnum ("NC");
2373 if (TN_no_color_video == -1)
2374 TN_no_color_video = 0;
2375 }
2376
2377 MagicWrap = tgetflag ("xn");
2378 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2379 the former flag imply the latter. */
2380 AutoWrap = MagicWrap || tgetflag ("am");
2381 memory_below_frame = tgetflag ("db");
2382 TF_hazeltine = tgetflag ("hz");
2383 must_write_spaces = tgetflag ("in");
2384 meta_key = tgetflag ("km") || tgetflag ("MT");
2385 TF_insmode_motion = tgetflag ("mi");
2386 TF_standout_motion = tgetflag ("ms");
2387 TF_underscore = tgetflag ("ul");
2388 TF_xs = tgetflag ("xs");
2389 TF_teleray = tgetflag ("xt");
2390
2391 term_get_fkeys (address);
2392
2393 /* Get frame size from system, or else from termcap. */
2394 {
2395 int height, width;
2396 get_frame_size (&width, &height);
2397 FRAME_WIDTH (sf) = width;
2398 FRAME_HEIGHT (sf) = height;
2399 }
2400
2401 if (FRAME_WIDTH (sf) <= 0)
2402 SET_FRAME_WIDTH (sf, tgetnum ("co"));
2403 else
2404 /* Keep width and external_width consistent */
2405 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
2406 if (FRAME_HEIGHT (sf) <= 0)
2407 FRAME_HEIGHT (sf) = tgetnum ("li");
2408
2409 if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
2410 fatal ("Screen size %dx%d is too small",
2411 FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
2412
2413 min_padding_speed = tgetnum ("pb");
2414 TN_standout_width = tgetnum ("sg");
2415 TabWidth = tgetnum ("tw");
2416
2417 #ifdef VMS
2418 /* These capabilities commonly use ^J.
2419 I don't know why, but sending them on VMS does not work;
2420 it causes following spaces to be lost, sometimes.
2421 For now, the simplest fix is to avoid using these capabilities ever. */
2422 if (Down && Down[0] == '\n')
2423 Down = 0;
2424 #endif /* VMS */
2425
2426 if (!TS_bell)
2427 TS_bell = "\07";
2428
2429 if (!TS_fwd_scroll)
2430 TS_fwd_scroll = Down;
2431
2432 PC = TS_pad_char ? *TS_pad_char : 0;
2433
2434 if (TabWidth < 0)
2435 TabWidth = 8;
2436
2437 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2438 and newer termcap doc does not seem to say there is a default.
2439 if (!Wcm.cm_tab)
2440 Wcm.cm_tab = "\t";
2441 */
2442
2443 if (TS_standout_mode == 0)
2444 {
2445 TN_standout_width = tgetnum ("ug");
2446 TS_end_standout_mode = tgetstr ("ue", address);
2447 TS_standout_mode = tgetstr ("us", address);
2448 }
2449
2450 /* If no `se' string, try using a `me' string instead.
2451 If that fails, we can't use standout mode at all. */
2452 if (TS_end_standout_mode == 0)
2453 {
2454 char *s = tgetstr ("me", address);
2455 if (s != 0)
2456 TS_end_standout_mode = s;
2457 else
2458 TS_standout_mode = 0;
2459 }
2460
2461 if (TF_teleray)
2462 {
2463 Wcm.cm_tab = 0;
2464 /* Teleray: most programs want a space in front of TS_standout_mode,
2465 but Emacs can do without it (and give one extra column). */
2466 TS_standout_mode = "\033RD";
2467 TN_standout_width = 1;
2468 /* But that means we cannot rely on ^M to go to column zero! */
2469 CR = 0;
2470 /* LF can't be trusted either -- can alter hpos */
2471 /* if move at column 0 thru a line with TS_standout_mode */
2472 Down = 0;
2473 }
2474
2475 /* Special handling for certain terminal types known to need it */
2476
2477 if (!strcmp (terminal_type, "supdup"))
2478 {
2479 memory_below_frame = 1;
2480 Wcm.cm_losewrap = 1;
2481 }
2482 if (!strncmp (terminal_type, "c10", 3)
2483 || !strcmp (terminal_type, "perq"))
2484 {
2485 /* Supply a makeshift :wi string.
2486 This string is not valid in general since it works only
2487 for windows starting at the upper left corner;
2488 but that is all Emacs uses.
2489
2490 This string works only if the frame is using
2491 the top of the video memory, because addressing is memory-relative.
2492 So first check the :ti string to see if that is true.
2493
2494 It would be simpler if the :wi string could go in the termcap
2495 entry, but it can't because it is not fully valid.
2496 If it were in the termcap entry, it would confuse other programs. */
2497 if (!TS_set_window)
2498 {
2499 p = TS_termcap_modes;
2500 while (*p && strcmp (p, "\033v "))
2501 p++;
2502 if (*p)
2503 TS_set_window = "\033v%C %C %C %C ";
2504 }
2505 /* Termcap entry often fails to have :in: flag */
2506 must_write_spaces = 1;
2507 /* :ti string typically fails to have \E^G! in it */
2508 /* This limits scope of insert-char to one line. */
2509 strcpy (area, TS_termcap_modes);
2510 strcat (area, "\033\007!");
2511 TS_termcap_modes = area;
2512 area += strlen (area) + 1;
2513 p = AbsPosition;
2514 /* Change all %+ parameters to %C, to handle
2515 values above 96 correctly for the C100. */
2516 while (*p)
2517 {
2518 if (p[0] == '%' && p[1] == '+')
2519 p[1] = 'C';
2520 p++;
2521 }
2522 }
2523
2524 FrameRows = FRAME_HEIGHT (sf);
2525 FrameCols = FRAME_WIDTH (sf);
2526 specified_window = FRAME_HEIGHT (sf);
2527
2528 if (Wcm_init () == -1) /* can't do cursor motion */
2529 #ifdef VMS
2530 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2531 It lacks the ability to position the cursor.\n\
2532 If that is not the actual type of terminal you have, use either the\n\
2533 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2534 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2535 terminal_type);
2536 #else /* not VMS */
2537 # ifdef TERMINFO
2538 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2539 It lacks the ability to position the cursor.\n\
2540 If that is not the actual type of terminal you have,\n\
2541 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2542 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2543 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2544 terminal_type);
2545 # else /* TERMCAP */
2546 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2547 It lacks the ability to position the cursor.\n\
2548 If that is not the actual type of terminal you have,\n\
2549 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2550 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2551 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2552 terminal_type);
2553 # endif /* TERMINFO */
2554 #endif /*VMS */
2555 if (FRAME_HEIGHT (sf) <= 0
2556 || FRAME_WIDTH (sf) <= 0)
2557 fatal ("The frame size has not been specified");
2558
2559 delete_in_insert_mode
2560 = TS_delete_mode && TS_insert_mode
2561 && !strcmp (TS_delete_mode, TS_insert_mode);
2562
2563 se_is_so = (TS_standout_mode
2564 && TS_end_standout_mode
2565 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2566
2567 /* Remove width of standout marker from usable width of line */
2568 if (TN_standout_width > 0)
2569 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
2570
2571 UseTabs = tabs_safe_p () && TabWidth == 8;
2572
2573 scroll_region_ok
2574 = (Wcm.cm_abs
2575 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2576
2577 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2578 && (TS_del_line || TS_del_multi_lines))
2579 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2580
2581 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2582 || TS_pad_inserted_char || TS_ins_multi_chars)
2583 && (TS_del_char || TS_del_multi_chars));
2584
2585 fast_clear_end_of_line = TS_clr_line != 0;
2586
2587 init_baud_rate ();
2588 if (read_socket_hook) /* Baudrate is somewhat */
2589 /* meaningless in this case */
2590 baud_rate = 9600;
2591
2592 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2593 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2594 #endif /* WINDOWSNT */
2595 }
2596
2597 /* VARARGS 1 */
2598 void
2599 fatal (str, arg1, arg2)
2600 char *str, *arg1, *arg2;
2601 {
2602 fprintf (stderr, "emacs: ");
2603 fprintf (stderr, str, arg1, arg2);
2604 fprintf (stderr, "\n");
2605 fflush (stderr);
2606 exit (1);
2607 }
2608
2609 void
2610 syms_of_term ()
2611 {
2612 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2613 "Non-nil means the system uses terminfo rather than termcap.\n\
2614 This variable can be used by terminal emulator packages.");
2615 #ifdef TERMINFO
2616 system_uses_terminfo = 1;
2617 #else
2618 system_uses_terminfo = 0;
2619 #endif
2620
2621 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2622 "Non-nil means call this function to ring the bell.\n\
2623 The function should accept no arguments.");
2624 Vring_bell_function = Qnil;
2625
2626 defsubr (&Stty_display_color_p);
2627 }
2628