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