diff --git a/src/buffer.c b/src/buffer.c
index c6f9eb2..6859320 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5126,6 +5126,15 @@ init_buffer_once (void)
   bset_last_selected_window (&buffer_local_flags, make_number (0));
 
   idx = 1;
+/* *************************************************************************** */
+/* multiple cursors */
+
+  XSETFASTINT (BVAR (&buffer_local_flags, mc_glyph_list), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, crosshairs), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, crosshairs_horizontal_ruler), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, crosshairs_vertical_ruler), idx); ++idx;
+
+/* *************************************************************************** */
   XSETFASTINT (BVAR (&buffer_local_flags, mode_line_format), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, abbrev_mode), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, overwrite_mode), idx); ++idx;
@@ -5205,6 +5214,15 @@ init_buffer_once (void)
   /* Must do these before making the first buffer! */
 
   /* real setup is done in bindings.el */
+/* *************************************************************************** */
+/* multiple cursors */
+
+  bset_blv_mc_glyph_list (&buffer_defaults, Qnil);
+  bset_blv_crosshairs (&buffer_defaults, Qnil);
+  bset_blv_crosshairs_horizontal_ruler (&buffer_defaults, Qt);
+  bset_blv_crosshairs_vertical_ruler (&buffer_defaults, Qt);
+
+/* *************************************************************************** */
   bset_mode_line_format (&buffer_defaults, build_pure_c_string ("%-"));
   bset_header_line_format (&buffer_defaults, Qnil);
   bset_abbrev_mode (&buffer_defaults, Qnil);
@@ -5453,6 +5471,16 @@ syms_of_buffer (void)
   staticpro (&QSFundamental);
   staticpro (&Vbuffer_alist);
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+  DEFSYM (Qmc_glyph_list, "mc-glyph-list");
+  DEFSYM (Qcrosshairs, "crosshairs");
+  DEFSYM (Qcrosshairs_horizontal_ruler, "crosshairs-horizontal-ruler");
+  DEFSYM (Qcrosshairs_vertical_ruler, "crosshairs-vertical-ruler");
+
+/* *************************************************************************** */
+
   DEFSYM (Qchoice, "choice");
   DEFSYM (Qleft, "left");
   DEFSYM (Qright, "right");
