dispnew.c 58.1 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Updating of data structures for redisplay.
2 3
   Copyright (C) 1985, 1986, 1987, 1988, 1990, 
   1992, 1993 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
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 19 20 21 22 23 24 25 26 27 28 29
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
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */


#include <signal.h>

#include "config.h"
#include <stdio.h>
#include <ctype.h>

#include "termchar.h"
#include "termopts.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
30
#include "termhooks.h"
Jim Blandy's avatar
Jim Blandy committed
31 32 33 34
#include "cm.h"
#include "lisp.h"
#include "dispextern.h"
#include "buffer.h"
Jim Blandy's avatar
Jim Blandy committed
35
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
36 37 38 39 40
#include "window.h"
#include "commands.h"
#include "disptab.h"
#include "indent.h"

41
#include "systty.h"
Jim Blandy's avatar
Jim Blandy committed
42 43
#include "systime.h"

Jim Blandy's avatar
Jim Blandy committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif	/* HAVE_X_WINDOWS */

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))

#ifndef PENDING_OUTPUT_COUNT
/* Get number of chars of output now in the buffer of a stdio stream.
   This ought to be built in in stdio, but it isn't.
   Some s- files override this because their stdio internals differ.  */
#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
#endif

Jim Blandy's avatar
Jim Blandy committed
58
/* Nonzero upon entry to redisplay means do not assume anything about
Jim Blandy's avatar
Jim Blandy committed
59
   current contents of actual terminal frame; clear and redraw it.  */
Jim Blandy's avatar
Jim Blandy committed
60

Jim Blandy's avatar
Jim Blandy committed
61
int frame_garbaged;
Jim Blandy's avatar
Jim Blandy committed
62 63 64 65 66 67 68 69 70 71

/* Nonzero means last display completed.  Zero means it was preempted. */

int display_completed;

/* Lisp variable visible-bell; enables use of screen-flash
   instead of audible bell.  */

int visible_bell;

Jim Blandy's avatar
Jim Blandy committed
72
/* Invert the color of the whole frame, at a low level.  */
Jim Blandy's avatar
Jim Blandy committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

int inverse_video;

/* Line speed of the terminal.  */

int baud_rate;

/* nil or a symbol naming the window system under which emacs is
   running ('x is the only current possibility).  */

Lisp_Object Vwindow_system;

/* Version number of X windows: 10, 11 or nil.  */
Lisp_Object Vwindow_system_version;

/* Vector of glyph definitions.  Indexed by glyph number,
   the contents are a string which is how to output the glyph.

   If Vglyph_table is nil, a glyph is output by using its low 8 bits
   as a character code.  */

Lisp_Object Vglyph_table;

/* Display table to use for vectors that don't specify their own.  */

Lisp_Object Vstandard_display_table;

/* Nonzero means reading single-character input with prompt
Jim Blandy's avatar
Jim Blandy committed
101 102 103
   so put cursor on minibuffer after the prompt.
   positive means at end of text in echo area;
   negative means at beginning of line.  */
Jim Blandy's avatar
Jim Blandy committed
104 105
int cursor_in_echo_area;

Jim Blandy's avatar
Jim Blandy committed
106 107
/* The currently selected frame.
   In a single-frame version, this variable always remains 0.  */
Jim Blandy's avatar
Jim Blandy committed
108

Jim Blandy's avatar
Jim Blandy committed
109
FRAME_PTR selected_frame;
Jim Blandy's avatar
Jim Blandy committed
110

Jim Blandy's avatar
Jim Blandy committed
111 112 113 114
/* A frame which is not just a minibuffer, or 0 if there are no such
   frames.  This is usually the most recent such frame that was
   selected.  In a single-frame version, this variable always remains 0.  */
FRAME_PTR last_nonminibuf_frame;
Jim Blandy's avatar
Jim Blandy committed
115

Jim Blandy's avatar
Jim Blandy committed
116
/* In a single-frame version, the information that would otherwise
117 118 119 120 121 122
   exist inside frame objects lives in the following structure instead.

   NOTE: the_only_frame is not checked for garbage collection; don't
   store collectable objects in any of its fields!

   You're not/The only frame in town/...  */
Jim Blandy's avatar
Jim Blandy committed
123

Jim Blandy's avatar
Jim Blandy committed
124 125
#ifndef MULTI_FRAME
struct frame the_only_frame;
Jim Blandy's avatar
Jim Blandy committed
126
#endif
Jim Blandy's avatar
Jim Blandy committed
127 128

/* This is a vector, made larger whenever it isn't large enough,
Jim Blandy's avatar
Jim Blandy committed
129 130 131
   which is used inside `update_frame' to hold the old contents
   of the FRAME_PHYS_LINES of the frame being updated.  */
struct frame_glyphs **ophys_lines;
Jim Blandy's avatar
Jim Blandy committed
132 133 134 135 136 137 138 139 140 141 142
/* Length of vector currently allocated.  */
int ophys_lines_length;

FILE *termscript;	/* Stdio stream being used for copy of all output.  */

struct cm Wcm;		/* Structure for info on cursor positioning */

extern short ospeed;	/* Output speed (from sg_ospeed) */

int delayed_size_change;  /* 1 means SIGWINCH happened when not safe.  */

Jim Blandy's avatar
Jim Blandy committed
143
#ifdef MULTI_FRAME
Jim Blandy's avatar
Jim Blandy committed
144

Jim Blandy's avatar
Jim Blandy committed
145 146 147 148
DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
  "Clear frame FRAME and output again what is supposed to appear on it.")
  (frame)
     Lisp_Object frame;
Jim Blandy's avatar
Jim Blandy committed
149
{
Jim Blandy's avatar
Jim Blandy committed
150
  FRAME_PTR f;
Jim Blandy's avatar
Jim Blandy committed
151

Jim Blandy's avatar
Jim Blandy committed
152 153 154
  CHECK_LIVE_FRAME (frame, 0);
  f = XFRAME (frame);
  update_begin (f);
Jim Blandy's avatar
Jim Blandy committed
155
  /*  set_terminal_modes (); */
Jim Blandy's avatar
Jim Blandy committed
156
  clear_frame ();
157
  clear_frame_records (f);
Jim Blandy's avatar
Jim Blandy committed
158
  update_end (f);
Jim Blandy's avatar
Jim Blandy committed
159 160 161 162
  fflush (stdout);
  windows_or_buffers_changed++;
  /* Mark all windows as INaccurate,
     so that every window will have its redisplay done.  */
Jim Blandy's avatar
Jim Blandy committed
163 164
  mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
  f->garbaged = 0;
Jim Blandy's avatar
Jim Blandy committed
165 166 167 168
  return Qnil;
}

DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
169
  "Clear and redisplay all visible frames.")
Jim Blandy's avatar
Jim Blandy committed
170 171
  ()
{
Jim Blandy's avatar
Jim Blandy committed
172
  Lisp_Object frame, tail;
Jim Blandy's avatar
Jim Blandy committed
173

Jim Blandy's avatar
Jim Blandy committed
174
  for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
Jim Blandy's avatar
Jim Blandy committed
175
    {
Jim Blandy's avatar
Jim Blandy committed
176
      frame = XCONS (tail)->car;
Jim Blandy's avatar
Jim Blandy committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

      /* If we simply redrew all visible frames, whether or not they
	 were garbaged, then this would make all frames clear and
	 redraw whenever a new frame is created or an existing frame
	 is de-iconified; those events set the global frame_garbaged
	 flag, to which redisplay responds by calling this function.

	 This used to redraw all visible frames; the only advantage of
	 that approach is that if a frame changes from invisible to
	 visible without setting its garbaged flag, it still gets
	 redisplayed.  But that should never happen; since invisible
	 frames are not updated, they should always be marked as
	 garbaged when they become visible again.  If that doesn't
	 happen, it's a bug in the visibility code, not a bug here.  */
      if (FRAME_VISIBLE_P (XFRAME (frame))
	  && FRAME_GARBAGED_P (XFRAME (frame)))
Jim Blandy's avatar
Jim Blandy committed
193
	Fredraw_frame (frame);
Jim Blandy's avatar
Jim Blandy committed
194 195 196 197
    }
  return Qnil;
}

Jim Blandy's avatar
Jim Blandy committed
198 199
redraw_frame (f)
     FRAME_PTR f;
Jim Blandy's avatar
Jim Blandy committed
200
{
Jim Blandy's avatar
Jim Blandy committed
201 202 203
  Lisp_Object frame;
  XSET (frame, Lisp_Frame, f);
  Fredraw_frame (frame);
Jim Blandy's avatar
Jim Blandy committed
204 205
}

Jim Blandy's avatar
Jim Blandy committed
206
#else /* not MULTI_FRAME */
Jim Blandy's avatar
Jim Blandy committed
207

208
DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
Jim Blandy's avatar
Jim Blandy committed
209 210 211 212 213
  "Clear screen and output again what is supposed to appear on it.")
  ()
{
  update_begin (0);
  set_terminal_modes ();
Jim Blandy's avatar
Jim Blandy committed
214
  clear_frame ();
Jim Blandy's avatar
Jim Blandy committed
215 216
  update_end (0);
  fflush (stdout);
Jim Blandy's avatar
Jim Blandy committed
217
  clear_frame_records (0);
Jim Blandy's avatar
Jim Blandy committed
218 219 220
  windows_or_buffers_changed++;
  /* Mark all windows as INaccurate,
     so that every window will have its redisplay done.  */
221
  mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
Jim Blandy's avatar
Jim Blandy committed
222 223 224
  return Qnil;
}

Jim Blandy's avatar
Jim Blandy committed
225
#endif /* not MULTI_FRAME */
Jim Blandy's avatar
Jim Blandy committed
226

Jim Blandy's avatar
Jim Blandy committed
227 228 229
static struct frame_glyphs *
make_frame_glyphs (frame, empty)
     register FRAME_PTR frame;
Jim Blandy's avatar
Jim Blandy committed
230 231 232
     int empty;
{
  register int i;
Jim Blandy's avatar
Jim Blandy committed
233 234 235 236
  register width = FRAME_WIDTH (frame);
  register height = FRAME_HEIGHT (frame);
  register struct frame_glyphs *new =
    (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
Jim Blandy's avatar
Jim Blandy committed
237

Jim Blandy's avatar
Jim Blandy committed
238
  SET_GLYPHS_FRAME (new, frame);
Jim Blandy's avatar
Jim Blandy committed
239 240 241 242 243 244 245 246 247 248
  new->height = height;
  new->width = width;
  new->used = (int *) xmalloc (height * sizeof (int));
  new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
  new->highlight = (char *) xmalloc (height * sizeof (char));
  new->enable = (char *) xmalloc (height * sizeof (char));
  bzero (new->enable, height * sizeof (char));
  new->bufp = (int *) xmalloc (height * sizeof (int));

#ifdef HAVE_X_WINDOWS
249
  if (FRAME_X_P (frame))
Jim Blandy's avatar
Jim Blandy committed
250 251 252 253 254
    {
      new->top_left_x = (short *) xmalloc (height * sizeof (short));
      new->top_left_y = (short *) xmalloc (height * sizeof (short));
      new->pix_width = (short *) xmalloc (height * sizeof (short));
      new->pix_height = (short *) xmalloc (height * sizeof (short));
255
      new->max_ascent = (short *) xmalloc (height * sizeof (short));
Jim Blandy's avatar
Jim Blandy committed
256 257 258 259 260 261
    }
#endif

  if (empty)
    {
      /* Make the buffer used by decode_mode_spec.  This buffer is also
Jim Blandy's avatar
Jim Blandy committed
262
         used as temporary storage when updating the frame.  See scroll.c. */
Jim Blandy's avatar
Jim Blandy committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
      unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);

      new->total_contents = (GLYPH *) xmalloc (total_glyphs);
      bzero (new->total_contents, total_glyphs);
    }
  else
    {
      unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);

      new->total_contents = (GLYPH *) xmalloc (total_glyphs);
      bzero (new->total_contents, total_glyphs);
      for (i = 0; i < height; i++)
	new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
    }

  return new;
}

static void
Jim Blandy's avatar
Jim Blandy committed
282 283 284
free_frame_glyphs (frame, glyphs)
     FRAME_PTR frame;
     struct frame_glyphs *glyphs;
