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