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