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