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