]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Update copyright year to 2015
[gnu-emacs] / src / xdisp.c
index 0d314688c2655a56d0fbe341e43271b140ca09ff..aa5bfcbcbe423bdaf1336aa5ddca3216657b4055 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2015 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -347,7 +347,7 @@ Lisp_Object Qtext;
 /* Holds the list (error).  */
 static Lisp_Object list_of_error;
 
-static Lisp_Object Qfontification_functions;
+Lisp_Object Qfontification_functions;
 
 static Lisp_Object Qwrap_prefix;
 static Lisp_Object Qline_prefix;
@@ -905,7 +905,7 @@ static void iterate_out_of_display_property (struct it *);
 static void pop_it (struct it *);
 static void sync_frame_with_window_matrix_rows (struct window *);
 static void redisplay_internal (void);
-static int echo_area_display (int);
+static bool echo_area_display (bool);
 static void redisplay_windows (Lisp_Object);
 static void redisplay_window (Lisp_Object, bool);
 static Lisp_Object redisplay_window_error (Lisp_Object);
@@ -1406,6 +1406,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   struct text_pos top;
   int visible_p = 0;
   struct buffer *old_buffer = NULL;
+  bool r2l = false;
 
   if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
@@ -1691,6 +1692,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
          *rowh = max (0, (min (bottom_y, it.last_visible_y)
                           - max (top_y, window_top_y)));
          *vpos = it.vpos;
+         if (it.bidi_it.paragraph_dir == R2L)
+           r2l = true;
        }
     }
   else
@@ -1720,6 +1723,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                           - max (it2.current_y,
                                  WINDOW_HEADER_LINE_HEIGHT (w))));
          *vpos = it2.vpos;
+         if (it2.bidi_it.paragraph_dir == R2L)
+           r2l = true;
        }
       else
        bidi_unshelve_cache (it2data, 1);
@@ -1729,10 +1734,20 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
 
-  if (visible_p && w->hscroll > 0)
-    *x -=
-      window_hscroll_limited (w, WINDOW_XFRAME (w))
-      * WINDOW_FRAME_COLUMN_WIDTH (w);
+  if (visible_p)
+    {
+      if (w->hscroll > 0)
+       *x -=
+         window_hscroll_limited (w, WINDOW_XFRAME (w))
+         * WINDOW_FRAME_COLUMN_WIDTH (w);
+      /* For lines in an R2L paragraph, we need to mirror the X pixel
+         coordinate wrt the text area.  For the reasons, see the
+         commentary in buffer_posn_from_coords and the explanation of
+         the geometry used by the move_it_* functions at the end of
+         the large commentary near the beginning of this file.  */
+      if (r2l)
+       *x = window_box_width (w, TEXT_AREA) - *x - 1;
+    }
 
 #if 0
   /* Debugging code.  */
@@ -7332,27 +7347,15 @@ set_iterator_to_next (struct it *it, int reseat_p)
       else if (it->cmp_it.id >= 0)
        {
          /* We are currently getting glyphs from a composition.  */
-         int i;
-
          if (! it->bidi_p)
            {
              IT_CHARPOS (*it) += it->cmp_it.nchars;
              IT_BYTEPOS (*it) += it->cmp_it.nbytes;
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               {
-                 it->cmp_it.from = it->cmp_it.to;
-               }
-             else
-               {
-                 it->cmp_it.id = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it),
-                                               it->end_charpos, Qnil);
-               }
            }
