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