diff --git a/src/buffer.c b/src/buffer.c
index 98b61c3..0d3ea74 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5073,6 +5073,9 @@ init_buffer_once (void)
   XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, cache_long_scans), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, posn_list), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, window_start_end_hook), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, mc_list), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx;
@@ -5166,6 +5169,9 @@ init_buffer_once (void)
   XSETFASTINT (BVAR (&buffer_defaults, fill_column), 70);
   XSETFASTINT (BVAR (&buffer_defaults, left_margin), 0);
   bset_cache_long_scans (&buffer_defaults, Qt);
+  bset_posn_list (&buffer_defaults, Qnil);
+  bset_window_start_end_hook (&buffer_defaults, Qnil);
+  bset_mc_list (&buffer_defaults, Qnil);
   bset_file_truename (&buffer_defaults, Qnil);
   XSETFASTINT (BVAR (&buffer_defaults, display_count), 0);
   XSETFASTINT (BVAR (&buffer_defaults, left_margin_cols), 0);
@@ -5379,6 +5385,10 @@ syms_of_buffer (void)
   staticpro (&QSFundamental);
   staticpro (&Vbuffer_alist);
 
+  DEFSYM (Qposn_list, "posn-list");
+  DEFSYM (Qwindow_start_end_hook, "window-start-end-hook");
+  DEFSYM (Qmc_list, "mc-list");
+
   DEFSYM (Qchoice, "choice");
   DEFSYM (Qleft, "left");
   DEFSYM (Qright, "right");
@@ -6148,6 +6158,18 @@ maintained internally by the Emacs primitives.  Enabling or disabling
 the cache should not affect the behavior of any of the motion
 functions; it should only affect their performance.  */);
 
+  DEFVAR_PER_BUFFER ("window-start-end-hook", &BVAR (current_buffer, window_start_end_hook), Qnil,
+    doc: /* A bufer-local hook used to obtain new `window-start` and `window-end`
+during redisplay.  The function attached to this hook has the following arguments:
+WINDOW, WINDOW-START, WINDOW-END, PBOL-START, PEOL-END, FULLY-P.  */);
+
+  DEFVAR_PER_BUFFER ("posn-list", &BVAR (current_buffer, posn_list), Qnil,
+    doc: /* A bufer-local variable to store the value of `posn-fn'.  */);
+
+  DEFVAR_PER_BUFFER ("mc-list", &BVAR (current_buffer, mc_list), Qnil,
+    doc: /* A bufer-local variable to store the value of the multiple cursors to be displayed
+during the next redisplay.  */);
+
   DEFVAR_PER_BUFFER ("point-before-scroll", &BVAR (current_buffer, point_before_scroll), Qnil,
 		     doc: /* Value of point before the last series of scroll operations, or nil.  */);
 
diff --git a/src/buffer.h b/src/buffer.h
index 5783bfb..01c3755 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -643,6 +643,15 @@ struct buffer
      cache are enabled.  See search.c, indent.c and bidi.c for details.  */
   Lisp_Object cache_long_scans_;
 
+  /* The name of the hook.  */
+  Lisp_Object window_start_end_hook_;
+
+  /* The name of list.  */
+  Lisp_Object posn_list_;
+
+  /* The name of list used by multiple cursors for next redisplay.  */
+  Lisp_Object mc_list_;
+
   /* If the width run cache is enabled, this table contains the
      character widths width_run_cache (see above) assumes.  When we
      do a thorough redisplay, we compare this against the buffer's
@@ -885,6 +894,21 @@ struct buffer
    buffer.  (Some setters that are private to a single .c file are
    defined as static in those files.)  */
 INLINE void
+bset_window_start_end_hook (struct buffer *b, Lisp_Object val)
+{
+  b->window_start_end_hook_ = val;
+}
+INLINE void
+bset_posn_list (struct buffer *b, Lisp_Object val)
+{
+  b->posn_list_ = val;
+}
+INLINE void
+bset_mc_list (struct buffer *b, Lisp_Object val)
+{
+  b->mc_list_ = val;
+}
+INLINE void
 bset_bidi_paragraph_direction (struct buffer *b, Lisp_Object val)
 {
   b->bidi_paragraph_direction_ = val;
diff --git a/src/dispextern.h b/src/dispextern.h
index 00667c5..8e4a7f4 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2891,7 +2891,8 @@ struct redisplay_interface
 			      struct glyph_row *glyph_row,
 			      int x, int y,
 			      enum text_cursor_kinds cursor_type,
-			      int cursor_width, bool on_p, bool active_p);
+			      int cursor_width, bool on_p, bool active_p,
+			      int red, int green, int blue);
 
   /* Draw vertical border for window W from (X,Y_0) to (X,Y_1).  */
   void (*draw_vertical_window_border) (struct window *w,
@@ -3287,11 +3288,11 @@ extern void x_fix_overlapping_area (struct window *, struct glyph_row *,
                                     enum glyph_row_area, int);
 extern void draw_phys_cursor_glyph (struct window *,
                                     struct glyph_row *,
-                                    enum draw_glyphs_face);
+                                    enum draw_glyphs_face, char *);
 extern void get_phys_cursor_geometry (struct window *, struct glyph_row *,
                                       struct glyph *, int *, int *, int *);
-extern void erase_phys_cursor (struct window *);
-extern void display_and_set_cursor (struct window *, bool, int, int, int, int);
+extern void erase_phys_cursor (struct window *, char *);
+extern void display_and_set_cursor (struct window *, bool, int, int, int, int, char *);
 extern void x_update_cursor (struct frame *, bool);
 extern void x_clear_cursor (struct window *);
 extern void x_draw_vertical_border (struct window *w);
diff --git a/src/keyboard.c b/src/keyboard.c
index 4e1ac15..329cba0 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1244,6 +1244,15 @@ static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
                               bool, bool, bool, bool);
 static void adjust_point_for_property (ptrdiff_t, bool);
 
+static void
+set_window_start_end_hook (void)
+{
+  Lisp_Object window = (selected_window);
+  struct window *w = decode_live_window (window);
+  w->window_start_end_hook_force = true;
+  w->window_start_end_hook_pending = true;
+}
+
 Lisp_Object
 command_loop_1 (void)
 {
@@ -1269,6 +1278,8 @@ command_loop_1 (void)
       if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
 	safe_run_hooks (Qpost_command_hook);
 
+      set_window_start_end_hook ();
+
       /* If displaying a message, resize the echo area window to fit
 	 that message's size exactly.  */
       if (!NILP (echo_area_buffer[0]))
@@ -1485,6 +1496,8 @@ command_loop_1 (void)
 
       safe_run_hooks (Qpost_command_hook);
 
+      set_window_start_end_hook ();
+
       /* If displaying a message, resize the echo area window to fit
 	 that message's size exactly.  */
       if (!NILP (echo_area_buffer[0]))
diff --git a/src/nsterm.m b/src/nsterm.m
index 185753d..b27f185 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1023,7 +1023,7 @@ ns_update_window_end (struct window *w, bool cursor_on_p,
       if (cursor_on_p)
 	display_and_set_cursor (w, 1,
 				w->output_cursor.hpos, w->output_cursor.vpos,
-				w->output_cursor.x, w->output_cursor.y);
+				w->output_cursor.x, w->output_cursor.y, "nsterm.m:1024");
 
       if (draw_window_fringes (w, 1))
 	{
@@ -2696,7 +2696,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
 static void
 ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
 		       int x, int y, enum text_cursor_kinds cursor_type,
-		       int cursor_width, bool on_p, bool active_p)
+		       int cursor_width, bool on_p, bool active_p, int red, int green, int blue)
 /* --------------------------------------------------------------------------
      External call (RIF): draw cursor.
      Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
@@ -2781,7 +2781,12 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
       hollow_color = FRAME_CURSOR_COLOR (f);
     }
   else
-    [FRAME_CURSOR_COLOR (f) set];
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        [[NSColor colorWithCalibratedRed: red green: green blue: blue alpha: 1.0] set];
+        else
+          [FRAME_CURSOR_COLOR (f) set];
+    }
 
 #ifdef NS_IMPL_COCOA
   /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
@@ -2824,7 +2829,7 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
 
   /* draw the character under the cursor */
   if (cursor_type != NO_CURSOR)
