emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to obtain x/y/hpos/vpos at eol -- excluding overlay 'after-strin


From: Keith David Bershatsky
Subject: Re: How to obtain x/y/hpos/vpos at eol -- excluding overlay 'after-string.
Date: Tue, 05 Apr 2016 10:37:44 -0700

There two (2) major roadblocks that I have encountered with multiple cursors:

PROBLEM # 1:  `mc_x_y_hpos_vpos` needs to be modified to exclude overlays from 
the calculation so that placement and removal of fake cursors can be correctly 
achieved.  Any assistance in modifying this function to exclude overlays from 
the calculation would be greatly appreciated.

    /* The mission critical function used by multiple cursors to extract 
coordinates.  */
    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, pos;
      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);
          pos = it.current.pos;
          x = it.current_x;
          y = it.current_y;
          hpos = it.hpos;
          vpos = it.vpos;
          bidi_unshelve_cache (itdata, false);
        }
        else
          {
            x = -1;
            y = -1;
            hpos = -1;
            vpos = -1;
          }
      return listn (CONSTYPE_PURE, 4, make_number (x), make_number (y), 
make_number (hpos), make_number (vpos));
    }


PROBLEM # 2:  When no scrolling occurs, the cache of previously laid multiple 
cursors is sufficient to remove them.  When scrolling occurs (less than a full 
screen) -- e.g., previous/next-line or scroll-up/down -- the multiple cursors 
become moving targets.  In that scenario, the previously recorded x/y/hpos/vpos 
will not suffice.  I tried something elaborate to calculate the differential of 
`y` and `vpos` based on scrolling; however, that didn't work.  Either my 
calculations are way off, or I do not understand what is happening when 
scrolling occurs.  My idea was that I could add or subtract the differential 
from the stored values in the cache to pinpoint the new locations for the 
previously laid multiple cursors whenever scrolling occurred.

