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