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