(struct saved_window): Add members orig_top and
[bpt/emacs.git] / src / window.c
index 12b1542..676156c 100644 (file)
@@ -79,6 +79,7 @@ static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
 static int foreach_window_1 P_ ((struct window *,
                                 int (* fn) (struct window *, void *),
                                 void *));
+static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 
 /* This is the window in which the terminal's cursor should
    be left when nothing is being done with it.  This must
@@ -337,7 +338,7 @@ POS defaults to point in WINDOW; WINDOW defaults to the selected window.")
         char in the window.  */
       if (!NILP (fully))
        {
-         pos_visible_p (w, posint, &fully_p);
+         pos_visible_p (w, posint, &fully_p, !NILP (fully));
          in_window = fully_p ? Qt : Qnil;
        }
       else
@@ -350,7 +351,7 @@ POS defaults to point in WINDOW; WINDOW defaults to the selected window.")
     in_window = Qnil;
   else
     {
-      if (pos_visible_p (w, posint, &fully_p))
+      if (pos_visible_p (w, posint, &fully_p, !NILP (fully)))
        in_window = NILP (fully) || fully_p ? Qt : Qnil;
       else
        in_window = Qnil;
@@ -494,6 +495,11 @@ coordinates_in_window (w, x, y)
   int left_x, right_x, top_y, bottom_y;
   int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
 
+  /* Let's make this a global enum later, instead of using numbers
+     everywhere.  */
+  enum {ON_NOTHING, ON_TEXT, ON_MODE_LINE, ON_VERTICAL_BORDER,
+       ON_HEADER_LINE, ON_LEFT_FRINGE, ON_RIGHT_FRINGE};
+
   /* In what's below, we subtract 1 when computing right_x because we
      want the rightmost pixel, which is given by left_pixel+width-1.  */
   if (w->pseudo_window_p)
@@ -513,6 +519,7 @@ coordinates_in_window (w, x, y)
       bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
     }
 
+  /* Completely outside anything interesting?  */
   if (*y < top_y
       || *y >= bottom_y
       || *x < (left_x
@@ -520,19 +527,37 @@ coordinates_in_window (w, x, y)
               - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
                  * CANON_X_UNIT (f)))
       || *x > right_x + flags_area_width)
