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