-    draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+    draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR, "nsterm.m:2824");
 
 #ifdef NS_IMPL_COCOA
   NSEnableScreenUpdates ();
diff --git a/src/w32term.c b/src/w32term.c
index 36a5021..93e90bc 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -685,7 +685,7 @@ x_update_window_end (struct window *w, bool cursor_on_p,
       if (cursor_on_p)
 	display_and_set_cursor (w, true,
 				w->output_cursor.hpos, w->output_cursor.vpos,
-				w->output_cursor.x, w->output_cursor.y);
+				w->output_cursor.x, w->output_cursor.y, "w32term.c:686");
 
       if (draw_window_fringes (w, true))
 	{
@@ -5535,7 +5535,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row,
     {
       struct glyph_row *row;
       row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
-      draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+      draw_phys_cursor_glyph (w, row, DRAW_CURSOR, "w32term.c: 5538");
     }
   else
     {
@@ -5626,7 +5626,7 @@ w32_clear_frame_area (struct frame *f, int x, int y, int width, int height)
 static void
 w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
 			int x, int y, enum text_cursor_kinds cursor_type,
-			int cursor_width, bool on_p, bool active_p)
+			int cursor_width, bool on_p, bool active_p, int red, int green, int blue)
 {
   if (on_p)
     {
@@ -5638,7 +5638,7 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
 	     wrong values of w->phys_cursor, as they have been
 	     overwritten before this function was called. */
 	  if (w->phys_cursor_type != NO_CURSOR)
-	    erase_phys_cursor (w);
+	    erase_phys_cursor (w, "w32term.c:5641");
 
 	  cursor_type = w->phys_cursor_type = NO_CURSOR;
 	  w->phys_cursor_width = -1;
@@ -5698,7 +5698,7 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
 	  break;
 
 	case FILLED_BOX_CURSOR:
-	  draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+	  draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR, "w32term.c:5701");
 	  break;
 
 	case BAR_CURSOR:
diff --git a/src/window.h b/src/window.h
index 2c03033..a28c677 100644
--- a/src/window.h
+++ b/src/window.h
@@ -395,6 +395,19 @@ struct window
     /* Z_BYTE - buffer position of the last glyph in the current matrix of W.
        Should be nonnegative, and only valid if window_end_valid is true.  */
     ptrdiff_t window_end_bytepos;
+
+    /* True means force a call to Vwindow_start_end_hook.  */
+    bool_bf window_start_end_hook_force : 1;
+
+    /* True means the hook has not yet run with point fully visible.  */
+    bool_bf window_start_end_hook_pending : 1;
+
+    /* Values for previous and current `window-start' and `window-end'.  */
+    int window_start_end_hook_int_window_start, window_start_end_hook_int_window_end,
+        window_start_end_hook_int_previous_window_start, window_start_end_hook_int_previous_window_end;
+
+    /* The cache for multiple cursors.  */
+    Lisp_Object mc_cache;
   };
 
 /* Most code should use these functions to set Lisp fields in struct
diff --git a/src/xdisp.c b/src/xdisp.c
index 5b96144..102ac23 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -13414,6 +13414,93 @@ do { if (! polling_stopped_here) stop_polling ();	\
 do { if (polling_stopped_here) start_polling ();	\
        polling_stopped_here = false; } while (false)
 
+static void
+run_window_start_end_hook (Lisp_Object window, struct text_pos startp, EMACS_INT posint, struct it it, char *string, bool force)
+{
+  struct window *w = decode_live_window (window);
+  Lisp_Object buf;
+  struct buffer *b;
+  buf = w->contents;
+  CHECK_BUFFER (buf);
+  b = XBUFFER (buf);
+  struct buffer *old_buffer = NULL;
+  void *itdata = NULL;
+  bool fully_p = false;
+  int x, y, rtop, rbot, rowh, vpos, startp_integer, endp, pbol_startp, peol_endp;
+  startp_integer = CHARPOS (startp);
+  if (b != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal (b);
+    }
+  if (w->window_start_end_hook_pending
+        && (!NILP (BVAR (current_buffer, window_start_end_hook))
+            || !NILP (BVAR (current_buffer, mc_list))
+            || w->mc_cache))
+    {
+      if (((posint >= CHARPOS (startp) && posint <= BUF_ZV (b))
+            && CHARPOS (startp) >= BUF_BEGV (b)
+            && CHARPOS (startp) <= BUF_ZV (b)
+            && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)))
+        fully_p = !rtop && !rbot;
+      if (fully_p)
+        {
+          w->window_start_end_hook_int_previous_window_start = w->window_start_end_hook_int_window_start;
+          w->window_start_end_hook_int_window_start = startp_integer;
+          itdata = bidi_shelve_cache ();
+          start_display (&it, w, startp);
+          move_it_vertically (&it, window_box_height (w));
+          if (it.current_y < it.last_visible_y)
+            move_it_past_eol (&it);
+          endp = (IT_CHARPOS (it));
+          w->window_start_end_hook_int_previous_window_end = w->window_start_end_hook_int_window_end;
+          w->window_start_end_hook_int_window_end = endp;
+          bidi_unshelve_cache (itdata, false);
+          SET_PT (startp_integer);
+          pbol_startp = XINT (Fline_beginning_position (Qnil));
+          SET_PT (endp);
+          peol_endp = XINT (Fline_end_position (Qnil));
+          SET_PT (posint);
+#ifdef GLYPH_DEBUG
+          debug_method_add (w, "%s -- x: %d | y: %d | startp: %d | endp: %d | pbol_startp: %d | peol_endp: %d",
+                               string, x, y, startp_integer, endp, pbol_startp, peol_endp);
+#endif
+          /* Reset the flag _before_ calling Lisp, not after, so that
+             if Lisp does signal an error, the flag will be reset, and
+             won't cause the hook to be called ad nauseam.  */
+          w->window_start_end_hook_pending = false;
+          /* When calling Lisp from redisplay, always use safe_call, to be
+             protected against errors signaled by that Lisp.  */
+          /* safe_call:  fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7  */
+          safe_call (8,
+              Qrun_hook_with_args,
+              Qwindow_start_end_hook,
+              window,
+              make_number (startp_integer),
+              make_number (endp),
+              make_number (pbol_startp),
+              make_number (peol_endp),
+              fully_p ? Qt : Qnil);
+          /* At the catch-all when scrolling with the mouse wheel, this next section causes a visual flash
+          of cursor in the wrong position due to SET_PT above.  */
+          if (force)
+            {
+              clear_glyph_matrix (w->desired_matrix);
+              try_window (window, startp, 0);
+            }
+        }
+        else
+          {
+#ifdef GLYPH_DEBUG
+            /* See the doc-string for `pos-visible-in-window-p'.  */
+            debug_method_add (w, "%s -- x: %d | y: %d | rtop: %d | rbot %d | rowh: %d | vpos: %d",
+                                 string, x, y, rtop, rbot, rowh, vpos);
+#endif
+          }
+    }
+  if (old_buffer)
+    set_buffer_internal (old_buffer);
+}
 
 /* Perhaps in the future avoid recentering windows if it
    is not necessary; currently that causes some problems.  */
