(cal-tex-cursor-filofax-week): Renamed from cal-tex-cursor-week6.
[emacs.git] / src / dispnew.c
blobe9978749e2a47966702b591e32a94010656db85e
1 /* Updating of data structures for redisplay.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 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 /* cm.h must come after dispextern.h on Windows. */
33 #include "dispextern.h"
34 #include "cm.h"
35 #include "buffer.h"
36 #include "frame.h"
37 #include "window.h"
38 #include "commands.h"
39 #include "disptab.h"
40 #include "indent.h"
41 #include "intervals.h"
43 #include "systty.h"
44 #include "syssignal.h"
46 #ifdef HAVE_X_WINDOWS
47 #include "xterm.h"
48 #endif /* HAVE_X_WINDOWS */
50 #ifdef HAVE_NTGUI
51 #include "w32term.h"
52 #endif /* HAVE_NTGUI */
54 /* Include systime.h after xterm.h to avoid double inclusion of time.h. */
55 #include "systime.h"
57 #include <errno.h>
59 #define max(a, b) ((a) > (b) ? (a) : (b))
60 #define min(a, b) ((a) < (b) ? (a) : (b))
62 /* Get number of chars of output now in the buffer of a stdio stream.
63 This ought to be built in in stdio, but it isn't.
64 Some s- files override this because their stdio internals differ. */
65 #ifdef __GNU_LIBRARY__
66 /* The s- file might have overridden the definition with one that works for
67 the system's C library. But we are using the GNU C library, so this is
68 the right definition for every system. */
69 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
70 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
71 #else
72 #undef PENDING_OUTPUT_COUNT
73 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
74 #endif
75 #else /* not __GNU_LIBRARY__ */
76 #ifndef PENDING_OUTPUT_COUNT
77 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
78 #endif
79 #endif
81 static void change_frame_size_1 ();
83 /* Nonzero upon entry to redisplay means do not assume anything about
84 current contents of actual terminal frame; clear and redraw it. */
86 int frame_garbaged;
88 /* Nonzero means last display completed. Zero means it was preempted. */
90 int display_completed;
92 /* Lisp variable visible-bell; enables use of screen-flash
93 instead of audible bell. */
95 int visible_bell;
97 /* Invert the color of the whole frame, at a low level. */
99 int inverse_video;
101 /* Line speed of the terminal. */
103 int baud_rate;
105 /* nil or a symbol naming the window system under which emacs is
106 running ('x is the only current possibility). */
108 Lisp_Object Vwindow_system;
110 /* Version number of X windows: 10, 11 or nil. */
111 Lisp_Object Vwindow_system_version;
113 /* Vector of glyph definitions. Indexed by glyph number,
114 the contents are a string which is how to output the glyph.
116 If Vglyph_table is nil, a glyph is output by using its low 8 bits
117 as a character code. */
119 Lisp_Object Vglyph_table;
121 /* Display table to use for vectors that don't specify their own. */
123 Lisp_Object Vstandard_display_table;
125 /* Nonzero means reading single-character input with prompt
126 so put cursor on minibuffer after the prompt.
127 positive means at end of text in echo area;
128 negative means at beginning of line. */
129 int cursor_in_echo_area;
131 Lisp_Object Qdisplay_table;
133 /* The currently selected frame.
134 In a single-frame version, this variable always holds the address of
135 the_only_frame. */
137 FRAME_PTR selected_frame;
139 /* A frame which is not just a minibuffer, or 0 if there are no such
140 frames. This is usually the most recent such frame that was
141 selected. In a single-frame version, this variable always holds
142 the address of the_only_frame. */
143 FRAME_PTR last_nonminibuf_frame;
145 /* In a single-frame version, the information that would otherwise
146 exist inside frame objects lives in the following structure instead.
148 NOTE: the_only_frame is not checked for garbage collection; don't
149 store collectible objects in any of its fields!
151 You're not/The only frame in town/... */
153 #ifndef MULTI_FRAME
154 struct frame the_only_frame;
155 #endif
157 /* This is a vector, made larger whenever it isn't large enough,
158 which is used inside `update_frame' to hold the old contents
159 of the FRAME_PHYS_LINES of the frame being updated. */
160 struct frame_glyphs **ophys_lines;
161 /* Length of vector currently allocated. */
162 int ophys_lines_length;
164 FILE *termscript; /* Stdio stream being used for copy of all output. */
166 struct cm Wcm; /* Structure for info on cursor positioning */
168 extern short ospeed; /* Output speed (from sg_ospeed) */
170 int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
172 #ifdef MULTI_FRAME
174 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
175 "Clear frame FRAME and output again what is supposed to appear on it.")
176 (frame)
177 Lisp_Object frame;
179 FRAME_PTR f;
181 CHECK_LIVE_FRAME (frame, 0);
182 f = XFRAME (frame);
183 update_begin (f);
184 /* set_terminal_modes (); */
185 clear_frame ();
186 clear_frame_records (f);
187 update_end (f);
188 fflush (stdout);
189 windows_or_buffers_changed++;
190 /* Mark all windows as INaccurate,
191 so that every window will have its redisplay done. */
192 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
193 f->garbaged = 0;
194 return Qnil;
197 redraw_frame (f)
198 FRAME_PTR f;
200 Lisp_Object frame;
201 XSETFRAME (frame, f);
202 Fredraw_frame (frame);
205 #else
207 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
208 /* Don't confuse make-docfile by having two doc strings for this function.
209 make-docfile does not pay attention to #if, for good reason! */
211 (frame)
212 Lisp_Object frame;
214 update_begin (0);
215 set_terminal_modes ();
216 clear_frame ();
217 update_end (0);
218 fflush (stdout);
219 clear_frame_records (0);
220 windows_or_buffers_changed++;
221 /* Mark all windows as INaccurate,
222 so that every window will have its redisplay done. */
223 mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
224 return Qnil;
227 #endif
229 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
230 "Clear and redisplay all visible frames.")
233 Lisp_Object tail, frame;
235 FOR_EACH_FRAME (tail, frame)
236 if (FRAME_VISIBLE_P (XFRAME (frame)))
237 Fredraw_frame (frame);
239 return Qnil;
242 /* This is used when frame_garbaged is set.
243 Redraw the individual frames marked as garbaged. */
245 void
246 redraw_garbaged_frames ()
248 Lisp_Object tail, frame;
250 FOR_EACH_FRAME (tail, frame)
251 if (FRAME_VISIBLE_P (XFRAME (frame))
252 && FRAME_GARBAGED_P (XFRAME (frame)))
253 Fredraw_frame (frame);
257 static struct frame_glyphs *
258 make_frame_glyphs (frame, empty)
259 register FRAME_PTR frame;
260 int empty;
262 register int i;
263 register width = FRAME_WIDTH (frame);
264 register height = FRAME_HEIGHT (frame);
265 register struct frame_glyphs *new
266 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
268 SET_GLYPHS_FRAME (new, frame);
269 new->height = height;
270 new->width = width;
271 new->used = (int *) xmalloc (height * sizeof (int));
272 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
273 new->charstarts = (int **) xmalloc (height * sizeof (int *));
274 new->highlight = (char *) xmalloc (height * sizeof (char));
275 new->enable = (char *) xmalloc (height * sizeof (char));
276 bzero (new->enable, height * sizeof (char));
277 new->bufp = (int *) xmalloc (height * sizeof (int));
279 #ifdef HAVE_WINDOW_SYSTEM
280 if (FRAME_WINDOW_P (frame))
282 new->top_left_x = (short *) xmalloc (height * sizeof (short));
283 new->top_left_y = (short *) xmalloc (height * sizeof (short));
284 new->pix_width = (short *) xmalloc (height * sizeof (short));
285 new->pix_height = (short *) xmalloc (height * sizeof (short));
286 new->max_ascent = (short *) xmalloc (height * sizeof (short));
288 #endif /* HAVE_WINDOW_SYSTEM */
290 if (empty)
292 /* Make the buffer used by decode_mode_spec. This buffer is also
293 used as temporary storage when updating the frame. See scroll.c. */
294 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
295 unsigned int total_charstarts = (width + 2) * sizeof (int);
297 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
298 bzero (new->total_contents, total_glyphs);
300 new->total_charstarts = (int *) xmalloc (total_charstarts);
301 bzero (new->total_charstarts, total_glyphs);
303 else
305 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
307 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
308 bzero (new->total_contents, total_glyphs);
309 for (i = 0; i < height; i++)
310 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
312 if (!FRAME_TERMCAP_P (frame))
314 unsigned int total_charstarts = height * (width + 2) * sizeof (int);
316 new->total_charstarts = (int *) xmalloc (total_charstarts);
317 bzero (new->total_charstarts, total_charstarts);
318 for (i = 0; i < height; i++)
319 new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
321 else
323 /* Without a window system, we don't really need charstarts.
324 So use a small amount of space to make enough data structure
325 to prevent crashes in display_text_line. */
326 new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
327 for (i = 0; i < height; i++)
328 new->charstarts[i] = new->total_charstarts;
332 return new;
335 void
336 free_frame_glyphs (frame, glyphs)
337 FRAME_PTR frame;
338 struct frame_glyphs *glyphs;
340 if (glyphs->total_contents)
341 xfree (glyphs->total_contents);
342 if (glyphs->total_charstarts)
343 xfree (glyphs->total_charstarts);
345 xfree (glyphs->used);
346 xfree (glyphs->glyphs);
347 xfree (glyphs->highlight);
348 xfree (glyphs->enable);
349 xfree (glyphs->bufp);
350 if (glyphs->charstarts)
351 xfree (glyphs->charstarts);
353 #ifdef HAVE_WINDOW_SYSTEM
354 if (FRAME_WINDOW_P (frame))
356 xfree (glyphs->top_left_x);
357 xfree (glyphs->top_left_y);
358 xfree (glyphs->pix_width);
359 xfree (glyphs->pix_height);
360 xfree (glyphs->max_ascent);
362 #endif /* HAVE_WINDOW_SYSTEM */
364 xfree (glyphs);
367 void
368 remake_frame_glyphs (frame)
369 FRAME_PTR frame;
371 if (FRAME_CURRENT_GLYPHS (frame))
372 free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
373 if (FRAME_DESIRED_GLYPHS (frame))
374 free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
375 if (FRAME_TEMP_GLYPHS (frame))
376 free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
378 if (FRAME_MESSAGE_BUF (frame))
380 /* Reallocate the frame's message buffer; remember that
381 echo_area_glyphs may be pointing here. */
382 char *old_message_buf = FRAME_MESSAGE_BUF (frame);
384 FRAME_MESSAGE_BUF (frame)
385 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
386 FRAME_WIDTH (frame) + 1);
388 if (echo_area_glyphs == old_message_buf)
389 echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
390 if (previous_echo_glyphs == old_message_buf)
391 previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
393 else
394 FRAME_MESSAGE_BUF (frame)
395 = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
397 FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
398 FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
399 FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
400 if (! FRAME_TERMCAP_P (frame) || frame == selected_frame)
401 SET_FRAME_GARBAGED (frame);
404 /* Return the hash code of contents of line VPOS in frame-matrix M. */
406 static int
407 line_hash_code (m, vpos)
408 register struct frame_glyphs *m;
409 int vpos;
411 register GLYPH *body, *end;
412 register int h = 0;
414 if (!m->enable[vpos])
415 return 0;
417 /* Give all highlighted lines the same hash code
418 so as to encourage scrolling to leave them in place. */
419 if (m->highlight[vpos])
420 return -1;
422 body = m->glyphs[vpos];
424 if (must_write_spaces)
425 while (1)
427 GLYPH g = *body++;
429 if (g == 0)
430 break;
431 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
433 else
434 while (1)
436 GLYPH g = *body++;
438 if (g == 0)
439 break;
440 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
443 if (h)
444 return h;
445 return 1;
448 /* Return number of characters in line in M at vpos VPOS,
449 except don't count leading and trailing spaces
450 unless the terminal requires those to be explicitly output. */
452 static unsigned int
453 line_draw_cost (m, vpos)
454 struct frame_glyphs *m;
455 int vpos;
457 register GLYPH *beg = m->glyphs[vpos];
458 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
459 register int i;
460 register int tlen = GLYPH_TABLE_LENGTH;
461 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
463 /* Ignore trailing and leading spaces if we can. */
464 if (!must_write_spaces)
466 while ((end != beg) && (*end == SPACEGLYPH))
467 --end;
468 if (end == beg)
469 return (0); /* All blank line. */
471 while (*beg == SPACEGLYPH)
472 ++beg;
475 /* If we don't have a glyph-table, each glyph is one character,
476 so return the number of glyphs. */
477 if (tbase == 0)
478 return end - beg;
480 /* Otherwise, scan the glyphs and accumulate their total size in I. */
481 i = 0;
482 while ((beg <= end) && *beg)
484 register GLYPH g = *beg++;
486 if (GLYPH_SIMPLE_P (tbase, tlen, g))
487 i += 1;
488 else
489 i += GLYPH_LENGTH (tbase, g);
491 return i;
494 /* The functions on this page are the interface from xdisp.c to redisplay.
496 The only other interface into redisplay is through setting
497 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
498 and SET_FRAME_GARBAGED (frame). */
500 /* cancel_line eliminates any request to display a line at position `vpos' */
502 cancel_line (vpos, frame)
503 int vpos;
504 register FRAME_PTR frame;
506 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
509 clear_frame_records (frame)
510 register FRAME_PTR frame;
512 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
515 /* Clear out all display lines for a coming redisplay. */
517 void
518 init_desired_glyphs (frame)
519 register FRAME_PTR frame;
521 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
522 int vpos;
523 int height = FRAME_HEIGHT (frame);
525 for (vpos = 0; vpos < height; vpos++)
526 desired_glyphs->enable[vpos] = 0;
529 /* Prepare to display on line VPOS starting at HPOS within it. */
531 void
532 get_display_line (frame, vpos, hpos)
533 register FRAME_PTR frame;
534 int vpos;
535 register int hpos;
537 register struct frame_glyphs *glyphs;
538 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
539 register GLYPH *p;
541 if (vpos < 0)
542 abort ();
544 if (! desired_glyphs->enable[vpos])
546 desired_glyphs->used[vpos] = 0;
547 desired_glyphs->highlight[vpos] = 0;
548 desired_glyphs->enable[vpos] = 1;
551 if (hpos > desired_glyphs->used[vpos])
553 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
554 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
556 desired_glyphs->used[vpos] = hpos;
557 while (g != end)
558 *g++ = SPACEGLYPH;
562 /* Like bcopy except never gets confused by overlap. */
564 void
565 safe_bcopy (from, to, size)
566 char *from, *to;
567 int size;
569 if (size <= 0 || from == to)
570 return;
572 /* If the source and destination don't overlap, then bcopy can
573 handle it. If they do overlap, but the destination is lower in
574 memory than the source, we'll assume bcopy can handle that. */
575 if (to < from || from + size <= to)
576 bcopy (from, to, size);
578 /* Otherwise, we'll copy from the end. */
579 else
581 register char *endf = from + size;
582 register char *endt = to + size;
584 /* If TO - FROM is large, then we should break the copy into
585 nonoverlapping chunks of TO - FROM bytes each. However, if
586 TO - FROM is small, then the bcopy function call overhead
587 makes this not worth it. The crossover point could be about
588 anywhere. Since I don't think the obvious copy loop is too
589 bad, I'm trying to err in its favor. */
590 if (to - from < 64)
593 *--endt = *--endf;
594 while (endf != from);
596 else
598 for (;;)
600 endt -= (to - from);
601 endf -= (to - from);
603 if (endt < to)
604 break;
606 bcopy (endf, endt, to - from);
609 /* If SIZE wasn't a multiple of TO - FROM, there will be a
610 little left over. The amount left over is
611 (endt + (to - from)) - to, which is endt - from. */
612 bcopy (from, to, endt - from);
617 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
618 DISTANCE may be negative. */
620 static void
621 rotate_vector (vector, size, distance)
622 char *vector;
623 int size;
624 int distance;
626 char *temp = (char *) alloca (size);
628 if (distance < 0)
629 distance += size;
631 bcopy (vector, temp + distance, size - distance);
632 bcopy (vector + size - distance, temp, distance);
633 bcopy (temp, vector, size);
636 /* Scroll lines from vpos FROM up to but not including vpos END
637 down by AMOUNT lines (AMOUNT may be negative).
638 Returns nonzero if done, zero if terminal cannot scroll them. */
641 scroll_frame_lines (frame, from, end, amount, newpos)
642 register FRAME_PTR frame;
643 int from, end, amount, newpos;
645 register int i;
646 register struct frame_glyphs *current_frame
647 = FRAME_CURRENT_GLYPHS (frame);
648 int pos_adjust;
649 int width = FRAME_WIDTH (frame);
651 if (!line_ins_del_ok)
652 return 0;
654 if (amount == 0)
655 return 1;
657 if (amount > 0)
659 update_begin (frame);
660 set_terminal_window (end + amount);
661 if (!scroll_region_ok)
662 ins_del_lines (end, -amount);
663 ins_del_lines (from, amount);
664 set_terminal_window (0);
666 rotate_vector (current_frame->glyphs + from,
667 sizeof (GLYPH *) * (end + amount - from),
668 amount * sizeof (GLYPH *));
670 rotate_vector (current_frame->charstarts + from,
671 sizeof (int *) * (end + amount - from),
672 amount * sizeof (int *));
674 safe_bcopy (current_frame->used + from,
675 current_frame->used + from + amount,
676 (end - from) * sizeof current_frame->used[0]);
678 safe_bcopy (current_frame->highlight + from,
679 current_frame->highlight + from + amount,
680 (end - from) * sizeof current_frame->highlight[0]);
682 safe_bcopy (current_frame->enable + from,
683 current_frame->enable + from + amount,
684 (end - from) * sizeof current_frame->enable[0]);
686 /* Adjust the lines by an amount
687 that puts the first of them at NEWPOS. */
688 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
690 /* Offset each char position in the charstarts lines we moved
691 by pos_adjust. */
692 for (i = from + amount; i < end + amount; i++)
694 int *line = current_frame->charstarts[i];
695 int col;
696 for (col = 0; col < width; col++)
697 if (line[col] > 0)
698 line[col] += pos_adjust;
700 for (i = from; i < from + amount; i++)
702 int *line = current_frame->charstarts[i];
703 int col;
704 line[0] = -1;
705 for (col = 0; col < width; col++)
706 line[col] = 0;
709 /* Mark the lines made empty by scrolling as enabled, empty and
710 normal video. */
711 bzero (current_frame->used + from,
712 amount * sizeof current_frame->used[0]);
713 bzero (current_frame->highlight + from,
714 amount * sizeof current_frame->highlight[0]);
715 for (i = from; i < from + amount; i++)
717 current_frame->glyphs[i][0] = '\0';
718 current_frame->charstarts[i][0] = -1;
719 current_frame->enable[i] = 1;
722 safe_bcopy (current_frame->bufp + from,
723 current_frame->bufp + from + amount,
724 (end - from) * sizeof current_frame->bufp[0]);
726 #ifdef HAVE_WINDOW_SYSTEM
727 if (FRAME_WINDOW_P (frame))
729 safe_bcopy (current_frame->top_left_x + from,
730 current_frame->top_left_x + from + amount,
731 (end - from) * sizeof current_frame->top_left_x[0]);
733 safe_bcopy (current_frame->top_left_y + from,
734 current_frame->top_left_y + from + amount,
735 (end - from) * sizeof current_frame->top_left_y[0]);
737 safe_bcopy (current_frame->pix_width + from,
738 current_frame->pix_width + from + amount,
739 (end - from) * sizeof current_frame->pix_width[0]);
741 safe_bcopy (current_frame->pix_height + from,
742 current_frame->pix_height + from + amount,
743 (end - from) * sizeof current_frame->pix_height[0]);
745 safe_bcopy (current_frame->max_ascent + from,
746 current_frame->max_ascent + from + amount,
747 (end - from) * sizeof current_frame->max_ascent[0]);
749 #endif /* HAVE_WINDOW_SYSTEM */
751 update_end (frame);
753 if (amount < 0)
755 update_begin (frame);
756 set_terminal_window (end);
757 ins_del_lines (from + amount, amount);
758 if (!scroll_region_ok)
759 ins_del_lines (end + amount, -amount);
760 set_terminal_window (0);
762 rotate_vector (current_frame->glyphs + from + amount,
763 sizeof (GLYPH *) * (end - from - amount),
764 amount * sizeof (GLYPH *));
766 rotate_vector (current_frame->charstarts + from + amount,
767 sizeof (int *) * (end - from - amount),
768 amount * sizeof (int *));
770 safe_bcopy (current_frame->used + from,
771 current_frame->used + from + amount,
772 (end - from) * sizeof current_frame->used[0]);
774 safe_bcopy (current_frame->highlight + from,
775 current_frame->highlight + from + amount,
776 (end - from) * sizeof current_frame->highlight[0]);
778 safe_bcopy (current_frame->enable + from,
779 current_frame->enable + from + amount,
780 (end - from) * sizeof current_frame->enable[0]);
782 /* Adjust the lines by an amount
783 that puts the first of them at NEWPOS. */
784 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
786 /* Offset each char position in the charstarts lines we moved
787 by pos_adjust. */
788 for (i = from + amount; i < end + amount; i++)
790 int *line = current_frame->charstarts[i];
791 int col;
792 for (col = 0; col < width; col++)
793 if (line[col] > 0)
794 line[col] += pos_adjust;
796 for (i = end + amount; i < end; i++)
798 int *line = current_frame->charstarts[i];
799 int col;
800 line[0] = -1;
801 for (col = 0; col < width; col++)
802 line[col] = 0;
805 /* Mark the lines made empty by scrolling as enabled, empty and
806 normal video. */
807 bzero (current_frame->used + end + amount,
808 - amount * sizeof current_frame->used[0]);
809 bzero (current_frame->highlight + end + amount,
810 - amount * sizeof current_frame->highlight[0]);
811 for (i = end + amount; i < end; i++)
813 current_frame->glyphs[i][0] = '\0';
814 current_frame->charstarts[i][0] = 0;
815 current_frame->enable[i] = 1;
818 safe_bcopy (current_frame->bufp + from,
819 current_frame->bufp + from + amount,
820 (end - from) * sizeof current_frame->bufp[0]);
822 #ifdef HAVE_WINDOW_SYSTEM
823 if (FRAME_WINDOW_P (frame))
825 safe_bcopy (current_frame->top_left_x + from,
826 current_frame->top_left_x + from + amount,
827 (end - from) * sizeof current_frame->top_left_x[0]);
829 safe_bcopy (current_frame->top_left_y + from,
830 current_frame->top_left_y + from + amount,
831 (end - from) * sizeof current_frame->top_left_y[0]);
833 safe_bcopy (current_frame->pix_width + from,
834 current_frame->pix_width + from + amount,
835 (end - from) * sizeof current_frame->pix_width[0]);
837 safe_bcopy (current_frame->pix_height + from,
838 current_frame->pix_height + from + amount,
839 (end - from) * sizeof current_frame->pix_height[0]);
841 safe_bcopy (current_frame->max_ascent + from,
842 current_frame->max_ascent + from + amount,
843 (end - from) * sizeof current_frame->max_ascent[0]);
845 #endif /* HAVE_WINDOW_SYSTEM */
847 update_end (frame);
849 return 1;
852 /* After updating a window W that isn't the full frame wide,
853 copy all the columns that W does not occupy
854 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
855 so that update_frame will not change those columns. */
857 preserve_other_columns (w)
858 struct window *w;
860 register int vpos;
861 register struct frame_glyphs *current_frame, *desired_frame;
862 register FRAME_PTR frame = XFRAME (w->frame);
863 int start = XFASTINT (w->left);
864 int end = XFASTINT (w->left) + XFASTINT (w->width);
865 int bot = XFASTINT (w->top) + XFASTINT (w->height);
867 current_frame = FRAME_CURRENT_GLYPHS (frame);
868 desired_frame = FRAME_DESIRED_GLYPHS (frame);
870 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
872 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
874 if (start > 0)
876 int len;
878 bcopy (current_frame->glyphs[vpos],
879 desired_frame->glyphs[vpos],
880 start * sizeof (current_frame->glyphs[vpos][0]));
881 bcopy (current_frame->charstarts[vpos],
882 desired_frame->charstarts[vpos],
883 start * sizeof (current_frame->charstarts[vpos][0]));
884 len = min (start, current_frame->used[vpos]);
885 if (desired_frame->used[vpos] < len)
886 desired_frame->used[vpos] = len;
888 if (current_frame->used[vpos] > end
889 && desired_frame->used[vpos] < current_frame->used[vpos])
891 while (desired_frame->used[vpos] < end)
893 int used = desired_frame->used[vpos]++;
894 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
895 desired_frame->glyphs[vpos][used] = 0;
897 bcopy (current_frame->glyphs[vpos] + end,
898 desired_frame->glyphs[vpos] + end,
899 ((current_frame->used[vpos] - end)
900 * sizeof (current_frame->glyphs[vpos][0])));
901 bcopy (current_frame->charstarts[vpos] + end,
902 desired_frame->charstarts[vpos] + end,
903 ((current_frame->used[vpos] - end)
904 * sizeof (current_frame->charstarts[vpos][0])));
905 desired_frame->used[vpos] = current_frame->used[vpos];
911 #if 0
913 /* If window w does not need to be updated and isn't the full frame wide,
914 copy all the columns that w does occupy
915 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
916 so that update_frame will not change those columns.
918 Have not been able to figure out how to use this correctly. */
920 preserve_my_columns (w)
921 struct window *w;
923 register int vpos, fin;
924 register struct frame_glyphs *l1, *l2;
925 register FRAME_PTR frame = XFRAME (w->frame);
926 int start = XFASTINT (w->left);
927 int end = XFASTINT (w->left) + XFASTINT (w->width);
928 int bot = XFASTINT (w->top) + XFASTINT (w->height);
930 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
932 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
933 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
935 if (l2->length > start && l1->length < l2->length)
937 fin = l2->length;
938 if (fin > end) fin = end;
939 while (l1->length < start)
940 l1->body[l1->length++] = ' ';
941 bcopy (l2->body + start, l1->body + start, fin - start);
942 l1->length = fin;
948 #endif
950 /* Adjust by ADJUST the charstart values in window W
951 after vpos VPOS, which counts relative to the frame
952 (not relative to W itself). */
954 void
955 adjust_window_charstarts (w, vpos, adjust)
956 struct window *w;
957 int vpos;
958 int adjust;
960 int left = XFASTINT (w->left);
961 int top = XFASTINT (w->top);
962 int right = left + window_internal_width (w);
963 int bottom = top + window_internal_height (w);
964 int i;
966 for (i = vpos + 1; i < bottom; i++)
968 int *charstart
969 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
970 int j;
971 for (j = left; j < right; j++)
972 if (charstart[j] > 0)
973 charstart[j] += adjust;
977 /* Check the charstarts values in the area of window W
978 for internal consistency. We cannot check that they are "right";
979 we can only look for something nonsensical. */
981 verify_charstarts (w)
982 struct window *w;
984 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
985 int i;
986 int top = XFASTINT (w->top);
987 int bottom = top + window_internal_height (w);
988 int left = XFASTINT (w->left);
989 int right = left + window_internal_width (w);
990 int next_line;
991 int truncate = (XINT (w->hscroll)
992 || (truncate_partial_width_windows
993 && (XFASTINT (w->width) < FRAME_WIDTH (f)))
994 || !NILP (XBUFFER (w->buffer)->truncate_lines));
996 for (i = top; i < bottom; i++)
998 int j;
999 int last;
1000 int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
1002 if (i != top)
1004 if (truncate)
1006 /* If we are truncating lines, allow a jump
1007 in charstarts from one line to the next. */
1008 if (charstart[left] < next_line)
1009 abort ();
1011 else
1013 if (charstart[left] != next_line)
1014 abort ();
1018 for (j = left; j < right; j++)
1019 if (charstart[j] > 0)
1020 last = charstart[j];
1021 /* Record where the next line should start. */
1022 next_line = last;
1023 if (BUF_ZV (XBUFFER (w->buffer)) != last)
1025 /* If there's a newline between the two lines, count that. */
1026 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
1027 if (endchar == '\n')
1028 next_line++;
1033 /* On discovering that the redisplay for a window was no good,
1034 cancel the columns of that window, so that when the window is
1035 displayed over again get_display_line will not complain. */
1037 cancel_my_columns (w)
1038 struct window *w;
1040 register int vpos;
1041 register struct frame_glyphs *desired_glyphs
1042 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
1043 register int start = XFASTINT (w->left);
1044 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
1046 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
1047 if (desired_glyphs->enable[vpos]
1048 && desired_glyphs->used[vpos] >= start)
1049 desired_glyphs->used[vpos] = start;
1052 /* These functions try to perform directly and immediately on the frame
1053 the necessary output for one change in the buffer.
1054 They may return 0 meaning nothing was done if anything is difficult,
1055 or 1 meaning the output was performed properly.
1056 They assume that the frame was up to date before the buffer
1057 change being displayed. They make various other assumptions too;
1058 see command_loop_1 where these are called. */
1061 direct_output_for_insert (g)
1062 int g;
1064 register FRAME_PTR frame = selected_frame;
1065 register struct frame_glyphs *current_frame
1066 = FRAME_CURRENT_GLYPHS (frame);
1068 #ifndef COMPILER_REGISTER_BUG
1069 register
1070 #endif /* COMPILER_REGISTER_BUG */
1071 struct window *w = XWINDOW (selected_window);
1072 #ifndef COMPILER_REGISTER_BUG
1073 register
1074 #endif /* COMPILER_REGISTER_BUG */
1075 int hpos = FRAME_CURSOR_X (frame);
1076 #ifndef COMPILER_REGISTER_BUG
1077 register
1078 #endif /* COMPILER_REGISTER_BUG */
1079 int vpos = FRAME_CURSOR_Y (frame);
1081 /* Give up if about to continue line. */
1082 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
1084 /* Avoid losing if cursor is in invisible text off left margin */
1085 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
1087 /* Give up if cursor outside window (in minibuf, probably) */
1088 || cursor_in_echo_area
1089 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1090 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
1092 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
1093 || !display_completed
1095 /* Give up if buffer appears in two places. */
1096 || buffer_shared > 1
1098 #ifdef USE_TEXT_PROPERTIES
1099 /* Intervals have already been adjusted, point is after the
1100 character that was just inserted. */
1101 /* Give up if character is invisible. */
1102 /* Give up if character has a face property.
1103 At the moment we only lose at end of line or end of buffer
1104 and only with faces that have some background */
1105 /* Instead of wasting time, give up if character has any text properties */
1106 || ! NILP (Ftext_properties_at (make_number (point - 1), Qnil))
1107 #endif
1109 /* Give up if w is minibuffer and a message is being displayed there */
1110 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1111 return 0;
1114 int face = 0;
1115 #ifdef HAVE_FACES
1116 int dummy;
1118 if (FRAME_WINDOW_P (frame))
1119 face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point, 0);
1120 #endif
1121 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
1122 current_frame->charstarts[vpos][hpos] = point - 1;
1123 /* Record the entry for after the newly inserted character. */
1124 current_frame->charstarts[vpos][hpos + 1] = point;
1125 adjust_window_charstarts (w, vpos, 1);
1127 unchanged_modified = MODIFF;
1128 beg_unchanged = GPT - BEG;
1129 XSETFASTINT (w->last_point, point);
1130 XSETFASTINT (w->last_point_x, hpos);
1131 XSETFASTINT (w->last_modified, MODIFF);
1133 reassert_line_highlight (0, vpos);
1134 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
1135 fflush (stdout);
1136 ++FRAME_CURSOR_X (frame);
1137 if (hpos == current_frame->used[vpos])
1139 current_frame->used[vpos] = hpos + 1;
1140 current_frame->glyphs[vpos][hpos + 1] = 0;
1143 return 1;
1147 direct_output_forward_char (n)
1148 int n;
1150 register FRAME_PTR frame = selected_frame;
1151 register struct window *w = XWINDOW (selected_window);
1152 Lisp_Object position;
1153 int hpos = FRAME_CURSOR_X (frame);
1155 /* Give up if in truncated text at end of line. */
1156 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
1157 return 0;
1159 /* Avoid losing if cursor is in invisible text off left margin
1160 or about to go off either side of window. */
1161 if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
1162 && (XINT (w->hscroll) || n < 0))
1163 || (n > 0
1164 && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
1165 || cursor_in_echo_area)
1166 return 0;
1168 /* Can't use direct output if highlighting a region. */
1169 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1170 return 0;
1172 /* Can't use direct output at an overlay boundary; it might have
1173 before-string or after-string properties. */
1174 if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
1175 return 0;
1177 #ifdef USE_TEXT_PROPERTIES
1178 /* Don't use direct output next to an invisible character
1179 since we might need to do something special. */
1181 XSETFASTINT (position, point);
1182 if (XFASTINT (position) < ZV
1183 && ! NILP (Fget_char_property (position,
1184 Qinvisible,
1185 selected_window)))
1186 return 0;
1188 XSETFASTINT (position, point - 1);
1189 if (XFASTINT (position) >= BEGV
1190 && ! NILP (Fget_char_property (position,
1191 Qinvisible,
1192 selected_window)))
1193 return 0;
1194 #endif
1196 FRAME_CURSOR_X (frame) += n;
1197 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
1198 XSETFASTINT (w->last_point, point);
1199 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
1200 fflush (stdout);
1202 return 1;
1205 static void update_line ();
1207 /* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
1208 Value is nonzero if redisplay stopped due to pending input.
1209 FORCE nonzero means do not stop for pending input. */
1212 update_frame (f, force, inhibit_hairy_id)
1213 FRAME_PTR f;
1214 int force;
1215 int inhibit_hairy_id;
1217 register struct frame_glyphs *current_frame;
1218 register struct frame_glyphs *desired_frame = 0;
1219 register int i;
1220 int pause;
1221 int preempt_count = baud_rate / 2400 + 1;
1222 extern input_pending;
1223 #ifdef HAVE_WINDOW_SYSTEM
1224 register int downto, leftmost;
1225 #endif
1227 if (baud_rate != FRAME_COST_BAUD_RATE (f))
1228 calculate_costs (f);
1230 if (preempt_count <= 0)
1231 preempt_count = 1;
1233 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1235 detect_input_pending ();
1236 if (input_pending && !force)
1238 pause = 1;
1239 goto do_pause;
1242 update_begin (f);
1244 if (!line_ins_del_ok)
1245 inhibit_hairy_id = 1;
1247 /* These are separate to avoid a possible bug in the AIX C compiler. */
1248 current_frame = FRAME_CURRENT_GLYPHS (f);
1249 desired_frame = FRAME_DESIRED_GLYPHS (f);
1251 /* See if any of the desired lines are enabled; don't compute for
1252 i/d line if just want cursor motion. */
1253 for (i = 0; i < FRAME_HEIGHT (f); i++)
1254 if (desired_frame->enable[i])
1255 break;
1257 /* Try doing i/d line, if not yet inhibited. */
1258 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1259 force |= scrolling (f);
1261 /* Update the individual lines as needed. Do bottom line first. */
1263 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1264 update_line (f, FRAME_HEIGHT (f) - 1);
1266 #ifdef HAVE_WINDOW_SYSTEM
1267 if (FRAME_WINDOW_P (f))
1269 leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
1270 if (desired_frame->enable[0])
1272 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1273 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
1274 = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
1275 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
1276 current_frame->top_left_x[0] = leftmost;
1277 current_frame->top_left_y[0] = downto;
1280 #endif /* HAVE_WINDOW_SYSTEM */
1282 /* Now update the rest of the lines. */
1283 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
1285 if (desired_frame->enable[i])
1287 if (FRAME_TERMCAP_P (f))
1289 /* Flush out every so many lines.
1290 Also flush out if likely to have more than 1k buffered
1291 otherwise. I'm told that some telnet connections get
1292 really screwed by more than 1k output at once. */
1293 int outq = PENDING_OUTPUT_COUNT (stdout);
1294 if (outq > 900
1295 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1297 fflush (stdout);
1298 if (preempt_count == 1)
1300 #ifdef EMACS_OUTQSIZE
1301 if (EMACS_OUTQSIZE (0, &outq) < 0)
1302 /* Probably not a tty. Ignore the error and reset
1303 * the outq count. */
1304 outq = PENDING_OUTPUT_COUNT (stdout);
1305 #endif
1306 outq *= 10;
1307 if (baud_rate <= outq && baud_rate > 0)
1308 sleep (outq / baud_rate);
1311 if ((i - 1) % preempt_count == 0)
1312 detect_input_pending ();
1315 update_line (f, i);
1316 #ifdef HAVE_WINDOW_SYSTEM
1317 if (FRAME_WINDOW_P (f))
1319 current_frame->top_left_y[i] = downto;
1320 current_frame->top_left_x[i] = leftmost;
1322 #endif /* HAVE_WINDOW_SYSTEM */
1325 #ifdef HAVE_WINDOW_SYSTEM
1326 if (FRAME_WINDOW_P (f))
1327 downto += current_frame->pix_height[i];
1328 #endif /* HAVE_WINDOW_SYSTEM */
1330 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
1332 /* Now just clean up termcap drivers and set cursor, etc. */
1333 if (!pause)
1335 if ((cursor_in_echo_area
1336 /* If we are showing a message instead of the minibuffer,
1337 show the cursor for the message instead of for the
1338 (now hidden) minibuffer contents. */
1339 || (EQ (minibuf_window, selected_window)
1340 && EQ (minibuf_window, echo_area_window)
1341 && echo_area_glyphs != 0))
1342 /* These cases apply only to the frame that contains
1343 the active minibuffer window. */
1344 && FRAME_HAS_MINIBUF_P (f)
1345 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window))
1347 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1348 int row, col;
1350 if (cursor_in_echo_area < 0)
1352 row = top;
1353 col = 0;
1355 else
1357 /* If the minibuffer is several lines high, find the last
1358 line that has any text on it. */
1359 row = FRAME_HEIGHT (f);
1362 row--;
1363 if (current_frame->enable[row])
1364 col = current_frame->used[row];
1365 else
1366 col = 0;
1368 while (row > top && col == 0);
1370 if (col >= FRAME_WIDTH (f))
1372 col = 0;
1373 if (row < FRAME_HEIGHT (f) - 1)
1374 row++;
1378 cursor_to (row, col);
1380 else
1381 cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
1382 FRAME_WIDTH (f) - 1), 0));
1385 update_end (f);
1387 if (termscript)
1388 fflush (termscript);
1389 fflush (stdout);
1391 /* Here if output is preempted because input is detected. */
1392 do_pause:
1394 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1395 display_completed = !pause;
1397 bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
1398 return pause;
1401 /* Called when about to quit, to check for doing so
1402 at an improper time. */
1404 void
1405 quit_error_check ()
1407 #if 0
1408 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
1409 return;
1410 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
1411 abort ();
1412 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
1413 abort ();
1414 #endif
1417 /* Decide what insert/delete line to do, and do it */
1419 extern void scrolling_1 ();
1421 scrolling (frame)
1422 FRAME_PTR frame;
1424 int unchanged_at_top, unchanged_at_bottom;
1425 int window_size;
1426 int changed_lines;
1427 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1428 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1429 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1430 int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1431 register int i;
1432 int free_at_end_vpos = FRAME_HEIGHT (frame);
1433 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1434 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
1436 /* Compute hash codes of all the lines.
1437 Also calculate number of changed lines,
1438 number of unchanged lines at the beginning,
1439 and number of unchanged lines at the end. */
1441 changed_lines = 0;
1442 unchanged_at_top = 0;
1443 unchanged_at_bottom = FRAME_HEIGHT (frame);
1444 for (i = 0; i < FRAME_HEIGHT (frame); i++)
1446 /* Give up on this scrolling if some old lines are not enabled. */
1447 if (!current_frame->enable[i])
1448 return 0;
1449 old_hash[i] = line_hash_code (current_frame, i);
1450 if (! desired_frame->enable[i])
1451 new_hash[i] = old_hash[i];
1452 else
1453 new_hash[i] = line_hash_code (desired_frame, i);
1455 if (old_hash[i] != new_hash[i])
1457 changed_lines++;
1458 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
1460 else if (i == unchanged_at_top)
1461 unchanged_at_top++;
1462 draw_cost[i] = line_draw_cost (desired_frame, i);
1463 old_draw_cost[i] = line_draw_cost (current_frame, i);
1466 /* If changed lines are few, don't allow preemption, don't scroll. */
1467 if (!scroll_region_ok && changed_lines < baud_rate / 2400
1468 || unchanged_at_bottom == FRAME_HEIGHT (frame))
1469 return 1;
1471 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
1472 - unchanged_at_bottom);
1474 if (scroll_region_ok)
1475 free_at_end_vpos -= unchanged_at_bottom;
1476 else if (memory_below_frame)
1477 free_at_end_vpos = -1;
1479 /* If large window, fast terminal and few lines in common between
1480 current frame and desired frame, don't bother with i/d calc. */
1481 if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
1482 && (window_size >=
1483 10 * scrolling_max_lines_saved (unchanged_at_top,
1484 FRAME_HEIGHT (frame) - unchanged_at_bottom,
1485 old_hash, new_hash, draw_cost)))
1486 return 0;
1488 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
1489 draw_cost + unchanged_at_top - 1,
1490 old_draw_cost + unchanged_at_top - 1,
1491 old_hash + unchanged_at_top - 1,
1492 new_hash + unchanged_at_top - 1,
1493 free_at_end_vpos - unchanged_at_top);
1495 return 0;
1498 /* Return the offset in its buffer of the character at location col, line
1499 in the given window. */
1501 buffer_posn_from_coords (window, col, line)
1502 struct window *window;
1503 int col, line;
1505 int hscroll = XINT (window->hscroll);
1506 int window_left = XFASTINT (window->left);
1508 /* The actual width of the window is window->width less one for the
1509 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1510 window. */
1511 int window_width = window_internal_width (window) - 1;
1513 int startp = marker_position (window->start);
1515 /* Since compute_motion will only operate on the current buffer,
1516 we need to save the old one and restore it when we're done. */
1517 struct buffer *old_current_buffer = current_buffer;
1518 struct position *posn;
1520 current_buffer = XBUFFER (window->buffer);
1522 /* We can't get a correct result in this case,
1523 but at least prevent compute_motion from crashing. */
1524 if (startp < BEGV)
1525 startp = BEGV;
1527 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1528 (window->frame))->bufp to avoid scanning from the very top of
1529 the window, but it isn't maintained correctly, and I'm not even
1530 sure I will keep it. */
1531 posn = compute_motion (startp, 0,
1532 ((window == XWINDOW (minibuf_window) && startp == BEG
1533 ? minibuf_prompt_width : 0)
1534 + (hscroll ? 1 - hscroll : 0)),
1536 ZV, line, col,
1537 window_width, hscroll, 0, window);
1539 current_buffer = old_current_buffer;
1541 /* compute_motion considers frame points past the end of a line
1542 to be *after* the newline, i.e. at the start of the next line.
1543 This is reasonable, but not really what we want. So if the
1544 result is on a line below LINE, back it up one character. */
1545 if (posn->vpos > line)
1546 return posn->bufpos - 1;
1547 else
1548 return posn->bufpos;
1551 static int
1552 count_blanks (r)
1553 register GLYPH *r;
1555 register GLYPH *p = r;
1556 while (*p++ == SPACEGLYPH);
1557 return p - r - 1;
1560 static int
1561 count_match (str1, str2)
1562 GLYPH *str1, *str2;
1564 register GLYPH *p1 = str1;
1565 register GLYPH *p2 = str2;
1566 while (*p1++ == *p2++);
1567 return p1 - str1 - 1;
1570 /* Char insertion/deletion cost vector, from term.c */
1571 extern int *char_ins_del_vector;
1573 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
1575 static void
1576 update_line (frame, vpos)
1577 register FRAME_PTR frame;
1578 int vpos;
1580 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1581 int *temp1;
1582 int tem;
1583 int osp, nsp, begmatch, endmatch, olen, nlen;
1584 int save;
1585 register struct frame_glyphs *current_frame
1586 = FRAME_CURRENT_GLYPHS (frame);
1587 register struct frame_glyphs *desired_frame
1588 = FRAME_DESIRED_GLYPHS (frame);
1590 if (desired_frame->highlight[vpos]
1591 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
1593 change_line_highlight (desired_frame->highlight[vpos], vpos,
1594 (current_frame->enable[vpos] ?
1595 current_frame->used[vpos] : 0));
1596 current_frame->enable[vpos] = 0;
1598 else
1599 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
1601 if (! current_frame->enable[vpos])
1603 olen = 0;
1605 else
1607 obody = current_frame->glyphs[vpos];
1608 olen = current_frame->used[vpos];
1609 if (! current_frame->highlight[vpos])
1611 if (!must_write_spaces)
1612 while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
1613 olen--;
1615 else
1617 /* For an inverse-video line, remember we gave it
1618 spaces all the way to the frame edge
1619 so that the reverse video extends all the way across. */
1621 while (olen < FRAME_WIDTH (frame) - 1)
1622 obody[olen++] = SPACEGLYPH;
1626 /* One way or another, this will enable the line being updated. */
1627 current_frame->enable[vpos] = 1;
1628 current_frame->used[vpos] = desired_frame->used[vpos];
1629 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1630 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
1632 #ifdef HAVE_WINDOW_SYSTEM
1633 if (FRAME_WINDOW_P (frame))
1635 current_frame->pix_width[vpos]
1636 = current_frame->used[vpos]
1637 * FONT_WIDTH (FRAME_FONT (frame));
1638 current_frame->pix_height[vpos]
1639 = FRAME_LINE_HEIGHT (frame);
1641 #endif /* HAVE_WINDOW_SYSTEM */
1643 if (!desired_frame->enable[vpos])
1645 nlen = 0;
1646 goto just_erase;
1649 nbody = desired_frame->glyphs[vpos];
1650 nlen = desired_frame->used[vpos];
1652 /* Pretend trailing spaces are not there at all,
1653 unless for one reason or another we must write all spaces. */
1654 if (! desired_frame->highlight[vpos])
1656 if (!must_write_spaces)
1657 /* We know that the previous character byte contains 0. */
1658 while (nbody[nlen - 1] == SPACEGLYPH)
1659 nlen--;
1661 else
1663 /* For an inverse-video line, give it extra trailing spaces
1664 all the way to the frame edge
1665 so that the reverse video extends all the way across. */
1667 while (nlen < FRAME_WIDTH (frame) - 1)
1668 nbody[nlen++] = SPACEGLYPH;
1671 /* If there's no i/d char, quickly do the best we can without it. */
1672 if (!char_ins_del_ok)
1674 int i,j;
1676 #if 0
1677 if (FRAME_X_P (frame))
1679 /* Under X, erase everything we are going to rewrite,
1680 and rewrite everything from the first char that's changed.
1681 This is part of supporting fonts like Courier
1682 whose chars can overlap outside the char width. */
1683 for (i = 0; i < nlen; i++)
1684 if (i >= olen || nbody[i] != obody[i])
1685 break;
1687 cursor_to (vpos, i);
1688 if (i != olen)
1689 clear_end_of_line (olen);
1690 write_glyphs (nbody + i, nlen - i);
1692 else
1694 #endif /* 0 */
1695 for (i = 0; i < nlen; i++)
1697 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1699 cursor_to (vpos, i);
1700 for (j = 1; (i + j < nlen &&
1701 (i + j >= olen || nbody[i+j] != obody[i+j]));
1702 j++);
1704 /* Output this run of non-matching chars. */
1705 write_glyphs (nbody + i, j);
1706 i += j - 1;
1708 /* Now find the next non-match. */
1712 /* Clear the rest of the line, or the non-clear part of it. */
1713 if (olen > nlen)
1715 cursor_to (vpos, nlen);
1716 clear_end_of_line (olen);
1719 /* Exchange contents between current_frame and new_frame. */
1720 temp = desired_frame->glyphs[vpos];
1721 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1722 current_frame->glyphs[vpos] = temp;
1724 /* Exchange charstarts between current_frame and new_frame. */
1725 temp1 = desired_frame->charstarts[vpos];
1726 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1727 current_frame->charstarts[vpos] = temp1;
1729 return;
1732 if (!olen)
1734 nsp = (must_write_spaces || desired_frame->highlight[vpos])
1735 ? 0 : count_blanks (nbody);
1736 if (nlen > nsp)
1738 cursor_to (vpos, nsp);
1739 write_glyphs (nbody + nsp, nlen - nsp);
1742 /* Exchange contents between current_frame and new_frame. */
1743 temp = desired_frame->glyphs[vpos];
1744 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1745 current_frame->glyphs[vpos] = temp;
1747 /* Exchange charstarts between current_frame and new_frame. */
1748 temp1 = desired_frame->charstarts[vpos];
1749 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1750 current_frame->charstarts[vpos] = temp1;
1752 return;
1755 obody[olen] = 1;
1756 save = nbody[nlen];
1757 nbody[nlen] = 0;
1759 /* Compute number of leading blanks in old and new contents. */
1760 osp = count_blanks (obody);
1761 if (!desired_frame->highlight[vpos])
1762 nsp = count_blanks (nbody);
1763 else
1764 nsp = 0;
1766 /* Compute number of matching chars starting with first nonblank. */
1767 begmatch = count_match (obody + osp, nbody + nsp);
1769 /* Spaces in new match implicit space past the end of old. */
1770 /* A bug causing this to be a no-op was fixed in 18.29. */
1771 if (!must_write_spaces && osp + begmatch == olen)
1773 np1 = nbody + nsp;
1774 while (np1[begmatch] == SPACEGLYPH)
1775 begmatch++;
1778 /* Avoid doing insert/delete char
1779 just cause number of leading spaces differs
1780 when the following text does not match. */
1781 if (begmatch == 0 && osp != nsp)
1782 osp = nsp = min (osp, nsp);
1784 /* Find matching characters at end of line */
1785 op1 = obody + olen;
1786 np1 = nbody + nlen;
1787 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1788 while (op1 > op2 && op1[-1] == np1[-1])
1790 op1--;
1791 np1--;
1793 endmatch = obody + olen - op1;
1795 /* Put correct value back in nbody[nlen].
1796 This is important because direct_output_for_insert
1797 can write into the line at a later point.
1798 If this screws up the zero at the end of the line, re-establish it. */
1799 nbody[nlen] = save;
1800 obody[olen] = 0;
1802 /* tem gets the distance to insert or delete.
1803 endmatch is how many characters we save by doing so.
1804 Is it worth it? */
1806 tem = (nlen - nsp) - (olen - osp);
1807 if (endmatch && tem
1808 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
1809 endmatch = 0;
1811 /* nsp - osp is the distance to insert or delete.
1812 If that is nonzero, begmatch is known to be nonzero also.
1813 begmatch + endmatch is how much we save by doing the ins/del.
1814 Is it worth it? */
1816 if (nsp != osp
1817 && (!char_ins_del_ok
1818 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
1820 begmatch = 0;
1821 endmatch = 0;
1822 osp = nsp = min (osp, nsp);
1825 /* Now go through the line, inserting, writing and
1826 deleting as appropriate. */
1828 if (osp > nsp)
1830 cursor_to (vpos, nsp);
1831 delete_glyphs (osp - nsp);
1833 else if (nsp > osp)
1835 /* If going to delete chars later in line
1836 and insert earlier in the line,
1837 must delete first to avoid losing data in the insert */
1838 if (endmatch && nlen < olen + nsp - osp)
1840 cursor_to (vpos, nlen - endmatch + osp - nsp);
1841 delete_glyphs (olen + nsp - osp - nlen);
1842 olen = nlen - (nsp - osp);
1844 cursor_to (vpos, osp);
1845 insert_glyphs ((char *)0, nsp - osp);
1847 olen += nsp - osp;
1849 tem = nsp + begmatch + endmatch;
1850 if (nlen != tem || olen != tem)
1852 cursor_to (vpos, nsp + begmatch);
1853 if (!endmatch || nlen == olen)
1855 /* If new text being written reaches right margin,
1856 there is no need to do clear-to-eol at the end.
1857 (and it would not be safe, since cursor is not
1858 going to be "at the margin" after the text is done) */
1859 if (nlen == FRAME_WIDTH (frame))
1860 olen = 0;
1861 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1863 #ifdef obsolete
1865 /* the following code loses disastrously if tem == nlen.
1866 Rather than trying to fix that case, I am trying the simpler
1867 solution found above. */
1869 /* If the text reaches to the right margin,
1870 it will lose one way or another (depending on AutoWrap)
1871 to clear to end of line after outputting all the text.
1872 So pause with one character to go and clear the line then. */
1873 if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
1875 /* endmatch must be zero, and tem must equal nsp + begmatch */
1876 write_glyphs (nbody + tem, nlen - tem - 1);
1877 clear_end_of_line (olen);
1878 olen = 0; /* Don't let it be cleared again later */
1879 write_glyphs (nbody + nlen - 1, 1);
1881 else
1882 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1883 #endif /* OBSOLETE */
1886 else if (nlen > olen)
1888 write_glyphs (nbody + nsp + begmatch, olen - tem);
1889 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1890 olen = nlen;
1892 else if (olen > nlen)
1894 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1895 delete_glyphs (olen - nlen);
1896 olen = nlen;
1900 just_erase:
1901 /* If any unerased characters remain after the new line, erase them. */
1902 if (olen > nlen)
1904 cursor_to (vpos, nlen);
1905 clear_end_of_line (olen);
1908 /* Exchange contents between current_frame and new_frame. */
1909 temp = desired_frame->glyphs[vpos];
1910 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1911 current_frame->glyphs[vpos] = temp;
1913 /* Exchange charstarts between current_frame and new_frame. */
1914 temp1 = desired_frame->charstarts[vpos];
1915 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1916 current_frame->charstarts[vpos] = temp1;
1919 /* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
1920 session's frames, frame names, buffers, buffer-read-only flags, and
1921 buffer-modified-flags, and a trailing sentinel (so we don't need to
1922 add length checks). */
1923 static Lisp_Object frame_and_buffer_state;
1925 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
1926 Sframe_or_buffer_changed_p, 0, 0, 0,
1927 "Return non-nil if the frame and buffer state appears to have changed.\n\
1928 The state variable is an internal vector containing all frames and buffers,\n\
1929 aside from buffers whose names start with space,\n\
1930 along with the buffers' read-only and modified flags, which allows a fast\n\
1931 check to see whether the menu bars might need to be recomputed.\n\
1932 If this function returns non-nil, it updates the internal vector to reflect\n\
1933 the current state.\n")
1936 Lisp_Object tail, frame, buf;
1937 Lisp_Object *vecp;
1938 int n;
1940 vecp = XVECTOR (frame_and_buffer_state)->contents;
1941 FOR_EACH_FRAME (tail, frame)
1943 if (!EQ (*vecp++, frame))
1944 goto changed;
1945 if (!EQ (*vecp++, XFRAME (frame)->name))
1946 goto changed;
1948 /* Check that the buffer info matches.
1949 No need to test for the end of the vector
1950 because the last element of the vector is lambda
1951 and that will always cause a mismatch. */
1952 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1954 buf = XCONS (XCONS (tail)->car)->cdr;
1955 /* Ignore buffers that aren't included in buffer lists. */
1956 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
1957 continue;
1958 if (!EQ (*vecp++, buf))
1959 goto changed;
1960 if (!EQ (*vecp++, XBUFFER (buf)->read_only))
1961 goto changed;
1962 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
1963 goto changed;
1965 /* Detect deletion of a buffer at the end of the list. */
1966 if (*vecp == Qlambda)
1967 return Qnil;
1968 changed:
1969 /* Start with 1 so there is room for at least one lambda at the end. */
1970 n = 1;
1971 FOR_EACH_FRAME (tail, frame)
1972 n += 2;
1973 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1974 n += 3;
1975 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
1976 if (n > XVECTOR (frame_and_buffer_state)->size
1977 || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
1978 /* Add 20 extra so we grow it less often. */
1979 frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
1980 vecp = XVECTOR (frame_and_buffer_state)->contents;
1981 FOR_EACH_FRAME (tail, frame)
1983 *vecp++ = frame;
1984 *vecp++ = XFRAME (frame)->name;
1986 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1988 buf = XCONS (XCONS (tail)->car)->cdr;
1989 /* Ignore buffers that aren't included in buffer lists. */
1990 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
1991 continue;
1992 *vecp++ = buf;
1993 *vecp++ = XBUFFER (buf)->read_only;
1994 *vecp++ = Fbuffer_modified_p (buf);
1996 /* Fill up the vector with lambdas (always at least one). */
1997 *vecp++ = Qlambda;
1998 while (vecp - XVECTOR (frame_and_buffer_state)->contents
1999 < XVECTOR (frame_and_buffer_state)->size)
2000 *vecp++ = Qlambda;
2001 /* Make sure we didn't overflow the vector. */
2002 if (vecp - XVECTOR (frame_and_buffer_state)->contents
2003 > XVECTOR (frame_and_buffer_state)->size)
2004 abort ();
2005 return Qt;
2008 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
2009 1, 1, "FOpen termscript file: ",
2010 "Start writing all terminal output to FILE as well as the terminal.\n\
2011 FILE = nil means just close any termscript file currently open.")
2012 (file)
2013 Lisp_Object file;
2015 if (termscript != 0) fclose (termscript);
2016 termscript = 0;
2018 if (! NILP (file))
2020 file = Fexpand_file_name (file, Qnil);
2021 termscript = fopen (XSTRING (file)->data, "w");
2022 if (termscript == 0)
2023 report_file_error ("Opening termscript", Fcons (file, Qnil));
2025 return Qnil;
2029 #ifdef SIGWINCH
2030 SIGTYPE
2031 window_change_signal (signalnum) /* If we don't have an argument, */
2032 int signalnum; /* some compilers complain in signal calls. */
2034 int width, height;
2035 extern int errno;
2036 int old_errno = errno;
2038 get_frame_size (&width, &height);
2040 /* The frame size change obviously applies to a termcap-controlled
2041 frame. Find such a frame in the list, and assume it's the only
2042 one (since the redisplay code always writes to stdout, not a
2043 FILE * specified in the frame structure). Record the new size,
2044 but don't reallocate the data structures now. Let that be done
2045 later outside of the signal handler. */
2048 Lisp_Object tail, frame;
2050 FOR_EACH_FRAME (tail, frame)
2052 if (FRAME_TERMCAP_P (XFRAME (frame)))
2054 change_frame_size (XFRAME (frame), height, width, 0, 1);
2055 break;
2060 signal (SIGWINCH, window_change_signal);
2061 errno = old_errno;
2063 #endif /* SIGWINCH */
2066 /* Do any change in frame size that was requested by a signal. */
2068 do_pending_window_change ()
2070 /* If window_change_signal should have run before, run it now. */
2071 while (delayed_size_change)
2073 Lisp_Object tail, frame;
2075 delayed_size_change = 0;
2077 FOR_EACH_FRAME (tail, frame)
2079 FRAME_PTR f = XFRAME (frame);
2081 int height = FRAME_NEW_HEIGHT (f);
2082 int width = FRAME_NEW_WIDTH (f);
2084 if (height != 0 || width != 0)
2085 change_frame_size (f, height, width, 0, 0);
2091 /* Change the frame height and/or width. Values may be given as zero to
2092 indicate no change is to take place.
2094 If DELAY is non-zero, then assume we're being called from a signal
2095 handler, and queue the change for later - perhaps the next
2096 redisplay. Since this tries to resize windows, we can't call it
2097 from a signal handler. */
2099 change_frame_size (f, newheight, newwidth, pretend, delay)
2100 register FRAME_PTR f;
2101 int newheight, newwidth, pretend;
2103 Lisp_Object tail, frame;
2104 if (FRAME_TERMCAP_P (f))
2106 /* When using termcap, all frames use the same screen,
2107 so a change in size affects all termcap frames. */
2108 FOR_EACH_FRAME (tail, frame)
2109 if (FRAME_TERMCAP_P (XFRAME (frame)))
2110 change_frame_size_1 (XFRAME (frame), newheight, newwidth,
2111 pretend, delay);
2113 else
2114 change_frame_size_1 (f, newheight, newwidth, pretend, delay);
2117 static void
2118 change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
2119 register FRAME_PTR frame;
2120 int newheight, newwidth, pretend, delay;
2122 /* If we can't deal with the change now, queue it for later. */
2123 if (delay)
2125 FRAME_NEW_HEIGHT (frame) = newheight;
2126 FRAME_NEW_WIDTH (frame) = newwidth;
2127 delayed_size_change = 1;
2128 return;
2131 /* This size-change overrides any pending one for this frame. */
2132 FRAME_NEW_HEIGHT (frame) = 0;
2133 FRAME_NEW_WIDTH (frame) = 0;
2135 /* If an argument is zero, set it to the current value. */
2136 newheight || (newheight = FRAME_HEIGHT (frame));
2137 newwidth || (newwidth = FRAME_WIDTH (frame));
2139 /* Round up to the smallest acceptable size. */
2140 check_frame_size (frame, &newheight, &newwidth);
2142 /* If we're not changing the frame size, quit now. */
2143 if (newheight == FRAME_HEIGHT (frame)
2144 && newwidth == FRAME_WIDTH (frame))
2145 return;
2147 if (newheight != FRAME_HEIGHT (frame))
2149 if (FRAME_HAS_MINIBUF_P (frame)
2150 && ! FRAME_MINIBUF_ONLY_P (frame))
2152 /* Frame has both root and minibuffer. */
2153 set_window_height (FRAME_ROOT_WINDOW (frame),
2154 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
2155 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
2156 newheight - 1);
2157 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
2159 else
2160 /* Frame has just one top-level window. */
2161 set_window_height (FRAME_ROOT_WINDOW (frame),
2162 newheight - FRAME_MENU_BAR_LINES (frame), 0);
2164 if (FRAME_TERMCAP_P (frame) && !pretend)
2165 FrameRows = newheight;
2167 #if 0
2168 if (frame->output_method == output_termcap)
2170 frame_height = newheight;
2171 if (!pretend)
2172 FrameRows = newheight;
2174 #endif
2177 if (newwidth != FRAME_WIDTH (frame))
2179 set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
2180 if (FRAME_HAS_MINIBUF_P (frame))
2181 set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
2183 if (FRAME_TERMCAP_P (frame) && !pretend)
2184 FrameCols = newwidth;
2185 #if 0
2186 if (frame->output_method == output_termcap)
2188 frame_width = newwidth;
2189 if (!pretend)
2190 FrameCols = newwidth;
2192 #endif
2195 FRAME_HEIGHT (frame) = newheight;
2196 FRAME_WIDTH (frame) = newwidth;
2198 if (FRAME_CURSOR_X (frame) >= FRAME_WIDTH (frame))
2199 FRAME_CURSOR_X (frame) = FRAME_WIDTH (frame) - 1;
2200 if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
2201 FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
2203 remake_frame_glyphs (frame);
2204 calculate_costs (frame);
2207 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2208 Ssend_string_to_terminal, 1, 1, 0,
2209 "Send STRING to the terminal without alteration.\n\
2210 Control characters in STRING will have terminal-dependent effects.")
2211 (str)
2212 Lisp_Object str;
2214 CHECK_STRING (str, 0);
2215 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
2216 fflush (stdout);
2217 if (termscript)
2219 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
2220 fflush (termscript);
2222 return Qnil;
2225 DEFUN ("ding", Fding, Sding, 0, 1, 0,
2226 "Beep, or flash the screen.\n\
2227 Also, unless an argument is given,\n\
2228 terminate any keyboard macro currently executing.")
2229 (arg)
2230 Lisp_Object arg;
2232 if (!NILP (arg))
2234 if (noninteractive)
2235 putchar (07);
2236 else
2237 ring_bell ();
2238 fflush (stdout);
2240 else
2241 bitch_at_user ();
2243 return Qnil;
2246 bitch_at_user ()
2248 if (noninteractive)
2249 putchar (07);
2250 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2251 error ("Keyboard macro terminated by a command ringing the bell");
2252 else
2253 ring_bell ();
2254 fflush (stdout);
2257 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
2258 "Pause, without updating display, for SECONDS seconds.\n\
2259 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2260 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2261 additional wait period, in milliseconds; this may be useful if your\n\
2262 Emacs was built without floating point support.\n\
2263 \(Not all operating systems support waiting for a fraction of a second.)")
2264 (seconds, milliseconds)
2265 Lisp_Object seconds, milliseconds;
2267 int sec, usec;
2269 if (NILP (milliseconds))
2270 XSETINT (milliseconds, 0);
2271 else
2272 CHECK_NUMBER (milliseconds, 1);
2273 usec = XINT (milliseconds) * 1000;
2275 #ifdef LISP_FLOAT_TYPE
2277 double duration = extract_float (seconds);
2278 sec = (int) duration;
2279 usec += (duration - sec) * 1000000;
2281 #else
2282 CHECK_NUMBER (seconds, 0);
2283 sec = XINT (seconds);
2284 #endif
2286 #ifndef EMACS_HAS_USECS
2287 if (sec == 0 && usec != 0)
2288 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
2289 #endif
2291 /* Assure that 0 <= usec < 1000000. */
2292 if (usec < 0)
2294 /* We can't rely on the rounding being correct if user is negative. */
2295 if (-1000000 < usec)
2296 sec--, usec += 1000000;
2297 else
2298 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
2300 else
2301 sec += usec / 1000000, usec %= 1000000;
2303 if (sec <= 0)
2304 return Qnil;
2307 Lisp_Object zero;
2309 XSETFASTINT (zero, 0);
2310 wait_reading_process_input (sec, usec, zero, 0);
2313 /* We should always have wait_reading_process_input; we have a dummy
2314 implementation for systems which don't support subprocesses. */
2315 #if 0
2316 /* No wait_reading_process_input */
2317 immediate_quit = 1;
2318 QUIT;
2320 #ifdef VMS
2321 sys_sleep (sec);
2322 #else /* not VMS */
2323 /* The reason this is done this way
2324 (rather than defined (H_S) && defined (H_T))
2325 is because the VMS preprocessor doesn't grok `defined' */
2326 #ifdef HAVE_SELECT
2327 EMACS_GET_TIME (end_time);
2328 EMACS_SET_SECS_USECS (timeout, sec, usec);
2329 EMACS_ADD_TIME (end_time, end_time, timeout);
2331 while (1)
2333 EMACS_GET_TIME (timeout);
2334 EMACS_SUB_TIME (timeout, end_time, timeout);
2335 if (EMACS_TIME_NEG_P (timeout)
2336 || !select (1, 0, 0, 0, &timeout))
2337 break;
2339 #else /* not HAVE_SELECT */
2340 sleep (sec);
2341 #endif /* HAVE_SELECT */
2342 #endif /* not VMS */
2344 immediate_quit = 0;
2345 #endif /* no subprocesses */
2347 return Qnil;
2350 /* This is just like wait_reading_process_input, except that
2351 it does the redisplay.
2353 It's also much like Fsit_for, except that it can be used for
2354 waiting for input as well. */
2356 Lisp_Object
2357 sit_for (sec, usec, reading, display)
2358 int sec, usec, reading, display;
2360 Lisp_Object read_kbd;
2362 if (detect_input_pending ())
2363 return Qnil;
2365 if (display)
2366 redisplay_preserve_echo_area ();
2368 if (sec == 0 && usec == 0)
2369 return Qt;
2371 #ifdef SIGIO
2372 gobble_input (0);
2373 #endif
2375 XSETINT (read_kbd, reading ? -1 : 1);
2376 wait_reading_process_input (sec, usec, read_kbd, display);
2379 /* wait_reading_process_input should always be available now; it is
2380 simulated in a simple way on systems that don't support
2381 subprocesses. */
2382 #if 0
2383 /* No wait_reading_process_input available. */
2384 immediate_quit = 1;
2385 QUIT;
2387 waitchannels = 1;
2388 #ifdef VMS
2389 input_wait_timeout (XINT (arg));
2390 #else /* not VMS */
2391 #ifndef HAVE_TIMEVAL
2392 timeout_sec = sec;
2393 select (1, &waitchannels, 0, 0, &timeout_sec);
2394 #else /* HAVE_TIMEVAL */
2395 timeout.tv_sec = sec;
2396 timeout.tv_usec = usec;
2397 select (1, &waitchannels, 0, 0, &timeout);
2398 #endif /* HAVE_TIMEVAL */
2399 #endif /* not VMS */
2401 immediate_quit = 0;
2402 #endif
2404 return detect_input_pending () ? Qnil : Qt;
2407 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
2408 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
2409 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2410 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2411 additional wait period, in milliseconds; this may be useful if your\n\
2412 Emacs was built without floating point support.\n\
2413 \(Not all operating systems support waiting for a fraction of a second.)\n\
2414 Optional third arg non-nil means don't redisplay, just wait for input.\n\
2415 Redisplay is preempted as always if input arrives, and does not happen\n\
2416 if input is available before it starts.\n\
2417 Value is t if waited the full time with no input arriving.")
2418 (seconds, milliseconds, nodisp)
2419 Lisp_Object seconds, milliseconds, nodisp;
2421 int sec, usec;
2423 if (NILP (milliseconds))
2424 XSETINT (milliseconds, 0);
2425 else
2426 CHECK_NUMBER (milliseconds, 1);
2427 usec = XINT (milliseconds) * 1000;
2429 #ifdef LISP_FLOAT_TYPE
2431 double duration = extract_float (seconds);
2432 sec = (int) duration;
2433 usec += (duration - sec) * 1000000;
2435 #else
2436 CHECK_NUMBER (seconds, 0);
2437 sec = XINT (seconds);
2438 #endif
2440 #ifndef EMACS_HAS_USECS
2441 if (usec != 0 && sec == 0)
2442 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
2443 #endif
2445 return sit_for (sec, usec, 0, NILP (nodisp));
2448 char *terminal_type;
2450 /* Initialization done when Emacs fork is started, before doing stty. */
2451 /* Determine terminal type and set terminal_driver */
2452 /* Then invoke its decoding routine to set up variables
2453 in the terminal package */
2455 init_display ()
2457 #ifdef HAVE_X_WINDOWS
2458 extern int display_arg;
2459 #endif
2461 meta_key = 0;
2462 inverse_video = 0;
2463 cursor_in_echo_area = 0;
2464 terminal_type = (char *) 0;
2466 /* Now is the time to initialize this; it's used by init_sys_modes
2467 during startup. */
2468 Vwindow_system = Qnil;
2470 /* If the user wants to use a window system, we shouldn't bother
2471 initializing the terminal. This is especially important when the
2472 terminal is so dumb that emacs gives up before and doesn't bother
2473 using the window system.
2475 If the DISPLAY environment variable is set, try to use X, and die
2476 with an error message if that doesn't work. */
2478 #ifdef HAVE_X_WINDOWS
2479 if (! display_arg)
2481 #ifdef VMS
2482 display_arg = (getenv ("DECW$DISPLAY") != 0);
2483 #else
2484 display_arg = (getenv ("DISPLAY") != 0);
2485 #endif
2488 if (!inhibit_window_system && display_arg)
2490 Vwindow_system = intern ("x");
2491 #ifdef HAVE_X11
2492 Vwindow_system_version = make_number (11);
2493 #else
2494 Vwindow_system_version = make_number (10);
2495 #endif
2496 return;
2498 #endif /* HAVE_X_WINDOWS */
2500 #ifdef HAVE_NTGUI
2501 if (!inhibit_window_system)
2503 Vwindow_system = intern ("win32");
2504 Vwindow_system_version = make_number (1);
2505 return;
2507 #endif /* HAVE_NTGUI */
2509 /* If no window system has been specified, try to use the terminal. */
2510 if (! isatty (0))
2512 fprintf (stderr, "emacs: standard input is not a tty\n");
2513 exit (1);
2516 /* Look at the TERM variable */
2517 terminal_type = (char *) getenv ("TERM");
2518 if (!terminal_type)
2520 #ifdef VMS
2521 fprintf (stderr, "Please specify your terminal type.\n\
2522 For types defined in VMS, use set term /device=TYPE.\n\
2523 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2524 \(The quotation marks are necessary since terminal types are lower case.)\n");
2525 #else
2526 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2527 #endif
2528 exit (1);
2531 #ifdef VMS
2532 /* VMS DCL tends to upcase things, so downcase term type.
2533 Hardly any uppercase letters in terminal types; should be none. */
2535 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2536 char *p;
2538 strcpy (new, terminal_type);
2540 for (p = new; *p; p++)
2541 if (isupper (*p))
2542 *p = tolower (*p);
2544 terminal_type = new;
2546 #endif
2548 term_init (terminal_type);
2550 remake_frame_glyphs (selected_frame);
2551 calculate_costs (selected_frame);
2553 /* X and Y coordinates of the cursor between updates. */
2554 FRAME_CURSOR_X (selected_frame) = 0;
2555 FRAME_CURSOR_Y (selected_frame) = 0;
2557 #ifdef SIGWINCH
2558 #ifndef CANNOT_DUMP
2559 if (initialized)
2560 #endif /* CANNOT_DUMP */
2561 signal (SIGWINCH, window_change_signal);
2562 #endif /* SIGWINCH */
2565 syms_of_display ()
2567 #ifdef MULTI_FRAME
2568 defsubr (&Sredraw_frame);
2569 #endif
2570 defsubr (&Sredraw_display);
2571 defsubr (&Sframe_or_buffer_changed_p);
2572 defsubr (&Sopen_termscript);
2573 defsubr (&Sding);
2574 defsubr (&Ssit_for);
2575 defsubr (&Ssleep_for);
2576 defsubr (&Ssend_string_to_terminal);
2578 frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
2579 staticpro (&frame_and_buffer_state);
2581 Qdisplay_table = intern ("display-table");
2582 staticpro (&Qdisplay_table);
2584 DEFVAR_INT ("baud-rate", &baud_rate,
2585 "*The output baud rate of the terminal.\n\
2586 On most systems, changing this value will affect the amount of padding\n\
2587 and the other strategic decisions made during redisplay.");
2588 DEFVAR_BOOL ("inverse-video", &inverse_video,
2589 "*Non-nil means invert the entire frame display.\n\
2590 This means everything is in inverse video which otherwise would not be.");
2591 DEFVAR_BOOL ("visible-bell", &visible_bell,
2592 "*Non-nil means try to flash the frame to represent a bell.");
2593 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
2594 "*Non-nil means no need to redraw entire frame after suspending.\n\
2595 A non-nil value is useful if the terminal can automatically preserve\n\
2596 Emacs's frame display when you reenter Emacs.\n\
2597 It is up to you to set this variable if your terminal can do that.");
2598 DEFVAR_LISP ("window-system", &Vwindow_system,
2599 "A symbol naming the window-system under which Emacs is running\n\
2600 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
2601 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2602 "The version number of the window system in use.\n\
2603 For X windows, this is 10 or 11.");
2604 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2605 "Non-nil means put cursor in minibuffer, at end of any message there.");
2606 DEFVAR_LISP ("glyph-table", &Vglyph_table,
2607 "Table defining how to output a glyph code to the frame.\n\
2608 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2609 Each element can be:\n\
2610 integer: a glyph code which this glyph is an alias for.\n\
2611 string: output this glyph using that string (not impl. in X windows).\n\
2612 nil: this glyph mod 256 is char code to output,\n\
2613 and this glyph / 256 is face code for X windows (see `face-id').");
2614 Vglyph_table = Qnil;
2616 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2617 "Display table to use for buffers that specify none.\n\
2618 See `buffer-display-table' for more information.");
2619 Vstandard_display_table = Qnil;
2621 /* Initialize `window-system', unless init_display already decided it. */
2622 #ifdef CANNOT_DUMP
2623 if (noninteractive)
2624 #endif
2626 Vwindow_system = Qnil;
2627 Vwindow_system_version = Qnil;