*** empty log message ***
[emacs.git] / src / dispnew.c
blobed4321dfe72c2084180c93ebbeb9be94e6a890fb
1 /* Updating of data structures for redisplay.
2 Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <signal.h>
23 #include "config.h"
24 #include <stdio.h>
25 #include <ctype.h>
27 #include "termchar.h"
28 #include "termopts.h"
29 #include "cm.h"
30 #include "lisp.h"
31 #include "dispextern.h"
32 #include "buffer.h"
33 #include "screen.h"
34 #include "window.h"
35 #include "commands.h"
36 #include "disptab.h"
37 #include "indent.h"
39 #include "systerm.h"
40 #include "systime.h"
42 #ifdef HAVE_X_WINDOWS
43 #include "xterm.h"
44 #endif /* HAVE_X_WINDOWS */
46 #define max(a, b) ((a) > (b) ? (a) : (b))
47 #define min(a, b) ((a) < (b) ? (a) : (b))
49 #ifndef PENDING_OUTPUT_COUNT
50 /* Get number of chars of output now in the buffer of a stdio stream.
51 This ought to be built in in stdio, but it isn't.
52 Some s- files override this because their stdio internals differ. */
53 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
54 #endif
56 /* Nonzero upon entry to redisplay means do not assume anything about
57 current contents of actual terminal screen; clear and redraw it. */
59 int screen_garbaged;
61 /* Nonzero means last display completed. Zero means it was preempted. */
63 int display_completed;
65 /* Lisp variable visible-bell; enables use of screen-flash
66 instead of audible bell. */
68 int visible_bell;
70 /* Invert the color of the whole screen, at a low level. */
72 int inverse_video;
74 /* Line speed of the terminal. */
76 int baud_rate;
78 /* nil or a symbol naming the window system under which emacs is
79 running ('x is the only current possibility). */
81 Lisp_Object Vwindow_system;
83 /* Version number of X windows: 10, 11 or nil. */
84 Lisp_Object Vwindow_system_version;
86 /* Vector of glyph definitions. Indexed by glyph number,
87 the contents are a string which is how to output the glyph.
89 If Vglyph_table is nil, a glyph is output by using its low 8 bits
90 as a character code. */
92 Lisp_Object Vglyph_table;
94 /* Display table to use for vectors that don't specify their own. */
96 Lisp_Object Vstandard_display_table;
98 /* Nonzero means reading single-character input with prompt
99 so put cursor on minibuffer after the prompt. */
101 int cursor_in_echo_area;
103 /* The currently selected screen.
104 In a single-screen version, this variable always remains 0. */
106 SCREEN_PTR selected_screen;
108 /* In a single-screen version, the information that would otherwise
109 exist inside a `struct screen' lives in the following variables instead. */
111 #ifndef MULTI_SCREEN
113 /* Desired terminal cursor position (to show position of point),
114 origin zero */
116 int cursX, cursY;
118 /* Description of current screen contents */
120 struct screen_glyphs *current_glyphs;
122 /* Description of desired screen contents */
124 struct screen_glyphs *desired_glyphs;
126 #endif /* not MULTI_SCREEN */
128 /* This is a vector, made larger whenever it isn't large enough,
129 which is used inside `update_screen' to hold the old contents
130 of the SCREEN_PHYS_LINES of the screen being updated. */
131 struct screen_glyphs **ophys_lines;
132 /* Length of vector currently allocated. */
133 int ophys_lines_length;
135 FILE *termscript; /* Stdio stream being used for copy of all output. */
137 struct cm Wcm; /* Structure for info on cursor positioning */
139 extern short ospeed; /* Output speed (from sg_ospeed) */
141 int in_display; /* 1 if in redisplay: can't handle SIGWINCH now. */
143 int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
144 int delayed_screen_height; /* Remembered new screen height. */
145 int delayed_screen_width; /* Remembered new screen width. */
147 #ifdef MULTI_SCREEN
149 DEFUN ("redraw-screen", Fredraw_screen, Sredraw_screen, 1, 1, 0,
150 "Clear screen SCREEN and output again what is supposed to appear on it.")
151 (screen)
152 Lisp_Object screen;
154 SCREEN_PTR s;
156 CHECK_LIVE_SCREEN (screen, 0);
157 s = XSCREEN (screen);
158 update_begin (s);
159 /* set_terminal_modes (); */
160 clear_screen ();
161 update_end (s);
162 fflush (stdout);
163 clear_screen_records (s);
164 windows_or_buffers_changed++;
165 /* Mark all windows as INaccurate,
166 so that every window will have its redisplay done. */
167 mark_window_display_accurate (SCREEN_ROOT_WINDOW (s), 0);
168 s->garbaged = 0;
169 return Qnil;
172 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
173 "Redraw all screens marked as having their images garbled.")
176 Lisp_Object screen, tail;
178 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
180 screen = XCONS (tail)->car;
181 if (XSCREEN (screen)->garbaged && XSCREEN (screen)->visible)
182 Fredraw_screen (screen);
184 return Qnil;
187 redraw_screen (s)
188 SCREEN_PTR s;
190 Lisp_Object screen;
191 XSET (screen, Lisp_Screen, s);
192 Fredraw_screen (screen);
195 #else /* not MULTI_SCREEN */
197 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, 0,
198 "Clear screen and output again what is supposed to appear on it.")
201 update_begin (0);
202 set_terminal_modes ();
203 clear_screen ();
204 update_end (0);
205 fflush (stdout);
206 clear_screen_records (0);
207 windows_or_buffers_changed++;
208 /* Mark all windows as INaccurate,
209 so that every window will have its redisplay done. */
210 mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0);
211 return Qnil;
214 #endif /* not MULTI_SCREEN */
216 static struct screen_glyphs *
217 make_screen_glyphs (screen, empty)
218 register SCREEN_PTR screen;
219 int empty;
221 register int i;
222 register width = SCREEN_WIDTH (screen);
223 register height = SCREEN_HEIGHT (screen);
224 register struct screen_glyphs *new =
225 (struct screen_glyphs *) xmalloc (sizeof (struct screen_glyphs));
227 SET_GLYPHS_SCREEN (new, screen);
228 new->height = height;
229 new->width = width;
230 new->used = (int *) xmalloc (height * sizeof (int));
231 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
232 new->highlight = (char *) xmalloc (height * sizeof (char));
233 new->enable = (char *) xmalloc (height * sizeof (char));
234 bzero (new->enable, height * sizeof (char));
235 new->bufp = (int *) xmalloc (height * sizeof (int));
237 #ifdef HAVE_X_WINDOWS
238 if (SCREEN_IS_X (screen))
240 new->nruns = (int *) xmalloc (height * sizeof (int));
241 new->face_list
242 = (struct run **) xmalloc (height * sizeof (struct run *));
243 new->top_left_x = (short *) xmalloc (height * sizeof (short));
244 new->top_left_y = (short *) xmalloc (height * sizeof (short));
245 new->pix_width = (short *) xmalloc (height * sizeof (short));
246 new->pix_height = (short *) xmalloc (height * sizeof (short));
248 #endif
250 if (empty)
252 /* Make the buffer used by decode_mode_spec. This buffer is also
253 used as temporary storage when updating the screen. See scroll.c. */
254 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
256 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
257 bzero (new->total_contents, total_glyphs);
259 else
261 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
263 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
264 bzero (new->total_contents, total_glyphs);
265 for (i = 0; i < height; i++)
266 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
269 return new;
272 static void
273 free_screen_glyphs (screen, glyphs)
274 SCREEN_PTR screen;
275 struct screen_glyphs *glyphs;
277 if (glyphs->total_contents)
278 free (glyphs->total_contents);
280 free (glyphs->used);
281 free (glyphs->glyphs);
282 free (glyphs->highlight);
283 free (glyphs->enable);
284 free (glyphs->bufp);
286 #ifdef HAVE_X_WINDOWS
287 if (SCREEN_IS_X (screen))
289 free (glyphs->nruns);
290 free (glyphs->face_list);
291 free (glyphs->top_left_x);
292 free (glyphs->top_left_y);
293 free (glyphs->pix_width);
294 free (glyphs->pix_height);
296 #endif
298 free (glyphs);
301 static void
302 remake_screen_glyphs (screen)
303 SCREEN_PTR screen;
305 if (SCREEN_CURRENT_GLYPHS (screen))
306 free_screen_glyphs (screen, SCREEN_CURRENT_GLYPHS (screen));
307 if (SCREEN_DESIRED_GLYPHS (screen))
308 free_screen_glyphs (screen, SCREEN_DESIRED_GLYPHS (screen));
309 if (SCREEN_TEMP_GLYPHS (screen))
310 free_screen_glyphs (screen, SCREEN_TEMP_GLYPHS (screen));
312 if (SCREEN_MESSAGE_BUF (screen))
313 SCREEN_MESSAGE_BUF (screen)
314 = (char *) xrealloc (SCREEN_MESSAGE_BUF (screen),
315 SCREEN_WIDTH (screen) + 1);
316 else
317 SCREEN_MESSAGE_BUF (screen)
318 = (char *) xmalloc (SCREEN_WIDTH (screen) + 1);
320 SCREEN_CURRENT_GLYPHS (screen) = make_screen_glyphs (screen, 0);
321 SCREEN_DESIRED_GLYPHS (screen) = make_screen_glyphs (screen, 0);
322 SCREEN_TEMP_GLYPHS (screen) = make_screen_glyphs (screen, 1);
323 SET_SCREEN_GARBAGED (screen);
326 /* Return the hash code of contents of line VPOS in screen-matrix M. */
328 static int
329 line_hash_code (m, vpos)
330 register struct screen_glyphs *m;
331 int vpos;
333 register GLYPH *body, *end;
334 register int h = 0;
336 if (!m->enable[vpos])
337 return 0;
339 /* Give all lighlighted lines the same hash code
340 so as to encourage scrolling to leave them in place. */
341 if (m->highlight[vpos])
342 return -1;
344 body = m->glyphs[vpos];
346 if (must_write_spaces)
347 while (1)
349 GLYPH g = *body++;
351 if (g == 0)
352 break;
353 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
355 else
356 while (1)
358 GLYPH g = *body++;
360 if (g == 0)
361 break;
362 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
365 if (h)
366 return h;
367 return 1;
370 /* Return number of characters in line in M at vpos VPOS,
371 except don't count leading and trailing spaces
372 unless the terminal requires those to be explicitly output. */
374 static unsigned int
375 line_draw_cost (m, vpos)
376 struct screen_glyphs *m;
377 int vpos;
379 register GLYPH *beg = m->glyphs[vpos];
380 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
381 register int i;
382 register int tlen = GLYPH_TABLE_LENGTH;
383 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
385 /* Ignore trailing and leading spaces if we can. */
386 if (!must_write_spaces)
388 while ((end != beg) && (*end == SPACEGLYPH))
389 --end;
390 if (end == beg)
391 return (0); /* All blank line. */
393 while (*beg == SPACEGLYPH)
394 ++beg;
397 /* If we don't have a glyph-table, each glyph is one character,
398 so return the number of glyphs. */
399 if (tbase == 0)
400 return end - beg;
402 /* Otherwise, scan the glyphs and accumulate their total size in I. */
403 i = 0;
404 while ((beg <= end) && *beg)
406 register GLYPH g = *beg++;
408 if (GLYPH_SIMPLE_P (tbase, tlen, g))
409 i += 1;
410 else
411 i += GLYPH_LENGTH (tbase, g);
413 return i;
416 /* The functions on this page are the interface from xdisp.c to redisplay.
418 The only other interface into redisplay is through setting
419 SCREEN_CURSOR_X (screen) and SCREEN_CURSOR_Y (screen)
420 and SET_SCREEN_GARBAGED (screen). */
422 /* cancel_line eliminates any request to display a line at position `vpos' */
424 cancel_line (vpos, screen)
425 int vpos;
426 register SCREEN_PTR screen;
428 SCREEN_DESIRED_GLYPHS (screen)->enable[vpos] = 0;
431 clear_screen_records (screen)
432 register SCREEN_PTR screen;
434 bzero (SCREEN_CURRENT_GLYPHS (screen)->enable, SCREEN_HEIGHT (screen));
437 /* Prepare to display on line VPOS starting at HPOS within it. */
439 void
440 get_display_line (screen, vpos, hpos)
441 register SCREEN_PTR screen;
442 int vpos;
443 register int hpos;
445 register struct screen_glyphs *glyphs;
446 register struct screen_glyphs *desired_glyphs = SCREEN_DESIRED_GLYPHS (screen);
447 register GLYPH *p;
449 if (vpos < 0 || (! SCREEN_VISIBLE_P (screen)))
450 abort ();
452 if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
453 abort ();
455 if (! desired_glyphs->enable[vpos])
457 desired_glyphs->used[vpos] = 0;
458 desired_glyphs->highlight[vpos] = 0;
459 desired_glyphs->enable[vpos] = 1;
462 if (hpos > desired_glyphs->used[vpos])
464 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
465 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
467 desired_glyphs->used[vpos] = hpos;
468 while (g != end)
469 *g++ = SPACEGLYPH;
473 /* Like bcopy except never gets confused by overlap. */
475 void
476 safe_bcopy (from, to, size)
477 char *from, *to;
478 int size;
480 register char *endf;
481 register char *endt;
483 if (size == 0)
484 return;
486 /* If destination is higher in memory, and overlaps source zone,
487 copy from the end. */
488 if (from < to && from + size > to)
490 endf = from + size;
491 endt = to + size;
493 /* If TO - FROM is large, then we should break the copy into
494 nonoverlapping chunks of TO - FROM bytes each. However, if
495 TO - FROM is small, then the bcopy function call overhead
496 makes this not worth it. The crossover point could be about
497 anywhere. Since I don't think the obvious copy loop is ever
498 too bad, I'm trying to err in its favor. */
499 if (to - from < 64)
502 *--endt = *--endf;
503 while (endf != from);
505 else
507 /* Since TO - FROM >= 64, the overlap is less than SIZE,
508 so we can always safely do this loop once. */
509 while (endt > to)
511 endt -= (to - from);
512 endf -= (to - from);
514 bcopy (endf, endt, to - from);
517 /* If TO - FROM wasn't a multiple of SIZE, there will be a
518 little left over. The amount left over is
519 (endt + (to - from)) - to, which is endt - from. */
520 bcopy (from, to, endt - from);
523 else
524 bcopy (from, to, size);
527 #if 0
528 void
529 safe_bcopy (from, to, size)
530 char *from, *to;
531 int size;
533 register char *endf;
534 register char *endt;
536 if (size == 0)
537 return;
539 /* If destination is higher in memory, and overlaps source zone,
540 copy from the end. */
541 if (from < to && from + size > to)
543 endf = from + size;
544 endt = to + size;
547 *--endt = *--endf;
548 while (endf != from);
550 return;
553 bcopy (from, to, size);
555 #endif
557 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
558 DISTANCE may be negative. */
560 static void
561 rotate_vector (vector, size, distance)
562 char *vector;
563 int size;
564 int distance;
566 char *temp = (char *) alloca (size);
568 if (distance < 0)
569 distance += size;
571 bcopy (vector, temp + distance, size - distance);
572 bcopy (vector + size - distance, temp, distance);
573 bcopy (temp, vector, size);
576 /* Scroll lines from vpos FROM up to but not including vpos END
577 down by AMOUNT lines (AMOUNT may be negative).
578 Returns nonzero if done, zero if terminal cannot scroll them. */
581 scroll_screen_lines (screen, from, end, amount)
582 register SCREEN_PTR screen;
583 int from, end, amount;
585 register int i;
586 register struct screen_glyphs *current_screen
587 = SCREEN_CURRENT_GLYPHS (screen);
589 if (!line_ins_del_ok)
590 return 0;
592 if (amount == 0)
593 return 1;
595 if (amount > 0)
597 update_begin (screen);
598 set_terminal_window (end + amount);
599 if (!scroll_region_ok)
600 ins_del_lines (end, -amount);
601 ins_del_lines (from, amount);
602 set_terminal_window (0);
604 rotate_vector (current_screen->glyphs + from,
605 sizeof (GLYPH *) * (end + amount - from),
606 amount * sizeof (GLYPH *));
608 safe_bcopy (current_screen->used + from,
609 current_screen->used + from + amount,
610 (end - from) * sizeof current_screen->used[0]);
612 safe_bcopy (current_screen->highlight + from,
613 current_screen->highlight + from + amount,
614 (end - from) * sizeof current_screen->highlight[0]);
616 safe_bcopy (current_screen->enable + from,
617 current_screen->enable + from + amount,
618 (end - from) * sizeof current_screen->enable[0]);
620 /* Mark the lines made empty by scrolling as enabled, empty and
621 normal video. */
622 bzero (current_screen->used + from,
623 amount * sizeof current_screen->used[0]);
624 bzero (current_screen->highlight + from,
625 amount * sizeof current_screen->highlight[0]);
626 for (i = from; i < from + amount; i++)
628 current_screen->glyphs[i][0] = '\0';
629 current_screen->enable[i] = 1;
632 safe_bcopy (current_screen->bufp + from,
633 current_screen->bufp + from + amount,
634 (end - from) * sizeof current_screen->bufp[0]);
636 #ifdef HAVE_X_WINDOWS
637 if (SCREEN_IS_X (screen))
639 safe_bcopy (current_screen->nruns + from,
640 current_screen->nruns + from + amount,
641 (end - from) * sizeof current_screen->nruns[0]);
643 safe_bcopy (current_screen->face_list + from,
644 current_screen->face_list + from + amount,
645 (end - from) * sizeof current_screen->face_list[0]);
647 safe_bcopy (current_screen->top_left_x + from,
648 current_screen->top_left_x + from + amount,
649 (end - from) * sizeof current_screen->top_left_x[0]);
651 safe_bcopy (current_screen->top_left_y + from,
652 current_screen->top_left_y + from + amount,
653 (end - from) * sizeof current_screen->top_left_y[0]);
655 safe_bcopy (current_screen->pix_width + from,
656 current_screen->pix_width + from + amount,
657 (end - from) * sizeof current_screen->pix_width[0]);
659 safe_bcopy (current_screen->pix_height + from,
660 current_screen->pix_height + from + amount,
661 (end - from) * sizeof current_screen->pix_height[0]);
663 #endif /* HAVE_X_WINDOWS */
665 update_end (screen);
667 if (amount < 0)
669 update_begin (screen);
670 set_terminal_window (end);
671 ins_del_lines (from + amount, amount);
672 if (!scroll_region_ok)
673 ins_del_lines (end + amount, -amount);
674 set_terminal_window (0);
676 rotate_vector (current_screen->glyphs + from + amount,
677 sizeof (GLYPH *) * (end - from - amount),
678 amount * sizeof (GLYPH *));
680 safe_bcopy (current_screen->used + from,
681 current_screen->used + from + amount,
682 (end - from) * sizeof current_screen->used[0]);
684 safe_bcopy (current_screen->highlight + from,
685 current_screen->highlight + from + amount,
686 (end - from) * sizeof current_screen->highlight[0]);
688 safe_bcopy (current_screen->enable + from,
689 current_screen->enable + from + amount,
690 (end - from) * sizeof current_screen->enable[0]);
692 /* Mark the lines made empty by scrolling as enabled, empty and
693 normal video. */
694 bzero (current_screen->used + end + amount,
695 - amount * sizeof current_screen->used[0]);
696 bzero (current_screen->highlight + end + amount,
697 - amount * sizeof current_screen->highlight[0]);
698 for (i = end + amount; i < end; i++)
700 current_screen->glyphs[i][0] = '\0';
701 current_screen->enable[i] = 1;
704 safe_bcopy (current_screen->bufp + from,
705 current_screen->bufp + from + amount,
706 (end - from) * sizeof current_screen->bufp[0]);
708 #ifdef HAVE_X_WINDOWS
709 if (SCREEN_IS_X (screen))
711 safe_bcopy (current_screen->nruns + from,
712 current_screen->nruns + from + amount,
713 (end - from) * sizeof current_screen->nruns[0]);
715 safe_bcopy (current_screen->face_list + from,
716 current_screen->face_list + from + amount,
717 (end - from) * sizeof current_screen->face_list[0]);
719 safe_bcopy (current_screen->top_left_x + from,
720 current_screen->top_left_x + from + amount,
721 (end - from) * sizeof current_screen->top_left_x[0]);
723 safe_bcopy (current_screen->top_left_y + from,
724 current_screen->top_left_y + from + amount,
725 (end - from) * sizeof current_screen->top_left_y[0]);
727 safe_bcopy (current_screen->pix_width + from,
728 current_screen->pix_width + from + amount,
729 (end - from) * sizeof current_screen->pix_width[0]);
731 safe_bcopy (current_screen->pix_height + from,
732 current_screen->pix_height + from + amount,
733 (end - from) * sizeof current_screen->pix_height[0]);
735 #endif /* HAVE_X_WINDOWS */
737 update_end (screen);
739 return 1;
742 /* After updating a window W that isn't the full screen wide,
743 copy all the columns that W does not occupy
744 into the SCREEN_DESIRED_GLYPHS (screen) from the SCREEN_PHYS_GLYPHS (screen)
745 so that update_screen will not change those columns. */
747 preserve_other_columns (w)
748 struct window *w;
750 register int vpos;
751 register struct screen_glyphs *current_screen, *desired_screen;
752 register SCREEN_PTR screen = XSCREEN (w->screen);
753 int start = XFASTINT (w->left);
754 int end = XFASTINT (w->left) + XFASTINT (w->width);
755 int bot = XFASTINT (w->top) + XFASTINT (w->height);
757 current_screen = SCREEN_CURRENT_GLYPHS (screen);
758 desired_screen = SCREEN_DESIRED_GLYPHS (screen);
760 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
762 if (current_screen->enable[vpos] && desired_screen->enable[vpos])
764 if (start > 0)
766 int len;
768 bcopy (current_screen->glyphs[vpos],
769 desired_screen->glyphs[vpos], start);
770 len = min (start, current_screen->used[vpos]);
771 if (desired_screen->used[vpos] < len)
772 desired_screen->used[vpos] = len;
774 if (current_screen->used[vpos] > end
775 && desired_screen->used[vpos] < current_screen->used[vpos])
777 while (desired_screen->used[vpos] < end)
778 desired_screen->glyphs[vpos][desired_screen->used[vpos]++]
779 = SPACEGLYPH;
780 bcopy (current_screen->glyphs[vpos] + end,
781 desired_screen->glyphs[vpos] + end,
782 current_screen->used[vpos] - end);
783 desired_screen->used[vpos] = current_screen->used[vpos];
789 #if 0
791 /* If window w does not need to be updated and isn't the full screen wide,
792 copy all the columns that w does occupy
793 into the SCREEN_DESIRED_LINES (screen) from the SCREEN_PHYS_LINES (screen)
794 so that update_screen will not change those columns.
796 Have not been able to figure out how to use this correctly. */
798 preserve_my_columns (w)
799 struct window *w;
801 register int vpos, fin;
802 register struct screen_glyphs *l1, *l2;
803 register SCREEN_PTR screen = XSCREEN (w->screen);
804 int start = XFASTINT (w->left);
805 int end = XFASTINT (w->left) + XFASTINT (w->width);
806 int bot = XFASTINT (w->top) + XFASTINT (w->height);
808 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
810 if ((l1 = SCREEN_DESIRED_GLYPHS (screen)->glyphs[vpos + 1])
811 && (l2 = SCREEN_PHYS_GLYPHS (screen)->glyphs[vpos + 1]))
813 if (l2->length > start && l1->length < l2->length)
815 fin = l2->length;
816 if (fin > end) fin = end;
817 while (l1->length < start)
818 l1->body[l1->length++] = ' ';
819 bcopy (l2->body + start, l1->body + start, fin - start);
820 l1->length = fin;
826 #endif
828 /* On discovering that the redisplay for a window was no good,
829 cancel the columns of that window, so that when the window is
830 displayed over again get_display_line will not complain. */
832 cancel_my_columns (w)
833 struct window *w;
835 register int vpos;
836 register SCREEN_PTR screen = XSCREEN (w->screen);
837 register struct screen_glyphs *desired_glyphs = screen->desired_glyphs;
838 register int start = XFASTINT (w->left);
839 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
841 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
842 if (desired_glyphs->enable[vpos]
843 && desired_glyphs->used[vpos] >= start)
844 desired_glyphs->used[vpos] = start;
847 /* These functions try to perform directly and immediately on the screen
848 the necessary output for one change in the buffer.
849 They may return 0 meaning nothing was done if anything is difficult,
850 or 1 meaning the output was performed properly.
851 They assume that the screen was up to date before the buffer
852 change being displayed. THey make various other assumptions too;
853 see command_loop_1 where these are called. */
856 direct_output_for_insert (g)
857 int g;
859 register SCREEN_PTR screen = selected_screen;
860 register struct screen_glyphs *current_screen
861 = SCREEN_CURRENT_GLYPHS (screen);
863 #ifndef COMPILER_REGISTER_BUG
864 register
865 #endif /* COMPILER_REGISTER_BUG */
866 struct window *w = XWINDOW (selected_window);
867 #ifndef COMPILER_REGISTER_BUG
868 register
869 #endif /* COMPILER_REGISTER_BUG */
870 int hpos = SCREEN_CURSOR_X (screen);
871 #ifndef COMPILER_REGISTER_BUG
872 register
873 #endif /* COMPILER_REGISTER_BUG */
874 int vpos = SCREEN_CURSOR_Y (screen);
876 /* Give up if about to continue line */
877 if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
879 /* Avoid losing if cursor is in invisible text off left margin */
880 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
882 /* Give up if cursor outside window (in minibuf, probably) */
883 || SCREEN_CURSOR_Y (screen) < XFASTINT (w->top)
884 || SCREEN_CURSOR_Y (screen) >= XFASTINT (w->top) + XFASTINT (w->height)
886 /* Give up if cursor not really at SCREEN_CURSOR_X, SCREEN_CURSOR_Y */
887 || !display_completed
889 /* Give up if buffer appears in two places. */
890 || buffer_shared > 1
892 /* Give up if w is minibuffer and a message is being displayed there */
893 || (MINI_WINDOW_P (w) && echo_area_glyphs))
894 return 0;
896 current_screen->glyphs[vpos][hpos] = g;
897 unchanged_modified = MODIFF;
898 beg_unchanged = GPT - BEG;
899 XFASTINT (w->last_point) = point;
900 XFASTINT (w->last_point_x) = hpos;
901 XFASTINT (w->last_modified) = MODIFF;
903 reassert_line_highlight (0, vpos);
904 write_glyphs (&current_screen->glyphs[vpos][hpos], 1);
905 fflush (stdout);
906 ++SCREEN_CURSOR_X (screen);
907 if (hpos == current_screen->used[vpos])
909 current_screen->used[vpos] = hpos + 1;
910 current_screen->glyphs[vpos][hpos + 1] = 0;
913 return 1;
917 direct_output_forward_char (n)
918 int n;
920 register SCREEN_PTR screen = selected_screen;
921 register struct window *w = XWINDOW (selected_window);
923 /* Avoid losing if cursor is in invisible text off left margin
924 or about to go off either side of window. */
925 if ((SCREEN_CURSOR_X (screen) == XFASTINT (w->left)
926 && (XINT (w->hscroll) || n < 0))
927 || (n > 0
928 && (SCREEN_CURSOR_X (screen) + 1
929 >= (XFASTINT (w->left) + XFASTINT (w->width)
930 - (XFASTINT (w->width) < SCREEN_WIDTH (screen))
931 - 1))))
932 return 0;
934 SCREEN_CURSOR_X (screen) += n;
935 XFASTINT (w->last_point_x) = SCREEN_CURSOR_X (screen);
936 XFASTINT (w->last_point) = point;
937 cursor_to (SCREEN_CURSOR_Y (screen), SCREEN_CURSOR_X (screen));
938 fflush (stdout);
939 return 1;
942 static void update_line ();
944 /* Update screen S based on the data in SCREEN_DESIRED_GLYPHS.
945 Value is nonzero if redisplay stopped due to pending input.
946 FORCE nonzero means do not stop for pending input. */
949 update_screen (s, force, inhibit_hairy_id)
950 SCREEN_PTR s;
951 int force;
952 int inhibit_hairy_id;
954 register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
955 register struct screen_glyphs *desired_screen = SCREEN_DESIRED_GLYPHS (s);
956 register int i;
957 int pause;
958 int preempt_count = baud_rate / 2400 + 1;
959 extern input_pending;
960 #ifdef HAVE_X_WINDOWS
961 register int downto, leftmost;
962 #endif
964 if (SCREEN_HEIGHT (s) == 0) abort (); /* Some bug zeros some core */
966 detect_input_pending ();
967 if (input_pending && !force)
969 pause = 1;
970 goto do_pause;
973 update_begin (s);
975 if (!line_ins_del_ok)
976 inhibit_hairy_id = 1;
978 /* See if any of the desired lines are enabled; don't compute for
979 i/d line if just want cursor motion. */
980 for (i = 0; i < SCREEN_HEIGHT (s); i++)
981 if (desired_screen->enable[i])
982 break;
984 /* Try doing i/d line, if not yet inhibited. */
985 if (!inhibit_hairy_id && i < SCREEN_HEIGHT (s))
986 force |= scrolling (s);
988 /* Update the individual lines as needed. Do bottom line first. */
990 if (desired_screen->enable[SCREEN_HEIGHT (s) - 1])
991 update_line (s, SCREEN_HEIGHT (s) - 1);
993 #ifdef HAVE_X_WINDOWS
994 if (SCREEN_IS_X (s))
996 leftmost = downto = s->display.x->internal_border_width;
997 if (desired_screen->enable[0])
999 current_screen->top_left_x[SCREEN_HEIGHT (s) - 1] = leftmost;
1000 current_screen->top_left_y[SCREEN_HEIGHT (s) - 1]
1001 = PIXEL_HEIGHT (s) - s->display.x->internal_border_width
1002 - LINE_HEIGHT(s, SCREEN_HEIGHT (s) - 1);
1003 current_screen->top_left_x[0] = leftmost;
1004 current_screen->top_left_y[0] = downto;
1007 #endif /* HAVE_X_WINDOWS */
1009 /* Now update the rest of the lines. */
1010 for (i = 0; i < SCREEN_HEIGHT (s) - 1 && (force || !input_pending); i++)
1012 if (desired_screen->enable[i])
1014 if (SCREEN_IS_TERMCAP (s))
1016 /* Flush out every so many lines.
1017 Also flush out if likely to have more than 1k buffered
1018 otherwise. I'm told that some telnet connections get
1019 really screwed by more than 1k output at once. */
1020 int outq = PENDING_OUTPUT_COUNT (stdout);
1021 if (outq > 900
1022 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1024 fflush (stdout);
1025 if (preempt_count == 1)
1027 #ifdef EMACS_OUTQSIZE
1028 if (EMACS_OUTQSIZE (0, &outq) < 0)
1029 /* Probably not a tty. Ignore the error and reset
1030 * the outq count. */
1031 outq = PENDING_OUTPUT_COUNT (stdout);
1032 #endif
1033 outq *= 10;
1034 sleep (outq / baud_rate);
1037 if ((i - 1) % preempt_count == 0)
1038 detect_input_pending ();
1041 update_line (s, i);
1042 #ifdef HAVE_X_WINDOWS
1043 if (SCREEN_IS_X (s))
1045 current_screen->top_left_y[i] = downto;
1046 current_screen->top_left_x[i] = leftmost;
1048 #endif /* HAVE_X_WINDOWS */
1051 if (SCREEN_IS_X (s))
1052 downto += LINE_HEIGHT(s, i);
1054 pause = (i < SCREEN_HEIGHT (s) - 1) ? i : 0;
1056 /* Now just clean up termcap drivers and set cursor, etc. */
1057 if (!pause)
1060 if (s == selected_screen && cursor_in_echo_area < 0)
1061 cursor_to (SCREEN_HEIGHT (s) - 1, 0);
1062 else if (s == selected_screen && cursor_in_echo_area
1063 && !desired_screen->used[SCREEN_HEIGHT (s) - 1])
1064 cursor_to (SCREEN_HEIGHT (s), 0);
1065 else if (cursor_in_echo_area)
1066 cursor_to (SCREEN_HEIGHT (s) - 1,
1067 min (SCREEN_WIDTH (s) - 1,
1068 desired_screen->used[SCREEN_HEIGHT (s) - 1]));
1069 else
1070 cursor_to (SCREEN_CURSOR_Y (s), max (min (SCREEN_CURSOR_X (s),
1071 SCREEN_WIDTH (s) - 1), 0));
1074 update_end (s);
1076 if (termscript)
1077 fflush (termscript);
1078 fflush (stdout);
1080 /* Here if output is preempted because input is detected. */
1081 do_pause:
1083 if (SCREEN_HEIGHT (s) == 0) abort (); /* Some bug zeros some core */
1084 display_completed = !pause;
1086 bzero (desired_screen->enable, SCREEN_HEIGHT (s));
1087 return pause;
1090 /* Called when about to quit, to check for doing so
1091 at an improper time. */
1093 void
1094 quit_error_check ()
1096 if (SCREEN_DESIRED_GLYPHS (selected_screen) == 0)
1097 return;
1098 if (SCREEN_DESIRED_GLYPHS (selected_screen)->enable[0])
1099 abort ();
1100 if (SCREEN_DESIRED_GLYPHS (selected_screen)->enable[SCREEN_HEIGHT (selected_screen) - 1])
1101 abort ();
1104 /* Decide what insert/delete line to do, and do it */
1106 extern void scrolling_1 ();
1108 scrolling (screen)
1109 SCREEN_PTR screen;
1111 int unchanged_at_top, unchanged_at_bottom;
1112 int window_size;
1113 int changed_lines;
1114 int *old_hash = (int *) alloca (SCREEN_HEIGHT (screen) * sizeof (int));
1115 int *new_hash = (int *) alloca (SCREEN_HEIGHT (screen) * sizeof (int));
1116 int *draw_cost = (int *) alloca (SCREEN_HEIGHT (screen) * sizeof (int));
1117 register int i;
1118 int free_at_end_vpos = SCREEN_HEIGHT (screen);
1119 register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (screen);
1120 register struct screen_glyphs *desired_screen = SCREEN_DESIRED_GLYPHS (screen);
1122 /* Compute hash codes of all the lines.
1123 Also calculate number of changed lines,
1124 number of unchanged lines at the beginning,
1125 and number of unchanged lines at the end. */
1127 changed_lines = 0;
1128 unchanged_at_top = 0;
1129 unchanged_at_bottom = SCREEN_HEIGHT (screen);
1130 for (i = 0; i < SCREEN_HEIGHT (screen); i++)
1132 /* Give up on this scrolling if some old lines are not enabled. */
1133 if (!current_screen->enable[i])
1134 return 0;
1135 old_hash[i] = line_hash_code (current_screen, i);
1136 if (! desired_screen->enable[i])
1137 new_hash[i] = old_hash[i];
1138 else
1139 new_hash[i] = line_hash_code (desired_screen, i);
1141 if (old_hash[i] != new_hash[i])
1143 changed_lines++;
1144 unchanged_at_bottom = SCREEN_HEIGHT (screen) - i - 1;
1146 else if (i == unchanged_at_top)
1147 unchanged_at_top++;
1148 draw_cost[i] = line_draw_cost (desired_screen, i);
1151 /* If changed lines are few, don't allow preemption, don't scroll. */
1152 if (changed_lines < baud_rate / 2400
1153 || unchanged_at_bottom == SCREEN_HEIGHT (screen))
1154 return 1;
1156 window_size = (SCREEN_HEIGHT (screen) - unchanged_at_top
1157 - unchanged_at_bottom);
1159 if (scroll_region_ok)
1160 free_at_end_vpos -= unchanged_at_bottom;
1161 else if (memory_below_screen)
1162 free_at_end_vpos = -1;
1164 /* If large window, fast terminal and few lines in common between
1165 current screen and desired screen, don't bother with i/d calc. */
1166 if (window_size >= 18 && baud_rate > 2400
1167 && (window_size >=
1168 10 * scrolling_max_lines_saved (unchanged_at_top,
1169 SCREEN_HEIGHT (screen) - unchanged_at_bottom,
1170 old_hash, new_hash, draw_cost)))
1171 return 0;
1173 scrolling_1 (screen, window_size, unchanged_at_top, unchanged_at_bottom,
1174 draw_cost + unchanged_at_top - 1,
1175 old_hash + unchanged_at_top - 1,
1176 new_hash + unchanged_at_top - 1,
1177 free_at_end_vpos - unchanged_at_top);
1179 return 0;
1182 /* Return the offset in its buffer of the character at location col, line
1183 in the given window. */
1185 buffer_posn_from_coords (window, col, line)
1186 struct window *window;
1187 int col, line;
1189 int window_left = XFASTINT (window->left);
1191 /* The actual width of the window is window->width less one for the
1192 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1193 window. */
1194 int window_width = (XFASTINT (window->width) - 1
1195 - (XFASTINT (window->width) + window_left
1196 != SCREEN_WIDTH (XSCREEN (window->screen))));
1198 int startp = marker_position (window->start);
1200 /* Since compute_motion will only operate on the current buffer,
1201 we need to save the old one and restore it when we're done. */
1202 struct buffer *old_current_buffer = current_buffer;
1203 struct position *posn;
1205 current_buffer = XBUFFER (window->buffer);
1207 /* It would be nice if we could use SCREEN_CURRENT_GLYPHS (XSCREEN
1208 (window->screen))->bufp to avoid scanning from the very top of
1209 the window, but it isn't maintained correctly, and I'm not even
1210 sure I will keep it. */
1211 posn = compute_motion (startp, 0,
1212 (window == XWINDOW (minibuf_window) && startp == 1
1213 ? minibuf_prompt_width : 0),
1214 ZV, line, col - window_left,
1215 window_width, XINT (window->hscroll), 0);
1217 current_buffer = old_current_buffer;
1219 /* compute_motion considers screen points past the end of a line
1220 to be *after* the newline, i.e. at the start of the next line.
1221 This is reasonable, but not really what we want. So if the
1222 result is on a line below LINE, back it up one character. */
1223 if (posn->vpos > line)
1224 return posn->bufpos - 1;
1225 else
1226 return posn->bufpos;
1229 static int
1230 count_blanks (r)
1231 register GLYPH *r;
1233 register GLYPH *p = r;
1234 while (*r++ == SPACEGLYPH);
1235 return r - p - 1;
1238 static int
1239 count_match (str1, str2)
1240 GLYPH *str1, *str2;
1242 register GLYPH *p1 = str1;
1243 register GLYPH *p2 = str2;
1244 while (*p1++ == *p2++);
1245 return p1 - str1 - 1;
1248 /* Char insertion/deletion cost vector, from term.c */
1249 extern int *char_ins_del_vector;
1251 #define char_ins_del_cost(s) (&char_ins_del_vector[SCREEN_HEIGHT((s))])
1253 static void
1254 update_line (screen, vpos)
1255 register SCREEN_PTR screen;
1256 int vpos;
1258 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1259 int tem;
1260 int osp, nsp, begmatch, endmatch, olen, nlen;
1261 int save;
1262 register struct screen_glyphs *current_screen
1263 = SCREEN_CURRENT_GLYPHS (screen);
1264 register struct screen_glyphs *desired_screen
1265 = SCREEN_DESIRED_GLYPHS (screen);
1267 if (desired_screen->highlight[vpos]
1268 != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
1270 change_line_highlight (desired_screen->highlight[vpos], vpos,
1271 (current_screen->enable[vpos] ?
1272 current_screen->used[vpos] : 0));
1273 current_screen->enable[vpos] = 0;
1275 else
1276 reassert_line_highlight (desired_screen->highlight[vpos], vpos);
1278 if (! current_screen->enable[vpos])
1280 olen = 0;
1282 else
1284 obody = current_screen->glyphs[vpos];
1285 olen = current_screen->used[vpos];
1286 if (! current_screen->highlight[vpos])
1288 if (!must_write_spaces)
1289 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1290 olen--;
1292 else
1294 /* For an inverse-video line, remember we gave it
1295 spaces all the way to the screen edge
1296 so that the reverse video extends all the way across. */
1298 while (olen < SCREEN_WIDTH (screen) - 1)
1299 obody[olen++] = SPACEGLYPH;
1303 /* One way or another, this will enable the line being updated. */
1304 current_screen->enable[vpos] = 1;
1305 current_screen->used[vpos] = desired_screen->used[vpos];
1306 current_screen->highlight[vpos] = desired_screen->highlight[vpos];
1307 current_screen->bufp[vpos] = desired_screen->bufp[vpos];
1309 #ifdef HAVE_X_WINDOWS
1310 if (SCREEN_IS_X (screen))
1312 current_screen->pix_width[vpos]
1313 = current_screen->used[vpos]
1314 * FONT_WIDTH (screen->display.x->font);
1315 current_screen->pix_height[vpos]
1316 = FONT_HEIGHT (screen->display.x->font);
1318 #endif /* HAVE_X_WINDOWS */
1320 if (!desired_screen->enable[vpos])
1322 nlen = 0;
1323 goto just_erase;
1326 nbody = desired_screen->glyphs[vpos];
1327 nlen = desired_screen->used[vpos];
1329 /* Pretend trailing spaces are not there at all,
1330 unless for one reason or another we must write all spaces. */
1331 if (! desired_screen->highlight[vpos])
1333 if (!must_write_spaces)
1334 /* We know that the previous character byte contains 0. */
1335 while (nbody[nlen - 1] == SPACEGLYPH)
1336 nlen--;
1338 else
1340 /* For an inverse-video line, give it extra trailing spaces
1341 all the way to the screen edge
1342 so that the reverse video extends all the way across. */
1344 while (nlen < SCREEN_WIDTH (screen) - 1)
1345 nbody[nlen++] = SPACEGLYPH;
1348 /* If there's no i/d char, quickly do the best we can without it. */
1349 if (!char_ins_del_ok)
1351 int i,j;
1353 for (i = 0; i < nlen; i++)
1355 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1357 cursor_to (vpos, i);
1358 for (j = 1; (i + j < nlen &&
1359 (i + j >= olen || nbody[i+j] != obody[i+j]));
1360 j++);
1362 /* Output this run of non-matching chars. */
1363 write_glyphs (nbody + i, j);
1364 i += j - 1;
1366 /* Now find the next non-match. */
1370 /* Clear the rest of the line, or the non-clear part of it. */
1371 if (olen > nlen)
1373 cursor_to (vpos, nlen);
1374 clear_end_of_line (olen);
1377 /* Exchange contents between current_screen and new_screen. */
1378 temp = desired_screen->glyphs[vpos];
1379 desired_screen->glyphs[vpos] = current_screen->glyphs[vpos];
1380 current_screen->glyphs[vpos] = temp;
1382 return;
1385 if (!olen)
1387 nsp = (must_write_spaces || desired_screen->highlight[vpos])
1388 ? 0 : count_blanks (nbody);
1389 if (nlen > nsp)
1391 cursor_to (vpos, nsp);
1392 write_glyphs (nbody + nsp, nlen - nsp);
1395 /* Exchange contents between current_screen and new_screen. */
1396 temp = desired_screen->glyphs[vpos];
1397 desired_screen->glyphs[vpos] = current_screen->glyphs[vpos];
1398 current_screen->glyphs[vpos] = temp;
1400 return;
1403 obody[olen] = 1;
1404 save = nbody[nlen];
1405 nbody[nlen] = 0;
1407 /* Compute number of leading blanks in old and new contents. */
1408 osp = count_blanks (obody);
1409 if (!desired_screen->highlight[vpos])
1410 nsp = count_blanks (nbody);
1411 else
1412 nsp = 0;
1414 /* Compute number of matching chars starting with first nonblank. */
1415 begmatch = count_match (obody + osp, nbody + nsp);
1417 /* Spaces in new match implicit space past the end of old. */
1418 /* A bug causing this to be a no-op was fixed in 18.29. */
1419 if (!must_write_spaces && osp + begmatch == olen)
1421 np1 = nbody + nsp;
1422 while (np1[begmatch] == SPACEGLYPH)
1423 begmatch++;
1426 /* Avoid doing insert/delete char
1427 just cause number of leading spaces differs
1428 when the following text does not match. */
1429 if (begmatch == 0 && osp != nsp)
1430 osp = nsp = min (osp, nsp);
1432 /* Find matching characters at end of line */
1433 op1 = obody + olen;
1434 np1 = nbody + nlen;
1435 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1436 while (op1 > op2 && op1[-1] == np1[-1])
1438 op1--;
1439 np1--;
1441 endmatch = obody + olen - op1;
1443 /* Put correct value back in nbody[nlen].
1444 This is important because direct_output_for_insert
1445 can write into the line at a later point.
1446 If this screws up the zero at the end of the line, re-establish it. */
1447 nbody[nlen] = save;
1448 obody[olen] = 0;
1450 /* tem gets the distance to insert or delete.
1451 endmatch is how many characters we save by doing so.
1452 Is it worth it? */
1454 tem = (nlen - nsp) - (olen - osp);
1455 if (endmatch && tem
1456 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (screen)[tem]))
1457 endmatch = 0;
1459 /* nsp - osp is the distance to insert or delete.
1460 If that is nonzero, begmatch is known to be nonzero also.
1461 begmatch + endmatch is how much we save by doing the ins/del.
1462 Is it worth it? */
1464 if (nsp != osp
1465 && (!char_ins_del_ok
1466 || begmatch + endmatch <= char_ins_del_cost (screen)[nsp - osp]))
1468 begmatch = 0;
1469 endmatch = 0;
1470 osp = nsp = min (osp, nsp);
1473 /* Now go through the line, inserting, writing and
1474 deleting as appropriate. */
1476 if (osp > nsp)
1478 cursor_to (vpos, nsp);
1479 delete_glyphs (osp - nsp);
1481 else if (nsp > osp)
1483 /* If going to delete chars later in line
1484 and insert earlier in the line,
1485 must delete first to avoid losing data in the insert */
1486 if (endmatch && nlen < olen + nsp - osp)
1488 cursor_to (vpos, nlen - endmatch + osp - nsp);
1489 delete_glyphs (olen + nsp - osp - nlen);
1490 olen = nlen - (nsp - osp);
1492 cursor_to (vpos, osp);
1493 insert_glyphs ((char *)0, nsp - osp);
1495 olen += nsp - osp;
1497 tem = nsp + begmatch + endmatch;
1498 if (nlen != tem || olen != tem)
1500 cursor_to (vpos, nsp + begmatch);
1501 if (!endmatch || nlen == olen)
1503 /* If new text being written reaches right margin,
1504 there is no need to do clear-to-eol at the end.
1505 (and it would not be safe, since cursor is not
1506 going to be "at the margin" after the text is done) */
1507 if (nlen == SCREEN_WIDTH (screen))
1508 olen = 0;
1509 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1511 #ifdef obsolete
1513 /* the following code loses disastrously if tem == nlen.
1514 Rather than trying to fix that case, I am trying the simpler
1515 solution found above. */
1517 /* If the text reaches to the right margin,
1518 it will lose one way or another (depending on AutoWrap)
1519 to clear to end of line after outputting all the text.
1520 So pause with one character to go and clear the line then. */
1521 if (nlen == SCREEN_WIDTH (screen) && fast_clear_end_of_line && olen > nlen)
1523 /* endmatch must be zero, and tem must equal nsp + begmatch */
1524 write_glyphs (nbody + tem, nlen - tem - 1);
1525 clear_end_of_line (olen);
1526 olen = 0; /* Don't let it be cleared again later */
1527 write_glyphs (nbody + nlen - 1, 1);
1529 else
1530 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1531 #endif /* OBSOLETE */
1534 else if (nlen > olen)
1536 write_glyphs (nbody + nsp + begmatch, olen - tem);
1537 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1538 olen = nlen;
1540 else if (olen > nlen)
1542 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1543 delete_glyphs (olen - nlen);
1544 olen = nlen;
1548 just_erase:
1549 /* If any unerased characters remain after the new line, erase them. */
1550 if (olen > nlen)
1552 cursor_to (vpos, nlen);
1553 clear_end_of_line (olen);
1556 /* Exchange contents between current_screen and new_screen. */
1557 temp = desired_screen->glyphs[vpos];
1558 desired_screen->glyphs[vpos] = current_screen->glyphs[vpos];
1559 current_screen->glyphs[vpos] = temp;
1562 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1563 1, 1, "FOpen termscript file: ",
1564 "Start writing all terminal output to FILE as well as the terminal.\n\
1565 FILE = nil means just close any termscript file currently open.")
1566 (file)
1567 Lisp_Object file;
1569 if (termscript != 0) fclose (termscript);
1570 termscript = 0;
1572 if (! NILP (file))
1574 file = Fexpand_file_name (file, Qnil);
1575 termscript = fopen (XSTRING (file)->data, "w");
1576 if (termscript == 0)
1577 report_file_error ("Opening termscript", Fcons (file, Qnil));
1579 return Qnil;
1583 #ifdef SIGWINCH
1584 SIGTYPE
1585 window_change_signal ()
1587 int width, height;
1588 extern int errno;
1589 int old_errno = errno;
1591 get_screen_size (&width, &height);
1593 /* The screen size change obviously applies to a termcap-controlled
1594 screen. Find such a screen in the list, and assume it's the only
1595 one (since the redisplay code always writes to stdout, not a
1596 FILE * specified in the screen structure). Record the new size,
1597 but don't reallocate the data structures now. Let that be done
1598 later outside of the signal handler. */
1601 Lisp_Object tail;
1603 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
1605 SCREEN_PTR s = XSCREEN (XCONS (tail)->car);
1607 if (SCREEN_IS_TERMCAP (s))
1609 ++in_display;
1610 change_screen_size (s, height, width, 0);
1611 --in_display;
1612 break;
1617 signal (SIGWINCH, window_change_signal);
1618 errno = old_errno;
1620 #endif /* SIGWINCH */
1623 /* Do any change in screen size that was requested by a signal. */
1625 do_pending_window_change ()
1627 /* If window_change_signal should have run before, run it now. */
1628 while (delayed_size_change)
1630 Lisp_Object tail;
1632 delayed_size_change = 0;
1634 for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
1636 SCREEN_PTR s = XSCREEN (XCONS (tail)->car);
1637 int height = SCREEN_NEW_HEIGHT (s);
1638 int width = SCREEN_NEW_WIDTH (s);
1640 SCREEN_NEW_HEIGHT (s) = 0;
1641 SCREEN_NEW_WIDTH (s) = 0;
1643 if (height != 0)
1644 change_screen_size (s, height, width, 0);
1650 /* Change the screen height and/or width. Values may be given as zero to
1651 indicate no change is to take place. */
1653 change_screen_size (screen, newlength, newwidth, pretend)
1654 register SCREEN_PTR screen;
1655 register int newlength, newwidth, pretend;
1657 /* If we can't deal with the change now, queue it for later. */
1658 if (in_display)
1660 SCREEN_NEW_HEIGHT (screen) = newlength;
1661 SCREEN_NEW_WIDTH (screen) = newwidth;
1662 delayed_size_change = 1;
1663 return;
1666 /* This size-change overrides any pending one for this screen. */
1667 SCREEN_NEW_HEIGHT (screen) = 0;
1668 SCREEN_NEW_WIDTH (screen) = 0;
1670 if ((newlength == 0 || newlength == SCREEN_HEIGHT (screen))
1671 && (newwidth == 0 || newwidth == SCREEN_WIDTH (screen)))
1672 return;
1674 if (newlength && newlength != SCREEN_HEIGHT (screen))
1676 if (SCREEN_HAS_MINIBUF (screen)
1677 && ! SCREEN_MINIBUF_ONLY_P (screen))
1679 /* Screen has both root and minibuffer. */
1680 set_window_height (SCREEN_ROOT_WINDOW (screen),
1681 newlength - 1, 0);
1682 XFASTINT (XWINDOW (SCREEN_MINIBUF_WINDOW (screen))->top)
1683 = newlength - 1;
1684 set_window_height (SCREEN_MINIBUF_WINDOW (screen), 1, 0);
1686 else
1687 /* Screen has just one top-level window. */
1688 set_window_height (SCREEN_ROOT_WINDOW (screen), newlength, 0);
1690 if (SCREEN_IS_TERMCAP (screen) && !pretend)
1691 ScreenRows = newlength;
1693 #if 0
1694 if (screen->output_method == output_termcap)
1696 screen_height = newlength;
1697 if (!pretend)
1698 ScreenRows = newlength;
1700 #endif
1703 if (newwidth && newwidth != SCREEN_WIDTH (screen))
1705 set_window_width (SCREEN_ROOT_WINDOW (screen), newwidth, 0);
1706 if (SCREEN_HAS_MINIBUF (screen))
1707 set_window_width (SCREEN_MINIBUF_WINDOW (screen), newwidth, 0);
1708 SCREEN_WIDTH (screen) = newwidth;
1710 if (SCREEN_IS_TERMCAP (screen) && !pretend)
1711 ScreenCols = newwidth;
1712 #if 0
1713 if (screen->output_method == output_termcap)
1715 screen_width = newwidth;
1716 if (!pretend)
1717 ScreenCols = newwidth;
1719 #endif
1722 if (newlength)
1723 SCREEN_HEIGHT (screen) = newlength;
1725 remake_screen_glyphs (screen);
1726 calculate_costs (screen);
1729 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
1730 Ssend_string_to_terminal, 1, 1, 0,
1731 "Send STRING to the terminal without alteration.\n\
1732 Control characters in STRING will have terminal-dependent effects.")
1733 (str)
1734 Lisp_Object str;
1736 CHECK_STRING (str, 0);
1737 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
1738 fflush (stdout);
1739 if (termscript)
1741 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
1742 fflush (termscript);
1744 return Qnil;
1747 DEFUN ("ding", Fding, Sding, 0, 1, 0,
1748 "Beep, or flash the screen.\n\
1749 Also, unless an argument is given,\n\
1750 terminate any keyboard macro currently executing.")
1751 (arg)
1752 Lisp_Object arg;
1754 if (!NILP (arg))
1756 ring_bell ();
1757 fflush (stdout);
1759 else
1760 bitch_at_user ();
1762 return Qnil;
1765 bitch_at_user ()
1767 if (noninteractive)
1768 putchar (07);
1769 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
1770 error ("Keyboard macro terminated by a command ringing the bell");
1771 else
1772 ring_bell ();
1773 fflush (stdout);
1776 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
1777 "Pause, without updating display, for ARG seconds.\n\
1778 Optional second arg non-nil means ARG is measured in milliseconds.\n\
1779 \(Not all operating systems support milliseconds.)")
1780 (n, millisec)
1781 Lisp_Object n, millisec;
1783 int usec = 0;
1784 int sec;
1786 CHECK_NUMBER (n, 0);
1787 sec = XINT (n);
1788 if (sec <= 0)
1789 return Qnil;
1791 if (!NILP (millisec))
1793 #ifndef EMACS_HAS_USECS
1794 error ("millisecond sit-for not supported on %s", SYSTEM_TYPE);
1795 #else
1796 usec = sec % 1000 * 1000;
1797 sec /= 1000;
1798 #endif
1801 wait_reading_process_input (sec, usec, 0, 0);
1803 #if 0 /* No wait_reading_process_input */
1804 immediate_quit = 1;
1805 QUIT;
1807 #ifdef VMS
1808 sys_sleep (sec);
1809 #else /* not VMS */
1810 /* The reason this is done this way
1811 (rather than defined (H_S) && defined (H_T))
1812 is because the VMS preprocessor doesn't grok `defined' */
1813 #ifdef HAVE_SELECT
1814 EMACS_GET_TIME (end_time);
1815 EMACS_SET_SECS_USECS (timeout, sec, usec);
1816 EMACS_ADD_TIME (end_time, end_time, timeout);
1818 while (1)
1820 EMACS_GET_TIME (timeout);
1821 EMACS_SUB_TIME (timeout, end_time, timeout);
1822 if (EMACS_TIME_NEG_P (timeout)
1823 || !select (1, 0, 0, 0, &timeout))
1824 break;
1826 #else /* not HAVE_SELECT */
1827 sleep (sec);
1828 #endif /* HAVE_SELECT */
1829 #endif /* not VMS */
1831 immediate_quit = 0;
1832 #endif /* no subprocesses */
1834 return Qnil;
1837 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
1838 "Perform redisplay, then wait for ARG seconds or until input is available.\n\
1839 Optional second arg non-nil means ARG counts in milliseconds.\n\
1840 Optional third arg non-nil means don't redisplay, just wait for input.\n\
1841 Redisplay is preempted as always if input arrives, and does not happen\n\
1842 if input is available before it starts.\n\
1843 Value is t if waited the full time with no input arriving.")
1844 (n, millisec, nodisp)
1845 Lisp_Object n, millisec, nodisp;
1847 int usec = 0;
1848 int sec;
1850 CHECK_NUMBER (n, 0);
1852 if (detect_input_pending ())
1853 return Qnil;
1855 if (EQ (nodisp, Qnil))
1856 redisplay_preserve_echo_area ();
1858 sec = XINT (n);
1859 if (sec <= 0)
1860 return Qt;
1862 if (!NILP (millisec))
1864 #ifndef EMACS_HAS_USECS
1865 error ("millisecond sleep-for not supported on %s", SYSTEM_TYPE);
1866 #else
1867 usec = sec % 1000 * 1000;
1868 sec /= 1000;
1869 #endif
1872 #ifdef SIGIO
1873 gobble_input ();
1874 #endif /* SIGIO */
1875 wait_reading_process_input (sec, usec, 1, 1);
1877 #if 0 /* No wait_reading_process_input available. */
1878 immediate_quit = 1;
1879 QUIT;
1881 waitchannels = 1;
1882 #ifdef VMS
1883 input_wait_timeout (XINT (n));
1884 #else /* not VMS */
1885 #ifndef HAVE_TIMEVAL
1886 timeout_sec = sec;
1887 select (1, &waitchannels, 0, 0, &timeout_sec);
1888 #else /* HAVE_TIMEVAL */
1889 timeout.tv_sec = sec;
1890 timeout.tv_usec = usec;
1891 select (1, &waitchannels, 0, 0, &timeout);
1892 #endif /* HAVE_TIMEVAL */
1893 #endif /* not VMS */
1895 immediate_quit = 0;
1896 #endif
1898 return detect_input_pending () ? Qnil : Qt;
1901 DEFUN ("sleep-for-millisecs", Fsleep_for_millisecs, Ssleep_for_millisecs,
1902 1, 1, 0,
1903 "Pause, without updating display, for ARG milliseconds.")
1905 Lisp_Object n;
1907 #ifndef EMACS_HAS_USECS
1908 error ("sleep-for-millisecs not supported on %s", SYSTEM_TYPE);
1909 #else
1910 CHECK_NUMBER (n, 0);
1911 wait_reading_process_input (XINT (n) / 1000, XINT (n) % 1000 * 1000,
1912 0, 0);
1913 return Qnil;
1914 #endif /* EMACS_HAS_USECS */
1917 char *terminal_type;
1919 /* Initialization done when Emacs fork is started, before doing stty. */
1920 /* Determine terminal type and set terminal_driver */
1921 /* Then invoke its decoding routine to set up variables
1922 in the terminal package */
1924 init_display ()
1926 #ifdef HAVE_X_WINDOWS
1927 extern int display_arg;
1928 #endif
1930 meta_key = 0;
1931 inverse_video = 0;
1932 cursor_in_echo_area = 0;
1933 terminal_type = (char *) 0;
1935 /* If the DISPLAY environment variable is set, try to use X, and
1936 die with an error message if that doesn't work. */
1938 /* Check if we're using a window system here before trying to
1939 initialize the terminal. If we check the terminal first,
1941 If someone has indicated that they want
1942 to use a window system, we shouldn't bother initializing the
1943 terminal. This is especially important when the terminal is so
1944 dumb that emacs gives up before and doesn't bother using the window
1945 system. */
1947 #ifdef HAVE_X_WINDOWS
1948 if (!inhibit_window_system && (display_arg || getenv ("DISPLAY")))
1950 Vwindow_system = intern ("x");
1951 #ifdef HAVE_X11
1952 Vwindow_system_version = make_number (11);
1953 #else
1954 Vwindow_system_version = make_number (10);
1955 #endif
1956 return;
1958 #endif /* HAVE_X_WINDOWS */
1960 /* If no window system has been specified, try to use the terminal. */
1961 if (! isatty (0))
1963 fprintf (stderr, "emacs: standard input is not a tty\n");
1964 exit (1);
1967 /* Look at the TERM variable */
1968 terminal_type = (char *) getenv ("TERM");
1969 if (!terminal_type)
1971 #ifdef VMS
1972 fprintf (stderr, "Please specify your terminal type.\n\
1973 For types defined in VMS, use set term /device=TYPE.\n\
1974 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
1975 \(The quotation marks are necessary since terminal types are lower case.)\n");
1976 #else
1977 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
1978 #endif
1979 exit (1);
1982 #ifdef VMS
1983 /* VMS DCL tends to upcase things, so downcase term type.
1984 Hardly any uppercase letters in terminal types; should be none. */
1986 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
1987 char *p;
1989 strcpy (new, terminal_type);
1991 for (p = new; *p; p++)
1992 if (isupper (*p))
1993 *p = tolower (*p);
1995 terminal_type = new;
1997 #endif
1999 term_init (terminal_type);
2001 remake_screen_glyphs (selected_screen);
2002 calculate_costs (selected_screen);
2004 /* X and Y coordinates of the cursor between updates. */
2005 SCREEN_CURSOR_X (selected_screen) = 0;
2006 SCREEN_CURSOR_Y (selected_screen) = 0;
2008 #ifdef SIGWINCH
2009 #ifndef CANNOT_DUMP
2010 if (initialized)
2011 #endif /* CANNOT_DUMP */
2012 signal (SIGWINCH, window_change_signal);
2013 #endif /* SIGWINCH */
2016 syms_of_display ()
2018 #ifdef MULTI_SCREEN
2019 defsubr (&Sredraw_screen);
2020 #endif
2021 defsubr (&Sredraw_display);
2022 defsubr (&Sopen_termscript);
2023 defsubr (&Sding);
2024 defsubr (&Ssit_for);
2025 defsubr (&Ssleep_for);
2026 defsubr (&Ssend_string_to_terminal);
2028 DEFVAR_INT ("baud-rate", &baud_rate,
2029 "The output baud rate of the terminal.\n\
2030 On most systems, changing this value will affect the amount of padding\n\
2031 and the other strategic decisions made during redisplay.");
2032 DEFVAR_BOOL ("inverse-video", &inverse_video,
2033 "*Non-nil means invert the entire screen display.\n\
2034 This means everything is in inverse video which otherwise would not be.");
2035 DEFVAR_BOOL ("visible-bell", &visible_bell,
2036 "*Non-nil means try to flash the screen to represent a bell.");
2037 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
2038 "*Non-nil means no need to redraw entire screen after suspending.\n\
2039 A non-nil value is useful if the terminal can automatically preserve\n\
2040 Emacs's screen display when you reenter Emacs.\n\
2041 It is up to you to set this variable if your terminal can do that.");
2042 DEFVAR_LISP ("window-system", &Vwindow_system,
2043 "A symbol naming the window-system under which Emacs is running\n\
2044 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
2045 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2046 "The version number of the window system in use.\n\
2047 For X windows, this is 10 or 11.");
2048 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2049 "Non-nil means put cursor in minibuffer, at end of any message there.");
2050 DEFVAR_LISP ("glyph-table", &Vglyph_table,
2051 "Table defining how to output a glyph code to the screen.\n\
2052 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2053 Each element can be:\n\
2054 integer: a glyph code which this glyph is an alias for.\n\
2055 string: output this glyph using that string (not impl. in X windows).\n\
2056 nil: this glyph mod 256 is char code to output,\n\
2057 and this glyph / 256 is face code for X windows (see `x-set-face').");
2058 Vglyph_table = Qnil;
2060 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2061 "Display table to use for buffers that specify none.\n\
2062 See `buffer-display-table' for more information.");
2063 Vstandard_display_table = Qnil;
2065 /* Initialize `window-system', unless init_display already decided it. */
2066 #ifdef CANNOT_DUMP
2067 if (noninteractive)
2068 #endif
2070 Vwindow_system = Qnil;
2071 Vwindow_system_version = Qnil;