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