term.c 75.2 KB
Newer Older
1
/* Terminal control module for terminals described by TERMCAP
2 3
   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
                 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
4 5 6 7 8

This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Jim Blandy's avatar
Jim Blandy committed
9
the Free Software Foundation; either version 2, or (at your option)
Jim Blandy's avatar
Jim Blandy committed
10 11 12 13 14 15 16 17 18
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
Lute Kamstra's avatar
Lute Kamstra committed
19 20
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.  */
Jim Blandy's avatar
Jim Blandy committed
21

22
/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>.  */
Jim Blandy's avatar
Jim Blandy committed
23

24
#include <config.h>
Jim Blandy's avatar
Jim Blandy committed
25 26
#include <stdio.h>
#include <ctype.h>
Gerd Moellmann's avatar
Gerd Moellmann committed
27
#include <string.h>
28
#include <stdarg.h>
29

Jim Blandy's avatar
Jim Blandy committed
30 31 32
#include "termchar.h"
#include "termopts.h"
#include "lisp.h"
Karl Heuer's avatar
Karl Heuer committed
33 34
#include "charset.h"
#include "coding.h"
35
#include "keyboard.h"
Jim Blandy's avatar
Jim Blandy committed
36
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
37 38
#include "disptab.h"
#include "termhooks.h"
Andreas Schwab's avatar
Andreas Schwab committed
39
#include "dispextern.h"
Gerd Moellmann's avatar
Gerd Moellmann committed
40
#include "window.h"
Stefan Monnier's avatar
Stefan Monnier committed
41
#include "keymap.h"
Gerd Moellmann's avatar
Gerd Moellmann committed
42

43 44 45 46 47
/* For now, don't try to include termcap.h.  On some systems,
   configure finds a non-standard termcap.h that the main build
   won't find.  */

#if defined HAVE_TERMCAP_H && 0
48
#include <termcap.h>
49 50 51 52 53
#else
extern void tputs P_ ((const char *, int, int (*)(int)));
extern int tgetent P_ ((char *, const char *));
extern int tgetflag P_ ((char *id));
extern int tgetnum P_ ((char *id));
54 55
#endif

56
#include "cm.h"
Andreas Schwab's avatar
Andreas Schwab committed
57 58 59
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
60
#ifdef MAC_OS
61 62
#include "macterm.h"
#endif
Karl Heuer's avatar
Karl Heuer committed
63

Gerd Moellmann's avatar
Gerd Moellmann committed
64 65 66 67 68
static void turn_on_face P_ ((struct frame *, int face_id));
static void turn_off_face P_ ((struct frame *, int face_id));
static void tty_show_cursor P_ ((void));
static void tty_hide_cursor P_ ((void));

69
#define OUTPUT(a) \
70
     tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
Jim Blandy's avatar
Jim Blandy committed
71 72
#define OUTPUT1(a) tputs (a, 1, cmputc)
#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
Gerd Moellmann's avatar
Gerd Moellmann committed
73

74 75 76
#define OUTPUT_IF(a)							\
     do {								\
       if (a)								\
77
         tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame))	\
78 79
			  - curY), cmputc);				\
     } while (0)
80

81
#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
Jim Blandy's avatar
Jim Blandy committed
82

83 84 85 86
/* Display space properties */

extern Lisp_Object Qspace, QCalign_to, QCwidth;

87
/* Function to use to ring the bell.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
88

89 90
Lisp_Object Vring_bell_function;

91
/* Terminal characteristics that higher levels want to look at.
Jim Blandy's avatar
Jim Blandy committed
92 93 94 95 96 97 98 99 100 101 102
   These are all extern'd in termchar.h */

int must_write_spaces;		/* Nonzero means spaces in the text
				   must actually be output; can't just skip
				   over some columns to leave them blank.  */
int min_padding_speed;		/* Speed below which no padding necessary */

int line_ins_del_ok;		/* Terminal can insert and delete lines */
int char_ins_del_ok;		/* Terminal can insert and delete chars */
int scroll_region_ok;		/* Terminal supports setting the
				   scroll window */
103 104
int scroll_region_cost;		/* Cost of setting a scroll window,
				   measured in characters */
Jim Blandy's avatar
Jim Blandy committed
105
int memory_below_frame;		/* Terminal remembers lines
Jim Blandy's avatar
Jim Blandy committed
106 107 108
				   scrolled off bottom */
int fast_clear_end_of_line;	/* Terminal has a `ce' string */

Jim Blandy's avatar
Jim Blandy committed
109
/* Nonzero means no need to redraw the entire frame on resuming
Jim Blandy's avatar
Jim Blandy committed
110 111
   a suspended Emacs.  This is useful on terminals with multiple pages,
   where one page is used for Emacs and another for all else. */
Gerd Moellmann's avatar
Gerd Moellmann committed
112

Jim Blandy's avatar
Jim Blandy committed
113 114 115 116 117
int no_redraw_on_reenter;

/* Hook functions that you can set to snap out the functions in this file.
   These are all extern'd in termhooks.h  */

Andreas Schwab's avatar
Andreas Schwab committed
118 119 120 121 122
void (*cursor_to_hook) P_ ((int, int));
void (*raw_cursor_to_hook) P_ ((int, int));
void (*clear_to_end_hook) P_ ((void));
void (*clear_frame_hook) P_ ((void));
void (*clear_end_of_line_hook) P_ ((int));
Jim Blandy's avatar
Jim Blandy committed
123

Andreas Schwab's avatar
Andreas Schwab committed
124
void (*ins_del_lines_hook) P_ ((int, int));
Jim Blandy's avatar
Jim Blandy committed
125

Andreas Schwab's avatar
Andreas Schwab committed
126
void (*delete_glyphs_hook) P_ ((int));
Jim Blandy's avatar
Jim Blandy committed
127

Andreas Schwab's avatar
Andreas Schwab committed
128
void (*ring_bell_hook) P_ ((void));
Jim Blandy's avatar
Jim Blandy committed
129

