Even more compile stuff.
[emacs.git] / src / dispnew.c
blobbc521fb26e128eaa0aefdc84a798fedd1f2ad801
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>
22 #include <stdio.h>
24 #include <config.h>
25 #include <ctype.h>
27 #include "lisp.h"
28 #include "termchar.h"
29 #include "termopts.h"
30 #include "termhooks.h"
31 #include "cm.h"
32 #include "dispextern.h"
33 #include "buffer.h"
34 #include "frame.h"
35 #include "window.h"
36 #include "commands.h"
37 #include "disptab.h"
38 #include "indent.h"
39 #include "intervals.h"
41 #include "systty.h"
42 #include "systime.h"
44 #ifdef HAVE_X_WINDOWS
45 #include "xterm.h"
46 #endif /* HAVE_X_WINDOWS */
48 #include <errno.h>
50 #define max(a, b) ((a) > (b) ? (a) : (b))
51 #define min(a, b) ((a) < (b) ? (a) : (b))
53 /* Get number of chars of output now in the buffer of a stdio stream.
54 This ought to be built in in stdio, but it isn't.
55 Some s- files override this because their stdio internals differ. */
56 #ifdef __GNU_LIBRARY__
57 /* The s- file might have overridden the definition with one that works for
58 the system's C library. But we are using the GNU C library, so this is
59 the right definition for every system. */
60 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
61 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
62 #else
63 #undef PENDING_OUTPUT_COUNT
64 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
65 #endif
66 #else /* not __GNU_LIBRARY__ */
67 #ifndef PENDING_OUTPUT_COUNT
68 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
69 #endif
70 #endif
72 /* Nonzero upon entry to redisplay means do not assume anything about
73 current contents of actual terminal frame; clear and redraw it. */
75 int frame_garbaged;
77 /* Nonzero means last display completed. Zero means it was preempted. */
79 int display_completed;
81 /* Lisp variable visible-bell; enables use of screen-flash
82 instead of audible bell. */
84 int visible_bell;
86 /* Invert the color of the whole frame, at a low level. */
88 int inverse_video;
90 /* Line speed of the terminal. */
92 int baud_rate;
94 /* nil or a symbol naming the window system under which emacs is
95 running ('x is the only current possibility). */
97 Lisp_Object Vwindow_system;
99 /* Version number of X windows: 10, 11 or nil. */
100 Lisp_Object Vwindow_system_version;
102 /* Vector of glyph definitions. Indexed by glyph number,
103 the contents are a string which is how to output the glyph.
105 If Vglyph_table is nil, a glyph is output by using its low 8 bits
106 as a character code. */
108 Lisp_Object Vglyph_table;
110 /* Display table to use for vectors that don't specify their own. */
112 Lisp_Object Vstandard_display_table;
114 /* Nonzero means reading single-character input with prompt
115 so put cursor on minibuffer after the prompt.
116 positive means at end of text in echo area;
117 negative means at beginning of line. */
118 int cursor_in_echo_area;
120 /* The currently selected frame.
121 In a single-frame version, this variable always remains 0. */
123 FRAME_PTR selected_frame;
125 /* A frame which is not just a minibuffer, or 0 if there are no such
126 frames. This is usually the most recent such frame that was
127 selected. In a single-frame version, this variable always remains 0. */
128 FRAME_PTR last_nonminibuf_frame;
130 /* In a single-frame version, the information that would otherwise
131 exist inside frame objects lives in the following structure instead.
133 NOTE: the_only_frame is not checked for garbage collection; don't
134 store collectible objects in any of its fields!
136 You're not/The only frame in town/... */
138 #ifndef MULTI_FRAME
139 struct frame the_only_frame;
140 #endif
142 /* This is a vector, made larger whenever it isn't large enough,
143 which is used inside `update_frame' to hold the old contents
144 of the FRAME_PHYS_LINES of the frame being updated. */
145 struct frame_glyphs **ophys_lines;
146 /* Length of vector currently allocated. */
147 int ophys_lines_length;
149 FILE *termscript; /* Stdio stream being used for copy of all output. */
151 struct cm Wcm; /* Structure for info on cursor positioning */
153 extern short ospeed; /* Output speed (from sg_ospeed) */
155 int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
157 #ifdef MULTI_FRAME
159 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
160 "Clear frame FRAME and output again what is supposed to appear on it.")
161 (frame)
162 Lisp_Object frame;
164 FRAME_PTR f;
166 CHECK_LIVE_FRAME (frame, 0);
167 f = XFRAME (frame);
168 update_begin (f);
169 /* set_terminal_modes (); */
170 clear_frame ();
171 clear_frame_records (f);
172 update_end (f);
173 fflush (stdout);
174 windows_or_buffers_changed++;
175 /* Mark all windows as INaccurate,
176 so that every window will have its redisplay done. */
177 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
178 f->garbaged = 0;
179 return Qnil;
182 redraw_frame (f)
183 FRAME_PTR f;
185 Lisp_Object frame;
186 XSET (frame, Lisp_Frame, f);
187 Fredraw_frame (frame);
190 #else
192 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
193 "Clear frame FRAME and output again what is supposed to appear on it.")
194 (frame)
195 Lisp_Object frame;
197 update_begin (0);
198 set_terminal_modes ();
199 clear_frame ();
200 update_end (0);
201 fflush (stdout);
202 clear_frame_records (0);
203 windows_or_buffers_changed++;
204 /* Mark all windows as INaccurate,
205 so that every window will have its redisplay done. */
206 mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
207 return Qnil;
210 #endif
212 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
213 "Clear and redisplay all visible frames.")
216 Lisp_Object tail, frame;
218 FOR_EACH_FRAME (tail, frame)
219 if (FRAME_VISIBLE_P (XFRAME (frame)))
220 Fredraw_frame (frame);
222 return Qnil;
225 /* This is used when frame_garbaged is set.
226 Redraw the individual frames marked as garbaged. */
228 void
229 redraw_garbaged_frames ()
231 Lisp_Object tail, frame;
233 FOR_EACH_FRAME (tail, frame)
234 if (FRAME_VISIBLE_P (XFRAME (frame))
235 && FRAME_GARBAGED_P (XFRAME (frame)))
236 Fredraw_frame (frame);
240 static struct frame_glyphs *
241 make_frame_glyphs (frame, empty)
242 register FRAME_PTR frame;
243 int empty;
245 register int i;
246 register width = FRAME_WIDTH (frame);
247 register height = FRAME_HEIGHT (frame);
248 register struct frame_glyphs *new
249 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
251 SET_GLYPHS_FRAME (new, frame);
252 new->height = height;
253 new->width = width;
254 new->used = (int *) xmalloc (height * sizeof (int));
255 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
256 new->charstarts = (int **) xmalloc (height * sizeof (int *));
257 new->highlight = (char *) xmalloc (height * sizeof (char));
258 new->enable = (char *) xmalloc (height * sizeof (char));
259 bzero (new->enable, height * sizeof (char));
260 new->bufp = (int *) xmalloc (height * sizeof (int));
262 #ifdef HAVE_X_WINDOWS
263 if (FRAME_X_P (frame))
265 new->top_left_x = (short *) xmalloc (height * sizeof (short));
266 new->top_left_y = (short *) xmalloc (height * sizeof (short));
267 new->pix_width = (short *) xmalloc (height * sizeof (short));
268 new->pix_height = (short *) xmalloc (height * sizeof (short));
269 new->max_ascent = (short *) xmalloc (height * sizeof (short));
271 #endif
273 if (empty)
275 /* Make the buffer used by decode_mode_spec. This buffer is also
276 used as temporary storage when updating the frame. See scroll.c. */
277 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
278 unsigned int total_charstarts = (width + 2) * sizeof (int);
280 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
281 bzero (new->total_contents, total_glyphs);
283 new->total_charstarts = (int *) xmalloc (total_charstarts);
284 bzero (new->total_charstarts, total_glyphs);
286 else
288 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
290 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
291 bzero (new->total_contents, total_glyphs);
292 for (i = 0; i < height; i++)
293 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
295 if (!FRAME_TERMCAP_P (frame))
297 unsigned int total_charstarts = height * (width + 2) * sizeof (int);
299 new->total_charstarts = (int *) xmalloc (total_charstarts);
300 bzero (new->total_charstarts, total_charstarts);
301 for (i = 0; i < height; i++)
302 new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
304 else
306 /* Without a window system, we don't really need charstarts.
307 So use a small amount of space to make enough data structure
308 to prevent crashes in display_text_line. */
309 new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
310 for (i = 0; i < height; i++)
311 new->charstarts[i] = new->total_charstarts;
315 return new;
318 static void
319 free_frame_glyphs (frame, glyphs)
320 FRAME_PTR frame;
321 struct frame_glyphs *glyphs;
323 if (glyphs->total_contents)
324 xfree (glyphs->total_contents);
325 if (glyphs->total_charstarts)
326 xfree (glyphs->total_charstarts);
328 xfree (glyphs->used);
329 xfree (glyphs->glyphs);
330 xfree (glyphs->highlight);
331 xfree (glyphs->enable);
332 xfree (glyphs->bufp);
333 if (glyphs->charstarts)
334 xfree (glyphs->charstarts);
336 #ifdef HAVE_X_WINDOWS
337 if (FRAME_X_P (frame))
339 xfree (glyphs->top_left_x);
340 xfree (glyphs->top_left_y);
341 xfree (glyphs->pix_width);
342 xfree (glyphs->pix_height);
343 xfree (glyphs->max_ascent);
345 #endif
347 xfree (glyphs);
350 static void
351 remake_frame_glyphs (frame)
352 FRAME_PTR frame;
354 if (FRAME_CURRENT_GLYPHS (frame))
355 free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
356 if (FRAME_DESIRED_GLYPHS (frame))
357 free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
358 if (FRAME_TEMP_GLYPHS (frame))
359 free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
361 if (FRAME_MESSAGE_BUF (frame))
363 /* Reallocate the frame's message buffer; remember that
364 echo_area_glyphs may be pointing here. */
365 char *old_message_buf = FRAME_MESSAGE_BUF (frame);
367 FRAME_MESSAGE_BUF (frame)
368 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
369 FRAME_WIDTH (frame) + 1);
371 if (echo_area_glyphs == old_message_buf)
372 echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
373 if (previous_echo_glyphs == old_message_buf)
374 previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
376 else
377 FRAME_MESSAGE_BUF (frame)
378 = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
380 FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
381 FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
382 FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
383 SET_FRAME_GARBAGED (frame);
386 /* Return the hash code of contents of line VPOS in frame-matrix M. */
388 static int
389 line_hash_code (m, vpos)
390 register struct frame_glyphs *m;
391 int vpos;
393 register GLYPH *body, *end;
394 register int h = 0;
396 if (!m->enable[vpos])
397 return 0;
399 /* Give all highlighted lines the same hash code
400 so as to encourage scrolling to leave them in place. */
401 if (m->highlight[vpos])
402 return -1;
404 body = m->glyphs[vpos];
406 if (must_write_spaces)
407 while (1)
409 GLYPH g = *body++;
411 if (g == 0)
412 break;
413 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
415 else
416 while (1)
418 GLYPH g = *body++;
420 if (g == 0)
421 break;
422 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
425 if (h)
426 return h;
427 return 1;
430 /* Return number of characters in line in M at vpos VPOS,
431 except don't count leading and trailing spaces
432 unless the terminal requires those to be explicitly output. */
434 static unsigned int
435 line_draw_cost (m, vpos)
436 struct frame_glyphs *m;
437 int vpos;
439 register GLYPH *beg = m->glyphs[vpos];
440 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
441 register int i;
442 register int tlen = GLYPH_TABLE_LENGTH;
443 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
445 /* Ignore trailing and leading spaces if we can. */
446 if (!must_write_spaces)
448 while ((end != beg) && (*end == SPACEGLYPH))
449 --end;
450 if (end == beg)
451 return (0); /* All blank line. */
453 while (*beg == SPACEGLYPH)
454 ++beg;
457 /* If we don't have a glyph-table, each glyph is one character,
458 so return the number of glyphs. */
459 if (tbase == 0)
460 return end - beg;
462 /* Otherwise, scan the glyphs and accumulate their total size in I. */
463 i = 0;
464 while ((beg <= end) && *beg)
466 register GLYPH g = *beg++;
468 if (GLYPH_SIMPLE_P (tbase, tlen, g))
469 i += 1;
470 else
471 i += GLYPH_LENGTH (tbase, g);
473 return i;
476 /* The functions on this page are the interface from xdisp.c to redisplay.
478 The only other interface into redisplay is through setting
479 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
480 and SET_FRAME_GARBAGED (frame). */
482 /* cancel_line eliminates any request to display a line at position `vpos' */
484 cancel_line (vpos, frame)
485 int vpos;
486 register FRAME_PTR frame;
488 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
491 clear_frame_records (frame)
492 register FRAME_PTR frame;
494 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
497 /* Prepare to display on line VPOS starting at HPOS within it. */
499 void
500 get_display_line (frame, vpos, hpos)
501 register FRAME_PTR frame;
502 int vpos;
503 register int hpos;
505 register struct frame_glyphs *glyphs;
506 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
507 register GLYPH *p;
509 if (vpos < 0)
510 abort ();
512 if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
513 abort ();
515 if (! desired_glyphs->enable[vpos])
517 desired_glyphs->used[vpos] = 0;
518 desired_glyphs->highlight[vpos] = 0;
519 desired_glyphs->enable[vpos] = 1;
522 if (hpos > desired_glyphs->used[vpos])
524 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
525 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
527 desired_glyphs->used[vpos] = hpos;
528 while (g != end)
529 *g++ = SPACEGLYPH;
533 /* Like bcopy except never gets confused by overlap. */
535 void
536 safe_bcopy (from, to, size)
537 char *from, *to;
538 int size;
540 if (size <= 0 || from == to)
541 return;
543 /* If the source and destination don't overlap, then bcopy can
544 handle it. If they do overlap, but the destination is lower in
545 memory than the source, we'll assume bcopy can handle that. */
546 if (to < from || from + size <= to)
547 bcopy (from, to, size);
549 /* Otherwise, we'll copy from the end. */
550 else
552 register char *endf = from + size;
553 register char *endt = to + size;
555 /* If TO - FROM is large, then we should break the copy into
556 nonoverlapping chunks of TO - FROM bytes each. However, if
557 TO - FROM is small, then the bcopy function call overhead
558 makes this not worth it. The crossover point could be about
559 anywhere. Since I don't think the obvious copy loop is too
560 bad, I'm trying to err in its favor. */
561 if (to - from < 64)
564 *--endt = *--endf;
565 while (endf != from);
567 else
569 for (;;)
571 endt -= (to - from);
572 endf -= (to - from);
574 if (endt < to)
575 break;
577 bcopy (endf, endt, to - from);
580 /* If SIZE wasn't a multiple of TO - FROM, there will be a
581 little left over. The amount left over is
582 (endt + (to - from)) - to, which is endt - from. */
583 bcopy (from, to, endt - from);
588 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
589 DISTANCE may be negative. */
591 static void
592 rotate_vector (vector, size, distance)
593 char *vector;
594 int size;
595 int distance;
597 char *temp = (char *) alloca (size);
599 if (distance < 0)
600 distance += size;
602 bcopy (vector, temp + distance, size - distance);
603 bcopy (vector + size - distance, temp, distance);
604 bcopy (temp, vector, size);
607 /* Scroll lines from vpos FROM up to but not including vpos END
608 down by AMOUNT lines (AMOUNT may be negative).
609 Returns nonzero if done, zero if terminal cannot scroll them. */
612 scroll_frame_lines (frame, from, end, amount, newpos)
613 register FRAME_PTR frame;
614 int from, end, amount, newpos;
616 register int i;
617 register struct frame_glyphs *current_frame
618 = FRAME_CURRENT_GLYPHS (frame);
619 int pos_adjust;
620 int width = FRAME_WIDTH (frame);
622 if (!line_ins_del_ok)
623 return 0;
625 if (amount == 0)
626 return 1;
628 if (amount > 0)
630 update_begin (frame);
631 set_terminal_window (end + amount);
632 if (!scroll_region_ok)
633 ins_del_lines (end, -amount);
634 ins_del_lines (from, amount);
635 set_terminal_window (0);
637 rotate_vector (current_frame->glyphs + from,
638 sizeof (GLYPH *) * (end + amount - from),
639 amount * sizeof (GLYPH *));
641 rotate_vector (current_frame->charstarts + from,
642 sizeof (int *) * (end + amount - from),
643 amount * sizeof (int *));
645 safe_bcopy (current_frame->used + from,
646 current_frame->used + from + amount,
647 (end - from) * sizeof current_frame->used[0]);
649 safe_bcopy (current_frame->highlight + from,
650 current_frame->highlight + from + amount,
651 (end - from) * sizeof current_frame->highlight[0]);
653 safe_bcopy (current_frame->enable + from,
654 current_frame->enable + from + amount,
655 (end - from) * sizeof current_frame->enable[0]);
657 /* Adjust the lines by an amount
658 that puts the first of them at NEWPOS. */
659 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
661 /* Offset each char position in the charstarts lines we moved
662 by pos_adjust. */
663 for (i = from + amount; i < end + amount; i++)
665 int *line = current_frame->charstarts[i];
666 int col;
667 for (col = 0; col < width; col++)
668 if (line[col] > 0)
669 line[col] += pos_adjust;
671 for (i = from; i < from + amount; i++)
673 int *line = current_frame->charstarts[i];
674 int col;
675 line[0] = -1;
676 for (col = 0; col < width; col++)
677 line[col] = 0;
680 /* Mark the lines made empty by scrolling as enabled, empty and
681 normal video. */
682 bzero (current_frame->used + from,
683 amount * sizeof current_frame->used[0]);
684 bzero (current_frame->highlight + from,
685 amount * sizeof current_frame->highlight[0]);
686 for (i = from; i < from + amount; i++)
688 current_frame->glyphs[i][0] = '\0';
689 current_frame->charstarts[i][0] = -1;
690 current_frame->enable[i] = 1;
693 safe_bcopy (current_frame->bufp + from,
694 current_frame->bufp + from + amount,
695 (end - from) * sizeof current_frame->bufp[0]);
697 #ifdef HAVE_X_WINDOWS
698 if (FRAME_X_P (frame))
700 safe_bcopy (current_frame->top_left_x + from,
701 current_frame->top_left_x + from + amount,
702 (end - from) * sizeof current_frame->top_left_x[0]);
704 safe_bcopy (current_frame->top_left_y + from,
705 current_frame->top_left_y + from + amount,
706 (end - from) * sizeof current_frame->top_left_y[0]);
708 safe_bcopy (current_frame->pix_width + from,
709 current_frame->pix_width + from + amount,
710 (end - from) * sizeof current_frame->pix_width[0]);
712 safe_bcopy (current_frame->pix_height + from,
713 current_frame->pix_height + from + amount,
714 (end - from) * sizeof current_frame->pix_height[0]);
716 safe_bcopy (current_frame->max_ascent + from,
717 current_frame->max_ascent + from + amount,
718 (end - from) * sizeof current_frame->max_ascent[0]);
720 #endif /* HAVE_X_WINDOWS */
722 update_end (frame);
724 if (amount < 0)
726 update_begin (frame);
727 set_terminal_window (end);
728 ins_del_lines (from + amount, amount);
729 if (!scroll_region_ok)
730 ins_del_lines (end + amount, -amount);
731 set_terminal_window (0);
733 rotate_vector (current_frame->glyphs + from + amount,
734 sizeof (GLYPH *) * (end - from - amount),
735 amount * sizeof (GLYPH *));
737 rotate_vector (current_frame->charstarts + from + amount,
738 sizeof (int *) * (end - from - amount),
739 amount * sizeof (int *));
741 safe_bcopy (current_frame->used + from,
742 current_frame->used + from + amount,
743 (end - from) * sizeof current_frame->used[0]);
745 safe_bcopy (current_frame->highlight + from,
746 current_frame->highlight + from + amount,
747 (end - from) * sizeof current_frame->highlight[0]);
749 safe_bcopy (current_frame->enable + from,
750 current_frame->enable + from + amount,
751 (end - from) * sizeof current_frame->enable[0]);
753 /* Adjust the lines by an amount
754 that puts the first of them at NEWPOS. */
755 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
757 /* Offset each char position in the charstarts lines we moved
758 by pos_adjust. */
759 for (i = from + amount; i < end + amount; i++)
761 int *line = current_frame->charstarts[i];
762 int col;
763 for (col = 0; col < width; col++)
764 if (line[col] > 0)
765 line[col] += pos_adjust;
767 for (i = end + amount; i < end; i++)
769 int *line = current_frame->charstarts[i];
770 int col;
771 line[0] = -1;
772 for (col = 0; col < width; col++)
773 line[col] = 0;
776 /* Mark the lines made empty by scrolling as enabled, empty and
777 normal video. */
778 bzero (current_frame->used + end + amount,
779 - amount * sizeof current_frame->used[0]);
780 bzero (current_frame->highlight + end + amount,
781 - amount * sizeof current_frame->highlight[0]);
782 for (i = end + amount; i < end; i++)
784 current_frame->glyphs[i][0] = '\0';
785 current_frame->charstarts[i][0] = 0;
786 current_frame->enable[i] = 1;
789 safe_bcopy (current_frame->bufp + from,
790 current_frame->bufp + from + amount,
791 (end - from) * sizeof current_frame->bufp[0]);
793 #ifdef HAVE_X_WINDOWS
794 if (FRAME_X_P (frame))
796 safe_bcopy (current_frame->top_left_x + from,
797 current_frame->top_left_x + from + amount,
798 (end - from) * sizeof current_frame->top_left_x[0]);
800 safe_bcopy (current_frame->top_left_y + from,
801 current_frame->top_left_y + from + amount,
802 (end - from) * sizeof current_frame->top_left_y[0]);
804 safe_bcopy (current_frame->pix_width + from,
805 current_frame->pix_width + from + amount,
806 (end - from) * sizeof current_frame->pix_width[0]);
808 safe_bcopy (current_frame->pix_height + from,
809 current_frame->pix_height + from + amount,
810 (end - from) * sizeof current_frame->pix_height[0]);
812 safe_bcopy (current_frame->max_ascent + from,
813 current_frame->max_ascent + from + amount,
814 (end - from) * sizeof current_frame->max_ascent[0]);
816 #endif /* HAVE_X_WINDOWS */
818 update_end (frame);
820 return 1;
823 /* After updating a window W that isn't the full frame wide,
824 copy all the columns that W does not occupy
825 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
826 so that update_frame will not change those columns. */
828 preserve_other_columns (w)
829 struct window *w;
831 register int vpos;
832 register struct frame_glyphs *current_frame, *desired_frame;
833 register FRAME_PTR frame = XFRAME (w->frame);
834 int start = XFASTINT (w->left);
835 int end = XFASTINT (w->left) + XFASTINT (w->width);
836 int bot = XFASTINT (w->top) + XFASTINT (w->height);
838 current_frame = FRAME_CURRENT_GLYPHS (frame);
839 desired_frame = FRAME_DESIRED_GLYPHS (frame);
841 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
843 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
845 if (start > 0)
847 int len;
849 bcopy (current_frame->glyphs[vpos],
850 desired_frame->glyphs[vpos],
851 start * sizeof (current_frame->glyphs[vpos]));
852 bcopy (current_frame->charstarts[vpos],
853 desired_frame->charstarts[vpos],
854 start * sizeof (current_frame->charstarts[vpos]));
855 len = min (start, current_frame->used[vpos]);
856 if (desired_frame->used[vpos] < len)
857 desired_frame->used[vpos] = len;
859 if (current_frame->used[vpos] > end
860 && desired_frame->used[vpos] < current_frame->used[vpos])
862 while (desired_frame->used[vpos] < end)
864 int used = desired_frame->used[vpos]++;
865 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
866 desired_frame->glyphs[vpos][used] = 0;
868 bcopy (current_frame->glyphs[vpos] + end,
869 desired_frame->glyphs[vpos] + end,
870 ((current_frame->used[vpos] - end)
871 * sizeof (current_frame->glyphs[vpos])));
872 bcopy (current_frame->charstarts[vpos] + end,
873 desired_frame->charstarts[vpos] + end,
874 ((current_frame->used[vpos] - end)
875 * sizeof (current_frame->charstarts[vpos])));
876 desired_frame->used[vpos] = current_frame->used[vpos];
882 #if 0
884 /* If window w does not need to be updated and isn't the full frame wide,
885 copy all the columns that w does occupy
886 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
887 so that update_frame will not change those columns.
889 Have not been able to figure out how to use this correctly. */
891 preserve_my_columns (w)
892 struct window *w;
894 register int vpos, fin;
895 register struct frame_glyphs *l1, *l2;
896 register FRAME_PTR frame = XFRAME (w->frame);
897 int start = XFASTINT (w->left);
898 int end = XFASTINT (w->left) + XFASTINT (w->width);
899 int bot = XFASTINT (w->top) + XFASTINT (w->height);
901 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
903 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
904 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
906 if (l2->length > start && l1->length < l2->length)
908 fin = l2->length;
909 if (fin > end) fin = end;
910 while (l1->length < start)
911 l1->body[l1->length++] = ' ';
912 bcopy (l2->body + start, l1->body + start, fin - start);
913 l1->length = fin;
919 #endif
921 /* Adjust by ADJUST the charstart values in window W
922 after vpos VPOS, which counts relative to the frame
923 (not relative to W itself). */
925 void
926 adjust_window_charstarts (w, vpos, adjust)
927 struct window *w;
928 int vpos;
929 int adjust;
931 int left = XFASTINT (w->left);
932 int top = XFASTINT (w->top);
933 int right = left + window_internal_width (w);
934 int bottom = top + window_internal_height (w);
935 int i;
937 for (i = vpos + 1; i < bottom; i++)
939 int *charstart
940 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
941 int j;
942 for (j = left; j < right; j++)
943 if (charstart[j] > 0)
944 charstart[j] += adjust;
948 /* Check the charstarts values in the area of window W
949 for internal consistency. We cannot check that they are "right";
950 we can only look for something nonsensical. */
952 verify_charstarts (w)
953 struct window *w;
955 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
956 int i;
957 int top = XFASTINT (w->top);
958 int bottom = top + window_internal_height (w);
959 int left = XFASTINT (w->left);
960 int right = left + window_internal_width (w);
961 int next_line;
962 int truncate = (XINT (w->hscroll)
963 || (truncate_partial_width_windows
964 && (XFASTINT (w->width) < FRAME_WIDTH (f)))
965 || !NILP (XBUFFER (w->buffer)->truncate_lines));
967 for (i = top; i < bottom; i++)
969 int j;
970 int last;
971 int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
973 if (i != top)
975 if (truncate)
977 /* If we are truncating lines, allow a jump
978 in charstarts from one line to the next. */
979 if (charstart[left] < next_line)
980 abort ();
982 else
984 if (charstart[left] != next_line)
985 abort ();
989 for (j = left; j < right; j++)
990 if (charstart[j] > 0)
991 last = charstart[j];
992 /* Record where the next line should start. */
993 next_line = last;
994 if (BUF_ZV (XBUFFER (w->buffer)) != last)
996 /* If there's a newline between the two lines, count that. */
997 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
998 if (endchar == '\n')
999 next_line++;
1004 /* On discovering that the redisplay for a window was no good,
1005 cancel the columns of that window, so that when the window is
1006 displayed over again get_display_line will not complain. */
1008 cancel_my_columns (w)
1009 struct window *w;
1011 register int vpos;
1012 register struct frame_glyphs *desired_glyphs
1013 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
1014 register int start = XFASTINT (w->left);
1015 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
1017 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
1018 if (desired_glyphs->enable[vpos]
1019 && desired_glyphs->used[vpos] >= start)
1020 desired_glyphs->used[vpos] = start;
1023 /* These functions try to perform directly and immediately on the frame
1024 the necessary output for one change in the buffer.
1025 They may return 0 meaning nothing was done if anything is difficult,
1026 or 1 meaning the output was performed properly.
1027 They assume that the frame was up to date before the buffer
1028 change being displayed. They make various other assumptions too;
1029 see command_loop_1 where these are called. */
1032 direct_output_for_insert (g)
1033 int g;
1035 register FRAME_PTR frame = selected_frame;
1036 register struct frame_glyphs *current_frame
1037 = FRAME_CURRENT_GLYPHS (frame);
1039 #ifndef COMPILER_REGISTER_BUG
1040 register
1041 #endif /* COMPILER_REGISTER_BUG */
1042 struct window *w = XWINDOW (selected_window);
1043 #ifndef COMPILER_REGISTER_BUG
1044 register
1045 #endif /* COMPILER_REGISTER_BUG */
1046 int hpos = FRAME_CURSOR_X (frame);
1047 #ifndef COMPILER_REGISTER_BUG
1048 register
1049 #endif /* COMPILER_REGISTER_BUG */
1050 int vpos = FRAME_CURSOR_Y (frame);
1052 /* Give up if about to continue line. */
1053 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
1055 /* Avoid losing if cursor is in invisible text off left margin */
1056 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
1058 /* Give up if cursor outside window (in minibuf, probably) */
1059 || cursor_in_echo_area
1060 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1061 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
1063 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
1064 || !display_completed
1066 /* Give up if buffer appears in two places. */
1067 || buffer_shared > 1
1069 #ifdef USE_TEXT_PROPERTIES
1070 /* Intervals have already been adjusted, point is after the
1071 character that was just inserted. */
1072 /* Give up if character is invisible. */
1073 /* Give up if character has a face property.
1074 At the moment we only lose at end of line or end of buffer
1075 and only with faces that have some background */
1076 /* Instead of wasting time, give up if character has any text properties */
1077 || ! NILP (Ftext_properties_at (XFASTINT (point - 1), Qnil))
1078 #endif
1080 /* Give up if w is minibuffer and a message is being displayed there */
1081 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1082 return 0;
1085 #ifdef HAVE_X_WINDOWS
1086 int dummy;
1087 int face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point);
1088 #endif
1089 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
1090 current_frame->charstarts[vpos][hpos] = point - 1;
1091 /* Record the entry for after the newly inserted character. */
1092 current_frame->charstarts[vpos][hpos + 1] = point;
1093 adjust_window_charstarts (w, vpos, 1);
1095 unchanged_modified = MODIFF;
1096 beg_unchanged = GPT - BEG;
1097 XFASTINT (w->last_point) = point;
1098 XFASTINT (w->last_point_x) = hpos;
1099 XFASTINT (w->last_modified) = MODIFF;
1101 reassert_line_highlight (0, vpos);
1102 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
1103 fflush (stdout);
1104 ++FRAME_CURSOR_X (frame);
1105 if (hpos == current_frame->used[vpos])
1107 current_frame->used[vpos] = hpos + 1;
1108 current_frame->glyphs[vpos][hpos + 1] = 0;
1111 return 1;
1115 direct_output_forward_char (n)
1116 int n;
1118 register FRAME_PTR frame = selected_frame;
1119 register struct window *w = XWINDOW (selected_window);
1120 int position;
1121 int hpos = FRAME_CURSOR_X (frame);
1123 /* Give up if in truncated text at end of line. */
1124 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
1125 return 0;
1127 /* Avoid losing if cursor is in invisible text off left margin
1128 or about to go off either side of window. */
1129 if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
1130 && (XINT (w->hscroll) || n < 0))
1131 || (n > 0
1132 && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
1133 || cursor_in_echo_area)
1134 return 0;
1136 /* Can't use direct output if highlighting a region. */
1137 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1138 return 0;
1140 #ifdef USE_TEXT_PROPERTIES
1141 /* Don't use direct output next to an invisible character
1142 since we might need to do something special. */
1144 XFASTINT (position) = point;
1145 if (XFASTINT (position) < ZV
1146 && ! NILP (Fget_char_property (position,
1147 Qinvisible,
1148 selected_window)))
1149 return 0;
1151 XFASTINT (position) = point - 1;
1152 if (XFASTINT (position) >= BEGV
1153 && ! NILP (Fget_char_property (position,
1154 Qinvisible,
1155 selected_window)))
1156 return 0;
1157 #endif
1159 FRAME_CURSOR_X (frame) += n;
1160 XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
1161 XFASTINT (w->last_point) = point;
1162 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
1163 fflush (stdout);
1165 return 1;
1168 static void update_line ();
1170 /* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
1171 Value is nonzero if redisplay stopped due to pending input.
1172 FORCE nonzero means do not stop for pending input. */
1175 update_frame (f, force, inhibit_hairy_id)
1176 FRAME_PTR f;
1177 int force;
1178 int inhibit_hairy_id;
1180 register struct frame_glyphs *current_frame;
1181 register struct frame_glyphs *desired_frame = 0;
1182 register int i;
1183 int pause;
1184 int preempt_count = baud_rate / 2400 + 1;
1185 extern input_pending;
1186 #ifdef HAVE_X_WINDOWS
1187 register int downto, leftmost;
1188 #endif
1190 if (preempt_count <= 0)
1191 preempt_count = 1;
1193 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1195 detect_input_pending ();
1196 if (input_pending && !force)
1198 pause = 1;
1199 goto do_pause;
1202 update_begin (f);
1204 if (!line_ins_del_ok)
1205 inhibit_hairy_id = 1;
1207 /* These are separate to avoid a possible bug in the AIX C compiler. */
1208 current_frame = FRAME_CURRENT_GLYPHS (f);
1209 desired_frame = FRAME_DESIRED_GLYPHS (f);
1211 /* See if any of the desired lines are enabled; don't compute for
1212 i/d line if just want cursor motion. */
1213 for (i = 0; i < FRAME_HEIGHT (f); i++)
1214 if (desired_frame->enable[i])
1215 break;
1217 /* Try doing i/d line, if not yet inhibited. */
1218 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1219 force |= scrolling (f);
1221 /* Update the individual lines as needed. Do bottom line first. */
1223 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1224 update_line (f, FRAME_HEIGHT (f) - 1);
1226 #ifdef HAVE_X_WINDOWS
1227 if (FRAME_X_P (f))
1229 leftmost = downto = f->display.x->internal_border_width;
1230 if (desired_frame->enable[0])
1232 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1233 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
1234 = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
1235 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
1236 current_frame->top_left_x[0] = leftmost;
1237 current_frame->top_left_y[0] = downto;
1240 #endif /* HAVE_X_WINDOWS */
1242 /* Now update the rest of the lines. */
1243 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
1245 if (desired_frame->enable[i])
1247 if (FRAME_TERMCAP_P (f))
1249 /* Flush out every so many lines.
1250 Also flush out if likely to have more than 1k buffered
1251 otherwise. I'm told that some telnet connections get
1252 really screwed by more than 1k output at once. */
1253 int outq = PENDING_OUTPUT_COUNT (stdout);
1254 if (outq > 900
1255 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1257 fflush (stdout);
1258 if (preempt_count == 1)
1260 #ifdef EMACS_OUTQSIZE
1261 if (EMACS_OUTQSIZE (0, &outq) < 0)
1262 /* Probably not a tty. Ignore the error and reset
1263 * the outq count. */
1264 outq = PENDING_OUTPUT_COUNT (stdout);
1265 #endif
1266 outq *= 10;
1267 if (baud_rate <= outq && baud_rate > 0)
1268 sleep (outq / baud_rate);
1271 if ((i - 1) % preempt_count == 0)
1272 detect_input_pending ();
1275 update_line (f, i);
1276 #ifdef HAVE_X_WINDOWS
1277 if (FRAME_X_P (f))
1279 current_frame->top_left_y[i] = downto;
1280 current_frame->top_left_x[i] = leftmost;
1282 #endif /* HAVE_X_WINDOWS */
1285 #ifdef HAVE_X_WINDOWS
1286 if (FRAME_X_P (f))
1287 downto += current_frame->pix_height[i];
1288 #endif
1290 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
1292 /* Now just clean up termcap drivers and set cursor, etc. */
1293 if (!pause)
1295 if (cursor_in_echo_area
1296 && FRAME_HAS_MINIBUF_P (f))
1298 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1299 int row, col;
1301 if (cursor_in_echo_area < 0)
1303 row = top;
1304 col = 0;
1306 else
1308 /* If the minibuffer is several lines high, find the last
1309 line that has any text on it. */
1310 row = FRAME_HEIGHT (f);
1313 row--;
1314 if (current_frame->enable[row])
1315 col = current_frame->used[row];
1316 else
1317 col = 0;
1319 while (row > top && col == 0);
1321 if (col >= FRAME_WIDTH (f))
1323 col = 0;
1324 if (row < FRAME_HEIGHT (f) - 1)
1325 row++;
1329 cursor_to (row, col);
1331 else
1332 cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
1333 FRAME_WIDTH (f) - 1), 0));
1336 update_end (f);
1338 if (termscript)
1339 fflush (termscript);
1340 fflush (stdout);
1342 /* Here if output is preempted because input is detected. */
1343 do_pause:
1345 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1346 display_completed = !pause;
1348 bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
1349 return pause;
1352 /* Called when about to quit, to check for doing so
1353 at an improper time. */
1355 void
1356 quit_error_check ()
1358 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
1359 return;
1360 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
1361 abort ();
1362 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
1363 abort ();
1366 /* Decide what insert/delete line to do, and do it */
1368 extern void scrolling_1 ();
1370 scrolling (frame)
1371 FRAME_PTR frame;
1373 int unchanged_at_top, unchanged_at_bottom;
1374 int window_size;
1375 int changed_lines;
1376 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1377 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1378 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1379 register int i;
1380 int free_at_end_vpos = FRAME_HEIGHT (frame);
1381 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1382 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
1384 /* Compute hash codes of all the lines.
1385 Also calculate number of changed lines,
1386 number of unchanged lines at the beginning,
1387 and number of unchanged lines at the end. */
1389 changed_lines = 0;
1390 unchanged_at_top = 0;
1391 unchanged_at_bottom = FRAME_HEIGHT (frame);
1392 for (i = 0; i < FRAME_HEIGHT (frame); i++)
1394 /* Give up on this scrolling if some old lines are not enabled. */
1395 if (!current_frame->enable[i])
1396 return 0;
1397 old_hash[i] = line_hash_code (current_frame, i);
1398 if (! desired_frame->enable[i])
1399 new_hash[i] = old_hash[i];
1400 else
1401 new_hash[i] = line_hash_code (desired_frame, i);
1403 if (old_hash[i] != new_hash[i])
1405 changed_lines++;
1406 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
1408 else if (i == unchanged_at_top)
1409 unchanged_at_top++;
1410 draw_cost[i] = line_draw_cost (desired_frame, i);
1413 /* If changed lines are few, don't allow preemption, don't scroll. */
1414 if (changed_lines < baud_rate / 2400
1415 || unchanged_at_bottom == FRAME_HEIGHT (frame))
1416 return 1;
1418 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
1419 - unchanged_at_bottom);
1421 if (scroll_region_ok)
1422 free_at_end_vpos -= unchanged_at_bottom;
1423 else if (memory_below_frame)
1424 free_at_end_vpos = -1;
1426 /* If large window, fast terminal and few lines in common between
1427 current frame and desired frame, don't bother with i/d calc. */
1428 if (window_size >= 18 && baud_rate > 2400
1429 && (window_size >=
1430 10 * scrolling_max_lines_saved (unchanged_at_top,
1431 FRAME_HEIGHT (frame) - unchanged_at_bottom,
1432 old_hash, new_hash, draw_cost)))
1433 return 0;
1435 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
1436 draw_cost + unchanged_at_top - 1,
1437 old_hash + unchanged_at_top - 1,
1438 new_hash + unchanged_at_top - 1,
1439 free_at_end_vpos - unchanged_at_top);
1441 return 0;
1444 /* Return the offset in its buffer of the character at location col, line
1445 in the given window. */
1447 buffer_posn_from_coords (window, col, line)
1448 struct window *window;
1449 int col, line;
1451 int hscroll = XINT (window->hscroll);
1452 int window_left = XFASTINT (window->left);
1454 /* The actual width of the window is window->width less one for the
1455 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1456 window. */
1457 int window_width = window_internal_width (window) - 1;
1459 int startp = marker_position (window->start);
1461 /* Since compute_motion will only operate on the current buffer,
1462 we need to save the old one and restore it when we're done. */
1463 struct buffer *old_current_buffer = current_buffer;
1464 struct position *posn;
1466 current_buffer = XBUFFER (window->buffer);
1468 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1469 (window->frame))->bufp to avoid scanning from the very top of
1470 the window, but it isn't maintained correctly, and I'm not even
1471 sure I will keep it. */
1472 posn = compute_motion (startp, 0,
1473 (window == XWINDOW (minibuf_window) && startp == 1
1474 ? minibuf_prompt_width : 0)
1475 + (hscroll ? 1 - hscroll : 0),
1476 ZV, line, col,
1477 window_width, hscroll, 0, window);
1479 current_buffer = old_current_buffer;
1481 /* compute_motion considers frame points past the end of a line
1482 to be *after* the newline, i.e. at the start of the next line.
1483 This is reasonable, but not really what we want. So if the
1484 result is on a line below LINE, back it up one character. */
1485 if (posn->vpos > line)
1486 return posn->bufpos - 1;
1487 else
1488 return posn->bufpos;
1491 static int
1492 count_blanks (r)
1493 register GLYPH *r;
1495 register GLYPH *p = r;
1496 while (*p++ == SPACEGLYPH);
1497 return p - r - 1;
1500 static int
1501 count_match (str1, str2)
1502 GLYPH *str1, *str2;
1504 register GLYPH *p1 = str1;
1505 register GLYPH *p2 = str2;
1506 while (*p1++ == *p2++);
1507 return p1 - str1 - 1;
1510 /* Char insertion/deletion cost vector, from term.c */
1511 extern int *char_ins_del_vector;
1513 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
1515 static void
1516 update_line (frame, vpos)
1517 register FRAME_PTR frame;
1518 int vpos;
1520 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1521 int *temp1;
1522 int tem;
1523 int osp, nsp, begmatch, endmatch, olen, nlen;
1524 int save;
1525 register struct frame_glyphs *current_frame
1526 = FRAME_CURRENT_GLYPHS (frame);
1527 register struct frame_glyphs *desired_frame
1528 = FRAME_DESIRED_GLYPHS (frame);
1530 if (desired_frame->highlight[vpos]
1531 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
1533 change_line_highlight (desired_frame->highlight[vpos], vpos,
1534 (current_frame->enable[vpos] ?
1535 current_frame->used[vpos] : 0));
1536 current_frame->enable[vpos] = 0;
1538 else
1539 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
1541 if (! current_frame->enable[vpos])
1543 olen = 0;
1545 else
1547 obody = current_frame->glyphs[vpos];
1548 olen = current_frame->used[vpos];
1549 if (! current_frame->highlight[vpos])
1551 if (!must_write_spaces)
1552 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1553 olen--;
1555 else
1557 /* For an inverse-video line, remember we gave it
1558 spaces all the way to the frame edge
1559 so that the reverse video extends all the way across. */
1561 while (olen < FRAME_WIDTH (frame) - 1)
1562 obody[olen++] = SPACEGLYPH;
1566 /* One way or another, this will enable the line being updated. */
1567 current_frame->enable[vpos] = 1;
1568 current_frame->used[vpos] = desired_frame->used[vpos];
1569 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1570 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
1572 #ifdef HAVE_X_WINDOWS
1573 if (FRAME_X_P (frame))
1575 current_frame->pix_width[vpos]
1576 = current_frame->used[vpos]
1577 * FONT_WIDTH (frame->display.x->font);
1578 current_frame->pix_height[vpos]
1579 = frame->display.x->line_height;
1581 #endif /* HAVE_X_WINDOWS */
1583 if (!desired_frame->enable[vpos])
1585 nlen = 0;
1586 goto just_erase;
1589 nbody = desired_frame->glyphs[vpos];
1590 nlen = desired_frame->used[vpos];
1592 /* Pretend trailing spaces are not there at all,
1593 unless for one reason or another we must write all spaces. */
1594 if (! desired_frame->highlight[vpos])
1596 if (!must_write_spaces)
1597 /* We know that the previous character byte contains 0. */
1598 while (nbody[nlen - 1] == SPACEGLYPH)
1599 nlen--;
1601 else
1603 /* For an inverse-video line, give it extra trailing spaces
1604 all the way to the frame edge
1605 so that the reverse video extends all the way across. */
1607 while (nlen < FRAME_WIDTH (frame) - 1)
1608 nbody[nlen++] = SPACEGLYPH;
1611 /* If there's no i/d char, quickly do the best we can without it. */
1612 if (!char_ins_del_ok)
1614 int i,j;
1616 #if 0
1617 if (FRAME_X_P (frame))
1619 /* Under X, erase everything we are going to rewrite,
1620 and rewrite everything from the first char that's changed.
1621 This is part of supporting fonts like Courier
1622 whose chars can overlap outside the char width. */
1623 for (i = 0; i < nlen; i++)
1624 if (i >= olen || nbody[i] != obody[i])
1625 break;
1627 cursor_to (vpos, i);
1628 if (i != olen)
1629 clear_end_of_line (olen);
1630 write_glyphs (nbody + i, nlen - i);
1632 else
1634 #endif /* 0 */
1635 for (i = 0; i < nlen; i++)
1637 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1639 cursor_to (vpos, i);
1640 for (j = 1; (i + j < nlen &&
1641 (i + j >= olen || nbody[i+j] != obody[i+j]));
1642 j++);
1644 /* Output this run of non-matching chars. */
1645 write_glyphs (nbody + i, j);
1646 i += j - 1;
1648 /* Now find the next non-match. */
1652 /* Clear the rest of the line, or the non-clear part of it. */
1653 if (olen > nlen)
1655 cursor_to (vpos, nlen);
1656 clear_end_of_line (olen);
1659 /* Exchange contents between current_frame and new_frame. */
1660 temp = desired_frame->glyphs[vpos];
1661 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1662 current_frame->glyphs[vpos] = temp;
1664 /* Exchange charstarts between current_frame and new_frame. */
1665 temp1 = desired_frame->charstarts[vpos];
1666 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1667 current_frame->charstarts[vpos] = temp1;
1669 return;
1672 if (!olen)
1674 nsp = (must_write_spaces || desired_frame->highlight[vpos])
1675 ? 0 : count_blanks (nbody);
1676 if (nlen > nsp)
1678 cursor_to (vpos, nsp);
1679 write_glyphs (nbody + nsp, nlen - nsp);
1682 /* Exchange contents between current_frame and new_frame. */
1683 temp = desired_frame->glyphs[vpos];
1684 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1685 current_frame->glyphs[vpos] = temp;
1687 /* Exchange charstarts between current_frame and new_frame. */
1688 temp1 = desired_frame->charstarts[vpos];
1689 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1690 current_frame->charstarts[vpos] = temp1;
1692 return;
1695 obody[olen] = 1;
1696 save = nbody[nlen];
1697 nbody[nlen] = 0;
1699 /* Compute number of leading blanks in old and new contents. */
1700 osp = count_blanks (obody);
1701 if (!desired_frame->highlight[vpos])
1702 nsp = count_blanks (nbody);
1703 else
1704 nsp = 0;
1706 /* Compute number of matching chars starting with first nonblank. */
1707 begmatch = count_match (obody + osp, nbody + nsp);
1709 /* Spaces in new match implicit space past the end of old. */
1710 /* A bug causing this to be a no-op was fixed in 18.29. */
1711 if (!must_write_spaces && osp + begmatch == olen)
1713 np1 = nbody + nsp;
1714 while (np1[begmatch] == SPACEGLYPH)
1715 begmatch++;
1718 /* Avoid doing insert/delete char
1719 just cause number of leading spaces differs
1720 when the following text does not match. */
1721 if (begmatch == 0 && osp != nsp)
1722 osp = nsp = min (osp, nsp);
1724 /* Find matching characters at end of line */
1725 op1 = obody + olen;
1726 np1 = nbody + nlen;
1727 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1728 while (op1 > op2 && op1[-1] == np1[-1])
1730 op1--;
1731 np1--;
1733 endmatch = obody + olen - op1;
1735 /* Put correct value back in nbody[nlen].
1736 This is important because direct_output_for_insert
1737 can write into the line at a later point.
1738 If this screws up the zero at the end of the line, re-establish it. */
1739 nbody[nlen] = save;
1740 obody[olen] = 0;
1742 /* tem gets the distance to insert or delete.
1743 endmatch is how many characters we save by doing so.
1744 Is it worth it? */
1746 tem = (nlen - nsp) - (olen - osp);
1747 if (endmatch && tem
1748 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
1749 endmatch = 0;
1751 /* nsp - osp is the distance to insert or delete.
1752 If that is nonzero, begmatch is known to be nonzero also.
1753 begmatch + endmatch is how much we save by doing the ins/del.
1754 Is it worth it? */
1756 if (nsp != osp
1757 && (!char_ins_del_ok
1758 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
1760 begmatch = 0;
1761 endmatch = 0;
1762 osp = nsp = min (osp, nsp);
1765 /* Now go through the line, inserting, writing and
1766 deleting as appropriate. */
1768 if (osp > nsp)
1770 cursor_to (vpos, nsp);
1771 delete_glyphs (osp - nsp);
1773 else if (nsp > osp)
1775 /* If going to delete chars later in line
1776 and insert earlier in the line,
1777 must delete first to avoid losing data in the insert */
1778 if (endmatch && nlen < olen + nsp - osp)
1780 cursor_to (vpos, nlen - endmatch + osp - nsp);
1781 delete_glyphs (olen + nsp - osp - nlen);
1782 olen = nlen - (nsp - osp);
1784 cursor_to (vpos, osp);
1785 insert_glyphs ((char *)0, nsp - osp);
1787 olen += nsp - osp;
1789 tem = nsp + begmatch + endmatch;
1790 if (nlen != tem || olen != tem)
1792 cursor_to (vpos, nsp + begmatch);
1793 if (!endmatch || nlen == olen)
1795 /* If new text being written reaches right margin,
1796 there is no need to do clear-to-eol at the end.
1797 (and it would not be safe, since cursor is not
1798 going to be "at the margin" after the text is done) */
1799 if (nlen == FRAME_WIDTH (frame))
1800 olen = 0;
1801 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1803 #ifdef obsolete
1805 /* the following code loses disastrously if tem == nlen.
1806 Rather than trying to fix that case, I am trying the simpler
1807 solution found above. */
1809 /* If the text reaches to the right margin,
1810 it will lose one way or another (depending on AutoWrap)
1811 to clear to end of line after outputting all the text.
1812 So pause with one character to go and clear the line then. */
1813 if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
1815 /* endmatch must be zero, and tem must equal nsp + begmatch */
1816 write_glyphs (nbody + tem, nlen - tem - 1);
1817 clear_end_of_line (olen);
1818 olen = 0; /* Don't let it be cleared again later */
1819 write_glyphs (nbody + nlen - 1, 1);
1821 else
1822 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1823 #endif /* OBSOLETE */
1826 else if (nlen > olen)
1828 write_glyphs (nbody + nsp + begmatch, olen - tem);
1829 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1830 olen = nlen;
1832 else if (olen > nlen)
1834 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1835 delete_glyphs (olen - nlen);
1836 olen = nlen;
1840 just_erase:
1841 /* If any unerased characters remain after the new line, erase them. */
1842 if (olen > nlen)
1844 cursor_to (vpos, nlen);
1845 clear_end_of_line (olen);
1848 /* Exchange contents between current_frame and new_frame. */
1849 temp = desired_frame->glyphs[vpos];
1850 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1851 current_frame->glyphs[vpos] = temp;
1853 /* Exchange charstarts between current_frame and new_frame. */
1854 temp1 = desired_frame->charstarts[vpos];
1855 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1856 current_frame->charstarts[vpos] = temp1;
1859 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1860 1, 1, "FOpen termscript file: ",
1861 "Start writing all terminal output to FILE as well as the terminal.\n\
1862 FILE = nil means just close any termscript file currently open.")
1863 (file)
1864 Lisp_Object file;
1866 if (termscript != 0) fclose (termscript);
1867 termscript = 0;
1869 if (! NILP (file))
1871 file = Fexpand_file_name (file, Qnil);
1872 termscript = fopen (XSTRING (file)->data, "w");
1873 if (termscript == 0)
1874 report_file_error ("Opening termscript", Fcons (file, Qnil));
1876 return Qnil;
1880 #ifdef SIGWINCH
1881 SIGTYPE
1882 window_change_signal ()
1884 int width, height;
1885 extern int errno;
1886 int old_errno = errno;
1888 get_frame_size (&width, &height);
1890 /* The frame size change obviously applies to a termcap-controlled
1891 frame. Find such a frame in the list, and assume it's the only
1892 one (since the redisplay code always writes to stdout, not a
1893 FILE * specified in the frame structure). Record the new size,
1894 but don't reallocate the data structures now. Let that be done
1895 later outside of the signal handler. */
1898 Lisp_Object tail, frame;
1900 FOR_EACH_FRAME (tail, frame)
1902 if (FRAME_TERMCAP_P (XFRAME (frame)))
1904 change_frame_size (XFRAME (frame), height, width, 0, 1);
1905 break;
1910 signal (SIGWINCH, window_change_signal);
1911 errno = old_errno;
1913 #endif /* SIGWINCH */
1916 /* Do any change in frame size that was requested by a signal. */
1918 do_pending_window_change ()
1920 /* If window_change_signal should have run before, run it now. */
1921 while (delayed_size_change)
1923 Lisp_Object tail, frame;
1925 delayed_size_change = 0;
1927 FOR_EACH_FRAME (tail, frame)
1929 FRAME_PTR f = XFRAME (frame);
1931 int height = FRAME_NEW_HEIGHT (f);
1932 int width = FRAME_NEW_WIDTH (f);
1934 if (height != 0 || width != 0)
1935 change_frame_size (f, height, width, 0, 0);
1941 /* Change the frame height and/or width. Values may be given as zero to
1942 indicate no change is to take place.
1944 If DELAY is non-zero, then assume we're being called from a signal
1945 handler, and queue the change for later - perhaps the next
1946 redisplay. Since this tries to resize windows, we can't call it
1947 from a signal handler. */
1949 change_frame_size (frame, newheight, newwidth, pretend, delay)
1950 register FRAME_PTR frame;
1951 int newheight, newwidth, pretend;
1953 /* If we can't deal with the change now, queue it for later. */
1954 if (delay)
1956 FRAME_NEW_HEIGHT (frame) = newheight;
1957 FRAME_NEW_WIDTH (frame) = newwidth;
1958 delayed_size_change = 1;
1959 return;
1962 /* This size-change overrides any pending one for this frame. */
1963 FRAME_NEW_HEIGHT (frame) = 0;
1964 FRAME_NEW_WIDTH (frame) = 0;
1966 /* If an argument is zero, set it to the current value. */
1967 newheight || (newheight = FRAME_HEIGHT (frame));
1968 newwidth || (newwidth = FRAME_WIDTH (frame));
1970 /* Round up to the smallest acceptable size. */
1971 check_frame_size (frame, &newheight, &newwidth);
1973 /* If we're not changing the frame size, quit now. */
1974 if (newheight == FRAME_HEIGHT (frame)
1975 && newwidth == FRAME_WIDTH (frame))
1976 return;
1978 if (newheight != FRAME_HEIGHT (frame))
1980 if (FRAME_HAS_MINIBUF_P (frame)
1981 && ! FRAME_MINIBUF_ONLY_P (frame))
1983 /* Frame has both root and minibuffer. */
1984 set_window_height (FRAME_ROOT_WINDOW (frame),
1985 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
1986 XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
1987 = newheight - 1;
1988 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
1990 else
1991 /* Frame has just one top-level window. */
1992 set_window_height (FRAME_ROOT_WINDOW (frame),
1993 newheight - FRAME_MENU_BAR_LINES (frame), 0);
1995 if (FRAME_TERMCAP_P (frame) && !pretend)
1996 FrameRows = newheight;
1998 #if 0
1999 if (frame->output_method == output_termcap)
2001 frame_height = newheight;
2002 if (!pretend)
2003 FrameRows = newheight;
2005 #endif
2008 if (newwidth != FRAME_WIDTH (frame))
2010 set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
2011 if (FRAME_HAS_MINIBUF_P (frame))
2012 set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
2014 if (FRAME_TERMCAP_P (frame) && !pretend)
2015 FrameCols = newwidth;
2016 #if 0
2017 if (frame->output_method == output_termcap)
2019 frame_width = newwidth;
2020 if (!pretend)
2021 FrameCols = newwidth;
2023 #endif
2026 FRAME_HEIGHT (frame) = newheight;
2027 FRAME_WIDTH (frame) = newwidth;
2029 remake_frame_glyphs (frame);
2030 calculate_costs (frame);
2033 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2034 Ssend_string_to_terminal, 1, 1, 0,
2035 "Send STRING to the terminal without alteration.\n\
2036 Control characters in STRING will have terminal-dependent effects.")
2037 (str)
2038 Lisp_Object str;
2040 CHECK_STRING (str, 0);
2041 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
2042 fflush (stdout);
2043 if (termscript)
2045 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
2046 fflush (termscript);
2048 return Qnil;
2051 DEFUN ("ding", Fding, Sding, 0, 1, 0,
2052 "Beep, or flash the screen.\n\
2053 Also, unless an argument is given,\n\
2054 terminate any keyboard macro currently executing.")
2055 (arg)
2056 Lisp_Object arg;
2058 if (!NILP (arg))
2060 if (noninteractive)
2061 putchar (07);
2062 else
2063 ring_bell ();
2064 fflush (stdout);
2066 else
2067 bitch_at_user ();
2069 return Qnil;
2072 bitch_at_user ()
2074 if (noninteractive)
2075 putchar (07);
2076 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2077 error ("Keyboard macro terminated by a command ringing the bell");
2078 else
2079 ring_bell ();
2080 fflush (stdout);
2083 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
2084 "Pause, without updating display, for SECONDS seconds.\n\
2085 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2086 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2087 additional wait period, in milliseconds; this may be useful if your\n\
2088 Emacs was built without floating point support.\n\
2089 \(Not all operating systems support waiting for a fraction of a second.)")
2090 (seconds, milliseconds)
2091 Lisp_Object seconds, milliseconds;
2093 int sec, usec;
2095 if (NILP (milliseconds))
2096 XSET (milliseconds, Lisp_Int, 0);
2097 else
2098 CHECK_NUMBER (milliseconds, 1);
2099 usec = XINT (milliseconds) * 1000;
2101 #ifdef LISP_FLOAT_TYPE
2103 double duration = extract_float (seconds);
2104 sec = (int) duration;
2105 usec += (duration - sec) * 1000000;
2107 #else
2108 CHECK_NUMBER (seconds, 0);
2109 sec = XINT (seconds);
2110 #endif
2112 #ifndef EMACS_HAS_USECS
2113 if (sec == 0 && usec != 0)
2114 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
2115 #endif
2117 /* Assure that 0 <= usec < 1000000. */
2118 if (usec < 0)
2120 /* We can't rely on the rounding being correct if user is negative. */
2121 if (-1000000 < usec)
2122 sec--, usec += 1000000;
2123 else
2124 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
2126 else
2127 sec += usec / 1000000, usec %= 1000000;
2129 if (sec <= 0)
2130 return Qnil;
2133 Lisp_Object zero;
2135 XFASTINT (zero) = 0;
2136 wait_reading_process_input (sec, usec, zero, 0);
2139 /* We should always have wait_reading_process_input; we have a dummy
2140 implementation for systems which don't support subprocesses. */
2141 #if 0
2142 /* No wait_reading_process_input */
2143 immediate_quit = 1;
2144 QUIT;
2146 #ifdef VMS
2147 sys_sleep (sec);
2148 #else /* not VMS */
2149 /* The reason this is done this way
2150 (rather than defined (H_S) && defined (H_T))
2151 is because the VMS preprocessor doesn't grok `defined' */
2152 #ifdef HAVE_SELECT
2153 EMACS_GET_TIME (end_time);
2154 EMACS_SET_SECS_USECS (timeout, sec, usec);
2155 EMACS_ADD_TIME (end_time, end_time, timeout);
2157 while (1)
2159 EMACS_GET_TIME (timeout);
2160 EMACS_SUB_TIME (timeout, end_time, timeout);
2161 if (EMACS_TIME_NEG_P (timeout)
2162 || !select (1, 0, 0, 0, &timeout))
2163 break;
2165 #else /* not HAVE_SELECT */
2166 sleep (sec);
2167 #endif /* HAVE_SELECT */
2168 #endif /* not VMS */
2170 immediate_quit = 0;
2171 #endif /* no subprocesses */
2173 return Qnil;
2176 /* This is just like wait_reading_process_input, except that
2177 it does the redisplay.
2179 It's also much like Fsit_for, except that it can be used for
2180 waiting for input as well. One differnce is that sit_for
2181 does not call prepare_menu_bars; Fsit_for does call that. */
2183 Lisp_Object
2184 sit_for (sec, usec, reading, display)
2185 int sec, usec, reading, display;
2187 Lisp_Object read_kbd;
2189 if (detect_input_pending ())
2190 return Qnil;
2192 if (display)
2193 redisplay_preserve_echo_area ();
2195 if (sec == 0 && usec == 0)
2196 return Qt;
2198 #ifdef SIGIO
2199 gobble_input (0);
2200 #endif
2202 XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
2203 wait_reading_process_input (sec, usec, read_kbd, display);
2206 /* wait_reading_process_input should always be available now; it is
2207 simulated in a simple way on systems that don't support
2208 subprocesses. */
2209 #if 0
2210 /* No wait_reading_process_input available. */
2211 immediate_quit = 1;
2212 QUIT;
2214 waitchannels = 1;
2215 #ifdef VMS
2216 input_wait_timeout (XINT (arg));
2217 #else /* not VMS */
2218 #ifndef HAVE_TIMEVAL
2219 timeout_sec = sec;
2220 select (1, &waitchannels, 0, 0, &timeout_sec);
2221 #else /* HAVE_TIMEVAL */
2222 timeout.tv_sec = sec;
2223 timeout.tv_usec = usec;
2224 select (1, &waitchannels, 0, 0, &timeout);
2225 #endif /* HAVE_TIMEVAL */
2226 #endif /* not VMS */
2228 immediate_quit = 0;
2229 #endif
2231 return detect_input_pending () ? Qnil : Qt;
2234 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
2235 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
2236 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2237 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2238 additional wait period, in milliseconds; this may be useful if your\n\
2239 Emacs was built without floating point support.\n\
2240 \(Not all operating systems support waiting for a fraction of a second.)\n\
2241 Optional third arg non-nil means don't redisplay, just wait for input.\n\
2242 Redisplay is preempted as always if input arrives, and does not happen\n\
2243 if input is available before it starts.\n\
2244 Value is t if waited the full time with no input arriving.")
2245 (seconds, milliseconds, nodisp)
2246 Lisp_Object seconds, milliseconds, nodisp;
2248 int sec, usec;
2250 if (NILP (milliseconds))
2251 XSET (milliseconds, Lisp_Int, 0);
2252 else
2253 CHECK_NUMBER (milliseconds, 1);
2254 usec = XINT (milliseconds) * 1000;
2256 #ifdef LISP_FLOAT_TYPE
2258 double duration = extract_float (seconds);
2259 sec = (int) duration;
2260 usec += (duration - sec) * 1000000;
2262 #else
2263 CHECK_NUMBER (seconds, 0);
2264 sec = XINT (seconds);
2265 #endif
2267 #ifndef EMACS_HAS_USECS
2268 if (usec != 0 && sec == 0)
2269 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
2270 #endif
2272 if (NILP (nodisp))
2273 prepare_menu_bars ();
2274 return sit_for (sec, usec, 0, NILP (nodisp));
2277 char *terminal_type;
2279 /* Initialization done when Emacs fork is started, before doing stty. */
2280 /* Determine terminal type and set terminal_driver */
2281 /* Then invoke its decoding routine to set up variables
2282 in the terminal package */
2284 init_display ()
2286 #ifdef HAVE_X_WINDOWS
2287 extern int display_arg;
2288 #endif
2290 meta_key = 0;
2291 inverse_video = 0;
2292 cursor_in_echo_area = 0;
2293 terminal_type = (char *) 0;
2295 /* Now is the time to initialize this; it's used by init_sys_modes
2296 during startup. */
2297 Vwindow_system = Qnil;
2299 /* If the user wants to use a window system, we shouldn't bother
2300 initializing the terminal. This is especially important when the
2301 terminal is so dumb that emacs gives up before and doesn't bother
2302 using the window system.
2304 If the DISPLAY environment variable is set, try to use X, and die
2305 with an error message if that doesn't work. */
2307 #ifdef HAVE_X_WINDOWS
2308 if (! display_arg)
2310 #ifdef VMS
2311 display_arg = (getenv ("DECW$DISPLAY") != 0);
2312 #else
2313 display_arg = (getenv ("DISPLAY") != 0);
2314 #endif
2317 if (!inhibit_window_system && display_arg)
2319 Vwindow_system = intern ("x");
2320 #ifdef HAVE_X11
2321 Vwindow_system_version = make_number (11);
2322 #else
2323 Vwindow_system_version = make_number (10);
2324 #endif
2325 return;
2327 #endif /* HAVE_X_WINDOWS */
2329 /* If no window system has been specified, try to use the terminal. */
2330 if (! isatty (0))
2332 fprintf (stderr, "emacs: standard input is not a tty\n");
2333 exit (1);
2336 /* Look at the TERM variable */
2337 terminal_type = (char *) getenv ("TERM");
2338 if (!terminal_type)
2340 #ifdef VMS
2341 fprintf (stderr, "Please specify your terminal type.\n\
2342 For types defined in VMS, use set term /device=TYPE.\n\
2343 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2344 \(The quotation marks are necessary since terminal types are lower case.)\n");
2345 #else
2346 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2347 #endif
2348 exit (1);
2351 #ifdef VMS
2352 /* VMS DCL tends to upcase things, so downcase term type.
2353 Hardly any uppercase letters in terminal types; should be none. */
2355 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2356 char *p;
2358 strcpy (new, terminal_type);
2360 for (p = new; *p; p++)
2361 if (isupper (*p))
2362 *p = tolower (*p);
2364 terminal_type = new;
2366 #endif
2368 term_init (terminal_type);
2370 remake_frame_glyphs (selected_frame);
2371 calculate_costs (selected_frame);
2373 /* X and Y coordinates of the cursor between updates. */
2374 FRAME_CURSOR_X (selected_frame) = 0;
2375 FRAME_CURSOR_Y (selected_frame) = 0;
2377 #ifdef SIGWINCH
2378 #ifndef CANNOT_DUMP
2379 if (initialized)
2380 #endif /* CANNOT_DUMP */
2381 signal (SIGWINCH, window_change_signal);
2382 #endif /* SIGWINCH */
2385 syms_of_display ()
2387 #ifdef MULTI_FRAME
2388 defsubr (&Sredraw_frame);
2389 #endif
2390 defsubr (&Sredraw_display);
2391 defsubr (&Sopen_termscript);
2392 defsubr (&Sding);
2393 defsubr (&Ssit_for);
2394 defsubr (&Ssleep_for);
2395 defsubr (&Ssend_string_to_terminal);
2397 DEFVAR_INT ("baud-rate", &baud_rate,
2398 "The output baud rate of the terminal.\n\
2399 On most systems, changing this value will affect the amount of padding\n\
2400 and the other strategic decisions made during redisplay.");
2401 DEFVAR_BOOL ("inverse-video", &inverse_video,
2402 "*Non-nil means invert the entire frame display.\n\
2403 This means everything is in inverse video which otherwise would not be.");
2404 DEFVAR_BOOL ("visible-bell", &visible_bell,
2405 "*Non-nil means try to flash the frame to represent a bell.");
2406 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
2407 "*Non-nil means no need to redraw entire frame after suspending.\n\
2408 A non-nil value is useful if the terminal can automatically preserve\n\
2409 Emacs's frame display when you reenter Emacs.\n\
2410 It is up to you to set this variable if your terminal can do that.");
2411 DEFVAR_LISP ("window-system", &Vwindow_system,
2412 "A symbol naming the window-system under which Emacs is running\n\
2413 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
2414 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2415 "The version number of the window system in use.\n\
2416 For X windows, this is 10 or 11.");
2417 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2418 "Non-nil means put cursor in minibuffer, at end of any message there.");
2419 DEFVAR_LISP ("glyph-table", &Vglyph_table,
2420 "Table defining how to output a glyph code to the frame.\n\
2421 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2422 Each element can be:\n\
2423 integer: a glyph code which this glyph is an alias for.\n\
2424 string: output this glyph using that string (not impl. in X windows).\n\
2425 nil: this glyph mod 256 is char code to output,\n\
2426 and this glyph / 256 is face code for X windows (see `face-id').");
2427 Vglyph_table = Qnil;
2429 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2430 "Display table to use for buffers that specify none.\n\
2431 See `buffer-display-table' for more information.");
2432 Vstandard_display_table = Qnil;
2434 /* Initialize `window-system', unless init_display already decided it. */
2435 #ifdef CANNOT_DUMP
2436 if (noninteractive)
2437 #endif
2439 Vwindow_system = Qnil;
2440 Vwindow_system_version = Qnil;