Subject: Re: bug#22873: Can we support multiple cursors?

From: Keith David Bershatsky <[email-masked]>
Date: Sun, 13 Aug 2017 20:20:10 -0700

I read through the comments in xdisp.c that immediately precede move_it_to and I also looked at all of it uses within xdisp.c, but I am still unclear how to limit move_it_to the it.last_visible_y.  I got the impression that if I put it.last_visible_y as an argument of move_it_to, that `it` would move to that location instead of POS if POS cannot be found.  I'd like the function mc_x_y_hpos_vpos to return valid coordinates if POSINT is on the visible window, or -1 for all four coordinates if it is not visible.  I'm calling mc_x_y_hpos_vpos late in the redisplay cycle and the START/END arguments "should be" correct.  I am unclear as why the Y and VPOS were sometimes out of bounds in a few corner cases (e.g., when I compiled a tex document that had errors in the LaTeX code) -- my best guess is that START/END may have been wrong because another window was opened displaying the tex compile messages.

I was pretty sure that I could substitute window_box_height for window-body-height (with a non-nil PIXELWISE argument), and that is why I phrased that previous comment with a degree of uncertainty.  Based on your comment, I now feel better about using window_box_height.  I was unaware that my usage of move_it_to may have been incorrect, so that is why I was trying to come up with new ways to workaround coordinates that were out of bounds.  If we can fix mc_x_y_hpos_vpos, then there would be no need to perform additional subsequent checks to see whether the values were correct.

Drawing and erasing fake cursors is done by temporarily hijacking w->phys_cursor and then calling either erase_phys_cursor or draw_window_cursor.

Today, I added "if (it.current_y >= it.last_visible_y) ... goto done"

Lisp_Object
mc_x_y_hpos_vpos (struct window *w, EMACS_INT posint, EMACS_INT start, EMACS_INT end)
{
  struct it it;
  void *itdata = bidi_shelve_cache ();
  struct text_pos pt;
  int x, y, hpos, vpos;
  if (posint >= start
      && posint <= end)
    {
      SET_TEXT_POS_FROM_MARKER (pt, w->start);
      start_display (&it, w, pt);
      move_it_to (&it, posint, -1, -1, -1, MOVE_TO_POS);
      if (it.current_y >= it.last_visible_y)
        {
          bidi_unshelve_cache (itdata, false);
          goto done;
        }
      x = it.current_x;
      y = it.current_y;
      hpos = it.hpos;
      vpos = it.vpos;
      bidi_unshelve_cache (itdata, false);
    }
    else
      {
        done:
        x = -1;
        y = -1;
        hpos = -1;
        vpos = -1;
      }
  return
    listn (CONSTYPE_HEAP, 4, make_number (x), make_number (y), make_number (hpos), make_number (vpos));
}