(direct_output_forward_char): Reenable check against
[bpt/emacs.git] / src / dispnew.c
1 /* Updating of data structures for redisplay.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1997
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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)
10 any later version.
11
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.
16
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. */
21
22
23 #include <signal.h>
24
25 #include <config.h>
26
27 #include <stdio.h>
28 #include <ctype.h>
29
30 #include "lisp.h"
31 #include "termchar.h"
32 #include "termopts.h"
33 #include "termhooks.h"
34 /* cm.h must come after dispextern.h on Windows. */
35 #include "dispextern.h"
36 #include "cm.h"
37 #include "buffer.h"
38 #include "charset.h"
39 #include "frame.h"
40 #include "window.h"
41 #include "commands.h"
42 #include "disptab.h"
43 #include "indent.h"
44 #include "intervals.h"
45 #include "blockinput.h"
46
47 /* I don't know why DEC Alpha OSF1 fail to compile this file if we
48 include the following file. */
49 /* #include "systty.h" */
50 #include "syssignal.h"
51
52 #ifdef HAVE_X_WINDOWS
53 #include "xterm.h"
54 #endif /* HAVE_X_WINDOWS */
55
56 #ifdef HAVE_NTGUI
57 #include "w32term.h"
58 #endif /* HAVE_NTGUI */
59
60 /* Include systime.h after xterm.h to avoid double inclusion of time.h. */
61 #include "systime.h"
62
63 #include <errno.h>
64
65 #define max(a, b) ((a) > (b) ? (a) : (b))
66 #define min(a, b) ((a) < (b) ? (a) : (b))
67
68 /* Get number of chars of output now in the buffer of a stdio stream.
69 This ought to be built in in stdio, but it isn't.
70 Some s- files override this because their stdio internals differ. */
71 #ifdef __GNU_LIBRARY__
72 /* The s- file might have overridden the definition with one that works for
73 the system's C library. But we are using the GNU C library, so this is
74 the right definition for every system. */
75 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
76 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
77 #else
78 #undef PENDING_OUTPUT_COUNT
79 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
80 #endif
81 #else /* not __GNU_LIBRARY__ */
82 #ifndef PENDING_OUTPUT_COUNT
83 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
84 #endif
85 #endif
86
87 static void change_frame_size_1 ();
88
89 /* Nonzero upon entry to redisplay means do not assume anything about
90 current contents of actual terminal frame; clear and redraw it. */
91
92 int frame_garbaged;
93
94 /* Nonzero means last display completed. Zero means it was preempted. */
95
96 int display_completed;
97
98 /* Lisp variable visible-bell; enables use of screen-flash
99 instead of audible bell. */
100
101 int visible_bell;
102
103 /* Invert the color of the whole frame, at a low level. */
104
105 int inverse_video;
106
107 /* Line speed of the terminal. */
108
109 int baud_rate;
110
111 /* nil or a symbol naming the window system under which emacs is
112 running ('x is the only current possibility). */
113
114 Lisp_Object Vwindow_system;
115
116 /* Version number of X windows: 10, 11 or nil. */
117 Lisp_Object Vwindow_system_version;
118
119 /* Vector of glyph definitions. Indexed by glyph number,
120 the contents are a string which is how to output the glyph.
121
122 If Vglyph_table is nil, a glyph is output by using its low 8 bits
123 as a character code. */
124
125 Lisp_Object Vglyph_table;
126
127 /* Display table to use for vectors that don't specify their own. */
128
129 Lisp_Object Vstandard_display_table;
130
131 /* Nonzero means reading single-character input with prompt
132 so put cursor on minibuffer after the prompt.
133 positive means at end of text in echo area;
134 negative means at beginning of line. */
135 int cursor_in_echo_area;
136
137 Lisp_Object Qdisplay_table;
138 \f
139 /* The currently selected frame.
140 In a single-frame version, this variable always holds the address of
141 the_only_frame. */
142
143 FRAME_PTR selected_frame;
144
145 /* A frame which is not just a minibuffer, or 0 if there are no such
146 frames. This is usually the most recent such frame that was
147 selected. In a single-frame version, this variable always holds
148 the address of the_only_frame. */
149 FRAME_PTR last_nonminibuf_frame;
150
151 /* This is a vector, made larger whenever it isn't large enough,
152 which is used inside `update_frame' to hold the old contents
153 of the FRAME_PHYS_LINES of the frame being updated. */
154 struct frame_glyphs **ophys_lines;
155 /* Length of vector currently allocated. */
156 int ophys_lines_length;
157
158 FILE *termscript; /* Stdio stream being used for copy of all output. */
159
160 struct cm Wcm; /* Structure for info on cursor positioning */
161
162 int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
163 \f
164 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
165 "Clear frame FRAME and output again what is supposed to appear on it.")
166 (frame)
167 Lisp_Object frame;
168 {
169 FRAME_PTR f;
170
171 CHECK_LIVE_FRAME (frame, 0);
172 f = XFRAME (frame);
173 update_begin (f);
174 if (FRAME_MSDOS_P (f))
175 set_terminal_modes ();
176 clear_frame ();
177 clear_frame_records (f);
178 update_end (f);
179 fflush (stdout);
180 windows_or_buffers_changed++;
181 /* Mark all windows as INaccurate,
182 so that every window will have its redisplay done. */
183 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
184 f->garbaged = 0;
185 return Qnil;
186 }
187
188 redraw_frame (f)
189 FRAME_PTR f;
190 {
191 Lisp_Object frame;
192 XSETFRAME (frame, f);
193 Fredraw_frame (frame);
194 }
195
196 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
197 "Clear and redisplay all visible frames.")
198 ()
199 {
200 Lisp_Object tail, frame;
201
202 FOR_EACH_FRAME (tail, frame)
203 if (FRAME_VISIBLE_P (XFRAME (frame)))
204 Fredraw_frame (frame);
205
206 return Qnil;
207 }
208
209 /* This is used when frame_garbaged is set.
210 Redraw the individual frames marked as garbaged. */
211
212 void
213 redraw_garbaged_frames ()
214 {
215 Lisp_Object tail, frame;
216
217 FOR_EACH_FRAME (tail, frame)
218 if (FRAME_VISIBLE_P (XFRAME (frame))
219 && FRAME_GARBAGED_P (XFRAME (frame)))
220 Fredraw_frame (frame);
221 }
222
223 \f
224 static struct frame_glyphs *
225 make_frame_glyphs (frame, empty)
226 register FRAME_PTR frame;
227 int empty;
228 {
229 register int i;
230 register width = FRAME_WINDOW_WIDTH (frame);
231 register height = FRAME_HEIGHT (frame);
232 register struct frame_glyphs *new
233 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
234
235 SET_GLYPHS_FRAME (new, frame);
236 new->height = height;
237 new->width = width;
238 new->used = (int *) xmalloc (height * sizeof (int));
239 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
240 new->charstarts = (int **) xmalloc (height * sizeof (int *));
241 new->highlight = (char *) xmalloc (height * sizeof (char));
242 new->enable = (char *) xmalloc (height * sizeof (char));
243 bzero (new->enable, height * sizeof (char));
244 new->bufp = (int *) xmalloc (height * sizeof (int));
245
246 #ifdef HAVE_WINDOW_SYSTEM
247 if (FRAME_WINDOW_P (frame))
248 {
249 new->top_left_x = (short *) xmalloc (height * sizeof (short));
250 new->top_left_y = (short *) xmalloc (height * sizeof (short));
251 new->pix_width = (short *) xmalloc (height * sizeof (short));
252 new->pix_height = (short *) xmalloc (height * sizeof (short));
253 new->max_ascent = (short *) xmalloc (height * sizeof (short));
254 }
255 #endif /* HAVE_WINDOW_SYSTEM */
256
257 if (empty)
258 {
259 /* Make the buffer used by decode_mode_spec. This buffer is also
260 used as temporary storage when updating the frame. See scroll.c. */
261 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
262 unsigned int total_charstarts = (width + 2) * sizeof (int);
263
264 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
265 bzero (new->total_contents, total_glyphs);
266
267 new->total_charstarts = (int *) xmalloc (total_charstarts);
268 bzero (new->total_charstarts, total_charstarts);
269 }
270 else
271 {
272 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
273
274 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
275 bzero (new->total_contents, total_glyphs);
276 for (i = 0; i < height; i++)
277 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
278
279 if (!FRAME_TERMCAP_P (frame))
280 {
281 unsigned int total_charstarts = height * (width + 2) * sizeof (int);
282
283 new->total_charstarts = (int *) xmalloc (total_charstarts);
284 bzero (new->total_charstarts, total_charstarts);
285 for (i = 0; i < height; i++)
286 new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
287 }
288 else
289 {
290 /* Without a window system, we don't really need charstarts.
291 So use a small amount of space to make enough data structure
292 to prevent crashes in display_text_line. */
293 new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
294 for (i = 0; i < height; i++)
295 new->charstarts[i] = new->total_charstarts;
296 }
297 }
298
299 return new;
300 }
301
302 void
303 free_frame_glyphs (frame, glyphs)
304 FRAME_PTR frame;
305 struct frame_glyphs *glyphs;
306 {
307 if (glyphs->total_contents)
308 xfree (glyphs->total_contents);
309 if (glyphs->total_charstarts)
310 xfree (glyphs->total_charstarts);
311
312 xfree (glyphs->used);
313 xfree (glyphs->glyphs);
314 xfree (glyphs->highlight);
315 xfree (glyphs->enable);
316 xfree (glyphs->bufp);
317 if (glyphs->charstarts)
318 xfree (glyphs->charstarts);
319
320 #ifdef HAVE_WINDOW_SYSTEM
321 if (FRAME_WINDOW_P (frame))
322 {
323 xfree (glyphs->top_left_x);
324 xfree (glyphs->top_left_y);
325 xfree (glyphs->pix_width);
326 xfree (glyphs->pix_height);
327 xfree (glyphs->max_ascent);
328 }
329 #endif /* HAVE_WINDOW_SYSTEM */
330
331 xfree (glyphs);
332 }
333
334 void
335 remake_frame_glyphs (frame)
336 FRAME_PTR frame;
337 {
338 if (FRAME_CURRENT_GLYPHS (frame))
339 free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
340 if (FRAME_DESIRED_GLYPHS (frame))
341 free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
342 if (FRAME_TEMP_GLYPHS (frame))
343 free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
344
345 if (FRAME_MESSAGE_BUF (frame))
346 {
347 /* Reallocate the frame's message buffer; remember that
348 echo_area_glyphs may be pointing here. */
349 char *old_message_buf = FRAME_MESSAGE_BUF (frame);
350
351 FRAME_MESSAGE_BUF (frame)
352 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
353 FRAME_MESSAGE_BUF_SIZE (frame) + 1);
354
355 if (echo_area_glyphs == old_message_buf)
356 echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
357 if (previous_echo_glyphs == old_message_buf)
358 previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
359 }
360 else
361 FRAME_MESSAGE_BUF (frame)
362 = (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (frame) + 1);
363
364 FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
365 FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
366 FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
367 if (FRAME_WINDOW_P (frame) || frame == selected_frame)
368 SET_FRAME_GARBAGED (frame);
369 }
370 \f
371 /* Return the hash code of contents of line VPOS in frame-matrix M. */
372
373 static int
374 line_hash_code (m, vpos)
375 register struct frame_glyphs *m;
376 int vpos;
377 {
378 register GLYPH *body, *end;
379 register int h = 0;
380
381 if (!m->enable[vpos])
382 return 0;
383
384 /* Give all highlighted lines the same hash code
385 so as to encourage scrolling to leave them in place. */
386 if (m->highlight[vpos])
387 return -1;
388
389 body = m->glyphs[vpos];
390
391 if (must_write_spaces)
392 while (1)
393 {
394 GLYPH g = *body++;
395
396 if (g == 0)
397 break;
398 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
399 }
400 else
401 while (1)
402 {
403 GLYPH g = *body++;
404
405 if (g == 0)
406 break;
407 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
408 }
409
410 if (h)
411 return h;
412 return 1;
413 }
414
415 /* Return number of characters in line in M at vpos VPOS,
416 except don't count leading and trailing spaces
417 unless the terminal requires those to be explicitly output. */
418
419 static unsigned int
420 line_draw_cost (m, vpos)
421 struct frame_glyphs *m;
422 int vpos;
423 {
424 register GLYPH *beg = m->glyphs[vpos];
425 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
426 register int i;
427 register int tlen = GLYPH_TABLE_LENGTH;
428 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
429
430 /* Ignore trailing and leading spaces if we can. */
431 if (!must_write_spaces)
432 {
433 while ((end != beg) && (*end == SPACEGLYPH))
434 --end;
435 if (end == beg)
436 return (0); /* All blank line. */
437
438 while (*beg == SPACEGLYPH)
439 ++beg;
440 }
441
442 /* If we don't have a glyph-table, each glyph is one character,
443 so return the number of glyphs. */
444 if (tbase == 0)
445 return end - beg;
446
447 /* Otherwise, scan the glyphs and accumulate their total size in I. */
448 i = 0;
449 while ((beg <= end) && *beg)
450 {
451 register GLYPH g = *beg++;
452
453 if (GLYPH_SIMPLE_P (tbase, tlen, g))
454 i += 1;
455 else
456 i += GLYPH_LENGTH (tbase, g);
457 }
458 return i;
459 }
460 \f
461 /* The functions on this page are the interface from xdisp.c to redisplay.
462
463 The only other interface into redisplay is through setting
464 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
465 and SET_FRAME_GARBAGED (frame). */
466
467 /* cancel_line eliminates any request to display a line at position `vpos' */
468
469 cancel_line (vpos, frame)
470 int vpos;
471 register FRAME_PTR frame;
472 {
473 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
474 }
475
476 clear_frame_records (frame)
477 register FRAME_PTR frame;
478 {
479 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
480 }
481
482 /* Clear out all display lines for a coming redisplay. */
483
484 void
485 init_desired_glyphs (frame)
486 register FRAME_PTR frame;
487 {
488 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
489 int vpos;
490 int height = FRAME_HEIGHT (frame);
491
492 for (vpos = 0; vpos < height; vpos++)
493 desired_glyphs->enable[vpos] = 0;
494 }
495
496 /* Prepare to display on line VPOS starting at HPOS within it. */
497
498 void
499 get_display_line (frame, vpos, hpos)
500 register FRAME_PTR frame;
501 int vpos;
502 register int hpos;
503 {
504 register struct frame_glyphs *glyphs;
505 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
506 register GLYPH *p;
507
508 if (vpos < 0)
509 abort ();
510
511 if (! desired_glyphs->enable[vpos])
512 {
513 desired_glyphs->used[vpos] = 0;
514 desired_glyphs->highlight[vpos] = 0;
515 desired_glyphs->enable[vpos] = 1;
516 }
517
518 if (hpos > desired_glyphs->used[vpos])
519 {
520 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
521 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
522
523 desired_glyphs->used[vpos] = hpos;
524 while (g != end)
525 *g++ = SPACEGLYPH;
526 }
527 }
528
529 /* Like bcopy except never gets confused by overlap. */
530
531 void
532 safe_bcopy (from, to, size)
533 char *from, *to;
534 int size;
535 {
536 if (size <= 0 || from == to)
537 return;
538
539 /* If the source and destination don't overlap, then bcopy can
540 handle it. If they do overlap, but the destination is lower in
541 memory than the source, we'll assume bcopy can handle that. */
542 if (to < from || from + size <= to)
543 bcopy (from, to, size);
544
545 /* Otherwise, we'll copy from the end. */
546 else
547 {
548 register char *endf = from + size;
549 register char *endt = to + size;
550
551 /* If TO - FROM is large, then we should break the copy into
552 nonoverlapping chunks of TO - FROM bytes each. However, if
553 TO - FROM is small, then the bcopy function call overhead
554 makes this not worth it. The crossover point could be about
555 anywhere. Since I don't think the obvious copy loop is too
556 bad, I'm trying to err in its favor. */
557 if (to - from < 64)
558 {
559 do
560 *--endt = *--endf;
561 while (endf != from);
562 }
563 else
564 {
565 for (;;)
566 {
567 endt -= (to - from);
568 endf -= (to - from);
569
570 if (endt < to)
571 break;
572
573 bcopy (endf, endt, to - from);
574 }
575
576 /* If SIZE wasn't a multiple of TO - FROM, there will be a
577 little left over. The amount left over is
578 (endt + (to - from)) - to, which is endt - from. */
579 bcopy (from, to, endt - from);
580 }
581 }
582 }
583
584 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
585 DISTANCE may be negative. */
586
587 static void
588 rotate_vector (vector, size, distance)
589 char *vector;
590 int size;
591 int distance;
592 {
593 char *temp = (char *) alloca (size);
594
595 if (distance < 0)
596 distance += size;
597
598 bcopy (vector, temp + distance, size - distance);
599 bcopy (vector + size - distance, temp, distance);
600 bcopy (temp, vector, size);
601 }
602
603 /* Scroll lines from vpos FROM up to but not including vpos END
604 down by AMOUNT lines (AMOUNT may be negative).
605 Returns nonzero if done, zero if terminal cannot scroll them. */
606
607 int
608 scroll_frame_lines (frame, from, end, amount, newpos)
609 register FRAME_PTR frame;
610 int from, end, amount, newpos;
611 {
612 register int i;
613 register struct frame_glyphs *current_frame
614 = FRAME_CURRENT_GLYPHS (frame);
615 int pos_adjust;
616 int width = FRAME_WINDOW_WIDTH (frame);
617
618 if (!line_ins_del_ok)
619 return 0;
620
621 if (amount == 0)
622 return 1;
623
624 if (amount > 0)
625 {
626 update_begin (frame);
627 set_terminal_window (end + amount);
628 if (!scroll_region_ok)
629 ins_del_lines (end, -amount);
630 ins_del_lines (from, amount);
631 set_terminal_window (0);
632
633 rotate_vector (current_frame->glyphs + from,
634 sizeof (GLYPH *) * (end + amount - from),
635 amount * sizeof (GLYPH *));
636
637 rotate_vector (current_frame->charstarts + from,
638 sizeof (int *) * (end + amount - from),
639 amount * sizeof (int *));
640
641 safe_bcopy (current_frame->used + from,
642 current_frame->used + from + amount,
643 (end - from) * sizeof current_frame->used[0]);
644
645 safe_bcopy (current_frame->highlight + from,
646 current_frame->highlight + from + amount,
647 (end - from) * sizeof current_frame->highlight[0]);
648
649 safe_bcopy (current_frame->enable + from,
650 current_frame->enable + from + amount,
651 (end - from) * sizeof current_frame->enable[0]);
652
653 /* Adjust the lines by an amount
654 that puts the first of them at NEWPOS. */
655 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
656
657 /* Offset each char position in the charstarts lines we moved
658 by pos_adjust. */
659 for (i = from + amount; i < end + amount; i++)
660 {
661 int *line = current_frame->charstarts[i];
662 int col;
663 for (col = 0; col < width; col++)
664 if (line[col] > 0)
665 line[col] += pos_adjust;
666 }
667 for (i = from; i < from + amount; i++)
668 {
669 int *line = current_frame->charstarts[i];
670 int col;
671 line[0] = -1;
672 for (col = 0; col < width; col++)
673 line[col] = 0;
674 }
675
676 /* Mark the lines made empty by scrolling as enabled, empty and
677 normal video. */
678 bzero (current_frame->used + from,
679 amount * sizeof current_frame->used[0]);
680 bzero (current_frame->highlight + from,
681 amount * sizeof current_frame->highlight[0]);
682 for (i = from; i < from + amount; i++)
683 {
684 current_frame->glyphs[i][0] = '\0';
685 current_frame->charstarts[i][0] = -1;
686 current_frame->enable[i] = 1;
687 }
688
689 safe_bcopy (current_frame->bufp + from,
690 current_frame->bufp + from + amount,
691 (end - from) * sizeof current_frame->bufp[0]);
692
693 #ifdef HAVE_WINDOW_SYSTEM
694 if (FRAME_WINDOW_P (frame))
695 {
696 safe_bcopy (current_frame->top_left_x + from,
697 current_frame->top_left_x + from + amount,
698 (end - from) * sizeof current_frame->top_left_x[0]);
699
700 safe_bcopy (current_frame->top_left_y + from,
701 current_frame->top_left_y + from + amount,
702 (end - from) * sizeof current_frame->top_left_y[0]);
703
704 safe_bcopy (current_frame->pix_width + from,
705 current_frame->pix_width + from + amount,
706 (end - from) * sizeof current_frame->pix_width[0]);
707
708 safe_bcopy (current_frame->pix_height + from,
709 current_frame->pix_height + from + amount,
710 (end - from) * sizeof current_frame->pix_height[0]);
711
712 safe_bcopy (current_frame->max_ascent + from,
713 current_frame->max_ascent + from + amount,
714 (end - from) * sizeof current_frame->max_ascent[0]);
715 }
716 #endif /* HAVE_WINDOW_SYSTEM */
717
718 update_end (frame);
719 }
720 if (amount < 0)
721 {
722 update_begin (frame);
723 set_terminal_window (end);
724 ins_del_lines (from + amount, amount);
725 if (!scroll_region_ok)
726 ins_del_lines (end + amount, -amount);
727 set_terminal_window (0);
728
729 rotate_vector (current_frame->glyphs + from + amount,
730 sizeof (GLYPH *) * (end - from - amount),
731 amount * sizeof (GLYPH *));
732
733 rotate_vector (current_frame->charstarts + from + amount,
734 sizeof (int *) * (end - from - amount),
735 amount * sizeof (int *));
736
737 safe_bcopy (current_frame->used + from,
738 current_frame->used + from + amount,
739 (end - from) * sizeof current_frame->used[0]);
740
741 safe_bcopy (current_frame->highlight + from,
742 current_frame->highlight + from + amount,
743 (end - from) * sizeof current_frame->highlight[0]);
744
745 safe_bcopy (current_frame->enable + from,
746 current_frame->enable + from + amount,
747 (end - from) * sizeof current_frame->enable[0]);
748
749 /* Adjust the lines by an amount
750 that puts the first of them at NEWPOS. */
751 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
752
753 /* Offset each char position in the charstarts lines we moved
754 by pos_adjust. */
755 for (i = from + amount; i < end + amount; i++)
756 {
757 int *line = current_frame->charstarts[i];
758 int col;
759 for (col = 0; col < width; col++)
760 if (line[col] > 0)
761 line[col] += pos_adjust;
762 }
763 for (i = end + amount; i < end; i++)
764 {
765 int *line = current_frame->charstarts[i];
766 int col;
767 line[0] = -1;
768 for (col = 0; col < width; col++)
769 line[col] = 0;
770 }
771
772 /* Mark the lines made empty by scrolling as enabled, empty and
773 normal video. */
774 bzero (current_frame->used + end + amount,
775 - amount * sizeof current_frame->used[0]);
776 bzero (current_frame->highlight + end + amount,
777 - amount * sizeof current_frame->highlight[0]);
778 for (i = end + amount; i < end; i++)
779 {
780 current_frame->glyphs[i][0] = '\0';
781 current_frame->charstarts[i][0] = 0;
782 current_frame->enable[i] = 1;
783 }
784
785 safe_bcopy (current_frame->bufp + from,
786 current_frame->bufp + from + amount,
787 (end - from) * sizeof current_frame->bufp[0]);
788
789 #ifdef HAVE_WINDOW_SYSTEM
790 if (FRAME_WINDOW_P (frame))
791 {
792 safe_bcopy (current_frame->top_left_x + from,
793 current_frame->top_left_x + from + amount,
794 (end - from) * sizeof current_frame->top_left_x[0]);
795
796 safe_bcopy (current_frame->top_left_y + from,
797 current_frame->top_left_y + from + amount,
798 (end - from) * sizeof current_frame->top_left_y[0]);
799
800 safe_bcopy (current_frame->pix_width + from,
801 current_frame->pix_width + from + amount,
802 (end - from) * sizeof current_frame->pix_width[0]);
803
804 safe_bcopy (current_frame->pix_height + from,
805 current_frame->pix_height + from + amount,
806 (end - from) * sizeof current_frame->pix_height[0]);
807
808 safe_bcopy (current_frame->max_ascent + from,
809 current_frame->max_ascent + from + amount,
810 (end - from) * sizeof current_frame->max_ascent[0]);
811 }
812 #endif /* HAVE_WINDOW_SYSTEM */
813
814 update_end (frame);
815 }
816 return 1;
817 }
818 \f
819 /* After updating a window W that isn't the full frame wide,
820 copy all the columns that W does not occupy
821 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
822 so that update_frame will not change those columns. */
823
824 preserve_other_columns (w)
825 struct window *w;
826 {
827 register int vpos;
828 register struct frame_glyphs *current_frame, *desired_frame;
829 register FRAME_PTR frame = XFRAME (w->frame);
830 int start = WINDOW_LEFT_MARGIN (w);
831 int end = WINDOW_RIGHT_EDGE (w);
832 int bot = XFASTINT (w->top) + XFASTINT (w->height);
833
834 current_frame = FRAME_CURRENT_GLYPHS (frame);
835 desired_frame = FRAME_DESIRED_GLYPHS (frame);
836
837 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
838 {
839 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
840 {
841 if (start > 0)
842 {
843 int len;
844
845 bcopy (current_frame->glyphs[vpos],
846 desired_frame->glyphs[vpos],
847 start * sizeof (current_frame->glyphs[vpos][0]));
848 bcopy (current_frame->charstarts[vpos],
849 desired_frame->charstarts[vpos],
850 start * sizeof (current_frame->charstarts[vpos][0]));
851 len = min (start, current_frame->used[vpos]);
852 if (desired_frame->used[vpos] < len)
853 desired_frame->used[vpos] = len;
854 }
855 if (current_frame->used[vpos] > end
856 && desired_frame->used[vpos] < current_frame->used[vpos])
857 {
858 while (desired_frame->used[vpos] < end)
859 {
860 int used = desired_frame->used[vpos]++;
861 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
862 desired_frame->glyphs[vpos][used] = 0;
863 }
864 bcopy (current_frame->glyphs[vpos] + end,
865 desired_frame->glyphs[vpos] + end,
866 ((current_frame->used[vpos] - end)
867 * sizeof (current_frame->glyphs[vpos][0])));
868 bcopy (current_frame->charstarts[vpos] + end,
869 desired_frame->charstarts[vpos] + end,
870 ((current_frame->used[vpos] - end)
871 * sizeof (current_frame->charstarts[vpos][0])));
872 desired_frame->used[vpos] = current_frame->used[vpos];
873 }
874 }
875 }
876 }
877 \f
878 #if 0
879
880 /* If window w does not need to be updated and isn't the full frame wide,
881 copy all the columns that w does occupy
882 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
883 so that update_frame will not change those columns.
884
885 Have not been able to figure out how to use this correctly. */
886
887 preserve_my_columns (w)
888 struct window *w;
889 {
890 register int vpos, fin;
891 register struct frame_glyphs *l1, *l2;
892 register FRAME_PTR frame = XFRAME (w->frame);
893 int start = WINDOW_LEFT_MARGIN (w);
894 int end = WINDOW_RIGHT_EDGE (w);
895 int bot = XFASTINT (w->top) + XFASTINT (w->height);
896
897 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
898 {
899 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
900 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
901 {
902 if (l2->length > start && l1->length < l2->length)
903 {
904 fin = l2->length;
905 if (fin > end) fin = end;
906 while (l1->length < start)
907 l1->body[l1->length++] = ' ';
908 bcopy (l2->body + start, l1->body + start, fin - start);
909 l1->length = fin;
910 }
911 }
912 }
913 }
914
915 #endif
916 \f
917 /* Adjust by ADJUST the charstart values in window W
918 after vpos VPOS, which counts relative to the frame
919 (not relative to W itself). */
920
921 void
922 adjust_window_charstarts (w, vpos, adjust)
923 struct window *w;
924 int vpos;
925 int adjust;
926 {
927 int left = WINDOW_LEFT_MARGIN (w);
928 int top = XFASTINT (w->top);
929 int right = left + window_internal_width (w);
930 int bottom = top + window_internal_height (w);
931 int i;
932
933 for (i = vpos + 1; i < bottom; i++)
934 {
935 int *charstart
936 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
937 int j;
938 for (j = left; j < right; j++)
939 if (charstart[j] > 0)
940 charstart[j] += adjust;
941 }
942 }
943
944 /* Check the charstarts values in the area of window W
945 for internal consistency. We cannot check that they are "right";
946 we can only look for something nonsensical. */
947
948 verify_charstarts (w)
949 struct window *w;
950 {
951 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
952 int i;
953 int top = XFASTINT (w->top);
954 int bottom = top + window_internal_height (w);
955 int left = WINDOW_LEFT_MARGIN (w);
956 int right = left + window_internal_width (w);
957 int next_line;
958 int truncate = (XINT (w->hscroll)
959 || (truncate_partial_width_windows
960 && !WINDOW_FULL_WIDTH_P (w))
961 || !NILP (XBUFFER (w->buffer)->truncate_lines));
962
963 for (i = top; i < bottom; i++)
964 {
965 int j;
966 int last;
967 int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
968
969 if (i != top)
970 {
971 if (truncate)
972 {
973 /* If we are truncating lines, allow a jump
974 in charstarts from one line to the next. */
975 if (charstart[left] < next_line)
976 abort ();
977 }
978 else
979 {
980 if (charstart[left] != next_line)
981 abort ();
982 }
983 }
984
985 for (j = left; j < right; j++)
986 if (charstart[j] > 0)
987 last = charstart[j];
988 /* Record where the next line should start. */
989 next_line = last;
990 if (BUF_ZV (XBUFFER (w->buffer)) != last)
991 {
992 /* If there's a newline between the two lines, count that. */
993 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
994 if (endchar == '\n')
995 next_line++;
996 }
997 }
998 }
999 \f
1000 /* On discovering that the redisplay for a window was no good,
1001 cancel the columns of that window, so that when the window is
1002 displayed over again get_display_line will not complain. */
1003
1004 cancel_my_columns (w)
1005 struct window *w;
1006 {
1007 register int vpos;
1008 register struct frame_glyphs *desired_glyphs
1009 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
1010 register int start = WINDOW_LEFT_MARGIN (w);
1011 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
1012
1013 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
1014 if (desired_glyphs->enable[vpos]
1015 && desired_glyphs->used[vpos] >= start)
1016 desired_glyphs->used[vpos] = start;
1017 }
1018 \f
1019 /* These functions try to perform directly and immediately on the frame
1020 the necessary output for one change in the buffer.
1021 They may return 0 meaning nothing was done if anything is difficult,
1022 or 1 meaning the output was performed properly.
1023 They assume that the frame was up to date before the buffer
1024 change being displayed. They make various other assumptions too;
1025 see command_loop_1 where these are called. */
1026
1027 int
1028 direct_output_for_insert (g)
1029 int g;
1030 {
1031 register FRAME_PTR frame = selected_frame;
1032 register struct frame_glyphs *current_frame
1033 = FRAME_CURRENT_GLYPHS (frame);
1034
1035 #ifndef COMPILER_REGISTER_BUG
1036 register
1037 #endif /* COMPILER_REGISTER_BUG */
1038 struct window *w = XWINDOW (selected_window);
1039 #ifndef COMPILER_REGISTER_BUG
1040 register
1041 #endif /* COMPILER_REGISTER_BUG */
1042 int hpos = FRAME_CURSOR_X (frame);
1043 #ifndef COMPILER_REGISTER_BUG
1044 register
1045 #endif /* COMPILER_REGISTER_BUG */
1046 int vpos = FRAME_CURSOR_Y (frame);
1047
1048 /* Give up if about to continue line. */
1049 if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1
1050
1051 /* Avoid losing if cursor is in invisible text off left margin */
1052 || (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w))
1053
1054 /* Give up if cursor outside window (in minibuf, probably) */
1055 || cursor_in_echo_area
1056 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1057 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
1058
1059 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
1060 || !display_completed
1061
1062 /* Give up if buffer appears in two places. */
1063 || buffer_shared > 1
1064
1065 #ifdef USE_TEXT_PROPERTIES
1066 /* Intervals have already been adjusted, point is after the
1067 character that was just inserted. */
1068 /* Give up if character is invisible. */
1069 /* Give up if character has a face property.
1070 At the moment we only lose at end of line or end of buffer
1071 and only with faces that have some background */
1072 /* Instead of wasting time, give up if character has any text properties */
1073 || ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil))
1074 #endif
1075
1076 /* Give up if w is minibuffer and a message is being displayed there */
1077 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1078 return 0;
1079
1080 {
1081 int face = 0;
1082 #ifdef HAVE_FACES
1083 int dummy;
1084
1085 if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame))
1086 face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0);
1087 #endif
1088 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
1089 current_frame->charstarts[vpos][hpos] = PT - 1;
1090 /* Record the entry for after the newly inserted character. */
1091 current_frame->charstarts[vpos][hpos + 1] = PT;
1092 adjust_window_charstarts (w, vpos, 1);
1093 }
1094 unchanged_modified = MODIFF;
1095 beg_unchanged = GPT - BEG;
1096 XSETFASTINT (w->last_point, PT);
1097 XSETFASTINT (w->last_point_x, hpos);
1098 XSETFASTINT (w->last_modified, MODIFF);
1099 XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
1100
1101 reassert_line_highlight (0, vpos);
1102 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
1103 fflush (stdout);
1104 ++FRAME_CURSOR_X (frame);
1105 if (hpos == current_frame->used[vpos])
1106 {
1107 current_frame->used[vpos] = hpos + 1;
1108 current_frame->glyphs[vpos][hpos + 1] = 0;
1109 }
1110
1111 return 1;
1112 }
1113
1114 int
1115 direct_output_forward_char (n)
1116 int n;
1117 {
1118 register FRAME_PTR frame = selected_frame;
1119 register struct window *w = XWINDOW (selected_window);
1120 Lisp_Object position;
1121 int hpos = FRAME_CURSOR_X (frame);
1122
1123 /* Give up if in truncated text at end of line. */
1124 /* This check is not redundant. */
1125 if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1)
1126 return 0;
1127
1128 /* Give up if the buffer's direction is reversed (i.e. right-to-left). */
1129 if (!NILP (XBUFFER(w->buffer)->direction_reversed))
1130 return 0;
1131
1132 /* Avoid losing if cursor is in invisible text off left margin
1133 or about to go off either side of window. */
1134 if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w)
1135 && (XINT (w->hscroll) || n < 0))
1136 || (n > 0
1137 && (FRAME_CURSOR_X (frame) + 1
1138 >= XFASTINT (w->left) + window_internal_width (w) - 1))
1139 /* BUG FIX: Added "XFASTINT (w->left)". Without this,
1140 direct_output_forward_char() always fails on "the right"
1141 window. */
1142 || cursor_in_echo_area)
1143 return 0;
1144
1145 /* Can't use direct output if highlighting a region. */
1146 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1147 return 0;
1148
1149 /* Can't use direct output at an overlay boundary; it might have
1150 before-string or after-string properties. */
1151 if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
1152 return 0;
1153
1154 #ifdef USE_TEXT_PROPERTIES
1155 /* Don't use direct output next to an invisible character
1156 since we might need to do something special. */
1157
1158 XSETFASTINT (position, PT);
1159 if (XFASTINT (position) < ZV
1160 && ! NILP (Fget_char_property (position,
1161 Qinvisible,
1162 selected_window)))
1163 return 0;
1164
1165 XSETFASTINT (position, PT - 1);
1166 if (XFASTINT (position) >= BEGV
1167 && ! NILP (Fget_char_property (position,
1168 Qinvisible,
1169 selected_window)))
1170 return 0;
1171 #endif
1172
1173 FRAME_CURSOR_X (frame) += n;
1174 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
1175 XSETFASTINT (w->last_point, PT);
1176 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
1177 fflush (stdout);
1178
1179 return 1;
1180 }
1181 \f
1182 static void update_line ();
1183
1184 /* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
1185 Value is nonzero if redisplay stopped due to pending input.
1186 FORCE nonzero means do not stop for pending input. */
1187
1188 int
1189 update_frame (f, force, inhibit_hairy_id)
1190 FRAME_PTR f;
1191 int force;
1192 int inhibit_hairy_id;
1193 {
1194 register struct frame_glyphs *current_frame;
1195 register struct frame_glyphs *desired_frame = 0;
1196 register int i;
1197 int pause;
1198 int preempt_count = baud_rate / 2400 + 1;
1199 extern input_pending;
1200 #ifdef HAVE_WINDOW_SYSTEM
1201 register int downto, leftmost;
1202 #endif
1203
1204 if (baud_rate != FRAME_COST_BAUD_RATE (f))
1205 calculate_costs (f);
1206
1207 if (preempt_count <= 0)
1208 preempt_count = 1;
1209
1210 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1211
1212 detect_input_pending ();
1213 if (input_pending && !force)
1214 {
1215 pause = 1;
1216 goto do_pause;
1217 }
1218
1219 update_begin (f);
1220
1221 if (!line_ins_del_ok)
1222 inhibit_hairy_id = 1;
1223
1224 /* These are separate to avoid a possible bug in the AIX C compiler. */
1225 current_frame = FRAME_CURRENT_GLYPHS (f);
1226 desired_frame = FRAME_DESIRED_GLYPHS (f);
1227
1228 /* See if any of the desired lines are enabled; don't compute for
1229 i/d line if just want cursor motion. */
1230 for (i = 0; i < FRAME_HEIGHT (f); i++)
1231 if (desired_frame->enable[i])
1232 break;
1233
1234 /* Try doing i/d line, if not yet inhibited. */
1235 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1236 force |= scrolling (f);
1237
1238 /* Update the individual lines as needed. Do bottom line first. */
1239
1240 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1241 update_line (f, FRAME_HEIGHT (f) - 1);
1242
1243 #ifdef HAVE_WINDOW_SYSTEM
1244 if (FRAME_WINDOW_P (f))
1245 {
1246 leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
1247 if (desired_frame->enable[0])
1248 {
1249 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1250 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
1251 = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
1252 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
1253 current_frame->top_left_x[0] = leftmost;
1254 current_frame->top_left_y[0] = downto;
1255 }
1256 }
1257 #endif /* HAVE_WINDOW_SYSTEM */
1258
1259 /* Now update the rest of the lines. */
1260 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
1261 {
1262 if (desired_frame->enable[i])
1263 {
1264 if (FRAME_TERMCAP_P (f))
1265 {
1266 /* Flush out every so many lines.
1267 Also flush out if likely to have more than 1k buffered
1268 otherwise. I'm told that some telnet connections get
1269 really screwed by more than 1k output at once. */
1270 int outq = PENDING_OUTPUT_COUNT (stdout);
1271 if (outq > 900
1272 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1273 {
1274 fflush (stdout);
1275 if (preempt_count == 1)
1276 {
1277 #ifdef EMACS_OUTQSIZE
1278 if (EMACS_OUTQSIZE (0, &outq) < 0)
1279 /* Probably not a tty. Ignore the error and reset
1280 * the outq count. */
1281 outq = PENDING_OUTPUT_COUNT (stdout);
1282 #endif
1283 outq *= 10;
1284 if (baud_rate <= outq && baud_rate > 0)
1285 sleep (outq / baud_rate);
1286 }
1287 }
1288 }
1289
1290 if ((i - 1) % preempt_count == 0)
1291 detect_input_pending ();
1292
1293 update_line (f, i);
1294 #ifdef HAVE_WINDOW_SYSTEM
1295 if (FRAME_WINDOW_P (f))
1296 {
1297 current_frame->top_left_y[i] = downto;
1298 current_frame->top_left_x[i] = leftmost;
1299 }
1300 #endif /* HAVE_WINDOW_SYSTEM */
1301 }
1302
1303 #ifdef HAVE_WINDOW_SYSTEM
1304 if (FRAME_WINDOW_P (f))
1305 downto += current_frame->pix_height[i];
1306 #endif /* HAVE_WINDOW_SYSTEM */
1307 }
1308 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
1309
1310 /* Now just clean up termcap drivers and set cursor, etc. */
1311 if (!pause)
1312 {
1313 if ((cursor_in_echo_area
1314 /* If we are showing a message instead of the minibuffer,
1315 show the cursor for the message instead of for the
1316 (now hidden) minibuffer contents. */
1317 || (EQ (minibuf_window, selected_window)
1318 && EQ (minibuf_window, echo_area_window)
1319 && echo_area_glyphs != 0))
1320 /* These cases apply only to the frame that contains
1321 the active minibuffer window. */
1322 && FRAME_HAS_MINIBUF_P (f)
1323 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
1324 {
1325 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1326 int row, col;
1327
1328 if (cursor_in_echo_area < 0)
1329 {
1330 row = top;
1331 col = 0;
1332 }
1333 else
1334 {
1335 /* If the minibuffer is several lines high, find the last
1336 line that has any text on it. */
1337 row = FRAME_HEIGHT (f);
1338 do
1339 {
1340 row--;
1341 if (current_frame->enable[row])
1342 col = current_frame->used[row];
1343 else
1344 col = 0;
1345 }
1346 while (row > top && col == 0);
1347
1348 if (col >= FRAME_WINDOW_WIDTH (f))
1349 {
1350 col = 0;
1351 if (row < FRAME_HEIGHT (f) - 1)
1352 row++;
1353 }
1354 }
1355
1356 cursor_to (row, col);
1357 }
1358 else
1359 cursor_to (FRAME_CURSOR_Y (f),
1360 max (min (FRAME_CURSOR_X (f),
1361 FRAME_WINDOW_WIDTH (f) - 1), 0));
1362 }
1363
1364 update_end (f);
1365
1366 if (termscript)
1367 fflush (termscript);
1368 fflush (stdout);
1369
1370 /* Here if output is preempted because input is detected. */
1371 do_pause:
1372
1373 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1374 display_completed = !pause;
1375
1376 bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
1377 return pause;
1378 }
1379
1380 /* Called when about to quit, to check for doing so
1381 at an improper time. */
1382
1383 void
1384 quit_error_check ()
1385 {
1386 #if 0
1387 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
1388 return;
1389 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
1390 abort ();
1391 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
1392 abort ();
1393 #endif
1394 }
1395 \f
1396 /* Decide what insert/delete line to do, and do it */
1397
1398 extern void scrolling_1 ();
1399
1400 scrolling (frame)
1401 FRAME_PTR frame;
1402 {
1403 int unchanged_at_top, unchanged_at_bottom;
1404 int window_size;
1405 int changed_lines;
1406 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1407 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1408 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1409 int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1410 register int i;
1411 int free_at_end_vpos = FRAME_HEIGHT (frame);
1412 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1413 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
1414
1415 /* Compute hash codes of all the lines.
1416 Also calculate number of changed lines,
1417 number of unchanged lines at the beginning,
1418 and number of unchanged lines at the end. */
1419
1420 changed_lines = 0;
1421 unchanged_at_top = 0;
1422 unchanged_at_bottom = FRAME_HEIGHT (frame);
1423 for (i = 0; i < FRAME_HEIGHT (frame); i++)
1424 {
1425 /* Give up on this scrolling if some old lines are not enabled. */
1426 if (!current_frame->enable[i])
1427 return 0;
1428 old_hash[i] = line_hash_code (current_frame, i);
1429 if (! desired_frame->enable[i])
1430 {
1431 /* This line cannot be redrawn, so don't let scrolling mess it. */
1432 new_hash[i] = old_hash[i];
1433 #define INFINITY 1000000 /* Taken from scroll.c */
1434 draw_cost[i] = INFINITY;
1435 }
1436 else
1437 {
1438 new_hash[i] = line_hash_code (desired_frame, i);
1439 draw_cost[i] = line_draw_cost (desired_frame, i);
1440 }
1441
1442 if (old_hash[i] != new_hash[i])
1443 {
1444 changed_lines++;
1445 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
1446 }
1447 else if (i == unchanged_at_top)
1448 unchanged_at_top++;
1449 old_draw_cost[i] = line_draw_cost (current_frame, i);
1450 }
1451
1452 /* If changed lines are few, don't allow preemption, don't scroll. */
1453 if (!scroll_region_ok && changed_lines < baud_rate / 2400
1454 || unchanged_at_bottom == FRAME_HEIGHT (frame))
1455 return 1;
1456
1457 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
1458 - unchanged_at_bottom);
1459
1460 if (scroll_region_ok)
1461 free_at_end_vpos -= unchanged_at_bottom;
1462 else if (memory_below_frame)
1463 free_at_end_vpos = -1;
1464
1465 /* If large window, fast terminal and few lines in common between
1466 current frame and desired frame, don't bother with i/d calc. */
1467 if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
1468 && (window_size >=
1469 10 * scrolling_max_lines_saved (unchanged_at_top,
1470 FRAME_HEIGHT (frame) - unchanged_at_bottom,
1471 old_hash, new_hash, draw_cost)))
1472 return 0;
1473
1474 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
1475 draw_cost + unchanged_at_top - 1,
1476 old_draw_cost + unchanged_at_top - 1,
1477 old_hash + unchanged_at_top - 1,
1478 new_hash + unchanged_at_top - 1,
1479 free_at_end_vpos - unchanged_at_top);
1480
1481 return 0;
1482 }
1483 \f
1484 /* Return the offset in its buffer of the character at location col, line
1485 in the given window. */
1486 int
1487 buffer_posn_from_coords (window, col, line)
1488 struct window *window;
1489 int col, line;
1490 {
1491 int hscroll = XINT (window->hscroll);
1492 int window_left = WINDOW_LEFT_MARGIN (window);
1493
1494 /* The actual width of the window is window->width less one for the
1495 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1496 window. */
1497 int window_width = window_internal_width (window) - 1;
1498
1499 int startp = marker_position (window->start);
1500
1501 /* Since compute_motion will only operate on the current buffer,
1502 we need to save the old one and restore it when we're done. */
1503 struct buffer *old_current_buffer = current_buffer;
1504 struct position *posn;
1505
1506 current_buffer = XBUFFER (window->buffer);
1507
1508 /* We can't get a correct result in this case,
1509 but at least prevent compute_motion from crashing. */
1510 if (startp < BEGV)
1511 startp = BEGV;
1512
1513 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1514 (window->frame))->bufp to avoid scanning from the very top of
1515 the window, but it isn't maintained correctly, and I'm not even
1516 sure I will keep it. */
1517 posn = compute_motion (startp, 0,
1518 ((window == XWINDOW (minibuf_window) && startp == BEG
1519 ? minibuf_prompt_width : 0)
1520 + (hscroll ? 1 - hscroll : 0)),
1521 0,
1522 ZV, line, col,
1523 window_width, hscroll, 0, window);
1524
1525 current_buffer = old_current_buffer;
1526
1527 /* compute_motion considers frame points past the end of a line
1528 to be *after* the newline, i.e. at the start of the next line.
1529 This is reasonable, but not really what we want. So if the
1530 result is on a line below LINE, back it up one character. */
1531 if (posn->vpos > line)
1532 return posn->bufpos - 1;
1533 else
1534 return posn->bufpos;
1535 }
1536 \f
1537 static int
1538 count_blanks (r)
1539 register GLYPH *r;
1540 {
1541 register GLYPH *p = r;
1542 while (*p++ == SPACEGLYPH);
1543 return p - r - 1;
1544 }
1545
1546 static int
1547 count_match (str1, str2)
1548 GLYPH *str1, *str2;
1549 {
1550 register GLYPH *p1 = str1;
1551 register GLYPH *p2 = str2;
1552 while (*p1++ == *p2++);
1553 return p1 - str1 - 1;
1554 }
1555
1556 /* Char insertion/deletion cost vector, from term.c */
1557 extern int *char_ins_del_vector;
1558
1559 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
1560
1561 static void
1562 update_line (frame, vpos)
1563 register FRAME_PTR frame;
1564 int vpos;
1565 {
1566 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
1567 int *temp1;
1568 int tem;
1569 int osp, nsp, begmatch, endmatch, olen, nlen;
1570 GLYPH save;
1571 register struct frame_glyphs *current_frame
1572 = FRAME_CURRENT_GLYPHS (frame);
1573 register struct frame_glyphs *desired_frame
1574 = FRAME_DESIRED_GLYPHS (frame);
1575
1576 if (desired_frame->highlight[vpos]
1577 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
1578 {
1579 change_line_highlight (desired_frame->highlight[vpos], vpos,
1580 (current_frame->enable[vpos] ?
1581 current_frame->used[vpos] : 0));
1582 current_frame->enable[vpos] = 0;
1583 }
1584 else
1585 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
1586
1587 if (! current_frame->enable[vpos])
1588 {
1589 olen = 0;
1590 }
1591 else
1592 {
1593 obody = current_frame->glyphs[vpos];
1594 olen = current_frame->used[vpos];
1595 if (! current_frame->highlight[vpos])
1596 {
1597 if (!must_write_spaces)
1598 while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
1599 olen--;
1600 }
1601 else
1602 {
1603 /* For an inverse-video line, remember we gave it
1604 spaces all the way to the frame edge
1605 so that the reverse video extends all the way across. */
1606
1607 while (olen < FRAME_WINDOW_WIDTH (frame) - 1)
1608 obody[olen++] = SPACEGLYPH;
1609 }
1610 }
1611
1612 /* One way or another, this will enable the line being updated. */
1613 current_frame->enable[vpos] = 1;
1614 current_frame->used[vpos] = desired_frame->used[vpos];
1615 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1616 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
1617
1618 #ifdef HAVE_WINDOW_SYSTEM
1619 if (FRAME_WINDOW_P (frame))
1620 {
1621 current_frame->pix_width[vpos]
1622 = current_frame->used[vpos]
1623 * FONT_WIDTH (FRAME_FONT (frame));
1624 current_frame->pix_height[vpos]
1625 = FRAME_LINE_HEIGHT (frame);
1626 }
1627 #endif /* HAVE_WINDOW_SYSTEM */
1628
1629 if (!desired_frame->enable[vpos])
1630 {
1631 nlen = 0;
1632 goto just_erase;
1633 }
1634
1635 nbody = desired_frame->glyphs[vpos];
1636 nlen = desired_frame->used[vpos];
1637
1638 /* Pretend trailing spaces are not there at all,
1639 unless for one reason or another we must write all spaces. */
1640 if (! desired_frame->highlight[vpos])
1641 {
1642 if (!must_write_spaces)
1643 /* We know that the previous character byte contains 0. */
1644 while (nbody[nlen - 1] == SPACEGLYPH)
1645 nlen--;
1646 }
1647 else
1648 {
1649 /* For an inverse-video line, give it extra trailing spaces
1650 all the way to the frame edge
1651 so that the reverse video extends all the way across. */
1652
1653 while (nlen < FRAME_WINDOW_WIDTH (frame) - 1)
1654 nbody[nlen++] = SPACEGLYPH;
1655 }
1656
1657 /* If there's no i/d char, quickly do the best we can without it. */
1658 if (!char_ins_del_ok)
1659 {
1660 int i,j;
1661
1662 #if 0
1663 if (FRAME_X_P (frame))
1664 {
1665 /* Under X, erase everything we are going to rewrite,
1666 and rewrite everything from the first char that's changed.
1667 This is part of supporting fonts like Courier
1668 whose chars can overlap outside the char width. */
1669 for (i = 0; i < nlen; i++)
1670 if (i >= olen || nbody[i] != obody[i])
1671 break;
1672
1673 cursor_to (vpos, i);
1674 if (i != olen)
1675 clear_end_of_line (olen);
1676 write_glyphs (nbody + i, nlen - i);
1677 }
1678 else
1679 {}
1680 #endif /* 0 */
1681 for (i = 0; i < nlen; i++)
1682 {
1683 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1684 {
1685 cursor_to (vpos, i);
1686 for (j = 1;
1687 (i + j < nlen
1688 && (i + j >= olen || nbody[i + j] != obody[i + j]
1689 || (nbody[i + j] & GLYPH_MASK_PADDING)));
1690 j++);
1691
1692 /* Output this run of non-matching chars. */
1693 write_glyphs (nbody + i, j);
1694 i += j - 1;
1695
1696 /* Now find the next non-match. */
1697 }
1698 }
1699
1700 /* Clear the rest of the line, or the non-clear part of it. */
1701 if (olen > nlen)
1702 {
1703 cursor_to (vpos, nlen);
1704 clear_end_of_line (olen);
1705 }
1706
1707 /* Exchange contents between current_frame and new_frame. */
1708 temp = desired_frame->glyphs[vpos];
1709 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1710 current_frame->glyphs[vpos] = temp;
1711
1712 /* Exchange charstarts between current_frame and new_frame. */
1713 temp1 = desired_frame->charstarts[vpos];
1714 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1715 current_frame->charstarts[vpos] = temp1;
1716
1717 return;
1718 }
1719
1720 if (!olen)
1721 {
1722 nsp = (must_write_spaces || desired_frame->highlight[vpos])
1723 ? 0 : count_blanks (nbody);
1724 if (nlen > nsp)
1725 {
1726 cursor_to (vpos, nsp);
1727 write_glyphs (nbody + nsp, nlen - nsp);
1728 }
1729
1730 /* Exchange contents between current_frame and new_frame. */
1731 temp = desired_frame->glyphs[vpos];
1732 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1733 current_frame->glyphs[vpos] = temp;
1734
1735 /* Exchange charstarts between current_frame and new_frame. */
1736 temp1 = desired_frame->charstarts[vpos];
1737 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1738 current_frame->charstarts[vpos] = temp1;
1739
1740 return;
1741 }
1742
1743 obody[olen] = 1;
1744 save = nbody[nlen];
1745 nbody[nlen] = 0;
1746
1747 /* Compute number of leading blanks in old and new contents. */
1748 osp = count_blanks (obody);
1749 if (!desired_frame->highlight[vpos])
1750 nsp = count_blanks (nbody);
1751 else
1752 nsp = 0;
1753
1754 /* Compute number of matching chars starting with first nonblank. */
1755 begmatch = count_match (obody + osp, nbody + nsp);
1756
1757 /* Spaces in new match implicit space past the end of old. */
1758 /* A bug causing this to be a no-op was fixed in 18.29. */
1759 if (!must_write_spaces && osp + begmatch == olen)
1760 {
1761 np1 = nbody + nsp;
1762 while (np1[begmatch] == SPACEGLYPH)
1763 begmatch++;
1764 }
1765
1766 /* Avoid doing insert/delete char
1767 just cause number of leading spaces differs
1768 when the following text does not match. */
1769 if (begmatch == 0 && osp != nsp)
1770 osp = nsp = min (osp, nsp);
1771
1772 /* Find matching characters at end of line */
1773 op1 = obody + olen;
1774 np1 = nbody + nlen;
1775 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1776 while (op1 > op2 && op1[-1] == np1[-1])
1777 {
1778 op1--;
1779 np1--;
1780 }
1781 endmatch = obody + olen - op1;
1782
1783 /* Put correct value back in nbody[nlen].
1784 This is important because direct_output_for_insert
1785 can write into the line at a later point.
1786 If this screws up the zero at the end of the line, re-establish it. */
1787 nbody[nlen] = save;
1788 obody[olen] = 0;
1789
1790 /* tem gets the distance to insert or delete.
1791 endmatch is how many characters we save by doing so.
1792 Is it worth it? */
1793
1794 tem = (nlen - nsp) - (olen - osp);
1795 if (endmatch && tem
1796 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
1797 endmatch = 0;
1798
1799 /* nsp - osp is the distance to insert or delete.
1800 If that is nonzero, begmatch is known to be nonzero also.
1801 begmatch + endmatch is how much we save by doing the ins/del.
1802 Is it worth it? */
1803
1804 if (nsp != osp
1805 && (!char_ins_del_ok
1806 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
1807 {
1808 begmatch = 0;
1809 endmatch = 0;
1810 osp = nsp = min (osp, nsp);
1811 }
1812
1813 /* Now go through the line, inserting, writing and
1814 deleting as appropriate. */
1815
1816 if (osp > nsp)
1817 {
1818 cursor_to (vpos, nsp);
1819 delete_glyphs (osp - nsp);
1820 }
1821 else if (nsp > osp)
1822 {
1823 /* If going to delete chars later in line
1824 and insert earlier in the line,
1825 must delete first to avoid losing data in the insert */
1826 if (endmatch && nlen < olen + nsp - osp)
1827 {
1828 cursor_to (vpos, nlen - endmatch + osp - nsp);
1829 delete_glyphs (olen + nsp - osp - nlen);
1830 olen = nlen - (nsp - osp);
1831 }
1832 cursor_to (vpos, osp);
1833 insert_glyphs ((char *)0, nsp - osp);
1834 }
1835 olen += nsp - osp;
1836
1837 tem = nsp + begmatch + endmatch;
1838 if (nlen != tem || olen != tem)
1839 {
1840 cursor_to (vpos, nsp + begmatch);
1841 if (!endmatch || nlen == olen)
1842 {
1843 /* If new text being written reaches right margin,
1844 there is no need to do clear-to-eol at the end.
1845 (and it would not be safe, since cursor is not
1846 going to be "at the margin" after the text is done) */
1847 if (nlen == FRAME_WINDOW_WIDTH (frame))
1848 olen = 0;
1849 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1850
1851 #ifdef obsolete
1852
1853 /* the following code loses disastrously if tem == nlen.
1854 Rather than trying to fix that case, I am trying the simpler
1855 solution found above. */
1856
1857 /* If the text reaches to the right margin,
1858 it will lose one way or another (depending on AutoWrap)
1859 to clear to end of line after outputting all the text.
1860 So pause with one character to go and clear the line then. */
1861 if (nlen == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
1862 {
1863 /* endmatch must be zero, and tem must equal nsp + begmatch */
1864 write_glyphs (nbody + tem, nlen - tem - 1);
1865 clear_end_of_line (olen);
1866 olen = 0; /* Don't let it be cleared again later */
1867 write_glyphs (nbody + nlen - 1, 1);
1868 }
1869 else
1870 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1871 #endif /* OBSOLETE */
1872
1873 }
1874 else if (nlen > olen)
1875 {
1876 /* Here, we used to have the following simple code:
1877 ----------------------------------------
1878 write_glyphs (nbody + nsp + begmatch, olen - tem);
1879 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1880 ----------------------------------------
1881 but it doesn't work if nbody[nsp + begmatch + olen - tem]
1882 is a padding glyph. */
1883 int out = olen - tem; /* Columns to be overwritten originally. */
1884 int del;
1885
1886 /* Calculate columns we can actually overwrite. */
1887 while (nbody[nsp + begmatch + out] & GLYPH_MASK_PADDING) out--;
1888 write_glyphs (nbody + nsp + begmatch, out);
1889 /* If we left columns to be overwritten. we must delete them. */
1890 del = olen - tem - out;
1891 if (del > 0) delete_glyphs (del);
1892 /* At last, we insert columns not yet written out. */
1893 insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
1894 olen = nlen;
1895 }
1896 else if (olen > nlen)
1897 {
1898 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1899 delete_glyphs (olen - nlen);
1900 olen = nlen;
1901 }
1902 }
1903
1904 just_erase:
1905 /* If any unerased characters remain after the new line, erase them. */
1906 if (olen > nlen)
1907 {
1908 cursor_to (vpos, nlen);
1909 clear_end_of_line (olen);
1910 }
1911
1912 /* Exchange contents between current_frame and new_frame. */
1913 temp = desired_frame->glyphs[vpos];
1914 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1915 current_frame->glyphs[vpos] = temp;
1916
1917 /* Exchange charstarts between current_frame and new_frame. */
1918 temp1 = desired_frame->charstarts[vpos];
1919 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1920 current_frame->charstarts[vpos] = temp1;
1921 }
1922 \f
1923 /* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
1924 session's frames, frame names, buffers, buffer-read-only flags, and
1925 buffer-modified-flags, and a trailing sentinel (so we don't need to
1926 add length checks). */
1927 static Lisp_Object frame_and_buffer_state;
1928
1929 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
1930 Sframe_or_buffer_changed_p, 0, 0, 0,
1931 "Return non-nil if the frame and buffer state appears to have changed.\n\
1932 The state variable is an internal vector containing all frames and buffers,\n\
1933 aside from buffers whose names start with space,\n\
1934 along with the buffers' read-only and modified flags, which allows a fast\n\
1935 check to see whether the menu bars might need to be recomputed.\n\
1936 If this function returns non-nil, it updates the internal vector to reflect\n\
1937 the current state.\n")
1938 ()
1939 {
1940 Lisp_Object tail, frame, buf;
1941 Lisp_Object *vecp;
1942 int n;
1943
1944 vecp = XVECTOR (frame_and_buffer_state)->contents;
1945 FOR_EACH_FRAME (tail, frame)
1946 {
1947 if (!EQ (*vecp++, frame))
1948 goto changed;
1949 if (!EQ (*vecp++, XFRAME (frame)->name))
1950 goto changed;
1951 }
1952 /* Check that the buffer info matches.
1953 No need to test for the end of the vector
1954 because the last element of the vector is lambda
1955 and that will always cause a mismatch. */
1956 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1957 {
1958 buf = XCONS (XCONS (tail)->car)->cdr;
1959 /* Ignore buffers that aren't included in buffer lists. */
1960 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
1961 continue;
1962 if (!EQ (*vecp++, buf))
1963 goto changed;
1964 if (!EQ (*vecp++, XBUFFER (buf)->read_only))
1965 goto changed;
1966 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
1967 goto changed;
1968 }
1969 /* Detect deletion of a buffer at the end of the list. */
1970 if (EQ (*vecp, Qlambda))
1971 return Qnil;
1972 changed:
1973 /* Start with 1 so there is room for at least one lambda at the end. */
1974 n = 1;
1975 FOR_EACH_FRAME (tail, frame)
1976 n += 2;
1977 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1978 n += 3;
1979 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
1980 if (n > XVECTOR (frame_and_buffer_state)->size
1981 || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
1982 /* Add 20 extra so we grow it less often. */
1983 frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
1984 vecp = XVECTOR (frame_and_buffer_state)->contents;
1985 FOR_EACH_FRAME (tail, frame)
1986 {
1987 *vecp++ = frame;
1988 *vecp++ = XFRAME (frame)->name;
1989 }
1990 for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1991 {
1992 buf = XCONS (XCONS (tail)->car)->cdr;
1993 /* Ignore buffers that aren't included in buffer lists. */
1994 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
1995 continue;
1996 *vecp++ = buf;
1997 *vecp++ = XBUFFER (buf)->read_only;
1998 *vecp++ = Fbuffer_modified_p (buf);
1999 }
2000 /* Fill up the vector with lambdas (always at least one). */
2001 *vecp++ = Qlambda;
2002 while (vecp - XVECTOR (frame_and_buffer_state)->contents
2003 < XVECTOR (frame_and_buffer_state)->size)
2004 *vecp++ = Qlambda;
2005 /* Make sure we didn't overflow the vector. */
2006 if (vecp - XVECTOR (frame_and_buffer_state)->contents
2007 > XVECTOR (frame_and_buffer_state)->size)
2008 abort ();
2009 return Qt;
2010 }
2011 \f
2012 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
2013 1, 1, "FOpen termscript file: ",
2014 "Start writing all terminal output to FILE as well as the terminal.\n\
2015 FILE = nil means just close any termscript file currently open.")
2016 (file)
2017 Lisp_Object file;
2018 {
2019 if (termscript != 0) fclose (termscript);
2020 termscript = 0;
2021
2022 if (! NILP (file))
2023 {
2024 file = Fexpand_file_name (file, Qnil);
2025 termscript = fopen (XSTRING (file)->data, "w");
2026 if (termscript == 0)
2027 report_file_error ("Opening termscript", Fcons (file, Qnil));
2028 }
2029 return Qnil;
2030 }
2031 \f
2032
2033 #ifdef SIGWINCH
2034 SIGTYPE
2035 window_change_signal (signalnum) /* If we don't have an argument, */
2036 int signalnum; /* some compilers complain in signal calls. */
2037 {
2038 int width, height;
2039 extern int errno;
2040 int old_errno = errno;
2041
2042 get_frame_size (&width, &height);
2043
2044 /* The frame size change obviously applies to a termcap-controlled
2045 frame. Find such a frame in the list, and assume it's the only
2046 one (since the redisplay code always writes to stdout, not a
2047 FILE * specified in the frame structure). Record the new size,
2048 but don't reallocate the data structures now. Let that be done
2049 later outside of the signal handler. */
2050
2051 {
2052 Lisp_Object tail, frame;
2053
2054 FOR_EACH_FRAME (tail, frame)
2055 {
2056 if (FRAME_TERMCAP_P (XFRAME (frame)))
2057 {
2058 change_frame_size (XFRAME (frame), height, width, 0, 1);
2059 break;
2060 }
2061 }
2062 }
2063
2064 signal (SIGWINCH, window_change_signal);
2065 errno = old_errno;
2066 }
2067 #endif /* SIGWINCH */
2068
2069
2070 /* Do any change in frame size that was requested by a signal. */
2071
2072 do_pending_window_change ()
2073 {
2074 /* If window_change_signal should have run before, run it now. */
2075 while (delayed_size_change)
2076 {
2077 Lisp_Object tail, frame;
2078
2079 delayed_size_change = 0;
2080
2081 FOR_EACH_FRAME (tail, frame)
2082 {
2083 FRAME_PTR f = XFRAME (frame);
2084
2085 int height = FRAME_NEW_HEIGHT (f);
2086 int width = FRAME_NEW_WIDTH (f);
2087
2088 if (height != 0 || width != 0)
2089 change_frame_size (f, height, width, 0, 0);
2090 }
2091 }
2092 }
2093
2094
2095 /* Change the frame height and/or width. Values may be given as zero to
2096 indicate no change is to take place.
2097
2098 If DELAY is non-zero, then assume we're being called from a signal
2099 handler, and queue the change for later - perhaps the next
2100 redisplay. Since this tries to resize windows, we can't call it
2101 from a signal handler. */
2102
2103 change_frame_size (f, newheight, newwidth, pretend, delay)
2104 register FRAME_PTR f;
2105 int newheight, newwidth, pretend;
2106 {
2107 Lisp_Object tail, frame;
2108
2109 if (! FRAME_WINDOW_P (f))
2110 {
2111 /* When using termcap, or on MS-DOS, all frames use
2112 the same screen, so a change in size affects all frames. */
2113 FOR_EACH_FRAME (tail, frame)
2114 if (! FRAME_WINDOW_P (XFRAME (frame)))
2115 change_frame_size_1 (XFRAME (frame), newheight, newwidth,
2116 pretend, delay);
2117 }
2118 else
2119 change_frame_size_1 (f, newheight, newwidth, pretend, delay);
2120 }
2121
2122 static void
2123 change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
2124 register FRAME_PTR frame;
2125 int newheight, newwidth, pretend, delay;
2126 {
2127 int new_frame_window_width;
2128 unsigned int total_glyphs;
2129
2130 /* If we can't deal with the change now, queue it for later. */
2131 if (delay)
2132 {
2133 FRAME_NEW_HEIGHT (frame) = newheight;
2134 FRAME_NEW_WIDTH (frame) = newwidth;
2135 delayed_size_change = 1;
2136 return;
2137 }
2138
2139 /* This size-change overrides any pending one for this frame. */
2140 FRAME_NEW_HEIGHT (frame) = 0;
2141 FRAME_NEW_WIDTH (frame) = 0;
2142
2143 /* If an argument is zero, set it to the current value. */
2144 if (newheight == 0)
2145 newheight = FRAME_HEIGHT (frame);
2146 if (newwidth == 0)
2147 newwidth = FRAME_WIDTH (frame);
2148 new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth);
2149
2150 total_glyphs = newheight * (newwidth + 2) * sizeof (GLYPH);
2151
2152 /* If these sizes are so big they cause overflow,
2153 just ignore the change. It's not clear what better we could do. */
2154 if (total_glyphs / sizeof (GLYPH) / newheight != newwidth + 2)
2155 return;
2156
2157 /* Round up to the smallest acceptable size. */
2158 check_frame_size (frame, &newheight, &newwidth);
2159
2160 /* If we're not changing the frame size, quit now. */
2161 if (newheight == FRAME_HEIGHT (frame)
2162 && new_frame_window_width == FRAME_WINDOW_WIDTH (frame))
2163 return;
2164
2165 BLOCK_INPUT;
2166
2167 #ifdef MSDOS
2168 /* We only can set screen dimensions to certain values supported
2169 by our video hardware. Try to find the smallest size greater
2170 or equal to the requested dimensions. */
2171 dos_set_window_size (&newheight, &newwidth);
2172 #endif
2173
2174 if (newheight != FRAME_HEIGHT (frame))
2175 {
2176 if (FRAME_HAS_MINIBUF_P (frame)
2177 && ! FRAME_MINIBUF_ONLY_P (frame))
2178 {
2179 /* Frame has both root and minibuffer. */
2180 set_window_height (FRAME_ROOT_WINDOW (frame),
2181 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
2182 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
2183 newheight - 1);
2184 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
2185 }
2186 else
2187 /* Frame has just one top-level window. */
2188 set_window_height (FRAME_ROOT_WINDOW (frame),
2189 newheight - FRAME_MENU_BAR_LINES (frame), 0);
2190
2191 if (FRAME_TERMCAP_P (frame) && !pretend)
2192 FrameRows = newheight;
2193
2194 #if 0
2195 if (frame->output_method == output_termcap)
2196 {
2197 frame_height = newheight;
2198 if (!pretend)
2199 FrameRows = newheight;
2200 }
2201 #endif
2202 }
2203
2204 if (new_frame_window_width != FRAME_WINDOW_WIDTH (frame))
2205 {
2206 set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0);
2207 if (FRAME_HAS_MINIBUF_P (frame))
2208 set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0);
2209
2210 if (FRAME_TERMCAP_P (frame) && !pretend)
2211 FrameCols = newwidth;
2212 #if 0
2213 if (frame->output_method == output_termcap)
2214 {
2215 frame_width = newwidth;
2216 if (!pretend)
2217 FrameCols = newwidth;
2218 }
2219 #endif
2220 }
2221
2222 FRAME_HEIGHT (frame) = newheight;
2223 SET_FRAME_WIDTH (frame, newwidth);
2224
2225 if (FRAME_CURSOR_X (frame) >= FRAME_WINDOW_WIDTH (frame))
2226 FRAME_CURSOR_X (frame) = FRAME_WINDOW_WIDTH (frame) - 1;
2227 if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
2228 FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
2229
2230 remake_frame_glyphs (frame);
2231 calculate_costs (frame);
2232
2233 UNBLOCK_INPUT;
2234
2235 /* This isn't quite a no-op: it runs window-configuration-change-hook. */
2236 Fset_window_buffer (FRAME_SELECTED_WINDOW (frame),
2237 XWINDOW (FRAME_SELECTED_WINDOW (frame))->buffer);
2238 }
2239 \f
2240 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2241 Ssend_string_to_terminal, 1, 1, 0,
2242 "Send STRING to the terminal without alteration.\n\
2243 Control characters in STRING will have terminal-dependent effects.")
2244 (string)
2245 Lisp_Object string;
2246 {
2247 CHECK_STRING (string, 0);
2248 fwrite (XSTRING (string)->data, 1, XSTRING (string)->size, stdout);
2249 fflush (stdout);
2250 if (termscript)
2251 {
2252 fwrite (XSTRING (string)->data, 1, XSTRING (string)->size, termscript);
2253 fflush (termscript);
2254 }
2255 return Qnil;
2256 }
2257
2258 DEFUN ("ding", Fding, Sding, 0, 1, 0,
2259 "Beep, or flash the screen.\n\
2260 Also, unless an argument is given,\n\
2261 terminate any keyboard macro currently executing.")
2262 (arg)
2263 Lisp_Object arg;
2264 {
2265 if (!NILP (arg))
2266 {
2267 if (noninteractive)
2268 putchar (07);
2269 else
2270 ring_bell ();
2271 fflush (stdout);
2272 }
2273 else
2274 bitch_at_user ();
2275
2276 return Qnil;
2277 }
2278
2279 bitch_at_user ()
2280 {
2281 if (noninteractive)
2282 putchar (07);
2283 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2284 error ("Keyboard macro terminated by a command ringing the bell");
2285 else
2286 ring_bell ();
2287 fflush (stdout);
2288 }
2289
2290 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
2291 "Pause, without updating display, for SECONDS seconds.\n\
2292 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2293 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2294 additional wait period, in milliseconds; this may be useful if your\n\
2295 Emacs was built without floating point support.\n\
2296 \(Not all operating systems support waiting for a fraction of a second.)")
2297 (seconds, milliseconds)
2298 Lisp_Object seconds, milliseconds;
2299 {
2300 int sec, usec;
2301
2302 if (NILP (milliseconds))
2303 XSETINT (milliseconds, 0);
2304 else
2305 CHECK_NUMBER (milliseconds, 1);
2306 usec = XINT (milliseconds) * 1000;
2307
2308 #ifdef LISP_FLOAT_TYPE
2309 {
2310 double duration = extract_float (seconds);
2311 sec = (int) duration;
2312 usec += (duration - sec) * 1000000;
2313 }
2314 #else
2315 CHECK_NUMBER (seconds, 0);
2316 sec = XINT (seconds);
2317 #endif
2318
2319 #ifndef EMACS_HAS_USECS
2320 if (sec == 0 && usec != 0)
2321 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
2322 #endif
2323
2324 /* Assure that 0 <= usec < 1000000. */
2325 if (usec < 0)
2326 {
2327 /* We can't rely on the rounding being correct if user is negative. */
2328 if (-1000000 < usec)
2329 sec--, usec += 1000000;
2330 else
2331 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
2332 }
2333 else
2334 sec += usec / 1000000, usec %= 1000000;
2335
2336 if (sec < 0 || (sec == 0 && usec == 0))
2337 return Qnil;
2338
2339 {
2340 Lisp_Object zero;
2341
2342 XSETFASTINT (zero, 0);
2343 wait_reading_process_input (sec, usec, zero, 0);
2344 }
2345
2346 /* We should always have wait_reading_process_input; we have a dummy
2347 implementation for systems which don't support subprocesses. */
2348 #if 0
2349 /* No wait_reading_process_input */
2350 immediate_quit = 1;
2351 QUIT;
2352
2353 #ifdef VMS
2354 sys_sleep (sec);
2355 #else /* not VMS */
2356 /* The reason this is done this way
2357 (rather than defined (H_S) && defined (H_T))
2358 is because the VMS preprocessor doesn't grok `defined' */
2359 #ifdef HAVE_SELECT
2360 EMACS_GET_TIME (end_time);
2361 EMACS_SET_SECS_USECS (timeout, sec, usec);
2362 EMACS_ADD_TIME (end_time, end_time, timeout);
2363
2364 while (1)
2365 {
2366 EMACS_GET_TIME (timeout);
2367 EMACS_SUB_TIME (timeout, end_time, timeout);
2368 if (EMACS_TIME_NEG_P (timeout)
2369 || !select (1, 0, 0, 0, &timeout))
2370 break;
2371 }
2372 #else /* not HAVE_SELECT */
2373 sleep (sec);
2374 #endif /* HAVE_SELECT */
2375 #endif /* not VMS */
2376
2377 immediate_quit = 0;
2378 #endif /* no subprocesses */
2379
2380 return Qnil;
2381 }
2382
2383 /* This is just like wait_reading_process_input, except that
2384 it does the redisplay.
2385
2386 It's also much like Fsit_for, except that it can be used for
2387 waiting for input as well. */
2388
2389 Lisp_Object
2390 sit_for (sec, usec, reading, display, initial_display)
2391 int sec, usec, reading, display, initial_display;
2392 {
2393 Lisp_Object read_kbd;
2394
2395 swallow_events (display);
2396
2397 if (detect_input_pending_run_timers (display))
2398 return Qnil;
2399
2400 if (initial_display)
2401 redisplay_preserve_echo_area ();
2402
2403 if (sec == 0 && usec == 0)
2404 return Qt;
2405
2406 #ifdef SIGIO
2407 gobble_input (0);
2408 #endif
2409
2410 XSETINT (read_kbd, reading ? -1 : 1);
2411 wait_reading_process_input (sec, usec, read_kbd, display);
2412
2413 return detect_input_pending () ? Qnil : Qt;
2414 }
2415
2416 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
2417 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
2418 SECONDS may be a floating-point value, meaning that you can wait for a\n\
2419 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2420 additional wait period, in milliseconds; this may be useful if your\n\
2421 Emacs was built without floating point support.\n\
2422 \(Not all operating systems support waiting for a fraction of a second.)\n\
2423 Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
2424 Redisplay is preempted as always if input arrives, and does not happen\n\
2425 if input is available before it starts.\n\
2426 Value is t if waited the full time with no input arriving.")
2427 (seconds, milliseconds, nodisp)
2428 Lisp_Object seconds, milliseconds, nodisp;
2429 {
2430 int sec, usec;
2431
2432 if (NILP (milliseconds))
2433 XSETINT (milliseconds, 0);
2434 else
2435 CHECK_NUMBER (milliseconds, 1);
2436 usec = XINT (milliseconds) * 1000;
2437
2438 #ifdef LISP_FLOAT_TYPE
2439 {
2440 double duration = extract_float (seconds);
2441 sec = (int) duration;
2442 usec += (duration - sec) * 1000000;
2443 }
2444 #else
2445 CHECK_NUMBER (seconds, 0);
2446 sec = XINT (seconds);
2447 #endif
2448
2449 #ifndef EMACS_HAS_USECS
2450 if (usec != 0 && sec == 0)
2451 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
2452 #endif
2453
2454 return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
2455 }
2456 \f
2457 char *terminal_type;
2458
2459 /* Initialization done when Emacs fork is started, before doing stty. */
2460 /* Determine terminal type and set terminal_driver */
2461 /* Then invoke its decoding routine to set up variables
2462 in the terminal package */
2463
2464 init_display ()
2465 {
2466 #ifdef HAVE_X_WINDOWS
2467 extern int display_arg;
2468 #endif
2469
2470 meta_key = 0;
2471 inverse_video = 0;
2472 cursor_in_echo_area = 0;
2473 terminal_type = (char *) 0;
2474
2475 /* Now is the time to initialize this; it's used by init_sys_modes
2476 during startup. */
2477 Vwindow_system = Qnil;
2478
2479 /* If the user wants to use a window system, we shouldn't bother
2480 initializing the terminal. This is especially important when the
2481 terminal is so dumb that emacs gives up before and doesn't bother
2482 using the window system.
2483
2484 If the DISPLAY environment variable is set and nonempty,
2485 try to use X, and die with an error message if that doesn't work. */
2486
2487 #ifdef HAVE_X_WINDOWS
2488 if (! display_arg)
2489 {
2490 char *display;
2491 #ifdef VMS
2492 display = getenv ("DECW$DISPLAY");
2493 #else
2494 display = getenv ("DISPLAY");
2495 #endif
2496
2497 display_arg = (display != 0 && *display != 0);
2498 }
2499
2500 if (!inhibit_window_system && display_arg
2501 #ifndef CANNOT_DUMP
2502 && initialized
2503 #endif
2504 )
2505 {
2506 Vwindow_system = intern ("x");
2507 #ifdef HAVE_X11
2508 Vwindow_system_version = make_number (11);
2509 #else
2510 Vwindow_system_version = make_number (10);
2511 #endif
2512 #if defined (LINUX) && defined (HAVE_LIBNCURSES)
2513 /* In some versions of ncurses,
2514 tputs crashes if we have not called tgetent.
2515 So call tgetent. */
2516 { char b[2044]; tgetent (b, "xterm");}
2517 #endif
2518 return;
2519 }
2520 #endif /* HAVE_X_WINDOWS */
2521
2522 #ifdef HAVE_NTGUI
2523 if (!inhibit_window_system)
2524 {
2525 Vwindow_system = intern ("w32");
2526 Vwindow_system_version = make_number (1);
2527 return;
2528 }
2529 #endif /* HAVE_NTGUI */
2530
2531 /* If no window system has been specified, try to use the terminal. */
2532 if (! isatty (0))
2533 {
2534 fatal ("standard input is not a tty");
2535 exit (1);
2536 }
2537
2538 /* Look at the TERM variable */
2539 terminal_type = (char *) getenv ("TERM");
2540 if (!terminal_type)
2541 {
2542 #ifdef VMS
2543 fprintf (stderr, "Please specify your terminal type.\n\
2544 For types defined in VMS, use set term /device=TYPE.\n\
2545 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2546 \(The quotation marks are necessary since terminal types are lower case.)\n");
2547 #else
2548 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2549 #endif
2550 exit (1);
2551 }
2552
2553 #ifdef VMS
2554 /* VMS DCL tends to upcase things, so downcase term type.
2555 Hardly any uppercase letters in terminal types; should be none. */
2556 {
2557 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2558 char *p;
2559
2560 strcpy (new, terminal_type);
2561
2562 for (p = new; *p; p++)
2563 if (isupper (*p))
2564 *p = tolower (*p);
2565
2566 terminal_type = new;
2567 }
2568 #endif
2569
2570 term_init (terminal_type);
2571
2572 {
2573 int width = FRAME_WINDOW_WIDTH (selected_frame);
2574 int height = FRAME_HEIGHT (selected_frame);
2575
2576 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
2577
2578 /* If these sizes are so big they cause overflow,
2579 just ignore the change. It's not clear what better we could do. */
2580 if (total_glyphs / sizeof (GLYPH) / height != width + 2)
2581 fatal ("screen size %dx%d too big", width, height);
2582 }
2583
2584 remake_frame_glyphs (selected_frame);
2585 calculate_costs (selected_frame);
2586
2587 /* X and Y coordinates of the cursor between updates. */
2588 FRAME_CURSOR_X (selected_frame) = 0;
2589 FRAME_CURSOR_Y (selected_frame) = 0;
2590
2591 #ifdef SIGWINCH
2592 #ifndef CANNOT_DUMP
2593 if (initialized)
2594 #endif /* CANNOT_DUMP */
2595 signal (SIGWINCH, window_change_signal);
2596 #endif /* SIGWINCH */
2597 }
2598 \f
2599 syms_of_display ()
2600 {
2601 defsubr (&Sredraw_frame);
2602 defsubr (&Sredraw_display);
2603 defsubr (&Sframe_or_buffer_changed_p);
2604 defsubr (&Sopen_termscript);
2605 defsubr (&Sding);
2606 defsubr (&Ssit_for);
2607 defsubr (&Ssleep_for);
2608 defsubr (&Ssend_string_to_terminal);
2609
2610 frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
2611 staticpro (&frame_and_buffer_state);
2612
2613 Qdisplay_table = intern ("display-table");
2614 staticpro (&Qdisplay_table);
2615
2616 DEFVAR_INT ("baud-rate", &baud_rate,
2617 "*The output baud rate of the terminal.\n\
2618 On most systems, changing this value will affect the amount of padding\n\
2619 and the other strategic decisions made during redisplay.");
2620 DEFVAR_BOOL ("inverse-video", &inverse_video,
2621 "*Non-nil means invert the entire frame display.\n\
2622 This means everything is in inverse video which otherwise would not be.");
2623 DEFVAR_BOOL ("visible-bell", &visible_bell,
2624 "*Non-nil means try to flash the frame to represent a bell.");
2625 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
2626 "*Non-nil means no need to redraw entire frame after suspending.\n\
2627 A non-nil value is useful if the terminal can automatically preserve\n\
2628 Emacs's frame display when you reenter Emacs.\n\
2629 It is up to you to set this variable if your terminal can do that.");
2630 DEFVAR_LISP ("window-system", &Vwindow_system,
2631 "A symbol naming the window-system under which Emacs is running\n\
2632 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
2633 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2634 "The version number of the window system in use.\n\
2635 For X windows, this is 10 or 11.");
2636 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2637 "Non-nil means put cursor in minibuffer, at end of any message there.");
2638 DEFVAR_LISP ("glyph-table", &Vglyph_table,
2639 "Table defining how to output a glyph code to the frame.\n\
2640 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2641 Each element can be:\n\
2642 integer: a glyph code which this glyph is an alias for.\n\
2643 string: output this glyph using that string (not impl. in X windows).\n\
2644 nil: this glyph mod 256 is char code to output,\n\
2645 and this glyph / 256 is face code for X windows (see `face-id').");
2646 Vglyph_table = Qnil;
2647
2648 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2649 "Display table to use for buffers that specify none.\n\
2650 See `buffer-display-table' for more information.");
2651 Vstandard_display_table = Qnil;
2652
2653 /* Initialize `window-system', unless init_display already decided it. */
2654 #ifdef CANNOT_DUMP
2655 if (noninteractive)
2656 #endif
2657 {
2658 Vwindow_system = Qnil;
2659 Vwindow_system_version = Qnil;
2660 }
2661 }