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