Andreas Schwab's avatar
Andreas Schwab committed
130 131 132 133 134
void (*reset_terminal_modes_hook) P_ ((void));
void (*set_terminal_modes_hook) P_ ((void));
void (*update_begin_hook) P_ ((struct frame *));
void (*update_end_hook) P_ ((struct frame *));
void (*set_terminal_window_hook) P_ ((int));
Gerd Moellmann's avatar
Gerd Moellmann committed
135 136 137
void (*insert_glyphs_hook) P_ ((struct glyph *, int));
void (*write_glyphs_hook) P_ ((struct glyph *, int));
void (*delete_glyphs_hook) P_ ((int));
Jim Blandy's avatar
Jim Blandy committed
138

139
int (*read_socket_hook) P_ ((int, int, struct input_event *));
Jim Blandy's avatar
Jim Blandy committed
140

Andreas Schwab's avatar
Andreas Schwab committed
141
void (*frame_up_to_date_hook) P_ ((struct frame *));
142

143
/* Return the current position of the mouse.
144 145 146 147 148

   Set *f to the frame the mouse is in, or zero if the mouse is in no
   Emacs frame.  If it is set to zero, all the other arguments are
   garbage.

149 150 151 152
   If the motion started in a scroll bar, set *bar_window to the
   scroll bar's window, *part to the part the mouse is currently over,
   *x to the position of the mouse along the scroll bar, and *y to the
   overall length of the scroll bar.
153 154 155 156 157 158 159 160

   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
   row of the character cell the mouse is over.

   Set *time to the time the mouse was at the returned position.

   This should clear mouse_moved until the next motion
   event arrives.  */
161

Andreas Schwab's avatar
Andreas Schwab committed
162
void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
163
				 Lisp_Object *bar_window,
164
				 enum scroll_bar_part *part,
165 166
				 Lisp_Object *x,
				 Lisp_Object *y,
Andreas Schwab's avatar
Andreas Schwab committed
167
				 unsigned long *time));
Jim Blandy's avatar
Jim Blandy committed
168

Jim Blandy's avatar
Jim Blandy committed
169
/* When reading from a minibuffer in a different frame, Emacs wants
Gerd Moellmann's avatar
Gerd Moellmann committed
170
   to shift the highlight from the selected frame to the mini-buffer's
Jim Blandy's avatar
Jim Blandy committed
171
   frame; under X, this means it lies about where the focus is.
Jim Blandy's avatar
Jim Blandy committed
172 173
   This hook tells the window system code to re-decide where to put
   the highlight.  */
174

Andreas Schwab's avatar
Andreas Schwab committed
175
void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
Jim Blandy's avatar
Jim Blandy committed
176

Jim Blandy's avatar
Jim Blandy committed
177 178 179 180 181 182 183 184 185 186
/* If we're displaying frames using a window system that can stack
   frames on top of each other, this hook allows you to bring a frame
   to the front, or bury it behind all the other windows.  If this
   hook is zero, that means the device we're displaying on doesn't
   support overlapping frames, so there's no need to raise or lower
   anything.

   If RAISE is non-zero, F is brought to the front, before all other
   windows.  If RAISE is zero, F is sent to the back, behind all other
   windows.  */
187

Andreas Schwab's avatar
Andreas Schwab committed
188
void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
Jim Blandy's avatar
Jim Blandy committed
189

190
/* Set the vertical scroll bar for WINDOW to have its upper left corner
191 192 193
   at (TOP, LEFT), and be LENGTH rows high.  Set its handle to
   indicate that we are displaying PORTION characters out of a total
   of WHOLE characters, starting at POSITION.  If WINDOW doesn't yet
194
   have a scroll bar, create one for it.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
195

196
void (*set_vertical_scroll_bar_hook)
Andreas Schwab's avatar
Andreas Schwab committed
197 198
     P_ ((struct window *window,
	  int portion, int whole, int position));
199

200

201
/* The following three hooks are used when we're doing a thorough
202
   redisplay of the frame.  We don't explicitly know which scroll bars
203 204 205
   are going to be deleted, because keeping track of when windows go
   away is a real pain - can you say set-window-configuration?
   Instead, we just assert at the beginning of redisplay that *all*
206
   scroll bars are to be removed, and then save scroll bars from the
Karl Heuer's avatar
Karl Heuer committed
207
   fiery pit when we actually redisplay their window.  */
208

209 210
/* Arrange for all scroll bars on FRAME to be removed at the next call
   to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
211
   `*redeem_scroll_bar_hook' is applied to its window before the judgment.
212

213
   This should be applied to each frame each time its window tree is
214 215 216
   redisplayed, even if it is not displaying scroll bars at the moment;
   if the HAS_SCROLL_BARS flag has just been turned off, only calling
   this and the judge_scroll_bars_hook will get rid of them.
217 218

   If non-zero, this hook should be safe to apply to any frame,
219
   whether or not it can support scroll bars, and whether or not it is
220
   currently displaying them.  */
221

Andreas Schwab's avatar
Andreas Schwab committed
222
void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
223

224 225
/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
   Note that it's okay to redeem a scroll bar that is not condemned.  */
226

Andreas Schwab's avatar
Andreas Schwab committed
227
void (*redeem_scroll_bar_hook) P_ ((struct window *window));
228

229
/* Remove all scroll bars on FRAME that haven't been saved since the
230
   last call to `*condemn_scroll_bars_hook'.
231

232
   This should be applied to each frame after each time its window
233 234 235
   tree is redisplayed, even if it is not displaying scroll bars at the
   moment; if the HAS_SCROLL_BARS flag has just been turned off, only
   calling this and condemn_scroll_bars_hook will get rid of them.
236 237

   If non-zero, this hook should be safe to apply to any frame,
238
   whether or not it can support scroll bars, and whether or not it is
239
   currently displaying them.  */
240

Andreas Schwab's avatar
Andreas Schwab committed
241
void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
242

Jim Blandy's avatar
Jim Blandy committed
243 244
/* Strings, numbers and flags taken from the termcap entry.  */

Karl Heuer's avatar
Karl Heuer committed
245
char *TS_ins_line;		/* "al" */
Jim Blandy's avatar
Jim Blandy committed
246 247 248 249
char *TS_ins_multi_lines;	/* "AL" (one parameter, # lines to insert) */
char *TS_bell;			/* "bl" */
char *TS_clr_to_bottom;		/* "cd" */
char *TS_clr_line;		/* "ce", clear to end of line */
Jim Blandy's avatar
Jim Blandy committed
250
char *TS_clr_frame;		/* "cl" */
Jim Blandy's avatar
Jim Blandy committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
char *TS_set_scroll_region;	/* "cs" (2 params, first line and last line) */
char *TS_set_scroll_region_1;   /* "cS" (4 params: total lines,
				   lines above scroll region, lines below it,
				   total lines again) */
