(struct x_display_info): Struct renamed from x_screen.
[bpt/emacs.git] / src / dispnew.c
CommitLineData
4588ec20 1/* Updating of data structures for redisplay.
60a8948a 2 Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
4588ec20
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
fa61c701 8the Free Software Foundation; either version 2, or (at your option)
4588ec20
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <signal.h>
22
18160b98 23#include <config.h>
565620a5
RS
24
25#include <stdio.h>
4588ec20
JB
26#include <ctype.h>
27
47099d6f 28#include "lisp.h"
4588ec20
JB
29#include "termchar.h"
30#include "termopts.h"
3be08bea 31#include "termhooks.h"
4588ec20 32#include "cm.h"
4588ec20
JB
33#include "dispextern.h"
34#include "buffer.h"
502b9b64 35#include "frame.h"
4588ec20
JB
36#include "window.h"
37#include "commands.h"
38#include "disptab.h"
39#include "indent.h"
d169fe39 40#include "intervals.h"
4588ec20 41
648fa17d 42#include "systty.h"
a41f8bed 43
4588ec20
JB
44#ifdef HAVE_X_WINDOWS
45#include "xterm.h"
46#endif /* HAVE_X_WINDOWS */
47
6cbd1643
RS
48/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
49#include "systime.h"
50
3883a901
RS
51#include <errno.h>
52
4588ec20
JB
53#define max(a, b) ((a) > (b) ? (a) : (b))
54#define min(a, b) ((a) < (b) ? (a) : (b))
55
4588ec20
JB
56/* Get number of chars of output now in the buffer of a stdio stream.
57 This ought to be built in in stdio, but it isn't.
58 Some s- files override this because their stdio internals differ. */
e3271ae5 59#ifdef __GNU_LIBRARY__
097c2824
RM
60/* The s- file might have overridden the definition with one that works for
61 the system's C library. But we are using the GNU C library, so this is
62 the right definition for every system. */
3883a901
RS
63#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
64#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
65#else
cb5558ff 66#undef PENDING_OUTPUT_COUNT
e3271ae5 67#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
3883a901
RS
68#endif
69#else /* not __GNU_LIBRARY__ */
cb5558ff 70#ifndef PENDING_OUTPUT_COUNT
4588ec20
JB
71#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
72#endif
e3271ae5 73#endif
4588ec20 74
a41f8bed 75/* Nonzero upon entry to redisplay means do not assume anything about
502b9b64 76 current contents of actual terminal frame; clear and redraw it. */
4588ec20 77
502b9b64 78int frame_garbaged;
4588ec20
JB
79
80/* Nonzero means last display completed. Zero means it was preempted. */
81
82int display_completed;
83
84/* Lisp variable visible-bell; enables use of screen-flash
85 instead of audible bell. */
86
87int visible_bell;
88
502b9b64 89/* Invert the color of the whole frame, at a low level. */
4588ec20
JB
90
91int inverse_video;
92
93/* Line speed of the terminal. */
94
95int baud_rate;
96
97/* nil or a symbol naming the window system under which emacs is
98 running ('x is the only current possibility). */
99
100Lisp_Object Vwindow_system;
101
102/* Version number of X windows: 10, 11 or nil. */
103Lisp_Object Vwindow_system_version;
104
105/* Vector of glyph definitions. Indexed by glyph number,
106 the contents are a string which is how to output the glyph.
107
108 If Vglyph_table is nil, a glyph is output by using its low 8 bits
109 as a character code. */
110
111Lisp_Object Vglyph_table;
112
113/* Display table to use for vectors that don't specify their own. */
114
115Lisp_Object Vstandard_display_table;
116
117/* Nonzero means reading single-character input with prompt
1113d9db
JB
118 so put cursor on minibuffer after the prompt.
119 positive means at end of text in echo area;
120 negative means at beginning of line. */
4588ec20
JB
121int cursor_in_echo_area;
122\f
502b9b64 123/* The currently selected frame.
87485d6f
MW
124 In a single-frame version, this variable always holds the address of
125 the_only_frame. */
4588ec20 126
502b9b64 127FRAME_PTR selected_frame;
4588ec20 128
502b9b64
JB
129/* A frame which is not just a minibuffer, or 0 if there are no such
130 frames. This is usually the most recent such frame that was
87485d6f
MW
131 selected. In a single-frame version, this variable always holds
132 the address of the_only_frame. */
502b9b64 133FRAME_PTR last_nonminibuf_frame;
e5d77022 134
502b9b64 135/* In a single-frame version, the information that would otherwise
190721ac
JB
136 exist inside frame objects lives in the following structure instead.
137
138 NOTE: the_only_frame is not checked for garbage collection; don't
eb8c3be9 139 store collectible objects in any of its fields!
190721ac
JB
140
141 You're not/The only frame in town/... */
4588ec20 142
502b9b64
JB
143#ifndef MULTI_FRAME
144struct frame the_only_frame;
e5d77022 145#endif
4588ec20
JB
146
147/* This is a vector, made larger whenever it isn't large enough,
502b9b64
JB
148 which is used inside `update_frame' to hold the old contents
149 of the FRAME_PHYS_LINES of the frame being updated. */
150struct frame_glyphs **ophys_lines;
4588ec20
JB
151/* Length of vector currently allocated. */
152int ophys_lines_length;
153
154FILE *termscript; /* Stdio stream being used for copy of all output. */
155
156struct cm Wcm; /* Structure for info on cursor positioning */
157
158extern short ospeed; /* Output speed (from sg_ospeed) */
159
4588ec20 160int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
4588ec20 161\f
502b9b64 162#ifdef MULTI_FRAME
4588ec20 163
502b9b64
JB
164DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
165 "Clear frame FRAME and output again what is supposed to appear on it.")
166 (frame)
167 Lisp_Object frame;
4588ec20 168{
502b9b64 169 FRAME_PTR f;
4588ec20 170
502b9b64
JB
171 CHECK_LIVE_FRAME (frame, 0);
172 f = XFRAME (frame);
173 update_begin (f);
4588ec20 174 /* set_terminal_modes (); */
502b9b64 175 clear_frame ();
b6a65ac2 176 clear_frame_records (f);
502b9b64 177 update_end (f);
4588ec20 178 fflush (stdout);
4588ec20
JB
179 windows_or_buffers_changed++;
180 /* Mark all windows as INaccurate,
181 so that every window will have its redisplay done. */
502b9b64
JB
182 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
183 f->garbaged = 0;
4588ec20
JB
184 return Qnil;
185}
186
502b9b64
JB
187redraw_frame (f)
188 FRAME_PTR f;
4588ec20 189{
502b9b64 190 Lisp_Object frame;
e9c9a718 191 XSETFRAME (frame, f);
502b9b64 192 Fredraw_frame (frame);
4588ec20
JB
193}
194
35f56f96 195#else
4588ec20 196
d8039c5c 197DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
35f56f96
JB
198 "Clear frame FRAME and output again what is supposed to appear on it.")
199 (frame)
200 Lisp_Object frame;
4588ec20
JB
201{
202 update_begin (0);
203 set_terminal_modes ();
502b9b64 204 clear_frame ();
4588ec20
JB
205 update_end (0);
206 fflush (stdout);
502b9b64 207 clear_frame_records (0);
4588ec20
JB
208 windows_or_buffers_changed++;
209 /* Mark all windows as INaccurate,
210 so that every window will have its redisplay done. */
b5c685f4 211 mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
4588ec20
JB
212 return Qnil;
213}
214
35f56f96
JB
215#endif
216
217DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
218 "Clear and redisplay all visible frames.")
219 ()
220{
221 Lisp_Object tail, frame;
222
223 FOR_EACH_FRAME (tail, frame)
9223a96a 224 if (FRAME_VISIBLE_P (XFRAME (frame)))
35f56f96
JB
225 Fredraw_frame (frame);
226
227 return Qnil;
228}
229
9223a96a
RS
230/* This is used when frame_garbaged is set.
231 Redraw the individual frames marked as garbaged. */
232
233void
234redraw_garbaged_frames ()
235{
236 Lisp_Object tail, frame;
237
238 FOR_EACH_FRAME (tail, frame)
239 if (FRAME_VISIBLE_P (XFRAME (frame))
240 && FRAME_GARBAGED_P (XFRAME (frame)))
241 Fredraw_frame (frame);
242}
243
4588ec20 244\f
502b9b64
JB
245static struct frame_glyphs *
246make_frame_glyphs (frame, empty)
247 register FRAME_PTR frame;
4588ec20
JB
248 int empty;
249{
250 register int i;
502b9b64
JB
251 register width = FRAME_WIDTH (frame);
252 register height = FRAME_HEIGHT (frame);
60a8948a
RS
253 register struct frame_glyphs *new
254 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
4588ec20 255
502b9b64 256 SET_GLYPHS_FRAME (new, frame);
4588ec20
JB
257 new->height = height;
258 new->width = width;
259 new->used = (int *) xmalloc (height * sizeof (int));
260 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
60a8948a 261 new->charstarts = (int **) xmalloc (height * sizeof (int *));
4588ec20
JB
262 new->highlight = (char *) xmalloc (height * sizeof (char));
263 new->enable = (char *) xmalloc (height * sizeof (char));
264 bzero (new->enable, height * sizeof (char));
265 new->bufp = (int *) xmalloc (height * sizeof (int));
266
267#ifdef HAVE_X_WINDOWS
b6a65ac2 268 if (FRAME_X_P (frame))
4588ec20 269 {
4588ec20
JB
270 new->top_left_x = (short *) xmalloc (height * sizeof (short));
271 new->top_left_y = (short *) xmalloc (height * sizeof (short));
272 new->pix_width = (short *) xmalloc (height * sizeof (short));
273 new->pix_height = (short *) xmalloc (height * sizeof (short));
448fd7c0 274 new->max_ascent = (short *) xmalloc (height * sizeof (short));
4588ec20
JB
275 }
276#endif
277
278 if (empty)
279 {
280 /* Make the buffer used by decode_mode_spec. This buffer is also
502b9b64 281 used as temporary storage when updating the frame. See scroll.c. */
4588ec20 282 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
d52bad65 283 unsigned int total_charstarts = (width + 2) * sizeof (int);
4588ec20
JB
284
285 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
286 bzero (new->total_contents, total_glyphs);
d52bad65
RS
287
288 new->total_charstarts = (int *) xmalloc (total_charstarts);
289 bzero (new->total_charstarts, total_glyphs);
4588ec20
JB
290 }
291 else
292 {
293 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
294
295 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
296 bzero (new->total_contents, total_glyphs);
297 for (i = 0; i < height; i++)
298 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
60a8948a
RS
299
300 if (!FRAME_TERMCAP_P (frame))
301 {
302 unsigned int total_charstarts = height * (width + 2) * sizeof (int);
303
304 new->total_charstarts = (int *) xmalloc (total_charstarts);
305 bzero (new->total_charstarts, total_charstarts);
306 for (i = 0; i < height; i++)
307 new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
308 }
309 else
310 {
311 /* Without a window system, we don't really need charstarts.
312 So use a small amount of space to make enough data structure
313 to prevent crashes in display_text_line. */
314 new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
315 for (i = 0; i < height; i++)
316 new->charstarts[i] = new->total_charstarts;
317 }
4588ec20
JB
318 }
319
320 return new;
321}
322
05233a7d 323void
502b9b64
JB
324free_frame_glyphs (frame, glyphs)
325 FRAME_PTR frame;
326 struct frame_glyphs *glyphs;
4588ec20
JB
327{
328 if (glyphs->total_contents)
9ac0d9e0 329 xfree (glyphs->total_contents);
60a8948a
RS
330 if (glyphs->total_charstarts)
331 xfree (glyphs->total_charstarts);
4588ec20 332
9ac0d9e0
JB
333 xfree (glyphs->used);
334 xfree (glyphs->glyphs);
335 xfree (glyphs->highlight);
336 xfree (glyphs->enable);
337 xfree (glyphs->bufp);
60a8948a
RS
338 if (glyphs->charstarts)
339 xfree (glyphs->charstarts);
4588ec20
JB
340
341#ifdef HAVE_X_WINDOWS
b6a65ac2 342 if (FRAME_X_P (frame))
4588ec20 343 {
9ac0d9e0
JB
344 xfree (glyphs->top_left_x);
345 xfree (glyphs->top_left_y);
346 xfree (glyphs->pix_width);
347 xfree (glyphs->pix_height);
348 xfree (glyphs->max_ascent);
4588ec20
JB
349 }
350#endif
351
9ac0d9e0 352 xfree (glyphs);
4588ec20
JB
353}
354
355static void
502b9b64
JB
356remake_frame_glyphs (frame)
357 FRAME_PTR frame;
4588ec20 358{
502b9b64
JB
359 if (FRAME_CURRENT_GLYPHS (frame))
360 free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
361 if (FRAME_DESIRED_GLYPHS (frame))
362 free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
363 if (FRAME_TEMP_GLYPHS (frame))
364 free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
365
366 if (FRAME_MESSAGE_BUF (frame))
832a0726
JB
367 {
368 /* Reallocate the frame's message buffer; remember that
369 echo_area_glyphs may be pointing here. */
370 char *old_message_buf = FRAME_MESSAGE_BUF (frame);
371
372 FRAME_MESSAGE_BUF (frame)
373 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
374 FRAME_WIDTH (frame) + 1);
375
376 if (echo_area_glyphs == old_message_buf)
377 echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
378 if (previous_echo_glyphs == old_message_buf)
379 previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
380 }
4588ec20 381 else
502b9b64
JB
382 FRAME_MESSAGE_BUF (frame)
383 = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
4588ec20 384
502b9b64
JB
385 FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
386 FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
387 FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
388 SET_FRAME_GARBAGED (frame);
4588ec20
JB
389}
390\f
502b9b64 391/* Return the hash code of contents of line VPOS in frame-matrix M. */
4588ec20
JB
392
393static int
394line_hash_code (m, vpos)
502b9b64 395 register struct frame_glyphs *m;
4588ec20
JB
396 int vpos;
397{
398 register GLYPH *body, *end;
399 register int h = 0;
400
401 if (!m->enable[vpos])
402 return 0;
403
94aa5d2d 404 /* Give all highlighted lines the same hash code
4588ec20
JB
405 so as to encourage scrolling to leave them in place. */
406 if (m->highlight[vpos])
407 return -1;
408
409 body = m->glyphs[vpos];
410
411 if (must_write_spaces)
412 while (1)
413 {
414 GLYPH g = *body++;
415
416 if (g == 0)
417 break;
418 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
419 }
420 else
421 while (1)
422 {
423 GLYPH g = *body++;
424
425 if (g == 0)
426 break;
427 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
428 }
429
430 if (h)
431 return h;
432 return 1;
433}
434
435/* Return number of characters in line in M at vpos VPOS,
436 except don't count leading and trailing spaces
437 unless the terminal requires those to be explicitly output. */
438
439static unsigned int
440line_draw_cost (m, vpos)
502b9b64 441 struct frame_glyphs *m;
4588ec20
JB
442 int vpos;
443{
444 register GLYPH *beg = m->glyphs[vpos];
445 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
446 register int i;
447 register int tlen = GLYPH_TABLE_LENGTH;
448 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
449
450 /* Ignore trailing and leading spaces if we can. */
451 if (!must_write_spaces)
452 {
453 while ((end != beg) && (*end == SPACEGLYPH))
454 --end;
455 if (end == beg)
456 return (0); /* All blank line. */
457
458 while (*beg == SPACEGLYPH)
459 ++beg;
460 }
461
462 /* If we don't have a glyph-table, each glyph is one character,
463 so return the number of glyphs. */
464 if (tbase == 0)
465 return end - beg;
466
467 /* Otherwise, scan the glyphs and accumulate their total size in I. */
468 i = 0;
469 while ((beg <= end) && *beg)
470 {
471 register GLYPH g = *beg++;
472
473 if (GLYPH_SIMPLE_P (tbase, tlen, g))
474 i += 1;
475 else
476 i += GLYPH_LENGTH (tbase, g);
477 }
478 return i;
479}
480\f
481/* The functions on this page are the interface from xdisp.c to redisplay.
482
483 The only other interface into redisplay is through setting
502b9b64
JB
484 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
485 and SET_FRAME_GARBAGED (frame). */
4588ec20
JB
486
487/* cancel_line eliminates any request to display a line at position `vpos' */
488
502b9b64 489cancel_line (vpos, frame)
4588ec20 490 int vpos;
502b9b64 491 register FRAME_PTR frame;
4588ec20 492{
502b9b64 493 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
4588ec20
JB
494}
495
502b9b64
JB
496clear_frame_records (frame)
497 register FRAME_PTR frame;
4588ec20 498{
502b9b64 499 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
4588ec20
JB
500}
501
502/* Prepare to display on line VPOS starting at HPOS within it. */
503
504void
502b9b64
JB
505get_display_line (frame, vpos, hpos)
506 register FRAME_PTR frame;
4588ec20
JB
507 int vpos;
508 register int hpos;
509{
502b9b64
JB
510 register struct frame_glyphs *glyphs;
511 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
512 register GLYPH *p;
513
7c3c72ec 514 if (vpos < 0)
4588ec20
JB
515 abort ();
516
517 if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
518 abort ();
519
520 if (! desired_glyphs->enable[vpos])
521 {
522 desired_glyphs->used[vpos] = 0;
523 desired_glyphs->highlight[vpos] = 0;
524 desired_glyphs->enable[vpos] = 1;
525 }
526
527 if (hpos > desired_glyphs->used[vpos])
528 {
529 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
530 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
531
532 desired_glyphs->used[vpos] = hpos;
533 while (g != end)
534 *g++ = SPACEGLYPH;
535 }
536}
537
538/* Like bcopy except never gets confused by overlap. */
539
540void
541safe_bcopy (from, to, size)
542 char *from, *to;
543 int size;
544{
b5c685f4 545 if (size <= 0 || from == to)
4588ec20
JB
546 return;
547
b5c685f4
JB
548 /* If the source and destination don't overlap, then bcopy can
549 handle it. If they do overlap, but the destination is lower in
550 memory than the source, we'll assume bcopy can handle that. */
551 if (to < from || from + size <= to)
552 bcopy (from, to, size);
553
554 /* Otherwise, we'll copy from the end. */
555 else
4588ec20 556 {
b5c685f4
JB
557 register char *endf = from + size;
558 register char *endt = to + size;
4588ec20
JB
559
560 /* If TO - FROM is large, then we should break the copy into
561 nonoverlapping chunks of TO - FROM bytes each. However, if
562 TO - FROM is small, then the bcopy function call overhead
563 makes this not worth it. The crossover point could be about
b5c685f4
JB
564 anywhere. Since I don't think the obvious copy loop is too
565 bad, I'm trying to err in its favor. */
4588ec20
JB
566 if (to - from < 64)
567 {
568 do
569 *--endt = *--endf;
570 while (endf != from);
571 }
572 else
573 {
b5c685f4 574 for (;;)
4588ec20
JB
575 {
576 endt -= (to - from);
577 endf -= (to - from);
578
b5c685f4
JB
579 if (endt < to)
580 break;
581
4588ec20
JB
582 bcopy (endf, endt, to - from);
583 }
b5c685f4
JB
584
585 /* If SIZE wasn't a multiple of TO - FROM, there will be a
4588ec20
JB
586 little left over. The amount left over is
587 (endt + (to - from)) - to, which is endt - from. */
588 bcopy (from, to, endt - from);
589 }
590 }
4588ec20
JB
591}
592
98038dc0 593/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
4588ec20
JB
594 DISTANCE may be negative. */
595
596static void
597rotate_vector (vector, size, distance)
598 char *vector;
599 int size;
600 int distance;
601{
602 char *temp = (char *) alloca (size);
603
604 if (distance < 0)
605 distance += size;
606
607 bcopy (vector, temp + distance, size - distance);
608 bcopy (vector + size - distance, temp, distance);
609 bcopy (temp, vector, size);
610}
611
612/* Scroll lines from vpos FROM up to but not including vpos END
613 down by AMOUNT lines (AMOUNT may be negative).
614 Returns nonzero if done, zero if terminal cannot scroll them. */
615
616int
d52bad65 617scroll_frame_lines (frame, from, end, amount, newpos)
502b9b64 618 register FRAME_PTR frame;
d52bad65 619 int from, end, amount, newpos;
4588ec20
JB
620{
621 register int i;
502b9b64
JB
622 register struct frame_glyphs *current_frame
623 = FRAME_CURRENT_GLYPHS (frame);
d52bad65 624 int pos_adjust;
23b0200c 625 int width = FRAME_WIDTH (frame);
4588ec20
JB
626
627 if (!line_ins_del_ok)
628 return 0;
629
630 if (amount == 0)
631 return 1;
632
633 if (amount > 0)
634 {
502b9b64 635 update_begin (frame);
4588ec20
JB
636 set_terminal_window (end + amount);
637 if (!scroll_region_ok)
638 ins_del_lines (end, -amount);
639 ins_del_lines (from, amount);
640 set_terminal_window (0);
641
502b9b64 642 rotate_vector (current_frame->glyphs + from,
4588ec20
JB
643 sizeof (GLYPH *) * (end + amount - from),
644 amount * sizeof (GLYPH *));
645
60a8948a 646 rotate_vector (current_frame->charstarts + from,
d52bad65
RS
647 sizeof (int *) * (end + amount - from),
648 amount * sizeof (int *));
649
23b0200c
RS
650 safe_bcopy (current_frame->used + from,
651 current_frame->used + from + amount,
652 (end - from) * sizeof current_frame->used[0]);
653
654 safe_bcopy (current_frame->highlight + from,
655 current_frame->highlight + from + amount,
656 (end - from) * sizeof current_frame->highlight[0]);
657
658 safe_bcopy (current_frame->enable + from,
659 current_frame->enable + from + amount,
660 (end - from) * sizeof current_frame->enable[0]);
661
d52bad65
RS
662 /* Adjust the lines by an amount
663 that puts the first of them at NEWPOS. */
23b0200c 664 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
60a8948a
RS
665
666 /* Offset each char position in the charstarts lines we moved
667 by pos_adjust. */
23b0200c 668 for (i = from + amount; i < end + amount; i++)
60a8948a 669 {
d52bad65 670 int *line = current_frame->charstarts[i];
60a8948a 671 int col;
23b0200c
RS
672 for (col = 0; col < width; col++)
673 if (line[col] > 0)
674 line[col] += pos_adjust;
60a8948a 675 }
23b0200c 676 for (i = from; i < from + amount; i++)
60a8948a 677 {
d52bad65 678 int *line = current_frame->charstarts[i];
60a8948a
RS
679 int col;
680 line[0] = -1;
23b0200c 681 for (col = 0; col < width; col++)
60a8948a
RS
682 line[col] = 0;
683 }
684
4588ec20
JB
685 /* Mark the lines made empty by scrolling as enabled, empty and
686 normal video. */
502b9b64
JB
687 bzero (current_frame->used + from,
688 amount * sizeof current_frame->used[0]);
689 bzero (current_frame->highlight + from,
690 amount * sizeof current_frame->highlight[0]);
4588ec20
JB
691 for (i = from; i < from + amount; i++)
692 {
502b9b64 693 current_frame->glyphs[i][0] = '\0';
60a8948a 694 current_frame->charstarts[i][0] = -1;
502b9b64 695 current_frame->enable[i] = 1;
4588ec20
JB
696 }
697
502b9b64
JB
698 safe_bcopy (current_frame->bufp + from,
699 current_frame->bufp + from + amount,
700 (end - from) * sizeof current_frame->bufp[0]);
4588ec20
JB
701
702#ifdef HAVE_X_WINDOWS
b6a65ac2 703 if (FRAME_X_P (frame))
4588ec20 704 {
502b9b64
JB
705 safe_bcopy (current_frame->top_left_x + from,
706 current_frame->top_left_x + from + amount,
707 (end - from) * sizeof current_frame->top_left_x[0]);
4588ec20 708
502b9b64
JB
709 safe_bcopy (current_frame->top_left_y + from,
710 current_frame->top_left_y + from + amount,
711 (end - from) * sizeof current_frame->top_left_y[0]);
4588ec20 712
502b9b64
JB
713 safe_bcopy (current_frame->pix_width + from,
714 current_frame->pix_width + from + amount,
715 (end - from) * sizeof current_frame->pix_width[0]);
4588ec20 716
502b9b64
JB
717 safe_bcopy (current_frame->pix_height + from,
718 current_frame->pix_height + from + amount,
719 (end - from) * sizeof current_frame->pix_height[0]);
448fd7c0
JA
720
721 safe_bcopy (current_frame->max_ascent + from,
722 current_frame->max_ascent + from + amount,
723 (end - from) * sizeof current_frame->max_ascent[0]);
4588ec20
JB
724 }
725#endif /* HAVE_X_WINDOWS */
726
502b9b64 727 update_end (frame);
4588ec20
JB
728 }
729 if (amount < 0)
730 {
502b9b64 731 update_begin (frame);
4588ec20
JB
732 set_terminal_window (end);
733 ins_del_lines (from + amount, amount);
734 if (!scroll_region_ok)
735 ins_del_lines (end + amount, -amount);
736 set_terminal_window (0);
737
502b9b64 738 rotate_vector (current_frame->glyphs + from + amount,
4588ec20
JB
739 sizeof (GLYPH *) * (end - from - amount),
740 amount * sizeof (GLYPH *));
741
60a8948a 742 rotate_vector (current_frame->charstarts + from + amount,
d52bad65
RS
743 sizeof (int *) * (end - from - amount),
744 amount * sizeof (int *));
745
23b0200c
RS
746 safe_bcopy (current_frame->used + from,
747 current_frame->used + from + amount,
748 (end - from) * sizeof current_frame->used[0]);
749
750 safe_bcopy (current_frame->highlight + from,
751 current_frame->highlight + from + amount,
752 (end - from) * sizeof current_frame->highlight[0]);
753
754 safe_bcopy (current_frame->enable + from,
755 current_frame->enable + from + amount,
756 (end - from) * sizeof current_frame->enable[0]);
757
d52bad65
RS
758 /* Adjust the lines by an amount
759 that puts the first of them at NEWPOS. */
23b0200c 760 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
60a8948a
RS
761
762 /* Offset each char position in the charstarts lines we moved
763 by pos_adjust. */
764 for (i = from + amount; i < end + amount; i++)
765 {
d52bad65 766 int *line = current_frame->charstarts[i];
60a8948a 767 int col;
23b0200c
RS
768 for (col = 0; col < width; col++)
769 if (line[col] > 0)
770 line[col] += pos_adjust;
60a8948a 771 }
23b0200c 772 for (i = end + amount; i < end; i++)
60a8948a 773 {
d52bad65 774 int *line = current_frame->charstarts[i];
60a8948a
RS
775 int col;
776 line[0] = -1;
23b0200c 777 for (col = 0; col < width; col++)
60a8948a
RS
778 line[col] = 0;
779 }
780
4588ec20
JB
781 /* Mark the lines made empty by scrolling as enabled, empty and
782 normal video. */
502b9b64
JB
783 bzero (current_frame->used + end + amount,
784 - amount * sizeof current_frame->used[0]);
785 bzero (current_frame->highlight + end + amount,
786 - amount * sizeof current_frame->highlight[0]);
4588ec20
JB
787 for (i = end + amount; i < end; i++)
788 {
502b9b64 789 current_frame->glyphs[i][0] = '\0';
60a8948a 790 current_frame->charstarts[i][0] = 0;
502b9b64 791 current_frame->enable[i] = 1;
4588ec20
JB
792 }
793
502b9b64
JB
794 safe_bcopy (current_frame->bufp + from,
795 current_frame->bufp + from + amount,
796 (end - from) * sizeof current_frame->bufp[0]);
4588ec20
JB
797
798#ifdef HAVE_X_WINDOWS
b6a65ac2 799 if (FRAME_X_P (frame))
4588ec20 800 {
502b9b64
JB
801 safe_bcopy (current_frame->top_left_x + from,
802 current_frame->top_left_x + from + amount,
803 (end - from) * sizeof current_frame->top_left_x[0]);
4588ec20 804
502b9b64
JB
805 safe_bcopy (current_frame->top_left_y + from,
806 current_frame->top_left_y + from + amount,
807 (end - from) * sizeof current_frame->top_left_y[0]);
4588ec20 808
502b9b64
JB
809 safe_bcopy (current_frame->pix_width + from,
810 current_frame->pix_width + from + amount,
811 (end - from) * sizeof current_frame->pix_width[0]);
4588ec20 812
502b9b64
JB
813 safe_bcopy (current_frame->pix_height + from,
814 current_frame->pix_height + from + amount,
815 (end - from) * sizeof current_frame->pix_height[0]);
448fd7c0
JA
816
817 safe_bcopy (current_frame->max_ascent + from,
818 current_frame->max_ascent + from + amount,
819 (end - from) * sizeof current_frame->max_ascent[0]);
4588ec20
JB
820 }
821#endif /* HAVE_X_WINDOWS */
822
502b9b64 823 update_end (frame);
4588ec20
JB
824 }
825 return 1;
826}
827\f
502b9b64 828/* After updating a window W that isn't the full frame wide,
4588ec20 829 copy all the columns that W does not occupy
502b9b64
JB
830 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
831 so that update_frame will not change those columns. */
4588ec20
JB
832
833preserve_other_columns (w)
834 struct window *w;
835{
836 register int vpos;
502b9b64
JB
837 register struct frame_glyphs *current_frame, *desired_frame;
838 register FRAME_PTR frame = XFRAME (w->frame);
4588ec20
JB
839 int start = XFASTINT (w->left);
840 int end = XFASTINT (w->left) + XFASTINT (w->width);
841 int bot = XFASTINT (w->top) + XFASTINT (w->height);
842
502b9b64
JB
843 current_frame = FRAME_CURRENT_GLYPHS (frame);
844 desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
845
846 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
847 {
502b9b64 848 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
4588ec20
JB
849 {
850 if (start > 0)
851 {
852 int len;
853
502b9b64 854 bcopy (current_frame->glyphs[vpos],
aec9f5f6 855 desired_frame->glyphs[vpos],
4b34bd81 856 start * sizeof (current_frame->glyphs[vpos][0]));
60a8948a
RS
857 bcopy (current_frame->charstarts[vpos],
858 desired_frame->charstarts[vpos],
4b34bd81 859 start * sizeof (current_frame->charstarts[vpos][0]));
502b9b64
JB
860 len = min (start, current_frame->used[vpos]);
861 if (desired_frame->used[vpos] < len)
862 desired_frame->used[vpos] = len;
4588ec20 863 }
502b9b64
JB
864 if (current_frame->used[vpos] > end
865 && desired_frame->used[vpos] < current_frame->used[vpos])
4588ec20 866 {
502b9b64 867 while (desired_frame->used[vpos] < end)
60a8948a
RS
868 {
869 int used = desired_frame->used[vpos]++;
870 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
871 desired_frame->glyphs[vpos][used] = 0;
872 }
502b9b64
JB
873 bcopy (current_frame->glyphs[vpos] + end,
874 desired_frame->glyphs[vpos] + end,
aec9f5f6 875 ((current_frame->used[vpos] - end)
4b34bd81 876 * sizeof (current_frame->glyphs[vpos][0])));
60a8948a
RS
877 bcopy (current_frame->charstarts[vpos] + end,
878 desired_frame->charstarts[vpos] + end,
879 ((current_frame->used[vpos] - end)
4b34bd81 880 * sizeof (current_frame->charstarts[vpos][0])));
502b9b64 881 desired_frame->used[vpos] = current_frame->used[vpos];
4588ec20
JB
882 }
883 }
884 }
885}
886\f
887#if 0
888
502b9b64 889/* If window w does not need to be updated and isn't the full frame wide,
4588ec20 890 copy all the columns that w does occupy
502b9b64
JB
891 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
892 so that update_frame will not change those columns.
4588ec20
JB
893
894 Have not been able to figure out how to use this correctly. */
895
896preserve_my_columns (w)
897 struct window *w;
898{
899 register int vpos, fin;
502b9b64
JB
900 register struct frame_glyphs *l1, *l2;
901 register FRAME_PTR frame = XFRAME (w->frame);
4588ec20
JB
902 int start = XFASTINT (w->left);
903 int end = XFASTINT (w->left) + XFASTINT (w->width);
904 int bot = XFASTINT (w->top) + XFASTINT (w->height);
905
906 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
907 {
502b9b64
JB
908 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
909 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
4588ec20
JB
910 {
911 if (l2->length > start && l1->length < l2->length)
912 {
913 fin = l2->length;
914 if (fin > end) fin = end;
915 while (l1->length < start)
916 l1->body[l1->length++] = ' ';
917 bcopy (l2->body + start, l1->body + start, fin - start);
918 l1->length = fin;
919 }
920 }
921 }
922}
923
924#endif
925\f
b64b3980 926/* Adjust by ADJUST the charstart values in window W
23b0200c 927 after vpos VPOS, which counts relative to the frame
b64b3980
RS
928 (not relative to W itself). */
929
930void
931adjust_window_charstarts (w, vpos, adjust)
932 struct window *w;
933 int vpos;
934 int adjust;
935{
936 int left = XFASTINT (w->left);
937 int top = XFASTINT (w->top);
23b0200c
RS
938 int right = left + window_internal_width (w);
939 int bottom = top + window_internal_height (w);
b64b3980
RS
940 int i;
941
23b0200c 942 for (i = vpos + 1; i < bottom; i++)
b64b3980
RS
943 {
944 int *charstart
945 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
946 int j;
947 for (j = left; j < right; j++)
948 if (charstart[j] > 0)
949 charstart[j] += adjust;
950 }
951}
23b0200c 952
352f1545
RS
953/* Check the charstarts values in the area of window W
954 for internal consistency. We cannot check that they are "right";
955 we can only look for something nonsensical. */
956
23b0200c
RS
957verify_charstarts (w)
958 struct window *w;
959{
960 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
961 int i;
962 int top = XFASTINT (w->top);
963 int bottom = top + window_internal_height (w);
964 int left = XFASTINT (w->left);
965 int right = left + window_internal_width (w);
966 int next_line;
352f1545
RS
967 int truncate = (XINT (w->hscroll)
968 || (truncate_partial_width_windows
969 && (XFASTINT (w->width) < FRAME_WIDTH (f)))
970 || !NILP (XBUFFER (w->buffer)->truncate_lines));
23b0200c
RS
971
972 for (i = top; i < bottom; i++)
973 {
974 int j;
975 int last;
352f1545 976 int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
23b0200c
RS
977
978 if (i != top)
352f1545
RS
979 {
980 if (truncate)
981 {
982 /* If we are truncating lines, allow a jump
983 in charstarts from one line to the next. */
984 if (charstart[left] < next_line)
985 abort ();
986 }
987 else
988 {
989 if (charstart[left] != next_line)
990 abort ();
991 }
992 }
23b0200c
RS
993
994 for (j = left; j < right; j++)
995 if (charstart[j] > 0)
996 last = charstart[j];
2e8907d3
RS
997 /* Record where the next line should start. */
998 next_line = last;
999 if (BUF_ZV (XBUFFER (w->buffer)) != last)
1000 {
1001 /* If there's a newline between the two lines, count that. */
1002 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
1003 if (endchar == '\n')
1004 next_line++;
1005 }
23b0200c
RS
1006 }
1007}
b64b3980 1008\f
4588ec20
JB
1009/* On discovering that the redisplay for a window was no good,
1010 cancel the columns of that window, so that when the window is
1011 displayed over again get_display_line will not complain. */
1012
1013cancel_my_columns (w)
1014 struct window *w;
1015{
1016 register int vpos;
60a8948a
RS
1017 register struct frame_glyphs *desired_glyphs
1018 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
4588ec20
JB
1019 register int start = XFASTINT (w->left);
1020 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
1021
1022 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
1023 if (desired_glyphs->enable[vpos]
1024 && desired_glyphs->used[vpos] >= start)
1025 desired_glyphs->used[vpos] = start;
1026}
1027\f
502b9b64 1028/* These functions try to perform directly and immediately on the frame
4588ec20
JB
1029 the necessary output for one change in the buffer.
1030 They may return 0 meaning nothing was done if anything is difficult,
1031 or 1 meaning the output was performed properly.
502b9b64 1032 They assume that the frame was up to date before the buffer
94aa5d2d 1033 change being displayed. They make various other assumptions too;
4588ec20
JB
1034 see command_loop_1 where these are called. */
1035
1036int
1037direct_output_for_insert (g)
1038 int g;
1039{
502b9b64
JB
1040 register FRAME_PTR frame = selected_frame;
1041 register struct frame_glyphs *current_frame
1042 = FRAME_CURRENT_GLYPHS (frame);
4588ec20
JB
1043
1044#ifndef COMPILER_REGISTER_BUG
1045 register
1046#endif /* COMPILER_REGISTER_BUG */
1047 struct window *w = XWINDOW (selected_window);
1048#ifndef COMPILER_REGISTER_BUG
1049 register
1050#endif /* COMPILER_REGISTER_BUG */
502b9b64 1051 int hpos = FRAME_CURSOR_X (frame);
4588ec20
JB
1052#ifndef COMPILER_REGISTER_BUG
1053 register
1054#endif /* COMPILER_REGISTER_BUG */
502b9b64 1055 int vpos = FRAME_CURSOR_Y (frame);
4588ec20 1056
fa61c701
JB
1057 /* Give up if about to continue line. */
1058 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
1059
4588ec20
JB
1060 /* Avoid losing if cursor is in invisible text off left margin */
1061 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
1062
1063 /* Give up if cursor outside window (in minibuf, probably) */
648fa17d 1064 || cursor_in_echo_area
502b9b64
JB
1065 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1066 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
4588ec20 1067
502b9b64 1068 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
4588ec20
JB
1069 || !display_completed
1070
1071 /* Give up if buffer appears in two places. */
1072 || buffer_shared > 1
1073
d169fe39
RS
1074#ifdef USE_TEXT_PROPERTIES
1075 /* Intervals have already been adjusted, point is after the
1076 character that was just inserted. */
ef4d2f9e 1077 /* Give up if character is invisible. */
d169fe39
RS
1078 /* Give up if character has a face property.
1079 At the moment we only lose at end of line or end of buffer
1080 and only with faces that have some background */
1081 /* Instead of wasting time, give up if character has any text properties */
254277e1 1082 || ! NILP (Ftext_properties_at (make_number (point - 1), Qnil))
d169fe39
RS
1083#endif
1084
4588ec20
JB
1085 /* Give up if w is minibuffer and a message is being displayed there */
1086 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1087 return 0;
1088
517b2e01 1089 {
19dff8dc 1090 int face = 0;
87485d6f 1091#ifdef HAVE_FACES
517b2e01 1092 int dummy;
19dff8dc
RS
1093
1094 if (FRAME_X_P (frame))
ea62c5a5 1095 face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point, 0);
517b2e01 1096#endif
a1c3de84 1097 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
839c7dfb
RS
1098 current_frame->charstarts[vpos][hpos] = point - 1;
1099 /* Record the entry for after the newly inserted character. */
1100 current_frame->charstarts[vpos][hpos + 1] = point;
b64b3980 1101 adjust_window_charstarts (w, vpos, 1);
517b2e01 1102 }
4588ec20
JB
1103 unchanged_modified = MODIFF;
1104 beg_unchanged = GPT - BEG;
a5d8b611
KH
1105 XSETFASTINT (w->last_point, point);
1106 XSETFASTINT (w->last_point_x, hpos);
1107 XSETFASTINT (w->last_modified, MODIFF);
4588ec20
JB
1108
1109 reassert_line_highlight (0, vpos);
502b9b64 1110 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
4588ec20 1111 fflush (stdout);
502b9b64
JB
1112 ++FRAME_CURSOR_X (frame);
1113 if (hpos == current_frame->used[vpos])
4588ec20 1114 {
502b9b64
JB
1115 current_frame->used[vpos] = hpos + 1;
1116 current_frame->glyphs[vpos][hpos + 1] = 0;
4588ec20
JB
1117 }
1118
1119 return 1;
1120}
1121
1122int
1123direct_output_forward_char (n)
1124 int n;
1125{
502b9b64 1126 register FRAME_PTR frame = selected_frame;
4588ec20 1127 register struct window *w = XWINDOW (selected_window);
254277e1 1128 Lisp_Object position;
ea0d86af
RS
1129 int hpos = FRAME_CURSOR_X (frame);
1130
1131 /* Give up if in truncated text at end of line. */
1132 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
1133 return 0;
1134
a9764248
JB
1135 /* Avoid losing if cursor is in invisible text off left margin
1136 or about to go off either side of window. */
502b9b64 1137 if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
a9764248
JB
1138 && (XINT (w->hscroll) || n < 0))
1139 || (n > 0
fa61c701 1140 && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
648fa17d 1141 || cursor_in_echo_area)
4588ec20 1142 return 0;
d169fe39 1143
de83c314
RS
1144 /* Can't use direct output if highlighting a region. */
1145 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1146 return 0;
1147
d169fe39
RS
1148#ifdef USE_TEXT_PROPERTIES
1149 /* Don't use direct output next to an invisible character
1150 since we might need to do something special. */
1151
a5d8b611 1152 XSETFASTINT (position, point);
2f24f5ac 1153 if (XFASTINT (position) < ZV
294634fb 1154 && ! NILP (Fget_char_property (position,
2f24f5ac 1155 Qinvisible,
294634fb
KH
1156 selected_window)))
1157 return 0;
d169fe39 1158
a5d8b611 1159 XSETFASTINT (position, point - 1);
2f24f5ac 1160 if (XFASTINT (position) >= BEGV
294634fb 1161 && ! NILP (Fget_char_property (position,
2f24f5ac 1162 Qinvisible,
294634fb
KH
1163 selected_window)))
1164 return 0;
d169fe39
RS
1165#endif
1166
502b9b64 1167 FRAME_CURSOR_X (frame) += n;
a5d8b611
KH
1168 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
1169 XSETFASTINT (w->last_point, point);
502b9b64 1170 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
4588ec20 1171 fflush (stdout);
d169fe39 1172
4588ec20
JB
1173 return 1;
1174}
1175\f
1176static void update_line ();
1177
502b9b64 1178/* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
4588ec20
JB
1179 Value is nonzero if redisplay stopped due to pending input.
1180 FORCE nonzero means do not stop for pending input. */
1181
1182int
502b9b64
JB
1183update_frame (f, force, inhibit_hairy_id)
1184 FRAME_PTR f;
4588ec20
JB
1185 int force;
1186 int inhibit_hairy_id;
1187{
54633da0 1188 register struct frame_glyphs *current_frame;
7098a0fa 1189 register struct frame_glyphs *desired_frame = 0;
4588ec20
JB
1190 register int i;
1191 int pause;
1192 int preempt_count = baud_rate / 2400 + 1;
1193 extern input_pending;
1194#ifdef HAVE_X_WINDOWS
1195 register int downto, leftmost;
1196#endif
1197
d88c2b9e
RS
1198 if (preempt_count <= 0)
1199 preempt_count = 1;
1200
502b9b64 1201 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1202
1203 detect_input_pending ();
1204 if (input_pending && !force)
1205 {
1206 pause = 1;
1207 goto do_pause;
1208 }
1209
502b9b64 1210 update_begin (f);
4588ec20
JB
1211
1212 if (!line_ins_del_ok)
1213 inhibit_hairy_id = 1;
1214
7098a0fa
RS
1215 /* These are separate to avoid a possible bug in the AIX C compiler. */
1216 current_frame = FRAME_CURRENT_GLYPHS (f);
1217 desired_frame = FRAME_DESIRED_GLYPHS (f);
1218
efb859b4
JB
1219 /* See if any of the desired lines are enabled; don't compute for
1220 i/d line if just want cursor motion. */
502b9b64
JB
1221 for (i = 0; i < FRAME_HEIGHT (f); i++)
1222 if (desired_frame->enable[i])
4588ec20
JB
1223 break;
1224
1225 /* Try doing i/d line, if not yet inhibited. */
502b9b64
JB
1226 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1227 force |= scrolling (f);
4588ec20
JB
1228
1229 /* Update the individual lines as needed. Do bottom line first. */
1230
502b9b64
JB
1231 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1232 update_line (f, FRAME_HEIGHT (f) - 1);
4588ec20
JB
1233
1234#ifdef HAVE_X_WINDOWS
b6a65ac2 1235 if (FRAME_X_P (f))
4588ec20 1236 {
502b9b64
JB
1237 leftmost = downto = f->display.x->internal_border_width;
1238 if (desired_frame->enable[0])
4588ec20 1239 {
502b9b64
JB
1240 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1241 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
1242 = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
448fd7c0 1243 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
502b9b64
JB
1244 current_frame->top_left_x[0] = leftmost;
1245 current_frame->top_left_y[0] = downto;
4588ec20
JB
1246 }
1247 }
1248#endif /* HAVE_X_WINDOWS */
1249
1250 /* Now update the rest of the lines. */
502b9b64 1251 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
4588ec20 1252 {
502b9b64 1253 if (desired_frame->enable[i])
4588ec20 1254 {
b6a65ac2 1255 if (FRAME_TERMCAP_P (f))
4588ec20
JB
1256 {
1257 /* Flush out every so many lines.
1258 Also flush out if likely to have more than 1k buffered
1259 otherwise. I'm told that some telnet connections get
1260 really screwed by more than 1k output at once. */
1261 int outq = PENDING_OUTPUT_COUNT (stdout);
1262 if (outq > 900
1263 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1264 {
1265 fflush (stdout);
1266 if (preempt_count == 1)
1267 {
a41f8bed
JB
1268#ifdef EMACS_OUTQSIZE
1269 if (EMACS_OUTQSIZE (0, &outq) < 0)
4588ec20
JB
1270 /* Probably not a tty. Ignore the error and reset
1271 * the outq count. */
1272 outq = PENDING_OUTPUT_COUNT (stdout);
1273#endif
1274 outq *= 10;
d520f0d2 1275 if (baud_rate <= outq && baud_rate > 0)
d88c2b9e 1276 sleep (outq / baud_rate);
4588ec20
JB
1277 }
1278 }
1279 if ((i - 1) % preempt_count == 0)
1280 detect_input_pending ();
1281 }
1282
502b9b64 1283 update_line (f, i);
4588ec20 1284#ifdef HAVE_X_WINDOWS
b6a65ac2 1285 if (FRAME_X_P (f))
4588ec20 1286 {
502b9b64
JB
1287 current_frame->top_left_y[i] = downto;
1288 current_frame->top_left_x[i] = leftmost;
4588ec20
JB
1289 }
1290#endif /* HAVE_X_WINDOWS */
1291 }
1292
e5d77022 1293#ifdef HAVE_X_WINDOWS
b6a65ac2 1294 if (FRAME_X_P (f))
448fd7c0 1295 downto += current_frame->pix_height[i];
e5d77022 1296#endif
4588ec20 1297 }
502b9b64 1298 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
4588ec20
JB
1299
1300 /* Now just clean up termcap drivers and set cursor, etc. */
1301 if (!pause)
1302 {
648fa17d
JB
1303 if (cursor_in_echo_area
1304 && FRAME_HAS_MINIBUF_P (f))
1113d9db 1305 {
648fa17d
JB
1306 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1307 int row, col;
1308
1309 if (cursor_in_echo_area < 0)
1310 {
1311 row = top;
1312 col = 0;
1313 }
1113d9db 1314 else
648fa17d
JB
1315 {
1316 /* If the minibuffer is several lines high, find the last
1317 line that has any text on it. */
1318 row = FRAME_HEIGHT (f);
1319 do
1320 {
1321 row--;
1322 if (current_frame->enable[row])
1323 col = current_frame->used[row];
1324 else
1325 col = 0;
1326 }
1327 while (row > top && col == 0);
1328
1329 if (col >= FRAME_WIDTH (f))
1330 {
1331 col = 0;
1332 if (row < FRAME_HEIGHT (f) - 1)
1333 row++;
1334 }
1335 }
1336
1337 cursor_to (row, col);
1113d9db 1338 }
4588ec20 1339 else
502b9b64
JB
1340 cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
1341 FRAME_WIDTH (f) - 1), 0));
4588ec20
JB
1342 }
1343
502b9b64 1344 update_end (f);
4588ec20
JB
1345
1346 if (termscript)
1347 fflush (termscript);
1348 fflush (stdout);
1349
1350 /* Here if output is preempted because input is detected. */
1351 do_pause:
1352
502b9b64 1353 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1354 display_completed = !pause;
1355
f5843453 1356 bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
4588ec20
JB
1357 return pause;
1358}
1359
1360/* Called when about to quit, to check for doing so
1361 at an improper time. */
1362
1363void
1364quit_error_check ()
1365{
502b9b64 1366 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
4588ec20 1367 return;
502b9b64 1368 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
4588ec20 1369 abort ();
502b9b64 1370 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
4588ec20
JB
1371 abort ();
1372}
1373\f
1374/* Decide what insert/delete line to do, and do it */
1375
1376extern void scrolling_1 ();
1377
502b9b64
JB
1378scrolling (frame)
1379 FRAME_PTR frame;
4588ec20
JB
1380{
1381 int unchanged_at_top, unchanged_at_bottom;
1382 int window_size;
1383 int changed_lines;
502b9b64
JB
1384 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1385 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1386 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
4588ec20 1387 register int i;
502b9b64
JB
1388 int free_at_end_vpos = FRAME_HEIGHT (frame);
1389 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1390 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
1391
1392 /* Compute hash codes of all the lines.
1393 Also calculate number of changed lines,
1394 number of unchanged lines at the beginning,
1395 and number of unchanged lines at the end. */
1396
1397 changed_lines = 0;
1398 unchanged_at_top = 0;
502b9b64
JB
1399 unchanged_at_bottom = FRAME_HEIGHT (frame);
1400 for (i = 0; i < FRAME_HEIGHT (frame); i++)
4588ec20
JB
1401 {
1402 /* Give up on this scrolling if some old lines are not enabled. */
502b9b64 1403 if (!current_frame->enable[i])
4588ec20 1404 return 0;
502b9b64
JB
1405 old_hash[i] = line_hash_code (current_frame, i);
1406 if (! desired_frame->enable[i])
4588ec20
JB
1407 new_hash[i] = old_hash[i];
1408 else
502b9b64 1409 new_hash[i] = line_hash_code (desired_frame, i);
4588ec20
JB
1410
1411 if (old_hash[i] != new_hash[i])
1412 {
1413 changed_lines++;
502b9b64 1414 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
4588ec20
JB
1415 }
1416 else if (i == unchanged_at_top)
1417 unchanged_at_top++;
502b9b64 1418 draw_cost[i] = line_draw_cost (desired_frame, i);
4588ec20
JB
1419 }
1420
1421 /* If changed lines are few, don't allow preemption, don't scroll. */
1422 if (changed_lines < baud_rate / 2400
502b9b64 1423 || unchanged_at_bottom == FRAME_HEIGHT (frame))
4588ec20
JB
1424 return 1;
1425
502b9b64 1426 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
4588ec20
JB
1427 - unchanged_at_bottom);
1428
1429 if (scroll_region_ok)
1430 free_at_end_vpos -= unchanged_at_bottom;
502b9b64 1431 else if (memory_below_frame)
4588ec20
JB
1432 free_at_end_vpos = -1;
1433
1434 /* If large window, fast terminal and few lines in common between
502b9b64 1435 current frame and desired frame, don't bother with i/d calc. */
4588ec20
JB
1436 if (window_size >= 18 && baud_rate > 2400
1437 && (window_size >=
1438 10 * scrolling_max_lines_saved (unchanged_at_top,
502b9b64 1439 FRAME_HEIGHT (frame) - unchanged_at_bottom,
4588ec20
JB
1440 old_hash, new_hash, draw_cost)))
1441 return 0;
1442
502b9b64 1443 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
4588ec20
JB
1444 draw_cost + unchanged_at_top - 1,
1445 old_hash + unchanged_at_top - 1,
1446 new_hash + unchanged_at_top - 1,
1447 free_at_end_vpos - unchanged_at_top);
1448
1449 return 0;
1450}
1451\f
1452/* Return the offset in its buffer of the character at location col, line
1453 in the given window. */
1454int
1455buffer_posn_from_coords (window, col, line)
1456 struct window *window;
1457 int col, line;
1458{
ef0fdbb1 1459 int hscroll = XINT (window->hscroll);
4588ec20
JB
1460 int window_left = XFASTINT (window->left);
1461
1462 /* The actual width of the window is window->width less one for the
efb859b4
JB
1463 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1464 window. */
fa61c701 1465 int window_width = window_internal_width (window) - 1;
4588ec20 1466
efb859b4 1467 int startp = marker_position (window->start);
4588ec20
JB
1468
1469 /* Since compute_motion will only operate on the current buffer,
1470 we need to save the old one and restore it when we're done. */
1471 struct buffer *old_current_buffer = current_buffer;
efb859b4 1472 struct position *posn;
4588ec20
JB
1473
1474 current_buffer = XBUFFER (window->buffer);
1475
502b9b64
JB
1476 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1477 (window->frame))->bufp to avoid scanning from the very top of
efb859b4
JB
1478 the window, but it isn't maintained correctly, and I'm not even
1479 sure I will keep it. */
1480 posn = compute_motion (startp, 0,
1481 (window == XWINDOW (minibuf_window) && startp == 1
ef0fdbb1
KH
1482 ? minibuf_prompt_width : 0)
1483 + (hscroll ? 1 - hscroll : 0),
fb0f454a 1484 ZV, line, col,
e37f06d7 1485 window_width, hscroll, 0, window);
4588ec20
JB
1486
1487 current_buffer = old_current_buffer;
1488
502b9b64 1489 /* compute_motion considers frame points past the end of a line
efb859b4
JB
1490 to be *after* the newline, i.e. at the start of the next line.
1491 This is reasonable, but not really what we want. So if the
1492 result is on a line below LINE, back it up one character. */
1493 if (posn->vpos > line)
1494 return posn->bufpos - 1;
1495 else
1496 return posn->bufpos;
4588ec20
JB
1497}
1498\f
1499static int
1500count_blanks (r)
1501 register GLYPH *r;
1502{
1503 register GLYPH *p = r;
94aa5d2d
RS
1504 while (*p++ == SPACEGLYPH);
1505 return p - r - 1;
4588ec20
JB
1506}
1507
1508static int
1509count_match (str1, str2)
1510 GLYPH *str1, *str2;
1511{
1512 register GLYPH *p1 = str1;
1513 register GLYPH *p2 = str2;
1514 while (*p1++ == *p2++);
1515 return p1 - str1 - 1;
1516}
1517
1518/* Char insertion/deletion cost vector, from term.c */
1519extern int *char_ins_del_vector;
1520
945807a3 1521#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
4588ec20
JB
1522
1523static void
502b9b64
JB
1524update_line (frame, vpos)
1525 register FRAME_PTR frame;
4588ec20
JB
1526 int vpos;
1527{
1528 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
60a8948a 1529 int *temp1;
4588ec20
JB
1530 int tem;
1531 int osp, nsp, begmatch, endmatch, olen, nlen;
1532 int save;
502b9b64
JB
1533 register struct frame_glyphs *current_frame
1534 = FRAME_CURRENT_GLYPHS (frame);
1535 register struct frame_glyphs *desired_frame
1536 = FRAME_DESIRED_GLYPHS (frame);
4588ec20 1537
502b9b64
JB
1538 if (desired_frame->highlight[vpos]
1539 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
4588ec20 1540 {
502b9b64
JB
1541 change_line_highlight (desired_frame->highlight[vpos], vpos,
1542 (current_frame->enable[vpos] ?
1543 current_frame->used[vpos] : 0));
1544 current_frame->enable[vpos] = 0;
4588ec20
JB
1545 }
1546 else
502b9b64 1547 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
4588ec20 1548
502b9b64 1549 if (! current_frame->enable[vpos])
4588ec20
JB
1550 {
1551 olen = 0;
1552 }
1553 else
1554 {
502b9b64
JB
1555 obody = current_frame->glyphs[vpos];
1556 olen = current_frame->used[vpos];
1557 if (! current_frame->highlight[vpos])
4588ec20
JB
1558 {
1559 if (!must_write_spaces)
1560 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1561 olen--;
1562 }
1563 else
1564 {
1565 /* For an inverse-video line, remember we gave it
502b9b64 1566 spaces all the way to the frame edge
4588ec20
JB
1567 so that the reverse video extends all the way across. */
1568
502b9b64 1569 while (olen < FRAME_WIDTH (frame) - 1)
4588ec20
JB
1570 obody[olen++] = SPACEGLYPH;
1571 }
1572 }
1573
1574 /* One way or another, this will enable the line being updated. */
502b9b64
JB
1575 current_frame->enable[vpos] = 1;
1576 current_frame->used[vpos] = desired_frame->used[vpos];
1577 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1578 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
4588ec20
JB
1579
1580#ifdef HAVE_X_WINDOWS
b6a65ac2 1581 if (FRAME_X_P (frame))
4588ec20 1582 {
502b9b64
JB
1583 current_frame->pix_width[vpos]
1584 = current_frame->used[vpos]
1585 * FONT_WIDTH (frame->display.x->font);
1586 current_frame->pix_height[vpos]
39d1fe00 1587 = frame->display.x->line_height;
4588ec20
JB
1588 }
1589#endif /* HAVE_X_WINDOWS */
1590
502b9b64 1591 if (!desired_frame->enable[vpos])
4588ec20
JB
1592 {
1593 nlen = 0;
1594 goto just_erase;
1595 }
1596
502b9b64
JB
1597 nbody = desired_frame->glyphs[vpos];
1598 nlen = desired_frame->used[vpos];
4588ec20
JB
1599
1600 /* Pretend trailing spaces are not there at all,
1601 unless for one reason or another we must write all spaces. */
502b9b64 1602 if (! desired_frame->highlight[vpos])
4588ec20
JB
1603 {
1604 if (!must_write_spaces)
1605 /* We know that the previous character byte contains 0. */
1606 while (nbody[nlen - 1] == SPACEGLYPH)
1607 nlen--;
1608 }
1609 else
1610 {
1611 /* For an inverse-video line, give it extra trailing spaces
502b9b64 1612 all the way to the frame edge
4588ec20
JB
1613 so that the reverse video extends all the way across. */
1614
502b9b64 1615 while (nlen < FRAME_WIDTH (frame) - 1)
4588ec20
JB
1616 nbody[nlen++] = SPACEGLYPH;
1617 }
1618
1619 /* If there's no i/d char, quickly do the best we can without it. */
1620 if (!char_ins_del_ok)
1621 {
1622 int i,j;
1623
76426794
RS
1624#if 0
1625 if (FRAME_X_P (frame))
1626 {
1627 /* Under X, erase everything we are going to rewrite,
1628 and rewrite everything from the first char that's changed.
1629 This is part of supporting fonts like Courier
1630 whose chars can overlap outside the char width. */
1631 for (i = 0; i < nlen; i++)
1632 if (i >= olen || nbody[i] != obody[i])
1633 break;
1634
1635 cursor_to (vpos, i);
1636 if (i != olen)
1637 clear_end_of_line (olen);
1638 write_glyphs (nbody + i, nlen - i);
1639 }
1640 else
1641 {}
1642#endif /* 0 */
4588ec20
JB
1643 for (i = 0; i < nlen; i++)
1644 {
1645 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1646 {
1647 cursor_to (vpos, i);
1648 for (j = 1; (i + j < nlen &&
1649 (i + j >= olen || nbody[i+j] != obody[i+j]));
1650 j++);
1651
1652 /* Output this run of non-matching chars. */
1653 write_glyphs (nbody + i, j);
1654 i += j - 1;
1655
1656 /* Now find the next non-match. */
1657 }
1658 }
1659
1660 /* Clear the rest of the line, or the non-clear part of it. */
1661 if (olen > nlen)
1662 {
1663 cursor_to (vpos, nlen);
1664 clear_end_of_line (olen);
1665 }
1666
502b9b64
JB
1667 /* Exchange contents between current_frame and new_frame. */
1668 temp = desired_frame->glyphs[vpos];
1669 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1670 current_frame->glyphs[vpos] = temp;
4588ec20 1671
60a8948a
RS
1672 /* Exchange charstarts between current_frame and new_frame. */
1673 temp1 = desired_frame->charstarts[vpos];
1674 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1675 current_frame->charstarts[vpos] = temp1;
1676
4588ec20
JB
1677 return;
1678 }
1679
1680 if (!olen)
1681 {
502b9b64 1682 nsp = (must_write_spaces || desired_frame->highlight[vpos])
4588ec20
JB
1683 ? 0 : count_blanks (nbody);
1684 if (nlen > nsp)
1685 {
1686 cursor_to (vpos, nsp);
1687 write_glyphs (nbody + nsp, nlen - nsp);
1688 }
1689
502b9b64
JB
1690 /* Exchange contents between current_frame and new_frame. */
1691 temp = desired_frame->glyphs[vpos];
1692 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1693 current_frame->glyphs[vpos] = temp;
4588ec20 1694
60a8948a
RS
1695 /* Exchange charstarts between current_frame and new_frame. */
1696 temp1 = desired_frame->charstarts[vpos];
1697 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1698 current_frame->charstarts[vpos] = temp1;
1699
4588ec20
JB
1700 return;
1701 }
1702
1703 obody[olen] = 1;
1704 save = nbody[nlen];
1705 nbody[nlen] = 0;
1706
1707 /* Compute number of leading blanks in old and new contents. */
1708 osp = count_blanks (obody);
502b9b64 1709 if (!desired_frame->highlight[vpos])
4588ec20
JB
1710 nsp = count_blanks (nbody);
1711 else
1712 nsp = 0;
1713
1714 /* Compute number of matching chars starting with first nonblank. */
1715 begmatch = count_match (obody + osp, nbody + nsp);
1716
1717 /* Spaces in new match implicit space past the end of old. */
1718 /* A bug causing this to be a no-op was fixed in 18.29. */
1719 if (!must_write_spaces && osp + begmatch == olen)
1720 {
1721 np1 = nbody + nsp;
1722 while (np1[begmatch] == SPACEGLYPH)
1723 begmatch++;
1724 }
1725
1726 /* Avoid doing insert/delete char
1727 just cause number of leading spaces differs
1728 when the following text does not match. */
1729 if (begmatch == 0 && osp != nsp)
1730 osp = nsp = min (osp, nsp);
1731
1732 /* Find matching characters at end of line */
1733 op1 = obody + olen;
1734 np1 = nbody + nlen;
1735 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1736 while (op1 > op2 && op1[-1] == np1[-1])
1737 {
1738 op1--;
1739 np1--;
1740 }
1741 endmatch = obody + olen - op1;
1742
1743 /* Put correct value back in nbody[nlen].
1744 This is important because direct_output_for_insert
1745 can write into the line at a later point.
1746 If this screws up the zero at the end of the line, re-establish it. */
1747 nbody[nlen] = save;
1748 obody[olen] = 0;
1749
1750 /* tem gets the distance to insert or delete.
1751 endmatch is how many characters we save by doing so.
1752 Is it worth it? */
1753
1754 tem = (nlen - nsp) - (olen - osp);
1755 if (endmatch && tem
502b9b64 1756 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
4588ec20
JB
1757 endmatch = 0;
1758
1759 /* nsp - osp is the distance to insert or delete.
1760 If that is nonzero, begmatch is known to be nonzero also.
1761 begmatch + endmatch is how much we save by doing the ins/del.
1762 Is it worth it? */
1763
1764 if (nsp != osp
1765 && (!char_ins_del_ok
502b9b64 1766 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
4588ec20
JB
1767 {
1768 begmatch = 0;
1769 endmatch = 0;
1770 osp = nsp = min (osp, nsp);
1771 }
1772
1773 /* Now go through the line, inserting, writing and
1774 deleting as appropriate. */
1775
1776 if (osp > nsp)
1777 {
1778 cursor_to (vpos, nsp);
1779 delete_glyphs (osp - nsp);
1780 }
1781 else if (nsp > osp)
1782 {
1783 /* If going to delete chars later in line
1784 and insert earlier in the line,
1785 must delete first to avoid losing data in the insert */
1786 if (endmatch && nlen < olen + nsp - osp)
1787 {
1788 cursor_to (vpos, nlen - endmatch + osp - nsp);
1789 delete_glyphs (olen + nsp - osp - nlen);
1790 olen = nlen - (nsp - osp);
1791 }
1792 cursor_to (vpos, osp);
1793 insert_glyphs ((char *)0, nsp - osp);
1794 }
1795 olen += nsp - osp;
1796
1797 tem = nsp + begmatch + endmatch;
1798 if (nlen != tem || olen != tem)
1799 {
1800 cursor_to (vpos, nsp + begmatch);
1801 if (!endmatch || nlen == olen)
1802 {
1803 /* If new text being written reaches right margin,
1804 there is no need to do clear-to-eol at the end.
1805 (and it would not be safe, since cursor is not
1806 going to be "at the margin" after the text is done) */
502b9b64 1807 if (nlen == FRAME_WIDTH (frame))
4588ec20
JB
1808 olen = 0;
1809 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1810
1811#ifdef obsolete
1812
1813/* the following code loses disastrously if tem == nlen.
1814 Rather than trying to fix that case, I am trying the simpler
1815 solution found above. */
1816
1817 /* If the text reaches to the right margin,
1818 it will lose one way or another (depending on AutoWrap)
1819 to clear to end of line after outputting all the text.
1820 So pause with one character to go and clear the line then. */
502b9b64 1821 if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
4588ec20
JB
1822 {
1823 /* endmatch must be zero, and tem must equal nsp + begmatch */
1824 write_glyphs (nbody + tem, nlen - tem - 1);
1825 clear_end_of_line (olen);
1826 olen = 0; /* Don't let it be cleared again later */
1827 write_glyphs (nbody + nlen - 1, 1);
1828 }
1829 else
1830 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1831#endif /* OBSOLETE */
1832
1833 }
1834 else if (nlen > olen)
1835 {
1836 write_glyphs (nbody + nsp + begmatch, olen - tem);
1837 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1838 olen = nlen;
1839 }
1840 else if (olen > nlen)
1841 {
1842 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1843 delete_glyphs (olen - nlen);
1844 olen = nlen;
1845 }
1846 }
1847
1848 just_erase:
1849 /* If any unerased characters remain after the new line, erase them. */
1850 if (olen > nlen)
1851 {
1852 cursor_to (vpos, nlen);
1853 clear_end_of_line (olen);
1854 }
1855
502b9b64
JB
1856 /* Exchange contents between current_frame and new_frame. */
1857 temp = desired_frame->glyphs[vpos];
1858 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1859 current_frame->glyphs[vpos] = temp;
60a8948a
RS
1860
1861 /* Exchange charstarts between current_frame and new_frame. */
1862 temp1 = desired_frame->charstarts[vpos];
1863 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1864 current_frame->charstarts[vpos] = temp1;
4588ec20
JB
1865}
1866\f
267ad509 1867/* A vector of size >= NFRAMES + 3 * NBUFFERS + 1, containing the session's
078b3696
KH
1868 frames, buffers, buffer-read-only flags, and buffer-modified-flags,
1869 and a trailing sentinel (so we don't need to add length checks). */
1870static Lisp_Object frame_and_buffer_state;
1871
1872DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
1873 Sframe_or_buffer_changed_p, 0, 0, 0,
1874 "Return non-nil if the frame and buffer state appears to have changed.\n\
1875The state variable is an internal vector containing all frames and buffers,\n\
1876along with the buffers' read-only and modified flags, which allows a fast\n\
1877check to see whether the menu bars might need to be recomputed.\n\
1878If this function returns non-nil, it updates the internal vector to reflect\n\
1879the current state.\n")
1880 ()
1881{
1882 Lisp_Object tail, frame, buf;
1883 Lisp_Object *vecp;
1884 int n;
1885 vecp = XVECTOR (frame_and_buffer_state)->contents;
1886 FOR_EACH_FRAME (tail, frame)
1887 if (!EQ (*vecp++, frame))
1888 goto changed;
50cf83f8
RS
1889 /* Check that the buffer info matches.
1890 No need to test for the end of the vector
1891 because the last element of the vector is lambda
1892 and that will always cause a mismatch. */
078b3696
KH
1893 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1894 {
1895 buf = XCONS (XCONS (tail)->car)->cdr;
1896 if (!EQ (*vecp++, buf))
1897 goto changed;
1898 if (!EQ (*vecp++, XBUFFER (buf)->read_only))
1899 goto changed;
1900 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
1901 goto changed;
1902 }
50cf83f8
RS
1903 /* Detect deletion of a buffer at the end of the list. */
1904 if (*vecp == Qlambda)
1905 return Qnil;
078b3696 1906 changed:
50cf83f8 1907 /* Start with 1 so there is room for at least on lambda at the end. */
078b3696
KH
1908 n = 1;
1909 FOR_EACH_FRAME (tail, frame)
1910 n++;
1911 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1912 n += 3;
267ad509
KH
1913 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
1914 if (n > XVECTOR (frame_and_buffer_state)->size
1915 || n < XVECTOR (frame_and_buffer_state)->size / 2)
1916 frame_and_buffer_state = Fmake_vector (make_number (n), Qlambda);
078b3696
KH
1917 vecp = XVECTOR (frame_and_buffer_state)->contents;
1918 FOR_EACH_FRAME (tail, frame)
1919 *vecp++ = frame;
1920 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1921 {
1922 buf = XCONS (XCONS (tail)->car)->cdr;
1923 *vecp++ = buf;
1924 *vecp++ = XBUFFER (buf)->read_only;
1925 *vecp++ = Fbuffer_modified_p (buf);
1926 }
267ad509
KH
1927 /* If we left any slack in the vector, fill it up now. */
1928 for (; n < XVECTOR (frame_and_buffer_state)->size; ++n)
1929 *vecp++ = Qlambda;
078b3696
KH
1930 return Qt;
1931}
1932\f
4588ec20
JB
1933DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1934 1, 1, "FOpen termscript file: ",
1935 "Start writing all terminal output to FILE as well as the terminal.\n\
1936FILE = nil means just close any termscript file currently open.")
1937 (file)
1938 Lisp_Object file;
1939{
1940 if (termscript != 0) fclose (termscript);
1941 termscript = 0;
1942
efb859b4 1943 if (! NILP (file))
4588ec20
JB
1944 {
1945 file = Fexpand_file_name (file, Qnil);
1946 termscript = fopen (XSTRING (file)->data, "w");
1947 if (termscript == 0)
1948 report_file_error ("Opening termscript", Fcons (file, Qnil));
1949 }
1950 return Qnil;
1951}
1952\f
1953
1954#ifdef SIGWINCH
efb859b4 1955SIGTYPE
4588ec20
JB
1956window_change_signal ()
1957{
1958 int width, height;
1959 extern int errno;
1960 int old_errno = errno;
1961
502b9b64 1962 get_frame_size (&width, &height);
4588ec20 1963
502b9b64
JB
1964 /* The frame size change obviously applies to a termcap-controlled
1965 frame. Find such a frame in the list, and assume it's the only
4588ec20 1966 one (since the redisplay code always writes to stdout, not a
502b9b64 1967 FILE * specified in the frame structure). Record the new size,
4588ec20
JB
1968 but don't reallocate the data structures now. Let that be done
1969 later outside of the signal handler. */
1970
1971 {
35f56f96 1972 Lisp_Object tail, frame;
4588ec20 1973
35f56f96 1974 FOR_EACH_FRAME (tail, frame)
4588ec20 1975 {
35f56f96 1976 if (FRAME_TERMCAP_P (XFRAME (frame)))
4588ec20 1977 {
35f56f96 1978 change_frame_size (XFRAME (frame), height, width, 0, 1);
4588ec20
JB
1979 break;
1980 }
1981 }
1982 }
1983
1984 signal (SIGWINCH, window_change_signal);
1985 errno = old_errno;
1986}
1987#endif /* SIGWINCH */
1988
1989
502b9b64 1990/* Do any change in frame size that was requested by a signal. */
4588ec20
JB
1991
1992do_pending_window_change ()
1993{
1994 /* If window_change_signal should have run before, run it now. */
1995 while (delayed_size_change)
1996 {
35f56f96 1997 Lisp_Object tail, frame;
4588ec20
JB
1998
1999 delayed_size_change = 0;
2000
35f56f96 2001 FOR_EACH_FRAME (tail, frame)
4588ec20 2002 {
35f56f96
JB
2003 FRAME_PTR f = XFRAME (frame);
2004
502b9b64
JB
2005 int height = FRAME_NEW_HEIGHT (f);
2006 int width = FRAME_NEW_WIDTH (f);
4588ec20 2007
08f7aa3e 2008 if (height != 0 || width != 0)
b6a65ac2 2009 change_frame_size (f, height, width, 0, 0);
4588ec20
JB
2010 }
2011 }
2012}
2013
2014
502b9b64 2015/* Change the frame height and/or width. Values may be given as zero to
b6a65ac2 2016 indicate no change is to take place.
4588ec20 2017
b6a65ac2
JB
2018 If DELAY is non-zero, then assume we're being called from a signal
2019 handler, and queue the change for later - perhaps the next
2020 redisplay. Since this tries to resize windows, we can't call it
2021 from a signal handler. */
2022
2023change_frame_size (frame, newheight, newwidth, pretend, delay)
502b9b64 2024 register FRAME_PTR frame;
b6a65ac2 2025 int newheight, newwidth, pretend;
4588ec20
JB
2026{
2027 /* If we can't deal with the change now, queue it for later. */
b6a65ac2 2028 if (delay)
4588ec20 2029 {
b6a65ac2 2030 FRAME_NEW_HEIGHT (frame) = newheight;
502b9b64 2031 FRAME_NEW_WIDTH (frame) = newwidth;
4588ec20
JB
2032 delayed_size_change = 1;
2033 return;
2034 }
2035
502b9b64
JB
2036 /* This size-change overrides any pending one for this frame. */
2037 FRAME_NEW_HEIGHT (frame) = 0;
b6a65ac2
JB
2038 FRAME_NEW_WIDTH (frame) = 0;
2039
08f7aa3e 2040 /* If an argument is zero, set it to the current value. */
b6a65ac2
JB
2041 newheight || (newheight = FRAME_HEIGHT (frame));
2042 newwidth || (newwidth = FRAME_WIDTH (frame));
4588ec20 2043
b6a65ac2
JB
2044 /* Round up to the smallest acceptable size. */
2045 check_frame_size (frame, &newheight, &newwidth);
2046
2047 /* If we're not changing the frame size, quit now. */
2048 if (newheight == FRAME_HEIGHT (frame)
2049 && newwidth == FRAME_WIDTH (frame))
4588ec20
JB
2050 return;
2051
b6a65ac2 2052 if (newheight != FRAME_HEIGHT (frame))
4588ec20 2053 {
b6a65ac2 2054 if (FRAME_HAS_MINIBUF_P (frame)
502b9b64 2055 && ! FRAME_MINIBUF_ONLY_P (frame))
4588ec20 2056 {
502b9b64
JB
2057 /* Frame has both root and minibuffer. */
2058 set_window_height (FRAME_ROOT_WINDOW (frame),
cb470ab1 2059 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
a5d8b611
KH
2060 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
2061 newheight - 1);
502b9b64 2062 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
4588ec20
JB
2063 }
2064 else
502b9b64 2065 /* Frame has just one top-level window. */
cb470ab1
RS
2066 set_window_height (FRAME_ROOT_WINDOW (frame),
2067 newheight - FRAME_MENU_BAR_LINES (frame), 0);
b6a65ac2
JB
2068
2069 if (FRAME_TERMCAP_P (frame) && !pretend)
2070 FrameRows = newheight;
4588ec20
JB
2071
2072#if 0
502b9b64 2073 if (frame->output_method == output_termcap)
4588ec20 2074 {
b6a65ac2 2075 frame_height = newheight;
4588ec20 2076 if (!pretend)
b6a65ac2 2077 FrameRows = newheight;
4588ec20
JB
2078 }
2079#endif
2080 }
2081
b6a65ac2 2082 if (newwidth != FRAME_WIDTH (frame))
4588ec20 2083 {
502b9b64 2084 set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
b6a65ac2 2085 if (FRAME_HAS_MINIBUF_P (frame))
502b9b64 2086 set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
4588ec20 2087
b6a65ac2 2088 if (FRAME_TERMCAP_P (frame) && !pretend)
502b9b64 2089 FrameCols = newwidth;
4588ec20 2090#if 0
502b9b64 2091 if (frame->output_method == output_termcap)
4588ec20 2092 {
502b9b64 2093 frame_width = newwidth;
4588ec20 2094 if (!pretend)
502b9b64 2095 FrameCols = newwidth;
4588ec20
JB
2096 }
2097#endif
2098 }
2099
b6a65ac2
JB
2100 FRAME_HEIGHT (frame) = newheight;
2101 FRAME_WIDTH (frame) = newwidth;
986e61b8
RS
2102
2103 if (FRAME_CURSOR_X (frame) >= FRAME_WIDTH (frame))
2104 FRAME_CURSOR_X (frame) = FRAME_WIDTH (frame) - 1;
2105 if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
2106 FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
2107
502b9b64
JB
2108 remake_frame_glyphs (frame);
2109 calculate_costs (frame);
4588ec20
JB
2110}
2111\f
2112DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2113 Ssend_string_to_terminal, 1, 1, 0,
2114 "Send STRING to the terminal without alteration.\n\
2115Control characters in STRING will have terminal-dependent effects.")
2116 (str)
2117 Lisp_Object str;
2118{
2119 CHECK_STRING (str, 0);
2120 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
2121 fflush (stdout);
2122 if (termscript)
2123 {
2124 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
2125 fflush (termscript);
2126 }
2127 return Qnil;
2128}
2129
2130DEFUN ("ding", Fding, Sding, 0, 1, 0,
2131 "Beep, or flash the screen.\n\
2132Also, unless an argument is given,\n\
2133terminate any keyboard macro currently executing.")
2134 (arg)
2135 Lisp_Object arg;
2136{
efb859b4 2137 if (!NILP (arg))
4588ec20 2138 {
7fa788da
RS
2139 if (noninteractive)
2140 putchar (07);
2141 else
2142 ring_bell ();
4588ec20
JB
2143 fflush (stdout);
2144 }
2145 else
2146 bitch_at_user ();
2147
2148 return Qnil;
2149}
2150
2151bitch_at_user ()
2152{
2153 if (noninteractive)
2154 putchar (07);
2155 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2156 error ("Keyboard macro terminated by a command ringing the bell");
2157 else
2158 ring_bell ();
2159 fflush (stdout);
2160}
2161
2162DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
767229f8 2163 "Pause, without updating display, for SECONDS seconds.\n\
b07646f5
JB
2164SECONDS may be a floating-point value, meaning that you can wait for a\n\
2165fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2166additional wait period, in milliseconds; this may be useful if your\n\
2167Emacs was built without floating point support.\n\
2168\(Not all operating systems support waiting for a fraction of a second.)")
767229f8
JB
2169 (seconds, milliseconds)
2170 Lisp_Object seconds, milliseconds;
4588ec20 2171{
767229f8 2172 int sec, usec;
4588ec20 2173
767229f8 2174 if (NILP (milliseconds))
e9c9a718 2175 XSETINT (milliseconds, 0);
767229f8
JB
2176 else
2177 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
2178 usec = XINT (milliseconds) * 1000;
2179
2180#ifdef LISP_FLOAT_TYPE
2181 {
2182 double duration = extract_float (seconds);
2183 sec = (int) duration;
2184 usec += (duration - sec) * 1000000;
2185 }
2186#else
2187 CHECK_NUMBER (seconds, 0);
2188 sec = XINT (seconds);
2189#endif
4588ec20 2190
a41f8bed 2191#ifndef EMACS_HAS_USECS
767229f8
JB
2192 if (sec == 0 && usec != 0)
2193 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
4588ec20 2194#endif
767229f8
JB
2195
2196 /* Assure that 0 <= usec < 1000000. */
2197 if (usec < 0)
2198 {
2199 /* We can't rely on the rounding being correct if user is negative. */
2200 if (-1000000 < usec)
2201 sec--, usec += 1000000;
2202 else
2203 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
4588ec20 2204 }
767229f8
JB
2205 else
2206 sec += usec / 1000000, usec %= 1000000;
2207
5c48f0da 2208 if (sec <= 0)
767229f8 2209 return Qnil;
4588ec20 2210
f76475ad
JB
2211 {
2212 Lisp_Object zero;
2213
a5d8b611 2214 XSETFASTINT (zero, 0);
f76475ad
JB
2215 wait_reading_process_input (sec, usec, zero, 0);
2216 }
d1af74e9 2217
767229f8
JB
2218 /* We should always have wait_reading_process_input; we have a dummy
2219 implementation for systems which don't support subprocesses. */
2220#if 0
2221 /* No wait_reading_process_input */
4588ec20
JB
2222 immediate_quit = 1;
2223 QUIT;
2224
2225#ifdef VMS
2226 sys_sleep (sec);
2227#else /* not VMS */
2228/* The reason this is done this way
2229 (rather than defined (H_S) && defined (H_T))
2230 is because the VMS preprocessor doesn't grok `defined' */
2231#ifdef HAVE_SELECT
a41f8bed
JB
2232 EMACS_GET_TIME (end_time);
2233 EMACS_SET_SECS_USECS (timeout, sec, usec);
d1af74e9 2234 EMACS_ADD_TIME (end_time, end_time, timeout);
a41f8bed 2235
4588ec20
JB
2236 while (1)
2237 {
a41f8bed
JB
2238 EMACS_GET_TIME (timeout);
2239 EMACS_SUB_TIME (timeout, end_time, timeout);
2240 if (EMACS_TIME_NEG_P (timeout)
2241 || !select (1, 0, 0, 0, &timeout))
4588ec20
JB
2242 break;
2243 }
4588ec20
JB
2244#else /* not HAVE_SELECT */
2245 sleep (sec);
2246#endif /* HAVE_SELECT */
2247#endif /* not VMS */
2248
2249 immediate_quit = 0;
2250#endif /* no subprocesses */
2251
2252 return Qnil;
2253}
2254
f76475ad
JB
2255/* This is just like wait_reading_process_input, except that
2256 it does the redisplay.
2257
ea0d86af
RS
2258 It's also much like Fsit_for, except that it can be used for
2259 waiting for input as well. One differnce is that sit_for
2260 does not call prepare_menu_bars; Fsit_for does call that. */
4588ec20 2261
f76475ad
JB
2262Lisp_Object
2263sit_for (sec, usec, reading, display)
2264 int sec, usec, reading, display;
2265{
2266 Lisp_Object read_kbd;
4588ec20
JB
2267
2268 if (detect_input_pending ())
2269 return Qnil;
4588ec20 2270
f76475ad
JB
2271 if (display)
2272 redisplay_preserve_echo_area ();
4588ec20 2273
dfdb645c
JB
2274 if (sec == 0 && usec == 0)
2275 return Qt;
2276
4588ec20 2277#ifdef SIGIO
8fc798e9 2278 gobble_input (0);
f76475ad
JB
2279#endif
2280
e9c9a718 2281 XSETINT (read_kbd, reading ? -1 : 1);
f76475ad
JB
2282 wait_reading_process_input (sec, usec, read_kbd, display);
2283
d1af74e9 2284
500ab754
JB
2285 /* wait_reading_process_input should always be available now; it is
2286 simulated in a simple way on systems that don't support
2287 subprocesses. */
2288#if 0
2289 /* No wait_reading_process_input available. */
4588ec20
JB
2290 immediate_quit = 1;
2291 QUIT;
2292
2293 waitchannels = 1;
2294#ifdef VMS
f76475ad 2295 input_wait_timeout (XINT (arg));
4588ec20 2296#else /* not VMS */
d1af74e9
JB
2297#ifndef HAVE_TIMEVAL
2298 timeout_sec = sec;
2299 select (1, &waitchannels, 0, 0, &timeout_sec);
2300#else /* HAVE_TIMEVAL */
2301 timeout.tv_sec = sec;
2302 timeout.tv_usec = usec;
4588ec20 2303 select (1, &waitchannels, 0, 0, &timeout);
d1af74e9 2304#endif /* HAVE_TIMEVAL */
4588ec20
JB
2305#endif /* not VMS */
2306
2307 immediate_quit = 0;
d1af74e9 2308#endif
4588ec20
JB
2309
2310 return detect_input_pending () ? Qnil : Qt;
2311}
2312
f76475ad 2313DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
767229f8 2314 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
b07646f5
JB
2315SECONDS may be a floating-point value, meaning that you can wait for a\n\
2316fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2317additional wait period, in milliseconds; this may be useful if your\n\
2318Emacs was built without floating point support.\n\
2319\(Not all operating systems support waiting for a fraction of a second.)\n\
f76475ad
JB
2320Optional third arg non-nil means don't redisplay, just wait for input.\n\
2321Redisplay is preempted as always if input arrives, and does not happen\n\
2322if input is available before it starts.\n\
2323Value is t if waited the full time with no input arriving.")
767229f8
JB
2324 (seconds, milliseconds, nodisp)
2325 Lisp_Object seconds, milliseconds, nodisp;
f76475ad 2326{
767229f8 2327 int sec, usec;
f76475ad 2328
767229f8 2329 if (NILP (milliseconds))
e9c9a718 2330 XSETINT (milliseconds, 0);
767229f8
JB
2331 else
2332 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
2333 usec = XINT (milliseconds) * 1000;
2334
2335#ifdef LISP_FLOAT_TYPE
2336 {
2337 double duration = extract_float (seconds);
2338 sec = (int) duration;
2339 usec += (duration - sec) * 1000000;
2340 }
2341#else
2342 CHECK_NUMBER (seconds, 0);
2343 sec = XINT (seconds);
2344#endif
f76475ad 2345
f76475ad 2346#ifndef EMACS_HAS_USECS
767229f8
JB
2347 if (usec != 0 && sec == 0)
2348 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
f76475ad 2349#endif
f76475ad 2350
ea0d86af
RS
2351 if (NILP (nodisp))
2352 prepare_menu_bars ();
f76475ad
JB
2353 return sit_for (sec, usec, 0, NILP (nodisp));
2354}
4588ec20
JB
2355\f
2356char *terminal_type;
2357
2358/* Initialization done when Emacs fork is started, before doing stty. */
2359/* Determine terminal type and set terminal_driver */
2360/* Then invoke its decoding routine to set up variables
2361 in the terminal package */
2362
2363init_display ()
2364{
2365#ifdef HAVE_X_WINDOWS
2366 extern int display_arg;
2367#endif
2368
2369 meta_key = 0;
2370 inverse_video = 0;
2371 cursor_in_echo_area = 0;
2372 terminal_type = (char *) 0;
2373
1315c181
JB
2374 /* Now is the time to initialize this; it's used by init_sys_modes
2375 during startup. */
2376 Vwindow_system = Qnil;
4588ec20 2377
1315c181
JB
2378 /* If the user wants to use a window system, we shouldn't bother
2379 initializing the terminal. This is especially important when the
2380 terminal is so dumb that emacs gives up before and doesn't bother
2381 using the window system.
4588ec20 2382
1315c181
JB
2383 If the DISPLAY environment variable is set, try to use X, and die
2384 with an error message if that doesn't work. */
4588ec20
JB
2385
2386#ifdef HAVE_X_WINDOWS
d460af17
JB
2387 if (! display_arg)
2388 {
2389#ifdef VMS
5de9f849 2390 display_arg = (getenv ("DECW$DISPLAY") != 0);
d460af17 2391#else
5de9f849 2392 display_arg = (getenv ("DISPLAY") != 0);
d460af17 2393#endif
f040093a 2394 }
d460af17
JB
2395
2396 if (!inhibit_window_system && display_arg)
4588ec20
JB
2397 {
2398 Vwindow_system = intern ("x");
2399#ifdef HAVE_X11
2400 Vwindow_system_version = make_number (11);
2401#else
2402 Vwindow_system_version = make_number (10);
2403#endif
2404 return;
2405 }
2406#endif /* HAVE_X_WINDOWS */
2407
2408 /* If no window system has been specified, try to use the terminal. */
2409 if (! isatty (0))
2410 {
2411 fprintf (stderr, "emacs: standard input is not a tty\n");
2412 exit (1);
2413 }
2414
2415 /* Look at the TERM variable */
2416 terminal_type = (char *) getenv ("TERM");
2417 if (!terminal_type)
2418 {
2419#ifdef VMS
2420 fprintf (stderr, "Please specify your terminal type.\n\
2421For types defined in VMS, use set term /device=TYPE.\n\
2422For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2423\(The quotation marks are necessary since terminal types are lower case.)\n");
2424#else
2425 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2426#endif
2427 exit (1);
2428 }
2429
2430#ifdef VMS
2431 /* VMS DCL tends to upcase things, so downcase term type.
2432 Hardly any uppercase letters in terminal types; should be none. */
2433 {
2434 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2435 char *p;
2436
2437 strcpy (new, terminal_type);
2438
2439 for (p = new; *p; p++)
2440 if (isupper (*p))
2441 *p = tolower (*p);
2442
2443 terminal_type = new;
2444 }
2445#endif
2446
2447 term_init (terminal_type);
2448
502b9b64
JB
2449 remake_frame_glyphs (selected_frame);
2450 calculate_costs (selected_frame);
4588ec20
JB
2451
2452 /* X and Y coordinates of the cursor between updates. */
502b9b64
JB
2453 FRAME_CURSOR_X (selected_frame) = 0;
2454 FRAME_CURSOR_Y (selected_frame) = 0;
4588ec20
JB
2455
2456#ifdef SIGWINCH
2457#ifndef CANNOT_DUMP
2458 if (initialized)
2459#endif /* CANNOT_DUMP */
2460 signal (SIGWINCH, window_change_signal);
2461#endif /* SIGWINCH */
2462}
2463\f
2464syms_of_display ()
2465{
502b9b64
JB
2466#ifdef MULTI_FRAME
2467 defsubr (&Sredraw_frame);
4588ec20
JB
2468#endif
2469 defsubr (&Sredraw_display);
078b3696 2470 defsubr (&Sframe_or_buffer_changed_p);
4588ec20
JB
2471 defsubr (&Sopen_termscript);
2472 defsubr (&Sding);
2473 defsubr (&Ssit_for);
2474 defsubr (&Ssleep_for);
2475 defsubr (&Ssend_string_to_terminal);
2476
078b3696
KH
2477 frame_and_buffer_state = Fmake_vector (make_number (1), Qlambda);
2478 staticpro (&frame_and_buffer_state);
2479
4588ec20 2480 DEFVAR_INT ("baud-rate", &baud_rate,
eb285955 2481 "*The output baud rate of the terminal.\n\
4588ec20
JB
2482On most systems, changing this value will affect the amount of padding\n\
2483and the other strategic decisions made during redisplay.");
2484 DEFVAR_BOOL ("inverse-video", &inverse_video,
502b9b64 2485 "*Non-nil means invert the entire frame display.\n\
4588ec20
JB
2486This means everything is in inverse video which otherwise would not be.");
2487 DEFVAR_BOOL ("visible-bell", &visible_bell,
502b9b64 2488 "*Non-nil means try to flash the frame to represent a bell.");
4588ec20 2489 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
502b9b64 2490 "*Non-nil means no need to redraw entire frame after suspending.\n\
4588ec20 2491A non-nil value is useful if the terminal can automatically preserve\n\
502b9b64 2492Emacs's frame display when you reenter Emacs.\n\
4588ec20
JB
2493It is up to you to set this variable if your terminal can do that.");
2494 DEFVAR_LISP ("window-system", &Vwindow_system,
2495 "A symbol naming the window-system under which Emacs is running\n\
2496\(such as `x'), or nil if emacs is running on an ordinary terminal.");
2497 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2498 "The version number of the window system in use.\n\
2499For X windows, this is 10 or 11.");
2500 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2501 "Non-nil means put cursor in minibuffer, at end of any message there.");
2502 DEFVAR_LISP ("glyph-table", &Vglyph_table,
502b9b64 2503 "Table defining how to output a glyph code to the frame.\n\
4588ec20
JB
2504If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2505Each element can be:\n\
2506 integer: a glyph code which this glyph is an alias for.\n\
2507 string: output this glyph using that string (not impl. in X windows).\n\
2508 nil: this glyph mod 256 is char code to output,\n\
6666f05a 2509 and this glyph / 256 is face code for X windows (see `face-id').");
4588ec20
JB
2510 Vglyph_table = Qnil;
2511
2512 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2513 "Display table to use for buffers that specify none.\n\
2514See `buffer-display-table' for more information.");
2515 Vstandard_display_table = Qnil;
2516
2517 /* Initialize `window-system', unless init_display already decided it. */
2518#ifdef CANNOT_DUMP
2519 if (noninteractive)
2520#endif
2521 {
2522 Vwindow_system = Qnil;
2523 Vwindow_system_version = Qnil;
2524 }
2525}