*** empty log message ***
[bpt/emacs.git] / src / dispnew.c
CommitLineData
4588ec20
JB
1/* Updating of data structures for redisplay.
2 Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <signal.h>
22
23#include "config.h"
24#include <stdio.h>
25#include <ctype.h>
26
27#ifdef NEED_TIME_H
28#include <time.h>
29#else /* not NEED_TIME_H */
30#ifdef HAVE_TIMEVAL
31#include <sys/time.h>
32#endif /* HAVE_TIMEVAL */
33#endif /* not NEED_TIME_H */
34
35#ifdef HAVE_TERMIO
36#include <termio.h>
37#ifdef TCOUTQ
38#undef TIOCOUTQ
39#define TIOCOUTQ TCOUTQ
40#endif /* TCOUTQ defined */
41#include <fcntl.h>
42#else
43#ifndef VMS
44#include <sys/ioctl.h>
45#endif /* not VMS */
46#endif /* not HAVE_TERMIO */
47
48/* Allow m- file to inhibit use of FIONREAD. */
49#ifdef BROKEN_FIONREAD
50#undef FIONREAD
51#endif
52
53/* Interupt input is not used if there is no FIONREAD. */
54#ifndef FIONREAD
55#undef SIGIO
56#endif
57
4588ec20
JB
58#include "termchar.h"
59#include "termopts.h"
60#include "cm.h"
61#include "lisp.h"
62#include "dispextern.h"
63#include "buffer.h"
64#include "screen.h"
65#include "window.h"
66#include "commands.h"
67#include "disptab.h"
68#include "indent.h"
69
70#ifdef HAVE_X_WINDOWS
71#include "xterm.h"
72#endif /* HAVE_X_WINDOWS */
73
74#define max(a, b) ((a) > (b) ? (a) : (b))
75#define min(a, b) ((a) < (b) ? (a) : (b))
76
77#ifndef PENDING_OUTPUT_COUNT
78/* Get number of chars of output now in the buffer of a stdio stream.
79 This ought to be built in in stdio, but it isn't.
80 Some s- files override this because their stdio internals differ. */
81#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
82#endif
83
84/* Nonzero means do not assume anything about current
85 contents of actual terminal screen */
86
87int screen_garbaged;
88
89/* Nonzero means last display completed. Zero means it was preempted. */
90
91int display_completed;
92
93/* Lisp variable visible-bell; enables use of screen-flash
94 instead of audible bell. */
95
96int visible_bell;
97
98/* Invert the color of the whole screen, at a low level. */
99
100int inverse_video;
101
102/* Line speed of the terminal. */
103
104int baud_rate;
105
106/* nil or a symbol naming the window system under which emacs is
107 running ('x is the only current possibility). */
108
109Lisp_Object Vwindow_system;
110
111/* Version number of X windows: 10, 11 or nil. */
112Lisp_Object Vwindow_system_version;
113
114/* Vector of glyph definitions. Indexed by glyph number,
115 the contents are a string which is how to output the glyph.
116
117 If Vglyph_table is nil, a glyph is output by using its low 8 bits
118 as a character code. */
119
120Lisp_Object Vglyph_table;
121
122/* Display table to use for vectors that don't specify their own. */
123
124Lisp_Object Vstandard_display_table;
125
126/* Nonzero means reading single-character input with prompt
127 so put cursor on minibuffer after the prompt. */
128
129int cursor_in_echo_area;
130\f
131/* The currently selected screen.
132 In a single-screen version, this variable always remains 0. */
133
134SCREEN_PTR selected_screen;
135
136/* In a single-screen version, the information that would otherwise
137 exist inside a `struct screen' lives in the following variables instead. */
138
139#ifndef MULTI_SCREEN
140
141/* Desired terminal cursor position (to show position of point),
142 origin zero */
143
144int cursX, cursY;
145
146/* Description of current screen contents */
147
148struct screen_glyphs *current_glyphs;
149
150/* Description of desired screen contents */
151
152struct screen_glyphs *desired_glyphs;
153
154#endif /* not MULTI_SCREEN */
155
156/* This is a vector, made larger whenever it isn't large enough,
157 which is used inside `update_screen' to hold the old contents
158 of the SCREEN_PHYS_LINES of the screen being updated. */
159struct screen_glyphs **ophys_lines;
160/* Length of vector currently allocated. */
161int ophys_lines_length;
162
163FILE *termscript; /* Stdio stream being used for copy of all output. */
164
165struct cm Wcm; /* Structure for info on cursor positioning */
166
167extern short ospeed; /* Output speed (from sg_ospeed) */
168
169int in_display; /* 1 if in redisplay: can't handle SIGWINCH now. */
170
171int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
172int delayed_screen_height; /* Remembered new screen height. */
173int delayed_screen_width; /* Remembered new screen width. */
174\f
175#ifdef MULTI_SCREEN
176
177DEFUN ("redraw-screen", Fredraw_screen, Sredraw_screen, 1, 1, 0,
178 "Clear screen SCREEN and output again what is supposed to appear on it.")
179 (screen)
180 Lisp_Object screen;
181{
182 SCREEN_PTR s;
183
efb859b4 184 CHECK_LIVE_SCREEN (screen, 0);
4588ec20
JB
185 s = XSCREEN (screen);
186 update_begin (s);
187 /* set_terminal_modes (); */
188 clear_screen ();
189 update_end (s);
190 fflush (stdout);
191 clear_screen_records (s);
192 windows_or_buffers_changed++;
193 /* Mark all windows as INaccurate,
194 so that every window will have its redisplay done. */
195 mark_window_display_accurate (SCREEN_ROOT_WINDOW (s), 0);
196 s->garbaged = 0;
197 return Qnil;
198}
199
200DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
201 "Redraw all screens marked as having their images garbled.")
202 ()
203{
204 Lisp_Object screen, tail;
205
206 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
207 {
208 screen = XCONS (tail)->car;
209 if (XSCREEN (screen)->garbaged && XSCREEN (screen)->visible)
210 Fredraw_screen (screen);
211 }
212 return Qnil;
213}
214
215redraw_screen (s)
216 SCREEN_PTR s;
217{
218 Lisp_Object screen;
219 XSET (screen, Lisp_Screen, s);
220 Fredraw_screen (screen);
221}
222
223#else /* not MULTI_SCREEN */
224
225DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, 0,
226 "Clear screen and output again what is supposed to appear on it.")
227 ()
228{
229 update_begin (0);
230 set_terminal_modes ();
231 clear_screen ();
232 update_end (0);
233 fflush (stdout);
234 clear_screen_records (0);
235 windows_or_buffers_changed++;
236 /* Mark all windows as INaccurate,
237 so that every window will have its redisplay done. */
238 mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0);
239 return Qnil;
240}
241
242#endif /* not MULTI_SCREEN */
243\f
244static struct screen_glyphs *
245make_screen_glyphs (screen, empty)
246 register SCREEN_PTR screen;
247 int empty;
248{
249 register int i;
250 register width = SCREEN_WIDTH (screen);
251 register height = SCREEN_HEIGHT (screen);
252 register struct screen_glyphs *new =
253 (struct screen_glyphs *) xmalloc (sizeof (struct screen_glyphs));
254
255 SET_GLYPHS_SCREEN (new, screen);
256 new->height = height;
257 new->width = width;
258 new->used = (int *) xmalloc (height * sizeof (int));
259 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
260 new->highlight = (char *) xmalloc (height * sizeof (char));
261 new->enable = (char *) xmalloc (height * sizeof (char));
262 bzero (new->enable, height * sizeof (char));
263 new->bufp = (int *) xmalloc (height * sizeof (int));
264
265#ifdef HAVE_X_WINDOWS
266 if (SCREEN_IS_X (screen))
267 {
268 new->nruns = (int *) xmalloc (height * sizeof (int));
269 new->face_list
270 = (struct run **) xmalloc (height * sizeof (struct run *));
271 new->top_left_x = (short *) xmalloc (height * sizeof (short));
272 new->top_left_y = (short *) xmalloc (height * sizeof (short));
273 new->pix_width = (short *) xmalloc (height * sizeof (short));
274 new->pix_height = (short *) xmalloc (height * sizeof (short));
275 }
276#endif
277
278 if (empty)
279 {
280 /* Make the buffer used by decode_mode_spec. This buffer is also
281 used as temporary storage when updating the screen. See scroll.c. */
282 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
283
284 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
285 bzero (new->total_contents, total_glyphs);
286 }
287 else
288 {
289 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
290
291 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
292 bzero (new->total_contents, total_glyphs);
293 for (i = 0; i < height; i++)
294 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
295 }
296
297 return new;
298}
299
300static void
301free_screen_glyphs (screen, glyphs)
302 SCREEN_PTR screen;
303 struct screen_glyphs *glyphs;
304{
305 if (glyphs->total_contents)
306 free (glyphs->total_contents);
307
308 free (glyphs->used);
309 free (glyphs->glyphs);
310 free (glyphs->highlight);
311 free (glyphs->enable);
312 free (glyphs->bufp);
313
314#ifdef HAVE_X_WINDOWS
315 if (SCREEN_IS_X (screen))
316 {
317 free (glyphs->nruns);
318 free (glyphs->face_list);
319 free (glyphs->top_left_x);
320 free (glyphs->top_left_y);
321 free (glyphs->pix_width);
322 free (glyphs->pix_height);
323 }
324#endif
325
326 free (glyphs);
327}
328
329static void
330remake_screen_glyphs (screen)
331 SCREEN_PTR screen;
332{
333 if (SCREEN_CURRENT_GLYPHS (screen))
334 free_screen_glyphs (screen, SCREEN_CURRENT_GLYPHS (screen));
335 if (SCREEN_DESIRED_GLYPHS (screen))
336 free_screen_glyphs (screen, SCREEN_DESIRED_GLYPHS (screen));
337 if (SCREEN_TEMP_GLYPHS (screen))
338 free_screen_glyphs (screen, SCREEN_TEMP_GLYPHS (screen));
339
340 if (SCREEN_MESSAGE_BUF (screen))
341 SCREEN_MESSAGE_BUF (screen)
342 = (char *) xrealloc (SCREEN_MESSAGE_BUF (screen),
343 SCREEN_WIDTH (screen) + 1);
344 else
345 SCREEN_MESSAGE_BUF (screen)
346 = (char *) xmalloc (SCREEN_WIDTH (screen) + 1);
347
348 SCREEN_CURRENT_GLYPHS (screen) = make_screen_glyphs (screen, 0);
349 SCREEN_DESIRED_GLYPHS (screen) = make_screen_glyphs (screen, 0);
350 SCREEN_TEMP_GLYPHS (screen) = make_screen_glyphs (screen, 1);
351 SET_SCREEN_GARBAGED (screen);
352}
353\f
354/* Return the hash code of contents of line VPOS in screen-matrix M. */
355
356static int
357line_hash_code (m, vpos)
358 register struct screen_glyphs *m;
359 int vpos;
360{
361 register GLYPH *body, *end;
362 register int h = 0;
363
364 if (!m->enable[vpos])
365 return 0;
366
367 /* Give all lighlighted lines the same hash code
368 so as to encourage scrolling to leave them in place. */
369 if (m->highlight[vpos])
370 return -1;
371
372 body = m->glyphs[vpos];
373
374 if (must_write_spaces)
375 while (1)
376 {
377 GLYPH g = *body++;
378
379 if (g == 0)
380 break;
381 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
382 }
383 else
384 while (1)
385 {
386 GLYPH g = *body++;
387
388 if (g == 0)
389 break;
390 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
391 }
392
393 if (h)
394 return h;
395 return 1;
396}
397
398/* Return number of characters in line in M at vpos VPOS,
399 except don't count leading and trailing spaces
400 unless the terminal requires those to be explicitly output. */
401
402static unsigned int
403line_draw_cost (m, vpos)
404 struct screen_glyphs *m;
405 int vpos;
406{
407 register GLYPH *beg = m->glyphs[vpos];
408 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
409 register int i;
410 register int tlen = GLYPH_TABLE_LENGTH;
411 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
412
413 /* Ignore trailing and leading spaces if we can. */
414 if (!must_write_spaces)
415 {
416 while ((end != beg) && (*end == SPACEGLYPH))
417 --end;
418 if (end == beg)
419 return (0); /* All blank line. */
420
421 while (*beg == SPACEGLYPH)
422 ++beg;
423 }
424
425 /* If we don't have a glyph-table, each glyph is one character,
426 so return the number of glyphs. */
427 if (tbase == 0)
428 return end - beg;
429
430 /* Otherwise, scan the glyphs and accumulate their total size in I. */
431 i = 0;
432 while ((beg <= end) && *beg)
433 {
434 register GLYPH g = *beg++;
435
436 if (GLYPH_SIMPLE_P (tbase, tlen, g))
437 i += 1;
438 else
439 i += GLYPH_LENGTH (tbase, g);
440 }
441 return i;
442}
443\f
444/* The functions on this page are the interface from xdisp.c to redisplay.
445
446 The only other interface into redisplay is through setting
447 SCREEN_CURSOR_X (screen) and SCREEN_CURSOR_Y (screen)
448 and SET_SCREEN_GARBAGED (screen). */
449
450/* cancel_line eliminates any request to display a line at position `vpos' */
451
452cancel_line (vpos, screen)
453 int vpos;
454 register SCREEN_PTR screen;
455{
456 SCREEN_DESIRED_GLYPHS (screen)->enable[vpos] = 0;
457}
458
459clear_screen_records (screen)
460 register SCREEN_PTR screen;
461{
462 bzero (SCREEN_CURRENT_GLYPHS (screen)->enable, SCREEN_HEIGHT (screen));
463}
464
465/* Prepare to display on line VPOS starting at HPOS within it. */
466
467void
468get_display_line (screen, vpos, hpos)
469 register SCREEN_PTR screen;
470 int vpos;
471 register int hpos;
472{
473 register struct screen_glyphs *glyphs;
474 register struct screen_glyphs *desired_glyphs = SCREEN_DESIRED_GLYPHS (screen);
475 register GLYPH *p;
476
477 if (vpos < 0 || (! SCREEN_VISIBLE_P (screen)))
478 abort ();
479
480 if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
481 abort ();
482
483 if (! desired_glyphs->enable[vpos])
484 {
485 desired_glyphs->used[vpos] = 0;
486 desired_glyphs->highlight[vpos] = 0;
487 desired_glyphs->enable[vpos] = 1;
488 }
489
490 if (hpos > desired_glyphs->used[vpos])
491 {
492 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
493 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
494
495 desired_glyphs->used[vpos] = hpos;
496 while (g != end)
497 *g++ = SPACEGLYPH;
498 }
499}
500
501/* Like bcopy except never gets confused by overlap. */
502
503void
504safe_bcopy (from, to, size)
505 char *from, *to;
506 int size;
507{
508 register char *endf;
509 register char *endt;
510
511 if (size == 0)
512 return;
513
514 /* If destination is higher in memory, and overlaps source zone,
515 copy from the end. */
516 if (from < to && from + size > to)
517 {
518 endf = from + size;
519 endt = to + size;
520
521 /* If TO - FROM is large, then we should break the copy into
522 nonoverlapping chunks of TO - FROM bytes each. However, if
523 TO - FROM is small, then the bcopy function call overhead
524 makes this not worth it. The crossover point could be about
525 anywhere. Since I don't think the obvious copy loop is ever
526 too bad, I'm trying to err in its favor. */
527 if (to - from < 64)
528 {
529 do
530 *--endt = *--endf;
531 while (endf != from);
532 }
533 else
534 {
98038dc0
JB
535 /* Since TO - FROM >= 64, the overlap is less than SIZE,
536 so we can always safely do this loop once. */
4588ec20
JB
537 while (endt > to)
538 {
539 endt -= (to - from);
540 endf -= (to - from);
541
542 bcopy (endf, endt, to - from);
543 }
544
545 /* If TO - FROM wasn't a multiple of SIZE, there will be a
546 little left over. The amount left over is
547 (endt + (to - from)) - to, which is endt - from. */
548 bcopy (from, to, endt - from);
549 }
550 }
551 else
552 bcopy (from, to, size);
553}
554
555#if 0
556void
557safe_bcopy (from, to, size)
558 char *from, *to;
559 int size;
560{
561 register char *endf;
562 register char *endt;
563
564 if (size == 0)
565 return;
566
567 /* If destination is higher in memory, and overlaps source zone,
568 copy from the end. */
569 if (from < to && from + size > to)
570 {
571 endf = from + size;
572 endt = to + size;
573
574 do
575 *--endt = *--endf;
576 while (endf != from);
577
578 return;
579 }
580
581 bcopy (from, to, size);
582}
583#endif
584
98038dc0 585/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
4588ec20
JB
586 DISTANCE may be negative. */
587
588static void
589rotate_vector (vector, size, distance)
590 char *vector;
591 int size;
592 int distance;
593{
594 char *temp = (char *) alloca (size);
595
596 if (distance < 0)
597 distance += size;
598
599 bcopy (vector, temp + distance, size - distance);
600 bcopy (vector + size - distance, temp, distance);
601 bcopy (temp, vector, size);
602}
603
604/* Scroll lines from vpos FROM up to but not including vpos END
605 down by AMOUNT lines (AMOUNT may be negative).
606 Returns nonzero if done, zero if terminal cannot scroll them. */
607
608int
609scroll_screen_lines (screen, from, end, amount)
610 register SCREEN_PTR screen;
611 int from, end, amount;
612{
613 register int i;
614 register struct screen_glyphs *current_screen
615 = SCREEN_CURRENT_GLYPHS (screen);
616
617 if (!line_ins_del_ok)
618 return 0;
619
620 if (amount == 0)
621 return 1;
622
623 if (amount > 0)
624 {
625 update_begin (screen);
626 set_terminal_window (end + amount);
627 if (!scroll_region_ok)
628 ins_del_lines (end, -amount);
629 ins_del_lines (from, amount);
630 set_terminal_window (0);
631
632 rotate_vector (current_screen->glyphs + from,
633 sizeof (GLYPH *) * (end + amount - from),
634 amount * sizeof (GLYPH *));
635
636 safe_bcopy (current_screen->used + from,
637 current_screen->used + from + amount,
638 (end - from) * sizeof current_screen->used[0]);
639
640 safe_bcopy (current_screen->highlight + from,
641 current_screen->highlight + from + amount,
642 (end - from) * sizeof current_screen->highlight[0]);
643
644 safe_bcopy (current_screen->enable + from,
645 current_screen->enable + from + amount,
646 (end - from) * sizeof current_screen->enable[0]);
647
648 /* Mark the lines made empty by scrolling as enabled, empty and
649 normal video. */
650 bzero (current_screen->used + from,
651 amount * sizeof current_screen->used[0]);
652 bzero (current_screen->highlight + from,
653 amount * sizeof current_screen->highlight[0]);
654 for (i = from; i < from + amount; i++)
655 {
656 current_screen->glyphs[i][0] = '\0';
657 current_screen->enable[i] = 1;
658 }
659
660 safe_bcopy (current_screen->bufp + from,
661 current_screen->bufp + from + amount,
662 (end - from) * sizeof current_screen->bufp[0]);
663
664#ifdef HAVE_X_WINDOWS
665 if (SCREEN_IS_X (screen))
666 {
667 safe_bcopy (current_screen->nruns + from,
668 current_screen->nruns + from + amount,
669 (end - from) * sizeof current_screen->nruns[0]);
670
671 safe_bcopy (current_screen->face_list + from,
672 current_screen->face_list + from + amount,
673 (end - from) * sizeof current_screen->face_list[0]);
674
675 safe_bcopy (current_screen->top_left_x + from,
676 current_screen->top_left_x + from + amount,
677 (end - from) * sizeof current_screen->top_left_x[0]);
678
679 safe_bcopy (current_screen->top_left_y + from,
680 current_screen->top_left_y + from + amount,
681 (end - from) * sizeof current_screen->top_left_y[0]);
682
683 safe_bcopy (current_screen->pix_width + from,
684 current_screen->pix_width + from + amount,
685 (end - from) * sizeof current_screen->pix_width[0]);
686
687 safe_bcopy (current_screen->pix_height + from,
688 current_screen->pix_height + from + amount,
689 (end - from) * sizeof current_screen->pix_height[0]);
690 }
691#endif /* HAVE_X_WINDOWS */
692
693 update_end (screen);
694 }
695 if (amount < 0)
696 {
697 update_begin (screen);
698 set_terminal_window (end);
699 ins_del_lines (from + amount, amount);
700 if (!scroll_region_ok)
701 ins_del_lines (end + amount, -amount);
702 set_terminal_window (0);
703
704 rotate_vector (current_screen->glyphs + from + amount,
705 sizeof (GLYPH *) * (end - from - amount),
706 amount * sizeof (GLYPH *));
707
708 safe_bcopy (current_screen->used + from,
709 current_screen->used + from + amount,
710 (end - from) * sizeof current_screen->used[0]);
711
712 safe_bcopy (current_screen->highlight + from,
713 current_screen->highlight + from + amount,
714 (end - from) * sizeof current_screen->highlight[0]);
715
716 safe_bcopy (current_screen->enable + from,
717 current_screen->enable + from + amount,
718 (end - from) * sizeof current_screen->enable[0]);
719
720 /* Mark the lines made empty by scrolling as enabled, empty and
721 normal video. */
722 bzero (current_screen->used + end + amount,
723 - amount * sizeof current_screen->used[0]);
724 bzero (current_screen->highlight + end + amount,
725 - amount * sizeof current_screen->highlight[0]);
726 for (i = end + amount; i < end; i++)
727 {
728 current_screen->glyphs[i][0] = '\0';
729 current_screen->enable[i] = 1;
730 }
731
732 safe_bcopy (current_screen->bufp + from,
733 current_screen->bufp + from + amount,
734 (end - from) * sizeof current_screen->bufp[0]);
735
736#ifdef HAVE_X_WINDOWS
737 if (SCREEN_IS_X (screen))
738 {
739 safe_bcopy (current_screen->nruns + from,
740 current_screen->nruns + from + amount,
741 (end - from) * sizeof current_screen->nruns[0]);
742
743 safe_bcopy (current_screen->face_list + from,
744 current_screen->face_list + from + amount,
745 (end - from) * sizeof current_screen->face_list[0]);
746
747 safe_bcopy (current_screen->top_left_x + from,
748 current_screen->top_left_x + from + amount,
749 (end - from) * sizeof current_screen->top_left_x[0]);
750
751 safe_bcopy (current_screen->top_left_y + from,
752 current_screen->top_left_y + from + amount,
753 (end - from) * sizeof current_screen->top_left_y[0]);
754
755 safe_bcopy (current_screen->pix_width + from,
756 current_screen->pix_width + from + amount,
757 (end - from) * sizeof current_screen->pix_width[0]);
758
759 safe_bcopy (current_screen->pix_height + from,
760 current_screen->pix_height + from + amount,
761 (end - from) * sizeof current_screen->pix_height[0]);
762 }
763#endif /* HAVE_X_WINDOWS */
764
765 update_end (screen);
766 }
767 return 1;
768}
769\f
770/* After updating a window W that isn't the full screen wide,
771 copy all the columns that W does not occupy
772 into the SCREEN_DESIRED_GLYPHS (screen) from the SCREEN_PHYS_GLYPHS (screen)
773 so that update_screen will not change those columns. */
774
775preserve_other_columns (w)
776 struct window *w;
777{
778 register int vpos;
779 register struct screen_glyphs *current_screen, *desired_screen;
780 register SCREEN_PTR screen = XSCREEN (w->screen);
781 int start = XFASTINT (w->left);
782 int end = XFASTINT (w->left) + XFASTINT (w->width);
783 int bot = XFASTINT (w->top) + XFASTINT (w->height);
784
785 current_screen = SCREEN_CURRENT_GLYPHS (screen);
786 desired_screen = SCREEN_DESIRED_GLYPHS (screen);
787
788 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
789 {
790 if (current_screen->enable[vpos] && desired_screen->enable[vpos])
791 {
792 if (start > 0)
793 {
794 int len;
795
796 bcopy (current_screen->glyphs[vpos],
797 desired_screen->glyphs[vpos], start);
798 len = min (start, current_screen->used[vpos]);
799 if (desired_screen->used[vpos] < len)
800 desired_screen->used[vpos] = len;
801 }
802 if (current_screen->used[vpos] > end
803 && desired_screen->used[vpos] < current_screen->used[vpos])
804 {
805 while (desired_screen->used[vpos] < end)
806 desired_screen->glyphs[vpos][desired_screen->used[vpos]++]
807 = SPACEGLYPH;
808 bcopy (current_screen->glyphs[vpos] + end,
809 desired_screen->glyphs[vpos] + end,
810 current_screen->used[vpos] - end);
811 desired_screen->used[vpos] = current_screen->used[vpos];
812 }
813 }
814 }
815}
816\f
817#if 0
818
819/* If window w does not need to be updated and isn't the full screen wide,
820 copy all the columns that w does occupy
821 into the SCREEN_DESIRED_LINES (screen) from the SCREEN_PHYS_LINES (screen)
822 so that update_screen will not change those columns.
823
824 Have not been able to figure out how to use this correctly. */
825
826preserve_my_columns (w)
827 struct window *w;
828{
829 register int vpos, fin;
830 register struct screen_glyphs *l1, *l2;
831 register SCREEN_PTR screen = XSCREEN (w->screen);
832 int start = XFASTINT (w->left);
833 int end = XFASTINT (w->left) + XFASTINT (w->width);
834 int bot = XFASTINT (w->top) + XFASTINT (w->height);
835
836 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
837 {
838 if ((l1 = SCREEN_DESIRED_GLYPHS (screen)->glyphs[vpos + 1])
839 && (l2 = SCREEN_PHYS_GLYPHS (screen)->glyphs[vpos + 1]))
840 {
841 if (l2->length > start && l1->length < l2->length)
842 {
843 fin = l2->length;
844 if (fin > end) fin = end;
845 while (l1->length < start)
846 l1->body[l1->length++] = ' ';
847 bcopy (l2->body + start, l1->body + start, fin - start);
848 l1->length = fin;
849 }
850 }
851 }
852}
853
854#endif
855\f
856/* On discovering that the redisplay for a window was no good,
857 cancel the columns of that window, so that when the window is
858 displayed over again get_display_line will not complain. */
859
860cancel_my_columns (w)
861 struct window *w;
862{
863 register int vpos;
864 register SCREEN_PTR screen = XSCREEN (w->screen);
865 register struct screen_glyphs *desired_glyphs = screen->desired_glyphs;
866 register int start = XFASTINT (w->left);
867 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
868
869 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
870 if (desired_glyphs->enable[vpos]
871 && desired_glyphs->used[vpos] >= start)
872 desired_glyphs->used[vpos] = start;
873}
874\f
875/* These functions try to perform directly and immediately on the screen
876 the necessary output for one change in the buffer.
877 They may return 0 meaning nothing was done if anything is difficult,
878 or 1 meaning the output was performed properly.
879 They assume that the screen was up to date before the buffer
880 change being displayed. THey make various other assumptions too;
881 see command_loop_1 where these are called. */
882
883int
884direct_output_for_insert (g)
885 int g;
886{
887 register SCREEN_PTR screen = selected_screen;
888 register struct screen_glyphs *current_screen
889 = SCREEN_CURRENT_GLYPHS (screen);
890
891#ifndef COMPILER_REGISTER_BUG
892 register
893#endif /* COMPILER_REGISTER_BUG */
894 struct window *w = XWINDOW (selected_window);
895#ifndef COMPILER_REGISTER_BUG
896 register
897#endif /* COMPILER_REGISTER_BUG */
898 int hpos = SCREEN_CURSOR_X (screen);
899#ifndef COMPILER_REGISTER_BUG
900 register
901#endif /* COMPILER_REGISTER_BUG */
902 int vpos = SCREEN_CURSOR_Y (screen);
903
904 /* Give up if about to continue line */
905 if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
906
907 /* Avoid losing if cursor is in invisible text off left margin */
908 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
909
910 /* Give up if cursor outside window (in minibuf, probably) */
911 || SCREEN_CURSOR_Y (screen) < XFASTINT (w->top)
912 || SCREEN_CURSOR_Y (screen) >= XFASTINT (w->top) + XFASTINT (w->height)
913
914 /* Give up if cursor not really at SCREEN_CURSOR_X, SCREEN_CURSOR_Y */
915 || !display_completed
916
917 /* Give up if buffer appears in two places. */
918 || buffer_shared > 1
919
920 /* Give up if w is minibuffer and a message is being displayed there */
921 || (MINI_WINDOW_P (w) && echo_area_glyphs))
922 return 0;
923
924 current_screen->glyphs[vpos][hpos] = g;
925 unchanged_modified = MODIFF;
926 beg_unchanged = GPT - BEG;
927 XFASTINT (w->last_point) = point;
928 XFASTINT (w->last_point_x) = hpos;
929 XFASTINT (w->last_modified) = MODIFF;
930
931 reassert_line_highlight (0, vpos);
932 write_glyphs (&current_screen->glyphs[vpos][hpos], 1);
933 fflush (stdout);
934 ++SCREEN_CURSOR_X (screen);
935 if (hpos == current_screen->used[vpos])
936 {
937 current_screen->used[vpos] = hpos + 1;
938 current_screen->glyphs[vpos][hpos + 1] = 0;
939 }
940
941 return 1;
942}
943
944int
945direct_output_forward_char (n)
946 int n;
947{
948 register SCREEN_PTR screen = selected_screen;
949 register struct window *w = XWINDOW (selected_window);
950
951 /* Avoid losing if cursor is in invisible text off left margin */
952 if (XINT (w->hscroll) && SCREEN_CURSOR_X (screen) == XFASTINT (w->left))
953 return 0;
954
955 SCREEN_CURSOR_X (screen) += n;
956 XFASTINT (w->last_point_x) = SCREEN_CURSOR_X (screen);
957 XFASTINT (w->last_point) = point;
958 cursor_to (SCREEN_CURSOR_Y (screen), SCREEN_CURSOR_X (screen));
959 fflush (stdout);
960 return 1;
961}
962\f
963static void update_line ();
964
965/* Update screen S based on the data in SCREEN_DESIRED_GLYPHS.
966 Value is nonzero if redisplay stopped due to pending input.
967 FORCE nonzero means do not stop for pending input. */
968
969int
970update_screen (s, force, inhibit_hairy_id)
971 SCREEN_PTR s;
972 int force;
973 int inhibit_hairy_id;
974{
975 register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
976 register struct screen_glyphs *desired_screen = SCREEN_DESIRED_GLYPHS (s);
977 register int i;
978 int pause;
979 int preempt_count = baud_rate / 2400 + 1;
980 extern input_pending;
981#ifdef HAVE_X_WINDOWS
982 register int downto, leftmost;
983#endif
984
985 if (SCREEN_HEIGHT (s) == 0) abort (); /* Some bug zeros some core */
986
987 detect_input_pending ();
988 if (input_pending && !force)
989 {
990 pause = 1;
991 goto do_pause;
992 }
993
994 update_begin (s);
995
996 if (!line_ins_del_ok)
997 inhibit_hairy_id = 1;
998
efb859b4
JB
999 /* See if any of the desired lines are enabled; don't compute for
1000 i/d line if just want cursor motion. */
4588ec20
JB
1001 for (i = 0; i < SCREEN_HEIGHT (s); i++)
1002 if (desired_screen->enable[i])
1003 break;
1004
1005 /* Try doing i/d line, if not yet inhibited. */
1006 if (!inhibit_hairy_id && i < SCREEN_HEIGHT (s))
1007 force |= scrolling (s);
1008
1009 /* Update the individual lines as needed. Do bottom line first. */
1010
1011 if (desired_screen->enable[SCREEN_HEIGHT (s) - 1])
1012 update_line (s, SCREEN_HEIGHT (s) - 1);
1013
1014#ifdef HAVE_X_WINDOWS
1015 if (SCREEN_IS_X (s))
1016 {
1017 leftmost = downto = s->display.x->internal_border_width;
1018 if (desired_screen->enable[0])
1019 {
1020 current_screen->top_left_x[SCREEN_HEIGHT (s) - 1] = leftmost;
1021 current_screen->top_left_y[SCREEN_HEIGHT (s) - 1]
1022 = PIXEL_HEIGHT (s) - s->display.x->internal_border_width
1023 - LINE_HEIGHT(s, SCREEN_HEIGHT (s) - 1);
1024 current_screen->top_left_x[0] = leftmost;
1025 current_screen->top_left_y[0] = downto;
1026 }
1027 }
1028#endif /* HAVE_X_WINDOWS */
1029
1030 /* Now update the rest of the lines. */
1031 for (i = 0; i < SCREEN_HEIGHT (s) - 1 && (force || !input_pending); i++)
1032 {
1033 if (desired_screen->enable[i])
1034 {
1035 if (SCREEN_IS_TERMCAP (s))
1036 {
1037 /* Flush out every so many lines.
1038 Also flush out if likely to have more than 1k buffered
1039 otherwise. I'm told that some telnet connections get
1040 really screwed by more than 1k output at once. */
1041 int outq = PENDING_OUTPUT_COUNT (stdout);
1042 if (outq > 900
1043 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1044 {
1045 fflush (stdout);
1046 if (preempt_count == 1)
1047 {
1048#ifdef TIOCOUTQ
1049 if (ioctl (0, TIOCOUTQ, &outq) < 0)
1050 /* Probably not a tty. Ignore the error and reset
1051 * the outq count. */
1052 outq = PENDING_OUTPUT_COUNT (stdout);
1053#endif
1054 outq *= 10;
1055 sleep (outq / baud_rate);
1056 }
1057 }
1058 if ((i - 1) % preempt_count == 0)
1059 detect_input_pending ();
1060 }
1061
1062 update_line (s, i);
1063#ifdef HAVE_X_WINDOWS
1064 if (SCREEN_IS_X (s))
1065 {
1066 current_screen->top_left_y[i] = downto;
1067 current_screen->top_left_x[i] = leftmost;
1068 }
1069#endif /* HAVE_X_WINDOWS */
1070 }
1071
1072 if (SCREEN_IS_X (s))
1073 downto += LINE_HEIGHT(s, i);
1074 }
1075 pause = (i < SCREEN_HEIGHT (s) - 1) ? i : 0;
1076
1077 /* Now just clean up termcap drivers and set cursor, etc. */
1078 if (!pause)
1079 {
1080
1081 if (s == selected_screen && cursor_in_echo_area < 0)
1082 cursor_to (SCREEN_HEIGHT (s) - 1, 0);
1083 else if (s == selected_screen && cursor_in_echo_area
1084 && !desired_screen->used[SCREEN_HEIGHT (s) - 1])
1085 cursor_to (SCREEN_HEIGHT (s), 0);
1086 else if (cursor_in_echo_area)
1087 cursor_to (SCREEN_HEIGHT (s) - 1,
1088 min (SCREEN_WIDTH (s) - 1,
1089 desired_screen->used[SCREEN_HEIGHT (s) - 1]));
1090 else
1091 cursor_to (SCREEN_CURSOR_Y (s), max (min (SCREEN_CURSOR_X (s),
1092 SCREEN_WIDTH (s) - 1), 0));
1093 }
1094
1095 update_end (s);
1096
1097 if (termscript)
1098 fflush (termscript);
1099 fflush (stdout);
1100
1101 /* Here if output is preempted because input is detected. */
1102 do_pause:
1103
1104 if (SCREEN_HEIGHT (s) == 0) abort (); /* Some bug zeros some core */
1105 display_completed = !pause;
1106
1107 bzero (desired_screen->enable, SCREEN_HEIGHT (s));
1108 return pause;
1109}
1110
1111/* Called when about to quit, to check for doing so
1112 at an improper time. */
1113
1114void
1115quit_error_check ()
1116{
1117 if (SCREEN_DESIRED_GLYPHS (selected_screen) == 0)
1118 return;
1119 if (SCREEN_DESIRED_GLYPHS (selected_screen)->enable[0])
1120 abort ();
1121 if (SCREEN_DESIRED_GLYPHS (selected_screen)->enable[SCREEN_HEIGHT (selected_screen) - 1])
1122 abort ();
1123}
1124\f
1125/* Decide what insert/delete line to do, and do it */
1126
1127extern void scrolling_1 ();
1128
1129scrolling (screen)
1130 SCREEN_PTR screen;
1131{
1132 int unchanged_at_top, unchanged_at_bottom;
1133 int window_size;
1134 int changed_lines;
1135 int *old_hash = (int *) alloca (SCREEN_HEIGHT (screen) * sizeof (int));
1136 int *new_hash = (int *) alloca (SCREEN_HEIGHT (screen) * sizeof (int));
1137 int *draw_cost = (int *) alloca (SCREEN_HEIGHT (screen) * sizeof (int));
1138 register int i;
1139 int free_at_end_vpos = SCREEN_HEIGHT (screen);
1140 register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (screen);
1141 register struct screen_glyphs *desired_screen = SCREEN_DESIRED_GLYPHS (screen);
1142
1143 /* Compute hash codes of all the lines.
1144 Also calculate number of changed lines,
1145 number of unchanged lines at the beginning,
1146 and number of unchanged lines at the end. */
1147
1148 changed_lines = 0;
1149 unchanged_at_top = 0;
1150 unchanged_at_bottom = SCREEN_HEIGHT (screen);
1151 for (i = 0; i < SCREEN_HEIGHT (screen); i++)
1152 {
1153 /* Give up on this scrolling if some old lines are not enabled. */
1154 if (!current_screen->enable[i])
1155 return 0;
1156 old_hash[i] = line_hash_code (current_screen, i);
1157 if (! desired_screen->enable[i])
1158 new_hash[i] = old_hash[i];
1159 else
1160 new_hash[i] = line_hash_code (desired_screen, i);
1161
1162 if (old_hash[i] != new_hash[i])
1163 {
1164 changed_lines++;
1165 unchanged_at_bottom = SCREEN_HEIGHT (screen) - i - 1;
1166 }
1167 else if (i == unchanged_at_top)
1168 unchanged_at_top++;
1169 draw_cost[i] = line_draw_cost (desired_screen, i);
1170 }
1171
1172 /* If changed lines are few, don't allow preemption, don't scroll. */
1173 if (changed_lines < baud_rate / 2400
1174 || unchanged_at_bottom == SCREEN_HEIGHT (screen))
1175 return 1;
1176
1177 window_size = (SCREEN_HEIGHT (screen) - unchanged_at_top
1178 - unchanged_at_bottom);
1179
1180 if (scroll_region_ok)
1181 free_at_end_vpos -= unchanged_at_bottom;
1182 else if (memory_below_screen)
1183 free_at_end_vpos = -1;
1184
1185 /* If large window, fast terminal and few lines in common between
1186 current screen and desired screen, don't bother with i/d calc. */
1187 if (window_size >= 18 && baud_rate > 2400
1188 && (window_size >=
1189 10 * scrolling_max_lines_saved (unchanged_at_top,
1190 SCREEN_HEIGHT (screen) - unchanged_at_bottom,
1191 old_hash, new_hash, draw_cost)))
1192 return 0;
1193
1194 scrolling_1 (screen, window_size, unchanged_at_top, unchanged_at_bottom,
1195 draw_cost + unchanged_at_top - 1,
1196 old_hash + unchanged_at_top - 1,
1197 new_hash + unchanged_at_top - 1,
1198 free_at_end_vpos - unchanged_at_top);
1199
1200 return 0;
1201}
1202\f
1203/* Return the offset in its buffer of the character at location col, line
1204 in the given window. */
1205int
1206buffer_posn_from_coords (window, col, line)
1207 struct window *window;
1208 int col, line;
1209{
1210 int window_left = XFASTINT (window->left);
1211
1212 /* The actual width of the window is window->width less one for the
efb859b4
JB
1213 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1214 window. */
4588ec20
JB
1215 int window_width = (XFASTINT (window->width) - 1
1216 - (XFASTINT (window->width) + window_left
1217 != SCREEN_WIDTH (XSCREEN (window->screen))));
1218
efb859b4 1219 int startp = marker_position (window->start);
4588ec20
JB
1220
1221 /* Since compute_motion will only operate on the current buffer,
1222 we need to save the old one and restore it when we're done. */
1223 struct buffer *old_current_buffer = current_buffer;
efb859b4 1224 struct position *posn;
4588ec20
JB
1225
1226 current_buffer = XBUFFER (window->buffer);
1227
efb859b4
JB
1228 /* It would be nice if we could use SCREEN_CURRENT_GLYPHS (XSCREEN
1229 (window->screen))->bufp to avoid scanning from the very top of
1230 the window, but it isn't maintained correctly, and I'm not even
1231 sure I will keep it. */
1232 posn = compute_motion (startp, 0,
1233 (window == XWINDOW (minibuf_window) && startp == 1
1234 ? minibuf_prompt_width : 0),
1235 ZV, line, col - window_left,
1236 window_width, XINT (window->hscroll), 0);
4588ec20
JB
1237
1238 current_buffer = old_current_buffer;
1239
efb859b4
JB
1240 /* compute_motion considers screen points past the end of a line
1241 to be *after* the newline, i.e. at the start of the next line.
1242 This is reasonable, but not really what we want. So if the
1243 result is on a line below LINE, back it up one character. */
1244 if (posn->vpos > line)
1245 return posn->bufpos - 1;
1246 else
1247 return posn->bufpos;
4588ec20
JB
1248}
1249\f
1250static int
1251count_blanks (r)
1252 register GLYPH *r;
1253{
1254 register GLYPH *p = r;
1255 while (*r++ == SPACEGLYPH);
1256 return r - p - 1;
1257}
1258
1259static int
1260count_match (str1, str2)
1261 GLYPH *str1, *str2;
1262{
1263 register GLYPH *p1 = str1;
1264 register GLYPH *p2 = str2;
1265 while (*p1++ == *p2++);
1266 return p1 - str1 - 1;
1267}
1268
1269/* Char insertion/deletion cost vector, from term.c */
1270extern int *char_ins_del_vector;
1271
1272#define char_ins_del_cost(s) (&char_ins_del_vector[SCREEN_HEIGHT((s))])
1273
1274static void
1275update_line (screen, vpos)
1276 register SCREEN_PTR screen;
1277 int vpos;
1278{
1279 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1280 int tem;
1281 int osp, nsp, begmatch, endmatch, olen, nlen;
1282 int save;
1283 register struct screen_glyphs *current_screen
1284 = SCREEN_CURRENT_GLYPHS (screen);
1285 register struct screen_glyphs *desired_screen
1286 = SCREEN_DESIRED_GLYPHS (screen);
1287
1288 if (desired_screen->highlight[vpos]
1289 != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
1290 {
1291 change_line_highlight (desired_screen->highlight[vpos], vpos,
1292 (current_screen->enable[vpos] ?
1293 current_screen->used[vpos] : 0));
1294 current_screen->enable[vpos] = 0;
1295 }
1296 else
1297 reassert_line_highlight (desired_screen->highlight[vpos], vpos);
1298
1299 if (! current_screen->enable[vpos])
1300 {
1301 olen = 0;
1302 }
1303 else
1304 {
1305 obody = current_screen->glyphs[vpos];
1306 olen = current_screen->used[vpos];
1307 if (! current_screen->highlight[vpos])
1308 {
1309 if (!must_write_spaces)
1310 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1311 olen--;
1312 }
1313 else
1314 {
1315 /* For an inverse-video line, remember we gave it
1316 spaces all the way to the screen edge
1317 so that the reverse video extends all the way across. */
1318
1319 while (olen < SCREEN_WIDTH (screen) - 1)
1320 obody[olen++] = SPACEGLYPH;
1321 }
1322 }
1323
1324 /* One way or another, this will enable the line being updated. */
1325 current_screen->enable[vpos] = 1;
1326 current_screen->used[vpos] = desired_screen->used[vpos];
1327 current_screen->highlight[vpos] = desired_screen->highlight[vpos];
1328 current_screen->bufp[vpos] = desired_screen->bufp[vpos];
1329
1330#ifdef HAVE_X_WINDOWS
1331 if (SCREEN_IS_X (screen))
1332 {
1333 current_screen->pix_width[vpos]
1334 = current_screen->used[vpos]
1335 * FONT_WIDTH (screen->display.x->font);
1336 current_screen->pix_height[vpos]
1337 = FONT_HEIGHT (screen->display.x->font);
1338 }
1339#endif /* HAVE_X_WINDOWS */
1340
1341 if (!desired_screen->enable[vpos])
1342 {
1343 nlen = 0;
1344 goto just_erase;
1345 }
1346
1347 nbody = desired_screen->glyphs[vpos];
1348 nlen = desired_screen->used[vpos];
1349
1350 /* Pretend trailing spaces are not there at all,
1351 unless for one reason or another we must write all spaces. */
1352 if (! desired_screen->highlight[vpos])
1353 {
1354 if (!must_write_spaces)
1355 /* We know that the previous character byte contains 0. */
1356 while (nbody[nlen - 1] == SPACEGLYPH)
1357 nlen--;
1358 }
1359 else
1360 {
1361 /* For an inverse-video line, give it extra trailing spaces
1362 all the way to the screen edge
1363 so that the reverse video extends all the way across. */
1364
1365 while (nlen < SCREEN_WIDTH (screen) - 1)
1366 nbody[nlen++] = SPACEGLYPH;
1367 }
1368
1369 /* If there's no i/d char, quickly do the best we can without it. */
1370 if (!char_ins_del_ok)
1371 {
1372 int i,j;
1373
1374 for (i = 0; i < nlen; i++)
1375 {
1376 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1377 {
1378 cursor_to (vpos, i);
1379 for (j = 1; (i + j < nlen &&
1380 (i + j >= olen || nbody[i+j] != obody[i+j]));
1381 j++);
1382
1383 /* Output this run of non-matching chars. */
1384 write_glyphs (nbody + i, j);
1385 i += j - 1;
1386
1387 /* Now find the next non-match. */
1388 }
1389 }
1390
1391 /* Clear the rest of the line, or the non-clear part of it. */
1392 if (olen > nlen)
1393 {
1394 cursor_to (vpos, nlen);
1395 clear_end_of_line (olen);
1396 }
1397
1398 /* Exchange contents between current_screen and new_screen. */
1399 temp = desired_screen->glyphs[vpos];
1400 desired_screen->glyphs[vpos] = current_screen->glyphs[vpos];
1401 current_screen->glyphs[vpos] = temp;
1402
1403 return;
1404 }
1405
1406 if (!olen)
1407 {
1408 nsp = (must_write_spaces || desired_screen->highlight[vpos])
1409 ? 0 : count_blanks (nbody);
1410 if (nlen > nsp)
1411 {
1412 cursor_to (vpos, nsp);
1413 write_glyphs (nbody + nsp, nlen - nsp);
1414 }
1415
1416 /* Exchange contents between current_screen and new_screen. */
1417 temp = desired_screen->glyphs[vpos];
1418 desired_screen->glyphs[vpos] = current_screen->glyphs[vpos];
1419 current_screen->glyphs[vpos] = temp;
1420
1421 return;
1422 }
1423
1424 obody[olen] = 1;
1425 save = nbody[nlen];
1426 nbody[nlen] = 0;
1427
1428 /* Compute number of leading blanks in old and new contents. */
1429 osp = count_blanks (obody);
1430 if (!desired_screen->highlight[vpos])
1431 nsp = count_blanks (nbody);
1432 else
1433 nsp = 0;
1434
1435 /* Compute number of matching chars starting with first nonblank. */
1436 begmatch = count_match (obody + osp, nbody + nsp);
1437
1438 /* Spaces in new match implicit space past the end of old. */
1439 /* A bug causing this to be a no-op was fixed in 18.29. */
1440 if (!must_write_spaces && osp + begmatch == olen)
1441 {
1442 np1 = nbody + nsp;
1443 while (np1[begmatch] == SPACEGLYPH)
1444 begmatch++;
1445 }
1446
1447 /* Avoid doing insert/delete char
1448 just cause number of leading spaces differs
1449 when the following text does not match. */
1450 if (begmatch == 0 && osp != nsp)
1451 osp = nsp = min (osp, nsp);
1452
1453 /* Find matching characters at end of line */
1454 op1 = obody + olen;
1455 np1 = nbody + nlen;
1456 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1457 while (op1 > op2 && op1[-1] == np1[-1])
1458 {
1459 op1--;
1460 np1--;
1461 }
1462 endmatch = obody + olen - op1;
1463
1464 /* Put correct value back in nbody[nlen].
1465 This is important because direct_output_for_insert
1466 can write into the line at a later point.
1467 If this screws up the zero at the end of the line, re-establish it. */
1468 nbody[nlen] = save;
1469 obody[olen] = 0;
1470
1471 /* tem gets the distance to insert or delete.
1472 endmatch is how many characters we save by doing so.
1473 Is it worth it? */
1474
1475 tem = (nlen - nsp) - (olen - osp);
1476 if (endmatch && tem
1477 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (screen)[tem]))
1478 endmatch = 0;
1479
1480 /* nsp - osp is the distance to insert or delete.
1481 If that is nonzero, begmatch is known to be nonzero also.
1482 begmatch + endmatch is how much we save by doing the ins/del.
1483 Is it worth it? */
1484
1485 if (nsp != osp
1486 && (!char_ins_del_ok
1487 || begmatch + endmatch <= char_ins_del_cost (screen)[nsp - osp]))
1488 {
1489 begmatch = 0;
1490 endmatch = 0;
1491 osp = nsp = min (osp, nsp);
1492 }
1493
1494 /* Now go through the line, inserting, writing and
1495 deleting as appropriate. */
1496
1497 if (osp > nsp)
1498 {
1499 cursor_to (vpos, nsp);
1500 delete_glyphs (osp - nsp);
1501 }
1502 else if (nsp > osp)
1503 {
1504 /* If going to delete chars later in line
1505 and insert earlier in the line,
1506 must delete first to avoid losing data in the insert */
1507 if (endmatch && nlen < olen + nsp - osp)
1508 {
1509 cursor_to (vpos, nlen - endmatch + osp - nsp);
1510 delete_glyphs (olen + nsp - osp - nlen);
1511 olen = nlen - (nsp - osp);
1512 }
1513 cursor_to (vpos, osp);
1514 insert_glyphs ((char *)0, nsp - osp);
1515 }
1516 olen += nsp - osp;
1517
1518 tem = nsp + begmatch + endmatch;
1519 if (nlen != tem || olen != tem)
1520 {
1521 cursor_to (vpos, nsp + begmatch);
1522 if (!endmatch || nlen == olen)
1523 {
1524 /* If new text being written reaches right margin,
1525 there is no need to do clear-to-eol at the end.
1526 (and it would not be safe, since cursor is not
1527 going to be "at the margin" after the text is done) */
1528 if (nlen == SCREEN_WIDTH (screen))
1529 olen = 0;
1530 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1531
1532#ifdef obsolete
1533
1534/* the following code loses disastrously if tem == nlen.
1535 Rather than trying to fix that case, I am trying the simpler
1536 solution found above. */
1537
1538 /* If the text reaches to the right margin,
1539 it will lose one way or another (depending on AutoWrap)
1540 to clear to end of line after outputting all the text.
1541 So pause with one character to go and clear the line then. */
1542 if (nlen == SCREEN_WIDTH (screen) && fast_clear_end_of_line && olen > nlen)
1543 {
1544 /* endmatch must be zero, and tem must equal nsp + begmatch */
1545 write_glyphs (nbody + tem, nlen - tem - 1);
1546 clear_end_of_line (olen);
1547 olen = 0; /* Don't let it be cleared again later */
1548 write_glyphs (nbody + nlen - 1, 1);
1549 }
1550 else
1551 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1552#endif /* OBSOLETE */
1553
1554 }
1555 else if (nlen > olen)
1556 {
1557 write_glyphs (nbody + nsp + begmatch, olen - tem);
1558 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1559 olen = nlen;
1560 }
1561 else if (olen > nlen)
1562 {
1563 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1564 delete_glyphs (olen - nlen);
1565 olen = nlen;
1566 }
1567 }
1568
1569 just_erase:
1570 /* If any unerased characters remain after the new line, erase them. */
1571 if (olen > nlen)
1572 {
1573 cursor_to (vpos, nlen);
1574 clear_end_of_line (olen);
1575 }
1576
1577 /* Exchange contents between current_screen and new_screen. */
1578 temp = desired_screen->glyphs[vpos];
1579 desired_screen->glyphs[vpos] = current_screen->glyphs[vpos];
1580 current_screen->glyphs[vpos] = temp;
1581}
1582\f
1583DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1584 1, 1, "FOpen termscript file: ",
1585 "Start writing all terminal output to FILE as well as the terminal.\n\
1586FILE = nil means just close any termscript file currently open.")
1587 (file)
1588 Lisp_Object file;
1589{
1590 if (termscript != 0) fclose (termscript);
1591 termscript = 0;
1592
efb859b4 1593 if (! NILP (file))
4588ec20
JB
1594 {
1595 file = Fexpand_file_name (file, Qnil);
1596 termscript = fopen (XSTRING (file)->data, "w");
1597 if (termscript == 0)
1598 report_file_error ("Opening termscript", Fcons (file, Qnil));
1599 }
1600 return Qnil;
1601}
1602\f
1603
1604#ifdef SIGWINCH
efb859b4 1605SIGTYPE
4588ec20
JB
1606window_change_signal ()
1607{
1608 int width, height;
1609 extern int errno;
1610 int old_errno = errno;
1611
1612 get_screen_size (&width, &height);
1613
1614 /* The screen size change obviously applies to a termcap-controlled
1615 screen. Find such a screen in the list, and assume it's the only
1616 one (since the redisplay code always writes to stdout, not a
1617 FILE * specified in the screen structure). Record the new size,
1618 but don't reallocate the data structures now. Let that be done
1619 later outside of the signal handler. */
1620
1621 {
1622 Lisp_Object tail;
1623
1624 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
1625 {
1626 SCREEN_PTR s = XSCREEN (XCONS (tail)->car);
1627
efb859b4 1628 if (SCREEN_IS_TERMCAP (s))
4588ec20
JB
1629 {
1630 ++in_display;
1631 change_screen_size (s, height, width, 0);
1632 --in_display;
1633 break;
1634 }
1635 }
1636 }
1637
1638 signal (SIGWINCH, window_change_signal);
1639 errno = old_errno;
1640}
1641#endif /* SIGWINCH */
1642
1643
1644/* Do any change in screen size that was requested by a signal. */
1645
1646do_pending_window_change ()
1647{
1648 /* If window_change_signal should have run before, run it now. */
1649 while (delayed_size_change)
1650 {
1651 Lisp_Object tail;
1652
1653 delayed_size_change = 0;
1654
1655 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
1656 {
1657 SCREEN_PTR s = XSCREEN (XCONS (tail)->car);
1658 int height = SCREEN_NEW_HEIGHT (s);
1659 int width = SCREEN_NEW_WIDTH (s);
1660
1661 SCREEN_NEW_HEIGHT (s) = 0;
1662 SCREEN_NEW_WIDTH (s) = 0;
1663
1664 if (height != 0)
1665 change_screen_size (s, height, width, 0);
1666 }
1667 }
1668}
1669
1670
1671/* Change the screen height and/or width. Values may be given as zero to
1672 indicate no change is to take place. */
1673
1674change_screen_size (screen, newlength, newwidth, pretend)
1675 register SCREEN_PTR screen;
1676 register int newlength, newwidth, pretend;
1677{
1678 /* If we can't deal with the change now, queue it for later. */
1679 if (in_display)
1680 {
1681 SCREEN_NEW_HEIGHT (screen) = newlength;
1682 SCREEN_NEW_WIDTH (screen) = newwidth;
1683 delayed_size_change = 1;
1684 return;
1685 }
1686
1687 /* This size-change overrides any pending one for this screen. */
1688 SCREEN_NEW_HEIGHT (screen) = 0;
1689 SCREEN_NEW_WIDTH (screen) = 0;
1690
1691 if ((newlength == 0 || newlength == SCREEN_HEIGHT (screen))
1692 && (newwidth == 0 || newwidth == SCREEN_WIDTH (screen)))
1693 return;
1694
1695 if (newlength && newlength != SCREEN_HEIGHT (screen))
1696 {
efb859b4
JB
1697 if (SCREEN_HAS_MINIBUF (screen)
1698 && ! SCREEN_MINIBUF_ONLY_P (screen))
4588ec20
JB
1699 {
1700 /* Screen has both root and minibuffer. */
1701 set_window_height (SCREEN_ROOT_WINDOW (screen),
1702 newlength - 1, 0);
1703 XFASTINT (XWINDOW (SCREEN_MINIBUF_WINDOW (screen))->top)
1704 = newlength - 1;
1705 set_window_height (SCREEN_MINIBUF_WINDOW (screen), 1, 0);
1706 }
1707 else
1708 /* Screen has just one top-level window. */
1709 set_window_height (SCREEN_ROOT_WINDOW (screen), newlength, 0);
1710
efb859b4 1711 if (SCREEN_IS_TERMCAP (screen) && !pretend)
4588ec20
JB
1712 ScreenRows = newlength;
1713
1714#if 0
1715 if (screen->output_method == output_termcap)
1716 {
1717 screen_height = newlength;
1718 if (!pretend)
1719 ScreenRows = newlength;
1720 }
1721#endif
1722 }
1723
1724 if (newwidth && newwidth != SCREEN_WIDTH (screen))
1725 {
1726 set_window_width (SCREEN_ROOT_WINDOW (screen), newwidth, 0);
efb859b4 1727 if (SCREEN_HAS_MINIBUF (screen))
4588ec20
JB
1728 set_window_width (SCREEN_MINIBUF_WINDOW (screen), newwidth, 0);
1729 SCREEN_WIDTH (screen) = newwidth;
1730
1731 if (SCREEN_IS_TERMCAP (screen) && !pretend)
1732 ScreenCols = newwidth;
1733#if 0
1734 if (screen->output_method == output_termcap)
1735 {
1736 screen_width = newwidth;
1737 if (!pretend)
1738 ScreenCols = newwidth;
1739 }
1740#endif
1741 }
1742
1743 if (newlength)
1744 SCREEN_HEIGHT (screen) = newlength;
1745
1746 remake_screen_glyphs (screen);
1747 calculate_costs (screen);
1748}
1749\f
1750DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
1751 Ssend_string_to_terminal, 1, 1, 0,
1752 "Send STRING to the terminal without alteration.\n\
1753Control characters in STRING will have terminal-dependent effects.")
1754 (str)
1755 Lisp_Object str;
1756{
1757 CHECK_STRING (str, 0);
1758 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
1759 fflush (stdout);
1760 if (termscript)
1761 {
1762 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
1763 fflush (termscript);
1764 }
1765 return Qnil;
1766}
1767
1768DEFUN ("ding", Fding, Sding, 0, 1, 0,
1769 "Beep, or flash the screen.\n\
1770Also, unless an argument is given,\n\
1771terminate any keyboard macro currently executing.")
1772 (arg)
1773 Lisp_Object arg;
1774{
efb859b4 1775 if (!NILP (arg))
4588ec20
JB
1776 {
1777 ring_bell ();
1778 fflush (stdout);
1779 }
1780 else
1781 bitch_at_user ();
1782
1783 return Qnil;
1784}
1785
1786bitch_at_user ()
1787{
1788 if (noninteractive)
1789 putchar (07);
1790 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
1791 error ("Keyboard macro terminated by a command ringing the bell");
1792 else
1793 ring_bell ();
1794 fflush (stdout);
1795}
1796
1797DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
1798 "Pause, without updating display, for ARG seconds.\n\
1799Optional second arg non-nil means ARG is measured in milliseconds.\n\
1800\(Not all operating systems support milliseconds.)")
1801 (n, millisec)
1802 Lisp_Object n, millisec;
1803{
1804#ifndef subprocesses
1805#ifdef HAVE_TIMEVAL
1806 struct timeval timeout, end_time, garbage1;
1807#endif /* HAVE_TIMEVAL */
1808#endif /* no subprocesses */
1809 int usec = 0;
1810 int sec;
1811
1812 CHECK_NUMBER (n, 0);
1813 sec = XINT (n);
1814 if (sec <= 0)
1815 return Qnil;
1816
efb859b4 1817 if (!NILP (millisec))
4588ec20
JB
1818 {
1819#ifndef HAVE_TIMEVAL
1820 error ("millisecond sit-for not supported on %s", SYSTEM_TYPE);
1821#else
1822 usec = sec % 1000 * 1000;
1823 sec /= 1000;
1824#endif
1825 }
1826
1827#ifdef subprocesses
1828 wait_reading_process_input (sec, usec, 0, 0);
1829#else /* No subprocesses */
1830 immediate_quit = 1;
1831 QUIT;
1832
1833#ifdef VMS
1834 sys_sleep (sec);
1835#else /* not VMS */
1836/* The reason this is done this way
1837 (rather than defined (H_S) && defined (H_T))
1838 is because the VMS preprocessor doesn't grok `defined' */
1839#ifdef HAVE_SELECT
1840#ifdef HAVE_TIMEVAL
1841 gettimeofday (&end_time, &garbage1);
1842 end_time.tv_sec += sec;
1843 end_time.tv_usec += usec;
1844 if (end_time.tv_usec >= 1000000)
1845 end_time.tv_sec++, end_time.tv_usec -= 1000000;
1846
1847 while (1)
1848 {
1849 gettimeofday (&timeout, &garbage1);
1850 timeout.tv_sec = end_time.tv_sec - timeout.tv_sec;
1851 timeout.tv_usec = end_time.tv_usec - timeout.tv_usec;
1852 if (timeout.tv_usec < 0)
1853 timeout.tv_usec += 1000000, timeout.tv_sec--;
1854 if (timeout.tv_sec < 0)
1855 break;
1856 if (!select (1, 0, 0, 0, &timeout))
1857 break;
1858 }
1859#else /* not HAVE_TIMEVAL */
1860 /* Is it safe to quit out of `sleep'? I'm afraid to trust it. */
1861 sleep (sec);
1862#endif /* HAVE_TIMEVAL */
1863#else /* not HAVE_SELECT */
1864 sleep (sec);
1865#endif /* HAVE_SELECT */
1866#endif /* not VMS */
1867
1868 immediate_quit = 0;
1869#endif /* no subprocesses */
1870
1871 return Qnil;
1872}
1873
1874DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
1875 "Perform redisplay, then wait for ARG seconds or until input is available.\n\
1876Optional second arg non-nil means ARG counts in milliseconds.\n\
1877Optional third arg non-nil means don't redisplay, just wait for input.\n\
1878Redisplay is preempted as always if input arrives, and does not happen\n\
1879if input is available before it starts.\n\
1880Value is t if waited the full time with no input arriving.")
1881 (n, millisec, nodisp)
1882 Lisp_Object n, millisec, nodisp;
1883{
1884#ifndef subprocesses
1885#ifdef HAVE_TIMEVAL
1886 struct timeval timeout;
1887#else
1888 int timeout_sec;
1889#endif
1890 int waitchannels;
1891#endif /* no subprocesses */
1892 int usec = 0;
1893 int sec;
1894
1895 CHECK_NUMBER (n, 0);
1896
1897 if (detect_input_pending ())
1898 return Qnil;
1899
1900 if (EQ (nodisp, Qnil))
1901 redisplay_preserve_echo_area ();
1902
1903 sec = XINT (n);
1904 if (sec <= 0)
1905 return Qt;
1906
efb859b4 1907 if (!NILP (millisec))
4588ec20
JB
1908 {
1909#ifndef HAVE_TIMEVAL
1910 error ("millisecond sleep-for not supported on %s", SYSTEM_TYPE);
1911#else
1912 usec = sec % 1000 * 1000;
1913 sec /= 1000;
1914#endif
1915 }
1916
1917#ifdef subprocesses
1918#ifdef SIGIO
1919 gobble_input ();
1920#endif /* SIGIO */
1921 wait_reading_process_input (sec, usec, 1, 1);
1922#else /* no subprocesses */
1923 immediate_quit = 1;
1924 QUIT;
1925
1926 waitchannels = 1;
1927#ifdef VMS
1928 input_wait_timeout (XINT (n));
1929#else /* not VMS */
1930#ifndef HAVE_TIMEVAL
1931 timeout_sec = sec;
1932 select (1, &waitchannels, 0, 0, &timeout_sec);
1933#else /* HAVE_TIMEVAL */
1934 timeout.tv_sec = sec;
1935 timeout.tv_usec = usec;
1936 select (1, &waitchannels, 0, 0, &timeout);
1937#endif /* HAVE_TIMEVAL */
1938#endif /* not VMS */
1939
1940 immediate_quit = 0;
1941#endif /* no subprocesses */
1942
1943 return detect_input_pending () ? Qnil : Qt;
1944}
1945
1946DEFUN ("sleep-for-millisecs", Fsleep_for_millisecs, Ssleep_for_millisecs,
1947 1, 1, 0,
1948 "Pause, without updating display, for ARG milliseconds.")
1949 (n)
1950 Lisp_Object n;
1951{
1952#ifndef HAVE_TIMEVAL
1953 error ("sleep-for-millisecs not supported on %s", SYSTEM_TYPE);
1954#else
1955 CHECK_NUMBER (n, 0);
1956 wait_reading_process_input (XINT (n) / 1000, XINT (n) % 1000 * 1000,
1957 0, 0);
1958 return Qnil;
1959#endif /* HAVE_TIMEVAL */
1960}
1961\f
1962char *terminal_type;
1963
1964/* Initialization done when Emacs fork is started, before doing stty. */
1965/* Determine terminal type and set terminal_driver */
1966/* Then invoke its decoding routine to set up variables
1967 in the terminal package */
1968
1969init_display ()
1970{
1971#ifdef HAVE_X_WINDOWS
1972 extern int display_arg;
1973#endif
1974
1975 meta_key = 0;
1976 inverse_video = 0;
1977 cursor_in_echo_area = 0;
1978 terminal_type = (char *) 0;
1979
1980 /* If the DISPLAY environment variable is set, try to use X, and
1981 die with an error message if that doesn't work. */
1982
1983 /* Check if we're using a window system here before trying to
1984 initialize the terminal. If we check the terminal first,
1985
1986 If someone has indicated that they want
1987 to use a window system, we shouldn't bother initializing the
1988 terminal. This is especially important when the terminal is so
1989 dumb that emacs gives up before and doesn't bother using the window
1990 system. */
1991
1992#ifdef HAVE_X_WINDOWS
efb859b4 1993 if (!inhibit_window_system && (display_arg || getenv ("DISPLAY")))
4588ec20
JB
1994 {
1995 Vwindow_system = intern ("x");
1996#ifdef HAVE_X11
1997 Vwindow_system_version = make_number (11);
1998#else
1999 Vwindow_system_version = make_number (10);
2000#endif
2001 return;
2002 }
2003#endif /* HAVE_X_WINDOWS */
2004
2005 /* If no window system has been specified, try to use the terminal. */
2006 if (! isatty (0))
2007 {
2008 fprintf (stderr, "emacs: standard input is not a tty\n");
2009 exit (1);
2010 }
2011
2012 /* Look at the TERM variable */
2013 terminal_type = (char *) getenv ("TERM");
2014 if (!terminal_type)
2015 {
2016#ifdef VMS
2017 fprintf (stderr, "Please specify your terminal type.\n\
2018For types defined in VMS, use set term /device=TYPE.\n\
2019For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2020\(The quotation marks are necessary since terminal types are lower case.)\n");
2021#else
2022 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2023#endif
2024 exit (1);
2025 }
2026
2027#ifdef VMS
2028 /* VMS DCL tends to upcase things, so downcase term type.
2029 Hardly any uppercase letters in terminal types; should be none. */
2030 {
2031 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2032 char *p;
2033
2034 strcpy (new, terminal_type);
2035
2036 for (p = new; *p; p++)
2037 if (isupper (*p))
2038 *p = tolower (*p);
2039
2040 terminal_type = new;
2041 }
2042#endif
2043
2044 term_init (terminal_type);
2045
2046 remake_screen_glyphs (selected_screen);
2047 calculate_costs (selected_screen);
2048
2049 /* X and Y coordinates of the cursor between updates. */
2050 SCREEN_CURSOR_X (selected_screen) = 0;
2051 SCREEN_CURSOR_Y (selected_screen) = 0;
2052
2053#ifdef SIGWINCH
2054#ifndef CANNOT_DUMP
2055 if (initialized)
2056#endif /* CANNOT_DUMP */
2057 signal (SIGWINCH, window_change_signal);
2058#endif /* SIGWINCH */
2059}
2060\f
2061syms_of_display ()
2062{
2063#ifdef MULTI_SCREEN
2064 defsubr (&Sredraw_screen);
2065#endif
2066 defsubr (&Sredraw_display);
2067 defsubr (&Sopen_termscript);
2068 defsubr (&Sding);
2069 defsubr (&Ssit_for);
2070 defsubr (&Ssleep_for);
2071 defsubr (&Ssend_string_to_terminal);
2072
2073 DEFVAR_INT ("baud-rate", &baud_rate,
2074 "The output baud rate of the terminal.\n\
2075On most systems, changing this value will affect the amount of padding\n\
2076and the other strategic decisions made during redisplay.");
2077 DEFVAR_BOOL ("inverse-video", &inverse_video,
2078 "*Non-nil means invert the entire screen display.\n\
2079This means everything is in inverse video which otherwise would not be.");
2080 DEFVAR_BOOL ("visible-bell", &visible_bell,
2081 "*Non-nil means try to flash the screen to represent a bell.");
2082 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
2083 "*Non-nil means no need to redraw entire screen after suspending.\n\
2084A non-nil value is useful if the terminal can automatically preserve\n\
2085Emacs's screen display when you reenter Emacs.\n\
2086It is up to you to set this variable if your terminal can do that.");
2087 DEFVAR_LISP ("window-system", &Vwindow_system,
2088 "A symbol naming the window-system under which Emacs is running\n\
2089\(such as `x'), or nil if emacs is running on an ordinary terminal.");
2090 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2091 "The version number of the window system in use.\n\
2092For X windows, this is 10 or 11.");
2093 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2094 "Non-nil means put cursor in minibuffer, at end of any message there.");
2095 DEFVAR_LISP ("glyph-table", &Vglyph_table,
2096 "Table defining how to output a glyph code to the screen.\n\
2097If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2098Each element can be:\n\
2099 integer: a glyph code which this glyph is an alias for.\n\
2100 string: output this glyph using that string (not impl. in X windows).\n\
2101 nil: this glyph mod 256 is char code to output,\n\
2102 and this glyph / 256 is face code for X windows (see `x-set-face').");
2103 Vglyph_table = Qnil;
2104
2105 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2106 "Display table to use for buffers that specify none.\n\
2107See `buffer-display-table' for more information.");
2108 Vstandard_display_table = Qnil;
2109
2110 /* Initialize `window-system', unless init_display already decided it. */
2111#ifdef CANNOT_DUMP
2112 if (noninteractive)
2113#endif
2114 {
2115 Vwindow_system = Qnil;
2116 Vwindow_system_version = Qnil;
2117 }
2118}
2119