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