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