* xfaces.c (unload_color): Don't #include <X11/Intrinsic.h>,
[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
502b9b64 958 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
959
960 detect_input_pending ();
961 if (input_pending && !force)
962 {
963 pause = 1;
964 goto do_pause;
965 }
966
502b9b64 967 update_begin (f);
4588ec20
JB
968
969 if (!line_ins_del_ok)
970 inhibit_hairy_id = 1;
971
efb859b4
JB
972 /* See if any of the desired lines are enabled; don't compute for
973 i/d line if just want cursor motion. */
502b9b64
JB
974 for (i = 0; i < FRAME_HEIGHT (f); i++)
975 if (desired_frame->enable[i])
4588ec20
JB
976 break;
977
978 /* Try doing i/d line, if not yet inhibited. */
502b9b64
JB
979 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
980 force |= scrolling (f);
4588ec20
JB
981
982 /* Update the individual lines as needed. Do bottom line first. */
983
502b9b64
JB
984 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
985 update_line (f, FRAME_HEIGHT (f) - 1);
4588ec20
JB
986
987#ifdef HAVE_X_WINDOWS
b6a65ac2 988 if (FRAME_X_P (f))
4588ec20 989 {
502b9b64
JB
990 leftmost = downto = f->display.x->internal_border_width;
991 if (desired_frame->enable[0])
4588ec20 992 {
502b9b64
JB
993 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
994 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
995 = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
448fd7c0 996 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
502b9b64
JB
997 current_frame->top_left_x[0] = leftmost;
998 current_frame->top_left_y[0] = downto;
4588ec20
JB
999 }
1000 }
1001#endif /* HAVE_X_WINDOWS */
1002
1003 /* Now update the rest of the lines. */
502b9b64 1004 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
4588ec20 1005 {
502b9b64 1006 if (desired_frame->enable[i])
4588ec20 1007 {
b6a65ac2 1008 if (FRAME_TERMCAP_P (f))
4588ec20
JB
1009 {
1010 /* Flush out every so many lines.
1011 Also flush out if likely to have more than 1k buffered
1012 otherwise. I'm told that some telnet connections get
1013 really screwed by more than 1k output at once. */
1014 int outq = PENDING_OUTPUT_COUNT (stdout);
1015 if (outq > 900
1016 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1017 {
1018 fflush (stdout);
1019 if (preempt_count == 1)
1020 {
a41f8bed
JB
1021#ifdef EMACS_OUTQSIZE
1022 if (EMACS_OUTQSIZE (0, &outq) < 0)
4588ec20
JB
1023 /* Probably not a tty. Ignore the error and reset
1024 * the outq count. */
1025 outq = PENDING_OUTPUT_COUNT (stdout);
1026#endif
1027 outq *= 10;
1028 sleep (outq / baud_rate);
1029 }
1030 }
1031 if ((i - 1) % preempt_count == 0)
1032 detect_input_pending ();
1033 }
1034
502b9b64 1035 update_line (f, i);
4588ec20 1036#ifdef HAVE_X_WINDOWS
b6a65ac2 1037 if (FRAME_X_P (f))
4588ec20 1038 {
502b9b64
JB
1039 current_frame->top_left_y[i] = downto;
1040 current_frame->top_left_x[i] = leftmost;
4588ec20
JB
1041 }
1042#endif /* HAVE_X_WINDOWS */
1043 }
1044
e5d77022 1045#ifdef HAVE_X_WINDOWS
b6a65ac2 1046 if (FRAME_X_P (f))
448fd7c0 1047 downto += current_frame->pix_height[i];
e5d77022 1048#endif
4588ec20 1049 }
502b9b64 1050 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
4588ec20
JB
1051
1052 /* Now just clean up termcap drivers and set cursor, etc. */
1053 if (!pause)
1054 {
648fa17d
JB
1055 if (cursor_in_echo_area
1056 && FRAME_HAS_MINIBUF_P (f))
1113d9db 1057 {
648fa17d
JB
1058 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1059 int row, col;
1060
1061 if (cursor_in_echo_area < 0)
1062 {
1063 row = top;
1064 col = 0;
1065 }
1113d9db 1066 else
648fa17d
JB
1067 {
1068 /* If the minibuffer is several lines high, find the last
1069 line that has any text on it. */
1070 row = FRAME_HEIGHT (f);
1071 do
1072 {
1073 row--;
1074 if (current_frame->enable[row])
1075 col = current_frame->used[row];
1076 else
1077 col = 0;
1078 }
1079 while (row > top && col == 0);
1080
1081 if (col >= FRAME_WIDTH (f))
1082 {
1083 col = 0;
1084 if (row < FRAME_HEIGHT (f) - 1)
1085 row++;
1086 }
1087 }
1088
1089 cursor_to (row, col);
1113d9db 1090 }
4588ec20 1091 else
502b9b64
JB
1092 cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
1093 FRAME_WIDTH (f) - 1), 0));
4588ec20
JB
1094 }
1095
502b9b64 1096 update_end (f);
4588ec20
JB
1097
1098 if (termscript)
1099 fflush (termscript);
1100 fflush (stdout);
1101
1102 /* Here if output is preempted because input is detected. */
1103 do_pause:
1104
502b9b64 1105 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1106 display_completed = !pause;
1107
502b9b64 1108 bzero (desired_frame->enable, FRAME_HEIGHT (f));
4588ec20
JB
1109 return pause;
1110}
1111
1112/* Called when about to quit, to check for doing so
1113 at an improper time. */
1114
1115void
1116quit_error_check ()
1117{
502b9b64 1118 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
4588ec20 1119 return;
502b9b64 1120 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
4588ec20 1121 abort ();
502b9b64 1122 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
4588ec20
JB
1123 abort ();
1124}
1125\f
1126/* Decide what insert/delete line to do, and do it */
1127
1128extern void scrolling_1 ();
1129
502b9b64
JB
1130scrolling (frame)
1131 FRAME_PTR frame;
4588ec20
JB
1132{
1133 int unchanged_at_top, unchanged_at_bottom;
1134 int window_size;
1135 int changed_lines;
502b9b64
JB
1136 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1137 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1138 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
4588ec20 1139 register int i;
502b9b64
JB
1140 int free_at_end_vpos = FRAME_HEIGHT (frame);
1141 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1142 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
1143
1144 /* Compute hash codes of all the lines.
1145 Also calculate number of changed lines,
1146 number of unchanged lines at the beginning,
1147 and number of unchanged lines at the end. */
1148
1149 changed_lines = 0;
1150 unchanged_at_top = 0;
502b9b64
JB
1151 unchanged_at_bottom = FRAME_HEIGHT (frame);
1152 for (i = 0; i < FRAME_HEIGHT (frame); i++)
4588ec20
JB
1153 {
1154 /* Give up on this scrolling if some old lines are not enabled. */
502b9b64 1155 if (!current_frame->enable[i])
4588ec20 1156 return 0;
502b9b64
JB
1157 old_hash[i] = line_hash_code (current_frame, i);
1158 if (! desired_frame->enable[i])
4588ec20
JB
1159 new_hash[i] = old_hash[i];
1160 else
502b9b64 1161 new_hash[i] = line_hash_code (desired_frame, i);
4588ec20
JB
1162
1163 if (old_hash[i] != new_hash[i])
1164 {
1165 changed_lines++;
502b9b64 1166 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
4588ec20
JB
1167 }
1168 else if (i == unchanged_at_top)
1169 unchanged_at_top++;
502b9b64 1170 draw_cost[i] = line_draw_cost (desired_frame, i);
4588ec20
JB
1171 }
1172
1173 /* If changed lines are few, don't allow preemption, don't scroll. */
1174 if (changed_lines < baud_rate / 2400
502b9b64 1175 || unchanged_at_bottom == FRAME_HEIGHT (frame))
4588ec20
JB
1176 return 1;
1177
502b9b64 1178 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
4588ec20
JB
1179 - unchanged_at_bottom);
1180
1181 if (scroll_region_ok)
1182 free_at_end_vpos -= unchanged_at_bottom;
502b9b64 1183 else if (memory_below_frame)
4588ec20
JB
1184 free_at_end_vpos = -1;
1185
1186 /* If large window, fast terminal and few lines in common between
502b9b64 1187 current frame and desired frame, don't bother with i/d calc. */
4588ec20
JB
1188 if (window_size >= 18 && baud_rate > 2400
1189 && (window_size >=
1190 10 * scrolling_max_lines_saved (unchanged_at_top,
502b9b64 1191 FRAME_HEIGHT (frame) - unchanged_at_bottom,
4588ec20
JB
1192 old_hash, new_hash, draw_cost)))
1193 return 0;
1194
502b9b64 1195 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
4588ec20
JB
1196 draw_cost + unchanged_at_top - 1,
1197 old_hash + unchanged_at_top - 1,
1198 new_hash + unchanged_at_top - 1,
1199 free_at_end_vpos - unchanged_at_top);
1200
1201 return 0;
1202}
1203\f
1204/* Return the offset in its buffer of the character at location col, line
1205 in the given window. */
1206int
1207buffer_posn_from_coords (window, col, line)
1208 struct window *window;
1209 int col, line;
1210{
1211 int window_left = XFASTINT (window->left);
1212
1213 /* The actual width of the window is window->width less one for the
efb859b4
JB
1214 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1215 window. */
fa61c701 1216 int window_width = window_internal_width (window) - 1;
4588ec20 1217
efb859b4 1218 int startp = marker_position (window->start);
4588ec20
JB
1219
1220 /* Since compute_motion will only operate on the current buffer,
1221 we need to save the old one and restore it when we're done. */
1222 struct buffer *old_current_buffer = current_buffer;
efb859b4 1223 struct position *posn;
4588ec20
JB
1224
1225 current_buffer = XBUFFER (window->buffer);
1226
502b9b64
JB
1227 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1228 (window->frame))->bufp to avoid scanning from the very top of
efb859b4
JB
1229 the window, but it isn't maintained correctly, and I'm not even
1230 sure I will keep it. */
1231 posn = compute_motion (startp, 0,
1232 (window == XWINDOW (minibuf_window) && startp == 1
1233 ? minibuf_prompt_width : 0),
1234 ZV, line, col - window_left,
1235 window_width, XINT (window->hscroll), 0);
4588ec20
JB
1236
1237 current_buffer = old_current_buffer;
1238
502b9b64 1239 /* compute_motion considers frame points past the end of a line
efb859b4
JB
1240 to be *after* the newline, i.e. at the start of the next line.
1241 This is reasonable, but not really what we want. So if the
1242 result is on a line below LINE, back it up one character. */
1243 if (posn->vpos > line)
1244 return posn->bufpos - 1;
1245 else
1246 return posn->bufpos;
4588ec20
JB
1247}
1248\f
1249static int
1250count_blanks (r)
1251 register GLYPH *r;
1252{
1253 register GLYPH *p = r;
94aa5d2d
RS
1254 while (*p++ == SPACEGLYPH);
1255 return p - r - 1;
4588ec20
JB
1256}
1257
1258static int
1259count_match (str1, str2)
1260 GLYPH *str1, *str2;
1261{
1262 register GLYPH *p1 = str1;
1263 register GLYPH *p2 = str2;
1264 while (*p1++ == *p2++);
1265 return p1 - str1 - 1;
1266}
1267
1268/* Char insertion/deletion cost vector, from term.c */
1269extern int *char_ins_del_vector;
1270
945807a3 1271#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
4588ec20
JB
1272
1273static void
502b9b64
JB
1274update_line (frame, vpos)
1275 register FRAME_PTR frame;
4588ec20
JB
1276 int vpos;
1277{
1278 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1279 int tem;
1280 int osp, nsp, begmatch, endmatch, olen, nlen;
1281 int save;
502b9b64
JB
1282 register struct frame_glyphs *current_frame
1283 = FRAME_CURRENT_GLYPHS (frame);
1284 register struct frame_glyphs *desired_frame
1285 = FRAME_DESIRED_GLYPHS (frame);
4588ec20 1286
502b9b64
JB
1287 if (desired_frame->highlight[vpos]
1288 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
4588ec20 1289 {
502b9b64
JB
1290 change_line_highlight (desired_frame->highlight[vpos], vpos,
1291 (current_frame->enable[vpos] ?
1292 current_frame->used[vpos] : 0));
1293 current_frame->enable[vpos] = 0;
4588ec20
JB
1294 }
1295 else
502b9b64 1296 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
4588ec20 1297
502b9b64 1298 if (! current_frame->enable[vpos])
4588ec20
JB
1299 {
1300 olen = 0;
1301 }
1302 else
1303 {
502b9b64
JB
1304 obody = current_frame->glyphs[vpos];
1305 olen = current_frame->used[vpos];
1306 if (! current_frame->highlight[vpos])
4588ec20
JB
1307 {
1308 if (!must_write_spaces)
1309 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1310 olen--;
1311 }
1312 else
1313 {
1314 /* For an inverse-video line, remember we gave it
502b9b64 1315 spaces all the way to the frame edge
4588ec20
JB
1316 so that the reverse video extends all the way across. */
1317
502b9b64 1318 while (olen < FRAME_WIDTH (frame) - 1)
4588ec20
JB
1319 obody[olen++] = SPACEGLYPH;
1320 }
1321 }
1322
1323 /* One way or another, this will enable the line being updated. */
502b9b64
JB
1324 current_frame->enable[vpos] = 1;
1325 current_frame->used[vpos] = desired_frame->used[vpos];
1326 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1327 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
4588ec20
JB
1328
1329#ifdef HAVE_X_WINDOWS
b6a65ac2 1330 if (FRAME_X_P (frame))
4588ec20 1331 {
502b9b64
JB
1332 current_frame->pix_width[vpos]
1333 = current_frame->used[vpos]
1334 * FONT_WIDTH (frame->display.x->font);
1335 current_frame->pix_height[vpos]
1336 = FONT_HEIGHT (frame->display.x->font);
4588ec20
JB
1337 }
1338#endif /* HAVE_X_WINDOWS */
1339
502b9b64 1340 if (!desired_frame->enable[vpos])
4588ec20
JB
1341 {
1342 nlen = 0;
1343 goto just_erase;
1344 }
1345
502b9b64
JB
1346 nbody = desired_frame->glyphs[vpos];
1347 nlen = desired_frame->used[vpos];
4588ec20
JB
1348
1349 /* Pretend trailing spaces are not there at all,
1350 unless for one reason or another we must write all spaces. */
502b9b64 1351 if (! desired_frame->highlight[vpos])
4588ec20
JB
1352 {
1353 if (!must_write_spaces)
1354 /* We know that the previous character byte contains 0. */
1355 while (nbody[nlen - 1] == SPACEGLYPH)
1356 nlen--;
1357 }
1358 else
1359 {
1360 /* For an inverse-video line, give it extra trailing spaces
502b9b64 1361 all the way to the frame edge
4588ec20
JB
1362 so that the reverse video extends all the way across. */
1363
502b9b64 1364 while (nlen < FRAME_WIDTH (frame) - 1)
4588ec20
JB
1365 nbody[nlen++] = SPACEGLYPH;
1366 }
1367
1368 /* If there's no i/d char, quickly do the best we can without it. */
1369 if (!char_ins_del_ok)
1370 {
1371 int i,j;
1372
1373 for (i = 0; i < nlen; i++)
1374 {
1375 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1376 {
1377 cursor_to (vpos, i);
1378 for (j = 1; (i + j < nlen &&
1379 (i + j >= olen || nbody[i+j] != obody[i+j]));
1380 j++);
1381
1382 /* Output this run of non-matching chars. */
1383 write_glyphs (nbody + i, j);
1384 i += j - 1;
1385
1386 /* Now find the next non-match. */
1387 }
1388 }
1389
1390 /* Clear the rest of the line, or the non-clear part of it. */
1391 if (olen > nlen)
1392 {
1393 cursor_to (vpos, nlen);
1394 clear_end_of_line (olen);
1395 }
1396
502b9b64
JB
1397 /* Exchange contents between current_frame and new_frame. */
1398 temp = desired_frame->glyphs[vpos];
1399 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1400 current_frame->glyphs[vpos] = temp;
4588ec20
JB
1401
1402 return;
1403 }
1404
1405 if (!olen)
1406 {
502b9b64 1407 nsp = (must_write_spaces || desired_frame->highlight[vpos])
4588ec20
JB
1408 ? 0 : count_blanks (nbody);
1409 if (nlen > nsp)
1410 {
1411 cursor_to (vpos, nsp);
1412 write_glyphs (nbody + nsp, nlen - nsp);
1413 }
1414
502b9b64
JB
1415 /* Exchange contents between current_frame and new_frame. */
1416 temp = desired_frame->glyphs[vpos];
1417 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1418 current_frame->glyphs[vpos] = temp;
4588ec20
JB
1419
1420 return;
1421 }
1422
1423 obody[olen] = 1;
1424 save = nbody[nlen];
1425 nbody[nlen] = 0;
1426
1427 /* Compute number of leading blanks in old and new contents. */
1428 osp = count_blanks (obody);
502b9b64 1429 if (!desired_frame->highlight[vpos])
4588ec20
JB
1430 nsp = count_blanks (nbody);
1431 else
1432 nsp = 0;
1433
1434 /* Compute number of matching chars starting with first nonblank. */
1435 begmatch = count_match (obody + osp, nbody + nsp);
1436
1437 /* Spaces in new match implicit space past the end of old. */
1438 /* A bug causing this to be a no-op was fixed in 18.29. */
1439 if (!must_write_spaces && osp + begmatch == olen)
1440 {
1441 np1 = nbody + nsp;
1442 while (np1[begmatch] == SPACEGLYPH)
1443 begmatch++;
1444 }
1445
1446 /* Avoid doing insert/delete char
1447 just cause number of leading spaces differs
1448 when the following text does not match. */
1449 if (begmatch == 0 && osp != nsp)
1450 osp = nsp = min (osp, nsp);
1451
1452 /* Find matching characters at end of line */
1453 op1 = obody + olen;
1454 np1 = nbody + nlen;
1455 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1456 while (op1 > op2 && op1[-1] == np1[-1])
1457 {
1458 op1--;
1459 np1--;
1460 }
1461 endmatch = obody + olen - op1;
1462
1463 /* Put correct value back in nbody[nlen].
1464 This is important because direct_output_for_insert
1465 can write into the line at a later point.
1466 If this screws up the zero at the end of the line, re-establish it. */
1467 nbody[nlen] = save;
1468 obody[olen] = 0;
1469
1470 /* tem gets the distance to insert or delete.
1471 endmatch is how many characters we save by doing so.
1472 Is it worth it? */
1473
1474 tem = (nlen - nsp) - (olen - osp);
1475 if (endmatch && tem
502b9b64 1476 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
4588ec20
JB
1477 endmatch = 0;
1478
1479 /* nsp - osp is the distance to insert or delete.
1480 If that is nonzero, begmatch is known to be nonzero also.
1481 begmatch + endmatch is how much we save by doing the ins/del.
1482 Is it worth it? */
1483
1484 if (nsp != osp
1485 && (!char_ins_del_ok
502b9b64 1486 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
4588ec20
JB
1487 {
1488 begmatch = 0;
1489 endmatch = 0;
1490 osp = nsp = min (osp, nsp);
1491 }
1492
1493 /* Now go through the line, inserting, writing and
1494 deleting as appropriate. */
1495
1496 if (osp > nsp)
1497 {
1498 cursor_to (vpos, nsp);
1499 delete_glyphs (osp - nsp);
1500 }
1501 else if (nsp > osp)
1502 {
1503 /* If going to delete chars later in line
1504 and insert earlier in the line,
1505 must delete first to avoid losing data in the insert */
1506 if (endmatch && nlen < olen + nsp - osp)
1507 {
1508 cursor_to (vpos, nlen - endmatch + osp - nsp);
1509 delete_glyphs (olen + nsp - osp - nlen);
1510 olen = nlen - (nsp - osp);
1511 }
1512 cursor_to (vpos, osp);
1513 insert_glyphs ((char *)0, nsp - osp);
1514 }
1515 olen += nsp - osp;
1516
1517 tem = nsp + begmatch + endmatch;
1518 if (nlen != tem || olen != tem)
1519 {
1520 cursor_to (vpos, nsp + begmatch);
1521 if (!endmatch || nlen == olen)
1522 {
1523 /* If new text being written reaches right margin,
1524 there is no need to do clear-to-eol at the end.
1525 (and it would not be safe, since cursor is not
1526 going to be "at the margin" after the text is done) */
502b9b64 1527 if (nlen == FRAME_WIDTH (frame))
4588ec20
JB
1528 olen = 0;
1529 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1530
1531#ifdef obsolete
1532
1533/* the following code loses disastrously if tem == nlen.
1534 Rather than trying to fix that case, I am trying the simpler
1535 solution found above. */
1536
1537 /* If the text reaches to the right margin,
1538 it will lose one way or another (depending on AutoWrap)
1539 to clear to end of line after outputting all the text.
1540 So pause with one character to go and clear the line then. */
502b9b64 1541 if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
4588ec20
JB
1542 {
1543 /* endmatch must be zero, and tem must equal nsp + begmatch */
1544 write_glyphs (nbody + tem, nlen - tem - 1);
1545 clear_end_of_line (olen);
1546 olen = 0; /* Don't let it be cleared again later */
1547 write_glyphs (nbody + nlen - 1, 1);
1548 }
1549 else
1550 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1551#endif /* OBSOLETE */
1552
1553 }
1554 else if (nlen > olen)
1555 {
1556 write_glyphs (nbody + nsp + begmatch, olen - tem);
1557 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1558 olen = nlen;
1559 }
1560 else if (olen > nlen)
1561 {
1562 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1563 delete_glyphs (olen - nlen);
1564 olen = nlen;
1565 }
1566 }
1567
1568 just_erase:
1569 /* If any unerased characters remain after the new line, erase them. */
1570 if (olen > nlen)
1571 {
1572 cursor_to (vpos, nlen);
1573 clear_end_of_line (olen);
1574 }
1575
502b9b64
JB
1576 /* Exchange contents between current_frame and new_frame. */
1577 temp = desired_frame->glyphs[vpos];
1578 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1579 current_frame->glyphs[vpos] = temp;
4588ec20
JB
1580}
1581\f
1582DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1583 1, 1, "FOpen termscript file: ",
1584 "Start writing all terminal output to FILE as well as the terminal.\n\
1585FILE = nil means just close any termscript file currently open.")
1586 (file)
1587 Lisp_Object file;
1588{
1589 if (termscript != 0) fclose (termscript);
1590 termscript = 0;
1591
efb859b4 1592 if (! NILP (file))
4588ec20
JB
1593 {
1594 file = Fexpand_file_name (file, Qnil);
1595 termscript = fopen (XSTRING (file)->data, "w");
1596 if (termscript == 0)
1597 report_file_error ("Opening termscript", Fcons (file, Qnil));
1598 }
1599 return Qnil;
1600}
1601\f
1602
1603#ifdef SIGWINCH
efb859b4 1604SIGTYPE
4588ec20
JB
1605window_change_signal ()
1606{
1607 int width, height;
1608 extern int errno;
1609 int old_errno = errno;
1610
502b9b64 1611 get_frame_size (&width, &height);
4588ec20 1612
502b9b64
JB
1613 /* The frame size change obviously applies to a termcap-controlled
1614 frame. Find such a frame in the list, and assume it's the only
4588ec20 1615 one (since the redisplay code always writes to stdout, not a
502b9b64 1616 FILE * specified in the frame structure). Record the new size,
4588ec20
JB
1617 but don't reallocate the data structures now. Let that be done
1618 later outside of the signal handler. */
1619
1620 {
35f56f96 1621 Lisp_Object tail, frame;
4588ec20 1622
35f56f96 1623 FOR_EACH_FRAME (tail, frame)
4588ec20 1624 {
35f56f96 1625 if (FRAME_TERMCAP_P (XFRAME (frame)))
4588ec20 1626 {
35f56f96 1627 change_frame_size (XFRAME (frame), height, width, 0, 1);
4588ec20
JB
1628 break;
1629 }
1630 }
1631 }
1632
1633 signal (SIGWINCH, window_change_signal);
1634 errno = old_errno;
1635}
1636#endif /* SIGWINCH */
1637
1638
502b9b64 1639/* Do any change in frame size that was requested by a signal. */
4588ec20
JB
1640
1641do_pending_window_change ()
1642{
1643 /* If window_change_signal should have run before, run it now. */
1644 while (delayed_size_change)
1645 {
35f56f96 1646 Lisp_Object tail, frame;
4588ec20
JB
1647
1648 delayed_size_change = 0;
1649
35f56f96 1650 FOR_EACH_FRAME (tail, frame)
4588ec20 1651 {
35f56f96
JB
1652 FRAME_PTR f = XFRAME (frame);
1653
502b9b64
JB
1654 int height = FRAME_NEW_HEIGHT (f);
1655 int width = FRAME_NEW_WIDTH (f);
4588ec20 1656
502b9b64
JB
1657 FRAME_NEW_HEIGHT (f) = 0;
1658 FRAME_NEW_WIDTH (f) = 0;
4588ec20
JB
1659
1660 if (height != 0)
b6a65ac2 1661 change_frame_size (f, height, width, 0, 0);
4588ec20
JB
1662 }
1663 }
1664}
1665
1666
502b9b64 1667/* Change the frame height and/or width. Values may be given as zero to
b6a65ac2 1668 indicate no change is to take place.
4588ec20 1669
b6a65ac2
JB
1670 If DELAY is non-zero, then assume we're being called from a signal
1671 handler, and queue the change for later - perhaps the next
1672 redisplay. Since this tries to resize windows, we can't call it
1673 from a signal handler. */
1674
1675change_frame_size (frame, newheight, newwidth, pretend, delay)
502b9b64 1676 register FRAME_PTR frame;
b6a65ac2 1677 int newheight, newwidth, pretend;
4588ec20
JB
1678{
1679 /* If we can't deal with the change now, queue it for later. */
b6a65ac2 1680 if (delay)
4588ec20 1681 {
b6a65ac2 1682 FRAME_NEW_HEIGHT (frame) = newheight;
502b9b64 1683 FRAME_NEW_WIDTH (frame) = newwidth;
4588ec20
JB
1684 delayed_size_change = 1;
1685 return;
1686 }
1687
502b9b64
JB
1688 /* This size-change overrides any pending one for this frame. */
1689 FRAME_NEW_HEIGHT (frame) = 0;
b6a65ac2
JB
1690 FRAME_NEW_WIDTH (frame) = 0;
1691
1692 /* If an arguments is zero, set it to the current value. */
1693 newheight || (newheight = FRAME_HEIGHT (frame));
1694 newwidth || (newwidth = FRAME_WIDTH (frame));
4588ec20 1695
b6a65ac2
JB
1696 /* Round up to the smallest acceptable size. */
1697 check_frame_size (frame, &newheight, &newwidth);
1698
1699 /* If we're not changing the frame size, quit now. */
1700 if (newheight == FRAME_HEIGHT (frame)
1701 && newwidth == FRAME_WIDTH (frame))
4588ec20
JB
1702 return;
1703
b6a65ac2 1704 if (newheight != FRAME_HEIGHT (frame))
4588ec20 1705 {
b6a65ac2 1706 if (FRAME_HAS_MINIBUF_P (frame)
502b9b64 1707 && ! FRAME_MINIBUF_ONLY_P (frame))
4588ec20 1708 {
502b9b64
JB
1709 /* Frame has both root and minibuffer. */
1710 set_window_height (FRAME_ROOT_WINDOW (frame),
cb470ab1 1711 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
502b9b64 1712 XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
b6a65ac2 1713 = newheight - 1;
502b9b64 1714 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
4588ec20
JB
1715 }
1716 else
502b9b64 1717 /* Frame has just one top-level window. */
cb470ab1
RS
1718 set_window_height (FRAME_ROOT_WINDOW (frame),
1719 newheight - FRAME_MENU_BAR_LINES (frame), 0);
b6a65ac2
JB
1720
1721 if (FRAME_TERMCAP_P (frame) && !pretend)
1722 FrameRows = newheight;
4588ec20
JB
1723
1724#if 0
502b9b64 1725 if (frame->output_method == output_termcap)
4588ec20 1726 {
b6a65ac2 1727 frame_height = newheight;
4588ec20 1728 if (!pretend)
b6a65ac2 1729 FrameRows = newheight;
4588ec20
JB
1730 }
1731#endif
1732 }
1733
b6a65ac2 1734 if (newwidth != FRAME_WIDTH (frame))
4588ec20 1735 {
502b9b64 1736 set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
b6a65ac2 1737 if (FRAME_HAS_MINIBUF_P (frame))
502b9b64 1738 set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
4588ec20 1739
b6a65ac2 1740 if (FRAME_TERMCAP_P (frame) && !pretend)
502b9b64 1741 FrameCols = newwidth;
4588ec20 1742#if 0
502b9b64 1743 if (frame->output_method == output_termcap)
4588ec20 1744 {
502b9b64 1745 frame_width = newwidth;
4588ec20 1746 if (!pretend)
502b9b64 1747 FrameCols = newwidth;
4588ec20
JB
1748 }
1749#endif
1750 }
1751
b6a65ac2
JB
1752 FRAME_HEIGHT (frame) = newheight;
1753 FRAME_WIDTH (frame) = newwidth;
1754
502b9b64
JB
1755 remake_frame_glyphs (frame);
1756 calculate_costs (frame);
4588ec20
JB
1757}
1758\f
1759DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
1760 Ssend_string_to_terminal, 1, 1, 0,
1761 "Send STRING to the terminal without alteration.\n\
1762Control characters in STRING will have terminal-dependent effects.")
1763 (str)
1764 Lisp_Object str;
1765{
1766 CHECK_STRING (str, 0);
1767 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
1768 fflush (stdout);
1769 if (termscript)
1770 {
1771 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
1772 fflush (termscript);
1773 }
1774 return Qnil;
1775}
1776
1777DEFUN ("ding", Fding, Sding, 0, 1, 0,
1778 "Beep, or flash the screen.\n\
1779Also, unless an argument is given,\n\
1780terminate any keyboard macro currently executing.")
1781 (arg)
1782 Lisp_Object arg;
1783{
efb859b4 1784 if (!NILP (arg))
4588ec20 1785 {
7fa788da
RS
1786 if (noninteractive)
1787 putchar (07);
1788 else
1789 ring_bell ();
4588ec20
JB
1790 fflush (stdout);
1791 }
1792 else
1793 bitch_at_user ();
1794
1795 return Qnil;
1796}
1797
1798bitch_at_user ()
1799{
1800 if (noninteractive)
1801 putchar (07);
1802 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
1803 error ("Keyboard macro terminated by a command ringing the bell");
1804 else
1805 ring_bell ();
1806 fflush (stdout);
1807}
1808
1809DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
767229f8 1810 "Pause, without updating display, for SECONDS seconds.\n\
b07646f5
JB
1811SECONDS may be a floating-point value, meaning that you can wait for a\n\
1812fraction of a second. Optional second arg MILLISECONDS specifies an\n\
1813additional wait period, in milliseconds; this may be useful if your\n\
1814Emacs was built without floating point support.\n\
1815\(Not all operating systems support waiting for a fraction of a second.)")
767229f8
JB
1816 (seconds, milliseconds)
1817 Lisp_Object seconds, milliseconds;
4588ec20 1818{
767229f8 1819 int sec, usec;
4588ec20 1820
767229f8
JB
1821 if (NILP (milliseconds))
1822 XSET (milliseconds, Lisp_Int, 0);
1823 else
1824 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
1825 usec = XINT (milliseconds) * 1000;
1826
1827#ifdef LISP_FLOAT_TYPE
1828 {
1829 double duration = extract_float (seconds);
1830 sec = (int) duration;
1831 usec += (duration - sec) * 1000000;
1832 }
1833#else
1834 CHECK_NUMBER (seconds, 0);
1835 sec = XINT (seconds);
1836#endif
4588ec20 1837
a41f8bed 1838#ifndef EMACS_HAS_USECS
767229f8
JB
1839 if (sec == 0 && usec != 0)
1840 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
4588ec20 1841#endif
767229f8
JB
1842
1843 /* Assure that 0 <= usec < 1000000. */
1844 if (usec < 0)
1845 {
1846 /* We can't rely on the rounding being correct if user is negative. */
1847 if (-1000000 < usec)
1848 sec--, usec += 1000000;
1849 else
1850 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
4588ec20 1851 }
767229f8
JB
1852 else
1853 sec += usec / 1000000, usec %= 1000000;
1854
92723877 1855 if (sec < 0)
767229f8 1856 return Qnil;
4588ec20 1857
f76475ad
JB
1858 {
1859 Lisp_Object zero;
1860
1861 XFASTINT (zero) = 0;
1862 wait_reading_process_input (sec, usec, zero, 0);
1863 }
d1af74e9 1864
767229f8
JB
1865 /* We should always have wait_reading_process_input; we have a dummy
1866 implementation for systems which don't support subprocesses. */
1867#if 0
1868 /* No wait_reading_process_input */
4588ec20
JB
1869 immediate_quit = 1;
1870 QUIT;
1871
1872#ifdef VMS
1873 sys_sleep (sec);
1874#else /* not VMS */
1875/* The reason this is done this way
1876 (rather than defined (H_S) && defined (H_T))
1877 is because the VMS preprocessor doesn't grok `defined' */
1878#ifdef HAVE_SELECT
a41f8bed
JB
1879 EMACS_GET_TIME (end_time);
1880 EMACS_SET_SECS_USECS (timeout, sec, usec);
d1af74e9 1881 EMACS_ADD_TIME (end_time, end_time, timeout);
a41f8bed 1882
4588ec20
JB
1883 while (1)
1884 {
a41f8bed
JB
1885 EMACS_GET_TIME (timeout);
1886 EMACS_SUB_TIME (timeout, end_time, timeout);
1887 if (EMACS_TIME_NEG_P (timeout)
1888 || !select (1, 0, 0, 0, &timeout))
4588ec20
JB
1889 break;
1890 }
4588ec20
JB
1891#else /* not HAVE_SELECT */
1892 sleep (sec);
1893#endif /* HAVE_SELECT */
1894#endif /* not VMS */
1895
1896 immediate_quit = 0;
1897#endif /* no subprocesses */
1898
1899 return Qnil;
1900}
1901
f76475ad
JB
1902/* This is just like wait_reading_process_input, except that
1903 it does the redisplay.
1904
1905 It's also just like Fsit_for, except that it can be used for
1906 waiting for input as well. */
4588ec20 1907
f76475ad
JB
1908Lisp_Object
1909sit_for (sec, usec, reading, display)
1910 int sec, usec, reading, display;
1911{
1912 Lisp_Object read_kbd;
4588ec20
JB
1913
1914 if (detect_input_pending ())
1915 return Qnil;
4588ec20 1916
f76475ad
JB
1917 if (display)
1918 redisplay_preserve_echo_area ();
4588ec20 1919
dfdb645c
JB
1920 if (sec == 0 && usec == 0)
1921 return Qt;
1922
4588ec20 1923#ifdef SIGIO
8fc798e9 1924 gobble_input (0);
f76475ad
JB
1925#endif
1926
1927 XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
1928 wait_reading_process_input (sec, usec, read_kbd, display);
1929
d1af74e9 1930
500ab754
JB
1931 /* wait_reading_process_input should always be available now; it is
1932 simulated in a simple way on systems that don't support
1933 subprocesses. */
1934#if 0
1935 /* No wait_reading_process_input available. */
4588ec20
JB
1936 immediate_quit = 1;
1937 QUIT;
1938
1939 waitchannels = 1;
1940#ifdef VMS
f76475ad 1941 input_wait_timeout (XINT (arg));
4588ec20 1942#else /* not VMS */
d1af74e9
JB
1943#ifndef HAVE_TIMEVAL
1944 timeout_sec = sec;
1945 select (1, &waitchannels, 0, 0, &timeout_sec);
1946#else /* HAVE_TIMEVAL */
1947 timeout.tv_sec = sec;
1948 timeout.tv_usec = usec;
4588ec20 1949 select (1, &waitchannels, 0, 0, &timeout);
d1af74e9 1950#endif /* HAVE_TIMEVAL */
4588ec20
JB
1951#endif /* not VMS */
1952
1953 immediate_quit = 0;
d1af74e9 1954#endif
4588ec20
JB
1955
1956 return detect_input_pending () ? Qnil : Qt;
1957}
1958
f76475ad 1959DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
767229f8 1960 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
b07646f5
JB
1961SECONDS may be a floating-point value, meaning that you can wait for a\n\
1962fraction of a second. Optional second arg MILLISECONDS specifies an\n\
1963additional wait period, in milliseconds; this may be useful if your\n\
1964Emacs was built without floating point support.\n\
1965\(Not all operating systems support waiting for a fraction of a second.)\n\
f76475ad
JB
1966Optional third arg non-nil means don't redisplay, just wait for input.\n\
1967Redisplay is preempted as always if input arrives, and does not happen\n\
1968if input is available before it starts.\n\
1969Value is t if waited the full time with no input arriving.")
767229f8
JB
1970 (seconds, milliseconds, nodisp)
1971 Lisp_Object seconds, milliseconds, nodisp;
f76475ad 1972{
767229f8 1973 int sec, usec;
f76475ad 1974
767229f8
JB
1975 if (NILP (milliseconds))
1976 XSET (milliseconds, Lisp_Int, 0);
1977 else
1978 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
1979 usec = XINT (milliseconds) * 1000;
1980
1981#ifdef LISP_FLOAT_TYPE
1982 {
1983 double duration = extract_float (seconds);
1984 sec = (int) duration;
1985 usec += (duration - sec) * 1000000;
1986 }
1987#else
1988 CHECK_NUMBER (seconds, 0);
1989 sec = XINT (seconds);
1990#endif
f76475ad 1991
f76475ad 1992#ifndef EMACS_HAS_USECS
767229f8
JB
1993 if (usec != 0 && sec == 0)
1994 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
f76475ad 1995#endif
f76475ad
JB
1996
1997 return sit_for (sec, usec, 0, NILP (nodisp));
1998}
4588ec20
JB
1999\f
2000char *terminal_type;
2001
2002/* Initialization done when Emacs fork is started, before doing stty. */
2003/* Determine terminal type and set terminal_driver */
2004/* Then invoke its decoding routine to set up variables
2005 in the terminal package */
2006
2007init_display ()
2008{
2009#ifdef HAVE_X_WINDOWS
2010 extern int display_arg;
2011#endif
2012
2013 meta_key = 0;
2014 inverse_video = 0;
2015 cursor_in_echo_area = 0;
2016 terminal_type = (char *) 0;
2017
1315c181
JB
2018 /* Now is the time to initialize this; it's used by init_sys_modes
2019 during startup. */
2020 Vwindow_system = Qnil;
4588ec20 2021
1315c181
JB
2022 /* If the user wants to use a window system, we shouldn't bother
2023 initializing the terminal. This is especially important when the
2024 terminal is so dumb that emacs gives up before and doesn't bother
2025 using the window system.
4588ec20 2026
1315c181
JB
2027 If the DISPLAY environment variable is set, try to use X, and die
2028 with an error message if that doesn't work. */
4588ec20
JB
2029
2030#ifdef HAVE_X_WINDOWS
d460af17
JB
2031 if (! display_arg)
2032 {
2033#ifdef VMS
5de9f849 2034 display_arg = (getenv ("DECW$DISPLAY") != 0);
d460af17 2035#else
5de9f849 2036 display_arg = (getenv ("DISPLAY") != 0);
d460af17 2037#endif
f040093a 2038 }
d460af17
JB
2039
2040 if (!inhibit_window_system && display_arg)
4588ec20
JB
2041 {
2042 Vwindow_system = intern ("x");
2043#ifdef HAVE_X11
2044 Vwindow_system_version = make_number (11);
2045#else
2046 Vwindow_system_version = make_number (10);
2047#endif
2048 return;
2049 }
2050#endif /* HAVE_X_WINDOWS */
2051
2052 /* If no window system has been specified, try to use the terminal. */
2053 if (! isatty (0))
2054 {
2055 fprintf (stderr, "emacs: standard input is not a tty\n");
2056 exit (1);
2057 }
2058
2059 /* Look at the TERM variable */
2060 terminal_type = (char *) getenv ("TERM");
2061 if (!terminal_type)
2062 {
2063#ifdef VMS
2064 fprintf (stderr, "Please specify your terminal type.\n\
2065For types defined in VMS, use set term /device=TYPE.\n\
2066For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2067\(The quotation marks are necessary since terminal types are lower case.)\n");
2068#else
2069 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2070#endif
2071 exit (1);
2072 }
2073
2074#ifdef VMS
2075 /* VMS DCL tends to upcase things, so downcase term type.
2076 Hardly any uppercase letters in terminal types; should be none. */
2077 {
2078 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2079 char *p;
2080
2081 strcpy (new, terminal_type);
2082
2083 for (p = new; *p; p++)
2084 if (isupper (*p))
2085 *p = tolower (*p);
2086
2087 terminal_type = new;
2088 }
2089#endif
2090
2091 term_init (terminal_type);
2092
502b9b64
JB
2093 remake_frame_glyphs (selected_frame);
2094 calculate_costs (selected_frame);
4588ec20
JB
2095
2096 /* X and Y coordinates of the cursor between updates. */
502b9b64
JB
2097 FRAME_CURSOR_X (selected_frame) = 0;
2098 FRAME_CURSOR_Y (selected_frame) = 0;
4588ec20
JB
2099
2100#ifdef SIGWINCH
2101#ifndef CANNOT_DUMP
2102 if (initialized)
2103#endif /* CANNOT_DUMP */
2104 signal (SIGWINCH, window_change_signal);
2105#endif /* SIGWINCH */
2106}
2107\f
2108syms_of_display ()
2109{
502b9b64
JB
2110#ifdef MULTI_FRAME
2111 defsubr (&Sredraw_frame);
4588ec20
JB
2112#endif
2113 defsubr (&Sredraw_display);
2114 defsubr (&Sopen_termscript);
2115 defsubr (&Sding);
2116 defsubr (&Ssit_for);
2117 defsubr (&Ssleep_for);
2118 defsubr (&Ssend_string_to_terminal);
2119
2120 DEFVAR_INT ("baud-rate", &baud_rate,
2121 "The output baud rate of the terminal.\n\
2122On most systems, changing this value will affect the amount of padding\n\
2123and the other strategic decisions made during redisplay.");
2124 DEFVAR_BOOL ("inverse-video", &inverse_video,
502b9b64 2125 "*Non-nil means invert the entire frame display.\n\
4588ec20
JB
2126This means everything is in inverse video which otherwise would not be.");
2127 DEFVAR_BOOL ("visible-bell", &visible_bell,
502b9b64 2128 "*Non-nil means try to flash the frame to represent a bell.");
4588ec20 2129 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
502b9b64 2130 "*Non-nil means no need to redraw entire frame after suspending.\n\
4588ec20 2131A non-nil value is useful if the terminal can automatically preserve\n\
502b9b64 2132Emacs's frame display when you reenter Emacs.\n\
4588ec20
JB
2133It is up to you to set this variable if your terminal can do that.");
2134 DEFVAR_LISP ("window-system", &Vwindow_system,
2135 "A symbol naming the window-system under which Emacs is running\n\
2136\(such as `x'), or nil if emacs is running on an ordinary terminal.");
2137 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2138 "The version number of the window system in use.\n\
2139For X windows, this is 10 or 11.");
2140 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2141 "Non-nil means put cursor in minibuffer, at end of any message there.");
2142 DEFVAR_LISP ("glyph-table", &Vglyph_table,
502b9b64 2143 "Table defining how to output a glyph code to the frame.\n\
4588ec20
JB
2144If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2145Each element can be:\n\
2146 integer: a glyph code which this glyph is an alias for.\n\
2147 string: output this glyph using that string (not impl. in X windows).\n\
2148 nil: this glyph mod 256 is char code to output,\n\
2149 and this glyph / 256 is face code for X windows (see `x-set-face').");
2150 Vglyph_table = Qnil;
2151
2152 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2153 "Display table to use for buffers that specify none.\n\
2154See `buffer-display-table' for more information.");
2155 Vstandard_display_table = Qnil;
2156
2157 /* Initialize `window-system', unless init_display already decided it. */
2158#ifdef CANNOT_DUMP
2159 if (noninteractive)
2160#endif
2161 {
2162 Vwindow_system = Qnil;
2163 Vwindow_system_version = Qnil;
2164 }
2165}
2166