term.c 76 KB
Newer Older
1
/* Terminal control module for terminals described by TERMCAP
Miles Bader's avatar
Miles Bader committed
2
   Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002
3
   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
19 20
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, 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

29 30
#include <sys/file.h>

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

45 46 47 48 49
/* 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
50
#include <termcap.h>
51 52 53 54 55
#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));
56 57
#endif

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

66 67 68 69
#ifndef O_RDWR
#define O_RDWR 2
#endif

Gerd Moellmann's avatar
Gerd Moellmann committed
70 71
static void turn_on_face P_ ((struct frame *, int face_id));
static void turn_off_face P_ ((struct frame *, int face_id));
72 73 74 75 76 77
static void tty_show_cursor P_ ((struct tty_output *));
static void tty_hide_cursor P_ ((struct tty_output *));

void delete_tty P_ ((struct tty_output *));
static void delete_tty_1 P_ ((struct tty_output *));

Gerd Moellmann's avatar
Gerd Moellmann committed
78

79 80 81 82 83 84
#define OUTPUT(tty, a)                                          \
  emacs_tputs ((tty), a,                                        \
               (int) (FRAME_LINES (XFRAME (selected_frame))     \
                      - curY (tty)),                            \
               cmputc)

85 86
#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
Gerd Moellmann's avatar
Gerd Moellmann committed
87

88
#define OUTPUT_IF(tty, a)                                               \
89 90 91 92 93 94 95
  do {                                                                  \
    if (a)                                                              \
      emacs_tputs ((tty), a,                                            \
                   (int) (FRAME_LINES (XFRAME (selected_frame))         \
                          - curY (tty) ),                               \
                   cmputc);                                             \
  } while (0)
96

97
#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
Jim Blandy's avatar
Jim Blandy committed
98

99
/* Function to use to ring the bell.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
100

101 102
Lisp_Object Vring_bell_function;

103
/* Terminal characteristics that higher levels want to look at. */
104 105

struct tty_output *tty_list;
Jim Blandy's avatar
Jim Blandy committed
106

107 108 109 110
/* Nonzero means no need to redraw the entire frame on resuming a
   suspended Emacs.  This is useful on terminals with multiple
   pages, where one page is used for Emacs and another for all
   else. */
Jim Blandy's avatar
Jim Blandy committed
111
int no_redraw_on_reenter;
112
  
Jim Blandy's avatar
Jim Blandy committed
113 114 115
/* 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
116 117 118 119 120
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
121

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

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

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

Andreas Schwab's avatar
Andreas Schwab committed
128 129 130 131 132
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
133 134 135
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
136

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

Andreas Schwab's avatar
Andreas Schwab committed
139
void (*frame_up_to_date_hook) P_ ((struct frame *));
140

141
/* Return the current position of the mouse.
142 143 144 145 146

   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.

147 148 149 150
   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.
151 152 153 154 155 156 157 158

   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.  */
159

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

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

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

Jim Blandy's avatar
Jim Blandy committed
175 176 177 178 179 180 181 182 183 184
/* 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.  */
185

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

188
/* Set the vertical scroll bar for WINDOW to have its upper left corner
189 190 191
   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
192
   have a scroll bar, create one for it.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
193

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

198

199
/* The following three hooks are used when we're doing a thorough
200
   redisplay of the frame.  We don't explicitly know which scroll bars
201 202 203
   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*
204
   scroll bars are to be removed, and then save scroll bars from the
Karl Heuer's avatar
Karl Heuer committed
205
   fiery pit when we actually redisplay their window.  */
206

207 208
/* 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
209
   `*redeem_scroll_bar_hook' is applied to its window before the judgment.
210

211
   This should be applied to each frame each time its window tree is
212 213 214
   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.
215 216

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

Andreas Schwab's avatar
Andreas Schwab committed
220
void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
221

222 223
/* 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.  */
224

Andreas Schwab's avatar
Andreas Schwab committed
225
void (*redeem_scroll_bar_hook) P_ ((struct window *window));
226

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

230
   This should be applied to each frame after each time its window
231 232 233
   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.
234 235

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

Andreas Schwab's avatar
Andreas Schwab committed
239
void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
240

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

