aboutsummaryrefslogtreecommitdiff
path: root/popup.c
diff options
context:
space:
mode:
Diffstat (limited to 'popup.c')
-rw-r--r--popup.c157
1 files changed, 119 insertions, 38 deletions
diff --git a/popup.c b/popup.c
index 3f64a852..2e57153d 100644
--- a/popup.c
+++ b/popup.c
@@ -30,9 +30,15 @@ struct popup_data {
struct client *c;
struct cmdq_item *item;
int flags;
+ char *title;
+
+ struct grid_cell border_cell;
+ enum box_lines border_lines;
struct screen s;
+ struct grid_cell defaults;
struct colour_palette palette;
+
struct job *job;
struct input_ctx *ictx;
int status;
@@ -116,7 +122,7 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
ttyctx->wsx = c->tty.sx;
ttyctx->wsy = c->tty.sy;
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
ttyctx->xoff = ttyctx->rxoff = pd->px;
ttyctx->yoff = ttyctx->ryoff = pd->py;
} else {
@@ -132,6 +138,7 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
{
struct popup_data *pd = ctx->arg;
+ memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults);
ttyctx->palette = &pd->palette;
ttyctx->redraw_cb = popup_redraw_cb;
ttyctx->set_client_cb = popup_set_client_cb;
@@ -146,7 +153,7 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
if (pd->md != NULL)
return (menu_mode_cb(c, pd->md, cx, cy));
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
*cx = pd->px + pd->s.cx;
*cy = pd->py + pd->s.cy;
} else {
@@ -156,18 +163,49 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
return (&pd->s);
}
-static int
-popup_check_cb(struct client *c, void *data, u_int px, u_int py)
+/* 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 overlay_ranges *r)
{
struct popup_data *pd = data;
+ struct overlay_ranges or[2];
+ u_int i, j, k = 0;
- if (pd->md != NULL && menu_check_cb(c, pd->md, px, py) == 0)
- return (0);
- if (px < pd->px || px > pd->px + pd->sx - 1)
- return (1);
- if (py < pd->py || py > pd->py + pd->sy - 1)
- return (1);
- return (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 < 2; i++) {
+ server_client_overlay_range(pd->px, pd->py, pd->sx,
+ pd->sy, r->px[i], py, r->nx[i], &or[i]);
+ }
+
+ /*
+ * or has up to OVERLAY_MAX_RANGES non-overlapping ranges,
+ * ordered from left to right. Collect them in the output.
+ */
+ for (i = 0; i < 2; i++) {
+ /* Each or[i] only has 2 ranges. */
+ for (j = 0; j < 2; j++) {
+ if (or[i].nx[j] > 0) {
+ r->px[k] = or[i].px[j];
+ r->nx[k] = or[i].nx[j];
+ k++;
+ }
+ }
+ }
+
+ /* Zero remaining ranges if any. */
+ for (i = k; i < OVERLAY_MAX_RANGES; i++) {
+ r->px[i] = 0;
+ r->nx[i] = 0;
+ }
+
+ return;
+ }
+
+ server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy, px, py, nx,
+ r);
}
static void
@@ -179,26 +217,29 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
struct screen_write_ctx ctx;
u_int i, px = pd->px, py = pd->py;
struct colour_palette *palette = &pd->palette;
- struct grid_cell gc;
+ struct grid_cell defaults;
screen_init(&s, pd->sx, pd->sy, 0);
screen_write_start(&ctx, &s);
screen_write_clearscreen(&ctx, 8);
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
screen_write_cursormove(&ctx, 0, 0, 0);
screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx, pd->sy);
} else if (pd->sx > 2 && pd->sy > 2) {
- screen_write_box(&ctx, pd->sx, pd->sy);
+ screen_write_box(&ctx, pd->sx, pd->sy, pd->border_lines,
+ &pd->border_cell, pd->title);
screen_write_cursormove(&ctx, 1, 1, 0);
screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2,
pd->sy - 2);
}
screen_write_stop(&ctx);
- memcpy(&gc, &grid_default_cell, sizeof gc);
- gc.fg = pd->palette.fg;
- gc.bg = pd->palette.bg;
+ memcpy(&defaults, &pd->defaults, sizeof defaults);
+ if (defaults.fg == 8)
+ defaults.fg = palette->fg;
+ if (defaults.bg == 8)
+ defaults.bg = palette->bg;
if (pd->md != NULL) {
c->overlay_check = menu_check_cb;
@@ -207,8 +248,10 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
c->overlay_check = NULL;
c->overlay_data = NULL;
}
- for (i = 0; i < pd->sy; i++)
- tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &gc, palette);
+ for (i = 0; i < pd->sy; i++) {
+ tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &defaults,
+ palette);
+ }
if (pd->md != NULL) {
c->overlay_check = NULL;
c->overlay_data = NULL;
@@ -245,6 +288,7 @@ popup_free_cb(struct client *c, void *data)
screen_free(&pd->s);
colour_palette_free(&pd->palette);
+ free(pd->title);
free(pd);
}
@@ -278,7 +322,7 @@ popup_resize_cb(__unused struct client *c, void *data)
pd->px = pd->ppx;
/* Avoid zero size screens. */
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
screen_resize(&pd->s, pd->sx, pd->sy, 0);
if (pd->job != NULL)
job_resize(pd->job, pd->sx, pd->sy );
@@ -404,7 +448,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
pd->ppy = py;
server_redraw_client(c);
} else if (pd->dragging == SIZE) {
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
if (m->x < pd->px + 1)
return;
if (m->y < pd->py + 1)
@@ -420,7 +464,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
pd->psx = pd->sx;
pd->psy = pd->sy;
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
screen_resize(&pd->s, pd->sx, pd->sy, 0);
if (pd->job != NULL)
job_resize(pd->job, pd->sx, pd->sy);
@@ -464,11 +508,11 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
m->x > pd->px + pd->sx - 1 ||
m->y < pd->py ||
m->y > pd->py + pd->sy - 1) {
- if (MOUSE_BUTTONS(m->b) == 2)
+ if (MOUSE_BUTTONS(m->b) == MOUSE_BUTTON_3)
goto menu;
return (0);
}
- if (~pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines != BOX_LINES_NONE) {
if (m->x == pd->px)
border = LEFT;
else if (m->x == pd->px + pd->sx - 1)
@@ -479,16 +523,16 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
border = BOTTOM;
}
if ((m->b & MOUSE_MASK_MODIFIERS) == 0 &&
- MOUSE_BUTTONS(m->b) == 2 &&
+ MOUSE_BUTTONS(m->b) == MOUSE_BUTTON_3 &&
(border == LEFT || border == TOP))
goto menu;
if (((m->b & MOUSE_MASK_MODIFIERS) == MOUSE_MASK_META) ||
border != NONE) {
if (!MOUSE_DRAG(m->b))
goto out;
- if (MOUSE_BUTTONS(m->lb) == 0)
+ if (MOUSE_BUTTONS(m->lb) == MOUSE_BUTTON_1)
pd->dragging = MOVE;
- else if (MOUSE_BUTTONS(m->lb) == 2)
+ else if (MOUSE_BUTTONS(m->lb) == MOUSE_BUTTON_3)
pd->dragging = SIZE;
pd->dx = m->lx - pd->px;
pd->dy = m->ly - pd->py;
@@ -502,7 +546,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
if (pd->job != NULL) {
if (KEYC_IS_MOUSE(event->key)) {
/* Must be inside, checked already. */
- if (pd->flags & POPUP_NOBORDER) {
+ if (pd->border_lines == BOX_LINES_NONE) {
px = m->x - pd->px;
py = m->y - pd->py;
} else {
@@ -521,10 +565,10 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
menu:
pd->menu = menu_create("");
if (pd->flags & POPUP_INTERNAL) {
- menu_add_items(pd->menu, popup_internal_menu_items, NULL, NULL,
+ menu_add_items(pd->menu, popup_internal_menu_items, NULL, c,
NULL);
} else
- menu_add_items(pd->menu, popup_menu_items, NULL, NULL, NULL);
+ menu_add_items(pd->menu, popup_menu_items, NULL, c, NULL);
if (m->x >= (pd->menu->width + 4) / 2)
x = m->x - (pd->menu->width + 4) / 2;
else
@@ -588,14 +632,25 @@ popup_job_complete_cb(struct job *job)
}
int
-popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
- u_int sy, const char *shellcmd, int argc, char **argv, const char *cwd,
- struct client *c, struct session *s, popup_close_cb cb, void *arg)
+popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
+ u_int py, u_int sx, u_int sy, struct environ *env, const char *shellcmd,
+ int argc, char **argv, const char *cwd, const char *title, struct client *c,
+ struct session *s, const char* style, const char* border_style,
+ popup_close_cb cb, void *arg)
{
struct popup_data *pd;
u_int jx, jy;
+ struct options *o;
+ struct style sytmp;
+
+ if (s != NULL)
+ o = s->curw->window->options;
+ else
+ o = c->session->curw->window->options;
- if (flags & POPUP_NOBORDER) {
+ if (lines == BOX_LINES_DEFAULT)
+ lines = options_get_number(o, "popup-border-lines");
+ if (lines == BOX_LINES_NONE) {
if (sx < 1 || sy < 1)
return (-1);
jx = sx;
@@ -612,6 +667,8 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd = xcalloc(1, sizeof *pd);
pd->item = item;
pd->flags = flags;
+ if (title != NULL)
+ pd->title = xstrdup(title);
pd->c = c;
pd->c->references++;
@@ -620,10 +677,33 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd->arg = arg;
pd->status = 128 + SIGHUP;
- screen_init(&pd->s, sx - 2, sy - 2, 0);
+ pd->border_lines = lines;
+ memcpy(&pd->border_cell, &grid_default_cell, sizeof pd->border_cell);
+ style_apply(&pd->border_cell, o, "popup-border-style", NULL);
+ if (border_style != NULL) {
+ style_set(&sytmp, &grid_default_cell);
+ if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) {
+ pd->border_cell.fg = sytmp.gc.fg;
+ pd->border_cell.bg = sytmp.gc.bg;
+ }
+ }
+ pd->border_cell.attr = 0;
+
+ screen_init(&pd->s, jx, jy, 0);
colour_palette_init(&pd->palette);
colour_palette_from_option(&pd->palette, global_w_options);
+ memcpy(&pd->defaults, &grid_default_cell, sizeof pd->defaults);
+ style_apply(&pd->defaults, o, "popup-style", NULL);
+ if (style != NULL) {
+ style_set(&sytmp, &grid_default_cell);
+ if (style_parse(&sytmp, &pd->defaults, style) == 0) {
+ pd->defaults.fg = sytmp.gc.fg;
+ pd->defaults.bg = sytmp.gc.bg;
+ }
+ }
+ pd->defaults.attr = 0;
+
pd->px = px;
pd->py = py;
pd->sx = sx;
@@ -634,7 +714,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd->psx = sx;
pd->psy = sy;
- pd->job = job_run(shellcmd, argc, argv, s, cwd,
+ pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy);
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette);
@@ -723,8 +803,9 @@ popup_editor(struct client *c, const char *buf, size_t len,
py = (c->tty.sy / 2) - (sy / 2);
xasprintf(&cmd, "%s %s", editor, path);
- if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, NULL, px, py, sx, sy,
- cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) {
+ if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, BOX_LINES_DEFAULT,
+ NULL, px, py, sx, sy, NULL, cmd, 0, NULL, _PATH_TMP, NULL, c, NULL,
+ NULL, NULL, popup_editor_close_cb, pe) != 0) {
popup_editor_free(pe);
free(cmd);
return (-1);