Annotation of GNUtools/emacs/src/window.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.