[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?