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