]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Munge comment associated w/ last change to describe intent; nfc.
[gnu-emacs] / src / xdisp.c
index 40e83c7d37c4248a937558187ea4183809957056..d7de7dbe8262baa8219cce6ea48a058371c3b923 100644 (file)
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
 
@@ -231,7 +231,7 @@ extern Lisp_Object Qhelp_echo;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
-Lisp_Object Qredisplay_end_trigger_functions;
+Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
 Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
 Lisp_Object Qfontified;
@@ -2408,7 +2408,9 @@ start_display (it, w, pos)
   init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
   it->first_vpos = first_vpos;
 
-  if (!it->truncate_lines_p)
+  /* Don't reseat to previous visible line start if current start
+     position is in a string or image.  */
+  if (it->method == GET_FROM_BUFFER && !it->truncate_lines_p)
     {
       int start_at_line_beg_p;
       int first_y = it->current_y;
@@ -5871,6 +5873,15 @@ next_element_from_composition (it)
             Moving an iterator without producing glyphs
  ***********************************************************************/
 
+/* Check if iterator is at a position corresponding to a valid buffer
+   position after some move_it_ call.  */
+
+#define IT_POS_VALID_AFTER_MOVE_P(it)                  \
+  ((it)->method == GET_FROM_STRING                     \
+   ? IT_STRING_CHARPOS (*it) == 0                      \
+   : 1)
+
+
 /* Move iterator IT to a specified buffer or X position within one
    line on the display without producing glyphs.
 
@@ -6379,8 +6390,12 @@ move_it_vertically_backward (it, dy)
      y-distance.  */
   it2 = *it;
   it2.max_ascent = it2.max_descent = 0;
-  move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
-             MOVE_TO_POS | MOVE_TO_VPOS);
+  do
+    {
+      move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
+                 MOVE_TO_POS | MOVE_TO_VPOS);
+    }
+  while (!IT_POS_VALID_AFTER_MOVE_P (&it2));
   xassert (IT_CHARPOS (*it) >= BEGV);
   it3 = it2;
 
@@ -6578,21 +6593,45 @@ move_it_by_lines (it, dvpos, need_y_p)
       last_height = 0;
     }
   else if (dvpos > 0)
-    move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
+    {
+      move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
+      if (!IT_POS_VALID_AFTER_MOVE_P (it))
+       move_it_to (it, IT_CHARPOS (*it) + 1, -1, -1, -1, MOVE_TO_POS);
+    }
   else
     {
       struct it it2;
       int start_charpos, i;
 
       /* Start at the beginning of the screen line containing IT's
-        position.  */
+        position.  This may actually move vertically backwards,
+         in case of overlays, so adjust dvpos accordingly.  */
+      dvpos += it->vpos;
       move_it_vertically_backward (it, 0);
+      dvpos -= it->vpos;
 
       /* Go back -DVPOS visible lines and reseat the iterator there.  */
       start_charpos = IT_CHARPOS (*it);
-      for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
+      for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i)
        back_to_previous_visible_line_start (it);
       reseat (it, it->current.pos, 1);
+
+      /* Move further back if we end up in a string or an image.  */
+      while (!IT_POS_VALID_AFTER_MOVE_P (it))
+       {
+         /* First try to move to start of display line.  */
+         dvpos += it->vpos;
+         move_it_vertically_backward (it, 0);
+         dvpos -= it->vpos;
+         if (IT_POS_VALID_AFTER_MOVE_P (it))
+           break;
+         /* If start of line is still in string or image,
+            move further back.  */
+         back_to_previous_visible_line_start (it);
+         reseat (it, it->current.pos, 1);
+         dvpos--;
+       }
+
       it->current_x = it->hpos = 0;
 
       /* Above call may have moved too far if continuation lines
@@ -10046,7 +10085,9 @@ select_frame_for_redisplay (frame)
            (BUFFER_LOCAL_VALUEP (val)
             || SOME_BUFFER_LOCAL_VALUEP (val)))
        && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      Fsymbol_value (sym);
+      /* Use find_symbol_value rather than Fsymbol_value
+        to avoid an error if it is void.  */
+      find_symbol_value (sym);
 
   for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
     if (CONSP (XCAR (tail))
@@ -10057,7 +10098,7 @@ select_frame_for_redisplay (frame)
            (BUFFER_LOCAL_VALUEP (val)
             || SOME_BUFFER_LOCAL_VALUEP (val)))
        && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      Fsymbol_value (sym);
