(ediff-autostore-merges): Doc fix.
[bpt/emacs.git] / src / dispnew.c
CommitLineData
4588ec20 1/* Updating of data structures for redisplay.
4a2f9c6a 2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 1998
ba704fd4 3 Free Software Foundation, Inc.
4588ec20
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
fa61c701 9the Free Software Foundation; either version 2, or (at your option)
4588ec20
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
4588ec20
JB
21
22
23#include <signal.h>
24
18160b98 25#include <config.h>
565620a5
RS
26
27#include <stdio.h>
4588ec20
JB
28#include <ctype.h>
29
47099d6f 30#include "lisp.h"
4588ec20
JB
31#include "termchar.h"
32#include "termopts.h"
3be08bea 33#include "termhooks.h"
a0879520 34/* cm.h must come after dispextern.h on Windows. */
fd2e066a
GV
35#include "dispextern.h"
36#include "cm.h"
4588ec20 37#include "buffer.h"
24e86043 38#include "charset.h"
502b9b64 39#include "frame.h"
4588ec20
JB
40#include "window.h"
41#include "commands.h"
42#include "disptab.h"
43#include "indent.h"
d169fe39 44#include "intervals.h"
97cf50e7 45#include "blockinput.h"
4588ec20 46
24e86043
KH
47/* I don't know why DEC Alpha OSF1 fail to compile this file if we
48 include the following file. */
49/* #include "systty.h" */
58b2bb63 50#include "syssignal.h"
a41f8bed 51
4588ec20
JB
52#ifdef HAVE_X_WINDOWS
53#include "xterm.h"
54#endif /* HAVE_X_WINDOWS */
55
fd2e066a
GV
56#ifdef HAVE_NTGUI
57#include "w32term.h"
58#endif /* HAVE_NTGUI */
59
6cbd1643
RS
60/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
61#include "systime.h"
62
3883a901
RS
63#include <errno.h>
64
4588ec20
JB
65#define max(a, b) ((a) > (b) ? (a) : (b))
66#define min(a, b) ((a) < (b) ? (a) : (b))
ceafe86b
KH
67#define minmax(floor, val, ceil) \
68 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
4588ec20 69
4588ec20
JB
70/* Get number of chars of output now in the buffer of a stdio stream.
71 This ought to be built in in stdio, but it isn't.
72 Some s- files override this because their stdio internals differ. */
e3271ae5 73#ifdef __GNU_LIBRARY__
097c2824
RM
74/* The s- file might have overridden the definition with one that works for
75 the system's C library. But we are using the GNU C library, so this is
76 the right definition for every system. */
3883a901
RS
77#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
78#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
79#else
cb5558ff 80#undef PENDING_OUTPUT_COUNT
e3271ae5 81#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
3883a901
RS
82#endif
83#else /* not __GNU_LIBRARY__ */
cb5558ff 84#ifndef PENDING_OUTPUT_COUNT
4588ec20
JB
85#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
86#endif
e3271ae5 87#endif
4588ec20 88
45140e01
RS
89static void change_frame_size_1 ();
90
a41f8bed 91/* Nonzero upon entry to redisplay means do not assume anything about
502b9b64 92 current contents of actual terminal frame; clear and redraw it. */
4588ec20 93
502b9b64 94int frame_garbaged;
4588ec20
JB
95
96/* Nonzero means last display completed. Zero means it was preempted. */
97
98int display_completed;
99
100/* Lisp variable visible-bell; enables use of screen-flash
101 instead of audible bell. */
102
103int visible_bell;
104
502b9b64 105/* Invert the color of the whole frame, at a low level. */
4588ec20
JB
106
107int inverse_video;
108
109/* Line speed of the terminal. */
110
111int baud_rate;
112
113/* nil or a symbol naming the window system under which emacs is
114 running ('x is the only current possibility). */
115
116Lisp_Object Vwindow_system;
117
118/* Version number of X windows: 10, 11 or nil. */
119Lisp_Object Vwindow_system_version;
120
121/* Vector of glyph definitions. Indexed by glyph number,
122 the contents are a string which is how to output the glyph.
123
124 If Vglyph_table is nil, a glyph is output by using its low 8 bits
125 as a character code. */
126
127Lisp_Object Vglyph_table;
128
129/* Display table to use for vectors that don't specify their own. */
130
131Lisp_Object Vstandard_display_table;
132
133/* Nonzero means reading single-character input with prompt
1113d9db
JB
134 so put cursor on minibuffer after the prompt.
135 positive means at end of text in echo area;
136 negative means at beginning of line. */
4588ec20 137int cursor_in_echo_area;
9cda4f7c
RS
138
139Lisp_Object Qdisplay_table;
4588ec20 140\f
502b9b64 141/* The currently selected frame.
87485d6f
MW
142 In a single-frame version, this variable always holds the address of
143 the_only_frame. */
4588ec20 144
502b9b64 145FRAME_PTR selected_frame;
4588ec20 146
502b9b64
JB
147/* A frame which is not just a minibuffer, or 0 if there are no such
148 frames. This is usually the most recent such frame that was
87485d6f
MW
149 selected. In a single-frame version, this variable always holds
150 the address of the_only_frame. */
502b9b64 151FRAME_PTR last_nonminibuf_frame;
e5d77022 152
4588ec20 153/* This is a vector, made larger whenever it isn't large enough,
502b9b64
JB
154 which is used inside `update_frame' to hold the old contents
155 of the FRAME_PHYS_LINES of the frame being updated. */
156struct frame_glyphs **ophys_lines;
4588ec20
JB
157/* Length of vector currently allocated. */
158int ophys_lines_length;
159
160FILE *termscript; /* Stdio stream being used for copy of all output. */
161
162struct cm Wcm; /* Structure for info on cursor positioning */
163
4588ec20 164int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
4588ec20 165\f
502b9b64
JB
166DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
167 "Clear frame FRAME and output again what is supposed to appear on it.")
168 (frame)
169 Lisp_Object frame;
4588ec20 170{
502b9b64 171 FRAME_PTR f;
4588ec20 172
502b9b64
JB
173 CHECK_LIVE_FRAME (frame, 0);
174 f = XFRAME (frame);
175 update_begin (f);
93e54836
RS
176 if (FRAME_MSDOS_P (f))
177 set_terminal_modes ();
502b9b64 178 clear_frame ();
b6a65ac2 179 clear_frame_records (f);
502b9b64 180 update_end (f);
4588ec20 181 fflush (stdout);
4588ec20
JB
182 windows_or_buffers_changed++;
183 /* Mark all windows as INaccurate,
184 so that every window will have its redisplay done. */
502b9b64
JB
185 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
186 f->garbaged = 0;
4588ec20
JB
187 return Qnil;
188}
189
502b9b64
JB
190redraw_frame (f)
191 FRAME_PTR f;
4588ec20 192{
502b9b64 193 Lisp_Object frame;
e9c9a718 194 XSETFRAME (frame, f);
502b9b64 195 Fredraw_frame (frame);
4588ec20
JB
196}
197
35f56f96
JB
198DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
199 "Clear and redisplay all visible frames.")
200 ()
201{
202 Lisp_Object tail, frame;
203
204 FOR_EACH_FRAME (tail, frame)
9223a96a 205 if (FRAME_VISIBLE_P (XFRAME (frame)))
35f56f96
JB
206 Fredraw_frame (frame);
207
208 return Qnil;
209}
210
9223a96a
RS
211/* This is used when frame_garbaged is set.
212 Redraw the individual frames marked as garbaged. */
213
214void
215redraw_garbaged_frames ()
216{
217 Lisp_Object tail, frame;
218
219 FOR_EACH_FRAME (tail, frame)
220 if (FRAME_VISIBLE_P (XFRAME (frame))
221 && FRAME_GARBAGED_P (XFRAME (frame)))
222 Fredraw_frame (frame);
223}
224
4588ec20 225\f
502b9b64
JB
226static struct frame_glyphs *
227make_frame_glyphs (frame, empty)
228 register FRAME_PTR frame;
4588ec20
JB
229 int empty;
230{
231 register int i;
29ec5d84 232 register width = FRAME_WINDOW_WIDTH (frame);
502b9b64 233 register height = FRAME_HEIGHT (frame);
60a8948a
RS
234 register struct frame_glyphs *new
235 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
4588ec20 236
502b9b64 237 SET_GLYPHS_FRAME (new, frame);
4588ec20
JB
238 new->height = height;
239 new->width = width;
240 new->used = (int *) xmalloc (height * sizeof (int));
241 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
60a8948a 242 new->charstarts = (int **) xmalloc (height * sizeof (int *));
4588ec20
JB
243 new->highlight = (char *) xmalloc (height * sizeof (char));
244 new->enable = (char *) xmalloc (height * sizeof (char));
245 bzero (new->enable, height * sizeof (char));
246 new->bufp = (int *) xmalloc (height * sizeof (int));
247
fd2e066a
GV
248#ifdef HAVE_WINDOW_SYSTEM
249 if (FRAME_WINDOW_P (frame))
4588ec20 250 {
4588ec20
JB
251 new->top_left_x = (short *) xmalloc (height * sizeof (short));
252 new->top_left_y = (short *) xmalloc (height * sizeof (short));
253 new->pix_width = (short *) xmalloc (height * sizeof (short));
254 new->pix_height = (short *) xmalloc (height * sizeof (short));
448fd7c0 255 new->max_ascent = (short *) xmalloc (height * sizeof (short));
4588ec20 256 }
fd2e066a 257#endif /* HAVE_WINDOW_SYSTEM */
4588ec20
JB
258
259 if (empty)
260 {
261 /* Make the buffer used by decode_mode_spec. This buffer is also
502b9b64 262 used as temporary storage when updating the frame. See scroll.c. */
4588ec20 263 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
d52bad65 264 unsigned int total_charstarts = (width + 2) * sizeof (int);
4588ec20
JB
265
266 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
267 bzero (new->total_contents, total_glyphs);
d52bad65
RS
268
269 new->total_charstarts = (int *) xmalloc (total_charstarts);
aba5d0f4 270 bzero (new->total_charstarts, total_charstarts);
4588ec20
JB
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
05233a7d 304void
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 321
fd2e066a
GV
322#ifdef HAVE_WINDOW_SYSTEM
323 if (FRAME_WINDOW_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 330 }
fd2e066a 331#endif /* HAVE_WINDOW_SYSTEM */
4588ec20 332
9ac0d9e0 333 xfree (glyphs);
4588ec20
JB
334}
335
45140e01 336void
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),
24e86043 355 FRAME_MESSAGE_BUF_SIZE (frame) + 1);
832a0726
JB
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 363 FRAME_MESSAGE_BUF (frame)
24e86043 364 = (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (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);
8a376b3b 369 if (FRAME_WINDOW_P (frame) || frame == selected_frame)
45140e01 370 SET_FRAME_GARBAGED (frame);
4588ec20
JB
371}
372\f
502b9b64 373/* Return the hash code of contents of line VPOS in frame-matrix M. */
4588ec20
JB
374
375static int
376line_hash_code (m, vpos)
502b9b64 377 register struct frame_glyphs *m;
4588ec20
JB
378 int vpos;
379{
380 register GLYPH *body, *end;
381 register int h = 0;
382
383 if (!m->enable[vpos])
384 return 0;
385
94aa5d2d 386 /* Give all highlighted lines the same hash code
4588ec20
JB
387 so as to encourage scrolling to leave them in place. */
388 if (m->highlight[vpos])
389 return -1;
390
391 body = m->glyphs[vpos];
392
393 if (must_write_spaces)
394 while (1)
395 {
396 GLYPH g = *body++;
397
398 if (g == 0)
399 break;
400 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
401 }
402 else
403 while (1)
404 {
405 GLYPH g = *body++;
406
407 if (g == 0)
408 break;
409 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
410 }
411
412 if (h)
413 return h;
414 return 1;
415}
416
417/* Return number of characters in line in M at vpos VPOS,
418 except don't count leading and trailing spaces
419 unless the terminal requires those to be explicitly output. */
420
421static unsigned int
422line_draw_cost (m, vpos)
502b9b64 423 struct frame_glyphs *m;
4588ec20
JB
424 int vpos;
425{
426 register GLYPH *beg = m->glyphs[vpos];
427 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
428 register int i;
429 register int tlen = GLYPH_TABLE_LENGTH;
430 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
431
432 /* Ignore trailing and leading spaces if we can. */
433 if (!must_write_spaces)
434 {
435 while ((end != beg) && (*end == SPACEGLYPH))
436 --end;
437 if (end == beg)
438 return (0); /* All blank line. */
439
440 while (*beg == SPACEGLYPH)
441 ++beg;
442 }
443
444 /* If we don't have a glyph-table, each glyph is one character,
445 so return the number of glyphs. */
446 if (tbase == 0)
447 return end - beg;
448
449 /* Otherwise, scan the glyphs and accumulate their total size in I. */
450 i = 0;
451 while ((beg <= end) && *beg)
452 {
453 register GLYPH g = *beg++;
454
455 if (GLYPH_SIMPLE_P (tbase, tlen, g))
456 i += 1;
457 else
458 i += GLYPH_LENGTH (tbase, g);
459 }
460 return i;
461}
462\f
463/* The functions on this page are the interface from xdisp.c to redisplay.
464
465 The only other interface into redisplay is through setting
502b9b64
JB
466 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
467 and SET_FRAME_GARBAGED (frame). */
4588ec20
JB
468
469/* cancel_line eliminates any request to display a line at position `vpos' */
470
502b9b64 471cancel_line (vpos, frame)
4588ec20 472 int vpos;
502b9b64 473 register FRAME_PTR frame;
4588ec20 474{
502b9b64 475 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
4588ec20
JB
476}
477
502b9b64
JB
478clear_frame_records (frame)
479 register FRAME_PTR frame;
4588ec20 480{
502b9b64 481 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
4588ec20
JB
482}
483
836d2cde
RS
484/* Clear out all display lines for a coming redisplay. */
485
486void
487init_desired_glyphs (frame)
488 register FRAME_PTR frame;
489{
490 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
491 int vpos;
492 int height = FRAME_HEIGHT (frame);
493
494 for (vpos = 0; vpos < height; vpos++)
495 desired_glyphs->enable[vpos] = 0;
496}
497
4588ec20
JB
498/* Prepare to display on line VPOS starting at HPOS within it. */
499
500void
502b9b64
JB
501get_display_line (frame, vpos, hpos)
502 register FRAME_PTR frame;
4588ec20
JB
503 int vpos;
504 register int hpos;
505{
502b9b64
JB
506 register struct frame_glyphs *glyphs;
507 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
508 register GLYPH *p;
509
7c3c72ec 510 if (vpos < 0)
4588ec20
JB
511 abort ();
512
4588ec20
JB
513 if (! desired_glyphs->enable[vpos])
514 {
515 desired_glyphs->used[vpos] = 0;
516 desired_glyphs->highlight[vpos] = 0;
517 desired_glyphs->enable[vpos] = 1;
518 }
519
520 if (hpos > desired_glyphs->used[vpos])
521 {
522 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
523 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
524
525 desired_glyphs->used[vpos] = hpos;
526 while (g != end)
527 *g++ = SPACEGLYPH;
528 }
529}
530
531/* Like bcopy except never gets confused by overlap. */
532
533void
534safe_bcopy (from, to, size)
535 char *from, *to;
536 int size;
537{
b5c685f4 538 if (size <= 0 || from == to)
4588ec20
JB
539 return;
540
b5c685f4
JB
541 /* If the source and destination don't overlap, then bcopy can
542 handle it. If they do overlap, but the destination is lower in
543 memory than the source, we'll assume bcopy can handle that. */
544 if (to < from || from + size <= to)
545 bcopy (from, to, size);
546
547 /* Otherwise, we'll copy from the end. */
548 else
4588ec20 549 {
b5c685f4
JB
550 register char *endf = from + size;
551 register char *endt = to + size;
4588ec20
JB
552
553 /* If TO - FROM is large, then we should break the copy into
554 nonoverlapping chunks of TO - FROM bytes each. However, if
555 TO - FROM is small, then the bcopy function call overhead
556 makes this not worth it. The crossover point could be about
b5c685f4
JB
557 anywhere. Since I don't think the obvious copy loop is too
558 bad, I'm trying to err in its favor. */
4588ec20
JB
559 if (to - from < 64)
560 {
561 do
562 *--endt = *--endf;
563 while (endf != from);
564 }
565 else
566 {
b5c685f4 567 for (;;)
4588ec20
JB
568 {
569 endt -= (to - from);
570 endf -= (to - from);
571
b5c685f4
JB
572 if (endt < to)
573 break;
574
4588ec20
JB
575 bcopy (endf, endt, to - from);
576 }
b5c685f4
JB
577
578 /* If SIZE wasn't a multiple of TO - FROM, there will be a
4588ec20
JB
579 little left over. The amount left over is
580 (endt + (to - from)) - to, which is endt - from. */
581 bcopy (from, to, endt - from);
582 }
583 }
4588ec20
JB
584}
585
98038dc0 586/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
4588ec20
JB
587 DISTANCE may be negative. */
588
589static void
590rotate_vector (vector, size, distance)
591 char *vector;
592 int size;
593 int distance;
594{
595 char *temp = (char *) alloca (size);
596
597 if (distance < 0)
598 distance += size;
599
600 bcopy (vector, temp + distance, size - distance);
601 bcopy (vector + size - distance, temp, distance);
602 bcopy (temp, vector, size);
603}
604
605/* Scroll lines from vpos FROM up to but not including vpos END
606 down by AMOUNT lines (AMOUNT may be negative).
607 Returns nonzero if done, zero if terminal cannot scroll them. */
608
609int
d52bad65 610scroll_frame_lines (frame, from, end, amount, newpos)
502b9b64 611 register FRAME_PTR frame;
d52bad65 612 int from, end, amount, newpos;
4588ec20
JB
613{
614 register int i;
502b9b64
JB
615 register struct frame_glyphs *current_frame
616 = FRAME_CURRENT_GLYPHS (frame);
d52bad65 617 int pos_adjust;
29ec5d84 618 int width = FRAME_WINDOW_WIDTH (frame);
4588ec20
JB
619
620 if (!line_ins_del_ok)
621 return 0;
622
623 if (amount == 0)
624 return 1;
625
626 if (amount > 0)
627 {
502b9b64 628 update_begin (frame);
4588ec20
JB
629 set_terminal_window (end + amount);
630 if (!scroll_region_ok)
631 ins_del_lines (end, -amount);
632 ins_del_lines (from, amount);
633 set_terminal_window (0);
634
502b9b64 635 rotate_vector (current_frame->glyphs + from,
4588ec20
JB
636 sizeof (GLYPH *) * (end + amount - from),
637 amount * sizeof (GLYPH *));
638
60a8948a 639 rotate_vector (current_frame->charstarts + from,
d52bad65
RS
640 sizeof (int *) * (end + amount - from),
641 amount * sizeof (int *));
642
23b0200c
RS
643 safe_bcopy (current_frame->used + from,
644 current_frame->used + from + amount,
645 (end - from) * sizeof current_frame->used[0]);
646
647 safe_bcopy (current_frame->highlight + from,
648 current_frame->highlight + from + amount,
649 (end - from) * sizeof current_frame->highlight[0]);
650
651 safe_bcopy (current_frame->enable + from,
652 current_frame->enable + from + amount,
653 (end - from) * sizeof current_frame->enable[0]);
654
d52bad65
RS
655 /* Adjust the lines by an amount
656 that puts the first of them at NEWPOS. */
23b0200c 657 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
60a8948a
RS
658
659 /* Offset each char position in the charstarts lines we moved
660 by pos_adjust. */
23b0200c 661 for (i = from + amount; i < end + amount; i++)
60a8948a 662 {
d52bad65 663 int *line = current_frame->charstarts[i];
60a8948a 664 int col;
23b0200c
RS
665 for (col = 0; col < width; col++)
666 if (line[col] > 0)
667 line[col] += pos_adjust;
60a8948a 668 }
23b0200c 669 for (i = from; i < from + amount; i++)
60a8948a 670 {
d52bad65 671 int *line = current_frame->charstarts[i];
60a8948a
RS
672 int col;
673 line[0] = -1;
23b0200c 674 for (col = 0; col < width; col++)
60a8948a
RS
675 line[col] = 0;
676 }
677
4588ec20
JB
678 /* Mark the lines made empty by scrolling as enabled, empty and
679 normal video. */
502b9b64
JB
680 bzero (current_frame->used + from,
681 amount * sizeof current_frame->used[0]);
682 bzero (current_frame->highlight + from,
683 amount * sizeof current_frame->highlight[0]);
4588ec20
JB
684 for (i = from; i < from + amount; i++)
685 {
502b9b64 686 current_frame->glyphs[i][0] = '\0';
60a8948a 687 current_frame->charstarts[i][0] = -1;
502b9b64 688 current_frame->enable[i] = 1;
4588ec20
JB
689 }
690
502b9b64
JB
691 safe_bcopy (current_frame->bufp + from,
692 current_frame->bufp + from + amount,
693 (end - from) * sizeof current_frame->bufp[0]);
4588ec20 694
fd2e066a
GV
695#ifdef HAVE_WINDOW_SYSTEM
696 if (FRAME_WINDOW_P (frame))
4588ec20 697 {
502b9b64
JB
698 safe_bcopy (current_frame->top_left_x + from,
699 current_frame->top_left_x + from + amount,
700 (end - from) * sizeof current_frame->top_left_x[0]);
4588ec20 701
502b9b64
JB
702 safe_bcopy (current_frame->top_left_y + from,
703 current_frame->top_left_y + from + amount,
704 (end - from) * sizeof current_frame->top_left_y[0]);
4588ec20 705
502b9b64
JB
706 safe_bcopy (current_frame->pix_width + from,
707 current_frame->pix_width + from + amount,
708 (end - from) * sizeof current_frame->pix_width[0]);
4588ec20 709
502b9b64
JB
710 safe_bcopy (current_frame->pix_height + from,
711 current_frame->pix_height + from + amount,
712 (end - from) * sizeof current_frame->pix_height[0]);
448fd7c0
JA
713
714 safe_bcopy (current_frame->max_ascent + from,
715 current_frame->max_ascent + from + amount,
716 (end - from) * sizeof current_frame->max_ascent[0]);
4588ec20 717 }
fd2e066a 718#endif /* HAVE_WINDOW_SYSTEM */
4588ec20 719
502b9b64 720 update_end (frame);
4588ec20
JB
721 }
722 if (amount < 0)
723 {
502b9b64 724 update_begin (frame);
4588ec20
JB
725 set_terminal_window (end);
726 ins_del_lines (from + amount, amount);
727 if (!scroll_region_ok)
728 ins_del_lines (end + amount, -amount);
729 set_terminal_window (0);
730
502b9b64 731 rotate_vector (current_frame->glyphs + from + amount,
4588ec20
JB
732 sizeof (GLYPH *) * (end - from - amount),
733 amount * sizeof (GLYPH *));
734
60a8948a 735 rotate_vector (current_frame->charstarts + from + amount,
d52bad65
RS
736 sizeof (int *) * (end - from - amount),
737 amount * sizeof (int *));
738
23b0200c
RS
739 safe_bcopy (current_frame->used + from,
740 current_frame->used + from + amount,
741 (end - from) * sizeof current_frame->used[0]);
742
743 safe_bcopy (current_frame->highlight + from,
744 current_frame->highlight + from + amount,
745 (end - from) * sizeof current_frame->highlight[0]);
746
747 safe_bcopy (current_frame->enable + from,
748 current_frame->enable + from + amount,
749 (end - from) * sizeof current_frame->enable[0]);
750
d52bad65
RS
751 /* Adjust the lines by an amount
752 that puts the first of them at NEWPOS. */
23b0200c 753 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
60a8948a
RS
754
755 /* Offset each char position in the charstarts lines we moved
756 by pos_adjust. */
757 for (i = from + amount; i < end + amount; i++)
758 {
d52bad65 759 int *line = current_frame->charstarts[i];
60a8948a 760 int col;
23b0200c
RS
761 for (col = 0; col < width; col++)
762 if (line[col] > 0)
763 line[col] += pos_adjust;
60a8948a 764 }
23b0200c 765 for (i = end + amount; i < end; i++)
60a8948a 766 {
d52bad65 767 int *line = current_frame->charstarts[i];
60a8948a
RS
768 int col;
769 line[0] = -1;
23b0200c 770 for (col = 0; col < width; col++)
60a8948a
RS
771 line[col] = 0;
772 }
773
4588ec20
JB
774 /* Mark the lines made empty by scrolling as enabled, empty and
775 normal video. */
502b9b64
JB
776 bzero (current_frame->used + end + amount,
777 - amount * sizeof current_frame->used[0]);
778 bzero (current_frame->highlight + end + amount,
779 - amount * sizeof current_frame->highlight[0]);
4588ec20
JB
780 for (i = end + amount; i < end; i++)
781 {
502b9b64 782 current_frame->glyphs[i][0] = '\0';
60a8948a 783 current_frame->charstarts[i][0] = 0;
502b9b64 784 current_frame->enable[i] = 1;
4588ec20
JB
785 }
786
502b9b64
JB
787 safe_bcopy (current_frame->bufp + from,
788 current_frame->bufp + from + amount,
789 (end - from) * sizeof current_frame->bufp[0]);
4588ec20 790
fd2e066a
GV
791#ifdef HAVE_WINDOW_SYSTEM
792 if (FRAME_WINDOW_P (frame))
4588ec20 793 {
502b9b64
JB
794 safe_bcopy (current_frame->top_left_x + from,
795 current_frame->top_left_x + from + amount,
796 (end - from) * sizeof current_frame->top_left_x[0]);
4588ec20 797
502b9b64
JB
798 safe_bcopy (current_frame->top_left_y + from,
799 current_frame->top_left_y + from + amount,
800 (end - from) * sizeof current_frame->top_left_y[0]);
4588ec20 801
502b9b64
JB
802 safe_bcopy (current_frame->pix_width + from,
803 current_frame->pix_width + from + amount,
804 (end - from) * sizeof current_frame->pix_width[0]);
4588ec20 805
502b9b64
JB
806 safe_bcopy (current_frame->pix_height + from,
807 current_frame->pix_height + from + amount,
808 (end - from) * sizeof current_frame->pix_height[0]);
448fd7c0
JA
809
810 safe_bcopy (current_frame->max_ascent + from,
811 current_frame->max_ascent + from + amount,
812 (end - from) * sizeof current_frame->max_ascent[0]);
4588ec20 813 }
fd2e066a 814#endif /* HAVE_WINDOW_SYSTEM */
4588ec20 815
502b9b64 816 update_end (frame);
4588ec20
JB
817 }
818 return 1;
819}
820\f
502b9b64 821/* After updating a window W that isn't the full frame wide,
4588ec20 822 copy all the columns that W does not occupy
502b9b64
JB
823 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
824 so that update_frame will not change those columns. */
4588ec20
JB
825
826preserve_other_columns (w)
827 struct window *w;
828{
829 register int vpos;
502b9b64
JB
830 register struct frame_glyphs *current_frame, *desired_frame;
831 register FRAME_PTR frame = XFRAME (w->frame);
9bfd4456
RS
832 int start = WINDOW_LEFT_MARGIN (w);
833 int end = WINDOW_RIGHT_EDGE (w);
4588ec20
JB
834 int bot = XFASTINT (w->top) + XFASTINT (w->height);
835
502b9b64
JB
836 current_frame = FRAME_CURRENT_GLYPHS (frame);
837 desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
838
839 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
840 {
502b9b64 841 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
4588ec20
JB
842 {
843 if (start > 0)
844 {
845 int len;
846
502b9b64 847 bcopy (current_frame->glyphs[vpos],
aec9f5f6 848 desired_frame->glyphs[vpos],
4b34bd81 849 start * sizeof (current_frame->glyphs[vpos][0]));
60a8948a
RS
850 bcopy (current_frame->charstarts[vpos],
851 desired_frame->charstarts[vpos],
4b34bd81 852 start * sizeof (current_frame->charstarts[vpos][0]));
502b9b64
JB
853 len = min (start, current_frame->used[vpos]);
854 if (desired_frame->used[vpos] < len)
855 desired_frame->used[vpos] = len;
4588ec20 856 }
502b9b64
JB
857 if (current_frame->used[vpos] > end
858 && desired_frame->used[vpos] < current_frame->used[vpos])
4588ec20 859 {
502b9b64 860 while (desired_frame->used[vpos] < end)
60a8948a
RS
861 {
862 int used = desired_frame->used[vpos]++;
863 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
864 desired_frame->glyphs[vpos][used] = 0;
865 }
502b9b64
JB
866 bcopy (current_frame->glyphs[vpos] + end,
867 desired_frame->glyphs[vpos] + end,
aec9f5f6 868 ((current_frame->used[vpos] - end)
4b34bd81 869 * sizeof (current_frame->glyphs[vpos][0])));
60a8948a
RS
870 bcopy (current_frame->charstarts[vpos] + end,
871 desired_frame->charstarts[vpos] + end,
872 ((current_frame->used[vpos] - end)
4b34bd81 873 * sizeof (current_frame->charstarts[vpos][0])));
502b9b64 874 desired_frame->used[vpos] = current_frame->used[vpos];
4588ec20
JB
875 }
876 }
877 }
878}
879\f
880#if 0
881
502b9b64 882/* If window w does not need to be updated and isn't the full frame wide,
4588ec20 883 copy all the columns that w does occupy
502b9b64
JB
884 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
885 so that update_frame will not change those columns.
4588ec20
JB
886
887 Have not been able to figure out how to use this correctly. */
888
889preserve_my_columns (w)
890 struct window *w;
891{
892 register int vpos, fin;
502b9b64
JB
893 register struct frame_glyphs *l1, *l2;
894 register FRAME_PTR frame = XFRAME (w->frame);
9bfd4456
RS
895 int start = WINDOW_LEFT_MARGIN (w);
896 int end = WINDOW_RIGHT_EDGE (w);
4588ec20
JB
897 int bot = XFASTINT (w->top) + XFASTINT (w->height);
898
899 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
900 {
502b9b64
JB
901 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
902 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
4588ec20
JB
903 {
904 if (l2->length > start && l1->length < l2->length)
905 {
906 fin = l2->length;
907 if (fin > end) fin = end;
908 while (l1->length < start)
909 l1->body[l1->length++] = ' ';
910 bcopy (l2->body + start, l1->body + start, fin - start);
911 l1->length = fin;
912 }
913 }
914 }
915}
916
917#endif
918\f
b64b3980 919/* Adjust by ADJUST the charstart values in window W
23b0200c 920 after vpos VPOS, which counts relative to the frame
b64b3980
RS
921 (not relative to W itself). */
922
923void
924adjust_window_charstarts (w, vpos, adjust)
925 struct window *w;
926 int vpos;
927 int adjust;
928{
9bfd4456 929 int left = WINDOW_LEFT_MARGIN (w);
b64b3980 930 int top = XFASTINT (w->top);
23b0200c
RS
931 int right = left + window_internal_width (w);
932 int bottom = top + window_internal_height (w);
b64b3980
RS
933 int i;
934
23b0200c 935 for (i = vpos + 1; i < bottom; i++)
b64b3980
RS
936 {
937 int *charstart
938 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
939 int j;
940 for (j = left; j < right; j++)
941 if (charstart[j] > 0)
942 charstart[j] += adjust;
943 }
944}
23b0200c 945
352f1545
RS
946/* Check the charstarts values in the area of window W
947 for internal consistency. We cannot check that they are "right";
948 we can only look for something nonsensical. */
949
23b0200c
RS
950verify_charstarts (w)
951 struct window *w;
952{
953 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
954 int i;
955 int top = XFASTINT (w->top);
956 int bottom = top + window_internal_height (w);
9bfd4456 957 int left = WINDOW_LEFT_MARGIN (w);
23b0200c
RS
958 int right = left + window_internal_width (w);
959 int next_line;
352f1545
RS
960 int truncate = (XINT (w->hscroll)
961 || (truncate_partial_width_windows
9bfd4456 962 && !WINDOW_FULL_WIDTH_P (w))
352f1545 963 || !NILP (XBUFFER (w->buffer)->truncate_lines));
23b0200c
RS
964
965 for (i = top; i < bottom; i++)
966 {
967 int j;
968 int last;
352f1545 969 int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
23b0200c
RS
970
971 if (i != top)
352f1545
RS
972 {
973 if (truncate)
974 {
975 /* If we are truncating lines, allow a jump
976 in charstarts from one line to the next. */
977 if (charstart[left] < next_line)
978 abort ();
979 }
980 else
981 {
982 if (charstart[left] != next_line)
983 abort ();
984 }
985 }
23b0200c
RS
986
987 for (j = left; j < right; j++)
988 if (charstart[j] > 0)
989 last = charstart[j];
2e8907d3
RS
990 /* Record where the next line should start. */
991 next_line = last;
992 if (BUF_ZV (XBUFFER (w->buffer)) != last)
993 {
994 /* If there's a newline between the two lines, count that. */
995 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
996 if (endchar == '\n')
997 next_line++;
998 }
23b0200c
RS
999 }
1000}
b64b3980 1001\f
4588ec20
JB
1002/* On discovering that the redisplay for a window was no good,
1003 cancel the columns of that window, so that when the window is
1004 displayed over again get_display_line will not complain. */
1005
1006cancel_my_columns (w)
1007 struct window *w;
1008{
1009 register int vpos;
60a8948a
RS
1010 register struct frame_glyphs *desired_glyphs
1011 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
9bfd4456 1012 register int start = WINDOW_LEFT_MARGIN (w);
4588ec20
JB
1013 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
1014
1015 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
1016 if (desired_glyphs->enable[vpos]
1017 && desired_glyphs->used[vpos] >= start)
1018 desired_glyphs->used[vpos] = start;
1019}
1020\f
502b9b64 1021/* These functions try to perform directly and immediately on the frame
4588ec20
JB
1022 the necessary output for one change in the buffer.
1023 They may return 0 meaning nothing was done if anything is difficult,
1024 or 1 meaning the output was performed properly.
502b9b64 1025 They assume that the frame was up to date before the buffer
94aa5d2d 1026 change being displayed. They make various other assumptions too;
4588ec20
JB
1027 see command_loop_1 where these are called. */
1028
1029int
1030direct_output_for_insert (g)
1031 int g;
1032{
502b9b64
JB
1033 register FRAME_PTR frame = selected_frame;
1034 register struct frame_glyphs *current_frame
1035 = FRAME_CURRENT_GLYPHS (frame);
4588ec20
JB
1036
1037#ifndef COMPILER_REGISTER_BUG
1038 register
1039#endif /* COMPILER_REGISTER_BUG */
1040 struct window *w = XWINDOW (selected_window);
1041#ifndef COMPILER_REGISTER_BUG
1042 register
1043#endif /* COMPILER_REGISTER_BUG */
502b9b64 1044 int hpos = FRAME_CURSOR_X (frame);
4588ec20
JB
1045#ifndef COMPILER_REGISTER_BUG
1046 register
1047#endif /* COMPILER_REGISTER_BUG */
502b9b64 1048 int vpos = FRAME_CURSOR_Y (frame);
4588ec20 1049
fa61c701 1050 /* Give up if about to continue line. */
9bfd4456 1051 if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1
fa61c701 1052
4588ec20 1053 /* Avoid losing if cursor is in invisible text off left margin */
9bfd4456 1054 || (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w))
4588ec20
JB
1055
1056 /* Give up if cursor outside window (in minibuf, probably) */
648fa17d 1057 || cursor_in_echo_area
502b9b64
JB
1058 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1059 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
4588ec20 1060
502b9b64 1061 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
4588ec20
JB
1062 || !display_completed
1063
1064 /* Give up if buffer appears in two places. */
1065 || buffer_shared > 1
1066
d169fe39
RS
1067#ifdef USE_TEXT_PROPERTIES
1068 /* Intervals have already been adjusted, point is after the
1069 character that was just inserted. */
ef4d2f9e 1070 /* Give up if character is invisible. */
d169fe39
RS
1071 /* Give up if character has a face property.
1072 At the moment we only lose at end of line or end of buffer
1073 and only with faces that have some background */
1074 /* Instead of wasting time, give up if character has any text properties */
6ec8bbd2 1075 || ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil))
d169fe39
RS
1076#endif
1077
4588ec20
JB
1078 /* Give up if w is minibuffer and a message is being displayed there */
1079 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1080 return 0;
1081
517b2e01 1082 {
19dff8dc 1083 int face = 0;
87485d6f 1084#ifdef HAVE_FACES
517b2e01 1085 int dummy;
19dff8dc 1086
93e54836 1087 if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame))
6ec8bbd2 1088 face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0);
517b2e01 1089#endif
a1c3de84 1090 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
6ec8bbd2 1091 current_frame->charstarts[vpos][hpos] = PT - 1;
839c7dfb 1092 /* Record the entry for after the newly inserted character. */
6ec8bbd2 1093 current_frame->charstarts[vpos][hpos + 1] = PT;
b64b3980 1094 adjust_window_charstarts (w, vpos, 1);
517b2e01 1095 }
4588ec20
JB
1096 unchanged_modified = MODIFF;
1097 beg_unchanged = GPT - BEG;
6ec8bbd2 1098 XSETFASTINT (w->last_point, PT);
4673d3e5 1099 XSETFASTINT (w->last_point_x, hpos + 1);
a5d8b611 1100 XSETFASTINT (w->last_modified, MODIFF);
663b3df3 1101 XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
4588ec20
JB
1102
1103 reassert_line_highlight (0, vpos);
502b9b64 1104 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
4588ec20 1105 fflush (stdout);
502b9b64
JB
1106 ++FRAME_CURSOR_X (frame);
1107 if (hpos == current_frame->used[vpos])
4588ec20 1108 {
502b9b64
JB
1109 current_frame->used[vpos] = hpos + 1;
1110 current_frame->glyphs[vpos][hpos + 1] = 0;
4588ec20
JB
1111 }
1112
1113 return 1;
1114}
1115
1116int
1117direct_output_forward_char (n)
1118 int n;
1119{
502b9b64 1120 register FRAME_PTR frame = selected_frame;
4588ec20 1121 register struct window *w = XWINDOW (selected_window);
254277e1 1122 Lisp_Object position;
ea0d86af
RS
1123 int hpos = FRAME_CURSOR_X (frame);
1124
1125 /* Give up if in truncated text at end of line. */
ba704fd4 1126 /* This check is not redundant. */
9bfd4456 1127 if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1)
ea0d86af 1128 return 0;
24e86043
KH
1129
1130 /* Give up if the buffer's direction is reversed (i.e. right-to-left). */
1131 if (!NILP (XBUFFER(w->buffer)->direction_reversed))
1132 return 0;
ea0d86af 1133
a9764248
JB
1134 /* Avoid losing if cursor is in invisible text off left margin
1135 or about to go off either side of window. */
9bfd4456 1136 if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w)
a9764248
JB
1137 && (XINT (w->hscroll) || n < 0))
1138 || (n > 0
24e86043
KH
1139 && (FRAME_CURSOR_X (frame) + 1
1140 >= XFASTINT (w->left) + window_internal_width (w) - 1))
1141 /* BUG FIX: Added "XFASTINT (w->left)". Without this,
1142 direct_output_forward_char() always fails on "the right"
1143 window. */
648fa17d 1144 || cursor_in_echo_area)
4588ec20 1145 return 0;
15874c59 1146
de83c314
RS
1147 /* Can't use direct output if highlighting a region. */
1148 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1149 return 0;
1150
15874c59
KH
1151 /* Can't use direct output at an overlay boundary; it might have
1152 before-string or after-string properties. */
1153 if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
1154 return 0;
1155
d169fe39
RS
1156#ifdef USE_TEXT_PROPERTIES
1157 /* Don't use direct output next to an invisible character
1158 since we might need to do something special. */
1159
6ec8bbd2 1160 XSETFASTINT (position, PT);
2f24f5ac 1161 if (XFASTINT (position) < ZV
294634fb 1162 && ! NILP (Fget_char_property (position,
2f24f5ac 1163 Qinvisible,
294634fb
KH
1164 selected_window)))
1165 return 0;
d169fe39 1166
6ec8bbd2 1167 XSETFASTINT (position, PT - 1);
2f24f5ac 1168 if (XFASTINT (position) >= BEGV
294634fb 1169 && ! NILP (Fget_char_property (position,
2f24f5ac 1170 Qinvisible,
294634fb
KH
1171 selected_window)))
1172 return 0;
d169fe39
RS
1173#endif
1174
502b9b64 1175 FRAME_CURSOR_X (frame) += n;
a5d8b611 1176 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
6ec8bbd2 1177 XSETFASTINT (w->last_point, PT);
502b9b64 1178 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
4588ec20 1179 fflush (stdout);
d169fe39 1180
4588ec20
JB
1181 return 1;
1182}
1183\f
1184static void update_line ();
1185
502b9b64 1186/* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
4588ec20
JB
1187 Value is nonzero if redisplay stopped due to pending input.
1188 FORCE nonzero means do not stop for pending input. */
1189
1190int
502b9b64
JB
1191update_frame (f, force, inhibit_hairy_id)
1192 FRAME_PTR f;
4588ec20
JB
1193 int force;
1194 int inhibit_hairy_id;
1195{
54633da0 1196 register struct frame_glyphs *current_frame;
7098a0fa 1197 register struct frame_glyphs *desired_frame = 0;
4588ec20
JB
1198 register int i;
1199 int pause;
1200 int preempt_count = baud_rate / 2400 + 1;
1201 extern input_pending;
fd2e066a 1202#ifdef HAVE_WINDOW_SYSTEM
4588ec20
JB
1203 register int downto, leftmost;
1204#endif
1205
c37e4889
RS
1206 if (baud_rate != FRAME_COST_BAUD_RATE (f))
1207 calculate_costs (f);
1208
d88c2b9e
RS
1209 if (preempt_count <= 0)
1210 preempt_count = 1;
1211
502b9b64 1212 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1213
1214 detect_input_pending ();
1215 if (input_pending && !force)
1216 {
1217 pause = 1;
1218 goto do_pause;
1219 }
1220
502b9b64 1221 update_begin (f);
4588ec20
JB
1222
1223 if (!line_ins_del_ok)
1224 inhibit_hairy_id = 1;
1225
7098a0fa
RS
1226 /* These are separate to avoid a possible bug in the AIX C compiler. */
1227 current_frame = FRAME_CURRENT_GLYPHS (f);
1228 desired_frame = FRAME_DESIRED_GLYPHS (f);
1229
efb859b4
JB
1230 /* See if any of the desired lines are enabled; don't compute for
1231 i/d line if just want cursor motion. */
502b9b64
JB
1232 for (i = 0; i < FRAME_HEIGHT (f); i++)
1233 if (desired_frame->enable[i])
4588ec20
JB
1234 break;
1235
1236 /* Try doing i/d line, if not yet inhibited. */
502b9b64
JB
1237 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1238 force |= scrolling (f);
4588ec20
JB
1239
1240 /* Update the individual lines as needed. Do bottom line first. */
1241
502b9b64
JB
1242 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1243 update_line (f, FRAME_HEIGHT (f) - 1);
4588ec20 1244
fd2e066a
GV
1245#ifdef HAVE_WINDOW_SYSTEM
1246 if (FRAME_WINDOW_P (f))
4588ec20 1247 {
fd2e066a 1248 leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
502b9b64 1249 if (desired_frame->enable[0])
4588ec20 1250 {
502b9b64
JB
1251 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1252 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
fd2e066a 1253 = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
448fd7c0 1254 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
502b9b64
JB
1255 current_frame->top_left_x[0] = leftmost;
1256 current_frame->top_left_y[0] = downto;
4588ec20
JB
1257 }
1258 }
fd2e066a 1259#endif /* HAVE_WINDOW_SYSTEM */
4588ec20
JB
1260
1261 /* Now update the rest of the lines. */
502b9b64 1262 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
4588ec20 1263 {
502b9b64 1264 if (desired_frame->enable[i])
4588ec20 1265 {
b6a65ac2 1266 if (FRAME_TERMCAP_P (f))
4588ec20
JB
1267 {
1268 /* Flush out every so many lines.
1269 Also flush out if likely to have more than 1k buffered
1270 otherwise. I'm told that some telnet connections get
1271 really screwed by more than 1k output at once. */
1272 int outq = PENDING_OUTPUT_COUNT (stdout);
1273 if (outq > 900
1274 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1275 {
1276 fflush (stdout);
1277 if (preempt_count == 1)
1278 {
a41f8bed
JB
1279#ifdef EMACS_OUTQSIZE
1280 if (EMACS_OUTQSIZE (0, &outq) < 0)
4588ec20
JB
1281 /* Probably not a tty. Ignore the error and reset
1282 * the outq count. */
1283 outq = PENDING_OUTPUT_COUNT (stdout);
1284#endif
1285 outq *= 10;
d520f0d2 1286 if (baud_rate <= outq && baud_rate > 0)
d88c2b9e 1287 sleep (outq / baud_rate);
4588ec20
JB
1288 }
1289 }
4588ec20
JB
1290 }
1291
a2960116
RS
1292 if ((i - 1) % preempt_count == 0)
1293 detect_input_pending ();
1294
502b9b64 1295 update_line (f, i);
fd2e066a
GV
1296#ifdef HAVE_WINDOW_SYSTEM
1297 if (FRAME_WINDOW_P (f))
4588ec20 1298 {
502b9b64
JB
1299 current_frame->top_left_y[i] = downto;
1300 current_frame->top_left_x[i] = leftmost;
4588ec20 1301 }
fd2e066a 1302#endif /* HAVE_WINDOW_SYSTEM */
4588ec20
JB
1303 }
1304
fd2e066a
GV
1305#ifdef HAVE_WINDOW_SYSTEM
1306 if (FRAME_WINDOW_P (f))
448fd7c0 1307 downto += current_frame->pix_height[i];
fd2e066a 1308#endif /* HAVE_WINDOW_SYSTEM */
4588ec20 1309 }
502b9b64 1310 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
4588ec20
JB
1311
1312 /* Now just clean up termcap drivers and set cursor, etc. */
1313 if (!pause)
1314 {
48cf7030 1315 if ((cursor_in_echo_area
2577053b
RS
1316 /* If we are showing a message instead of the minibuffer,
1317 show the cursor for the message instead of for the
1318 (now hidden) minibuffer contents. */
1319 || (EQ (minibuf_window, selected_window)
1320 && EQ (minibuf_window, echo_area_window)
1321 && echo_area_glyphs != 0))
1322 /* These cases apply only to the frame that contains
1323 the active minibuffer window. */
1324 && FRAME_HAS_MINIBUF_P (f)
140f8645 1325 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
1113d9db 1326 {
648fa17d
JB
1327 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1328 int row, col;
1329
1330 if (cursor_in_echo_area < 0)
1331 {
1332 row = top;
1333 col = 0;
1334 }
1113d9db 1335 else
648fa17d
JB
1336 {
1337 /* If the minibuffer is several lines high, find the last
1338 line that has any text on it. */
1339 row = FRAME_HEIGHT (f);
1340 do
1341 {
1342 row--;
1343 if (current_frame->enable[row])
1344 col = current_frame->used[row];
1345 else
1346 col = 0;
1347 }
1348 while (row > top && col == 0);
1349
29ec5d84 1350 if (col >= FRAME_WINDOW_WIDTH (f))
648fa17d
JB
1351 {
1352 col = 0;
1353 if (row < FRAME_HEIGHT (f) - 1)
1354 row++;
1355 }
1356 }
1357
1358 cursor_to (row, col);
1113d9db 1359 }
4588ec20 1360 else
9bfd4456 1361 cursor_to (FRAME_CURSOR_Y (f),
ceafe86b 1362 minmax (0, FRAME_CURSOR_X (f), FRAME_WINDOW_WIDTH (f) - 1));
4588ec20
JB
1363 }
1364
502b9b64 1365 update_end (f);
4588ec20
JB
1366
1367 if (termscript)
1368 fflush (termscript);
1369 fflush (stdout);
1370
1371 /* Here if output is preempted because input is detected. */
1372 do_pause:
1373
502b9b64 1374 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1375 display_completed = !pause;
1376
f5843453 1377 bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
4588ec20
JB
1378 return pause;
1379}
1380
1381/* Called when about to quit, to check for doing so
1382 at an improper time. */
1383
1384void
1385quit_error_check ()
1386{
1c78509b 1387#if 0
502b9b64 1388 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
4588ec20 1389 return;
502b9b64 1390 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
4588ec20 1391 abort ();
502b9b64 1392 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
4588ec20 1393 abort ();
1c78509b 1394#endif
4588ec20
JB
1395}
1396\f
1397/* Decide what insert/delete line to do, and do it */
1398
1399extern void scrolling_1 ();
1400
502b9b64
JB
1401scrolling (frame)
1402 FRAME_PTR frame;
4588ec20
JB
1403{
1404 int unchanged_at_top, unchanged_at_bottom;
1405 int window_size;
1406 int changed_lines;
502b9b64
JB
1407 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1408 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1409 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
190bb91a 1410 int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
4588ec20 1411 register int i;
502b9b64
JB
1412 int free_at_end_vpos = FRAME_HEIGHT (frame);
1413 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1414 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
1415
1416 /* Compute hash codes of all the lines.
1417 Also calculate number of changed lines,
1418 number of unchanged lines at the beginning,
1419 and number of unchanged lines at the end. */
1420
1421 changed_lines = 0;
1422 unchanged_at_top = 0;
502b9b64
JB
1423 unchanged_at_bottom = FRAME_HEIGHT (frame);
1424 for (i = 0; i < FRAME_HEIGHT (frame); i++)
4588ec20
JB
1425 {
1426 /* Give up on this scrolling if some old lines are not enabled. */
502b9b64 1427 if (!current_frame->enable[i])
4588ec20 1428 return 0;
502b9b64
JB
1429 old_hash[i] = line_hash_code (current_frame, i);
1430 if (! desired_frame->enable[i])
f188b3c4
RS
1431 {
1432 /* This line cannot be redrawn, so don't let scrolling mess it. */
1433 new_hash[i] = old_hash[i];
1434#define INFINITY 1000000 /* Taken from scroll.c */
1435 draw_cost[i] = INFINITY;
1436 }
4588ec20 1437 else
f188b3c4
RS
1438 {
1439 new_hash[i] = line_hash_code (desired_frame, i);
1440 draw_cost[i] = line_draw_cost (desired_frame, i);
1441 }
4588ec20
JB
1442
1443 if (old_hash[i] != new_hash[i])
1444 {
1445 changed_lines++;
502b9b64 1446 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
4588ec20
JB
1447 }
1448 else if (i == unchanged_at_top)
1449 unchanged_at_top++;
190bb91a 1450 old_draw_cost[i] = line_draw_cost (current_frame, i);
4588ec20
JB
1451 }
1452
1453 /* If changed lines are few, don't allow preemption, don't scroll. */
190bb91a 1454 if (!scroll_region_ok && changed_lines < baud_rate / 2400
502b9b64 1455 || unchanged_at_bottom == FRAME_HEIGHT (frame))
4588ec20
JB
1456 return 1;
1457
502b9b64 1458 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
4588ec20
JB
1459 - unchanged_at_bottom);
1460
1461 if (scroll_region_ok)
1462 free_at_end_vpos -= unchanged_at_bottom;
502b9b64 1463 else if (memory_below_frame)
4588ec20
JB
1464 free_at_end_vpos = -1;
1465
1466 /* If large window, fast terminal and few lines in common between
502b9b64 1467 current frame and desired frame, don't bother with i/d calc. */
190bb91a 1468 if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
4588ec20
JB
1469 && (window_size >=
1470 10 * scrolling_max_lines_saved (unchanged_at_top,
502b9b64 1471 FRAME_HEIGHT (frame) - unchanged_at_bottom,
4588ec20
JB
1472 old_hash, new_hash, draw_cost)))
1473 return 0;
1474
502b9b64 1475 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
4588ec20 1476 draw_cost + unchanged_at_top - 1,
190bb91a 1477 old_draw_cost + unchanged_at_top - 1,
4588ec20
JB
1478 old_hash + unchanged_at_top - 1,
1479 new_hash + unchanged_at_top - 1,
1480 free_at_end_vpos - unchanged_at_top);
1481
1482 return 0;
1483}
1484\f
1485/* Return the offset in its buffer of the character at location col, line
1486 in the given window. */
1487int
1488buffer_posn_from_coords (window, col, line)
1489 struct window *window;
1490 int col, line;
1491{
ef0fdbb1 1492 int hscroll = XINT (window->hscroll);
9bfd4456 1493 int window_left = WINDOW_LEFT_MARGIN (window);
4588ec20
JB
1494
1495 /* The actual width of the window is window->width less one for the
efb859b4
JB
1496 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1497 window. */
fa61c701 1498 int window_width = window_internal_width (window) - 1;
4588ec20 1499
efb859b4 1500 int startp = marker_position (window->start);
4588ec20
JB
1501
1502 /* Since compute_motion will only operate on the current buffer,
1503 we need to save the old one and restore it when we're done. */
1504 struct buffer *old_current_buffer = current_buffer;
efb859b4 1505 struct position *posn;
4588ec20
JB
1506
1507 current_buffer = XBUFFER (window->buffer);
1508
2ba9ed58
KH
1509 /* We can't get a correct result in this case,
1510 but at least prevent compute_motion from crashing. */
1511 if (startp < BEGV)
1512 startp = BEGV;
1513
502b9b64
JB
1514 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1515 (window->frame))->bufp to avoid scanning from the very top of
efb859b4
JB
1516 the window, but it isn't maintained correctly, and I'm not even
1517 sure I will keep it. */
1518 posn = compute_motion (startp, 0,
94129385
KH
1519 ((window == XWINDOW (minibuf_window) && startp == BEG
1520 ? minibuf_prompt_width : 0)
1521 + (hscroll ? 1 - hscroll : 0)),
1522 0,
fb0f454a 1523 ZV, line, col,
e37f06d7 1524 window_width, hscroll, 0, window);
4588ec20
JB
1525
1526 current_buffer = old_current_buffer;
1527
502b9b64 1528 /* compute_motion considers frame points past the end of a line
efb859b4
JB
1529 to be *after* the newline, i.e. at the start of the next line.
1530 This is reasonable, but not really what we want. So if the
1531 result is on a line below LINE, back it up one character. */
1532 if (posn->vpos > line)
1533 return posn->bufpos - 1;
1534 else
1535 return posn->bufpos;
4588ec20
JB
1536}
1537\f
1538static int
1539count_blanks (r)
1540 register GLYPH *r;
1541{
1542 register GLYPH *p = r;
94aa5d2d
RS
1543 while (*p++ == SPACEGLYPH);
1544 return p - r - 1;
4588ec20
JB
1545}
1546
1547static int
1548count_match (str1, str2)
1549 GLYPH *str1, *str2;
1550{
1551 register GLYPH *p1 = str1;
1552 register GLYPH *p2 = str2;
1553 while (*p1++ == *p2++);
1554 return p1 - str1 - 1;
1555}
1556
1557/* Char insertion/deletion cost vector, from term.c */
1558extern int *char_ins_del_vector;
1559
29ec5d84 1560#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
4588ec20
JB
1561
1562static void
502b9b64
JB
1563update_line (frame, vpos)
1564 register FRAME_PTR frame;
4588ec20
JB
1565 int vpos;
1566{
1567 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
60a8948a 1568 int *temp1;
4588ec20
JB
1569 int tem;
1570 int osp, nsp, begmatch, endmatch, olen, nlen;
24e86043 1571 GLYPH save;
502b9b64
JB
1572 register struct frame_glyphs *current_frame
1573 = FRAME_CURRENT_GLYPHS (frame);
1574 register struct frame_glyphs *desired_frame
1575 = FRAME_DESIRED_GLYPHS (frame);
4588ec20 1576
502b9b64
JB
1577 if (desired_frame->highlight[vpos]
1578 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
4588ec20 1579 {
502b9b64
JB
1580 change_line_highlight (desired_frame->highlight[vpos], vpos,
1581 (current_frame->enable[vpos] ?
1582 current_frame->used[vpos] : 0));
1583 current_frame->enable[vpos] = 0;
4588ec20
JB
1584 }
1585 else
502b9b64 1586 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
4588ec20 1587
502b9b64 1588 if (! current_frame->enable[vpos])
4588ec20
JB
1589 {
1590 olen = 0;
1591 }
1592 else
1593 {
502b9b64
JB
1594 obody = current_frame->glyphs[vpos];
1595 olen = current_frame->used[vpos];
1596 if (! current_frame->highlight[vpos])
4588ec20
JB
1597 {
1598 if (!must_write_spaces)
ed874011 1599 while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
4588ec20
JB
1600 olen--;
1601 }
1602 else
1603 {
1604 /* For an inverse-video line, remember we gave it
502b9b64 1605 spaces all the way to the frame edge
4588ec20
JB
1606 so that the reverse video extends all the way across. */
1607
29ec5d84 1608 while (olen < FRAME_WINDOW_WIDTH (frame) - 1)
4588ec20
JB
1609 obody[olen++] = SPACEGLYPH;
1610 }
1611 }
1612
1613 /* One way or another, this will enable the line being updated. */
502b9b64
JB
1614 current_frame->enable[vpos] = 1;
1615 current_frame->used[vpos] = desired_frame->used[vpos];
1616 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1617 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
4588ec20 1618
fd2e066a
GV
1619#ifdef HAVE_WINDOW_SYSTEM
1620 if (FRAME_WINDOW_P (frame))
4588ec20 1621 {
502b9b64
JB
1622 current_frame->pix_width[vpos]
1623 = current_frame->used[vpos]
fd2e066a 1624 * FONT_WIDTH (FRAME_FONT (frame));
502b9b64 1625 current_frame->pix_height[vpos]
fd2e066a 1626 = FRAME_LINE_HEIGHT (frame);
4588ec20 1627 }
fd2e066a 1628#endif /* HAVE_WINDOW_SYSTEM */
4588ec20 1629
502b9b64 1630 if (!desired_frame->enable[vpos])
4588ec20
JB
1631 {
1632 nlen = 0;
1633 goto just_erase;
1634 }
1635
502b9b64
JB
1636 nbody = desired_frame->glyphs[vpos];
1637 nlen = desired_frame->used[vpos];
4588ec20
JB
1638
1639 /* Pretend trailing spaces are not there at all,
1640 unless for one reason or another we must write all spaces. */
502b9b64 1641 if (! desired_frame->highlight[vpos])
4588ec20
JB
1642 {
1643 if (!must_write_spaces)
1644 /* We know that the previous character byte contains 0. */
1645 while (nbody[nlen - 1] == SPACEGLYPH)
1646 nlen--;
1647 }
1648 else
1649 {
1650 /* For an inverse-video line, give it extra trailing spaces
502b9b64 1651 all the way to the frame edge
4588ec20
JB
1652 so that the reverse video extends all the way across. */
1653
29ec5d84 1654 while (nlen < FRAME_WINDOW_WIDTH (frame) - 1)
4588ec20
JB
1655 nbody[nlen++] = SPACEGLYPH;
1656 }
1657
1658 /* If there's no i/d char, quickly do the best we can without it. */
1659 if (!char_ins_del_ok)
1660 {
1661 int i,j;
1662
76426794
RS
1663#if 0
1664 if (FRAME_X_P (frame))
1665 {
1666 /* Under X, erase everything we are going to rewrite,
1667 and rewrite everything from the first char that's changed.
1668 This is part of supporting fonts like Courier
1669 whose chars can overlap outside the char width. */
1670 for (i = 0; i < nlen; i++)
1671 if (i >= olen || nbody[i] != obody[i])
1672 break;
1673
1674 cursor_to (vpos, i);
1675 if (i != olen)
1676 clear_end_of_line (olen);
1677 write_glyphs (nbody + i, nlen - i);
1678 }
1679 else
1680 {}
1681#endif /* 0 */
4588ec20
JB
1682 for (i = 0; i < nlen; i++)
1683 {
1684 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1685 {
1686 cursor_to (vpos, i);
24e86043
KH
1687 for (j = 1;
1688 (i + j < nlen
1689 && (i + j >= olen || nbody[i + j] != obody[i + j]
1690 || (nbody[i + j] & GLYPH_MASK_PADDING)));
4588ec20
JB
1691 j++);
1692
1693 /* Output this run of non-matching chars. */
1694 write_glyphs (nbody + i, j);
1695 i += j - 1;
1696
1697 /* Now find the next non-match. */
1698 }
1699 }
1700
1701 /* Clear the rest of the line, or the non-clear part of it. */
1702 if (olen > nlen)
1703 {
1704 cursor_to (vpos, nlen);
1705 clear_end_of_line (olen);
1706 }
1707
502b9b64
JB
1708 /* Exchange contents between current_frame and new_frame. */
1709 temp = desired_frame->glyphs[vpos];
1710 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1711 current_frame->glyphs[vpos] = temp;
4588ec20 1712
60a8948a
RS
1713 /* Exchange charstarts between current_frame and new_frame. */
1714 temp1 = desired_frame->charstarts[vpos];
1715 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1716 current_frame->charstarts[vpos] = temp1;
1717
4588ec20
JB
1718 return;
1719 }
1720
1721 if (!olen)
1722 {
502b9b64 1723 nsp = (must_write_spaces || desired_frame->highlight[vpos])
4588ec20
JB
1724 ? 0 : count_blanks (nbody);
1725 if (nlen > nsp)
1726 {
1727 cursor_to (vpos, nsp);
1728 write_glyphs (nbody + nsp, nlen - nsp);
1729 }
1730
502b9b64
JB
1731 /* Exchange contents between current_frame and new_frame. */
1732 temp = desired_frame->glyphs[vpos];
1733 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1734 current_frame->glyphs[vpos] = temp;
4588ec20 1735
60a8948a
RS
1736 /* Exchange charstarts between current_frame and new_frame. */
1737 temp1 = desired_frame->charstarts[vpos];
1738 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1739 current_frame->charstarts[vpos] = temp1;
1740
4588ec20
JB
1741 return;
1742 }
1743
1744 obody[olen] = 1;
1745 save = nbody[nlen];
1746 nbody[nlen] = 0;
1747
1748 /* Compute number of leading blanks in old and new contents. */
1749 osp = count_blanks (obody);
502b9b64 1750 if (!desired_frame->highlight[vpos])
4588ec20
JB
1751 nsp = count_blanks (nbody);
1752 else
1753 nsp = 0;
1754
1755 /* Compute number of matching chars starting with first nonblank. */
1756 begmatch = count_match (obody + osp, nbody + nsp);
1757
1758 /* Spaces in new match implicit space past the end of old. */
1759 /* A bug causing this to be a no-op was fixed in 18.29. */
1760 if (!must_write_spaces && osp + begmatch == olen)
1761 {
1762 np1 = nbody + nsp;
1763 while (np1[begmatch] == SPACEGLYPH)
1764 begmatch++;
1765 }
1766
1767 /* Avoid doing insert/delete char
1768 just cause number of leading spaces differs
1769 when the following text does not match. */
1770 if (begmatch == 0 && osp != nsp)
1771 osp = nsp = min (osp, nsp);
1772
1773 /* Find matching characters at end of line */
1774 op1 = obody + olen;
1775 np1 = nbody + nlen;
1776 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1777 while (op1 > op2 && op1[-1] == np1[-1])
1778 {
1779 op1--;
1780 np1--;
1781 }
1782 endmatch = obody + olen - op1;
1783
1784 /* Put correct value back in nbody[nlen].
1785 This is important because direct_output_for_insert
1786 can write into the line at a later point.
1787 If this screws up the zero at the end of the line, re-establish it. */
1788 nbody[nlen] = save;
1789 obody[olen] = 0;
1790
1791 /* tem gets the distance to insert or delete.
1792 endmatch is how many characters we save by doing so.
1793 Is it worth it? */
1794
1795 tem = (nlen - nsp) - (olen - osp);
1796 if (endmatch && tem
502b9b64 1797 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
4588ec20
JB
1798 endmatch = 0;
1799
1800 /* nsp - osp is the distance to insert or delete.
1801 If that is nonzero, begmatch is known to be nonzero also.
1802 begmatch + endmatch is how much we save by doing the ins/del.
1803 Is it worth it? */
1804
1805 if (nsp != osp
1806 && (!char_ins_del_ok
502b9b64 1807 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
4588ec20
JB
1808 {
1809 begmatch = 0;
1810 endmatch = 0;
1811 osp = nsp = min (osp, nsp);
1812 }
1813
1814 /* Now go through the line, inserting, writing and
1815 deleting as appropriate. */
1816
1817 if (osp > nsp)
1818 {
1819 cursor_to (vpos, nsp);
1820 delete_glyphs (osp - nsp);
1821 }
1822 else if (nsp > osp)
1823 {
1824 /* If going to delete chars later in line
1825 and insert earlier in the line,
1826 must delete first to avoid losing data in the insert */
1827 if (endmatch && nlen < olen + nsp - osp)
1828 {
1829 cursor_to (vpos, nlen - endmatch + osp - nsp);
1830 delete_glyphs (olen + nsp - osp - nlen);
1831 olen = nlen - (nsp - osp);
1832 }
1833 cursor_to (vpos, osp);
1834 insert_glyphs ((char *)0, nsp - osp);
1835 }
1836 olen += nsp - osp;
1837
1838 tem = nsp + begmatch + endmatch;
1839 if (nlen != tem || olen != tem)
1840 {
1841 cursor_to (vpos, nsp + begmatch);
1842 if (!endmatch || nlen == olen)
1843 {
1844 /* If new text being written reaches right margin,
1845 there is no need to do clear-to-eol at the end.
1846 (and it would not be safe, since cursor is not
1847 going to be "at the margin" after the text is done) */
29ec5d84 1848 if (nlen == FRAME_WINDOW_WIDTH (frame))
4588ec20
JB
1849 olen = 0;
1850 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1851
1852#ifdef obsolete
1853
1854/* the following code loses disastrously if tem == nlen.
1855 Rather than trying to fix that case, I am trying the simpler
1856 solution found above. */
1857
1858 /* If the text reaches to the right margin,
1859 it will lose one way or another (depending on AutoWrap)
1860 to clear to end of line after outputting all the text.
1861 So pause with one character to go and clear the line then. */
29ec5d84 1862 if (nlen == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
4588ec20
JB
1863 {
1864 /* endmatch must be zero, and tem must equal nsp + begmatch */
1865 write_glyphs (nbody + tem, nlen - tem - 1);
1866 clear_end_of_line (olen);
1867 olen = 0; /* Don't let it be cleared again later */
1868 write_glyphs (nbody + nlen - 1, 1);
1869 }
1870 else
1871 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1872#endif /* OBSOLETE */
1873
1874 }
1875 else if (nlen > olen)
1876 {
24e86043
KH
1877 /* Here, we used to have the following simple code:
1878 ----------------------------------------
1879 write_glyphs (nbody + nsp + begmatch, olen - tem);
1880 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1881 ----------------------------------------
1882 but it doesn't work if nbody[nsp + begmatch + olen - tem]
1883 is a padding glyph. */
1884 int out = olen - tem; /* Columns to be overwritten originally. */
1885 int del;
1886
1887 /* Calculate columns we can actually overwrite. */
1888 while (nbody[nsp + begmatch + out] & GLYPH_MASK_PADDING) out--;
1889 write_glyphs (nbody + nsp + begmatch, out);
1890 /* If we left columns to be overwritten. we must delete them. */
1891 del = olen - tem - out;
1892 if (del > 0) delete_glyphs (del);
1893 /* At last, we insert columns not yet written out. */
1894 insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
4588ec20
JB
1895 olen = nlen;
1896 }
1897 else if (olen > nlen)
1898 {
1899 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1900 delete_glyphs (olen - nlen);
1901 olen = nlen;
1902 }
1903 }
1904
1905 just_erase:
1906 /* If any unerased characters remain after the new line, erase them. */
1907 if (olen > nlen)
1908 {
1909 cursor_to (vpos, nlen);
1910 clear_end_of_line (olen);
1911 }
1912
502b9b64
JB
1913 /* Exchange contents between current_frame and new_frame. */
1914 temp = desired_frame->glyphs[vpos];
1915 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1916 current_frame->glyphs[vpos] = temp;
60a8948a
RS
1917
1918 /* Exchange charstarts between current_frame and new_frame. */
1919 temp1 = desired_frame->charstarts[vpos];
1920 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1921 current_frame->charstarts[vpos] = temp1;
4588ec20
JB
1922}
1923\f
6f7bbf79
KH
1924/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
1925 session's frames, frame names, buffers, buffer-read-only flags, and
1926 buffer-modified-flags, and a trailing sentinel (so we don't need to
1927 add length checks). */
078b3696
KH
1928static Lisp_Object frame_and_buffer_state;
1929
1930DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
1931 Sframe_or_buffer_changed_p, 0, 0, 0,
1932 "Return non-nil if the frame and buffer state appears to have changed.\n\
1933The state variable is an internal vector containing all frames and buffers,\n\
836d2cde 1934aside from buffers whose names start with space,\n\
078b3696
KH
1935along with the buffers' read-only and modified flags, which allows a fast\n\
1936check to see whether the menu bars might need to be recomputed.\n\
1937If this function returns non-nil, it updates the internal vector to reflect\n\
1938the current state.\n")
1939 ()
1940{
1941 Lisp_Object tail, frame, buf;
1942 Lisp_Object *vecp;
1943 int n;
bd9e3e75 1944
078b3696
KH
1945 vecp = XVECTOR (frame_and_buffer_state)->contents;
1946 FOR_EACH_FRAME (tail, frame)
bd9e3e75
KH
1947 {
1948 if (!EQ (*vecp++, frame))
1949 goto changed;
1950 if (!EQ (*vecp++, XFRAME (frame)->name))
1951 goto changed;
1952 }
50cf83f8
RS
1953 /* Check that the buffer info matches.
1954 No need to test for the end of the vector
1955 because the last element of the vector is lambda
1956 and that will always cause a mismatch. */
078b3696
KH
1957 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1958 {
1959 buf = XCONS (XCONS (tail)->car)->cdr;
836d2cde
RS
1960 /* Ignore buffers that aren't included in buffer lists. */
1961 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
1962 continue;
078b3696
KH
1963 if (!EQ (*vecp++, buf))
1964 goto changed;
1965 if (!EQ (*vecp++, XBUFFER (buf)->read_only))
1966 goto changed;
1967 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
1968 goto changed;
1969 }
50cf83f8 1970 /* Detect deletion of a buffer at the end of the list. */
488f0c64 1971 if (EQ (*vecp, Qlambda))
50cf83f8 1972 return Qnil;
078b3696 1973 changed:
5dad8282 1974 /* Start with 1 so there is room for at least one lambda at the end. */
078b3696
KH
1975 n = 1;
1976 FOR_EACH_FRAME (tail, frame)
d1dad759 1977 n += 2;
078b3696
KH
1978 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1979 n += 3;
267ad509
KH
1980 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
1981 if (n > XVECTOR (frame_and_buffer_state)->size
d1dad759
KH
1982 || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
1983 /* Add 20 extra so we grow it less often. */
1984 frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
078b3696
KH
1985 vecp = XVECTOR (frame_and_buffer_state)->contents;
1986 FOR_EACH_FRAME (tail, frame)
bd9e3e75
KH
1987 {
1988 *vecp++ = frame;
1989 *vecp++ = XFRAME (frame)->name;
1990 }
078b3696
KH
1991 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1992 {
1993 buf = XCONS (XCONS (tail)->car)->cdr;
836d2cde
RS
1994 /* Ignore buffers that aren't included in buffer lists. */
1995 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
1996 continue;
078b3696
KH
1997 *vecp++ = buf;
1998 *vecp++ = XBUFFER (buf)->read_only;
1999 *vecp++ = Fbuffer_modified_p (buf);
2000 }
d1dad759
KH
2001 /* Fill up the vector with lambdas (always at least one). */
2002 *vecp++ = Qlambda;
2003 while (vecp - XVECTOR (frame_and_buffer_state)->contents
2004 < XVECTOR (frame_and_buffer_state)->size)
267ad509 2005 *vecp++ = Qlambda;
d1dad759
KH
2006 /* Make sure we didn't overflow the vector. */
2007 if (vecp - XVECTOR (frame_and_buffer_state)->contents
2008 > XVECTOR (frame_and_buffer_state)->size)
2009 abort ();
078b3696
KH
2010 return Qt;
2011}
2012\f
4588ec20
JB
2013DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
2014 1, 1, "FOpen termscript file: ",
2015 "Start writing all terminal output to FILE as well as the terminal.\n\
2016FILE = nil means just close any termscript file currently open.")
2017 (file)
2018 Lisp_Object file;
2019{
2020 if (termscript != 0) fclose (termscript);
2021 termscript = 0;
2022
efb859b4 2023 if (! NILP (file))
4588ec20
JB
2024 {
2025 file = Fexpand_file_name (file, Qnil);
2026 termscript = fopen (XSTRING (file)->data, "w");
2027 if (termscript == 0)
2028 report_file_error ("Opening termscript", Fcons (file, Qnil));
2029 }
2030 return Qnil;
2031}
2032\f
2033
2034#ifdef SIGWINCH
efb859b4 2035SIGTYPE
61cbef47
RS
2036window_change_signal (signalnum) /* If we don't have an argument, */
2037 int signalnum; /* some compilers complain in signal calls. */
4588ec20
JB
2038{
2039 int width, height;
2040 extern int errno;
2041 int old_errno = errno;
2042
502b9b64 2043 get_frame_size (&width, &height);
4588ec20 2044
502b9b64
JB
2045 /* The frame size change obviously applies to a termcap-controlled
2046 frame. Find such a frame in the list, and assume it's the only
4588ec20 2047 one (since the redisplay code always writes to stdout, not a
502b9b64 2048 FILE * specified in the frame structure). Record the new size,
4588ec20
JB
2049 but don't reallocate the data structures now. Let that be done
2050 later outside of the signal handler. */
2051
2052 {
35f56f96 2053 Lisp_Object tail, frame;
4588ec20 2054
35f56f96 2055 FOR_EACH_FRAME (tail, frame)
4588ec20 2056 {
35f56f96 2057 if (FRAME_TERMCAP_P (XFRAME (frame)))
4588ec20 2058 {
35f56f96 2059 change_frame_size (XFRAME (frame), height, width, 0, 1);
4588ec20
JB
2060 break;
2061 }
2062 }
2063 }
2064
2065 signal (SIGWINCH, window_change_signal);
2066 errno = old_errno;
2067}
2068#endif /* SIGWINCH */
2069
2070
502b9b64 2071/* Do any change in frame size that was requested by a signal. */
4588ec20
JB
2072
2073do_pending_window_change ()
2074{
2075 /* If window_change_signal should have run before, run it now. */
2076 while (delayed_size_change)
2077 {
35f56f96 2078 Lisp_Object tail, frame;
4588ec20
JB
2079
2080 delayed_size_change = 0;
2081
35f56f96 2082 FOR_EACH_FRAME (tail, frame)
4588ec20 2083 {
35f56f96
JB
2084 FRAME_PTR f = XFRAME (frame);
2085
502b9b64
JB
2086 int height = FRAME_NEW_HEIGHT (f);
2087 int width = FRAME_NEW_WIDTH (f);
4588ec20 2088
08f7aa3e 2089 if (height != 0 || width != 0)
b6a65ac2 2090 change_frame_size (f, height, width, 0, 0);
4588ec20
JB
2091 }
2092 }
2093}
2094
2095
502b9b64 2096/* Change the frame height and/or width. Values may be given as zero to
b6a65ac2 2097 indicate no change is to take place.
4588ec20 2098
b6a65ac2
JB
2099 If DELAY is non-zero, then assume we're being called from a signal
2100 handler, and queue the change for later - perhaps the next
2101 redisplay. Since this tries to resize windows, we can't call it
2102 from a signal handler. */
2103
45140e01
RS
2104change_frame_size (f, newheight, newwidth, pretend, delay)
2105 register FRAME_PTR f;
2106 int newheight, newwidth, pretend;
2107{
2108 Lisp_Object tail, frame;
3826ea1a 2109
8a376b3b 2110 if (! FRAME_WINDOW_P (f))
45140e01 2111 {
93e54836
RS
2112 /* When using termcap, or on MS-DOS, all frames use
2113 the same screen, so a change in size affects all frames. */
45140e01 2114 FOR_EACH_FRAME (tail, frame)
8a376b3b 2115 if (! FRAME_WINDOW_P (XFRAME (frame)))
45140e01
RS
2116 change_frame_size_1 (XFRAME (frame), newheight, newwidth,
2117 pretend, delay);
2118 }
2119 else
2120 change_frame_size_1 (f, newheight, newwidth, pretend, delay);
2121}
2122
2123static void
2124change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
502b9b64 2125 register FRAME_PTR frame;
a1d789d0 2126 int newheight, newwidth, pretend, delay;
4588ec20 2127{
9bfd4456 2128 int new_frame_window_width;
3826ea1a 2129 unsigned int total_glyphs;
e523f7e5 2130 int count = specpdl_ptr - specpdl;
3826ea1a 2131
4588ec20 2132 /* If we can't deal with the change now, queue it for later. */
b6a65ac2 2133 if (delay)
4588ec20 2134 {
b6a65ac2 2135 FRAME_NEW_HEIGHT (frame) = newheight;
502b9b64 2136 FRAME_NEW_WIDTH (frame) = newwidth;
4588ec20
JB
2137 delayed_size_change = 1;
2138 return;
2139 }
2140
502b9b64
JB
2141 /* This size-change overrides any pending one for this frame. */
2142 FRAME_NEW_HEIGHT (frame) = 0;
b6a65ac2
JB
2143 FRAME_NEW_WIDTH (frame) = 0;
2144
08f7aa3e 2145 /* If an argument is zero, set it to the current value. */
ae19c6f2
EN
2146 if (newheight == 0)
2147 newheight = FRAME_HEIGHT (frame);
2148 if (newwidth == 0)
2149 newwidth = FRAME_WIDTH (frame);
9bfd4456 2150 new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth);
4588ec20 2151
3826ea1a
RS
2152 total_glyphs = newheight * (newwidth + 2) * sizeof (GLYPH);
2153
2154 /* If these sizes are so big they cause overflow,
2155 just ignore the change. It's not clear what better we could do. */
2156 if (total_glyphs / sizeof (GLYPH) / newheight != newwidth + 2)
2157 return;
2158
b6a65ac2
JB
2159 /* Round up to the smallest acceptable size. */
2160 check_frame_size (frame, &newheight, &newwidth);
2161
2162 /* If we're not changing the frame size, quit now. */
2163 if (newheight == FRAME_HEIGHT (frame)
9bfd4456 2164 && new_frame_window_width == FRAME_WINDOW_WIDTH (frame))
4588ec20
JB
2165 return;
2166
cbb95688
RS
2167 BLOCK_INPUT;
2168
886a8a6c
KH
2169#ifdef MSDOS
2170 /* We only can set screen dimensions to certain values supported
2171 by our video hardware. Try to find the smallest size greater
2172 or equal to the requested dimensions. */
2173 dos_set_window_size (&newheight, &newwidth);
2174#endif
2175
b6a65ac2 2176 if (newheight != FRAME_HEIGHT (frame))
4588ec20 2177 {
b6a65ac2 2178 if (FRAME_HAS_MINIBUF_P (frame)
502b9b64 2179 && ! FRAME_MINIBUF_ONLY_P (frame))
4588ec20 2180 {
502b9b64
JB
2181 /* Frame has both root and minibuffer. */
2182 set_window_height (FRAME_ROOT_WINDOW (frame),
cb470ab1 2183 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
a5d8b611
KH
2184 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
2185 newheight - 1);
502b9b64 2186 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
4588ec20
JB
2187 }
2188 else
502b9b64 2189 /* Frame has just one top-level window. */
cb470ab1
RS
2190 set_window_height (FRAME_ROOT_WINDOW (frame),
2191 newheight - FRAME_MENU_BAR_LINES (frame), 0);
b6a65ac2
JB
2192
2193 if (FRAME_TERMCAP_P (frame) && !pretend)
2194 FrameRows = newheight;
4588ec20
JB
2195
2196#if 0
502b9b64 2197 if (frame->output_method == output_termcap)
4588ec20 2198 {
b6a65ac2 2199 frame_height = newheight;
4588ec20 2200 if (!pretend)
b6a65ac2 2201 FrameRows = newheight;
4588ec20
JB
2202 }
2203#endif
2204 }
2205
9bfd4456 2206 if (new_frame_window_width != FRAME_WINDOW_WIDTH (frame))
4588ec20 2207 {
9bfd4456 2208 set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0);
b6a65ac2 2209 if (FRAME_HAS_MINIBUF_P (frame))
9bfd4456 2210 set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0);
4588ec20 2211
b6a65ac2 2212 if (FRAME_TERMCAP_P (frame) && !pretend)
502b9b64 2213 FrameCols = newwidth;
4588ec20 2214#if 0
502b9b64 2215 if (frame->output_method == output_termcap)
4588ec20 2216 {
502b9b64 2217 frame_width = newwidth;
4588ec20 2218 if (!pretend)
502b9b64 2219 FrameCols = newwidth;
4588ec20
JB
2220 }
2221#endif
2222 }
2223
b6a65ac2 2224 FRAME_HEIGHT (frame) = newheight;
9bfd4456 2225 SET_FRAME_WIDTH (frame, newwidth);
986e61b8 2226
29ec5d84
RS
2227 if (FRAME_CURSOR_X (frame) >= FRAME_WINDOW_WIDTH (frame))
2228 FRAME_CURSOR_X (frame) = FRAME_WINDOW_WIDTH (frame) - 1;
986e61b8
RS
2229 if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
2230 FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
2231
502b9b64
JB
2232 remake_frame_glyphs (frame);
2233 calculate_costs (frame);
97cf50e7
RS
2234
2235 UNBLOCK_INPUT;
61730a69 2236
e523f7e5
RS
2237 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2238
61730a69
RS
2239 /* This isn't quite a no-op: it runs window-configuration-change-hook. */
2240 Fset_window_buffer (FRAME_SELECTED_WINDOW (frame),
2241 XWINDOW (FRAME_SELECTED_WINDOW (frame))->buffer);
e523f7e5
RS
2242
2243 unbind_to (count, Qnil);
4588ec20
JB
2244}
2245\f
2246DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2247 Ssend_string_to_terminal, 1, 1, 0,
2248 "Send STRING to the terminal without alteration.\n\
2249Control characters in STRING will have terminal-dependent effects.")
e912ba09
EN
2250 (string)
2251 Lisp_Object string;
4588ec20 2252{
94f3db62 2253 /* ??? Perhaps we should do something special for multibyte strings here. */
e912ba09 2254 CHECK_STRING (string, 0);
fc932ac6 2255 fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), stdout);
4588ec20
JB
2256 fflush (stdout);
2257 if (termscript)
2258 {
fc932ac6
RS
2259 fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)),
2260 termscript);
4588ec20
JB
2261 fflush (termscript);
2262 }
2263 return Qnil;
2264}
2265
2266DEFUN ("ding", Fding, Sding, 0, 1, 0,
2267 "Beep, or flash the screen.\n\
2268Also, unless an argument is given,\n\
2269terminate any keyboard macro currently executing.")
2270 (arg)
2271 Lisp_Object arg;
2272{
efb859b4 2273 if (!NILP (arg))
4588ec20 2274 {
7fa788da
RS
2275 if (noninteractive)
2276 putchar (07);
2277 else
2278 ring_bell ();
4588ec20
JB
2279 fflush (stdout);
2280 }
2281 else
2282 bitch_at_user ();
2283
2284 return Qnil;
2285}
2286
2287bitch_at_user ()
2288{
2289 if (noninteractive)
2290 putchar (07);
2291 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2292 error ("Keyboard macro terminated by a command ringing the bell");
2293 else
2294 ring_bell ();
2295 fflush (stdout);
2296}
2297
2298DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
767229f8 2299 "Pause, without updating display, for SECONDS seconds.\n\
b07646f5
JB
2300SECONDS may be a floating-point value, meaning that you can wait for a\n\
2301fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2302additional wait period, in milliseconds; this may be useful if your\n\
2303Emacs was built without floating point support.\n\
2304\(Not all operating systems support waiting for a fraction of a second.)")
767229f8
JB
2305 (seconds, milliseconds)
2306 Lisp_Object seconds, milliseconds;
4588ec20 2307{
767229f8 2308 int sec, usec;
4588ec20 2309
767229f8 2310 if (NILP (milliseconds))
e9c9a718 2311 XSETINT (milliseconds, 0);
767229f8
JB
2312 else
2313 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
2314 usec = XINT (milliseconds) * 1000;
2315
2316#ifdef LISP_FLOAT_TYPE
2317 {
2318 double duration = extract_float (seconds);
2319 sec = (int) duration;
2320 usec += (duration - sec) * 1000000;
2321 }
2322#else
2323 CHECK_NUMBER (seconds, 0);
2324 sec = XINT (seconds);
2325#endif
4588ec20 2326
a41f8bed 2327#ifndef EMACS_HAS_USECS
767229f8
JB
2328 if (sec == 0 && usec != 0)
2329 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
4588ec20 2330#endif
767229f8
JB
2331
2332 /* Assure that 0 <= usec < 1000000. */
2333 if (usec < 0)
2334 {
2335 /* We can't rely on the rounding being correct if user is negative. */
2336 if (-1000000 < usec)
2337 sec--, usec += 1000000;
2338 else
2339 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
4588ec20 2340 }
767229f8
JB
2341 else
2342 sec += usec / 1000000, usec %= 1000000;
2343
6b5153b1 2344 if (sec < 0 || (sec == 0 && usec == 0))
767229f8 2345 return Qnil;
4588ec20 2346
f76475ad
JB
2347 {
2348 Lisp_Object zero;
2349
a5d8b611 2350 XSETFASTINT (zero, 0);
f76475ad
JB
2351 wait_reading_process_input (sec, usec, zero, 0);
2352 }
d1af74e9 2353
767229f8
JB
2354 /* We should always have wait_reading_process_input; we have a dummy
2355 implementation for systems which don't support subprocesses. */
2356#if 0
2357 /* No wait_reading_process_input */
4588ec20
JB
2358 immediate_quit = 1;
2359 QUIT;
2360
2361#ifdef VMS
2362 sys_sleep (sec);
2363#else /* not VMS */
2364/* The reason this is done this way
2365 (rather than defined (H_S) && defined (H_T))
2366 is because the VMS preprocessor doesn't grok `defined' */
2367#ifdef HAVE_SELECT
a41f8bed
JB
2368 EMACS_GET_TIME (end_time);
2369 EMACS_SET_SECS_USECS (timeout, sec, usec);
d1af74e9 2370 EMACS_ADD_TIME (end_time, end_time, timeout);
a41f8bed 2371
4588ec20
JB
2372 while (1)
2373 {
a41f8bed
JB
2374 EMACS_GET_TIME (timeout);
2375 EMACS_SUB_TIME (timeout, end_time, timeout);
2376 if (EMACS_TIME_NEG_P (timeout)
2377 || !select (1, 0, 0, 0, &timeout))
4588ec20
JB
2378 break;
2379 }
4588ec20
JB
2380#else /* not HAVE_SELECT */
2381 sleep (sec);
2382#endif /* HAVE_SELECT */
2383#endif /* not VMS */
2384
2385 immediate_quit = 0;
2386#endif /* no subprocesses */
2387
2388 return Qnil;
2389}
2390
f76475ad
JB
2391/* This is just like wait_reading_process_input, except that
2392 it does the redisplay.
2393
ea0d86af 2394 It's also much like Fsit_for, except that it can be used for
836d2cde 2395 waiting for input as well. */
4588ec20 2396
f76475ad 2397Lisp_Object
ae5a0dd4
RS
2398sit_for (sec, usec, reading, display, initial_display)
2399 int sec, usec, reading, display, initial_display;
f76475ad
JB
2400{
2401 Lisp_Object read_kbd;
4588ec20 2402
ccddf474
RS
2403 swallow_events (display);
2404
f80bd2d7 2405 if (detect_input_pending_run_timers (display))
4588ec20 2406 return Qnil;
4588ec20 2407
ae5a0dd4 2408 if (initial_display)
f76475ad 2409 redisplay_preserve_echo_area ();
4588ec20 2410
dfdb645c
JB
2411 if (sec == 0 && usec == 0)
2412 return Qt;
2413
4588ec20 2414#ifdef SIGIO
8fc798e9 2415 gobble_input (0);
f76475ad
JB
2416#endif
2417
e9c9a718 2418 XSETINT (read_kbd, reading ? -1 : 1);
f76475ad
JB
2419 wait_reading_process_input (sec, usec, read_kbd, display);
2420
4588ec20
JB
2421 return detect_input_pending () ? Qnil : Qt;
2422}
2423
f76475ad 2424DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
767229f8 2425 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
b07646f5
JB
2426SECONDS may be a floating-point value, meaning that you can wait for a\n\
2427fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2428additional wait period, in milliseconds; this may be useful if your\n\
2429Emacs was built without floating point support.\n\
2430\(Not all operating systems support waiting for a fraction of a second.)\n\
e912ba09 2431Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
f76475ad
JB
2432Redisplay is preempted as always if input arrives, and does not happen\n\
2433if input is available before it starts.\n\
2434Value is t if waited the full time with no input arriving.")
767229f8
JB
2435 (seconds, milliseconds, nodisp)
2436 Lisp_Object seconds, milliseconds, nodisp;
f76475ad 2437{
767229f8 2438 int sec, usec;
f76475ad 2439
767229f8 2440 if (NILP (milliseconds))
e9c9a718 2441 XSETINT (milliseconds, 0);
767229f8
JB
2442 else
2443 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
2444 usec = XINT (milliseconds) * 1000;
2445
2446#ifdef LISP_FLOAT_TYPE
2447 {
2448 double duration = extract_float (seconds);
2449 sec = (int) duration;
2450 usec += (duration - sec) * 1000000;
2451 }
2452#else
2453 CHECK_NUMBER (seconds, 0);
2454 sec = XINT (seconds);
2455#endif
f76475ad 2456
f76475ad 2457#ifndef EMACS_HAS_USECS
767229f8
JB
2458 if (usec != 0 && sec == 0)
2459 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
f76475ad 2460#endif
f76475ad 2461
ae5a0dd4 2462 return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
f76475ad 2463}
4588ec20
JB
2464\f
2465char *terminal_type;
2466
2467/* Initialization done when Emacs fork is started, before doing stty. */
2468/* Determine terminal type and set terminal_driver */
2469/* Then invoke its decoding routine to set up variables
2470 in the terminal package */
2471
2472init_display ()
2473{
2474#ifdef HAVE_X_WINDOWS
2475 extern int display_arg;
2476#endif
2477
2478 meta_key = 0;
2479 inverse_video = 0;
2480 cursor_in_echo_area = 0;
2481 terminal_type = (char *) 0;
2482
1315c181
JB
2483 /* Now is the time to initialize this; it's used by init_sys_modes
2484 during startup. */
2485 Vwindow_system = Qnil;
4588ec20 2486
1315c181
JB
2487 /* If the user wants to use a window system, we shouldn't bother
2488 initializing the terminal. This is especially important when the
2489 terminal is so dumb that emacs gives up before and doesn't bother
2490 using the window system.
4588ec20 2491
36bbad1d
KH
2492 If the DISPLAY environment variable is set and nonempty,
2493 try to use X, and die with an error message if that doesn't work. */
4588ec20
JB
2494
2495#ifdef HAVE_X_WINDOWS
d460af17
JB
2496 if (! display_arg)
2497 {
36bbad1d 2498 char *display;
d460af17 2499#ifdef VMS
36bbad1d 2500 display = getenv ("DECW$DISPLAY");
d460af17 2501#else
36bbad1d 2502 display = getenv ("DISPLAY");
d460af17 2503#endif
36bbad1d
KH
2504
2505 display_arg = (display != 0 && *display != 0);
f040093a 2506 }
d460af17 2507
9e4555e8
RS
2508 if (!inhibit_window_system && display_arg
2509#ifndef CANNOT_DUMP
2510 && initialized
2511#endif
2512 )
4588ec20
JB
2513 {
2514 Vwindow_system = intern ("x");
2515#ifdef HAVE_X11
2516 Vwindow_system_version = make_number (11);
2517#else
2518 Vwindow_system_version = make_number (10);
039e5d71
KH
2519#endif
2520#if defined (LINUX) && defined (HAVE_LIBNCURSES)
2521 /* In some versions of ncurses,
6a428f77 2522 tputs crashes if we have not called tgetent.
039e5d71
KH
2523 So call tgetent. */
2524 { char b[2044]; tgetent (b, "xterm");}
4588ec20
JB
2525#endif
2526 return;
2527 }
2528#endif /* HAVE_X_WINDOWS */
2529
fd2e066a
GV
2530#ifdef HAVE_NTGUI
2531 if (!inhibit_window_system)
2532 {
60c7469c 2533 Vwindow_system = intern ("w32");
fd2e066a
GV
2534 Vwindow_system_version = make_number (1);
2535 return;
2536 }
2537#endif /* HAVE_NTGUI */
2538
4588ec20
JB
2539 /* If no window system has been specified, try to use the terminal. */
2540 if (! isatty (0))
2541 {
1559a86d 2542 fatal ("standard input is not a tty");
4588ec20
JB
2543 exit (1);
2544 }
2545
2546 /* Look at the TERM variable */
2547 terminal_type = (char *) getenv ("TERM");
2548 if (!terminal_type)
2549 {
2550#ifdef VMS
2551 fprintf (stderr, "Please specify your terminal type.\n\
2552For types defined in VMS, use set term /device=TYPE.\n\
2553For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2554\(The quotation marks are necessary since terminal types are lower case.)\n");
2555#else
2556 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2557#endif
2558 exit (1);
2559 }
2560
2561#ifdef VMS
2562 /* VMS DCL tends to upcase things, so downcase term type.
2563 Hardly any uppercase letters in terminal types; should be none. */
2564 {
2565 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2566 char *p;
2567
2568 strcpy (new, terminal_type);
2569
2570 for (p = new; *p; p++)
2571 if (isupper (*p))
2572 *p = tolower (*p);
2573
2574 terminal_type = new;
2575 }
2576#endif
2577
2578 term_init (terminal_type);
2579
d86c299a
RS
2580 {
2581 int width = FRAME_WINDOW_WIDTH (selected_frame);
2582 int height = FRAME_HEIGHT (selected_frame);
2583
2584 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
2585
2586 /* If these sizes are so big they cause overflow,
2587 just ignore the change. It's not clear what better we could do. */
2588 if (total_glyphs / sizeof (GLYPH) / height != width + 2)
1559a86d 2589 fatal ("screen size %dx%d too big", width, height);
d86c299a
RS
2590 }
2591
502b9b64
JB
2592 remake_frame_glyphs (selected_frame);
2593 calculate_costs (selected_frame);
4588ec20
JB
2594
2595 /* X and Y coordinates of the cursor between updates. */
502b9b64
JB
2596 FRAME_CURSOR_X (selected_frame) = 0;
2597 FRAME_CURSOR_Y (selected_frame) = 0;
4588ec20
JB
2598
2599#ifdef SIGWINCH
2600#ifndef CANNOT_DUMP
2601 if (initialized)
2602#endif /* CANNOT_DUMP */
2603 signal (SIGWINCH, window_change_signal);
2604#endif /* SIGWINCH */
2605}
2606\f
2607syms_of_display ()
2608{
502b9b64 2609 defsubr (&Sredraw_frame);
4588ec20 2610 defsubr (&Sredraw_display);
078b3696 2611 defsubr (&Sframe_or_buffer_changed_p);
4588ec20
JB
2612 defsubr (&Sopen_termscript);
2613 defsubr (&Sding);
2614 defsubr (&Ssit_for);
2615 defsubr (&Ssleep_for);
2616 defsubr (&Ssend_string_to_terminal);
2617
d1dad759 2618 frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
078b3696
KH
2619 staticpro (&frame_and_buffer_state);
2620
9cda4f7c
RS
2621 Qdisplay_table = intern ("display-table");
2622 staticpro (&Qdisplay_table);
2623
4588ec20 2624 DEFVAR_INT ("baud-rate", &baud_rate,
eb285955 2625 "*The output baud rate of the terminal.\n\
4588ec20
JB
2626On most systems, changing this value will affect the amount of padding\n\
2627and the other strategic decisions made during redisplay.");
2628 DEFVAR_BOOL ("inverse-video", &inverse_video,
502b9b64 2629 "*Non-nil means invert the entire frame display.\n\
4588ec20
JB
2630This means everything is in inverse video which otherwise would not be.");
2631 DEFVAR_BOOL ("visible-bell", &visible_bell,
502b9b64 2632 "*Non-nil means try to flash the frame to represent a bell.");
4588ec20 2633 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
502b9b64 2634 "*Non-nil means no need to redraw entire frame after suspending.\n\
4588ec20 2635A non-nil value is useful if the terminal can automatically preserve\n\
502b9b64 2636Emacs's frame display when you reenter Emacs.\n\
4588ec20
JB
2637It is up to you to set this variable if your terminal can do that.");
2638 DEFVAR_LISP ("window-system", &Vwindow_system,
2639 "A symbol naming the window-system under which Emacs is running\n\
2640\(such as `x'), or nil if emacs is running on an ordinary terminal.");
2641 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2642 "The version number of the window system in use.\n\
2643For X windows, this is 10 or 11.");
2644 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2645 "Non-nil means put cursor in minibuffer, at end of any message there.");
2646 DEFVAR_LISP ("glyph-table", &Vglyph_table,
502b9b64 2647 "Table defining how to output a glyph code to the frame.\n\
4588ec20
JB
2648If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2649Each element can be:\n\
2650 integer: a glyph code which this glyph is an alias for.\n\
2651 string: output this glyph using that string (not impl. in X windows).\n\
2652 nil: this glyph mod 256 is char code to output,\n\
6666f05a 2653 and this glyph / 256 is face code for X windows (see `face-id').");
4588ec20
JB
2654 Vglyph_table = Qnil;
2655
2656 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2657 "Display table to use for buffers that specify none.\n\
2658See `buffer-display-table' for more information.");
2659 Vstandard_display_table = Qnil;
2660
2661 /* Initialize `window-system', unless init_display already decided it. */
2662#ifdef CANNOT_DUMP
2663 if (noninteractive)
2664#endif
2665 {
2666 Vwindow_system = Qnil;
2667 Vwindow_system_version = Qnil;
2668 }
2669}