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