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