@@ -13687,6 +13774,7 @@ redisplay_internal (void)
       && match_p
       && !w->force_start
       && !w->optional_new_start
+      && !w->window_start_end_hook_force
       /* Point must be on the line that we have info recorded about.  */
       && PT >= CHARPOS (tlbufpos)
       && PT <= Z - CHARPOS (tlendpos)
@@ -15388,6 +15476,8 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
   /* Run window scroll functions.  */
   startp = run_window_scroll_functions (window, startp);
 
+  run_window_start_end_hook (window, startp, PT, it, "try_scrolling", false);
+
   /* Display the window.  Give up if new fonts are loaded, or if point
      doesn't appear.  */
   if (!try_window (window, startp, 0))
@@ -16053,6 +16143,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   ptrdiff_t beg_unchanged, end_unchanged;
   int frame_line_height;
   bool use_desired_matrix;
+  bool window_start_end_hook_suppress_wsf = false;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
   opoint = lpoint;
@@ -16243,13 +16334,16 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
   /* If someone specified a new starting point but did not insist,
      check whether it can be used.  */
-  if ((w->optional_new_start || window_frozen_p (w))
+  if ((w->optional_new_start || w->window_start_end_hook_force || window_frozen_p (w))
       && CHARPOS (startp) >= BEGV
       && CHARPOS (startp) <= ZV)
     {
+
+      if (w->window_start_end_hook_force && !w->optional_new_start && !window_frozen_p (w) && !w->force_start)
+        window_start_end_hook_suppress_wsf = true;
+
       ptrdiff_t it_charpos;
 
-      w->optional_new_start = false;
       start_display (&it, w, startp);
       move_it_to (&it, PT, 0, it.last_visible_y, -1,
 		  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
@@ -16270,14 +16364,28 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	    w->force_start = true;
 #ifdef GLYPH_DEBUG
 	  if (w->force_start)
-	    {
-	      if (window_frozen_p (w))
-		debug_method_add (w, "set force_start from frozen window start");
-	      else
-		debug_method_add (w, "set force_start from optional_new_start");
-	    }
+    {
+      if (window_frozen_p (w))
+        {
+        debug_method_add (w, "redisplay_window (force_start):  window_frozen_p (w)");
+      }
+      else if (w->optional_new_start)
+        {
+        debug_method_add (w, "redisplay_window (force_start):  w->optional_new_start");
+      }
+      else if (w->window_start_end_hook_force)
+        {
+        debug_method_add (w, "redisplay_window (force_start):  w->window_start_end_hook_force");
+      }
+      else
+        {
+        debug_method_add (w, "redisplay_window (force_start):  This situation is not yet contemplated.");
+      }
+    }
 #endif
 	}
+      w->optional_new_start = false;
+      w->window_start_end_hook_force = false;
     }
 
  force_start:
@@ -16305,11 +16413,18 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	 than to get into an infinite loop calling the hook functions
 	 and having them get more errors.  */
       if (!update_mode_line
-	  || ! NILP (Vwindow_scroll_functions))
+	  || ! NILP (Vwindow_scroll_functions)
+	  || ! NILP (BVAR (current_buffer, window_start_end_hook)))
 	{
 	  update_mode_line = true;
 	  w->update_mode_line = true;
-	  startp = run_window_scroll_functions (window, startp);
+
+  /* Run window scroll functions.  */
+  if (!window_start_end_hook_suppress_wsf)
+    startp = run_window_scroll_functions (window, startp);
+
+  run_window_start_end_hook (window, startp, PT, it, "redisplay_window (force_start)", false);
+
 	}
 
       if (CHARPOS (startp) < BEGV)
@@ -16460,9 +16575,13 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	  goto try_to_scroll;
 	}
 
+  /* When scrolling with the mouse wheel, PT has not yet been reset so we use CHARPOS (startp).  */
+  run_window_start_end_hook (window, startp, CHARPOS (startp), it, "redisplay_window:  catch-all", false);
+
 #ifdef GLYPH_DEBUG
-      debug_method_add (w, "forced window start");
+      debug_method_add (w, "redisplay_window:  forced window start");
 #endif
+
       goto done;
     }
 
@@ -16577,6 +16696,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	     because a window scroll function can have changed the
 	     buffer.  */
 	  || !NILP (Vwindow_scroll_functions)
+	  || !NILP (BVAR (current_buffer, window_start_end_hook))
 	  || MINI_WINDOW_P (w)
 	  || !(used_current_matrix_p
 	       = try_window_reusing_current_matrix (w)))
@@ -16774,6 +16894,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* Run scroll hooks.  */
   startp = run_window_scroll_functions (window, it.current.pos);
 
+  run_window_start_end_hook (window, startp, PT, it, "redisplay_window (recenter)", false);
+
   /* Redisplay the window.  */
   use_desired_matrix = false;
   if (!current_matrix_up_to_date_p
@@ -16782,6 +16904,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       /* Don't use try_window_reusing_current_matrix in this case
 	 because it can have changed the buffer.  */
       || !NILP (Vwindow_scroll_functions)
+      || !NILP (BVAR (current_buffer, window_start_end_hook))
       || !just_this_one_p
       || MINI_WINDOW_P (w)
       || !(used_current_matrix_p
@@ -16902,7 +17025,13 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	  clear_glyph_matrix (w->desired_matrix);
 	  if (1 == try_window (window, it.current.pos,
 			       TRY_WINDOW_CHECK_MARGINS))
-	    goto done;
+    {
+      /* To avoid a visual hick-up, it is necessary to set the last argument to true -- that triggers
+      `clear_glyph_matrix' and `try_window' after the functions attached to the hook have run.  */
+      run_window_start_end_hook (window, it.current.pos, PT, it, "redisplay_window (post-recenter)", true);
+      goto done;
+    }
+
 	}
 
       /* If centering point failed to make the whole line visible,
@@ -23657,6 +23786,20 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 	  return "@";
       }
 
+    case 'w':
+      {
+  ptrdiff_t window_start = marker_position (w->start);
+  pint2str (decode_mode_spec_buf, width, window_start);
+  return decode_mode_spec_buf;
+      }
+
+    case 'W':
+      {
+  ptrdiff_t window_end = BUF_Z (b) - w->window_end_pos;
+  pint2str (decode_mode_spec_buf, width, window_end);
+  return decode_mode_spec_buf;
+      }
+
     case 'z':
       /* coding-system (not including end-of-line format) */
     case 'Z':
@@ -23705,6 +23848,335 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     return "";
 }
 