char *TS_del_char;		/* "dc" */
char *TS_del_multi_chars;	/* "DC" (one parameter, # chars to delete) */
char *TS_del_line;		/* "dl" */
char *TS_del_multi_lines;	/* "DL" (one parameter, # lines to delete) */
char *TS_delete_mode;		/* "dm", enter character-delete mode */
char *TS_end_delete_mode;	/* "ed", leave character-delete mode */
char *TS_end_insert_mode;	/* "ei", leave character-insert mode */
char *TS_ins_char;		/* "ic" */
char *TS_ins_multi_chars;	/* "IC" (one parameter, # chars to insert) */
char *TS_insert_mode;		/* "im", enter character-insert mode */
char *TS_pad_inserted_char;	/* "ip".  Just padding, no commands.  */
char *TS_end_keypad_mode;	/* "ke" */
char *TS_keypad_mode;		/* "ks" */
char *TS_pad_char;		/* "pc", char to use as padding */
char *TS_repeat;		/* "rp" (2 params, # times to repeat
				   and character to be repeated) */
char *TS_end_standout_mode;	/* "se" */
char *TS_fwd_scroll;		/* "sf" */
char *TS_standout_mode;		/* "so" */
char *TS_rev_scroll;		/* "sr" */
char *TS_end_termcap_modes;	/* "te" */
char *TS_termcap_modes;		/* "ti" */
char *TS_visible_bell;		/* "vb" */
Gerd Moellmann's avatar
Gerd Moellmann committed
278 279 280
char *TS_cursor_normal;		/* "ve" */
char *TS_cursor_visible;	/* "vs" */
char *TS_cursor_invisible;	/* "vi" */
Jim Blandy's avatar
Jim Blandy committed
281 282 283
char *TS_set_window;		/* "wi" (4 params, start and end of window,
				   each as vpos and hpos) */

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
/* Value of the "NC" (no_color_video) capability, or 0 if not
   present.  */

static int TN_no_color_video;

/* Meaning of bits in no_color_video.  Each bit set means that the
   corresponding attribute cannot be combined with colors.  */

enum no_color_bit
{
  NC_STANDOUT	 = 1 << 0,
  NC_UNDERLINE	 = 1 << 1,
  NC_REVERSE	 = 1 << 2,
  NC_BLINK	 = 1 << 3,
  NC_DIM	 = 1 << 4,
  NC_BOLD	 = 1 << 5,
  NC_INVIS	 = 1 << 6,
  NC_PROTECT	 = 1 << 7,
  NC_ALT_CHARSET = 1 << 8
};

Gerd Moellmann's avatar
Gerd Moellmann committed
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
/* "md" -- turn on bold (extra bright mode).  */

char *TS_enter_bold_mode;

/* "mh" -- turn on half-bright mode.  */

char *TS_enter_dim_mode;

/* "mb" -- enter blinking mode.  */

char *TS_enter_blink_mode;

/* "mr" -- enter reverse video mode.  */

char *TS_enter_reverse_mode;

/* "us"/"ue" -- start/end underlining.  */

char *TS_exit_underline_mode, *TS_enter_underline_mode;

/* "as"/"ae" -- start/end alternate character set.  Not really
   supported, yet.  */

char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;

/* "me" -- switch appearances off.  */

char *TS_exit_attribute_mode;

/* "Co" -- number of colors.  */

int TN_max_colors;

/* "pa" -- max. number of color pairs on screen.  Not handled yet.
   Could be a problem if not equal to TN_max_colors * TN_max_colors.  */

int TN_max_pairs;

/* "op" -- SVr4 set default pair to its original value.  */

char *TS_orig_pair;

/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
   1 param, the color index.  */

char *TS_set_foreground, *TS_set_background;

Jim Blandy's avatar
Jim Blandy committed
352 353 354
int TF_hazeltine;	/* termcap hz flag. */
int TF_insmode_motion;	/* termcap mi flag: can move while in insert mode. */
int TF_standout_motion;	/* termcap mi flag: can move while in standout mode. */
Gerd Moellmann's avatar
Gerd Moellmann committed
355 356
int TF_underscore;	/* termcap ul flag: _ underlines if over-struck on
			   non-blank position.  Must clear before writing _.  */
Jim Blandy's avatar
Jim Blandy committed
357 358 359 360 361 362 363 364 365 366 367 368
int TF_teleray;		/* termcap xt flag: many weird consequences.
			   For t1061. */

static int RPov;	/* # chars to start a TS_repeat */

static int delete_in_insert_mode;	/* delete mode == insert mode */

static int se_is_so;	/* 1 if same string both enters and leaves
			   standout mode */

/* internal state */

369
/* The largest frame width in any call to calculate_costs.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
370

371
int max_frame_cols;
Gerd Moellmann's avatar
Gerd Moellmann committed
372

373
/* The largest frame height in any call to calculate_costs.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
374

375
int max_frame_lines;
376

377
static int costs_set;	  /* Nonzero if costs have been calculated. */
Jim Blandy's avatar
Jim Blandy committed
378 379 380 381 382

int insert_mode;			/* Nonzero when in insert mode.  */
int standout_mode;			/* Nonzero when in standout mode.  */

/* Size of window specified by higher levels.
Jim Blandy's avatar
Jim Blandy committed
383
   This is the number of lines, from the top of frame downwards,
Jim Blandy's avatar
Jim Blandy committed
384 385
   which can participate in insert-line/delete-line operations.

386
   Effectively it excludes the bottom frame_lines - specified_window_size
Jim Blandy's avatar
Jim Blandy committed
387 388 389 390
   lines from those operations.  */

int specified_window;

Jim Blandy's avatar
Jim Blandy committed
391
/* Frame currently being redisplayed; 0 if not currently redisplaying.
Jim Blandy's avatar
Jim Blandy committed
392 393
   (Direct output does not count).  */

