1 /* Updating of data structures for redisplay.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 1998
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
37 #include "termhooks.h"
38 /* cm.h must come after dispextern.h on Windows. */
39 #include "dispextern.h"
48 #include "intervals.h"
49 #include "blockinput.h"
53 /* I don't know why DEC Alpha OSF1 fail to compile this file if we
54 include the following file. */
55 /* #include "systty.h" */
56 #include "syssignal.h"
60 #endif /* HAVE_X_WINDOWS */
64 #endif /* HAVE_NTGUI */
66 /* Include systime.h after xterm.h to avoid double inclusion of time.h. */
71 #define max(a, b) ((a) > (b) ? (a) : (b))
72 #define min(a, b) ((a) < (b) ? (a) : (b))
73 #define minmax(floor, val, ceil) \
74 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
76 /* Get number of chars of output now in the buffer of a stdio stream.
77 This ought to be built in in stdio, but it isn't.
78 Some s- files override this because their stdio internals differ. */
79 #ifdef __GNU_LIBRARY__
80 /* The s- file might have overridden the definition with one that works for
81 the system's C library. But we are using the GNU C library, so this is
82 the right definition for every system. */
83 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
84 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
86 #undef PENDING_OUTPUT_COUNT
87 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
89 #else /* not __GNU_LIBRARY__ */
90 #ifndef PENDING_OUTPUT_COUNT
91 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
95 static void change_frame_size_1 ();
97 /* Nonzero upon entry to redisplay means do not assume anything about
98 current contents of actual terminal frame; clear and redraw it. */
102 /* Nonzero means last display completed. Zero means it was preempted. */
104 int display_completed
;
106 /* Lisp variable visible-bell; enables use of screen-flash
107 instead of audible bell. */
111 /* Invert the color of the whole frame, at a low level. */
115 /* Line speed of the terminal. */
119 /* nil or a symbol naming the window system under which emacs is
120 running ('x is the only current possibility). */
122 Lisp_Object Vwindow_system
;
124 /* Version number of X windows: 10, 11 or nil. */
125 Lisp_Object Vwindow_system_version
;
127 /* Vector of glyph definitions. Indexed by glyph number,
128 the contents are a string which is how to output the glyph.
130 If Vglyph_table is nil, a glyph is output by using its low 8 bits
131 as a character code. */
133 Lisp_Object Vglyph_table
;
135 /* Display table to use for vectors that don't specify their own. */
137 Lisp_Object Vstandard_display_table
;
139 /* Nonzero means reading single-character input with prompt
140 so put cursor on minibuffer after the prompt.
141 positive means at end of text in echo area;
142 negative means at beginning of line. */
143 int cursor_in_echo_area
;
145 Lisp_Object Qdisplay_table
;
147 /* The currently selected frame.
148 In a single-frame version, this variable always holds the address of
151 FRAME_PTR selected_frame
;
153 /* A frame which is not just a minibuffer, or 0 if there are no such
154 frames. This is usually the most recent such frame that was
155 selected. In a single-frame version, this variable always holds
156 the address of the_only_frame. */
157 FRAME_PTR last_nonminibuf_frame
;
159 /* This is a vector, made larger whenever it isn't large enough,
160 which is used inside `update_frame' to hold the old contents
161 of the FRAME_PHYS_LINES of the frame being updated. */
162 struct frame_glyphs
**ophys_lines
;
163 /* Length of vector currently allocated. */
164 int ophys_lines_length
;
166 FILE *termscript
; /* Stdio stream being used for copy of all output. */
168 struct cm Wcm
; /* Structure for info on cursor positioning */
170 int delayed_size_change
; /* 1 means SIGWINCH happened when not safe. */
172 DEFUN ("redraw-frame", Fredraw_frame
, Sredraw_frame
, 1, 1, 0,
173 "Clear frame FRAME and output again what is supposed to appear on it.")
179 CHECK_LIVE_FRAME (frame
, 0);
182 if (FRAME_MSDOS_P (f
))
183 set_terminal_modes ();
185 clear_frame_records (f
);
188 windows_or_buffers_changed
++;
189 /* Mark all windows as INaccurate,
190 so that every window will have its redisplay done. */
191 mark_window_display_accurate (FRAME_ROOT_WINDOW (f
), 0);
201 XSETFRAME (frame
, f
);
202 Fredraw_frame (frame
);
205 DEFUN ("redraw-display", Fredraw_display
, Sredraw_display
, 0, 0, "",
206 "Clear and redisplay all visible frames.")
209 Lisp_Object tail
, frame
;
211 FOR_EACH_FRAME (tail
, frame
)
212 if (FRAME_VISIBLE_P (XFRAME (frame
)))
213 Fredraw_frame (frame
);
218 /* This is used when frame_garbaged is set.
219 Redraw the individual frames marked as garbaged. */
222 redraw_garbaged_frames ()
224 Lisp_Object tail
, frame
;
226 FOR_EACH_FRAME (tail
, frame
)
227 if (FRAME_VISIBLE_P (XFRAME (frame
))
228 && FRAME_GARBAGED_P (XFRAME (frame
)))
229 Fredraw_frame (frame
);
233 static struct frame_glyphs
*
234 make_frame_glyphs (frame
, empty
)
235 register FRAME_PTR frame
;
239 register int width
= FRAME_WINDOW_WIDTH (frame
);
240 register int height
= FRAME_HEIGHT (frame
);
241 register struct frame_glyphs
*new
242 = (struct frame_glyphs
*) xmalloc (sizeof (struct frame_glyphs
));
244 SET_GLYPHS_FRAME (new, frame
);
245 new->height
= height
;
247 new->used
= (int *) xmalloc (height
* sizeof (int));
248 new->glyphs
= (GLYPH
**) xmalloc (height
* sizeof (GLYPH
*));
249 new->charstarts
= (int **) xmalloc (height
* sizeof (int *));
250 new->highlight
= (char *) xmalloc (height
* sizeof (char));
251 new->enable
= (char *) xmalloc (height
* sizeof (char));
252 bzero (new->enable
, height
* sizeof (char));
253 new->bufp
= (int *) xmalloc (height
* sizeof (int));
255 #ifdef HAVE_WINDOW_SYSTEM
256 if (FRAME_WINDOW_P (frame
))
258 new->top_left_x
= (short *) xmalloc (height
* sizeof (short));
259 new->top_left_y
= (short *) xmalloc (height
* sizeof (short));
260 new->pix_width
= (short *) xmalloc (height
* sizeof (short));
261 new->pix_height
= (short *) xmalloc (height
* sizeof (short));
262 new->max_ascent
= (short *) xmalloc (height
* sizeof (short));
264 #endif /* HAVE_WINDOW_SYSTEM */
268 /* Make the buffer used by decode_mode_spec. This buffer is also
269 used as temporary storage when updating the frame. See scroll.c. */
270 unsigned int total_glyphs
= (width
+ 2) * sizeof (GLYPH
);
271 unsigned int total_charstarts
= (width
+ 2) * sizeof (int);
273 new->total_contents
= (GLYPH
*) xmalloc (total_glyphs
);
274 bzero (new->total_contents
, total_glyphs
);
276 new->total_charstarts
= (int *) xmalloc (total_charstarts
);
277 bzero (new->total_charstarts
, total_charstarts
);
281 unsigned int total_glyphs
= height
* (width
+ 2) * sizeof (GLYPH
);
283 new->total_contents
= (GLYPH
*) xmalloc (total_glyphs
);
284 bzero (new->total_contents
, total_glyphs
);
285 for (i
= 0; i
< height
; i
++)
286 new->glyphs
[i
] = new->total_contents
+ i
* (width
+ 2) + 1;
288 if (!FRAME_TERMCAP_P (frame
))
290 unsigned int total_charstarts
= height
* (width
+ 2) * sizeof (int);
292 new->total_charstarts
= (int *) xmalloc (total_charstarts
);
293 bzero (new->total_charstarts
, total_charstarts
);
294 for (i
= 0; i
< height
; i
++)
295 new->charstarts
[i
] = new->total_charstarts
+ i
* (width
+ 2) + 1;
299 /* Without a window system, we don't really need charstarts.
300 So use a small amount of space to make enough data structure
301 to prevent crashes in display_text_line. */
302 new->total_charstarts
= (int *) xmalloc ((width
+ 2) * sizeof (int));
303 for (i
= 0; i
< height
; i
++)
304 new->charstarts
[i
] = new->total_charstarts
;
312 free_frame_glyphs (frame
, glyphs
)
314 struct frame_glyphs
*glyphs
;
316 if (glyphs
->total_contents
)
317 xfree (glyphs
->total_contents
);
318 if (glyphs
->total_charstarts
)
319 xfree (glyphs
->total_charstarts
);
321 xfree (glyphs
->used
);
322 xfree (glyphs
->glyphs
);
323 xfree (glyphs
->highlight
);
324 xfree (glyphs
->enable
);
325 xfree (glyphs
->bufp
);
326 if (glyphs
->charstarts
)
327 xfree (glyphs
->charstarts
);
329 #ifdef HAVE_WINDOW_SYSTEM
330 if (FRAME_WINDOW_P (frame
))
332 xfree (glyphs
->top_left_x
);
333 xfree (glyphs
->top_left_y
);
334 xfree (glyphs
->pix_width
);
335 xfree (glyphs
->pix_height
);
336 xfree (glyphs
->max_ascent
);
338 #endif /* HAVE_WINDOW_SYSTEM */
344 remake_frame_glyphs (frame
)
347 if (FRAME_CURRENT_GLYPHS (frame
))
348 free_frame_glyphs (frame
, FRAME_CURRENT_GLYPHS (frame
));
349 if (FRAME_DESIRED_GLYPHS (frame
))
350 free_frame_glyphs (frame
, FRAME_DESIRED_GLYPHS (frame
));
351 if (FRAME_TEMP_GLYPHS (frame
))
352 free_frame_glyphs (frame
, FRAME_TEMP_GLYPHS (frame
));
354 if (FRAME_MESSAGE_BUF (frame
))
356 /* Reallocate the frame's message buffer; remember that
357 echo_area_glyphs may be pointing here. */
358 char *old_message_buf
= FRAME_MESSAGE_BUF (frame
);
360 FRAME_MESSAGE_BUF (frame
)
361 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame
),
362 FRAME_MESSAGE_BUF_SIZE (frame
) + 1);
364 if (echo_area_glyphs
== old_message_buf
)
365 echo_area_glyphs
= FRAME_MESSAGE_BUF (frame
);
366 if (previous_echo_glyphs
== old_message_buf
)
367 previous_echo_glyphs
= FRAME_MESSAGE_BUF (frame
);
370 FRAME_MESSAGE_BUF (frame
)
371 = (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (frame
) + 1);
373 FRAME_CURRENT_GLYPHS (frame
) = make_frame_glyphs (frame
, 0);
374 FRAME_DESIRED_GLYPHS (frame
) = make_frame_glyphs (frame
, 0);
375 FRAME_TEMP_GLYPHS (frame
) = make_frame_glyphs (frame
, 1);
376 if (FRAME_WINDOW_P (frame
) || frame
== selected_frame
)
377 SET_FRAME_GARBAGED (frame
);
380 /* Return the hash code of contents of line VPOS in frame-matrix M. */
383 line_hash_code (m
, vpos
)
384 register struct frame_glyphs
*m
;
387 register GLYPH
*body
, *end
;
390 if (!m
->enable
[vpos
])
393 /* Give all highlighted lines the same hash code
394 so as to encourage scrolling to leave them in place. */
395 if (m
->highlight
[vpos
])
398 body
= m
->glyphs
[vpos
];
400 if (must_write_spaces
)
407 h
= (((h
<< 4) + (h
>> 24)) & 0x0fffffff) + g
- SPACEGLYPH
;
416 h
= (((h
<< 4) + (h
>> 24)) & 0x0fffffff) + g
;
424 /* Return number of characters in line in M at vpos VPOS,
425 except don't count leading and trailing spaces
426 unless the terminal requires those to be explicitly output. */
429 line_draw_cost (m
, vpos
)
430 struct frame_glyphs
*m
;
433 register GLYPH
*beg
= m
->glyphs
[vpos
];
434 register GLYPH
*end
= m
->glyphs
[vpos
] + m
->used
[vpos
];
436 register int tlen
= GLYPH_TABLE_LENGTH
;
437 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
439 /* Ignore trailing and leading spaces if we can. */
440 if (!must_write_spaces
)
442 while ((end
!= beg
) && (*end
== SPACEGLYPH
))
445 return (0); /* All blank line. */
447 while (*beg
== SPACEGLYPH
)
451 /* If we don't have a glyph-table, each glyph is one character,
452 so return the number of glyphs. */
456 /* Otherwise, scan the glyphs and accumulate their total size in I. */
458 while ((beg
<= end
) && *beg
)
460 register GLYPH g
= *beg
++;
462 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
465 i
+= GLYPH_LENGTH (tbase
, g
);
470 /* The functions on this page are the interface from xdisp.c to redisplay.
472 The only other interface into redisplay is through setting
473 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
474 and SET_FRAME_GARBAGED (frame). */
476 /* cancel_line eliminates any request to display a line at position `vpos' */
479 cancel_line (vpos
, frame
)
481 register FRAME_PTR frame
;
483 FRAME_DESIRED_GLYPHS (frame
)->enable
[vpos
] = 0;
487 clear_frame_records (frame
)
488 register FRAME_PTR frame
;
490 bzero (FRAME_CURRENT_GLYPHS (frame
)->enable
, FRAME_HEIGHT (frame
));
493 /* Clear out all display lines for a coming redisplay. */
496 init_desired_glyphs (frame
)
497 register FRAME_PTR frame
;
499 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (frame
);
501 int height
= FRAME_HEIGHT (frame
);
503 for (vpos
= 0; vpos
< height
; vpos
++)
504 desired_glyphs
->enable
[vpos
] = 0;
507 /* Prepare to display on line VPOS starting at HPOS within it. */
510 get_display_line (frame
, vpos
, hpos
)
511 register FRAME_PTR frame
;
515 register struct frame_glyphs
*glyphs
;
516 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (frame
);
522 if (! desired_glyphs
->enable
[vpos
])
524 desired_glyphs
->used
[vpos
] = 0;
525 desired_glyphs
->highlight
[vpos
] = 0;
526 desired_glyphs
->enable
[vpos
] = 1;
529 if (hpos
> desired_glyphs
->used
[vpos
])
531 GLYPH
*g
= desired_glyphs
->glyphs
[vpos
] + desired_glyphs
->used
[vpos
];
532 GLYPH
*end
= desired_glyphs
->glyphs
[vpos
] + hpos
;
534 desired_glyphs
->used
[vpos
] = hpos
;
540 /* Like bcopy except never gets confused by overlap. */
543 safe_bcopy (from
, to
, size
)
547 if (size
<= 0 || from
== to
)
550 /* If the source and destination don't overlap, then bcopy can
551 handle it. If they do overlap, but the destination is lower in
552 memory than the source, we'll assume bcopy can handle that. */
553 if (to
< from
|| from
+ size
<= to
)
554 bcopy (from
, to
, size
);
556 /* Otherwise, we'll copy from the end. */
559 register char *endf
= from
+ size
;
560 register char *endt
= to
+ size
;
562 /* If TO - FROM is large, then we should break the copy into
563 nonoverlapping chunks of TO - FROM bytes each. However, if
564 TO - FROM is small, then the bcopy function call overhead
565 makes this not worth it. The crossover point could be about
566 anywhere. Since I don't think the obvious copy loop is too
567 bad, I'm trying to err in its favor. */
572 while (endf
!= from
);
584 bcopy (endf
, endt
, to
- from
);
587 /* If SIZE wasn't a multiple of TO - FROM, there will be a
588 little left over. The amount left over is
589 (endt + (to - from)) - to, which is endt - from. */
590 bcopy (from
, to
, endt
- from
);
595 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
596 DISTANCE may be negative. */
599 rotate_vector (vector
, size
, distance
)
604 char *temp
= (char *) alloca (size
);
609 bcopy (vector
, temp
+ distance
, size
- distance
);
610 bcopy (vector
+ size
- distance
, temp
, distance
);
611 bcopy (temp
, vector
, size
);
614 /* Scroll lines from vpos FROM up to but not including vpos END
615 down by AMOUNT lines (AMOUNT may be negative).
616 Returns nonzero if done, zero if terminal cannot scroll them. */
619 scroll_frame_lines (frame
, from
, end
, amount
, newpos
)
620 register FRAME_PTR frame
;
621 int from
, end
, amount
, newpos
;
624 register struct frame_glyphs
*current_frame
625 = FRAME_CURRENT_GLYPHS (frame
);
627 int width
= FRAME_WINDOW_WIDTH (frame
);
629 if (!line_ins_del_ok
)
637 update_begin (frame
);
638 set_terminal_window (end
+ amount
);
639 if (!scroll_region_ok
)
640 ins_del_lines (end
, -amount
);
641 ins_del_lines (from
, amount
);
642 set_terminal_window (0);
644 rotate_vector (current_frame
->glyphs
+ from
,
645 sizeof (GLYPH
*) * (end
+ amount
- from
),
646 amount
* sizeof (GLYPH
*));
648 rotate_vector (current_frame
->charstarts
+ from
,
649 sizeof (int *) * (end
+ amount
- from
),
650 amount
* sizeof (int *));
652 safe_bcopy (current_frame
->used
+ from
,
653 current_frame
->used
+ from
+ amount
,
654 (end
- from
) * sizeof current_frame
->used
[0]);
656 safe_bcopy (current_frame
->highlight
+ from
,
657 current_frame
->highlight
+ from
+ amount
,
658 (end
- from
) * sizeof current_frame
->highlight
[0]);
660 safe_bcopy (current_frame
->enable
+ from
,
661 current_frame
->enable
+ from
+ amount
,
662 (end
- from
) * sizeof current_frame
->enable
[0]);
664 /* Adjust the lines by an amount
665 that puts the first of them at NEWPOS. */
666 pos_adjust
= newpos
- current_frame
->charstarts
[from
+ amount
][0];
668 /* Offset each char position in the charstarts lines we moved
670 for (i
= from
+ amount
; i
< end
+ amount
; i
++)
672 int *line
= current_frame
->charstarts
[i
];
674 for (col
= 0; col
< width
; col
++)
676 line
[col
] += pos_adjust
;
678 for (i
= from
; i
< from
+ amount
; i
++)
680 int *line
= current_frame
->charstarts
[i
];
683 for (col
= 0; col
< width
; col
++)
687 /* Mark the lines made empty by scrolling as enabled, empty and
689 bzero (current_frame
->used
+ from
,
690 amount
* sizeof current_frame
->used
[0]);
691 bzero (current_frame
->highlight
+ from
,
692 amount
* sizeof current_frame
->highlight
[0]);
693 for (i
= from
; i
< from
+ amount
; i
++)
695 current_frame
->glyphs
[i
][0] = '\0';
696 current_frame
->charstarts
[i
][0] = -1;
697 current_frame
->enable
[i
] = 1;
700 safe_bcopy (current_frame
->bufp
+ from
,
701 current_frame
->bufp
+ from
+ amount
,
702 (end
- from
) * sizeof current_frame
->bufp
[0]);
704 #ifdef HAVE_WINDOW_SYSTEM
705 if (FRAME_WINDOW_P (frame
))
707 safe_bcopy (current_frame
->top_left_x
+ from
,
708 current_frame
->top_left_x
+ from
+ amount
,
709 (end
- from
) * sizeof current_frame
->top_left_x
[0]);
711 safe_bcopy (current_frame
->top_left_y
+ from
,
712 current_frame
->top_left_y
+ from
+ amount
,
713 (end
- from
) * sizeof current_frame
->top_left_y
[0]);
715 safe_bcopy (current_frame
->pix_width
+ from
,
716 current_frame
->pix_width
+ from
+ amount
,
717 (end
- from
) * sizeof current_frame
->pix_width
[0]);
719 safe_bcopy (current_frame
->pix_height
+ from
,
720 current_frame
->pix_height
+ from
+ amount
,
721 (end
- from
) * sizeof current_frame
->pix_height
[0]);
723 safe_bcopy (current_frame
->max_ascent
+ from
,
724 current_frame
->max_ascent
+ from
+ amount
,
725 (end
- from
) * sizeof current_frame
->max_ascent
[0]);
727 #endif /* HAVE_WINDOW_SYSTEM */
733 update_begin (frame
);
734 set_terminal_window (end
);
735 ins_del_lines (from
+ amount
, amount
);
736 if (!scroll_region_ok
)
737 ins_del_lines (end
+ amount
, -amount
);
738 set_terminal_window (0);
740 rotate_vector (current_frame
->glyphs
+ from
+ amount
,
741 sizeof (GLYPH
*) * (end
- from
- amount
),
742 amount
* sizeof (GLYPH
*));
744 rotate_vector (current_frame
->charstarts
+ from
+ amount
,
745 sizeof (int *) * (end
- from
- amount
),
746 amount
* sizeof (int *));
748 safe_bcopy (current_frame
->used
+ from
,
749 current_frame
->used
+ from
+ amount
,
750 (end
- from
) * sizeof current_frame
->used
[0]);
752 safe_bcopy (current_frame
->highlight
+ from
,
753 current_frame
->highlight
+ from
+ amount
,
754 (end
- from
) * sizeof current_frame
->highlight
[0]);
756 safe_bcopy (current_frame
->enable
+ from
,
757 current_frame
->enable
+ from
+ amount
,
758 (end
- from
) * sizeof current_frame
->enable
[0]);
760 /* Adjust the lines by an amount
761 that puts the first of them at NEWPOS. */
762 pos_adjust
= newpos
- current_frame
->charstarts
[from
+ amount
][0];
764 /* Offset each char position in the charstarts lines we moved
766 for (i
= from
+ amount
; i
< end
+ amount
; i
++)
768 int *line
= current_frame
->charstarts
[i
];
770 for (col
= 0; col
< width
; col
++)
772 line
[col
] += pos_adjust
;
774 for (i
= end
+ amount
; i
< end
; i
++)
776 int *line
= current_frame
->charstarts
[i
];
779 for (col
= 0; col
< width
; col
++)
783 /* Mark the lines made empty by scrolling as enabled, empty and
785 bzero (current_frame
->used
+ end
+ amount
,
786 - amount
* sizeof current_frame
->used
[0]);
787 bzero (current_frame
->highlight
+ end
+ amount
,
788 - amount
* sizeof current_frame
->highlight
[0]);
789 for (i
= end
+ amount
; i
< end
; i
++)
791 current_frame
->glyphs
[i
][0] = '\0';
792 current_frame
->charstarts
[i
][0] = 0;
793 current_frame
->enable
[i
] = 1;
796 safe_bcopy (current_frame
->bufp
+ from
,
797 current_frame
->bufp
+ from
+ amount
,
798 (end
- from
) * sizeof current_frame
->bufp
[0]);
800 #ifdef HAVE_WINDOW_SYSTEM
801 if (FRAME_WINDOW_P (frame
))
803 safe_bcopy (current_frame
->top_left_x
+ from
,
804 current_frame
->top_left_x
+ from
+ amount
,
805 (end
- from
) * sizeof current_frame
->top_left_x
[0]);
807 safe_bcopy (current_frame
->top_left_y
+ from
,
808 current_frame
->top_left_y
+ from
+ amount
,
809 (end
- from
) * sizeof current_frame
->top_left_y
[0]);
811 safe_bcopy (current_frame
->pix_width
+ from
,
812 current_frame
->pix_width
+ from
+ amount
,
813 (end
- from
) * sizeof current_frame
->pix_width
[0]);
815 safe_bcopy (current_frame
->pix_height
+ from
,
816 current_frame
->pix_height
+ from
+ amount
,
817 (end
- from
) * sizeof current_frame
->pix_height
[0]);
819 safe_bcopy (current_frame
->max_ascent
+ from
,
820 current_frame
->max_ascent
+ from
+ amount
,
821 (end
- from
) * sizeof current_frame
->max_ascent
[0]);
823 #endif /* HAVE_WINDOW_SYSTEM */
830 /* After updating a window W that isn't the full frame wide,
831 copy all the columns that W does not occupy
832 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
833 so that update_frame will not change those columns. */
836 preserve_other_columns (w
)
840 register struct frame_glyphs
*current_frame
, *desired_frame
;
841 register FRAME_PTR frame
= XFRAME (w
->frame
);
842 int start
= WINDOW_LEFT_MARGIN (w
);
843 int end
= WINDOW_RIGHT_EDGE (w
);
844 int bot
= XFASTINT (w
->top
) + XFASTINT (w
->height
);
846 current_frame
= FRAME_CURRENT_GLYPHS (frame
);
847 desired_frame
= FRAME_DESIRED_GLYPHS (frame
);
849 for (vpos
= XFASTINT (w
->top
); vpos
< bot
; vpos
++)
851 if (current_frame
->enable
[vpos
] && desired_frame
->enable
[vpos
])
857 bcopy (current_frame
->glyphs
[vpos
],
858 desired_frame
->glyphs
[vpos
],
859 start
* sizeof (current_frame
->glyphs
[vpos
][0]));
860 bcopy (current_frame
->charstarts
[vpos
],
861 desired_frame
->charstarts
[vpos
],
862 start
* sizeof (current_frame
->charstarts
[vpos
][0]));
863 len
= min (start
, current_frame
->used
[vpos
]);
864 if (desired_frame
->used
[vpos
] < len
)
865 desired_frame
->used
[vpos
] = len
;
867 if (current_frame
->used
[vpos
] > end
868 && desired_frame
->used
[vpos
] < current_frame
->used
[vpos
])
870 while (desired_frame
->used
[vpos
] < end
)
872 int used
= desired_frame
->used
[vpos
]++;
873 desired_frame
->glyphs
[vpos
][used
] = SPACEGLYPH
;
874 desired_frame
->glyphs
[vpos
][used
] = 0;
876 bcopy (current_frame
->glyphs
[vpos
] + end
,
877 desired_frame
->glyphs
[vpos
] + end
,
878 ((current_frame
->used
[vpos
] - end
)
879 * sizeof (current_frame
->glyphs
[vpos
][0])));
880 bcopy (current_frame
->charstarts
[vpos
] + end
,
881 desired_frame
->charstarts
[vpos
] + end
,
882 ((current_frame
->used
[vpos
] - end
)
883 * sizeof (current_frame
->charstarts
[vpos
][0])));
884 desired_frame
->used
[vpos
] = current_frame
->used
[vpos
];
892 /* If window w does not need to be updated and isn't the full frame wide,
893 copy all the columns that w does occupy
894 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
895 so that update_frame will not change those columns.
897 Have not been able to figure out how to use this correctly. */
899 preserve_my_columns (w
)
902 register int vpos
, fin
;
903 register struct frame_glyphs
*l1
, *l2
;
904 register FRAME_PTR frame
= XFRAME (w
->frame
);
905 int start
= WINDOW_LEFT_MARGIN (w
);
906 int end
= WINDOW_RIGHT_EDGE (w
);
907 int bot
= XFASTINT (w
->top
) + XFASTINT (w
->height
);
909 for (vpos
= XFASTINT (w
->top
); vpos
< bot
; vpos
++)
911 if ((l1
= FRAME_DESIRED_GLYPHS (frame
)->glyphs
[vpos
+ 1])
912 && (l2
= FRAME_PHYS_GLYPHS (frame
)->glyphs
[vpos
+ 1]))
914 if (l2
->length
> start
&& l1
->length
< l2
->length
)
917 if (fin
> end
) fin
= end
;
918 while (l1
->length
< start
)
919 l1
->body
[l1
->length
++] = ' ';
920 bcopy (l2
->body
+ start
, l1
->body
+ start
, fin
- start
);
929 /* Adjust by ADJUST the charstart values in window W
930 after vpos VPOS, which counts relative to the frame
931 (not relative to W itself). */
934 adjust_window_charstarts (w
, vpos
, adjust
)
939 int left
= WINDOW_LEFT_MARGIN (w
);
940 int top
= XFASTINT (w
->top
);
941 int right
= left
+ window_internal_width (w
);
942 int bottom
= top
+ window_internal_height (w
);
945 for (i
= vpos
+ 1; i
< bottom
; i
++)
948 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[i
];
950 for (j
= left
; j
< right
; j
++)
951 if (charstart
[j
] > 0)
952 charstart
[j
] += adjust
;
956 /* Check the charstarts values in the area of window W
957 for internal consistency. We cannot check that they are "right";
958 we can only look for something nonsensical. */
961 verify_charstarts (w
)
964 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
966 int top
= XFASTINT (w
->top
);
967 int bottom
= top
+ window_internal_height (w
);
968 int left
= WINDOW_LEFT_MARGIN (w
);
969 int right
= left
+ window_internal_width (w
);
971 int truncate
= (XINT (w
->hscroll
)
972 || (truncate_partial_width_windows
973 && !WINDOW_FULL_WIDTH_P (w
))
974 || !NILP (XBUFFER (w
->buffer
)->truncate_lines
));
976 for (i
= top
; i
< bottom
; i
++)
980 int *charstart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[i
];
986 /* If we are truncating lines, allow a jump
987 in charstarts from one line to the next. */
988 if (charstart
[left
] < next_line
)
993 if (charstart
[left
] != next_line
)
998 for (j
= left
; j
< right
; j
++)
999 if (charstart
[j
] > 0)
1000 last
= charstart
[j
];
1001 /* Record where the next line should start. */
1003 if (BUF_ZV (XBUFFER (w
->buffer
)) != last
)
1005 /* If there's a newline between the two lines, count that. */
1006 int endchar
= *BUF_CHAR_ADDRESS (XBUFFER (w
->buffer
), last
);
1007 if (endchar
== '\n')
1013 /* On discovering that the redisplay for a window was no good,
1014 cancel the columns of that window, so that when the window is
1015 displayed over again get_display_line will not complain. */
1018 cancel_my_columns (w
)
1022 register struct frame_glyphs
*desired_glyphs
1023 = FRAME_DESIRED_GLYPHS (XFRAME (w
->frame
));
1024 register int start
= WINDOW_LEFT_MARGIN (w
);
1025 register int bot
= XFASTINT (w
->top
) + XFASTINT (w
->height
);
1027 for (vpos
= XFASTINT (w
->top
); vpos
< bot
; vpos
++)
1028 if (desired_glyphs
->enable
[vpos
]
1029 && desired_glyphs
->used
[vpos
] >= start
)
1030 desired_glyphs
->used
[vpos
] = start
;
1033 /* These functions try to perform directly and immediately on the frame
1034 the necessary output for one change in the buffer.
1035 They may return 0 meaning nothing was done if anything is difficult,
1036 or 1 meaning the output was performed properly.
1037 They assume that the frame was up to date before the buffer
1038 change being displayed. They make various other assumptions too;
1039 see command_loop_1 where these are called. */
1042 direct_output_for_insert (g
)
1045 register FRAME_PTR frame
= selected_frame
;
1046 register struct frame_glyphs
*current_frame
1047 = FRAME_CURRENT_GLYPHS (frame
);
1049 #ifndef COMPILER_REGISTER_BUG
1051 #endif /* COMPILER_REGISTER_BUG */
1052 struct window
*w
= XWINDOW (selected_window
);
1053 #ifndef COMPILER_REGISTER_BUG
1055 #endif /* COMPILER_REGISTER_BUG */
1056 int hpos
= FRAME_CURSOR_X (frame
);
1057 #ifndef COMPILER_REGISTER_BUG
1059 #endif /* COMPILER_REGISTER_BUG */
1060 int vpos
= FRAME_CURSOR_Y (frame
);
1062 /* Give up if about to continue line. */
1063 if (hpos
>= WINDOW_LEFT_MARGIN (w
) + window_internal_width (w
) - 1
1065 /* Avoid losing if cursor is in invisible text off left margin */
1066 || (XINT (w
->hscroll
) && hpos
== WINDOW_LEFT_MARGIN (w
))
1068 /* Give up if cursor outside window (in minibuf, probably) */
1069 || cursor_in_echo_area
1070 || FRAME_CURSOR_Y (frame
) < XFASTINT (w
->top
)
1071 || FRAME_CURSOR_Y (frame
) >= XFASTINT (w
->top
) + XFASTINT (w
->height
)
1073 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
1074 || !display_completed
1076 /* Give up if buffer appears in two places. */
1077 || buffer_shared
> 1
1079 #ifdef USE_TEXT_PROPERTIES
1080 /* Intervals have already been adjusted, point is after the
1081 character that was just inserted. */
1082 /* Give up if character is invisible. */
1083 /* Give up if character has a face property.
1084 At the moment we only lose at end of line or end of buffer
1085 and only with faces that have some background */
1086 /* Instead of wasting time, give up if character has any text properties */
1087 || ! NILP (Ftext_properties_at (make_number (PT
- 1), Qnil
))
1090 /* Give up if w is minibuffer and a message is being displayed there */
1091 || (MINI_WINDOW_P (w
) && echo_area_glyphs
))
1099 if (FRAME_WINDOW_P (frame
) || FRAME_MSDOS_P (frame
))
1100 face
= compute_char_face (frame
, w
, PT
- 1, -1, -1, &dummy
, PT
, 0);
1102 current_frame
->glyphs
[vpos
][hpos
] = MAKE_GLYPH (frame
, g
, face
);
1103 current_frame
->charstarts
[vpos
][hpos
] = PT
- 1;
1104 /* Record the entry for after the newly inserted character. */
1105 current_frame
->charstarts
[vpos
][hpos
+ 1] = PT
;
1106 adjust_window_charstarts (w
, vpos
, 1);
1108 unchanged_modified
= MODIFF
;
1109 beg_unchanged
= GPT
- BEG
;
1110 XSETFASTINT (w
->last_point
, PT
);
1111 XSETFASTINT (w
->last_point_x
, hpos
+ 1);
1112 XSETFASTINT (w
->last_modified
, MODIFF
);
1113 XSETFASTINT (w
->last_overlay_modified
, OVERLAY_MODIFF
);
1115 reassert_line_highlight (0, vpos
);
1116 write_glyphs (¤t_frame
->glyphs
[vpos
][hpos
], 1);
1118 ++FRAME_CURSOR_X (frame
);
1119 if (hpos
== current_frame
->used
[vpos
])
1121 current_frame
->used
[vpos
] = hpos
+ 1;
1122 current_frame
->glyphs
[vpos
][hpos
+ 1] = 0;
1129 direct_output_forward_char (n
)
1132 register FRAME_PTR frame
= selected_frame
;
1133 register struct window
*w
= XWINDOW (selected_window
);
1134 Lisp_Object position
;
1135 int hpos
= FRAME_CURSOR_X (frame
);
1137 /* Give up if in truncated text at end of line. */
1138 /* This check is not redundant. */
1139 if (hpos
>= WINDOW_LEFT_MARGIN (w
) + window_internal_width (w
) - 1)
1142 /* Give up if the buffer's direction is reversed (i.e. right-to-left). */
1143 if (!NILP (XBUFFER(w
->buffer
)->direction_reversed
))
1146 /* Avoid losing if cursor is in invisible text off left margin
1147 or about to go off either side of window. */
1148 if ((FRAME_CURSOR_X (frame
) == WINDOW_LEFT_MARGIN (w
)
1149 && (XINT (w
->hscroll
) || n
< 0))
1151 && (FRAME_CURSOR_X (frame
) + 1
1152 >= XFASTINT (w
->left
) + window_internal_width (w
) - 1))
1153 /* BUG FIX: Added "XFASTINT (w->left)". Without this,
1154 direct_output_forward_char() always fails on "the right"
1156 || cursor_in_echo_area
)
1159 /* Can't use direct output if highlighting a region. */
1160 if (!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1163 /* Can't use direct output at an overlay boundary; it might have
1164 before-string or after-string properties. */
1165 if (overlay_touches_p (PT
) || overlay_touches_p (PT
- n
))
1168 #ifdef USE_TEXT_PROPERTIES
1169 /* Don't use direct output next to an invisible character
1170 since we might need to do something special. */
1172 XSETFASTINT (position
, PT
);
1173 if (XFASTINT (position
) < ZV
1174 && ! NILP (Fget_char_property (position
,
1179 XSETFASTINT (position
, PT
- 1);
1180 if (XFASTINT (position
) >= BEGV
1181 && ! NILP (Fget_char_property (position
,
1187 FRAME_CURSOR_X (frame
) += n
;
1188 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (frame
));
1189 XSETFASTINT (w
->last_point
, PT
);
1190 cursor_to (FRAME_CURSOR_Y (frame
), FRAME_CURSOR_X (frame
));
1196 static void update_line ();
1198 /* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
1199 Value is nonzero if redisplay stopped due to pending input.
1200 FORCE nonzero means do not stop for pending input. */
1203 update_frame (f
, force
, inhibit_hairy_id
)
1206 int inhibit_hairy_id
;
1208 register struct frame_glyphs
*current_frame
;
1209 register struct frame_glyphs
*desired_frame
= 0;
1212 int preempt_count
= baud_rate
/ 2400 + 1;
1213 extern int input_pending
;
1214 #ifdef HAVE_WINDOW_SYSTEM
1215 register int downto
, leftmost
;
1218 if (baud_rate
!= FRAME_COST_BAUD_RATE (f
))
1219 calculate_costs (f
);
1221 if (preempt_count
<= 0)
1224 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1226 detect_input_pending ();
1227 if (input_pending
&& !force
)
1235 if (!line_ins_del_ok
)
1236 inhibit_hairy_id
= 1;
1238 /* These are separate to avoid a possible bug in the AIX C compiler. */
1239 current_frame
= FRAME_CURRENT_GLYPHS (f
);
1240 desired_frame
= FRAME_DESIRED_GLYPHS (f
);
1242 /* See if any of the desired lines are enabled; don't compute for
1243 i/d line if just want cursor motion. */
1244 for (i
= 0; i
< FRAME_HEIGHT (f
); i
++)
1245 if (desired_frame
->enable
[i
])
1248 /* Try doing i/d line, if not yet inhibited. */
1249 if (!inhibit_hairy_id
&& i
< FRAME_HEIGHT (f
))
1250 force
|= scrolling (f
);
1252 /* Update the individual lines as needed. Do bottom line first. */
1254 if (desired_frame
->enable
[FRAME_HEIGHT (f
) - 1])
1255 update_line (f
, FRAME_HEIGHT (f
) - 1);
1257 #ifdef HAVE_WINDOW_SYSTEM
1258 if (FRAME_WINDOW_P (f
))
1260 leftmost
= downto
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1261 if (desired_frame
->enable
[0])
1263 current_frame
->top_left_x
[FRAME_HEIGHT (f
) - 1] = leftmost
;
1264 current_frame
->top_left_y
[FRAME_HEIGHT (f
) - 1]
1265 = PIXEL_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
)
1266 - current_frame
->pix_height
[FRAME_HEIGHT (f
) - 1];
1267 current_frame
->top_left_x
[0] = leftmost
;
1268 current_frame
->top_left_y
[0] = downto
;
1271 #endif /* HAVE_WINDOW_SYSTEM */
1273 /* Now update the rest of the lines. */
1274 for (i
= 0; i
< FRAME_HEIGHT (f
) - 1 && (force
|| !input_pending
); i
++)
1276 if (desired_frame
->enable
[i
])
1278 if (FRAME_TERMCAP_P (f
))
1280 /* Flush out every so many lines.
1281 Also flush out if likely to have more than 1k buffered
1282 otherwise. I'm told that some telnet connections get
1283 really screwed by more than 1k output at once. */
1284 int outq
= PENDING_OUTPUT_COUNT (stdout
);
1286 || (outq
> 20 && ((i
- 1) % preempt_count
== 0)))
1289 if (preempt_count
== 1)
1291 #ifdef EMACS_OUTQSIZE
1292 if (EMACS_OUTQSIZE (0, &outq
) < 0)
1293 /* Probably not a tty. Ignore the error and reset
1294 * the outq count. */
1295 outq
= PENDING_OUTPUT_COUNT (stdout
);
1298 if (baud_rate
<= outq
&& baud_rate
> 0)
1299 sleep (outq
/ baud_rate
);
1304 if ((i
- 1) % preempt_count
== 0)
1305 detect_input_pending ();
1308 #ifdef HAVE_WINDOW_SYSTEM
1309 if (FRAME_WINDOW_P (f
))
1311 current_frame
->top_left_y
[i
] = downto
;
1312 current_frame
->top_left_x
[i
] = leftmost
;
1314 #endif /* HAVE_WINDOW_SYSTEM */
1317 #ifdef HAVE_WINDOW_SYSTEM
1318 if (FRAME_WINDOW_P (f
))
1319 downto
+= current_frame
->pix_height
[i
];
1320 #endif /* HAVE_WINDOW_SYSTEM */
1322 pause
= (i
< FRAME_HEIGHT (f
) - 1) ? i
: 0;
1324 /* Now just clean up termcap drivers and set cursor, etc. */
1327 if ((cursor_in_echo_area
1328 /* If we are showing a message instead of the minibuffer,
1329 show the cursor for the message instead of for the
1330 (now hidden) minibuffer contents. */
1331 || (EQ (minibuf_window
, selected_window
)
1332 && EQ (minibuf_window
, echo_area_window
)
1333 && echo_area_glyphs
!= 0))
1334 /* These cases apply only to the frame that contains
1335 the active minibuffer window. */
1336 && FRAME_HAS_MINIBUF_P (f
)
1337 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
1339 int top
= XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f
))->top
);
1342 if (cursor_in_echo_area
< 0)
1349 /* If the minibuffer is several lines high, find the last
1350 line that has any text on it. */
1351 row
= FRAME_HEIGHT (f
);
1355 if (current_frame
->enable
[row
])
1356 col
= current_frame
->used
[row
];
1360 while (row
> top
&& col
== 0);
1362 /* Make sure COL is not out of range. */
1363 if (col
>= FRAME_CURSOR_X_LIMIT (f
))
1365 /* If we have another row, advance cursor into it. */
1366 if (row
< FRAME_HEIGHT (f
) - 1)
1368 col
= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1371 /* Otherwise move it back in range. */
1373 col
= FRAME_CURSOR_X_LIMIT (f
) - 1;
1377 cursor_to (row
, col
);
1380 cursor_to (FRAME_CURSOR_Y (f
),
1381 minmax (0, FRAME_CURSOR_X (f
),
1382 FRAME_CURSOR_X_LIMIT (f
) - 1));
1388 fflush (termscript
);
1391 /* Here if output is preempted because input is detected. */
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
));
1401 /* Called when about to quit, to check for doing so
1402 at an improper time. */
1408 if (FRAME_DESIRED_GLYPHS (selected_frame
) == 0)
1410 if (FRAME_DESIRED_GLYPHS (selected_frame
)->enable
[0])
1412 if (FRAME_DESIRED_GLYPHS (selected_frame
)->enable
[FRAME_HEIGHT (selected_frame
) - 1])
1417 /* Decide what insert/delete line to do, and do it */
1419 extern void scrolling_1 ();
1425 int unchanged_at_top
, unchanged_at_bottom
;
1428 int *old_hash
= (int *) alloca (FRAME_HEIGHT (frame
) * sizeof (int));
1429 int *new_hash
= (int *) alloca (FRAME_HEIGHT (frame
) * sizeof (int));
1430 int *draw_cost
= (int *) alloca (FRAME_HEIGHT (frame
) * sizeof (int));
1431 int *old_draw_cost
= (int *) alloca (FRAME_HEIGHT (frame
) * sizeof (int));
1433 int free_at_end_vpos
= FRAME_HEIGHT (frame
);
1434 register struct frame_glyphs
*current_frame
= FRAME_CURRENT_GLYPHS (frame
);
1435 register struct frame_glyphs
*desired_frame
= FRAME_DESIRED_GLYPHS (frame
);
1437 /* Compute hash codes of all the lines.
1438 Also calculate number of changed lines,
1439 number of unchanged lines at the beginning,
1440 and number of unchanged lines at the end. */
1443 unchanged_at_top
= 0;
1444 unchanged_at_bottom
= FRAME_HEIGHT (frame
);
1445 for (i
= 0; i
< FRAME_HEIGHT (frame
); i
++)
1447 /* Give up on this scrolling if some old lines are not enabled. */
1448 if (!current_frame
->enable
[i
])
1450 old_hash
[i
] = line_hash_code (current_frame
, i
);
1451 if (! desired_frame
->enable
[i
])
1453 /* This line cannot be redrawn, so don't let scrolling mess it. */
1454 new_hash
[i
] = old_hash
[i
];
1455 #define INFINITY 1000000 /* Taken from scroll.c */
1456 draw_cost
[i
] = INFINITY
;
1460 new_hash
[i
] = line_hash_code (desired_frame
, i
);
1461 draw_cost
[i
] = line_draw_cost (desired_frame
, i
);
1464 if (old_hash
[i
] != new_hash
[i
])
1467 unchanged_at_bottom
= FRAME_HEIGHT (frame
) - i
- 1;
1469 else if (i
== unchanged_at_top
)
1471 old_draw_cost
[i
] = line_draw_cost (current_frame
, i
);
1474 /* If changed lines are few, don't allow preemption, don't scroll. */
1475 if (!scroll_region_ok
&& changed_lines
< baud_rate
/ 2400
1476 || unchanged_at_bottom
== FRAME_HEIGHT (frame
))
1479 window_size
= (FRAME_HEIGHT (frame
) - unchanged_at_top
1480 - unchanged_at_bottom
);
1482 if (scroll_region_ok
)
1483 free_at_end_vpos
-= unchanged_at_bottom
;
1484 else if (memory_below_frame
)
1485 free_at_end_vpos
= -1;
1487 /* If large window, fast terminal and few lines in common between
1488 current frame and desired frame, don't bother with i/d calc. */
1489 if (!scroll_region_ok
&& window_size
>= 18 && baud_rate
> 2400
1491 10 * scrolling_max_lines_saved (unchanged_at_top
,
1492 FRAME_HEIGHT (frame
) - unchanged_at_bottom
,
1493 old_hash
, new_hash
, draw_cost
)))
1496 scrolling_1 (frame
, window_size
, unchanged_at_top
, unchanged_at_bottom
,
1497 draw_cost
+ unchanged_at_top
- 1,
1498 old_draw_cost
+ unchanged_at_top
- 1,
1499 old_hash
+ unchanged_at_top
- 1,
1500 new_hash
+ unchanged_at_top
- 1,
1501 free_at_end_vpos
- unchanged_at_top
);
1506 /* Return the offset in its buffer of the character at location col, line
1507 in the given window. */
1509 buffer_posn_from_coords (window
, col
, line
)
1510 struct window
*window
;
1513 int hscroll
= XINT (window
->hscroll
);
1514 int window_left
= WINDOW_LEFT_MARGIN (window
);
1516 /* The actual width of the window is window->width less one for the
1517 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1519 int window_width
= window_internal_width (window
) - 1;
1521 int startp
= marker_position (window
->start
);
1523 /* Since compute_motion will only operate on the current buffer,
1524 we need to save the old one and restore it when we're done. */
1525 struct buffer
*old_current_buffer
= current_buffer
;
1526 struct position
*posn
;
1528 current_buffer
= XBUFFER (window
->buffer
);
1530 /* We can't get a correct result in this case,
1531 but at least prevent compute_motion from crashing. */
1535 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1536 (window->frame))->bufp to avoid scanning from the very top of
1537 the window, but it isn't maintained correctly, and I'm not even
1538 sure I will keep it. */
1539 posn
= compute_motion (startp
, 0,
1540 ((window
== XWINDOW (minibuf_window
) && startp
== BEG
1541 ? minibuf_prompt_width
: 0)
1542 + (hscroll
? 1 - hscroll
: 0)),
1545 window_width
, hscroll
, 0, window
);
1547 current_buffer
= old_current_buffer
;
1549 /* compute_motion considers frame points past the end of a line
1550 to be *after* the newline, i.e. at the start of the next line.
1551 This is reasonable, but not really what we want. So if the
1552 result is on a line below LINE, back it up one character. */
1553 if (posn
->vpos
> line
)
1554 return posn
->bufpos
- 1;
1556 return posn
->bufpos
;
1563 register GLYPH
*p
= r
;
1564 while (*p
++ == SPACEGLYPH
);
1569 count_match (str1
, str2
)
1572 register GLYPH
*p1
= str1
;
1573 register GLYPH
*p2
= str2
;
1574 while (*p1
++ == *p2
++);
1575 return p1
- str1
- 1;
1578 /* Char insertion/deletion cost vector, from term.c */
1579 extern int *char_ins_del_vector
;
1581 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
1584 update_line (frame
, vpos
)
1585 register FRAME_PTR frame
;
1588 register GLYPH
*obody
, *nbody
, *op1
, *op2
, *np1
, *temp
;
1591 int osp
, nsp
, begmatch
, endmatch
, olen
, nlen
;
1593 register struct frame_glyphs
*current_frame
1594 = FRAME_CURRENT_GLYPHS (frame
);
1595 register struct frame_glyphs
*desired_frame
1596 = FRAME_DESIRED_GLYPHS (frame
);
1598 if (desired_frame
->highlight
[vpos
]
1599 != (current_frame
->enable
[vpos
] && current_frame
->highlight
[vpos
]))
1601 change_line_highlight (desired_frame
->highlight
[vpos
], vpos
,
1602 (current_frame
->enable
[vpos
] ?
1603 current_frame
->used
[vpos
] : 0));
1604 current_frame
->enable
[vpos
] = 0;
1607 reassert_line_highlight (desired_frame
->highlight
[vpos
], vpos
);
1609 if (! current_frame
->enable
[vpos
])
1615 obody
= current_frame
->glyphs
[vpos
];
1616 olen
= current_frame
->used
[vpos
];
1617 if (! current_frame
->highlight
[vpos
])
1619 if (!must_write_spaces
)
1620 while (olen
> 0 && obody
[olen
- 1] == SPACEGLYPH
)
1625 /* For an inverse-video line, remember we gave it
1626 spaces all the way to the frame edge
1627 so that the reverse video extends all the way across. */
1629 while (olen
< FRAME_WINDOW_WIDTH (frame
) - 1)
1630 obody
[olen
++] = SPACEGLYPH
;
1634 /* One way or another, this will enable the line being updated. */
1635 current_frame
->enable
[vpos
] = 1;
1636 current_frame
->used
[vpos
] = desired_frame
->used
[vpos
];
1637 current_frame
->highlight
[vpos
] = desired_frame
->highlight
[vpos
];
1638 current_frame
->bufp
[vpos
] = desired_frame
->bufp
[vpos
];
1640 #ifdef HAVE_WINDOW_SYSTEM
1641 if (FRAME_WINDOW_P (frame
))
1643 current_frame
->pix_width
[vpos
]
1644 = current_frame
->used
[vpos
]
1645 * FONT_WIDTH (FRAME_FONT (frame
));
1646 current_frame
->pix_height
[vpos
]
1647 = FRAME_LINE_HEIGHT (frame
);
1649 #endif /* HAVE_WINDOW_SYSTEM */
1651 if (!desired_frame
->enable
[vpos
])
1657 nbody
= desired_frame
->glyphs
[vpos
];
1658 nlen
= desired_frame
->used
[vpos
];
1660 /* Pretend trailing spaces are not there at all,
1661 unless for one reason or another we must write all spaces. */
1662 if (! desired_frame
->highlight
[vpos
])
1664 if (!must_write_spaces
)
1665 /* We know that the previous character byte contains 0. */
1666 while (nbody
[nlen
- 1] == SPACEGLYPH
)
1671 /* For an inverse-video line, give it extra trailing spaces
1672 all the way to the frame edge
1673 so that the reverse video extends all the way across. */
1675 while (nlen
< FRAME_WINDOW_WIDTH (frame
) - 1)
1676 nbody
[nlen
++] = SPACEGLYPH
;
1679 /* If there's no i/d char, quickly do the best we can without it. */
1680 if (!char_ins_del_ok
)
1685 if (FRAME_X_P (frame
))
1687 /* Under X, erase everything we are going to rewrite,
1688 and rewrite everything from the first char that's changed.
1689 This is part of supporting fonts like Courier
1690 whose chars can overlap outside the char width. */
1691 for (i
= 0; i
< nlen
; i
++)
1692 if (i
>= olen
|| nbody
[i
] != obody
[i
])
1695 cursor_to (vpos
, i
);
1697 clear_end_of_line (olen
);
1698 write_glyphs (nbody
+ i
, nlen
- i
);
1703 for (i
= 0; i
< nlen
; i
++)
1705 if (i
>= olen
|| nbody
[i
] != obody
[i
]) /* A non-matching char. */
1707 cursor_to (vpos
, i
);
1710 && (i
+ j
>= olen
|| nbody
[i
+ j
] != obody
[i
+ j
]
1711 || (nbody
[i
+ j
] & GLYPH_MASK_PADDING
)));
1714 /* Output this run of non-matching chars. */
1715 write_glyphs (nbody
+ i
, j
);
1718 /* Now find the next non-match. */
1722 /* Clear the rest of the line, or the non-clear part of it. */
1725 cursor_to (vpos
, nlen
);
1726 clear_end_of_line (olen
);
1729 /* Exchange contents between current_frame and new_frame. */
1730 temp
= desired_frame
->glyphs
[vpos
];
1731 desired_frame
->glyphs
[vpos
] = current_frame
->glyphs
[vpos
];
1732 current_frame
->glyphs
[vpos
] = temp
;
1734 /* Exchange charstarts between current_frame and new_frame. */
1735 temp1
= desired_frame
->charstarts
[vpos
];
1736 desired_frame
->charstarts
[vpos
] = current_frame
->charstarts
[vpos
];
1737 current_frame
->charstarts
[vpos
] = temp1
;
1744 nsp
= (must_write_spaces
|| desired_frame
->highlight
[vpos
])
1745 ? 0 : count_blanks (nbody
);
1748 cursor_to (vpos
, nsp
);
1749 write_glyphs (nbody
+ nsp
, nlen
- nsp
);
1752 /* Exchange contents between current_frame and new_frame. */
1753 temp
= desired_frame
->glyphs
[vpos
];
1754 desired_frame
->glyphs
[vpos
] = current_frame
->glyphs
[vpos
];
1755 current_frame
->glyphs
[vpos
] = temp
;
1757 /* Exchange charstarts between current_frame and new_frame. */
1758 temp1
= desired_frame
->charstarts
[vpos
];
1759 desired_frame
->charstarts
[vpos
] = current_frame
->charstarts
[vpos
];
1760 current_frame
->charstarts
[vpos
] = temp1
;
1769 /* Compute number of leading blanks in old and new contents. */
1770 osp
= count_blanks (obody
);
1771 if (!desired_frame
->highlight
[vpos
])
1772 nsp
= count_blanks (nbody
);
1776 /* Compute number of matching chars starting with first nonblank. */
1777 begmatch
= count_match (obody
+ osp
, nbody
+ nsp
);
1779 /* Spaces in new match implicit space past the end of old. */
1780 /* A bug causing this to be a no-op was fixed in 18.29. */
1781 if (!must_write_spaces
&& osp
+ begmatch
== olen
)
1784 while (np1
[begmatch
] == SPACEGLYPH
)
1788 /* Avoid doing insert/delete char
1789 just cause number of leading spaces differs
1790 when the following text does not match. */
1791 if (begmatch
== 0 && osp
!= nsp
)
1792 osp
= nsp
= min (osp
, nsp
);
1794 /* Find matching characters at end of line */
1797 op2
= op1
+ begmatch
- min (olen
- osp
, nlen
- nsp
);
1798 while (op1
> op2
&& op1
[-1] == np1
[-1])
1803 endmatch
= obody
+ olen
- op1
;
1805 /* Put correct value back in nbody[nlen].
1806 This is important because direct_output_for_insert
1807 can write into the line at a later point.
1808 If this screws up the zero at the end of the line, re-establish it. */
1812 /* tem gets the distance to insert or delete.
1813 endmatch is how many characters we save by doing so.
1816 tem
= (nlen
- nsp
) - (olen
- osp
);
1818 && (!char_ins_del_ok
|| endmatch
<= char_ins_del_cost (frame
)[tem
]))
1821 /* nsp - osp is the distance to insert or delete.
1822 If that is nonzero, begmatch is known to be nonzero also.
1823 begmatch + endmatch is how much we save by doing the ins/del.
1827 && (!char_ins_del_ok
1828 || begmatch
+ endmatch
<= char_ins_del_cost (frame
)[nsp
- osp
]))
1832 osp
= nsp
= min (osp
, nsp
);
1835 /* Now go through the line, inserting, writing and
1836 deleting as appropriate. */
1840 cursor_to (vpos
, nsp
);
1841 delete_glyphs (osp
- nsp
);
1845 /* If going to delete chars later in line
1846 and insert earlier in the line,
1847 must delete first to avoid losing data in the insert */
1848 if (endmatch
&& nlen
< olen
+ nsp
- osp
)
1850 cursor_to (vpos
, nlen
- endmatch
+ osp
- nsp
);
1851 delete_glyphs (olen
+ nsp
- osp
- nlen
);
1852 olen
= nlen
- (nsp
- osp
);
1854 cursor_to (vpos
, osp
);
1855 insert_glyphs ((GLYPH
*) 0, nsp
- osp
);
1859 tem
= nsp
+ begmatch
+ endmatch
;
1860 if (nlen
!= tem
|| olen
!= tem
)
1862 cursor_to (vpos
, nsp
+ begmatch
);
1863 if (!endmatch
|| nlen
== olen
)
1865 /* If new text being written reaches right margin,
1866 there is no need to do clear-to-eol at the end.
1867 (and it would not be safe, since cursor is not
1868 going to be "at the margin" after the text is done) */
1869 if (nlen
== FRAME_WINDOW_WIDTH (frame
))
1871 write_glyphs (nbody
+ nsp
+ begmatch
, nlen
- tem
);
1875 /* the following code loses disastrously if tem == nlen.
1876 Rather than trying to fix that case, I am trying the simpler
1877 solution found above. */
1879 /* If the text reaches to the right margin,
1880 it will lose one way or another (depending on AutoWrap)
1881 to clear to end of line after outputting all the text.
1882 So pause with one character to go and clear the line then. */
1883 if (nlen
== FRAME_WINDOW_WIDTH (frame
) && fast_clear_end_of_line
&& olen
> nlen
)
1885 /* endmatch must be zero, and tem must equal nsp + begmatch */
1886 write_glyphs (nbody
+ tem
, nlen
- tem
- 1);
1887 clear_end_of_line (olen
);
1888 olen
= 0; /* Don't let it be cleared again later */
1889 write_glyphs (nbody
+ nlen
- 1, 1);
1892 write_glyphs (nbody
+ nsp
+ begmatch
, nlen
- tem
);
1893 #endif /* OBSOLETE */
1896 else if (nlen
> olen
)
1898 /* Here, we used to have the following simple code:
1899 ----------------------------------------
1900 write_glyphs (nbody + nsp + begmatch, olen - tem);
1901 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1902 ----------------------------------------
1903 but it doesn't work if nbody[nsp + begmatch + olen - tem]
1904 is a padding glyph. */
1905 int out
= olen
- tem
; /* Columns to be overwritten originally. */
1908 /* Calculate columns we can actually overwrite. */
1909 while (nbody
[nsp
+ begmatch
+ out
] & GLYPH_MASK_PADDING
) out
--;
1910 write_glyphs (nbody
+ nsp
+ begmatch
, out
);
1911 /* If we left columns to be overwritten. we must delete them. */
1912 del
= olen
- tem
- out
;
1913 if (del
> 0) delete_glyphs (del
);
1914 /* At last, we insert columns not yet written out. */
1915 insert_glyphs (nbody
+ nsp
+ begmatch
+ out
, nlen
- olen
+ del
);
1918 else if (olen
> nlen
)
1920 write_glyphs (nbody
+ nsp
+ begmatch
, nlen
- tem
);
1921 delete_glyphs (olen
- nlen
);
1927 /* If any unerased characters remain after the new line, erase them. */
1930 cursor_to (vpos
, nlen
);
1931 clear_end_of_line (olen
);
1934 /* Exchange contents between current_frame and new_frame. */
1935 temp
= desired_frame
->glyphs
[vpos
];
1936 desired_frame
->glyphs
[vpos
] = current_frame
->glyphs
[vpos
];
1937 current_frame
->glyphs
[vpos
] = temp
;
1939 /* Exchange charstarts between current_frame and new_frame. */
1940 temp1
= desired_frame
->charstarts
[vpos
];
1941 desired_frame
->charstarts
[vpos
] = current_frame
->charstarts
[vpos
];
1942 current_frame
->charstarts
[vpos
] = temp1
;
1945 /* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
1946 session's frames, frame names, buffers, buffer-read-only flags, and
1947 buffer-modified-flags, and a trailing sentinel (so we don't need to
1948 add length checks). */
1949 static Lisp_Object frame_and_buffer_state
;
1951 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p
,
1952 Sframe_or_buffer_changed_p
, 0, 0, 0,
1953 "Return non-nil if the frame and buffer state appears to have changed.\n\
1954 The state variable is an internal vector containing all frames and buffers,\n\
1955 aside from buffers whose names start with space,\n\
1956 along with the buffers' read-only and modified flags, which allows a fast\n\
1957 check to see whether the menu bars might need to be recomputed.\n\
1958 If this function returns non-nil, it updates the internal vector to reflect\n\
1959 the current state.\n")
1962 Lisp_Object tail
, frame
, buf
;
1966 vecp
= XVECTOR (frame_and_buffer_state
)->contents
;
1967 FOR_EACH_FRAME (tail
, frame
)
1969 if (!EQ (*vecp
++, frame
))
1971 if (!EQ (*vecp
++, XFRAME (frame
)->name
))
1974 /* Check that the buffer info matches.
1975 No need to test for the end of the vector
1976 because the last element of the vector is lambda
1977 and that will always cause a mismatch. */
1978 for (tail
= Vbuffer_alist
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1980 buf
= XCONS (XCONS (tail
)->car
)->cdr
;
1981 /* Ignore buffers that aren't included in buffer lists. */
1982 if (XSTRING (XBUFFER (buf
)->name
)->data
[0] == ' ')
1984 if (!EQ (*vecp
++, buf
))
1986 if (!EQ (*vecp
++, XBUFFER (buf
)->read_only
))
1988 if (!EQ (*vecp
++, Fbuffer_modified_p (buf
)))
1991 /* Detect deletion of a buffer at the end of the list. */
1992 if (EQ (*vecp
, Qlambda
))
1995 /* Start with 1 so there is room for at least one lambda at the end. */
1997 FOR_EACH_FRAME (tail
, frame
)
1999 for (tail
= Vbuffer_alist
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
2001 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
2002 if (n
> XVECTOR (frame_and_buffer_state
)->size
2003 || n
+ 20 < XVECTOR (frame_and_buffer_state
)->size
/ 2)
2004 /* Add 20 extra so we grow it less often. */
2005 frame_and_buffer_state
= Fmake_vector (make_number (n
+ 20), Qlambda
);
2006 vecp
= XVECTOR (frame_and_buffer_state
)->contents
;
2007 FOR_EACH_FRAME (tail
, frame
)
2010 *vecp
++ = XFRAME (frame
)->name
;
2012 for (tail
= Vbuffer_alist
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
2014 buf
= XCONS (XCONS (tail
)->car
)->cdr
;
2015 /* Ignore buffers that aren't included in buffer lists. */
2016 if (XSTRING (XBUFFER (buf
)->name
)->data
[0] == ' ')
2019 *vecp
++ = XBUFFER (buf
)->read_only
;
2020 *vecp
++ = Fbuffer_modified_p (buf
);
2022 /* Fill up the vector with lambdas (always at least one). */
2024 while (vecp
- XVECTOR (frame_and_buffer_state
)->contents
2025 < XVECTOR (frame_and_buffer_state
)->size
)
2027 /* Make sure we didn't overflow the vector. */
2028 if (vecp
- XVECTOR (frame_and_buffer_state
)->contents
2029 > XVECTOR (frame_and_buffer_state
)->size
)
2034 DEFUN ("open-termscript", Fopen_termscript
, Sopen_termscript
,
2035 1, 1, "FOpen termscript file: ",
2036 "Start writing all terminal output to FILE as well as the terminal.\n\
2037 FILE = nil means just close any termscript file currently open.")
2041 if (termscript
!= 0) fclose (termscript
);
2046 file
= Fexpand_file_name (file
, Qnil
);
2047 termscript
= fopen (XSTRING (file
)->data
, "w");
2048 if (termscript
== 0)
2049 report_file_error ("Opening termscript", Fcons (file
, Qnil
));
2057 window_change_signal (signalnum
) /* If we don't have an argument, */
2058 int signalnum
; /* some compilers complain in signal calls. */
2062 int old_errno
= errno
;
2064 get_frame_size (&width
, &height
);
2066 /* The frame size change obviously applies to a termcap-controlled
2067 frame. Find such a frame in the list, and assume it's the only
2068 one (since the redisplay code always writes to stdout, not a
2069 FILE * specified in the frame structure). Record the new size,
2070 but don't reallocate the data structures now. Let that be done
2071 later outside of the signal handler. */
2074 Lisp_Object tail
, frame
;
2076 FOR_EACH_FRAME (tail
, frame
)
2078 if (FRAME_TERMCAP_P (XFRAME (frame
)))
2080 change_frame_size (XFRAME (frame
), height
, width
, 0, 1);
2086 signal (SIGWINCH
, window_change_signal
);
2089 #endif /* SIGWINCH */
2092 /* Do any change in frame size that was requested by a signal. */
2095 do_pending_window_change ()
2097 /* If window_change_signal should have run before, run it now. */
2098 while (delayed_size_change
)
2100 Lisp_Object tail
, frame
;
2102 delayed_size_change
= 0;
2104 FOR_EACH_FRAME (tail
, frame
)
2106 FRAME_PTR f
= XFRAME (frame
);
2108 int height
= FRAME_NEW_HEIGHT (f
);
2109 int width
= FRAME_NEW_WIDTH (f
);
2111 if (height
!= 0 || width
!= 0)
2112 change_frame_size (f
, height
, width
, 0, 0);
2118 /* Change the frame height and/or width. Values may be given as zero to
2119 indicate no change is to take place.
2121 If DELAY is non-zero, then assume we're being called from a signal
2122 handler, and queue the change for later - perhaps the next
2123 redisplay. Since this tries to resize windows, we can't call it
2124 from a signal handler. */
2127 change_frame_size (f
, newheight
, newwidth
, pretend
, delay
)
2128 register FRAME_PTR f
;
2129 int newheight
, newwidth
, pretend
, delay
;
2131 Lisp_Object tail
, frame
;
2133 if (! FRAME_WINDOW_P (f
))
2135 /* When using termcap, or on MS-DOS, all frames use
2136 the same screen, so a change in size affects all frames. */
2137 FOR_EACH_FRAME (tail
, frame
)
2138 if (! FRAME_WINDOW_P (XFRAME (frame
)))
2139 change_frame_size_1 (XFRAME (frame
), newheight
, newwidth
,
2143 change_frame_size_1 (f
, newheight
, newwidth
, pretend
, delay
);
2147 change_frame_size_1 (frame
, newheight
, newwidth
, pretend
, delay
)
2148 register FRAME_PTR frame
;
2149 int newheight
, newwidth
, pretend
, delay
;
2151 int new_frame_window_width
;
2152 unsigned int total_glyphs
;
2153 int count
= specpdl_ptr
- specpdl
;
2155 /* If we can't deal with the change now, queue it for later. */
2158 FRAME_NEW_HEIGHT (frame
) = newheight
;
2159 FRAME_NEW_WIDTH (frame
) = newwidth
;
2160 delayed_size_change
= 1;
2164 /* This size-change overrides any pending one for this frame. */
2165 FRAME_NEW_HEIGHT (frame
) = 0;
2166 FRAME_NEW_WIDTH (frame
) = 0;
2168 /* If an argument is zero, set it to the current value. */
2170 newheight
= FRAME_HEIGHT (frame
);
2172 newwidth
= FRAME_WIDTH (frame
);
2173 new_frame_window_width
= FRAME_WINDOW_WIDTH_ARG (frame
, newwidth
);
2175 total_glyphs
= newheight
* (newwidth
+ 2) * sizeof (GLYPH
);
2177 /* If these sizes are so big they cause overflow,
2178 just ignore the change. It's not clear what better we could do. */
2179 if (total_glyphs
/ sizeof (GLYPH
) / newheight
!= newwidth
+ 2)
2182 /* Round up to the smallest acceptable size. */
2183 check_frame_size (frame
, &newheight
, &newwidth
);
2185 /* If we're not changing the frame size, quit now. */
2186 if (newheight
== FRAME_HEIGHT (frame
)
2187 && new_frame_window_width
== FRAME_WINDOW_WIDTH (frame
))
2193 /* We only can set screen dimensions to certain values supported
2194 by our video hardware. Try to find the smallest size greater
2195 or equal to the requested dimensions. */
2196 dos_set_window_size (&newheight
, &newwidth
);
2199 if (newheight
!= FRAME_HEIGHT (frame
))
2201 if (FRAME_HAS_MINIBUF_P (frame
)
2202 && ! FRAME_MINIBUF_ONLY_P (frame
))
2204 /* Frame has both root and minibuffer. */
2205 set_window_height (FRAME_ROOT_WINDOW (frame
),
2206 newheight
- 1 - FRAME_MENU_BAR_LINES (frame
), 0);
2207 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame
))->top
,
2209 set_window_height (FRAME_MINIBUF_WINDOW (frame
), 1, 0);
2212 /* Frame has just one top-level window. */
2213 set_window_height (FRAME_ROOT_WINDOW (frame
),
2214 newheight
- FRAME_MENU_BAR_LINES (frame
), 0);
2216 if (FRAME_TERMCAP_P (frame
) && !pretend
)
2217 FrameRows
= newheight
;
2220 if (frame
->output_method
== output_termcap
)
2222 frame_height
= newheight
;
2224 FrameRows
= newheight
;
2229 if (new_frame_window_width
!= FRAME_WINDOW_WIDTH (frame
))
2231 set_window_width (FRAME_ROOT_WINDOW (frame
), new_frame_window_width
, 0);
2232 if (FRAME_HAS_MINIBUF_P (frame
))
2233 set_window_width (FRAME_MINIBUF_WINDOW (frame
), new_frame_window_width
, 0);
2235 if (FRAME_TERMCAP_P (frame
) && !pretend
)
2236 FrameCols
= newwidth
;
2238 if (frame
->output_method
== output_termcap
)
2240 frame_width
= newwidth
;
2242 FrameCols
= newwidth
;
2247 FRAME_HEIGHT (frame
) = newheight
;
2248 SET_FRAME_WIDTH (frame
, newwidth
);
2250 if (FRAME_CURSOR_X (frame
) >= FRAME_CURSOR_X_LIMIT (frame
))
2251 FRAME_CURSOR_X (frame
) = FRAME_CURSOR_X_LIMIT (frame
) - 1;
2252 if (FRAME_CURSOR_Y (frame
) >= FRAME_HEIGHT (frame
))
2253 FRAME_CURSOR_Y (frame
) = FRAME_HEIGHT (frame
) - 1;
2255 remake_frame_glyphs (frame
);
2256 calculate_costs (frame
);
2260 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
2262 /* This isn't quite a no-op: it runs window-configuration-change-hook. */
2263 Fset_window_buffer (FRAME_SELECTED_WINDOW (frame
),
2264 XWINDOW (FRAME_SELECTED_WINDOW (frame
))->buffer
);
2266 unbind_to (count
, Qnil
);
2269 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal
,
2270 Ssend_string_to_terminal
, 1, 1, 0,
2271 "Send STRING to the terminal without alteration.\n\
2272 Control characters in STRING will have terminal-dependent effects.")
2276 /* ??? Perhaps we should do something special for multibyte strings here. */
2277 CHECK_STRING (string
, 0);
2278 fwrite (XSTRING (string
)->data
, 1, STRING_BYTES (XSTRING (string
)), stdout
);
2282 fwrite (XSTRING (string
)->data
, 1, STRING_BYTES (XSTRING (string
)),
2284 fflush (termscript
);
2289 DEFUN ("ding", Fding
, Sding
, 0, 1, 0,
2290 "Beep, or flash the screen.\n\
2291 Also, unless an argument is given,\n\
2292 terminate any keyboard macro currently executing.")
2315 else if (!INTERACTIVE
) /* Stop executing a keyboard macro. */
2316 error ("Keyboard macro terminated by a command ringing the bell");
2322 DEFUN ("sleep-for", Fsleep_for
, Ssleep_for
, 1, 2, 0,
2323 "Pause, without updating display, for SECONDS seconds.\n\
2324 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2325 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2326 additional wait period, in milliseconds; this may be useful if your\n\
2327 Emacs was built without floating point support.\n\
2328 \(Not all operating systems support waiting for a fraction of a second.)")
2329 (seconds
, milliseconds
)
2330 Lisp_Object seconds
, milliseconds
;
2334 if (NILP (milliseconds
))
2335 XSETINT (milliseconds
, 0);
2337 CHECK_NUMBER (milliseconds
, 1);
2338 usec
= XINT (milliseconds
) * 1000;
2340 #ifdef LISP_FLOAT_TYPE
2342 double duration
= extract_float (seconds
);
2343 sec
= (int) duration
;
2344 usec
+= (duration
- sec
) * 1000000;
2347 CHECK_NUMBER (seconds
, 0);
2348 sec
= XINT (seconds
);
2351 #ifndef EMACS_HAS_USECS
2352 if (sec
== 0 && usec
!= 0)
2353 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE
);
2356 /* Assure that 0 <= usec < 1000000. */
2359 /* We can't rely on the rounding being correct if user is negative. */
2360 if (-1000000 < usec
)
2361 sec
--, usec
+= 1000000;
2363 sec
-= -usec
/ 1000000, usec
= 1000000 - (-usec
% 1000000);
2366 sec
+= usec
/ 1000000, usec
%= 1000000;
2368 if (sec
< 0 || (sec
== 0 && usec
== 0))
2374 XSETFASTINT (zero
, 0);
2375 wait_reading_process_input (sec
, usec
, zero
, 0);
2378 /* We should always have wait_reading_process_input; we have a dummy
2379 implementation for systems which don't support subprocesses. */
2381 /* No wait_reading_process_input */
2388 /* The reason this is done this way
2389 (rather than defined (H_S) && defined (H_T))
2390 is because the VMS preprocessor doesn't grok `defined' */
2392 EMACS_GET_TIME (end_time
);
2393 EMACS_SET_SECS_USECS (timeout
, sec
, usec
);
2394 EMACS_ADD_TIME (end_time
, end_time
, timeout
);
2398 EMACS_GET_TIME (timeout
);
2399 EMACS_SUB_TIME (timeout
, end_time
, timeout
);
2400 if (EMACS_TIME_NEG_P (timeout
)
2401 || !select (1, 0, 0, 0, &timeout
))
2404 #else /* not HAVE_SELECT */
2406 #endif /* HAVE_SELECT */
2407 #endif /* not VMS */
2410 #endif /* no subprocesses */
2415 /* This is just like wait_reading_process_input, except that
2416 it does the redisplay.
2418 It's also much like Fsit_for, except that it can be used for
2419 waiting for input as well. */
2422 sit_for (sec
, usec
, reading
, display
, initial_display
)
2423 int sec
, usec
, reading
, display
, initial_display
;
2425 Lisp_Object read_kbd
;
2427 swallow_events (display
);
2429 if (detect_input_pending_run_timers (display
))
2432 if (initial_display
)
2433 redisplay_preserve_echo_area ();
2435 if (sec
== 0 && usec
== 0)
2442 XSETINT (read_kbd
, reading
? -1 : 1);
2443 wait_reading_process_input (sec
, usec
, read_kbd
, display
);
2445 return detect_input_pending () ? Qnil
: Qt
;
2448 DEFUN ("sit-for", Fsit_for
, Ssit_for
, 1, 3, 0,
2449 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
2450 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2451 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2452 additional wait period, in milliseconds; this may be useful if your\n\
2453 Emacs was built without floating point support.\n\
2454 \(Not all operating systems support waiting for a fraction of a second.)\n\
2455 Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
2456 Redisplay is preempted as always if input arrives, and does not happen\n\
2457 if input is available before it starts.\n\
2458 Value is t if waited the full time with no input arriving.")
2459 (seconds
, milliseconds
, nodisp
)
2460 Lisp_Object seconds
, milliseconds
, nodisp
;
2464 if (NILP (milliseconds
))
2465 XSETINT (milliseconds
, 0);
2467 CHECK_NUMBER (milliseconds
, 1);
2468 usec
= XINT (milliseconds
) * 1000;
2470 #ifdef LISP_FLOAT_TYPE
2472 double duration
= extract_float (seconds
);
2473 sec
= (int) duration
;
2474 usec
+= (duration
- sec
) * 1000000;
2477 CHECK_NUMBER (seconds
, 0);
2478 sec
= XINT (seconds
);
2481 #ifndef EMACS_HAS_USECS
2482 if (usec
!= 0 && sec
== 0)
2483 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE
);
2486 return sit_for (sec
, usec
, 0, NILP (nodisp
), NILP (nodisp
));
2489 char *terminal_type
;
2491 /* Initialization done when Emacs fork is started, before doing stty. */
2492 /* Determine terminal type and set terminal_driver */
2493 /* Then invoke its decoding routine to set up variables
2494 in the terminal package */
2499 #ifdef HAVE_X_WINDOWS
2500 extern int display_arg
;
2505 cursor_in_echo_area
= 0;
2506 terminal_type
= (char *) 0;
2508 /* Now is the time to initialize this; it's used by init_sys_modes
2510 Vwindow_system
= Qnil
;
2512 /* If the user wants to use a window system, we shouldn't bother
2513 initializing the terminal. This is especially important when the
2514 terminal is so dumb that emacs gives up before and doesn't bother
2515 using the window system.
2517 If the DISPLAY environment variable is set and nonempty,
2518 try to use X, and die with an error message if that doesn't work. */
2520 #ifdef HAVE_X_WINDOWS
2525 display
= getenv ("DECW$DISPLAY");
2527 display
= getenv ("DISPLAY");
2530 display_arg
= (display
!= 0 && *display
!= 0);
2533 if (!inhibit_window_system
&& display_arg
2539 Vwindow_system
= intern ("x");
2541 Vwindow_system_version
= make_number (11);
2543 Vwindow_system_version
= make_number (10);
2545 #if defined (LINUX) && defined (HAVE_LIBNCURSES)
2546 /* In some versions of ncurses,
2547 tputs crashes if we have not called tgetent.
2549 { char b
[2044]; tgetent (b
, "xterm");}
2553 #endif /* HAVE_X_WINDOWS */
2556 if (!inhibit_window_system
)
2558 Vwindow_system
= intern ("w32");
2559 Vwindow_system_version
= make_number (1);
2562 #endif /* HAVE_NTGUI */
2564 /* If no window system has been specified, try to use the terminal. */
2567 fatal ("standard input is not a tty");
2571 /* Look at the TERM variable */
2572 terminal_type
= (char *) getenv ("TERM");
2576 fprintf (stderr
, "Please specify your terminal type.\n\
2577 For types defined in VMS, use set term /device=TYPE.\n\
2578 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2579 \(The quotation marks are necessary since terminal types are lower case.)\n");
2581 fprintf (stderr
, "Please set the environment variable TERM; see tset(1).\n");
2587 /* VMS DCL tends to upcase things, so downcase term type.
2588 Hardly any uppercase letters in terminal types; should be none. */
2590 char *new = (char *) xmalloc (strlen (terminal_type
) + 1);
2593 strcpy (new, terminal_type
);
2595 for (p
= new; *p
; p
++)
2599 terminal_type
= new;
2603 term_init (terminal_type
);
2606 int width
= FRAME_WINDOW_WIDTH (selected_frame
);
2607 int height
= FRAME_HEIGHT (selected_frame
);
2609 unsigned int total_glyphs
= height
* (width
+ 2) * sizeof (GLYPH
);
2611 /* If these sizes are so big they cause overflow,
2612 just ignore the change. It's not clear what better we could do. */
2613 if (total_glyphs
/ sizeof (GLYPH
) / height
!= width
+ 2)
2614 fatal ("screen size %dx%d too big", width
, height
);
2617 remake_frame_glyphs (selected_frame
);
2618 calculate_costs (selected_frame
);
2620 /* X and Y coordinates of the cursor between updates. */
2621 FRAME_CURSOR_X (selected_frame
) = 0;
2622 FRAME_CURSOR_Y (selected_frame
) = 0;
2627 #endif /* CANNOT_DUMP */
2628 signal (SIGWINCH
, window_change_signal
);
2629 #endif /* SIGWINCH */
2635 defsubr (&Sredraw_frame
);
2636 defsubr (&Sredraw_display
);
2637 defsubr (&Sframe_or_buffer_changed_p
);
2638 defsubr (&Sopen_termscript
);
2640 defsubr (&Ssit_for
);
2641 defsubr (&Ssleep_for
);
2642 defsubr (&Ssend_string_to_terminal
);
2644 frame_and_buffer_state
= Fmake_vector (make_number (20), Qlambda
);
2645 staticpro (&frame_and_buffer_state
);
2647 Qdisplay_table
= intern ("display-table");
2648 staticpro (&Qdisplay_table
);
2650 DEFVAR_INT ("baud-rate", &baud_rate
,
2651 "*The output baud rate of the terminal.\n\
2652 On most systems, changing this value will affect the amount of padding\n\
2653 and the other strategic decisions made during redisplay.");
2654 DEFVAR_BOOL ("inverse-video", &inverse_video
,
2655 "*Non-nil means invert the entire frame display.\n\
2656 This means everything is in inverse video which otherwise would not be.");
2657 DEFVAR_BOOL ("visible-bell", &visible_bell
,
2658 "*Non-nil means try to flash the frame to represent a bell.");
2659 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter
,
2660 "*Non-nil means no need to redraw entire frame after suspending.\n\
2661 A non-nil value is useful if the terminal can automatically preserve\n\
2662 Emacs's frame display when you reenter Emacs.\n\
2663 It is up to you to set this variable if your terminal can do that.");
2664 DEFVAR_LISP ("window-system", &Vwindow_system
,
2665 "A symbol naming the window-system under which Emacs is running\n\
2666 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
2667 DEFVAR_LISP ("window-system-version", &Vwindow_system_version
,
2668 "The version number of the window system in use.\n\
2669 For X windows, this is 10 or 11.");
2670 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area
,
2671 "Non-nil means put cursor in minibuffer, at end of any message there.");
2672 DEFVAR_LISP ("glyph-table", &Vglyph_table
,
2673 "Table defining how to output a glyph code to the frame.\n\
2674 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2675 Each element can be:\n\
2676 integer: a glyph code which this glyph is an alias for.\n\
2677 string: output this glyph using that string (not impl. in X windows).\n\
2678 nil: this glyph mod 256 is char code to output,\n\
2679 and this glyph / 256 is face code for X windows (see `face-id').");
2680 Vglyph_table
= Qnil
;
2682 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table
,
2683 "Display table to use for buffers that specify none.\n\
2684 See `buffer-display-table' for more information.");
2685 Vstandard_display_table
= Qnil
;
2687 /* Initialize `window-system', unless init_display already decided it. */
2692 Vwindow_system
= Qnil
;
2693 Vwindow_system_version
= Qnil
;