-    /* Completely outside anything interesting.  */
-    return 0;
-  else if (WINDOW_WANTS_MODELINE_P (w)
-          && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
-    /* On the mode line.  */
-    return 2;
-  else if (WINDOW_WANTS_HEADER_LINE_P (w)
-          && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
-    /* On the top line.  */
-    return 4;
+    return ON_NOTHING;
+  
+  /* On the mode line or header line?  If it's near the start of
+     the mode or header line of window that's has a horizontal
+     sibling, say it's on the vertical line.  That's to be able
+     to resize windows horizontally in case we're using toolkit
+     scroll bars.  */
+  
+  if (WINDOW_WANTS_MODELINE_P (w)
+      && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
+    {
+      if (XFASTINT (w->left) > 0
+         && (abs (*x - XFASTINT (w->left) * CANON_X_UNIT (f))
+             < CANON_X_UNIT (f) / 2))
+       return ON_VERTICAL_BORDER;
+      return ON_MODE_LINE;
+    }
+  
+  if (WINDOW_WANTS_HEADER_LINE_P (w)
+      && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
+    {
+      if (XFASTINT (w->left) > 0
+         && (abs (*x - XFASTINT (w->left) * CANON_X_UNIT (f))
+             < CANON_X_UNIT (f) / 2))
+       return ON_VERTICAL_BORDER;
+      return ON_HEADER_LINE;
+    }
+  
   /* Need to say "*x > right_x" rather than >=, since on character
      terminals, the vertical line's x coordinate is right_x.  */
-  else if (*x < left_x || *x > right_x)
+  if (*x < left_x || *x > right_x)
     {
       /* Other lines than the mode line don't include flags areas and
         scroll bars on the left.  */
@@ -540,22 +565,21 @@ coordinates_in_window (w, x, y)
       /* Convert X and Y to window-relative pixel coordinates.  */
       *x -= left_x;
       *y -= top_y;
-      return *x < left_x ? 5 : 6;
+      return *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
     }
+  
   /* Here, too, "*x > right_x" is because of character terminals.  */
-  else if (!w->pseudo_window_p
-          && !WINDOW_RIGHTMOST_P (w)
-          && *x > right_x - CANON_X_UNIT (f))
+  if (!w->pseudo_window_p
+      && !WINDOW_RIGHTMOST_P (w)
+      && *x > right_x - CANON_X_UNIT (f))
     /* On the border on the right side of the window?  Assume that
        this area begins at RIGHT_X minus a canonical char width.  */
-    return 3;
-  else
-    {
-      /* Convert X and Y to window-relative pixel coordinates.  */
-      *x -= left_x;
-      *y -= top_y;
-      return 1;
-    }
+    return ON_VERTICAL_BORDER;
+  
+  /* Convert X and Y to window-relative pixel coordinates.  */
+  *x -= left_x;
+  *y -= top_y;
+  return ON_TEXT;
 }
 
 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
@@ -1549,9 +1573,35 @@ argument ALL_FRAMES is non-nil, cycle through all frames.")
 
 
 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
-  "Return a list of windows in canonical ordering.\n\
-Arguments are like for `next-window'.")
-  (window, minibuf, all_frames)
+  "Return a list of windows on FRAME, starting with WINDOW.\n\
+FRAME nil or omitted means use the selected frame.\n\
+WINDOW nil or omitted means use the selected window.\n\
+MINIBUF t means include the minibuffer window, even if it isn't active.\n\
+MINIBUF nil or omitted means include the minibuffer window only\n\
+if it's active.\n\
+MINIBUF neither nil nor t means never include the minibuffer window.")
+  (frame, minibuf, window)
+     Lisp_Object frame, minibuf, window;
+{
+  Lisp_Object list;
+
+  if (NILP (window))
+    window = selected_window;
+  if (NILP (frame))
+    frame = selected_frame;
+
+  if (!EQ (frame, XWINDOW (window)->frame))
+    error ("Window is on a different frame");
+
+  return window_list_1 (window, minibuf, frame);
+}
+
+
+/* Return a list of windows in canonical ordering.  Arguments are like
+   for `next-window'.  */
+
+static Lisp_Object
+window_list_1 (window, minibuf, all_frames)
      Lisp_Object window, minibuf, all_frames;
 {
   Lisp_Object tail, list;
@@ -1637,7 +1687,7 @@ window_loop (type, obj, mini, frames)
      We can't just wait until we hit the first window again, because
      it might be deleted.  */
 
-  windows = Fwindow_list (window, mini ? Qt : Qnil, frame_arg);
+  windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
   GCPRO1 (windows);
   best_window = Qnil;
 
@@ -4351,7 +4401,8 @@ displayed_window_lines (w)
       int lines = (rest + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
       it.vpos += lines;
     }
-  else if (bottom_y > height)
+  else if (it.current_y < height && bottom_y > height)
+    /* Partially visible line at the bottom.  */
     ++it.vpos;
   
   return it.vpos;
@@ -4437,8 +4488,9 @@ struct saved_window
     Lisp_Object parent, prev;
     Lisp_Object start_at_line_beg;
     Lisp_Object display_table;
+    Lisp_Object orig_top, orig_height;
   };
-#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
+#define SAVED_WINDOW_VECTOR_SIZE 16 /* Arg to Fmake_vector */
 
 #define SAVED_WINDOW_N(swv,n) \
   ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
@@ -4500,7 +4552,6 @@ the return value is nil.  Otherwise the value is t.")
     {
       if (XBUFFER (new_current_buffer) == current_buffer)
        old_point = PT;
-
     }
 
   frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
@@ -4515,7 +4566,7 @@ the return value is nil.  Otherwise the value is t.")
       struct window *root_window;
       struct window **leaf_windows;
       int n_leaf_windows;
-      int k, i;
+      int k, i, n;
 
       /* If the frame has been resized since this window configuration was
         made, we change the frame to the size specified in the
@@ -4631,6 +4682,8 @@ the return value is nil.  Otherwise the value is t.")
          w->height = p->height;
          w->hscroll = p->hscroll;
          w->display_table = p->display_table;
+         w->orig_top = p->orig_top;
+         w->orig_height = p->orig_height;
          XSETFASTINT (w->last_modified, 0);
          XSETFASTINT (w->last_overlay_modified, 0);
 
@@ -4722,15 +4775,24 @@ the return value is nil.  Otherwise the value is t.")
 #endif
 
       /* Now, free glyph matrices in windows that were not reused.  */
-      for (i = 0; i < n_leaf_windows; ++i)
-       if (NILP (leaf_windows[i]->buffer))
-         {
-           /* Assert it's not reused as a combination.  */
-           xassert (NILP (leaf_windows[i]->hchild) 
-                    && NILP (leaf_windows[i]->vchild));
-           free_window_matrices (leaf_windows[i]);
-           SET_FRAME_GARBAGED (f);
-         }
+      for (i = n = 0; i < n_leaf_windows; ++i)
+       {
+         if (NILP (leaf_windows[i]->buffer))
+           {
+             /* Assert it's not reused as a combination.  */
+             xassert (NILP (leaf_windows[i]->hchild) 
+                      && NILP (leaf_windows[i]->vchild));
+             free_window_matrices (leaf_windows[i]);
+             SET_FRAME_GARBAGED (f);
+           }
+         else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
+           ++n;
+       }
+
+      /* If more than one window shows the new and old current buffer,
+        don't try to preserve point in that buffer.  */
+      if (old_point > 0 && n > 1)
+       old_point = -1;
       
       adjust_glyphs (f);
 
@@ -4887,6 +4949,8 @@ save_window_save (window, vector, i)
       p->height = w->height;
       p->hscroll = w->hscroll;
       p->display_table = w->display_table;
+      p->orig_top = w->orig_top;
+      p->orig_height = w->orig_height;
       if (!NILP (w->buffer))
        {
          /* Save w's value of point in the window configuration.
@@ -4984,8 +5048,7 @@ redirection (see `redirect-frame-focus').")
   for (i = 0; i < n_windows; i++)
     XVECTOR (tem)->contents[i]
       = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
-  save_window_save (FRAME_ROOT_WINDOW (f),
-                   XVECTOR (tem), 0);
+  save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
   XSETWINDOW_CONFIGURATION (tem, data);
   return (tem);
 }