Jim Blandy's avatar
Jim Blandy committed
394
FRAME_PTR updating_frame;
Jim Blandy's avatar
Jim Blandy committed
395

396
/* Provided for lisp packages.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
397

398 399
static int system_uses_terminfo;

400 401 402 403
/* Flag used in tty_show/hide_cursor.  */

static int tty_cursor_hidden;

Jim Blandy's avatar
Jim Blandy committed
404
char *tparam ();
405 406

extern char *tgetstr ();
Jim Blandy's avatar
Jim Blandy committed
407

408

409 410 411 412 413 414 415 416 417 418 419
#ifdef WINDOWSNT
/* We aren't X windows, but we aren't termcap either.  This makes me
   uncertain as to what value to use for frame.output_method.  For
   this file, we'll define FRAME_TERMCAP_P to be zero so that our
   output hooks get called instead of the termcap functions.  Probably
   the best long-term solution is to define an output_windows_nt...  */

#undef FRAME_TERMCAP_P
#define FRAME_TERMCAP_P(_f_) 0
#endif /* WINDOWSNT */

Andreas Schwab's avatar
Andreas Schwab committed
420
void
Jim Blandy's avatar
Jim Blandy committed
421 422
ring_bell ()
{
423
  if (!NILP (Vring_bell_function))
424 425 426 427 428 429 430 431 432 433
    {
      Lisp_Object function;

      /* Temporarily set the global variable to nil
	 so that if we get an error, it stays nil
	 and we don't call it over and over.

	 We don't specbind it, because that would carefully
	 restore the bad value if there's an error
	 and make the loop of errors happen anyway.  */
434

435 436 437 438 439 440
      function = Vring_bell_function;
      Vring_bell_function = Qnil;

      call0 (function);

      Vring_bell_function = function;
Jim Blandy's avatar
Jim Blandy committed
441
    }
442 443 444 445
  else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
    (*ring_bell_hook) ();
  else
    OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
Jim Blandy's avatar
Jim Blandy committed
446 447
}

Andreas Schwab's avatar
Andreas Schwab committed
448
void
Jim Blandy's avatar
Jim Blandy committed
449 450
set_terminal_modes ()
{
451
  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
Jim Blandy's avatar
Jim Blandy committed
452
    {
453 454 455 456 457 458 459 460 461 462 463
      if (TS_termcap_modes)
	OUTPUT (TS_termcap_modes);
      else
	{
	  /* Output enough newlines to scroll all the old screen contents
	     off the screen, so it won't be overwritten and lost.  */
	  int i;
	  for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
	    putchar ('\n');
	}

464 465 466
      OUTPUT_IF (TS_cursor_visible);
      OUTPUT_IF (TS_keypad_mode);
      losecursor ();
Jim Blandy's avatar
Jim Blandy committed
467
    }
468 469
  else
    (*set_terminal_modes_hook) ();
Jim Blandy's avatar
Jim Blandy committed
470 471
}

Andreas Schwab's avatar
Andreas Schwab committed
472
void
Jim Blandy's avatar
Jim Blandy committed
473 474
reset_terminal_modes ()
{
475
  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
Jim Blandy's avatar
Jim Blandy committed
476
    {
477
      turn_off_highlight ();
478 479 480 481 482 483 484
      turn_off_insert ();
      OUTPUT_IF (TS_end_keypad_mode);
      OUTPUT_IF (TS_cursor_normal);
      OUTPUT_IF (TS_end_termcap_modes);
      OUTPUT_IF (TS_orig_pair);
      /* Output raw CR so kernel can track the cursor hpos.  */
      cmputc ('\r');
Jim Blandy's avatar
Jim Blandy committed
485
    }
486 487
  else if (reset_terminal_modes_hook)
    (*reset_terminal_modes_hook) ();
Jim Blandy's avatar
Jim Blandy committed
488 489
}

Andreas Schwab's avatar
Andreas Schwab committed
490
void
Jim Blandy's avatar
Jim Blandy committed
491
update_begin (f)
492
     struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
493
{
Jim Blandy's avatar
Jim Blandy committed
494
  updating_frame = f;
495 496
  if (!FRAME_TERMCAP_P (f))
    update_begin_hook (f);
Jim Blandy's avatar
Jim Blandy committed
497 498
}

Andreas Schwab's avatar
Andreas Schwab committed
499
void
Jim Blandy's avatar
Jim Blandy committed
500
update_end (f)
501
     struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
502
{
503
  if (FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
504
    {
505 506 507 508
      if (!XWINDOW (selected_window)->cursor_off_p)
	tty_show_cursor ();
      turn_off_insert ();
      background_highlight ();
Jim Blandy's avatar
Jim Blandy committed
509
    }
510 511
  else
    update_end_hook (f);
512

513
  updating_frame = NULL;
Jim Blandy's avatar
Jim Blandy committed
514 515
}

Andreas Schwab's avatar
Andreas Schwab committed
516
void
Jim Blandy's avatar
Jim Blandy committed
517 518 519
set_terminal_window (size)
     int size;
{
520
  if (FRAME_TERMCAP_P (updating_frame))
Jim Blandy's avatar
Jim Blandy committed
521
    {
522
      specified_window = size ? size : FRAME_LINES (updating_frame);
523 524
      if (scroll_region_ok)
	set_scroll_region (0, specified_window);
Jim Blandy's avatar
Jim Blandy committed
525
    }
526 527
  else
    set_terminal_window_hook (size);
Jim Blandy's avatar
Jim Blandy committed
528 529
}

Andreas Schwab's avatar
Andreas Schwab committed
530
void
Jim Blandy's avatar
Jim Blandy committed
531 532 533 534
set_scroll_region (start, stop)
     int start, stop;
{
  char *buf;
535
  struct frame *sf = XFRAME (selected_frame);
536

Jim Blandy's avatar
Jim Blandy committed
537
  if (TS_set_scroll_region)
538
    buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
Jim Blandy's avatar
Jim Blandy committed
539
  else if (TS_set_scroll_region_1)
540
    buf = tparam (TS_set_scroll_region_1, 0, 0,
541 542 543
		  FRAME_LINES (sf), start,
		  FRAME_LINES (sf) - stop,
		  FRAME_LINES (sf));
Jim Blandy's avatar
Jim Blandy committed
544
  else
545
    buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf));