-         else if (! it->cmp_it.reversed_p)
+         else
            {
-             /* Composition created while scanning forward.  */
+             int i;
+
              /* Update IT's char/byte positions to point to the first
                 character of the next grapheme cluster, or to the
                 character visually after the current composition.  */
@@ -7360,52 +7363,34 @@ set_iterator_to_next (struct it *it, int reseat_p)
                bidi_move_to_visually_next (&it->bidi_it);
              IT_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_CHARPOS (*it) = it->bidi_it.charpos;
+           }
 
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               {
-                 /* Proceed to the next grapheme cluster.  */
-                 it->cmp_it.from = it->cmp_it.to;
-               }
-             else
-               {
-                 /* No more grapheme clusters in this composition.
-                    Find the next stop position.  */
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   /* Now we are scanning backward and don't know
-                      where to stop.  */
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it), stop, Qnil);
-               }
+         if ((! it->bidi_p || ! it->cmp_it.reversed_p)
+             && it->cmp_it.to < it->cmp_it.nglyphs)
+           {
+             /* Composition created while scanning forward.  Proceed
+                to the next grapheme cluster.  */
+             it->cmp_it.from = it->cmp_it.to;
+           }
+         else if ((it->bidi_p && it->cmp_it.reversed_p)
+                  && it->cmp_it.from > 0)
+           {
+             /* Composition created while scanning backward.  Proceed
+                to the previous grapheme cluster.  */
+             it->cmp_it.to = it->cmp_it.from;
            }
          else
            {
-             /* Composition created while scanning backward.  */
-             /* Update IT's char/byte positions to point to the last
-                character of the previous grapheme cluster, or the
-                character visually after the current composition.  */
-             for (i = 0; i < it->cmp_it.nchars; i++)
-               bidi_move_to_visually_next (&it->bidi_it);
-             IT_BYTEPOS (*it) = it->bidi_it.bytepos;
-             IT_CHARPOS (*it) = it->bidi_it.charpos;
-             if (it->cmp_it.from > 0)
-               {
-                 /* Proceed to the previous grapheme cluster.  */
-                 it->cmp_it.to = it->cmp_it.from;
-               }
-             else
-               {
-                 /* No more grapheme clusters in this composition.
-                    Find the next stop position.  */
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   /* Now we are scanning backward and don't know
-                      where to stop.  */
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it), stop, Qnil);
-               }
+             /* No more grapheme clusters in this composition.
+                Find the next stop position.  */
+             ptrdiff_t stop = it->end_charpos;
+
+             if (it->bidi_it.scan_dir < 0)
+               /* Now we are scanning backward and don't know
+                  where to stop.  */
+               stop = -1;
+             composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
+                                           IT_BYTEPOS (*it), stop, Qnil);
            }
        }
       else
@@ -7534,61 +7519,63 @@ set_iterator_to_next (struct it *it, int reseat_p)
        }
       if (it->cmp_it.id >= 0)
        {
-         int i;
-
+         /* We are delivering display elements from a composition.
+            Update the string position past the grapheme cluster
+            we've just processed.  */
          if (! it->bidi_p)
            {
              IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
              IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               it->cmp_it.from = it->cmp_it.to;
-             else
-               {
-                 it->cmp_it.id = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it),
-                                               it->end_charpos, it->string);
-               }
            }
-         else if (! it->cmp_it.reversed_p)
+         else
            {
+             int i;
+
              for (i = 0; i < it->cmp_it.nchars; i++)
                bidi_move_to_visually_next (&it->bidi_it);
              IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+           }
 
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               it->cmp_it.from = it->cmp_it.to;
-             else
-               {
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it), stop,
-                                               it->string);
-               }
+         /* Did we exhaust all the grapheme clusters of this
+            composition?  */
+         if ((! it->bidi_p || ! it->cmp_it.reversed_p)
+             && (it->cmp_it.to < it->cmp_it.nglyphs))
+           {
+             /* Not all the grapheme clusters were processed yet;
+                advance to the next cluster.  */
+             it->cmp_it.from = it->cmp_it.to;
+           }
+         else if ((it->bidi_p && it->cmp_it.reversed_p)
+                  && it->cmp_it.from > 0)
+           {
+             /* Likewise: advance to the next cluster, but going in
+                the reverse direction.  */
+             it->cmp_it.to = it->cmp_it.from;
            }
          else
            {
-             for (i = 0; i < it->cmp_it.nchars; i++)
-               bidi_move_to_visually_next (&it->bidi_it);
-             IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
-             IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
-             if (it->cmp_it.from > 0)
-               it->cmp_it.to = it->cmp_it.from;
-             else
+             /* This composition was fully processed; find the next
+                candidate place for checking for composed
+                characters.  */
+             /* Always limit string searches to the string length;
+                any padding spaces are not part of the string, and
+                there cannot be any compositions in that padding.  */
+             ptrdiff_t stop = SCHARS (it->string);
+
+             if (it->bidi_p && it->bidi_it.scan_dir < 0)
+               stop = -1;
+             else if (it->end_charpos < stop)
                {
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it), stop,
-                                               it->string);
+                 /* Cf. PRECISION in reseat_to_string: we might be
+                    limited in how many of the string characters we
+                    need to deliver.  */
+                 stop = it->end_charpos;
                }
