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