@@ -5490,6 +5518,24 @@ syms_of_buffer (void)
   Fput (Qprotected_field, Qerror_message,
 	build_pure_c_string ("Attempt to modify a protected field"));
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+  DEFVAR_PER_BUFFER ("mc-glyph-list", &BVAR (current_buffer, mc_glyph_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 ("crosshairs", &BVAR (current_buffer, crosshairs), Qnil,
+    doc: /* A bufer-local variable to activate/deactivate crosshairs.  */);
+
+  DEFVAR_PER_BUFFER ("crosshairs-horizontal-ruler", &BVAR (current_buffer, crosshairs_horizontal_ruler), Qnil,
+    doc: /* A bufer-local variable to activate/deactivate the crosshairs horizontal ruler.  */);
+
+  DEFVAR_PER_BUFFER ("crosshairs-vertical-ruler", &BVAR (current_buffer, crosshairs_vertical_ruler), Qnil,
+    doc: /* A bufer-local variable to activate/deactivate the crosshairs vertical ruler.  */);
+
+/* *************************************************************************** */
+
   DEFVAR_PER_BUFFER ("header-line-format",
 		     &BVAR (current_buffer, header_line_format),
 		     Qnil,
diff --git a/src/buffer.h b/src/buffer.h
index 46c7c6e..8bde95e 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -658,6 +658,23 @@ struct buffer
      cache are enabled.  See search.c, indent.c and bidi.c for details.  */
   Lisp_Object cache_long_scans_;
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+  /* The name of list used by multiple cursors for next redisplay.  */
+  Lisp_Object mc_glyph_list_;
+
+  /* The name of list.  */
+  Lisp_Object crosshairs_;
+
+  /* The name of the crosshairs horizontal ruler.  */
+  Lisp_Object crosshairs_horizontal_ruler_;
+
+  /* The name of the crosshairs vertical ruler.  */
+  Lisp_Object crosshairs_vertical_ruler_;
+
+/* *************************************************************************** */
+
   /* 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
@@ -918,6 +935,36 @@ XBUFFER (Lisp_Object a)
 /* Most code should use these functions to set Lisp fields in struct
    buffer.  (Some setters that are private to a single .c file are
    defined as static in those files.)  */
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+INLINE void
+bset_blv_mc_glyph_list (struct buffer *b, Lisp_Object val)
+{
+  b->mc_glyph_list_ = val;
+}
+
+INLINE void
+bset_blv_crosshairs (struct buffer *b, Lisp_Object val)
+{
+  b->crosshairs_ = val;
+}
+
+INLINE void
+bset_blv_crosshairs_horizontal_ruler (struct buffer *b, Lisp_Object val)
+{
+  b->crosshairs_horizontal_ruler_ = val;
+}
+
+INLINE void
+bset_blv_crosshairs_vertical_ruler (struct buffer *b, Lisp_Object val)
+{
+  b->crosshairs_vertical_ruler_ = val;
+}
+
+/* *************************************************************************** */
+
 INLINE void
 bset_bidi_paragraph_direction (struct buffer *b, Lisp_Object val)
 {
diff --git a/src/dispextern.h b/src/dispextern.h
index 430afbf..f1d5415 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2889,7 +2889,13 @@ 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);
+/* *************************************************************************** */
+/* multiple cursors */
+
+         int cursor_width, bool on_p, bool active_p,
+         Lisp_Object color_vector, Lisp_Object flavor);
+
+/* *************************************************************************** */
 
   /* Draw vertical border for window W from (X,Y_0) to (X,Y_1).  */
   void (*draw_vertical_window_border) (struct window *w,
@@ -3274,6 +3280,13 @@ extern void get_font_ascent_descent (struct font *, int *, int *);
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+void mc_portal (struct window *, bool);
+
+/* *************************************************************************** */
+
 #ifdef GLYPH_DEBUG
 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
 #endif
diff --git a/src/fringe.c b/src/fringe.c
index 087ef33..103bbb6 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -431,6 +431,224 @@ static unsigned short empty_line_bits[] = {
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
 
+/* *************************************************************************** */
+/* multiple cursors
+
+/*  ;; AUTHOR:  Nikolaj Schumacher -- https://github.com/nschum/fringe-helper.el
+    (defun +-fringe-helper-hexadecimal (&rest strings)
+    "Convert STRINGS into a vector usable for `define-fringe-bitmap'.
+    Each string in STRINGS represents a line of the fringe bitmap.
+    Periods (.) are background-colored pixel; Xs are foreground-colored. The
+    fringe bitmap always is aligned to the right. If the fringe has half
+    width, only the left 4 pixels of an 8 pixel bitmap will be shown.
+    For example, the following code defines a diagonal line.
+    \(+-fringe-helper-hexadecimal
+    \"XX......\"
+    \"..XX....\"
+    \"....XX..\"
+    \"......XX\"\)"
+      (unless (cdr strings)
+        (setq strings (split-string (car strings) "\n")))
+      (apply 'vector
+        (mapcar
+          (lambda (str)
+            (let ((num 0))
+              (dolist (c (string-to-list str))
+                (setq num (+ (* num 2) (if (eq c ?.) 0 1))))
+              (format "%#-x" num)))
+          strings)))
+*/
+
+/* 24
+    (+-fringe-helper-hexadecimal
+      "x......."
+      "x......."
+      "x......."
+      "x..xx..."
+      "x...xx.."
+      "x....xx."
+      "x.xxxxxx"
+      "x.xxxxxx"
+      "x....xx."
+      "x...xx.."
+      "x..xx..."
+      "x......."
+      "x......."
+      "x.......")
+*/
+static unsigned short mc_vertical_bar_right_angle_bits[] ={
+  0x80, 0x80, 0x80, 0x98, 0x8c, 0x86, 0xbf,
+  0xbf, 0x86, 0x8c, 0x98, 0x80, 0x80, 0x80};
+
+/* 25
+    (+-fringe-helper-hexadecimal
+      "xxxxxxxx"
+      "x......x"
+      "x......x"
+      "x..xx..x"
+      "x...xx.x"
+      "x....xxx"
+      "x.xxxxxx"
+      "x.xxxxxx"
+      "x....xxx"
+      "x...xx.x"
+      "x..xx..x"
+      "x......x"
+      "x......x"
+      "xxxxxxxx")
+*/
+static unsigned short mc_hollow_rectangle_right_angle_bits[] ={
+  0xff, 0x81, 0x81, 0x99, 0x8d, 0x87, 0xbf,
+  0xbf, 0x87, 0x8d, 0x99, 0x81, 0x81, 0xff};
+
+/* 26
+    (+-fringe-helper-hexadecimal
+      "xxxxxxxx"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "x......x"
+      "xxxxxxxx")
+*/
+static unsigned short mc_hollow_rectangle_bits[] ={
+  0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff};
+
+/* 27
+    (+-fringe-helper-hexadecimal
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x......."
+      "x.......")
+*/
+static unsigned short mc_vertical_bar_bits[] ={
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
+
+/* 28
+    (+-fringe-helper-hexadecimal
+      "xx......"
+      ".xx....."
+      "..xx...."
+      "...xx..."
+      "....xx.."
+      ".....xx."
+      "......xx"
+      ".....xx."
+      "....xx.."
+      "...xx..."
+      "..xx...."
+      ".xx....."
+      "xx......")
+*/
+static unsigned short mc_right_angle_bits[] ={
+  0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0};
+
+/* 29
+    (+-fringe-helper-hexadecimal
+      "xx......"
+      "xx......"
+      " xx....."
+      ".xx....."
+      "..xx...."
+      "..xx...."
+      "...xx..."
+      "...xx..."
+      "....xx.."
+      "....xx.."
+      ".....xx."
+      ".....xx."
+      "......xx"
+      "......xx")
+*/
+static unsigned short mc_backslash_bits[] ={
+  0xc0, 0xc0, 0xe0, 0x60, 0x30, 0x30, 0x18, 0x18, 0xc, 0xc, 0x6, 0x6, 0x3, 0x3};
+
+/* 30
+    (+-fringe-helper-hexadecimal
+      "xx......"
+      "xx......"
+      "xxx....."
+      "xxx....."
+      "x.xx...."
+      "x.xx...."
+      "x..xx..."
+      "x..xx..."
+      "x...xx.."
+      "x...xx.."
+      "x....xx."
+      "x....xx."
+      "x.....xx"
+      "x.....xx")
+*/
+static unsigned short mc_vertical_bar_backslash_bits[] ={
+  0xc0, 0xc0, 0xe0, 0xe0, 0xb0, 0xb0, 0x98,
+  0x98, 0x8c, 0x8c, 0x86, 0x86, 0x83, 0x83};
+
+/* 31
+    (+-fringe-helper-hexadecimal
+      ".xxxxxx."
+      "xxxx.x.."
+      "xxxx.x.."
+      "xxxx.x.."
+      ".xxx.x.."
+      "...x.x.."
+      "...x.x.."
+      "...x.x.."
+      "...x.x.."
+      "...x.x.."
+      "...x.x..")
+*/
+static unsigned short mc_pilcrow_bits[] ={
+  0x7e, 0xf4, 0xf4, 0xf4, 0x74, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14};
+
+/* 32
+    (+-fringe-helper-hexadecimal
+      "xx.xx..."
+      ".xx.xx.."
+      "..xx.xx."
+      "...xx.xx"
+      "..xx.xx."
+      ".xx.xx.."
+      "xx.xx...")
+*/
+static unsigned short mc_right_double_angle_bits[] ={
+  0xd8, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0xd8};
+
+/* 33
+    (+-fringe-helper-hexadecimal
+      "..xxxx.."
+      ".xxxxxx."
+      "x..xx..x"
+      "x..xx..x"
+      "xxxxxxxx"
+      "xx....xx"
+      "xxx..xxx"
+      ".xxxxxx."
+      "..xxxx..")
+*/
+static unsigned short mc_smiley_face_bits[] ={
+  0x3c, 0x7e, 0x99, 0x99, 0xff, 0xc3, 0xe7, 0x7e, 0x3c};
+
+/* *************************************************************************** */
 
 #define BYTES_PER_BITMAP_ROW  (sizeof (unsigned short))
 #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
@@ -465,6 +683,31 @@ static struct fringe_bitmap standard_bitmaps[] =
   { FRBITS (vertical_bar_bits),       8, 0, ALIGN_BITMAP_CENTER, 0 },
   { FRBITS (horizontal_bar_bits),     8, 0, ALIGN_BITMAP_BOTTOM, 0 },
   { FRBITS (empty_line_bits),         8, 3, ALIGN_BITMAP_TOP,    0 },
+/* *************************************************************************** */
+/* multiple cursors */
+
+  /* 24 */
+  { FRBITS (mc_vertical_bar_right_angle_bits),     8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 25 */
+  { FRBITS (mc_hollow_rectangle_right_angle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 26 */
+  { FRBITS (mc_hollow_rectangle_bits),             8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 27 */
+  { FRBITS (mc_vertical_bar_bits),                 8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 28 */
+  { FRBITS (mc_right_angle_bits),         8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 29 */
+  { FRBITS (mc_backslash_bits),                    8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 30 */
+  { FRBITS (mc_vertical_bar_backslash_bits),       8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 31 */
+  { FRBITS (mc_pilcrow_bits),                      8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 32 */
+  { FRBITS (mc_right_double_angle_bits),           8, 0, ALIGN_BITMAP_CENTER, 0 },
+  /* 33 */
+  { FRBITS (mc_smiley_face_bits),                  8, 0, ALIGN_BITMAP_CENTER, 0 },
+
+/* *************************************************************************** */
 };
 
 #define NO_FRINGE_BITMAP 0
@@ -1722,6 +1965,75 @@ If nil, also continue lines which are exactly as wide as the window.  */);
   DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps,
     doc: /* List of fringe bitmap symbols.  */);
   Vfringe_bitmaps = Qnil;
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+  /* (get 'empty-line 'fringe) => 23 => the last standard-bitmap before this one.
+  See `fringe.el`. */
+
+  /* 24 */
+  DEFSYM (Qmc_vertical_bar_right_angle, "+-vertical-bar-right-angle");
+  Vfringe_bitmaps = Fcons (Qmc_vertical_bar_right_angle, Vfringe_bitmaps);
+  Fput (Qmc_vertical_bar_right_angle, Qfringe, make_number (24));
+  /* (get '+-vertical-bar-right-angle 'fringe) => 24 */
+
+  /* 25 */
+  DEFSYM (Qmc_hollow_rectangle_right_angle, "+-hollow-rectangle-right-angle");
+  Vfringe_bitmaps = Fcons (Qmc_hollow_rectangle_right_angle, Vfringe_bitmaps);
+  Fput (Qmc_hollow_rectangle_right_angle, Qfringe, make_number (25));
+  /* (get '+-hollow-rectangle-right-angle 'fringe) => 25 */
+
+  /* 26 */
+  DEFSYM (Qmc_hollow_rectangle, "+-hollow-rectangle");
+  Vfringe_bitmaps = Fcons (Qmc_hollow_rectangle, Vfringe_bitmaps);
+  Fput (Qmc_hollow_rectangle, Qfringe, make_number (26));
+  /* (get '+-hollow-rectangle 'fringe) => 26 */
+
+  /* 27 */
+  DEFSYM (Qmc_vertical_bar, "+-vertical-bar");
+  Vfringe_bitmaps = Fcons (Qmc_vertical_bar, Vfringe_bitmaps);
+  Fput (Qmc_vertical_bar, Qfringe, make_number (27));
+  /* (get '+-vertical-bar 'fringe) => 27 */
+
+  /* 28 */
+  DEFSYM (Qmc_right_angle, "+-right-angle");
+  Vfringe_bitmaps = Fcons (Qmc_right_angle, Vfringe_bitmaps);
+  Fput (Qmc_right_angle, Qfringe, make_number (28));
+  /* (get '+-right-angle 'fringe) => 28 */
+
+  /* 29 */
+  DEFSYM (Qmc_backslash, "+-backslash");
+  Vfringe_bitmaps = Fcons (Qmc_backslash, Vfringe_bitmaps);
+  Fput (Qmc_backslash, Qfringe, make_number (29));
+  /* (get '+-backslash 'fringe) => 29 */
+
+  /* 30 */
+  DEFSYM (Qmc_vertical_bar_backslash, "+-vertical-bar-backslash");
+  Vfringe_bitmaps = Fcons (Qmc_vertical_bar_backslash, Vfringe_bitmaps);
+  Fput (Qmc_vertical_bar_backslash, Qfringe, make_number (30));
+  /* (get '+-vertical-bar-backslash 'fringe) => 30 */
+
+  /* 31 */
+  DEFSYM (Qmc_pilcrow, "+-pilcrow");
+  Vfringe_bitmaps = Fcons (Qmc_pilcrow, Vfringe_bitmaps);
+  Fput (Qmc_pilcrow, Qfringe, make_number (31));
+  /* (get '+-pilcrow 'fringe) => 31 */
+
+  /* 32 */
+  DEFSYM (Qmc_right_double_angle, "+-right-double-angle");
+  Vfringe_bitmaps = Fcons (Qmc_right_double_angle, Vfringe_bitmaps);
+  Fput (Qmc_right_double_angle, Qfringe, make_number (32));
+  /* (get '+-right-double-angle 'fringe) => 32 */
+
+  /* 33 */
+  DEFSYM (Qmc_smiley_face, "+-smiley-face");
+  Vfringe_bitmaps = Fcons (Qmc_smiley_face, Vfringe_bitmaps);
+  Fput (Qmc_smiley_face, Qfringe, make_number (33));
+  /* (get '+-smiley-face 'fringe) => 33 */
+
+/* *************************************************************************** */
+
 }
 
 /* Garbage collection hook */
diff --git a/src/keyboard.c b/src/keyboard.c
index 57757cf..0b54433 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1254,6 +1254,27 @@ static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
                               bool, bool, bool, bool);
 static void adjust_point_for_property (ptrdiff_t, bool);
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+static void
+kbd_mc_activate_cursors (void)
+{
+  struct window *w = decode_live_window (selected_window);
+  w->mc.draw_glyph_cursor = true;
+  w->mc.erase_glyph_cursor = true;
+}
+
+static void
+kbd_mc_activate_crosshairs (void)
+{
+  struct window *w = decode_live_window (selected_window);
+  w->mc.draw_crosshairs = true;
+  w->mc.erase_crosshairs = true;
+}
+
+/* *************************************************************************** */
+
 Lisp_Object
 command_loop_1 (void)
 {
@@ -1450,6 +1471,13 @@ command_loop_1 (void)
       Vreal_this_command = cmd;
       safe_run_hooks (Qpre_command_hook);
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+      kbd_mc_activate_cursors ();
+
+/* *************************************************************************** */
+
       already_adjusted = 0;
 
       if (NILP (Vthis_command))
diff --git a/src/nsterm.m b/src/nsterm.m
index 50e06c9..9679362 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1134,10 +1134,12 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
     {
       block_input ();
 
-      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);
+/* *************************************************************************** */
+/* multiple cursors */
+
+      mc_portal (w, cursor_on_p);
+
+/* *************************************************************************** */
 
       if (draw_window_fringes (w, 1))
 	{
@@ -3005,7 +3007,13 @@ so some key presses (TAB) are swallowed by the system. */
 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)
+/* *************************************************************************** */
+/* multiple cursors */
+
+  int cursor_width, bool on_p, bool active_p,
+  Lisp_Object color_vector, Lisp_Object flavor)
+
+/* *************************************************************************** */
 /* --------------------------------------------------------------------------
      External call (RIF): draw cursor.
      Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
@@ -3039,8 +3047,29 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
 
   if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
     {
-      if (glyph_row->exact_window_width_line_p
-          && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+      /* This modification enables placement of the cursor-in-fringe bitmap when
+      the window-width is slightly less than `glyph_row->exact_window_width_line_p`.
+      This modification also prevents drawing the real cursor on the fringe (instead
+      of using the cursor-in-fringe bitmap) in the above-mentioned circumstance.
+      See the following related patches:
+      -  July 19, 2016:  bf5ddded70c11edaf3514b25da27fc71cfb8e965
+      -  May 21, 2016:  e5015c5d9632a0bf685c093249ae4a7d3e825b13
+      See the following bug reports:  #16856 and #29233. */
+      int frame_char_width = FRAME_COLUMN_WIDTH (f);
+      int text_area_width = window_box_width (w, TEXT_AREA);
+      bool cursor_in_fringe_p = w->phys_cursor.x + frame_char_width >= text_area_width;
+      if ((glyph_row->exact_window_width_line_p
+            && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+          || cursor_in_fringe_p)
+
+/* *************************************************************************** */
+
+
         {
           glyph_row->cursor_in_fringe_p = 1;
           draw_fringe_bitmap (w, glyph_row, 0);
@@ -3085,8 +3114,47 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
 
 
   face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id);
-  if (face && NS_FACE_BACKGROUND (face)
-      == ns_index_color (FRAME_CURSOR_COLOR (f), f))
+
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+/* EXAMPLE OF HOW TO LOOK-UP A COLOR:
+  enum face_id face_id = lookup_named_face (f, intern ("+-vertical-bar-face"), true);
+  struct face *face = FACE_FROM_ID (f, face_id);
+  NSColor *color = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f);
+*/
+
+  if (EQ (flavor, Qmc_glyph)
+      || EQ (flavor, Qmc_glyphless)
+      || EQ (flavor, Qmc_glyph_tab))
+    {
+      Lisp_Object buf = w->contents;
+      CHECK_BUFFER (buf);
+      struct buffer *b = XBUFFER (buf);
+      bool region_active_p = (!NILP (Vtransient_mark_mode)
+                              && !NILP (BVAR (b, mark_active)));
+      ptrdiff_t region_beginning = (region_active_p) ? XINT (Fregion_beginning ()) : -1;
+      ptrdiff_t region_end = (region_active_p) ? XINT (Fregion_end ()) : -1;
+      bool region_p = (region_active_p
+                       && PT >= region_beginning
+                       && PT < region_end);
+      double red = XFLOAT_DATA (AREF (color_vector, 0));
+      double green = XFLOAT_DATA (AREF (color_vector, 1));
+      double blue = XFLOAT_DATA (AREF (color_vector, 2));
+      [[NSColor colorWithCalibratedRed: red green: green blue: blue alpha: 1.0] set];
+      if (region_p)
+        hollow_color = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
+        else if (face && NS_FACE_BACKGROUND (face) == ns_index_color (FRAME_CURSOR_COLOR (f), f))
+          hollow_color = FRAME_CURSOR_COLOR (f);
+      /* FIXME:  Add a condition for `hollow_color` if the region foreground is the
+      same as the default background and choose an appropriate color if so. */
+    }
+  else if (face && NS_FACE_BACKGROUND (face)
+           == ns_index_color (FRAME_CURSOR_COLOR (f), f))
+
+/* *************************************************************************** */
+
     {
       [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
       hollow_color = FRAME_CURSOR_COLOR (f);
@@ -3133,9 +3201,16 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
     }
   ns_unfocus (f);
 
-  /* draw the character under the cursor */
-  if (cursor_type != NO_CURSOR)
-    draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+/* *************************************************************************** */
+/* multiple cursors */
+
+   /* draw the character under the cursor */
+  if (cursor_type != NO_CURSOR
+      && !EQ (flavor, Qmc_glyphless)
+      && !EQ (flavor, Qmc_glyph_tab))
+     draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+
+/* *************************************************************************** */
 
 #ifdef NS_IMPL_COCOA
   NSEnableScreenUpdates ();
diff --git a/src/w32term.c b/src/w32term.c
index 7c2d86b..b079135 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -705,10 +705,12 @@ x_update_window_end (struct window *w, bool cursor_on_p,
     {
       block_input ();
 
-      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);
+/* *************************************************************************** */
+/* multiple cursors */
+
+      mc_portal (w, cursor_on_p);
+
+/* *************************************************************************** */
 
       if (draw_window_fringes (w, true))
 	{
@@ -973,7 +975,11 @@ static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
 static void
 x_set_cursor_gc (struct glyph_string *s)
 {
-  if (s->font == FRAME_FONT (s->f)
+/* *************************************************************************** */
+/* multiple cursors */
+
+  struct window *w = decode_live_window (selected_window);
+  if ((s->font == FRAME_FONT (s->f)
       && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
       && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
       /* Sometimes we are not called for each change in the default
@@ -981,6 +987,9 @@ x_set_cursor_gc (struct glyph_string *s)
 	 test in the next line gives us a chance to resync.  */
       && s->f->output_data.w32->cursor_gc->foreground == s->face->background
       && !s->cmp)
+      || w->mc.cursor_gc_default)
+
+/* *************************************************************************** */
     s->gc = s->f->output_data.w32->cursor_gc;
   else
     {
@@ -5746,7 +5755,13 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row,
 	 invisible.  Use the glyph's foreground color instead in this
 	 case, on the assumption that the glyph's colors are chosen so
 	 that the glyph is legible.  */
-      if (face->background == cursor_color)
+/* *************************************************************************** */
+/* multiple cursors */
+
+      if (face->background == cursor_color
+          && !w->mc.cursor_gc_invisible_okay)
+
+/* *************************************************************************** */
 	cursor_color = face->foreground;
 
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
@@ -5823,7 +5838,13 @@ 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)
+/* *************************************************************************** */
+/* multiple cursors */
+
+  int cursor_width, bool on_p, bool active_p,
+  Lisp_Object color_vector, Lisp_Object flavor)
+
+/* *************************************************************************** */
 {
   if (on_p)
     {
@@ -5888,31 +5909,118 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
 	  return;
 	}
 
-      switch (cursor_type)
-	{
-	case HOLLOW_BOX_CURSOR:
-	  x_draw_hollow_cursor (w, glyph_row);
-	  break;
-
-	case FILLED_BOX_CURSOR:
-	  draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
-	  break;
-
-	case BAR_CURSOR:
-	  x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
-	  break;
-
-	case HBAR_CURSOR:
-	  x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
-	  break;
-
-	case NO_CURSOR:
-	  w->phys_cursor_width = 0;
-	  break;
+/* *************************************************************************** */
+/* BEGIN multiple cursors */
+  double red = XFLOAT_DATA (AREF (color_vector, 0));
+  double green = XFLOAT_DATA (AREF (color_vector, 1));
+  double blue = XFLOAT_DATA (AREF (color_vector, 2));
+  switch (cursor_type)
+  {
+    case HOLLOW_BOX_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.w32->cursor_pixel'.  */
+        {
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          COLORREF orig_val = f->output_data.w32->cursor_pixel;
+          int int_red = red * 255;
+          int int_green = green * 255;
+          int int_blue = blue * 255;
+          f->output_data.w32->cursor_pixel = PALETTERGB (int_red, int_green, int_blue);
+          x_draw_hollow_cursor (w, glyph_row);
+          f->output_data.w32->cursor_pixel = orig_val;
+        }
+        else
+          x_draw_hollow_cursor (w, glyph_row);
+      break;
+    }
+    case FILLED_BOX_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.w32->cursor_gc' by borrowing the
+        functionality of `x_make_gc' in w32fns.c.  */
+        {
+          block_input ();
+          Lisp_Object window = (selected_window);
+          struct window *w = decode_live_window (window);
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          int int_red = red * 255;
+          int int_green = green * 255;
+          int int_blue = blue * 255;
+          XGCValues gc_values;
+          unsigned long mask = GCFont | GCForeground | GCBackground;
+          COLORREF orig_val_a = FRAME_BACKGROUND_PIXEL (f);
+          COLORREF orig_val_b = f->output_data.w32->cursor_pixel;
+          gc_values.font = FRAME_FONT (f);
+          gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
+          gc_values.background = PALETTERGB (int_red, int_green, int_blue);
+          f->output_data.w32->cursor_gc
+            = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &gc_values);
+          /* When `w->mc.cursor_gc_default = true', force `x_set_cursor_gc' to
+          use `s->f->output_data.w32->cursor_gc'.  */
+          w->mc.cursor_gc_default = true;
+          draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+          w->mc.cursor_gc_default = false;
+          gc_values.font = FRAME_FONT (f);
+          gc_values.foreground = orig_val_a;
+          gc_values.background = orig_val_b;
+          f->output_data.w32->cursor_gc
+            = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &gc_values);
+          unblock_input ();
+        }
+        else
+          draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+      break;
+    }
+    case BAR_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.w32->cursor_pixel'.  */
+        {
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          COLORREF orig_val = f->output_data.w32->cursor_pixel;
+          int int_red = red * 255;
+          int int_green = green * 255;
+          int int_blue = blue * 255;
+          f->output_data.w32->cursor_pixel = PALETTERGB (int_red, int_green, int_blue);
+          w->mc.cursor_gc_invisible_okay = true;
+          x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+          w->mc.cursor_gc_invisible_okay = false;
+          f->output_data.w32->cursor_pixel = orig_val;
+        }
+        else
+          x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+      break;
+    }
+    case HBAR_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.w32->cursor_pixel'.  */
+        {
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          COLORREF orig_val = f->output_data.w32->cursor_pixel;
+          int int_red = red * 255;
+          int int_green = green * 255;
+          int int_blue = blue * 255;
+          f->output_data.w32->cursor_pixel = PALETTERGB (int_red, int_green, int_blue);
+          w->mc.cursor_gc_invisible_okay = true;
+          x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+          w->mc.cursor_gc_invisible_okay = false;
+          f->output_data.w32->cursor_pixel = orig_val;
+        }
+        else
+          x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+      break;
+    }
+    case NO_CURSOR:
+      w->phys_cursor_width = 0;
+      break;
+    default:
+      emacs_abort ();
+  }
+/* END multiple cursors */
+/* *************************************************************************** */
 
-	default:
-	  emacs_abort ();
-	}
     }
 }
 
diff --git a/src/window.c b/src/window.c
index 504dcd3..8daee35 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6789,6 +6789,27 @@ get_phys_cursor_glyph (struct window *w)
   struct glyph *glyph;
   int hpos = w->phys_cursor.hpos;
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+/* This modification enables placement of the cursor-in-fringe bitmap when
+the window-width is slightly less than `glyph_row->exact_window_width_line_p`.
+This modification also prevents drawing the real cursor on the fringe (instead
+of using the cursor-in-fringe bitmap) in the above-mentioned circumstance.
+See the following related patches:
+-  July 19, 2016:  bf5ddded70c11edaf3514b25da27fc71cfb8e965
+-  May 21, 2016:  e5015c5d9632a0bf685c093249ae4a7d3e825b13
+See the following bug reports:  #16856 and #29233. */
+
+  struct frame *f = XFRAME (w->frame);
+  int frame_char_width = FRAME_COLUMN_WIDTH (f);
+  int text_area_width = window_box_width (w, TEXT_AREA);
+  bool cursor_in_fringe_p = w->phys_cursor.x + frame_char_width >= text_area_width;
+  if (cursor_in_fringe_p)
+    return NULL;
+
+/* *************************************************************************** */
+
   if (!(w->phys_cursor.vpos >= 0
 	&& w->phys_cursor.vpos < w->current_matrix->nrows))
     return NULL;
diff --git a/src/window.h b/src/window.h
index 25c9686..482334f 100644
--- a/src/window.h
+++ b/src/window.h
@@ -76,6 +76,39 @@ one and the same, so its prev and next members are nil.
 
 A dead window has its contents field set to nil.  */
 
+/* *************************************************************************** */
+/* BEGIN multiple cursors */
+
+/* Suffixes for the `mc` window pointer prefix. */
+struct multiple_cursors
+{
+  /* Values for previous and current `window-start' and `window-end'. */
+  EMACS_INT current_start, current_end, previous_start, previous_end, current_x, previous_x;
+
+  /* True means to force `x_set_cursor_gc' to use `s->f->output_data.w32->cursor_gc'
+  in w32term.c or `s->f->output_data.x->cursor_gc' in xterm.c. */
+  bool_bf cursor_gc_default : 1;
+
+  /* True means `x_set_cursor_gc' should permit the foreground and background
+  colors to be the same.  The default behavior disallows an invisible result. */
+  bool_bf cursor_gc_invisible_okay : 1;
+
+  /* True means `mc_calc' has not run yet drawn glyph fake cursors. */
+  bool_bf draw_glyph_cursor : 1;
+
+  /* True means `mc_calc' has not run yet erased glyph fake cursors. */
+  bool_bf erase_glyph_cursor : 1;
+
+  /* True means crosshairs have not yet been drawn. */
+  bool_bf draw_crosshairs : 1;
+
+  /* True means crosshairs have not yet been erased. */
+  bool_bf erase_crosshairs : 1;
+};
+
+/* END multiple cursors */
+/* *************************************************************************** */
+
 struct cursor_pos
 {
   /* Pixel position.  These are always window relative.  */
@@ -178,6 +211,20 @@ struct window
     /* An alist with parameters.  */
     Lisp_Object window_parameters;
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+    /* The cache for multiple glyph cursors.  For an example of the structure of
+    the list, see the comments at the beginning of `mc_calc' in xdisp.c.  */
+    Lisp_Object mc_glyph_cache;
+
+    /* The cache for multiple glyph/glyphless cursors that form crosshairs.  For an
+    example of the structure of the list, see the comments at the beginning of
+    `mc_crosshairs' in xdisp.c.  */
+    Lisp_Object crosshairs_cache;
+
+/* *************************************************************************** */
+
     /* No Lisp data may follow below this point without changing
        mark_object in alloc.c.  The member current_matrix must be the
        first non-Lisp member.  */
@@ -280,6 +327,14 @@ struct window
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+    /* The prefix for window pointers relating to multiple cursors.  */
+    struct multiple_cursors mc;
+
+/* *************************************************************************** */
+
     /* Cursor type of last cursor drawn on the window.  */
     enum text_cursor_kinds phys_cursor_type;
 
@@ -417,6 +472,23 @@ XWINDOW (Lisp_Object a)
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+INLINE void
+wset_mc_glyph_cache (struct window *w, Lisp_Object val)
+{
+  w->mc_glyph_cache = val;
+}
+
+INLINE void
+wset_crosshairs_cache (struct window *w, Lisp_Object val)
+{
+  w->crosshairs_cache = val;
+}
+
+/* *************************************************************************** */
+
 /* Most code should use these functions to set Lisp fields in struct
    window.  */
 INLINE void
diff --git a/src/xdisp.c b/src/xdisp.c
index 02c5d76..641b96b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -907,6 +907,1547 @@ static void produce_special_glyphs (struct it *, enum display_element_type);
 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
 static bool coords_in_mouse_face_p (struct window *, int, int);
 
+/* *************************************************************************** */
+/* BEGIN multiple cursors */
+
+/* MULTIPLE CURSORS:  Emacs Bug #22873 (feature request)
+
+   CROSSHAIRS:  Emacs Bug #17684 (feature request)
+
+PATCH VERSION:  011
+Apply patch to master branch (03/28/2016):  a30e7e12ed8465e2565dd318d921bc87f52ce18e
+git reset --hard a30e7e12ed8465e2565dd318d921bc87f52ce18e
+
+EXAMPLE #1:  (setq mc-glyph-list '((1 "hbar" "magenta")
+                             (2 "bar" "purple")
+                             (3 "box" "#00FF00")
+                             (4 "hollow" "#0000FF")
+                             (5 ("hbar" 3) [1.0 0.0 1.0])
+                             (6 ("bar" 3) [0.0 1.0 1.0])))
+
+EXAMPLE #2:  (setq mc-glyph-list nil)
+
+TODO:
+
+-  Set up a user option similar to `cursor-in-non-selected-windows'.
+
+-  Explore the idea of whether we need additional code to handle removing/redrawing
+   fake cursors when windows change sizes / layouts.
+
+-  Fake cursors are being redrawn too often when mousing over text (underneath the
+   real cursor) with mouse-face properties, and also when non-selected windows/frames
+   have an ongoing process that require frequent redisplay updates.
+
+-  Optimize drawing/erasing fake cursors.
+
+-  Implement a way to properly calculate X, Y, HPOS, VPOS when dealing with overlays
+   text properties, composition characters, tabs, etc.
+
+-  Implement a test for crosshairs to see if the buffer uses monospace versus
+   proportional fonts, and suppress crosshairs when the latter.
+
+-  Implement functionality similar to the multiple cursors library by Magnar Sveen.
+
+LEGEND
+
+fprintf (stderr, "string: %s | int: %d\n", SSDATA (build_string ("foo")), 69);
+
+if (BUFFERP (w->contents) && STRINGP (BVAR (XBUFFER (w->contents), name)))
+  fprintf (stderr, "ns_update_window_end:  %s\n", SSDATA (BVAR (XBUFFER (w->contents), name)));
+
+AUTO_STRING (my_string_one, "This is the value of `my_object_one':  %s");
+Lisp_Object my_object_one = make_float (0.1);
+CALLN (Fmessage, my_string_one, my_object_one);
+
+AUTO_STRING (my_string_two, "This is the value of `my_object_two':  %s");
+Lisp_Object my_object_two = make_number (777);
+CALLN (Fmessage, my_string_two, my_object_two);
+
+WINDOW:  w->contents
+
+BUFFER:  XBUFFER (w->contents)
+
+BUFFER LOCAL VARIABLE:  BVAR (XBUFFER (w->contents), variable_name)
+
+NO NARROWING:
+
+BEG == Beginning of Buffer (window displays current buffer)
+
+ZV == End of Buffer (window displays current buffer)
+
+BEG_BYTE == Beginning Byte of Buffer
+
+Z_BYTE == Ending Byte of Buffer
+
+NARROWED -- "V":
+
+BEGV == Beginning of NARROWED Buffer (window displays current buffer)
+
+ZV == End of NARROWED Buffer (window displays current buffer)
+
+BEGV_BYTE == Beginning Byte of NARROWED Buffer
+
+ZV_BYTE == Ending Byte of NARROWED buffer
+
+WINDOW DOES NOT NECESSARILY DISPLAY BUFFER:
+
+bob_disregard_narrow = BUF_BEG (buffer)
+eob_disregard_narrow = BUF_Z (buffer)
+
+bob_respect_narrow = BUF_BEGV (buffer)
+eob_respect_narrow = BUF_ZV (buffer)
+
+window_start = marker_position (w->start)
+window_end = eob_disregard_narrow - w->window_end_pos
+
+buffer_size = eob_disregard_narrow - bob_disregard_narrow
+
+buffer_narrowed_p = (eob_respect_narrow - bob_respect_narrow != buffer_size)
+
+window_contents_visible_p = (bob_respect_narrow == window_start
+                             && eob_respect_narrow == window_end)
+
+This is the C [ternary operator][1] (Objective-C is a superset of C):
+
+    label.frame = (inPseudoEditMode) ? kLabelIndentedRect : kLabelRect;
+
+is semantically equivalent to
+
+    if(inPseudoEditMode) {
+     label.frame = kLabelIndentedRect;
+    } else {
+     label.frame = kLabelRect;
+    }
+
+The ternary with no first element (e.g. `variable ?: anotherVariable`) means the same as `(valOrVar != 0) ? valOrVar : anotherValOrVar`
+
+EASSERT:
+
+  eassert (BUF_BEG (b) <= charpos && charpos <= BUF_Z (b));
+  bool barf_crash = (BUF_BEG (b) <= ZV && ZV <= BUF_Z (b)) ? false : true; */
+
+#include <time.h>
+#include <ftoastr.h>
+#include <math.h>
+
+#define NO_FRINGE_BITMAP 0
+
+/* Function prototypes.  */
+
+static void debug_method_add (struct window *, char const *, ...);
+
+static bool hscrolling_current_line_p (struct window *w);
+
+static int window_hscroll_limited (struct window *w, struct frame *f);
+
+static void pint2str (register char *, register int, register ptrdiff_t);
+
+/* This is meant to be used when target is visible and when code is sandwiched:
+     update_begin (f);
+     block_input ();
+     mc_erase_glyph_cursor (w, x, y, hpos, vpos, cursor_type);
+     unblock_input ();
+     update_end (f); */
+static void
+mc_erase_glyph_cursor (struct window *w, ptrdiff_t x, ptrdiff_t y, ptrdiff_t hpos,
+                       ptrdiff_t vpos, enum text_cursor_kinds cursor_type)
+{
+  /* `matrix_row' in `dispnew.c` contains the following tests,
+  eassert (matrix && matrix->rows);
+  eassert (row >= 0 && row < matrix->nrows); */
+  bool barf_crash_one = (w->current_matrix && w->current_matrix->rows) ? false : true;
+  if (barf_crash_one)
+    return;
+  bool barf_crash_two = (vpos >= 0 && vpos < w->current_matrix->nrows) ? false : true;
+  if (barf_crash_two)
+    return;
+  if (x < 0
+      || y < 0
+      || hpos < 0
+      || vpos < 0)
+    return;
+  /* Record the current values for w->phys_cursor. */
+  ptrdiff_t original_x = w->phys_cursor.x;
+  ptrdiff_t original_y = w->phys_cursor.y;
+  ptrdiff_t original_hpos = w->phys_cursor.hpos;
+  ptrdiff_t original_vpos = w->phys_cursor.vpos;
+  enum text_cursor_kinds original_cursor_type = w->phys_cursor_type;
+  /* Hijack w->phys_cursor by setting new values. */
+  w->phys_cursor.x = x;
+  w->phys_cursor.y = y;
+  w->phys_cursor.hpos = hpos;
+  w->phys_cursor.vpos = vpos;
+  w->phys_cursor_type = cursor_type;
+  erase_phys_cursor (w);
+  /* Restore the previous values for w->phys_cursor. */
+  w->phys_cursor.x = original_x;
+  w->phys_cursor.y = original_y;
+  w->phys_cursor.hpos = original_hpos;
+  w->phys_cursor.vpos = original_vpos;
+  w->phys_cursor_type = original_cursor_type;
+}
+
+/* This is meant to be used when target is visible and when code is sandwiched:
+     update_begin (f);
+     block_input ();
+     mc_draw_erase_hybrid (...);
+     unblock_input ();
+     update_end (f);
+We call this a draw/erase hybrid because it does all of the following:
+-  Draw all glyph cursors, but erase with `mc_erase_glyph_cursor'.
+-  Draw/erase all fringe bitmaps relating to crosshairs.
+-  Draw/erase all glyphless cursors. */
+static void
+mc_draw_erase_hybrid (struct window *w, ptrdiff_t x, ptrdiff_t y, ptrdiff_t hpos, ptrdiff_t vpos,
+                      enum text_cursor_kinds cursor_type, int cursor_width,
+                      Lisp_Object color_vector, Lisp_Object flavor)
+{
+  /* `matrix_row' in `dispnew.c` contains the following tests,
+  eassert (matrix && matrix->rows);
+  eassert (row >= 0 && row < matrix->nrows); */
+  bool barf_crash_one = (w->current_matrix && w->current_matrix->rows) ? false : true;
+  if (barf_crash_one)
+    return;
+  bool barf_crash_two = (vpos >= 0 && vpos < w->current_matrix->nrows) ? false : true;
+  if (barf_crash_two)
+    return;
+  if (x < 0
+      || y < 0
+      || hpos < 0
+      || vpos < 0)
+    return;
+  struct frame *f = XFRAME (w->frame);
+  struct glyph_row *glyph_row = MATRIX_ROW (w->current_matrix, vpos);
+  /* Record some of the current values for the cursor and glyph_row. */
+  bool original_cursor_in_fringe_p = glyph_row->cursor_in_fringe_p;
+  bool original_reversed_p = glyph_row->reversed_p;
+  ptrdiff_t original_x = w->phys_cursor.x;
+  ptrdiff_t original_y = w->phys_cursor.y;
+  ptrdiff_t original_hpos = w->phys_cursor.hpos;
+  ptrdiff_t original_vpos = w->phys_cursor.vpos;
+  ptrdiff_t original_ascent = w->phys_cursor_ascent;
+  ptrdiff_t original_height = w->phys_cursor_height;
+  enum text_cursor_kinds original_cursor_type = w->phys_cursor_type;
+  /* Hijack w->phys_cursor. */
+  w->phys_cursor.hpos = hpos;
+  w->phys_cursor.vpos = vpos;
+  w->phys_cursor.x = x;
+  w->phys_cursor.y = glyph_row->y;
+  w->phys_cursor_type = cursor_type;
+  w->phys_cursor_ascent = glyph_row->ascent;
+  w->phys_cursor_height = glyph_row->height;
+  /* (get '+-left-fringe-overlay-position 'overlay-arrow-bitmap)
+     => '+-overlay-arrow-bitmap
+     => Qmc_smiley_face */
+  /* Lisp_Object val = Fget (intern ("+-left-fringe-overlay-position"), Qoverlay_arrow_bitmap); */
+  Lisp_Object marker = find_symbol_value (intern ("overlay-arrow-position"));
+  int fringe_bitmap = NO_FRINGE_BITMAP;
+  int face_id = DEFAULT_FACE_ID;
+  if (EQ (flavor, Qoverlay_arrow_bitmap))
+    {
+      Lisp_Object vlist;
+      for (vlist = Voverlay_arrow_variable_list;
+           CONSP (vlist);
+           vlist = XCDR (vlist))
+        {
+          Lisp_Object var = XCAR (vlist);
+          Lisp_Object val;
+          if (!SYMBOLP (var))
+            continue;
+          val = find_symbol_value (var);
+          if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
+            fringe_bitmap = lookup_fringe_bitmap (val);
+        }
+      glyph_row->overlay_arrow_bitmap = (cursor_type != NO_CURSOR)
+                                        ? fringe_bitmap /* lookup_fringe_bitmap (flavor) */
+                                        : NO_FRINGE_BITMAP;
+      draw_fringe_bitmap (w, glyph_row, true);
+      /* optimization 3:  DRAW the `overlay-arrow-bitmap' if there is a marker. */
+      if (MARKERP (marker)
+          && XMARKER (marker)->buffer
+          && BUFFER_LIVE_P (XMARKER (marker)->buffer))
+        {
+          glyph_row->overlay_arrow_bitmap = fringe_bitmap;
+          draw_fringe_bitmap (w, glyph_row, true);
+        }
+    }
+    else if (EQ (flavor, Qmc_hollow_rectangle_right_angle)
+             || EQ (flavor, Qmc_hollow_rectangle)
+             || EQ (flavor, Qmc_vertical_bar_right_angle)
+             || EQ (flavor, Qmc_vertical_bar)
+             || EQ (flavor, Qmc_vertical_bar_backslash))
+      {
+        fringe_bitmap = (cursor_type != NO_CURSOR)
+                        ? lookup_fringe_bitmap (flavor)
+                        : NO_FRINGE_BITMAP;
+        face_id = (cursor_type != NO_CURSOR)
+                  ? lookup_named_face (f, intern ("+-vertical-bar-face"), true)
+                  : DEFAULT_FACE_ID;
+        glyph_row->cursor_in_fringe_p = false;
+        glyph_row->fringe_bitmap_periodic_p = 0;
+        glyph_row->right_fringe_bitmap = fringe_bitmap;
+        glyph_row->right_fringe_face_id = face_id;
+        glyph_row->right_fringe_offset = 0;
+        draw_fringe_bitmap (w, glyph_row, false);
+      }
+      else if (EQ (flavor, Qmc_glyph)
+               || EQ (flavor, Qmc_glyphless)
+               || EQ (flavor, Qmc_glyph_tab))
+        FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y, cursor_type,
+                                           cursor_width, true, false,
+                                           color_vector, flavor);
+  /* Restore the previous values for w->phys_cursor and glyph_row. */
+  w->phys_cursor.x = original_x;
+  w->phys_cursor.y = original_y;
+  w->phys_cursor.hpos = original_hpos;
+  w->phys_cursor.vpos = original_vpos;
+  w->phys_cursor_type = original_cursor_type;
+  glyph_row->cursor_in_fringe_p = original_cursor_in_fringe_p;
+  glyph_row->reversed_p = original_reversed_p;
+  w->phys_cursor_ascent = original_ascent;
+  w->phys_cursor_height = original_height;
+}
+
+static 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;
+}
+
+static Lisp_Object
+mc_cursor_type_to_lisp (int arg)
+{
+  switch (arg)
+    {
+    case FILLED_BOX_CURSOR: return Qbox;
+    case HOLLOW_BOX_CURSOR: return Qhollow;
+    case HBAR_CURSOR: return Qhbar;
+    case BAR_CURSOR: return Qbar;
+    case NO_CURSOR:
+    default: return intern ("no");
+    }
+}
+
+static Lisp_Object
+mc_color_vector_calc (struct window *w, Lisp_Object color)
+{
+  CHECK_STRING (color);
+  Lisp_Object target_frame = w->frame;
+  Lisp_Object color_values;
+  double valmax = XINT (XCAR (Fxw_color_values (build_string ("#ffffff"), target_frame)));
+  Lisp_Object vlist;
+  ptrdiff_t x;
+  int i = 0;
+  Lisp_Object temp = Qnil;
+  Lisp_Object vector = (Fmake_vector (make_number (3), Qnil));
+  if (!NILP (Fmemq ((Fframep (target_frame)), listn (CONSTYPE_HEAP, 3, intern ("x"), intern ("w32"), intern ("ns")))))
+    {
+      color_values = (Fxw_color_values (color, target_frame));
+      for (vlist = color_values;
+           CONSP (vlist);
+           vlist = XCDR (vlist))
+        {
+          x = XINT (XCAR (vlist));
+          temp = make_float (x / valmax);
+          ASET (vector, i, temp);
+          i = i + 1;
+        }
+    }
+  return vector;
+}
+
+/* You only need to call lookup_basic_face if it.face_id is a basic face
+AND face-remapping-alist is non-nil.  If it.face_id is not a basic
+face, lookup_basic_face will abort, and you should call lookup_face
+instead.  For a remapped non-basic face you will have to look up
+face-remapping-alist manually and then use lookup_named_face. */
+static Lisp_Object
+mc_bg_color_vector (struct window *w, enum face_id face_id)
+{
+  struct frame *f = XFRAME (w->frame);
+  struct face *face;
+  Lisp_Object color, color_vector;
+  if (!NILP (Vface_remapping_alist)
+      && (face_id == DEFAULT_FACE_ID /* Qdefault */
+          || face_id == MODE_LINE_FACE_ID /* Qmode_line */
+          || face_id == MODE_LINE_INACTIVE_FACE_ID /* Qmode_line_inactive */
+          || face_id == HEADER_LINE_FACE_ID /* Qheader_line */
+          || face_id == TOOL_BAR_FACE_ID /* Qtool_bar */
+          || face_id == FRINGE_FACE_ID /* Qfringe */
+          || face_id == SCROLL_BAR_FACE_ID /* Qscroll_bar */
+          || face_id == BORDER_FACE_ID /* Qborder */
+          || face_id == CURSOR_FACE_ID /* Qcursor */
+          || face_id == MOUSE_FACE_ID /* Qmouse */
+          || face_id == MENU_FACE_ID /* Qmenu */
+          || face_id == WINDOW_DIVIDER_FACE_ID /* Qwindow_divider */
+          || face_id == WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID /* Qwindow_divider_first_pixel */
+          || face_id == WINDOW_DIVIDER_LAST_PIXEL_FACE_ID /* Qwindow_divider_last_pixel */
+          || face_id == VERTICAL_BORDER_FACE_ID /* Qvertical_border */
+          /* Qinternal_border */
+          /* || face_id == INTERNAL_BORDER_FACE_ID) */
+          ))
+    face = FACE_FROM_ID (f, lookup_basic_face (f, face_id));
+    else
+      face = FACE_FROM_ID (f, face_id);
+  color = face->lface[LFACE_BACKGROUND_INDEX];
+  CHECK_STRING (color);
+  color_vector = mc_color_vector_calc (w, color);
+  return color_vector;
+}
+
+/* MC_GLYPH_CACHE:
+-  The first element is compared to the `mc-glyph-list' to determine whether we need to
+   recalculate coordinates.  [We also check whether window-start/window-end changed.]
+-  The second element contains all previously calculated coordinates.
+-  The third element is the buffer where the `mc_glyph_cache' was set.  Because the
+   `mc_glyph_cache' is window-local, we need to check both the window and the buffer.
+     (((3 hbar [1.0 0.0 0.0])
+       (4 bar [0.0 1.0 0.0])
+       (5 box [0.0 0.0 1.0])
+       (6 hollow [0.8 0.4 0.2])
+       (7 (hbar 3) [1.0 0.0 1.0])
+       (8 (bar 3) [0.0 1.0 1.0]))
+      (((3 hbar [1.0 0.0 0.0]) (22 20 2 0))
+       ((4 bar [0.0 1.0 0.0]) (33 20 3 0))
+       ((5 box [0.0 0.0 1.0]) (44 20 4 0))
+       ((6 hollow [0.8 0.4 0.2]) (55 20 5 0))
+       ((7 (hbar 3) [1.0 0.0 1.0]) (66 20 6 0))
+       ((8 (bar 3) [0.0 1.0 1.0]) (77 20 7 0)))
+      (BUFFER where `mc_glyph_cache' was set.)) */
+/* If REMOVE is 0, then draw fake cursors.  If REMOVE is 1, then erase fake cursors. */
+void
+mc_calc (struct window *w, bool remove)
+{
+  /* `start_display' calls `init_iterator' which crashes Emacs if:
+  eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer) && charpos <= ZV))
+  This happens when multiple cursors are active and the user types:  M-x .... */
+  ptrdiff_t charpos = marker_position (w->start);
+  bool barf_crash_one = (charpos < 0 || (charpos >= BUF_BEG (current_buffer) && charpos <= ZV)) ? false : true;
+  if (barf_crash_one)
+    return;
+  struct frame *f = XFRAME (w->frame);
+  struct window *sw = XWINDOW (f->selected_window);
+  Lisp_Object buf = w->contents;
+  CHECK_BUFFER (buf);
+  struct buffer *b = XBUFFER (buf);
+  /* We want to make sure we have the right buffer before testing buffer local variables. */
+  Lisp_Object buffer_display_table = BVAR (b, display_table);
+  bool buffer_display_table_p = !NILP (buffer_display_table);
+  Lisp_Object line_feed_vector;
+  if (buffer_display_table_p)
+    line_feed_vector = Faref (buffer_display_table, make_number (10));
+  struct it it;
+  void *itdata = bidi_shelve_cache ();
+  struct it saved_it_for_window_start;
+  void *saved_itdata_for_window_start = NULL;
+  struct text_pos start_text_position;
+  ptrdiff_t it_start;
+  int first_x, last_x;
+  int lnum_width = 0;
+  int lnum_pixel_width = 0;
+  bool hscl = (!w->suspend_auto_hscroll
+               && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents), Qcurrent_line)
+               && w->hscroll > 0);
+  int hscl_first_hpos = window_hscroll_limited (w, f);
+  int frame_char_width = FRAME_COLUMN_WIDTH (f);
+  int text_area_width = window_box_width (w, TEXT_AREA);
+  int right_fringe_width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+  int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+  enum text_cursor_kinds cursor_type;
+  int cursor_width = 1;
+  ptrdiff_t posint, x, y, hpos, vpos;
+  /* An idle timer situation at the outset may not necessarily invoke `redisplay_window',
+  which is where certain multiple cursor values are set at the tail end thereof. */
+  if (!w->mc.current_start)
+    w->mc.current_start = marker_position (w->start);
+  Lisp_Object specs, lisp_type, color_vector, vlist, x_y_hpos_vpos;
+  Lisp_Object temp = Qnil;
+  Lisp_Object result = Qnil;
+  SET_TEXT_POS_FROM_MARKER (start_text_position, w->start);
+  start_display (&it, w, start_text_position);
+  first_x = it.first_visible_x;
+  last_x = it.last_visible_x;
+  it_start = IT_CHARPOS (it);
+  SAVE_IT (saved_it_for_window_start, it, saved_itdata_for_window_start);
+  /* Finish priming the IT for potential line numbers. */
+  if (!NILP (Vdisplay_line_numbers)
+      && !EQ (Vdisplay_line_numbers, Qvisual))
+    {
+      it.first_visible_x = 0;
+      move_it_by_lines (&it, 1);
+      lnum_width = it.lnum_width;
+      lnum_pixel_width = it.lnum_pixel_width;
+      RESTORE_IT (&it, &saved_it_for_window_start, saved_itdata_for_window_start);
+      it.first_visible_x = first_x;
+      it.last_visible_x = last_x;
+      it.lnum_width = lnum_width;
+      it.lnum_pixel_width = lnum_pixel_width;
+      SAVE_IT (saved_it_for_window_start, it, saved_itdata_for_window_start);
+    }
+/* ******************************************************************************
+                              REMOVE GLYPH CURSORS
+****************************************************************************** */
+  /* Remove the cursors using the cache if the conditions are satisfied. */
+  if ((remove && !NILP (w->mc_glyph_cache) && NILP (BVAR (b, mc_glyph_list)))
+      || (!NILP (w->mc_glyph_cache) && !NILP (BVAR (b, mc_glyph_list)) && (remove || w != sw)))
+    {
+      /* Erase the real cursor so that the whole vertical line gets removed, not just the fake cursors. */
+      mc_erase_glyph_cursor (w, w->phys_cursor.x, w->phys_cursor.y, w->phys_cursor.hpos,
+                             w->phys_cursor.vpos, w->phys_cursor_type);
+      /* Process the MC_GLYPH_CACHE. */
+      if (!NILP (w->mc_glyph_cache))
+        {
+          for (vlist = XCAR (XCDR (w->mc_glyph_cache));
+               CONSP (vlist);
+               vlist = XCDR (vlist))
+            {
+              specs = XCAR (XCAR (vlist));
+              lisp_type = Fnth (make_number (1), specs);
+             if (CONSP (lisp_type))
+                cursor_type = mc_lisp_to_cursor_type (XCAR (lisp_type));
+                else
+                  cursor_type = mc_lisp_to_cursor_type (lisp_type);
+              x_y_hpos_vpos = XCAR (XCDR (XCAR (vlist)));
+              x = XINT (Fnth (make_number (0), x_y_hpos_vpos));
+              y = XINT (Fnth (make_number (1), x_y_hpos_vpos));
+              hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos));
+              vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos));
+              mc_erase_glyph_cursor (w, x, y, hpos, vpos, cursor_type);
+            }
+          if (NILP (BVAR (b, mc_glyph_list)))
+            wset_mc_glyph_cache (w, Qnil);
+        }
+      w->mc.erase_glyph_cursor = false;
+    }
+/* ******************************************************************************
+                              REDRAW GLYPH CURSORS
+****************************************************************************** */
+  /* If the first element of w->mc_glyph_cache is the same as the local variable mc_glyph_list,
+     and the previous/current window-start/window-end are the same (e.g., no scrolling),
+     then redraw the cursors using the cache.  This avoids recalculating coordinates. */
+  if (!remove
+      && w == sw
+      && w->mc.current_start
+      && w->mc.current_end
+      && w->mc.previous_start
+      && w->mc.previous_end
+      && w->mc.current_start == w->mc.previous_start
+      && w->mc.current_end == w->mc.previous_end
+      && !NILP (BVAR (b, mc_glyph_list))
+      && !NILP (w->mc_glyph_cache)
+      && !NILP (Fequal (Fnth (make_number (0), w->mc_glyph_cache), BVAR (b, mc_glyph_list))))
+    {
+      for (vlist = XCAR (XCDR (w->mc_glyph_cache));
+           CONSP (vlist);
+           vlist = XCDR (vlist))
+        {
+          specs = XCAR (XCAR (vlist));
+          posint = XINT (Fnth (make_number (0), specs));
+          lisp_type = Fnth (make_number (1), specs);
+          if (CONSP (lisp_type))
+            cursor_type = mc_lisp_to_cursor_type (XCAR (lisp_type));
+            else
+              cursor_type = mc_lisp_to_cursor_type (lisp_type);
+          if (CONSP (lisp_type))
+            cursor_width = XINT (XCAR (XCDR (lisp_type)));
+            else
+              cursor_width = 1;
+          color_vector = Fnth (make_number (2), specs);
+          if (STRINGP (color_vector))
+            color_vector = mc_color_vector_calc (w, color_vector);
+          x_y_hpos_vpos = XCAR (XCDR (XCAR (vlist)));
+          x = XINT (Fnth (make_number (0), x_y_hpos_vpos));
+          y = XINT (Fnth (make_number (1), x_y_hpos_vpos));
+          hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos));
+          vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos));
+          mc_draw_erase_hybrid (w, x, y, hpos, vpos, cursor_type, cursor_width, color_vector, Qmc_glyph);
+        }
+      w->mc.draw_glyph_cursor = false;
+    }
+/* ******************************************************************************
+                             DRAW GLYPH CURSORS ANEW
+****************************************************************************** */
+    /* Draw the cursors anew because something has changed, e.g., the first element of
+       w->mc_glyph_cache is NOT the same as the local variable mc_glyph_list; and/or, the previous/
+       current window-start/window-end are NOT the same (e.g., scrolling has occurred).
+       Semi-expensive calculation of coordinates is required. */
+    else if (!remove
+             && w == sw
+             && w->mc.current_start
+             && !NILP (BVAR (b, mc_glyph_list)))
+      {
+        for (vlist = BVAR (b, mc_glyph_list);
+             CONSP (vlist);
+             vlist = XCDR (vlist))
+          {
+            specs = XCAR (vlist);
+            posint = XINT (Fnth (make_number (0), specs));
+            lisp_type = Fnth (make_number (1), specs);
+            if (CONSP (lisp_type))
+              cursor_type = mc_lisp_to_cursor_type (XCAR (lisp_type));
+              else
+                cursor_type = mc_lisp_to_cursor_type (lisp_type);
+            if (CONSP (lisp_type))
+              cursor_width = XINT (XCAR (XCDR (lisp_type)));
+              else
+                cursor_width = 1;
+            color_vector = Fnth (make_number (2), specs);
+            if (STRINGP (color_vector))
+              color_vector = mc_color_vector_calc (w, color_vector);
+            RESTORE_IT (&it, &saved_it_for_window_start, saved_itdata_for_window_start);
+            /* FIXME:  When dealing with a line feed `buffer-display-table' issue,
+            implement a system using `mc_move_it_in_display_line' to avoid overshooting.
+            The current strategy to do this would be to first use `move_it_to' and see if
+            it encountered a line feed.  If so, then call `move_it_by_lines (&it, 0)` and
+            then `mc_move_it_in_display_line' -- stopping at the correct X. */
+            move_it_to (&it, posint, it.last_visible_x, it.last_visible_y - 1, -1, MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+            /* (aref buffer-display-table ?\n) == [(182 . 127) 10] */
+            bool line_feed_overshoot = (FETCH_BYTE (IT_BYTEPOS (it)) == '\n'
+                                        && buffer_display_table_p
+                                        && VECTORP (line_feed_vector)
+                                        && ASIZE (line_feed_vector) > 1
+                                        && ITERATOR_AT_END_OF_LINE_P (&it));
+            int adjust_x = (line_feed_overshoot) ? frame_char_width : 0;
+            int adjust_hpos = (line_feed_overshoot) ? 1 : 0;
+            if (IT_CHARPOS (it) != posint)
+              {
+                x = -1;
+                y = -1;
+                hpos = -1;
+                vpos = -1;
+                goto done_one;
+              }
+            y = it.current_y;
+            if (header_line_height > 0)
+              vpos = it.vpos + 1;
+              else
+                vpos = it.vpos;
+            if (hscl)
+              {
+                x = it.current_x - (hscl_first_hpos * frame_char_width) - adjust_x;
+                hpos = it.hpos - hscl_first_hpos - adjust_hpos;
+              }
+              else
+                {
+                  x = it.current_x - first_x - adjust_x;
+                  hpos = it.hpos - adjust_hpos;
+                }
+            done_one:
+            x_y_hpos_vpos = listn (CONSTYPE_HEAP, 4, make_number (x), make_number (y), make_number (hpos), make_number (vpos));
+            temp = Fcons (specs, Fcons (x_y_hpos_vpos, Qnil));
+            result = Fcons (temp, result);
+            mc_draw_erase_hybrid (w, x, y, hpos, vpos, cursor_type, cursor_width, color_vector, Qmc_glyph);
+          }
+/* `w->mc_glyph_cache' is set for the window, not buffer+window -- i.e., all buffers appearing
+in the same window via `switch-to-buffer' will have `w->mc_glyph_cache'.  This behavior
+is consistent with functions such as `set-window-display-table'.  We deal with this in
+`nsterm.m' / `w32term.c' / `xterm.c' by comparing `w->contents' to the value of the `buf'
+stored in `w->mc_glyph_cache':  (EQ (w->contents, XCAR (Fnth (make_number (2), w->mc_glyph_cache)))) */
+        if (!NILP (result))
+          wset_mc_glyph_cache (w, listn (CONSTYPE_HEAP, 3,
+                                     BVAR (b, mc_glyph_list),
+                                     Freverse (result),
+                                     Fcons (buf, Qnil)));
+        w->mc.draw_glyph_cursor = false;
+      }
+  bidi_unshelve_cache (itdata, false);
+}
+
+int
+mc_move_it_in_display_line (struct window *w, struct it *it, int target_x)
+{
+  if (IT_CHARPOS (*it) == ZV)
+    return MOVE_POS_MATCH_OR_ZV;
+  struct it saved_it;
+  void *saved_data = bidi_shelve_cache ();
+  enum move_it_result rc = MOVE_X_REACHED;
+  int new_x, prev_x;
+  /* When `auto-hscroll-mode' is set to `current-line` and we are horizontal scrolling
+  a long line that approaches or exceeds an `it.current.x` of approximately 1000, `rc`
+  will erroneously return early with a MOVE_LINE_TRUNCATED indicator  without pushing
+  forwards until IT reaches the target_x.  As a workaround, ignore MOVE_LINE_TRUNCATED. */
+  while (it->current_x + it->pixel_width <= target_x
+         && (rc == MOVE_X_REACHED
+             || rc == MOVE_LINE_TRUNCATED
+             || (it->line_wrap == WORD_WRAP
+                 && rc == MOVE_POS_MATCH_OR_ZV)))
+    {
+      SAVE_IT (saved_it, *it, saved_data);
+      new_x = it->current_x + it->pixel_width;
+      if (new_x == it->current_x)
+        new_x++;
+      rc = move_it_in_display_line_to (it, ZV, new_x, MOVE_TO_POS | MOVE_TO_X);
+      if (ITERATOR_AT_END_OF_LINE_P (it)
+          || FETCH_BYTE (IT_BYTEPOS (*it)) == '\n'
+          /* #28936:  `move_it_in_display_line_to' returns MOVE_POS_MATCH_OR_ZV
+          before reaching ZV when the latter is at the end of the line AND `word-wrap'
+          is non-nil:  abcdefg[ZV].  The workaround is to add an extra check using
+          IT_CHARPOS and comparing it to ZV. */
+          || (rc == MOVE_POS_MATCH_OR_ZV
+              && IT_CHARPOS (*it) == ZV))
+        break;
+    }
+  /* When word-wrap is on, TO_X may lie past the end of a wrapped line.
+  Then it->current is the character on the next line, so backtrack to the
+  space before the wrap point.  */
+  if (it->line_wrap == WORD_WRAP
+      && rc == MOVE_LINE_CONTINUED)
+    {
+      prev_x = max (it->current_x - 1, 0);
+      RESTORE_IT (it, &saved_it, saved_data);
+      move_it_in_display_line_to (it, -1, prev_x, MOVE_TO_X);
+    }
+  bidi_unshelve_cache (saved_data, true);
+  /* Workaround for bug #28936 -- correct the erroneous MOVE_POS_MATCH_OR_ZV. */
+  if (it->current_x == target_x
+      && rc == MOVE_POS_MATCH_OR_ZV
+      && IT_CHARPOS (*it) != ZV)
+    rc = MOVE_X_REACHED;
+  return rc;
+}
+
+static void
+mc_crosshairs_helper (struct window *w, ptrdiff_t x, ptrdiff_t y, ptrdiff_t hpos, ptrdiff_t vpos,
+                      enum text_cursor_kinds type, int width,
+                      Lisp_Object foreground, Lisp_Object background,
+                      Lisp_Object flavor, ptrdiff_t pos, Lisp_Object *result)
+{
+  Lisp_Object temp;
+  mc_draw_erase_hybrid (w, x, y, hpos, vpos, type, width, foreground, flavor);
+  temp = listn (CONSTYPE_HEAP, 10,
+                make_number (x),
+                make_number (y),
+                make_number (hpos),
+                make_number (vpos),
+                mc_cursor_type_to_lisp (type),
+                make_number (width),
+                foreground,
+                background,
+                flavor,
+                make_number (pos));
+  *result = Fcons (temp, *result);
+}
+
+void
+mc_draw_crosshairs (struct window *w)
+{
+  /* Eli Z.:  This doesn't feel relevant.  You can always redisplay a window that is
+  not the selected window, provided that you take care to switch to its buffer
+  (redisplay does that already). */
+  if (w != XWINDOW (selected_window))
+    return;
+  /* Eli Z.:  How did you get into this situation?  It shouldn't happen during redisplay. */
+  if (!WINDOW_VALID_P (selected_window))
+    return;
+  struct frame *f = XFRAME (w->frame);
+  Lisp_Object buf = w->contents;
+  CHECK_BUFFER (buf);
+  struct buffer *b = XBUFFER (buf);
+/* eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
+   eassert (charpos == BYTE_TO_CHAR (bytepos));
+   eassert (BUF_BEG_BYTE (b) <= bytepos && bytepos <= BUF_Z_BYTE (b)); */
+  ptrdiff_t charpos = marker_position (w->start);
+  ptrdiff_t bytepos = marker_byte_position (w->start);
+  /* Eli Z.:  If window's start point is invalid, it means the window needs to be
+  redisplayed.  Again, I'm not sure I understand how do you get into this situation
+  in the middle of redisplay. */
+  bool barf_crash_one = (charpos >= BEGV && charpos <= ZV) ? false : true;
+  if (barf_crash_one)
+    return;
+  /* Eli Z.:  Likewise.  Markers are updated when a buffer is modified, so this
+  should never happen. */
+  bool barf_crash_two = (charpos == BYTE_TO_CHAR (bytepos)) ? false : true;
+  if (barf_crash_two)
+    return;
+  /* Eli Z.:  Since you already verified the same condition about the character
+  position, and you already verified that the character position and the byte
+  position are consistent, this condition is redundant. */
+/*
+  bool barf_crash_three = (BUF_BEG_BYTE (b) <= bytepos && bytepos <= BUF_Z_BYTE (b)) ? false : true;
+  if (barf_crash_three)
+    return;
+*/
+  if (!BUFFERP (buf))
+    return;
+  if (NILP (BVAR (b, crosshairs)))
+    return;
+  if (NILP (BVAR (b, crosshairs_horizontal_ruler))
+      && NILP (BVAR (b, crosshairs_vertical_ruler)))
+    return;
+/* ******************************************************************************
+                              BEGIN JOURNEY ...
+****************************************************************************** */
+/*
+#ifdef GLYPH_DEBUG
+  clock_t start, end;
+  double cpu_time_used;
+  char buf_time[DBL_BUFSIZE_BOUND];
+  start = clock();
+#endif
+*/
+  struct it it;
+  void *itdata = bidi_shelve_cache ();
+  struct it saved_it_for_window_start;
+  void *saved_itdata_for_window_start = NULL;
+  struct it saved_it_for_horizontal_ruler;
+  void *saved_itdata_for_horizontal_ruler = NULL;
+  enum move_it_result rc = MOVE_X_REACHED;
+  struct text_pos start_text_position;
+  ptrdiff_t it_start;
+  int first_x, last_x;
+  int lnum_width = 0;
+  int lnum_pixel_width = 0;
+  int frame_char_width = FRAME_COLUMN_WIDTH (f);
+  bool hscl = (!w->suspend_auto_hscroll
+               && EQ (Fbuffer_local_value (Qauto_hscroll_mode, buf), Qcurrent_line)
+               && w->hscroll > 0);
+  int hscl_first_hpos = window_hscroll_limited (w, f);
+  int hscl_first_x = hscl_first_hpos * frame_char_width;
+  int text_area_width = window_box_width (w, TEXT_AREA);
+  bool cursor_in_fringe_p = w->output_cursor.x + frame_char_width >= text_area_width;
+  struct glyph_row *glyph_row;
+  int right_fringe_width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+  int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+  int cursor_width = 1;
+  ptrdiff_t opoint_pt = PT;
+  int relative_x, hpos, vpos;
+  int opoint_x = w->output_cursor.x;
+  int opoint_y = w->output_cursor.y;
+  int opoint_hpos = w->output_cursor.hpos;
+  int opoint_vpos = w->output_cursor.vpos;
+  ptrdiff_t current_col = current_column ();
+  bool fill_column_p = !NILP (BVAR (b, fill_column));
+  ptrdiff_t fill_col = XINT (BVAR (b, fill_column));
+  Lisp_Object result = Qnil;
+  Lisp_Object flavor = Qnil;
+  /* Values for the current column of the vertical line. */
+  Lisp_Object foreground = Fmake_vector (make_number (3), Qnil);
+  struct glyph *phys_cursor_glyph;
+  enum face_id face_id = ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
+                           ? DEFAULT_FACE_ID
+                           : phys_cursor_glyph->face_id;
+/* ******************************************************************************
+                             COLOR OF CROSSHAIRS
+****************************************************************************** */
+  enum face_id even_face_id = lookup_named_face (f, intern ("+-even-numbered-column-face"), true);
+  struct face *even_face = FACE_FROM_ID (f, even_face_id);
+  Lisp_Object even_color = even_face->lface[LFACE_FOREGROUND_INDEX];
+  CHECK_STRING (even_color);
+  Lisp_Object even_color_vector = mc_color_vector_calc (w, even_color);
+  enum face_id odd_face_id = lookup_named_face (f, intern ("+-odd-numbered-column-face"), true);
+  struct face *odd_face = FACE_FROM_ID (f, odd_face_id);
+  Lisp_Object odd_color = odd_face->lface[LFACE_FOREGROUND_INDEX];
+  CHECK_STRING (odd_color);
+  Lisp_Object odd_color_vector = mc_color_vector_calc (w, odd_color);
+  enum face_id fill_face_id = lookup_named_face (f, intern ("+-beyond-fill-column-face"), true);
+  struct face *fill_face = FACE_FROM_ID (f, fill_face_id);
+  Lisp_Object fill_color = fill_face->lface[LFACE_FOREGROUND_INDEX];
+  CHECK_STRING (fill_color);
+  Lisp_Object fill_color_vector = mc_color_vector_calc (w, fill_color);
+  /* red */
+  if (current_col % 2 != 0
+      && !fill_column_p)
+    foreground = odd_color_vector;
+  /* yellow */
+  if (current_col % 2 == 0
+      && !fill_column_p)
+    foreground = even_color_vector;
+  /* red */
+  if (current_col % 2 != 0
+      && fill_column_p
+      && current_col <= fill_col)
+    foreground = odd_color_vector;
+  /* yellow */
+  if (current_col % 2 == 0
+      && fill_column_p
+      && current_col <= fill_col)
+    foreground = even_color_vector;
+  /* green */
+  if (fill_column_p
+      && current_col > fill_col)
+    foreground = fill_color_vector;
+/* ******************************************************************************
+                      START DISPLAY AND PRIME IT
+****************************************************************************** */
+  /* Begin the journey at w->start. */
+  SET_TEXT_POS_FROM_MARKER (start_text_position, w->start);
+  start_display (&it, w, start_text_position);
+  first_x = it.first_visible_x;
+  last_x = it.last_visible_x;
+  it_start = IT_CHARPOS (it);
+  SAVE_IT (saved_it_for_window_start, it, saved_itdata_for_window_start);
+  /* Finish priming the IT for potential line numbers. */
+  if (!NILP (Vdisplay_line_numbers)
+      && !EQ (Vdisplay_line_numbers, Qvisual))
+    {
+      it.first_visible_x = 0;
+      move_it_by_lines (&it, 1);
+      lnum_width = it.lnum_width;
+      lnum_pixel_width = it.lnum_pixel_width;
+      RESTORE_IT (&it, &saved_it_for_window_start, saved_itdata_for_window_start);
+      it.first_visible_x = first_x;
+      it.last_visible_x = last_x;
+      it.lnum_width = lnum_width;
+      it.lnum_pixel_width = lnum_pixel_width;
+      SAVE_IT (saved_it_for_window_start, it, saved_itdata_for_window_start);
+    }
+  /* This might happen on OSX 10.11 when restoring desktop at the beginning
+  of a new session? */
+  if (it_start > opoint_pt)
+    return;
+/* ******************************************************************************
+                         REPLACE THE REAL CURSOR
+****************************************************************************** */
+  erase_phys_cursor (w);
+  glyph_row = MATRIX_ROW (w->current_matrix, opoint_vpos);
+  if (!cursor_in_fringe_p)
+    flavor = Qmc_glyph;
+    /* This condition probably does not exist for the real fake cursor. */
+    else if (cursor_in_fringe_p
+             && glyph_row->continued_p)
+      flavor = Qmc_pilcrow;
+      else if (cursor_in_fringe_p
+               && glyph_row->truncated_on_right_p)
+        flavor = Qmc_hollow_rectangle_right_angle;
+        else if (cursor_in_fringe_p
+                 && !glyph_row->continued_p
+                 && !glyph_row->truncated_on_right_p)
+          flavor = Qmc_hollow_rectangle;
+  mc_crosshairs_helper (w, opoint_x, opoint_y, opoint_hpos, opoint_vpos,
+                        HOLLOW_BOX_CURSOR, cursor_width,
+                        foreground, mc_bg_color_vector (w, face_id),
+                        flavor, opoint_pt, &result);
+  mc_crosshairs_helper (w, opoint_x, opoint_y, opoint_hpos, opoint_vpos,
+                        HOLLOW_BOX_CURSOR, cursor_width,
+                        foreground, mc_bg_color_vector (w, face_id),
+                        Qoverlay_arrow_bitmap, opoint_pt, &result);
+  if (NILP (BVAR (b, crosshairs_horizontal_ruler)))
+    goto vertical_ruler;
+/* ******************************************************************************
+                      HORIZONTAL RULER:  GOTO LINE BEGIN
+****************************************************************************** */
+  /* Place the IT on the current line containing PT. */
+  int voffset = (header_line_height > 0
+                 && opoint_vpos > 0)
+                  ? opoint_vpos - 1
+                  : opoint_vpos;
+  if (voffset > 0)
+    move_it_by_lines (&it, voffset);
+/* ******************************************************************************
+                HORIZONTAL RULER:  FIRST X => PENULTIMATE EOL
+****************************************************************************** */
+  while (true)
+    {
+      flavor = (it.c != '\t') ? Qmc_glyph : Qmc_glyph_tab;
+      if (hscl)
+        {
+          relative_x = it.current_x - (hscl_first_hpos * frame_char_width);
+          hpos = it.hpos - hscl_first_hpos;
+        }
+        else
+          {
+            relative_x = it.current_x - first_x;
+            hpos = it.hpos;
+          }
+      if (header_line_height > 0)
+        vpos = it.vpos + 1;
+        else
+          vpos = it.vpos;
+      bool lpw_reached_p = ((hscl
+                             && it.current_x >= hscl_first_x + lnum_pixel_width)
+                            || (!hscl
+                                && it.current_x >= first_x + lnum_pixel_width));
+      bool final_loop_p = (ITERATOR_AT_END_OF_LINE_P (&it)
+                           || FETCH_BYTE (IT_BYTEPOS (it)) == '\n'
+                           || rc == MOVE_POS_MATCH_OR_ZV);
+      bool tab_invisible_p = (it.c == '\t');
+      bool tab_visible_p = (it.c != '\t'
+                            && FETCH_BYTE (IT_BYTEPOS (it)) == '\t');
+      bool real_fake_cursor_p = (opoint_x == relative_x
+                                 && opoint_y == it.current_y
+                                 && opoint_hpos == hpos
+                                 && opoint_vpos == vpos);
+      /* it.c == '\t' when IT is at a tab-width spacer following a
+      `buffer-display-table' glyph such as ».  Another way to test
+      for this condition is when it.c == FETCH_BYTE (IT_BYTEPOS (it)). */
+      if (!real_fake_cursor_p
+          && lpw_reached_p
+          && !tab_invisible_p)
+        mc_crosshairs_helper (w, relative_x, it.current_y, hpos, vpos,
+                              HBAR_CURSOR, cursor_width,
+                              foreground, mc_bg_color_vector (w, it.face_id),
+                              flavor, IT_CHARPOS (it), &result);
+      /* FIXME:  Drawing a Qmc_glyph HBAR_CURSOR on certain letters (A, m, M, w, W)
+      located to the immediate right of a tab spacer, cause the Qmc_glyphless
+      HBAR_CURSOR to the immediate left to be erased.  This is probably an
+      overhang situation.  An obvious workaround would be to record the
+      coordinates for the Qmc_glyphless cursors and then draw them all AFTER the
+      Qmc_glyph cursors have been laid.  How about pushing all the coordinates
+      to the cache, and then executing a variation of `mc_redraw_crosshairs'
+      [with said version being rewritten] to loop twice over the list, first
+      for Qmc_glyph, and then for Qmc_glyphless? */
+      if (!real_fake_cursor_p
+          && lpw_reached_p
+          && tab_invisible_p)
+        {
+          int i, count = it.pixel_width / frame_char_width;
+          for (i = 0; i < count; i++)
+            {
+              mc_crosshairs_helper (w, relative_x, it.current_y, hpos, vpos,
+                                    HBAR_CURSOR, cursor_width,
+                                    foreground, mc_bg_color_vector (w, it.face_id),
+                                    flavor, IT_CHARPOS (it), &result);
+              relative_x = relative_x + frame_char_width;
+emacs_abort ();
+            }
+        }
+      if (final_loop_p)
+        break;
+      rc = mc_move_it_in_display_line (w, &it, it.current_x + it.pixel_width);
+      if (rc == MOVE_LINE_CONTINUED)
+        break;
+      relative_x = (hscl)
+                   ? it.current_x - (hscl_first_hpos * frame_char_width)
+                   : it.current_x - first_x;
+      if (relative_x + frame_char_width >= text_area_width)
+        break;
+    }
+/* ******************************************************************************
+       HORIZONTAL RULER:  DRAW FLOATING GLYPHLESS LINE (POST-EOL TO FRINGE)
+****************************************************************************** */
+  if (ITERATOR_AT_END_OF_LINE_P (&it)
+       || FETCH_BYTE (IT_BYTEPOS (it)) == '\n'
+       || rc == MOVE_POS_MATCH_OR_ZV
+       || rc == MOVE_LINE_CONTINUED)
+    {
+      /* We want to start drawing the floating horizontal line from just after IT
+      (line feed; ZV; or space-word_wrap) until the right fringe.  We are NOT
+      using `it.pixel_width` because its value will be zero if there is only a
+      line feed at the end of the buffer; e.g., a situation where line numbers
+      are inhibited, but @lawlist prefers seeing crosshairs in that situation.
+      If the line is empty or hidden by horizontal scrolling, then `it.current_x`
+      may be somewhere before `lnum_pixel_width`.  The real cursor will be to the
+      left of `lnum_pixel_width` if we are horizontal scrolling and point is
+      hidden somewhere to the left thereof. */
+      if ((hscl
+           && it.current_x < hscl_first_x + lnum_pixel_width)
+          || (!hscl
+              && it.current_x < first_x + lnum_pixel_width))
+        relative_x = lnum_pixel_width;
+        else
+          relative_x = relative_x + frame_char_width;
+      /* CORNER CASES:
+      -  When the beginning of the active region is at the line feed character
+         of a current line that is horizontally scrolled.  it.face_id returns
+         the foreground of the frame, instead of the active region.
+      -  An empty line ending in a line feed character returns the foreground
+         of the frame, instead of the active region.  This happens because we
+         do not force `mc_move_it_in_display_line' to keep travelling to
+         `first_x + lnum_pixel_width`.
+      -  When there is an imaginary empty line at the end of the buffer with
+         nothing other than ZV, we want to use the frame default face if ZV
+         is at the end of an active region.  */
+      if ((hscl
+           && (ITERATOR_AT_END_OF_LINE_P (&it)
+               || FETCH_BYTE (IT_BYTEPOS (it)) == '\n')
+           && it.current_x - hscl_first_x == opoint_x)
+          ||
+          (!hscl
+           && (ITERATOR_AT_END_OF_LINE_P (&it)
+               || FETCH_BYTE (IT_BYTEPOS (it)) == '\n')
+           && it.current_x - first_x < lnum_pixel_width))
+        it.face_id = face_id;
+        else if (IT_CHARPOS (it) == ZV)
+          it.face_id = DEFAULT_FACE_ID;
+      while (relative_x + frame_char_width < text_area_width)
+        {
+          mc_crosshairs_helper (w, relative_x, it.current_y, hpos, vpos,
+                                HBAR_CURSOR, cursor_width,
+                                foreground, mc_bg_color_vector (w, it.face_id),
+                                Qmc_glyphless, IT_CHARPOS (it), &result);
+          relative_x = relative_x + frame_char_width;
+        }
+    }
+/* ******************************************************************************
+           VERTICAL RULER:  COMBINATION OF GLYPH & GLYPHLESS CURSORS
+****************************************************************************** */
+  vertical_ruler:
+  if (NILP (BVAR (b, crosshairs_vertical_ruler)))
+    goto crosshairs_finish;
+  RESTORE_IT (&it, &saved_it_for_window_start, saved_itdata_for_window_start);
+  rc = MOVE_X_REACHED;
+  while (true)
+    {
+      rc = mc_move_it_in_display_line (w, &it, first_x + opoint_x);
+      relative_x = it.current_x - first_x;
+/*
+#ifdef GLYPH_DEBUG
+  debug_method_add (w, "w->min_hscroll: %d", w->min_hscroll);
+#endif
+*/
+      /* No need to specially set HPOS.  A glyph cursor will rely upon `opoint_x' and `opoint_hpos'.
+      A glyphless cursor will rely upon `it.hpos' because it is beyond any glyph that might exist. */
+      if (header_line_height > 0)
+        vpos = it.vpos + 1;
+        else
+          vpos = it.vpos;
+      bool real_fake_cursor_p = (opoint_y == it.current_y
+                               && vpos == opoint_vpos);
+      glyph_row = MATRIX_ROW (w->current_matrix, vpos);
+      if (cursor_in_fringe_p
+          && glyph_row->truncated_on_right_p)
+        flavor = Qmc_vertical_bar_right_angle;
+        else if (cursor_in_fringe_p
+                 && glyph_row->continued_p)
+          flavor = Qmc_vertical_bar_backslash;
+          else if (cursor_in_fringe_p
+                   && !glyph_row->truncated_on_right_p
+                   && !glyph_row->continued_p)
+            flavor = Qmc_vertical_bar;
+            else if ((FETCH_BYTE (IT_BYTEPOS (it)) != '\n'
+                      /* We are at a line feed character and the vertical ruler intersects. */
+                      || (FETCH_BYTE (IT_BYTEPOS (it)) == '\n'
+                          && relative_x == opoint_x))
+                     /* If we are at ZV, we want to use a glyphless cursor because it will
+                     most likely be floating somewhere off to the right of ZV.  We could
+                     probably place a glyph cursor at exactly ZV by creating an additional
+                     condition in the next section, but it is not that important. */
+                     && rc != MOVE_POS_MATCH_OR_ZV
+                     && !real_fake_cursor_p
+                     && it.c != '\t'
+                     && relative_x / frame_char_width >= lnum_pixel_width
+                     && rc != MOVE_LINE_CONTINUED)
+              flavor = Qmc_glyph;
+              else if (it.c == '\t')
+                flavor = Qmc_glyph_tab;
+                  else
+                    flavor = Qmc_glyphless;
+      /* CORNER CASES:
+      -  When the vertical line is to the left of the text and just to the right
+         of the line numbers, we want the default face.
+      -  When there is an imaginary empty line at the end of the buffer with
+         nothing other than ZV, we want to use the frame default face if ZV
+         is at the end of an active region.  */
+      if ((relative_x <= lnum_pixel_width
+           && w->hscroll > 0)
+          || IT_CHARPOS (it) == ZV)
+        it.face_id = DEFAULT_FACE_ID;
+      if (!real_fake_cursor_p)
+        mc_crosshairs_helper (w, opoint_x, it.current_y, it.hpos, vpos,
+                              BAR_CURSOR, cursor_width,
+                              foreground, mc_bg_color_vector (w, it.face_id),
+                              flavor, IT_CHARPOS (it), &result);
+      /* This combination of a ZV check before `move_it_by_lines' followed by a
+      Y check subsequent thereto gives us the FEATURE of having a vertical line
+      following a line terminating with ZV.  Whereas `display-line-numbers-mode'
+      has a FEATURE of suppressing the line numbers in this situation, we draw
+      crosshairs in that situation.  `mc_move_it_in_display_line' has been
+      equipped with a condition to test for ZV at the outset and return if true,
+      which prevents Emacs from crashing. */
+      if (IT_CHARPOS (it) == ZV)
+        break;
+      move_it_by_lines (&it, 1);
+      if (it.current_y >= it.last_visible_y)
+        break;
+    }
+/* ******************************************************************************
+                                SET THE CACHE
+****************************************************************************** */
+  crosshairs_finish:
+  if (!NILP (result))
+    wset_crosshairs_cache (w, listn (CONSTYPE_HEAP, 3,
+                                     Freverse (result),
+                                     Fcons (selected_window, Qnil),
+                                     Fcons (buf, Qnil)));
+  w->mc.draw_crosshairs = false;
+  bidi_unshelve_cache (itdata, false);
+/*
+#ifdef GLYPH_DEBUG
+  end = clock();
+  cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+  dtoastr (buf_time, sizeof buf_time, 0, 0, cpu_time_used);
+  debug_method_add (w, "mc_draw_crosshairs:  TIME (%s)", buf_time);
+#endif
+*/
+}
+
+void
+mc_redraw_crosshairs (struct window *w)
+{
+/*
+#ifdef GLYPH_DEBUG
+  clock_t start, end;
+  double cpu_time_used;
+  char buf_time[DBL_BUFSIZE_BOUND];
+  start = clock();
+#endif
+*/
+  Lisp_Object vlist = Qnil;
+  Lisp_Object specs = Qnil;
+  int x, y, hpos, vpos;
+  enum text_cursor_kinds cursor_type;
+  int cursor_width;
+  Lisp_Object foreground = Qnil;
+  Lisp_Object background = Qnil;
+  Lisp_Object flavor = Qnil;
+  ptrdiff_t pos;
+  for (vlist = XCAR (w->crosshairs_cache);
+       CONSP (vlist);
+       vlist = XCDR (vlist))
+    {
+      specs = XCAR (vlist);
+      x = XINT (Fnth (make_number (0), specs));
+      y = XINT (Fnth (make_number (1), specs));
+      hpos = XINT (Fnth (make_number (2), specs));
+      vpos = XINT (Fnth (make_number (3), specs));
+      cursor_type = mc_lisp_to_cursor_type (Fnth (make_number (4), specs));
+      cursor_width = XINT (Fnth (make_number (5), specs));
+      foreground = Fnth (make_number (6), specs);
+      background = Fnth (make_number (7), specs);
+      flavor = Fnth (make_number (8), specs);
+      pos = XINT (Fnth (make_number (9), specs));
+      mc_draw_erase_hybrid (w, x, y, hpos, vpos, cursor_type, cursor_width, foreground, flavor);
+    }
+/*
+#ifdef GLYPH_DEBUG
+  end = clock();
+  cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+  dtoastr (buf_time, sizeof buf_time, 0, 0, cpu_time_used);
+  debug_method_add (w, "mc_redraw_crosshairs:  TIME (%s)", buf_time);
+#endif
+*/
+}
+
+void
+mc_erase_crosshairs (struct window *w, bool delete_cache)
+{
+/*
+#ifdef GLYPH_DEBUG
+  clock_t start, end;
+  double cpu_time_used;
+  char buf_time[DBL_BUFSIZE_BOUND];
+  start = clock();
+#endif
+*/
+  Lisp_Object vlist = Qnil;
+  Lisp_Object specs = Qnil;
+  int x, y, hpos, vpos;
+  enum text_cursor_kinds cursor_type;
+  int cursor_width;
+  Lisp_Object foreground = Qnil;
+  Lisp_Object background = Qnil;
+  Lisp_Object flavor = Qnil;
+  ptrdiff_t pos;
+  /* Depending upon the direction of movement and distance from the real cursor the current command
+  takes us, the previous real cursor will be left behind.  I tried restoring point after draw/erase,
+  but that didn't fix the issue.  So for now, we just erase the real cursor. */
+  mc_erase_glyph_cursor (w, w->phys_cursor.x, w->phys_cursor.y, w->phys_cursor.hpos,
+                         w->phys_cursor.vpos, w->phys_cursor_type);
+  for (vlist = XCAR (w->crosshairs_cache);
+       CONSP (vlist);
+       vlist = XCDR (vlist))
+    {
+      specs = XCAR (vlist);
+      x = XINT (Fnth (make_number (0), specs));
+      y = XINT (Fnth (make_number (1), specs));
+      hpos = XINT (Fnth (make_number (2), specs));
+      vpos = XINT (Fnth (make_number (3), specs));
+      cursor_type = mc_lisp_to_cursor_type (Fnth (make_number (4), specs));
+      cursor_width = XINT (Fnth (make_number (5), specs));
+      foreground = Fnth (make_number (6), specs);
+      background = Fnth (make_number (7), specs);
+      flavor = Fnth (make_number (8), specs);
+      pos = XINT (Fnth (make_number (9), specs));
+      if (EQ (flavor, Qmc_glyph))
+        mc_erase_glyph_cursor (w, x, y, hpos, vpos, cursor_type);
+          else
+            {
+              if (EQ (flavor, Qoverlay_arrow_bitmap)
+                  || EQ (flavor, Qmc_hollow_rectangle_right_angle)
+                  || EQ (flavor, Qmc_hollow_rectangle)
+                  || EQ (flavor, Qmc_vertical_bar_right_angle)
+                  || EQ (flavor, Qmc_vertical_bar)
+                  || EQ (flavor, Qmc_vertical_bar_backslash))
+                cursor_type = NO_CURSOR;
+              mc_draw_erase_hybrid (w, x, y, hpos, vpos, cursor_type, cursor_width, background, flavor);
+            }
+    }
+  if (delete_cache)
+    wset_crosshairs_cache (w, Qnil);
+  w->mc.erase_crosshairs = false;
+/*
+#ifdef GLYPH_DEBUG
+  end = clock();
+  cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+  dtoastr (buf_time, sizeof buf_time, 0, 0, cpu_time_used);
+  debug_method_add (w, "mc_erase_crosshairs:  TIME (%s)", buf_time);
+#endif
+*/
+}
+
+void
+mc_portal (struct window *w, bool cursor_on_p)
+{
+/* ******************************************************************************
+                              MULTIPLE CURSORS
+****************************************************************************** */
+  if (!MINI_WINDOW_P (w)
+      && w->mc.erase_glyph_cursor
+      && !NILP (w->mc_glyph_cache)
+      && EQ (w->contents, XCAR (Fnth (make_number (2), w->mc_glyph_cache))))
+    mc_calc (w, 1);
+  if (w == XWINDOW (selected_window)
+      && WINDOW_VALID_P (selected_window)
+      && !MINI_WINDOW_P (w)
+      && w->mc.draw_glyph_cursor
+      && !NILP (BVAR (XBUFFER (w->contents), mc_glyph_list)))
+    /* Draw fake cursors */
+    mc_calc (w, 0);
+    /* First attempt at dealing with a `redisplay_preserve_echo_area' situation. */
+    else if (!MINI_WINDOW_P (w)
+             && !w->mc.draw_glyph_cursor
+             && !NILP (BVAR (XBUFFER (w->contents), mc_glyph_list))
+             && !NILP (w->mc_glyph_cache)
+             && EQ (w->contents, XCAR (Fnth (make_number (2), w->mc_glyph_cache))))
+      {
+        /* Remove fake cursors. */
+        mc_calc (w, 1);
+        /* Draw fake cursors */
+        mc_calc (w, 0);
+      }
+/* ******************************************************************************
+                              CROSSHAIRS
+****************************************************************************** */
+  /* Remove crosshairs and delete the cache, but ONLY if we plan on redrawing them.
+  In a timer situation, we want to erase and redraw -- we go from `checkpoint_2'
+  in `redisplay_internal' and force our way over to `update_frame' 2 of 3.
+  Emacs refreshes the selected window after about 1 to 2 minutes of no activity
+  even though there is nothing attached to the `time_list'/`idle_timer_list'.
+  In that refresh no-timer situation, we want to erase/draw using the cache. */
+  if (!MINI_WINDOW_P (w)
+      && w->mc.erase_crosshairs
+      && w->mc.draw_crosshairs
+      && !NILP (w->crosshairs_cache)
+      && w == XWINDOW (XCAR (Fnth (make_number (1), w->crosshairs_cache)))
+      && EQ (w->contents, XCAR (Fnth (make_number (2), w->crosshairs_cache))))
+    mc_erase_crosshairs (w, true);
+  if (w == XWINDOW (selected_window)
+      && WINDOW_VALID_P (selected_window)
+      && !MINI_WINDOW_P (w)
+      && (!NILP (BVAR (XBUFFER (w->contents), crosshairs))
+          /* A rare circumstance where crosshairs mode is non-nil, but the
+          user has unwittingly set both `crosshairs-horizontal-ruler' to nil and also
+          set `crosshairs-vertical-ruler' to nil -- i.e., there is nothing to do. */
+          && (!NILP (BVAR (XBUFFER (w->contents), crosshairs_horizontal_ruler))
+              || !NILP (BVAR (XBUFFER (w->contents), crosshairs_vertical_ruler))))
+      && w->mc.draw_crosshairs)
+    /* Draw crosshairs. */
+    mc_draw_crosshairs (w);
+    /* A situation that occurs with `redisplay_preserve_echo_area'. */
+    else if (!MINI_WINDOW_P (w)
+             && !w->mc.draw_crosshairs
+             && !NILP (w->crosshairs_cache)
+             && !NILP (BVAR (XBUFFER (w->contents), crosshairs))
+             && w == XWINDOW (XCAR (Fnth (make_number (1), w->crosshairs_cache)))
+             && EQ (w->contents, XCAR (Fnth (make_number (2), w->crosshairs_cache))))
+      {
+        /* Remove crosshairs, but do NOT delete the cache. */
+        mc_erase_crosshairs (w, false);
+        /* Redraw the crosshairs using the cache. */
+        mc_redraw_crosshairs (w);
+      }
+      /* CATCHALL:  DRAW THE REAL CURSOR (maybe)! */
+      else 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);
+}
+
+void
+mc_record_x_wstart_wend (struct window *w)
+{
+  /* Record prior values for cursor X, window-start and window-end.
+  The goal here is to facilitate `mc_calc' redraw multiple fake
+  cursors using the cache if nothing has changed. */
+  if (!MINI_WINDOW_P (w)
+      && w->mc.draw_glyph_cursor
+      && (!NILP (BVAR (XBUFFER (w->contents), mc_glyph_list))
+          || !NILP (w->mc_glyph_cache)))
+    {
+      if (w->mc.current_start)
+        w->mc.previous_start = w->mc.current_start;
+        else
+          w->mc.previous_start = -1;
+      if (w->mc.current_end)
+        w->mc.previous_end = w->mc.current_end;
+        else
+          w->mc.previous_end = -1;
+      w->mc.current_start = marker_position (w->start);
+      w->mc.current_end = BUF_Z (XBUFFER (w->contents)) - w->window_end_pos;
+      /* The assumption is that `w->output_cursor.x` is updated AFTER `redisplay_window'.
+      This is only relevant when using glyphless multiple fake cursors because it is
+      possible that the buffer points remain the same, but the X may have changed.
+      Crosshairs do not use `w->mc.previous_x`.  If it turns out that `w->output_cursor.x`
+      is updated DURING `redisplay_window', then it will be necessary to change this
+      to use `it.current_x' and perhaps run `start_display' to get that value. */
+      if (w->output_cursor.x)
+        w->mc.previous_x = w->output_cursor.x;
+          else
+            w->mc.previous_x = -1;
+    }
+}
+
+void
+mc_remove_everything (struct window *w)
+{
+  /* Remove fake cursors.  If we rely upon `update_frame' to remove fake cursors,
+  then it would be too late to remove fake cursors from all areas of the visible
+  window when cutting/pasting text and perhaps a few other situations that may exist.
+  FIXME:  The user can see the cursors being removed at the outset of redisplay. */
+  bool remove_cursors = false;
+  bool remove_crosshairs = false;
+  if (!w->pseudo_window_p
+      && w == XWINDOW (selected_window)
+      && !MINI_WINDOW_P (w)
+      && !NILP (w->mc_glyph_cache)
+      && EQ (w->contents, XCAR (Fnth (make_number (2), w->mc_glyph_cache))))
+    remove_cursors = true;
+  if (!w->pseudo_window_p
+      /* The crosshairs interfere with the browse-kill-ring library. */
+      /* && w == XWINDOW (selected_window) */
+      && !MINI_WINDOW_P (w)
+      && !NILP (w->crosshairs_cache)
+      && w == XWINDOW (XCAR (Fnth (make_number (1), w->crosshairs_cache)))
+      && EQ (w->contents, XCAR (Fnth (make_number (2), w->crosshairs_cache))))
+    remove_crosshairs = true;
+  if (remove_cursors
+      || remove_crosshairs)
+    {
+      struct frame *f = XFRAME (w->frame);
+      update_begin (f);
+      block_input ();
+      if (remove_cursors)
+        mc_calc (w, 1);
+      /* Remove crosshairs and delete the cache. */
+      if (remove_crosshairs)
+        mc_erase_crosshairs (w, true);
+      unblock_input ();
+      update_end (f);
+    }
+}
+
+int
+mc_crosshairs_p (struct window *w)
+{
+/* Moving the mouse triggers `update_window_cursor' which calls
+`display_and_set_cursor' that would otherwise remove a portion of the horizontal
+ruler at point and/or from point at end of visual line to window edge. */
+  if (!MINI_WINDOW_P (w)
+      && !w->mc.draw_crosshairs
+      && !NILP (w->crosshairs_cache)
+      && !NILP (BVAR (XBUFFER (w->contents), crosshairs))
+      && w == XWINDOW (XCAR (Fnth (make_number (1), w->crosshairs_cache)))
+      && EQ (w->contents, XCAR (Fnth (make_number (2), w->crosshairs_cache))))
+    return true;
+    else
+      return false;
+}
+
+int
+mc_without_update_frame (struct window *w)
+{
+/* `timer-list' / `timer-idle-list':  The boolean switches are not automatically
+turned on when a function attached to a timer is called.  We have switches that are
+set in `keyboard.c` for multiple fake cursors (e.g., a keyboard press).  We set
+the switches manually for both multiple cursors and crosshairs in conjunction with
+timer functions.  `update_frame' may not be called if there are no changes to the
+window/buffer.  To test this theory, throw the switches for crosshairs from an idle
+timer without drawing/erasing any overlays in the buffer.  `kbd_mc_activate_cursors'
+sets the multiple cursors boolean switches to `true` whenever there is a keyboard
+triggered command.  However, that does not necessarily mean that we need to draw
+multiple cursors.  Inasmuch as the multiple cursors boolean switches might have
+been set through a timer function, it is better to check the buffer local variables
+and the window caches.  In the case of crosshairs, the corresponding boolean
+switches are only set when we really want to draw the crosshairs.
+-  We also use this function as part of `update_window_cursor' when mousing over
+something that would ordinarily cause the real cursor to be redrawn. */
+      if (!NILP (w->mc_glyph_cache)
+          || !NILP (BVAR (XBUFFER (w->contents), mc_glyph_list))
+          || w->mc.draw_crosshairs
+          || mc_crosshairs_p (w))
+        {
+          /* We are bypassing `update_frame' and going straight to `mc_portal'. */
+          struct frame *f = XFRAME (w->frame);
+          update_begin (f);
+          block_input ();
+          mc_portal (w, true);
+          unblock_input ();
+          update_end (f);
+          return true;
+        }
+        else
+          return false;
+}
+
+DEFUN ("mc-activate-crosshairs", Fmc_activate_crosshairs, Smc_activate_crosshairs, 1, 1, 0,
+       doc: /* Doc-string. */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_live_window (window);
+  w->mc.draw_crosshairs = true;
+  w->mc.erase_crosshairs = true;
+  return Qnil;
+}
+
+DEFUN ("mc-activate-cursors", Fmc_activate_cursors, Smc_activate_cursors, 1, 1, 0,
+       doc: /* When using a timer, `kbd_mc_activate_cursors' in `keyboard.c' is not called.
+There are also some other circumstances where `mc-activate-cursors' is helpful. */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_live_window (window);
+  w->mc.draw_glyph_cursor = true;
+  w->mc.erase_glyph_cursor = true;
+  return Qnil;
+}
+
+DEFUN ("bug-28936", Fbug_28936, Sbug_28936, 1, 1, 0,
+       doc: /* Demonstrate the Emacs bug # 28936. */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_live_window (window);
+  struct it it;
+  void *itdata = bidi_shelve_cache ();
+  struct text_pos start_text_position;
+  int target_x;
+  enum move_it_result rc;
+  struct buffer *b = XBUFFER (w->contents);
+  b->word_wrap_ = Qt;
+  SET_TEXT_POS_FROM_MARKER (start_text_position, w->start);
+  start_display (&it, w, start_text_position);
+  move_it_to (&it, PT, it.last_visible_x, it.last_visible_y - 1, -1, MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+  target_x = it.current_x;
+  move_it_by_lines (&it, 0);
+  rc = mc_move_it_in_display_line (w, &it, target_x);
+  bidi_unshelve_cache (itdata, false);
+  return make_number (rc);
+}
+
+/* END multiple cursors */
+/* *************************************************************************** */
 
 
 /***********************************************************************
@@ -14162,6 +15703,19 @@ redisplay_internal (void)
 #ifdef HAVE_WINDOW_SYSTEM
 	      update_window_fringes (w, false);
 #endif
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+/* NOTE:  An idle-timer function may not necessarily trigger `redisplay_window'.
+`optimization 1` (which includes left/right cursor movement on the first screen
+line), and `optimization 3` (which includes left/right cursor movement on screen
+lines subsequent to the first screen line), bypass `redisplay_window'. */
+
+      mc_remove_everything (w);
+
+/* *************************************************************************** */
+
 	      goto update;
 	    }
 	  else
@@ -14184,6 +15738,16 @@ redisplay_internal (void)
 		  && (w = XWINDOW (selected_window)) != sw)
 		goto retry;
 
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+       if (mc_without_update_frame (w))
+         goto end_of_redisplay;
+
+/* *************************************************************************** */
+
+
 	      /* We used to always goto end_of_redisplay here, but this
 		 isn't enough if we have a blinking cursor.  */
 	      if (w->cursor_off_p == w->last_cursor_off_p)
@@ -14225,6 +15789,19 @@ redisplay_internal (void)
 		  *w->desired_matrix->method = 0;
 		  debug_method_add (w, "optimization 3");
 #endif
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+/* NOTE:  An idle-timer function may not necessarily trigger `redisplay_window'.
+`optimization 1` (which includes left/right cursor movement on the first screen
+line), and `optimization 3` (which includes left/right cursor movement on screen
+lines subsequent to the first screen line), bypass `redisplay_window'. */
+
+      mc_remove_everything (w);
+
+/* *************************************************************************** */
+
 		  goto update;
 		}
 	      else
@@ -14358,6 +15935,18 @@ redisplay_internal (void)
 		    unrequest_sigio ();
 		  STOP_POLLING;
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+    /* On Emacs for Windows, crosshairs will not draw at the beginning of the buffer
+    without this condition when the idle-timer switches are toggled.  This may have
+    been due to the parentheses overlays that were removed and did not need to be
+    redrawn since opening parentheses at the beginning of the buffer are not highlighted. */
+    if (w->mc.draw_crosshairs)
+      w->must_be_updated_p = true;
+
+/* *************************************************************************** */
+
 		  pending |= update_frame (f, false, false);
 		  f->cursor_type_changed = false;
 		  f->updated_p = true;
@@ -17564,6 +19153,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   else
     TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
 
+/* *************************************************************************** */
+/* BEGIN multiple cursors */
+
+/* NOTE:  An idle-timer function may not necessarily trigger `redisplay_window'.
+`optimization 1` (which includes left/right cursor movement on the first screen
+line), and `optimization 3` (which includes left/right cursor movement on screen
+lines subsequent to the first screen line), bypass `redisplay_window'. */
+
+  mc_record_x_wstart_wend (w);
+
+  mc_remove_everything (w);
+
+/* *************************************************************************** */
+
   set_buffer_internal_1 (old);
   /* Avoid an abort in TEMP_SET_PT_BOTH if the buffer has become
      shorter.  This can be caused by log truncation in *Messages*.  */
@@ -24608,6 +26211,25 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 	  return "@";
       }
 
+/* *************************************************************************** */
+/* multiple cursors */
+
+    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':
@@ -29468,9 +31090,19 @@ display_and_set_cursor (struct window *w, bool on,
       w->phys_cursor.vpos = vpos;
     }
 
-  FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
-                                     new_cursor_type, new_cursor_width,
-                                     on, active_cursor);
+/* *************************************************************************** */
+/* multiple cursors */
+
+  Lisp_Object color_vector = (Fmake_vector (make_number (3), Qnil));
+  ASET (color_vector, 0, make_float (-1.0));
+  ASET (color_vector, 1, make_float (-1.0));
+  ASET (color_vector, 2, make_float (-1.0));
+   FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
+                                      new_cursor_type, new_cursor_width,
+                                     on, active_cursor, color_vector, Qnil);
+
+/* *************************************************************************** */
+
 }
 
 