Jim Blandy's avatar
Jim Blandy committed
285 286 287 288 289 290 291 292 293 294 295
{
  if (glyphs->total_contents)
    free (glyphs->total_contents);

  free (glyphs->used);
  free (glyphs->glyphs);
  free (glyphs->highlight);
  free (glyphs->enable);
  free (glyphs->bufp);

#ifdef HAVE_X_WINDOWS
296
  if (FRAME_X_P (frame))
Jim Blandy's avatar
Jim Blandy committed
297 298 299 300 301
    {
      free (glyphs->top_left_x);
      free (glyphs->top_left_y);
      free (glyphs->pix_width);
      free (glyphs->pix_height);
302
      free (glyphs->max_ascent);
Jim Blandy's avatar
Jim Blandy committed
303 304 305 306 307 308 309
    }
#endif

  free (glyphs);
}

static void
Jim Blandy's avatar
Jim Blandy committed
310 311
remake_frame_glyphs (frame)
     FRAME_PTR frame;
Jim Blandy's avatar
Jim Blandy committed
312
{
Jim Blandy's avatar
Jim Blandy committed
313 314 315 316 317 318 319 320
  if (FRAME_CURRENT_GLYPHS (frame))
    free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
  if (FRAME_DESIRED_GLYPHS (frame))
    free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
  if (FRAME_TEMP_GLYPHS (frame))
    free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));

  if (FRAME_MESSAGE_BUF (frame))
321 322 323 324 325 326 327 328 329 330 331 332 333 334
    {
      /* Reallocate the frame's message buffer; remember that
	 echo_area_glyphs may be pointing here.  */
      char *old_message_buf = FRAME_MESSAGE_BUF (frame);

      FRAME_MESSAGE_BUF (frame)
	= (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
			     FRAME_WIDTH (frame) + 1);

      if (echo_area_glyphs == old_message_buf)
	echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
      if (previous_echo_glyphs == old_message_buf)
	previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
    }
Jim Blandy's avatar
Jim Blandy committed
335
  else
Jim Blandy's avatar
Jim Blandy committed
336 337
    FRAME_MESSAGE_BUF (frame)
      = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
Jim Blandy's avatar
Jim Blandy committed
338

Jim Blandy's avatar
Jim Blandy committed
339 340 341 342
  FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
  FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
  FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
  SET_FRAME_GARBAGED (frame);
Jim Blandy's avatar
Jim Blandy committed
343 344
}

Jim Blandy's avatar
Jim Blandy committed
345
/* Return the hash code of contents of line VPOS in frame-matrix M.  */
Jim Blandy's avatar
Jim Blandy committed
346 347 348

static int
line_hash_code (m, vpos)
Jim Blandy's avatar
Jim Blandy committed
349
     register struct frame_glyphs *m;
Jim Blandy's avatar
Jim Blandy committed
350 351 352 353 354 355 356 357
     int vpos;
{
  register GLYPH *body, *end;
  register int h = 0;

  if (!m->enable[vpos])
    return 0;

358
  /* Give all highlighted lines the same hash code
Jim Blandy's avatar
Jim Blandy committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
     so as to encourage scrolling to leave them in place.  */
  if (m->highlight[vpos])
    return -1;

  body = m->glyphs[vpos];

  if (must_write_spaces)
    while (1)
      {
	GLYPH g = *body++;

	if (g == 0)
	  break;
	h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
      }
  else
    while (1)
      {
	GLYPH g = *body++;

	if (g == 0)
	  break;
	h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
      }

  if (h)
    return h;
  return 1;
}

/* Return number of characters in line in M at vpos VPOS,
   except don't count leading and trailing spaces
   unless the terminal requires those to be explicitly output.  */

static unsigned int
line_draw_cost (m, vpos)
Jim Blandy's avatar
Jim Blandy committed
395
     struct frame_glyphs *m;
Jim Blandy's avatar
Jim Blandy committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
     int vpos;
{
  register GLYPH *beg = m->glyphs[vpos];
  register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
  register int i;
  register int tlen = GLYPH_TABLE_LENGTH;
  register Lisp_Object *tbase = GLYPH_TABLE_BASE;

  /* Ignore trailing and leading spaces if we can.  */
  if (!must_write_spaces)
    {
      while ((end != beg) && (*end == SPACEGLYPH))
	--end;
      if (end == beg)
	return (0); /* All blank line. */

      while (*beg == SPACEGLYPH)
	++beg;
    }

  /* If we don't have a glyph-table, each glyph is one character,
     so return the number of glyphs.  */
  if (tbase == 0)
    return end - beg;

  /* Otherwise, scan the glyphs and accumulate their total size in I.  */
  i = 0;
  while ((beg <= end) && *beg)
    {
      register GLYPH g = *beg++;

      if (GLYPH_SIMPLE_P (tbase, tlen, g))
	i += 1;
      else
	i += GLYPH_LENGTH (tbase, g);
    }
  return i;
}

/* The functions on this page are the interface from xdisp.c to redisplay.

   The only other interface into redisplay is through setting
Jim Blandy's avatar
Jim Blandy committed
438 439
   FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
   and SET_FRAME_GARBAGED (frame).  */
Jim Blandy's avatar
Jim Blandy committed
440 441 442

/* cancel_line eliminates any request to display a line at position `vpos' */

Jim Blandy's avatar
Jim Blandy committed
443
cancel_line (vpos, frame)
Jim Blandy's avatar
Jim Blandy committed
444
     int vpos;
Jim Blandy's avatar
Jim Blandy committed
445
     register FRAME_PTR frame;
Jim Blandy's avatar
Jim Blandy committed
446
{
Jim Blandy's avatar
Jim Blandy committed
447
  FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
Jim Blandy's avatar
Jim Blandy committed
448 449
}

Jim Blandy's avatar
Jim Blandy committed
450 451
clear_frame_records (frame)
     register FRAME_PTR frame;
Jim Blandy's avatar
Jim Blandy committed
452
{
Jim Blandy's avatar
Jim Blandy committed
453
  bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
Jim Blandy's avatar
Jim Blandy committed
454 455 456 457 458
}

/* Prepare to display on line VPOS starting at HPOS within it.  */

void
Jim Blandy's avatar
Jim Blandy committed
459 460
get_display_line (frame, vpos, hpos)
     register FRAME_PTR frame;
