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