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