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