Subject: bug#17684: #22873 (multiple fake cursors); and, #17684 (crosshairs / fill-column).

From: Keith David Bershatsky <[email-masked]>
Date: Thu, 13 Dec 2018 23:11:07 -0800

Version 017.000 [12/13/2018]

CHANGELOG:

-  nsterm.m:  Cursors are now drawn subsequent to the expose_frame/window loop
   of dirty rectangles within drawRect.  `update_window_cursor' within
   `expose_frame' is now disabled when HAVE_NS.

-  FRAMED_BOX_CURSOR is a new cursor type that is a variant of the
   FILLED_BOX_CURSOR, which has support for different colors depending upon
   whether it is in the active/inactive window and at the beginning/ending of
   an active region.

-  Visible fill column now takes into consideration the line number pixel-width
   and horizontal scrolling (if any) when calculating the X coordinate.

-  Disabled visible fill column when X coordinate is beyond text area width, and
   when prior to the line number pixel width (or zero if no line numbers) with
   horizontal scrolling in effect.

-  Restricted trace-redisplay messages to just the most relevant functions.

-  Customized a few of the faces to provide better visibility of crosshairs with
   a white background in an Emacs -Q situation.

-  Eliminated the usage of MC_GLYPH_TAB as there are really only two kinds that
   are used:  MC_GLYPH | MC_GLYPHLESS

-  Eliminated a few abort / immediate return of functions that appear to no
   longer be necessary to avoid crashing Emacs.

-  Fixed one cash in the multiple fake cursors section of code when the real
   cursor is not associated with a glyph; i.e., `get_phys_cursor_glyph' == NULL.

-  As to the real fake cursor of crosshairs (intersection of vertical/horizontal
   rulers), when mc-real-fake-cursor is nil/"no"/'no, the BAR_CURSOR now uses
   MC_GLYPHLESS so as not to create a superimposed glyph on top of the MC_GLYPH
   that was placed when drawing the horizontal ruler.

-  Identified a right overhang situation that causes the fake cursor over a
   STRETCH to be erased.  [Additional work is needed projects to be done below.]

-  `mc_get_phys_cursor_geometry' now uses `row->visible_height' without taking
   into consideration the FRAME_LINE_HEIGHT.

-  Added some tracing messages to a couple of functions.

-  Miscellaneous minor bug fixes.

SETUP:

Step 1:  git clone -b master git://git.sv.gnu.org/emacs.git

Step 2:  In the new emacs folder, go back to an Emacs version from 12/13/2018:

git reset --hard 8ffc0f2dd753879b0795714c29c86082aa9fd155

Step 3:  From within the new emacs folder created in Step 1, apply the patch:

git apply /path/to/the/attached.diff

[There should not be any error messages at this point; i.e, you should be returned to a new command prompt.]

Step 4:  ./autogen.sh

Step 5:  ./configure ... [your custom options]

Step 6:  make

Step 7:  make install

