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