Jim Blandy's avatar
Jim Blandy committed
461 462 463
     int vpos;
     register int hpos;
{
Jim Blandy's avatar
Jim Blandy committed
464 465
  register struct frame_glyphs *glyphs;
  register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
Jim Blandy's avatar
Jim Blandy committed
466 467
  register GLYPH *p;

468
  if (vpos < 0)
Jim Blandy's avatar
Jim Blandy committed
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
    abort ();

  if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
    abort ();

  if (! desired_glyphs->enable[vpos])
    {
      desired_glyphs->used[vpos] = 0;
      desired_glyphs->highlight[vpos] = 0;
      desired_glyphs->enable[vpos] = 1;
    }

  if (hpos > desired_glyphs->used[vpos])
    {
      GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
      GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;

      desired_glyphs->used[vpos] = hpos;
      while (g != end)
	*g++ = SPACEGLYPH;
    }
}

/* Like bcopy except never gets confused by overlap.  */

void
safe_bcopy (from, to, size)
     char *from, *to;
     int size;
{
499
  if (size <= 0 || from == to)
Jim Blandy's avatar
Jim Blandy committed
500 501
    return;

502 503 504 505 506 507 508 509
  /* If the source and destination don't overlap, then bcopy can
     handle it.  If they do overlap, but the destination is lower in
     memory than the source, we'll assume bcopy can handle that.  */
  if (to < from || from + size <= to)
    bcopy (from, to, size);

  /* Otherwise, we'll copy from the end.  */
  else
Jim Blandy's avatar
Jim Blandy committed
510
    {
511 512
      register char *endf = from + size;
      register char *endt = to + size;
Jim Blandy's avatar
Jim Blandy committed
513 514 515 516 517

      /* If TO - FROM is large, then we should break the copy into
	 nonoverlapping chunks of TO - FROM bytes each.  However, if
	 TO - FROM is small, then the bcopy function call overhead
	 makes this not worth it.  The crossover point could be about
518 519
	 anywhere.  Since I don't think the obvious copy loop is too
	 bad, I'm trying to err in its favor.  */
Jim Blandy's avatar
Jim Blandy committed
520 521 522 523 524 525 526 527
      if (to - from < 64)
	{
	  do
	    *--endt = *--endf;
	  while (endf != from);
	}
      else
	{
528
	  for (;;)
Jim Blandy's avatar
Jim Blandy committed
529 530 531 532
	    {
	      endt -= (to - from);
	      endf -= (to - from);

533 534 535
	      if (endt < to)
		break;

Jim Blandy's avatar
Jim Blandy committed
536 537
	      bcopy (endf, endt, to - from);
	    }
538 539

	  /* If SIZE wasn't a multiple of TO - FROM, there will be a
Jim Blandy's avatar
Jim Blandy committed
540 541 542 543 544 545 546
	     little left over.  The amount left over is
	     (endt + (to - from)) - to, which is endt - from.  */
	  bcopy (from, to, endt - from);
	}
    }
}     

Jim Blandy's avatar
Jim Blandy committed
547
/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
Jim Blandy's avatar
Jim Blandy committed
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
   DISTANCE may be negative.  */

static void
rotate_vector (vector, size, distance)
     char *vector;
     int size;
     int distance;
{
  char *temp = (char *) alloca (size);

  if (distance < 0)
    distance += size;

  bcopy (vector, temp + distance, size - distance);
  bcopy (vector + size - distance, temp, distance);
  bcopy (temp, vector, size);
}

/* Scroll lines from vpos FROM up to but not including vpos END
   down by AMOUNT lines (AMOUNT may be negative).
   Returns nonzero if done, zero if terminal cannot scroll them.  */

int
Jim Blandy's avatar
Jim Blandy committed
571 572
scroll_frame_lines (frame, from, end, amount)
     register FRAME_PTR frame;
