term.c 78.7 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
static void tty_show_cursor P_ ((struct tty_display_info *));
static void tty_hide_cursor P_ ((struct tty_display_info *));
74

75 76
void delete_tty P_ ((struct tty_display_info *));
static void delete_tty_1 P_ ((struct tty_display_info *));
77

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_display_info *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 113 114

Lisp_Object Qframe_tty_name, Qframe_tty_type;

Jim Blandy's avatar
Jim Blandy committed
115 116 117
/* 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_ ((struct input_event *, int, int));
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

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259

/* 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
260 261
/* internal state */

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

264
int max_frame_cols;
Gerd Moellmann's avatar
Gerd Moellmann committed
265

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

268
int max_frame_lines;
269

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

Jim Blandy's avatar
Jim Blandy committed
273
FRAME_PTR updating_frame;
Jim Blandy's avatar
Jim Blandy committed
274

275
/* Provided for lisp packages.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
276

277 278
static int system_uses_terminfo;

Jim Blandy's avatar
Jim Blandy committed
279
char *tparam ();
280 281

extern char *tgetstr ();
Jim Blandy's avatar
Jim Blandy committed
282

283

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

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

312 313 314 315 316 317
      function = Vring_bell_function;
      Vring_bell_function = Qnil;

      call0 (function);

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

327
void tty_set_terminal_modes (struct tty_display_info *tty)
328 329 330 331 332 333 334
{
  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
335
void
336
set_terminal_modes ()
Jim Blandy's avatar
Jim Blandy committed
337
{
338 339
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
  if (FRAME_TERMCAP_P (f))
340
    tty_set_terminal_modes (FRAME_TTY (f));
341 342
  else
    (*set_terminal_modes_hook) ();
Jim Blandy's avatar
Jim Blandy committed
343 344
}

345
void tty_reset_terminal_modes (struct tty_display_info *tty)
346 347 348 349 350 351 352 353 354 355 356 357
{
  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
358
void
359
reset_terminal_modes ()
Jim Blandy's avatar
Jim Blandy committed
360
{
361 362
  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
  if (FRAME_TERMCAP_P (f))
363
    tty_reset_terminal_modes (FRAME_TTY (f));
364 365
  else if (reset_terminal_modes_hook)
    (*reset_terminal_modes_hook) ();
Jim Blandy's avatar
Jim Blandy committed
366 367
}

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

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

392
  updating_frame = NULL;
Jim Blandy's avatar
Jim Blandy committed
393 394
}

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

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

419 420 421 422
  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,
423 424 425
		  FRAME_LINES (f), start,
		  FRAME_LINES (f) - stop,
		  FRAME_LINES (f));
Jim Blandy's avatar
Jim Blandy committed
426
  else
427
    buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
428

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

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

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

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

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

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

Gerd Moellmann's avatar
Gerd Moellmann committed
478 479 480 481

/* Make cursor invisible.  */

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


/* Ensure that cursor is visible.  */

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


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

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

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

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

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

547
  tty = FRAME_TTY (f);
548

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

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

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

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

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

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

Jim Blandy's avatar
Jim Blandy committed
620
/* Clear entire frame */
Jim Blandy's avatar
Jim Blandy committed
621

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

Karoly Lorentey's avatar
Karoly Lorentey committed
666 667
  tty_clear_end_of_line (FRAME_TTY (f), first_unused_hpos);
}
668