+      find_symbol_value (sym);
 }
 
 
@@ -10131,6 +10172,16 @@ redisplay_internal (preserve_echo_area)
   ++redisplaying_p;
   specbind (Qinhibit_free_realized_faces, Qnil);
 
+  {
+    Lisp_Object tail, frame;
+
+    FOR_EACH_FRAME (tail, frame)
+      {
+       struct frame *f = XFRAME (frame);
+       f->already_hscrolled_p = 0;
+      }
+  }
+
  retry:
   pause = 0;
   reconsider_clip_changes (w, current_buffer);
@@ -10565,8 +10616,12 @@ redisplay_internal (preserve_echo_area)
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                {
                  /* See if we have to hscroll.  */
-                 if (hscroll_windows (f->root_window))
-                   goto retry;
+                 if (!f->already_hscrolled_p)
+                   {
+                     f->already_hscrolled_p = 1;
+                     if (hscroll_windows (f->root_window))
+                       goto retry;
+                   }
 
                  /* Prevent various kinds of signals during display
                     update.  stdio is not robust about handling
@@ -11294,7 +11349,7 @@ cursor_row_fully_visible_p (w, force_p, current_matrix_p)
   window_height = window_box_height (w);
   if (row->height >= window_height)
     {
-      if (!force_p || w->vscroll)
+      if (!force_p || MINI_WINDOW_P (w) || w->vscroll)
        return 1;
     }
   return 0;
@@ -11824,7 +11879,10 @@ try_cursor_movement (window, startp, scroll_step)
              while (!row->mode_line_p
                     && (MATRIX_ROW_START_CHARPOS (row) > PT
                         || (MATRIX_ROW_START_CHARPOS (row) == PT
-                            && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
+                            && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
+                                || (/* STARTS_IN_MIDDLE_OF_STRING_P (row) */
+                                    row > w->current_matrix->rows
+                                    && (row-1)->ends_in_newline_from_string_p))))
                     && (row->y > top_scroll_margin
                         || CHARPOS (startp) == BEGV))
                {
@@ -12729,7 +12787,8 @@ try_window (window, pos, check_margins)
     }
 
   /* Don't let the cursor end in the scroll margins.  */
-  if (check_margins)
+  if (check_margins
+      && !MINI_WINDOW_P (w))
     {
       int this_scroll_margin, cursor_height;
 
@@ -12740,11 +12799,11 @@ try_window (window, pos, check_margins)
 
       if ((w->cursor.y < this_scroll_margin
           && CHARPOS (pos) > BEGV)
-         /* Old redisplay didn't take scroll margin into account at the bottom,
-            but then global-hl-line-mode doesn't scroll.  KFS 2004-06-14 */
-         || (w->cursor.y + (make_cursor_line_fully_visible_p
-                            ? cursor_height + this_scroll_margin
-                            : 1)) > it.last_visible_y)
+         /* rms: considering make_cursor_line_fully_visible_p here
+            seems to give wrong results.  We don't want to recenter
+            when the last line is partly visible, we want to allow
+            that case to be handled in the usual way.  */
+         || (w->cursor.y + 1) > it.last_visible_y)
        {
          w->cursor.vpos = -1;
          clear_glyph_matrix (w->desired_matrix);
@@ -14994,10 +15053,12 @@ cursor_row_p (w, row)
   if (PT == MATRIX_ROW_END_CHARPOS (row))
     {
       /* If the row ends with a newline from a string, we don't want
-        the cursor there (if the row is continued it doesn't end in a
-        newline).  */
+        the cursor there, but we still want it at the start of the
+        string if the string starts in this row.
+        If the row is continued it doesn't end in a newline.  */
       if (CHARPOS (row->end.string_pos) >= 0)
-       cursor_row_p = row->continued_p;
+       cursor_row_p = (row->continued_p
+                       || PT >= MATRIX_ROW_START_CHARPOS (row));
       else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
        {
          /* If the row ends in middle of a real character,
@@ -23075,6 +23136,12 @@ and its new display-start position.  Note that the value of `window-end'
 is not valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
 
+  DEFVAR_LISP ("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions,
+    doc: /* Functions called when redisplay of a window reaches the end trigger.
+Each function is called with two arguments, the window and the end trigger value.
+See `set-window-redisplay-end-trigger'.  */);
+  Vredisplay_end_trigger_functions = Qnil;
+
   DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
     doc: /* *Non-nil means autoselect window with mouse pointer.  */);
   mouse_autoselect_window = 0;