Jim Blandy's avatar
Jim Blandy committed
573 574 575
     int from, end, amount;
{
  register int i;
Jim Blandy's avatar
Jim Blandy committed
576 577
  register struct frame_glyphs *current_frame
    = FRAME_CURRENT_GLYPHS (frame);
Jim Blandy's avatar
Jim Blandy committed
578 579 580 581 582 583 584 585 586

  if (!line_ins_del_ok)
    return 0;

  if (amount == 0)
    return 1;

  if (amount > 0)
    {
Jim Blandy's avatar
Jim Blandy committed
587
      update_begin (frame);
Jim Blandy's avatar
Jim Blandy committed
588 589 590 591 592 593
      set_terminal_window (end + amount);
      if (!scroll_region_ok)
	ins_del_lines (end, -amount);
      ins_del_lines (from, amount);
      set_terminal_window (0);

Jim Blandy's avatar
Jim Blandy committed
594
      rotate_vector (current_frame->glyphs + from,
Jim Blandy's avatar
Jim Blandy committed
595 596 597
		     sizeof (GLYPH *) * (end + amount - from),
		     amount * sizeof (GLYPH *));

Jim Blandy's avatar
Jim Blandy committed
598 599 600
      safe_bcopy (current_frame->used + from,
		  current_frame->used + from + amount,
		  (end - from) * sizeof current_frame->used[0]);
Jim Blandy's avatar
Jim Blandy committed
601

Jim Blandy's avatar
Jim Blandy committed
602 603 604
      safe_bcopy (current_frame->highlight + from,
		  current_frame->highlight + from + amount,
		  (end - from) * sizeof current_frame->highlight[0]);
Jim Blandy's avatar
Jim Blandy committed
605

Jim Blandy's avatar
Jim Blandy committed
606 607 608
      safe_bcopy (current_frame->enable + from,
		  current_frame->enable + from + amount,
		  (end - from) * sizeof current_frame->enable[0]);
Jim Blandy's avatar
Jim Blandy committed
609 610 611

      /* Mark the lines made empty by scrolling as enabled, empty and
	 normal video.  */
Jim Blandy's avatar
Jim Blandy committed
612 613 614 615
      bzero (current_frame->used + from,
	     amount * sizeof current_frame->used[0]);
      bzero (current_frame->highlight + from,
	     amount * sizeof current_frame->highlight[0]);
Jim Blandy's avatar
Jim Blandy committed
616 617
      for (i = from; i < from + amount; i++)
	{
Jim Blandy's avatar
Jim Blandy committed
618 619
	  current_frame->glyphs[i][0] = '\0';
	  current_frame->enable[i] = 1;
Jim Blandy's avatar
Jim Blandy committed
620 621
	}

Jim Blandy's avatar
Jim Blandy committed
622 623 624
      safe_bcopy (current_frame->bufp + from,
		  current_frame->bufp + from + amount,
		  (end - from) * sizeof current_frame->bufp[0]);
Jim Blandy's avatar
Jim Blandy committed
625 626

#ifdef HAVE_X_WINDOWS
627
      if (FRAME_X_P (frame))
Jim Blandy's avatar
Jim Blandy committed
628
	{
Jim Blandy's avatar
Jim Blandy committed
629 630 631
	  safe_bcopy (current_frame->top_left_x + from,
		      current_frame->top_left_x + from + amount,
		      (end - from) * sizeof current_frame->top_left_x[0]);
Jim Blandy's avatar
Jim Blandy committed
632

Jim Blandy's avatar
Jim Blandy committed
633 634 635
	  safe_bcopy (current_frame->top_left_y + from,
		      current_frame->top_left_y + from + amount,
		      (end - from) * sizeof current_frame->top_left_y[0]);
Jim Blandy's avatar
Jim Blandy committed
636

Jim Blandy's avatar
Jim Blandy committed
637 638 639
	  safe_bcopy (current_frame->pix_width + from,
		      current_frame->pix_width + from + amount,
		      (end - from) * sizeof current_frame->pix_width[0]);
Jim Blandy's avatar
Jim Blandy committed
640

Jim Blandy's avatar
Jim Blandy committed
641 642 643
	  safe_bcopy (current_frame->pix_height + from,
		      current_frame->pix_height + from + amount,
		      (end - from) * sizeof current_frame->pix_height[0]);
644 645 646 647

	  safe_bcopy (current_frame->max_ascent + from,
		      current_frame->max_ascent + from + amount,
		      (end - from) * sizeof current_frame->max_ascent[0]);
Jim Blandy's avatar
Jim Blandy committed
648 649 650
	}
#endif				/* HAVE_X_WINDOWS */

Jim Blandy's avatar
Jim Blandy committed
651
      update_end (frame);
Jim Blandy's avatar
Jim Blandy committed
652 653 654
    }
  if (amount < 0)
    {
Jim Blandy's avatar
Jim Blandy committed
655
      update_begin (frame);
Jim Blandy's avatar
Jim Blandy committed
656 657 658 659 660 661
      set_terminal_window (end);
      ins_del_lines (from + amount, amount);
      if (!scroll_region_ok)
	ins_del_lines (end + amount, -amount);
      set_terminal_window (0);

Jim Blandy's avatar
Jim Blandy committed
662
      rotate_vector (current_frame->glyphs + from + amount,
Jim Blandy's avatar
Jim Blandy committed
663 664 665
		     sizeof (GLYPH *) * (end - from - amount),
		     amount * sizeof (GLYPH *));

Jim Blandy's avatar
Jim Blandy committed
666 667 668
      safe_bcopy (current_frame->used + from,
		  current_frame->used + from + amount,
		  (end - from) * sizeof current_frame->used[0]);
Jim Blandy's avatar
Jim Blandy committed
669

Jim Blandy's avatar
Jim Blandy committed
670 671 672
      safe_bcopy (current_frame->highlight + from,
		  current_frame->highlight + from + amount,
		  (end - from) * sizeof current_frame->highlight[0]);
Jim Blandy's avatar
Jim Blandy committed
673

Jim Blandy's avatar
Jim Blandy committed
674 675 676
      safe_bcopy (current_frame->enable + from,
		  current_frame->enable + from + amount,
		  (end - from) * sizeof current_frame->enable[0]);
Jim Blandy's avatar
Jim Blandy committed
677 678 679

      /* Mark the lines made empty by scrolling as enabled, empty and
	 normal video.  */
Jim Blandy's avatar
Jim Blandy committed
680 681 682 683
      bzero (current_frame->used + end + amount,
	     - amount * sizeof current_frame->used[0]);
      bzero (current_frame->highlight + end + amount,
	     - amount * sizeof current_frame->highlight[0]);
Jim Blandy's avatar
Jim Blandy committed
684 685
      for (i = end + amount; i < end; i++)
	{
Jim Blandy's avatar
Jim Blandy committed
686 687
	  current_frame->glyphs[i][0] = '\0';
	  current_frame->enable[i] = 1;
Jim Blandy's avatar
Jim Blandy committed
688 689
	}

Jim Blandy's avatar
Jim Blandy committed
690 691 692
      safe_bcopy (current_frame->bufp + from,
		  current_frame->bufp + from + amount,
		  (end - from) * sizeof current_frame->bufp[0]);
Jim Blandy's avatar
Jim Blandy committed
693 694

#ifdef HAVE_X_WINDOWS
695
      if (FRAME_X_P (frame))
Jim Blandy's avatar
Jim Blandy committed
696
	{
Jim Blandy's avatar
Jim Blandy committed
697 698 699
	  safe_bcopy (current_frame->top_left_x + from,
		      current_frame->top_left_x + from + amount,
		      (end - from) * sizeof current_frame->top_left_x[0]);
Jim Blandy's avatar
Jim Blandy committed
700

Jim Blandy's avatar
Jim Blandy committed
701 702 703
	  safe_bcopy (current_frame->top_left_y + from,
		      current_frame->top_left_y + from + amount,
		      (end - from) * sizeof current_frame->top_left_y[0]);
Jim Blandy's avatar
Jim Blandy committed
704

Jim Blandy's avatar
Jim Blandy committed
705 706 707
	  safe_bcopy (current_frame->pix_width + from,
		      current_frame->pix_width + from + amount,
		      (end - from) * sizeof current_frame->pix_width[0]);
Jim Blandy's avatar
Jim Blandy committed
708

Jim Blandy's avatar
Jim Blandy committed
709 710 711
	  safe_bcopy (current_frame->pix_height + from,
		      current_frame->pix_height + from + amount,
		      (end - from) * sizeof current_frame->pix_height[0]);
712 713 714 715

	  safe_bcopy (current_frame->max_ascent + from,
		      current_frame->max_ascent + from + amount,
		      (end - from) * sizeof current_frame->max_ascent[0]);
Jim Blandy's avatar
Jim Blandy committed
716 717 718
	}
#endif				/* HAVE_X_WINDOWS */

Jim Blandy's avatar
Jim Blandy committed
719
      update_end (frame);
Jim Blandy's avatar
Jim Blandy committed
720 721 722 723
    }
  return 1;
}

