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