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: }