diff --git a/src/alloc.c b/src/alloc.c
index dd78386..570022f 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6206,6 +6206,29 @@ garbage_collect_1 (struct gcstat *gcst)
 
   *gcst = gcstat;
 
+
+/* *************************************************************************** */
+/* begin DEBUGGING */
+
+  Lisp_Object total[] = {
+    list2 (intern ("cons_cells_consed"), make_int (cons_cells_consed)),
+    list2 (intern ("symbols_consed"), make_int (symbols_consed)),
+    list2 (intern ("strings_consed"), make_int (strings_consed)),
+    list2 (intern ("string_chars_consed"), make_int (string_chars_consed)),
+    list2 (intern ("vector_cells_consed"), make_int (vector_cells_consed)),
+    list2 (intern ("floats_consed"), make_int (floats_consed)),
+    list2 (intern ("intervals_consed"), make_int (intervals_consed)),
+  };
+
+  Lisp_Object val = CALLMANY (Flist, total);
+  Lisp_Object string = Fprin1_to_string (val, Qnil);
+  char *char_string = SSDATA (string);
+  fprintf (stderr, "\n%s\n", char_string);
+
+/* end DEBUGGING */
+/* *************************************************************************** */
+
+
   /* GC is complete: now we can run our finalizer callbacks.  */
   run_finalizers (&doomed_finalizers);
 
diff --git a/src/buffer.c b/src/buffer.c
index ab47748..0364eba 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -133,6 +133,21 @@ CHECK_OVERLAY (Lisp_Object x)
 
 /* These setters are used only in this file, so they can be private.
    The public setters are inline functions defined in buffer.h.  */