+             composition_compute_stop_pos (&it->cmp_it,
+                                           IT_STRING_CHARPOS (*it),
+                                           IT_STRING_BYTEPOS (*it), stop,
+                                           it->string);
            }
        }
       else
@@ -7611,12 +7598,17 @@ set_iterator_to_next (struct it *it, int reseat_p)
              bidi_move_to_visually_next (&it->bidi_it);
              IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+             /* If the scan direction changes, we may need to update
+                the place where to check for composed characters.  */
              if (prev_scan_dir != it->bidi_it.scan_dir)
                {
-                 ptrdiff_t stop = it->end_charpos;
+                 ptrdiff_t stop = SCHARS (it->string);
 
                  if (it->bidi_it.scan_dir < 0)
                    stop = -1;
+                 else if (it->end_charpos < stop)
+                   stop = it->end_charpos;
+
                  composition_compute_stop_pos (&it->cmp_it,
                                                IT_STRING_CHARPOS (*it),
                                                IT_STRING_BYTEPOS (*it), stop,
@@ -8794,12 +8786,7 @@ move_it_in_display_line_to (struct it *it,
                         doesn't fit on the line, e.g. a wide image.  */
                      it->hpos == 0
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f)
-                         /* When word-wrap is ON and we have a valid
-                            wrap point, we don't allow the last glyph
-                            to "just barely fit" on the line.  */
-                         && (it->line_wrap != WORD_WRAP
-                             || wrap_it.sp < 0)))
+                         && FRAME_WINDOW_P (it->f)))
                    {
                      ++it->hpos;
                      it->current_x = new_x;
@@ -8866,7 +8853,8 @@ move_it_in_display_line_to (struct it *it,
                                }
                              if (ITERATOR_AT_END_OF_LINE_P (it)
                                  && (it->line_wrap != WORD_WRAP
-                                     || wrap_it.sp < 0))
+                                     || wrap_it.sp < 0
+                                     || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
                                {
                                  result = MOVE_NEWLINE_OR_CR;
                                  break;
@@ -10279,9 +10267,9 @@ message3_nolog (Lisp_Object m)
       else
        clear_message (true, true);
 
-      do_pending_window_change (0);
-      echo_area_display (1);
-      do_pending_window_change (0);
+      do_pending_window_change (false);
+      echo_area_display (true);
+      do_pending_window_change (false);
       if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
@@ -11252,13 +11240,13 @@ clear_garbaged_frames (void)
    is non-zero update selected_frame.  Value is non-zero if the
    mini-windows height has been changed.  */
 
-static int
-echo_area_display (int update_frame_p)
+static bool
+echo_area_display (bool update_frame_p)
 {
   Lisp_Object mini_window;
   struct window *w;
   struct frame *f;
-  int window_height_changed_p = 0;
+  bool window_height_changed_p = false;
   struct frame *sf = SELECTED_FRAME ();
 
   mini_window = FRAME_MINIBUF_WINDOW (sf);
@@ -11321,11 +11309,11 @@ echo_area_display (int update_frame_p)
              /* Window configuration is the same as before.
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
-             update_single_window (w, 1);
+             update_single_window (w);
              flush_frame (f);
            }
          else
-           update_frame (f, 1, 1);
+           update_frame (f, true, true);
 
          /* If cursor is in the echo area, make sure that the next
             redisplay displays the minibuffer, so that the cursor will
@@ -13439,7 +13427,7 @@ redisplay_internal (void)
   struct window *w = XWINDOW (selected_window);
   struct window *sw;
   struct frame *fr;
-  int pending;
+  bool pending;
   bool must_finish = 0, match_p;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
@@ -13499,7 +13487,7 @@ redisplay_internal (void)
   /* Remember the currently selected window.  */
   sw = w;
 
-  pending = 0;
+  pending = false;
   last_escape_glyph_frame = NULL;
   last_escape_glyph_face_id = (1 << FACE_ID_BITS);
   last_glyphless_glyph_frame = NULL;
@@ -13551,7 +13539,7 @@ redisplay_internal (void)
     }
 
   /* Notice any pending interrupt request to change frame size.  */
-  do_pending_window_change (1);
+  do_pending_window_change (true);
 
   /* do_pending_window_change could change the selected_window due to
      frame resizing which makes the selected window too small.  */
@@ -13598,7 +13586,7 @@ redisplay_internal (void)
             echo-area doesn't show through.  */
          && !MINI_WINDOW_P (XWINDOW (selected_window))))
     {
-      int window_height_changed_p = echo_area_display (0);
+      int window_height_changed_p = echo_area_display (false);
 
       if (message_cleared_p)
        update_miniwindow_p = true;
@@ -13806,7 +13794,7 @@ redisplay_internal (void)
        {
          if (!must_finish)
            {
-             do_pending_window_change (1);
+             do_pending_window_change (true);
              /* If selected_window changed, redisplay again.  */
              if (WINDOWP (selected_window)
                  && (w = XWINDOW (selected_window)) != sw)
@@ -13923,14 +13911,14 @@ redisplay_internal (void)
                  if (f->fonts_changed)
                    {
                      adjust_frame_glyphs (f);
-                     f->fonts_changed = 0;
+                     f->fonts_changed = false;
                      goto retry_frame;
                    }
 
                  /* See if we have to hscroll.  */
                  if (!f->already_hscrolled_p)
                    {
-                     f->already_hscrolled_p = 1;
+                     f->already_hscrolled_p = true;
                      if (hscroll_windows (f->root_window))
                        goto retry_frame;
                    }
@@ -13942,9 +13930,9 @@ redisplay_internal (void)
                    unrequest_sigio ();
                  STOP_POLLING;
 
-                 pending |= update_frame (f, 0, 0);
-                 f->cursor_type_changed = 0;
-                 f->updated_p = 1;
+                 pending |= update_frame (f, false, false);
+                 f->cursor_type_changed = false;
+                 f->updated_p = true;
                }
            }
        }
