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