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