Fix tq.el edge case
[bpt/emacs.git] / src / term.c
CommitLineData
d284f58f 1/* Terminal control module for terminals described by TERMCAP
0b5538bd 2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
4e6835db 3 2002, 2003, 2004, 2005, 2006, 2007 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"
1a935bfd 41#include "blockinput.h"
a168702a 42
ff23e1dd
GM
43/* For now, don't try to include termcap.h. On some systems,
44 configure finds a non-standard termcap.h that the main build
45 won't find. */
46
47#if defined HAVE_TERMCAP_H && 0
b0f61f15 48#include <termcap.h>
46d1b2bc
DL
49#else
50extern void tputs P_ ((const char *, int, int (*)(int)));
51extern int tgetent P_ ((char *, const char *));
52extern int tgetflag P_ ((char *id));
53extern int tgetnum P_ ((char *id));
b0f61f15
GM
54#endif
55
eccec691 56#include "cm.h"
dfcf069d
AS
57#ifdef HAVE_X_WINDOWS
58#include "xterm.h"
59#endif
e0f712ba 60#ifdef MAC_OS
1a578e9b
AC
61#include "macterm.h"
62#endif
c8951b18 63
a168702a
GM
64static void turn_on_face P_ ((struct frame *, int face_id));
65static void turn_off_face P_ ((struct frame *, int face_id));
66static void tty_show_cursor P_ ((void));
67static void tty_hide_cursor P_ ((void));
68
e52f4e08 69#define OUTPUT(a) \
9882535b 70 tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
08a24c47
JB
71#define OUTPUT1(a) tputs (a, 1, cmputc)
72#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
a168702a 73
b0f61f15
GM
74#define OUTPUT_IF(a) \
75 do { \
76 if (a) \
9882535b 77 tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) \
b0f61f15
GM
78 - curY), cmputc); \
79 } while (0)
177c0ea7 80
b0f61f15 81#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
08a24c47 82
f46c2aff
KS
83/* Display space properties */
84
85extern Lisp_Object Qspace, QCalign_to, QCwidth;
86
c291d9ef 87/* Function to use to ring the bell. */
a168702a 88
c291d9ef
RS
89Lisp_Object Vring_bell_function;
90
0db017c0
SM
91/* If true, use "vs", otherwise use "ve" to make the cursor visible. */
92
93static int visible_cursor;
94
eb8c3be9 95/* Terminal characteristics that higher levels want to look at.
08a24c47
JB
96 These are all extern'd in termchar.h */
97
08a24c47
JB
98int must_write_spaces; /* Nonzero means spaces in the text
99 must actually be output; can't just skip
100 over some columns to leave them blank. */
101int min_padding_speed; /* Speed below which no padding necessary */
102
103int line_ins_del_ok; /* Terminal can insert and delete lines */
104int char_ins_del_ok; /* Terminal can insert and delete chars */
105int scroll_region_ok; /* Terminal supports setting the
106 scroll window */
be7cd44f
RS
107int scroll_region_cost; /* Cost of setting a scroll window,
108 measured in characters */
ff11dfa1 109int memory_below_frame; /* Terminal remembers lines
08a24c47
JB
110 scrolled off bottom */
111int fast_clear_end_of_line; /* Terminal has a `ce' string */
112
ff11dfa1 113/* Nonzero means no need to redraw the entire frame on resuming
08a24c47
JB
114 a suspended Emacs. This is useful on terminals with multiple pages,
115 where one page is used for Emacs and another for all else. */
a168702a 116
08a24c47
JB
117int no_redraw_on_reenter;
118
119/* Hook functions that you can set to snap out the functions in this file.
120 These are all extern'd in termhooks.h */
121
dfcf069d
AS
122void (*cursor_to_hook) P_ ((int, int));
123void (*raw_cursor_to_hook) P_ ((int, int));
dfcf069d
AS
124void (*clear_to_end_hook) P_ ((void));
125void (*clear_frame_hook) P_ ((void));
126void (*clear_end_of_line_hook) P_ ((int));
08a24c47 127
dfcf069d 128void (*ins_del_lines_hook) P_ ((int, int));
08a24c47 129
dfcf069d 130void (*delete_glyphs_hook) P_ ((int));
08a24c47 131
dfcf069d 132void (*ring_bell_hook) P_ ((void));
08a24c47 133
dfcf069d
AS
134void (*reset_terminal_modes_hook) P_ ((void));
135void (*set_terminal_modes_hook) P_ ((void));
136void (*update_begin_hook) P_ ((struct frame *));
137void (*update_end_hook) P_ ((struct frame *));
138void (*set_terminal_window_hook) P_ ((int));
a168702a
GM
139void (*insert_glyphs_hook) P_ ((struct glyph *, int));
140void (*write_glyphs_hook) P_ ((struct glyph *, int));
141void (*delete_glyphs_hook) P_ ((int));
08a24c47 142
a4ab7d75 143int (*read_socket_hook) P_ ((int, int, struct input_event *));
08a24c47 144
dfcf069d 145void (*frame_up_to_date_hook) P_ ((struct frame *));
55cc089c 146
dfcf069d 147void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
371fbaeb 148 Lisp_Object *bar_window,
a3c87d4e 149 enum scroll_bar_part *part,
20a558dc
JB
150 Lisp_Object *x,
151 Lisp_Object *y,
dfcf069d 152 unsigned long *time));
08a24c47 153
ff11dfa1 154/* When reading from a minibuffer in a different frame, Emacs wants
a168702a 155 to shift the highlight from the selected frame to the mini-buffer's
ff11dfa1 156 frame; under X, this means it lies about where the focus is.
2e146aa4
JB
157 This hook tells the window system code to re-decide where to put
158 the highlight. */
d284f58f 159
dfcf069d 160void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
2e146aa4 161
dbc4e1c1
JB
162/* If we're displaying frames using a window system that can stack
163 frames on top of each other, this hook allows you to bring a frame
164 to the front, or bury it behind all the other windows. If this
165 hook is zero, that means the device we're displaying on doesn't
166 support overlapping frames, so there's no need to raise or lower
167 anything.
168
169 If RAISE is non-zero, F is brought to the front, before all other
170 windows. If RAISE is zero, F is sent to the back, behind all other
171 windows. */
d284f58f 172
dfcf069d 173void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
dbc4e1c1 174
3d644e94
JD
175/* If the value of the frame parameter changed, whis hook is called.
176 For example, if going from fullscreen to not fullscreen this hook
177 may do something OS dependent, like extended window manager hints on X11. */
178void (*fullscreen_hook) P_ ((struct frame *f));
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
177c0ea7 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. */
d284f58f 211
dfcf069d 212void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
371fbaeb 213
a3c87d4e
JB
214/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
215 Note that it's okay to redeem a scroll bar that is not condemned. */
d284f58f 216
dfcf069d 217void (*redeem_scroll_bar_hook) P_ ((struct window *window));
20a558dc 218
a3c87d4e 219/* Remove all scroll bars on FRAME that haven't been saved since the
177c0ea7 220 last call to `*condemn_scroll_bars_hook'.
20a558dc 221
371fbaeb 222 This should be applied to each frame after each time its window
a3c87d4e
JB
223 tree is redisplayed, even if it is not displaying scroll bars at the
224 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
225 calling this and condemn_scroll_bars_hook will get rid of them.
371fbaeb
JB
226
227 If non-zero, this hook should be safe to apply to any frame,
a3c87d4e 228 whether or not it can support scroll bars, and whether or not it is
371fbaeb 229 currently displaying them. */
d284f58f 230
dfcf069d 231void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
20a558dc 232
08a24c47
JB
233/* Strings, numbers and flags taken from the termcap entry. */
234
a4decb7f 235char *TS_ins_line; /* "al" */
08a24c47
JB
236char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
237char *TS_bell; /* "bl" */
238char *TS_clr_to_bottom; /* "cd" */
239char *TS_clr_line; /* "ce", clear to end of line */
ff11dfa1 240char *TS_clr_frame; /* "cl" */
08a24c47
JB
241char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
242char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
243 lines above scroll region, lines below it,
244 total lines again) */
245char *TS_del_char; /* "dc" */
246char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
247char *TS_del_line; /* "dl" */
248char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
249char *TS_delete_mode; /* "dm", enter character-delete mode */
250char *TS_end_delete_mode; /* "ed", leave character-delete mode */
251char *TS_end_insert_mode; /* "ei", leave character-insert mode */
252char *TS_ins_char; /* "ic" */
253char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
254char *TS_insert_mode; /* "im", enter character-insert mode */
255char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
256char *TS_end_keypad_mode; /* "ke" */
257char *TS_keypad_mode; /* "ks" */
258char *TS_pad_char; /* "pc", char to use as padding */
259char *TS_repeat; /* "rp" (2 params, # times to repeat
260 and character to be repeated) */
261char *TS_end_standout_mode; /* "se" */
262char *TS_fwd_scroll; /* "sf" */
263char *TS_standout_mode; /* "so" */
264char *TS_rev_scroll; /* "sr" */
265char *TS_end_termcap_modes; /* "te" */
266char *TS_termcap_modes; /* "ti" */
267char *TS_visible_bell; /* "vb" */
a168702a
GM
268char *TS_cursor_normal; /* "ve" */
269char *TS_cursor_visible; /* "vs" */
270char *TS_cursor_invisible; /* "vi" */
08a24c47
JB
271char *TS_set_window; /* "wi" (4 params, start and end of window,
272 each as vpos and hpos) */
273
4e6ba4a4
GM
274/* Value of the "NC" (no_color_video) capability, or 0 if not
275 present. */
276
277static int TN_no_color_video;
278
279/* Meaning of bits in no_color_video. Each bit set means that the
280 corresponding attribute cannot be combined with colors. */
281
282enum no_color_bit
283{
284 NC_STANDOUT = 1 << 0,
285 NC_UNDERLINE = 1 << 1,
286 NC_REVERSE = 1 << 2,
287 NC_BLINK = 1 << 3,
288 NC_DIM = 1 << 4,
289 NC_BOLD = 1 << 5,
290 NC_INVIS = 1 << 6,
291 NC_PROTECT = 1 << 7,
292 NC_ALT_CHARSET = 1 << 8
293};
294
a168702a
GM
295/* "md" -- turn on bold (extra bright mode). */
296
297char *TS_enter_bold_mode;
298
299/* "mh" -- turn on half-bright mode. */
300
301char *TS_enter_dim_mode;
302
303/* "mb" -- enter blinking mode. */
304
305char *TS_enter_blink_mode;
306
307/* "mr" -- enter reverse video mode. */
308
309char *TS_enter_reverse_mode;
310
311/* "us"/"ue" -- start/end underlining. */
312
313char *TS_exit_underline_mode, *TS_enter_underline_mode;
314
a168702a
GM
315/* "as"/"ae" -- start/end alternate character set. Not really
316 supported, yet. */
317
318char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
319
320/* "me" -- switch appearances off. */
321
322char *TS_exit_attribute_mode;
323
324/* "Co" -- number of colors. */
325
326int TN_max_colors;
327
328/* "pa" -- max. number of color pairs on screen. Not handled yet.
329 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
330
331int TN_max_pairs;
332
333/* "op" -- SVr4 set default pair to its original value. */
334
335char *TS_orig_pair;
336
337/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
338 1 param, the color index. */
339
340char *TS_set_foreground, *TS_set_background;
341
08a24c47
JB
342int TF_hazeltine; /* termcap hz flag. */
343int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
344int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
a168702a
GM
345int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
346 non-blank position. Must clear before writing _. */
08a24c47
JB
347int TF_teleray; /* termcap xt flag: many weird consequences.
348 For t1061. */
349
08a24c47
JB
350static int RPov; /* # chars to start a TS_repeat */
351
352static int delete_in_insert_mode; /* delete mode == insert mode */
353
354static int se_is_so; /* 1 if same string both enters and leaves
355 standout mode */
356
357/* internal state */
358
8dd0c7cb 359/* The largest frame width in any call to calculate_costs. */
a168702a 360
9882535b 361int max_frame_cols;
a168702a 362
8dd0c7cb 363/* The largest frame height in any call to calculate_costs. */
a168702a 364
9882535b 365int max_frame_lines;
8dd0c7cb 366
646e4dff 367static int costs_set; /* Nonzero if costs have been calculated. */
08a24c47
JB
368
369int insert_mode; /* Nonzero when in insert mode. */
370int standout_mode; /* Nonzero when in standout mode. */
371
372/* Size of window specified by higher levels.
ff11dfa1 373 This is the number of lines, from the top of frame downwards,
08a24c47
JB
374 which can participate in insert-line/delete-line operations.
375
9882535b 376 Effectively it excludes the bottom frame_lines - specified_window_size
08a24c47
JB
377 lines from those operations. */
378
379int specified_window;
380
ff11dfa1 381/* Frame currently being redisplayed; 0 if not currently redisplaying.
08a24c47
JB
382 (Direct output does not count). */
383
ff11dfa1 384FRAME_PTR updating_frame;
08a24c47 385
07c57952 386/* Provided for lisp packages. */
a168702a 387
07c57952
KH
388static int system_uses_terminfo;
389
d284f58f
GM
390/* Flag used in tty_show/hide_cursor. */
391
392static int tty_cursor_hidden;
393
08a24c47 394char *tparam ();
e4bfb3b6
RS
395
396extern char *tgetstr ();
e882229c
NR
397
398static void term_clear_mouse_face ();
399static void term_mouse_highlight (struct frame *f, int x, int y);
08a24c47 400\f
cb28b9c2 401
1a89b7c6
AI
402#ifdef WINDOWSNT
403/* We aren't X windows, but we aren't termcap either. This makes me
404 uncertain as to what value to use for frame.output_method. For
405 this file, we'll define FRAME_TERMCAP_P to be zero so that our
406 output hooks get called instead of the termcap functions. Probably
407 the best long-term solution is to define an output_windows_nt... */
408
409#undef FRAME_TERMCAP_P
410#define FRAME_TERMCAP_P(_f_) 0
411#endif /* WINDOWSNT */
412
7e5a23bd 413#ifdef HAVE_GPM
e882229c
NR
414#include <sys/fcntl.h>
415#include "buffer.h"
416
417/* Nonzero means mouse is enabled on Linux console. */
418int term_gpm = 0;
419
420/* These variables describe the range of text currently shown in its
421 mouse-face, together with the window they apply to. As long as
422 the mouse stays within this range, we need not redraw anything on
423 its account. Rows and columns are glyph matrix positions in
424 MOUSE_FACE_WINDOW. */
425static int mouse_face_beg_row, mouse_face_beg_col;
426static int mouse_face_end_row, mouse_face_end_col;
427static int mouse_face_past_end;
94da14a0 428static Lisp_Object Qmouse_face_window;
e882229c
NR
429static int mouse_face_face_id;
430
431/* FRAME and X, Y position of mouse when last checked for
432 highlighting. X and Y can be negative or out of range for the frame. */
433struct frame *mouse_face_mouse_frame;
434int mouse_face_mouse_x, mouse_face_mouse_y;
435
436static int pos_x, pos_y;
437static int last_mouse_x, last_mouse_y;
7e5a23bd 438#endif /* HAVE_GPM */
e882229c 439
dfcf069d 440void
08a24c47
JB
441ring_bell ()
442{
d284f58f 443 if (!NILP (Vring_bell_function))
c291d9ef
RS
444 {
445 Lisp_Object function;
446
447 /* Temporarily set the global variable to nil
448 so that if we get an error, it stays nil
449 and we don't call it over and over.
450
451 We don't specbind it, because that would carefully
452 restore the bad value if there's an error
453 and make the loop of errors happen anyway. */
177c0ea7 454
c291d9ef
RS
455 function = Vring_bell_function;
456 Vring_bell_function = Qnil;
457
458 call0 (function);
459
460 Vring_bell_function = function;
08a24c47 461 }
d284f58f
GM
462 else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
463 (*ring_bell_hook) ();
464 else
465 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
08a24c47
JB
466}
467
dfcf069d 468void
08a24c47
JB
469set_terminal_modes ()
470{
d284f58f 471 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
08a24c47 472 {
3ae9c96a
RS
473 if (TS_termcap_modes)
474 OUTPUT (TS_termcap_modes);
475 else
476 {
477 /* Output enough newlines to scroll all the old screen contents
478 off the screen, so it won't be overwritten and lost. */
479 int i;
480 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
481 putchar ('\n');
482 }
483
0db017c0 484 OUTPUT_IF (visible_cursor ? TS_cursor_visible : TS_cursor_normal);
d284f58f
GM
485 OUTPUT_IF (TS_keypad_mode);
486 losecursor ();
08a24c47 487 }
d284f58f
GM
488 else
489 (*set_terminal_modes_hook) ();
08a24c47
JB
490}
491
dfcf069d 492void
08a24c47
JB
493reset_terminal_modes ()
494{
d284f58f 495 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
08a24c47 496 {
54800acb 497 turn_off_highlight ();
d284f58f
GM
498 turn_off_insert ();
499 OUTPUT_IF (TS_end_keypad_mode);
500 OUTPUT_IF (TS_cursor_normal);
501 OUTPUT_IF (TS_end_termcap_modes);
502 OUTPUT_IF (TS_orig_pair);
503 /* Output raw CR so kernel can track the cursor hpos. */
d284f58f 504 cmputc ('\r');
08a24c47 505 }
d284f58f
GM
506 else if (reset_terminal_modes_hook)
507 (*reset_terminal_modes_hook) ();
08a24c47
JB
508}
509
dfcf069d 510void
ff11dfa1 511update_begin (f)
d284f58f 512 struct frame *f;
08a24c47 513{
ff11dfa1 514 updating_frame = f;
d284f58f
GM
515 if (!FRAME_TERMCAP_P (f))
516 update_begin_hook (f);
08a24c47
JB
517}
518
dfcf069d 519void
ff11dfa1 520update_end (f)
d284f58f 521 struct frame *f;
08a24c47 522{
d284f58f 523 if (FRAME_TERMCAP_P (f))
08a24c47 524 {
d284f58f
GM
525 if (!XWINDOW (selected_window)->cursor_off_p)
526 tty_show_cursor ();
527 turn_off_insert ();
528 background_highlight ();
08a24c47 529 }
d284f58f
GM
530 else
531 update_end_hook (f);
177c0ea7 532
d284f58f 533 updating_frame = NULL;
08a24c47
JB
534}
535
dfcf069d 536void
08a24c47
JB
537set_terminal_window (size)
538 int size;
539{
d284f58f 540 if (FRAME_TERMCAP_P (updating_frame))
08a24c47 541 {
9882535b 542 specified_window = size ? size : FRAME_LINES (updating_frame);
d284f58f
GM
543 if (scroll_region_ok)
544 set_scroll_region (0, specified_window);
08a24c47 545 }
d284f58f
GM
546 else
547 set_terminal_window_hook (size);
08a24c47
JB
548}
549
dfcf069d 550void
08a24c47
JB
551set_scroll_region (start, stop)
552 int start, stop;
553{
554 char *buf;
e52f4e08 555 struct frame *sf = XFRAME (selected_frame);
177c0ea7 556
08a24c47 557 if (TS_set_scroll_region)
d284f58f 558 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
08a24c47 559 else if (TS_set_scroll_region_1)
d284f58f 560 buf = tparam (TS_set_scroll_region_1, 0, 0,
9882535b
KS
561 FRAME_LINES (sf), start,
562 FRAME_LINES (sf) - stop,
563 FRAME_LINES (sf));
08a24c47 564 else
9882535b 565 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf));
177c0ea7 566
08a24c47 567 OUTPUT (buf);
9ac0d9e0 568 xfree (buf);
08a24c47
JB
569 losecursor ();
570}
d284f58f 571
08a24c47 572\f
d284f58f 573static void
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
54800acb 589/* Handle highlighting. */
08a24c47 590
dfcf069d 591void
08a24c47
JB
592turn_off_highlight ()
593{
54800acb
MB
594 if (standout_mode)
595 OUTPUT_IF (TS_end_standout_mode);
596 standout_mode = 0;
08a24c47
JB
597}
598
d284f58f 599static void
08a24c47
JB
600turn_on_highlight ()
601{
54800acb
MB
602 if (!standout_mode)
603 OUTPUT_IF (TS_standout_mode);
604 standout_mode = 1;
08a24c47
JB
605}
606
86a7d192
GM
607static void
608toggle_highlight ()
609{
610 if (standout_mode)
611 turn_off_highlight ();
612 else
613 turn_on_highlight ();
614}
615
a168702a
GM
616
617/* Make cursor invisible. */
618
619static void
620tty_hide_cursor ()
621{
d284f58f
GM
622 if (tty_cursor_hidden == 0)
623 {
624 tty_cursor_hidden = 1;
625 OUTPUT_IF (TS_cursor_invisible);
626 }
a168702a
GM
627}
628
629
630/* Ensure that cursor is visible. */
631
632static void
633tty_show_cursor ()
634{
d284f58f
GM
635 if (tty_cursor_hidden)
636 {
637 tty_cursor_hidden = 0;
638 OUTPUT_IF (TS_cursor_normal);
0db017c0
SM
639 if (visible_cursor)
640 OUTPUT_IF (TS_cursor_visible);
d284f58f 641 }
a168702a
GM
642}
643
644
08a24c47
JB
645/* Set standout mode to the state it should be in for
646 empty space inside windows. What this is,
647 depends on the user option inverse-video. */
648
dfcf069d 649void
08a24c47
JB
650background_highlight ()
651{
08a24c47
JB
652 if (inverse_video)
653 turn_on_highlight ();
654 else
655 turn_off_highlight ();
656}
657
658/* Set standout mode to the mode specified for the text to be output. */
659
dfcf069d 660static void
08a24c47
JB
661highlight_if_desired ()
662{
8ede64a5 663 if (inverse_video)
08a24c47 664 turn_on_highlight ();
8ede64a5
MB
665 else
666 turn_off_highlight ();
08a24c47
JB
667}
668\f
669
a168702a
GM
670/* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
671 frame-relative coordinates. */
08a24c47 672
dfcf069d 673void
a168702a
GM
674cursor_to (vpos, hpos)
675 int vpos, hpos;
08a24c47 676{
e52f4e08 677 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
177c0ea7 678
e52f4e08 679 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
08a24c47 680 {
a168702a 681 (*cursor_to_hook) (vpos, hpos);
08a24c47
JB
682 return;
683 }
684
36cae867
KH
685 /* Detect the case where we are called from reset_sys_modes
686 and the costs have never been calculated. Do nothing. */
8ede64a5 687 if (! costs_set)
36cae867
KH
688 return;
689
a168702a 690 if (curY == vpos && curX == hpos)
08a24c47
JB
691 return;
692 if (!TF_standout_motion)
693 background_highlight ();
694 if (!TF_insmode_motion)
695 turn_off_insert ();
a168702a 696 cmgoto (vpos, hpos);
08a24c47
JB
697}
698
699/* Similar but don't take any account of the wasted characters. */
700
dfcf069d 701void
08a24c47 702raw_cursor_to (row, col)
4746118a 703 int row, col;
08a24c47 704{
e52f4e08
GM
705 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
706 if (! FRAME_TERMCAP_P (f))
08a24c47
JB
707 {
708 (*raw_cursor_to_hook) (row, col);
709 return;
710 }
711 if (curY == row && curX == col)
712 return;
713 if (!TF_standout_motion)
714 background_highlight ();
715 if (!TF_insmode_motion)
716 turn_off_insert ();
717 cmgoto (row, col);
718}
719\f
720/* Erase operations */
721
ff11dfa1 722/* clear from cursor to end of frame */
dfcf069d 723void
08a24c47
JB
724clear_to_end ()
725{
726 register int i;
727
759d9005 728 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
729 {
730 (*clear_to_end_hook) ();
731 return;
732 }
733 if (TS_clr_to_bottom)
734 {
735 background_highlight ();
736 OUTPUT (TS_clr_to_bottom);
08a24c47
JB
737 }
738 else
739 {
9882535b 740 for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++)
08a24c47
JB
741 {
742 cursor_to (i, 0);
9882535b 743 clear_end_of_line (FRAME_COLS (XFRAME (selected_frame)));
08a24c47
JB
744 }
745 }
746}
747
ff11dfa1 748/* Clear entire frame */
08a24c47 749
dfcf069d 750void
ff11dfa1 751clear_frame ()
08a24c47 752{
e52f4e08 753 struct frame *sf = XFRAME (selected_frame);
177c0ea7 754
ff11dfa1 755 if (clear_frame_hook
e52f4e08 756 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
08a24c47 757 {
ff11dfa1 758 (*clear_frame_hook) ();
08a24c47
JB
759 return;
760 }
ff11dfa1 761 if (TS_clr_frame)
08a24c47
JB
762 {
763 background_highlight ();
ff11dfa1 764 OUTPUT (TS_clr_frame);
08a24c47
JB
765 cmat (0, 0);
766 }
767 else
768 {
769 cursor_to (0, 0);
770 clear_to_end ();
771 }
772}
773
08a24c47
JB
774/* Clear from cursor to end of line.
775 Assume that the line is already clear starting at column first_unused_hpos.
08a24c47
JB
776
777 Note that the cursor may be moved, on terminals lacking a `ce' string. */
778
dfcf069d 779void
8ede64a5 780clear_end_of_line (first_unused_hpos)
08a24c47
JB
781 int first_unused_hpos;
782{
783 register int i;
784
785 if (clear_end_of_line_hook
1820044b 786 && ! FRAME_TERMCAP_P ((updating_frame
ff11dfa1 787 ? updating_frame
e52f4e08 788 : XFRAME (selected_frame))))
08a24c47
JB
789 {
790 (*clear_end_of_line_hook) (first_unused_hpos);
791 return;
792 }
793
36cae867
KH
794 /* Detect the case where we are called from reset_sys_modes
795 and the costs have never been calculated. Do nothing. */
8ede64a5 796 if (! costs_set)
36cae867
KH
797 return;
798
08a24c47
JB
799 if (curX >= first_unused_hpos)
800 return;
08a24c47
JB
801 background_highlight ();
802 if (TS_clr_line)
803 {
804 OUTPUT1 (TS_clr_line);
805 }
806 else
807 { /* have to do it the hard way */
e52f4e08 808 struct frame *sf = XFRAME (selected_frame);
08a24c47
JB
809 turn_off_insert ();
810
a168702a 811 /* Do not write in last row last col with Auto-wrap on. */
9882535b
KS
812 if (AutoWrap && curY == FRAME_LINES (sf) - 1
813 && first_unused_hpos == FRAME_COLS (sf))
08a24c47
JB
814 first_unused_hpos--;
815
816 for (i = curX; i < first_unused_hpos; i++)
817 {
818 if (termscript)
819 fputc (' ', termscript);
820 putchar (' ');
821 }
822 cmplus (first_unused_hpos - curX);
823 }
824}
825\f
af645abf
KH
826/* Buffer to store the source and result of code conversion for terminal. */
827static unsigned char *encode_terminal_buf;
828/* Allocated size of the above buffer. */
829static int encode_terminal_bufsize;
a4decb7f 830
af645abf
KH
831/* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
832 Set CODING->produced to the byte-length of the resulting byte
833 sequence, and return a pointer to that byte sequence. */
a4decb7f 834
302db699 835unsigned char *
af645abf 836encode_terminal_code (src, src_len, coding)
a168702a 837 struct glyph *src;
a4decb7f 838 int src_len;
af645abf 839 struct coding_system *coding;
a4decb7f 840{
feef4f84 841 struct glyph *src_end = src + src_len;
085d5908 842 register GLYPH g;
af645abf
KH
843 unsigned char *buf;
844 int nchars, nbytes, required;
a4decb7f
KH
845 register int tlen = GLYPH_TABLE_LENGTH;
846 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
6589fd67 847
af645abf
KH
848 /* Allocate sufficient size of buffer to store all characters in
849 multibyte-form. But, it may be enlarged on demand if
850 Vglyph_table contains a string. */
851 required = MAX_MULTIBYTE_LENGTH * src_len;
852 if (encode_terminal_bufsize < required)
853 {
af645abf
KH
854 if (encode_terminal_bufsize == 0)
855 encode_terminal_buf = xmalloc (required);
856 else
857 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
d6d31e57 858 encode_terminal_bufsize = required;
af645abf 859 }
a4decb7f 860
af645abf
KH
861 buf = encode_terminal_buf;
862 nchars = 0;
a4decb7f
KH
863 while (src < src_end)
864 {
a4decb7f 865 /* We must skip glyphs to be padded for a wide character. */
a168702a 866 if (! CHAR_GLYPH_PADDING_P (*src))
a4decb7f 867 {
32de38e4
KH
868 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
869
870 if (g < 0 || g >= tlen)
085d5908 871 {
32de38e4 872 /* This glyph doesn't has an entry in Vglyph_table. */
af645abf
KH
873 if (CHAR_VALID_P (src->u.ch, 0))
874 buf += CHAR_STRING (src->u.ch, buf);
32de38e4 875 else
af645abf
KH
876 *buf++ = SPACEGLYPH;
877 nchars++;
085d5908 878 }
32de38e4 879 else
a4decb7f 880 {
32de38e4 881 /* This glyph has an entry in Vglyph_table,
a4decb7f
KH
882 so process any alias before testing for simpleness. */
883 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
32de38e4
KH
884
885 if (GLYPH_SIMPLE_P (tbase, tlen, g))
886 {
af645abf
KH
887 int c = FAST_GLYPH_CHAR (g);
888
889 if (CHAR_VALID_P (c, 0))
890 buf += CHAR_STRING (c, buf);
891 else
892 *buf++ = SPACEGLYPH;
893 nchars++;
32de38e4
KH
894 }
895 else
896 {
897 /* We have a string in Vglyph_table. */
af645abf
KH
898 Lisp_Object string;
899
900 string = tbase[g];
901 if (! STRING_MULTIBYTE (string))
902 string = string_to_multibyte (string);
903 nbytes = buf - encode_terminal_buf;
fd4a9f8f 904 if (encode_terminal_bufsize < nbytes + SBYTES (string))
af645abf
KH
905 {
906 encode_terminal_bufsize = nbytes + SBYTES (string);
907 encode_terminal_buf = xrealloc (encode_terminal_buf,
908 encode_terminal_bufsize);
909 buf = encode_terminal_buf + nbytes;
910 }
911 bcopy (SDATA (string), buf, SBYTES (string));
912 buf += SBYTES (string);
913 nchars += SCHARS (string);
32de38e4 914 }
171d7f24 915 }
a4decb7f
KH
916 }
917 src++;
918 }
177c0ea7 919
af645abf
KH
920 nbytes = buf - encode_terminal_buf;
921 coding->src_multibyte = 1;
922 coding->dst_multibyte = 0;
923 if (SYMBOLP (coding->pre_write_conversion)
924 && ! NILP (Ffboundp (coding->pre_write_conversion)))
925 {
feef4f84 926 run_pre_write_conversin_on_c_str (&encode_terminal_buf,
af645abf
KH
927 &encode_terminal_bufsize,
928 nchars, nbytes, coding);
929 nchars = coding->produced_char;
930 nbytes = coding->produced;
931 }
932 required = nbytes + encoding_buffer_size (coding, nbytes);
933 if (encode_terminal_bufsize < required)
934 {
935 encode_terminal_bufsize = required;
936 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
937 }
a4decb7f 938
af645abf
KH
939 encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
940 nbytes, encode_terminal_bufsize - nbytes);
941 return encode_terminal_buf + nbytes;
942}
08a24c47 943
dfcf069d 944void
08a24c47 945write_glyphs (string, len)
a168702a 946 register struct glyph *string;
08a24c47
JB
947 register int len;
948{
e52f4e08
GM
949 struct frame *sf = XFRAME (selected_frame);
950 struct frame *f = updating_frame ? updating_frame : sf;
af645abf
KH
951 unsigned char *conversion_buffer;
952 struct coding_system *coding;
08a24c47
JB
953
954 if (write_glyphs_hook
a168702a 955 && ! FRAME_TERMCAP_P (f))
08a24c47
JB
956 {
957 (*write_glyphs_hook) (string, len);
958 return;
959 }
960
08a24c47 961 turn_off_insert ();
d284f58f 962 tty_hide_cursor ();
08a24c47 963
a168702a 964 /* Don't dare write in last column of bottom line, if Auto-Wrap,
ff11dfa1 965 since that would scroll the whole frame on some terminals. */
08a24c47
JB
966
967 if (AutoWrap
9882535b
KS
968 && curY + 1 == FRAME_LINES (sf)
969 && (curX + len) == FRAME_COLS (sf))
08a24c47 970 len --;
a4decb7f
KH
971 if (len <= 0)
972 return;
08a24c47
JB
973
974 cmplus (len);
177c0ea7 975
af645abf
KH
976 /* If terminal_coding does any conversion, use it, otherwise use
977 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
978 because it always return 1 if the member src_multibyte is 1. */
979 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
980 ? &terminal_coding : &safe_terminal_coding);
6589fd67
KH
981 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
982 the tail. */
af645abf 983 coding->mode &= ~CODING_MODE_LAST_BLOCK;
177c0ea7 984
a4decb7f 985 while (len > 0)
08a24c47 986 {
a168702a 987 /* Identify a run of glyphs with the same face. */
32de38e4 988 int face_id = string->face_id;
a168702a 989 int n;
177c0ea7 990
a168702a 991 for (n = 1; n < len; ++n)
32de38e4 992 if (string[n].face_id != face_id)
a168702a
GM
993 break;
994
995 /* Turn appearance modes of the face of the run on. */
2535aa8c 996 highlight_if_desired ();
a168702a
GM
997 turn_on_face (f, face_id);
998
af645abf
KH
999 if (n == len)
1000 /* This is the last run. */
1001 coding->mode |= CODING_MODE_LAST_BLOCK;
1002 conversion_buffer = encode_terminal_code (string, n, coding);
1003 if (coding->produced > 0)
08a24c47 1004 {
1a935bfd 1005 BLOCK_INPUT;
af645abf
KH
1006 fwrite (conversion_buffer, 1, coding->produced, stdout);
1007 if (ferror (stdout))
1008 clearerr (stdout);
1009 if (termscript)
1010 fwrite (conversion_buffer, 1, coding->produced, termscript);
1a935bfd 1011 UNBLOCK_INPUT;
08a24c47 1012 }
af645abf
KH
1013 len -= n;
1014 string += n;
a168702a
GM
1015
1016 /* Turn appearance modes off. */
1017 turn_off_face (f, face_id);
65aa5e85 1018 turn_off_highlight ();
a4decb7f 1019 }
177c0ea7 1020
9a6b6f92 1021 cmcheckmagic ();
08a24c47
JB
1022}
1023
e882229c
NR
1024void
1025write_glyphs_with_face (string, len, face_id)
1026 register struct glyph *string;
1027 register int len, face_id;
1028{
1029 struct frame *sf = XFRAME (selected_frame);
1030 struct frame *f = updating_frame ? updating_frame : sf;
1031 unsigned char *conversion_buffer;
1032 struct coding_system *coding;
1033
1034 turn_off_insert ();
1035 tty_hide_cursor ();
1036
1037 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1038 since that would scroll the whole frame on some terminals. */
1039
1040 if (AutoWrap
1041 && curY + 1 == FRAME_LINES (sf)
1042 && (curX + len) == FRAME_COLS (sf))
1043 len --;
1044 if (len <= 0)
1045 return;
1046
1047 cmplus (len);
1048
1049 /* If terminal_coding does any conversion, use it, otherwise use
1050 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
1051 because it always return 1 if the member src_multibyte is 1. */
1052 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
1053 ? &terminal_coding : &safe_terminal_coding);
1054 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1055 the tail. */
1056 coding->mode &= ~CODING_MODE_LAST_BLOCK;
1057
1058
1059 /* Turn appearance modes of the face. */
1060 highlight_if_desired ();
1061 turn_on_face (f, face_id);
1062
1063 coding->mode |= CODING_MODE_LAST_BLOCK;
1064 conversion_buffer = encode_terminal_code (string, len, coding);
1065 if (coding->produced > 0)
1066 {
1067 BLOCK_INPUT;
1068 fwrite (conversion_buffer, 1, coding->produced, stdout);
1069 if (ferror (stdout))
1070 clearerr (stdout);
1071 if (termscript)
1072 fwrite (conversion_buffer, 1, coding->produced, termscript);
1073 UNBLOCK_INPUT;
1074 }
1075
1076 /* Turn appearance modes off. */
1077 turn_off_face (f, face_id);
1078 turn_off_highlight ();
1079
1080 cmcheckmagic ();
1081}
1082
08a24c47 1083/* If start is zero, insert blanks instead of a string at start */
177c0ea7 1084
dfcf069d 1085void
08a24c47 1086insert_glyphs (start, len)
a168702a 1087 register struct glyph *start;
08a24c47
JB
1088 register int len;
1089{
1090 char *buf;
6bbd7a29 1091 struct glyph *glyph = NULL;
e52f4e08 1092 struct frame *f, *sf;
af645abf
KH
1093 unsigned char *conversion_buffer;
1094 unsigned char space[1];
1095 struct coding_system *coding;
08a24c47 1096
a4decb7f
KH
1097 if (len <= 0)
1098 return;
1099
a168702a 1100 if (insert_glyphs_hook)
08a24c47
JB
1101 {
1102 (*insert_glyphs_hook) (start, len);
1103 return;
1104 }
a168702a 1105
e52f4e08
GM
1106 sf = XFRAME (selected_frame);
1107 f = updating_frame ? updating_frame : sf;
08a24c47
JB
1108
1109 if (TS_ins_multi_chars)
1110 {
1111 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1112 OUTPUT1 (buf);
9ac0d9e0 1113 xfree (buf);
08a24c47
JB
1114 if (start)
1115 write_glyphs (start, len);
1116 return;
1117 }
1118
1119 turn_on_insert ();
1120 cmplus (len);
af645abf
KH
1121
1122 if (! start)
1123 space[0] = SPACEGLYPH;
1124
1125 /* If terminal_coding does any conversion, use it, otherwise use
1126 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
1127 because it always return 1 if the member src_multibyte is 1. */
1128 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
1129 ? &terminal_coding : &safe_terminal_coding);
1130 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1131 the tail. */
1132 coding->mode &= ~CODING_MODE_LAST_BLOCK;
1133
07109bf9 1134 while (len-- > 0)
08a24c47
JB
1135 {
1136 OUTPUT1_IF (TS_ins_char);
1137 if (!start)
32de38e4 1138 {
af645abf
KH
1139 conversion_buffer = space;
1140 coding->produced = 1;
32de38e4 1141 }
08a24c47 1142 else
08a24c47 1143 {
65aa5e85 1144 highlight_if_desired ();
32de38e4 1145 turn_on_face (f, start->face_id);
816be8b8 1146 glyph = start;
a168702a 1147 ++start;
a4decb7f
KH
1148 /* We must open sufficient space for a character which
1149 occupies more than one column. */
a168702a 1150 while (len && CHAR_GLYPH_PADDING_P (*start))
a4decb7f
KH
1151 {
1152 OUTPUT1_IF (TS_ins_char);
1153 start++, len--;
1154 }
a4decb7f 1155
32de38e4
KH
1156 if (len <= 0)
1157 /* This is the last glyph. */
af645abf 1158 coding->mode |= CODING_MODE_LAST_BLOCK;
32de38e4 1159
af645abf 1160 conversion_buffer = encode_terminal_code (glyph, 1, coding);
32de38e4 1161 }
a4decb7f 1162
af645abf 1163 if (coding->produced > 0)
08a24c47 1164 {
1a935bfd 1165 BLOCK_INPUT;
af645abf 1166 fwrite (conversion_buffer, 1, coding->produced, stdout);
08a24c47
JB
1167 if (ferror (stdout))
1168 clearerr (stdout);
1169 if (termscript)
af645abf 1170 fwrite (conversion_buffer, 1, coding->produced, termscript);
1a935bfd 1171 UNBLOCK_INPUT;
08a24c47
JB
1172 }
1173
9a6b6f92 1174 OUTPUT1_IF (TS_pad_inserted_char);
32de38e4 1175 if (start)
65aa5e85
GM
1176 {
1177 turn_off_face (f, glyph->face_id);
1178 turn_off_highlight ();
1179 }
9a6b6f92 1180 }
177c0ea7 1181
9a6b6f92 1182 cmcheckmagic ();
08a24c47
JB
1183}
1184
dfcf069d 1185void
08a24c47
JB
1186delete_glyphs (n)
1187 register int n;
1188{
1189 char *buf;
1190 register int i;
1191
1820044b 1192 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
1193 {
1194 (*delete_glyphs_hook) (n);
1195 return;
1196 }
1197
1198 if (delete_in_insert_mode)
1199 {
1200 turn_on_insert ();
1201 }
1202 else
1203 {
1204 turn_off_insert ();
1205 OUTPUT_IF (TS_delete_mode);
1206 }
1207
1208 if (TS_del_multi_chars)
1209 {
1210 buf = tparam (TS_del_multi_chars, 0, 0, n);
1211 OUTPUT1 (buf);
9ac0d9e0 1212 xfree (buf);
08a24c47
JB
1213 }
1214 else
1215 for (i = 0; i < n; i++)
1216 OUTPUT1 (TS_del_char);
1217 if (!delete_in_insert_mode)
1218 OUTPUT_IF (TS_end_delete_mode);
1219}
1220\f
1221/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1222
dfcf069d 1223void
08a24c47
JB
1224ins_del_lines (vpos, n)
1225 int vpos, n;
1226{
1227 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1228 char *single = n > 0 ? TS_ins_line : TS_del_line;
1229 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
e52f4e08 1230 struct frame *sf;
08a24c47
JB
1231
1232 register int i = n > 0 ? n : -n;
1233 register char *buf;
1234
1820044b 1235 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
1236 {
1237 (*ins_del_lines_hook) (vpos, n);
1238 return;
1239 }
1240
e52f4e08 1241 sf = XFRAME (selected_frame);
177c0ea7 1242
08a24c47
JB
1243 /* If the lines below the insertion are being pushed
1244 into the end of the window, this is the same as clearing;
1245 and we know the lines are already clear, since the matching
1246 deletion has already been done. So can ignore this. */
1247 /* If the lines below the deletion are blank lines coming
1248 out of the end of the window, don't bother,
1249 as there will be a matching inslines later that will flush them. */
1250 if (scroll_region_ok && vpos + i >= specified_window)
1251 return;
9882535b 1252 if (!memory_below_frame && vpos + i >= FRAME_LINES (sf))
08a24c47
JB
1253 return;
1254
1255 if (multi)
1256 {
1257 raw_cursor_to (vpos, 0);
1258 background_highlight ();
1259 buf = tparam (multi, 0, 0, i);
1260 OUTPUT (buf);
9ac0d9e0 1261 xfree (buf);
08a24c47
JB
1262 }
1263 else if (single)
1264 {
1265 raw_cursor_to (vpos, 0);
1266 background_highlight ();
1267 while (--i >= 0)
1268 OUTPUT (single);
1269 if (TF_teleray)
1270 curX = 0;
1271 }
1272 else
1273 {
1274 set_scroll_region (vpos, specified_window);
1275 if (n < 0)
1276 raw_cursor_to (specified_window - 1, 0);
1277 else
1278 raw_cursor_to (vpos, 0);
1279 background_highlight ();
1280 while (--i >= 0)
1281 OUTPUTL (scroll, specified_window - vpos);
1282 set_scroll_region (0, specified_window);
1283 }
1284
ff11dfa1 1285 if (!scroll_region_ok && memory_below_frame && n < 0)
08a24c47 1286 {
9882535b 1287 cursor_to (FRAME_LINES (sf) + n, 0);
08a24c47
JB
1288 clear_to_end ();
1289 }
1290}
1291\f
1292/* Compute cost of sending "str", in characters,
1293 not counting any line-dependent padding. */
1294
1295int
1296string_cost (str)
1297 char *str;
1298{
1299 cost = 0;
1300 if (str)
1301 tputs (str, 0, evalcost);
1302 return cost;
1303}
1304
1305/* Compute cost of sending "str", in characters,
1306 counting any line-dependent padding at one line. */
1307
1308static int
1309string_cost_one_line (str)
1310 char *str;
1311{
1312 cost = 0;
1313 if (str)
1314 tputs (str, 1, evalcost);
1315 return cost;
1316}
1317
1318/* Compute per line amount of line-dependent padding,
1319 in tenths of characters. */
1320
1321int
1322per_line_cost (str)
1323 register char *str;
1324{
1325 cost = 0;
1326 if (str)
1327 tputs (str, 0, evalcost);
1328 cost = - cost;
1329 if (str)
1330 tputs (str, 10, evalcost);
1331 return cost;
1332}
1333
1334#ifndef old
1335/* char_ins_del_cost[n] is cost of inserting N characters.
8dd0c7cb 1336 char_ins_del_cost[-n] is cost of deleting N characters.
9882535b 1337 The length of this vector is based on max_frame_cols. */
08a24c47
JB
1338
1339int *char_ins_del_vector;
1340
9882535b 1341#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
08a24c47
JB
1342#endif
1343
1344/* ARGSUSED */
1345static void
ff11dfa1
JB
1346calculate_ins_del_char_costs (frame)
1347 FRAME_PTR frame;
08a24c47
JB
1348{
1349 int ins_startup_cost, del_startup_cost;
1350 int ins_cost_per_char, del_cost_per_char;
1351 register int i;
1352 register int *p;
1353
1354 if (TS_ins_multi_chars)
1355 {
1356 ins_cost_per_char = 0;
1357 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1358 }
1359 else if (TS_ins_char || TS_pad_inserted_char
1360 || (TS_insert_mode && TS_end_insert_mode))
1361 {
1362 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1363 + string_cost (TS_end_insert_mode))) / 100;
1364 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1365 + string_cost_one_line (TS_pad_inserted_char));
1366 }
1367 else
1368 {
1369 ins_startup_cost = 9999;
1370 ins_cost_per_char = 0;
1371 }
1372
1373 if (TS_del_multi_chars)
1374 {
1375 del_cost_per_char = 0;
1376 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1377 }
1378 else if (TS_del_char)
1379 {
1380 del_startup_cost = (string_cost (TS_delete_mode)
1381 + string_cost (TS_end_delete_mode));
1382 if (delete_in_insert_mode)
1383 del_startup_cost /= 2;
1384 del_cost_per_char = string_cost_one_line (TS_del_char);
1385 }
1386 else
1387 {
1388 del_startup_cost = 9999;
1389 del_cost_per_char = 0;
1390 }
1391
1392 /* Delete costs are at negative offsets */
ff11dfa1 1393 p = &char_ins_del_cost (frame)[0];
9882535b 1394 for (i = FRAME_COLS (frame); --i >= 0;)
08a24c47
JB
1395 *--p = (del_startup_cost += del_cost_per_char);
1396
1397 /* Doing nothing is free */
ff11dfa1 1398 p = &char_ins_del_cost (frame)[0];
08a24c47
JB
1399 *p++ = 0;
1400
1401 /* Insert costs are at positive offsets */
9882535b 1402 for (i = FRAME_COLS (frame); --i >= 0;)
08a24c47
JB
1403 *p++ = (ins_startup_cost += ins_cost_per_char);
1404}
1405
dfcf069d 1406void
ff11dfa1
JB
1407calculate_costs (frame)
1408 FRAME_PTR frame;
08a24c47 1409{
9f732a77
RS
1410 register char *f = (TS_set_scroll_region
1411 ? TS_set_scroll_region
1412 : TS_set_scroll_region_1);
08a24c47 1413
9f732a77 1414 FRAME_COST_BAUD_RATE (frame) = baud_rate;
08a24c47 1415
be7cd44f 1416 scroll_region_cost = string_cost (f);
08a24c47
JB
1417
1418 /* These variables are only used for terminal stuff. They are allocated
ff11dfa1 1419 once for the terminal frame of X-windows emacs, but not used afterwards.
08a24c47
JB
1420
1421 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
8ede64a5 1422 X turns off char_ins_del_ok. */
08a24c47 1423
9882535b
KS
1424 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1425 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
8dd0c7cb 1426
8ede64a5 1427 costs_set = 1;
08a24c47
JB
1428
1429 if (char_ins_del_vector != 0)
1430 char_ins_del_vector
1431 = (int *) xrealloc (char_ins_del_vector,
1432 (sizeof (int)
9882535b 1433 + 2 * max_frame_cols * sizeof (int)));
08a24c47
JB
1434 else
1435 char_ins_del_vector
1436 = (int *) xmalloc (sizeof (int)
9882535b 1437 + 2 * max_frame_cols * sizeof (int));
08a24c47 1438
08a24c47 1439 bzero (char_ins_del_vector, (sizeof (int)
9882535b 1440 + 2 * max_frame_cols * sizeof (int)));
08a24c47 1441
ff11dfa1
JB
1442 if (f && (!TS_ins_line && !TS_del_line))
1443 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1444 TS_rev_scroll, TS_ins_multi_lines,
1445 TS_fwd_scroll, TS_del_multi_lines,
ff11dfa1 1446 f, f, 1);
08a24c47 1447 else
ff11dfa1 1448 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1449 TS_ins_line, TS_ins_multi_lines,
1450 TS_del_line, TS_del_multi_lines,
1451 0, 0, 1);
1452
ff11dfa1 1453 calculate_ins_del_char_costs (frame);
08a24c47
JB
1454
1455 /* Don't use TS_repeat if its padding is worse than sending the chars */
1456 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1457 RPov = string_cost (TS_repeat);
1458 else
9882535b 1459 RPov = FRAME_COLS (frame) * 2;
08a24c47
JB
1460
1461 cmcostinit (); /* set up cursor motion costs */
1462}
1463\f
a796ac82
JB
1464struct fkey_table {
1465 char *cap, *name;
1466};
1467
01d8deb0
ER
1468 /* Termcap capability names that correspond directly to X keysyms.
1469 Some of these (marked "terminfo") aren't supplied by old-style
1470 (Berkeley) termcap entries. They're listed in X keysym order;
1471 except we put the keypad keys first, so that if they clash with
1472 other keys (as on the IBM PC keyboard) they get overridden.
1473 */
1474
a168702a
GM
1475static struct fkey_table keys[] =
1476{
8103ad1a
PJ
1477 {"kh", "home"}, /* termcap */
1478 {"kl", "left"}, /* termcap */
1479 {"ku", "up"}, /* termcap */
1480 {"kr", "right"}, /* termcap */
1481 {"kd", "down"}, /* termcap */
1482 {"%8", "prior"}, /* terminfo */
1483 {"%5", "next"}, /* terminfo */
1484 {"@7", "end"}, /* terminfo */
1485 {"@1", "begin"}, /* terminfo */
1486 {"*6", "select"}, /* terminfo */
1487 {"%9", "print"}, /* terminfo */
1488 {"@4", "execute"}, /* terminfo --- actually the `command' key */
01d8deb0
ER
1489 /*
1490 * "insert" --- see below
1491 */
8103ad1a
PJ
1492 {"&8", "undo"}, /* terminfo */
1493 {"%0", "redo"}, /* terminfo */
1494 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1495 {"@0", "find"}, /* terminfo */
1496 {"@2", "cancel"}, /* terminfo */
1497 {"%1", "help"}, /* terminfo */
01d8deb0
ER
1498 /*
1499 * "break" goes here, but can't be reliably intercepted with termcap
1500 */
8103ad1a 1501 {"&4", "reset"}, /* terminfo --- actually `restart' */
01d8deb0
ER
1502 /*
1503 * "system" and "user" --- no termcaps
1504 */
8103ad1a
PJ
1505 {"kE", "clearline"}, /* terminfo */
1506 {"kA", "insertline"}, /* terminfo */
1507 {"kL", "deleteline"}, /* terminfo */
1508 {"kI", "insertchar"}, /* terminfo */
1509 {"kD", "deletechar"}, /* terminfo */
1510 {"kB", "backtab"}, /* terminfo */
01d8deb0
ER
1511 /*
1512 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1513 */
8103ad1a 1514 {"@8", "kp-enter"}, /* terminfo */
01d8deb0
ER
1515 /*
1516 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1517 * "kp-multiply", "kp-add", "kp-separator",
1518 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1519 * --- no termcaps for any of these.
1520 */
8103ad1a 1521 {"K4", "kp-1"}, /* terminfo */
01d8deb0
ER
1522 /*
1523 * "kp-2" --- no termcap
1524 */
8103ad1a 1525 {"K5", "kp-3"}, /* terminfo */
01d8deb0
ER
1526 /*
1527 * "kp-4" --- no termcap
1528 */
8103ad1a 1529 {"K2", "kp-5"}, /* terminfo */
01d8deb0
ER
1530 /*
1531 * "kp-6" --- no termcap
1532 */
8103ad1a 1533 {"K1", "kp-7"}, /* terminfo */
01d8deb0
ER
1534 /*
1535 * "kp-8" --- no termcap
1536 */
8103ad1a 1537 {"K3", "kp-9"}, /* terminfo */
01d8deb0
ER
1538 /*
1539 * "kp-equal" --- no termcap
1540 */
8103ad1a
PJ
1541 {"k1", "f1"},
1542 {"k2", "f2"},
1543 {"k3", "f3"},
1544 {"k4", "f4"},
1545 {"k5", "f5"},
1546 {"k6", "f6"},
1547 {"k7", "f7"},
1548 {"k8", "f8"},
60ec7b7e
DN
1549 {"k9", "f9"},
1550
1551 {"&0", "S-cancel"}, /*shifted cancel key*/
1552 {"&9", "S-begin"}, /*shifted begin key*/
1553 {"*0", "S-find"}, /*shifted find key*/
1554 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1555 {"*4", "S-delete"}, /*shifted delete-character key*/
1556 {"*7", "S-end"}, /*shifted end key*/
1557 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1558 {"#1", "S-help"}, /*shifted help key*/
1559 {"#2", "S-home"}, /*shifted home key*/
1560 {"#3", "S-insert"}, /*shifted insert-character key*/
1561 {"#4", "S-left"}, /*shifted left-arrow key*/
1562 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1563 {"%c", "S-next"}, /*shifted next key*/
1564 {"%e", "S-prior"}, /*shifted previous key*/
1565 {"%f", "S-print"}, /*shifted print key*/
1566 {"%g", "S-redo"}, /*shifted redo key*/
1567 {"%i", "S-right"}, /*shifted right-arrow key*/
1568 {"!3", "S-undo"} /*shifted undo key*/
a796ac82
JB
1569 };
1570
f2a00342
RM
1571static char **term_get_fkeys_arg;
1572static Lisp_Object term_get_fkeys_1 ();
465db27b 1573
01d8deb0 1574/* Find the escape codes sent by the function keys for Vfunction_key_map.
177c0ea7 1575 This function scans the termcap function key sequence entries, and
01d8deb0
ER
1576 adds entries to Vfunction_key_map for each function key it finds. */
1577
5c2c7893
JB
1578void
1579term_get_fkeys (address)
1580 char **address;
f2a00342
RM
1581{
1582 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1583 errors during the call. The only errors should be from Fdefine_key
1584 when given a key sequence containing an invalid prefix key. If the
1585 termcap defines function keys which use a prefix that is already bound
1586 to a command by the default bindings, we should silently ignore that
1587 function key specification, rather than giving the user an error and
1588 refusing to run at all on such a terminal. */
1589
1590 extern Lisp_Object Fidentity ();
f2a00342
RM
1591 term_get_fkeys_arg = address;
1592 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1593}
1594
1595static Lisp_Object
1596term_get_fkeys_1 ()
5c2c7893 1597{
5c2c7893
JB
1598 int i;
1599
37085233 1600 char **address = term_get_fkeys_arg;
f778aff2 1601
3e65092f
RS
1602 /* This can happen if CANNOT_DUMP or with strange options. */
1603 if (!initialized)
1604 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1605
5c2c7893
JB
1606 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1607 {
1608 char *sequence = tgetstr (keys[i].cap, address);
1609 if (sequence)
f2a00342
RM
1610 Fdefine_key (Vfunction_key_map, build_string (sequence),
1611 Fmake_vector (make_number (1),
1612 intern (keys[i].name)));
5c2c7893 1613 }
a796ac82
JB
1614
1615 /* The uses of the "k0" capability are inconsistent; sometimes it
1616 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
eb8c3be9 1617 We will attempt to politely accommodate both systems by testing for
a796ac82
JB
1618 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1619 */
1620 {
1621 char *k_semi = tgetstr ("k;", address);
1622 char *k0 = tgetstr ("k0", address);
1623 char *k0_name = "f10";
1624
1625 if (k_semi)
1626 {
95c11956
SM
1627 if (k0)
1628 /* Define f0 first, so that f10 takes precedence in case the
1629 key sequences happens to be the same. */
1630 Fdefine_key (Vfunction_key_map, build_string (k0),
1631 Fmake_vector (make_number (1), intern ("f0")));
f2a00342
RM
1632 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1633 Fmake_vector (make_number (1), intern ("f10")));
a796ac82 1634 }
95c11956 1635 else if (k0)
f2a00342
RM
1636 Fdefine_key (Vfunction_key_map, build_string (k0),
1637 Fmake_vector (make_number (1), intern (k0_name)));
a796ac82 1638 }
01d8deb0
ER
1639
1640 /* Set up cookies for numbered function keys above f10. */
1641 {
1642 char fcap[3], fkey[4];
1643
fc4f24da 1644 fcap[0] = 'F'; fcap[2] = '\0';
01d8deb0
ER
1645 for (i = 11; i < 64; i++)
1646 {
1647 if (i <= 19)
1648 fcap[1] = '1' + i - 11;
1649 else if (i <= 45)
b59ab95c 1650 fcap[1] = 'A' + i - 20;
01d8deb0 1651 else
b59ab95c 1652 fcap[1] = 'a' + i - 46;
01d8deb0 1653
fc4f24da
RS
1654 {
1655 char *sequence = tgetstr (fcap, address);
1656 if (sequence)
1657 {
465db27b 1658 sprintf (fkey, "f%d", i);
f2a00342
RM
1659 Fdefine_key (Vfunction_key_map, build_string (sequence),
1660 Fmake_vector (make_number (1),
1661 intern (fkey)));
fc4f24da
RS
1662 }
1663 }
01d8deb0
ER
1664 }
1665 }
1666
1667 /*
1668 * Various mappings to try and get a better fit.
1669 */
1670 {
fc4f24da
RS
1671#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1672 if (!tgetstr (cap1, address)) \
1673 { \
1674 char *sequence = tgetstr (cap2, address); \
1675 if (sequence) \
f2a00342
RM
1676 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1677 Fmake_vector (make_number (1), \
1678 intern (sym))); \
fc4f24da 1679 }
177c0ea7 1680
01d8deb0 1681 /* if there's no key_next keycap, map key_npage to `next' keysym */
27b61785 1682 CONDITIONAL_REASSIGN ("%5", "kN", "next");
01d8deb0 1683 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
381d11a1 1684 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
01d8deb0 1685 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
27b61785 1686 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
403c995b
RS
1687 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1688 CONDITIONAL_REASSIGN ("@7", "kH", "end");
0a7f697a
KH
1689
1690 /* IBM has their own non-standard dialect of terminfo.
1691 If the standard name isn't found, try the IBM name. */
1692 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1693 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1694 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1695 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1696 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1697 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1698 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1699 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1700 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1dd40212 1701#undef CONDITIONAL_REASSIGN
01d8deb0 1702 }
a168702a
GM
1703
1704 return Qnil;
5c2c7893
JB
1705}
1706
1707\f
a168702a
GM
1708/***********************************************************************
1709 Character Display Information
1710 ***********************************************************************/
1711
47021b11
KS
1712/* Avoid name clash with functions defined in xterm.c */
1713#ifdef static
1714#define append_glyph append_glyph_term
1715#define produce_stretch_glyph produce_stretch_glyph_term
1716#endif
1717
a168702a 1718static void append_glyph P_ ((struct it *));
f46c2aff 1719static void produce_stretch_glyph P_ ((struct it *));
a168702a
GM
1720
1721
1722/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
d2b4c17d
KH
1723 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1724 the character for which to produce glyphs; IT->face_id contains the
1725 character's face. Padding glyphs are appended if IT->c has a
1726 IT->pixel_width > 1. */
177c0ea7 1727
a168702a
GM
1728static void
1729append_glyph (it)
1730 struct it *it;
1731{
1732 struct glyph *glyph, *end;
1733 int i;
1734
1735 xassert (it->glyph_row);
1736 glyph = (it->glyph_row->glyphs[it->area]
1737 + it->glyph_row->used[it->area]);
1738 end = it->glyph_row->glyphs[1 + it->area];
1739
177c0ea7
JB
1740 for (i = 0;
1741 i < it->pixel_width && glyph < end;
a168702a
GM
1742 ++i)
1743 {
1744 glyph->type = CHAR_GLYPH;
d13f3e2e 1745 glyph->pixel_width = 1;
d2b4c17d 1746 glyph->u.ch = it->char_to_display;
32de38e4
KH
1747 glyph->face_id = it->face_id;
1748 glyph->padding_p = i > 0;
a168702a
GM
1749 glyph->charpos = CHARPOS (it->position);
1750 glyph->object = it->object;
177c0ea7 1751
a168702a
GM
1752 ++it->glyph_row->used[it->area];
1753 ++glyph;
1754 }
1755}
1756
1757
b50fe468
RS
1758/* Produce glyphs for the display element described by IT. *IT
1759 specifies what we want to produce a glyph for (character, image, ...),
1760 and where in the glyph matrix we currently are (glyph row and hpos).
1761 produce_glyphs fills in output fields of *IT with information such as the
1762 pixel width and height of a character, and maybe output actual glyphs at
a168702a 1763 the same time if IT->glyph_row is non-null. See the explanation of
b50fe468
RS
1764 struct display_iterator in dispextern.h for an overview.
1765
1766 produce_glyphs also stores the result of glyph width, ascent
1767 etc. computations in *IT.
1768
1769 IT->glyph_row may be null, in which case produce_glyphs does not
1770 actually fill in the glyphs. This is used in the move_* functions
1771 in xdisp.c for text width and height computations.
1772
1773 Callers usually don't call produce_glyphs directly;
1774 instead they use the macro PRODUCE_GLYPHS. */
a168702a 1775
177c0ea7 1776void
a168702a
GM
1777produce_glyphs (it)
1778 struct it *it;
1779{
1780 /* If a hook is installed, let it do the work. */
1781 xassert (it->what == IT_CHARACTER
c7cba11d 1782 || it->what == IT_COMPOSITION
a168702a 1783 || it->what == IT_STRETCH);
177c0ea7 1784
f46c2aff
KS
1785 if (it->what == IT_STRETCH)
1786 {
1787 produce_stretch_glyph (it);
1788 goto done;
1789 }
1790
c7cba11d
KH
1791 /* Nothing but characters are supported on terminal frames. For a
1792 composition sequence, it->c is the first character of the
1793 sequence. */
1794 xassert (it->what == IT_CHARACTER
1795 || it->what == IT_COMPOSITION);
a168702a 1796
d2b4c17d
KH
1797 /* Maybe translate single-byte characters to multibyte. */
1798 it->char_to_display = it->c;
1799
a168702a
GM
1800 if (it->c >= 040 && it->c < 0177)
1801 {
1802 it->pixel_width = it->nglyphs = 1;
1803 if (it->glyph_row)
1804 append_glyph (it);
1805 }
1806 else if (it->c == '\n')
1807 it->pixel_width = it->nglyphs = 0;
1808 else if (it->c == '\t')
1809 {
2efdbcdd 1810 int absolute_x = (it->current_x
a168702a 1811 + it->continuation_lines_width);
177c0ea7
JB
1812 int next_tab_x
1813 = (((1 + absolute_x + it->tab_width - 1)
a168702a
GM
1814 / it->tab_width)
1815 * it->tab_width);
1816 int nspaces;
1817
1818 /* If part of the TAB has been displayed on the previous line
1819 which is continued now, continuation_lines_width will have
1820 been incremented already by the part that fitted on the
1821 continued line. So, we will get the right number of spaces
1822 here. */
1823 nspaces = next_tab_x - absolute_x;
177c0ea7 1824
a168702a
GM
1825 if (it->glyph_row)
1826 {
1827 int n = nspaces;
177c0ea7 1828
d2b4c17d 1829 it->char_to_display = ' ';
a168702a 1830 it->pixel_width = it->len = 1;
177c0ea7 1831
a168702a
GM
1832 while (n--)
1833 append_glyph (it);
a168702a
GM
1834 }
1835
1836 it->pixel_width = nspaces;
1837 it->nglyphs = nspaces;
1838 }
add44890
EZ
1839 else if (SINGLE_BYTE_CHAR_P (it->c))
1840 {
d2b4c17d
KH
1841 if (unibyte_display_via_language_environment
1842 && (it->c >= 0240
1843 || !NILP (Vnonascii_translation_table)))
1844 {
1845 int charset;
1846
1847 it->char_to_display = unibyte_char_to_multibyte (it->c);
1848 charset = CHAR_CHARSET (it->char_to_display);
1849 it->pixel_width = CHARSET_WIDTH (charset);
1850 it->nglyphs = it->pixel_width;
1851 if (it->glyph_row)
1852 append_glyph (it);
1853 }
1854 else
1855 {
1856 /* Coming here means that it->c is from display table, thus we
1857 must send the code as is to the terminal. Although there's
1858 no way to know how many columns it occupies on a screen, it
1859 is a good assumption that a single byte code has 1-column
1860 width. */
1861 it->pixel_width = it->nglyphs = 1;
1862 if (it->glyph_row)
1863 append_glyph (it);
1864 }
add44890 1865 }
a168702a
GM
1866 else
1867 {
c7cba11d
KH
1868 /* A multi-byte character. The display width is fixed for all
1869 characters of the set. Some of the glyphs may have to be
1870 ignored because they are already displayed in a continued
1871 line. */
a168702a
GM
1872 int charset = CHAR_CHARSET (it->c);
1873
c7cba11d 1874 it->pixel_width = CHARSET_WIDTH (charset);
a168702a 1875 it->nglyphs = it->pixel_width;
177c0ea7 1876
a168702a
GM
1877 if (it->glyph_row)
1878 append_glyph (it);
1879 }
1880
f46c2aff 1881 done:
177c0ea7 1882 /* Advance current_x by the pixel width as a convenience for
a168702a
GM
1883 the caller. */
1884 if (it->area == TEXT_AREA)
1885 it->current_x += it->pixel_width;
cfe8a05e
GM
1886 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1887 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
a168702a
GM
1888}
1889
1890
f46c2aff
KS
1891/* Produce a stretch glyph for iterator IT. IT->object is the value
1892 of the glyph property displayed. The value must be a list
1893 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1894 being recognized:
1895
1896 1. `:width WIDTH' specifies that the space should be WIDTH *
1897 canonical char width wide. WIDTH may be an integer or floating
1898 point number.
1899
1900 2. `:align-to HPOS' specifies that the space should be wide enough
1901 to reach HPOS, a value in canonical character units. */
1902
1903static void
1904produce_stretch_glyph (it)
1905 struct it *it;
1906{
1907 /* (space :width WIDTH ...) */
1908 Lisp_Object prop, plist;
1909 int width = 0, align_to = -1;
1910 int zero_width_ok_p = 0;
1911 double tem;
1912
1913 /* List should start with `space'. */
1914 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1915 plist = XCDR (it->object);
1916
1917 /* Compute the width of the stretch. */
1918 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1919 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1920 {
1921 /* Absolute width `:width WIDTH' specified and valid. */
1922 zero_width_ok_p = 1;
1923 width = (int)(tem + 0.5);
1924 }
1925 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1926 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1927 {
1928 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
feef4f84 1929 align_to = (align_to < 0
f46c2aff
KS
1930 ? 0
1931 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1932 else if (align_to < 0)
1933 align_to = window_box_left_offset (it->w, TEXT_AREA);
1934 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1935 zero_width_ok_p = 1;
1936 }
1937 else
1938 /* Nothing specified -> width defaults to canonical char width. */
1939 width = FRAME_COLUMN_WIDTH (it->f);
1940
1941 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1942 width = 1;
1943
1944 if (width > 0 && it->glyph_row)
1945 {
1946 Lisp_Object o_object = it->object;
1947 Lisp_Object object = it->stack[it->sp - 1].string;
1948 int n = width;
f46c2aff
KS
1949
1950 if (!STRINGP (object))
1951 object = it->w->buffer;
1952 it->object = object;
d2b4c17d 1953 it->char_to_display = ' ';
f46c2aff
KS
1954 it->pixel_width = it->len = 1;
1955 while (n--)
1956 append_glyph (it);
1957 it->object = o_object;
f46c2aff
KS
1958 }
1959 it->pixel_width = width;
1960 it->nglyphs = width;
1961}
1962
1963
a168702a
GM
1964/* Get information about special display element WHAT in an
1965 environment described by IT. WHAT is one of IT_TRUNCATION or
1966 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1967 non-null glyph_row member. This function ensures that fields like
1968 face_id, c, len of IT are left untouched. */
1969
1970void
1971produce_special_glyphs (it, what)
1972 struct it *it;
1973 enum display_element_type what;
1974{
1975 struct it temp_it;
072d84a6 1976 GLYPH glyph;
177c0ea7 1977
a168702a
GM
1978 temp_it = *it;
1979 temp_it.dp = NULL;
1980 temp_it.what = IT_CHARACTER;
1981 temp_it.len = 1;
7c752c80 1982 temp_it.object = make_number (0);
a168702a
GM
1983 bzero (&temp_it.current, sizeof temp_it.current);
1984
1985 if (what == IT_CONTINUATION)
1986 {
1987 /* Continuation glyph. */
1988 if (it->dp
1989 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1990 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1991 {
072d84a6
RS
1992 glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
1993 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
a168702a
GM
1994 }
1995 else
072d84a6 1996 glyph = '\\';
a168702a
GM
1997 }
1998 else if (what == IT_TRUNCATION)
1999 {
2000 /* Truncation glyph. */
2001 if (it->dp
2002 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
2003 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
2004 {
072d84a6
RS
2005 glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
2006 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
a168702a
GM
2007 }
2008 else
072d84a6 2009 glyph = '$';
a168702a
GM
2010 }
2011 else
2012 abort ();
072d84a6
RS
2013
2014 temp_it.c = FAST_GLYPH_CHAR (glyph);
2015 temp_it.face_id = FAST_GLYPH_FACE (glyph);
2016 temp_it.len = CHAR_BYTES (temp_it.c);
2017
2018 produce_glyphs (&temp_it);
2019 it->pixel_width = temp_it.pixel_width;
2020 it->nglyphs = temp_it.pixel_width;
a168702a
GM
2021}
2022
2023
a168702a
GM
2024\f
2025/***********************************************************************
2026 Faces
2027 ***********************************************************************/
2028
4e6ba4a4
GM
2029/* Value is non-zero if attribute ATTR may be used. ATTR should be
2030 one of the enumerators from enum no_color_bit, or a bit set built
2031 from them. Some display attributes may not be used together with
2032 color; the termcap capability `NC' specifies which ones. */
2033
2034#define MAY_USE_WITH_COLORS_P(ATTR) \
2035 (TN_max_colors > 0 \
2036 ? (TN_no_color_video & (ATTR)) == 0 \
2037 : 1)
a168702a 2038
072d84a6
RS
2039/* Turn appearances of face FACE_ID on tty frame F on.
2040 FACE_ID is a realized face ID number, in the face cache. */
a168702a
GM
2041
2042static void
2043turn_on_face (f, face_id)
2044 struct frame *f;
2045 int face_id;
2046{
2047 struct face *face = FACE_FROM_ID (f, face_id);
86a7d192
GM
2048 long fg = face->foreground;
2049 long bg = face->background;
a168702a 2050
86a7d192
GM
2051 /* Do this first because TS_end_standout_mode may be the same
2052 as TS_exit_attribute_mode, which turns all appearances off. */
2053 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
2054 {
2055 if (TN_max_colors > 0)
2056 {
2057 if (fg >= 0 && bg >= 0)
2058 {
2059 /* If the terminal supports colors, we can set them
2060 below without using reverse video. The face's fg
2061 and bg colors are set as they should appear on
2062 the screen, i.e. they take the inverse-video'ness
2063 of the face already into account. */
2064 }
2065 else if (inverse_video)
2066 {
2067 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2068 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2069 toggle_highlight ();
2070 }
2071 else
2072 {
2073 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2074 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2075 toggle_highlight ();
2076 }
2077 }
2078 else
2079 {
2080 /* If we can't display colors, use reverse video
2081 if the face specifies that. */
37526b42
GM
2082 if (inverse_video)
2083 {
2084 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2085 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2086 toggle_highlight ();
2087 }
2088 else
2089 {
2090 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2091 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2092 toggle_highlight ();
2093 }
86a7d192
GM
2094 }
2095 }
a168702a
GM
2096
2097 if (face->tty_bold_p)
4e6ba4a4
GM
2098 {
2099 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
2100 OUTPUT1_IF (TS_enter_bold_mode);
2101 }
a168702a 2102 else if (face->tty_dim_p)
4e6ba4a4
GM
2103 if (MAY_USE_WITH_COLORS_P (NC_DIM))
2104 OUTPUT1_IF (TS_enter_dim_mode);
a168702a
GM
2105
2106 /* Alternate charset and blinking not yet used. */
4e6ba4a4
GM
2107 if (face->tty_alt_charset_p
2108 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
a168702a
GM
2109 OUTPUT1_IF (TS_enter_alt_charset_mode);
2110
4e6ba4a4
GM
2111 if (face->tty_blinking_p
2112 && MAY_USE_WITH_COLORS_P (NC_BLINK))
a168702a
GM
2113 OUTPUT1_IF (TS_enter_blink_mode);
2114
54800acb 2115 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
a168702a
GM
2116 OUTPUT1_IF (TS_enter_underline_mode);
2117
a168702a
GM
2118 if (TN_max_colors > 0)
2119 {
753d161b 2120 char *ts, *p;
177c0ea7 2121
753d161b
JL
2122 ts = standout_mode ? TS_set_background : TS_set_foreground;
2123 if (fg >= 0 && ts)
a168702a 2124 {
753d161b 2125 p = tparam (ts, NULL, 0, (int) fg);
a168702a
GM
2126 OUTPUT (p);
2127 xfree (p);
2128 }
2129
753d161b
JL
2130 ts = standout_mode ? TS_set_foreground : TS_set_background;
2131 if (bg >= 0 && ts)
a168702a 2132 {
753d161b 2133 p = tparam (ts, NULL, 0, (int) bg);
a168702a
GM
2134 OUTPUT (p);
2135 xfree (p);
2136 }
2137 }
2138}
177c0ea7 2139
a168702a
GM
2140
2141/* Turn off appearances of face FACE_ID on tty frame F. */
2142
2143static void
2144turn_off_face (f, face_id)
2145 struct frame *f;
2146 int face_id;
2147{
2148 struct face *face = FACE_FROM_ID (f, face_id);
a168702a
GM
2149
2150 xassert (face != NULL);
2151
2152 if (TS_exit_attribute_mode)
2153 {
2154 /* Capability "me" will turn off appearance modes double-bright,
2155 half-bright, reverse-video, standout, underline. It may or
2156 may not turn off alt-char-mode. */
2157 if (face->tty_bold_p
2158 || face->tty_dim_p
2159 || face->tty_reverse_p
2160 || face->tty_alt_charset_p
2161 || face->tty_blinking_p
2162 || face->tty_underline_p)
65aa5e85
GM
2163 {
2164 OUTPUT1_IF (TS_exit_attribute_mode);
2165 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
2166 standout_mode = 0;
2167 }
a168702a
GM
2168
2169 if (face->tty_alt_charset_p)
2170 OUTPUT_IF (TS_exit_alt_charset_mode);
2171 }
2172 else
2173 {
2174 /* If we don't have "me" we can only have those appearances
2175 that have exit sequences defined. */
2176 if (face->tty_alt_charset_p)
2177 OUTPUT_IF (TS_exit_alt_charset_mode);
2178
54800acb 2179 if (face->tty_underline_p)
a168702a
GM
2180 OUTPUT_IF (TS_exit_underline_mode);
2181 }
2182
2183 /* Switch back to default colors. */
2184 if (TN_max_colors > 0
f9d2fdc4
EZ
2185 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2186 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2187 || (face->background != FACE_TTY_DEFAULT_COLOR
2188 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
a168702a
GM
2189 OUTPUT1_IF (TS_orig_pair);
2190}
177c0ea7
JB
2191
2192
b63a55ac
MB
2193/* Return non-zero if the terminal on frame F supports all of the
2194 capabilities in CAPS simultaneously, with foreground and background
2195 colors FG and BG. */
2196
4a8130f2
MB
2197int
2198tty_capable_p (f, caps, fg, bg)
b63a55ac
MB
2199 struct frame *f;
2200 unsigned caps;
2201 unsigned long fg, bg;
2202{
2203#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \
2204 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \
2205 return 0;
2206
2207 TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE);
2208 TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
2209 TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD);
2210 TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM);
2211 TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK);
2212 TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2213
2214 /* We can do it! */
2215 return 1;
2216}
2217
2218
a168702a
GM
2219/* Return non-zero if the terminal is capable to display colors. */
2220
2221DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
981e4297 2222 0, 1, 0,
99fdd6bc
EZ
2223 doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
2224 (display)
2225 Lisp_Object display;
a168702a
GM
2226{
2227 return TN_max_colors > 0 ? Qt : Qnil;
2228}
2229
bfa62f96
EZ
2230/* Return the number of supported colors. */
2231DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2232 Stty_display_color_cells, 0, 1, 0,
99fdd6bc
EZ
2233 doc: /* Return the number of colors supported by TTY on DISPLAY. */)
2234 (display)
2235 Lisp_Object display;
bfa62f96
EZ
2236{
2237 return make_number (TN_max_colors);
2238}
2239
ace28297 2240#ifndef WINDOWSNT
a168702a 2241
ace28297
EZ
2242/* Save or restore the default color-related capabilities of this
2243 terminal. */
2244static void
2245tty_default_color_capabilities (save)
2246 int save;
2247{
2248 static char
2249 *default_orig_pair, *default_set_foreground, *default_set_background;
2250 static int default_max_colors, default_max_pairs, default_no_color_video;
2251
2252 if (save)
2253 {
2254 if (default_orig_pair)
2255 xfree (default_orig_pair);
2256 default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
2257
2258 if (default_set_foreground)
2259 xfree (default_set_foreground);
2260 default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
2261 : NULL;
2262
2263 if (default_set_background)
2264 xfree (default_set_background);
2265 default_set_background = TS_set_background ? xstrdup (TS_set_background)
2266 : NULL;
2267
2268 default_max_colors = TN_max_colors;
2269 default_max_pairs = TN_max_pairs;
2270 default_no_color_video = TN_no_color_video;
2271 }
2272 else
2273 {
2274 TS_orig_pair = default_orig_pair;
2275 TS_set_foreground = default_set_foreground;
2276 TS_set_background = default_set_background;
2277 TN_max_colors = default_max_colors;
2278 TN_max_pairs = default_max_pairs;
2279 TN_no_color_video = default_no_color_video;
2280 }
2281}
2282
2283/* Setup one of the standard tty color schemes according to MODE.
2284 MODE's value is generally the number of colors which we want to
2285 support; zero means set up for the default capabilities, the ones
2286 we saw at term_init time; -1 means turn off color support. */
2287void
2288tty_setup_colors (mode)
2289 int mode;
2290{
40409f05
EZ
2291 /* Canonicalize all negative values of MODE. */
2292 if (mode < -1)
2293 mode = -1;
2294
ace28297
EZ
2295 switch (mode)
2296 {
2297 case -1: /* no colors at all */
2298 TN_max_colors = 0;
2299 TN_max_pairs = 0;
2300 TN_no_color_video = 0;
2301 TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
2302 break;
2303 case 0: /* default colors, if any */
2304 default:
2305 tty_default_color_capabilities (0);
2306 break;
2307 case 8: /* 8 standard ANSI colors */
2308 TS_orig_pair = "\033[0m";
2309#ifdef TERMINFO
2310 TS_set_foreground = "\033[3%p1%dm";
2311 TS_set_background = "\033[4%p1%dm";
2312#else
2313 TS_set_foreground = "\033[3%dm";
2314 TS_set_background = "\033[4%dm";
2315#endif
2316 TN_max_colors = 8;
2317 TN_max_pairs = 64;
2318 TN_no_color_video = 0;
2319 break;
2320 }
2321}
2322
2323void
2324set_tty_color_mode (f, val)
2325 struct frame *f;
2326 Lisp_Object val;
2327{
dfc7a077 2328 Lisp_Object color_mode_spec, current_mode_spec;
ace28297
EZ
2329 Lisp_Object color_mode, current_mode;
2330 int mode, old_mode;
2331 extern Lisp_Object Qtty_color_mode;
2332 Lisp_Object tty_color_mode_alist;
2333
2334 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2335 Qnil);
2336
9ac61a89 2337 if (INTEGERP (val))
ace28297
EZ
2338 color_mode = val;
2339 else
2340 {
2341 if (NILP (tty_color_mode_alist))
2342 color_mode_spec = Qnil;
2343 else
2344 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
ace28297
EZ
2345
2346 if (CONSP (color_mode_spec))
2347 color_mode = XCDR (color_mode_spec);
2348 else
2349 color_mode = Qnil;
2350 }
545d91d5
RS
2351
2352 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2353
ace28297
EZ
2354 if (CONSP (current_mode_spec))
2355 current_mode = XCDR (current_mode_spec);
2356 else
2357 current_mode = Qnil;
9ac61a89 2358 if (INTEGERP (color_mode))
ace28297
EZ
2359 mode = XINT (color_mode);
2360 else
2361 mode = 0; /* meaning default */
9ac61a89 2362 if (INTEGERP (current_mode))
ace28297
EZ
2363 old_mode = XINT (current_mode);
2364 else
2365 old_mode = 0;
2366
2367 if (mode != old_mode)
2368 {
2369 tty_setup_colors (mode);
2370 /* This recomputes all the faces given the new color
2371 definitions. */
2372 call0 (intern ("tty-set-up-initial-frame-faces"));
2373 redraw_frame (f);
2374 }
2375}
2376
2377#endif /* !WINDOWSNT */
a168702a
GM
2378
2379\f
e882229c
NR
2380/***********************************************************************
2381 Mouse
2382 ***********************************************************************/
2383
7e5a23bd 2384#ifdef HAVE_GPM
94da14a0
NR
2385void term_mouse_moveto (int x, int y)
2386{
2387 const char *name;
2388 int fd;
2389 name = (const char *) ttyname (0);
2390 fd = open (name, O_WRONLY);
2391 /* TODO: how to set mouse position?
2392 SOME_FUNCTION (x, y, fd); */
2393 close (fd);
2394 last_mouse_x = x;
2395 last_mouse_y = y;
2396}
2397
e882229c
NR
2398static void
2399term_show_mouse_face (enum draw_glyphs_face draw)
2400{
94da14a0 2401 struct window *w = XWINDOW (Qmouse_face_window);
e882229c
NR
2402 int save_x, save_y;
2403 int i, j;
2404
2405 if (/* If window is in the process of being destroyed, don't bother
2406 to do anything. */
2407 w->current_matrix != NULL
2408 /* Recognize when we are called to operate on rows that don't exist
2409 anymore. This can happen when a window is split. */
2410 && mouse_face_end_row < w->current_matrix->nrows)
2411 {
2412 /* write_glyphs writes at cursor position, so we need to
2413 temporarily move cursor coordinates to the beginning of
2414 the highlight region. */
2415
2416 /* Save current cursor co-ordinates */
2417 save_y = curY;
2418 save_x = curX;
2419
2420 /* Note that mouse_face_beg_row etc. are window relative. */
2421 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2422 {
2423 int start_hpos, end_hpos, nglyphs;
2424 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2425
2426 /* Don't do anything if row doesn't have valid contents. */
2427 if (!row->enabled_p)
2428 continue;
2429
2430 /* For all but the first row, the highlight starts at column 0. */
2431 if (i == mouse_face_beg_row)
2432 start_hpos = mouse_face_beg_col;
2433 else
2434 start_hpos = 0;
2435
2436 if (i == mouse_face_end_row)
2437 end_hpos = mouse_face_end_col;
2438 else
2439 {
2440 end_hpos = row->used[TEXT_AREA];
2441 if (draw == DRAW_NORMAL_TEXT)
2442 row->fill_line_p = 1; /* Clear to end of line */
2443 }
2444
2445 if (end_hpos <= start_hpos)
2446 continue;
2447 /* Record that some glyphs of this row are displayed in
2448 mouse-face. */
2449 row->mouse_face_p = draw > 0;
2450
2451 nglyphs = end_hpos - start_hpos;
2452
2453 if (end_hpos >= row->used[TEXT_AREA])
2454 nglyphs = row->used[TEXT_AREA] - start_hpos;
2455
2456 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2457 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2458 + WINDOW_LEFT_EDGE_X (w);
2459
2460 cursor_to (pos_y, pos_x);
2461
2462 if (draw == DRAW_MOUSE_FACE)
2463 {
2464 write_glyphs_with_face (row->glyphs[TEXT_AREA] + start_hpos,
2465 nglyphs, mouse_face_face_id);
2466 }
2467 else /* draw == DRAW_NORMAL_TEXT */
2468 write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2469 }
2470 cursor_to (save_y, save_x);
2471 }
2472}
2473
2474static void
2475term_clear_mouse_face ()
2476{
94da14a0 2477 if (!NILP (Qmouse_face_window))
e882229c
NR
2478 term_show_mouse_face (DRAW_NORMAL_TEXT);
2479
2480 mouse_face_beg_row = mouse_face_beg_col = -1;
2481 mouse_face_end_row = mouse_face_end_col = -1;
94da14a0 2482 Qmouse_face_window = Qnil;
e882229c
NR
2483}
2484
2485/* Find the glyph matrix position of buffer position POS in window W.
2486 *HPOS and *VPOS are set to the positions found. W's current glyphs
2487 must be up to date. If POS is above window start return (0, 0).
2488 If POS is after end of W, return end of last line in W.
2489 - taken from msdos.c */
2490static int
2491fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2492{
2493 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2494 int yb = window_text_bottom_y (w);
2495 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2496
2497 while (row->y < yb)
2498 {
2499 if (row->used[TEXT_AREA])
2500 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2501 else
2502 line_start_position = 0;
2503
2504 if (line_start_position > pos)
2505 break;
2506 /* If the position sought is the end of the buffer,
2507 don't include the blank lines at the bottom of the window. */
2508 else if (line_start_position == pos
2509 && pos == BUF_ZV (XBUFFER (w->buffer)))
2510 {
2511 maybe_next_line_p = 1;
2512 break;
2513 }
2514 else if (line_start_position > 0)
2515 best_row = row;
2516
2517 /* Don't overstep the last matrix row, lest we get into the
2518 never-never land... */
2519 if (row->y + 1 >= yb)
2520 break;
2521
2522 ++row;
2523 }
2524
2525 /* Find the right column within BEST_ROW. */
2526 lastcol = 0;
2527 row = best_row;
2528 for (i = 0; i < row->used[TEXT_AREA]; i++)
2529 {
2530 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2531 int charpos;
2532
2533 charpos = glyph->charpos;
2534 if (charpos == pos)
2535 {
2536 *hpos = i;
2537 *vpos = row->y;
2538 return 1;
2539 }
2540 else if (charpos > pos)
2541 break;
2542 else if (charpos > 0)
2543 lastcol = i;
2544 }
2545
2546 /* If we're looking for the end of the buffer,
2547 and we didn't find it in the line we scanned,
2548 use the start of the following line. */
2549 if (maybe_next_line_p)
2550 {
2551 ++row;
2552 lastcol = 0;
2553 }
2554
2555 *vpos = row->y;
2556 *hpos = lastcol + 1;
2557 return 0;
2558}
2559
2560static void
2561term_mouse_highlight (struct frame *f, int x, int y)
2562{
2563 enum window_part part;
2564 Lisp_Object window;
2565 struct window *w;
2566 struct buffer *b;
2567
2568 if (NILP (Vmouse_highlight)
2569 || !f->glyphs_initialized_p)
2570 return;
2571
2572 mouse_face_mouse_x = x;
2573 mouse_face_mouse_y = y;
2574 mouse_face_mouse_frame = f;
2575
2576 /* Which window is that in? */
2577 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2578
2579 /* Not on a window -> return. */
2580 if (!WINDOWP (window))
2581 return;
2582
94da14a0 2583 if (!EQ (window, Qmouse_face_window))
e882229c
NR
2584 term_clear_mouse_face ();
2585
2586 w = XWINDOW (window);
2587
2588 /* Are we in a window whose display is up to date?
2589 And verify the buffer's text has not changed. */
2590 b = XBUFFER (w->buffer);
2591 if (part == ON_TEXT
2592 && EQ (w->window_end_valid, w->buffer)
2593 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2594 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2595 {
2596 int pos, i, nrows = w->current_matrix->nrows;
2597 struct glyph_row *row;
2598 struct glyph *glyph;
2599
2600 /* Find the glyph under X/Y. */
2601 glyph = NULL;
2602 if (y >= 0 && y < nrows)
2603 {
2604 row = MATRIX_ROW (w->current_matrix, y);
2605 /* Give up if some row before the one we are looking for is
2606 not enabled. */
2607 for (i = 0; i <= y; i++)
2608 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2609 break;
2610 if (i > y /* all rows upto and including the one at Y are enabled */
2611 && row->displays_text_p
2612 && x < window_box_width (w, TEXT_AREA))
2613 {
2614 glyph = row->glyphs[TEXT_AREA];
2615 if (x >= row->used[TEXT_AREA])
2616 glyph = NULL;
2617 else
2618 {
2619 glyph += x;
2620 if (!BUFFERP (glyph->object))
2621 glyph = NULL;
2622 }
2623 }
2624 }
2625
2626 /* Clear mouse face if X/Y not over text. */
2627 if (glyph == NULL)
2628 {
2629 term_clear_mouse_face ();
2630 return;
2631 }
2632
2633 if (!BUFFERP (glyph->object))
2634 abort ();
2635 pos = glyph->charpos;
2636
2637 /* Check for mouse-face. */
2638 {
2639 extern Lisp_Object Qmouse_face;
2640 Lisp_Object mouse_face, overlay, position, *overlay_vec;
3b8c0c70 2641 int noverlays, obegv, ozv;
e882229c
NR
2642 struct buffer *obuf;
2643
2644 /* If we get an out-of-range value, return now; avoid an error. */
2645 if (pos > BUF_Z (b))
2646 return;
2647
2648 /* Make the window's buffer temporarily current for
2649 overlays_at and compute_char_face. */
2650 obuf = current_buffer;
2651 current_buffer = b;
2652 obegv = BEGV;
2653 ozv = ZV;
2654 BEGV = BEG;
2655 ZV = Z;
2656
2657 /* Is this char mouse-active? */
2658 XSETINT (position, pos);
2659
2660 /* Put all the overlays we want in a vector in overlay_vec. */
2661 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2662 /* Sort overlays into increasing priority order. */
2663 noverlays = sort_overlays (overlay_vec, noverlays, w);
2664
2665 /* Check mouse-face highlighting. */
94da14a0 2666 if (!(EQ (window, Qmouse_face_window)
e882229c
NR
2667 && y >= mouse_face_beg_row
2668 && y <= mouse_face_end_row
2669 && (y > mouse_face_beg_row
2670 || x >= mouse_face_beg_col)
2671 && (y < mouse_face_end_row
2672 || x < mouse_face_end_col
2673 || mouse_face_past_end)))
2674 {
2675 /* Clear the display of the old active region, if any. */
2676 term_clear_mouse_face ();
2677
2678 /* Find the highest priority overlay that has a mouse-face
2679 property. */
2680 overlay = Qnil;
2681 for (i = noverlays - 1; i >= 0; --i)
2682 {
2683 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2684 if (!NILP (mouse_face))
2685 {
2686 overlay = overlay_vec[i];
2687 break;
2688 }
2689 }
2690
2691 /* If no overlay applies, get a text property. */
2692 if (NILP (overlay))
2693 mouse_face = Fget_text_property (position, Qmouse_face,
2694 w->buffer);
2695
2696 /* Handle the overlay case. */
2697 if (!NILP (overlay))
2698 {
2699 /* Find the range of text around this char that
2700 should be active. */
2701 Lisp_Object before, after;
2702 int ignore;
2703
2704
2705 before = Foverlay_start (overlay);
2706 after = Foverlay_end (overlay);
2707 /* Record this as the current active region. */
2708 fast_find_position (w, XFASTINT (before),
2709 &mouse_face_beg_col,
2710 &mouse_face_beg_row);
2711
2712 mouse_face_past_end
2713 = !fast_find_position (w, XFASTINT (after),
2714 &mouse_face_end_col,
2715 &mouse_face_end_row);
94da14a0 2716 Qmouse_face_window = window;
e882229c
NR
2717
2718 mouse_face_face_id
2719 = face_at_buffer_position (w, pos, 0, 0,
2720 &ignore, pos + 1, 1);
2721
2722 /* Display it as active. */
2723 term_show_mouse_face (DRAW_MOUSE_FACE);
2724 }
2725 /* Handle the text property case. */
2726 else if (!NILP (mouse_face))
2727 {
2728 /* Find the range of text around this char that
2729 should be active. */
2730 Lisp_Object before, after, beginning, end;
2731 int ignore;
2732
2733 beginning = Fmarker_position (w->start);
2734 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2735 before
2736 = Fprevious_single_property_change (make_number (pos + 1),
2737 Qmouse_face,
2738 w->buffer, beginning);
2739 after
2740 = Fnext_single_property_change (position, Qmouse_face,
2741 w->buffer, end);
2742
2743 /* Record this as the current active region. */
2744 fast_find_position (w, XFASTINT (before),
2745 &mouse_face_beg_col,
2746 &mouse_face_beg_row);
2747 mouse_face_past_end
2748 = !fast_find_position (w, XFASTINT (after),
2749 &mouse_face_end_col,
2750 &mouse_face_end_row);
94da14a0 2751 Qmouse_face_window = window;
e882229c
NR
2752
2753 mouse_face_face_id
2754 = face_at_buffer_position (w, pos, 0, 0,
2755 &ignore, pos + 1, 1);
2756
2757 /* Display it as active. */
2758 term_show_mouse_face (DRAW_MOUSE_FACE);
2759 }
2760 }
2761
2762 /* Look for a `help-echo' property. */
2763 {
2764 Lisp_Object help;
2765 extern Lisp_Object Qhelp_echo;
2766
2767 /* Check overlays first. */
2768 help = Qnil;
2769 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2770 {
2771 overlay = overlay_vec[i];
2772 help = Foverlay_get (overlay, Qhelp_echo);
2773 }
2774
2775 if (!NILP (help))
2776 {
2777 help_echo_string = help;
2778 help_echo_window = window;
2779 help_echo_object = overlay;
2780 help_echo_pos = pos;
2781 }
2782 /* Try text properties. */
2783 else if (NILP (help)
2784 && ((STRINGP (glyph->object)
2785 && glyph->charpos >= 0
2786 && glyph->charpos < SCHARS (glyph->object))
2787 || (BUFFERP (glyph->object)
2788 && glyph->charpos >= BEGV
2789 && glyph->charpos < ZV)))
2790 {
2791 help = Fget_text_property (make_number (glyph->charpos),
2792 Qhelp_echo, glyph->object);
2793 if (!NILP (help))
2794 {
2795 help_echo_string = help;
2796 help_echo_window = window;
2797 help_echo_object = glyph->object;
2798 help_echo_pos = glyph->charpos;
2799 }
2800 }
2801 }
2802
2803 BEGV = obegv;
2804 ZV = ozv;
2805 current_buffer = obuf;
2806 }
2807 }
2808}
2809
2810static int
2811term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2812{
2813 /* Has the mouse moved off the glyph it was on at the last sighting? */
2814 if (event->x != last_mouse_x || event->y != last_mouse_y)
2815 {
2816 frame->mouse_moved = 1;
2817 term_mouse_highlight (frame, event->x - 1, event->y - 1);
2818 /* Remember which glyph we're now on. */
2819 last_mouse_x = event->x;
2820 last_mouse_y = event->y;
2821 return 1;
2822 }
2823 return 0;
2824}
2825
2826/* Return the current position of the mouse.
2827
2828 Set *f to the frame the mouse is in, or zero if the mouse is in no
2829 Emacs frame. If it is set to zero, all the other arguments are
2830 garbage.
2831
2832 Set *bar_window to Qnil, and *x and *y to the column and
2833 row of the character cell the mouse is over.
2834
2835 Set *time to the time the mouse was at the returned position.
2836
2837 This should clear mouse_moved until the next motion
94da14a0 2838 event arrives. */
e882229c
NR
2839static void
2840term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2841 enum scroll_bar_part *part, Lisp_Object *x,
2842 Lisp_Object *y, unsigned long *time)
2843{
e882229c 2844 struct timeval now;
94da14a0
NR
2845 Lisp_Object frame, window;
2846 struct window *w;
e882229c
NR
2847
2848 *fp = SELECTED_FRAME ();
94da14a0 2849 (*fp)->mouse_moved = 0;
e882229c
NR
2850
2851 *bar_window = Qnil;
2852 *part = 0;
2853
94da14a0
NR
2854 XSETINT (*x, last_mouse_x);
2855 XSETINT (*y, last_mouse_y);
2856 XSETFRAME (frame, *fp);
2857 window = Fwindow_at (*x, *y, frame);
e882229c 2858
94da14a0
NR
2859 XSETINT (*x, last_mouse_x - WINDOW_LEFT_EDGE_COL (XWINDOW (window)));
2860 XSETINT (*y, last_mouse_y - WINDOW_TOP_EDGE_LINE (XWINDOW (window)));
e882229c
NR
2861 gettimeofday(&now, 0);
2862 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
e882229c
NR
2863}
2864
2865/* Prepare a mouse-event in *RESULT for placement in the input queue.
2866
2867 If the event is a button press, then note that we have grabbed
2868 the mouse. */
2869
2870static Lisp_Object
2871term_mouse_click (struct input_event *result, Gpm_Event *event,
2872 struct frame *f)
2873{
2874 struct timeval now;
2875 int i, j;
2876
2877 result->kind = GPM_CLICK_EVENT;
2878 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2879 {
2880 if (event->buttons & j) {
2881 result->code = i; /* button number */
2882 break;
2883 }
2884 }
2885 gettimeofday(&now, 0);
2886 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2887
2888 if (event->type & GPM_UP)
2889 result->modifiers = up_modifier;
2890 else if (event->type & GPM_DOWN)
2891 result->modifiers = down_modifier;
2892 else
2893 result->modifiers = 0;
2894
2895 if (event->type & GPM_SINGLE)
2896 result->modifiers |= click_modifier;
2897
2898 if (event->type & GPM_DOUBLE)
2899 result->modifiers |= double_modifier;
2900
2901 if (event->type & GPM_TRIPLE)
2902 result->modifiers |= triple_modifier;
2903
2904 if (event->type & GPM_DRAG)
2905 result->modifiers |= drag_modifier;
2906
2907 if (!(event->type & (GPM_MOVE|GPM_DRAG))) {
2908
2909 /* 1 << KG_SHIFT */
2910 if (event->modifiers & (1 << 0))
2911 result->modifiers |= shift_modifier;
2912
2913 /* 1 << KG_CTRL */
2914 if (event->modifiers & (1 << 2))
2915 result->modifiers |= ctrl_modifier;
2916
2917 /* 1 << KG_ALT || KG_ALTGR */
2918 if (event->modifiers & (1 << 3)
2919 || event->modifiers & (1 << 1))
2920 result->modifiers |= meta_modifier;
2921 }
2922
2923 XSETINT (result->x, event->x - 1);
2924 XSETINT (result->y, event->y - 1);
2925 XSETFRAME (result->frame_or_window, f);
2926 result->arg = Qnil;
2927 return Qnil;
2928}
2929
2930int
2931handle_one_term_event (Gpm_Event *event, struct input_event* hold_quit)
2932{
2933 struct frame *f = SELECTED_FRAME ();
2934 int i, j, fd;
2935 struct input_event ie;
2936 int do_help = 0;
2937 int count = 0;
2938
2939 EVENT_INIT (ie);
2940 ie.kind = NO_EVENT;
2941 ie.arg = Qnil;
2942
2943 if (event->type & GPM_MOVE) {
2944 unsigned char buf[6 * sizeof (short)];
2945 unsigned short *arg = (unsigned short *) buf + 1;
2946 const char *name;
2947
2948 previous_help_echo_string = help_echo_string;
2949 help_echo_string = Qnil;
2950
2951 /* Display mouse pointer */
2952 buf[sizeof(short) - 1] = 2; /* set selection */
2953
2954 arg[0] = arg[2] = (unsigned short) event->x;
2955 arg[1] = arg[3] = (unsigned short) event->y;
2956 arg[4] = (unsigned short) 3;
2957
2958 name = (const char *) ttyname (0);
2959 fd = open (name, O_WRONLY);
2960 ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1);
94da14a0 2961 close (fd);
e882229c
NR
2962
2963 term_mouse_movement (f, event);
2964
2965 /* If the contents of the global variable help_echo_string
2966 has changed, generate a HELP_EVENT. */
2967 if (!NILP (help_echo_string)
2968 || !NILP (previous_help_echo_string))
2969 do_help = 1;
2970
2971 goto done;
2972 }
2973 else {
2974 f->mouse_moved = 0;
2975 term_mouse_click (&ie, event, f);
e882229c
NR
2976 }
2977
2978 done:
2979 if (ie.kind != NO_EVENT)
2980 {
2981 kbd_buffer_store_event_hold (&ie, hold_quit);
2982 count++;
2983 }
2984
2985 if (do_help
2986 && !(hold_quit && hold_quit->kind != NO_EVENT))
2987 {
2988 Lisp_Object frame;
2989
2990 if (f)
2991 XSETFRAME (frame, f);
2992 else
2993 frame = Qnil;
2994
2995 gen_help_event (help_echo_string, frame, help_echo_window,
2996 help_echo_object, help_echo_pos);
2997 count++;
2998 }
2999
3000 return count;
3001}
3002
3003DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection,
3004 0, 0, 0,
3005 doc: /* Open a connection to Gpm. */)
3006 ()
3007{
3008 Gpm_Connect connection;
3009
3010 connection.eventMask = ~0;
3011 connection.defaultMask = ~GPM_HARD;
3012 connection.maxMod = ~0;
3013 connection.minMod = 0;
3014
3015 if (Gpm_Open (&connection, 0) < 0)
3016 return Qnil;
3017 else
3018 {
3019 term_gpm = 1;
3020 reset_sys_modes ();
3021 init_sys_modes ();
3022 add_gpm_wait_descriptor (gpm_fd);
3023 return Qt;
3024 }
3025}
3026
3027DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection,
3028 0, 0, 0,
3029 doc: /* Close a connection to Gpm. */)
3030 ()
3031{
3032 delete_gpm_wait_descriptor (gpm_fd);
3033 while (Gpm_Close()); /* close all the stack */
3034 term_gpm = 0;
3035 return Qnil;
3036}
7e5a23bd 3037#endif /* HAVE_GPM */
e882229c
NR
3038
3039\f
a168702a
GM
3040/***********************************************************************
3041 Initialization
3042 ***********************************************************************/
3043
dfcf069d 3044void
08a24c47
JB
3045term_init (terminal_type)
3046 char *terminal_type;
3047{
3048 char *area;
3049 char **address = &area;
3a06a6d9 3050 char *buffer = NULL;
5846981b 3051 int buffer_size = 4096;
08a24c47
JB
3052 register char *p;
3053 int status;
e52f4e08 3054 struct frame *sf = XFRAME (selected_frame);
08a24c47 3055
af645abf
KH
3056 encode_terminal_bufsize = 0;
3057
7e5a23bd 3058#ifdef HAVE_GPM
94da14a0
NR
3059 mouse_position_hook = term_mouse_position;
3060 Qmouse_face_window = Qnil;
e882229c
NR
3061#endif
3062
cb28b9c2 3063#ifdef WINDOWSNT
29f27c39 3064 initialize_w32_display ();
cb28b9c2
RS
3065
3066 Wcm_clear ();
cb28b9c2 3067
a678d9ff 3068 area = (char *) xmalloc (2044);
cb28b9c2 3069
9882535b
KS
3070 FrameRows = FRAME_LINES (sf);
3071 FrameCols = FRAME_COLS (sf);
3072 specified_window = FRAME_LINES (sf);
cb28b9c2
RS
3073
3074 delete_in_insert_mode = 1;
3075
3076 UseTabs = 0;
3077 scroll_region_ok = 0;
3078
3079 /* Seems to insert lines when it's not supposed to, messing
3080 up the display. In doing a trace, it didn't seem to be
3081 called much, so I don't think we're losing anything by
3082 turning it off. */
3083
3084 line_ins_del_ok = 0;
3085 char_ins_del_ok = 1;
3086
3087 baud_rate = 19200;
3088
e52f4e08
GM
3089 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
3090 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
acfcd5cd 3091 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
cb28b9c2
RS
3092
3093 return;
eccec691 3094#else /* not WINDOWSNT */
cb28b9c2 3095
08a24c47 3096 Wcm_clear ();
08a24c47 3097
3a06a6d9 3098 buffer = (char *) xmalloc (buffer_size);
08a24c47
JB
3099 status = tgetent (buffer, terminal_type);
3100 if (status < 0)
b0347178
KH
3101 {
3102#ifdef TERMINFO
e12c1054 3103 fatal ("Cannot open terminfo database file");
b0347178 3104#else
e12c1054 3105 fatal ("Cannot open termcap database file");
b0347178
KH
3106#endif
3107 }
08a24c47 3108 if (status == 0)
b0347178
KH
3109 {
3110#ifdef TERMINFO
3111 fatal ("Terminal type %s is not defined.\n\
3112If that is not the actual type of terminal you have,\n\
3113use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3114`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3115to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
b0347178
KH
3116 terminal_type);
3117#else
3118 fatal ("Terminal type %s is not defined.\n\
c5a9c3e6
RS
3119If that is not the actual type of terminal you have,\n\
3120use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3121`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3122to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
b0347178
KH
3123 terminal_type);
3124#endif
3125 }
3a06a6d9 3126
f730033e 3127#ifndef TERMINFO
3a06a6d9 3128 if (strlen (buffer) >= buffer_size)
08a24c47 3129 abort ();
f730033e 3130 buffer_size = strlen (buffer);
3dd3a502 3131#endif
f730033e 3132 area = (char *) xmalloc (buffer_size);
08a24c47
JB
3133
3134 TS_ins_line = tgetstr ("al", address);
3135 TS_ins_multi_lines = tgetstr ("AL", address);
3136 TS_bell = tgetstr ("bl", address);
3137 BackTab = tgetstr ("bt", address);
3138 TS_clr_to_bottom = tgetstr ("cd", address);
3139 TS_clr_line = tgetstr ("ce", address);
ff11dfa1 3140 TS_clr_frame = tgetstr ("cl", address);
2efdbcdd 3141 ColPosition = NULL; /* tgetstr ("ch", address); */
08a24c47
JB
3142 AbsPosition = tgetstr ("cm", address);
3143 CR = tgetstr ("cr", address);
3144 TS_set_scroll_region = tgetstr ("cs", address);
3145 TS_set_scroll_region_1 = tgetstr ("cS", address);
3146 RowPosition = tgetstr ("cv", address);
3147 TS_del_char = tgetstr ("dc", address);
3148 TS_del_multi_chars = tgetstr ("DC", address);
3149 TS_del_line = tgetstr ("dl", address);
3150 TS_del_multi_lines = tgetstr ("DL", address);
3151 TS_delete_mode = tgetstr ("dm", address);
3152 TS_end_delete_mode = tgetstr ("ed", address);
3153 TS_end_insert_mode = tgetstr ("ei", address);
3154 Home = tgetstr ("ho", address);
3155 TS_ins_char = tgetstr ("ic", address);
3156 TS_ins_multi_chars = tgetstr ("IC", address);
3157 TS_insert_mode = tgetstr ("im", address);
3158 TS_pad_inserted_char = tgetstr ("ip", address);
3159 TS_end_keypad_mode = tgetstr ("ke", address);
3160 TS_keypad_mode = tgetstr ("ks", address);
3161 LastLine = tgetstr ("ll", address);
3162 Right = tgetstr ("nd", address);
3163 Down = tgetstr ("do", address);
3164 if (!Down)
3165 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
3166#ifdef VMS
3167 /* VMS puts a carriage return before each linefeed,
3168 so it is not safe to use linefeeds. */
3169 if (Down && Down[0] == '\n' && Down[1] == '\0')
3170 Down = 0;
3171#endif /* VMS */
3172 if (tgetflag ("bs"))
3173 Left = "\b"; /* can't possibly be longer! */
3174 else /* (Actually, "bs" is obsolete...) */
3175 Left = tgetstr ("le", address);
3176 if (!Left)
3177 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
3178 TS_pad_char = tgetstr ("pc", address);
3179 TS_repeat = tgetstr ("rp", address);
3180 TS_end_standout_mode = tgetstr ("se", address);
3181 TS_fwd_scroll = tgetstr ("sf", address);
3182 TS_standout_mode = tgetstr ("so", address);
3183 TS_rev_scroll = tgetstr ("sr", address);
3184 Wcm.cm_tab = tgetstr ("ta", address);
3185 TS_end_termcap_modes = tgetstr ("te", address);
3186 TS_termcap_modes = tgetstr ("ti", address);
3187 Up = tgetstr ("up", address);
3188 TS_visible_bell = tgetstr ("vb", address);
a168702a
GM
3189 TS_cursor_normal = tgetstr ("ve", address);
3190 TS_cursor_visible = tgetstr ("vs", address);
3191 TS_cursor_invisible = tgetstr ("vi", address);
08a24c47 3192 TS_set_window = tgetstr ("wi", address);
177c0ea7 3193
a168702a
GM
3194 TS_enter_underline_mode = tgetstr ("us", address);
3195 TS_exit_underline_mode = tgetstr ("ue", address);
a168702a
GM
3196 TS_enter_bold_mode = tgetstr ("md", address);
3197 TS_enter_dim_mode = tgetstr ("mh", address);
3198 TS_enter_blink_mode = tgetstr ("mb", address);
3199 TS_enter_reverse_mode = tgetstr ("mr", address);
3200 TS_enter_alt_charset_mode = tgetstr ("as", address);
3201 TS_exit_alt_charset_mode = tgetstr ("ae", address);
3202 TS_exit_attribute_mode = tgetstr ("me", address);
177c0ea7 3203
08a24c47
JB
3204 MultiUp = tgetstr ("UP", address);
3205 MultiDown = tgetstr ("DO", address);
3206 MultiLeft = tgetstr ("LE", address);
3207 MultiRight = tgetstr ("RI", address);
3208
e7f90eab
GM
3209 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3210 color because we can't switch back to the default foreground and
3211 background. */
a168702a 3212 TS_orig_pair = tgetstr ("op", address);
e7f90eab 3213 if (TS_orig_pair)
a168702a 3214 {
e7f90eab
GM
3215 TS_set_foreground = tgetstr ("AF", address);
3216 TS_set_background = tgetstr ("AB", address);
3217 if (!TS_set_foreground)
3218 {
3219 /* SVr4. */
3220 TS_set_foreground = tgetstr ("Sf", address);
3221 TS_set_background = tgetstr ("Sb", address);
3222 }
177c0ea7 3223
e7f90eab
GM
3224 TN_max_colors = tgetnum ("Co");
3225 TN_max_pairs = tgetnum ("pa");
177c0ea7 3226
4e6ba4a4
GM
3227 TN_no_color_video = tgetnum ("NC");
3228 if (TN_no_color_video == -1)
3229 TN_no_color_video = 0;
a168702a 3230 }
a168702a 3231
ace28297
EZ
3232 tty_default_color_capabilities (1);
3233
e4058338
KH
3234 MagicWrap = tgetflag ("xn");
3235 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3236 the former flag imply the latter. */
3237 AutoWrap = MagicWrap || tgetflag ("am");
ff11dfa1 3238 memory_below_frame = tgetflag ("db");
08a24c47
JB
3239 TF_hazeltine = tgetflag ("hz");
3240 must_write_spaces = tgetflag ("in");
3241 meta_key = tgetflag ("km") || tgetflag ("MT");
3242 TF_insmode_motion = tgetflag ("mi");
3243 TF_standout_motion = tgetflag ("ms");
3244 TF_underscore = tgetflag ("ul");
08a24c47
JB
3245 TF_teleray = tgetflag ("xt");
3246
5c2c7893
JB
3247 term_get_fkeys (address);
3248
ff11dfa1 3249 /* Get frame size from system, or else from termcap. */
3b12ce12
RS
3250 {
3251 int height, width;
3252 get_frame_size (&width, &height);
9882535b
KS
3253 FRAME_COLS (sf) = width;
3254 FRAME_LINES (sf) = height;
3b12ce12
RS
3255 }
3256
9882535b
KS
3257 if (FRAME_COLS (sf) <= 0)
3258 SET_FRAME_COLS (sf, tgetnum ("co"));
1efd8636
RS
3259 else
3260 /* Keep width and external_width consistent */
9882535b
KS
3261 SET_FRAME_COLS (sf, FRAME_COLS (sf));
3262 if (FRAME_LINES (sf) <= 0)
3263 FRAME_LINES (sf) = tgetnum ("li");
177c0ea7 3264
9882535b 3265 if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
e12c1054 3266 fatal ("Screen size %dx%d is too small",
9882535b 3267 FRAME_LINES (sf), FRAME_COLS (sf));
ee7a2de4 3268
08a24c47 3269 min_padding_speed = tgetnum ("pb");
08a24c47
JB
3270 TabWidth = tgetnum ("tw");
3271
3272#ifdef VMS
3273 /* These capabilities commonly use ^J.
3274 I don't know why, but sending them on VMS does not work;
3275 it causes following spaces to be lost, sometimes.
3276 For now, the simplest fix is to avoid using these capabilities ever. */
3277 if (Down && Down[0] == '\n')
3278 Down = 0;
3279#endif /* VMS */
3280
3281 if (!TS_bell)
3282 TS_bell = "\07";
3283
3284 if (!TS_fwd_scroll)
3285 TS_fwd_scroll = Down;
3286
3287 PC = TS_pad_char ? *TS_pad_char : 0;
3288
3289 if (TabWidth < 0)
3290 TabWidth = 8;
177c0ea7 3291
08a24c47
JB
3292/* Turned off since /etc/termcap seems to have :ta= for most terminals
3293 and newer termcap doc does not seem to say there is a default.
3294 if (!Wcm.cm_tab)
3295 Wcm.cm_tab = "\t";
3296*/
3297
54800acb
MB
3298 /* We don't support standout modes that use `magic cookies', so
3299 turn off any that do. */
3300 if (TS_standout_mode && tgetnum ("sg") >= 0)
3301 {
3302 TS_standout_mode = 0;
3303 TS_end_standout_mode = 0;
3304 }
3305 if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
3306 {
3307 TS_enter_underline_mode = 0;
3308 TS_exit_underline_mode = 0;
3309 }
3310
3311 /* If there's no standout mode, try to use underlining instead. */
08a24c47
JB
3312 if (TS_standout_mode == 0)
3313 {
54800acb
MB
3314 TS_standout_mode = TS_enter_underline_mode;
3315 TS_end_standout_mode = TS_exit_underline_mode;
08a24c47
JB
3316 }
3317
afd359c4
RS
3318 /* If no `se' string, try using a `me' string instead.
3319 If that fails, we can't use standout mode at all. */
3320 if (TS_end_standout_mode == 0)
3321 {
e4bfb3b6 3322 char *s = tgetstr ("me", address);
afd359c4
RS
3323 if (s != 0)
3324 TS_end_standout_mode = s;
3325 else
3326 TS_standout_mode = 0;
3327 }
3328
08a24c47
JB
3329 if (TF_teleray)
3330 {
3331 Wcm.cm_tab = 0;
54800acb
MB
3332 /* We can't support standout mode, because it uses magic cookies. */
3333 TS_standout_mode = 0;
08a24c47
JB
3334 /* But that means we cannot rely on ^M to go to column zero! */
3335 CR = 0;
3336 /* LF can't be trusted either -- can alter hpos */
3337 /* if move at column 0 thru a line with TS_standout_mode */
3338 Down = 0;
3339 }
3340
3341 /* Special handling for certain terminal types known to need it */
3342
3343 if (!strcmp (terminal_type, "supdup"))
3344 {
ff11dfa1 3345 memory_below_frame = 1;
08a24c47
JB
3346 Wcm.cm_losewrap = 1;
3347 }
3348 if (!strncmp (terminal_type, "c10", 3)
3349 || !strcmp (terminal_type, "perq"))
3350 {
3351 /* Supply a makeshift :wi string.
3352 This string is not valid in general since it works only
3353 for windows starting at the upper left corner;
3354 but that is all Emacs uses.
3355
ff11dfa1 3356 This string works only if the frame is using
08a24c47
JB
3357 the top of the video memory, because addressing is memory-relative.
3358 So first check the :ti string to see if that is true.
3359
3360 It would be simpler if the :wi string could go in the termcap
3361 entry, but it can't because it is not fully valid.
3362 If it were in the termcap entry, it would confuse other programs. */
3363 if (!TS_set_window)
3364 {
3365 p = TS_termcap_modes;
3366 while (*p && strcmp (p, "\033v "))
3367 p++;
3368 if (*p)
3369 TS_set_window = "\033v%C %C %C %C ";
3370 }
3371 /* Termcap entry often fails to have :in: flag */
3372 must_write_spaces = 1;
3373 /* :ti string typically fails to have \E^G! in it */
3374 /* This limits scope of insert-char to one line. */
3375 strcpy (area, TS_termcap_modes);
3376 strcat (area, "\033\007!");
3377 TS_termcap_modes = area;
3378 area += strlen (area) + 1;
3379 p = AbsPosition;
3380 /* Change all %+ parameters to %C, to handle
3381 values above 96 correctly for the C100. */
3382 while (*p)
3383 {
3384 if (p[0] == '%' && p[1] == '+')
3385 p[1] = 'C';
3386 p++;
3387 }
3388 }
3389
9882535b
KS
3390 FrameRows = FRAME_LINES (sf);
3391 FrameCols = FRAME_COLS (sf);
3392 specified_window = FRAME_LINES (sf);
08a24c47
JB
3393
3394 if (Wcm_init () == -1) /* can't do cursor motion */
3395#ifdef VMS
3396 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3397It lacks the ability to position the cursor.\n\
3398If that is not the actual type of terminal you have, use either the\n\
3399DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
e12c1054 3400or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
08a24c47 3401 terminal_type);
37dad45a
RS
3402#else /* not VMS */
3403# ifdef TERMINFO
3404 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3405It lacks the ability to position the cursor.\n\
3406If that is not the actual type of terminal you have,\n\
3407use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3408`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3409to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
37dad45a
RS
3410 terminal_type);
3411# else /* TERMCAP */
08a24c47
JB
3412 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3413It lacks the ability to position the cursor.\n\
3414If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
3415use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3416`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3417to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
08a24c47 3418 terminal_type);
37dad45a
RS
3419# endif /* TERMINFO */
3420#endif /*VMS */
9882535b
KS
3421 if (FRAME_LINES (sf) <= 0
3422 || FRAME_COLS (sf) <= 0)
e12c1054 3423 fatal ("The frame size has not been specified");
08a24c47
JB
3424
3425 delete_in_insert_mode
3426 = TS_delete_mode && TS_insert_mode
3427 && !strcmp (TS_delete_mode, TS_insert_mode);
3428
3429 se_is_so = (TS_standout_mode
3430 && TS_end_standout_mode
3431 && !strcmp (TS_standout_mode, TS_end_standout_mode));
3432
08a24c47
JB
3433 UseTabs = tabs_safe_p () && TabWidth == 8;
3434
3435 scroll_region_ok
3436 = (Wcm.cm_abs
3437 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
3438
3439 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
3440 && (TS_del_line || TS_del_multi_lines))
3441 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
3442
3443 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
3444 || TS_pad_inserted_char || TS_ins_multi_chars)
3445 && (TS_del_char || TS_del_multi_chars));
3446
3447 fast_clear_end_of_line = TS_clr_line != 0;
3448
3449 init_baud_rate ();
3450 if (read_socket_hook) /* Baudrate is somewhat */
3451 /* meaningless in this case */
3452 baud_rate = 9600;
20a558dc 3453
e52f4e08
GM
3454 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
3455 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
eccec691 3456#endif /* WINDOWSNT */
3a06a6d9
RS
3457
3458 xfree (buffer);
08a24c47
JB
3459}
3460
3461/* VARARGS 1 */
dfcf069d 3462void
eb27c2ca
DN
3463fatal (str, arg1, arg2)
3464 char *str, *arg1, *arg2;
08a24c47
JB
3465{
3466 fprintf (stderr, "emacs: ");
eb27c2ca
DN
3467 fprintf (stderr, str, arg1, arg2);
3468 fprintf (stderr, "\n");
08a24c47
JB
3469 fflush (stderr);
3470 exit (1);
3471}
07c57952 3472
072d84a6
RS
3473DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 0, 0,
3474 doc: /* Declare that this terminal does not handle underlining.
3475This is used to override the terminfo data, for certain terminals that
3476do not really do underlining, but say that they do. */)
3477 ()
3478{
3479 TS_enter_underline_mode = 0;
3480 return Qnil;
3481}
3482
dfcf069d 3483void
07c57952
KH
3484syms_of_term ()
3485{
7ee72033
MB
3486 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3487 doc: /* Non-nil means the system uses terminfo rather than termcap.
228299fa 3488This variable can be used by terminal emulator packages. */);
07c57952
KH
3489#ifdef TERMINFO
3490 system_uses_terminfo = 1;
3491#else
3492 system_uses_terminfo = 0;
3493#endif
c291d9ef 3494
7ee72033
MB
3495 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
3496 doc: /* Non-nil means call this function to ring the bell.
228299fa 3497The function should accept no arguments. */);
c291d9ef 3498 Vring_bell_function = Qnil;
a168702a 3499
0db017c0
SM
3500 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3501 doc: /* Non-nil means to make the cursor very visible.
3502This only has an effect when running in a text terminal.
3503What means \"very visible\" is up to your terminal. It may make the cursor
3504bigger, or it may make it blink, or it may do nothing at all. */);
3505 visible_cursor = 1;
3506
a168702a 3507 defsubr (&Stty_display_color_p);
bfa62f96 3508 defsubr (&Stty_display_color_cells);
072d84a6 3509 defsubr (&Stty_no_underline);
7e5a23bd 3510#ifdef HAVE_GPM
e882229c
NR
3511 defsubr (&Sterm_open_connection);
3512 defsubr (&Sterm_close_connection);
94da14a0
NR
3513
3514 staticpro (&Qmouse_face_window);
7e5a23bd 3515#endif /* HAVE_GPM */
3d644e94
JD
3516
3517 fullscreen_hook = NULL;
07c57952 3518}
a168702a 3519
ab5796a9
MB
3520/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3521 (do not change this comment) */