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