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