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