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