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