(window_change_signal): Add ignored argument.
[emacs.git] / src / dispnew.c
blob3fbc9f55f8d231dde1a0461f588eeed7b24204dd
1 /* Updating of data structures for redisplay.
2 Copyright (C) 1985, 86, 87, 88, 93, 94 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 2, 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>
25 #include <stdio.h>
26 #include <ctype.h>
28 #include "lisp.h"
29 #include "termchar.h"
30 #include "termopts.h"
31 #include "termhooks.h"
32 #include "cm.h"
33 #include "dispextern.h"
34 #include "buffer.h"
35 #include "frame.h"
36 #include "window.h"
37 #include "commands.h"
38 #include "disptab.h"
39 #include "indent.h"
40 #include "intervals.h"
42 #include "systty.h"
44 #ifdef HAVE_X_WINDOWS
45 #include "xterm.h"
46 #endif /* HAVE_X_WINDOWS */
48 /* Include systime.h after xterm.h to avoid double inclusion of time.h. */
49 #include "systime.h"
51 #include <errno.h>
53 #define max(a, b) ((a) > (b) ? (a) : (b))
54 #define min(a, b) ((a) < (b) ? (a) : (b))
56 /* Get number of chars of output now in the buffer of a stdio stream.
57 This ought to be built in in stdio, but it isn't.
58 Some s- files override this because their stdio internals differ. */
59 #ifdef __GNU_LIBRARY__
60 /* The s- file might have overridden the definition with one that works for
61 the system's C library. But we are using the GNU C library, so this is
62 the right definition for every system. */
63 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
64 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
65 #else
66 #undef PENDING_OUTPUT_COUNT
67 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
68 #endif
69 #else /* not __GNU_LIBRARY__ */
70 #ifndef PENDING_OUTPUT_COUNT
71 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
72 #endif
73 #endif
75 /* Nonzero upon entry to redisplay means do not assume anything about
76 current contents of actual terminal frame; clear and redraw it. */
78 int frame_garbaged;
80 /* Nonzero means last display completed. Zero means it was preempted. */
82 int display_completed;
84 /* Lisp variable visible-bell; enables use of screen-flash
85 instead of audible bell. */
87 int visible_bell;
89 /* Invert the color of the whole frame, at a low level. */
91 int inverse_video;
93 /* Line speed of the terminal. */
95 int baud_rate;
97 /* nil or a symbol naming the window system under which emacs is
98 running ('x is the only current possibility). */
100 Lisp_Object Vwindow_system;
102 /* Version number of X windows: 10, 11 or nil. */
103 Lisp_Object Vwindow_system_version;
105 /* Vector of glyph definitions. Indexed by glyph number,
106 the contents are a string which is how to output the glyph.
108 If Vglyph_table is nil, a glyph is output by using its low 8 bits
109 as a character code. */
111 Lisp_Object Vglyph_table;
113 /* Display table to use for vectors that don't specify their own. */
115 Lisp_Object Vstandard_display_table;
117 /* Nonzero means reading single-character input with prompt
118 so put cursor on minibuffer after the prompt.
119 positive means at end of text in echo area;
120 negative means at beginning of line. */
121 int cursor_in_echo_area;
123 /* The currently selected frame.
124 In a single-frame version, this variable always holds the address of
125 the_only_frame. */
127 FRAME_PTR selected_frame;
129 /* A frame which is not just a minibuffer, or 0 if there are no such
130 frames. This is usually the most recent such frame that was
131 selected. In a single-frame version, this variable always holds
132 the address of the_only_frame. */
133 FRAME_PTR last_nonminibuf_frame;
135 /* In a single-frame version, the information that would otherwise
136 exist inside frame objects lives in the following structure instead.
138 NOTE: the_only_frame is not checked for garbage collection; don't
139 store collectible objects in any of its fields!
141 You're not/The only frame in town/... */
143 #ifndef MULTI_FRAME
144 struct frame the_only_frame;
145 #endif
147 /* This is a vector, made larger whenever it isn't large enough,
148 which is used inside `update_frame' to hold the old contents
149 of the FRAME_PHYS_LINES of the frame being updated. */
150 struct frame_glyphs **ophys_lines;
151 /* Length of vector currently allocated. */
152 int ophys_lines_length;
154 FILE *termscript; /* Stdio stream being used for copy of all output. */
156 struct cm Wcm; /* Structure for info on cursor positioning */
158 extern short ospeed; /* Output speed (from sg_ospeed) */
160 int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
162 #ifdef MULTI_FRAME
164 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
165 "Clear frame FRAME and output again what is supposed to appear on it.")
166 (frame)
167 Lisp_Object frame;
169 FRAME_PTR f;
171 CHECK_LIVE_FRAME (frame, 0);
172 f = XFRAME (frame);
173 update_begin (f);
174 /* set_terminal_modes (); */
175 clear_frame ();
176 clear_frame_records (f);
177 update_end (f);
178 fflush (stdout);
179 windows_or_buffers_changed++;
180 /* Mark all windows as INaccurate,
181 so that every window will have its redisplay done. */
182 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
183 f->garbaged = 0;
184 return Qnil;
187 redraw_frame (f)
188 FRAME_PTR f;
190 Lisp_Object frame;
191 XSETFRAME (frame, f);
192 Fredraw_frame (frame);
195 #else
197 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
198 "Clear frame FRAME and output again what is supposed to appear on it.")
199 (frame)
200 Lisp_Object frame;
202 update_begin (0);
203 set_terminal_modes ();
204 clear_frame ();
205 update_end (0);
206 fflush (stdout);
207 clear_frame_records (0);
208 windows_or_buffers_changed++;
209 /* Mark all windows as INaccurate,
210 so that every window will have its redisplay done. */
211 mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
212 return Qnil;
215 #endif
217 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
218 "Clear and redisplay all visible frames.")
221 Lisp_Object tail, frame;
223 FOR_EACH_FRAME (tail, frame)
224 if (FRAME_VISIBLE_P (XFRAME (frame)))
225 Fredraw_frame (frame);
227 return Qnil;
230 /* This is used when frame_garbaged is set.
231 Redraw the individual frames marked as garbaged. */
233 void
234 redraw_garbaged_frames ()
236 Lisp_Object tail, frame;
238 FOR_EACH_FRAME (tail, frame)
239 if (FRAME_VISIBLE_P (XFRAME (frame))
240 && FRAME_GARBAGED_P (XFRAME (frame)))
241 Fredraw_frame (frame);
245 static struct frame_glyphs *
246 make_frame_glyphs (frame, empty)
247 register FRAME_PTR frame;
248 int empty;
250 register int i;
251 register width = FRAME_WIDTH (frame);
252 register height = FRAME_HEIGHT (frame);
253 register struct frame_glyphs *new
254 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
256 SET_GLYPHS_FRAME (new, frame);
257 new->height = height;
258 new->width = width;
259 new->used = (int *) xmalloc (height * sizeof (int));
260 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
261 new->charstarts = (int **) xmalloc (height * sizeof (int *));
262 new->highlight = (char *) xmalloc (height * sizeof (char));
263 new->enable = (char *) xmalloc (height * sizeof (char));
264 bzero (new->enable, height * sizeof (char));
265 new->bufp = (int *) xmalloc (height * sizeof (int));
267 #ifdef HAVE_X_WINDOWS
268 if (FRAME_X_P (frame))
270 new->top_left_x = (short *) xmalloc (height * sizeof (short));
271 new->top_left_y = (short *) xmalloc (height * sizeof (short));
272 new->pix_width = (short *) xmalloc (height * sizeof (short));
273 new->pix_height = (short *) xmalloc (height * sizeof (short));
274 new->max_ascent = (short *) xmalloc (height * sizeof (short));
276 #endif
278 if (empty)
280 /* Make the buffer used by decode_mode_spec. This buffer is also
281 used as temporary storage when updating the frame. See scroll.c. */
282 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
283 unsigned int total_charstarts = (width + 2) * sizeof (int);
285 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
286 bzero (new->total_contents, total_glyphs);
288 new->total_charstarts = (int *) xmalloc (total_charstarts);
289 bzero (new->total_charstarts, total_glyphs);
291 else
293 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
295 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
296 bzero (new->total_contents, total_glyphs);
297 for (i = 0; i < height; i++)
298 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
300 if (!FRAME_TERMCAP_P (frame))
302 unsigned int total_charstarts = height * (width + 2) * sizeof (int);
304 new->total_charstarts = (int *) xmalloc (total_charstarts);
305 bzero (new->total_charstarts, total_charstarts);
306 for (i = 0; i < height; i++)
307 new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
309 else
311 /* Without a window system, we don't really need charstarts.
312 So use a small amount of space to make enough data structure
313 to prevent crashes in display_text_line. */
314 new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
315 for (i = 0; i < height; i++)
316 new->charstarts[i] = new->total_charstarts;
320 return new;
323 void
324 free_frame_glyphs (frame, glyphs)
325 FRAME_PTR frame;
326 struct frame_glyphs *glyphs;
328 if (glyphs->total_contents)
329 xfree (glyphs->total_contents);
330 if (glyphs->total_charstarts)
331 xfree (glyphs->total_charstarts);
333 xfree (glyphs->used);
334 xfree (glyphs->glyphs);
335 xfree (glyphs->highlight);
336 xfree (glyphs->enable);
337 xfree (glyphs->bufp);
338 if (glyphs->charstarts)
339 xfree (glyphs->charstarts);
341 #ifdef HAVE_X_WINDOWS
342 if (FRAME_X_P (frame))
344 xfree (glyphs->top_left_x);
345 xfree (glyphs->top_left_y);
346 xfree (glyphs->pix_width);
347 xfree (glyphs->pix_height);
348 xfree (glyphs->max_ascent);
350 #endif
352 xfree (glyphs);
355 static void
356 remake_frame_glyphs (frame)
357 FRAME_PTR frame;
359 if (FRAME_CURRENT_GLYPHS (frame))
360 free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
361 if (FRAME_DESIRED_GLYPHS (frame))
362 free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
363 if (FRAME_TEMP_GLYPHS (frame))
364 free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
366 if (FRAME_MESSAGE_BUF (frame))
368 /* Reallocate the frame's message buffer; remember that
369 echo_area_glyphs may be pointing here. */
370 char *old_message_buf = FRAME_MESSAGE_BUF (frame);
372 FRAME_MESSAGE_BUF (frame)
373 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
374 FRAME_WIDTH (frame) + 1);
376 if (echo_area_glyphs == old_message_buf)
377 echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
378 if (previous_echo_glyphs == old_message_buf)
379 previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
381 else
382 FRAME_MESSAGE_BUF (frame)
383 = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
385 FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
386 FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
387 FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
388 SET_FRAME_GARBAGED (frame);
391 /* Return the hash code of contents of line VPOS in frame-matrix M. */
393 static int
394 line_hash_code (m, vpos)
395 register struct frame_glyphs *m;
396 int vpos;
398 register GLYPH *body, *end;
399 register int h = 0;
401 if (!m->enable[vpos])
402 return 0;
404 /* Give all highlighted lines the same hash code
405 so as to encourage scrolling to leave them in place. */
406 if (m->highlight[vpos])
407 return -1;
409 body = m->glyphs[vpos];
411 if (must_write_spaces)
412 while (1)
414 GLYPH g = *body++;
416 if (g == 0)
417 break;
418 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
420 else
421 while (1)
423 GLYPH g = *body++;
425 if (g == 0)
426 break;
427 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
430 if (h)
431 return h;
432 return 1;
435 /* Return number of characters in line in M at vpos VPOS,
436 except don't count leading and trailing spaces
437 unless the terminal requires those to be explicitly output. */
439 static unsigned int
440 line_draw_cost (m, vpos)
441 struct frame_glyphs *m;
442 int vpos;
444 register GLYPH *beg = m->glyphs[vpos];
445 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
446 register int i;
447 register int tlen = GLYPH_TABLE_LENGTH;
448 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
450 /* Ignore trailing and leading spaces if we can. */
451 if (!must_write_spaces)
453 while ((end != beg) && (*end == SPACEGLYPH))
454 --end;
455 if (end == beg)
456 return (0); /* All blank line. */
458 while (*beg == SPACEGLYPH)
459 ++beg;
462 /* If we don't have a glyph-table, each glyph is one character,
463 so return the number of glyphs. */
464 if (tbase == 0)
465 return end - beg;
467 /* Otherwise, scan the glyphs and accumulate their total size in I. */
468 i = 0;
469 while ((beg <= end) && *beg)
471 register GLYPH g = *beg++;
473 if (GLYPH_SIMPLE_P (tbase, tlen, g))
474 i += 1;
475 else
476 i += GLYPH_LENGTH (tbase, g);
478 return i;
481 /* The functions on this page are the interface from xdisp.c to redisplay.
483 The only other interface into redisplay is through setting
484 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
485 and SET_FRAME_GARBAGED (frame). */
487 /* cancel_line eliminates any request to display a line at position `vpos' */
489 cancel_line (vpos, frame)
490 int vpos;
491 register FRAME_PTR frame;
493 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
496 clear_frame_records (frame)
497 register FRAME_PTR frame;
499 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
502 /* Prepare to display on line VPOS starting at HPOS within it. */
504 void
505 get_display_line (frame, vpos, hpos)
506 register FRAME_PTR frame;
507 int vpos;
508 register int hpos;
510 register struct frame_glyphs *glyphs;
511 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
512 register GLYPH *p;
514 if (vpos < 0)
515 abort ();
517 if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
518 abort ();
520 if (! desired_glyphs->enable[vpos])
522 desired_glyphs->used[vpos] = 0;
523 desired_glyphs->highlight[vpos] = 0;
524 desired_glyphs->enable[vpos] = 1;
527 if (hpos > desired_glyphs->used[vpos])
529 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
530 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
532 desired_glyphs->used[vpos] = hpos;
533 while (g != end)
534 *g++ = SPACEGLYPH;
538 /* Like bcopy except never gets confused by overlap. */
540 void
541 safe_bcopy (from, to, size)
542 char *from, *to;
543 int size;
545 if (size <= 0 || from == to)
546 return;
548 /* If the source and destination don't overlap, then bcopy can
549 handle it. If they do overlap, but the destination is lower in
550 memory than the source, we'll assume bcopy can handle that. */
551 if (to < from || from + size <= to)
552 bcopy (from, to, size);
554 /* Otherwise, we'll copy from the end. */
555 else
557 register char *endf = from + size;
558 register char *endt = to + size;
560 /* If TO - FROM is large, then we should break the copy into
561 nonoverlapping chunks of TO - FROM bytes each. However, if
562 TO - FROM is small, then the bcopy function call overhead
563 makes this not worth it. The crossover point could be about
564 anywhere. Since I don't think the obvious copy loop is too
565 bad, I'm trying to err in its favor. */
566 if (to - from < 64)
569 *--endt = *--endf;
570 while (endf != from);
572 else
574 for (;;)
576 endt -= (to - from);
577 endf -= (to - from);
579 if (endt < to)
580 break;
582 bcopy (endf, endt, to - from);
585 /* If SIZE wasn't a multiple of TO - FROM, there will be a
586 little left over. The amount left over is
587 (endt + (to - from)) - to, which is endt - from. */
588 bcopy (from, to, endt - from);
593 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
594 DISTANCE may be negative. */
596 static void
597 rotate_vector (vector, size, distance)
598 char *vector;
599 int size;
600 int distance;
602 char *temp = (char *) alloca (size);
604 if (distance < 0)
605 distance += size;
607 bcopy (vector, temp + distance, size - distance);
608 bcopy (vector + size - distance, temp, distance);
609 bcopy (temp, vector, size);
612 /* Scroll lines from vpos FROM up to but not including vpos END
613 down by AMOUNT lines (AMOUNT may be negative).
614 Returns nonzero if done, zero if terminal cannot scroll them. */
617 scroll_frame_lines (frame, from, end, amount, newpos)
618 register FRAME_PTR frame;
619 int from, end, amount, newpos;
621 register int i;
622 register struct frame_glyphs *current_frame
623 = FRAME_CURRENT_GLYPHS (frame);
624 int pos_adjust;
625 int width = FRAME_WIDTH (frame);
627 if (!line_ins_del_ok)
628 return 0;
630 if (amount == 0)
631 return 1;
633 if (amount > 0)
635 update_begin (frame);
636 set_terminal_window (end + amount);
637 if (!scroll_region_ok)
638 ins_del_lines (end, -amount);
639 ins_del_lines (from, amount);
640 set_terminal_window (0);
642 rotate_vector (current_frame->glyphs + from,
643 sizeof (GLYPH *) * (end + amount - from),
644 amount * sizeof (GLYPH *));
646 rotate_vector (current_frame->charstarts + from,
647 sizeof (int *) * (end + amount - from),
648 amount * sizeof (int *));
650 safe_bcopy (current_frame->used + from,
651 current_frame->used + from + amount,
652 (end - from) * sizeof current_frame->used[0]);
654 safe_bcopy (current_frame->highlight + from,
655 current_frame->highlight + from + amount,
656 (end - from) * sizeof current_frame->highlight[0]);
658 safe_bcopy (current_frame->enable + from,
659 current_frame->enable + from + amount,
660 (end - from) * sizeof current_frame->enable[0]);
662 /* Adjust the lines by an amount
663 that puts the first of them at NEWPOS. */
664 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
666 /* Offset each char position in the charstarts lines we moved
667 by pos_adjust. */
668 for (i = from + amount; i < end + amount; i++)
670 int *line = current_frame->charstarts[i];
671 int col;
672 for (col = 0; col < width; col++)
673 if (line[col] > 0)
674 line[col] += pos_adjust;
676 for (i = from; i < from + amount; i++)
678 int *line = current_frame->charstarts[i];
679 int col;
680 line[0] = -1;
681 for (col = 0; col < width; col++)
682 line[col] = 0;
685 /* Mark the lines made empty by scrolling as enabled, empty and
686 normal video. */
687 bzero (current_frame->used + from,
688 amount * sizeof current_frame->used[0]);
689 bzero (current_frame->highlight + from,
690 amount * sizeof current_frame->highlight[0]);
691 for (i = from; i < from + amount; i++)
693 current_frame->glyphs[i][0] = '\0';
694 current_frame->charstarts[i][0] = -1;
695 current_frame->enable[i] = 1;
698 safe_bcopy (current_frame->bufp + from,
699 current_frame->bufp + from + amount,
700 (end - from) * sizeof current_frame->bufp[0]);
702 #ifdef HAVE_X_WINDOWS
703 if (FRAME_X_P (frame))
705 safe_bcopy (current_frame->top_left_x + from,
706 current_frame->top_left_x + from + amount,
707 (end - from) * sizeof current_frame->top_left_x[0]);
709 safe_bcopy (current_frame->top_left_y + from,
710 current_frame->top_left_y + from + amount,
711 (end - from) * sizeof current_frame->top_left_y[0]);
713 safe_bcopy (current_frame->pix_width + from,
714 current_frame->pix_width + from + amount,
715 (end - from) * sizeof current_frame->pix_width[0]);
717 safe_bcopy (current_frame->pix_height + from,
718 current_frame->pix_height + from + amount,
719 (end - from) * sizeof current_frame->pix_height[0]);
721 safe_bcopy (current_frame->max_ascent + from,
722 current_frame->max_ascent + from + amount,
723 (end - from) * sizeof current_frame->max_ascent[0]);
725 #endif /* HAVE_X_WINDOWS */
727 update_end (frame);
729 if (amount < 0)
731 update_begin (frame);
732 set_terminal_window (end);
733 ins_del_lines (from + amount, amount);
734 if (!scroll_region_ok)
735 ins_del_lines (end + amount, -amount);
736 set_terminal_window (0);
738 rotate_vector (current_frame->glyphs + from + amount,
739 sizeof (GLYPH *) * (end - from - amount),
740 amount * sizeof (GLYPH *));
742 rotate_vector (current_frame->charstarts + from + amount,
743 sizeof (int *) * (end - from - amount),
744 amount * sizeof (int *));
746 safe_bcopy (current_frame->used + from,
747 current_frame->used + from + amount,
748 (end - from) * sizeof current_frame->used[0]);
750 safe_bcopy (current_frame->highlight + from,
751 current_frame->highlight + from + amount,
752 (end - from) * sizeof current_frame->highlight[0]);
754 safe_bcopy (current_frame->enable + from,
755 current_frame->enable + from + amount,
756 (end - from) * sizeof current_frame->enable[0]);
758 /* Adjust the lines by an amount
759 that puts the first of them at NEWPOS. */
760 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
762 /* Offset each char position in the charstarts lines we moved
763 by pos_adjust. */
764 for (i = from + amount; i < end + amount; i++)
766 int *line = current_frame->charstarts[i];
767 int col;
768 for (col = 0; col < width; col++)
769 if (line[col] > 0)
770 line[col] += pos_adjust;
772 for (i = end + amount; i < end; i++)
774 int *line = current_frame->charstarts[i];
775 int col;
776 line[0] = -1;
777 for (col = 0; col < width; col++)
778 line[col] = 0;
781 /* Mark the lines made empty by scrolling as enabled, empty and
782 normal video. */
783 bzero (current_frame->used + end + amount,
784 - amount * sizeof current_frame->used[0]);
785 bzero (current_frame->highlight + end + amount,
786 - amount * sizeof current_frame->highlight[0]);
787 for (i = end + amount; i < end; i++)
789 current_frame->glyphs[i][0] = '\0';
790 current_frame->charstarts[i][0] = 0;
791 current_frame->enable[i] = 1;
794 safe_bcopy (current_frame->bufp + from,
795 current_frame->bufp + from + amount,
796 (end - from) * sizeof current_frame->bufp[0]);
798 #ifdef HAVE_X_WINDOWS
799 if (FRAME_X_P (frame))
801 safe_bcopy (current_frame->top_left_x + from,
802 current_frame->top_left_x + from + amount,
803 (end - from) * sizeof current_frame->top_left_x[0]);
805 safe_bcopy (current_frame->top_left_y + from,
806 current_frame->top_left_y + from + amount,
807 (end - from) * sizeof current_frame->top_left_y[0]);
809 safe_bcopy (current_frame->pix_width + from,
810 current_frame->pix_width + from + amount,
811 (end - from) * sizeof current_frame->pix_width[0]);
813 safe_bcopy (current_frame->pix_height + from,
814 current_frame->pix_height + from + amount,
815 (end - from) * sizeof current_frame->pix_height[0]);
817 safe_bcopy (current_frame->max_ascent + from,
818 current_frame->max_ascent + from + amount,
819 (end - from) * sizeof current_frame->max_ascent[0]);
821 #endif /* HAVE_X_WINDOWS */
823 update_end (frame);
825 return 1;
828 /* After updating a window W that isn't the full frame wide,
829 copy all the columns that W does not occupy
830 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
831 so that update_frame will not change those columns. */
833 preserve_other_columns (w)
834 struct window *w;
836 register int vpos;
837 register struct frame_glyphs *current_frame, *desired_frame;
838 register FRAME_PTR frame = XFRAME (w->frame);
839 int start = XFASTINT (w->left);
840 int end = XFASTINT (w->left) + XFASTINT (w->width);
841 int bot = XFASTINT (w->top) + XFASTINT (w->height);
843 current_frame = FRAME_CURRENT_GLYPHS (frame);
844 desired_frame = FRAME_DESIRED_GLYPHS (frame);
846 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
848 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
850 if (start > 0)
852 int len;
854 bcopy (current_frame->glyphs[vpos],
855 desired_frame->glyphs[vpos],
856 start * sizeof (current_frame->glyphs[vpos][0]));
857 bcopy (current_frame->charstarts[vpos],
858 desired_frame->charstarts[vpos],
859 start * sizeof (current_frame->charstarts[vpos][0]));
860 len = min (start, current_frame->used[vpos]);
861 if (desired_frame->used[vpos] < len)
862 desired_frame->used[vpos] = len;
864 if (current_frame->used[vpos] > end
865 && desired_frame->used[vpos] < current_frame->used[vpos])
867 while (desired_frame->used[vpos] < end)
869 int used = desired_frame->used[vpos]++;
870 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
871 desired_frame->glyphs[vpos][used] = 0;
873 bcopy (current_frame->glyphs[vpos] + end,
874 desired_frame->glyphs[vpos] + end,
875 ((current_frame->used[vpos] - end)
876 * sizeof (current_frame->glyphs[vpos][0])));
877 bcopy (current_frame->charstarts[vpos] + end,
878 desired_frame->charstarts[vpos] + end,
879 ((current_frame->used[vpos] - end)
880 * sizeof (current_frame->charstarts[vpos][0])));
881 desired_frame->used[vpos] = current_frame->used[vpos];
887 #if 0
889 /* If window w does not need to be updated and isn't the full frame wide,
890 copy all the columns that w does occupy
891 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
892 so that update_frame will not change those columns.
894 Have not been able to figure out how to use this correctly. */
896 preserve_my_columns (w)
897 struct window *w;
899 register int vpos, fin;
900 register struct frame_glyphs *l1, *l2;
901 register FRAME_PTR frame = XFRAME (w->frame);
902 int start = XFASTINT (w->left);
903 int end = XFASTINT (w->left) + XFASTINT (w->width);
904 int bot = XFASTINT (w->top) + XFASTINT (w->height);
906 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
908 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
909 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
911 if (l2->length > start && l1->length < l2->length)
913 fin = l2->length;
914 if (fin > end) fin = end;
915 while (l1->length < start)
916 l1->body[l1->length++] = ' ';
917 bcopy (l2->body + start, l1->body + start, fin - start);
918 l1->length = fin;
924 #endif
926 /* Adjust by ADJUST the charstart values in window W
927 after vpos VPOS, which counts relative to the frame
928 (not relative to W itself). */
930 void
931 adjust_window_charstarts (w, vpos, adjust)
932 struct window *w;
933 int vpos;
934 int adjust;
936 int left = XFASTINT (w->left);
937 int top = XFASTINT (w->top);
938 int right = left + window_internal_width (w);
939 int bottom = top + window_internal_height (w);
940 int i;
942 for (i = vpos + 1; i < bottom; i++)
944 int *charstart
945 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
946 int j;
947 for (j = left; j < right; j++)
948 if (charstart[j] > 0)
949 charstart[j] += adjust;
953 /* Check the charstarts values in the area of window W
954 for internal consistency. We cannot check that they are "right";
955 we can only look for something nonsensical. */
957 verify_charstarts (w)
958 struct window *w;
960 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
961 int i;
962 int top = XFASTINT (w->top);
963 int bottom = top + window_internal_height (w);
964 int left = XFASTINT (w->left);
965 int right = left + window_internal_width (w);
966 int next_line;
967 int truncate = (XINT (w->hscroll)
968 || (truncate_partial_width_windows
969 && (XFASTINT (w->width) < FRAME_WIDTH (f)))
970 || !NILP (XBUFFER (w->buffer)->truncate_lines));
972 for (i = top; i < bottom; i++)
974 int j;
975 int last;
976 int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
978 if (i != top)
980 if (truncate)
982 /* If we are truncating lines, allow a jump
983 in charstarts from one line to the next. */
984 if (charstart[left] < next_line)
985 abort ();
987 else
989 if (charstart[left] != next_line)
990 abort ();
994 for (j = left; j < right; j++)
995 if (charstart[j] > 0)
996 last = charstart[j];
997 /* Record where the next line should start. */
998 next_line = last;
999 if (BUF_ZV (XBUFFER (w->buffer)) != last)
1001 /* If there's a newline between the two lines, count that. */
1002 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
1003 if (endchar == '\n')
1004 next_line++;
1009 /* On discovering that the redisplay for a window was no good,
1010 cancel the columns of that window, so that when the window is
1011 displayed over again get_display_line will not complain. */
1013 cancel_my_columns (w)
1014 struct window *w;
1016 register int vpos;
1017 register struct frame_glyphs *desired_glyphs
1018 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
1019 register int start = XFASTINT (w->left);
1020 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
1022 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
1023 if (desired_glyphs->enable[vpos]
1024 && desired_glyphs->used[vpos] >= start)
1025 desired_glyphs->used[vpos] = start;
1028 /* These functions try to perform directly and immediately on the frame
1029 the necessary output for one change in the buffer.
1030 They may return 0 meaning nothing was done if anything is difficult,
1031 or 1 meaning the output was performed properly.
1032 They assume that the frame was up to date before the buffer
1033 change being displayed. They make various other assumptions too;
1034 see command_loop_1 where these are called. */
1037 direct_output_for_insert (g)
1038 int g;
1040 register FRAME_PTR frame = selected_frame;
1041 register struct frame_glyphs *current_frame
1042 = FRAME_CURRENT_GLYPHS (frame);
1044 #ifndef COMPILER_REGISTER_BUG
1045 register
1046 #endif /* COMPILER_REGISTER_BUG */
1047 struct window *w = XWINDOW (selected_window);
1048 #ifndef COMPILER_REGISTER_BUG
1049 register
1050 #endif /* COMPILER_REGISTER_BUG */
1051 int hpos = FRAME_CURSOR_X (frame);
1052 #ifndef COMPILER_REGISTER_BUG
1053 register
1054 #endif /* COMPILER_REGISTER_BUG */
1055 int vpos = FRAME_CURSOR_Y (frame);
1057 /* Give up if about to continue line. */
1058 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
1060 /* Avoid losing if cursor is in invisible text off left margin */
1061 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
1063 /* Give up if cursor outside window (in minibuf, probably) */
1064 || cursor_in_echo_area
1065 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1066 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
1068 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
1069 || !display_completed
1071 /* Give up if buffer appears in two places. */
1072 || buffer_shared > 1
1074 #ifdef USE_TEXT_PROPERTIES
1075 /* Intervals have already been adjusted, point is after the
1076 character that was just inserted. */
1077 /* Give up if character is invisible. */
1078 /* Give up if character has a face property.
1079 At the moment we only lose at end of line or end of buffer
1080 and only with faces that have some background */
1081 /* Instead of wasting time, give up if character has any text properties */
1082 || ! NILP (Ftext_properties_at (make_number (point - 1), Qnil))
1083 #endif
1085 /* Give up if w is minibuffer and a message is being displayed there */
1086 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1087 return 0;
1090 int face = 0;
1091 #ifdef HAVE_FACES
1092 int dummy;
1094 if (FRAME_X_P (frame))
1095 face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point, 0);
1096 #endif
1097 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
1098 current_frame->charstarts[vpos][hpos] = point - 1;
1099 /* Record the entry for after the newly inserted character. */
1100 current_frame->charstarts[vpos][hpos + 1] = point;
1101 adjust_window_charstarts (w, vpos, 1);
1103 unchanged_modified = MODIFF;
1104 beg_unchanged = GPT - BEG;
1105 XSETFASTINT (w->last_point, point);
1106 XSETFASTINT (w->last_point_x, hpos);
1107 XSETFASTINT (w->last_modified, MODIFF);
1109 reassert_line_highlight (0, vpos);
1110 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
1111 fflush (stdout);
1112 ++FRAME_CURSOR_X (frame);
1113 if (hpos == current_frame->used[vpos])
1115 current_frame->used[vpos] = hpos + 1;
1116 current_frame->glyphs[vpos][hpos + 1] = 0;
1119 return 1;
1123 direct_output_forward_char (n)
1124 int n;
1126 register FRAME_PTR frame = selected_frame;
1127 register struct window *w = XWINDOW (selected_window);
1128 Lisp_Object position;
1129 int hpos = FRAME_CURSOR_X (frame);
1131 /* Give up if in truncated text at end of line. */
1132 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
1133 return 0;
1135 /* Avoid losing if cursor is in invisible text off left margin
1136 or about to go off either side of window. */
1137 if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
1138 && (XINT (w->hscroll) || n < 0))
1139 || (n > 0
1140 && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
1141 || cursor_in_echo_area)
1142 return 0;
1144 /* Can't use direct output if highlighting a region. */
1145 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1146 return 0;
1148 #ifdef USE_TEXT_PROPERTIES
1149 /* Don't use direct output next to an invisible character
1150 since we might need to do something special. */
1152 XSETFASTINT (position, point);
1153 if (XFASTINT (position) < ZV
1154 && ! NILP (Fget_char_property (position,
1155 Qinvisible,
1156 selected_window)))
1157 return 0;
1159 XSETFASTINT (position, point - 1);
1160 if (XFASTINT (position) >= BEGV
1161 && ! NILP (Fget_char_property (position,
1162 Qinvisible,
1163 selected_window)))
1164 return 0;
1165 #endif
1167 FRAME_CURSOR_X (frame) += n;
1168 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
1169 XSETFASTINT (w->last_point, point);
1170 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
1171 fflush (stdout);
1173 return 1;
1176 static void update_line ();
1178 /* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
1179 Value is nonzero if redisplay stopped due to pending input.
1180 FORCE nonzero means do not stop for pending input. */
1183 update_frame (f, force, inhibit_hairy_id)
1184 FRAME_PTR f;
1185 int force;
1186 int inhibit_hairy_id;
1188 register struct frame_glyphs *current_frame;
1189 register struct frame_glyphs *desired_frame = 0;
1190 register int i;
1191 int pause;
1192 int preempt_count = baud_rate / 2400 + 1;
1193 extern input_pending;
1194 #ifdef HAVE_X_WINDOWS
1195 register int downto, leftmost;
1196 #endif
1198 if (baud_rate != FRAME_COST_BAUD_RATE (f))
1199 calculate_costs (f);
1201 if (preempt_count <= 0)
1202 preempt_count = 1;
1204 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1206 detect_input_pending ();
1207 if (input_pending && !force)
1209 pause = 1;
1210 goto do_pause;
1213 update_begin (f);
1215 if (!line_ins_del_ok)
1216 inhibit_hairy_id = 1;
1218 /* These are separate to avoid a possible bug in the AIX C compiler. */
1219 current_frame = FRAME_CURRENT_GLYPHS (f);
1220 desired_frame = FRAME_DESIRED_GLYPHS (f);
1222 /* See if any of the desired lines are enabled; don't compute for
1223 i/d line if just want cursor motion. */
1224 for (i = 0; i < FRAME_HEIGHT (f); i++)
1225 if (desired_frame->enable[i])
1226 break;
1228 /* Try doing i/d line, if not yet inhibited. */
1229 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1230 force |= scrolling (f);
1232 /* Update the individual lines as needed. Do bottom line first. */
1234 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1235 update_line (f, FRAME_HEIGHT (f) - 1);
1237 #ifdef HAVE_X_WINDOWS
1238 if (FRAME_X_P (f))
1240 leftmost = downto = f->display.x->internal_border_width;
1241 if (desired_frame->enable[0])
1243 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1244 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
1245 = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
1246 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
1247 current_frame->top_left_x[0] = leftmost;
1248 current_frame->top_left_y[0] = downto;
1251 #endif /* HAVE_X_WINDOWS */
1253 /* Now update the rest of the lines. */
1254 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
1256 if (desired_frame->enable[i])
1258 if (FRAME_TERMCAP_P (f))
1260 /* Flush out every so many lines.
1261 Also flush out if likely to have more than 1k buffered
1262 otherwise. I'm told that some telnet connections get
1263 really screwed by more than 1k output at once. */
1264 int outq = PENDING_OUTPUT_COUNT (stdout);
1265 if (outq > 900
1266 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1268 fflush (stdout);
1269 if (preempt_count == 1)
1271 #ifdef EMACS_OUTQSIZE
1272 if (EMACS_OUTQSIZE (0, &outq) < 0)
1273 /* Probably not a tty. Ignore the error and reset
1274 * the outq count. */
1275 outq = PENDING_OUTPUT_COUNT (stdout);
1276 #endif
1277 outq *= 10;
1278 if (baud_rate <= outq && baud_rate > 0)
1279 sleep (outq / baud_rate);
1282 if ((i - 1) % preempt_count == 0)
1283 detect_input_pending ();
1286 update_line (f, i);
1287 #ifdef HAVE_X_WINDOWS
1288 if (FRAME_X_P (f))
1290 current_frame->top_left_y[i] = downto;
1291 current_frame->top_left_x[i] = leftmost;
1293 #endif /* HAVE_X_WINDOWS */
1296 #ifdef HAVE_X_WINDOWS
1297 if (FRAME_X_P (f))
1298 downto += current_frame->pix_height[i];
1299 #endif
1301 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
1303 /* Now just clean up termcap drivers and set cursor, etc. */
1304 if (!pause)
1306 if (cursor_in_echo_area
1307 && FRAME_HAS_MINIBUF_P (f))
1309 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1310 int row, col;
1312 if (cursor_in_echo_area < 0)
1314 row = top;
1315 col = 0;
1317 else
1319 /* If the minibuffer is several lines high, find the last
1320 line that has any text on it. */
1321 row = FRAME_HEIGHT (f);
1324 row--;
1325 if (current_frame->enable[row])
1326 col = current_frame->used[row];
1327 else
1328 col = 0;
1330 while (row > top && col == 0);
1332 if (col >= FRAME_WIDTH (f))
1334 col = 0;
1335 if (row < FRAME_HEIGHT (f) - 1)
1336 row++;
1340 cursor_to (row, col);
1342 else
1343 cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
1344 FRAME_WIDTH (f) - 1), 0));
1347 update_end (f);
1349 if (termscript)
1350 fflush (termscript);
1351 fflush (stdout);
1353 /* Here if output is preempted because input is detected. */
1354 do_pause:
1356 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1357 display_completed = !pause;
1359 bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
1360 return pause;
1363 /* Called when about to quit, to check for doing so
1364 at an improper time. */
1366 void
1367 quit_error_check ()
1369 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
1370 return;
1371 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
1372 abort ();
1373 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
1374 abort ();
1377 /* Decide what insert/delete line to do, and do it */
1379 extern void scrolling_1 ();
1381 scrolling (frame)
1382 FRAME_PTR frame;
1384 int unchanged_at_top, unchanged_at_bottom;
1385 int window_size;
1386 int changed_lines;
1387 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1388 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1389 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1390 int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1391 register int i;
1392 int free_at_end_vpos = FRAME_HEIGHT (frame);
1393 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1394 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
1396 /* Compute hash codes of all the lines.
1397 Also calculate number of changed lines,
1398 number of unchanged lines at the beginning,
1399 and number of unchanged lines at the end. */
1401 changed_lines = 0;
1402 unchanged_at_top = 0;
1403 unchanged_at_bottom = FRAME_HEIGHT (frame);
1404 for (i = 0; i < FRAME_HEIGHT (frame); i++)
1406 /* Give up on this scrolling if some old lines are not enabled. */
1407 if (!current_frame->enable[i])
1408 return 0;
1409 old_hash[i] = line_hash_code (current_frame, i);
1410 if (! desired_frame->enable[i])
1411 new_hash[i] = old_hash[i];
1412 else
1413 new_hash[i] = line_hash_code (desired_frame, i);
1415 if (old_hash[i] != new_hash[i])
1417 changed_lines++;
1418 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
1420 else if (i == unchanged_at_top)
1421 unchanged_at_top++;
1422 draw_cost[i] = line_draw_cost (desired_frame, i);
1423 old_draw_cost[i] = line_draw_cost (current_frame, i);
1426 /* If changed lines are few, don't allow preemption, don't scroll. */
1427 if (!scroll_region_ok && changed_lines < baud_rate / 2400
1428 || unchanged_at_bottom == FRAME_HEIGHT (frame))
1429 return 1;
1431 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
1432 - unchanged_at_bottom);
1434 if (scroll_region_ok)
1435 free_at_end_vpos -= unchanged_at_bottom;
1436 else if (memory_below_frame)
1437 free_at_end_vpos = -1;
1439 /* If large window, fast terminal and few lines in common between
1440 current frame and desired frame, don't bother with i/d calc. */
1441 if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
1442 && (window_size >=
1443 10 * scrolling_max_lines_saved (unchanged_at_top,
1444 FRAME_HEIGHT (frame) - unchanged_at_bottom,
1445 old_hash, new_hash, draw_cost)))
1446 return 0;
1448 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
1449 draw_cost + unchanged_at_top - 1,
1450 old_draw_cost + unchanged_at_top - 1,
1451 old_hash + unchanged_at_top - 1,
1452 new_hash + unchanged_at_top - 1,
1453 free_at_end_vpos - unchanged_at_top);
1455 return 0;
1458 /* Return the offset in its buffer of the character at location col, line
1459 in the given window. */
1461 buffer_posn_from_coords (window, col, line)
1462 struct window *window;
1463 int col, line;
1465 int hscroll = XINT (window->hscroll);
1466 int window_left = XFASTINT (window->left);
1468 /* The actual width of the window is window->width less one for the
1469 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1470 window. */
1471 int window_width = window_internal_width (window) - 1;
1473 int startp = marker_position (window->start);
1475 /* Since compute_motion will only operate on the current buffer,
1476 we need to save the old one and restore it when we're done. */
1477 struct buffer *old_current_buffer = current_buffer;
1478 struct position *posn;
1480 current_buffer = XBUFFER (window->buffer);
1482 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1483 (window->frame))->bufp to avoid scanning from the very top of
1484 the window, but it isn't maintained correctly, and I'm not even
1485 sure I will keep it. */
1486 posn = compute_motion (startp, 0,
1487 (window == XWINDOW (minibuf_window) && startp == 1
1488 ? minibuf_prompt_width : 0)
1489 + (hscroll ? 1 - hscroll : 0),
1490 ZV, line, col,
1491 window_width, hscroll, 0, window);
1493 current_buffer = old_current_buffer;
1495 /* compute_motion considers frame points past the end of a line
1496 to be *after* the newline, i.e. at the start of the next line.
1497 This is reasonable, but not really what we want. So if the
1498 result is on a line below LINE, back it up one character. */
1499 if (posn->vpos > line)
1500 return posn->bufpos - 1;
1501 else
1502 return posn->bufpos;
1505 static int
1506 count_blanks (r)
1507 register GLYPH *r;
1509 register GLYPH *p = r;
1510 while (*p++ == SPACEGLYPH);
1511 return p - r - 1;
1514 static int
1515 count_match (str1, str2)
1516 GLYPH *str1, *str2;
1518 register GLYPH *p1 = str1;
1519 register GLYPH *p2 = str2;
1520 while (*p1++ == *p2++);
1521 return p1 - str1 - 1;
1524 /* Char insertion/deletion cost vector, from term.c */
1525 extern int *char_ins_del_vector;
1527 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
1529 static void
1530 update_line (frame, vpos)
1531 register FRAME_PTR frame;
1532 int vpos;
1534 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1535 int *temp1;
1536 int tem;
1537 int osp, nsp, begmatch, endmatch, olen, nlen;
1538 int save;
1539 register struct frame_glyphs *current_frame
1540 = FRAME_CURRENT_GLYPHS (frame);
1541 register struct frame_glyphs *desired_frame
1542 = FRAME_DESIRED_GLYPHS (frame);
1544 if (desired_frame->highlight[vpos]
1545 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
1547 change_line_highlight (desired_frame->highlight[vpos], vpos,
1548 (current_frame->enable[vpos] ?
1549 current_frame->used[vpos] : 0));
1550 current_frame->enable[vpos] = 0;
1552 else
1553 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
1555 if (! current_frame->enable[vpos])
1557 olen = 0;
1559 else
1561 obody = current_frame->glyphs[vpos];
1562 olen = current_frame->used[vpos];
1563 if (! current_frame->highlight[vpos])
1565 if (!must_write_spaces)
1566 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1567 olen--;
1569 else
1571 /* For an inverse-video line, remember we gave it
1572 spaces all the way to the frame edge
1573 so that the reverse video extends all the way across. */
1575 while (olen < FRAME_WIDTH (frame) - 1)
1576 obody[olen++] = SPACEGLYPH;
1580 /* One way or another, this will enable the line being updated. */
1581 current_frame->enable[vpos] = 1;
1582 current_frame->used[vpos] = desired_frame->used[vpos];
1583 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1584 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
1586 #ifdef HAVE_X_WINDOWS
1587 if (FRAME_X_P (frame))
1589 current_frame->pix_width[vpos]
1590 = current_frame->used[vpos]
1591 * FONT_WIDTH (frame->display.x->font);
1592 current_frame->pix_height[vpos]
1593 = frame->display.x->line_height;
1595 #endif /* HAVE_X_WINDOWS */
1597 if (!desired_frame->enable[vpos])
1599 nlen = 0;
1600 goto just_erase;
1603 nbody = desired_frame->glyphs[vpos];
1604 nlen = desired_frame->used[vpos];
1606 /* Pretend trailing spaces are not there at all,
1607 unless for one reason or another we must write all spaces. */
1608 if (! desired_frame->highlight[vpos])
1610 if (!must_write_spaces)
1611 /* We know that the previous character byte contains 0. */
1612 while (nbody[nlen - 1] == SPACEGLYPH)
1613 nlen--;
1615 else
1617 /* For an inverse-video line, give it extra trailing spaces
1618 all the way to the frame edge
1619 so that the reverse video extends all the way across. */
1621 while (nlen < FRAME_WIDTH (frame) - 1)
1622 nbody[nlen++] = SPACEGLYPH;
1625 /* If there's no i/d char, quickly do the best we can without it. */
1626 if (!char_ins_del_ok)
1628 int i,j;
1630 #if 0
1631 if (FRAME_X_P (frame))
1633 /* Under X, erase everything we are going to rewrite,
1634 and rewrite everything from the first char that's changed.
1635 This is part of supporting fonts like Courier
1636 whose chars can overlap outside the char width. */
1637 for (i = 0; i < nlen; i++)
1638 if (i >= olen || nbody[i] != obody[i])
1639 break;
1641 cursor_to (vpos, i);
1642 if (i != olen)
1643 clear_end_of_line (olen);
1644 write_glyphs (nbody + i, nlen - i);
1646 else
1648 #endif /* 0 */
1649 for (i = 0; i < nlen; i++)
1651 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1653 cursor_to (vpos, i);
1654 for (j = 1; (i + j < nlen &&
1655 (i + j >= olen || nbody[i+j] != obody[i+j]));
1656 j++);
1658 /* Output this run of non-matching chars. */
1659 write_glyphs (nbody + i, j);
1660 i += j - 1;
1662 /* Now find the next non-match. */
1666 /* Clear the rest of the line, or the non-clear part of it. */
1667 if (olen > nlen)
1669 cursor_to (vpos, nlen);
1670 clear_end_of_line (olen);
1673 /* Exchange contents between current_frame and new_frame. */
1674 temp = desired_frame->glyphs[vpos];
1675 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1676 current_frame->glyphs[vpos] = temp;
1678 /* Exchange charstarts between current_frame and new_frame. */
1679 temp1 = desired_frame->charstarts[vpos];
1680 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1681 current_frame->charstarts[vpos] = temp1;
1683 return;
1686 if (!olen)
1688 nsp = (must_write_spaces || desired_frame->highlight[vpos])
1689 ? 0 : count_blanks (nbody);
1690 if (nlen > nsp)
1692 cursor_to (vpos, nsp);
1693 write_glyphs (nbody + nsp, nlen - nsp);
1696 /* Exchange contents between current_frame and new_frame. */
1697 temp = desired_frame->glyphs[vpos];
1698 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1699 current_frame->glyphs[vpos] = temp;
1701 /* Exchange charstarts between current_frame and new_frame. */
1702 temp1 = desired_frame->charstarts[vpos];
1703 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1704 current_frame->charstarts[vpos] = temp1;
1706 return;
1709 obody[olen] = 1;
1710 save = nbody[nlen];
1711 nbody[nlen] = 0;
1713 /* Compute number of leading blanks in old and new contents. */
1714 osp = count_blanks (obody);
1715 if (!desired_frame->highlight[vpos])
1716 nsp = count_blanks (nbody);
1717 else
1718 nsp = 0;
1720 /* Compute number of matching chars starting with first nonblank. */
1721 begmatch = count_match (obody + osp, nbody + nsp);
1723 /* Spaces in new match implicit space past the end of old. */
1724 /* A bug causing this to be a no-op was fixed in 18.29. */
1725 if (!must_write_spaces && osp + begmatch == olen)
1727 np1 = nbody + nsp;
1728 while (np1[begmatch] == SPACEGLYPH)
1729 begmatch++;
1732 /* Avoid doing insert/delete char
1733 just cause number of leading spaces differs
1734 when the following text does not match. */
1735 if (begmatch == 0 && osp != nsp)
1736 osp = nsp = min (osp, nsp);
1738 /* Find matching characters at end of line */
1739 op1 = obody + olen;
1740 np1 = nbody + nlen;
1741 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1742 while (op1 > op2 && op1[-1] == np1[-1])
1744 op1--;
1745 np1--;
1747 endmatch = obody + olen - op1;
1749 /* Put correct value back in nbody[nlen].
1750 This is important because direct_output_for_insert
1751 can write into the line at a later point.
1752 If this screws up the zero at the end of the line, re-establish it. */
1753 nbody[nlen] = save;
1754 obody[olen] = 0;
1756 /* tem gets the distance to insert or delete.
1757 endmatch is how many characters we save by doing so.
1758 Is it worth it? */
1760 tem = (nlen - nsp) - (olen - osp);
1761 if (endmatch && tem
1762 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
1763 endmatch = 0;
1765 /* nsp - osp is the distance to insert or delete.
1766 If that is nonzero, begmatch is known to be nonzero also.
1767 begmatch + endmatch is how much we save by doing the ins/del.
1768 Is it worth it? */
1770 if (nsp != osp
1771 && (!char_ins_del_ok
1772 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
1774 begmatch = 0;
1775 endmatch = 0;
1776 osp = nsp = min (osp, nsp);
1779 /* Now go through the line, inserting, writing and
1780 deleting as appropriate. */
1782 if (osp > nsp)
1784 cursor_to (vpos, nsp);
1785 delete_glyphs (osp - nsp);
1787 else if (nsp > osp)
1789 /* If going to delete chars later in line
1790 and insert earlier in the line,
1791 must delete first to avoid losing data in the insert */
1792 if (endmatch && nlen < olen + nsp - osp)
1794 cursor_to (vpos, nlen - endmatch + osp - nsp);
1795 delete_glyphs (olen + nsp - osp - nlen);
1796 olen = nlen - (nsp - osp);
1798 cursor_to (vpos, osp);
1799 insert_glyphs ((char *)0, nsp - osp);
1801 olen += nsp - osp;
1803 tem = nsp + begmatch + endmatch;
1804 if (nlen != tem || olen != tem)
1806 cursor_to (vpos, nsp + begmatch);
1807 if (!endmatch || nlen == olen)
1809 /* If new text being written reaches right margin,
1810 there is no need to do clear-to-eol at the end.
1811 (and it would not be safe, since cursor is not
1812 going to be "at the margin" after the text is done) */
1813 if (nlen == FRAME_WIDTH (frame))
1814 olen = 0;
1815 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1817 #ifdef obsolete
1819 /* the following code loses disastrously if tem == nlen.
1820 Rather than trying to fix that case, I am trying the simpler
1821 solution found above. */
1823 /* If the text reaches to the right margin,
1824 it will lose one way or another (depending on AutoWrap)
1825 to clear to end of line after outputting all the text.
1826 So pause with one character to go and clear the line then. */
1827 if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
1829 /* endmatch must be zero, and tem must equal nsp + begmatch */
1830 write_glyphs (nbody + tem, nlen - tem - 1);
1831 clear_end_of_line (olen);
1832 olen = 0; /* Don't let it be cleared again later */
1833 write_glyphs (nbody + nlen - 1, 1);
1835 else
1836 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1837 #endif /* OBSOLETE */
1840 else if (nlen > olen)
1842 write_glyphs (nbody + nsp + begmatch, olen - tem);
1843 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1844 olen = nlen;
1846 else if (olen > nlen)
1848 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1849 delete_glyphs (olen - nlen);
1850 olen = nlen;
1854 just_erase:
1855 /* If any unerased characters remain after the new line, erase them. */
1856 if (olen > nlen)
1858 cursor_to (vpos, nlen);
1859 clear_end_of_line (olen);
1862 /* Exchange contents between current_frame and new_frame. */
1863 temp = desired_frame->glyphs[vpos];
1864 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1865 current_frame->glyphs[vpos] = temp;
1867 /* Exchange charstarts between current_frame and new_frame. */
1868 temp1 = desired_frame->charstarts[vpos];
1869 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1870 current_frame->charstarts[vpos] = temp1;
1873 /* A vector of size >= NFRAMES + 3 * NBUFFERS + 1, containing the session's
1874 frames, buffers, buffer-read-only flags, and buffer-modified-flags,
1875 and a trailing sentinel (so we don't need to add length checks). */
1876 static Lisp_Object frame_and_buffer_state;
1878 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
1879 Sframe_or_buffer_changed_p, 0, 0, 0,
1880 "Return non-nil if the frame and buffer state appears to have changed.\n\
1881 The state variable is an internal vector containing all frames and buffers,\n\
1882 along with the buffers' read-only and modified flags, which allows a fast\n\
1883 check to see whether the menu bars might need to be recomputed.\n\
1884 If this function returns non-nil, it updates the internal vector to reflect\n\
1885 the current state.\n")
1888 Lisp_Object tail, frame, buf;
1889 Lisp_Object *vecp;
1890 int n;
1891 vecp = XVECTOR (frame_and_buffer_state)->contents;
1892 FOR_EACH_FRAME (tail, frame)
1893 if (!EQ (*vecp++, frame))
1894 goto changed;
1895 /* Check that the buffer info matches.
1896 No need to test for the end of the vector
1897 because the last element of the vector is lambda
1898 and that will always cause a mismatch. */
1899 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1901 buf = XCONS (XCONS (tail)->car)->cdr;
1902 if (!EQ (*vecp++, buf))
1903 goto changed;
1904 if (!EQ (*vecp++, XBUFFER (buf)->read_only))
1905 goto changed;
1906 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
1907 goto changed;
1909 /* Detect deletion of a buffer at the end of the list. */
1910 if (*vecp == Qlambda)
1911 return Qnil;
1912 changed:
1913 /* Start with 1 so there is room for at least one lambda at the end. */
1914 n = 1;
1915 FOR_EACH_FRAME (tail, frame)
1916 n++;
1917 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1918 n += 3;
1919 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
1920 if (n > XVECTOR (frame_and_buffer_state)->size
1921 || n < XVECTOR (frame_and_buffer_state)->size / 2)
1922 frame_and_buffer_state = Fmake_vector (make_number (n), Qlambda);
1923 vecp = XVECTOR (frame_and_buffer_state)->contents;
1924 FOR_EACH_FRAME (tail, frame)
1925 *vecp++ = frame;
1926 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1928 buf = XCONS (XCONS (tail)->car)->cdr;
1929 *vecp++ = buf;
1930 *vecp++ = XBUFFER (buf)->read_only;
1931 *vecp++ = Fbuffer_modified_p (buf);
1933 /* If we left any slack in the vector, fill it up now. */
1934 for (; n < XVECTOR (frame_and_buffer_state)->size; ++n)
1935 *vecp++ = Qlambda;
1936 return Qt;
1939 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1940 1, 1, "FOpen termscript file: ",
1941 "Start writing all terminal output to FILE as well as the terminal.\n\
1942 FILE = nil means just close any termscript file currently open.")
1943 (file)
1944 Lisp_Object file;
1946 if (termscript != 0) fclose (termscript);
1947 termscript = 0;
1949 if (! NILP (file))
1951 file = Fexpand_file_name (file, Qnil);
1952 termscript = fopen (XSTRING (file)->data, "w");
1953 if (termscript == 0)
1954 report_file_error ("Opening termscript", Fcons (file, Qnil));
1956 return Qnil;
1960 #ifdef SIGWINCH
1961 SIGTYPE
1962 window_change_signal (signalnum) /* If we don't have an argument, */
1963 int signalnum; /* some compilers complain in signal calls. */
1965 int width, height;
1966 extern int errno;
1967 int old_errno = errno;
1969 get_frame_size (&width, &height);
1971 /* The frame size change obviously applies to a termcap-controlled
1972 frame. Find such a frame in the list, and assume it's the only
1973 one (since the redisplay code always writes to stdout, not a
1974 FILE * specified in the frame structure). Record the new size,
1975 but don't reallocate the data structures now. Let that be done
1976 later outside of the signal handler. */
1979 Lisp_Object tail, frame;
1981 FOR_EACH_FRAME (tail, frame)
1983 if (FRAME_TERMCAP_P (XFRAME (frame)))
1985 change_frame_size (XFRAME (frame), height, width, 0, 1);
1986 break;
1991 signal (SIGWINCH, window_change_signal);
1992 errno = old_errno;
1994 #endif /* SIGWINCH */
1997 /* Do any change in frame size that was requested by a signal. */
1999 do_pending_window_change ()
2001 /* If window_change_signal should have run before, run it now. */
2002 while (delayed_size_change)
2004 Lisp_Object tail, frame;
2006 delayed_size_change = 0;
2008 FOR_EACH_FRAME (tail, frame)
2010 FRAME_PTR f = XFRAME (frame);
2012 int height = FRAME_NEW_HEIGHT (f);
2013 int width = FRAME_NEW_WIDTH (f);
2015 if (height != 0 || width != 0)
2016 change_frame_size (f, height, width, 0, 0);
2022 /* Change the frame height and/or width. Values may be given as zero to
2023 indicate no change is to take place.
2025 If DELAY is non-zero, then assume we're being called from a signal
2026 handler, and queue the change for later - perhaps the next
2027 redisplay. Since this tries to resize windows, we can't call it
2028 from a signal handler. */
2030 change_frame_size (frame, newheight, newwidth, pretend, delay)
2031 register FRAME_PTR frame;
2032 int newheight, newwidth, pretend;
2034 /* If we can't deal with the change now, queue it for later. */
2035 if (delay)
2037 FRAME_NEW_HEIGHT (frame) = newheight;
2038 FRAME_NEW_WIDTH (frame) = newwidth;
2039 delayed_size_change = 1;
2040 return;
2043 /* This size-change overrides any pending one for this frame. */
2044 FRAME_NEW_HEIGHT (frame) = 0;
2045 FRAME_NEW_WIDTH (frame) = 0;
2047 /* If an argument is zero, set it to the current value. */
2048 newheight || (newheight = FRAME_HEIGHT (frame));
2049 newwidth || (newwidth = FRAME_WIDTH (frame));
2051 /* Round up to the smallest acceptable size. */
2052 check_frame_size (frame, &newheight, &newwidth);
2054 /* If we're not changing the frame size, quit now. */
2055 if (newheight == FRAME_HEIGHT (frame)
2056 && newwidth == FRAME_WIDTH (frame))
2057 return;
2059 if (newheight != FRAME_HEIGHT (frame))
2061 if (FRAME_HAS_MINIBUF_P (frame)
2062 && ! FRAME_MINIBUF_ONLY_P (frame))
2064 /* Frame has both root and minibuffer. */
2065 set_window_height (FRAME_ROOT_WINDOW (frame),
2066 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
2067 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
2068 newheight - 1);
2069 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
2071 else
2072 /* Frame has just one top-level window. */
2073 set_window_height (FRAME_ROOT_WINDOW (frame),
2074 newheight - FRAME_MENU_BAR_LINES (frame), 0);
2076 if (FRAME_TERMCAP_P (frame) && !pretend)
2077 FrameRows = newheight;
2079 #if 0
2080 if (frame->output_method == output_termcap)
2082 frame_height = newheight;
2083 if (!pretend)
2084 FrameRows = newheight;
2086 #endif
2089 if (newwidth != FRAME_WIDTH (frame))
2091 set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
2092 if (FRAME_HAS_MINIBUF_P (frame))
2093 set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
2095 if (FRAME_TERMCAP_P (frame) && !pretend)
2096 FrameCols = newwidth;
2097 #if 0
2098 if (frame->output_method == output_termcap)
2100 frame_width = newwidth;
2101 if (!pretend)
2102 FrameCols = newwidth;
2104 #endif
2107 FRAME_HEIGHT (frame) = newheight;
2108 FRAME_WIDTH (frame) = newwidth;
2110 if (FRAME_CURSOR_X (frame) >= FRAME_WIDTH (frame))
2111 FRAME_CURSOR_X (frame) = FRAME_WIDTH (frame) - 1;
2112 if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
2113 FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
2115 remake_frame_glyphs (frame);
2116 calculate_costs (frame);
2119 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2120 Ssend_string_to_terminal, 1, 1, 0,
2121 "Send STRING to the terminal without alteration.\n\
2122 Control characters in STRING will have terminal-dependent effects.")
2123 (str)
2124 Lisp_Object str;
2126 CHECK_STRING (str, 0);
2127 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
2128 fflush (stdout);
2129 if (termscript)
2131 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
2132 fflush (termscript);
2134 return Qnil;
2137 DEFUN ("ding", Fding, Sding, 0, 1, 0,
2138 "Beep, or flash the screen.\n\
2139 Also, unless an argument is given,\n\
2140 terminate any keyboard macro currently executing.")
2141 (arg)
2142 Lisp_Object arg;
2144 if (!NILP (arg))
2146 if (noninteractive)
2147 putchar (07);
2148 else
2149 ring_bell ();
2150 fflush (stdout);
2152 else
2153 bitch_at_user ();
2155 return Qnil;
2158 bitch_at_user ()
2160 if (noninteractive)
2161 putchar (07);
2162 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2163 error ("Keyboard macro terminated by a command ringing the bell");
2164 else
2165 ring_bell ();
2166 fflush (stdout);
2169 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
2170 "Pause, without updating display, for SECONDS seconds.\n\
2171 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2172 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2173 additional wait period, in milliseconds; this may be useful if your\n\
2174 Emacs was built without floating point support.\n\
2175 \(Not all operating systems support waiting for a fraction of a second.)")
2176 (seconds, milliseconds)
2177 Lisp_Object seconds, milliseconds;
2179 int sec, usec;
2181 if (NILP (milliseconds))
2182 XSETINT (milliseconds, 0);
2183 else
2184 CHECK_NUMBER (milliseconds, 1);
2185 usec = XINT (milliseconds) * 1000;
2187 #ifdef LISP_FLOAT_TYPE
2189 double duration = extract_float (seconds);
2190 sec = (int) duration;
2191 usec += (duration - sec) * 1000000;
2193 #else
2194 CHECK_NUMBER (seconds, 0);
2195 sec = XINT (seconds);
2196 #endif
2198 #ifndef EMACS_HAS_USECS
2199 if (sec == 0 && usec != 0)
2200 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
2201 #endif
2203 /* Assure that 0 <= usec < 1000000. */
2204 if (usec < 0)
2206 /* We can't rely on the rounding being correct if user is negative. */
2207 if (-1000000 < usec)
2208 sec--, usec += 1000000;
2209 else
2210 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
2212 else
2213 sec += usec / 1000000, usec %= 1000000;
2215 if (sec <= 0)
2216 return Qnil;
2219 Lisp_Object zero;
2221 XSETFASTINT (zero, 0);
2222 wait_reading_process_input (sec, usec, zero, 0);
2225 /* We should always have wait_reading_process_input; we have a dummy
2226 implementation for systems which don't support subprocesses. */
2227 #if 0
2228 /* No wait_reading_process_input */
2229 immediate_quit = 1;
2230 QUIT;
2232 #ifdef VMS
2233 sys_sleep (sec);
2234 #else /* not VMS */
2235 /* The reason this is done this way
2236 (rather than defined (H_S) && defined (H_T))
2237 is because the VMS preprocessor doesn't grok `defined' */
2238 #ifdef HAVE_SELECT
2239 EMACS_GET_TIME (end_time);
2240 EMACS_SET_SECS_USECS (timeout, sec, usec);
2241 EMACS_ADD_TIME (end_time, end_time, timeout);
2243 while (1)
2245 EMACS_GET_TIME (timeout);
2246 EMACS_SUB_TIME (timeout, end_time, timeout);
2247 if (EMACS_TIME_NEG_P (timeout)
2248 || !select (1, 0, 0, 0, &timeout))
2249 break;
2251 #else /* not HAVE_SELECT */
2252 sleep (sec);
2253 #endif /* HAVE_SELECT */
2254 #endif /* not VMS */
2256 immediate_quit = 0;
2257 #endif /* no subprocesses */
2259 return Qnil;
2262 /* This is just like wait_reading_process_input, except that
2263 it does the redisplay.
2265 It's also much like Fsit_for, except that it can be used for
2266 waiting for input as well. One differnce is that sit_for
2267 does not call prepare_menu_bars; Fsit_for does call that. */
2269 Lisp_Object
2270 sit_for (sec, usec, reading, display)
2271 int sec, usec, reading, display;
2273 Lisp_Object read_kbd;
2275 if (detect_input_pending ())
2276 return Qnil;
2278 if (display)
2279 redisplay_preserve_echo_area ();
2281 if (sec == 0 && usec == 0)
2282 return Qt;
2284 #ifdef SIGIO
2285 gobble_input (0);
2286 #endif
2288 XSETINT (read_kbd, reading ? -1 : 1);
2289 wait_reading_process_input (sec, usec, read_kbd, display);
2292 /* wait_reading_process_input should always be available now; it is
2293 simulated in a simple way on systems that don't support
2294 subprocesses. */
2295 #if 0
2296 /* No wait_reading_process_input available. */
2297 immediate_quit = 1;
2298 QUIT;
2300 waitchannels = 1;
2301 #ifdef VMS
2302 input_wait_timeout (XINT (arg));
2303 #else /* not VMS */
2304 #ifndef HAVE_TIMEVAL
2305 timeout_sec = sec;
2306 select (1, &waitchannels, 0, 0, &timeout_sec);
2307 #else /* HAVE_TIMEVAL */
2308 timeout.tv_sec = sec;
2309 timeout.tv_usec = usec;
2310 select (1, &waitchannels, 0, 0, &timeout);
2311 #endif /* HAVE_TIMEVAL */
2312 #endif /* not VMS */
2314 immediate_quit = 0;
2315 #endif
2317 return detect_input_pending () ? Qnil : Qt;
2320 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
2321 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
2322 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2323 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2324 additional wait period, in milliseconds; this may be useful if your\n\
2325 Emacs was built without floating point support.\n\
2326 \(Not all operating systems support waiting for a fraction of a second.)\n\
2327 Optional third arg non-nil means don't redisplay, just wait for input.\n\
2328 Redisplay is preempted as always if input arrives, and does not happen\n\
2329 if input is available before it starts.\n\
2330 Value is t if waited the full time with no input arriving.")
2331 (seconds, milliseconds, nodisp)
2332 Lisp_Object seconds, milliseconds, nodisp;
2334 int sec, usec;
2336 if (NILP (milliseconds))
2337 XSETINT (milliseconds, 0);
2338 else
2339 CHECK_NUMBER (milliseconds, 1);
2340 usec = XINT (milliseconds) * 1000;
2342 #ifdef LISP_FLOAT_TYPE
2344 double duration = extract_float (seconds);
2345 sec = (int) duration;
2346 usec += (duration - sec) * 1000000;
2348 #else
2349 CHECK_NUMBER (seconds, 0);
2350 sec = XINT (seconds);
2351 #endif
2353 #ifndef EMACS_HAS_USECS
2354 if (usec != 0 && sec == 0)
2355 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
2356 #endif
2358 if (NILP (nodisp))
2359 prepare_menu_bars ();
2360 return sit_for (sec, usec, 0, NILP (nodisp));
2363 char *terminal_type;
2365 /* Initialization done when Emacs fork is started, before doing stty. */
2366 /* Determine terminal type and set terminal_driver */
2367 /* Then invoke its decoding routine to set up variables
2368 in the terminal package */
2370 init_display ()
2372 #ifdef HAVE_X_WINDOWS
2373 extern int display_arg;
2374 #endif
2376 meta_key = 0;
2377 inverse_video = 0;
2378 cursor_in_echo_area = 0;
2379 terminal_type = (char *) 0;
2381 /* Now is the time to initialize this; it's used by init_sys_modes
2382 during startup. */
2383 Vwindow_system = Qnil;
2385 /* If the user wants to use a window system, we shouldn't bother
2386 initializing the terminal. This is especially important when the
2387 terminal is so dumb that emacs gives up before and doesn't bother
2388 using the window system.
2390 If the DISPLAY environment variable is set, try to use X, and die
2391 with an error message if that doesn't work. */
2393 #ifdef HAVE_X_WINDOWS
2394 if (! display_arg)
2396 #ifdef VMS
2397 display_arg = (getenv ("DECW$DISPLAY") != 0);
2398 #else
2399 display_arg = (getenv ("DISPLAY") != 0);
2400 #endif
2403 if (!inhibit_window_system && display_arg)
2405 Vwindow_system = intern ("x");
2406 #ifdef HAVE_X11
2407 Vwindow_system_version = make_number (11);
2408 #else
2409 Vwindow_system_version = make_number (10);
2410 #endif
2411 return;
2413 #endif /* HAVE_X_WINDOWS */
2415 /* If no window system has been specified, try to use the terminal. */
2416 if (! isatty (0))
2418 fprintf (stderr, "emacs: standard input is not a tty\n");
2419 exit (1);
2422 /* Look at the TERM variable */
2423 terminal_type = (char *) getenv ("TERM");
2424 if (!terminal_type)
2426 #ifdef VMS
2427 fprintf (stderr, "Please specify your terminal type.\n\
2428 For types defined in VMS, use set term /device=TYPE.\n\
2429 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2430 \(The quotation marks are necessary since terminal types are lower case.)\n");
2431 #else
2432 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2433 #endif
2434 exit (1);
2437 #ifdef VMS
2438 /* VMS DCL tends to upcase things, so downcase term type.
2439 Hardly any uppercase letters in terminal types; should be none. */
2441 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2442 char *p;
2444 strcpy (new, terminal_type);
2446 for (p = new; *p; p++)
2447 if (isupper (*p))
2448 *p = tolower (*p);
2450 terminal_type = new;
2452 #endif
2454 term_init (terminal_type);
2456 remake_frame_glyphs (selected_frame);
2457 calculate_costs (selected_frame);
2459 /* X and Y coordinates of the cursor between updates. */
2460 FRAME_CURSOR_X (selected_frame) = 0;
2461 FRAME_CURSOR_Y (selected_frame) = 0;
2463 #ifdef SIGWINCH
2464 #ifndef CANNOT_DUMP
2465 if (initialized)
2466 #endif /* CANNOT_DUMP */
2467 signal (SIGWINCH, window_change_signal);
2468 #endif /* SIGWINCH */
2471 syms_of_display ()
2473 #ifdef MULTI_FRAME
2474 defsubr (&Sredraw_frame);
2475 #endif
2476 defsubr (&Sredraw_display);
2477 defsubr (&Sframe_or_buffer_changed_p);
2478 defsubr (&Sopen_termscript);
2479 defsubr (&Sding);
2480 defsubr (&Ssit_for);
2481 defsubr (&Ssleep_for);
2482 defsubr (&Ssend_string_to_terminal);
2484 frame_and_buffer_state = Fmake_vector (make_number (1), Qlambda);
2485 staticpro (&frame_and_buffer_state);
2487 DEFVAR_INT ("baud-rate", &baud_rate,
2488 "*The output baud rate of the terminal.\n\
2489 On most systems, changing this value will affect the amount of padding\n\
2490 and the other strategic decisions made during redisplay.");
2491 DEFVAR_BOOL ("inverse-video", &inverse_video,
2492 "*Non-nil means invert the entire frame display.\n\
2493 This means everything is in inverse video which otherwise would not be.");
2494 DEFVAR_BOOL ("visible-bell", &visible_bell,
2495 "*Non-nil means try to flash the frame to represent a bell.");
2496 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
2497 "*Non-nil means no need to redraw entire frame after suspending.\n\
2498 A non-nil value is useful if the terminal can automatically preserve\n\
2499 Emacs's frame display when you reenter Emacs.\n\
2500 It is up to you to set this variable if your terminal can do that.");
2501 DEFVAR_LISP ("window-system", &Vwindow_system,
2502 "A symbol naming the window-system under which Emacs is running\n\
2503 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
2504 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2505 "The version number of the window system in use.\n\
2506 For X windows, this is 10 or 11.");
2507 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2508 "Non-nil means put cursor in minibuffer, at end of any message there.");
2509 DEFVAR_LISP ("glyph-table", &Vglyph_table,
2510 "Table defining how to output a glyph code to the frame.\n\
2511 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2512 Each element can be:\n\
2513 integer: a glyph code which this glyph is an alias for.\n\
2514 string: output this glyph using that string (not impl. in X windows).\n\
2515 nil: this glyph mod 256 is char code to output,\n\
2516 and this glyph / 256 is face code for X windows (see `face-id').");
2517 Vglyph_table = Qnil;
2519 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2520 "Display table to use for buffers that specify none.\n\
2521 See `buffer-display-table' for more information.");
2522 Vstandard_display_table = Qnil;
2524 /* Initialize `window-system', unless init_display already decided it. */
2525 #ifdef CANNOT_DUMP
2526 if (noninteractive)
2527 #endif
2529 Vwindow_system = Qnil;
2530 Vwindow_system_version = Qnil;