]> git.eshelyaron.com Git - emacs.git/commitdiff
(Voverflow_newline_into_fringe): New variable.
authorKim F. Storm <storm@cua.dk>
Fri, 16 Jan 2004 18:47:20 +0000 (18:47 +0000)
committerKim F. Storm <storm@cua.dk>
Fri, 16 Jan 2004 18:47:20 +0000 (18:47 +0000)
(IT_OVERFLOW_NEWLINE_INTO_FRINGE): New macro.
(move_it_in_display_line_to): Overflow newline into fringe for
rows that are exactly as wide as the window.
(up_arrow_bits, down_arrow_bits, first_line_bits, last_line_bits)
(filled_box_cursor_bits, hollow_box_cursor_bits, bar_cursor_bits)
(hbar_cursor_bits, hollow_square_bits): New fringe bitmaps.
(fringe_bitmaps): Add new bitmaps.
(draw_fringe_bitmap): Make extern.  Remove WHICH arg.
Select proper bitmap for cursor in fringe when appropriate.
Handle alignment of bitmap to top or bottom of row.
(draw_row_fringe_bitmaps): Don't select bitmaps here; that is now
done by update_window_fringes.
(update_window_fringes, draw_window_fringes): New functions.
(redisplay_internal): Call update_window_fringes in case only
cursor row is updated.
(redisplay_window): Call update_window_fringes.
Explicitly call draw_window_fringes if redisplay was done using
the current matrix or the overlay arrow is in the window.
(try_window_reusing_current_matrix): Mark scrolled rows for
fringe update (to update buffer-boundaries / scrolling icons).
(find_last_unchanged_at_beg_row): Handle exact width lines line
continued lines.
(display_line): Overflow newline into fringe for rows that are
exactly as wide as the window.  Don't append space for newline
in this case.
(notice_overwritten_cursor): Explicitly clear cursor bitmap
in fringe as if it had been overwritten.
(erase_phys_cursor): Erase cursor bitmap in fringe.
(syms_of_xdisp): Mark show-trailing-whitespace and
void-text-area-pointer as user options.
DEFVAR_LISP Voverflow_newline_into_fringe.  Enable by default.

src/xdisp.c

index 20ec887bd60d7eb301a341cfe5ff88d011bdc38b..11d48c90ea07beab5a11e0bbdaad42068d2c5b61 100644 (file)
@@ -310,6 +310,19 @@ extern Lisp_Object Qscroll_bar;
 
 Lisp_Object Vshow_trailing_whitespace;
 
+/* Non-nil means that newline may flow into the right fringe.  */
+
+Lisp_Object Voverflow_newline_into_fringe;
+
+/* Test if overflow newline into fringe.  Called with iterator IT
+   at or past right window margin, and with IT->current_x set.  */ 
+
+#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it)    \
+  (!NILP (Voverflow_newline_into_fringe)       \
+   && FRAME_WINDOW_P (it->f)                   \
+   && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0    \
+   && it->current_x == it->last_visible_x)
+
 /* Non-nil means show the text cursor in void text areas
    i.e. in blank areas after eol and eob.  This used to be
    the default in 21.3.  */
@@ -5594,7 +5607,18 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                      ++it->hpos;
                      it->current_x = new_x;
                      if (i == it->nglyphs - 1)
