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