|
|
1.1 root 1: /* Newly written part of redisplay code.
2: Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 1, or (at your option)
9: any later version.
10:
11: GNU Emacs is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Emacs; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20:
21: /* This must precede sys/signal.h on certain machines. */
22: #include <sys/types.h>
23: #include <signal.h>
24:
25: #include "config.h"
26: #include <stdio.h>
27: #include <errno.h>
28:
29: #ifdef HAVE_TIMEVAL
30: #ifdef HPUX
31: #include <time.h>
32: #else
33: #include <sys/time.h>
34: #endif
35: #endif
36:
37: #ifdef HAVE_TERMIO
38: #include <termio.h>
39: #ifdef TCOUTQ
40: #undef TIOCOUTQ
41: #define TIOCOUTQ TCOUTQ
42: #include <fcntl.h>
43: #endif /* TCOUTQ defined */
44: #else
45: #ifndef VMS
46: #include <sys/ioctl.h>
47: #endif /* not VMS */
48: #endif /* not HAVE_TERMIO */
49:
50: /* Allow m- file to inhibit use of FIONREAD. */
51: #ifdef BROKEN_FIONREAD
52: #undef FIONREAD
53: #endif
54:
55: /* We are unable to use interrupts if FIONREAD is not available,
56: so flush SIGIO so we won't try. */
57: #ifndef FIONREAD
58: #ifdef SIGIO
59: #undef SIGIO
60: #endif
61: #endif
62:
63: #undef NULL
64:
65: #include "termchar.h"
66: #include "termopts.h"
67: #include "cm.h"
68: #include "dispextern.h"
69: #include "lisp.h"
70: #include "buffer.h"
71: #include "window.h"
72: #include "commands.h"
73:
74: #define max(a, b) ((a) > (b) ? (a) : (b))
75: #define min(a, b) ((a) < (b) ? (a) : (b))
76:
77: #ifndef PENDING_OUTPUT_COUNT
78: /* Get number of chars of output now in the buffer of a stdio stream.
79: This ought to be built in in stdio, but it isn't.
80: Some s- files override this because their stdio internals differ. */
81: #ifdef __GNU_LIBRARY__
82: #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
83: #else
84: #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
85: #endif
86: #endif /* No PENDING_OUTPUT_COUNT */
87:
88: /* Nonzero means do not assume anything about current
89: contents of actual terminal screen */
90:
91: int screen_garbaged;
92:
93: /* Desired terminal cursor position (to show position of point),
94: origin zero */
95:
96: int cursor_hpos, cursor_vpos;
97:
98: /* Nonzero means last display completed and cursor is really at
99: cursor_hpos, cursor_vpos. Zero means it was preempted. */
100:
101: int display_completed;
102:
103: /* Lisp variable visible-bell; enables use of screen-flash
104: instead of audible bell. */
105:
106: int visible_bell;
107:
108: /* Invert the color of the whole screen, at a low level. */
109:
110: int inverse_video;
111:
112: /* Line speed of the terminal. */
113:
114: int baud_rate;
115:
116: /* nil or a symbol naming the window system
117: under which emacs is running
118: ('x is the only current possibility). */
119:
120: Lisp_Object Vwindow_system;
121:
122: /* Version number of window system, or nil if no window system. */
123:
124: Lisp_Object Vwindow_system_version;
125:
126: /* Nonzero means reading single-character input with prompt
127: so put cursor on minibuffer after the prompt. */
128:
129: int cursor_in_echo_area;
130:
131: /* Nonzero means finish redisplay regardless of available input.
132: This is used with X windows to avoid a weird timing-dependent bug. */
133:
134: int force_redisplay;
135:
136: /* Description of actual screen contents. */
137:
138: struct matrix *current_screen;
139:
140: /* Description of desired screen contents. */
141:
142: struct matrix *new_screen;
143:
144: /* Buffer sometimes used to hold partial screen contents. */
145:
146: struct matrix *temp_screen;
147:
148: /* Stdio stream being used for copy of all terminal output. */
149:
150: FILE *termscript;
151:
152: /* Structure for info on cursor positioning */
153:
154: struct cm Wcm;
155:
156: int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
157: int delayed_screen_height; /* Remembered new screen height. */
158: int delayed_screen_width; /* Remembered new screen width. */
159:
160: /* This buffer records the history of display preemption. */
161:
162: struct preempt
163: {
164: /* Number of keyboard characters read so far at preempt. */
165: int keyboard_char_count;
166: /* Vertical position at which preemption occurred. */
167: int vpos;
168: };
169:
170: #define N_PREEMPTIONS 50
171:
172: /* Circular buffer recording recent display preemptions. */
173: struct preempt preemptions[N_PREEMPTIONS];
174:
175: /* Index of next element in preemptions. */
176: int preemption_index;
177:
178: /* Set these variables in the debugger to force a display preemption. */
179: int debug_preemption_vpos = -1;
180: int debug_preemption_char_count = -1;
181:
182: extern int num_input_chars;
183:
184: /* Free and reallocate current_screen and new_screen. */
185:
186: struct matrix *make_screen_structure ();
187:
188: remake_screen_structures ()
189: {
190: int i;
191:
192: if (current_screen)
193: free_screen_structure (current_screen);
194: if (new_screen)
195: free_screen_structure (new_screen);
196: if (temp_screen)
197: free_screen_structure (temp_screen);
198:
199: current_screen = make_screen_structure (0);
200: new_screen = make_screen_structure (0);
201: temp_screen = make_screen_structure (1);
202:
203: if (message_buf)
204: {
205: /* The echo_area_contents, used by error and message, may be pointing at
206: the string we are replacing. If so, update it. */
207: int repair_echo_area_contents = echo_area_contents == message_buf;
208:
209: message_buf = (char *) xrealloc (message_buf, screen_width + 1);
210:
211: if (repair_echo_area_contents) echo_area_contents = message_buf;
212: }
213: else
214: message_buf = (char *) xmalloc (screen_width + 1);
215:
216: /* This may fix a problem of occasionally displaying garbage in the echo area
217: after a resize in X Windows. */
218: for (i = 0; i < screen_width; i++)
219: message_buf[i] = ' ';
220: message_buf[screen_width] = 0;
221: }
222:
223: struct matrix *
224: make_screen_structure (empty)
225: int empty;
226: {
227: int i;
228: struct matrix *new = (struct matrix *) xmalloc (sizeof (struct matrix));
229:
230: new->height = screen_height;
231: new->width = screen_width;
232: new->highlight = (char *) xmalloc (screen_height);
233: new->enable = (char *) xmalloc (screen_height);
234: new->contents = (unsigned char **) xmalloc (screen_height * sizeof (char *));
235: new->used = (int *) xmalloc (screen_height * sizeof (int));
236: if (empty)
237: {
238: /* Make the buffer used by decode_mode_spec. */
239: new->total_contents = (unsigned char *) xmalloc (screen_width + 2);
240: for (i = 0; i < screen_width; i++)
241: new->total_contents[i] = ' ';
242: new->total_contents[screen_width] = 0;
243: }
244: else
245: {
246: /* Add 2 to leave extra bytes at beginning and end of each line. */
247: new->total_contents = (unsigned char *) xmalloc (screen_height * (screen_width + 2));
248: for (i = 0; i < screen_height; i++)
249: {
250: int j;
251:
252: new->contents[i] = new->total_contents + i * (screen_width + 2) + 1;
253: new->contents[i][screen_width] = 0;
254: new->contents[i][-1] = 0;
255: for (j = 0; j < screen_width; j++)
256: new->contents[i][j] = ' ';
257: }
258: }
259: bzero (new->enable, screen_height);
260: return new;
261: }
262:
263: free_screen_structure (matrix)
264: struct matrix *matrix;
265: {
266: if (matrix->total_contents)
267: free (matrix->total_contents);
268: free (matrix->contents);
269: free (matrix->highlight);
270: free (matrix->enable);
271: free (matrix->used);
272: free (matrix);
273: }
274:
275: /* Return the hash code of contents of line VPOS of screen-matrix M. */
276:
277: int
278: line_hash_code (m, vpos)
279: struct matrix *m;
280: int vpos;
281: {
282: register unsigned char *body;
283: register int h = 0;
284: /* Give all lighlighted lines the same hash code
285: so as to encourage scrolling to leave them in place. */
286: if (m->highlight[vpos])
287: return -1;
288:
289: body = m->contents[vpos];
290:
291: if (must_write_spaces)
292: {
293: while (1)
294: {
295: int c = *body++;
296: if (c == 0)
297: break;
298: h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c - ' ';
299: }
300: }
301: else
302: {
303: while (1)
304: {
305: int c = *body++;
306: if (c == 0)
307: break;
308: h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c;
309: }
310: }
311: if (h)
312: return h;
313: return 1;
314: }
315:
316: /* Return number of characters in line in M at vpos VPOS,
317: except don't count leading and trailing spaces
318: unless the terminal requires those to be explicitly output. */
319:
320: int
321: line_draw_cost (m, vpos)
322: struct matrix *m;
323: int vpos;
324: {
325: register unsigned char *body;
326: register int i;
327:
328: if (must_write_spaces)
329: return m->used[vpos];
330:
331: body = m->contents[vpos];
332: for (i = m->used[vpos]; i > 0 && body[i - 2] == ' '; i--);
333:
334: i -= count_blanks (body);
335: return max (i, 0);
336: }
337:
338: /* The functions on this page are the interface from xdisp.c to redisplay.
339:
340: The only other interface into redisplay is through setting
341: cursor_hpos and cursor_vpos (in xdisp.c) and setting screen_garbaged. */
342:
343: /* cancel_line eliminates any request to display a line at position `vpos' */
344:
345: cancel_line (vpos)
346: int vpos;
347: {
348: new_screen->enable[vpos] = 0;
349: }
350:
351: clear_screen_records ()
352: {
353: int i;
354:
355: bzero (current_screen->enable, screen_height);
356: }
357:
358: /* Get ready to display on line `vpos'
359: and set it up for outputting starting at `hpos' within it.
360: Return the text string where that line is stored. */
361:
362: unsigned char *
363: get_display_line (vpos, hpos)
364: int vpos;
365: register int hpos;
366: {
367: if (new_screen->enable[vpos] && new_screen->used[vpos] > hpos)
368: abort ();
369: if (! new_screen->enable[vpos])
370: {
371: new_screen->used[vpos] = 0;
372: new_screen->highlight[vpos] = 0;
373: new_screen->enable[vpos] = 1;
374: }
375:
376: if (hpos > new_screen->used[vpos])
377: {
378: unsigned char *p = new_screen->contents[vpos] + new_screen->used[vpos];
379: unsigned char *end = new_screen->contents[vpos] + hpos;
380: new_screen->used[vpos] = hpos;
381: while (p != end)
382: *p++ = ' ';
383: }
384:
385: return new_screen->contents[vpos];
386: }
387:
388: /* Scroll lines from vpos `from' up to but not including vpos `end'
389: down by `amount' lines (`amount' may be negative).
390: Returns nonzero if done, zero if terminal cannot scroll them. */
391:
392: int
393: scroll_screen_lines (from, end, amount)
394: int from, end, amount;
395: {
396: register int i;
397:
398: if (!line_ins_del_ok)
399: return 0;
400:
401: if (amount == 0)
402: return 1;
403: if (amount > 0)
404: {
405: set_terminal_window (end + amount);
406: if (!scroll_region_ok)
407: ins_del_lines (end, -amount);
408: ins_del_lines (from, amount);
409: set_terminal_window (0);
410:
411: rotate_vector (current_screen->contents + from,
412: sizeof (char *) * (end + amount - from),
413: amount * sizeof (char *));
414: safe_bcopy (current_screen->used + from,
415: current_screen->used + from + amount,
416: (end - from) * sizeof current_screen->used[0]);
417: safe_bcopy (current_screen->highlight + from,
418: current_screen->highlight + from + amount,
419: (end - from) * sizeof current_screen->highlight[0]);
420: safe_bcopy (current_screen->enable + from,
421: current_screen->enable + from + amount,
422: (end - from) * sizeof current_screen->enable[0]);
423: /* Mark the lines made empty by scrolling as enabled, empty and
424: normal video. */
425: bzero (current_screen->used + from,
426: amount * sizeof current_screen->used[0]);
427: bzero (current_screen->highlight + from,
428: amount * sizeof current_screen->highlight[0]);
429: for (i = from; i < from + amount; i++)
430: {
431: current_screen->contents[i][0] = '\0';
432: current_screen->enable[i] = 1;
433: }
434: }
435: if (amount < 0)
436: {
437: set_terminal_window (end);
438: ins_del_lines (from + amount, amount);
439: if (!scroll_region_ok)
440: ins_del_lines (end + amount, -amount);
441: set_terminal_window (0);
442:
443: rotate_vector (current_screen->contents + from + amount,
444: sizeof (char *) * (end - from - amount),
445: (end - from) * sizeof (char *));
446: safe_bcopy (current_screen->used + from,
447: current_screen->used + from + amount,
448: (end - from) * sizeof current_screen->used[0]);
449: safe_bcopy (current_screen->highlight + from,
450: current_screen->highlight + from + amount,
451: (end - from) * sizeof current_screen->highlight[0]);
452: safe_bcopy (current_screen->enable + from,
453: current_screen->enable + from + amount,
454: (end - from) * sizeof current_screen->enable[0]);
455: /* Mark the lines made empty by scrolling as enabled, empty and
456: normal video. */
457: bzero (current_screen->used + end + amount,
458: - amount * sizeof current_screen->used[0]);
459: bzero (current_screen->highlight + end + amount,
460: - amount * sizeof current_screen->highlight[0]);
461: for (i = end + amount; i < end; i++)
462: {
463: current_screen->contents[i][0] = '\0';
464: current_screen->enable[i] = 1;
465: }
466: }
467: return 1;
468: }
469:
470: /* Rotate a vector of SIZE bytes, by DISTANCE bytes.
471: DISTANCE may be negative. */
472:
473: rotate_vector (vector, size, distance)
474: char *vector;
475: int size;
476: int distance;
477: {
478: char *temp = (char *) alloca (size);
479:
480: if (distance < 0)
481: distance += size;
482:
483: bcopy (vector, temp + distance, size - distance);
484: bcopy (vector + size - distance, temp, distance);
485: bcopy (temp, vector, size);
486: }
487:
488: /* Like bcopy except never gets confused by overlap. */
489:
490: safe_bcopy (from, to, size)
491: char *from, *to;
492: int size;
493: {
494: register char *endf;
495: register char *endt;
496:
497: if (size == 0)
498: return;
499: if (from > to)
500: {
501: /* If destination is lower in memory, we can go from the beginning. */
502: endf = from + size;
503: while (from != endf)
504: *to++ = *from++;
505: return;
506: }
507:
508: /* If destination is higher in memory, we can go backwards from the end. */
509: endf = from + size;
510: endt = to + size;
511:
512: do
513: *--endt = *--endf;
514: while (endf != from);
515: }
516:
517: /* After updating a window w that isn't the full screen wide,
518: copy all the columns that w does not occupy
519: from current_screen to new_screen,
520: so that update_screen will not change those columns. */
521:
522: preserve_other_columns (w)
523: struct window *w;
524: {
525: register int vpos;
526: int start = XFASTINT (w->left);
527: int end = XFASTINT (w->left) + XFASTINT (w->width);
528: int bot = XFASTINT (w->top) + XFASTINT (w->height);
529:
530: for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
531: {
532: if (current_screen->enable[vpos] && new_screen->enable[vpos])
533: {
534: if (start > 0)
535: {
536: int len;
537:
538: bcopy (current_screen->contents[vpos],
539: new_screen->contents[vpos], start);
540: len = min (start, current_screen->used[vpos]);
541: if (new_screen->used[vpos] < len)
542: new_screen->used[vpos] = len;
543: }
544: if (current_screen->used[vpos] > end
545: && new_screen->used[vpos] < current_screen->used[vpos])
546: {
547: while (new_screen->used[vpos] < end)
548: new_screen->contents[vpos][new_screen->used[vpos]++] = ' ';
549: bcopy (current_screen->contents[vpos] + end,
550: new_screen->contents[vpos] + end,
551: current_screen->used[vpos] - end);
552: new_screen->used[vpos] = current_screen->used[vpos];
553: }
554: }
555: }
556: }
557:
558: /* On discovering that the redisplay for a window was no good,
559: cancel the columns of that window,
560: so that when the window is displayed over again
561: get_display_line will not complain. */
562:
563: cancel_my_columns (w)
564: struct window *w;
565: {
566: register int vpos;
567: register int start = XFASTINT (w->left);
568: register int bot = XFASTINT (w->top) + XFASTINT (w->height);
569:
570: for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
571: if (new_screen->enable[vpos] && new_screen->used[vpos] >= start)
572: new_screen->used[vpos] = start;
573: }
574:
575: /* These functions try to perform directly and immediately on the screen
576: the necessary output for one change in the buffer.
577: They may return 0 meaning nothing was done if anything is difficult,
578: or 1 meaning the output was performed properly.
579: They assume that the screen was up to date before the buffer
580: change being displayed. THey make various other assumptions too;
581: see command_loop_1 where these are called. */
582:
583: int
584: direct_output_for_insert (c)
585: int c;
586: {
587: #ifndef COMPILER_REGISTER_BUG
588: register
589: #endif COMPILER_REGISTER_BUG
590: struct window *w = XWINDOW (selected_window);
591: #ifndef COMPILER_REGISTER_BUG
592: register
593: #endif COMPILER_REGISTER_BUG
594: int hpos = cursor_hpos;
595: #ifndef COMPILER_REGISTER_BUG
596: register
597: #endif COMPILER_REGISTER_BUG
598: int vpos = cursor_vpos;
599:
600: /* Give up if about to continue line */
601: if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
602:
603: /* Avoid losing if cursor is in invisible text off left margin */
604: || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
605:
606: /* Give up if cursor outside window (in minibuf, probably) */
607: || cursor_vpos < XFASTINT (w->top)
608: || cursor_vpos >= XFASTINT (w->top) + XFASTINT (w->height)
609:
610: /* Give up if cursor not really at cursor_hpos, cursor_vpos */
611: || !display_completed
612:
613: /* Give up if w is minibuffer and a message is being displayed there */
614: || (EQ (selected_window, minibuf_window) && echo_area_contents))
615: return 0;
616:
617: current_screen->contents[vpos][hpos] = c;
618: unchanged_modified = MODIFF;
619: beg_unchanged = GPT - BEG;
620: XFASTINT (w->last_point) = point;
621: XFASTINT (w->last_point_x) = cursor_hpos;
622: XFASTINT (w->last_modified) = MODIFF;
623:
624: reassert_line_highlight (0, cursor_vpos);
625: output_chars (¤t_screen->contents[vpos][hpos], 1);
626: fflush (stdout);
627: ++cursor_hpos;
628: if (hpos == current_screen->used[vpos])
629: {
630: current_screen->used[vpos] = hpos + 1;
631: current_screen->contents[vpos][hpos + 1] = 0;
632: }
633: return 1;
634: }
635:
636: int
637: direct_output_forward_char (n)
638: int n;
639: {
640: register struct window *w = XWINDOW (selected_window);
641:
642: /* Avoid losing if cursor is in invisible text off left margin */
643: if (XINT (w->hscroll) && cursor_hpos == XFASTINT (w->left))
644: return 0;
645: /* Don't lose if we are in the truncated text at the end. */
646: if (cursor_hpos >= XFASTINT (w->left) + XFASTINT (w->width) - 1)
647: return 0;
648: /* Don't move past the window edges. */
649: if (cursor_hpos + n >= XFASTINT (w->left) + XFASTINT (w->width) - 1)
650: return 0;
651: if (cursor_hpos + n <= XFASTINT (w->left))
652: return 0;
653:
654: cursor_hpos += n;
655: XFASTINT (w->last_point_x) = cursor_hpos;
656: XFASTINT (w->last_point) = point;
657: move_cursor (cursor_vpos, cursor_hpos);
658: fflush (stdout);
659: return 1;
660: }
661:
662: /* Update the actual terminal screen based on the data in new_screen.
663: Value is nonzero if redisplay stopped due to pending input.
664: FORCE nonzero means do not stop for pending input. */
665:
666: update_screen (force, inhibit_hairy_id)
667: int force;
668: int inhibit_hairy_id;
669: {
670: register struct display_line **p;
671: register struct display_line *l, *lnew;
672: register int i;
673: int pause;
674: int preempt_count = baud_rate / 2400 + 1;
675: extern input_pending;
676:
677: if (screen_height == 0) abort (); /* Some bug zeros some core */
678:
679: if (force_redisplay)
680: force = 1;
681:
682: if (!force)
683: detect_input_pending ();
684: if (!force
685: && ((num_input_chars == debug_preemption_char_count
686: && debug_preemption_vpos == screen_height - 1)
687: || input_pending))
688: {
689: pause = screen_height;
690: goto do_pause;
691: }
692:
693: update_begin ();
694:
695: if (!line_ins_del_ok)
696: inhibit_hairy_id = 1;
697:
698: /* Don't compute for i/d line if just want cursor motion. */
699: for (i = 0; i < screen_height; i++)
700: if (new_screen->enable)
701: break;
702:
703: /* Try doing i/d line, if not yet inhibited. */
704: if (!inhibit_hairy_id && i < screen_height)
705: force |= scrolling ();
706:
707: /* Update the individual lines as needed. Do bottom line first. */
708:
709: if (new_screen->enable[screen_height - 1])
710: update_line (screen_height - 1);
711: for (i = 0; i < screen_height - 1 && (force || !input_pending); i++)
712: {
713: if (!force && num_input_chars == debug_preemption_char_count
714: && debug_preemption_vpos == i)
715: break;
716: if (new_screen->enable[i])
717: {
718: /* Flush out every so many lines.
719: Also flush out if likely to have more than 1k buffered
720: otherwise. I'm told that telnet connections get really
721: screwed by more than 1k output at once. */
722: int outq = PENDING_OUTPUT_COUNT (stdout);
723: if (outq > 900
724: || (outq > 20 && ((i - 1) % preempt_count == 0)))
725: {
726: fflush (stdout);
727: if (preempt_count == 1)
728: {
729: #ifdef TIOCOUTQ
730: if (ioctl (0, TIOCOUTQ, &outq) < 0)
731: /* Probably not a tty. Ignore the error and reset
732: * the outq count. */
733: outq = PENDING_OUTPUT_COUNT (stdout);
734: #endif
735: outq *= 10;
736: sleep (outq / baud_rate);
737: }
738: }
739: if ((i - 1) % preempt_count == 0 && !force)
740: detect_input_pending ();
741: /* Now update this line. */
742: update_line (i);
743: }
744: }
745: pause = (i < screen_height - 1) ? i + 1 : 0;
746:
747: /* Now just clean up termcap drivers and set cursor, etc. */
748: if (!pause)
749: {
750: if (cursor_in_echo_area < 0)
751: move_cursor (screen_height - 1, 0);
752: else if (cursor_in_echo_area > 0
753: && !current_screen->enable[screen_height - 1])
754: move_cursor (screen_height - 1, 0);
755: else if (cursor_in_echo_area)
756: move_cursor (screen_height - 1,
757: min (screen_width - 1,
758: current_screen->used[screen_height - 1]));
759: else
760: move_cursor (cursor_vpos, max (min (cursor_hpos, screen_width - 1), 0));
761: }
762:
763: update_end ();
764:
765: if (termscript)
766: fflush (termscript);
767: fflush (stdout);
768:
769: /* Here if output is preempted because input is detected. */
770: do_pause:
771:
772: if (screen_height == 0) abort (); /* Some bug zeros some core */
773: display_completed = !pause;
774: if (pause)
775: {
776: preemptions[preemption_index].vpos = pause - 1;
777: preemptions[preemption_index].keyboard_char_count = num_input_chars;
778: preemption_index++;
779: if (preemption_index == N_PREEMPTIONS)
780: preemption_index = 0;
781: }
782:
783: bzero (new_screen->enable, screen_height);
784: return pause;
785: }
786:
787: /* Called when about to quit, to check for doing so
788: at an improper time. */
789:
790: void
791: quit_error_check ()
792: {
793: if (new_screen == 0)
794: return;
795: if (new_screen->enable[0])
796: abort ();
797: if (new_screen->enable[screen_height - 1])
798: abort ();
799: }
800:
801: /* Decide what insert/delete line to do, and do it */
802:
803: scrolling ()
804: {
805: int unchanged_at_top, unchanged_at_bottom;
806: int window_size;
807: int changed_lines;
808: int *old_hash = (int *) alloca (screen_height * sizeof (int));
809: int *new_hash = (int *) alloca (screen_height * sizeof (int));
810: int *draw_cost = (int *) alloca (screen_height * sizeof (int));
811: register int i;
812: int free_at_end_vpos = screen_height;
813:
814: /* Compute hash codes of all the lines.
815: Also calculate number of changed lines,
816: number of unchanged lines at the beginning,
817: and number of unchanged lines at the end. */
818:
819: changed_lines = 0;
820: unchanged_at_top = 0;
821: unchanged_at_bottom = screen_height;
822: for (i = 0; i < screen_height; i++)
823: {
824: /* Give up on this scrolling if some old lines are not enabled. */
825: if (!current_screen->enable[i])
826: return 0;
827: old_hash[i] = line_hash_code (current_screen, i);
828: if (!new_screen->enable[i])
829: new_hash[i] = old_hash[i];
830: else
831: new_hash[i] = line_hash_code (new_screen, i);
832: if (old_hash[i] != new_hash[i])
833: {
834: changed_lines++;
835: unchanged_at_bottom = screen_height - i - 1;
836: }
837: else if (i == unchanged_at_top)
838: unchanged_at_top++;
839: /* If line is not changing, its redraw cost is infinite,
840: since we can't redraw it. */
841: if (!new_screen->enable[i])
842: draw_cost[i] = INFINITY;
843: else
844: draw_cost[i] = line_draw_cost (new_screen, i);
845: }
846:
847: /* If changed lines are few, don't allow preemption, don't scroll. */
848: if (changed_lines < baud_rate / 2400 || unchanged_at_bottom == screen_height)
849: return 1;
850:
851: window_size = screen_height - unchanged_at_top - unchanged_at_bottom;
852:
853: if (scroll_region_ok)
854: free_at_end_vpos -= unchanged_at_bottom;
855: else if (memory_below_screen)
856: free_at_end_vpos = -1;
857:
858: /* If large window, fast terminal and few lines in common between
859: current_screen and new_screen, don't bother with i/d calc. */
860: if (window_size >= 18 && baud_rate > 2400
861: && (window_size >=
862: 10 * scrolling_max_lines_saved (unchanged_at_top,
863: screen_height - unchanged_at_bottom,
864: old_hash, new_hash, draw_cost)))
865: return 0;
866:
867: scrolling_1 (window_size, unchanged_at_top, unchanged_at_bottom,
868: draw_cost + unchanged_at_top - 1,
869: old_hash + unchanged_at_top - 1,
870: new_hash + unchanged_at_top - 1,
871: free_at_end_vpos - unchanged_at_top);
872:
873: return 0;
874: }
875:
876: update_line (vpos)
877: int vpos;
878: {
879: register unsigned char *obody, *nbody, *op1, *op2, *np1;
880: int tem;
881: int osp, nsp, begmatch, endmatch, olen, nlen;
882: int save;
883: unsigned char *temp;
884:
885: /* Check for highlighting change. */
886: if (new_screen->highlight[vpos]
887: != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
888: {
889: change_line_highlight (new_screen->highlight[vpos], vpos,
890: (current_screen->enable[vpos]
891: ? current_screen->used[vpos] : 0));
892: current_screen->enable[vpos] = 0;
893: }
894: else
895: reassert_line_highlight (new_screen->highlight[vpos], vpos);
896:
897: /* ??? */
898: if (! current_screen->enable[vpos])
899: {
900: olen = 0;
901: }
902: else
903: {
904: obody = current_screen->contents[vpos];
905: olen = current_screen->used[vpos];
906:
907: /* Check for bugs that clobber obody[-1].
908: Such bugs might well clobber more than that,
909: so we need to find them, not try to ignore them. */
910: if (obody[-1] != 0)
911: abort ();
912:
913: if (! current_screen->highlight[vpos])
914: {
915: /* Note obody[-1] is always 0. */
916: if (!must_write_spaces)
917: while (obody[olen - 1] == ' ')
918: olen--;
919: }
920: else
921: {
922: /* For an inverse-video line, remember we gave it
923: spaces all the way to the screen edge
924: so that the reverse video extends all the way across. */
925: while (olen < screen_width - 1)
926: obody[olen++] = ' ';
927: }
928: }
929:
930: /* One way or another, this will enable the line being updated. */
931: current_screen->enable[vpos] = 1;
932: current_screen->used[vpos] = new_screen->used[vpos];
933: #if !defined (ALLIANT) || defined (ALLIANT_2800)
934: current_screen->highlight[vpos] = new_screen->highlight[vpos];
935: #else
936: {
937: /* Work around for compiler bug in cc on FX/80 which causes
938: "dispnew.c", line 896: compiler error: no table entry for op OREG. */
939: char tmp;
940: tmp = new_screen->highlight[vpos];
941: current_screen->highlight[vpos] = tmp;
942: }
943: #endif
944:
945: if (!new_screen->enable[vpos])
946: {
947: nlen = 0;
948: goto just_erase;
949: }
950:
951: nbody = new_screen->contents[vpos];
952: nlen = new_screen->used[vpos];
953:
954: /* Pretend trailing spaces are not there at all,
955: unless for one reason or another we must write all spaces. */
956: /* We know that the previous character byte contains 0. */
957: if (! new_screen->highlight[vpos])
958: {
959: if (!must_write_spaces)
960: while (nlen > 0 && nbody[nlen - 1] == ' ')
961: nlen--;
962: if (nlen == 0)
963: goto just_erase;
964: }
965: else
966: {
967: /* For an inverse-video line, give it extra trailing spaces
968: all the way to the screen edge
969: so that the reverse video extends all the way across. */
970: while (nlen < screen_width - 1)
971: nbody[nlen++] = ' ';
972: }
973:
974: /* If there's no i/d char, quickly do the best we can without it. */
975: if (!char_ins_del_ok)
976: {
977: int i,j;
978:
979: for (i = 0; i < nlen; i++)
980: {
981: if (i >= olen || nbody[i] != obody[i])
982: {
983: /* We found a non-matching char. */
984: move_cursor (vpos, i);
985: for (j = 1; (i + j < nlen &&
986: (i + j >= olen || nbody[i+j] != obody[i+j]));
987: j++);
988: /* Output this run of non-matching chars. */
989: output_chars (nbody + i, j);
990: i += j - 1;
991: /* Now find the next non-match. */
992: }
993: }
994: /* Clear the rest of the line, or the non-clear part of it. */
995: if (olen > nlen)
996: {
997: move_cursor (vpos, nlen);
998: clear_end_of_line (olen);
999: }
1000:
1001: /* Exchange contents between current_screen and new_screen. */
1002: temp = new_screen->contents[vpos];
1003: new_screen->contents[vpos] = current_screen->contents[vpos];
1004: current_screen->contents[vpos] = temp;
1005: return;
1006: }
1007:
1008: if (!olen)
1009: {
1010: nsp = (must_write_spaces || new_screen->highlight[vpos])
1011: ? 0 : count_blanks (nbody);
1012: if (nlen > nsp)
1013: {
1014: move_cursor (vpos, nsp);
1015: output_chars (nbody + nsp, nlen - nsp);
1016: }
1017:
1018: /* Exchange contents between current_screen and new_screen. */
1019: temp = new_screen->contents[vpos];
1020: new_screen->contents[vpos] = current_screen->contents[vpos];
1021: current_screen->contents[vpos] = temp;
1022: return;
1023: }
1024:
1025: obody[olen] = 1;
1026: save = nbody[nlen];
1027: nbody[nlen] = 0;
1028:
1029: /* Compute number of leading blanks in old and new contents. */
1030: osp = count_blanks (obody);
1031: if (!new_screen->highlight[vpos])
1032: nsp = count_blanks (nbody);
1033: else
1034: nsp = 0;
1035:
1036: /* Compute number of matching chars starting with first nonblank. */
1037: begmatch = count_match (obody + osp, nbody + nsp);
1038:
1039: /* Spaces in new match implicit space past the end of old. */
1040: /* A bug causing this to be a no-op was fixed in 18.29. */
1041: if (!must_write_spaces && osp + begmatch == olen)
1042: {
1043: np1 = nbody + nsp;
1044: while (np1[begmatch] == ' ')
1045: begmatch++;
1046: }
1047:
1048: /* Avoid doing insert/delete char
1049: just cause number of leading spaces differs
1050: when the following text does not match. */
1051: if (begmatch == 0 && osp != nsp)
1052: osp = nsp = min (osp, nsp);
1053:
1054: /* Find matching characters at end of line */
1055: op1 = obody + olen;
1056: np1 = nbody + nlen;
1057: op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1058: while (op1 > op2 && op1[-1] == np1[-1])
1059: {
1060: op1--;
1061: np1--;
1062: }
1063: endmatch = obody + olen - op1;
1064:
1065: /* Put correct value back in nbody[nlen].
1066: This is important because direct_output_for_insert
1067: can write into the line at a later point. */
1068: nbody[nlen] = save;
1069: /* Likewise, make sure that the null after the usable space in obody
1070: always remains a null. */
1071: obody[olen] = 0;
1072:
1073: /* tem gets the distance to insert or delete.
1074: endmatch is how many characters we save by doing so.
1075: Is it worth it? */
1076:
1077: tem = (nlen - nsp) - (olen - osp);
1078: if (endmatch && tem && endmatch <= DCICcost[tem])
1079: endmatch = 0;
1080:
1081: /* nsp - osp is the distance to insert or delete.
1082: begmatch + endmatch is how much we save by doing so.
1083: Is it worth it? */
1084:
1085: if (begmatch + endmatch > 0 && nsp != osp
1086: && begmatch + endmatch <= DCICcost[nsp - osp])
1087: {
1088: begmatch = 0;
1089: endmatch = 0;
1090: osp = nsp = min (osp, nsp);
1091: }
1092:
1093: /* Now go through the line, inserting, writing and deleting as appropriate. */
1094:
1095: if (osp > nsp)
1096: {
1097: move_cursor (vpos, nsp);
1098: delete_chars (osp - nsp);
1099: }
1100: else if (nsp > osp)
1101: {
1102: /* If going to delete chars later in line
1103: and insert earlier in the line,
1104: must delete first to avoid losing data in the insert */
1105: if (endmatch && nlen < olen + nsp - osp)
1106: {
1107: move_cursor (vpos, nlen - endmatch + osp - nsp);
1108: delete_chars (olen + nsp - osp - nlen);
1109: olen = nlen - (nsp - osp);
1110: }
1111: move_cursor (vpos, osp);
1112: insert_chars ((char *)0, nsp - osp);
1113: }
1114: olen += nsp - osp;
1115:
1116: tem = nsp + begmatch + endmatch;
1117: if (nlen != tem || olen != tem)
1118: {
1119: move_cursor (vpos, nsp + begmatch);
1120: if (!endmatch || nlen == olen)
1121: {
1122: /* If new text being written reaches right margin,
1123: there is no need to do clear-to-eol at the end.
1124: (and it would not be safe, since cursor is not
1125: going to be "at the margin" after the text is done) */
1126: if (nlen == screen_width)
1127: olen = 0;
1128: output_chars (nbody + nsp + begmatch, nlen - tem);
1129: #ifdef obsolete
1130: /* the following code loses disastrously if tem == nlen.
1131: Rather than trying to fix that case, I am trying the simpler
1132: solution found above. */
1133: /* If the text reaches to the right margin,
1134: it will lose one way or another (depending on AutoWrap)
1135: to clear to end of line after outputting all the text.
1136: So pause with one character to go and clear the line then. */
1137: if (nlen == screen_width && fast_clear_end_of_line && olen > nlen)
1138: {
1139: /* endmatch must be zero, and tem must equal nsp + begmatch */
1140: output_chars (nbody + tem, nlen - tem - 1);
1141: clear_end_of_line (olen);
1142: olen = 0; /* Don't let it be cleared again later */
1143: output_chars (nbody + nlen - 1, 1);
1144: }
1145: else
1146: output_chars (nbody + nsp + begmatch, nlen - tem);
1147: #endif
1148: }
1149: else if (nlen > olen)
1150: {
1151: output_chars (nbody + nsp + begmatch, olen - tem);
1152: insert_chars (nbody + nsp + begmatch + olen - tem, nlen - olen);
1153: olen = nlen;
1154: }
1155: else if (olen > nlen)
1156: {
1157: output_chars (nbody + nsp + begmatch, nlen - tem);
1158: delete_chars (olen - nlen);
1159: olen = nlen;
1160: }
1161: }
1162:
1163: just_erase:
1164: /* If any unerased characters remain after the new line, erase them. */
1165: if (olen > nlen)
1166: {
1167: move_cursor (vpos, nlen);
1168: clear_end_of_line (olen);
1169: }
1170:
1171: /* Exchange contents between current_screen and new_screen. */
1172: temp = new_screen->contents[vpos];
1173: new_screen->contents[vpos] = current_screen->contents[vpos];
1174: current_screen->contents[vpos] = temp;
1175: }
1176:
1177: count_blanks (str)
1178: char *str;
1179: {
1180: register char *p = str;
1181: while (*str++ == ' ');
1182: return str - p - 1;
1183: }
1184:
1185: count_match (str1, str2)
1186: char *str1, *str2;
1187: {
1188: register char *p1 = str1;
1189: register char *p2 = str2;
1190: while (*p1++ == *p2++);
1191: return p1 - str1 - 1;
1192: }
1193:
1194: DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1195: 1, 1, "FOpen termscript file: ",
1196: "Start writing all terminal output to FILE as well as the terminal.\n\
1197: FILE = nil means just close any termscript file currently open.")
1198: (file)
1199: Lisp_Object file;
1200: {
1201: if (termscript != 0) fclose (termscript);
1202: termscript = 0;
1203:
1204: if (! NULL (file))
1205: {
1206: file = Fexpand_file_name (file, Qnil);
1207: termscript = fopen (XSTRING (file)->data, "w");
1208: if (termscript == 0)
1209: report_file_error ("Opening termscript", Fcons (file, Qnil));
1210: }
1211: return Qnil;
1212: }
1213:
1214: DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
1215: "Tell redisplay that the screen has LINES lines.\n\
1216: Optional second arg non-nil means that redisplay should use LINES lines\n\
1217: but that the idea of the actual height of the screen should not be changed.")
1218: (n, pretend)
1219: Lisp_Object n, pretend;
1220: {
1221: CHECK_NUMBER (n, 0);
1222: change_screen_size (XINT (n), 0, !NULL (pretend), 0, 0);
1223: return Qnil;
1224: }
1225:
1226: DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
1227: "Tell redisplay that the screen has COLS columns.\n\
1228: Optional second arg non-nil means that redisplay should use COLS columns\n\
1229: but that the idea of the actual width of the screen should not be changed.")
1230: (n, pretend)
1231: Lisp_Object n, pretend;
1232: {
1233: CHECK_NUMBER (n, 0);
1234: change_screen_size (0, XINT (n), !NULL (pretend), 0, 0);
1235: return Qnil;
1236: }
1237:
1238: DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
1239: "Return number of lines on screen available for display.")
1240: ()
1241: {
1242: return make_number (screen_height);
1243: }
1244:
1245: DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
1246: "Return number of columns on screen available for display.")
1247: ()
1248: {
1249: return make_number (screen_width);
1250: }
1251:
1252: #ifdef SIGWINCH
1253: window_change_signal ()
1254: {
1255: int width, height;
1256: extern int errno;
1257: int old_errno = errno;
1258:
1259: get_screen_size (&width, &height);
1260: /* Record the new size, but don't reallocate the data structures now.
1261: Let that be done later outside of the signal handler. */
1262: change_screen_size (height, width, 0, 1, 0);
1263: signal (SIGWINCH, window_change_signal);
1264:
1265: errno = old_errno;
1266: }
1267: #endif /* SIGWINCH */
1268:
1269: /* Do any change in screen size that was requested by a signal. */
1270:
1271: do_pending_window_change ()
1272: {
1273: /* If change_screen_size should have run before, run it now. */
1274: while (delayed_size_change)
1275: {
1276: int newwidth = delayed_screen_width;
1277: int newheight = delayed_screen_height;
1278: delayed_size_change = 0;
1279: change_screen_size_1 (newheight, newwidth, 0, 0);
1280: }
1281: }
1282:
1283: /* Change the screen height and/or width. Values may be given as zero to
1284: indicate no change is to take place.
1285:
1286: PRETEND is normally 0; 1 means change used-size only but don't
1287: change the size used for calculations; -1 means don't redisplay.
1288:
1289: If DELAYED, don't change the screen size now; just record the new
1290: size and do the actual change at a more convenient time. The
1291: SIGWINCH handler and the X Windows ConfigureNotify code use this,
1292: because they can both be called at inconvenient times.
1293:
1294: FORCE means finish redisplay now regardless of pending input.
1295: This is effective only is DELAYED is not set. */
1296:
1297: change_screen_size (newlength, newwidth, pretend, delayed, force)
1298: register int newlength, newwidth, pretend, delayed, force;
1299: {
1300: /* Don't queue a size change if we won't really do anything. */
1301: if ((newlength == 0 || newlength == screen_height)
1302: && (newwidth == 0 || newwidth == screen_width))
1303: return;
1304: /* If we can't deal with the change now, queue it for later. */
1305: if (delayed)
1306: {
1307: delayed_screen_width = newwidth;
1308: delayed_screen_height = newlength;
1309: delayed_size_change = 1;
1310: }
1311: else
1312: {
1313: delayed_size_change = 0;
1314: change_screen_size_1 (newlength, newwidth, pretend, force);
1315: }
1316: }
1317:
1318: change_screen_size_1 (newlength, newwidth, pretend, force)
1319: register int newlength, newwidth, pretend, force;
1320: {
1321: if ((newlength == 0 || newlength == screen_height)
1322: && (newwidth == 0 || newwidth == screen_width))
1323: return;
1324: if (newlength && newlength != screen_height)
1325: {
1326: set_window_height (XWINDOW (minibuf_window)->prev, newlength - 1, 0);
1327: XFASTINT (XWINDOW (minibuf_window)->top) = newlength - 1;
1328: set_window_height (minibuf_window, 1, 0);
1329: screen_height = newlength;
1330: if (pretend <= 0)
1331: ScreenRows = newlength;
1332: set_terminal_window (0);
1333: }
1334: if (newwidth && newwidth != screen_width)
1335: {
1336: set_window_width (XWINDOW (minibuf_window)->prev, newwidth, 0);
1337: set_window_width (minibuf_window, newwidth, 0);
1338: screen_width = newwidth;
1339: if (pretend <= 0)
1340: ScreenCols = newwidth;
1341: }
1342: remake_screen_structures ();
1343: screen_garbaged = 1;
1344: calculate_costs ();
1345: force_redisplay += force;
1346: if (pretend >= 0)
1347: redisplay_preserve_echo_area ();
1348: force_redisplay -= force;
1349: }
1350:
1351: DEFUN ("baud-rate", Fbaud_rate, Sbaud_rate, 0, 0, 0,
1352: "Return the output baud rate of the terminal.")
1353: ()
1354: {
1355: Lisp_Object temp;
1356: XSET (temp, Lisp_Int, baud_rate);
1357: return temp;
1358: }
1359:
1360: DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
1361: Ssend_string_to_terminal, 1, 1, 0,
1362: "Send STRING to the terminal without alteration.\n\
1363: Control characters in STRING will have terminal-dependent effects.")
1364: (str)
1365: Lisp_Object str;
1366: {
1367: CHECK_STRING (str, 0);
1368: fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
1369: fflush (stdout);
1370: if (termscript)
1371: {
1372: fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
1373: fflush (termscript);
1374: }
1375: return Qnil;
1376: }
1377:
1378: DEFUN ("ding", Fding, Sding, 0, 1, 0,
1379: "Beep, or flash the screen.\n\
1380: Terminates any keyboard macro currently executing unless an argument\n\
1381: is given.")
1382: (arg)
1383: Lisp_Object arg;
1384: {
1385: if (!NULL (arg))
1386: {
1387: if (noninteractive)
1388: putchar (07);
1389: else
1390: ring_bell ();
1391: fflush (stdout);
1392: }
1393: else
1394: bell ();
1395: return Qnil;
1396: }
1397:
1398: bell ()
1399: {
1400: if (noninteractive)
1401: putchar (07);
1402: else if (!FROM_KBD) /* Stop executing a keyboard macro. */
1403: error ("Keyboard macro terminated by a command ringing the bell");
1404: else
1405: ring_bell ();
1406: fflush (stdout);
1407: }
1408:
1409: DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 1, 0,
1410: "Pause, without updating display, for ARG seconds.")
1411: (n)
1412: Lisp_Object n;
1413: {
1414: register int t;
1415: #ifndef subprocesses
1416: #ifdef HAVE_TIMEVAL
1417: struct timeval timeout, end_time, garbage1;
1418: #endif /* HAVE_TIMEVAL */
1419: #endif /* no subprocesses */
1420:
1421: CHECK_NUMBER (n, 0);
1422: t = XINT (n);
1423: if (t <= 0)
1424: return Qnil;
1425:
1426: #ifdef subprocesses
1427: wait_reading_process_input (t, 0, 0);
1428: #else /* No subprocesses */
1429: immediate_quit = 1;
1430: QUIT;
1431:
1432: #ifdef VMS
1433: sys_sleep (t);
1434: #else /* not VMS */
1435: /* The reason this is done this way
1436: (rather than defined (H_S) && defined (H_T))
1437: is because the VMS preprocessor doesn't grok `defined' */
1438: #ifdef HAVE_SELECT
1439: #ifdef HAVE_TIMEVAL
1440: gettimeofday (&end_time, &garbage1);
1441: end_time.tv_sec += t;
1442:
1443: while (1)
1444: {
1445: gettimeofday (&timeout, &garbage1);
1446:
1447: /* In effect, timeout = end_time - timeout.
1448: Break if result would be negative. */
1449: if (timeval_subtract (&timeout, end_time, timeout))
1450: break;
1451:
1452: if (!select (1, 0, 0, 0, &timeout))
1453: break;
1454: }
1455: #else /* not HAVE_TIMEVAL */
1456: /* Is it safe to quit out of `sleep'? I'm afraid to trust it. */
1457: sleep (t);
1458: #endif /* HAVE_TIMEVAL */
1459: #else /* not HAVE_SELECT */
1460: sleep (t);
1461: #endif /* HAVE_SELECT */
1462: #endif /* not VMS */
1463:
1464: immediate_quit = 0;
1465: #endif /* no subprocesses */
1466: return Qnil;
1467: }
1468:
1469: #ifdef HAVE_TIMEVAL
1470:
1471: /* Subtract the `struct timeval' values X and Y,
1472: storing the result in RESULT.
1473: Return 1 if the difference is negative, otherwise 0. */
1474:
1475: int
1476: timeval_subtract (result, x, y)
1477: struct timeval *result, x, y;
1478: {
1479: /* Perform the carry for the later subtraction by updating y.
1480: This is safer because on some systems
1481: the tv_sec member is unsigned. */
1482: if (x.tv_usec < y.tv_usec)
1483: {
1484: int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
1485: y.tv_usec -= 1000000 * nsec;
1486: y.tv_sec += nsec;
1487: }
1488: if (x.tv_usec - y.tv_usec > 1000000)
1489: {
1490: int nsec = (y.tv_usec - x.tv_usec) / 1000000;
1491: y.tv_usec += 1000000 * nsec;
1492: y.tv_sec -= nsec;
1493: }
1494:
1495: /* Compute the time remaining to wait. tv_usec is certainly positive. */
1496: result->tv_sec = x.tv_sec - y.tv_sec;
1497: result->tv_usec = x.tv_usec - y.tv_usec;
1498:
1499: /* Return indication of whether the result should be considered negative. */
1500: return x.tv_sec < y.tv_sec;
1501: }
1502: #endif /* HAVE_TIMEVAL */
1503:
1504: DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 2, 0,
1505: "Perform redisplay, then wait for ARG seconds or until input is available.\n\
1506: Optional second arg non-nil means don't redisplay.\n\
1507: Redisplay is preempted as always if input arrives, and does not happen\n\
1508: if input is available before it starts.\n\
1509: Value is t if waited the full time with no input arriving.")
1510: (n, nodisp)
1511: Lisp_Object n, nodisp;
1512: {
1513: #ifndef subprocesses
1514: #ifdef HAVE_TIMEVAL
1515: struct timeval timeout;
1516: #else
1517: int timeout_sec;
1518: #endif
1519: int waitchannels;
1520: #endif /* no subprocesses */
1521:
1522: CHECK_NUMBER (n, 0);
1523:
1524: if (detect_input_pending ())
1525: return Qnil;
1526:
1527: if (EQ (nodisp, Qnil))
1528: redisplay_preserve_echo_area ();
1529: if (XINT (n) > 0)
1530: {
1531: #ifdef subprocesses
1532: #ifdef SIGIO
1533: gobble_input ();
1534: #endif /* SIGIO */
1535: wait_reading_process_input (XINT (n), 1, 1);
1536: #else /* not subprocesses */
1537: immediate_quit = 1;
1538: QUIT;
1539:
1540: waitchannels = 1;
1541: #ifdef VMS
1542: input_wait_timeout (XINT (n));
1543: #else /* not VMS */
1544: #ifndef HAVE_TIMEVAL
1545: timeout_sec = XINT (n);
1546: select (1, &waitchannels, 0, 0, &timeout_sec);
1547: #else /* HAVE_TIMEVAL */
1548: timeout.tv_sec = XINT (n);
1549: timeout.tv_usec = 0;
1550: select (1, &waitchannels, 0, 0, &timeout);
1551: #endif /* HAVE_TIMEVAL */
1552: #endif /* not VMS */
1553:
1554: immediate_quit = 0;
1555: #endif /* not subprocesses */
1556: }
1557: return detect_input_pending () ? Qnil : Qt;
1558: }
1559:
1560: char *terminal_type;
1561:
1562: /* Initialization done when Emacs fork is started, before doing stty. */
1563: /* Determine terminal type and set terminal_driver */
1564: /* Then invoke its decoding routine to set up variables
1565: in the terminal package */
1566:
1567: init_display ()
1568: {
1569: #ifdef HAVE_X_WINDOWS
1570: extern Lisp_Object Vxterm;
1571: Vxterm = Qnil;
1572: #endif
1573:
1574: Vwindow_system = Qnil;
1575: meta_key = 0;
1576: inverse_video = 0;
1577: cursor_in_echo_area = 0;
1578: terminal_type = (char *) 0;
1579:
1580: if (!inhibit_window_system)
1581: {
1582: #ifdef HAVE_X_WINDOWS
1583: extern char *alternate_display;
1584: char *disp = (char *) egetenv ("DISPLAY");
1585:
1586: /* Note KSH likes to provide an empty string as an envvar value. */
1587: if (alternate_display || (disp && *disp))
1588: {
1589: x_term_init ();
1590: Vxterm = Qt;
1591: Vwindow_system = intern ("x");
1592: #ifdef X11
1593: Vwindow_system_version = make_number (11);
1594: #else
1595: Vwindow_system_version = make_number (10);
1596: #endif
1597: goto term_init_done;
1598: }
1599: #endif /* HAVE_X_WINDOWS */
1600: ;
1601: }
1602: /* Record we aren't using a window system. */
1603: inhibit_window_system = 1;
1604:
1605: /* Look at the TERM variable */
1606: terminal_type = (char *) getenv ("TERM");
1607: if (!terminal_type)
1608: {
1609: #ifdef VMS
1610: fprintf (stderr, "Please specify your terminal type.\n\
1611: For types defined in VMS, use set term /device=TYPE.\n\
1612: For types not defined in VMS, use define emacs_term \"TYPE\".\n\
1613: \(The quotation marks are necessary since terminal types are lower case.)\n");
1614: #else
1615: fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
1616: #endif
1617: exit (1);
1618: }
1619: term_init (terminal_type);
1620:
1621: term_init_done:
1622: remake_screen_structures ();
1623: calculate_costs ();
1624:
1625: #ifdef SIGWINCH
1626: #ifndef CANNOT_DUMP
1627: if (initialized)
1628: #endif /* CANNOT_DUMP */
1629: if (inhibit_window_system)
1630: signal (SIGWINCH, window_change_signal);
1631: #endif /* SIGWINCH */
1632: }
1633:
1634: syms_of_display ()
1635: {
1636: defsubr (&Sopen_termscript);
1637: defsubr (&Sding);
1638: defsubr (&Ssit_for);
1639: defsubr (&Sscreen_height);
1640: defsubr (&Sscreen_width);
1641: defsubr (&Sset_screen_height);
1642: defsubr (&Sset_screen_width);
1643: defsubr (&Ssleep_for);
1644: defsubr (&Sbaud_rate);
1645: defsubr (&Ssend_string_to_terminal);
1646:
1647: DEFVAR_BOOL ("inverse-video", &inverse_video,
1648: "*Non-nil means use inverse-video.");
1649: DEFVAR_BOOL ("visible-bell", &visible_bell,
1650: "*Non-nil means try to flash the screen to represent a bell.\n\
1651: Note: for X windows, you must use x-set-bell instead.");
1652: DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
1653: "*Non-nil means no need to redraw entire screen after suspending.\n\
1654: It is up to you to set this variable to inform Emacs.");
1655: DEFVAR_LISP ("window-system", &Vwindow_system,
1656: "A symbol naming the window-system under which Emacs is running,\n\
1657: \(such as `x'), or nil if emacs is running on an ordinary terminal.");
1658: DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
1659: "Version number of the window system Emacs is running under.");
1660: DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
1661: "Non-nil means put cursor in minibuffer after any message displayed there.");
1662:
1663: /* Initialize `window-system', unless init_display already decided it. */
1664: #ifdef CANNOT_DUMP
1665: if (noninteractive)
1666: #endif
1667: {
1668: Vwindow_system_version = Qnil;
1669: Vwindow_system = Qnil;
1670: }
1671: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.