|
|
1.1 ! root 1: /* Display generation from window structure and buffer text. ! 2: Copyright (C) 1985 Richard M. Stallman. ! 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: #define CURRENT_END_POS(w) \ ! 45: (XFASTINT (w->window_end_pos) < 0 \ ! 46: ? -1 - XFASTINT(w->window_end_pos) \ ! 47: : XFASTINT(w->window_end_pos)) ! 48: ! 49: /* The buffer position of the first character appearing ! 50: entirely or partially on the current screen line. ! 51: Or zero, which disables the optimization for the current screen line. */ ! 52: int this_line_bufpos; ! 53: ! 54: /* Number of characters past the end of this line, ! 55: including the terminating newline */ ! 56: int this_line_endpos; ! 57: ! 58: /* The vertical position of this screen line. */ ! 59: int this_line_vpos; ! 60: ! 61: /* Hpos value for start of display on this screen line. ! 62: Usually zero, but negative if first character really began on previous line */ ! 63: int this_line_hpos; ! 64: ! 65: /* Buffer that this_line variables are describing. */ ! 66: struct buffer *this_line_buffer; ! 67: ! 68: /* Value of minibuf_message when it was last acted on. ! 69: If this is nonzero, there is a message on the screen ! 70: in the minibuffer and it should be erased as soon ! 71: as it is no longer requested to appear. */ ! 72: char *prev_minibuf_message; ! 73: ! 74: /* Nonzero means truncate lines in all windows less wide than the screen */ ! 75: ! 76: int truncate_partial_width_windows; ! 77: ! 78: Lisp_Object Vglobal_mode_string; ! 79: ! 80: Lisp_Object Vglobal_minor_modes; ! 81: ! 82: /* The number of lines to try scrolling a ! 83: window by when point leaves the window; if ! 84: it is <=0 then point is centered in the window */ ! 85: int scroll_step; ! 86: ! 87: /* Nonzero if try_window_id has made blank lines at window bottom ! 88: since the last redisplay that paused */ ! 89: int blank_end_of_window; ! 90: ! 91: /* Number of windows showing the buffer of the selected window. */ ! 92: static int buffer_shared; ! 93: ! 94: /* display_text_line sets these to the screen position (origin 0) of point, ! 95: whether the window is selected or not. ! 96: Set one to -1 first to determine whether point was found afterwards. */ ! 97: ! 98: int point_vpos; ! 99: int point_hpos; ! 100: ! 101: int debug_end_pos; ! 102: ! 103: extern int default_ctl_arrow; /* Nonzero means display ctl chars */ ! 104: /* with uparrow in mode lines, etc */ ! 105: ! 106: int mode_line_inverse_video; /* Nonzero means display mode line highlighted */ ! 107: ! 108: struct position *display_text_line (); ! 109: ! 110: char *minibuf_prompt; /* Prompt to display in front of the minibuffer contents */ ! 111: ! 112: /* Width in columns of current minibuffer prompt. */ ! 113: ! 114: int minibuf_prompt_width; ! 115: ! 116: char *minibuf_message; /* Message to display instead of minibuffer contents ! 117: This is what the functions error and message make, ! 118: and command echoing uses it as well. ! 119: It overrides the minibuf_prompt as well as the buffer. */ ! 120: ! 121: int RecurseDepth; /* Depth in recursive edits */ ! 122: ! 123: int MinibufDepth; /* Depth in minibuffer invocations */ ! 124: ! 125: int RedoModes; /* true iff we should redraw the mode lines ! 126: on the next redisplay */ ! 127: ! 128: /* Minimum value of bf_s1 since last redisplay that finished. ! 129: Valid for current buffer unless Cant1WinOpt is nonzero. */ ! 130: ! 131: int beg_unchanged; ! 132: ! 133: /* Minimum value of bf_s2 since last redisplay that finished. ! 134: Valid for current buffer unless Cant1WinOpt is nonzero. */ ! 135: ! 136: int end_unchanged; ! 137: ! 138: /* bf_modified as of last redisplay that finished; ! 139: if it matches bf_modified, 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: DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "", ! 152: "Clear the screen and output again what is supposed to appear on it.") ! 153: () ! 154: { ! 155: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 156: set_terminal_modes (); ! 157: clear_screen (); ! 158: fflush (stdout); ! 159: clear_screen_records (); ! 160: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 161: windows_or_buffers_changed++; ! 162: /* Mark all windows as INaccurate, ! 163: so that every window will have its redisplay done. */ ! 164: mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0); ! 165: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 166: return Qnil; ! 167: } ! 168: ! 169: static char message_buf[MScreenWidth + 1]; ! 170: ! 171: /* dump an informative message to the minibuf */ ! 172: /* VARARGS 1 */ ! 173: message (m, a1, a2, a3) ! 174: char *m; ! 175: { ! 176: if (noninteractive) ! 177: { ! 178: if (noninteractive_need_newline) ! 179: putchar ('\n'); ! 180: printf (m, a1, a2, a3); ! 181: printf ("\n"); ! 182: fflush (stdout); ! 183: } ! 184: else if (INTERACTIVE) ! 185: { ! 186: doprnt (message_buf, sizeof message_buf - 1, m, &a1); ! 187: minibuf_message = message_buf; ! 188: display_minibuf_message (); ! 189: update_screen (1, 1); ! 190: } ! 191: } ! 192: ! 193: /* Specify m, a string, as a message in the minibuf. */ ! 194: message1 (m) ! 195: char *m; ! 196: { ! 197: if (noninteractive) ! 198: { ! 199: if (noninteractive_need_newline) ! 200: putchar ('\n'); ! 201: printf ("%s\n", m); ! 202: fflush (stdout); ! 203: } ! 204: else if (INTERACTIVE) ! 205: { ! 206: minibuf_message = m; ! 207: display_minibuf_message (); ! 208: update_screen (1, 1); ! 209: } ! 210: } ! 211: ! 212: display_minibuf_message () ! 213: { ! 214: register int vpos; ! 215: register struct display_line *line; ! 216: ! 217: if (screen_garbaged) ! 218: { ! 219: Fredraw_display (); ! 220: screen_garbaged = 0; ! 221: } ! 222: ! 223: if (minibuf_message || !MinibufDepth) ! 224: { ! 225: vpos = XFASTINT (XWINDOW (minibuf_window)->top); ! 226: line = get_display_line (vpos, 0); ! 227: display_string (XWINDOW (minibuf_window), line, ! 228: minibuf_message ? minibuf_message : "", ! 229: 0, 0, 0); ! 230: ! 231: /* If desired cursor location is on this line, put it at end of text */ ! 232: if (cursY == vpos) ! 233: cursX = line->length; ! 234: } ! 235: else if (!EQ (minibuf_window, selected_window)) ! 236: windows_or_buffers_changed++; ! 237: ! 238: if (EQ (minibuf_window, selected_window)) ! 239: this_line_bufpos = 0; ! 240: ! 241: prev_minibuf_message = minibuf_message; ! 242: } ! 243: ! 244: /* Do a screen update, taking possible shortcuts into account. ! 245: This is the main external entry point for redisplay */ ! 246: ! 247: DoDsp (SaveMiniBuf) ! 248: { ! 249: register struct window *w = XWINDOW (selected_window); ! 250: register int pause; ! 251: int inhibit_hairy_id = 0; ! 252: int must_finish = 0; ! 253: int all_windows = 0; ! 254: register int tlbufpos, tlendpos; ! 255: struct position pos; ! 256: extern int input_pending; ! 257: ! 258: if (noninteractive) ! 259: return; ! 260: ! 261: if (screen_garbaged) ! 262: { ! 263: Fredraw_display (); ! 264: screen_garbaged = 0; ! 265: } ! 266: ! 267: if (minibuf_message || ! 268: (prev_minibuf_message && !SaveMiniBuf)) ! 269: { ! 270: display_minibuf_message (); ! 271: must_finish = 1; ! 272: } ! 273: ! 274: if (clip_changed || windows_or_buffers_changed) ! 275: RedoModes++; ! 276: ! 277: /* Detect case that we need to write a star in the mode line. */ ! 278: if (XFASTINT (w->last_modified) < bf_modified ! 279: && XFASTINT (w->last_modified) <= bf_cur->save_modified) ! 280: { ! 281: w->redo_mode_line = Qt; ! 282: if (buffer_shared > 1) ! 283: RedoModes++; ! 284: } ! 285: ! 286: all_windows = RedoModes || buffer_shared > 1; ! 287: ! 288: tlbufpos = this_line_bufpos; ! 289: tlendpos = this_line_endpos; ! 290: if (!all_windows && tlbufpos > 0 && NULL (w->redo_mode_line) ! 291: /* Point must be on the line that we have info recorded about */ ! 292: && point >= tlbufpos ! 293: && point <= bf_s1 + bf_s2 + 1 - tlendpos ! 294: /* All text outside that line, including its final newline, ! 295: must be unchanged */ ! 296: && (XFASTINT (w->last_modified) >= bf_modified ! 297: || (beg_unchanged >= tlbufpos - 1 ! 298: && bf_s1 >= tlbufpos - 1 ! 299: && end_unchanged >= tlendpos ! 300: && bf_s2 >= tlendpos)) ! 301: /* Make sure recorded data applies to current buffer, etc */ ! 302: && NULL (w->force_start) ! 303: && bf_cur == XBUFFER (w->buffer) ! 304: && this_line_buffer == bf_cur) ! 305: { ! 306: if (tlbufpos > FirstCharacter && CharAt (tlbufpos - 1) != '\n' ! 307: && (tlbufpos == NumCharacters + 1 ! 308: || CharAt (tlbufpos) == '\n')) ! 309: /* Former continuation line has disappeared by becoming empty */ ! 310: ; ! 311: else if (XFASTINT (w->last_modified) < bf_modified ! 312: || EQ (selected_window, minibuf_window)) ! 313: { ! 314: point_vpos = -1; ! 315: display_text_line (w, tlbufpos, this_line_vpos, this_line_hpos, ! 316: pos_tab_offset (w, tlbufpos)); ! 317: /* If line contains point, is not continued, ! 318: and ends at same distance from eob as before, we win */ ! 319: if (point_vpos >= 0 && this_line_bufpos ! 320: && this_line_endpos == tlendpos) ! 321: { ! 322: cursX = point_hpos; ! 323: if (XFASTINT (w->width) != screen_width) ! 324: preserve_other_columns (w); ! 325: if (interrupt_input) ! 326: unrequest_sigio (); ! 327: goto update; ! 328: } ! 329: } ! 330: else if (point == XFASTINT (w->last_point)) ! 331: { ! 332: if (!must_finish) ! 333: return; ! 334: goto update; ! 335: } ! 336: else ! 337: { ! 338: pos = *compute_motion (tlbufpos, 0, ! 339: XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0, ! 340: point, 2, - (1 << (SHORTBITS - 1)), ! 341: XFASTINT (w->width) - 1 ! 342: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width), ! 343: XINT (w->hscroll), 0); ! 344: if (pos.vpos < 1) ! 345: { ! 346: cursX = max (XFASTINT (w->left), pos.hpos); ! 347: if (interrupt_input) ! 348: unrequest_sigio (); ! 349: goto update; ! 350: } ! 351: } ! 352: /* Text changed drastically or point moved off of line */ ! 353: cancel_line (this_line_vpos); ! 354: } ! 355: ! 356: this_line_bufpos = 0; ! 357: ! 358: if (interrupt_input) ! 359: unrequest_sigio (); ! 360: ! 361: if (all_windows) ! 362: redisplay_all_windows (); ! 363: else ! 364: { ! 365: inhibit_hairy_id = redisplay_window (selected_window, 1); ! 366: if (XFASTINT (w->width) != screen_width) ! 367: preserve_other_columns (w); ! 368: } ! 369: ! 370: update: ! 371: pause = update_screen (0, inhibit_hairy_id); ! 372: ! 373: /* If screen does not match, prevent doing single-line-update next time */ ! 374: if (pause) ! 375: this_line_bufpos = 0; ! 376: ! 377: /* Now text on screen agrees with windows, so ! 378: put info into the windows for partial redisplay to follow */ ! 379: ! 380: if (!pause) ! 381: { ! 382: register struct buffer_text *t ! 383: = XBUFFER (w->buffer) == bf_cur ! 384: ? &bf_text : &XBUFFER (w->buffer)->text; ! 385: ! 386: blank_end_of_window = 0; ! 387: clip_changed = 0; ! 388: unchanged_modified = t->modified; ! 389: beg_unchanged = t->size1, end_unchanged = t->size2; ! 390: ! 391: XFASTINT (w->last_point) = t->pointloc; ! 392: XFASTINT (w->last_point_x) = cursX; ! 393: XFASTINT (w->last_point_y) = cursY; ! 394: ! 395: if (all_windows) ! 396: mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 1); ! 397: else ! 398: { ! 399: w->redo_mode_line = Qnil; ! 400: XFASTINT (w->last_modified) = t->modified; ! 401: if (XFASTINT (w->window_end_pos) < 0) ! 402: XFASTINT (w->window_end_pos) = -1 - XFASTINT (w->window_end_pos); ! 403: } ! 404: RedoModes = 0; ! 405: windows_or_buffers_changed = 0; ! 406: } ! 407: ! 408: /* Start SIGIO interrupts coming again. ! 409: Having them off during the code above ! 410: makes it less likely one will discard output, ! 411: but not impossible, since there might be stuff ! 412: in the system buffer here. ! 413: But it is much hairier to try to do anything about that. */ ! 414: ! 415: if (interrupt_input) ! 416: request_sigio (); ! 417: } ! 418: ! 419: mark_window_display_accurate (window, flag) ! 420: Lisp_Object window; ! 421: int flag; ! 422: { ! 423: register struct window *w; ! 424: ! 425: for (;!NULL (window); window = w->next) ! 426: { ! 427: w = XWINDOW (window); ! 428: ! 429: XFASTINT (w->last_modified) ! 430: = !flag ? 0 ! 431: : XBUFFER (w->buffer) == bf_cur ! 432: ? bf_modified : XBUFFER (w->buffer)->text.modified; ! 433: if (XFASTINT (w->window_end_pos) < 0) ! 434: XFASTINT (w->window_end_pos) = -1 - XFASTINT (w->window_end_pos); ! 435: w->redo_mode_line = Qnil; ! 436: ! 437: if (!NULL (w->vchild)) ! 438: mark_window_display_accurate (w->vchild, flag); ! 439: if (!NULL (w->hchild)) ! 440: mark_window_display_accurate (w->hchild, flag); ! 441: } ! 442: } ! 443: ! 444: int do_id = 1; ! 445: ! 446: /* Do full redisplay of one or all windows. ! 447: This does not include updating the screen; ! 448: just generating lines to pass to update_screen. */ ! 449: ! 450: /* Entry point to redisplay all windows */ ! 451: ! 452: redisplay_all_windows () ! 453: { ! 454: buffer_shared = 0; ! 455: ! 456: redisplay_windows (XWINDOW (minibuf_window)->prev); ! 457: } ! 458: ! 459: redisplay_windows (window) ! 460: Lisp_Object window; ! 461: { ! 462: for (; !NULL (window); window = XWINDOW (window)->next) ! 463: redisplay_window (window, 0); ! 464: } ! 465: ! 466: redisplay_window (window, just_this_one) ! 467: Lisp_Object window; ! 468: int just_this_one; ! 469: { ! 470: register struct window *w = XWINDOW (window); ! 471: int height; ! 472: register int lpoint = point; ! 473: struct buffer *old = bf_cur; ! 474: register int width = XFASTINT (w->width) - 1 ! 475: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 476: register int startp = marker_position (w->start); ! 477: register int hscroll = XINT (w->hscroll); ! 478: struct position pos; ! 479: int inhibit_hairy_id = 0; ! 480: int opoint; ! 481: int tem; ! 482: ! 483: if (screen_height == 0) abort (); /* Some bug zeros some core */ ! 484: ! 485: /* If this is a combination window, do its children; that's all. */ ! 486: ! 487: if (!NULL (w->vchild)) ! 488: { ! 489: redisplay_windows (w->vchild); ! 490: return 0; ! 491: } ! 492: if (!NULL (w->hchild)) ! 493: { ! 494: redisplay_windows (w->hchild); ! 495: return 0; ! 496: } ! 497: if (NULL (w->buffer)) ! 498: abort (); ! 499: ! 500: if (RedoModes) ! 501: w->redo_mode_line = Qt; ! 502: ! 503: /* Otherwise set up data on this window; select its buffer and point value */ ! 504: ! 505: height = XFASTINT (w->height); ! 506: if (w != XWINDOW (minibuf_window)) ! 507: height--; ! 508: else if (minibuf_message) ! 509: return 0; ! 510: ! 511: SetBfx (XBUFFER (w->buffer)); ! 512: opoint = point; ! 513: ! 514: if (!just_this_one ! 515: && bf_cur == XBUFFER (XWINDOW (selected_window)->buffer)) ! 516: buffer_shared++; ! 517: ! 518: if (!EQ (window, selected_window)) ! 519: { ! 520: SetPoint (marker_position (w->pointm)); ! 521: if (point < FirstCharacter) ! 522: point = FirstCharacter; ! 523: else if (point > NumCharacters) ! 524: point = NumCharacters + 1; ! 525: } ! 526: ! 527: /* Handle case where place to start displaying has been specified */ ! 528: ! 529: if (!NULL (w->force_start)) ! 530: { ! 531: w->redo_mode_line = Qt; ! 532: w->force_start = Qnil; ! 533: XFASTINT (w->last_modified) = 0; ! 534: if (!try_window (window, startp)) ! 535: { ! 536: /* If point does not appear, move point so it does appear */ ! 537: pos = *compute_motion (startp, 0, ! 538: ((EQ (window, minibuf_window) && startp == 1) ! 539: ? minibuf_prompt_width : 0) ! 540: + ! 541: (hscroll ? 1 - hscroll : 0), ! 542: NumCharacters + 1, height / 2, ! 543: - (1 << (SHORTBITS - 1)), ! 544: width, hscroll, pos_tab_offset (w, startp)); ! 545: SetPoint (pos.bufpos); ! 546: if (w != XWINDOW (selected_window)) ! 547: Fset_marker (w->pointm, make_number (point), Qnil); ! 548: else ! 549: lpoint = point; ! 550: ! 551: if (EQ (window, selected_window)) ! 552: { ! 553: cursX = max (0, pos.hpos) + XFASTINT (w->left); ! 554: cursY = pos.vpos + XFASTINT (w->top); ! 555: } ! 556: } ! 557: goto done; ! 558: } ! 559: ! 560: /* Handle case where text has not changed, only point, ! 561: and it has not moved off the screen */ ! 562: ! 563: /* This code is not used for minibuffer for the sake of ! 564: the case of redisplaying to replace an echo area message; ! 565: since in that case the minibuffer contents per se are usually unchanged. ! 566: This code is of no real use in the minibuffer since ! 567: the handling of tlbufpos, etc., in DoDsp handles the same cases. */ ! 568: ! 569: if (XFASTINT (w->last_modified) >= bf_modified ! 570: && point >= startp && !clip_changed ! 571: && (just_this_one || XFASTINT (w->width) == screen_width) ! 572: && !EQ (window, minibuf_window)) ! 573: { ! 574: pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), ! 575: point, height + 1, 10000, width, hscroll, ! 576: pos_tab_offset (w, startp)); ! 577: ! 578: if (pos.vpos < height) ! 579: { ! 580: /* Ok, point is still on screen */ ! 581: if (w == XWINDOW (selected_window)) ! 582: { ! 583: /* These variables are supposed to be origin 1 */ ! 584: cursX = max (0, pos.hpos) + XFASTINT (w->left); ! 585: cursY = pos.vpos + XFASTINT (w->top); ! 586: } ! 587: /* This doesn't do the trick, because if a window to the right of ! 588: this one must be redisplayed, this does nothing because there ! 589: is nothing in DesiredScreen yet, and then the other window is ! 590: redisplayed, making likes that are empty in this window's columns. ! 591: if (XFASTINT (w->width) != screen_width) ! 592: preserve_my_columns (w); ! 593: */ ! 594: goto done; ! 595: } ! 596: /* Don't bother trying redisplay with same start; ! 597: we already know it will lose */ ! 598: } ! 599: else if (just_this_one && !EQ (window, minibuf_window) ! 600: && point >= startp ! 601: && XFASTINT (w->last_modified) ! 602: && XFASTINT (w->window_end_pos) >= 0 ! 603: && do_id && !clip_changed ! 604: && !blank_end_of_window ! 605: && XFASTINT (w->width) == screen_width ! 606: && (tem = try_window_id (selected_window)) ! 607: && tem != -2) ! 608: { ! 609: /* tem > 0 means success. tem == -1 means choose new start. ! 610: tem == -2 means try again with same start, ! 611: and nothing but whitespace follows the changed stuff. ! 612: tem == 0 means try again with same start. */ ! 613: if (tem > 0) ! 614: { ! 615: /* inhibit_hairy_id = 1; */ ! 616: goto done; ! 617: } ! 618: } ! 619: else if (startp >= FirstCharacter && startp <= NumCharacters + 1 ! 620: /* Avoid starting display at end of buffer! */ ! 621: && (startp <= NumCharacters || startp == FirstCharacter ! 622: || (XFASTINT (w->last_modified) >= bf_modified))) ! 623: { ! 624: /* Try to redisplay starting at same place as before */ ! 625: /* If point has not moved off screen, accept the results */ ! 626: if (try_window (window, startp)) ! 627: goto done; ! 628: else ! 629: cancel_my_columns (w); ! 630: } ! 631: ! 632: XFASTINT (w->last_modified) = 0; ! 633: w->redo_mode_line = Qt; ! 634: ! 635: /* Try to scroll by specified few lines */ ! 636: ! 637: if (scroll_step && !clip_changed) ! 638: { ! 639: if (point > startp) ! 640: { ! 641: pos = *vmotion (bf_s1 + bf_s2 + 1 - CURRENT_END_POS (w), ! 642: scroll_step, width, hscroll, window); ! 643: if (pos.vpos >= height) ! 644: goto scroll_fail; ! 645: } ! 646: ! 647: pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step, ! 648: width, hscroll, window); ! 649: ! 650: if (point >= pos.bufpos) ! 651: { ! 652: if (try_window (window, pos.bufpos)) ! 653: goto done; ! 654: else ! 655: cancel_my_columns (w); ! 656: } ! 657: scroll_fail: ; ! 658: } ! 659: ! 660: /* Finally, just choose place to start which centers point */ ! 661: ! 662: pos = *vmotion (point, - height / 2, width, hscroll, window); ! 663: try_window (window, pos.bufpos); ! 664: ! 665: done: ! 666: /* If window not full width, must redo its mode line ! 667: if the window to its side is being redone */ ! 668: if ((!NULL (w->redo_mode_line) ! 669: || (!just_this_one && width < screen_width - 1)) ! 670: && !EQ (window, minibuf_window)) ! 671: display_mode_line (w); ! 672: ! 673: SetPoint (opoint); ! 674: SetBfx (old); ! 675: SetPoint (lpoint); ! 676: ! 677: return inhibit_hairy_id; ! 678: } ! 679: ! 680: /* Do full redisplay on one window, ! 681: starting at position `pos', ! 682: and return nonzero if point appears in the displayed text */ ! 683: ! 684: try_window (window, pos) ! 685: Lisp_Object window; ! 686: register int pos; ! 687: { ! 688: register struct window *w = XWINDOW (window); ! 689: register int height = XFASTINT (w->height) - !EQ (window, minibuf_window); ! 690: register int vpos = XFASTINT (w->top); ! 691: register int last_text_vpos = vpos; ! 692: int tab_offset = pos_tab_offset (w, pos); ! 693: ! 694: struct position val; ! 695: ! 696: Fset_marker (w->start, make_number (pos), Qnil); ! 697: ! 698: point_vpos = -1; ! 699: val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; ! 700: ! 701: while (--height >= 0) ! 702: { ! 703: val = *display_text_line (w, pos, vpos, val.hpos, tab_offset); ! 704: tab_offset += XFASTINT (w->width) - 1; ! 705: if (val.vpos) tab_offset = 0; ! 706: vpos++; ! 707: if (pos != val.bufpos) ! 708: last_text_vpos ! 709: /* Next line, unless prev line ended in end of buffer with no cr */ ! 710: = vpos - (val.vpos && CharAt (val.bufpos - 1) != '\n'); ! 711: pos = val.bufpos; ! 712: } ! 713: ! 714: /* If last line is continued in middle of character, ! 715: include the split character in the text considered on the screen */ ! 716: if (val.hpos < XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0) ! 717: pos++; ! 718: ! 719: /* Make this -1 minus what it really should be, so that it is negative. ! 720: That serves as a signal that it is not really valid. ! 721: When screen updating is through, ! 722: change this to its correct positive value */ ! 723: XFASTINT (w->window_end_pos) = -1 - (bf_s1 + bf_s2 + 1 - pos); ! 724: XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top); ! 725: return point_vpos >= 0; ! 726: } ! 727: ! 728: /* Try to redisplay when buffer is modified locally, ! 729: computing insert/delete line to preserve text outside ! 730: the bounds of the changes. ! 731: Return 1 if successful, 0 if if cannot tell what to do, ! 732: or -1 to tell caller to find a new window start, ! 733: or -2 to tell caller that we did nothing because only whitespace ! 734: appears below the changed part of the screen. */ ! 735: ! 736: try_window_id (window) ! 737: Lisp_Object window; ! 738: { ! 739: int pos; ! 740: register struct window *w = XWINDOW (window); ! 741: register int height = XFASTINT (w->height) - !EQ (window, minibuf_window); ! 742: int top = XFASTINT (w->top); ! 743: int start = marker_position (w->start); ! 744: int width = XFASTINT (w->width) - 1 ! 745: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 746: int hscroll = XINT (w->hscroll); ! 747: int lmargin = hscroll > 0 ? 1 - hscroll : 0; ! 748: register int vpos; ! 749: register int i, tem; ! 750: int last_text_vpos = 0; ! 751: int stop_vpos; ! 752: ! 753: struct position val, bp, ep, xp, pp; ! 754: int scroll_amount = 0; ! 755: int delta; ! 756: int tab_offset, epto; ! 757: ! 758: if (bf_s1 < beg_unchanged) ! 759: beg_unchanged = bf_s1; ! 760: if (bf_s2 < end_unchanged) ! 761: end_unchanged = bf_s2; ! 762: ! 763: if (beg_unchanged + 1 < start) ! 764: return 0; /* Give up if changes go above top of window */ ! 765: ! 766: /* Find position before which nothing is changed. */ ! 767: bp = *compute_motion (start, 0, lmargin, ! 768: beg_unchanged + 1, 10000, 10000, width, hscroll, ! 769: pos_tab_offset (w, start)); ! 770: if (bp.vpos >= height) ! 771: return point < bp.bufpos && !bp.contin; ! 772: ! 773: vpos = bp.vpos; ! 774: ! 775: /* Find beginning of that screen line. Must display from there. */ ! 776: bp = *vmotion (bp.bufpos, 0, width, hscroll, window); ! 777: ! 778: pos = bp.bufpos; ! 779: val.hpos = lmargin; ! 780: if (pos < start) ! 781: return -1; ! 782: ! 783: /* If about to start displaying at the beginning of a continuation line, ! 784: really start with previous screen line, in case it was not ! 785: continued when last redisplayed */ ! 786: if (bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0) ! 787: { ! 788: bp = *vmotion (bp.bufpos, -1, width, hscroll, window); ! 789: --vpos; ! 790: pos = bp.bufpos; ! 791: } ! 792: ! 793: if (bp.contin && bp.hpos != lmargin) ! 794: { ! 795: val.hpos = bp.prevhpos - width + lmargin; ! 796: pos--; ! 797: } ! 798: ! 799: bp.vpos = vpos; ! 800: ! 801: /* Find first newline after which no more is changed */ ! 802: ep = *compute_motion (pos, vpos, val.hpos, ! 803: ScanBf ('\n', ! 804: bf_s1 + bf_s2 + 1 - max (end_unchanged, bf_tail_clip), ! 805: 1), ! 806: height, - (1 << (SHORTBITS - 1)), ! 807: width, hscroll, pos_tab_offset (w, bp.bufpos)); ! 808: ! 809: /* If changes reach past the text available on the screen, ! 810: just display rest of screen. */ ! 811: if (ep.bufpos > bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos)) ! 812: stop_vpos = height; ! 813: else ! 814: stop_vpos = ep.vpos; ! 815: ! 816: /* If no newline before ep, the line ep is on includes some changes ! 817: that must be displayed. Make sure we don't stop before it. */ ! 818: /* Also, if changes reach all the way until ep.bufpos, ! 819: it is possible that something was deleted after the ! 820: newline before it, so the following line must be redrawn. */ ! 821: if (stop_vpos == ep.vpos ! 822: && (ep.bufpos == FirstCharacter ! 823: || CharAt (ep.bufpos - 1) != '\n' ! 824: || ep.bufpos == bf_s1 + bf_s2 + 1 - end_unchanged)) ! 825: stop_vpos = ep.vpos + 1; ! 826: ! 827: point_vpos = -1; ! 828: ! 829: /* If changes do not reach to bottom of window, ! 830: figure out how much to scroll the rest of the window */ ! 831: if (stop_vpos < height) ! 832: { ! 833: /* Now determine how far up or down the rest of the window has moved */ ! 834: epto = pos_tab_offset (w, ep.bufpos); ! 835: xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, ! 836: bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos), ! 837: 10000, 0, width, hscroll, epto); ! 838: scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos); ! 839: ! 840: /* Is everything on screen below the changes whitespace? ! 841: If so, no scrolling is really necessary. */ ! 842: for (i = ep.bufpos; i < xp.bufpos; i++) ! 843: { ! 844: tem = CharAt (i); ! 845: if (tem != ' ' && tem != '\n' && tem != '\t') ! 846: break; ! 847: } ! 848: if (i == xp.bufpos) ! 849: return -2; ! 850: ! 851: XFASTINT (w->window_end_vpos) += scroll_amount; ! 852: ! 853: /* Before doing any scrolling, verify that point will be on screen. */ ! 854: if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height)) ! 855: { ! 856: if (point <= xp.bufpos) ! 857: { ! 858: pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, ! 859: point, height, - (1 << (SHORTBITS - 1)), ! 860: width, hscroll, epto); ! 861: } ! 862: else ! 863: { ! 864: pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, ! 865: point, height, - (1 << (SHORTBITS - 1)), ! 866: width, hscroll, pos_tab_offset (w, xp.bufpos)); ! 867: } ! 868: if (pp.bufpos < point || pp.vpos == height) ! 869: return 0; ! 870: point_vpos = pp.vpos + top; ! 871: point_hpos = pp.hpos + XFASTINT (w->left); ! 872: } ! 873: ! 874: if (stop_vpos - scroll_amount >= height ! 875: || ep.bufpos == xp.bufpos) ! 876: { ! 877: if (scroll_amount < 0) ! 878: stop_vpos -= scroll_amount; ! 879: scroll_amount = 0; ! 880: /* In this path, we have altered window_end_vpos ! 881: and not left it negative. ! 882: We must make sure that, in case display is preempted ! 883: before the screen changes to reflect what we do here, ! 884: further updates will not come to try_window_id ! 885: and assume the screen and window_end_vpos match. */ ! 886: blank_end_of_window = 1; ! 887: } ! 888: else if (!scroll_amount) ! 889: {} ! 890: else if (bp.bufpos == bf_s1 + bf_s2 + 1 - end_unchanged) ! 891: { ! 892: /* If pure deletion, scroll up as many lines as possible. ! 893: In common case of killing a line, this can save the ! 894: following line from being overwritten by scrolling ! 895: and therefore having to be redrawn. */ ! 896: tem = scroll_screen_lines (bp.vpos + top - scroll_amount, ! 897: top + height - max (0, scroll_amount), ! 898: scroll_amount); ! 899: if (!tem) stop_vpos = height; ! 900: } ! 901: else if (scroll_amount) ! 902: { ! 903: tem = scroll_screen_lines (ep.vpos + top - scroll_amount, ! 904: top + height - max (0, scroll_amount), ! 905: scroll_amount); ! 906: if (!tem) stop_vpos = height; ! 907: } ! 908: } ! 909: ! 910: /* In any case, do not display past bottom of window */ ! 911: if (stop_vpos >= height) ! 912: { ! 913: stop_vpos = height; ! 914: scroll_amount = 0; ! 915: } ! 916: ! 917: /* Handle case where pos is before w->start -- ! 918: can happen if part of line had been clipped and is not clipped now */ ! 919: if (vpos == 0 && pos < marker_position (w->start)) ! 920: Fset_marker (w->start, make_number (pos), Qnil); ! 921: ! 922: /* Redisplay the lines where the text was changed */ ! 923: last_text_vpos = vpos; ! 924: tab_offset = pos_tab_offset (w, pos); ! 925: if (val.hpos < 0) ! 926: tab_offset += XFASTINT (w->width) - 1; ! 927: while (vpos < stop_vpos) ! 928: { ! 929: val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); ! 930: tab_offset += XFASTINT (w->width) - 1; ! 931: if (val.vpos) tab_offset = 0; ! 932: if (pos != val.bufpos) ! 933: last_text_vpos ! 934: /* Next line, unless prev line ended in end of buffer with no cr */ ! 935: = vpos - (val.vpos && CharAt (val.bufpos - 1) != '\n'); ! 936: pos = val.bufpos; ! 937: } ! 938: ! 939: /* There are two cases: ! 940: 1) we have displayed down to the bottom of the window ! 941: 2) we have scrolled lines below stop_vpos by scroll_amount */ ! 942: ! 943: if (vpos == height) ! 944: { ! 945: /* If last line is continued in middle of character, ! 946: include the split character in the text considered on the screen */ ! 947: if (val.hpos < lmargin) ! 948: val.bufpos++; ! 949: XFASTINT (w->window_end_vpos) = last_text_vpos; ! 950: XFASTINT (w->window_end_pos) = -1 - (bf_s1 + bf_s2 + 1 - val.bufpos); ! 951: } ! 952: ! 953: /* If scrolling made blank lines at window bottom, ! 954: redisplay to fill those lines */ ! 955: if (scroll_amount < 0) ! 956: { ! 957: vpos = xp.vpos; ! 958: pos = xp.bufpos; ! 959: val.hpos = lmargin; ! 960: if (pos == NumCharacters + 1) ! 961: vpos = height + scroll_amount; ! 962: else if (xp.contin && xp.hpos != lmargin) ! 963: { ! 964: val.hpos = xp.prevhpos - width + lmargin; ! 965: pos--; ! 966: } ! 967: ! 968: blank_end_of_window = 1; ! 969: tab_offset = pos_tab_offset (w, pos); ! 970: if (val.hpos < 0) ! 971: tab_offset += XFASTINT (w->width) - 1; ! 972: ! 973: while (vpos < height) ! 974: { ! 975: val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); ! 976: tab_offset += XFASTINT (w->width) - 1; ! 977: if (val.vpos) tab_offset = 0; ! 978: pos = val.bufpos; ! 979: } ! 980: ! 981: /* Here is a case where display_line_text sets point_vpos wrong. ! 982: Make it be fixed up, below. */ ! 983: if (xp.bufpos == NumCharacters + 1 ! 984: && xp.bufpos == point) ! 985: point_vpos = -1; ! 986: } ! 987: ! 988: /* Attempt to adjust end-of-text positions to new bottom line */ ! 989: if (scroll_amount) ! 990: { ! 991: delta = height - xp.vpos; ! 992: if (delta < 0 ! 993: || (delta > 0 && xp.bufpos <= NumCharacters) ! 994: || (delta == 0 && xp.hpos)) ! 995: { ! 996: val = *vmotion (bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos), ! 997: delta, width, hscroll, window); ! 998: XFASTINT (w->window_end_pos) = bf_s1 + bf_s2 + 1 - val.bufpos; ! 999: XFASTINT (w->window_end_vpos) += val.vpos; ! 1000: } ! 1001: } ! 1002: ! 1003: /* If point was not in a line that was displayed, find it */ ! 1004: if (point_vpos < 0) ! 1005: { ! 1006: val = *compute_motion (start, 0, lmargin, point, 10000, 10000, ! 1007: width, hscroll, pos_tab_offset (w, start)); ! 1008: /* Admit failure if point is off screen now */ ! 1009: if (val.vpos >= height) ! 1010: { ! 1011: for (vpos = 0; vpos < height; vpos++) ! 1012: cancel_line (vpos + top); ! 1013: return 0; ! 1014: } ! 1015: point_vpos = val.vpos + top; ! 1016: point_hpos = val.hpos + XFASTINT (w->left); ! 1017: } ! 1018: ! 1019: cursX = max (0, point_hpos); ! 1020: cursY = point_vpos; ! 1021: ! 1022: if (debug_end_pos) ! 1023: { ! 1024: val = *compute_motion (start, 0, lmargin, NumCharacters + 1, ! 1025: height, - (1 << (SHORTBITS - 1)), ! 1026: width, hscroll, pos_tab_offset (w, start)); ! 1027: if (val.vpos != XFASTINT (w->window_end_vpos)) ! 1028: abort (); ! 1029: if ((XFASTINT (w->window_end_pos) < 0 ! 1030: ? -1 - XFASTINT (w->window_end_pos) ! 1031: : XFASTINT (w->window_end_pos)) ! 1032: != bf_s1 + bf_s2 + 1 - val.bufpos) ! 1033: abort (); ! 1034: } ! 1035: ! 1036: return 1; ! 1037: } ! 1038: ! 1039: /* Display one line of window w, starting at position `start' in w's buffer. ! 1040: Display starting at horizontal position `hpos', ! 1041: which is normally zero or negative. ! 1042: A negative value causes output up to hpos = 0 to be discarded. ! 1043: This is done for negative hscroll, or when this is a continuation line ! 1044: and the continuation occurred in the middle of a multi-column character. ! 1045: ! 1046: `taboffset' is an offset for ostensible hpos, used in tab stop calculations. ! 1047: ! 1048: Display on position `vpos' on the screen. (origin 0). ! 1049: ! 1050: Returns a `struct position' giving character to start next line with ! 1051: and where to display it, including a zero or negative hpos. ! 1052: The vpos field is not really a vpos; it is 1 unless the line is continued */ ! 1053: ! 1054: struct position val_display_text_line; ! 1055: ! 1056: struct position * ! 1057: display_text_line (w, start, vpos, hpos, taboffset) ! 1058: struct window *w; ! 1059: int start; ! 1060: int vpos; ! 1061: int hpos; ! 1062: int taboffset; ! 1063: { ! 1064: register int pos = start; ! 1065: register int c; ! 1066: register char *p1; ! 1067: int end; ! 1068: register int pause; ! 1069: register unsigned char *p; ! 1070: char *endp; ! 1071: register char *startp; ! 1072: register char *p1prev; ! 1073: register struct display_line *line; ! 1074: int tab_width = XFASTINT (XBUFFER (w->buffer)->tab_width); ! 1075: int ctl_arrow = !NULL (XBUFFER (w->buffer)->ctl_arrow); ! 1076: int width = XFASTINT (w->width) - 1 ! 1077: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 1078: struct position val; ! 1079: int lastpos; ! 1080: int invis; ! 1081: int hscroll = XINT (w->hscroll); ! 1082: int truncate = hscroll ! 1083: || (truncate_partial_width_windows ! 1084: && XFASTINT (w->width) < screen_width) ! 1085: || !NULL (XBUFFER (w->buffer)->truncate_lines); ! 1086: int selective ! 1087: = XTYPE (bf_cur->selective_display) == Lisp_Int ! 1088: ? XINT (bf_cur->selective_display) ! 1089: : !NULL (bf_cur->selective_display) ? -1 : 0; ! 1090: ! 1091: hpos += XFASTINT (w->left); ! 1092: line = get_display_line (vpos, XFASTINT (w->left)); ! 1093: if (tab_width <= 0) tab_width = 1; ! 1094: ! 1095: if (w == XWINDOW (minibuf_window) && start == 1) ! 1096: { ! 1097: if (minibuf_prompt) ! 1098: hpos = display_string (w, line, minibuf_prompt, hpos, ! 1099: !truncate ? '\\' : '$', ! 1100: 0); ! 1101: minibuf_prompt_width = hpos; ! 1102: } ! 1103: ! 1104: p1 = line->body + hpos; ! 1105: ! 1106: end = NumCharacters + 1; ! 1107: ! 1108: startp = line->body + XFASTINT (w->left); ! 1109: endp = startp + width; ! 1110: ! 1111: /* Loop generating characters. ! 1112: Stop at end of buffer, before newline, ! 1113: or if reach or pass continuation column. */ ! 1114: ! 1115: pause = pos; ! 1116: while (p1 < endp) ! 1117: { ! 1118: p1prev = p1; ! 1119: if (pos == pause) ! 1120: { ! 1121: if (pos == end) ! 1122: break; ! 1123: if (pos == point && point_vpos < 0) ! 1124: { ! 1125: point_vpos = vpos; ! 1126: point_hpos = p1 - startp; ! 1127: } ! 1128: ! 1129: pause = end; ! 1130: if (pos < point && point < pause) ! 1131: pause = point; ! 1132: if (pos <= bf_s1 && bf_s1 + 1 < pause) ! 1133: pause = bf_s1 + 1; ! 1134: ! 1135: p = &CharAt (pos); ! 1136: } ! 1137: c = *p++; ! 1138: if (c >= 040 && c < 0177) ! 1139: { ! 1140: if (p1 >= startp) ! 1141: *p1 = c; ! 1142: p1++; ! 1143: } ! 1144: else if (c == '\n') ! 1145: { ! 1146: invis = 0; ! 1147: while (pos < end ! 1148: && selective > 0 ! 1149: && position_indentation (pos + 1) >= selective) ! 1150: { ! 1151: invis = 1; ! 1152: pos = ScanBf ('\n', pos + 1, 1); ! 1153: if (CharAt (pos - 1) == '\n') ! 1154: pos--; ! 1155: } ! 1156: if (invis) ! 1157: { ! 1158: p1 += 4; ! 1159: if (p1 - startp > width) ! 1160: p1 = endp; ! 1161: strncpy (p1prev, " ...", p1 - p1prev); ! 1162: } ! 1163: break; ! 1164: } ! 1165: else if (c == '\t') ! 1166: { ! 1167: do ! 1168: { ! 1169: if (p1 >= startp) ! 1170: *p1 = ' '; ! 1171: p1++; ! 1172: } ! 1173: while ((p1 - startp + taboffset + hscroll - (hscroll > 0)) ! 1174: % tab_width); ! 1175: } ! 1176: else if (c == Ctl('M') && !NULL (bf_cur->selective_display)) ! 1177: { ! 1178: pos = ScanBf ('\n', pos, 1); ! 1179: if (CharAt (pos - 1) == '\n') ! 1180: pos--; ! 1181: break; ! 1182: } ! 1183: else if (c < 0200 && ctl_arrow) ! 1184: { ! 1185: if (p1 >= startp) ! 1186: *p1 = '^'; ! 1187: p1++; ! 1188: if (p1 >= startp) ! 1189: *p1 = c ^ 0100; ! 1190: p1++; ! 1191: } ! 1192: else ! 1193: { ! 1194: if (p1 >= startp) ! 1195: *p1 = '\\'; ! 1196: p1++; ! 1197: if (p1 >= startp) ! 1198: *p1 = (c >> 6) + '0'; ! 1199: p1++; ! 1200: if (p1 >= startp) ! 1201: *p1 = (7 & (c >> 3)) + '0'; ! 1202: p1++; ! 1203: if (p1 >= startp) ! 1204: *p1 = (7 & c) + '0'; ! 1205: p1++; ! 1206: } ! 1207: pos++; ! 1208: } ! 1209: ! 1210: val.hpos = - XINT (w->hscroll); ! 1211: if (val.hpos) ! 1212: { ! 1213: val.hpos++; ! 1214: /* If line not empty, insert truncation-at-left marker */ ! 1215: if (pos != start) ! 1216: { ! 1217: *startp = '$'; ! 1218: if (p1 <= startp) ! 1219: p1 = startp + 1; ! 1220: if (line->length <= XFASTINT (w->left)) ! 1221: line->length = XFASTINT (w->left) + 1; ! 1222: } ! 1223: } ! 1224: val.vpos = 1; ! 1225: ! 1226: /* Handle continuation in middle of a character */ ! 1227: /* by backing up over it */ ! 1228: if (p1 > endp) ! 1229: { ! 1230: /* Start the next line with that same character */ ! 1231: pos--; ! 1232: /* but at a negative hpos, to skip the columns output on this line. */ ! 1233: val.hpos += p1prev - endp; ! 1234: /* Keep in this line everything up to the continuation column. */ ! 1235: p1 = endp; ! 1236: } ! 1237: ! 1238: /* Finish deciding which character to start the next line on, ! 1239: and what hpos to start it at. ! 1240: Also set `lastpos' to the last position which counts as "on this line" ! 1241: for cursor-positioning. */ ! 1242: ! 1243: lastpos = pos; ! 1244: ! 1245: if (pos < NumCharacters + 1) ! 1246: { ! 1247: if (CharAt (pos) == '\n') ! 1248: /* If stopped due to a newline, start next line after it */ ! 1249: pos++; ! 1250: else ! 1251: /* Stopped due to right margin of window */ ! 1252: { ! 1253: if (truncate) ! 1254: { ! 1255: *p1++ = '$'; ! 1256: /* Truncating => start next line after next newline, ! 1257: and point is on this line if it is before the newline, ! 1258: and skip none of first char of next line */ ! 1259: pos = ScanBf ('\n', pos, 1); ! 1260: val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; ! 1261: ! 1262: lastpos = pos - (CharAt (pos - 1) == '\n'); ! 1263: } ! 1264: else ! 1265: { ! 1266: *p1++ = '\\'; ! 1267: val.vpos = 0; ! 1268: lastpos = 0; ! 1269: } ! 1270: } ! 1271: } ! 1272: ! 1273: if (start <= point && point <= lastpos && point_vpos < 0) ! 1274: { ! 1275: point_vpos = vpos; ! 1276: point_hpos = p1 - startp; ! 1277: } ! 1278: ! 1279: if (point_vpos == vpos) ! 1280: { ! 1281: if (point_hpos < 0) point_hpos = 0; ! 1282: if (point_hpos > width) point_hpos = width; ! 1283: point_hpos += XFASTINT (w->left); ! 1284: if (w == XWINDOW (selected_window)) ! 1285: { ! 1286: cursY = point_vpos; ! 1287: cursX = point_hpos; ! 1288: ! 1289: /* Line is not continued and did not start in middle of character */ ! 1290: if (hpos == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0) ! 1291: && val.vpos) ! 1292: { ! 1293: this_line_bufpos = start; ! 1294: this_line_buffer = bf_cur; ! 1295: this_line_vpos = vpos; ! 1296: this_line_hpos = hpos; ! 1297: this_line_endpos = bf_s1 + bf_s2 + 1 - lastpos; ! 1298: } ! 1299: else ! 1300: this_line_bufpos = 0; ! 1301: } ! 1302: } ! 1303: ! 1304: if (XFASTINT (w->width) + XFASTINT (w->left) != screen_width) ! 1305: { ! 1306: endp++; ! 1307: if (p1 < startp) p1 = startp; ! 1308: while (p1 < endp) *p1++ = ' '; ! 1309: *p1++ = '|'; ! 1310: } ! 1311: line->length = max (line->length, p1 - line->body); ! 1312: line->body[line->length] = 0; ! 1313: ! 1314: val.bufpos = pos; ! 1315: val_display_text_line = val; ! 1316: return &val_display_text_line; ! 1317: } ! 1318: ! 1319: /* Display the mode line for window w */ ! 1320: ! 1321: display_mode_line (w) ! 1322: struct window *w; ! 1323: { ! 1324: int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1; ! 1325: struct display_line *line = get_display_line (vpos, XFASTINT (w->left)); ! 1326: ! 1327: register unsigned char *s = XSTRING (bf_cur->mode_line_format)->data; ! 1328: ! 1329: display_string (w, line, s, XFASTINT (w->left), 0, 1); ! 1330: /* Make the mode line inverse video if the entire line ! 1331: is made of mode lines. ! 1332: I.e. if this window is full width, ! 1333: or if it is the child of a full width window ! 1334: (which implies that that window is split side-by-side ! 1335: and the rest of this line is mode lines of the sibling windows). */ ! 1336: if (XFASTINT (w->width) == screen_width ! 1337: || XFASTINT (XWINDOW (w->parent)->width) == screen_width) ! 1338: line->highlighted = mode_line_inverse_video; ! 1339: } ! 1340: ! 1341: char fmodetrunc_buf[100]; ! 1342: ! 1343: char * ! 1344: fmodetrunc (str, width) ! 1345: char *str; ! 1346: long width; ! 1347: { ! 1348: register char *buf = fmodetrunc_buf; ! 1349: register char *bp = buf; ! 1350: register long len; ! 1351: ! 1352: len = strlen(str); ! 1353: if (width && width < len) ! 1354: { ! 1355: strcpy(buf,str+len-width); ! 1356: if (buf[0] != '/') ! 1357: while (*bp) ! 1358: if (*bp++ == '/') ! 1359: { ! 1360: bp--; ! 1361: *--bp = '$'; ! 1362: return bp; ! 1363: } ! 1364: buf[0] = '$'; ! 1365: return buf; ! 1366: } ! 1367: return str; ! 1368: } ! 1369: ! 1370: char decode_mode_spec_buf[MScreenWidth + 1]; ! 1371: ! 1372: char * ! 1373: decode_mode_spec (w, string, data_ptr, len_ptr, max_ptr) ! 1374: struct window *w; ! 1375: register char *string; ! 1376: char **data_ptr; ! 1377: int *len_ptr; ! 1378: int *max_ptr; ! 1379: { ! 1380: register int width = 0; ! 1381: register char c; ! 1382: Lisp_Object lstr, proc, list; ! 1383: register char *str; ! 1384: int len; ! 1385: int pos, total; ! 1386: char *tbuf = decode_mode_spec_buf; ! 1387: #define tbufsize (sizeof decode_mode_spec_buf) ! 1388: ! 1389: lstr = Qnil, str = 0; ! 1390: ! 1391: while (isdigit (c = *string++)) ! 1392: width = width * 10 + (c - '0'); ! 1393: ! 1394: switch (c) ! 1395: { ! 1396: case 'b': ! 1397: lstr = bf_cur->name; ! 1398: if (width && XSTRING (lstr)->size > width) ! 1399: width = min (2 * width, XSTRING (lstr)->size); ! 1400: if (width && XSTRING (lstr)->size > width) ! 1401: { ! 1402: str = (char *) alloca (width + 1); ! 1403: bcopy (XSTRING (lstr)->data, str, width - 3); ! 1404: bcopy ("...", str + width - 3, 4); ! 1405: lstr = Qnil; ! 1406: } ! 1407: break; ! 1408: ! 1409: case 'f': ! 1410: if (NULL (bf_cur->filename)) ! 1411: str = "[none]"; ! 1412: else if (XTYPE (bf_cur->filename) == Lisp_String) ! 1413: str = fmodetrunc (XSTRING (bf_cur -> filename)->data, width); ! 1414: break; ! 1415: ! 1416: case 'm': ! 1417: lstr = bf_cur->mode_name; ! 1418: total = min (XSTRING (lstr)->size, tbufsize - 30); ! 1419: if (total < 0) total = 0; ! 1420: bcopy (XSTRING (lstr)->data, tbuf, total); ! 1421: len = 0; ! 1422: list = bf_cur->minor_modes; ! 1423: while (1) ! 1424: { ! 1425: if (!LISTP (list) && !len) ! 1426: { ! 1427: list = Vglobal_minor_modes; ! 1428: len = 1; ! 1429: } ! 1430: ! 1431: if (!(total < tbufsize - 30 && LISTP (list))) ! 1432: break; ! 1433: ! 1434: lstr = XCONS (list)->car; ! 1435: if (!LISTP (lstr)) ! 1436: goto foo; ! 1437: lstr = XCONS (lstr)->cdr; ! 1438: if (XTYPE (lstr) != Lisp_String) ! 1439: goto foo; ! 1440: tbuf[total++] = ' '; ! 1441: pos = min (XSTRING (lstr)->size, tbufsize - 30 - total); ! 1442: if (pos < 0) ! 1443: pos = 0; ! 1444: bcopy (XSTRING (lstr)->data, tbuf + total, pos); ! 1445: total += pos; ! 1446: foo: ! 1447: list = Fcdr (list); ! 1448: } ! 1449: str = tbuf; ! 1450: tbuf[total] = 0; ! 1451: /* if (bf_cur->abbrev_mode) ! 1452: strcat (tbuf, " Abbrev"); */ ! 1453: if (bf_head_clip > 1 || bf_tail_clip > 0) ! 1454: strcat (tbuf, " Narrow"); ! 1455: if (defining_kbd_macro) ! 1456: strcat (tbuf, " Def"); ! 1457: lstr = Qnil; ! 1458: break; ! 1459: ! 1460: case 'M': ! 1461: lstr = Vglobal_mode_string; ! 1462: break; ! 1463: ! 1464: case '*': ! 1465: str = !NULL (bf_cur->read_only) ? "%" ! 1466: : bf_modified > bf_cur->save_modified ? "*" :"-"; ! 1467: break; ! 1468: ! 1469: case 's': ! 1470: /* status of process */ ! 1471: #ifdef subprocesses ! 1472: proc = Fget_buffer_process (Fcurrent_buffer ()); ! 1473: if (NULL (proc)) ! 1474: str = "no process"; ! 1475: else ! 1476: lstr = Fsymbol_name (Fprocess_status (proc)); ! 1477: #else ! 1478: str = "no process"; ! 1479: #endif /* subprocesses */ ! 1480: break; ! 1481: ! 1482: case 'p': ! 1483: pos = marker_position (w->start); ! 1484: total = NumCharacters + 1 - FirstCharacter; ! 1485: ! 1486: if ((XFASTINT (w->window_end_pos) < 0 ! 1487: ? -1 - XFASTINT (w->window_end_pos) ! 1488: : XFASTINT (w->window_end_pos)) ! 1489: <= bf_tail_clip) ! 1490: { ! 1491: if (pos <= FirstCharacter) ! 1492: str = "All"; ! 1493: else ! 1494: str = "Bottom"; ! 1495: } ! 1496: else if (pos <= FirstCharacter) ! 1497: str = "Top"; ! 1498: else ! 1499: { ! 1500: total = ((pos - FirstCharacter) * 100 + total - 1) / total; ! 1501: /* We can't normally display a 3-digit number, ! 1502: so get us a 2-digit number that is close. */ ! 1503: if (total == 100) ! 1504: total = 99; ! 1505: sprintf (tbuf, "%2d%%", total); ! 1506: str = tbuf; ! 1507: } ! 1508: break; ! 1509: ! 1510: case '[': ! 1511: str = "[[[[[[[[[[" + 10 - (RecurseDepth - MinibufDepth); ! 1512: if (RecurseDepth - MinibufDepth > 10) ! 1513: str = "[[[... "; ! 1514: break; ! 1515: ! 1516: case ']': ! 1517: str = "]]]]]]]]]]" + 10 - (RecurseDepth - MinibufDepth); ! 1518: if (RecurseDepth - MinibufDepth > 10) ! 1519: str = " ...]]]"; ! 1520: break; ! 1521: ! 1522: case '-': ! 1523: str = "--------------------------------------------------------------------------------------------------------------------------------------------"; ! 1524: } ! 1525: ! 1526: /* Report the chosen mode item to the caller */ ! 1527: ! 1528: if (str) ! 1529: *data_ptr = str, *len_ptr = strlen (str); ! 1530: else if (XTYPE (lstr) == Lisp_String) ! 1531: *data_ptr = (char *) XSTRING (lstr)->data, ! 1532: *len_ptr = XSTRING (lstr)->size; ! 1533: else ! 1534: *data_ptr = 0, *len_ptr = 0; ! 1535: ! 1536: /* Report specified truncation or padding */ ! 1537: ! 1538: *max_ptr = width; ! 1539: ! 1540: /* Tell caller how much of mode line format was used up */ ! 1541: ! 1542: return string; ! 1543: } ! 1544: ! 1545: /* Display `string' on one line of window `w', starting at `hpos'. ! 1546: Display on the display_line `line', which should have ! 1547: been obtained by get_display_line (vpos, hpos) ! 1548: or in some suitable manner. ! 1549: ! 1550: `truncate' is character to display at end if truncated. ! 1551: `modeline' nonzero means substitute for % constructs. ! 1552: ! 1553: Returns ending hpos */ ! 1554: ! 1555: ! 1556: display_string (w, line, string, hpos, truncate, modeline) ! 1557: struct window *w; ! 1558: register struct display_line *line; ! 1559: unsigned char *string; ! 1560: int hpos; ! 1561: int truncate; ! 1562: int modeline; ! 1563: { ! 1564: register int c; ! 1565: register unsigned char *p1; ! 1566: int width = XFASTINT (w->width) - 1 ! 1567: - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width); ! 1568: int hscroll = XINT (w->hscroll); ! 1569: int tab_width = 8; ! 1570: register unsigned char *start; ! 1571: register unsigned char *end; ! 1572: char *modeeltstring; ! 1573: int modeeltleft = 0; ! 1574: int modeeltmax = 0; ! 1575: ! 1576: p1 = (unsigned char *) line->body + hpos; ! 1577: start = (unsigned char *) line->body + XFASTINT (w->left); ! 1578: end = start + width; ! 1579: ! 1580: while (p1 < end) ! 1581: { ! 1582: if (modeeltmax) ! 1583: { ! 1584: modeeltmax--; ! 1585: if (modeeltleft-- > 0) ! 1586: c = *modeeltstring++; ! 1587: else ! 1588: c = ' '; ! 1589: } ! 1590: else ! 1591: { ! 1592: c = *string++; ! 1593: if (!c) break; ! 1594: if (c == '%' && modeline) ! 1595: { ! 1596: string = (unsigned char *) ! 1597: decode_mode_spec (w, string, &modeeltstring, ! 1598: &modeeltleft, &modeeltmax); ! 1599: ! 1600: if (!modeeltmax) ! 1601: modeeltmax = modeeltleft; ! 1602: else if (modeeltleft > modeeltmax) ! 1603: modeeltleft = modeeltmax; ! 1604: ! 1605: continue; ! 1606: } ! 1607: } ! 1608: ! 1609: if (c >= 040 && c < 0177) ! 1610: { ! 1611: if (p1 >= start) ! 1612: *p1 = c; ! 1613: p1++; ! 1614: } ! 1615: else if (c == '\t') ! 1616: { ! 1617: do ! 1618: { ! 1619: if (p1 >= start) ! 1620: *p1 = ' '; ! 1621: p1++; ! 1622: } ! 1623: while ((p1 - start + hscroll - (hscroll > 0)) % tab_width); ! 1624: } ! 1625: else if (c < 0200 && default_ctl_arrow) ! 1626: { ! 1627: if (p1 >= start) ! 1628: *p1 = '^'; ! 1629: p1++; ! 1630: if (p1 >= start) ! 1631: *p1 = c ^ 0100; ! 1632: p1++; ! 1633: } ! 1634: else ! 1635: { ! 1636: if (p1 >= start) ! 1637: *p1 = '\\'; ! 1638: p1++; ! 1639: if (p1 >= start) ! 1640: *p1 = (c >> 6) + '0'; ! 1641: p1++; ! 1642: if (p1 >= start) ! 1643: *p1 = (7 & (c >> 3)) + '0'; ! 1644: p1++; ! 1645: if (p1 >= start) ! 1646: *p1 = (7 & c) + '0'; ! 1647: p1++; ! 1648: } ! 1649: } ! 1650: ! 1651: if (c) ! 1652: { ! 1653: p1 = end; ! 1654: if (truncate) *p1++ = truncate; ! 1655: } ! 1656: ! 1657: line->length = max (line->length, p1 - (unsigned char *) line->body); ! 1658: line->body[line->length] = 0; ! 1659: return p1 - (unsigned char *) line->body; ! 1660: } ! 1661: ! 1662: syms_of_xdisp () ! 1663: { ! 1664: DefLispVar ("global-mode-string", &Vglobal_mode_string, ! 1665: "String which mode line can display (if its format requests to)."); ! 1666: Vglobal_mode_string = Qnil; ! 1667: ! 1668: DefLispVar ("global-minor-modes", &Vglobal_minor_modes, ! 1669: "Alist of minor modes that are not per buffer.\n\ ! 1670: Cdr of each element is a string to display in mode line."); ! 1671: ! 1672: DefIntVar ("scroll-step", &scroll_step, ! 1673: "*The number of lines to try scrolling a window by when point moves out.\n\ ! 1674: If that fails to bring point back on screen, point is centered instead.\n\ ! 1675: If this is zero, point is always centered after it moves off screen."); ! 1676: ! 1677: DefIntVar ("debug-end-pos", &debug_end_pos, "Don't ask"); ! 1678: ! 1679: DefBoolVar ("truncate-partial-width-windows", ! 1680: &truncate_partial_width_windows, ! 1681: "*Non-nil means truncate lines in all windows less than full screen wide."); ! 1682: truncate_partial_width_windows = 1; ! 1683: ! 1684: DefBoolVar ("mode-line-inverse-video", &mode_line_inverse_video, ! 1685: "*Non-nil means use inverse video, or other suitable display mode, for the mode line."); ! 1686: mode_line_inverse_video = 1; ! 1687: ! 1688: defsubr (&Sredraw_display); ! 1689: } ! 1690: ! 1691: /* initialize the window system */ ! 1692: init_xdisp () ! 1693: { ! 1694: Lisp_Object root_window; ! 1695: #ifndef COMPILER_REGISTER_BUG ! 1696: register ! 1697: #endif COMPILER_REGISTER_BUG ! 1698: struct window *mini_w; ! 1699: ! 1700: this_line_bufpos = 0; ! 1701: ! 1702: mini_w = XWINDOW (minibuf_window); ! 1703: root_window = mini_w->prev; ! 1704: ! 1705: minibuf_message = 0; ! 1706: prev_minibuf_message = 0; ! 1707: ! 1708: if (!noninteractive) ! 1709: { ! 1710: XFASTINT (XWINDOW (root_window)->top) = 0; ! 1711: set_window_height (root_window, screen_height - 1, 0); ! 1712: XFASTINT (mini_w->top) = screen_height - 1; ! 1713: set_window_height (minibuf_window, 1, 0); ! 1714: ! 1715: XFASTINT (XWINDOW (root_window)->width) = screen_width; ! 1716: XFASTINT (mini_w->width) = screen_width; ! 1717: } ! 1718: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.