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