changeset 53608:81b31a8c3313

(Voverflow_newline_into_fringe): New variable. (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.
author Kim F. Storm <storm@cua.dk>
date Fri, 16 Jan 2004 18:47:20 +0000
parents 4262a032b45b
children 0bb1ce3944cd
files src/xdisp.c
diffstat 1 files changed, 556 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Fri Jan 16 18:46:47 2004 +0000
+++ b/src/xdisp.c	Fri Jan 16 18:47:20 2004 +0000
@@ -310,6 +310,19 @@
 
 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 @@
 		      ++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 @@
       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 @@
 
 #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 @@
   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.  */
-
-static void
-draw_fringe_bitmap (w, row, which, left_p)
+   drawn.
+   LEFT_P is 1 for left fringe, 0 for right fringe.
+*/
+
+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 @@
   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 @@
     }
 
   /* 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 @@
      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 @@
     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, bitmap, 0);
+    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.  */
+
+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 @@
 	      *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_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 @@
   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 @@
       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 @@
 	     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 @@
       || !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 @@
 #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 @@
 		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 @@
 
       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 @@
 	    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 @@
 	     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 @@
 		      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 @@
 	    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 @@
 
 	  /* 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 @@
 		  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 @@
      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;
-
-      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.
-
-	     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.)  */
-
-	  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;
-	}
-    }
+  int cx0, cx1, cy0, cy1;
+  struct glyph_row *row;
+
+  if (!w->phys_cursor_on_p)
+    return;
+  if (area != TEXT_AREA)
+    return;
+
+  row = w->current_matrix->rows + w->phys_cursor.vpos;
+  if (!row->displays_text_p)
+    return;
+
+  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 @@
   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 @@
 #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;