|
|
1.1 ! root 1: /* Window creation, deletion and examination for GNU Emacs. ! 2: Does not include redisplay. ! 3: Copyright (C) 1985 Richard M. Stallman. ! 4: ! 5: This file is part of GNU Emacs. ! 6: ! 7: GNU Emacs is distributed in the hope that it will be useful, ! 8: but WITHOUT ANY WARRANTY. No author or distributor ! 9: accepts responsibility to anyone for the consequences of using it ! 10: or for whether it serves any particular purpose or works at all, ! 11: unless he says so in writing. Refer to the GNU Emacs General Public ! 12: License for full details. ! 13: ! 14: Everyone is granted permission to copy, modify and redistribute ! 15: GNU Emacs, but only under the conditions described in the ! 16: GNU Emacs General Public License. A copy of this license is ! 17: supposed to have been given to you along with GNU Emacs so you ! 18: can know your rights and responsibilities. It should be in a ! 19: file named COPYING. Among other things, the copyright notice ! 20: and this notice must be preserved on all copies. */ ! 21: ! 22: ! 23: #include "config.h" ! 24: #include "lisp.h" ! 25: #include "buffer.h" ! 26: #include "window.h" ! 27: #include "commands.h" ! 28: #include "indent.h" ! 29: #include "termchar.h" ! 30: ! 31: Lisp_Object Qwindowp; ! 32: ! 33: Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window (); ! 34: Lisp_Object Fshow_buffer (), Fsplit_window (), Frecenter (); ! 35: ! 36: /* This is the window which displays the minibuffer. ! 37: It is always the same window. */ ! 38: ! 39: Lisp_Object minibuf_window; ! 40: ! 41: /* This is the window in which the terminal's cursor should ! 42: be left when nothing is being done with it. This must ! 43: always be a leaf window, and its buffer is selected by ! 44: the top level editing loop at the end of each command. */ ! 45: ! 46: Lisp_Object selected_window; ! 47: ! 48: /* If a window gets smaller than either of these, it is removed. */ ! 49: ! 50: int window_min_height; ! 51: int window_min_width; ! 52: ! 53: /* Nonzero implies pop_to_buffer should create windows. */ ! 54: ! 55: int pop_up_windows; ! 56: ! 57: /* display-buffer always splits the largest window ! 58: if that window is more than this high */ ! 59: ! 60: int split_height_threshold; ! 61: ! 62: /* Number of lines of continuity in scrolling by screenfuls. */ ! 63: ! 64: int next_screen_context_lines; ! 65: ! 66: /* Incremented for each window created. */ ! 67: ! 68: static int sequence_number; ! 69: ! 70: DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0, ! 71: "Returns t if OBJ is a window.") ! 72: (obj) ! 73: Lisp_Object obj; ! 74: { ! 75: return XTYPE (obj) == Lisp_Window ? Qt : Qnil; ! 76: } ! 77: ! 78: Lisp_Object ! 79: make_window () ! 80: { ! 81: Lisp_Object val; ! 82: register struct window *p; ! 83: ! 84: val = Fmake_vector ( ! 85: make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)) ! 86: / sizeof (Lisp_Object)), ! 87: Qnil); ! 88: XSETTYPE (val, Lisp_Window); ! 89: p = XWINDOW (val); ! 90: XFASTINT (p->left) = XFASTINT (p->top) ! 91: = XFASTINT (p->height) = XFASTINT (p->width) ! 92: = XFASTINT (p->hscroll) = 0; ! 93: XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0; ! 94: p->start = Fmake_marker (); ! 95: p->pointm = Fmake_marker (); ! 96: XFASTINT (p->sequence_number) = ++sequence_number; ! 97: XFASTINT (p->use_time) = 0; ! 98: return val; ! 99: } ! 100: ! 101: DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0, ! 102: "Return the window that the cursor appears in and commands apply to.") ! 103: () ! 104: { ! 105: return selected_window; ! 106: } ! 107: ! 108: DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, ! 109: Spos_visible_in_window_p, 0, 2, 0, ! 110: "Return t if position POS is currently on the screen in WINDOW.\n\ ! 111: Returns nil if that position is scrolled vertically out of view.\n\ ! 112: POS defaults to point; WINDOW, to the selected window.") ! 113: (pos, window) ! 114: Lisp_Object pos, window; ! 115: { ! 116: register struct window *w; ! 117: register int top; ! 118: register int height; ! 119: register int posint; ! 120: register struct buffer_text *text; ! 121: struct position posval; ! 122: ! 123: if (NULL (pos)) ! 124: posint = point; ! 125: else ! 126: { ! 127: CHECK_NUMBER_COERCE_MARKER (pos, 0); ! 128: posint = XINT (pos); ! 129: } ! 130: ! 131: if (NULL (window)) ! 132: window = selected_window; ! 133: else ! 134: CHECK_WINDOW (window, 1); ! 135: w = XWINDOW (window); ! 136: top = marker_position (w->start); ! 137: ! 138: if (posint < top) ! 139: return Qnil; ! 140: ! 141: height = XFASTINT (w->height) - !EQ (window, minibuf_window); ! 142: ! 143: bf_cur->text = bf_text; ! 144: text = &XBUFFER (w->buffer)->text; ! 145: if (XFASTINT (w->last_modified) >= text->modified) ! 146: { ! 147: /* If screen is up to date, ! 148: use the info recorded about how much text fit on it. */ ! 149: if (posint < text->size1 + text->size2 + 1 - XFASTINT (w->window_end_pos) ! 150: || (XFASTINT (w->window_end_vpos) < height)) ! 151: return Qt; ! 152: return Qnil; ! 153: } ! 154: else ! 155: { ! 156: if (posint > text->size1 + text->size2 + 1) ! 157: return Qnil; ! 158: /* If that info is not correct, calculate afresh */ ! 159: posval = *compute_motion (top, 0, 0, ! 160: posint, height, 0, ! 161: XFASTINT (w->width) - 1 ! 162: - (XFASTINT (w->width) + XFASTINT (w->left) != XFASTINT (XWINDOW (minibuf_window)->width)), ! 163: ! 164: XINT (w->hscroll), 0); ! 165: return posval.vpos < height ? Qt : Qnil; ! 166: } ! 167: } ! 168: ! 169: struct window * ! 170: decode_window (window) ! 171: Lisp_Object window; ! 172: { ! 173: if (NULL (window)) ! 174: return XWINDOW (selected_window); ! 175: ! 176: CHECK_WINDOW (window, 0); ! 177: return XWINDOW (window); ! 178: } ! 179: ! 180: DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0, ! 181: "Return the buffer that WINDOW is displaying.") ! 182: (window) ! 183: Lisp_Object window; ! 184: { ! 185: return decode_window (window)->buffer; ! 186: } ! 187: ! 188: DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0, ! 189: "Return the number of lines in WINDOW (including its mode line).") ! 190: (window) ! 191: Lisp_Object window; ! 192: { ! 193: return decode_window (window)->height; ! 194: } ! 195: ! 196: DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0, ! 197: "Return the number of columns in WINDOW.") ! 198: (window) ! 199: Lisp_Object window; ! 200: { ! 201: return decode_window (window)->width; ! 202: } ! 203: ! 204: DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0, ! 205: "Return the number of columns by which WINDOW is scrolled from left margin.") ! 206: (window) ! 207: Lisp_Object window; ! 208: { ! 209: return decode_window (window)->hscroll; ! 210: } ! 211: ! 212: DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0, ! 213: "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\ ! 214: NCOL should be zero or positive.") ! 215: (window, ncol) ! 216: Lisp_Object window, ncol; ! 217: { ! 218: CHECK_NUMBER (ncol, 1); ! 219: if (XINT (ncol) < 0) XFASTINT (ncol) = 0; ! 220: if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1))) ! 221: args_out_of_range (ncol, Qnil); ! 222: ! 223: clip_changed = 1; /* Prevent redisplay shortcuts */ ! 224: decode_window (window)->hscroll = ncol; ! 225: return ncol; ! 226: } ! 227: ! 228: DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0, ! 229: "Return a list of the edge coordinates of WINDOW.\n\ ! 230: \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of screen.") ! 231: (window) ! 232: Lisp_Object window; ! 233: { ! 234: register struct window *w = decode_window (window); ! 235: ! 236: return Fcons (w->left, Fcons (w->top, ! 237: Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)), ! 238: Fcons (make_number (XFASTINT (w->top) ! 239: + XFASTINT (w->height)), ! 240: Qnil)))); ! 241: } ! 242: ! 243: DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0, ! 244: "Return current value of point in WINDOW.") ! 245: (window) ! 246: Lisp_Object window; ! 247: { ! 248: return Fmarker_position (decode_window (window)->pointm); ! 249: } ! 250: ! 251: DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0, ! 252: "Return position at which display currently starts in WINDOW.") ! 253: (window) ! 254: Lisp_Object window; ! 255: { ! 256: return Fmarker_position (decode_window (window)->start); ! 257: } ! 258: ! 259: DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0, ! 260: "Make point value in WINDOW be at position POS in WINDOW's buffer.") ! 261: (window, pos) ! 262: Lisp_Object window, pos; ! 263: { ! 264: struct window *w = decode_window (window); ! 265: CHECK_NUMBER_COERCE_MARKER (pos, 1); ! 266: Fset_marker (w->pointm, pos, w->buffer); ! 267: return pos; ! 268: } ! 269: ! 270: DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0, ! 271: "Make display in WINDOW start at position POS in WINDOW's buffer.\n\ ! 272: Optional third arg NOFORCE non-nil inhibits next redisplay\n\ ! 273: from overriding motion of point in order to display at this exact start.") ! 274: (window, pos, noforce) ! 275: Lisp_Object window, pos, noforce; ! 276: { ! 277: struct window *w = decode_window (window); ! 278: CHECK_NUMBER_COERCE_MARKER (pos, 1); ! 279: Fset_marker (w->start, pos, w->buffer); ! 280: if (NULL (noforce)) ! 281: w->force_start = Qt; ! 282: w->redo_mode_line = Qt; ! 283: XFASTINT (w->last_modified) = 0; ! 284: return pos; ! 285: } ! 286: ! 287: DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "", ! 288: "Remove WINDOW from the display. Default is selected window.") ! 289: (window) ! 290: Lisp_Object window; ! 291: { ! 292: int osize; ! 293: Lisp_Object tem, parent; ! 294: register struct window *p; ! 295: ! 296: if (NULL (window)) ! 297: window = selected_window; ! 298: else ! 299: CHECK_WINDOW (window, 0); ! 300: ! 301: p = XWINDOW (window); ! 302: parent = p->parent; ! 303: if (NULL (parent)) ! 304: error ("Attempt to delete minibuffer or sole ordinary window"); ! 305: ! 306: windows_or_buffers_changed++; ! 307: ! 308: if (EQ (window, selected_window)) ! 309: Fselect_window (Fnext_window (window, Qnil)); ! 310: ! 311: tem = p->buffer; ! 312: /* tem is null for dummy parent windows ! 313: (which have inferiors but not any contents themselves) */ ! 314: if (!NULL (tem)) ! 315: { ! 316: unshow_buffer (p); ! 317: unchain_marker (p->pointm); ! 318: unchain_marker (p->start); ! 319: } ! 320: ! 321: tem = p->next; ! 322: if (!NULL (tem)) ! 323: XWINDOW (tem)->prev = p->prev; ! 324: ! 325: tem = p->prev; ! 326: if (!NULL (tem)) ! 327: XWINDOW (tem)->next = p->next; ! 328: ! 329: if (EQ (window, XWINDOW (parent)->hchild)) ! 330: XWINDOW (parent)->hchild = p->next; ! 331: if (EQ (window, XWINDOW (parent)->vchild)) ! 332: XWINDOW (parent)->vchild = p->next; ! 333: ! 334: /* Stretch the siblings to use all the available space */ ! 335: if (!NULL (XWINDOW (parent)->vchild)) ! 336: { ! 337: /* It's a vertical combination */ ! 338: osize = XFASTINT (XWINDOW (parent)->height); ! 339: XFASTINT (XWINDOW (parent)->height) ! 340: -= XFASTINT (p->height); ! 341: set_window_height (parent, osize, 1); ! 342: } ! 343: if (!NULL (XWINDOW (parent)->hchild)) ! 344: { ! 345: /* It's a horizontal combination */ ! 346: osize = XFASTINT (XWINDOW (parent)->width); ! 347: XFASTINT (XWINDOW (parent)->width) ! 348: -= XFASTINT (p->width); ! 349: set_window_width (parent, osize, 1); ! 350: } ! 351: ! 352: /* If parent now has only one child, ! 353: put the child into the parent's place. */ ! 354: ! 355: tem = XWINDOW (parent)->hchild; ! 356: if (NULL (tem)) ! 357: tem = XWINDOW (parent)->vchild; ! 358: if (NULL (XWINDOW (tem)->next)) ! 359: replace_window (parent, tem); ! 360: return Qnil; ! 361: } ! 362: ! 363: /* Put replacement into the window structure in place of old. */ ! 364: ! 365: replace_window (old, replacement) ! 366: Lisp_Object old, replacement; ! 367: { ! 368: Lisp_Object tem; ! 369: register struct window *o = XWINDOW (old), *p = XWINDOW (replacement); ! 370: ! 371: p->left = o->left; ! 372: p->top = o->top; ! 373: p->width = o->width; ! 374: p->height = o->height; ! 375: ! 376: p->next = tem = o->next; ! 377: if (!NULL (tem)) ! 378: XWINDOW (tem)->prev = replacement; ! 379: ! 380: p->prev = tem = o->prev; ! 381: if (!NULL (tem)) ! 382: XWINDOW (tem)->next = replacement; ! 383: ! 384: p->parent = tem = o->parent; ! 385: if (!NULL (tem)) ! 386: { ! 387: if (EQ (XWINDOW (tem)->vchild, old)) ! 388: XWINDOW (tem)->vchild = replacement; ! 389: if (EQ (XWINDOW (tem)->hchild, old)) ! 390: XWINDOW (tem)->hchild = replacement; ! 391: } ! 392: ! 393: /*** Here, if replacement is a vertical combination ! 394: and so is its new parent, we should make replacement's ! 395: children be children of that parent instead. ***/ ! 396: } ! 397: ! 398: DEFUN ("next-window", Fnext_window, Snext_window, 0, 2, 0, ! 399: "Return next window after WINDOW in canonical ordering of windows.") ! 400: (window, yesmini) ! 401: Lisp_Object window, yesmini; ! 402: { ! 403: Lisp_Object tem; ! 404: if (NULL (window)) ! 405: window = selected_window; ! 406: else ! 407: CHECK_WINDOW (window, 0); ! 408: do ! 409: { ! 410: while (tem = XWINDOW (window)->next, NULL (tem)) ! 411: if (tem = XWINDOW (window)->parent, !NULL (tem)) ! 412: window = tem; ! 413: else /* window must be minibuf_window now */ ! 414: { ! 415: tem = XWINDOW (window)->prev; ! 416: break; ! 417: } ! 418: window = tem; ! 419: while (1) ! 420: { ! 421: if (!NULL (XWINDOW (window)->hchild)) ! 422: window = XWINDOW (window)->hchild; ! 423: else if (!NULL (XWINDOW (window)->vchild)) ! 424: window = XWINDOW (window)->vchild; ! 425: else break; ! 426: } ! 427: } ! 428: while (EQ (window, minibuf_window) && NULL (yesmini) && !MinibufDepth); ! 429: return window; ! 430: } ! 431: ! 432: DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 1, 0, ! 433: "Return previous window before WINDOW in canonical ordering of windows.") ! 434: (window) ! 435: Lisp_Object window; ! 436: { ! 437: Lisp_Object tem; ! 438: if (NULL (window)) ! 439: window = selected_window; ! 440: else ! 441: CHECK_WINDOW (window, 0); ! 442: do /* at least once, and until not the minibuffer */ ! 443: { ! 444: while (tem = XWINDOW (window)->prev, NULL (tem)) ! 445: if (tem = XWINDOW (window)->parent, !NULL (tem)) ! 446: window = tem; ! 447: else /* window must be the root window now */ ! 448: { ! 449: tem = minibuf_window; ! 450: break; ! 451: } ! 452: window = tem; ! 453: while (1) ! 454: { ! 455: if (!NULL (XWINDOW (window)->hchild)) ! 456: window = XWINDOW (window)->hchild; ! 457: else if (!NULL (XWINDOW (window)->vchild)) ! 458: window = XWINDOW (window)->vchild; ! 459: else break; ! 460: while (tem = XWINDOW (window)->next, !NULL (tem)) ! 461: window = tem; ! 462: } ! 463: } ! 464: while (EQ (window, minibuf_window) && !MinibufDepth); ! 465: return window; ! 466: } ! 467: ! 468: DEFUN ("other-window", Fother_window, Sother_window, 1, 1, "p", ! 469: "Select the ARG'th different window.") ! 470: (n) ! 471: Lisp_Object n; ! 472: { ! 473: int i; ! 474: Lisp_Object w; ! 475: ! 476: CHECK_NUMBER (n, 0); ! 477: w = selected_window; ! 478: i = XINT (n); ! 479: ! 480: while (i > 0) ! 481: { ! 482: w = Fnext_window (w, Qnil); ! 483: i--; ! 484: } ! 485: while (i < 0) ! 486: { ! 487: w = Fprevious_window (w); ! 488: i++; ! 489: } ! 490: Fselect_window (w); ! 491: return Qnil; ! 492: } ! 493: ! 494: Lisp_Object ! 495: window_loop (type, obj) ! 496: int type; ! 497: Lisp_Object obj; ! 498: { ! 499: Lisp_Object w, w1, ret_w, tem; ! 500: register struct window *p, *q; ! 501: ! 502: w = minibuf_window; ! 503: ret_w = Qnil; ! 504: while (1) ! 505: { ! 506: p = XWINDOW (w); ! 507: w1 = Fnext_window (w, Qt); ! 508: if (!EQ (w, minibuf_window)) ! 509: switch (type) ! 510: { ! 511: case 1: ! 512: if (XBUFFER (p->buffer) == XBUFFER (obj)) ! 513: return w; ! 514: break; ! 515: ! 516: case 2: ! 517: /* t as arg means consider only full-width windows */ ! 518: if (!NULL (obj) && XFASTINT (p->width) != screen_width) ! 519: break; ! 520: if (NULL (ret_w) || ! 521: XFASTINT (XWINDOW (ret_w)->use_time) > XFASTINT (p->use_time)) ! 522: ret_w = w; ! 523: break; ! 524: ! 525: case 3: ! 526: if (p != XWINDOW (obj)) ! 527: Fdelete_window (w); ! 528: break; ! 529: ! 530: case 4: ! 531: if (EQ (p->buffer, obj)) ! 532: { ! 533: if (NULL (p->parent)) ! 534: { ! 535: tem = Fother_buffer (obj); ! 536: if (NULL (tem)) ! 537: tem = Fget_buffer_create (build_string ("*scratch*")); ! 538: Fshow_buffer (w, tem); ! 539: Fset_buffer (p->buffer); ! 540: } ! 541: else ! 542: Fdelete_window (w); ! 543: } ! 544: break; ! 545: ! 546: case 5: ! 547: q = XWINDOW (ret_w); ! 548: if (NULL (ret_w) || ! 549: (XFASTINT (p->height) * XFASTINT (p->width)) ! 550: > ! 551: (XFASTINT (q->height) * XFASTINT (q->width))) ! 552: ret_w = w; ! 553: break; ! 554: ! 555: case 6: ! 556: if (EQ (p->buffer, obj)) ! 557: { ! 558: tem = Fother_buffer (obj); ! 559: if (NULL (tem)) ! 560: tem = Fget_buffer_create (build_string ("*scratch*")); ! 561: Fshow_buffer (w, tem); ! 562: Fset_buffer (p->buffer); ! 563: } ! 564: break; ! 565: } ! 566: w = w1; ! 567: if (EQ (w, minibuf_window)) ! 568: return ret_w; ! 569: } ! 570: } ! 571: ! 572: DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 0, 0, ! 573: "Return the window least recently selected or used for display.") ! 574: () ! 575: { ! 576: Lisp_Object w; ! 577: /* First try for a window that is full-width */ ! 578: w = window_loop (2, Qt); ! 579: if (!NULL (w) && !EQ (w, selected_window)) ! 580: return w; ! 581: /* If none of them, try the rest */ ! 582: return window_loop (2, Qnil); ! 583: } ! 584: ! 585: DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 0, 0, ! 586: "Return the largest window in area.") ! 587: () ! 588: { ! 589: return window_loop (5, Qnil); ! 590: } ! 591: ! 592: DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 1, 0, ! 593: "Return a window currently displaying BUFFER, or nil if none.") ! 594: (buffer) ! 595: Lisp_Object buffer; ! 596: { ! 597: buffer = Fget_buffer (buffer); ! 598: if (XTYPE (buffer) == Lisp_Buffer) ! 599: return window_loop (1, buffer); ! 600: else return Qnil; ! 601: } ! 602: ! 603: DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows, ! 604: 0, 1, "", ! 605: "Make WINDOW (or the selected window) fill the screen.") ! 606: (w) ! 607: Lisp_Object w; ! 608: { ! 609: window_loop (3, !NULL (w) ? w : selected_window); ! 610: return Qnil; ! 611: } ! 612: ! 613: DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on, ! 614: 1, 1, "bDelete windows on (buffer): ", ! 615: "Delete all windows showing BUFFER.") ! 616: (buffer) ! 617: Lisp_Object buffer; ! 618: { ! 619: if (!NULL (buffer)) ! 620: { ! 621: buffer = Fget_buffer (buffer); ! 622: CHECK_BUFFER (buffer, 0); ! 623: window_loop (4, buffer); ! 624: } ! 625: return Qnil; ! 626: } ! 627: ! 628: DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, ! 629: Sreplace_buffer_in_windows, ! 630: 1, 1, "bReplace buffer in windows: ", ! 631: "Replace BUFFER with some other buffer in all windows showing it.") ! 632: (buffer) ! 633: Lisp_Object buffer; ! 634: { ! 635: if (!NULL (buffer)) ! 636: { ! 637: buffer = Fget_buffer (buffer); ! 638: CHECK_BUFFER (buffer, 0); ! 639: window_loop (6, buffer); ! 640: } ! 641: return Qnil; ! 642: } ! 643: ! 644: /* Set the height of WINDOW and all its inferiors. */ ! 645: /* Normally the window is deleted if it gets too small. ! 646: nodelete nonzero means do not do this. ! 647: (The caller should check later and do so if appropriate) */ ! 648: ! 649: set_window_height (window, height, nodelete) ! 650: Lisp_Object window; ! 651: int height; ! 652: int nodelete; ! 653: { ! 654: register struct window *w = XWINDOW (window); ! 655: register struct window *c; ! 656: int oheight = XFASTINT (w->height); ! 657: int top, pos, lastbot, opos, lastobot; ! 658: Lisp_Object child; ! 659: ! 660: if (window_min_height < 2) ! 661: window_min_height = 2; ! 662: ! 663: if (!nodelete && ! 664: height < (EQ(window, minibuf_window) ? 1 : window_min_height)) ! 665: { ! 666: Fdelete_window (window); ! 667: return; ! 668: } ! 669: ! 670: XFASTINT (w->last_modified) = 0; ! 671: windows_or_buffers_changed++; ! 672: XFASTINT (w->height) = height; ! 673: if (!NULL (w->hchild)) ! 674: { ! 675: for (child = w->hchild; !NULL (child); child = XWINDOW (child)->next) ! 676: { ! 677: XWINDOW (child)->top = w->top; ! 678: set_window_height (child, height, nodelete); ! 679: } ! 680: } ! 681: else if (!NULL (w->vchild)) ! 682: { ! 683: lastbot = top = XFASTINT (w->top); ! 684: lastobot = 0; ! 685: for (child = w->vchild; !NULL (child); child = c->next) ! 686: { ! 687: c = XWINDOW (child); ! 688: ! 689: opos = lastobot + XFASTINT (c->height); ! 690: ! 691: XFASTINT (c->top) = lastbot; ! 692: ! 693: pos = (((opos * height) << 1) + oheight) / (oheight << 1); ! 694: ! 695: /* Avoid confusion: inhibit deletion of child if becomes too small */ ! 696: set_window_height (child, pos + top - lastbot, 1); ! 697: ! 698: /* Now advance child to next window, ! 699: and set lastbot if child was not just deleted. */ ! 700: lastbot = pos + top, lastobot = opos; ! 701: } ! 702: /* Now delete any children that became too small. */ ! 703: if (!nodelete) ! 704: for (child = w->vchild; !NULL (child); child = XWINDOW (child)->next) ! 705: { ! 706: set_window_height (child, XINT (XWINDOW (child)->height), 0); ! 707: } ! 708: } ! 709: } ! 710: ! 711: /* Recursively set width of WINDOW and its inferiors. */ ! 712: ! 713: set_window_width (window, width, nodelete) ! 714: Lisp_Object window; ! 715: int width; ! 716: int nodelete; ! 717: { ! 718: register struct window *w = XWINDOW (window); ! 719: register struct window *c; ! 720: int owidth = XFASTINT (w->width); ! 721: int left, pos, lastright, opos, lastoright; ! 722: Lisp_Object child; ! 723: ! 724: if (!nodelete && width < window_min_width) ! 725: { ! 726: Fdelete_window (window); ! 727: return; ! 728: } ! 729: ! 730: XFASTINT (w->last_modified) = 0; ! 731: XFASTINT (w->width) = width; ! 732: if (!NULL (w->vchild)) ! 733: { ! 734: for (child = w->vchild; !NULL (child); child = XWINDOW (child)->next) ! 735: { ! 736: XWINDOW (child)->left = w->left; ! 737: set_window_width (child, width, nodelete); ! 738: } ! 739: } ! 740: else if (!NULL (w->hchild)) ! 741: { ! 742: lastright = left = XFASTINT (w->left); ! 743: lastoright = 0; ! 744: for (child = w->hchild; !NULL (child); child = c->next) ! 745: { ! 746: c = XWINDOW (child); ! 747: ! 748: opos = lastoright + XFASTINT (c->width); ! 749: ! 750: XFASTINT (c->left) = lastright; ! 751: ! 752: pos = (((opos * width) << 1) + owidth) / (owidth << 1); ! 753: ! 754: /* Inhibit deletion for becoming too small */ ! 755: set_window_width (child, pos + left - lastright, 1); ! 756: ! 757: /* Now advance child to next window, ! 758: and set lastright if child was not just deleted. */ ! 759: lastright = pos + left, lastoright = opos; ! 760: } ! 761: /* Delete children that became too small */ ! 762: if (!nodelete) ! 763: for (child = w->hchild; !NULL (child); child = XWINDOW (child)->next) ! 764: { ! 765: set_window_width (child, XINT (XWINDOW (child)->width), 0); ! 766: } ! 767: } ! 768: } ! 769: ! 770: static int window_select_count; ! 771: ! 772: DEFUN ("show-buffer", Fshow_buffer, Sshow_buffer, 2, 2, 0, ! 773: "Make WINDOW display BUFFER as its contents.\n\ ! 774: BUFFER can be a buffer or buffer name.") ! 775: (window, buffer) ! 776: Lisp_Object window, buffer; ! 777: { ! 778: Lisp_Object tem; ! 779: struct window *w = decode_window (window); ! 780: ! 781: buffer = Fget_buffer (buffer); ! 782: CHECK_BUFFER (buffer, 1); ! 783: ! 784: if (NULL (XBUFFER (buffer)->name)) ! 785: error ("Attempt to display deleted buffer"); ! 786: ! 787: tem = w->buffer; ! 788: if (!NULL (tem)) ! 789: unshow_buffer (w); ! 790: ! 791: w->buffer = buffer; ! 792: Fset_marker (w->pointm, ! 793: make_number (XBUFFER (buffer) == bf_cur ! 794: ? point : XBUFFER (buffer)->text.pointloc), ! 795: buffer); ! 796: Fset_marker (w->start, make_number (XBUFFER (buffer)->last_window_start), ! 797: buffer); ! 798: XFASTINT (w->last_modified) = 0; ! 799: windows_or_buffers_changed++; ! 800: if (EQ (window, selected_window)) ! 801: Fset_buffer (buffer); ! 802: ! 803: return Qnil; ! 804: } ! 805: ! 806: /* Record info on buffer window w is displaying ! 807: when it is about to cease to display that buffer. */ ! 808: ! 809: unshow_buffer (w) ! 810: struct window *w; ! 811: { ! 812: Lisp_Object buf; ! 813: buf = w->buffer; ! 814: ! 815: if (XBUFFER (buf) != XMARKER (w->pointm)->buffer) ! 816: abort (); ! 817: ! 818: if (w != XWINDOW (selected_window) ! 819: && EQ (buf, XWINDOW (selected_window)->buffer)) ! 820: return; ! 821: ! 822: if (XBUFFER (buf) == bf_cur) ! 823: { ! 824: if (w != XWINDOW (selected_window)) ! 825: point = marker_position (w->pointm); ! 826: } ! 827: else ! 828: XBUFFER (buf)->text.pointloc = ! 829: marker_position (w->pointm); ! 830: XBUFFER (buf)->last_window_start = ! 831: marker_position (w->start); ! 832: } ! 833: ! 834: DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0, ! 835: "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\ ! 836: The main editor command loop selects the buffer of the selected window\n\ ! 837: before each command.") ! 838: (window) ! 839: Lisp_Object window; ! 840: { ! 841: register struct window *w = XWINDOW (window); ! 842: register struct window *ow = XWINDOW (selected_window); ! 843: ! 844: CHECK_WINDOW (window, 0); ! 845: ! 846: if (NULL (w->buffer)) ! 847: error ("Trying to select window with no buffer"); ! 848: ! 849: XFASTINT (w->use_time) = ++window_select_count; ! 850: if (EQ (window, selected_window)) ! 851: return window; ! 852: ! 853: if (bf_cur == XBUFFER (ow->buffer)) ! 854: Fset_marker (ow->pointm, make_number (point), ow->buffer); ! 855: ! 856: selected_window = window; ! 857: ! 858: record_buffer (w->buffer); ! 859: Fset_buffer (w->buffer); ! 860: if (bf_cur == XBUFFER (ow->buffer)) ! 861: { ! 862: /* If the new and old windows show the same buffer, ! 863: Fset_buffer did nothing. So we must switch to ! 864: the new buffer's value of point. */ ! 865: SetPoint (marker_position (w->pointm)); ! 866: if (point < FirstCharacter) ! 867: point = FirstCharacter; ! 868: if (point > NumCharacters + 1) ! 869: point = NumCharacters + 1; ! 870: } ! 871: ! 872: windows_or_buffers_changed++; ! 873: ! 874: return window; ! 875: } ! 876: ! 877: DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2, 0, ! 878: "Make BUFFER appear in some window but don't select it.\n\ ! 879: BUFFER can be a buffer or a buffer name.\n\ ! 880: If BUFFER is shown already in some window, just uses that one,\n\ ! 881: unless the window is the selected window and NOTTHISWINDOW is non-nil.\n\ ! 882: Returns the window displaying BUFFER.") ! 883: (buffer, notthiswindow) ! 884: Lisp_Object buffer, notthiswindow; ! 885: { ! 886: Lisp_Object window; ! 887: buffer = Fget_buffer (buffer); ! 888: CHECK_BUFFER (buffer, 0); ! 889: ! 890: if (NULL (notthiswindow) ! 891: && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer)) ! 892: return selected_window; ! 893: ! 894: window = Fget_buffer_window (buffer); ! 895: if (!NULL (window) ! 896: && (NULL (notthiswindow) || !EQ (window, selected_window))) ! 897: return window; ! 898: ! 899: if (pop_up_windows) ! 900: { ! 901: /* Don't try to create a window if would get an error */ ! 902: if (window_min_height < 2) ! 903: window_min_height = 2; ! 904: if (split_height_threshold < window_min_height << 1) ! 905: split_height_threshold = window_min_height << 1; ! 906: ! 907: window = Fget_largest_window (); ! 908: if (window_height (window) >= split_height_threshold ! 909: && ! 910: XFASTINT (XWINDOW (window)->width) != screen_width) ! 911: window = Fsplit_window (window, Qnil, Qnil); ! 912: else ! 913: { ! 914: window = Fget_lru_window (); ! 915: if ((EQ (window, selected_window) ! 916: || (EQ (selected_window, minibuf_window) ! 917: && EQ (window, XWINDOW (minibuf_window)->prev))) ! 918: && window_height (window) >= window_min_height << 1) ! 919: window = Fsplit_window (window, Qnil, Qnil); ! 920: } ! 921: } ! 922: else ! 923: window = Fget_lru_window (); ! 924: ! 925: Fshow_buffer (window, buffer); ! 926: return window; ! 927: } ! 928: ! 929: temp_output_buffer_show (buf) ! 930: Lisp_Object buf; ! 931: { ! 932: struct buffer *old = bf_cur; ! 933: Lisp_Object window; ! 934: ! 935: Fset_buffer (buf); ! 936: XBUFFER (buf)->save_modified = bf_modified; ! 937: SetPoint (1); ! 938: bf_head_clip = 1; ! 939: bf_tail_clip = 0; ! 940: clip_changed = 1; ! 941: SetBfp (old); ! 942: ! 943: window = Fdisplay_buffer (buf, Qnil); ! 944: XFASTINT (XWINDOW (window)->hscroll) = 0; ! 945: Fset_marker (XWINDOW (window)->start, make_number (1), buf); ! 946: Fset_marker (XWINDOW (window)->pointm, make_number (1), buf); ! 947: } ! 948: ! 949: make_dummy_parent (window) ! 950: Lisp_Object window; ! 951: { ! 952: Lisp_Object old, new; ! 953: register struct window *o, *p; ! 954: old = window; ! 955: XSETTYPE (old, Lisp_Vector); ! 956: new = Fcopy_sequence (old); ! 957: XSETTYPE (new, Lisp_Window); ! 958: ! 959: o = XWINDOW (old); ! 960: p = XWINDOW (new); ! 961: XFASTINT (p->sequence_number) = ++sequence_number; ! 962: ! 963: /* Put new into window structure in place of window */ ! 964: replace_window (window, new); ! 965: ! 966: o->next = Qnil; ! 967: o->prev = Qnil; ! 968: o->vchild = Qnil; ! 969: o->hchild = Qnil; ! 970: o->parent = new; ! 971: ! 972: p->start = Qnil; ! 973: p->pointm = Qnil; ! 974: p->buffer = Qnil; ! 975: } ! 976: ! 977: DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "", ! 978: "Split WINDOW, putting SIZE lines in the first of the pair.\n\ ! 979: WINDOW defaults to selected one and SIZE to half its size.\n\ ! 980: If optional third arg HOR-FLAG is non-nil, split side by side\n\ ! 981: and put SIZE columns in the first of the pair.") ! 982: (window, chsize, horflag) ! 983: Lisp_Object window, chsize, horflag; ! 984: { ! 985: Lisp_Object new; ! 986: register struct window *o, *p; ! 987: int size; ! 988: ! 989: if (NULL (window)) ! 990: window = selected_window; ! 991: else ! 992: CHECK_WINDOW (window, 0); ! 993: ! 994: o = XWINDOW (window); ! 995: ! 996: if (NULL (chsize)) ! 997: { ! 998: if (!NULL (horflag)) ! 999: size = XFASTINT (o->width) >> 1; ! 1000: else ! 1001: size = XFASTINT (o->height) >> 1; ! 1002: } ! 1003: else ! 1004: { ! 1005: CHECK_NUMBER (chsize, 1); ! 1006: size = XINT (chsize); ! 1007: } ! 1008: ! 1009: if (EQ (window, minibuf_window)) ! 1010: error ("Attempt to split minibuffer window"); ! 1011: ! 1012: if (NULL (horflag)) ! 1013: { ! 1014: if (window_min_height < 2) ! 1015: window_min_height = 2; ! 1016: ! 1017: if (size < window_min_height || ! 1018: size + window_min_height > XFASTINT (o->height)) ! 1019: args_out_of_range_3 (window, chsize, horflag); ! 1020: if (NULL (o->parent) || ! 1021: NULL (XWINDOW (o->parent)->vchild)) ! 1022: { ! 1023: make_dummy_parent (window); ! 1024: new = o->parent; ! 1025: XWINDOW (new)->vchild = window; ! 1026: } ! 1027: } ! 1028: else ! 1029: { ! 1030: if (size < window_min_width || ! 1031: size + window_min_width > XFASTINT (o->width)) ! 1032: args_out_of_range_3 (window, chsize, horflag); ! 1033: if (NULL (o->parent) || ! 1034: NULL (XWINDOW (o->parent)->hchild)) ! 1035: { ! 1036: make_dummy_parent (window); ! 1037: new = o->parent; ! 1038: XWINDOW (new)->hchild = window; ! 1039: } ! 1040: } ! 1041: ! 1042: /* Now we know that window's parent is a vertical combination ! 1043: if we are dividing vertically, or a horizontal combination ! 1044: if we are making side-by-side windows */ ! 1045: ! 1046: windows_or_buffers_changed++; ! 1047: new = make_window (); ! 1048: p = XWINDOW (new); ! 1049: ! 1050: p->next = o->next; ! 1051: if (!NULL (p->next)) ! 1052: XWINDOW (p->next)->prev = new; ! 1053: p->prev = window; ! 1054: o->next = new; ! 1055: p->parent = o->parent; ! 1056: ! 1057: Fshow_buffer (new, o->buffer); ! 1058: ! 1059: /* Apportion the available screen space among the two new windows */ ! 1060: ! 1061: if (!NULL (horflag)) ! 1062: { ! 1063: p->height = o->height; ! 1064: p->top = o->top; ! 1065: XFASTINT (p->width) = XFASTINT (o->width) - size; ! 1066: XFASTINT (o->width) = size; ! 1067: XFASTINT (p->left) = XFASTINT (o->left) + size; ! 1068: } ! 1069: else ! 1070: { ! 1071: p->left = o->left; ! 1072: p->width = o->width; ! 1073: XFASTINT (p->height) = XFASTINT (o->height) - size; ! 1074: XFASTINT (o->height) = size; ! 1075: XFASTINT (p->top) = XFASTINT (o->top) + size; ! 1076: } ! 1077: ! 1078: return new; ! 1079: } ! 1080: ! 1081: DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p", ! 1082: "Make current window ARG lines bigger.\n\ ! 1083: From program, optional second arg non-nil means grow sideways ARG columns.") ! 1084: (n, side) ! 1085: Lisp_Object n, side; ! 1086: { ! 1087: CHECK_NUMBER (n, 0); ! 1088: change_window_height (XINT (n), !NULL (side)); ! 1089: return Qnil; ! 1090: } ! 1091: ! 1092: DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p", ! 1093: "Make current window ARG lines smaller.\n\ ! 1094: From program, optional second arg non-nil means shrink sideways ARG columns.") ! 1095: (n, side) ! 1096: Lisp_Object n, side; ! 1097: { ! 1098: CHECK_NUMBER (n, 0); ! 1099: change_window_height (-XINT (n), !NULL (side)); ! 1100: return Qnil; ! 1101: } ! 1102: ! 1103: int ! 1104: window_height (window) ! 1105: Lisp_Object window; ! 1106: { ! 1107: register struct window *p = XWINDOW (window); ! 1108: return XFASTINT (p->height); ! 1109: } ! 1110: ! 1111: int ! 1112: window_width (window) ! 1113: Lisp_Object window; ! 1114: { ! 1115: register struct window *p = XWINDOW (window); ! 1116: return XFASTINT (p->width); ! 1117: } ! 1118: ! 1119: #define MINSIZE(window) \ ! 1120: (widthflag ? window_min_width \ ! 1121: : (EQ (window, minibuf_window) ? 1 : window_min_height)) ! 1122: ! 1123: #define CURBEG(w) \ ! 1124: *(widthflag ? (int *) &w->left : (int *) &w->top) ! 1125: ! 1126: #define CURSIZE(w) \ ! 1127: *(widthflag ? (int *) &w->width : (int *) &w->height) ! 1128: ! 1129: /* Unlike set_window_height, this function ! 1130: also changes the heights of the siblings so as to ! 1131: keep everything consistent. */ ! 1132: ! 1133: change_window_height (delta, widthflag) ! 1134: int delta, widthflag; ! 1135: { ! 1136: Lisp_Object window, parent, tem; ! 1137: register struct window *p; ! 1138: int *sizep; ! 1139: int (*sizefun) () = widthflag ? window_width : window_height; ! 1140: int (*setsizefun) () = widthflag ? set_window_width : set_window_height; ! 1141: int opht, maxdelta; ! 1142: ! 1143: window = selected_window; ! 1144: while (1) ! 1145: { ! 1146: p = XWINDOW (window); ! 1147: parent = p->parent; ! 1148: if (NULL (parent)) ! 1149: { ! 1150: if (widthflag) ! 1151: error ("No other window to side of this one"); ! 1152: break; ! 1153: } ! 1154: if (widthflag ? !NULL (XWINDOW (parent)->hchild) ! 1155: : !NULL (XWINDOW (parent)->vchild)) ! 1156: break; ! 1157: window = parent; ! 1158: } ! 1159: ! 1160: sizep = &CURSIZE (p); ! 1161: ! 1162: if (*sizep + delta < MINSIZE (window)) ! 1163: { ! 1164: Fdelete_window (window); ! 1165: return; ! 1166: } ! 1167: ! 1168: maxdelta = (!NULL (parent) ? (*sizefun) (parent) - *sizep ! 1169: : (tem = (!NULL (p->next) ? p->next : p->prev), ! 1170: (*sizefun) (tem) - MINSIZE (tem))); ! 1171: ! 1172: if (delta > maxdelta) ! 1173: /* This case traps trying to make the minibuffer ! 1174: the full screen, or make the only window aside from the ! 1175: minibuffer the full screen. */ ! 1176: delta = maxdelta; ! 1177: ! 1178: if (!NULL (p->next) && ! 1179: (*sizefun) (p->next) - delta >= MINSIZE (p->next)) ! 1180: { ! 1181: (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0); ! 1182: (*setsizefun) (window, *sizep + delta, 0); ! 1183: CURBEG (XWINDOW (p->next)) += delta; ! 1184: /* This does not change size of p->next, ! 1185: but it propagates the new top edge to its children */ ! 1186: (*setsizefun) (p->next, (*sizefun) (p->next), 0); ! 1187: } ! 1188: else if (!NULL (p->prev) && ! 1189: (*sizefun) (p->prev) - delta >= MINSIZE (p->prev)) ! 1190: { ! 1191: (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0); ! 1192: CURBEG (p) -= delta; ! 1193: (*setsizefun) (window, *sizep + delta, 0); ! 1194: } ! 1195: else ! 1196: { ! 1197: opht = (*sizefun) (parent); ! 1198: ! 1199: delta = (int) ((float) (delta * opht) ! 1200: / (float) (opht - *sizep - delta)); ! 1201: /* Add delta lines or columns to this window, and to the parent, ! 1202: keeping things consistent while not affecting siblings. */ ! 1203: CURSIZE (XWINDOW (parent)) = opht + delta; ! 1204: (*setsizefun) (window, *sizep + delta, 0); ! 1205: /* Squeeze out delta lines or columns from our parent, ! 1206: shriking this window and siblings proportionately. ! 1207: This brings parent back to correct size. ! 1208: Delta was calculated so this makes this window the desired size, ! 1209: taking it all out of the siblings. */ ! 1210: (*setsizefun) (parent, opht, 0); ! 1211: } ! 1212: ! 1213: XFASTINT (p->last_modified) = 0; ! 1214: } ! 1215: ! 1216: static ! 1217: window_scroll (window, n) ! 1218: Lisp_Object window; ! 1219: int n; ! 1220: { ! 1221: register struct window *w = XWINDOW (window); ! 1222: register int opoint = point; ! 1223: register int ht, pos; ! 1224: int lose; ! 1225: Lisp_Object tem; ! 1226: ! 1227: ht = XFASTINT (w->height) - !EQ (window, minibuf_window); ! 1228: ! 1229: XFASTINT (tem) = point; ! 1230: tem = Fpos_visible_in_window_p (tem, window); ! 1231: ! 1232: if (NULL (tem)) ! 1233: { ! 1234: Fvertical_motion (make_number (- ht / 2)); ! 1235: XFASTINT (tem) = point; ! 1236: Fset_marker (w->start, tem, w->buffer); ! 1237: w->force_start = Qt; ! 1238: } ! 1239: ! 1240: SetPoint (marker_position (w->start)); ! 1241: lose = n < 0 && point == FirstCharacter; ! 1242: Fvertical_motion (make_number (n)); ! 1243: pos = point; ! 1244: SetPoint (opoint); ! 1245: ! 1246: if (lose) ! 1247: Fsignal (Qbeginning_of_buffer, Qnil); ! 1248: ! 1249: if (pos < NumCharacters + 1) ! 1250: { ! 1251: Fset_marker (w->start, make_number (pos), w->buffer); ! 1252: w->redo_mode_line = Qt; ! 1253: XFASTINT (w->last_modified) = 0; ! 1254: if (pos > opoint) ! 1255: SetPoint (pos); ! 1256: if (n < 0) ! 1257: { ! 1258: SetPoint (pos); ! 1259: tem = Fvertical_motion (make_number (ht)); ! 1260: if (point > opoint || XFASTINT (tem) < ht) ! 1261: SetPoint (opoint); ! 1262: else ! 1263: Fvertical_motion (make_number (-1)); ! 1264: } ! 1265: } ! 1266: else ! 1267: Fsignal (Qend_of_buffer, Qnil); ! 1268: } ! 1269: ! 1270: scroll_command (n, direction) ! 1271: Lisp_Object n; ! 1272: int direction; ! 1273: { ! 1274: register int defalt ! 1275: = direction * (window_height (selected_window) - 1 ! 1276: - next_screen_context_lines); ! 1277: ! 1278: if (NULL (n)) ! 1279: window_scroll (selected_window, defalt); ! 1280: else if (EQ (n, Qminus)) ! 1281: window_scroll (selected_window, - defalt); ! 1282: else ! 1283: { ! 1284: n = Fprefix_numeric_value (n); ! 1285: window_scroll (selected_window, XINT (n) * direction); ! 1286: } ! 1287: } ! 1288: ! 1289: DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P", ! 1290: "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\ ! 1291: When calling from a program, supply a number as argument or nil.") ! 1292: (n) ! 1293: Lisp_Object n; ! 1294: { ! 1295: scroll_command (n, 1); ! 1296: return Qnil; ! 1297: } ! 1298: ! 1299: DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P", ! 1300: "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\ ! 1301: When calling from a program, supply a number as argument or nil.") ! 1302: (n) ! 1303: Lisp_Object n; ! 1304: { ! 1305: scroll_command (n, -1); ! 1306: return Qnil; ! 1307: } ! 1308: ! 1309: DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P", ! 1310: "Scroll selected window display ARG columns left.\n\ ! 1311: Default for ARG is window width minus 2.") ! 1312: (arg) ! 1313: Lisp_Object arg; ! 1314: { ! 1315: if (NULL (arg)) ! 1316: XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2; ! 1317: else ! 1318: arg = Fprefix_numeric_value (arg); ! 1319: ! 1320: return Fset_window_hscroll (selected_window, ! 1321: make_number (XINT (XWINDOW (selected_window)->hscroll) ! 1322: + XINT (arg))); ! 1323: } ! 1324: ! 1325: DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P", ! 1326: "Scroll selected window display ARG columns right.\n\ ! 1327: Default for ARG is window width minus 2.") ! 1328: (arg) ! 1329: Lisp_Object arg; ! 1330: { ! 1331: if (NULL (arg)) ! 1332: XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2; ! 1333: else ! 1334: arg = Fprefix_numeric_value (arg); ! 1335: ! 1336: return Fset_window_hscroll (selected_window, ! 1337: make_number (XINT (XWINDOW (selected_window)->hscroll) ! 1338: - XINT (arg))); ! 1339: } ! 1340: ! 1341: DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P", ! 1342: "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\ ! 1343: The next window is the one below the current one; or the one at the top\n\ ! 1344: if the current one is at the bottom.\n\ ! 1345: When calling from a program, supply a number as argument or nil.") ! 1346: (n) ! 1347: Lisp_Object n; ! 1348: { ! 1349: Lisp_Object window; ! 1350: struct buffer *old = bf_cur; ! 1351: register int ht; ! 1352: register int opoint = point; ! 1353: ! 1354: window = Fnext_window (selected_window, Qnil); ! 1355: ht = window_height (window) - 1; ! 1356: ! 1357: if (EQ (window, selected_window)) ! 1358: error ("There is no other window"); ! 1359: ! 1360: Fset_buffer (XWINDOW (window)->buffer); ! 1361: SetPoint (marker_position (XWINDOW (window)->pointm)); ! 1362: ! 1363: if (NULL (n)) ! 1364: window_scroll (window, ht - next_screen_context_lines); ! 1365: else if (EQ (n, Qminus)) ! 1366: window_scroll (window, next_screen_context_lines - ht); ! 1367: else ! 1368: { ! 1369: if (XTYPE (n) == Lisp_Cons) ! 1370: n = Fcar (n); ! 1371: CHECK_NUMBER (n, 0); ! 1372: window_scroll (window, XINT (n)); ! 1373: } ! 1374: ! 1375: Fset_marker (XWINDOW (window)->pointm, make_number (point), Qnil); ! 1376: SetBfp (old); ! 1377: SetPoint (opoint); ! 1378: return Qnil; ! 1379: } ! 1380: ! 1381: DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P", ! 1382: "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\ ! 1383: The desired position of point is always relative to the current window.\n\ ! 1384: If there is no ARG (i.e., it is nil) then the entire screen is redisplayed.") ! 1385: (n) ! 1386: Lisp_Object n; ! 1387: { ! 1388: int ht = window_height (selected_window) ! 1389: - !EQ (selected_window, minibuf_window); ! 1390: struct window *w = XWINDOW (selected_window); ! 1391: register int opoint = point; ! 1392: ! 1393: if (NULL (n)) ! 1394: { ! 1395: extern int screen_garbaged; ! 1396: screen_garbaged++; ! 1397: XFASTINT (n) = ht / 2; ! 1398: } ! 1399: else ! 1400: { ! 1401: n = Fprefix_numeric_value (n); ! 1402: CHECK_NUMBER (n, 0); ! 1403: } ! 1404: ! 1405: if (XINT (n) < 0) ! 1406: XSETINT (n, XINT (n) + ht); ! 1407: ! 1408: XSETINT (n, - XINT (n)); ! 1409: ! 1410: Fvertical_motion (n); ! 1411: Fset_marker (w->start, make_number (point), w->buffer); ! 1412: ! 1413: SetPoint (opoint); ! 1414: w->force_start = Qt; ! 1415: ! 1416: return Qnil; ! 1417: } ! 1418: ! 1419: DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line, ! 1420: 1, 1, "P", ! 1421: "Position point relative to window.\n\ ! 1422: With no argument, position at text at center of window.\n\ ! 1423: An argument specifies screen line; zero means top of window,\n\ ! 1424: negative means relative to bottom of window.") ! 1425: (arg) ! 1426: Lisp_Object arg; ! 1427: { ! 1428: register struct window *w = XWINDOW (selected_window); ! 1429: int height = XFASTINT (w->height); ! 1430: register int start; ! 1431: ! 1432: if (!EQ (selected_window, minibuf_window)) height--; ! 1433: ! 1434: if (NULL (arg)) ! 1435: XFASTINT (arg) = height / 2; ! 1436: else ! 1437: { ! 1438: arg = Fprefix_numeric_value (arg); ! 1439: if (XINT (arg) < 0) ! 1440: XSETINT (arg, XINT (arg) + height); ! 1441: } ! 1442: ! 1443: start = marker_position (w->start); ! 1444: if (start < FirstCharacter || start > NumCharacters + 1) ! 1445: { ! 1446: Fvertical_motion (make_number (- height / 2)); ! 1447: Fset_marker (w->start, make_number (point), w->buffer); ! 1448: w->force_start = Qt; ! 1449: start = point; ! 1450: } ! 1451: else ! 1452: SetPoint (start); ! 1453: ! 1454: return Fvertical_motion (arg); ! 1455: } ! 1456: ! 1457: struct saved_window ! 1458: { ! 1459: Lisp_Object window; ! 1460: Lisp_Object buffer, start, pointm, mark; ! 1461: Lisp_Object left, top, width, height, hscroll; ! 1462: Lisp_Object parent, prev; ! 1463: }; ! 1464: ! 1465: struct save_window_data ! 1466: { ! 1467: long size; ! 1468: struct Lisp_Vector *unused; ! 1469: Lisp_Object nsaved; ! 1470: Lisp_Object current_window; ! 1471: Lisp_Object current_buffer; ! 1472: struct saved_window info[1]; ! 1473: }; ! 1474: ! 1475: Lisp_Object ! 1476: save_window_restore (arg) ! 1477: Lisp_Object arg; ! 1478: { ! 1479: register struct window *w; ! 1480: register struct save_window_data *data = (struct save_window_data *) XINTPTR (arg); ! 1481: register struct saved_window *p = data->info; ! 1482: Lisp_Object tem; ! 1483: register int k; ! 1484: ! 1485: windows_or_buffers_changed++; ! 1486: for (k = 0; k < XFASTINT (data->nsaved); k++, p++) ! 1487: { ! 1488: w = XWINDOW (p->window); ! 1489: w->next = Qnil; ! 1490: ! 1491: if (!NULL (p->parent)) ! 1492: w->parent = data->info[XFASTINT (p->parent)].window; ! 1493: else ! 1494: w->parent = Qnil; ! 1495: ! 1496: if (!NULL (p->prev)) ! 1497: { ! 1498: w->prev = data->info[XFASTINT (p->prev)].window; ! 1499: XWINDOW (w->prev)->next = p->window; ! 1500: } ! 1501: else ! 1502: { ! 1503: w->prev = Qnil; ! 1504: if (!NULL (w->parent)) ! 1505: { ! 1506: if (EQ (p->width, XWINDOW (w->parent)->width)) ! 1507: { ! 1508: XWINDOW (w->parent)->vchild = p->window; ! 1509: XWINDOW (w->parent)->hchild = Qnil; ! 1510: } ! 1511: else ! 1512: { ! 1513: XWINDOW (w->parent)->hchild = p->window; ! 1514: XWINDOW (w->parent)->vchild = Qnil; ! 1515: } ! 1516: } ! 1517: } ! 1518: w->left = p->left; ! 1519: w->top = p->top; ! 1520: w->width = p->width; ! 1521: w->height = p->height; ! 1522: w->hscroll = p->hscroll; ! 1523: XFASTINT (w->last_modified) = 0; ! 1524: ! 1525: /* Reinstall the saved buffer and pointers into it. */ ! 1526: if (NULL (p->buffer)) ! 1527: w->buffer = p->buffer; ! 1528: else ! 1529: { ! 1530: if (!NULL (XBUFFER (p->buffer)->name)) ! 1531: /* If saved buffer is alive, install it. */ ! 1532: { ! 1533: w->buffer = p->buffer; ! 1534: Fset_marker (w->start, Fmarker_position (p->start), w->buffer); ! 1535: Fset_marker (w->pointm, Fmarker_position (p->pointm), w->buffer); ! 1536: } ! 1537: else if (NULL (XBUFFER (w->buffer)->name)) ! 1538: /* Else if window's old buffer is dead too, get a live one. */ ! 1539: { ! 1540: w->buffer = Fcdr (Fcar (Vbuffer_alist)); ! 1541: /* Set window markers at start of buffer. ! 1542: Rely on Fset_marker to put them within the restriction. */ ! 1543: Fset_marker (w->start, make_number (0), w->buffer); ! 1544: Fset_marker (w->pointm, make_number (0), w->buffer); ! 1545: } ! 1546: unchain_marker (p->start); ! 1547: unchain_marker (p->pointm); ! 1548: ! 1549: tem = p->mark; ! 1550: if (NULL (tem)) ! 1551: XBUFFER (w->buffer)->mark = Qnil; ! 1552: else ! 1553: { ! 1554: if (NULL (XBUFFER (w->buffer)->mark)) ! 1555: XBUFFER (w->buffer)->mark = Fmake_marker (); ! 1556: ! 1557: Fset_marker (XBUFFER (w->buffer)->mark, ! 1558: Fmarker_position (p->mark), w->buffer); ! 1559: unchain_marker (p->mark); ! 1560: } ! 1561: } ! 1562: } ! 1563: ! 1564: Fselect_window (data->current_window); ! 1565: Fset_buffer (data->current_buffer); ! 1566: ! 1567: free (data); ! 1568: return Qnil; ! 1569: } ! 1570: ! 1571: count_windows (window) ! 1572: struct window *window; ! 1573: { ! 1574: int count = 1; ! 1575: if (!NULL (window->next)) ! 1576: count += count_windows (XWINDOW (window->next)); ! 1577: if (!NULL (window->vchild)) ! 1578: count += count_windows (XWINDOW (window->vchild)); ! 1579: if (!NULL (window->hchild)) ! 1580: count += count_windows (XWINDOW (window->hchild)); ! 1581: return count; ! 1582: } ! 1583: ! 1584: #define SAVE_DATA_SIZE(n_windows) \ ! 1585: ((n_windows - 1) * sizeof (struct saved_window) \ ! 1586: + sizeof (struct save_window_data)) ! 1587: ! 1588: Lisp_Object ! 1589: save_window_save () ! 1590: { ! 1591: Lisp_Object root; ! 1592: int n_windows; ! 1593: struct save_window_data *data; ! 1594: Lisp_Object tem; ! 1595: int size; ! 1596: ! 1597: root = XWINDOW (minibuf_window)->prev; ! 1598: n_windows = count_windows (XWINDOW (root)); ! 1599: ! 1600: size = SAVE_DATA_SIZE (n_windows); ! 1601: data = (struct save_window_data *) xmalloc (size); ! 1602: ! 1603: data->size = (size - sizeof (long) - sizeof (struct Lisp_Vector *)) ! 1604: / sizeof (Lisp_Object); ! 1605: XFASTINT (data->nsaved) = n_windows; ! 1606: data->current_window = selected_window; ! 1607: XSET (data->current_buffer, Lisp_Buffer, bf_cur); ! 1608: ! 1609: save_window_save_1 (root, data, 0); ! 1610: ! 1611: XSET (tem, Lisp_Temp_Vector, data); ! 1612: return tem; ! 1613: } ! 1614: ! 1615: save_window_save_1 (window, data, i) ! 1616: Lisp_Object window; ! 1617: struct save_window_data *data; ! 1618: int i; ! 1619: { ! 1620: struct saved_window *p; ! 1621: struct window *w; ! 1622: Lisp_Object tem; ! 1623: ! 1624: for (;!NULL (window); window = w->next) ! 1625: { ! 1626: p = &data->info[i]; ! 1627: w = XWINDOW (window); ! 1628: ! 1629: XFASTINT (w->temslot) = i++; ! 1630: p->window = window; ! 1631: p->buffer = w->buffer; ! 1632: p->left = w->left; ! 1633: p->top = w->top; ! 1634: p->width = w->width; ! 1635: p->height = w->height; ! 1636: p->hscroll = w->hscroll; ! 1637: if (!NULL (w->buffer)) ! 1638: { ! 1639: if (EQ (window, selected_window) ! 1640: && XBUFFER (w->buffer) == bf_cur) ! 1641: p->pointm = Fpoint_marker (); ! 1642: else ! 1643: p->pointm = Fcopy_marker (w->pointm); ! 1644: ! 1645: p->start = Fcopy_marker (w->start); ! 1646: ! 1647: tem = XBUFFER (w->buffer)->mark; ! 1648: if (!NULL (tem)) ! 1649: p->mark = Fcopy_marker (tem); ! 1650: else ! 1651: p->mark = Qnil; ! 1652: } ! 1653: else ! 1654: { ! 1655: p->pointm = Qnil; ! 1656: p->start = Qnil; ! 1657: p->mark = Qnil; ! 1658: } ! 1659: ! 1660: if (NULL (w->parent)) ! 1661: p->parent = Qnil; ! 1662: else ! 1663: p->parent = XWINDOW (w->parent)->temslot; ! 1664: ! 1665: if (NULL (w->prev)) ! 1666: p->prev = Qnil; ! 1667: else ! 1668: p->prev = XWINDOW (w->prev)->temslot; ! 1669: ! 1670: if (!NULL (w->vchild)) ! 1671: i = save_window_save_1 (w->vchild, data, i); ! 1672: if (!NULL (w->hchild)) ! 1673: i = save_window_save_1 (w->hchild, data, i); ! 1674: } ! 1675: ! 1676: return i; ! 1677: } ! 1678: ! 1679: DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion, ! 1680: 0, UNEVALLED, 0, ! 1681: "Execute body, preserving window sizes and contents.\n\ ! 1682: Restores which buffer appears in which window, where display starts,\n\ ! 1683: as well as the current buffer.\n\ ! 1684: Does not restore the value of point in that buffer.") ! 1685: (args) ! 1686: Lisp_Object args; ! 1687: { ! 1688: Lisp_Object tem, val; ! 1689: struct gcpro gcpro1; ! 1690: int count = specpdl_ptr - specpdl; ! 1691: ! 1692: tem = save_window_save (); ! 1693: ! 1694: GCPRO1 (*XOBJFWD (tem)); ! 1695: gcpro1.nvars ! 1696: = SAVE_DATA_SIZE (XFASTINT (((struct save_window_data *) XINTPTR (tem)) ! 1697: ->nsaved)) ! 1698: / 4; ! 1699: ! 1700: record_unwind_protect (save_window_restore, tem); ! 1701: val = Fprogn (args); ! 1702: UNGCPRO; ! 1703: unbind_to (count); ! 1704: return val; ! 1705: } ! 1706: ! 1707: init_window_once () ! 1708: { ! 1709: extern Lisp_Object get_minibuffer (); ! 1710: Lisp_Object root_window; ! 1711: ! 1712: root_window = make_window (); ! 1713: minibuf_window = make_window (); ! 1714: ! 1715: XWINDOW (root_window)->next = minibuf_window; ! 1716: XWINDOW (minibuf_window)->prev = root_window; ! 1717: ! 1718: /* These values 9 and 10 are arbitrary, ! 1719: just so that there is "something there." ! 1720: Correct values are put in in init_xdisp */ ! 1721: ! 1722: XFASTINT (XWINDOW (root_window)->width) = 10; ! 1723: XFASTINT (XWINDOW (minibuf_window)->width) = 10; ! 1724: ! 1725: XFASTINT (XWINDOW (root_window)->height) = 9; ! 1726: XFASTINT (XWINDOW (minibuf_window)->top) = 9; ! 1727: XFASTINT (XWINDOW (minibuf_window)->height) = 1; ! 1728: ! 1729: Fshow_buffer (root_window, Fcurrent_buffer ()); ! 1730: Fshow_buffer (minibuf_window, get_minibuffer (0)); ! 1731: ! 1732: selected_window = root_window; ! 1733: } ! 1734: ! 1735: syms_of_window () ! 1736: { ! 1737: Qwindowp = intern ("windowp"); ! 1738: staticpro (&Qwindowp); ! 1739: ! 1740: /* Make sure all windows get marked */ ! 1741: staticpro (&minibuf_window); ! 1742: ! 1743: DefBoolVar ("pop-up-windows", &pop_up_windows, ! 1744: "*Non-nil means display-buffer should make new windows."); ! 1745: pop_up_windows = 1; ! 1746: ! 1747: DefIntVar ("next-screen-context-lines", &next_screen_context_lines, ! 1748: "*Number of lines of continuity when scrolling by screenfuls."); ! 1749: next_screen_context_lines = 2; ! 1750: ! 1751: DefIntVar ("split-height-threshold", &split_height_threshold, ! 1752: "*display-buffer would prefer to split the largest window if this large.\n\ ! 1753: If there is only one window, it is split regardless of this value."); ! 1754: split_height_threshold = 500; ! 1755: ! 1756: DefIntVar ("window-min-height", &window_min_height, ! 1757: "*Delete any window less than this tall (including its mode line)."); ! 1758: window_min_height = 4; ! 1759: ! 1760: DefIntVar ("window-min-width", &window_min_width, ! 1761: "*Delete any window less than this wide."); ! 1762: window_min_width = 10; ! 1763: ! 1764: defsubr (&Sselected_window); ! 1765: defsubr (&Swindowp); ! 1766: defsubr (&Spos_visible_in_window_p); ! 1767: defsubr (&Swindow_buffer); ! 1768: defsubr (&Swindow_height); ! 1769: defsubr (&Swindow_width); ! 1770: defsubr (&Swindow_hscroll); ! 1771: defsubr (&Sset_window_hscroll); ! 1772: defsubr (&Swindow_edges); ! 1773: defsubr (&Swindow_point); ! 1774: defalias (&Swindow_point, "window-dot"); ! 1775: defsubr (&Swindow_start); ! 1776: defsubr (&Sset_window_point); ! 1777: defalias (&Sset_window_point, "set-window-dot"); ! 1778: defsubr (&Sset_window_start); ! 1779: defsubr (&Snext_window); ! 1780: defsubr (&Sprevious_window); ! 1781: defsubr (&Sother_window); ! 1782: defsubr (&Sget_lru_window); ! 1783: defsubr (&Sget_largest_window); ! 1784: defsubr (&Sget_buffer_window); ! 1785: defsubr (&Sdelete_other_windows); ! 1786: defsubr (&Sdelete_windows_on); ! 1787: defsubr (&Sreplace_buffer_in_windows); ! 1788: defsubr (&Sdelete_window); ! 1789: defsubr (&Sshow_buffer); ! 1790: defsubr (&Sselect_window); ! 1791: defsubr (&Sdisplay_buffer); ! 1792: defsubr (&Ssplit_window); ! 1793: defsubr (&Senlarge_window); ! 1794: defsubr (&Sshrink_window); ! 1795: defsubr (&Sscroll_up); ! 1796: defsubr (&Sscroll_down); ! 1797: defsubr (&Sscroll_left); ! 1798: defsubr (&Sscroll_right); ! 1799: defsubr (&Sscroll_other_window); ! 1800: defsubr (&Srecenter); ! 1801: defsubr (&Smove_to_window_line); ! 1802: defsubr (&Ssave_window_excursion); ! 1803: } ! 1804: ! 1805: keys_of_window () ! 1806: { ! 1807: defkey (CtlXmap, '1', "delete-other-windows"); ! 1808: defkey (CtlXmap, '2', "split-window"); ! 1809: defkey (CtlXmap, '0', "delete-window"); ! 1810: defkey (CtlXmap, 'o', "other-window"); ! 1811: defkey (CtlXmap, '^', "enlarge-window"); ! 1812: defkey (CtlXmap, '<', "scroll-left"); ! 1813: defkey (CtlXmap, '>', "scroll-right"); ! 1814: ! 1815: defkey (GlobalMap, Ctl ('V'), "scroll-up"); ! 1816: defkey (ESCmap, Ctl ('V'), "scroll-other-window"); ! 1817: defkey (ESCmap, 'v', "scroll-down"); ! 1818: ! 1819: defkey (GlobalMap, Ctl('L'), "recenter"); ! 1820: defkey (ESCmap, 'r', "move-to-window-line"); ! 1821: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.