|
|
1.1 ! root 1: /* Display generation from window structure and buffer text. ! 2: Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GNU Emacs is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU Emacs; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include <stdio.h> ! 23: /*#include <ctype.h>*/ ! 24: #undef NULL ! 25: #include "lisp.h" ! 26: #include "window.h" ! 27: #include "termchar.h" ! 28: #include "dispextern.h" ! 29: #include "buffer.h" ! 30: #include "indent.h" ! 31: #include "commands.h" ! 32: #include "macros.h" ! 33: ! 34: extern int interrupt_input; ! 35: extern int command_loop_level; ! 36: ! 37: /* Nonzero means print newline before next minibuffer message. */ ! 38: ! 39: int noninteractive_need_newline; ! 40: ! 41: #define min(a, b) ((a) < (b) ? (a) : (b)) ! 42: #define max(a, b) ((a) > (b) ? (a) : (b)) ! 43: ! 44: /* The buffer position of the first character appearing ! 45: entirely or partially on the current screen line. ! 46: Or zero, which disables the optimization for the current screen line. */ ! 47: static int this_line_bufpos; ! 48: ! 49: /* Number of characters past the end of this line, ! 50: including the terminating newline */ ! 51: static int this_line_endpos; ! 52: ! 53: /* The vertical position of this screen line. */ ! 54: static int this_line_vpos; ! 55: ! 56: /* Hpos value for start of display on this screen line. ! 57: Usually zero, but negative if first character really began ! 58: on previous line */ ! 59: static int this_line_start_hpos; ! 60: ! 61: /* Buffer that this_line variables are describing. */ ! 62: static struct buffer *this_line_buffer; ! 63: ! 64: /* Value of echo_area_contents when it was last acted on. ! 65: If this is nonzero, there is a message on the screen ! 66: in the minibuffer and it should be erased as soon ! 67: as it is no longer requested to appear. */ ! 68: char *prev_echo_area_contents; ! 69: ! 70: /* Nonzero means truncate lines in all windows less wide than the screen */ ! 71: int truncate_partial_width_windows; ! 72: ! 73: Lisp_Object Vglobal_mode_string; ! 74: ! 75: /* Marker for where to display an arrow on top of the buffer text. */ ! 76: Lisp_Object Voverlay_arrow_position; ! 77: ! 78: /* String to display for the arrow. */ ! 79: Lisp_Object Voverlay_arrow_string; ! 80: ! 81: /* Values of those variables at last redisplay. */ ! 82: Lisp_Object last_arrow_position, last_arrow_string; ! 83: ! 84: /* If cursor motion alone moves point off screen, ! 85: Try scrolling this many lines up or down if that will bring it back. */ ! 86: int scroll_step; ! 87: ! 88: /* Nonzero means send various TERMCAP strings when screen is cleared. */ ! 89: int reset_terminal_on_clear; ! 90: ! 91: /* Nonzero if try_window_id has made blank lines at window bottom ! 92: since the last redisplay that paused */ ! 93: static int blank_end_of_window; ! 94: ! 95: /* Number of windows showing the buffer of the selected window. ! 96: keyboard.c refers to this. */ ! 97: int buffer_shared; ! 98: ! 99: /* display_text_line sets these to the screen position (origin 0) of point, ! 100: whether the window is selected or not. ! 101: Set one to -1 first to determine whether point was found afterwards. */ ! 102: ! 103: static int point_vpos; ! 104: static int point_hpos; ! 105: ! 106: int debug_end_pos; ! 107: ! 108: /* Nonzero means display mode line highlighted */ ! 109: int mode_line_inverse_video; ! 110: ! 111: struct position *display_text_line (); ! 112: ! 113: /* Prompt to display in front of the minibuffer contents */ ! 114: char *minibuf_prompt; ! 115: ! 116: /* Width in columns of current minibuffer prompt. */ ! 117: int minibuf_prompt_width; ! 118: ! 119: /* Message to display instead of minibuffer contents ! 120: This is what the functions error and message make, ! 121: and command echoing uses it as well. ! 122: It overrides the minibuf_prompt as well as the buffer. */ ! 123: char *echo_area_contents; ! 124: ! 125: /* True iff we should redraw the mode lines on the next redisplay */ ! 126: int update_mode_lines; ! 127: ! 128: /* Smallest number of characters before the gap ! 129: at any time since last redisplay that finished. ! 130: Valid for current buffer when try_window_id can be called. */ ! 131: int beg_unchanged; ! 132: ! 133: /* Smallest number of characters after the gap ! 134: at any time since last redisplay that finished. ! 135: Valid for current buffer when try_window_id can be called. */ ! 136: int end_unchanged; ! 137: ! 138: /* MODIFF as of last redisplay that finished; ! 139: if it matches MODIFF, beg_unchanged and end_unchanged ! 140: contain no useful information */ ! 141: int unchanged_modified; ! 142: ! 143: /* Nonzero if head_clip or tail_clip of current buffer has changed ! 144: since last redisplay that finished */ ! 145: int clip_changed; ! 146: ! 147: /* Nonzero if window sizes or contents have changed ! 148: since last redisplay that finished */ ! 149: int windows_or_buffers_changed; ! 150: ! 151: char *decode_mode_spec (); ! 152: ! 153: DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "", ! 154: "Clear the screen and output again what is supposed to appear on it.") ! 155: () ! 156: { ! 157: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 158: if (reset_terminal_on_clear) ! 159: set_terminal_modes (); ! 160: clear_screen (); ! 161: fflush (stdout); ! 162: clear_screen_records (); ! 163: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 164: windows_or_buffers_changed++; ! 165: /* Mark all windows as INaccurate, ! 166: so that every window will have its redisplay done. */ ! 167: mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0); ! 168: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 169: return Qnil; ! 170: } ! 171: ! 172: /* Buffer used for messages formatted by `message', and by print. */ ! 173: char *message_buf; ! 174: ! 175: /* Nonzero if message_buf is being used by print; ! 176: zero if being used by message. */ ! 177: int message_buf_print; ! 178: ! 179: /* dump an informative message to the minibuf */ ! 180: /* VARARGS 1 */ ! 181: message (m, a1, a2, a3) ! 182: char *m; ! 183: { ! 184: if (noninteractive) ! 185: { ! 186: if (noninteractive_need_newline) ! 187: putchar ('\n'); ! 188: noninteractive_need_newline = 0; ! 189: printf (m, a1, a2, a3); ! 190: printf ("\n"); ! 191: fflush (stdout); ! 192: } ! 193: else if (FROM_KBD) ! 194: { ! 195: #ifdef NO_ARG_ARRAY ! 196: int a[3]; ! 197: a[0] = a1; ! 198: a[1] = a2; ! 199: a[2] = a3; ! 200: ! 201: doprnt (message_buf, screen_width, m, 3, a); ! 202: #else ! 203: doprnt (message_buf, screen_width, m, 3, &a1); ! 204: #endif /* NO_ARG_ARRAY */ ! 205: echo_area_contents = message_buf; ! 206: message_buf_print = 0; ! 207: do { ! 208: do_pending_window_change (); ! 209: display_echo_area_contents (); ! 210: update_screen (1, 1); ! 211: do_pending_window_change (); ! 212: } while (screen_garbaged); ! 213: } ! 214: } ! 215: ! 216: /* Specify m, a string, as a message in the minibuf. */ ! 217: message1 (m) ! 218: char *m; ! 219: { ! 220: if (noninteractive) ! 221: { ! 222: if (noninteractive_need_newline) ! 223: putchar ('\n'); ! 224: noninteractive_need_newline = 0; ! 225: printf ("%s\n", m); ! 226: fflush (stdout); ! 227: } ! 228: else if (FROM_KBD) ! 229: { ! 230: echo_area_contents = m; ! 231: do { ! 232: do_pending_window_change (); ! 233: display_echo_area_contents (); ! 234: update_screen (1, 1); ! 235: do_pending_window_change (); ! 236: } while (screen_garbaged); ! 237: } ! 238: } ! 239: ! 240: display_echo_area_contents () ! 241: { ! 242: register int vpos; ! 243: ! 244: if (screen_garbaged) ! 245: { ! 246: Fredraw_display (); ! 247: screen_garbaged = 0; ! 248: } ! 249: ! 250: if (echo_area_contents || minibuf_level == 0) ! 251: { ! 252: vpos = XFASTINT (XWINDOW (minibuf_window)->top); ! 253: get_display_line (vpos, 0); ! 254: display_string (XWINDOW (minibuf_window), vpos, ! 255: echo_area_contents ? echo_area_contents : "", ! 256: 0, 0, 0, screen_width); ! 257: ! 258: /* If desired cursor location is on this line, put it at end of text */ ! 259: if (cursor_vpos == vpos) ! 260: cursor_hpos = new_screen->used[vpos]; ! 261: ! 262: /* Fill the rest of the minibuffer window with blank lines. */ ! 263: { ! 264: int i; ! 265: ! 266: for (i = vpos + 1; i < vpos + XWINDOW (minibuf_window)->height; i++) ! 267: { ! 268: get_display_line (i, 0); ! 269: display_string (XWINDOW (minibuf_window), vpos, ! 270: "", 0, 0, 0, screen_width); ! 271: } ! 272: } ! 273: } ! 274: else if (!EQ (minibuf_window, selected_window)) ! 275: windows_or_buffers_changed++; ! 276: ! 277: if (EQ (minibuf_window, selected_window)) ! 278: this_line_bufpos = 0; ! 279: ! 280: prev_echo_area_contents = echo_area_contents; ! 281: } ! 282: ! 283: /* Do a screen update, taking possible shortcuts into account. ! 284: This is the main external entry point for redisplay. ! 285: ! 286: If the last redisplay displayed an echo area message and that ! 287: message is no longer requested, we clear the echo area ! 288: or bring back the minibuffer if that is in use. ! 289: ! 290: Everyone would like to have a hook here to call eval, ! 291: but that cannot be done safely without a lot of changes elsewhere. ! 292: This can be called from signal handlers; with alarms set up; ! 293: or with synchronous processes running. ! 294: See the function `echo' in keyboard.c. ! 295: See Fcall_process; if you called it from here, it could be ! 296: entered recursively. */ ! 297: ! 298: redisplay () ! 299: { ! 300: register struct window *w = XWINDOW (selected_window); ! 301: register int pause; ! 302: int inhibit_hairy_id = 0; ! 303: int must_finish = 0; ! 304: int all_windows; ! 305: register int tlbufpos, tlendpos; ! 306: struct position pos; ! 307: extern int input_pending; ! 308: ! 309: if (noninteractive) ! 310: return; ! 311: ! 312: /* Notice any pending interrupt request to change screen size. */ ! 313: do_pending_window_change (); ! 314: ! 315: if (screen_garbaged) ! 316: { ! 317: Fredraw_display (); ! 318: screen_garbaged = 0; ! 319: } ! 320: ! 321: /* Initially we have nothing to update on the screen. */ ! 322: bzero (new_screen->enable, new_screen->height); ! 323: ! 324: if (echo_area_contents != 0 || prev_echo_area_contents != 0) ! 325: { ! 326: display_echo_area_contents (); ! 327: must_finish = 1; ! 328: } ! 329: ! 330: if (clip_changed || windows_or_buffers_changed) ! 331: update_mode_lines++; ! 332: ! 333: /* Detect case that we need to write a star in the mode line. */ ! 334: if (XFASTINT (w->last_modified) < MODIFF ! 335: && XFASTINT (w->last_modified) <= current_buffer->save_modified) ! 336: { ! 337: w->update_mode_line = Qt; ! 338: if (buffer_shared > 1) ! 339: update_mode_lines++; ! 340: } ! 341: ! 342: all_windows = update_mode_lines || buffer_shared > 1; ! 343: ! 344: /* If specs for an arrow have changed, do thorough redisplay ! 345: to ensure we remove any arrow that should no longer exist. */ ! 346: if (Voverlay_arrow_position != last_arrow_position ! 347: || Voverlay_arrow_string != last_arrow_string) ! 348: all_windows = 1, clip_changed = 1; ! 349: ! 350: tlbufpos = this_line_bufpos; ! 351: tlendpos = this_line_endpos; ! 352: if (!all_windows && tlbufpos > 0 && NULL (w->update_mode_line) ! 353: /* Make sure recorded data applies to current buffer, etc */ ! 354: && this_line_buffer == current_buffer ! 355: && current_buffer == XBUFFER (w->buffer) ! 356: && NULL (w->force_start) ! 357: /* Point must be on the line that we have info recorded about */ ! 358: && point >= tlbufpos ! 359: && point <= Z - tlendpos ! 360: /* All text outside that line, including its final newline, ! 361: must be unchanged */ ! 362: && (XFASTINT (w->last_modified) >= MODIFF ! 363: || (beg_unchanged >= tlbufpos - 1 ! 364: && GPT >= tlbufpos ! 365: /* If selective display, can't optimize ! 366: if the changes start at the beginning of the line. */ ! 367: && ((XTYPE (current_buffer->selective_display) == Lisp_Int ! 368: && XINT (current_buffer->selective_display) > 0 ! 369: ? (beg_unchanged >= tlbufpos ! 370: && GPT > tlbufpos) ! 371: : 1)) ! 372: && end_unchanged >= tlendpos ! 373: && Z - GPT >= tlendpos))) ! 374: { ! 375: if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n' ! 376: && (tlbufpos == ZV ! 377: || FETCH_CHAR (tlbufpos) == '\n')) ! 378: /* Former continuation line has disappeared by becoming empty */ ! 379: goto cancel; ! 380: else if (XFASTINT (w->last_modified) < MODIFF ! 381: || EQ (selected_window, minibuf_window)) ! 382: { ! 383: point_vpos = -1; ! 384: display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos, ! 385: pos_tab_offset (w, tlbufpos)); ! 386: /* If line contains point, is not continued, ! 387: and ends at same distance from eob as before, we win */ ! 388: if (point_vpos >= 0 && this_line_bufpos ! 389: && this_line_endpos == tlendpos) ! 390: { ! 391: /* Done by display_text_line ! 392: cursor_hpos = point_hpos; ! 393: cursor_vpos = this_line_vpos; ! 394: */ ! 395: if (XFASTINT (w->width) != screen_width) ! 396: preserve_other_columns (w); ! 397: goto update; ! 398: } ! 399: else ! 400: goto cancel; ! 401: } ! 402: else if (point == XFASTINT (w->last_point)) ! 403: { ! 404: if (!must_finish) ! 405: return; ! 406: goto update; ! 407: } ! 408: else ! 409: { ! 410: pos = *compute_motion (tlbufpos, 0, ! 411: XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0, ! 412: point, 2, - (1 << (SHORTBITS - 1)), ! 413: XFASTINT (w->width) - 1 ! 414: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width), ! 415: XINT (w->hscroll), ! 416: pos_tab_offset (w, tlbufpos)); ! 417: if (pos.vpos < 1) ! 418: { ! 419: cursor_hpos = max (XFASTINT (w->left), pos.hpos); ! 420: cursor_vpos = this_line_vpos; ! 421: goto update; ! 422: } ! 423: else ! 424: goto cancel; ! 425: } ! 426: cancel: ! 427: /* Text changed drastically or point moved off of line */ ! 428: cancel_line (this_line_vpos); ! 429: } ! 430: ! 431: this_line_bufpos = 0; ! 432: ! 433: if (all_windows) ! 434: redisplay_all_windows (); ! 435: else ! 436: { ! 437: redisplay_window (selected_window, 1); ! 438: if (XFASTINT (w->width) != screen_width) ! 439: preserve_other_columns (w); ! 440: } ! 441: ! 442: update: ! 443: /* Prevent various kinds of signals during display update. ! 444: stdio is not robust about handling signals, ! 445: which can cause an apparent I/O error. */ ! 446: if (interrupt_input) ! 447: unrequest_sigio (); ! 448: stop_polling (); ! 449: ! 450: pause = update_screen (0, 0); ! 451: ! 452: /* If screen does not match, prevent doing single-line-update next time. ! 453: Also, don't forget to check every line to update the arrow. */ ! 454: if (pause) ! 455: { ! 456: this_line_bufpos = 0; ! 457: if (!NULL (last_arrow_position)) ! 458: { ! 459: last_arrow_position = Qt; ! 460: last_arrow_string = Qt; ! 461: } ! 462: /* If we pause after scrolling, some lines in PhysScreen may be null ! 463: and then preserve_other_columns won't be able to preserve all ! 464: the vertical-bar separators. So avoid using it in that case. */ ! 465: if (XFASTINT (w->width) != screen_width) ! 466: update_mode_lines = 1; ! 467: } ! 468: ! 469: /* Now text on screen agrees with windows, so ! 470: put info into the windows for partial redisplay to follow */ ! 471: ! 472: if (!pause) ! 473: { ! 474: struct buffer *b = XBUFFER (w->buffer); ! 475: ! 476: blank_end_of_window = 0; ! 477: clip_changed = 0; ! 478: unchanged_modified = BUF_MODIFF (b); ! 479: beg_unchanged = BUF_GPT (b) - BUF_BEG (b); ! 480: end_unchanged = BUF_Z (b) - BUF_GPT (b); ! 481: ! 482: XFASTINT (w->last_point) = BUF_PT (b); ! 483: XFASTINT (w->last_point_x) = cursor_hpos; ! 484: XFASTINT (w->last_point_y) = cursor_vpos; ! 485: ! 486: if (all_windows) ! 487: mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 1); ! 488: else ! 489: { ! 490: w->update_mode_line = Qnil; ! 491: XFASTINT (w->last_modified) = BUF_MODIFF (b); ! 492: w->window_end_valid = Qt; ! 493: last_arrow_position = Voverlay_arrow_position; ! 494: last_arrow_string = Voverlay_arrow_string; ! 495: } ! 496: update_mode_lines = 0; ! 497: windows_or_buffers_changed = 0; ! 498: } ! 499: ! 500: /* Start SIGIO interrupts coming again. ! 501: Having them off during the code above ! 502: makes it less likely one will discard output, ! 503: but not impossible, since there might be stuff ! 504: in the system buffer here. ! 505: But it is much hairier to try to do anything about that. */ ! 506: ! 507: if (interrupt_input) ! 508: request_sigio (); ! 509: start_polling (); ! 510: ! 511: do_pending_window_change (); ! 512: ! 513: if (screen_garbaged) ! 514: redisplay (); ! 515: } ! 516: ! 517: /* Redisplay, but leave alone any recent echo area message ! 518: unless another message has been requested in its place. */ ! 519: ! 520: redisplay_preserve_echo_area () ! 521: { ! 522: if (echo_area_contents == 0 && prev_echo_area_contents != 0) ! 523: { ! 524: echo_area_contents = prev_echo_area_contents; ! 525: redisplay (); ! 526: echo_area_contents = 0; ! 527: } ! 528: else ! 529: redisplay (); ! 530: } ! 531: ! 532: mark_window_display_accurate (window, flag) ! 533: Lisp_Object window; ! 534: int flag; ! 535: { ! 536: register struct window *w; ! 537: ! 538: for (;!NULL (window); window = w->next) ! 539: { ! 540: w = XWINDOW (window); ! 541: ! 542: if (!NULL (w->buffer)) ! 543: XFASTINT (w->last_modified) ! 544: = !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)); ! 545: w->window_end_valid = Qt; ! 546: w->update_mode_line = Qnil; ! 547: ! 548: if (!NULL (w->vchild)) ! 549: mark_window_display_accurate (w->vchild, flag); ! 550: if (!NULL (w->hchild)) ! 551: mark_window_display_accurate (w->hchild, flag); ! 552: } ! 553: ! 554: if (flag) ! 555: { ! 556: last_arrow_position = Voverlay_arrow_position; ! 557: last_arrow_string = Voverlay_arrow_string; ! 558: } ! 559: else ! 560: { ! 561: /* t is unequal to any useful value of Voverlay_arrow_... */ ! 562: last_arrow_position = Qt; ! 563: last_arrow_string = Qt; ! 564: } ! 565: } ! 566: ! 567: int do_id = 1; ! 568: ! 569: /* Do full redisplay of one or all windows. ! 570: This does not include updating the screen; ! 571: just generating lines to pass to update_screen. */ ! 572: ! 573: /* Entry point to redisplay all windows */ ! 574: ! 575: redisplay_all_windows () ! 576: { ! 577: buffer_shared = 0; ! 578: ! 579: redisplay_windows (XWINDOW (minibuf_window)->prev); ! 580: } ! 581: ! 582: redisplay_windows (window) ! 583: Lisp_Object window; ! 584: { ! 585: for (; !NULL (window); window = XWINDOW (window)->next) ! 586: redisplay_window (window, 0); ! 587: } ! 588: ! 589: redisplay_window (window, just_this_one) ! 590: Lisp_Object window; ! 591: int just_this_one; ! 592: { ! 593: register struct window *w = XWINDOW (window); ! 594: int height; ! 595: struct buffer *old = current_buffer; ! 596: register int width = XFASTINT (w->width) - 1 ! 597: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 598: register int startp; ! 599: register int hscroll = XINT (w->hscroll); ! 600: struct position pos; ! 601: int opoint; ! 602: int tem; ! 603: ! 604: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 605: ! 606: /* If this is a combination window, do its children; that's all. */ ! 607: ! 608: if (!NULL (w->vchild)) ! 609: { ! 610: redisplay_windows (w->vchild); ! 611: return; ! 612: } ! 613: if (!NULL (w->hchild)) ! 614: { ! 615: redisplay_windows (w->hchild); ! 616: return; ! 617: } ! 618: if (NULL (w->buffer)) ! 619: abort (); ! 620: ! 621: if (update_mode_lines) ! 622: w->update_mode_line = Qt; ! 623: ! 624: /* Otherwise set up data on this window; select its buffer and point value */ ! 625: ! 626: height = XFASTINT (w->height); ! 627: if (w != XWINDOW (minibuf_window)) ! 628: height--; ! 629: else if (echo_area_contents) ! 630: return 0; ! 631: ! 632: current_buffer = XBUFFER (w->buffer); ! 633: ! 634: if (!just_this_one ! 635: && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer)) ! 636: buffer_shared++; ! 637: ! 638: /* Go temporarily to where point is in the window being displayed. ! 639: We will restore point at the end. */ ! 640: opoint = point; ! 641: if (!EQ (window, selected_window)) ! 642: { ! 643: SET_PT (marker_position (w->pointm)); ! 644: if (point < BEGV) ! 645: point = BEGV; ! 646: else if (point > ZV) ! 647: point = ZV; ! 648: } ! 649: ! 650: /* If window-start is screwed up, choose a new one. */ ! 651: ! 652: if (XMARKER (w->start)->buffer != current_buffer) ! 653: goto recenter; ! 654: ! 655: startp = marker_position (w->start); ! 656: ! 657: /* Handle case where place to start displaying has been specified */ ! 658: ! 659: if (!NULL (w->force_start)) ! 660: { ! 661: w->update_mode_line = Qt; ! 662: w->force_start = Qnil; ! 663: XFASTINT (w->last_modified) = 0; ! 664: ! 665: /* Constrain the starting position to be within the visible range. */ ! 666: startp = clip_to_bounds (BEGV, startp, ZV); ! 667: ! 668: try_window (window, startp); ! 669: if (point_vpos < 0) ! 670: { ! 671: /* If point does not appear, move point so it does appear */ ! 672: pos = *compute_motion (startp, 0, ! 673: ((EQ (window, minibuf_window) && startp == 1) ! 674: ? minibuf_prompt_width : 0) ! 675: + ! 676: (hscroll ? 1 - hscroll : 0), ! 677: ZV, height / 2, ! 678: - (1 << (SHORTBITS - 1)), ! 679: width, hscroll, pos_tab_offset (w, startp)); ! 680: SET_PT (pos.bufpos); ! 681: if (w != XWINDOW (selected_window)) ! 682: Fset_marker (w->pointm, make_number (point), Qnil); ! 683: else ! 684: /* We want to change point permanently, ! 685: so don't restore the old value. */ ! 686: opoint = point; ! 687: ! 688: if (EQ (window, selected_window)) ! 689: { ! 690: cursor_hpos = max (0, pos.hpos) + XFASTINT (w->left); ! 691: cursor_vpos = pos.vpos + XFASTINT (w->top); ! 692: } ! 693: } ! 694: goto done; ! 695: } ! 696: ! 697: /* Handle case where text has not changed, only point, ! 698: and it has not moved off the screen */ ! 699: ! 700: /* This code is not used for minibuffer for the sake of ! 701: the case of redisplaying to replace an echo area message; ! 702: since in that case the minibuffer contents per se are usually unchanged. ! 703: This code is of no real use in the minibuffer since ! 704: the handling of this_line_bufpos, etc., ! 705: in redisplay handles the same cases. */ ! 706: ! 707: if (XFASTINT (w->last_modified) >= MODIFF ! 708: && point >= startp && !clip_changed ! 709: && (just_this_one || XFASTINT (w->width) == screen_width) ! 710: && !EQ (window, minibuf_window)) ! 711: { ! 712: pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), ! 713: point, height + 1, 10000, width, hscroll, ! 714: pos_tab_offset (w, startp)); ! 715: ! 716: if (pos.vpos < height) ! 717: { ! 718: /* Ok, point is still on screen */ ! 719: if (w == XWINDOW (selected_window)) ! 720: { ! 721: /* These variables are supposed to be origin 1 */ ! 722: cursor_hpos = max (0, pos.hpos) + XFASTINT (w->left); ! 723: cursor_vpos = pos.vpos + XFASTINT (w->top); ! 724: } ! 725: /* This doesn't do the trick, because if a window to the right of ! 726: this one must be redisplayed, this does nothing because there ! 727: is nothing in DesiredScreen yet, and then the other window is ! 728: redisplayed, making likes that are empty in this window's columns. ! 729: if (XFASTINT (w->width) != screen_width) ! 730: preserve_my_columns (w); ! 731: */ ! 732: goto done; ! 733: } ! 734: /* Don't bother trying redisplay with same start; ! 735: we already know it will lose */ ! 736: } ! 737: /* If current starting point was originally the beginning of a line ! 738: but no longer is, find a new starting point. */ ! 739: else if (!NULL (w->start_at_line_beg) ! 740: && !(startp == BEGV ! 741: || FETCH_CHAR (startp - 1) == '\n')) ! 742: { ! 743: goto recenter; ! 744: } ! 745: else if (just_this_one && !EQ (window, minibuf_window) ! 746: && point >= startp ! 747: && XFASTINT (w->last_modified) ! 748: && ! EQ (w->window_end_valid, Qnil) ! 749: && do_id && !clip_changed ! 750: && !blank_end_of_window ! 751: && XFASTINT (w->width) == screen_width ! 752: && EQ (last_arrow_position, Voverlay_arrow_position) ! 753: && EQ (last_arrow_string, Voverlay_arrow_string) ! 754: && (tem = try_window_id (selected_window)) ! 755: && tem != -2) ! 756: { ! 757: /* tem > 0 means success. tem == -1 means choose new start. ! 758: tem == -2 means try again with same start, ! 759: and nothing but whitespace follows the changed stuff. ! 760: tem == 0 means try again with same start. */ ! 761: if (tem > 0) ! 762: { ! 763: goto done; ! 764: } ! 765: } ! 766: else if (startp >= BEGV && startp <= ZV ! 767: /* Avoid starting display at end of buffer! */ ! 768: && (startp < ZV || startp == BEGV ! 769: || (XFASTINT (w->last_modified) >= MODIFF))) ! 770: { ! 771: /* Try to redisplay starting at same place as before */ ! 772: /* If point has not moved off screen, accept the results */ ! 773: try_window (window, startp); ! 774: if (point_vpos >= 0) ! 775: goto done; ! 776: else ! 777: cancel_my_columns (w); ! 778: } ! 779: ! 780: XFASTINT (w->last_modified) = 0; ! 781: w->update_mode_line = Qt; ! 782: ! 783: /* Try to scroll by specified few lines */ ! 784: ! 785: if (scroll_step && !clip_changed) ! 786: { ! 787: if (point > startp) ! 788: { ! 789: pos = *vmotion (Z - XFASTINT (w->window_end_pos), ! 790: scroll_step, width, hscroll, window); ! 791: if (pos.vpos >= height) ! 792: goto scroll_fail; ! 793: } ! 794: ! 795: pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step, ! 796: width, hscroll, window); ! 797: ! 798: if (point >= pos.bufpos) ! 799: { ! 800: try_window (window, pos.bufpos); ! 801: if (point_vpos >= 0) ! 802: goto done; ! 803: else ! 804: cancel_my_columns (w); ! 805: } ! 806: scroll_fail: ; ! 807: } ! 808: ! 809: /* Finally, just choose place to start which centers point */ ! 810: ! 811: recenter: ! 812: pos = *vmotion (point, - height / 2, width, hscroll, window); ! 813: try_window (window, pos.bufpos); ! 814: ! 815: startp = marker_position (w->start); ! 816: w->start_at_line_beg = ! 817: (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil; ! 818: ! 819: done: ! 820: /* If window not full width, must redo its mode line ! 821: if the window to its side is being redone */ ! 822: if ((!NULL (w->update_mode_line) ! 823: || (!just_this_one && width < screen_width - 1)) ! 824: && !EQ (window, minibuf_window)) ! 825: display_mode_line (w); ! 826: ! 827: SET_PT (opoint); ! 828: current_buffer = old; ! 829: } ! 830: ! 831: /* Do full redisplay on one window, ! 832: starting at position `pos'. */ ! 833: ! 834: try_window (window, pos) ! 835: Lisp_Object window; ! 836: register int pos; ! 837: { ! 838: register struct window *w = XWINDOW (window); ! 839: register int height = XFASTINT (w->height) - !EQ (window, minibuf_window); ! 840: register int vpos = XFASTINT (w->top); ! 841: register int last_text_vpos = vpos; ! 842: int tab_offset = pos_tab_offset (w, pos); ! 843: ! 844: struct position val; ! 845: ! 846: Fset_marker (w->start, make_number (pos), Qnil); ! 847: ! 848: point_vpos = -1; ! 849: val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; ! 850: ! 851: while (--height >= 0) ! 852: { ! 853: val = *display_text_line (w, pos, vpos, val.hpos, tab_offset); ! 854: tab_offset += (XFASTINT (w->width) - 1 ! 855: - (XFASTINT (w->width) + XFASTINT (w->left) ! 856: != screen_width)); ! 857: if (val.vpos) tab_offset = 0; ! 858: vpos++; ! 859: if (pos != val.bufpos) ! 860: last_text_vpos ! 861: /* Next line, unless prev line ended in end of buffer with no cr */ ! 862: = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n'); ! 863: pos = val.bufpos; ! 864: } ! 865: ! 866: /* If last line is continued in middle of character, ! 867: include the split character in the text considered on the screen */ ! 868: if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)) ! 869: pos++; ! 870: ! 871: /* Say where last char on screen will be, once redisplay is finished. */ ! 872: XFASTINT (w->window_end_pos) = Z - pos; ! 873: XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top); ! 874: /* But that is not valid info until redisplay finishes. */ ! 875: w->window_end_valid = Qnil; ! 876: } ! 877: ! 878: /* Try to redisplay when buffer is modified locally, ! 879: computing insert/delete line to preserve text outside ! 880: the bounds of the changes. ! 881: Return 1 if successful, 0 if if cannot tell what to do, ! 882: or -1 to tell caller to find a new window start, ! 883: or -2 to tell caller to do normal redisplay with same window start. */ ! 884: ! 885: static struct position debug_bp, debug_ep, debug_xp, debug_pp; ! 886: static int debug_start_vpos, debug_stop_vpos, debug_scroll_amount; ! 887: static int debug_dont_scroll; ! 888: ! 889: try_window_id (window) ! 890: Lisp_Object window; ! 891: { ! 892: int pos; ! 893: register struct window *w = XWINDOW (window); ! 894: register int height = XFASTINT (w->height) - !EQ (window, minibuf_window); ! 895: int top = XFASTINT (w->top); ! 896: int start = marker_position (w->start); ! 897: int width = XFASTINT (w->width) - 1 ! 898: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 899: int hscroll = XINT (w->hscroll); ! 900: int lmargin = hscroll > 0 ? 1 - hscroll : 0; ! 901: register int vpos; ! 902: register int i, tem; ! 903: int last_text_vpos = 0; ! 904: int stop_vpos; ! 905: ! 906: struct position val, bp, ep, xp, pp; ! 907: int scroll_amount = 0; ! 908: int delta; ! 909: int tab_offset, epto; ! 910: ! 911: if (GPT - BEG < beg_unchanged) ! 912: beg_unchanged = GPT - BEG; ! 913: if (Z - GPT < end_unchanged) ! 914: end_unchanged = Z - GPT; ! 915: ! 916: if (beg_unchanged + 1 < start) ! 917: return 0; /* Give up if changes go above top of window */ ! 918: ! 919: /* Find position before which nothing is changed. */ ! 920: bp = *compute_motion (start, 0, lmargin, ! 921: beg_unchanged + 1, height + 1, 0, width, hscroll, ! 922: pos_tab_offset (w, start)); ! 923: if (bp.vpos >= height) ! 924: { ! 925: if (point < bp.bufpos && !bp.contin) ! 926: { ! 927: /* All changes are below the screen, and point is on the screen. ! 928: We don't need to change the screen at all. ! 929: But we need to update window_end_pos to account for ! 930: any change in buffer size. */ ! 931: bp = *compute_motion (start, 0, lmargin, ! 932: Z, height, 0, ! 933: width, hscroll, pos_tab_offset (w, start)); ! 934: XFASTINT (w->window_end_vpos) = height; ! 935: XFASTINT (w->window_end_pos) = Z - bp.bufpos; ! 936: return 1; ! 937: } ! 938: return 0; ! 939: } ! 940: ! 941: vpos = bp.vpos; ! 942: ! 943: /* Find beginning of that screen line. Must display from there. */ ! 944: bp = *vmotion (bp.bufpos, 0, width, hscroll, window); ! 945: ! 946: pos = bp.bufpos; ! 947: val.hpos = lmargin; ! 948: if (pos < start) ! 949: return -1; ! 950: ! 951: /* If about to start displaying at the beginning of a continuation line, ! 952: really start with previous screen line, in case it was not ! 953: continued when last redisplayed */ ! 954: if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0) ! 955: || ! 956: /* Likewise if we have to worry about selective display. */ ! 957: (XTYPE (current_buffer->selective_display) == Lisp_Int ! 958: && XINT (current_buffer->selective_display) > 0 ! 959: && bp.bufpos - 1 == beg_unchanged && vpos > 0)) ! 960: { ! 961: bp = *vmotion (bp.bufpos, -1, width, hscroll, window); ! 962: --vpos; ! 963: pos = bp.bufpos; ! 964: } ! 965: ! 966: if (bp.contin && bp.hpos != lmargin) ! 967: { ! 968: val.hpos = bp.prevhpos - width + lmargin; ! 969: pos--; ! 970: } ! 971: ! 972: bp.vpos = vpos; ! 973: ! 974: /* Find first visible newline after which no more is changed. */ ! 975: tem = find_next_newline (Z - max (end_unchanged, Z - ZV), ! 976: 1); ! 977: if (XTYPE (current_buffer->selective_display) == Lisp_Int ! 978: && XINT (current_buffer->selective_display) > 0) ! 979: while (tem < ZV - 1 ! 980: && (position_indentation (tem) ! 981: >= XINT (current_buffer->selective_display))) ! 982: tem = find_next_newline (tem, 1); ! 983: ! 984: /* Compute the cursor position after that newline. */ ! 985: ep = *compute_motion (pos, vpos, val.hpos, tem, ! 986: height, - (1 << (SHORTBITS - 1)), ! 987: width, hscroll, pos_tab_offset (w, bp.bufpos)); ! 988: ! 989: /* If changes reach past the text available on the screen, ! 990: just display rest of screen. */ ! 991: if (ep.bufpos > Z - XFASTINT (w->window_end_pos)) ! 992: stop_vpos = height; ! 993: else ! 994: stop_vpos = ep.vpos; ! 995: ! 996: /* If no newline before ep, the line ep is on includes some changes ! 997: that must be displayed. Make sure we don't stop before it. */ ! 998: /* Also, if changes reach all the way until ep.bufpos, ! 999: it is possible that something was deleted after the ! 1000: newline before it, so the following line must be redrawn. */ ! 1001: if (stop_vpos == ep.vpos ! 1002: && (ep.bufpos == BEGV ! 1003: || FETCH_CHAR (ep.bufpos - 1) != '\n' ! 1004: || ep.bufpos == Z - end_unchanged)) ! 1005: stop_vpos = ep.vpos + 1; ! 1006: ! 1007: point_vpos = -1; ! 1008: debug_dont_scroll = 0; ! 1009: ! 1010: /* If changes do not reach to bottom of window, ! 1011: figure out how much to scroll the rest of the window */ ! 1012: if (stop_vpos < height) ! 1013: { ! 1014: /* Now determine how far up or down the rest of the window has moved */ ! 1015: epto = pos_tab_offset (w, ep.bufpos); ! 1016: xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, ! 1017: Z - XFASTINT (w->window_end_pos), ! 1018: 10000, 0, width, hscroll, epto); ! 1019: scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos); ! 1020: ! 1021: /* Is everything on screen below the changes whitespace? ! 1022: If so, no scrolling is really necessary. */ ! 1023: for (i = ep.bufpos; i < xp.bufpos; i++) ! 1024: { ! 1025: tem = FETCH_CHAR (i); ! 1026: if (tem != ' ' && tem != '\n' && tem != '\t') ! 1027: break; ! 1028: } ! 1029: if (i == xp.bufpos) ! 1030: return -2; ! 1031: ! 1032: XFASTINT (w->window_end_vpos) += scroll_amount; ! 1033: ! 1034: /* Before doing any scrolling, verify that point will be on screen. */ ! 1035: if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height)) ! 1036: { ! 1037: if (point <= xp.bufpos) ! 1038: { ! 1039: pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, ! 1040: point, height, - (1 << (SHORTBITS - 1)), ! 1041: width, hscroll, epto); ! 1042: } ! 1043: else ! 1044: { ! 1045: pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, ! 1046: point, height, - (1 << (SHORTBITS - 1)), ! 1047: width, hscroll, pos_tab_offset (w, xp.bufpos)); ! 1048: } ! 1049: if (pp.bufpos < point || pp.vpos == height) ! 1050: return 0; ! 1051: point_vpos = pp.vpos + top; ! 1052: point_hpos = pp.hpos + XFASTINT (w->left); ! 1053: } ! 1054: ! 1055: if (stop_vpos - scroll_amount >= height ! 1056: || ep.bufpos == xp.bufpos) ! 1057: { ! 1058: if (scroll_amount < 0) ! 1059: stop_vpos -= scroll_amount; ! 1060: scroll_amount = 0; ! 1061: debug_dont_scroll = 1; ! 1062: /* In this path, we have altered window_end_vpos ! 1063: and not left it negative. ! 1064: We must make sure that, in case display is preempted ! 1065: before the screen changes to reflect what we do here, ! 1066: further updates will not come to try_window_id ! 1067: and assume the screen and window_end_vpos match. */ ! 1068: blank_end_of_window = 1; ! 1069: } ! 1070: else if (!scroll_amount) ! 1071: {} ! 1072: else if (bp.bufpos == Z - end_unchanged) ! 1073: { ! 1074: /* If reprinting everything is nearly as fast as scrolling, ! 1075: don't bother scrolling. Can happen if lines are short. */ ! 1076: if (scroll_cost (bp.vpos + top - scroll_amount, ! 1077: top + height - max (0, scroll_amount), ! 1078: scroll_amount) ! 1079: > xp.bufpos - bp.bufpos - 20) ! 1080: /* Return "try normal display with same window-start." ! 1081: Too bad we can't prevent further scroll-thinking. */ ! 1082: return -2; ! 1083: /* If pure deletion, scroll up as many lines as possible. ! 1084: In common case of killing a line, this can save the ! 1085: following line from being overwritten by scrolling ! 1086: and therefore having to be redrawn. */ ! 1087: tem = scroll_screen_lines (bp.vpos + top - scroll_amount, ! 1088: top + height - max (0, scroll_amount), ! 1089: scroll_amount); ! 1090: if (!tem) stop_vpos = height; ! 1091: } ! 1092: else if (scroll_amount) ! 1093: { ! 1094: /* If reprinting everything is nearly as fast as scrolling, ! 1095: don't bother scrolling. Can happen if lines are short. */ ! 1096: /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an ! 1097: overestimate of cost of reprinting, since xp.bufpos ! 1098: would end up below the bottom of the window. */ ! 1099: if (scroll_cost (ep.vpos + top - scroll_amount, ! 1100: top + height - max (0, scroll_amount), ! 1101: scroll_amount) ! 1102: > xp.bufpos - ep.bufpos - 20) ! 1103: /* Return "try normal display with same window-start." ! 1104: Too bad we can't prevent further scroll-thinking. */ ! 1105: return -2; ! 1106: tem = scroll_screen_lines (ep.vpos + top - scroll_amount, ! 1107: top + height - max (0, scroll_amount), ! 1108: scroll_amount); ! 1109: if (!tem) stop_vpos = height; ! 1110: } ! 1111: } ! 1112: ! 1113: debug_scroll_amount = scroll_amount; ! 1114: debug_bp = bp; ! 1115: debug_ep = ep; ! 1116: debug_xp = xp; ! 1117: debug_pp = pp; ! 1118: ! 1119: /* In any case, do not display past bottom of window */ ! 1120: if (stop_vpos >= height) ! 1121: { ! 1122: stop_vpos = height; ! 1123: scroll_amount = 0; ! 1124: } ! 1125: ! 1126: debug_stop_vpos = stop_vpos; ! 1127: debug_start_vpos = vpos; ! 1128: ! 1129: /* Handle case where pos is before w->start -- ! 1130: can happen if part of line had been clipped and is not clipped now */ ! 1131: if (vpos == 0 && pos < marker_position (w->start)) ! 1132: Fset_marker (w->start, make_number (pos), Qnil); ! 1133: ! 1134: /* Redisplay the lines where the text was changed */ ! 1135: last_text_vpos = vpos; ! 1136: tab_offset = pos_tab_offset (w, pos); ! 1137: if (val.hpos + hscroll - (hscroll > 0) < 0) ! 1138: tab_offset += (XFASTINT (w->width) - 1 ! 1139: - (XFASTINT (w->width) + XFASTINT (w->left) ! 1140: != screen_width)); ! 1141: while (vpos < stop_vpos) ! 1142: { ! 1143: val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); ! 1144: tab_offset += (XFASTINT (w->width) - 1 ! 1145: - (XFASTINT (w->width) + XFASTINT (w->left) ! 1146: != screen_width)); ! 1147: if (val.vpos) tab_offset = 0; ! 1148: if (pos != val.bufpos) ! 1149: last_text_vpos ! 1150: /* Next line, unless prev line ended in end of buffer with no cr */ ! 1151: = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n'); ! 1152: pos = val.bufpos; ! 1153: } ! 1154: ! 1155: /* There are two cases: ! 1156: 1) we have displayed down to the bottom of the window ! 1157: 2) we have scrolled lines below stop_vpos by scroll_amount */ ! 1158: ! 1159: if (vpos == height) ! 1160: { ! 1161: /* If last line is continued in middle of character, ! 1162: include the split character in the text considered on the screen */ ! 1163: if (val.hpos < lmargin) ! 1164: val.bufpos++; ! 1165: XFASTINT (w->window_end_vpos) = last_text_vpos; ! 1166: XFASTINT (w->window_end_pos) = Z - val.bufpos; ! 1167: } ! 1168: ! 1169: /* If scrolling made blank lines at window bottom, ! 1170: redisplay to fill those lines */ ! 1171: if (scroll_amount < 0) ! 1172: { ! 1173: vpos = xp.vpos; ! 1174: pos = xp.bufpos; ! 1175: val.hpos = lmargin; ! 1176: if (pos == ZV) ! 1177: vpos = height + scroll_amount; ! 1178: else if (xp.contin && xp.hpos != lmargin) ! 1179: { ! 1180: val.hpos = xp.prevhpos - width + lmargin; ! 1181: pos--; ! 1182: } ! 1183: ! 1184: blank_end_of_window = 1; ! 1185: tab_offset = pos_tab_offset (w, pos); ! 1186: if (val.hpos < 0) ! 1187: tab_offset += (XFASTINT (w->width) - 1 ! 1188: - (XFASTINT (w->width) + XFASTINT (w->left) ! 1189: != screen_width)); ! 1190: ! 1191: while (vpos < height) ! 1192: { ! 1193: val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); ! 1194: tab_offset += (XFASTINT (w->width) - 1 ! 1195: - (XFASTINT (w->width) + XFASTINT (w->left) ! 1196: != screen_width)); ! 1197: if (val.vpos) tab_offset = 0; ! 1198: pos = val.bufpos; ! 1199: } ! 1200: ! 1201: /* Here is a case where display_text_line sets point_vpos wrong. ! 1202: Make it be fixed up, below. */ ! 1203: if (xp.bufpos == ZV ! 1204: && xp.bufpos == point) ! 1205: point_vpos = -1; ! 1206: } ! 1207: ! 1208: /* Attempt to adjust end-of-text positions to new bottom line */ ! 1209: if (scroll_amount) ! 1210: { ! 1211: delta = height - xp.vpos; ! 1212: if (delta < 0 ! 1213: || (delta > 0 && xp.bufpos < ZV) ! 1214: || (delta == 0 && xp.hpos)) ! 1215: { ! 1216: val = *vmotion (Z - XFASTINT (w->window_end_pos), ! 1217: delta, width, hscroll, window); ! 1218: XFASTINT (w->window_end_pos) = Z - val.bufpos; ! 1219: XFASTINT (w->window_end_vpos) += val.vpos; ! 1220: } ! 1221: } ! 1222: ! 1223: w->window_end_valid = Qnil; ! 1224: ! 1225: /* If point was not in a line that was displayed, find it */ ! 1226: if (point_vpos < 0) ! 1227: { ! 1228: val = *compute_motion (start, 0, lmargin, point, 10000, 10000, ! 1229: width, hscroll, pos_tab_offset (w, start)); ! 1230: /* Admit failure if point is off screen now */ ! 1231: if (val.vpos >= height) ! 1232: { ! 1233: for (vpos = 0; vpos < height; vpos++) ! 1234: cancel_line (vpos + top); ! 1235: return 0; ! 1236: } ! 1237: point_vpos = val.vpos + top; ! 1238: point_hpos = val.hpos + XFASTINT (w->left); ! 1239: } ! 1240: ! 1241: cursor_hpos = max (0, point_hpos); ! 1242: cursor_vpos = point_vpos; ! 1243: ! 1244: if (debug_end_pos) ! 1245: { ! 1246: val = *compute_motion (start, 0, lmargin, ZV, ! 1247: height, - (1 << (SHORTBITS - 1)), ! 1248: width, hscroll, pos_tab_offset (w, start)); ! 1249: if (val.vpos != XFASTINT (w->window_end_vpos)) ! 1250: abort (); ! 1251: if (XFASTINT (w->window_end_pos) != Z - val.bufpos) ! 1252: abort (); ! 1253: } ! 1254: ! 1255: return 1; ! 1256: } ! 1257: ! 1258: /* Display one line of window w, starting at position `start' in w's buffer. ! 1259: Display starting at horizontal position `hpos', ! 1260: which is normally zero or negative. ! 1261: A negative value causes output up to hpos = 0 to be discarded. ! 1262: This is done for negative hscroll, or when this is a continuation line ! 1263: and the continuation occurred in the middle of a multi-column character. ! 1264: ! 1265: `taboffset' is an offset for ostensible hpos, used in tab stop calculations. ! 1266: ! 1267: Display on position `vpos' on the screen. (origin 0). ! 1268: ! 1269: Returns a `struct position' giving character to start next line with ! 1270: and where to display it, including a zero or negative hpos. ! 1271: The vpos field is not really a vpos; it is 1 unless the line is continued */ ! 1272: ! 1273: struct position val_display_text_line; ! 1274: ! 1275: struct position * ! 1276: display_text_line (w, start, vpos, hpos, taboffset) ! 1277: struct window *w; ! 1278: int start; ! 1279: int vpos; ! 1280: int hpos; ! 1281: int taboffset; ! 1282: { ! 1283: register int pos = start; ! 1284: register int c; ! 1285: register unsigned char *p1; ! 1286: int end; ! 1287: register int pause; ! 1288: register unsigned char *p; ! 1289: unsigned char *endp; ! 1290: register unsigned char *startp; ! 1291: register unsigned char *p1prev = 0; ! 1292: int tab_width = XINT (current_buffer->tab_width); ! 1293: int ctl_arrow = !NULL (current_buffer->ctl_arrow); ! 1294: int width = XFASTINT (w->width) - 1 ! 1295: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 1296: struct position val; ! 1297: int lastpos; ! 1298: int invis; ! 1299: int hscroll = XINT (w->hscroll); ! 1300: int truncate = hscroll ! 1301: || (truncate_partial_width_windows ! 1302: && XFASTINT (w->width) < screen_width) ! 1303: || !NULL (current_buffer->truncate_lines); ! 1304: int selective ! 1305: = XTYPE (current_buffer->selective_display) == Lisp_Int ! 1306: ? XINT (current_buffer->selective_display) ! 1307: : !NULL (current_buffer->selective_display) ? -1 : 0; ! 1308: int selective_e = selective && !NULL (current_buffer->selective_display_ellipses); ! 1309: ! 1310: hpos += XFASTINT (w->left); ! 1311: get_display_line (vpos, XFASTINT (w->left)); ! 1312: if (tab_width <= 0 || tab_width > 20) tab_width = 8; ! 1313: ! 1314: if (w == XWINDOW (minibuf_window) && start == 1 ! 1315: && vpos == XFASTINT (w->top)) ! 1316: { ! 1317: if (minibuf_prompt) ! 1318: hpos = display_string (w, vpos, minibuf_prompt, hpos, ! 1319: !truncate ? '\\' : '$', -1, -1); ! 1320: minibuf_prompt_width = hpos; ! 1321: } ! 1322: ! 1323: p1 = new_screen->contents[vpos] + hpos; ! 1324: ! 1325: end = ZV; ! 1326: ! 1327: startp = new_screen->contents[vpos] + XFASTINT (w->left); ! 1328: endp = startp + width; ! 1329: ! 1330: /* Loop generating characters. ! 1331: Stop at end of buffer, before newline, ! 1332: or if reach or pass continuation column. */ ! 1333: ! 1334: pause = pos; ! 1335: while (p1 < endp) ! 1336: { ! 1337: p1prev = p1; ! 1338: if (pos == pause) ! 1339: { ! 1340: if (pos == end) ! 1341: break; ! 1342: if (pos == point && point_vpos < 0) ! 1343: { ! 1344: point_vpos = vpos; ! 1345: point_hpos = p1 - startp; ! 1346: } ! 1347: ! 1348: pause = end; ! 1349: if (pos < point && point < pause) ! 1350: pause = point; ! 1351: if (pos < GPT && GPT < pause) ! 1352: pause = GPT; ! 1353: ! 1354: p = &FETCH_CHAR (pos); ! 1355: } ! 1356: c = *p++; ! 1357: if (c >= 040 && c < 0177) ! 1358: { ! 1359: if (p1 >= startp) ! 1360: *p1 = c; ! 1361: p1++; ! 1362: } ! 1363: else if (c == '\n') ! 1364: { ! 1365: invis = 0; ! 1366: while (pos < end ! 1367: && selective > 0 ! 1368: && position_indentation (pos + 1) >= selective) ! 1369: { ! 1370: invis = 1; ! 1371: pos = find_next_newline (pos + 1, 1); ! 1372: if (FETCH_CHAR (pos - 1) == '\n') ! 1373: pos--; ! 1374: } ! 1375: if (invis && selective_e) ! 1376: { ! 1377: p1 += 4; ! 1378: if (p1 - startp > width) ! 1379: p1 = endp; ! 1380: if (p1prev >= startp) ! 1381: strncpy (p1prev, " ...", p1 - p1prev); ! 1382: } ! 1383: break; ! 1384: } ! 1385: else if (c == '\t') ! 1386: { ! 1387: do ! 1388: { ! 1389: if (p1 >= startp && p1 < endp) ! 1390: *p1 = ' '; ! 1391: p1++; ! 1392: } ! 1393: while ((p1 - startp + taboffset + hscroll - (hscroll > 0)) ! 1394: % tab_width); ! 1395: } ! 1396: else if (c == Ctl ('M') && selective == -1) ! 1397: { ! 1398: pos = find_next_newline (pos, 1); ! 1399: if (FETCH_CHAR (pos - 1) == '\n') ! 1400: pos--; ! 1401: if (selective_e) ! 1402: { ! 1403: p1 += 4; ! 1404: if (p1 - startp > width) ! 1405: p1 = endp; ! 1406: if (p1prev >= startp) ! 1407: strncpy (p1prev, " ...", p1 - p1prev); ! 1408: } ! 1409: break; ! 1410: } ! 1411: else if (c < 0200 && ctl_arrow) ! 1412: { ! 1413: if (p1 >= startp) ! 1414: *p1 = '^'; ! 1415: p1++; ! 1416: if (p1 >= startp && p1 < endp) ! 1417: *p1 = c ^ 0100; ! 1418: p1++; ! 1419: } ! 1420: else ! 1421: { ! 1422: if (p1 >= startp) ! 1423: *p1 = '\\'; ! 1424: p1++; ! 1425: if (p1 >= startp && p1 < endp) ! 1426: *p1 = (c >> 6) + '0'; ! 1427: p1++; ! 1428: if (p1 >= startp && p1 < endp) ! 1429: *p1 = (7 & (c >> 3)) + '0'; ! 1430: p1++; ! 1431: if (p1 >= startp && p1 < endp) ! 1432: *p1 = (7 & c) + '0'; ! 1433: p1++; ! 1434: } ! 1435: pos++; ! 1436: } ! 1437: ! 1438: val.hpos = - XINT (w->hscroll); ! 1439: if (val.hpos) ! 1440: val.hpos++; ! 1441: ! 1442: val.vpos = 1; ! 1443: ! 1444: lastpos = pos; ! 1445: ! 1446: /* Handle continuation in middle of a character */ ! 1447: /* by backing up over it */ ! 1448: if (p1 > endp) ! 1449: { ! 1450: if (p1prev) ! 1451: { ! 1452: /* Start the next line with that same character */ ! 1453: pos--; ! 1454: /* but at negative hpos, to skip the columns output on this line. */ ! 1455: val.hpos += p1prev - endp; ! 1456: } ! 1457: ! 1458: /* Keep in this line everything up to the continuation column. */ ! 1459: p1 = endp; ! 1460: } ! 1461: ! 1462: /* Finish deciding which character to start the next line on, ! 1463: and what hpos to start it at. ! 1464: Also set `lastpos' to the last position which counts as "on this line" ! 1465: for cursor-positioning. */ ! 1466: ! 1467: if (pos < ZV) ! 1468: { ! 1469: if (FETCH_CHAR (pos) == '\n') ! 1470: /* If stopped due to a newline, start next line after it */ ! 1471: pos++; ! 1472: else ! 1473: /* Stopped due to right margin of window */ ! 1474: { ! 1475: if (truncate) ! 1476: { ! 1477: *p1++ = '$'; ! 1478: /* Truncating => start next line after next newline, ! 1479: and point is on this line if it is before the newline, ! 1480: and skip none of first char of next line */ ! 1481: pos = find_next_newline (pos, 1); ! 1482: val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; ! 1483: ! 1484: lastpos = pos - (FETCH_CHAR (pos - 1) == '\n'); ! 1485: } ! 1486: else ! 1487: { ! 1488: *p1++ = '\\'; ! 1489: val.vpos = 0; ! 1490: lastpos--; ! 1491: } ! 1492: } ! 1493: } ! 1494: ! 1495: /* If point is at eol or in invisible text at eol, ! 1496: record its screen location now. */ ! 1497: ! 1498: if (start <= point && point <= lastpos && point_vpos < 0) ! 1499: { ! 1500: point_vpos = vpos; ! 1501: point_hpos = p1 - startp; ! 1502: } ! 1503: ! 1504: if (point_vpos == vpos) ! 1505: { ! 1506: if (point_hpos < 0) point_hpos = 0; ! 1507: if (point_hpos > width) point_hpos = width; ! 1508: point_hpos += XFASTINT (w->left); ! 1509: if (w == XWINDOW (selected_window)) ! 1510: { ! 1511: cursor_vpos = point_vpos; ! 1512: cursor_hpos = point_hpos; ! 1513: ! 1514: /* Line is not continued and did not start in middle of character */ ! 1515: if (hpos == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0) ! 1516: && val.vpos) ! 1517: { ! 1518: this_line_bufpos = start; ! 1519: this_line_buffer = current_buffer; ! 1520: this_line_vpos = point_vpos; ! 1521: this_line_start_hpos = hpos; ! 1522: this_line_endpos = Z - lastpos; ! 1523: } ! 1524: else ! 1525: this_line_bufpos = 0; ! 1526: } ! 1527: } ! 1528: ! 1529: /* If hscroll and line not empty, insert truncation-at-left marker */ ! 1530: if (hscroll && lastpos != start) ! 1531: { ! 1532: *startp = '$'; ! 1533: if (p1 <= startp) ! 1534: p1 = startp + 1; ! 1535: } ! 1536: ! 1537: if (XFASTINT (w->width) + XFASTINT (w->left) != screen_width) ! 1538: { ! 1539: endp++; ! 1540: if (p1 < startp) p1 = startp; ! 1541: while (p1 < endp) *p1++ = ' '; ! 1542: *p1++ = '|'; ! 1543: } ! 1544: new_screen->used[vpos] = max (new_screen->used[vpos], ! 1545: p1 - new_screen->contents[vpos]); ! 1546: new_screen->contents[vpos][new_screen->used[vpos]] = 0; ! 1547: ! 1548: /* If the start of this line is the overlay arrow-position, ! 1549: then put the arrow string into the display-line. */ ! 1550: ! 1551: if (XTYPE (Voverlay_arrow_position) == Lisp_Marker ! 1552: && current_buffer == XMARKER (Voverlay_arrow_position)->buffer ! 1553: && start == marker_position (Voverlay_arrow_position) ! 1554: && XTYPE (Voverlay_arrow_string) == Lisp_String) ! 1555: { ! 1556: unsigned char *p = XSTRING (Voverlay_arrow_string)->data; ! 1557: int len = XSTRING (Voverlay_arrow_string)->size; ! 1558: int minlen = (XFASTINT (w->width) - 1 ! 1559: - (XFASTINT (w->width) + XFASTINT (w->left) ! 1560: != screen_width)); ! 1561: ! 1562: if (len > minlen) ! 1563: len = minlen; ! 1564: bcopy (p, startp, len); ! 1565: if (new_screen->used[vpos] < len + startp - new_screen->contents[vpos]) ! 1566: new_screen->used[vpos] = len + startp - new_screen->contents[vpos]; ! 1567: } ! 1568: ! 1569: val.bufpos = pos; ! 1570: val_display_text_line = val; ! 1571: return &val_display_text_line; ! 1572: } ! 1573: ! 1574: /* Display the mode line for window w */ ! 1575: ! 1576: display_mode_line (w) ! 1577: struct window *w; ! 1578: { ! 1579: register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1; ! 1580: register int left = XFASTINT (w->left); ! 1581: register int right = XFASTINT (w->width) + left; ! 1582: get_display_line (vpos, left); ! 1583: ! 1584: display_mode_element (w, vpos, left, 0, right, right, ! 1585: current_buffer->mode_line_format); ! 1586: ! 1587: /* Make the mode line inverse video if the entire line ! 1588: is made of mode lines. ! 1589: I.e. if this window is full width, ! 1590: or if it is the child of a full width window ! 1591: (which implies that that window is split side-by-side ! 1592: and the rest of this line is mode lines of the sibling windows). */ ! 1593: if (XFASTINT (w->width) == screen_width || ! 1594: XFASTINT (XWINDOW (w->parent)->width) == screen_width) ! 1595: new_screen->highlight[vpos] = mode_line_inverse_video; ! 1596: ! 1597: } ! 1598: ! 1599: /* Contribute ELT to the mode line for window W. ! 1600: How it translates into text depends on its data type. ! 1601: ! 1602: LINE is the display-line that the mode line is being displayed in. ! 1603: ! 1604: HPOS is the position (absolute on screen) where this element's text ! 1605: should start. The output is truncated automatically at the right ! 1606: edge of window W. ! 1607: ! 1608: DEPTH is the depth in recursion. It is used to prevent ! 1609: infinite recursion here. ! 1610: ! 1611: MINENDCOL is the hpos before which the element may not end. ! 1612: The element is padded at the right with spaces if nec ! 1613: to reach this column. ! 1614: ! 1615: MAXENDCOL is the hpos past which this element may not extend. ! 1616: If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority. ! 1617: (This is necessary to make nested padding and truncation work.) ! 1618: ! 1619: Returns the hpos of the end of the text generated by ELT. ! 1620: The next element will receive that value as its HPOS arg, ! 1621: so as to concatenate the elements. */ ! 1622: ! 1623: int ! 1624: display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) ! 1625: struct window *w; ! 1626: int vpos; ! 1627: register int hpos; ! 1628: int depth; ! 1629: int minendcol; ! 1630: register int maxendcol; ! 1631: register Lisp_Object elt; ! 1632: { ! 1633: tail_recurse: ! 1634: if (depth > 10) ! 1635: goto invalid; ! 1636: ! 1637: depth++; ! 1638: ! 1639: #ifdef SWITCH_ENUM_BUG ! 1640: switch ((int) XTYPE (elt)) ! 1641: #else ! 1642: switch (XTYPE (elt)) ! 1643: #endif ! 1644: { ! 1645: case Lisp_String: ! 1646: { ! 1647: /* A string: output it and check for %-constructs within it. */ ! 1648: register unsigned char c; ! 1649: register unsigned char *this = XSTRING (elt)->data; ! 1650: ! 1651: while (hpos < maxendcol && *this) ! 1652: { ! 1653: unsigned char *last = this; ! 1654: while ((c = *this++) != '\0' && c != '%') ! 1655: ; ! 1656: if (this - 1 != last) ! 1657: { ! 1658: register int lim = --this - last + hpos; ! 1659: hpos = display_string (w, vpos, last, hpos, 0, hpos, ! 1660: min (lim, maxendcol)); ! 1661: } ! 1662: else /* c == '%' */ ! 1663: { ! 1664: register int spec_width = 0; ! 1665: ! 1666: /* We can't allow -ve args due to the "%-" construct */ ! 1667: /* Argument specifies minwidth but not maxwidth ! 1668: (maxwidth can be specified by ! 1669: (<negative-number> . <stuff>) mode-line elements) */ ! 1670: ! 1671: while ((c = *this++) >= '0' && c <= '9') ! 1672: { ! 1673: spec_width = spec_width * 10 + (c - '0'); ! 1674: } ! 1675: ! 1676: spec_width += hpos; ! 1677: if (spec_width > maxendcol) ! 1678: spec_width = maxendcol; ! 1679: ! 1680: if (c == 'M') ! 1681: hpos = display_mode_element (w, vpos, hpos, depth, ! 1682: spec_width, maxendcol, ! 1683: Vglobal_mode_string); ! 1684: else if (c != 0) ! 1685: hpos = display_string (w, vpos, ! 1686: decode_mode_spec (w, c, ! 1687: spec_width - hpos), ! 1688: hpos, 0, spec_width, maxendcol); ! 1689: } ! 1690: } ! 1691: } ! 1692: break; ! 1693: ! 1694: case Lisp_Symbol: ! 1695: /* A symbol: process the value of the symbol recursively ! 1696: as if it appeared here directly. Avoid error if symbol void. ! 1697: Special case: if value of symbol is a string, output the string ! 1698: literally. */ ! 1699: { ! 1700: register Lisp_Object tem; ! 1701: tem = Fboundp (elt); ! 1702: if (!NULL (tem)) ! 1703: { ! 1704: tem = Fsymbol_value (elt); ! 1705: /* If value is a string, output that string literally: ! 1706: don't check for % within it. */ ! 1707: if (XTYPE (tem) == Lisp_String) ! 1708: hpos = display_string (w, vpos, XSTRING (tem)->data, ! 1709: hpos, 0, minendcol, maxendcol); ! 1710: /* Give up right away for nil or t. */ ! 1711: else if (!EQ (tem, elt)) ! 1712: { elt = tem; goto tail_recurse; } ! 1713: } ! 1714: } ! 1715: break; ! 1716: ! 1717: case Lisp_Cons: ! 1718: { ! 1719: register Lisp_Object car, tem; ! 1720: ! 1721: /* A cons cell: three distinct cases. ! 1722: If first element is a string or a cons, process all the elements ! 1723: and effectively concatenate them. ! 1724: If first element is a negative number, truncate displaying cdr to ! 1725: at most that many characters. If positive, pad (with spaces) ! 1726: to at least that many characters. ! 1727: If first element is a symbol, process the cadr or caddr recursively ! 1728: according to whether the symbol's value is non-nil or nil. */ ! 1729: car = XCONS (elt)->car; ! 1730: if (XTYPE (car) == Lisp_Symbol) ! 1731: { ! 1732: tem = Fboundp (car); ! 1733: elt = XCONS (elt)->cdr; ! 1734: if (XTYPE (elt) != Lisp_Cons) ! 1735: goto invalid; ! 1736: /* elt is now the cdr, and we know it is a cons cell. ! 1737: Use its car if CAR has a non-nil value. */ ! 1738: if (!NULL (tem)) ! 1739: { ! 1740: tem = Fsymbol_value (car); ! 1741: if (!NULL (tem)) ! 1742: { elt = XCONS (elt)->car; goto tail_recurse; } ! 1743: } ! 1744: /* Symbol's value is nil (or symbol is unbound) ! 1745: Get the cddr of the original list ! 1746: and if possible find the caddr and use that. */ ! 1747: elt = XCONS (elt)->cdr; ! 1748: if (NULL (elt)) ! 1749: break; ! 1750: else if (XTYPE (elt) != Lisp_Cons) ! 1751: goto invalid; ! 1752: elt = XCONS (elt)->car; ! 1753: goto tail_recurse; ! 1754: } ! 1755: else if (XTYPE (car) == Lisp_Int) ! 1756: { ! 1757: register int lim = XINT (car); ! 1758: elt = XCONS (elt)->cdr; ! 1759: if (lim < 0) ! 1760: /* Negative int means reduce maximum width. ! 1761: DO NOT change MINENDCOL here! ! 1762: (20 -10 . foo) should truncate foo to 10 col ! 1763: and then pad to 20. */ ! 1764: maxendcol = min (maxendcol, hpos - lim); ! 1765: else if (lim > 0) ! 1766: { ! 1767: /* Padding specified. Don't let it be more than ! 1768: current maximum. */ ! 1769: lim += hpos; ! 1770: if (lim > maxendcol) ! 1771: lim = maxendcol; ! 1772: /* If that's more padding than already wanted, queue it. ! 1773: But don't reduce padding already specified even if ! 1774: that is beyond the current truncation point. */ ! 1775: if (lim > minendcol) ! 1776: minendcol = lim; ! 1777: } ! 1778: goto tail_recurse; ! 1779: } ! 1780: else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons) ! 1781: { ! 1782: register int limit = 50; ! 1783: /* LIMIT is to protect against circular lists. */ ! 1784: while (XTYPE (elt) == Lisp_Cons && --limit > 0 ! 1785: && hpos < maxendcol) ! 1786: { ! 1787: hpos = display_mode_element (w, vpos, hpos, depth, ! 1788: hpos, maxendcol, ! 1789: XCONS (elt)->car); ! 1790: elt = XCONS (elt)->cdr; ! 1791: } ! 1792: } ! 1793: } ! 1794: break; ! 1795: ! 1796: default: ! 1797: invalid: ! 1798: return (display_string (w, vpos, "*invalid*", hpos, 0, ! 1799: minendcol, maxendcol)); ! 1800: } ! 1801: ! 1802: end: ! 1803: if (minendcol > hpos) ! 1804: hpos = display_string (w, vpos, "", hpos, 0, minendcol, -1); ! 1805: return hpos; ! 1806: } ! 1807: ! 1808: /* Return a string for the output of a mode line %-spec ! 1809: for window W, generated by character C and width MAXWIDTH. */ ! 1810: ! 1811: char * ! 1812: decode_mode_spec (w, c, maxwidth) ! 1813: struct window *w; ! 1814: register char c; ! 1815: register int maxwidth; ! 1816: { ! 1817: Lisp_Object obj = Qnil; ! 1818: char *decode_mode_spec_buf = (char *) temp_screen->total_contents; ! 1819: ! 1820: switch (c) ! 1821: { ! 1822: case 'b': ! 1823: obj = current_buffer->name; ! 1824: #if 0 ! 1825: if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth) ! 1826: { ! 1827: bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1); ! 1828: decode_mode_spec_buf[maxwidth - 1] = '\\'; ! 1829: decode_mode_spec_buf[maxwidth] = '\0'; ! 1830: return decode_mode_spec_buf; ! 1831: } ! 1832: #endif ! 1833: break; ! 1834: ! 1835: case 'f': ! 1836: obj = current_buffer->filename; ! 1837: #if 0 ! 1838: if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth) ! 1839: { ! 1840: bcopy ("...", decode_mode_spec_buf, 3); ! 1841: bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3, ! 1842: decode_mode_spec_buf + 3, maxwidth - 3); ! 1843: return decode_mode_spec_buf; ! 1844: } ! 1845: #endif ! 1846: break; ! 1847: ! 1848: case 'm': ! 1849: obj = current_buffer->mode_name; ! 1850: break; ! 1851: ! 1852: case 'n': ! 1853: if (BEGV > BEG || ZV < Z) ! 1854: return " Narrow"; ! 1855: break; ! 1856: ! 1857: case '*': ! 1858: if (!NULL (current_buffer->read_only)) ! 1859: return "%"; ! 1860: if (MODIFF > current_buffer->save_modified) ! 1861: return "*"; ! 1862: return "-"; ! 1863: ! 1864: case 's': ! 1865: /* status of process */ ! 1866: #ifdef subprocesses ! 1867: obj = Fget_buffer_process (Fcurrent_buffer ()); ! 1868: if (NULL (obj)) ! 1869: return "no process"; ! 1870: obj = Fsymbol_name (Fprocess_status (obj)); ! 1871: break; ! 1872: #else ! 1873: return "no processes"; ! 1874: #endif /* subprocesses */ ! 1875: ! 1876: case 'p': ! 1877: { ! 1878: int pos = marker_position (w->start); ! 1879: int total = ZV - BEGV; ! 1880: ! 1881: if (XFASTINT (w->window_end_pos) <= Z - ZV) ! 1882: { ! 1883: if (pos <= BEGV) ! 1884: return "All"; ! 1885: else ! 1886: return "Bottom"; ! 1887: } ! 1888: else if (pos <= BEGV) ! 1889: return "Top"; ! 1890: else ! 1891: { ! 1892: total = ((pos - BEGV) * 100 + total - 1) / total; ! 1893: /* We can't normally display a 3-digit number, ! 1894: so get us a 2-digit number that is close. */ ! 1895: if (total == 100) ! 1896: total = 99; ! 1897: sprintf (decode_mode_spec_buf, "%2d%%", total); ! 1898: return decode_mode_spec_buf; ! 1899: } ! 1900: } ! 1901: ! 1902: case '[': ! 1903: { ! 1904: int i; ! 1905: char *p; ! 1906: if (command_loop_level > 5) ! 1907: return "[[[... "; ! 1908: p = decode_mode_spec_buf; ! 1909: for (i = 0; i < command_loop_level; i++) ! 1910: *p++ = '['; ! 1911: *p = 0; ! 1912: return decode_mode_spec_buf; ! 1913: } ! 1914: ! 1915: case '%': ! 1916: return "%"; ! 1917: ! 1918: case ']': ! 1919: { ! 1920: int i; ! 1921: char *p; ! 1922: if (command_loop_level > 5) ! 1923: return " ...]]]"; ! 1924: p = decode_mode_spec_buf; ! 1925: for (i = 0; i < command_loop_level; i++) ! 1926: *p++ = ']'; ! 1927: *p = 0; ! 1928: return decode_mode_spec_buf; ! 1929: } ! 1930: ! 1931: case '-': ! 1932: { ! 1933: int i; ! 1934: if (maxwidth < 140) ! 1935: return "--------------------------------------------------------------------------------------------------------------------------------------------"; ! 1936: for (i = 0; i < maxwidth; i++) ! 1937: decode_mode_spec_buf[i] = '-'; ! 1938: return decode_mode_spec_buf; ! 1939: } ! 1940: } ! 1941: ! 1942: if (XTYPE (obj) == Lisp_String) ! 1943: return (char *) XSTRING (obj)->data; ! 1944: else ! 1945: return ""; ! 1946: } ! 1947: ! 1948: /* Display STRING on one line of window W, starting at HPOS. ! 1949: Display at position VPOS. Caller should do get_display_line first. ! 1950: ! 1951: TRUNCATE is character to display at end if truncated. Zero for none. ! 1952: ! 1953: MINCOL is the first column ok to end at. (Pad with spaces to this col.) ! 1954: MAXCOL is the last column ok to end at. Truncate here. ! 1955: -1 for MINCOL or MAXCOL means no explicit minimum or maximum. ! 1956: Both count from the left edge of the screen, as does HPOS. ! 1957: The right edge of W is an implicit maximum. ! 1958: If TRUNCATE is nonzero, the implicit maximum is one column before the edge. ! 1959: ! 1960: Returns ending hpos */ ! 1961: ! 1962: display_string (w, vpos, string, hpos, truncate, mincol, maxcol) ! 1963: struct window *w; ! 1964: int vpos; ! 1965: unsigned char *string; ! 1966: int hpos; ! 1967: char truncate; ! 1968: int mincol, maxcol; ! 1969: { ! 1970: register int c; ! 1971: register unsigned char *p1; ! 1972: int hscroll = XINT (w->hscroll); ! 1973: int tab_width = XINT (current_buffer->tab_width); ! 1974: register unsigned char *start; ! 1975: register unsigned char *end; ! 1976: unsigned char *p1start = new_screen->contents[vpos] + hpos; ! 1977: int window_width = XFASTINT (w->width); ! 1978: ! 1979: if (tab_width <= 0 || tab_width > 20) tab_width = 8; ! 1980: ! 1981: p1 = p1start; ! 1982: start = new_screen->contents[vpos] + XFASTINT (w->left); ! 1983: end = start + window_width - (truncate != 0); ! 1984: ! 1985: if ((window_width + XFASTINT (w->left)) != screen_width) ! 1986: *end-- = '|'; ! 1987: ! 1988: if (maxcol >= 0 && end - new_screen->contents[vpos] > maxcol) ! 1989: end = new_screen->contents[vpos] + maxcol; ! 1990: if (maxcol >= 0 && mincol > maxcol) ! 1991: mincol = maxcol; ! 1992: ! 1993: while (p1 < end) ! 1994: { ! 1995: c = *string++; ! 1996: if (!c) break; ! 1997: if (c >= 040 && c < 0177) ! 1998: { ! 1999: if (p1 >= start) ! 2000: *p1 = c; ! 2001: p1++; ! 2002: } ! 2003: else if (c == '\t') ! 2004: { ! 2005: do ! 2006: { ! 2007: if (p1 >= start && p1 < end) ! 2008: *p1 = ' '; ! 2009: p1++; ! 2010: } ! 2011: while ((p1 - start + hscroll - (hscroll > 0)) % tab_width); ! 2012: } ! 2013: else if (c < 0200 && buffer_defaults.ctl_arrow) ! 2014: { ! 2015: if (p1 >= start) ! 2016: *p1 = '^'; ! 2017: p1++; ! 2018: if (p1 >= start && p1 < end) ! 2019: *p1 = c ^ 0100; ! 2020: p1++; ! 2021: } ! 2022: else ! 2023: { ! 2024: if (p1 >= start) ! 2025: *p1 = '\\'; ! 2026: p1++; ! 2027: if (p1 >= start && p1 < end) ! 2028: *p1 = (c >> 6) + '0'; ! 2029: p1++; ! 2030: if (p1 >= start && p1 < end) ! 2031: *p1 = (7 & (c >> 3)) + '0'; ! 2032: p1++; ! 2033: if (p1 >= start && p1 < end) ! 2034: *p1 = (7 & c) + '0'; ! 2035: p1++; ! 2036: } ! 2037: } ! 2038: ! 2039: if (c) ! 2040: { ! 2041: p1 = end; ! 2042: if (truncate) *p1++ = truncate; ! 2043: } ! 2044: else if (mincol >= 0) ! 2045: { ! 2046: end = new_screen->contents[vpos] + mincol; ! 2047: while (p1 < end) ! 2048: *p1++ = ' '; ! 2049: } ! 2050: ! 2051: { ! 2052: register int len = p1 - new_screen->contents[vpos]; ! 2053: if (len > new_screen->used[vpos]) ! 2054: new_screen->used[vpos] = len; ! 2055: new_screen->contents[vpos][new_screen->used[vpos]] = 0; ! 2056: return len; ! 2057: } ! 2058: } ! 2059: ! 2060: syms_of_xdisp () ! 2061: { ! 2062: staticpro (&last_arrow_position); ! 2063: staticpro (&last_arrow_string); ! 2064: last_arrow_position = Qnil; ! 2065: last_arrow_string = Qnil; ! 2066: ! 2067: DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string, ! 2068: "String displayed by mode-line-format's \"%m\" specifiation."); ! 2069: Vglobal_mode_string = Qnil; ! 2070: ! 2071: DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position, ! 2072: "Marker for where to display an arrow on top of the buffer text.\n\ ! 2073: This must be the beginning of a line in order to work.\n\ ! 2074: See also overlay-arrow-string."); ! 2075: Voverlay_arrow_position = Qnil; ! 2076: ! 2077: DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string, ! 2078: "String to display as an arrow. See also overlay-arrow-position."); ! 2079: Voverlay_arrow_string = Qnil; ! 2080: ! 2081: DEFVAR_INT ("scroll-step", &scroll_step, ! 2082: "*The number of lines to try scrolling a window by when point moves out.\n\ ! 2083: If that fails to bring point back on screen, point is centered instead.\n\ ! 2084: If this is zero, point is always centered after it moves off screen."); ! 2085: ! 2086: DEFVAR_BOOL ("reset-terminal-on-clear", &reset_terminal_on_clear, ! 2087: "Non-nil means re-init terminal modes for clear screen as on entry to Emacs."); ! 2088: reset_terminal_on_clear = 1; ! 2089: ! 2090: DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask"); ! 2091: ! 2092: DEFVAR_BOOL ("truncate-partial-width-windows", ! 2093: &truncate_partial_width_windows, ! 2094: "*Non-nil means truncate lines in all windows less than full screen wide."); ! 2095: truncate_partial_width_windows = 1; ! 2096: ! 2097: DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, ! 2098: "*Non-nil means use inverse video, or other suitable display mode, for the mode line."); ! 2099: mode_line_inverse_video = 1; ! 2100: ! 2101: defsubr (&Sredraw_display); ! 2102: } ! 2103: ! 2104: /* initialize the window system */ ! 2105: init_xdisp () ! 2106: { ! 2107: Lisp_Object root_window; ! 2108: #ifndef COMPILER_REGISTER_BUG ! 2109: register ! 2110: #endif COMPILER_REGISTER_BUG ! 2111: struct window *mini_w; ! 2112: ! 2113: this_line_bufpos = 0; ! 2114: ! 2115: mini_w = XWINDOW (minibuf_window); ! 2116: root_window = mini_w->prev; ! 2117: ! 2118: echo_area_contents = 0; ! 2119: prev_echo_area_contents = 0; ! 2120: ! 2121: if (!noninteractive) ! 2122: { ! 2123: XFASTINT (XWINDOW (root_window)->top) = 0; ! 2124: set_window_height (root_window, screen_height - 1, 0); ! 2125: XFASTINT (mini_w->top) = screen_height - 1; ! 2126: set_window_height (minibuf_window, 1, 0); ! 2127: ! 2128: XFASTINT (XWINDOW (root_window)->width) = screen_width; ! 2129: XFASTINT (mini_w->width) = screen_width; ! 2130: } ! 2131: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.