546

Jim Blandy's avatar
Jim Blandy committed
547
  OUTPUT (buf);
548
  xfree (buf);
Jim Blandy's avatar
Jim Blandy committed
549 550
  losecursor ();
}
551

Jim Blandy's avatar
Jim Blandy committed
552

553
static void
Jim Blandy's avatar
Jim Blandy committed
554 555 556 557 558 559 560
turn_on_insert ()
{
  if (!insert_mode)
    OUTPUT (TS_insert_mode);
  insert_mode = 1;
}

Andreas Schwab's avatar
Andreas Schwab committed
561
void
Jim Blandy's avatar
Jim Blandy committed
562 563 564 565 566 567 568
turn_off_insert ()
{
  if (insert_mode)
    OUTPUT (TS_end_insert_mode);
  insert_mode = 0;
}

569
/* Handle highlighting.  */
Jim Blandy's avatar
Jim Blandy committed
570

Andreas Schwab's avatar
Andreas Schwab committed
571
void
Jim Blandy's avatar
Jim Blandy committed
572 573
turn_off_highlight ()
{
574 575 576
  if (standout_mode)
    OUTPUT_IF (TS_end_standout_mode);
  standout_mode = 0;
Jim Blandy's avatar
Jim Blandy committed
577 578
}

579
static void
Jim Blandy's avatar
Jim Blandy committed
580 581
turn_on_highlight ()
{
582 583 584
  if (!standout_mode)
    OUTPUT_IF (TS_standout_mode);
  standout_mode = 1;
Jim Blandy's avatar
Jim Blandy committed
585 586
}

587 588 589 590 591 592 593 594 595
static void
toggle_highlight ()
{
  if (standout_mode)
    turn_off_highlight ();
  else
    turn_on_highlight ();
}

Gerd Moellmann's avatar
Gerd Moellmann committed
596 597 598 599 600 601

/* Make cursor invisible.  */