Jim Blandy's avatar
Jim Blandy committed
724
/* After updating a window W that isn't the full frame wide,
Jim Blandy's avatar
Jim Blandy committed
725
   copy all the columns that W does not occupy
Jim Blandy's avatar
Jim Blandy committed
726 727
   into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
   so that update_frame will not change those columns.  */
Jim Blandy's avatar
Jim Blandy committed
728 729 730 731 732

preserve_other_columns (w)
     struct window *w;
{
  register int vpos;
Jim Blandy's avatar
Jim Blandy committed
733 734
  register struct frame_glyphs *current_frame, *desired_frame;
  register FRAME_PTR frame = XFRAME (w->frame);
Jim Blandy's avatar
Jim Blandy committed
735 736 737 738
  int start = XFASTINT (w->left);
  int end = XFASTINT (w->left) + XFASTINT (w->width);
  int bot = XFASTINT (w->top) + XFASTINT (w->height);

Jim Blandy's avatar
Jim Blandy committed
739 740
  current_frame = FRAME_CURRENT_GLYPHS (frame);
  desired_frame = FRAME_DESIRED_GLYPHS (frame);
Jim Blandy's avatar
Jim Blandy committed
741 742 743

  for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
    {
Jim Blandy's avatar
Jim Blandy committed
744
      if (current_frame->enable[vpos] && desired_frame->enable[vpos])
Jim Blandy's avatar
Jim Blandy committed
745 746 747 748 749
	{
	  if (start > 0)
	    {
	      int len;

Jim Blandy's avatar
Jim Blandy committed
750 751 752 753 754
	      bcopy (current_frame->glyphs[vpos],
		     desired_frame->glyphs[vpos], start);
	      len = min (start, current_frame->used[vpos]);
	      if (desired_frame->used[vpos] < len)
		desired_frame->used[vpos] = len;
Jim Blandy's avatar
Jim Blandy committed
755
	    }
Jim Blandy's avatar
Jim Blandy committed
756 757
	  if (current_frame->used[vpos] > end
	      && desired_frame->used[vpos] < current_frame->used[vpos])
Jim Blandy's avatar
Jim Blandy committed
758
	    {
Jim Blandy's avatar
Jim Blandy committed
759 760
	      while (desired_frame->used[vpos] < end)
		desired_frame->glyphs[vpos][desired_frame->used[vpos]++]
Jim Blandy's avatar
Jim Blandy committed
761
		  = SPACEGLYPH;
Jim Blandy's avatar
Jim Blandy committed
762 763 764 765
	      bcopy (current_frame->glyphs[vpos] + end,
		     desired_frame->glyphs[vpos] + end,
		     current_frame->used[vpos] - end);
	      desired_frame->used[vpos] = current_frame->used[vpos];
Jim Blandy's avatar
Jim Blandy committed
766 767 768 769 770 771 772
	    }
	}
    }
}

#if 0

Jim Blandy's avatar
Jim Blandy committed
773
/* If window w does not need to be updated and isn't the full frame wide,
Jim Blandy's avatar
Jim Blandy committed
774
 copy all the columns that w does occupy
Jim Blandy's avatar
Jim Blandy committed
775 776
 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
 so that update_frame will not change those columns.
Jim Blandy's avatar
Jim Blandy committed
777 778 779 780 781 782 783

 Have not been able to figure out how to use this correctly.  */

preserve_my_columns (w)
     struct window *w;
{
  register int vpos, fin;
Jim Blandy's avatar
Jim Blandy committed
784 785
  register struct frame_glyphs *l1, *l2;
  register FRAME_PTR frame = XFRAME (w->frame);
Jim Blandy's avatar
Jim Blandy committed
786 787 788 789 790 791
  int start = XFASTINT (w->left);
  int end = XFASTINT (w->left) + XFASTINT (w->width);
  int bot = XFASTINT (w->top) + XFASTINT (w->height);

  for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
    {
Jim Blandy's avatar
Jim Blandy committed
792 793
      if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
	  && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
Jim Blandy's avatar
Jim Blandy committed
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
	{
	  if (l2->length > start && l1->length < l2->length)
	    {
	      fin = l2->length;
	      if (fin > end) fin = end;
	      while (l1->length < start)
		l1->body[l1->length++] = ' ';
	      bcopy (l2->body + start, l1->body + start, fin - start);
	      l1->length = fin;
	    }
	}
    }
}

#endif

/* On discovering that the redisplay for a window was no good,
   cancel the columns of that window, so that when the window is
   displayed over again get_display_line will not complain.  */

cancel_my_columns (w)
     struct window *w;
{
  register int vpos;
Jim Blandy's avatar
Jim Blandy committed
818 819
  register struct frame_glyphs *desired_glyphs =
    FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
Jim Blandy's avatar
Jim Blandy committed
820 821 822 823 824 825 826 827 828
  register int start = XFASTINT (w->left);
  register int bot = XFASTINT (w->top) + XFASTINT (w->height);

  for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
    if (desired_glyphs->enable[vpos]
	&& desired_glyphs->used[vpos] >= start)
      desired_glyphs->used[vpos] = start;
}

Jim Blandy's avatar
Jim Blandy committed
829
/* These functions try to perform directly and immediately on the frame
Jim Blandy's avatar
Jim Blandy committed
830 831 832
   the necessary output for one change in the buffer.
   They may return 0 meaning nothing was done if anything is difficult,
   or 1 meaning the output was performed properly.
Jim Blandy's avatar
Jim Blandy committed
833
   They assume that the frame was up to date before the buffer
834
   change being displayed.  They make various other assumptions too;
Jim Blandy's avatar
Jim Blandy committed
835 836 837 838 839 840
   see command_loop_1 where these are called.  */

