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