* xdisp.c (rows_from_pos_range): Add parens as per gcc -Wparentheses.
[bpt/emacs.git] / src / xdisp.c
index 3ac5651..c90184f 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2011  Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2012  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -4090,10 +4090,11 @@ handle_invisible_prop (struct it *it)
          while (invis_p);
 
          /* The position newpos is now either ZV or on visible text.  */
-         if (it->bidi_p && newpos < ZV)
+         if (it->bidi_p)
            {
              EMACS_INT bpos = CHAR_TO_BYTE (newpos);
-             int on_newline = FETCH_BYTE (bpos) == '\n';
+             int on_newline =
+               bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
              int after_newline =
                newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
 
@@ -4111,16 +4112,16 @@ handle_invisible_prop (struct it *it)
 
                  SET_TEXT_POS (tpos, newpos, bpos);
                  reseat_1 (it, tpos, 0);
-                 /* If we reseat on a newline, we need to prep the
+                 /* If we reseat on a newline/ZV, we need to prep the
                     bidi iterator for advancing to the next character
-                    after the newline, keeping the current paragraph
+                    after the newline/EOB, keeping the current paragraph
                     direction (so that PRODUCE_GLYPHS does TRT wrt
                     prepending/appending glyphs to a glyph row).  */
                  if (on_newline)
                    {
                      it->bidi_it.first_elt = 0;
                      it->bidi_it.paragraph_dir = pdir;
-                     it->bidi_it.ch = '\n';
+                     it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
                      it->bidi_it.nchars = 1;
                      it->bidi_it.ch_len = 1;
                    }
@@ -4338,7 +4339,7 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   int rv;
 
   if (CONSP (spec)
-      /* Simple specerties.  */
+      /* Simple specifications.  */
       && !EQ (XCAR (spec), Qimage)
       && !EQ (XCAR (spec), Qspace)
       && !EQ (XCAR (spec), Qwhen)
@@ -13644,7 +13645,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
   /* Non-zero means we've seen at least one glyph that came from a
      display string.  */
   int string_seen = 0;
-  /* Largest and smalles buffer positions seen so far during scan of
+  /* Largest and smallest buffer positions seen so far during scan of
      glyph row.  */
   EMACS_INT bpos_max = pos_before;
   EMACS_INT bpos_min = pos_after;
@@ -14360,7 +14361,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
     {
       int scroll_margin_y;
 
-      /* Compute the pixel ypos of the scroll margin, then move it to
+      /* Compute the pixel ypos of the scroll margin, then move IT to
         either that ypos or PT, whichever comes first.  */
       start_display (&it, w, startp);
       scroll_margin_y = it.last_visible_y - this_scroll_margin
@@ -14390,7 +14391,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          if (dy > scroll_max)
            return SCROLLING_FAILED;
 
-         scroll_down_p = 1;
+         if (dy > 0)
+           scroll_down_p = 1;
        }
     }
 
@@ -18886,7 +18888,8 @@ display_line (struct it *it)
 #define RECORD_MAX_MIN_POS(IT)                                 \
   do                                                           \
     {                                                          \
-      int composition_p = (IT)->what == IT_COMPOSITION;                \
+      int composition_p = !STRINGP ((IT)->string)              \
+       && ((IT)->what == IT_COMPOSITION);                      \
       EMACS_INT current_pos =                                  \
        composition_p ? (IT)->cmp_it.charpos                    \
                      : IT_CHARPOS (*(IT));                     \
@@ -25814,12 +25817,14 @@ cursor_in_mouse_face_p (struct window *w)
 \f
 /* Find the glyph rows START_ROW and END_ROW of window W that display
    characters between buffer positions START_CHARPOS and END_CHARPOS
-   (excluding END_CHARPOS).  This is similar to row_containing_pos,
-   but is more accurate when bidi reordering makes buffer positions
-   change non-linearly with glyph rows.  */
+   (excluding END_CHARPOS).  DISP_STRING is a display string that
+   covers these buffer positions.  This is similar to
+   row_containing_pos, but is more accurate when bidi reordering makes
+   buffer positions change non-linearly with glyph rows.  */
 static void
 rows_from_pos_range (struct window *w,
                     EMACS_INT start_charpos, EMACS_INT end_charpos,
+                    Lisp_Object disp_string,
                     struct glyph_row **start, struct glyph_row **end)
 {
   struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
@@ -25871,8 +25876,11 @@ rows_from_pos_range (struct window *w,
 
          while (g < e)
            {
-             if ((BUFFERP (g->object) || INTEGERP (g->object))
-                 && start_charpos <= g->charpos && g->charpos < end_charpos)
+             if (((BUFFERP (g->object) || INTEGERP (g->object))
+                  && start_charpos <= g->charpos && g->charpos < end_charpos)
+                 /* A glyph that comes from DISP_STRING is by
+                    definition to be highlighted.  */
+                 || EQ (g->object, disp_string))
                *start = row;
              g++;
            }
@@ -25891,14 +25899,15 @@ rows_from_pos_range (struct window *w,
   for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
     {
       struct glyph_row *next = row + 1;
+      EMACS_INT next_start = MATRIX_ROW_START_CHARPOS (next);
 
       if (!next->enabled_p
          || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
          /* The first row >= START whose range of displayed characters
             does NOT intersect the range [START_CHARPOS..END_CHARPOS]
             is the row END + 1.  */
-         || (start_charpos < MATRIX_ROW_START_CHARPOS (next)
-             && end_charpos < MATRIX_ROW_START_CHARPOS (next))
+         || (start_charpos < next_start
+             && end_charpos < next_start)
          || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
               || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
                   && !next->ends_at_zv_p
@@ -25917,12 +25926,29 @@ rows_from_pos_range (struct window *w,
             but none of the characters it displays are in the range, it is
             also END + 1. */
          struct glyph *g = next->glyphs[TEXT_AREA];
+         struct glyph *s = g;
          struct glyph *e = g + next->used[TEXT_AREA];
 
          while (g < e)
            {
-             if ((BUFFERP (g->object) || INTEGERP (g->object))
-                 && start_charpos <= g->charpos && g->charpos < end_charpos)
+             if (((BUFFERP (g->object) || INTEGERP (g->object))
+                  && ((start_charpos <= g->charpos && g->charpos < end_charpos)
+                      /* If the buffer position of the first glyph in
+                         the row is equal to END_CHARPOS, it means
+                         the last character to be highlighted is the
+                         newline of ROW, and we must consider NEXT as
+                         END, not END+1.  */
+                      || (((!next->reversed_p && g == s)
+                           || (next->reversed_p && g == e - 1))
+                          && (g->charpos == end_charpos
+                              /* Special case for when NEXT is an
+                                 empty line at ZV.  */
+                              || (g->charpos == -1
+                                  && !row->ends_at_zv_p
+                                  && next_start == end_charpos)))))
+                 /* A glyph that comes from DISP_STRING is by
+                    definition to be highlighted.  */
+                 || EQ (g->object, disp_string))
                break;
              g++;
            }
@@ -25931,6 +25957,13 @@ rows_from_pos_range (struct window *w,
              *end = row;
              break;
            }
+         /* The first row that ends at ZV must be the last to be
+            highlighted.  */
+         else if (next->ends_at_zv_p)
+           {
+             *end = next;
+             break;
+           }
        }
     }
 }
@@ -25966,7 +25999,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
   xassert (NILP (after_string) || STRINGP (after_string));
 
   /* Find the rows corresponding to START_CHARPOS and END_CHARPOS.  */
-  rows_from_pos_range (w, start_charpos, end_charpos, &r1, &r2);
+  rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
   if (r1 == NULL)
     r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
   /* If the before-string or display-string contains newlines,
@@ -26244,6 +26277,19 @@ mouse_face_from_buffer_pos (Lisp_Object window,
            }
          x += end->pixel_width;
        }
+      /* If we exited the above loop because we arrived at the last
+        glyph of the row, and its buffer position is still not in
+        range, it means the last character in range is the preceding
+        newline.  Bump the end column and x values to get past the
+        last glyph.  */
+      if (end == glyph
+         && BUFFERP (end->object)
+         && (end->charpos < start_charpos
+             || end->charpos >= end_charpos))
+       {
+         x += end->pixel_width;
+         ++end;
+       }
       hlinfo->mouse_face_end_x = x;
       hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
     }
@@ -28322,7 +28368,11 @@ all the functions in the list are called, with the frame as argument.  */);
 Each function is called with two arguments, the window and its new
 display-start position.  Note that these functions are also called by
 `set-window-buffer'.  Also note that the value of `window-end' is not
-valid when these functions are called.  */);
+valid when these functions are called.
+
+Warning: Do not use this feature to alter the way the window
+is scrolled.  It is not designed for that, and such use probably won't
+work.  */);
   Vwindow_scroll_functions = Qnil;
 
   DEFVAR_LISP ("window-text-change-functions",