int
direct_output_for_insert (g)
     int g;
{
Jim Blandy's avatar
Jim Blandy committed
841 842 843
  register FRAME_PTR frame = selected_frame;
  register struct frame_glyphs *current_frame
    = FRAME_CURRENT_GLYPHS (frame);
Jim Blandy's avatar
Jim Blandy committed
844 845 846 847 848 849 850 851

#ifndef COMPILER_REGISTER_BUG
  register
#endif /* COMPILER_REGISTER_BUG */
    struct window *w = XWINDOW (selected_window);
#ifndef COMPILER_REGISTER_BUG
  register
#endif /* COMPILER_REGISTER_BUG */
Jim Blandy's avatar
Jim Blandy committed
852
    int hpos = FRAME_CURSOR_X (frame);
Jim Blandy's avatar
Jim Blandy committed
853 854 855
#ifndef COMPILER_REGISTER_BUG
  register
#endif /* COMPILER_REGISTER_BUG */
Jim Blandy's avatar
Jim Blandy committed
856
    int vpos = FRAME_CURSOR_Y (frame);
Jim Blandy's avatar
Jim Blandy committed
857

858 859 860
  /* Give up if about to continue line.  */
  if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
    
Jim Blandy's avatar
Jim Blandy committed
861 862 863 864
  /* Avoid losing if cursor is in invisible text off left margin */
      || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
    
  /* Give up if cursor outside window (in minibuf, probably) */
865
      || cursor_in_echo_area
Jim Blandy's avatar
Jim Blandy committed
866 867
      || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
      || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
Jim Blandy's avatar
Jim Blandy committed
868

Jim Blandy's avatar
Jim Blandy committed
869
  /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
Jim Blandy's avatar
Jim Blandy committed
870 871 872 873 874 875 876 877 878
      || !display_completed

  /* Give up if buffer appears in two places.  */
      || buffer_shared > 1

  /* Give up if w is minibuffer and a message is being displayed there */
      || (MINI_WINDOW_P (w) && echo_area_glyphs))
    return 0;

Jim Blandy's avatar
Jim Blandy committed
879
  current_frame->glyphs[vpos][hpos] = g;
Jim Blandy's avatar
Jim Blandy committed
880 881 882 883 884 885 886
  unchanged_modified = MODIFF;
  beg_unchanged = GPT - BEG;
  XFASTINT (w->last_point) = point;
  XFASTINT (w->last_point_x) = hpos;
  XFASTINT (w->last_modified) = MODIFF;

  reassert_line_highlight (0, vpos);
Jim Blandy's avatar
Jim Blandy committed
887
  write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
Jim Blandy's avatar
Jim Blandy committed
888
  fflush (stdout);
Jim Blandy's avatar
Jim Blandy committed
889 890
  ++FRAME_CURSOR_X (frame);
  if (hpos == current_frame->used[vpos])
Jim Blandy's avatar
Jim Blandy committed
891
    {
Jim Blandy's avatar
Jim Blandy committed
892 893
      current_frame->used[vpos] = hpos + 1;
      current_frame->glyphs[vpos][hpos + 1] = 0;
Jim Blandy's avatar
Jim Blandy committed
894 895 896 897 898 899 900 901 902
    }

  return 1;
}

int
direct_output_forward_char (n)
     int n;
{
Jim Blandy's avatar
Jim Blandy committed
903
  register FRAME_PTR frame = selected_frame;
Jim Blandy's avatar
Jim Blandy committed
904 905
  register struct window *w = XWINDOW (selected_window);

Jim Blandy's avatar
Jim Blandy committed
906 907
  /* Avoid losing if cursor is in invisible text off left margin
     or about to go off either side of window.  */
Jim Blandy's avatar
Jim Blandy committed
908
  if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
Jim Blandy's avatar
Jim Blandy committed
909 910
       && (XINT (w->hscroll) || n < 0))
      || (n > 0
911
	  && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
912
      || cursor_in_echo_area)
Jim Blandy's avatar
Jim Blandy committed
913 914
    return 0;

Jim Blandy's avatar
Jim Blandy committed
915 916
  FRAME_CURSOR_X (frame) += n;
  XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
Jim Blandy's avatar
Jim Blandy committed
917
  XFASTINT (w->last_point) = point;
Jim Blandy's avatar
Jim Blandy committed
918
  cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
Jim Blandy's avatar
Jim Blandy committed
919 920 921 922 923 924
  fflush (stdout);
  return 1;
}

static void update_line ();

Jim Blandy's avatar
Jim Blandy committed
925
/* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
Jim Blandy's avatar
Jim Blandy committed
926 927 928 929
   Value is nonzero if redisplay stopped due to pending input.
   FORCE nonzero means do not stop for pending input.  */

int
Jim Blandy's avatar
Jim Blandy committed
930 931
update_frame (f, force, inhibit_hairy_id)
     FRAME_PTR f;