LEGEND:
* `start`:  window-start.
* `end`:  window-end.
* `prev`:  value from the prior command loop.
* `opoint`:  original point.
* `y_diff`:  differential of `y` coordinate between command loops.
* `vpos_diff:  differential of `vpos` between command loops.

  if ((!NILP (BVAR (current_buffer, mc_list)) || w->mc_cache)
      && !MINI_WINDOW_P (w))
    {
      Lisp_Object x_y_hpos_vpos_list;
      EMACS_INT start = CHARPOS (startp);
      EMACS_INT end = BUF_Z (buffer) - w->window_end_pos;
      if (w->mc.set_start_end)
        {
          if (w->mc.start)
            {
              w->mc.prev_start = w->mc.start;
              x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, w->mc.prev_start, 
start, end);
              w->mc.prev_start_x = XINT (Fnth (make_number (0), 
x_y_hpos_vpos_list));
              w->mc.prev_start_y = XINT (Fnth (make_number (1), 
x_y_hpos_vpos_list));
              w->mc.prev_start_hpos = XINT (Fnth (make_number (2), 
x_y_hpos_vpos_list));
              w->mc.prev_start_vpos = XINT (Fnth (make_number (3), 
x_y_hpos_vpos_list));
            }
            else
              {
                w->mc.prev_start = -1;
                w->mc.prev_start_x = -1;
                w->mc.prev_start_y = -1;
                w->mc.prev_start_hpos = -1;
                w->mc.prev_start_vpos = -1;
              }
          if (w->mc.end)
            {
              w->mc.prev_end = w->mc.end;
              /* eob IS visible].
              Excludes a situation when last visible line at bottom of window 
contains eob.  */
              if (w->mc.prev_end == end)
                {
                  x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, w->mc.prev_end, 
start, end);
                  w->mc.prev_end_x = w->mc.end_x;
                  w->mc.prev_end_y = w->mc.end_y;
                  w->mc.prev_end_hpos = w->mc.end_hpos;
                  w->mc.prev_end_vpos = w->mc.end_vpos;
                }
                /* eob is NOT visible.
                Excludes a situation when last visible line at bottom of window 
contains eob.  **/
                else
                  {
                    x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, w->mc.prev_end, 
start, end);
                    w->mc.prev_end_x = XINT (Fnth (make_number (0), 
x_y_hpos_vpos_list));
                    w->mc.prev_end_y = XINT (Fnth (make_number (1), 
x_y_hpos_vpos_list));
                    w->mc.prev_end_hpos = XINT (Fnth (make_number (2), 
x_y_hpos_vpos_list));
                    w->mc.prev_end_vpos = XINT (Fnth (make_number (3), 
x_y_hpos_vpos_list));
                  }
            }
            else
              {
                w->mc.prev_end = -1;
                w->mc.prev_end_x = -1;
                w->mc.prev_end_y = -1;
                w->mc.prev_end_hpos = -1;
                w->mc.prev_end_vpos = -1;
              }
          if (w->mc.opoint)
            {
              w->mc.prev_opoint = w->mc.opoint;
              w->mc.prev_opoint_x = w->mc.opoint_x;
              w->mc.prev_opoint_y = w->mc.opoint_y;
              w->mc.prev_opoint_hpos = w->mc.opoint_hpos;
              w->mc.prev_opoint_vpos = w->mc.opoint_vpos;
            }

          /* FIXME -- the X and HPOS will always be wrong if point is at an 
overlay after-string.  */
          w->mc.opoint = PT;
          x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, w->mc.opoint, start, end);
          w->mc.opoint_x = XINT (Fnth (make_number (0), x_y_hpos_vpos_list));
          w->mc.opoint_y = XINT (Fnth (make_number (1), x_y_hpos_vpos_list));
          w->mc.opoint_hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos_list));
          w->mc.opoint_vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos_list));

          w->mc.start = start;
          x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, start, start, end);
          w->mc.start_x = XINT (Fnth (make_number (0), x_y_hpos_vpos_list));
          w->mc.start_y = XINT (Fnth (make_number (1), x_y_hpos_vpos_list));
          w->mc.start_hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos_list));
          w->mc.start_vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos_list));

          w->mc.end = end;
          x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, end, start, end);
          w->mc.end_x = XINT (Fnth (make_number (0), x_y_hpos_vpos_list));
          w->mc.end_y = XINT (Fnth (make_number (1), x_y_hpos_vpos_list));
          w->mc.end_hpos = XINT (Fnth (make_number (2), x_y_hpos_vpos_list));
          w->mc.end_vpos = XINT (Fnth (make_number (3), x_y_hpos_vpos_list));

          /* Start remains the same.  */
          if (w->mc.prev_start_vpos == w->mc.start_vpos
              || w->mc.prev_end < w->mc.start)
            {
              w->mc.y_diff = 0;
              w->mc.vpos_diff = 0;
            }
            /* Screen moved ▼ -- e.g., `previous-line', `scroll-down'.  */
            else if (w->mc.prev_start_vpos > 0)
              {
                w->mc.y_diff = (w->mc.prev_start_y - w->mc.start_y) * -1;
                w->mc.vpos_diff = (w->mc.prev_start_vpos - w->mc.start_vpos) * 
-1;
              }
              /* Screen moved ▲ (eob NOT visible) -- e.g., `next-line', 
`scroll-up'.  */
              else if (w->mc.end_vpos > w->mc.prev_end_vpos && w->mc.prev_end 
!= -1)
                {
                  w->mc.y_diff = w->mc.end_y - w->mc.prev_end_y;
                  w->mc.vpos_diff = w->mc.end_vpos - w->mc.prev_end_vpos;
                }
                /* Screen moved ▲ (eob IS visible) -- e.g., `next-line', 
`scroll-up'.  */
                else if (w->mc.end_vpos < w->mc.prev_end_vpos && w->mc.prev_end 
!= -1)
                  {
                    w->mc.y_diff = w->mc.prev_end_y - w->mc.end_y;
                    w->mc.vpos_diff = w->mc.prev_end_vpos - w->mc.end_vpos;
                  }
                  /* Screen moved ▲ (eob just became visible) -- e.g., 
`next-line', `scroll-up'.
                  Absent subtracting 1 from w->mc.prev_end, that point and the 
new w->mc.end are
                  on the same line and it appears that nothing has changed -- 
w->mc.prev_end is
                  on the far left of the line and w->mc.end is on the far right 
of the line.  */
                  else if (w->mc.end_vpos == w->mc.prev_end_vpos)
                    {
                      x_y_hpos_vpos_list = mc_x_y_hpos_vpos (w, w->mc.prev_end 
- 1, start, end);
                      w->mc.prev_end_x = XINT (Fnth (make_number (0), 
x_y_hpos_vpos_list));
                      w->mc.prev_end_y = XINT (Fnth (make_number (1), 
x_y_hpos_vpos_list));
                      w->mc.prev_end_hpos = XINT (Fnth (make_number (2), 
x_y_hpos_vpos_list));
                      w->mc.prev_end_vpos = XINT (Fnth (make_number (3), 
x_y_hpos_vpos_list));
                      w->mc.y_diff = w->mc.end_y - w->mc.prev_end_y;
                      w->mc.vpos_diff = w->mc.end_vpos - w->mc.prev_end_vpos;
                    }
                /* `mc-list` has just been initialized -- previous start/end 
are set to -1.  */
                    else if (w->mc.prev_end == -1)
                      {
                        w->mc.y_diff = 0;
                        w->mc.vpos_diff = 0;
                      }

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

At Tue, 05 Apr 2016 18:08:09 +0300,
Eli Zaretskii wrote:
> 
> * * *
> 
> This is indeed about something you do in C.  However, I don't
> understand why you try using posn-at-point, which is a Lisp API, for a
> job you need to do in C.  On the C level, you have access to a more
> elaborate information, e.g. you can examine the object at point and do
> something when it is an overlay string.
> 
> I must admit I still don't see clearly why you need screen coordinates
> corresponding to a buffer position, in the multiple-curses scenario.
> Isn't it your code that positions those cursors in the first place?
> If so, why do you need to find out where those cursors are, if your
> code did the positioning?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]