-                       set_iterator_to_next (it, 1);
+                       {
+                         set_iterator_to_next (it, 1);
+                         if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                           {
+                             get_next_display_element (it);
+                             if (ITERATOR_AT_END_OF_LINE_P (it))
+                               {
+                                 result = MOVE_NEWLINE_OR_CR;
+                                 break;
+                               }
+                           }
+                       }
                    }
                  else
                    {
@@ -5651,6 +5675,15 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
       if (it->truncate_lines_p
          && it->current_x >= it->last_visible_x)
        {
+         if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+           {
+             get_next_display_element (it);
+             if (ITERATOR_AT_END_OF_LINE_P (it))
+               {
+                 result = MOVE_NEWLINE_OR_CR;
+                 break;
+               }
+           }
          result = MOVE_LINE_TRUNCATED;
          break;
        }
@@ -8899,26 +8932,205 @@ note_tool_bar_highlight (f, x, y)
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+/* Notice that all bitmaps bits are "mirrored".  */
+
 /* An arrow like this: `<-'.  */
+/*
+  ...xx...
+  ....xx..
+  .....xx.
+  ..xxxxxx
+  ..xxxxxx
+  .....xx.
+  ....xx..
+  ...xx...
+*/
 static unsigned char left_bits[] = {
    0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
 
+
 /* Right truncation arrow bitmap `->'.  */
+/*
+  ...xx...
+  ..xx....
+  .xx.....
+  xxxxxx..
+  xxxxxx..
+  .xx.....
+  ..xx....
+  ...xx...
+*/
 static unsigned char right_bits[] = {
    0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
 
+
+/* Up arrow bitmap.  */
+/*
+  ...xx...
+  ..xxxx..
+  .xxxxxx.
+  xxxxxxxx
+  ...xx...
+  ...xx...
+  ...xx...
+  ...xx...
+*/
+static unsigned char up_arrow_bits[] = {
+   0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
+
+
+/* Down arrow bitmap.  */
+/*
+  ...xx...
+  ...xx...
+  ...xx...
+  ...xx...
+  xxxxxxxx
+  .xxxxxx.
+  ..xxxx..
+  ...xx...
+*/
+static unsigned char down_arrow_bits[] = {
+   0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
+
 /* Marker for continued lines.  */
+/*
+  ..xxxx..
+  .xxxxx..
+  xx......
+  xxx..x..
+  xxxxxx..
+  .xxxxx..
+  ..xxxx..
+  .xxxxx..
+*/
 static unsigned char continued_bits[] = {
    0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
 
 /* Marker for continuation lines.  */
+/*
+  ..xxxx..
+  ..xxxxx.
+  ......xx
+  ..x..xxx
+  ..xxxxxx
+  ..xxxxx.
+  ..xxxx..
+  ..xxxxx.
+*/
 static unsigned char continuation_bits[] = {
    0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
 
 /* Overlay arrow bitmap.  A triangular arrow.  */
+/*
+  ......xx
+  ....xxxx
+  ...xxxxx
+  ..xxxxxx
+  ..xxxxxx
+  ...xxxxx
+  ....xxxx
+  ......xx
+*/
 static unsigned char ov_bits[] = {
    0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
 
+
+/* First line bitmap.  An left-up angle.  */
+/*
+  ..xxxxxx
+  ..xxxxxx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ........
+*/
+static unsigned char first_line_bits[] = {
+   0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
+
+
+/* Last line bitmap.  An left-down angle.  */
+/*
+  ........
+  xx......
+  xx......
+  xx......
+  xx......
+  xx......
+  xxxxxx..
+  xxxxxx..
+*/
+static unsigned char last_line_bits[] = {
+   0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
+
+/* Filled box cursor bitmap.  A filled box; max 13 pixels high.  */
+/*
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+  .xxxxxxx
+*/
+static unsigned char filled_box_cursor_bits[] = {
+   0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f};
+
+/* Hollow box cursor bitmap.  A hollow box; max 13 pixels high.  */
+/*
+  .xxxxxxx
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .x.....x
+  .xxxxxxx
+*/
+static unsigned char hollow_box_cursor_bits[] = {
+   0x7f, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7f};
+
+/* Bar cursor bitmap.  A vertical bar; max 13 pixels high.  */
+/*
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+  ......xx
+*/
+static unsigned char bar_cursor_bits[] = {
+   0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+
+/* HBar cursor bitmap.  A horisontal bar; 2 pixels high.  */
+/*
+  .xxxxxxx
+  .xxxxxxx
+*/
+static unsigned char hbar_cursor_bits[] = {
+  0x7f, 0x7f};
+
+
 /* Bitmap drawn to indicate lines not displaying text if
    `indicate-empty-lines' is non-nil.  */
 static unsigned char zv_bits[] = {
@@ -8931,32 +9143,89 @@ static unsigned char zv_bits[] = {
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
 
+/* Hollow square bitmap.  */
+/*
+  .xxxxxx.
+  .x....x.
+  .x....x.
+  .x....x.
+  .x....x.
+  .xxxxxx.
+*/
+static unsigned char hollow_square_bits[] = {
+   0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
+
+
 struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] =
 {
   { 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ },
   { 8, sizeof (left_bits), 0, left_bits },
   { 8, sizeof (right_bits), 0, right_bits },
+  { 8, sizeof (up_arrow_bits), -1, up_arrow_bits },
+  { 8, sizeof (down_arrow_bits), -2, down_arrow_bits },
   { 8, sizeof (continued_bits), 0, continued_bits },
   { 8, sizeof (continuation_bits), 0, continuation_bits },
   { 8, sizeof (ov_bits), 0, ov_bits },
-  { 8, sizeof (zv_bits), 3, zv_bits }
+  { 8, sizeof (first_line_bits), -1, first_line_bits },
+  { 8, sizeof (last_line_bits), -2, last_line_bits },
+  { 8, sizeof (filled_box_cursor_bits), 0, filled_box_cursor_bits },
+  { 8, sizeof (hollow_box_cursor_bits), 0, hollow_box_cursor_bits },
+  { 8, sizeof (bar_cursor_bits), 0, bar_cursor_bits },
+  { 8, sizeof (hbar_cursor_bits), -2, hbar_cursor_bits },
+  { 8, sizeof (zv_bits), 3, zv_bits },
+  { 8, sizeof (hollow_square_bits), 0, hollow_square_bits },
 };
 
 
 /* Draw the bitmap WHICH in one of the left or right fringes of
    window W.  ROW is the glyph row for which to display the bitmap; it
    determines the vertical position at which the bitmap has to be
-   drawn.  */
+   drawn.
+   LEFT_P is 1 for left fringe, 0 for right fringe.
+*/
 
-static void
-draw_fringe_bitmap (w, row, which, left_p)
+void
+draw_fringe_bitmap (w, row, left_p)
      struct window *w;
      struct glyph_row *row;
-     enum fringe_bitmap_type which;
      int left_p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct draw_fringe_bitmap_params p;
+  enum fringe_bitmap_type which;
+  int period;
+
+  if (left_p)
+    which = row->left_fringe_bitmap;
+  else if (!row->cursor_in_fringe_p)
+    which = row->right_fringe_bitmap;
+  else
+    switch (w->phys_cursor_type)
+      {
+      case HOLLOW_BOX_CURSOR:
+       if (row->visible_height >= sizeof(hollow_box_cursor_bits))
+         which = HOLLOW_BOX_CURSOR_BITMAP;
+       else
+         which = HOLLOW_SQUARE_BITMAP;
+       break;
+      case FILLED_BOX_CURSOR:
+       which = FILLED_BOX_CURSOR_BITMAP;
+       break;
+      case BAR_CURSOR:
+       which = BAR_CURSOR_BITMAP;
+       break;
+      case HBAR_CURSOR:
+       which = HBAR_CURSOR_BITMAP;
+       break;
+      case NO_CURSOR:
+      default:
+       w->phys_cursor_on_p = 0;
+       row->cursor_in_fringe_p = 0;
+       which = row->right_fringe_bitmap;
+       break;
+      }
+
+  period = fringe_bitmaps[which].period;
 
   /* Convert row to frame coordinates.  */
   p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
@@ -8965,9 +9234,7 @@ draw_fringe_bitmap (w, row, which, left_p)
   p.wd = fringe_bitmaps[which].width;
 
   p.h = fringe_bitmaps[which].height;
-  p.dh = (fringe_bitmaps[which].period
-         ? (p.y % fringe_bitmaps[which].period)
-         : 0);
+  p.dh = (period > 0 ? (p.y % period) : 0);
   p.h -= p.dh;
   /* Clip bitmap if too high.  */
   if (p.h > row->height)
@@ -9027,7 +9294,13 @@ draw_fringe_bitmap (w, row, which, left_p)
     }
 
   /* Adjust y to the offset in the row to start drawing the bitmap.  */
-  p.y += (row->height - p.h) / 2;
+  if (period == 0)
+    p.y += (row->height - p.h) / 2;
+  else if (period == -2)
+    {
+      p.h = fringe_bitmaps[which].height;
+      p.y += (row->visible_height - p.h);
+    }
 
   rif->draw_fringe_bitmap (w, row, &p);
 }
@@ -9040,8 +9313,6 @@ draw_row_fringe_bitmaps (w, row)
      struct window *w;
      struct glyph_row *row;
 {
-  enum fringe_bitmap_type bitmap;
-
   xassert (interrupt_input_blocked);
 
   /* If row is completely invisible, because of vscrolling, we
@@ -9050,35 +9321,35 @@ draw_row_fringe_bitmaps (w, row)
     return;
 
   if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
-    {
-      /* Decide which bitmap to draw in the left fringe.  */
-      if (row->overlay_arrow_p)
-       bitmap = OVERLAY_ARROW_BITMAP;
-      else if (row->truncated_on_left_p)
-       bitmap = LEFT_TRUNCATION_BITMAP;
-      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
-       bitmap = CONTINUATION_LINE_BITMAP;
-      else if (row->indicate_empty_line_p)
-       bitmap = ZV_LINE_BITMAP;
-      else
-       bitmap = NO_FRINGE_BITMAP;
-
-      draw_fringe_bitmap (w, row, bitmap, 1);
-    }
+    draw_fringe_bitmap (w, row, 1);
 
   if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
-    {
-      /* Decide which bitmap to draw in the right fringe.  */
-      if (row->truncated_on_right_p)
-       bitmap = RIGHT_TRUNCATION_BITMAP;
-      else if (row->continued_p)
-       bitmap = CONTINUED_LINE_BITMAP;
-      else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
-       bitmap = ZV_LINE_BITMAP;
-      else
-       bitmap = NO_FRINGE_BITMAP;
+    draw_fringe_bitmap (w, row, 0);
+}
+
+/* Draw the fringes of window W.  Only fringes for rows marked for
+   update in redraw_fringe_bitmaps_p are drawn.  */
 
-      draw_fringe_bitmap (w, row, bitmap, 0);
+void
+draw_window_fringes (w)
+     struct window *w;
+{
+  struct glyph_row *row;
+  int yb = window_text_bottom_y (w);
+  int nrows = w->current_matrix->nrows;
+  int y = 0, rn;
+
+  if (w->pseudo_window_p)
+    return;
+
+  for (y = 0, rn = 0, row = w->current_matrix->rows;
+       y < yb && rn < nrows;
+       y += row->height, ++row, ++rn)
+    {
+      if (!row->redraw_fringe_bitmaps_p)
+       continue;
+      draw_row_fringe_bitmaps (w, row);
+      row->redraw_fringe_bitmaps_p = 0;
     }
 }
 
@@ -9986,6 +10257,7 @@ redisplay_internal (preserve_echo_area)
              *w->desired_matrix->method = 0;
              debug_method_add (w, "optimization 1");
 #endif
+             update_window_fringes (w, 0);
              goto update;
            }
          else
@@ -11396,6 +11668,135 @@ set_vertical_scroll_bar (w)
   set_vertical_scroll_bar_hook (w, end - start, whole, start);
 }
 
+
+/* Recalculate the bitmaps to show in the fringes of window W.
+   If FORCE_P is 0, only mark rows with modified bitmaps for update in
+   redraw_fringe_bitmaps_p; else mark all rows for update.  */
+
+int
+update_window_fringes (w, force_p)
+     struct window *w;
+     int force_p;
+{
+  struct glyph_row *row, *cur = 0;
+  int yb = window_text_bottom_y (w);
+  int rn, nrows = w->current_matrix->nrows;
+  int y;
+  int redraw_p = 0;
+  Lisp_Object ind;
+
+  if (w->pseudo_window_p)
+    return 0;
+
+  if (!MINI_WINDOW_P (w)
+      && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
+    {
+      int do_eob = 1, do_bob = 1;
+
+      for (y = 0, rn = 0;
+          y < yb && rn < nrows;
+          y += row->height, ++rn)
+       {
+         unsigned indicate_bob_p, indicate_top_line_p;
+         unsigned indicate_eob_p, indicate_bottom_line_p;
+         
+         row = w->desired_matrix->rows + rn;
+         if (!row->enabled_p)
+           row = w->current_matrix->rows + rn;
+
+         indicate_bob_p = row->indicate_bob_p;
+         indicate_top_line_p = row->indicate_top_line_p;
+         indicate_eob_p = row->indicate_eob_p;
+         indicate_bottom_line_p = row->indicate_bottom_line_p;
+         
+         row->indicate_bob_p = row->indicate_top_line_p = 0;
+         row->indicate_eob_p = row->indicate_bottom_line_p = 0;
+
+         if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
+           row->indicate_bob_p = do_bob, do_bob = 0;
+         else if (EQ (ind, Qt)
+                  && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
+           row->indicate_top_line_p = 1;
+
+         if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
+           row->indicate_eob_p = do_eob, do_eob = 0;
+         else if (EQ (ind, Qt)
+                  && y + row->height >= yb)
+           row->indicate_bottom_line_p = 1;
+
+         if (indicate_bob_p != row->indicate_bob_p
+             || indicate_top_line_p != row->indicate_top_line_p
+             || indicate_eob_p != row->indicate_eob_p
+             || indicate_bottom_line_p != row->indicate_bottom_line_p)
+           row->redraw_fringe_bitmaps_p = 1;
+       }
+    }
+
+  for (y = 0, rn = 0;
+       y < yb && rn < nrows;
+       y += row->height, rn++)
+    {
+      enum fringe_bitmap_type left, right;
+
+      row = w->desired_matrix->rows + rn;
+      cur = w->current_matrix->rows + rn;
+      if (!row->enabled_p)
+       row = cur;
+
+      /* Decide which bitmap to draw in the left fringe.  */
+      if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
+       left = NO_FRINGE_BITMAP;
+      else if (row->overlay_arrow_p)
+       left = OVERLAY_ARROW_BITMAP;
+      else if (row->truncated_on_left_p)
+       left = LEFT_TRUNCATION_BITMAP;
+      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+       left = CONTINUATION_LINE_BITMAP;
+      else if (row->indicate_empty_line_p)
+       left = ZV_LINE_BITMAP;
+      else if (row->indicate_bob_p)
+       left = FIRST_LINE_BITMAP;
+      else
+       left = NO_FRINGE_BITMAP;
+
+      /* Decide which bitmap to draw in the right fringe.  */
+      if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
+       right = NO_FRINGE_BITMAP;
+      else if (row->truncated_on_right_p)
+       right = RIGHT_TRUNCATION_BITMAP;
+      else if (row->continued_p)
+       right = CONTINUED_LINE_BITMAP;
+      else if (row->indicate_eob_p)
+       right = LAST_LINE_BITMAP;
+      else if (row->indicate_top_line_p) 
+       right = UP_ARROW_BITMAP;
+      else if (row->indicate_bottom_line_p)
+       right = DOWN_ARROW_BITMAP;
+      else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
+       right = ZV_LINE_BITMAP;
+      else
+       right = NO_FRINGE_BITMAP;
+
+      if (force_p
+         || row->y != cur->y
+         || row->visible_height != cur->visible_height
+         || left != cur->left_fringe_bitmap
+         || right != cur->right_fringe_bitmap
+         || cur->redraw_fringe_bitmaps_p)
+       {
+         redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
+         cur->left_fringe_bitmap = left;
+         cur->right_fringe_bitmap = right;
+       }
+
+      row->left_fringe_bitmap = left;
+      row->right_fringe_bitmap = right;
+    }
+
+  return redraw_p;
+}
+
+
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
    selected_window is redisplayed.
 
@@ -11418,6 +11819,7 @@ redisplay_window (window, just_this_one_p)
   struct it it;
   /* Record it now because it's overwritten.  */
   int current_matrix_up_to_date_p = 0;
+  int used_current_matrix_p = 0;
   /* This is less strict than current_matrix_up_to_date_p.
      It indictes that the buffer contents and narrowing are unchanged.  */
   int buffer_unchanged_p = 0;
@@ -11724,6 +12126,7 @@ redisplay_window (window, just_this_one_p)
       switch (rc)
        {
        case CURSOR_MOVEMENT_SUCCESS:
+         used_current_matrix_p = 1;
          goto done;
 
 #if 0  /* try_cursor_movement never returns this value.  */
@@ -11788,7 +12191,8 @@ redisplay_window (window, just_this_one_p)
             buffer.  */
          || !NILP (Vwindow_scroll_functions)
          || MINI_WINDOW_P (w)
-         || !try_window_reusing_current_matrix (w))
+         || !(used_current_matrix_p =
+              try_window_reusing_current_matrix (w)))
        {
          IF_DEBUG (debug_method_add (w, "1"));
          try_window (window, startp);
@@ -11917,7 +12321,8 @@ redisplay_window (window, just_this_one_p)
       || !NILP (Vwindow_scroll_functions)
       || !just_this_one_p
       || MINI_WINDOW_P (w)
-      || !try_window_reusing_current_matrix (w))
+      || !(used_current_matrix_p =
+          try_window_reusing_current_matrix (w)))
     try_window (window, startp);
 
   /* If new fonts have been loaded (due to fontsets), give up.  We
@@ -12079,6 +12484,17 @@ redisplay_window (window, just_this_one_p)
 #endif
     }
 
+  if (update_window_fringes (w, 0)
+      && (used_current_matrix_p || overlay_arrow_seen)
+      && !w->pseudo_window_p)
+    {
+      update_begin (f);
+      BLOCK_INPUT;
+      draw_window_fringes (w);
+      UNBLOCK_INPUT;
+      update_end (f);
+    }
+
   /* We go to this label, with fonts_changed_p nonzero,
      if it is necessary to try again using larger glyph matrices.
      We have to redeem the scroll bar even in this case,
@@ -12335,6 +12751,7 @@ try_window_reusing_current_matrix (w)
                row->visible_height -= min_y - row->y;
              if (row->y + row->height > max_y)
                row->visible_height -= row->y + row->height - max_y;
+             row->redraw_fringe_bitmaps_p = 1;
 
              it.current_y += row->height;
 
@@ -12474,7 +12891,6 @@ try_window_reusing_current_matrix (w)
 
       if (run.height)
        {
-         struct frame *f = XFRAME (WINDOW_FRAME (w));
          update_begin (f);
          rif->update_window_begin_hook (w);
          rif->clear_window_mouse_face (w);
@@ -12495,6 +12911,7 @@ try_window_reusing_current_matrix (w)
            row->visible_height -= min_y - row->y;
          if (row->y + row->height > max_y)
            row->visible_height -= row->y + row->height - max_y;
+         row->redraw_fringe_bitmaps_p = 1;
        }
 
       /* Scroll the current matrix.  */
@@ -12617,7 +13034,8 @@ find_last_unchanged_at_beg_row (w)
             row is not unchanged because it may be no longer
             continued.  */
          && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
-              && row->continued_p))
+              && (row->continued_p
+                  || row->exact_window_width_line_p)))
        row_found = row;
 
       /* Stop if last visible row.  */
@@ -14513,7 +14931,18 @@ display_line (it)
                      it->continuation_lines_width += new_x;
                      ++it->hpos;
                      if (i == nglyphs - 1)
-                       set_iterator_to_next (it, 1);
+                       {
+                         set_iterator_to_next (it, 1);
+                         if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                           {
+                             get_next_display_element (it);
+                             if (ITERATOR_AT_END_OF_LINE_P (it))
+                               {
+                                 row->continued_p = 0;
+                                 row->exact_window_width_line_p = 1;
+                               }
+                           }
+                       }
                    }
                  else if (CHAR_GLYPH_PADDING_P (*glyph)
                           && !FRAME_WINDOW_P (it->f))
@@ -14615,6 +15044,7 @@ display_line (it)
            break;
        }
 
+    at_end_of_line:
       /* Is this a line end?  If yes, we're also done, after making
         sure that a non-default face is extended up to the right
         margin of the window.  */
@@ -14626,7 +15056,8 @@ display_line (it)
 
          /* Add a space at the end of the line that is used to
             display the cursor there.  */
-         append_space (it, 0);
+         if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+           append_space (it, 0);
 
          /* Extend the face to the end of the line.  */
          extend_face_to_end_of_line (it);
@@ -14667,6 +15098,19 @@ display_line (it)
                  produce_special_glyphs (it, IT_TRUNCATION);
                }
            }
+         else
+           {
+             /* Don't truncate if we can overflow newline into fringe.  */
+             if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+               {
+                 get_next_display_element (it);
+                 if (ITERATOR_AT_END_OF_LINE_P (it))
+                   {
+                     row->exact_window_width_line_p = 1;
+                     goto at_end_of_line;
+                   }
+               }
+           }
 
          row->truncated_on_right_p = 1;
          it->continuation_lines_width = 0;
@@ -19206,36 +19650,53 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      enum glyph_row_area area;
      int x0, y0, x1, y1;
 {
-  if (area == TEXT_AREA && w->phys_cursor_on_p)
-    {
-      int cx0 = w->phys_cursor.x;
-      int cx1 = cx0 + w->phys_cursor_width;
-      int cy0 = w->phys_cursor.y;
-      int cy1 = cy0 + w->phys_cursor_height;
+  int cx0, cx1, cy0, cy1;
+  struct glyph_row *row;
 
-      if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
-       {
-         /* The cursor image will be completely removed from the
-            screen if the output area intersects the cursor area in
-            y-direction.  When we draw in [y0 y1[, and some part of
-            the cursor is at y < y0, that part must have been drawn
-            before.  When scrolling, the cursor is erased before
-            actually scrolling, so we don't come here.  When not
-            scrolling, the rows above the old cursor row must have
-            changed, and in this case these rows must have written
-            over the cursor image.
+  if (!w->phys_cursor_on_p)
+    return;
+  if (area != TEXT_AREA)
+    return;
 
-            Likewise if part of the cursor is below y1, with the
-            exception of the cursor being in the first blank row at
-            the buffer and window end because update_text_area
-            doesn't draw that row.  (Except when it does, but
-            that's handled in update_text_area.)  */
+  row = w->current_matrix->rows + w->phys_cursor.vpos;
+  if (!row->displays_text_p)
+    return;
 
-         if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
-             && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
-           w->phys_cursor_on_p = 0;
-       }
+  if (row->cursor_in_fringe_p)
+    {
+      row->cursor_in_fringe_p = 0;
+      draw_fringe_bitmap (w, row, 0);
+      w->phys_cursor_on_p = 0;
+      return;
     }
+
+  cx0 = w->phys_cursor.x;
+  cx1 = cx0 + w->phys_cursor_width;
+  if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
+    return;
+
+  /* The cursor image will be completely removed from the
+     screen if the output area intersects the cursor area in
+     y-direction.  When we draw in [y0 y1[, and some part of
+     the cursor is at y < y0, that part must have been drawn
+     before.  When scrolling, the cursor is erased before
+     actually scrolling, so we don't come here.  When not
+     scrolling, the rows above the old cursor row must have
+     changed, and in this case these rows must have written
+     over the cursor image.
+
+     Likewise if part of the cursor is below y1, with the
+     exception of the cursor being in the first blank row at
+     the buffer and window end because update_text_area
+     doesn't draw that row.  (Except when it does, but
+     that's handled in update_text_area.)  */
+
+  cy0 = w->phys_cursor.y;
+  cy1 = cy0 + w->phys_cursor_height;
+  if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
+    return;
+
+  w->phys_cursor_on_p = 0;
 }
 
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -19370,6 +19831,14 @@ erase_phys_cursor (w)
   if (cursor_row->visible_height <= 0)
     goto mark_cursor_off;
 
+  /* If cursor is in the fringe, erase by drawing actual bitmap there.  */
+  if (cursor_row->cursor_in_fringe_p)
+    {
+      cursor_row->cursor_in_fringe_p = 0;
+      draw_fringe_bitmap (w, cursor_row, 0);
+      goto mark_cursor_off;
+    }
+
   /* This can happen when the new row is shorter than the old one.
      In this case, either draw_glyphs or clear_end_of_line
      should have cleared the cursor.  Note that we wouldn't be
@@ -21524,12 +21993,21 @@ wide as that tab on the display.  */);
 #endif
 
   DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
-    doc: /* Non-nil means highlight trailing whitespace.
+    doc: /* *Non-nil means highlight trailing whitespace.
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
+  DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
+    doc: /* *Non-nil means that newline may flow into the right fringe.
+This means that display lines which are exactly as wide as the window
+(not counting the final newline) will only occupy one screen line, by
+showing (or hiding) the final newline in the right fringe; when point
+is at the final newline, the cursor is shown in the right fringe.
+If nil, also continue lines which are exactly as wide as the window.  */);
+  Voverflow_newline_into_fringe = Qt;
+
   DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
-    doc: /* The pointer shape to show in void text areas.
+    doc: /* *The pointer shape to show in void text areas.
 Nil means to show the text pointer.  Other options are `arrow', `text',
 `hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */); 
   Vvoid_text_area_pointer = Qarrow;