static void
tty_hide_cursor ()
{
602 603 604 605 606
  if (tty_cursor_hidden == 0)
    {
      tty_cursor_hidden = 1;
      OUTPUT_IF (TS_cursor_invisible);
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
607 608 609 610 611 612 613 614
}


/* Ensure that cursor is visible.  */

static void
tty_show_cursor ()
{
615 616 617 618 619 620
  if (tty_cursor_hidden)
    {
      tty_cursor_hidden = 0;
      OUTPUT_IF (TS_cursor_normal);
      OUTPUT_IF (TS_cursor_visible);
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
621 622 623
}


Jim Blandy's avatar
Jim Blandy committed
624 625 626 627
/* Set standout mode to the state it should be in for
   empty space inside windows.  What this is,
   depends on the user option inverse-video.  */

Andreas Schwab's avatar
Andreas Schwab committed
628
void
Jim Blandy's avatar
Jim Blandy committed
629 630 631 632 633 634 635 636 637 638
background_highlight ()
{
  if (inverse_video)
    turn_on_highlight ();
  else
    turn_off_highlight ();
}

/* Set standout mode to the mode specified for the text to be output.  */

Andreas Schwab's avatar
Andreas Schwab committed
639
static void
Jim Blandy's avatar
Jim Blandy committed
640 641
highlight_if_desired ()
{
642
  if (inverse_video)
Jim Blandy's avatar
Jim Blandy committed
643
    turn_on_highlight ();
644 645
  else
    turn_off_highlight ();
Jim Blandy's avatar
Jim Blandy committed
646 647 648
}


Gerd Moellmann's avatar
Gerd Moellmann committed
649 650
/* Move cursor to row/column position VPOS/HPOS.  HPOS/VPOS are
   frame-relative coordinates.  */
Jim Blandy's avatar
Jim Blandy committed
651

Andreas Schwab's avatar
Andreas Schwab committed
652
void
Gerd Moellmann's avatar
Gerd Moellmann committed
653 654
cursor_to (vpos, hpos)
     int vpos, hpos;
Jim Blandy's avatar
Jim Blandy committed
655
{
656
  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
657

658
  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
Jim Blandy's avatar
Jim Blandy committed
659
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
660
      (*cursor_to_hook) (vpos, hpos);
Jim Blandy's avatar
Jim Blandy committed
661 662 663
      return;
    }

664 665
  /* Detect the case where we are called from reset_sys_modes
     and the costs have never been calculated.  Do nothing.  */
666
  if (! costs_set)
667 668
    return;

Gerd Moellmann's avatar
Gerd Moellmann committed
669
  if (curY == vpos && curX == hpos)
Jim Blandy's avatar
Jim Blandy committed
670 671 672 673 674
    return;
  if (!TF_standout_motion)
    background_highlight ();
  if (!TF_insmode_motion)
    turn_off_insert ();
Gerd Moellmann's avatar
Gerd Moellmann committed
675
  cmgoto (vpos, hpos);
Jim Blandy's avatar
Jim Blandy committed
676 677 678 679
}

/* Similar but don't take any account of the wasted characters.  */

Andreas Schwab's avatar
Andreas Schwab committed
680
void
Jim Blandy's avatar
Jim Blandy committed
681
raw_cursor_to (row, col)
Jim Blandy's avatar
Jim Blandy committed
682
     int row, col;
Jim Blandy's avatar
Jim Blandy committed
683
{
684 685
  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
  if (! FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
    {
      (*raw_cursor_to_hook) (row, col);
      return;
    }
  if (curY == row && curX == col)
    return;
  if (!TF_standout_motion)
    background_highlight ();
  if (!TF_insmode_motion)
    turn_off_insert ();
  cmgoto (row, col);
}

/* Erase operations */

Jim Blandy's avatar
Jim Blandy committed
701
/* clear from cursor to end of frame */
Andreas Schwab's avatar
Andreas Schwab committed
702
void
Jim Blandy's avatar
Jim Blandy committed
703 704 705 706
clear_to_end ()
{
  register int i;

707
  if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
Jim Blandy's avatar
Jim Blandy committed
708 709 710 711 712 713 714 715 716 717 718
    {
      (*clear_to_end_hook) ();
      return;
    }
  if (TS_clr_to_bottom)
    {
      background_highlight ();
      OUTPUT (TS_clr_to_bottom);
    }
  else
    {
719
      for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++)
Jim Blandy's avatar
Jim Blandy committed
720 721
	{
	  cursor_to (i, 0);
722
	  clear_end_of_line (FRAME_COLS (XFRAME (selected_frame)));
Jim Blandy's avatar
Jim Blandy committed
723 724 725 726
	}
    }
}

Jim Blandy's avatar
Jim Blandy committed
727
/* Clear entire frame */
Jim Blandy's avatar
Jim Blandy committed
728

Andreas Schwab's avatar
Andreas Schwab committed
729
void
Jim Blandy's avatar
Jim Blandy committed
730
clear_frame ()
Jim Blandy's avatar
Jim Blandy committed
731
{
732
  struct frame *sf = XFRAME (selected_frame);
733

Jim Blandy's avatar
Jim Blandy committed
734
  if (clear_frame_hook
735
      && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
Jim Blandy's avatar
Jim Blandy committed
736
    {
Jim Blandy's avatar
Jim Blandy committed
737
      (*clear_frame_hook) ();
Jim Blandy's avatar
Jim Blandy committed
738 739
      return;
    }
Jim Blandy's avatar
Jim Blandy committed
740
  if (TS_clr_frame)
Jim Blandy's avatar
Jim Blandy committed
741 742
    {
      background_highlight ();
Jim Blandy's avatar
Jim Blandy committed
743
      OUTPUT (TS_clr_frame);
Jim Blandy's avatar
Jim Blandy committed
744 745 746 747 748 749 750 751 752 753 754 755 756 757
      cmat (0, 0);
    }
  else
    {
      cursor_to (0, 0);
      clear_to_end ();
    }
}

/* Clear from cursor to end of line.
   Assume that the line is already clear starting at column first_unused_hpos.

   Note that the cursor may be moved, on terminals lacking a `ce' string.  */

Andreas Schwab's avatar
Andreas Schwab committed
758
void
759
clear_end_of_line (first_unused_hpos)
Jim Blandy's avatar
Jim Blandy committed
760 761 762 763 764
     int first_unused_hpos;
{
  register int i;

  if (clear_end_of_line_hook
765
      && ! FRAME_TERMCAP_P ((updating_frame
Jim Blandy's avatar
Jim Blandy committed
766
			       ? updating_frame
767
			     : XFRAME (selected_frame))))
Jim Blandy's avatar
Jim Blandy committed
768 769 770 771 772
    {
      (*clear_end_of_line_hook) (first_unused_hpos);
      return;
    }

773 774
  /* Detect the case where we are called from reset_sys_modes
     and the costs have never been calculated.  Do nothing.  */
775
  if (! costs_set)
776 777
    return;

Jim Blandy's avatar
Jim Blandy committed
778 779 780 781 782 783 784 785 786
  if (curX >= first_unused_hpos)
    return;
  background_highlight ();
  if (TS_clr_line)
    {
      OUTPUT1 (TS_clr_line);
    }
  else
    {			/* have to do it the hard way */
787
      struct frame *sf = XFRAME (selected_frame);
Jim Blandy's avatar
Jim Blandy committed
788 789
      turn_off_insert ();

Gerd Moellmann's avatar
Gerd Moellmann committed
790
      /* Do not write in last row last col with Auto-wrap on. */
791 792
      if (AutoWrap && curY == FRAME_LINES (sf) - 1
	  && first_unused_hpos == FRAME_COLS (sf))
Jim Blandy's avatar
Jim Blandy committed
793 794 795 796 797 798 799 800 801 802 803 804
	first_unused_hpos--;

      for (i = curX; i < first_unused_hpos; i++)
	{
	  if (termscript)
	    fputc (' ', termscript);
	  putchar (' ');
	}
      cmplus (first_unused_hpos - curX);
    }
}

805 806 807 808
/* Buffer to store the source and result of code conversion for terminal.  */
static unsigned char *encode_terminal_buf;
/* Allocated size of the above buffer.  */
static int encode_terminal_bufsize;
Karl Heuer's avatar
Karl Heuer committed
809

810 811 812
/* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
   Set CODING->produced to the byte-length of the resulting byte
   sequence, and return a pointer to that byte sequence.  */
Karl Heuer's avatar
Karl Heuer committed
813

814
unsigned char *
815
encode_terminal_code (src, src_len, coding)
Gerd Moellmann's avatar
Gerd Moellmann committed
816
     struct glyph *src;
Karl Heuer's avatar
Karl Heuer committed
817
     int src_len;
818
     struct coding_system *coding;
Karl Heuer's avatar
Karl Heuer committed
819
{
Gerd Moellmann's avatar
Gerd Moellmann committed
820
  struct glyph *src_start = src, *src_end = src + src_len;
821
  register GLYPH g;
822 823
  unsigned char *buf;
  int nchars, nbytes, required;
Karl Heuer's avatar
Karl Heuer committed
824 825
  register int tlen = GLYPH_TABLE_LENGTH;
  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
826

827 828 829 830 831 832 833 834 835 836
  /* Allocate sufficient size of buffer to store all characters in
     multibyte-form.  But, it may be enlarged on demand if
     Vglyph_table contains a string.  */
  required = MAX_MULTIBYTE_LENGTH * src_len;
  if (encode_terminal_bufsize < required)
    {
      if (encode_terminal_bufsize == 0)
	encode_terminal_buf = xmalloc (required);
      else
	encode_terminal_buf = xrealloc (encode_terminal_buf, required);
837
      encode_terminal_bufsize = required;
838
    }
Karl Heuer's avatar
Karl Heuer committed
839

840 841
  buf = encode_terminal_buf;
  nchars = 0;
Karl Heuer's avatar
Karl Heuer committed
842 843 844
  while (src < src_end)
    {
      /* We must skip glyphs to be padded for a wide character.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
845
      if (! CHAR_GLYPH_PADDING_P (*src))
Karl Heuer's avatar
Karl Heuer committed
846
	{
847 848 849
	  g = GLYPH_FROM_CHAR_GLYPH (src[0]);

	  if (g < 0 || g >= tlen)
850
	    {
851
	      /* This glyph doesn't has an entry in Vglyph_table.  */
852 853
	      if (CHAR_VALID_P (src->u.ch, 0))
		buf += CHAR_STRING (src->u.ch, buf);
854
	      else
855 856
		*buf++ = SPACEGLYPH;
	      nchars++;
857
	    }
858
	  else
Karl Heuer's avatar
Karl Heuer committed
859
	    {
860
	      /* This glyph has an entry in Vglyph_table,
Karl Heuer's avatar
Karl Heuer committed
861 862
		 so process any alias before testing for simpleness.  */
	      GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
863 864 865

	      if (GLYPH_SIMPLE_P (tbase, tlen, g))
		{
866 867 868 869 870 871 872
		  int c = FAST_GLYPH_CHAR (g);

		  if (CHAR_VALID_P (c, 0))
		    buf += CHAR_STRING (c, buf);
		  else
		    *buf++ = SPACEGLYPH;
		  nchars++;
873 874 875 876
		}
	      else
		{
		  /* We have a string in Vglyph_table.  */
877 878 879 880 881 882
		  Lisp_Object string;

		  string = tbase[g];
		  if (! STRING_MULTIBYTE (string))
		    string = string_to_multibyte (string);
		  nbytes = buf - encode_terminal_buf;
883
		  if (encode_terminal_bufsize < nbytes + SBYTES (string))
884 885 886 887 888 889 890 891 892
		    {
		      encode_terminal_bufsize = nbytes + SBYTES (string);
		      encode_terminal_buf = xrealloc (encode_terminal_buf,
						      encode_terminal_bufsize);
		      buf = encode_terminal_buf + nbytes;
		    }
		  bcopy (SDATA (string), buf, SBYTES (string));
		  buf += SBYTES (string);
		  nchars += SCHARS (string);
893
		}
Richard M. Stallman's avatar
Richard M. Stallman committed
894
	    }
Karl Heuer's avatar
Karl Heuer committed
895 896 897
	}
      src++;
    }
898

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
  nbytes = buf - encode_terminal_buf;
  coding->src_multibyte = 1;
  coding->dst_multibyte = 0;
  if (SYMBOLP (coding->pre_write_conversion)
      && ! NILP (Ffboundp (coding->pre_write_conversion)))
    {
      run_pre_write_conversin_on_c_str (&encode_terminal_buf, 
					&encode_terminal_bufsize,
					nchars, nbytes, coding);
      nchars = coding->produced_char;
      nbytes = coding->produced;
    }
  required = nbytes + encoding_buffer_size (coding, nbytes);
  if (encode_terminal_bufsize < required)
    {
      encode_terminal_bufsize = required;
      encode_terminal_buf = xrealloc (encode_terminal_buf, required);
    }
Karl Heuer's avatar
Karl Heuer committed
917

918 919 920 921
  encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
		 nbytes, encode_terminal_bufsize - nbytes);
  return encode_terminal_buf + nbytes;
}
Jim Blandy's avatar
Jim Blandy committed
922