/* 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
};

Jim Blandy's avatar
Jim Blandy committed
258 259
/* internal state */

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

262
int max_frame_cols;
Gerd Moellmann's avatar
Gerd Moellmann committed
263

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

266
int max_frame_lines;
267

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

Jim Blandy's avatar
Jim Blandy committed
271
FRAME_PTR updating_frame;
Jim Blandy's avatar
Jim Blandy committed
272

273
/* Provided for lisp packages.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
274

275 276
static int system_uses_terminfo;

Jim Blandy's avatar
Jim Blandy committed
277
char *tparam ();
278 279

extern char *tgetstr ();
Jim Blandy's avatar
Jim Blandy committed
280

281

282 283 284 285 286 287 288 289 290 291 292
#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
293
void
Jim Blandy's avatar
Jim Blandy committed
294 295
ring_bell ()
{
296 297
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));

298
  if (!NILP (Vring_bell_function))
299 300 301 302 303 304 305 306 307 308
    {
      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.  */
309

310 311 312 313 314 315
      function = Vring_bell_function;
      Vring_bell_function = Qnil;

      call0 (function);

      Vring_bell_function = function;
Jim Blandy's avatar
Jim Blandy committed
316
    }
317
  else if (!FRAME_TERMCAP_P (f))
318
    (*ring_bell_hook) ();
319
  else {
320
    struct tty_output *tty = FRAME_TTY (f);
321
    OUTPUT (tty, tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell);
322
  }
Jim Blandy's avatar
Jim Blandy committed
323 324
}

325 326 327 328 329 330 331 332
void tty_set_terminal_modes (struct tty_output *tty)
{
  OUTPUT_IF (tty, tty->TS_termcap_modes);
  OUTPUT_IF (tty, tty->TS_cursor_visible);
  OUTPUT_IF (tty, tty->TS_keypad_mode);
  losecursor (tty);
}

Andreas Schwab's avatar
Andreas Schwab committed
333
void
334
set_terminal_modes ()
Jim Blandy's avatar
Jim Blandy committed
335
{
336 337
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
  if (FRAME_TERMCAP_P (f))
338
    tty_set_terminal_modes (FRAME_TTY (f));
339 340
  else
    (*set_terminal_modes_hook) ();
Jim Blandy's avatar
Jim Blandy committed
341 342
}

343 344 345 346 347 348 349 350 351 352 353 354 355
void tty_reset_terminal_modes (struct tty_output *tty)
{
  turn_off_highlight (tty);
  turn_off_insert (tty);
  OUTPUT_IF (tty, tty->TS_end_keypad_mode);
  OUTPUT_IF (tty, tty->TS_cursor_normal);
  OUTPUT_IF (tty, tty->TS_end_termcap_modes);
  OUTPUT_IF (tty, tty->TS_orig_pair);
  /* Output raw CR so kernel can track the cursor hpos.  */
  current_tty = tty;
  cmputc ('\r');
}

Andreas Schwab's avatar
Andreas Schwab committed
356
void
357
reset_terminal_modes ()
Jim Blandy's avatar
Jim Blandy committed
358
{
359 360
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
  if (FRAME_TERMCAP_P (f))
361
    tty_reset_terminal_modes (FRAME_TTY (f));
362 363
  else if (reset_terminal_modes_hook)
    (*reset_terminal_modes_hook) ();
Jim Blandy's avatar
Jim Blandy committed
364 365
}

Andreas Schwab's avatar
Andreas Schwab committed
366
void
Jim Blandy's avatar
Jim Blandy committed
367
update_begin (f)
368
     struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
369
{
Jim Blandy's avatar
Jim Blandy committed
370
  updating_frame = f;
371 372
  if (!FRAME_TERMCAP_P (f))
    update_begin_hook (f);
Jim Blandy's avatar
Jim Blandy committed
373 374
}

Andreas Schwab's avatar
Andreas Schwab committed
375
void
Jim Blandy's avatar
Jim Blandy committed
376
update_end (f)
377
     struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