+static const char *
+internal_line_number_at_position (struct window *w, register int c, int field_width, Lisp_Object *string)
+{
+  Lisp_Object obj;
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
+  /* We are going to use f->decode_mode_spec_buffer as the buffer to
+     produce strings from numerical values, so limit preposterously
+     large values of FIELD_WIDTH to avoid overrunning the buffer's
+     end.  The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE
+     bytes plus the terminating null.  */
+  int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
+  struct buffer *b = current_buffer;
+  obj = Qnil;
+  *string = Qnil;
+  switch (c)
+    {
+    case 'l':
+      {
+  ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
+  ptrdiff_t topline, nlines, height;
+  ptrdiff_t junk;
+  /* %c and %l are ignored in `frame-title-format'.  */
+  if (mode_line_target == MODE_LINE_TITLE)
+    return "";
+  startpos = marker_position (w->start);
+  startpos_byte = marker_byte_position (w->start);
+  height = WINDOW_TOTAL_LINES (w);
+  /* If we decided that this buffer isn't suitable for line numbers,
+     don't forget that too fast.  */
+  if (w->base_line_pos == -1)
+    goto no_value;
+  /* If the buffer is very big, don't waste time.  */
+  if (INTEGERP (Vline_number_display_limit)
+      && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
+    {
+      w->base_line_pos = 0;
+      w->base_line_number = 0;
+      goto no_value;
+    }
+  if (w->base_line_number > 0
+      && w->base_line_pos > 0
+      && w->base_line_pos <= startpos)
+    {
+      line = w->base_line_number;
+      linepos = w->base_line_pos;
+      linepos_byte = buf_charpos_to_bytepos (b, linepos);
+    }
+  else
+    {
+      line = 1;
+      linepos = BUF_BEGV (b);
+      linepos_byte = BUF_BEGV_BYTE (b);
+    }
+  /* Count lines from base line to window start position.  */
+  nlines = display_count_lines (linepos_byte,
+              startpos_byte,
+              startpos, &junk);
+  topline = nlines + line;
+  /* Determine a new base line, if the old one is too close
+     or too far away, or if we did not have one.
+     "Too close" means it's plausible a scroll-down would
+     go back past it.  */
+  if (startpos == BUF_BEGV (b))
+    {
+      w->base_line_number = topline;
+      w->base_line_pos = BUF_BEGV (b);
+    }
+  else if (nlines < height + 25 || nlines > height * 3 + 50
+     || linepos == BUF_BEGV (b))
+    {
+      ptrdiff_t limit = BUF_BEGV (b);
+      ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
+      ptrdiff_t position;
+      ptrdiff_t distance =
+        (height * 2 + 30) * line_number_display_limit_width;
+      if (startpos - distance > limit)
+        {
+    limit = startpos - distance;
+    limit_byte = CHAR_TO_BYTE (limit);
+        }
+      nlines = display_count_lines (startpos_byte,
+            limit_byte,
+            - (height * 2 + 30),
+            &position);
+      /* If we couldn't find the lines we wanted within
+         line_number_display_limit_width chars per line,
+         give up on line numbers for this window.  */
+      if (position == limit_byte && limit == startpos - distance)
+        {
+    w->base_line_pos = -1;
+    w->base_line_number = 0;
+    goto no_value;
+        }
+      w->base_line_number = topline - nlines;
+      w->base_line_pos = BYTE_TO_CHAR (position);
+    }
+  /* Now count lines from the start pos to point.  */
+  nlines = display_count_lines (startpos_byte, PT_BYTE, PT, &junk);
+  /* Make the string to show.  */
+  pint2str (decode_mode_spec_buf, width, topline + nlines);
+  return decode_mode_spec_buf;
+    no_value:
+        {
+    char *p = decode_mode_spec_buf;
+    int pad = width - 2;
+    while (pad-- > 0)
+      *p++ = ' ';
+    *p++ = '?';
+    *p++ = '?';
+    *p = '\0';
+    return decode_mode_spec_buf;
+  }
+      }
+      break;
+    }
+  if (STRINGP (obj))
+    {
+      *string = obj;
+      return SSDATA (obj);
+    }
+  else
+    return "";
+}
+
+DEFUN ("line-number-at-position", Fline_number_at_position, Sline_number_at_position, 1, 2, 0,
+       doc: /* Return line number at position.  */)
+  (Lisp_Object window, Lisp_Object pos)
+{
+  struct window *w = decode_live_window (window);
+  Lisp_Object buf, foo_string, value;
+  struct buffer *b;
+  buf = w->contents;
+  CHECK_BUFFER (buf);
+  b = XBUFFER (buf);
+  struct buffer *old_buffer = NULL;
+  const char *spec;
+  EMACS_INT opoint, posint;
+  if (b != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal (b);
+    }
+  if (!NILP (pos))
+    {
+      opoint = PT;
+      posint = XINT (pos);
+      SET_PT (posint);
+    }
+  spec = internal_line_number_at_position (w, 'l', 0, &foo_string);
+  if (!NILP (pos))
+    SET_PT (opoint);
+  if (old_buffer)
+    set_buffer_internal (old_buffer);
+  value = build_string (spec);
+  value = Fstring_to_number (value, make_number (10));
+  return value;
+}
+
+DEFUN ("posn-fn", Fposn_fn, Sposn_fn, 4, 4, 0,
+       doc: /* Gather a list of various points in the visible window.  */)
+  (Lisp_Object window, ptrdiff_t start, ptrdiff_t end, ptrdiff_t vcol)
+{
+  struct window *w = decode_live_window (window);
+  Lisp_Object buf;
+  struct buffer *b;
+  buf = w->contents;
+  CHECK_BUFFER (buf);
+  b = XBUFFER (buf);
+  struct buffer *old_buffer = NULL;
+  const char *spec;
+  int counter = 0;
+  EMACS_INT opoint, min, max, new_pbol, new_peol, old_pbol, old_peol, pbovl, peovl, col_eovl,
+    pbovl_minus_1, peovl_plus_1, pfci, pfci_minus_1, pfci_plus_1, line;
+  /* EMACS_INT x, my_x, y, my_y, hpos, vpos, frame_char_width, frame_char_height, window_header_line_height  */
+  Lisp_Object foo_string, tab_pfci, char_at_pfci, char_before_pfci, char_after_pfci, char_at_peovl, string_char_at_pfci,
+    string_char_before_pfci, color_vector_bg, color_vector_fg, color_vector_bg_minus_1, color_vector_fg_minus_1;
+  Lisp_Object temp = Qnil;
+  Lisp_Object result = Qnil;
+  Lisp_Object foreground = intern ("foreground");
+  Lisp_Object background = intern ("background");
+  /* Lisp_Object frame;
+  struct frame *f = XFRAME (selected_frame);
+  frame_char_width = FRAME_COLUMN_WIDTH (f);
+  frame_char_height = FRAME_LINE_HEIGHT (f);
+  window_header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+  my_x = frame_char_width * vcol;  */
+  if (b != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal (b);
+    }
+  opoint = PT;
+  vcol = XINT (vcol);
+  start = XINT (start);
+  end = XINT (end);
+  min = BEGV;
+  max = ZV;
+  SET_PT (start);
+  while (Qt)
+    {
+      old_pbol = XINT (Fline_beginning_position (Qnil));
+      old_peol = XINT (Fline_end_position (Qnil));
+      pbovl = PT;
+      spec = internal_line_number_at_position (w, 'l', 0, &foo_string);
+      line = build_string (spec);
+      line = Fstring_to_number (line, make_number (10));
+      Fvertical_motion (make_number (1), window, Qnil);
+      /* my_y = (frame_char_height * counter) + window_header_line_height;  */
+      /* my_y = frame_char_height * counter;  */
+      new_pbol = XINT (Fline_beginning_position (Qnil));
+      new_peol = XINT (Fline_end_position (Qnil));
+      if (PT == end && !(PT == new_pbol))
+        peovl = end;
+        else if (old_pbol == old_peol)
+          {
+            pbovl = old_pbol;
+            peovl = old_peol;
+          }
+          else
+            peovl = PT - 1;
+      col_eovl = peovl - pbovl;
+      pbovl_minus_1 = pbovl - 1;
+      peovl_plus_1 = peovl + 1;
+      if (old_pbol == old_peol)
+        pfci = old_pbol;
+        else if ((pbovl + vcol) <= peovl)
+          pfci = pbovl + vcol;
+          else
+            pfci = peovl;
+      if (pfci > 0 && !(pfci >= max))
+        {
+          /* temp = Fposn_at_point (make_number (pfci), window);
+          x = XINT (XCAR (Fnth (make_number (2), temp)));
+          y = XINT (XCDR (Fnth (make_number (2), temp)));
+          hpos = XINT (XCAR (Fnth (make_number (6), temp)));
+          vpos = XINT (XCDR (Fnth (make_number (6), temp)));  */
+          pfci_minus_1 = pfci - 1;
+          pfci_plus_1 = pfci + 1;
+        }
+      if (pfci > 0 && !(pfci >= max))
+        char_at_pfci = (Fchar_after (make_number (pfci)));
+        else
+          char_at_pfci = Qnil;
+      if (pfci_minus_1 > 0 && !(pfci_minus_1 >= max))
+        char_before_pfci = (Fchar_after (make_number (pfci_minus_1)));
+        else
+          char_before_pfci = Qnil;
+      if (pfci_plus_1 > 0 && !(pfci_plus_1 >= max))
+        char_after_pfci = (Fchar_after (make_number (pfci_plus_1)));
+        else
+          char_after_pfci = Qnil;
+      if (peovl > 0 && !(peovl >= max))
+        char_at_peovl = (Fchar_after (make_number (peovl)));
+        else
+          char_at_peovl = Qnil;
+      if (Fcharacterp (char_at_pfci, Qnil))
+        string_char_at_pfci = (Fchar_to_string (char_at_pfci));
+        else
+          string_char_at_pfci = Qnil;
+      if (Fcharacterp (char_before_pfci, Qnil))
+        string_char_before_pfci = (Fchar_to_string (char_before_pfci));
+        else
+          string_char_before_pfci = Qnil;
+      if ((Fcharacterp (char_at_pfci, Qnil)) && char_at_pfci == 9)
+        tab_pfci = Qt;
+        else
+          tab_pfci = Qnil;
+      if (!NILP (pfci) && pfci >= start)
+        color_vector_bg = safe_call (4, Qcolor_vector_calc, window, make_number (pfci), background);
+        else
+          /* color_vector_bg = CALLN (Fvector, make_number (0.0), make_number (0.0), make_number (0.0));  */
+          color_vector_bg = Qnil;
+      if (!NILP (pfci) && pfci >= start)
+        color_vector_fg = safe_call (4, Qcolor_vector_calc, window, make_number (pfci), foreground);
+        else
+          /* color_vector_fg = CALLN (Fvector, make_number (1.0), make_number (1.0), make_number (1.0));  */
+          color_vector_fg = Qnil;
+      if (!NILP (pfci_minus_1) && pfci_minus_1 >= start)
+        color_vector_bg_minus_1 = safe_call (4, Qcolor_vector_calc, window, make_number (pfci_minus_1), background);
+        else
+          /* color_vector_bg_minus_1 = CALLN (Fvector, make_number (0.0), make_number (0.0), make_number (0.0));  */
+          color_vector_bg_minus_1 = Qnil;
+      if (!NILP (pfci_minus_1) && pfci_minus_1 >= start)
+        color_vector_fg_minus_1 = safe_call (4, Qcolor_vector_calc, window, make_number (pfci_minus_1), foreground);
+        else
+          /*  color_vector_fg_minus_1 = CALLN (Fvector, make_number (1.0), make_number (1.0), make_number (1.0));  */
+          color_vector_fg_minus_1 = Qnil;
+      temp = listn (CONSTYPE_PURE, 22,
+        Fcons (build_pure_c_string ("pbol"), make_number (old_pbol)),
+        Fcons (build_pure_c_string ("peol"), make_number (old_peol)),
+        Fcons (build_pure_c_string ("pbovl"), make_number (pbovl)),
+        Fcons (build_pure_c_string ("peovl"), make_number (peovl)),
+        Fcons (build_pure_c_string ("col-eovl"), make_number (col_eovl)),
+        Fcons (build_pure_c_string ("pbovl-1"), make_number (pbovl_minus_1)),
+        Fcons (build_pure_c_string ("peovl+1"), make_number (peovl_plus_1)),
+        Fcons (build_pure_c_string ("pfci"), make_number (pfci)),
+        Fcons (build_pure_c_string ("pfci-1"), make_number (pfci_minus_1)),
+        Fcons (build_pure_c_string ("pfci+1"), make_number (pfci_plus_1)),
+        Fcons (build_pure_c_string ("char-at-pfci"), char_at_pfci),
+        Fcons (build_pure_c_string ("char-before-pfci"), char_before_pfci),
+        Fcons (build_pure_c_string ("char-after-pfci"), char_after_pfci),
+        Fcons (build_pure_c_string ("char-at-peovl"), char_at_peovl),
+        Fcons (build_pure_c_string ("string-char-at-pfci"), string_char_at_pfci),
+        Fcons (build_pure_c_string ("string-char-before-pfci"), string_char_before_pfci),
+        Fcons (build_pure_c_string ("tab-pfci"), tab_pfci),
+        Fcons (build_pure_c_string ("line-number"), line),
+        Fcons (build_pure_c_string ("color-vector-bg"), color_vector_bg),
+        Fcons (build_pure_c_string ("color-vector-fg"), color_vector_fg),
+        Fcons (build_pure_c_string ("color-vector-bg-1"), color_vector_bg_minus_1),
+        Fcons (build_pure_c_string ("color-vector-fg-1"), color_vector_fg_minus_1));
+        /*  Fcons (build_pure_c_string ("my_posn-at-pfci (x, y, hpos, vpos)"),
+          Fcons (listn (CONSTYPE_PURE, 4, make_number (my_x), make_number (my_y), make_number (vcol), make_number (counter)), Qnil)),
+        Fcons (build_pure_c_string ("posn-at-pfci (x, y, hpos, vpos)"),
+          Fcons (listn (CONSTYPE_PURE, 4, make_number (x), make_number (y), make_number (hpos), make_number (vpos)), Qnil))  */
+      if (NILP (result))
+        result = Fcons (temp, Qnil);
+        else
+          result = Fcons (temp, result);
+      counter = 1 + counter;
+      if (PT >= end || PT == max)
+        break;
+    }
+  SET_PT (opoint);
+  if (old_buffer)
+    set_buffer_internal (old_buffer);
+  bset_posn_list (current_buffer, Freverse (result));
+  return BVAR (current_buffer, posn_list);
+}
 
 /* Count up to COUNT lines starting from START_BYTE.  COUNT negative
    means count lines back from START_BYTE.  But don't go beyond
@@ -28151,8 +28623,15 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
 
 void
 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
-			enum draw_glyphs_face hl)
+			enum draw_glyphs_face hl, char *string)
 {
+
+/*
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "draw_phys_cursor_glyph: %s", string);
+#endif
+*/
+
   /* If cursor hpos is out of bounds, don't draw garbage.  This can
      happen in mini-buffer windows when switching between echo area
      glyphs and mini-buffer.  */
@@ -28202,7 +28681,7 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
 /* Erase the image of a cursor of window W from the screen.  */
 
 void
-erase_phys_cursor (struct window *w)
+erase_phys_cursor (struct window *w, char *string)
 {
   struct frame *f = XFRAME (w->frame);
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
@@ -28214,6 +28693,12 @@ erase_phys_cursor (struct window *w)
   struct glyph *cursor_glyph;
   enum draw_glyphs_face hl;
 
+/*
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "erase_phys_cursor: %s", string);
+#endif
+*/
+
   /* No cursor displayed or row invalidated => nothing to do on the
      screen.  */
   if (w->phys_cursor_type == NO_CURSOR)
@@ -28308,13 +28793,401 @@ erase_phys_cursor (struct window *w)
     hl = DRAW_MOUSE_FACE;
   else
     hl = DRAW_NORMAL_TEXT;
-  draw_phys_cursor_glyph (w, cursor_row, hl);
+  draw_phys_cursor_glyph (w, cursor_row, hl, "xdisp.c: 1 of 1");
 
  mark_cursor_off:
   w->phys_cursor_on_p = false;
   w->phys_cursor_type = NO_CURSOR;
 }
 
+void
+mc_erase (struct window *w, EMACS_INT x, EMACS_INT y, EMACS_INT hpos, EMACS_INT vpos,
+                      enum text_cursor_kinds cursor_type, int cursor_width, int red, int green, int blue)
+{
+  int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+  if (header_line_height > 0)
+    vpos = vpos + 1;
+  struct frame *f = XFRAME (w->frame);
+  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+  bool mouse_face_here_p = false;
+  struct glyph_matrix *active_glyphs = w->current_matrix;
+  struct glyph_row *cursor_row;
+  struct glyph *cursor_glyph;
+  enum draw_glyphs_face hl;
+  cursor_row = MATRIX_ROW (active_glyphs, vpos);
+  /* Maybe clear the display under the cursor.  */
+  if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
+    {
+      int hollow_x, hollow_y;
+      int width;
+      if (!(vpos >= 0
+          && vpos < w->current_matrix->nrows))
+        cursor_glyph = NULL;
+      if (!cursor_row->enabled_p)
+        cursor_glyph = NULL;
+      if (w->hscroll)
+        {
+          /* When the window is hscrolled, cursor hpos can legitimately be
+           out of bounds, but we draw the cursor at the corresponding
+           window margin in that case.  */
+          if (!cursor_row->reversed_p && hpos < 0)
+            hpos = 0;
+          if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
+            hpos = cursor_row->used[TEXT_AREA] - 1;
+        }
+      if (0 <= hpos && hpos < cursor_row->used[TEXT_AREA])
+        cursor_glyph = cursor_row->glyphs[TEXT_AREA] + hpos;
+      else
+        cursor_glyph = NULL;
+      if (cursor_glyph == NULL)
+        goto mark_cursor_off;
+      width = cursor_glyph->pixel_width;
+      hollow_x = x;
+      if (x < 0)
+        {
+          width += hollow_x;
+          hollow_x = 0;
+        }
+      width = min (width, window_box_width (w, TEXT_AREA) - hollow_x);
+      hollow_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
+      hollow_x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, hollow_x);
+      if (width > 0)
+        FRAME_RIF (f)->clear_frame_area (f, hollow_x, hollow_y, width, cursor_row->visible_height);
+    }
+  /* Erase the cursor by redrawing the character underneath it.  */
+  if (mouse_face_here_p)
+    hl = DRAW_MOUSE_FACE;
+  else
+    hl = DRAW_NORMAL_TEXT;
+  /* If cursor hpos is out of bounds, don't draw garbage.  This can
+     happen in mini-buffer windows when switching between echo area
+     glyphs and mini-buffer.  */
+  if ((cursor_row->reversed_p
+       ? (hpos >= 0)
+       : (hpos < cursor_row->used[TEXT_AREA])))
+    {
+      int x1;
+      /* When the window is hscrolled, cursor hpos can legitimately be
+   out of bounds, but we draw the cursor at the corresponding
+   window margin in that case.  */
+      if (!cursor_row->reversed_p && hpos < 0)
+        hpos = 0;
+      if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
+        hpos = cursor_row->used[TEXT_AREA] - 1;
+      x1 = draw_glyphs (w, x, cursor_row, TEXT_AREA, hpos, hpos + 1,
+      hl, 0);
+      if (hl == DRAW_CURSOR)
+        w->phys_cursor_width = x1 - x;
+      /* When we erase the cursor, and ROW is overlapped by other
+   rows, make sure that these overlapping parts of other rows
+   are redrawn.  */
+        else if (hl == DRAW_NORMAL_TEXT && cursor_row->overlapped_p)
+          {
+            w->phys_cursor_width = x1 - x;
+            if (cursor_row > w->current_matrix->rows
+                && MATRIX_ROW_OVERLAPS_SUCC_P (cursor_row - 1))
+              x_fix_overlapping_area (w, cursor_row - 1, TEXT_AREA,
+                    OVERLAPS_ERASED_CURSOR);
+            if (MATRIX_ROW_BOTTOM_Y (cursor_row) < window_text_bottom_y (w)
+                && MATRIX_ROW_OVERLAPS_PRED_P (cursor_row + 1))
+              x_fix_overlapping_area (w, cursor_row + 1, TEXT_AREA,
+                    OVERLAPS_ERASED_CURSOR);
+          }
+    }
+  mark_cursor_off:
+  Qnil;
+}
+
+void
+mc_draw (struct window *w, bool on, EMACS_INT x, EMACS_INT y, EMACS_INT hpos, EMACS_INT vpos,
+                           enum text_cursor_kinds cursor_type, int cursor_width, int red, int green, int blue)
+{
+  int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+  if (header_line_height > 0)
+    vpos = vpos + 1;
+  struct frame *f = XFRAME (w->frame);
+  bool active_cursor;
+  struct glyph_row *glyph_row;
+  struct glyph *glyph;
+  int prior_hpos, prior_vpos, prior_x, prior_y;
+  glyph_row = MATRIX_ROW (w->current_matrix, vpos);
+  glyph = NULL;
+  if (!glyph_row->exact_window_width_line_p
+      || (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
+    glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
+  eassert (input_blocked_p ());
+  w->phys_cursor_ascent = glyph_row->ascent;
+  w->phys_cursor_height = glyph_row->height;
+  /* Record the current values for w->phys_cursor.x/y/hpos/vpos.  */
+  prior_hpos = w->phys_cursor.hpos;
+  prior_vpos = w->phys_cursor.vpos;
+  prior_x = w->phys_cursor.x;
+  prior_y = w->phys_cursor.y;
+  /* Hijack w->phys_cursor.x/y/hpos/vpos by setting new values.  */
+  w->phys_cursor.hpos = hpos;
+  w->phys_cursor.vpos = vpos;
+  w->phys_cursor.x = x;
+  w->phys_cursor.y = glyph_row->y;
+  FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on, active_cursor, red, green, blue);
+  /* Restore the previous values for w->phys_cursor.x/y/hpos/vpos.  */
+  w->phys_cursor.hpos = prior_hpos;
+  w->phys_cursor.vpos = prior_vpos;
+  w->phys_cursor.x = prior_x;
+  w->phys_cursor.y = prior_y;
+}
+
+Lisp_Object
+mc_x_y_hpos_vpos (struct window *w, EMACS_INT posint)
+{
+  struct it it;
+  void *itdata = bidi_shelve_cache ();
+  struct text_pos pt;
+  struct text_pos pos;
+  int x, y, hpos, vpos;
+  if (w->window_start_end_hook_int_window_start
+      && w->window_start_end_hook_int_window_end
+      && posint >= w->window_start_end_hook_int_window_start
+      && posint <= w->window_start_end_hook_int_window_end)
+    {
+      SET_TEXT_POS_FROM_MARKER (pt, w->start);
+      start_display (&it, w, pt);
+      move_it_to (&it, posint, -1, -1, -1, MOVE_TO_POS);
+      pos = it.current.pos;
+      x = it.current_x;
+      y = it.current_y;
+      hpos = it.hpos;
+      vpos = it.vpos;
+      bidi_unshelve_cache (itdata, false);
+    }
+    else
+      {
+        x = -1;
+        y = -1;
+        hpos = -1;
+        vpos = -1;
+      }
+  return listn (CONSTYPE_PURE, 4, make_number (x), make_number (y), make_number (hpos), make_number (vpos));
+}
+
+int
+mc_lisp_to_cursor_type (Lisp_Object arg)
+{
+  char *str;
+  if (XTYPE (arg) == Lisp_String)
+    str = SSDATA (arg);
+  else if (XTYPE (arg) == Lisp_Symbol)
+    str = SSDATA (SYMBOL_NAME (arg));
+  else return -1;
+  if (!strcmp (str, "box"))
+    return FILLED_BOX_CURSOR;
+  if (!strcmp (str, "hollow"))
+    return HOLLOW_BOX_CURSOR;
+  if (!strcmp (str, "hbar"))
+    return HBAR_CURSOR;
+  if (!strcmp (str, "bar"))
+    return BAR_CURSOR;
+  if (!strcmp (str, "no"))
+    return NO_CURSOR;
+  return -1;
+}
+
+/* EXAMPLE #1:  (setq mc-list '((3 "hbar" [1.0 0.0 0.0])
+                                (4 "vbar" [0.0 1.0 1.0])
+                                (5 "box" [1.0 1.0 1.0])
+                                (6 "hollow" [1.0 0.0 1.0])
+                                (7 ("hbar" 3) [1.0 0.0 0.0])
+                                (8 ("vbar" 3) [0.0 1.0 1.0])))
+   EXAMPLE #2:  (setq mc-list nil)
+The `mc_cache' is kept in the following example format:
+'((
+  (3 "hbar" [1.0 0.0 0.0])
+  (4 "vbar" [0.0 1.0 1.0])
+  (5 "box" [1.0 1.0 1.0])
+  (6 "hollow" [1.0 0.0 1.0])
+  (7 ("hbar" 3) [1.0 0.0 0.0])
+  (8 ("vbar" 3) [0.0 1.0 1.0]))
+ ((5
+   (44 20 4 0))
+  (6
+   (55 20 5 0))
+  (7
+   (66 20 6 0))
+  (8
+   (77 20 7 0))
+  (9
+   (88 20 8 0))
+  (10
+   (99 20 9 0))))
+To inspect the lisp object, use:
+  AUTO_STRING (format, "This is the lisp object value of mc_list:  %s");
+  CALLN (Fmessage, format, w->mc_list);  */
+void
+mc_calc (struct window *w)
+{
+  struct frame *f = XFRAME (w->frame);
+  struct window *sw = XWINDOW (f->selected_window);
+  enum text_cursor_kinds cursor_type = Qnil;
+  int cursor_width = 1;
+  int red, green, blue;
+  EMACS_INT posint, x, y, hpos, vpos;
+  Lisp_Object cursor_spec_list, cursor_spec_type, cursor_color_vector, vlist, x_y_hpos_vpos_list, buf;
+  Lisp_Object temp = Qnil;
+  Lisp_Object result = Qnil;
+  struct text_pos startp;
+  struct buffer *b;
+  buf = w->contents;
+  CHECK_BUFFER (buf);
+  b = XBUFFER (buf);
+  struct buffer *old_buffer = NULL;
+  struct it it;
+  void *itdata = NULL;
+  struct text_pos pt;
+  struct text_pos test_pos;
+  int test_x, test_y, test_hpos, test_vpos;
+  if (b != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal (b);
+    }
+  if (Fminibufferp (buf))
+    goto done;
+  if (w->mc_cache
+      && (NILP (Fequal (Fnth (make_number (0), w->mc_cache), BVAR (current_buffer, mc_list)))
+          || w != sw))
+    {
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "mc_calc:  remove cursors using cache");
+#endif
+      for (vlist = XCAR (XCDR (w->mc_cache));
+           CONSP (vlist);
+           vlist = XCDR (vlist))
+        {
+          cursor_spec_list = XCAR (XCAR (vlist));
+          posint = XINT (Fnth (make_number (0), cursor_spec_list));
+          cursor_spec_type = Fnth (make_number (1), cursor_spec_list);
+          if (CONSP (cursor_spec_type))
+            cursor_type = mc_lisp_to_cursor_type (XCAR (cursor_spec_type));
+            else
+              cursor_type = mc_lisp_to_cursor_type (cursor_spec_type);
+          if (CONSP (cursor_spec_type))
+            cursor_width = XINT (XCAR (XCDR (cursor_spec_type)));
+            else
+              cursor_width = 1;
+          cursor_color_vector = Fnth (make_number (2), cursor_spec_list);
+          red = XFLOAT_DATA (AREF (cursor_color_vector, 0));
+          green = XFLOAT_DATA (AREF (cursor_color_vector, 1));
+          blue = XFLOAT_DATA (AREF (cursor_color_vector, 2));
+          if (posint
+              && w->window_start_end_hook_int_window_start
+              && w->window_start_end_hook_int_window_end
+              && posint >= w->window_start_end_hook_int_window_start
+              && posint <= w->window_start_end_hook_int_window_end)
+            {
+              x_y_hpos_vpos_list = XCAR (XCDR (XCAR (vlist)));
+              x = XINT (Fnth (make_number (0), x_y_hpos_vpos_list));
+              y = XINT (Fnth (make_number (1), x_y_hpos_vpos_list));
+              hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos_list));
+              vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos_list));
+              mc_erase (w, x, y, hpos, vpos, cursor_type, cursor_width, red, green, blue);
+            }
+        }
+      w->mc_cache = Qnil;
+    }
+    else if (w == sw
+            && w->window_start_end_hook_int_window_start
+            && w->window_start_end_hook_int_window_end
+            && w->window_start_end_hook_int_previous_window_start
+            && w->window_start_end_hook_int_previous_window_end
+            && w->window_start_end_hook_int_window_start == w->window_start_end_hook_int_previous_window_start
+            && w->window_start_end_hook_int_window_end == w->window_start_end_hook_int_previous_window_end
+            && !NILP (BVAR (current_buffer, mc_list))
+            && w->mc_cache
+            && !NILP (Fequal (Fnth (make_number (0), w->mc_cache), BVAR (current_buffer, mc_list))))
+      {
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "mc_calc:  draw cursors using cache");
+#endif
+        for (vlist = XCAR (XCDR (w->mc_cache));
+             CONSP (vlist);
+             vlist = XCDR (vlist))
+          {
+            cursor_spec_list = XCAR (XCAR (vlist));
+            posint = XINT (Fnth (make_number (0), cursor_spec_list));
+            cursor_spec_type = Fnth (make_number (1), cursor_spec_list);
+            if (CONSP (cursor_spec_type))
+              cursor_type = mc_lisp_to_cursor_type (XCAR (cursor_spec_type));
+              else
+                cursor_type = mc_lisp_to_cursor_type (cursor_spec_type);
+            if (CONSP (cursor_spec_type))
+              cursor_width = XINT (XCAR (XCDR (cursor_spec_type)));
+              else
+                cursor_width = 1;
+            cursor_color_vector = Fnth (make_number (2), cursor_spec_list);
+            red = XFLOAT_DATA (AREF (cursor_color_vector, 0));
+            green = XFLOAT_DATA (AREF (cursor_color_vector, 1));
+            blue = XFLOAT_DATA (AREF (cursor_color_vector, 2));
+            if (posint
+                && w->window_start_end_hook_int_window_start
+                && w->window_start_end_hook_int_window_end
+                && posint >= w->window_start_end_hook_int_window_start
+                && posint <= w->window_start_end_hook_int_window_end)
+              {
+                x_y_hpos_vpos_list = XCAR (XCDR (XCAR (vlist)));
+                x = XINT (Fnth (make_number (0), x_y_hpos_vpos_list));
+                y = XINT (Fnth (make_number (1), x_y_hpos_vpos_list));
+                hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos_list));
+                vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos_list));
+                mc_draw (w, 1, x, y, hpos, vpos, cursor_type, cursor_width, red, green, blue);
+              }
+          }
+      }
+      else if (w == sw
+               && !NILP (BVAR (current_buffer, mc_list)))
+        {
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "mc_calc:  draw cursors anew");
+#endif
+          for (vlist = BVAR (current_buffer, mc_list);
+               CONSP (vlist);
+               vlist = XCDR (vlist))
+            {
+              cursor_spec_list = XCAR (vlist);
+              posint = XINT (Fnth (make_number (0), cursor_spec_list));
+              cursor_spec_type = Fnth (make_number (1), cursor_spec_list);
+              if (CONSP (cursor_spec_type))
+                cursor_type = mc_lisp_to_cursor_type (XCAR (cursor_spec_type));
+                else
+                  cursor_type = mc_lisp_to_cursor_type (cursor_spec_type);
+              if (CONSP (cursor_spec_type))
+                cursor_width = XINT (XCAR (XCDR (cursor_spec_type)));
+                else
+                  cursor_width = 1;
+              cursor_color_vector = Fnth (make_number (2), cursor_spec_list);
+              red = XFLOAT_DATA (AREF (cursor_color_vector, 0));
+              green = XFLOAT_DATA (AREF (cursor_color_vector, 1));
+              blue = XFLOAT_DATA (AREF (cursor_color_vector, 2));
+              if (posint)
+                {
+                  x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, posint);
+                  temp = Fcons (cursor_spec_list, Fcons (x_y_hpos_vpos_list, Qnil));
+                  result = Fcons (temp, result);
+                  x = XINT (Fnth (make_number (0), x_y_hpos_vpos_list));
+                  y = XINT (Fnth (make_number (1), x_y_hpos_vpos_list));
+                  hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos_list));
+                  vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos_list));
+                  if (w->window_start_end_hook_int_window_start
+                      && w->window_start_end_hook_int_window_end
+                      && posint >= w->window_start_end_hook_int_window_start
+                      && posint <= w->window_start_end_hook_int_window_end)
+                    mc_draw (w, 1, x, y, hpos, vpos, cursor_type, cursor_width, red, green, blue);
+                }
+            }
+          w->mc_cache = Fcons (BVAR (current_buffer, mc_list), Fcons (Freverse (result), Qnil));
+        }
+  done:
+  if (old_buffer)
+    set_buffer_internal (old_buffer);
+}
 
 /* Display or clear cursor of window W.  If !ON, clear the cursor.
    If ON, display the cursor; where to put the cursor is specified by
@@ -28322,7 +29195,7 @@ erase_phys_cursor (struct window *w)
 
 void
 display_and_set_cursor (struct window *w, bool on,
-			int hpos, int vpos, int x, int y)
+			int hpos, int vpos, int x, int y, char *string)
 {
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
@@ -28330,6 +29203,20 @@ display_and_set_cursor (struct window *w, bool on,
   bool active_cursor;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
+  /* These are not being used per se in `display_and_set_cursor', but the arguments have been
+  added to `draw_window_cursor`.  We need them as argument place holders.  If the values for
+  red/green/blue are not all greater than or equal to 0, then the default cursor_color prevails.  */
+  enum text_cursor_kinds cursor_type = Qnil;
+  int cursor_width = 1;
+  float red = -1.0;
+  float blue = -1.0;
+  float green = -1.0;
+
+/*
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "display_and_set_cursor:  %s", string);
+#endif
+*/
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
@@ -28379,7 +29266,7 @@ display_and_set_cursor (struct window *w, bool on,
 	  || new_cursor_type != w->phys_cursor_type
 	  || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
 	      && new_cursor_width != w->phys_cursor_width)))