Andreas Schwab's avatar
Andreas Schwab committed
923
void
Jim Blandy's avatar
Jim Blandy committed
924
write_glyphs (string, len)
Gerd Moellmann's avatar
Gerd Moellmann committed
925
     register struct glyph *string;
Jim Blandy's avatar
Jim Blandy committed
926 927
     register int len;
{
928 929
  struct frame *sf = XFRAME (selected_frame);
  struct frame *f = updating_frame ? updating_frame : sf;
930 931
  unsigned char *conversion_buffer;
  struct coding_system *coding;
Jim Blandy's avatar
Jim Blandy committed
932 933

  if (write_glyphs_hook
Gerd Moellmann's avatar
Gerd Moellmann committed
934
      && ! FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
935 936 937 938 939 940
    {
      (*write_glyphs_hook) (string, len);
      return;
    }

  turn_off_insert ();
941
  tty_hide_cursor ();
Jim Blandy's avatar
Jim Blandy committed
942

Gerd Moellmann's avatar
Gerd Moellmann committed
943
  /* Don't dare write in last column of bottom line, if Auto-Wrap,
Jim Blandy's avatar
Jim Blandy committed
944
     since that would scroll the whole frame on some terminals.  */
Jim Blandy's avatar
Jim Blandy committed
945 946

  if (AutoWrap
947 948
      && curY + 1 == FRAME_LINES (sf)
      && (curX + len) == FRAME_COLS (sf))
Jim Blandy's avatar
Jim Blandy committed
949
    len --;
Karl Heuer's avatar
Karl Heuer committed
950 951
  if (len <= 0)
    return;
Jim Blandy's avatar
Jim Blandy committed
952 953

  cmplus (len);
954

955 956 957 958 959
  /* If terminal_coding does any conversion, use it, otherwise use
     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
     because it always return 1 if the member src_multibyte is 1.  */
  coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
	    ? &terminal_coding : &safe_terminal_coding);
960 961
  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
     the tail.  */
962
  coding->mode &= ~CODING_MODE_LAST_BLOCK;
963

Karl Heuer's avatar
Karl Heuer committed
964
  while (len > 0)
Jim Blandy's avatar
Jim Blandy committed
965
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
966
      /* Identify a run of glyphs with the same face.  */
967
      int face_id = string->face_id;
Gerd Moellmann's avatar
Gerd Moellmann committed
968
      int n;
969

Gerd Moellmann's avatar
Gerd Moellmann committed
970
      for (n = 1; n < len; ++n)
971
	if (string[n].face_id != face_id)
Gerd Moellmann's avatar
Gerd Moellmann committed
972 973 974
	  break;

      /* Turn appearance modes of the face of the run on.  */
975
      highlight_if_desired ();
Gerd Moellmann's avatar
Gerd Moellmann committed
976 977
      turn_on_face (f, face_id);

978 979 980 981 982
      if (n == len)
	/* This is the last run.  */
	coding->mode |= CODING_MODE_LAST_BLOCK;
      conversion_buffer = encode_terminal_code (string, n, coding);
      if (coding->produced > 0)
Jim Blandy's avatar
Jim Blandy committed
983
	{
984 985 986 987 988
	  fwrite (conversion_buffer, 1, coding->produced, stdout);
	  if (ferror (stdout))
	    clearerr (stdout);
	  if (termscript)
	    fwrite (conversion_buffer, 1, coding->produced, termscript);
Jim Blandy's avatar
Jim Blandy committed
989
	}
990 991
      len -= n;
      string += n;
Gerd Moellmann's avatar
Gerd Moellmann committed
992 993 994

      /* Turn appearance modes off.  */
      turn_off_face (f, face_id);
995
      turn_off_highlight ();
Karl Heuer's avatar
Karl Heuer committed
996
    }
