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