@@ -14005,8 +13993,8 @@ redisplay_internal (void)
            goto retry;
 
          XWINDOW (selected_window)->must_be_updated_p = true;
-         pending = update_frame (sf, 0, 0);
-         sf->cursor_type_changed = 0;
+         pending = update_frame (sf, false, false);
+         sf->cursor_type_changed = false;
        }
 
       /* We may have called echo_area_display at the top of this
@@ -14020,8 +14008,8 @@ redisplay_internal (void)
       if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
        {
          XWINDOW (mini_window)->must_be_updated_p = true;
-         pending |= update_frame (mini_frame, 0, 0);
-         mini_frame->cursor_type_changed = 0;
+         pending |= update_frame (mini_frame, false, false);
+         mini_frame->cursor_type_changed = false;
          if (!pending && hscroll_windows (mini_window))
            goto retry;
        }
@@ -14098,7 +14086,7 @@ redisplay_internal (void)
     }
 
   /* Change frame size now if a change is pending.  */
-  do_pending_window_change (1);
+  do_pending_window_change (true);
 
   /* If we just did a pending size change, or have additional
      visible frames, or selected_window changed, redisplay again.  */
@@ -14114,7 +14102,7 @@ redisplay_internal (void)
 
   if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
     {
-      clear_face_cache (0);
+      clear_face_cache (false);
       clear_face_cache_count = 0;
     }
 
@@ -14158,9 +14146,9 @@ redisplay_preserve_echo_area (int from_where)
     {
       /* We have a previously displayed message, but no current
         message.  Redisplay the previous message.  */
-      display_last_displayed_message_p = 1;
+      display_last_displayed_message_p = true;
       redisplay_internal ();
-      display_last_displayed_message_p = 0;
+      display_last_displayed_message_p = false;
     }
   else
     redisplay_internal ();
@@ -20438,7 +20426,8 @@ display_line (struct it *it)
                        {
                          /* If line-wrap is on, check if a previous
                             wrap point was found.  */
-                         if (wrap_row_used > 0
+                         if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
+                             && wrap_row_used > 0
                              /* Even if there is a previous wrap
                                 point, continue the line here as
                                 usual, if (i) the previous character
@@ -20468,6 +20457,18 @@ display_line (struct it *it)
                                  row->continued_p = 0;
                                  row->exact_window_width_line_p = 1;
                                }
+                             /* If line-wrap is on, check if a
+                                previous wrap point was found.  */
+                             else if (wrap_row_used > 0
+                                      /* Even if there is a previous wrap
+                                         point, continue the line here as
+                                         usual, if (i) the previous character
+                                         was a space or tab AND (ii) the
+                                         current character is not.  */
+                                      && (!may_wrap
+                                          || IT_DISPLAYING_WHITESPACE (it)))
+                               goto back_to_wrap;
+
                            }
                        }
                      else if (it->bidi_p)