@@ -29502,10 +31134,28 @@ update_window_cursor (struct window *w, bool on)
       if (row->reversed_p && hpos >= row->used[TEXT_AREA])
 	hpos = row->used[TEXT_AREA] - 1;
 
-      block_input ();
-      display_and_set_cursor (w, on, hpos, vpos,
+/* *************************************************************************** */
+/* multiple cursors */
+
+      /* Moving the mouse triggers `update_window_cursor' which calls
+      `display_and_set_cursor' that would otherwise remove a portion of the
+      horizontal ruler from point at end of visual line to window edge. */
+      bool crosshairs_p = (!MINI_WINDOW_P (w)
+                           && !w->mc.draw_crosshairs
+                           && !NILP (w->crosshairs_cache)
+                           && !NILP (BVAR (XBUFFER (w->contents), crosshairs))
+                           && w == XWINDOW (XCAR (Fnth (make_number (1), w->crosshairs_cache)))
+                           && EQ (w->contents, XCAR (Fnth (make_number (2), w->crosshairs_cache))));
+      if (!crosshairs_p)
+        {
+       block_input ();
+       display_and_set_cursor (w, on, hpos, vpos,
 			      w->phys_cursor.x, w->phys_cursor.y);
-      unblock_input ();
+       unblock_input ();
+        }
+
+/* *************************************************************************** */
+
     }
 }
 