-    erase_phys_cursor (w);
+    erase_phys_cursor (w, "xdisp.c: 1 of 1");
 
   /* Don't check phys_cursor_on_p here because that flag is only set
      to false in some cases where we know that the cursor has been
@@ -28401,7 +29288,15 @@ display_and_set_cursor (struct window *w, bool on,
 
   FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
                                      new_cursor_type, new_cursor_width,
-                                     on, active_cursor);
+                                     on, active_cursor, red, green, blue);
+
+  /* `mc_calc' must follow the creation of the original/master cursor so that a fake cursor
+  is not erroneously erased during the process by the original/master cursor.  xdisp: 1 of 2
+  caused erroneous multiple cursors to be placed on the line at the top of the window when
+  interactively calling `beginning-of-buffer'.*/
+  if (NILP (Fequal (build_string (string), build_string ("xdisp: 1 of 2"))))
+    mc_calc (w);
+
 }
 
 
@@ -28435,7 +29330,7 @@ update_window_cursor (struct window *w, bool on)
 
       block_input ();
       display_and_set_cursor (w, on, hpos, vpos,
-			      w->phys_cursor.x, w->phys_cursor.y);
+			      w->phys_cursor.x, w->phys_cursor.y, "xdisp: 1 of 2");
       unblock_input ();
     }
 }