Jim Blandy's avatar
Jim Blandy committed
932 933 934
     int force;
     int inhibit_hairy_id;
{
Jim Blandy's avatar
Jim Blandy committed
935 936
  register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (f);
  register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (f);
Jim Blandy's avatar
Jim Blandy committed
937 938 939 940 941 942 943 944
  register int i;
  int pause;
  int preempt_count = baud_rate / 2400 + 1;
  extern input_pending;
#ifdef HAVE_X_WINDOWS
  register int downto, leftmost;
#endif

Jim Blandy's avatar
Jim Blandy committed
945
  if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
Jim Blandy's avatar
Jim Blandy committed
946 947 948 949 950 951 952 953

  detect_input_pending ();
  if (input_pending && !force)
    {
      pause = 1;
      goto do_pause;
    }

Jim Blandy's avatar
Jim Blandy committed
954
  update_begin (f);
Jim Blandy's avatar
Jim Blandy committed
955 956 957 958

  if (!line_ins_del_ok)
    inhibit_hairy_id = 1;

Jim Blandy's avatar
Jim Blandy committed
959 960
  /* See if any of the desired lines are enabled; don't compute for
     i/d line if just want cursor motion. */
Jim Blandy's avatar
Jim Blandy committed
961 962
  for (i = 0; i < FRAME_HEIGHT (f); i++)
    if (desired_frame->enable[i])
Jim Blandy's avatar
Jim Blandy committed
963 964 965
      break;

  /* Try doing i/d line, if not yet inhibited.  */
Jim Blandy's avatar
Jim Blandy committed
966 967
  if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
    force |= scrolling (f);
Jim Blandy's avatar
Jim Blandy committed
968 969 970

  /* Update the individual lines as needed.  Do bottom line first.  */

Jim Blandy's avatar
Jim Blandy committed
971 972
  if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
    update_line (f, FRAME_HEIGHT (f) - 1);
Jim Blandy's avatar
Jim Blandy committed
973 974

#ifdef HAVE_X_WINDOWS
975
  if (FRAME_X_P (f))
Jim Blandy's avatar
Jim Blandy committed
976
    {
Jim Blandy's avatar
Jim Blandy committed
977 978
      leftmost = downto = f->display.x->internal_border_width;
      if (desired_frame->enable[0])
Jim Blandy's avatar
Jim Blandy committed
979
	{
Jim Blandy's avatar
Jim Blandy committed
980 981 982
	  current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
	  current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
	    = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
983
	      - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
Jim Blandy's avatar
Jim Blandy committed
984 985
	  current_frame->top_left_x[0] = leftmost;
	  current_frame->top_left_y[0] = downto;
Jim Blandy's avatar
Jim Blandy committed
986 987 988 989 990
	}
    }
#endif /* HAVE_X_WINDOWS */

  /* Now update the rest of the lines. */
Jim Blandy's avatar
Jim Blandy committed
991
  for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
Jim Blandy's avatar
Jim Blandy committed
992
    {
Jim Blandy's avatar
Jim Blandy committed
993
      if (desired_frame->enable[i])
Jim Blandy's avatar
Jim Blandy committed
994
	{
995
	  if (FRAME_TERMCAP_P (f))
Jim Blandy's avatar
Jim Blandy committed
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
	    {
	      /* Flush out every so many lines.
		 Also flush out if likely to have more than 1k buffered
		 otherwise.   I'm told that some telnet connections get
		 really screwed by more than 1k output at once.  */
	      int outq = PENDING_OUTPUT_COUNT (stdout);
	      if (outq > 900
		  || (outq > 20 && ((i - 1) % preempt_count == 0)))
		{
		  fflush (stdout);
		  if (preempt_count == 1)
		    {
Jim Blandy's avatar
Jim Blandy committed
1008 1009
#ifdef EMACS_OUTQSIZE
		      if (EMACS_OUTQSIZE (0, &outq) < 0)
Jim Blandy's avatar
Jim Blandy committed
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
			/* Probably not a tty.  Ignore the error and reset
			 * the outq count. */
			outq = PENDING_OUTPUT_COUNT (stdout);
#endif
		      outq *= 10;
		      sleep (outq / baud_rate);
		    }
		}
	      if ((i - 1) % preempt_count == 0)
		detect_input_pending ();
	    }

Jim Blandy's avatar
Jim Blandy committed
1022
	  update_line (f, i);
Jim Blandy's avatar
Jim Blandy committed
1023
#ifdef HAVE_X_WINDOWS
1024
	  if (FRAME_X_P (f))
Jim Blandy's avatar
Jim Blandy committed
1025
	    {
Jim Blandy's avatar
Jim Blandy committed
1026 1027
	      current_frame->top_left_y[i] = downto;
	      current_frame->top_left_x[i] = leftmost;
Jim Blandy's avatar
Jim Blandy committed
1028 1029 1030 1031
	    }
#endif /* HAVE_X_WINDOWS */
	}

Jim Blandy's avatar
Jim Blandy committed
1032
#ifdef HAVE_X_WINDOWS
1033
      if (FRAME_X_P (f))
1034
	downto += current_frame->pix_height[i];
Jim Blandy's avatar
Jim Blandy committed
1035
#endif
Jim Blandy's avatar
Jim Blandy committed
1036
    }
Jim Blandy's avatar
Jim Blandy committed
1037
  pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
Jim Blandy's avatar
Jim Blandy committed
1038 1039 1040 1041

  /* Now just clean up termcap drivers and set cursor, etc.  */
  if (!pause)
    {
1042 1043
      if (cursor_in_echo_area
	  && FRAME_HAS_MINIBUF_P (f))
Jim Blandy's avatar
Jim Blandy committed
1044
	{
1045 1046 1047 1048 1049 1050 1051 1052
	  int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
	  int row, col;

	  if (cursor_in_echo_area < 0)
	    {
	      row = top;
	      col = 0;
	    }
Jim Blandy's avatar
Jim Blandy committed
1053
	  else
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
	    {
	      /* If the minibuffer is several lines high, find the last
		 line that has any text on it.  */
	      row = FRAME_HEIGHT (f);
	      do 
		{
		  row--;
		  if (current_frame->enable[row])
		    col = current_frame->used[row];
		  else
		    col = 0;
		}
	      while (row > top && col == 0);

	      if (col >= FRAME_WIDTH (f))
		{
		  col = 0;
		  if (row < FRAME_HEIGHT (f) - 1)
		    row++;
		}
	    }

	  cursor_to (row, col);
Jim Blandy's avatar
Jim Blandy committed
1077
	}
Jim Blandy's avatar
Jim Blandy committed
1078
      else
Jim Blandy's avatar
Jim Blandy committed
1079 1080
	cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
						  FRAME_WIDTH (f) - 1), 0));
Jim Blandy's avatar
Jim Blandy committed
1081 1082
    }

Jim Blandy's avatar
Jim Blandy committed
1083
  update_end (f);
Jim Blandy's avatar
Jim Blandy committed
1084 1085 1086 1087 1088 1089 1090 1091

  if (termscript)
    fflush (termscript);
  fflush (stdout);

  /* Here if output is preempted because input is detected.  */
 do_pause:

Jim Blandy's avatar
Jim Blandy committed
1092
  if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
Jim Blandy's avatar
Jim Blandy committed
1093 1094
  display_completed = !pause;

Jim Blandy's avatar
Jim Blandy committed
1095
  bzero (desired_frame->enable, FRAME_HEIGHT (f));
Jim Blandy's avatar
Jim Blandy committed
1096 1097 1098 1099 1100 1101 1102 1103 1104
  return pause;
}

/* Called when about to quit, to check for doing so
   at an improper time.  */

void
quit_error_check ()
{
Jim Blandy's avatar
Jim Blandy committed
1105
  if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
Jim Blandy's avatar
Jim Blandy committed
1106
    return;
Jim Blandy's avatar
Jim Blandy committed
1107
  if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
Jim Blandy's avatar
Jim Blandy committed
1108
    abort ();
Jim Blandy's avatar
Jim Blandy committed
1109
  if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
Jim Blandy's avatar
Jim Blandy committed
1110 1111 1112 1113 1114 1115 1116
    abort ();
}

/* Decide what insert/delete line to do, and do it */

extern void scrolling_1 ();