Karoly Lorentey's avatar
Karoly Lorentey committed
669
void
670
tty_clear_end_of_line (struct tty_display_info *tty, int first_unused_hpos)
Karoly Lorentey's avatar
Karoly Lorentey committed
671 672
{
  register int i;
673 674
  /* Detect the case where we are called from reset_sys_modes
     and the costs have never been calculated.  Do nothing.  */
675
  if (! tty->costs_set)
676 677
    return;

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

Gerd Moellmann's avatar
Gerd Moellmann committed
689
      /* Do not write in last row last col with Auto-wrap on. */
690
      if (AutoWrap (tty)
Karoly Lorentey's avatar
Karoly Lorentey committed
691 692
          && curY (tty) == FrameRows (tty) - 1
	  && first_unused_hpos == FrameCols (tty))
Jim Blandy's avatar
Jim Blandy committed
693 694
	first_unused_hpos--;

695
      for (i = curX (tty); i < first_unused_hpos; i++)
Jim Blandy's avatar
Jim Blandy committed
696
	{
697 698 699
	  if (TTY_TERMSCRIPT (tty))
	    fputc (' ', TTY_TERMSCRIPT (tty));
	  fputc (' ', TTY_OUTPUT (tty));
Jim Blandy's avatar
Jim Blandy committed
700
	}
701
      cmplus (tty, first_unused_hpos - curX (tty));
Jim Blandy's avatar
Jim Blandy committed
702 703 704
    }
}

Karl Heuer's avatar
Karl Heuer committed
705 706 707 708 709 710 711 712 713 714
/* 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
715
     struct glyph *src;
Karl Heuer's avatar
Karl Heuer committed
716 717 718 719
     int src_len;
     unsigned char *dst;
     int dst_len, *consumed;
{
Gerd Moellmann's avatar
Gerd Moellmann committed
720
  struct glyph *src_start = src, *src_end = src + src_len;
Karl Heuer's avatar
Karl Heuer committed
721
  unsigned char *dst_start = dst, *dst_end = dst + dst_len;
722
  register GLYPH g;
723 724
  unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
  const unsigned char *buf;
725
  int len;
Karl Heuer's avatar
Karl Heuer committed
726 727
  register int tlen = GLYPH_TABLE_LENGTH;
  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
728
  int result;
729 730
  struct coding_system *coding;

731 732 733 734
  /* 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
735 736
	    ? &terminal_coding
	    : &safe_terminal_coding);
Karl Heuer's avatar
Karl Heuer committed
737 738 739 740

  while (src < src_end)
    {
      /* We must skip glyphs to be padded for a wide character.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
741
      if (! CHAR_GLYPH_PADDING_P (*src))
Karl Heuer's avatar
Karl Heuer committed
742
	{
743 744 745
	  g = GLYPH_FROM_CHAR_GLYPH (src[0]);

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

	      if (GLYPH_SIMPLE_P (tbase, tlen, g))
		{
769 770 771 772 773
		  /* 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;
774
		  buf = workbuf;
775
		  coding->src_multibyte = 0;
776 777 778 779 780 781
		}
	      else
		{
		  /* We have a string in Vglyph_table.  */
		  len = GLYPH_LENGTH (tbase, g);
		  buf = GLYPH_STRING (tbase, g);
782
		  coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
783
		}
Richard M. Stallman's avatar
Richard M. Stallman committed
784
	    }
785

786
	  result = encode_coding (coding, buf, dst, len, dst_end - dst);
787
	  len -= coding->consumed;
788
	  dst += coding->produced;
789 790 791 792 793 794 795 796
	  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;

797 798
	  if (len > 0)
	    {
799 800 801 802 803
	      /* 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++;
804
	    }
Karl Heuer's avatar
Karl Heuer committed
805 806 807
	}
      src++;
    }
808

Karl Heuer's avatar
Karl Heuer committed
809 810 811 812
  *consumed = src - src_start;
  return (dst - dst_start);
}

Jim Blandy's avatar
Jim Blandy committed
813

Andreas Schwab's avatar
Andreas Schwab committed
814
void
Jim Blandy's avatar
Jim Blandy committed
815
write_glyphs (string, len)
Gerd Moellmann's avatar
Gerd Moellmann committed
816
     register struct glyph *string;
Jim Blandy's avatar
Jim Blandy committed
817 818
     register int len;
{
Karl Heuer's avatar
Karl Heuer committed
819