997

998
  cmcheckmagic ();
Jim Blandy's avatar
Jim Blandy committed
999 1000 1001
}

/* If start is zero, insert blanks instead of a string at start */
1002

Andreas Schwab's avatar
Andreas Schwab committed
1003
void
Jim Blandy's avatar
Jim Blandy committed
1004
insert_glyphs (start, len)
Gerd Moellmann's avatar
Gerd Moellmann committed
1005
     register struct glyph *start;
Jim Blandy's avatar
Jim Blandy committed
1006 1007 1008
     register int len;
{
  char *buf;
1009
  struct glyph *glyph = NULL;
1010
  struct frame *f, *sf;
1011 1012 1013
  unsigned char *conversion_buffer;
  unsigned char space[1];
  struct coding_system *coding;
Jim Blandy's avatar
Jim Blandy committed
1014

Karl Heuer's avatar
Karl Heuer committed
1015 1016 1017
  if (len <= 0)
    return;

Gerd Moellmann's avatar
Gerd Moellmann committed
1018
  if (insert_glyphs_hook)
Jim Blandy's avatar
Jim Blandy committed
1019 1020 1021 1022
    {
      (*insert_glyphs_hook) (start, len);
      return;
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
1023

1024 1025
  sf = XFRAME (selected_frame);
  f = updating_frame ? updating_frame : sf;
Jim Blandy's avatar
Jim Blandy committed
1026 1027 1028 1029 1030

  if (TS_ins_multi_chars)
    {
      buf = tparam (TS_ins_multi_chars, 0, 0, len);
      OUTPUT1 (buf);
1031
      xfree (buf);
Jim Blandy's avatar
Jim Blandy committed
1032 1033 1034 1035 1036 1037 1038
      if (start)
	write_glyphs (start, len);
      return;
    }

  turn_on_insert ();
  cmplus (len);
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051

  if (! start)
    space[0] = SPACEGLYPH;

  /* If terminal_coding does any conversion, use it, otherwise use
     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
     because it always return 1 if the member src_multibyte is 1.  */
  coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
	    ? &terminal_coding : &safe_terminal_coding);
  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
     the tail.  */
  coding->mode &= ~CODING_MODE_LAST_BLOCK;

1052
  while (len-- > 0)
Jim Blandy's avatar
Jim Blandy committed
1053 1054 1055
    {
      OUTPUT1_IF (TS_ins_char);
      if (!start)
1056
	{
1057 1058
	  conversion_buffer = space;
	  coding->produced = 1;
1059
	}
Jim Blandy's avatar
Jim Blandy committed
1060 1061
      else
	{
1062
	  highlight_if_desired ();
1063
	  turn_on_face (f, start->face_id);
1064
	  glyph = start;
Gerd Moellmann's avatar
Gerd Moellmann committed
1065
	  ++start;
Karl Heuer's avatar
Karl Heuer committed
1066 1067
	  /* We must open sufficient space for a character which
	     occupies more than one column.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
1068
	  while (len && CHAR_GLYPH_PADDING_P (*start))
Karl Heuer's avatar
Karl Heuer committed
1069 1070 1071 1072 1073
	    {
	      OUTPUT1_IF (TS_ins_char);
	      start++, len--;
	    }

1074 1075
	  if (len <= 0)
	    /* This is the last glyph.  */
1076
	    coding->mode |= CODING_MODE_LAST_BLOCK;
1077

1078
	  conversion_buffer = encode_terminal_code (glyph, 1, coding);
1079
	}
Karl Heuer's avatar
Karl Heuer committed
1080

1081
      if (coding->produced > 0)
Jim Blandy's avatar
Jim Blandy committed
1082
	{
1083
	  fwrite (conversion_buffer, 1, coding->produced, stdout);
Jim Blandy's avatar
Jim Blandy committed
1084 1085 1086
	  if (ferror (stdout))
	    clearerr (stdout);
	  if (termscript)
1087
	    fwrite (conversion_buffer, 1, coding->produced, termscript);
Jim Blandy's avatar
Jim Blandy committed
1088 1089
	}

1090
      OUTPUT1_IF (TS_pad_inserted_char);
1091
      if (start)
1092 1093 1094 1095
	{
	  turn_off_face (f, glyph->face_id);
	  turn_off_highlight ();
	}
1096
    }
1097

1098
  cmcheckmagic ();
Jim Blandy's avatar
Jim Blandy committed
1099 1100
}

Andreas Schwab's avatar
Andreas Schwab committed
1101
void
Jim Blandy's avatar
Jim Blandy committed
1102 1103 1104 1105 1106 1107
delete_glyphs (n)
     register int n;
{
  char *buf;
  register int i;

1108
  if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
Jim Blandy's avatar
Jim Blandy committed
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
    {
      (*delete_glyphs_hook) (n);
      return;
    }

  if (delete_in_insert_mode)
    {
      turn_on_insert ();
    }
  else
    {
      turn_off_insert ();
      OUTPUT_IF (TS_delete_mode);
    }

  if (TS_del_multi_chars)
    {
      buf = tparam (TS_del_multi_chars, 0, 0, n);
      OUTPUT1 (buf);
1128
      xfree (buf);
Jim Blandy's avatar
Jim Blandy committed
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
    }
  else
    for (i = 0; i < n; i++)
      OUTPUT1 (TS_del_char);
  if (!delete_in_insert_mode)
    OUTPUT_IF (TS_end_delete_mode);
}

/* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */

Andreas Schwab's avatar
Andreas Schwab committed
1139
void
Jim Blandy's avatar
Jim Blandy committed
1140 1141 1142 1143 1144 1145
ins_del_lines (vpos, n)
     int vpos, n;
{
  char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
  char *single = n > 0 ? TS_ins_line : TS_del_line;
  char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1146
  struct frame *sf;