@@ -28614,7 +29509,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
 
 	  block_input ();
 	  display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
-				  w->phys_cursor.x, w->phys_cursor.y);
+				  w->phys_cursor.x, w->phys_cursor.y, "xdisp: 2 of 2");
 	  unblock_input ();
 	}
 #endif	/* HAVE_WINDOW_SYSTEM */
@@ -31117,11 +32012,16 @@ They are still logged to the *Messages* buffer.  */);
   defsubr (&Swindow_text_pixel_size);
   defsubr (&Smove_point_visually);
   defsubr (&Sbidi_find_overridden_directionality);
+  defsubr (&Sline_number_at_position);
+  defsubr (&Sposn_fn);
 
   DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
   DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
   DEFSYM (Qoverriding_local_map, "overriding-local-map");
   DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
+  DEFSYM (Qline_number_at_position, "line-number-at-position");
+  DEFSYM (Qposn_fn, "posn-fn");
+  DEFSYM (Qcolor_vector_calc, "color-vector-calc");
   DEFSYM (Qwindow_text_change_functions, "window-text-change-functions");
   DEFSYM (Qredisplay_end_trigger_functions, "redisplay-end-trigger-functions");
   DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
diff --git a/src/xterm.c b/src/xterm.c
index 1f71afd..a991e9f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1151,7 +1151,7 @@ x_update_window_end (struct window *w, bool cursor_on_p,
       if (cursor_on_p)
 	display_and_set_cursor (w, true,
 				w->output_cursor.hpos, w->output_cursor.vpos,
-				w->output_cursor.x, w->output_cursor.y);
+				w->output_cursor.x, w->output_cursor.y, "xterm.c:1152");
 
       if (draw_window_fringes (w, true))
 	{
@@ -8935,7 +8935,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
     {
       struct glyph_row *r;
       r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
-      draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
+      draw_phys_cursor_glyph (w, r, DRAW_CURSOR, "xterm.c: 8938");
     }
   else
     {
@@ -9044,7 +9044,7 @@ x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
 static void
 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
 		      int y, enum text_cursor_kinds cursor_type,
-		      int cursor_width, bool on_p, bool active_p)
+		      int cursor_width, bool on_p, bool active_p, int red, int green, int blue)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
@@ -9070,7 +9070,7 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
 	      break;
 
 	    case FILLED_BOX_CURSOR:
-	      draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+	      draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR, "xterm.c:9073");
 	      break;
 
 	    case BAR_CURSOR:
