mirror of
https://github.com/tmux/tmux.git
synced 2026-02-14 01:59:18 +00:00
Associate each visible_ranges with some other object (tty, popup_data, etc) so
it is easier to keep track of its lifecycle, but still avoid allocating for each use.
This commit is contained in:
79
popup.c
79
popup.c
@@ -39,6 +39,9 @@ struct popup_data {
|
||||
struct grid_cell defaults;
|
||||
struct colour_palette palette;
|
||||
|
||||
struct visible_ranges r;
|
||||
struct visible_ranges or[2];
|
||||
|
||||
struct job *job;
|
||||
struct input_ctx *ictx;
|
||||
int status;
|
||||
@@ -164,50 +167,57 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
|
||||
}
|
||||
|
||||
/* Return parts of the input range which are not obstructed by the popup. */
|
||||
static void
|
||||
popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx,
|
||||
struct visible_ranges *r)
|
||||
static struct visible_ranges *
|
||||
popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
struct popup_data *pd = data;
|
||||
static struct visible_ranges or[2] = { { NULL, 0, 0 }, { NULL, 0, 0 } };
|
||||
u_int i, j, k = 0;
|
||||
struct popup_data *pd = data;
|
||||
struct visible_ranges *r = &pd->r;
|
||||
struct visible_ranges *mr;
|
||||
u_int i, j, k = 0;
|
||||
|
||||
if (pd->md != NULL) {
|
||||
/* Check each returned range for the menu against the popup. */
|
||||
menu_check_cb(c, pd->md, px, py, nx, r);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
server_client_overlay_range(pd->px, pd->py, pd->sx,
|
||||
pd->sy, r->ranges[i].px, py, r->ranges[i].nx, &or[i]);
|
||||
}
|
||||
/*
|
||||
* Work out the visible ranges for the menu (that is, the
|
||||
* ranges not covered by the menu). A menu should have at most
|
||||
* two ranges and we rely on this being the case.
|
||||
*/
|
||||
mr = menu_check_cb(c, pd->md, px, py, nx);
|
||||
if (mr->used > 2)
|
||||
fatalx("too many menu ranges");
|
||||
|
||||
/* Caller must free when no longer used. */
|
||||
if (r->size == 0) {
|
||||
r->ranges = xcalloc(2, sizeof(struct visible_range));
|
||||
r->size = 2;
|
||||
r->used = 0;
|
||||
/*
|
||||
* Walk the ranges still visible under the menu and check if
|
||||
* each is visible under the popup as well. At most there can be
|
||||
* three total ranges if popup and menu do not intersect.
|
||||
*/
|
||||
for (i = 0; i < mr->used; i++) {
|
||||
server_client_overlay_range(pd->px, pd->py, pd->sx,
|
||||
pd->sy, r->ranges[i].px, py, r->ranges[i].nx,
|
||||
&pd->or[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* or has up to OVERLAY_MAX_RANGES non-overlapping ranges,
|
||||
* ordered from left to right. Collect them in the output.
|
||||
* We now have nonoverlapping ranges from left to right.
|
||||
* Combine them together into the output.
|
||||
*/
|
||||
for (i = 0; i < r->used; i++) {
|
||||
/* Each or[i] only has up to 2 ranges. */
|
||||
for (j = 0; j < or[i].used; j++) {
|
||||
if (or[i].ranges[j].nx > 0) {
|
||||
r->ranges[k].px = or[i].ranges[j].px;
|
||||
r->ranges[k].nx = or[i].ranges[j].nx;
|
||||
k++;
|
||||
}
|
||||
server_client_ensure_ranges(r, 3);
|
||||
for (i = 0; i < mr->used; i++) {
|
||||
for (j = 0; j < pd->or[i].used; j++) {
|
||||
if (pd->or[i].ranges[j].nx == 0)
|
||||
continue;
|
||||
if (k >= 3)
|
||||
fatalx("too many popup & menu ranges");
|
||||
r->ranges[k].px = pd->or[i].ranges[j].px;
|
||||
r->ranges[k].nx = pd->or[i].ranges[j].nx;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
return (r);
|
||||
}
|
||||
|
||||
server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy,
|
||||
px, py, nx, r);
|
||||
|
||||
return;
|
||||
server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy, px, py, nx,
|
||||
r);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -288,6 +298,9 @@ popup_free_cb(struct client *c, void *data)
|
||||
job_free(pd->job);
|
||||
input_free(pd->ictx);
|
||||
|
||||
free(pd->or[0].ranges);
|
||||
free(pd->or[1].ranges);
|
||||
free(pd->r.ranges);
|
||||
screen_free(&pd->s);
|
||||
colour_palette_free(&pd->palette);
|
||||
|
||||
@@ -551,7 +564,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
|
||||
(event->key == '\033' || event->key == ('c'|KEYC_CTRL)))
|
||||
return (1);
|
||||
if (pd->job == NULL && (pd->flags & POPUP_CLOSEANYKEY) &&
|
||||
!KEYC_IS_MOUSE(event->key) && !KEYC_IS_PASTE(event->key))
|
||||
!KEYC_IS_MOUSE(event->key) && !KEYC_IS_PASTE(event->key))
|
||||
return (1);
|
||||
if (pd->job != NULL) {
|
||||
if (KEYC_IS_MOUSE(event->key)) {
|
||||
|
||||
Reference in New Issue
Block a user