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