378
{
379
  if (FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
380
    {
381
      struct tty_output *tty = FRAME_TTY (f);
382
      if (!XWINDOW (selected_window)->cursor_off_p)
383 384 385
	tty_show_cursor (tty);
      turn_off_insert (tty);
      background_highlight (tty);
Jim Blandy's avatar
Jim Blandy committed
386
    }
387 388
  else
    update_end_hook (f);
389

390
  updating_frame = NULL;
Jim Blandy's avatar
Jim Blandy committed
391 392
}

Andreas Schwab's avatar
Andreas Schwab committed
393
void
Jim Blandy's avatar
Jim Blandy committed
394 395 396
set_terminal_window (size)
     int size;
{
397 398
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
  if (FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
399
    {
400
      struct tty_output *tty = FRAME_TTY (f);
401
      tty->specified_window = size ? size : FRAME_LINES (f);
402
      if (TTY_SCROLL_REGION_OK (tty))
403
	set_scroll_region (0, tty->specified_window);
Jim Blandy's avatar
Jim Blandy committed
404
    }
405 406
  else
    set_terminal_window_hook (size);
Jim Blandy's avatar
Jim Blandy committed
407 408
}

Andreas Schwab's avatar
Andreas Schwab committed
409
void
Jim Blandy's avatar
Jim Blandy committed
410 411 412 413
set_scroll_region (start, stop)
     int start, stop;
{
  char *buf;
414 415
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
  struct tty_output *tty = FRAME_TTY (f);
416

417 418 419 420
  if (tty->TS_set_scroll_region)
    buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
  else if (tty->TS_set_scroll_region_1)
    buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
421 422 423
		  FRAME_LINES (f), start,
		  FRAME_LINES (f) - stop,
		  FRAME_LINES (f));
Jim Blandy's avatar
Jim Blandy committed
424
  else
425
    buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
426

427
  OUTPUT (tty, buf);
428
  xfree (buf);
429
  losecursor (tty);
Jim Blandy's avatar
Jim Blandy committed
430
}
431

Jim Blandy's avatar
Jim Blandy committed
432

433
static void
434
turn_on_insert (struct tty_output *tty)
Jim Blandy's avatar
Jim Blandy committed
435
{
436 437 438
  if (!tty->insert_mode)
    OUTPUT (tty, tty->TS_insert_mode);
  tty->insert_mode = 1;
Jim Blandy's avatar
Jim Blandy committed
439 440
}

Andreas Schwab's avatar
Andreas Schwab committed
441
void
442
turn_off_insert (struct tty_output *tty)
Jim Blandy's avatar
Jim Blandy committed
443
{
444 445 446
  if (tty->insert_mode)
    OUTPUT (tty, tty->TS_end_insert_mode);
  tty->insert_mode = 0;
Jim Blandy's avatar
Jim Blandy committed
447 448
}

449
/* Handle highlighting.  */
Jim Blandy's avatar
Jim Blandy committed
450

Andreas Schwab's avatar
Andreas Schwab committed
451
void
452
turn_off_highlight (struct tty_output *tty)
Jim Blandy's avatar
Jim Blandy committed
453
{
454 455 456
  if (tty->standout_mode)
    OUTPUT_IF (tty, tty->TS_end_standout_mode);
  tty->standout_mode = 0;
Jim Blandy's avatar
Jim Blandy committed
457 458
}

459
static void
460
turn_on_highlight (struct tty_output *tty)
Jim Blandy's avatar
Jim Blandy committed
461
{
462 463 464
  if (!tty->standout_mode)
    OUTPUT_IF (tty, tty->TS_standout_mode);
  tty->standout_mode = 1;
Jim Blandy's avatar
Jim Blandy committed
465 466
}

467
static void
468
toggle_highlight (struct tty_output *tty)
469
{
470 471
  if (tty->standout_mode)
    turn_off_highlight (tty);
472
  else
473
    turn_on_highlight (tty);
474 475
}

Gerd Moellmann's avatar
Gerd Moellmann committed
476 477 478 479

/* Make cursor invisible.  */

static void
480
tty_hide_cursor (struct tty_output *tty)
Gerd Moellmann's avatar
Gerd Moellmann committed
481
{
482
  if (tty->cursor_hidden == 0)
483
    {
484 485
      tty->cursor_hidden = 1;
      OUTPUT_IF (tty, tty->TS_cursor_invisible);
486
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
487 488 489 490 491 492
}


/* Ensure that cursor is visible.  */

static void
493
tty_show_cursor (struct tty_output *tty)
Gerd Moellmann's avatar
Gerd Moellmann committed
494
{
495
  if (tty->cursor_hidden)
496
    {
497 498 499
      tty->cursor_hidden = 0;
      OUTPUT_IF (tty, tty->TS_cursor_normal);
      OUTPUT_IF (tty, tty->TS_cursor_visible);
500
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
501 502 503
}


Jim Blandy's avatar
Jim Blandy committed
504 505 506 507
/* 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
508
void
509
background_highlight (struct tty_output *tty)
Jim Blandy's avatar
Jim Blandy committed
510 511
{
  if (inverse_video)
512
    turn_on_highlight (tty);
Jim Blandy's avatar
Jim Blandy committed
513
  else
514
    turn_off_highlight (tty);
Jim Blandy's avatar
Jim Blandy committed
515 516 517 518
}

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

Andreas Schwab's avatar
Andreas Schwab committed
519
static void
520
highlight_if_desired (struct tty_output *tty)
Jim Blandy's avatar
Jim Blandy committed
521
{
522
  if (inverse_video)
523
    turn_on_highlight (tty);
524
  else
525
    turn_off_highlight (tty);
Jim Blandy's avatar
Jim Blandy committed
526 527 528
}


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

Andreas Schwab's avatar
Andreas Schwab committed
532
void
Gerd Moellmann's avatar
Gerd Moellmann committed
533 534
cursor_to (vpos, hpos)
     int vpos, hpos;
Jim Blandy's avatar
Jim Blandy committed
535
{
536
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
537 538
  struct tty_output *tty;
  
539
  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
Jim Blandy's avatar
Jim Blandy committed
540
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
541
      (*cursor_to_hook) (vpos, hpos);
Jim Blandy's avatar
Jim Blandy committed
542 543 544
      return;
    }

545
  tty = FRAME_TTY (f);
546

547 548
  /* Detect the case where we are called from reset_sys_modes
     and the costs have never been calculated.  Do nothing.  */
549
  if (! tty->costs_set)
550 551
    return;

552 553
  if (curY (tty) == vpos
      && curX (tty) == hpos)
Jim Blandy's avatar
Jim Blandy committed
554
    return;
555 556 557 558
  if (!tty->TF_standout_motion)
    background_highlight (tty);
  if (!tty->TF_insmode_motion)
    turn_off_insert (tty);
559
  cmgoto (tty, vpos, hpos);
Jim Blandy's avatar
Jim Blandy committed
560 561 562 563
}

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

Andreas Schwab's avatar
Andreas Schwab committed
564
void
Jim Blandy's avatar
Jim Blandy committed
565
raw_cursor_to (row, col)
Jim Blandy's avatar
Jim Blandy committed
566
     int row, col;
Jim Blandy's avatar
Jim Blandy committed
567
{
568
  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
569
  struct tty_output *tty;
570
  if (! FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
571 572 573 574
    {
      (*raw_cursor_to_hook) (row, col);
      return;
    }
575
  tty = FRAME_TTY (f);
576 577
  if (curY (tty) == row
      && curX (tty) == col)
Jim Blandy's avatar
Jim Blandy committed
578
    return;
579 580 581 582
  if (!tty->TF_standout_motion)
    background_highlight (tty);
  if (!tty->TF_insmode_motion)
    turn_off_insert (tty);
583
  cmgoto (tty, row, col);
Jim Blandy's avatar
Jim Blandy committed
584 585 586 587
}

/* Erase operations */

Jim Blandy's avatar
Jim Blandy committed
588
/* clear from cursor to end of frame */
Andreas Schwab's avatar
Andreas Schwab committed
589
void
Jim Blandy's avatar
Jim Blandy committed
590 591 592 593
clear_to_end ()
{
  register int i;

594
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
595
  struct tty_output *tty;
596 597
  
  if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
598 599 600 601
    {
      (*clear_to_end_hook) ();
      return;
    }
602 603
  tty = FRAME_TTY (f);
  if (tty->TS_clr_to_bottom)
Jim Blandy's avatar
Jim Blandy committed
604
    {
605 606
      background_highlight (tty);
      OUTPUT (tty, tty->TS_clr_to_bottom);
Jim Blandy's avatar
Jim Blandy committed
607 608 609
    }
  else
    {
610
      for (i = curY (tty); i < FRAME_LINES (f); i++)
Jim Blandy's avatar
Jim Blandy committed
611 612
	{
	  cursor_to (i, 0);
613
	  clear_end_of_line (FRAME_COLS (f));
Jim Blandy's avatar
Jim Blandy committed
614 615 616 617
	}
    }
}

Jim Blandy's avatar
Jim Blandy committed
618
/* Clear entire frame */
Jim Blandy's avatar
Jim Blandy committed
619

Andreas Schwab's avatar
Andreas Schwab committed
620
void
Jim Blandy's avatar
Jim Blandy committed
621
clear_frame ()
Jim Blandy's avatar
Jim Blandy committed
622
{
623
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
624 625
  struct tty_output *tty;
  
626
  if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
627
    {
Jim Blandy's avatar
Jim Blandy committed
628
      (*clear_frame_hook) ();
Jim Blandy's avatar
Jim Blandy committed
629 630
      return;
    }
631 632
  tty = FRAME_TTY (f);
  if (tty->TS_clr_frame)
Jim Blandy's avatar
Jim Blandy committed
633
    {
634 635
      background_highlight (tty);
      OUTPUT (tty, tty->TS_clr_frame);
636
      cmat (tty, 0, 0);
Jim Blandy's avatar
Jim Blandy committed
637 638 639 640 641 642 643 644 645 646 647 648 649
    }
  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
650
void
651
clear_end_of_line (first_unused_hpos)
Jim Blandy's avatar
Jim Blandy committed
652 653 654 655
     int first_unused_hpos;
{
  register int i;

656
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
657
  struct tty_output *tty;
658
  
Jim Blandy's avatar
Jim Blandy committed
659
  if (clear_end_of_line_hook
660
      && ! FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
661 662 663 664 665
    {
      (*clear_end_of_line_hook) (first_unused_hpos);
      return;
    }

666
  tty = FRAME_TTY (f);
667

668 669
  /* Detect the case where we are called from reset_sys_modes
     and the costs have never been calculated.  Do nothing.  */
670
  if (! tty->costs_set)
671 672
    return;

673
  if (curX (tty) >= first_unused_hpos)
Jim Blandy's avatar
Jim Blandy committed
674
    return;
675 676
  background_highlight (tty);
  if (tty->TS_clr_line)
Jim Blandy's avatar
Jim Blandy committed
677
    {
678
      OUTPUT1 (tty, tty->TS_clr_line);
Jim Blandy's avatar
Jim Blandy committed
679 680 681
    }
  else
    {			/* have to do it the hard way */
682
      turn_off_insert (tty);
Jim Blandy's avatar
Jim Blandy committed
683

Gerd Moellmann's avatar
Gerd Moellmann committed
684
      /* Do not write in last row last col with Auto-wrap on. */
685 686
      if (AutoWrap (tty)
          && curY (tty) == FRAME_LINES (f) - 1
687
	  && first_unused_hpos == FRAME_COLS (f))
Jim Blandy's avatar
Jim Blandy committed
688 689
	first_unused_hpos--;

690
      for (i = curX (tty); i < first_unused_hpos; i++)
Jim Blandy's avatar
Jim Blandy committed
691
	{
692 693 694
	  if (TTY_TERMSCRIPT (tty))
	    fputc (' ', TTY_TERMSCRIPT (tty));
	  fputc (' ', TTY_OUTPUT (tty));
Jim Blandy's avatar
Jim Blandy committed
695
	}
696
      cmplus (tty, first_unused_hpos - curX (tty));
Jim Blandy's avatar
Jim Blandy committed
697 698 699
    }
}

Karl Heuer's avatar
Karl Heuer committed
700 701 702 703 704 705 706 707 708 709
/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
   store them at DST.  Do not write more than DST_LEN bytes.  That may
   require stopping before all SRC_LEN input glyphs have been
   converted.

   We store the number of glyphs actually converted in *CONSUMED.  The
   return value is the number of bytes store in DST.  */

int
encode_terminal_code (src, dst, src_len, dst_len, consumed)
Gerd Moellmann's avatar
Gerd Moellmann committed
710
     struct glyph *src;
Karl Heuer's avatar
Karl Heuer committed
711 712 713 714
     int src_len;
     unsigned char *dst;
     int dst_len, *consumed;
{
Gerd Moellmann's avatar
Gerd Moellmann committed
715
  struct glyph *src_start = src, *src_end = src + src_len;
Karl Heuer's avatar
Karl Heuer committed
716
  unsigned char *dst_start = dst, *dst_end = dst + dst_len;
717
  register GLYPH g;
718 719
  unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
  const unsigned char *buf;
720
  int len;
Karl Heuer's avatar
Karl Heuer committed
721 722
  register int tlen = GLYPH_TABLE_LENGTH;
  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
723
  int result;
724 725
  struct coding_system *coding;

726 727 728 729
  /* 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
730 731
	    ? &terminal_coding
	    : &safe_terminal_coding);
Karl Heuer's avatar
Karl Heuer committed
732 733 734 735

  while (src < src_end)
    {
      /* We must skip glyphs to be padded for a wide character.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
736
      if (! CHAR_GLYPH_PADDING_P (*src))
Karl Heuer's avatar
Karl Heuer committed
737
	{
738 739 740
	  g = GLYPH_FROM_CHAR_GLYPH (src[0]);

	  if (g < 0 || g >= tlen)
741
	    {
742 743 744 745 746
	      /* This glyph doesn't has an entry in Vglyph_table.  */
	      if (! CHAR_VALID_P (src->u.ch, 0))
		{
		  len = 1;
		  buf = " ";
747
		  coding->src_multibyte = 0;
748 749 750 751 752
		}
	      else
		{
		  len = CHAR_STRING (src->u.ch, workbuf);
		  buf = workbuf;
753
		  coding->src_multibyte = 1;
754
		}
755
	    }
756
	  else
Karl Heuer's avatar
Karl Heuer committed
757
	    {
758
	      /* This glyph has an entry in Vglyph_table,
Karl Heuer's avatar
Karl Heuer committed
759 760
		 so process any alias before testing for simpleness.  */
	      GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
761 762 763

	      if (GLYPH_SIMPLE_P (tbase, tlen, g))
		{
764 765 766 767 768
		  /* We set the multi-byte form of a character in G
		     (that should be an ASCII character) at
		     WORKBUF.  */
		  workbuf[0] = FAST_GLYPH_CHAR (g);
		  len = 1;
769
		  buf = workbuf;
770
		  coding->src_multibyte = 0;
771 772 773 774 775 776
		}
	      else
		{
		  /* We have a string in Vglyph_table.  */
		  len = GLYPH_LENGTH (tbase, g);
		  buf = GLYPH_STRING (tbase, g);
777
		  coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
778
		}
Richard M. Stallman's avatar
Richard M. Stallman committed
779
	    }
780

781
	  result = encode_coding (coding, buf, dst, len, dst_end - dst);
782
	  len -= coding->consumed;
783
	  dst += coding->produced;
784 785 786 787 788 789 790 791
	  if (result == CODING_FINISH_INSUFFICIENT_DST
	      || (result == CODING_FINISH_INSUFFICIENT_SRC
		  && len > dst_end - dst))
	    /* The remaining output buffer is too short.  We must
	       break the loop here without increasing SRC so that the
	       next call of this function starts from the same glyph.  */
	    break;

792 793
	  if (len > 0)
	    {
794 795 796 797 798
	      /* This is the case that a code of the range 0200..0237
		 exists in buf.  We must just write out such a code.  */
	      buf += coding->consumed;
	      while (len--)
		*dst++ = *buf++;
799
	    }
Karl Heuer's avatar
Karl Heuer committed
800 801 802
	}
      src++;
    }