+
+
+/* *************************************************************************** */
+/* begin MULTIPLE-CURSORS */
+
+static void
+bset_crosshairs (struct buffer *b, Lisp_Object val)
+{
+  b->crosshairs_ = val;
+}
+
+/* end MULTIPLE-CURSORS */
+/* *************************************************************************** */
+
+
 static void
 bset_abbrev_mode (struct buffer *b, Lisp_Object val)
 {
@@ -5142,6 +5157,16 @@ init_buffer_once (void)
   bset_last_selected_window (&buffer_local_flags, make_fixnum (0));
 
   idx = 1;
+
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+  XSETFASTINT (BVAR (&buffer_local_flags, crosshairs), 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;
@@ -5228,6 +5253,16 @@ init_buffer_once (void)
   /* Must do these before making the first buffer! */
 
   /* real setup is done in bindings.el */
+
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+  bset_crosshairs (&buffer_defaults, Qnil);
+
+/* *************************************************************************** */
+
+
   bset_mode_line_format (&buffer_defaults, build_pure_c_string ("%-"));
   bset_header_line_format (&buffer_defaults, Qnil);
   bset_abbrev_mode (&buffer_defaults, Qnil);
@@ -5464,6 +5499,15 @@ syms_of_buffer (void)
   staticpro (&QSFundamental);
   staticpro (&Vbuffer_alist);
 
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+  DEFSYM (Qcrosshairs, "crosshairs");
+
+/* *************************************************************************** */
+
+
   DEFSYM (Qchoice, "choice");
   DEFSYM (Qleft, "left");
   DEFSYM (Qright, "right");
@@ -5501,6 +5545,16 @@ syms_of_buffer (void)
   Fput (Qprotected_field, Qerror_message,
 	build_pure_c_string ("Attempt to modify a protected field"));
 
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+  DEFVAR_PER_BUFFER ("crosshairs", &BVAR (current_buffer, crosshairs), Qnil,
+    doc: /* A bufer-local variable to activate/deactivate crosshairs. */);
+
+/* *************************************************************************** */
+
+
   DEFVAR_PER_BUFFER ("header-line-format",
 		     &BVAR (current_buffer, header_line_format),
 		     Qnil,
diff --git a/src/buffer.h b/src/buffer.h
index f42c3e9..233dbca 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -636,6 +636,16 @@ 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 the buffer-local variable. */
+  Lisp_Object crosshairs_;
+
+/* *************************************************************************** */
+
+
   /* 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
diff --git a/src/dispnew.c b/src/dispnew.c
index ccb08ec..5068b11 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3384,10 +3384,39 @@ check_current_matrix_flags (struct window *w)
 /* Update display of window W.
    If FORCE_P, don't stop updating when input is pending.  */
 
+static Lisp_Object
+mc_listn (ptrdiff_t count, Lisp_Object arg, ...)
+{
+  eassume (0 < count);
+  Lisp_Object val = Fcons (arg, Qnil);
+  Lisp_Object tail = val;
+  va_list ap;
+  va_start (ap, arg);
+  for (ptrdiff_t i = 1; i < count; i++)
+    {
+      Lisp_Object elem = Fcons (va_arg (ap, Lisp_Object), Qnil);
+      XSETCDR (tail, elem);
+      tail = elem;
+    }
+  va_end (ap);
+  return val;
+}
+
 static bool
 update_window (struct window *w, bool force_p)
 {
   struct glyph_matrix *desired_matrix = w->desired_matrix;
+
+
+/* *************************************************************************** */
+/* begin MULTIPLE-CURSORS */
+
+  wset_ch_cache (w, Qnil);
+
+/* end MULTIPLE-CURSORS */
+/* *************************************************************************** */
+
+
   bool paused_p;
   int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
   struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
@@ -3497,6 +3526,48 @@ update_window (struct window *w, bool force_p)
 
     set_cursor:
 
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+   for (struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, 0);
+        desired_row < end
+        && (force_p || !input_pending)
+        && BUFFERP (w->contents)
+        && (!NILP (BVAR (XBUFFER (w->contents), crosshairs)));
+        ++desired_row)
+    {
+      if (desired_row->enabled_p)
+        continue;
+      wset_mc_temp_cache (w, Qnil);
+      int vpos = MATRIX_ROW_VPOS (desired_row, desired_matrix);
+      struct glyph_matrix *current_matrix = w->current_matrix;
+      struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
+      if (current_row->enabled_p)
+        {
+          Lisp_Object temp_result = Qnil;
+          for (int i = 0; i < 100; ++i)
+            {
+              Lisp_Object temp_sublist = mc_listn (1, make_fixnum (i));
+              temp_result = Fcons (temp_sublist, temp_result);
+            }
+          wset_mc_temp_cache (w, temp_result);
+        }
+    }
+
+  wset_mc_temp_cache (w, Qnil);
+
+  Lisp_Object result = Qnil;
+  for (int ii = 0; ii < 100; ++ii)
+    {
+      Lisp_Object sublist = mc_listn (1, make_fixnum (ii));
+      result = Fcons (sublist, result);
+    }
+  wset_ch_cache (w, result);
+
+/* *************************************************************************** */
+
+
       /* Update the header line after scrolling because a new header
 	 line would otherwise overwrite lines at the top of the window
 	 that can be scrolled.  */
diff --git a/src/pdumper.c b/src/pdumper.c
index cb2915c..dc79eb1 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2770,7 +2770,7 @@ dump_hash_table (struct dump_context *ctx,
 static dump_off
 dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
 {
-#if CHECK_STRUCTS && !defined HASH_buffer_E34A11C6B9
+#if CHECK_STRUCTS && !defined HASH_buffer_B712F6B3DC
 # error "buffer changed. See CHECK_STRUCTS comment."
 #endif
   struct buffer munged_buffer = *in_buffer;
diff --git a/src/window.h b/src/window.h
index fdef407..40b78ec 100644
--- a/src/window.h
+++ b/src/window.h
@@ -209,6 +209,21 @@ struct window
     /* An alist with parameters.  */
     Lisp_Object window_parameters;
 
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+    Lisp_Object mc_temp_cache;
+
+    /* The cache for crosshairs. */
+    Lisp_Object ch_cache;
+
+/* NOTE:  As of 04/08/2019 (a038df77de7b1aa2d73a6478493b8838b59e4982), the LAST
+   Lisp_Object must be `mode_line_help_echo'. */
+
+/* *************************************************************************** */
+
+
     /* The help echo text for this window.  Qnil if there's none.  */
     Lisp_Object mode_line_help_echo;
 
@@ -443,6 +458,25 @@ struct window
     ptrdiff_t window_end_bytepos;
   } GCALIGNED_STRUCT;
 
+
+/* *************************************************************************** */
+/* MULTIPLE-CURSORS */
+
+INLINE void
+wset_mc_temp_cache (struct window *w, Lisp_Object val)
+{
+  w->mc_temp_cache = val;
+}
+
+INLINE void
+wset_ch_cache (struct window *w, Lisp_Object val)
+{
+  w->ch_cache = val;
+}
+
+/* *************************************************************************** */
+
+
 INLINE bool
 WINDOWP (Lisp_Object a)
 {