-  To try out built-in fake cursors with Magnar Sveen's library (multiple-cursors), install that package first.  [If the multiple-cursors package is installed, an eval-after-load "multiple-cursors-core" statement within crosshairs.el will redefine a couple of functions and set up a few keyboard shortcuts.]  If the multiple-cursors package by Magnar Sveen is not already installed, then there are two easy ways to install that package:

   Type:  M-x mc-install

   OR, evaluate the following snippet:

  (progn
    (require 'package)
    (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
    (package-initialize)
    (package-refresh-contents)
    (package-install 'multiple-cursors))

-  To try out crosshairs and the visible fill column, type:  M-x +-mode

-  To try out only the visible fill column, type:  M-x mc-fill-column-mode

-  To try out the new cursor-type of a FRAMED_BOX_CURSOR without anything extra,
   evaluate the following snippet -- see the difference between inactive/active
   windows, and also the beginning/ending of an active region selection:

   (setq cursor-type 'framed
         cursor-in-non-selected-windows 'framed)

-  To use the new cursor type of a FRAMED_BOX_CURSOR with crosshairs or multiple
   fake cursors, evaluate the following snippet:

   (setq mc-real-fake-cursor 'framed)

-  To learn how to use the multiple fake cursors feature, examine the
   interactive function `mc-test'.

-  EXAMPLE OF HOW TO USE MULTIPLE FAKE CURSORS:

  ;;; (BUFFER-POSITION CURSOR-TYPE CURSOR-COLOR)
  ;;;
  (setq multiple-cursors-conf '((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])))

  ;;; TURN OFF.
  ;;;
  (setq multiple-cursors-conf nil)

TODO:

-  The current test for `auto_hscroll_mode_p' only looks for `current_line` and
   all five related tests are based upon that assumption, which may not be true.

-  Continue working on the sections of code within `draw_glyphs' that are
   responsible for redrawing a stretch tab (erasing a fake cursor) when the
   previous/next character has a left/right overhang.
   left_overwritten:  "	A"
   right_overwritten (GNU Emacs welcome screen without `buffer-display-table')
   and the real fake cursor is to the immediate right of the word "Tour":
   "Emacs Guided Tour	Overview".

-  Multiple Cursors:  If point is in the middle of a composite character, then
   select a fully composed character so that the fake cursor is visible.

-  Fake cursors are being redrawn too often when non-selected visible windows
   have an ongoing process that require frequent redisplay updates (e.g.,
   an eshell buffer.  @lawlist may have already corrected the frequent redisplay
   issue as to mouse-overs, but will need to check this once again to be sure.

-  Set up some tests to see what (if anything) needs to be done so that
   these features play nicely with certain overlays and text properties.

-  Implement functionality similar to Lisp multiple-cursors by Magnar Sveen.

-  Create a comprehensive list of items to test when modifying these features;
   and, add a test file.

-  Follow up with the Emacs team re bug#32177; i.e., (Current line number shifts
   one column to the left.)

-  Follow up with the Emacs team re bug#32060; i.e., (Horizontal Scrolling
   (Current Line):  Wrong line gets h-scrolled.)

-  Determine if bug #28936 needs to be fixed and help the Emacs team re same.

HOW DOES IT WORK?

-  Fake cursors are removed in two (2) locations within `redisplay_internal'
(if the cursor cache exists).  If the frame is not being updated, then call
`update_begin' before removing and call `update_end' when removing is complete.

-  Fake cursors are removed in two (2) locations within `redisplay_window'
(if the cursor cache exists).  If the frame is not being updated, then call
`update_begin' before removing and call `update_end' when removing is complete.

-  Whenever `display_and_set_cursor' is called and not immediately returned,
cursors are calculated and drawn; or, if the cursor cache already exist, then
erase and redraw.  If the frame is not being updated, then call `update_begin'
before drawing/removing and call `update_end' when drawing/removing is complete.

-  The calculations for drawing fake cursors are based upon modified versions
of the functions `dump_glyph_matrix' and `dump_glyph_row', which generate the
correct coordinates for placing the fake cursors.

-  Fake cursors come in two types:  (1) cursor with a glyph on top; (2) cursor
with nothing on top [e.g., floating anywhere on the visible window].

-  There are two basic settings:  (1) draw or erase/redraw forthwith (whenever
the real cursor would ordinarily be drawn); or, (2) draw on an idle-timer and,
if the cursor cache exists, then erase/redraw in certain circumstances when the
real cursor would ordinarily be redrawn.  New calculations and cursor cache
update occur on the initial call of either of the aforementioned two scenarios.

-  All three features (multiple fake cursors, crosshairs, and visible fill
column) operate on the same principal.  There are similar functions for each
feature, with the only main difference being that multiple fake cursors look for
a particular buffer position when dumping the glyph matrix and looping through
each row, whereas crosshairs and visible fill column look for a particular
window relative X coordinate.

-  At this time, there is nothing fancy about multiple fake cursors -- i.e.,
Emacs only looks for a buffer position and creates a fake cursor with the
desired cursor type and cursor color.  Magnar's Lisp library is still the only
mechanism I am aware of that does the magic.  Instead of placing a visible
overlay where fake cursors would ordinarily be created using Magnar's library,
there are a few modifications to his Lisp functions that are contained within
crosshairs.el.  From the list of fake cursor overlays created by Magnar's
library, Emacs gathers the list of buffer positions and then draws built-in fake
cursors that are within the confines of the visible windows.