@@ -32216,6 +33866,26 @@ x_intersect_rectangles (XRectangle *r1, XRectangle *r2, XRectangle *result)
 void
 syms_of_xdisp (void)
 {
+
+/* *************************************************************************** */
+/* BEGIN multiple cursors */
+
+  DEFSYM (Qmc_glyph, "mc-glyph-cursor");
+  DEFSYM (Qmc_glyphless, "mc-glypless-cursor");
+  DEFSYM (Qmc_glyph_tab, "mc-glyph-tab");
+
+  defsubr (&Smc_activate_cursors);
+  DEFSYM (Qmc_activate_cursors, "mc-activate-cursors");
+
+  defsubr (&Smc_activate_crosshairs);
+  DEFSYM (Qmc_activate_crosshairs, "mc-activate-crosshairs");
+
+  defsubr (&Sbug_28936);
+  DEFSYM (Qbug_28936, "bug-28936");
+
+/* END multiple cursors */
+/* *************************************************************************** */
+
   Vwith_echo_area_save_vector = Qnil;
   staticpro (&Vwith_echo_area_save_vector);
 
diff --git a/src/xterm.c b/src/xterm.c
index 1b45cf1..f2a3cb7 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1163,10 +1163,12 @@ x_update_window_end (struct window *w, bool cursor_on_p,
     {
       block_input ();
 
-      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);
+/* *************************************************************************** */
+/* multiple cursors */
+
+      mc_portal (w, cursor_on_p);
+
+/* *************************************************************************** */
 
       if (draw_window_fringes (w, true))
 	{
@@ -1550,10 +1552,17 @@ static void x_check_font (struct frame *, struct font *);
 static void
 x_set_cursor_gc (struct glyph_string *s)
 {
-  if (s->font == FRAME_FONT (s->f)
+/* *************************************************************************** */
+/* multiple cursors */
+
+  struct window *w = decode_live_window (selected_window);
+  if ((s->font == FRAME_FONT (s->f)
       && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
       && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
       && !s->cmp)
+      || w->mc.cursor_gc_default)
+
+/* *************************************************************************** */
     s->gc = s->f->output_data.x->cursor_gc;
   else
     {
@@ -9310,7 +9319,16 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
 	 invisible.  Use the glyph's foreground color instead in this
 	 case, on the assumption that the glyph's colors are chosen so
 	 that the glyph is legible.  */
-      if (face->background == f->output_data.x->cursor_pixel)
+
+/* *************************************************************************** */
+/* multiple cursors */
+
+      if (face->background == f->output_data.x->cursor_pixel
+          && !w->mc.cursor_gc_invisible_okay)
+
+
+/* *************************************************************************** */
+
 	xgcv.background = xgcv.foreground = face->foreground;
       else
 	xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
@@ -9398,7 +9416,13 @@ 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)
+/* *************************************************************************** */
+/* multiple cursors */
+
+  int cursor_width, bool on_p, bool active_p,
+  Lisp_Object color_vector, Lisp_Object flavor)
+
+/* *************************************************************************** */
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
@@ -9417,31 +9441,124 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
 	}
       else
 	{
-	  switch (cursor_type)
-	    {
-	    case HOLLOW_BOX_CURSOR:
-	      x_draw_hollow_cursor (w, glyph_row);
-	      break;
 
-	    case FILLED_BOX_CURSOR:
-	      draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
-	      break;
-
-	    case BAR_CURSOR:
-	      x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
-	      break;
-
-	    case HBAR_CURSOR:
-	      x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
-	      break;
-
-	    case NO_CURSOR:
-	      w->phys_cursor_width = 0;
-	      break;
+/* *************************************************************************** */
+/* BEGIN multiple cursors */
+  double red = XFLOAT_DATA (AREF (color_vector, 0));
+  double green = XFLOAT_DATA (AREF (color_vector, 1));
+  double blue = XFLOAT_DATA (AREF (color_vector, 2));
+  switch (cursor_type)
+  {
+    case HOLLOW_BOX_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.x->cursor_pixel'.  */
+        {
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+          unsigned long orig_val = f->output_data.x->cursor_pixel;
+          int int_red = red * 65535;
+          int int_green = green * 65535;
+          int int_blue = blue * 65535;
+          f->output_data.x->cursor_pixel = x_make_truecolor_pixel (dpyinfo, int_red, int_green, int_blue);
+          x_draw_hollow_cursor (w, glyph_row);
+          f->output_data.x->cursor_pixel = orig_val;
+        }
+        else
+          x_draw_hollow_cursor (w, glyph_row);
+      break;
+    }
+    case FILLED_BOX_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.x->cursor_gc' by borrowing the
+        functionality of `x_make_gc' in xfns.c.  */
+        {
+          block_input ();
+          Lisp_Object window = (selected_window);
+          struct window *w = decode_live_window (window);
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+          int int_red = red * 65535;
+          int int_green = green * 65535;
+          int int_blue = blue * 65535;
+          XGCValues gc_values;
+          unsigned long mask = GCForeground | GCBackground | GCFillStyle | GCLineWidth;
+          unsigned long orig_val_a = FRAME_BACKGROUND_PIXEL (f);
+          unsigned long orig_val_b = f->output_data.x->cursor_pixel;
+          gc_values.line_width = 0;  /* Means 1 using fast algorithm.  */
+          gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
+          gc_values.background = x_make_truecolor_pixel (dpyinfo, int_red, int_green, int_blue);
+          gc_values.fill_style = FillOpaqueStippled;
+          f->output_data.x->cursor_gc
+            = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, &gc_values);
+          /* Force `x_set_cursor_gc' to use `s->f->output_data.x->cursor_gc'.  */
+          w->mc.cursor_gc_default = true;
+          draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+          w->mc.cursor_gc_default = false;
+          gc_values.line_width = 0;  /* Means 1 using fast algorithm.  */
+          gc_values.foreground = orig_val_a;
+          gc_values.background = orig_val_b;
+          gc_values.fill_style = FillOpaqueStippled;
+          f->output_data.x->cursor_gc
+            = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, &gc_values);
+          unblock_input ();
+        }
+        else
+          draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+      break;
+    }
+    case BAR_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.x->cursor_pixel'.  */
+        {
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+          unsigned long orig_val = f->output_data.x->cursor_pixel;
+          int int_red = red * 65535;
+          int int_green = green * 65535;
+          int int_blue = blue * 65535;
+          f->output_data.x->cursor_pixel = x_make_truecolor_pixel (dpyinfo, int_red, int_green, int_blue);
+          w->mc.cursor_gc_invisible_okay = true;
+          x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+          w->mc.cursor_gc_invisible_okay = false;
+          f->output_data.x->cursor_pixel = orig_val;
+        }
+        else
+          x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+      break;
+    }
+    case HBAR_CURSOR:
+    {
+      if (red >= 0 && blue >= 0 && green >= 0)
+        /* Temporarily hijack `f->output_data.x->cursor_pixel'.  */
+        {
+          struct frame *f = XFRAME (WINDOW_FRAME (w));
+          struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+          unsigned long orig_val = f->output_data.x->cursor_pixel;
+          int int_red = red * 65535;
+          int int_green = green * 65535;
+          int int_blue = blue * 65535;
+          f->output_data.x->cursor_pixel = x_make_truecolor_pixel (dpyinfo, int_red, int_green, int_blue);
+          w->mc.cursor_gc_invisible_okay = true;
+          x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+          w->mc.cursor_gc_invisible_okay = false;
+          f->output_data.x->cursor_pixel = orig_val;
+        }
+        else
+          x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+      break;
+    }
+    case NO_CURSOR:
+      w->phys_cursor_width = 0;
+      break;
+    default:
+      emacs_abort ();
+  }
+/* END multiple cursors */
+/* *************************************************************************** */
 
-	    default:
-	      emacs_abort ();
-	    }
 	}
 
 #ifdef HAVE_X_I18N
