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