1*b0ba1202Snicm /* $OpenBSD: cmd-display-menu.c,v 1.44 2025/01/27 09:05:22 nicm Exp $ */ 23546f4c9Snicm 33546f4c9Snicm /* 43546f4c9Snicm * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com> 53546f4c9Snicm * 63546f4c9Snicm * Permission to use, copy, modify, and distribute this software for any 73546f4c9Snicm * purpose with or without fee is hereby granted, provided that the above 83546f4c9Snicm * copyright notice and this permission notice appear in all copies. 93546f4c9Snicm * 103546f4c9Snicm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 113546f4c9Snicm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 123546f4c9Snicm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 133546f4c9Snicm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 143546f4c9Snicm * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 153546f4c9Snicm * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 163546f4c9Snicm * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 173546f4c9Snicm */ 183546f4c9Snicm 193546f4c9Snicm #include <sys/types.h> 203546f4c9Snicm 21309e6403Snicm #include <paths.h> 223546f4c9Snicm #include <stdlib.h> 233546f4c9Snicm #include <string.h> 243546f4c9Snicm 253546f4c9Snicm #include "tmux.h" 263546f4c9Snicm 273546f4c9Snicm /* 283546f4c9Snicm * Display a menu on a client. 293546f4c9Snicm */ 303546f4c9Snicm 31e4c0b811Snicm static enum args_parse_type cmd_display_menu_args_parse(struct args *, 32e4c0b811Snicm u_int, char **); 333546f4c9Snicm static enum cmd_retval cmd_display_menu_exec(struct cmd *, 343546f4c9Snicm struct cmdq_item *); 350cac3d2dSnicm static enum cmd_retval cmd_display_popup_exec(struct cmd *, 360cac3d2dSnicm struct cmdq_item *); 373546f4c9Snicm 383546f4c9Snicm const struct cmd_entry cmd_display_menu_entry = { 393546f4c9Snicm .name = "display-menu", 403546f4c9Snicm .alias = "menu", 413546f4c9Snicm 42324571b2Snicm .args = { "b:c:C:H:s:S:MOt:T:x:y:", 1, -1, cmd_display_menu_args_parse }, 43324571b2Snicm .usage = "[-MO] [-b border-lines] [-c target-client] " 4419c94b00Snicm "[-C starting-choice] [-H selected-style] [-s style] " 4519c94b00Snicm "[-S border-style] " CMD_TARGET_PANE_USAGE " [-T title] " 4619c94b00Snicm "[-x position] [-y position] name key command ...", 473546f4c9Snicm 483546f4c9Snicm .target = { 't', CMD_FIND_PANE, 0 }, 493546f4c9Snicm 50035dc73dSnicm .flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG, 513546f4c9Snicm .exec = cmd_display_menu_exec 523546f4c9Snicm }; 533546f4c9Snicm 540cac3d2dSnicm const struct cmd_entry cmd_display_popup_entry = { 550cac3d2dSnicm .name = "display-popup", 560cac3d2dSnicm .alias = "popup", 570cac3d2dSnicm 58ffda99cdSnicm .args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL }, 59ccb627cdSnicm .usage = "[-BCE] [-b border-lines] [-c target-client] " 60ccb627cdSnicm "[-d start-directory] [-e environment] [-h height] " 61ffda99cdSnicm "[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE 62ffda99cdSnicm " [-T title] [-w width] [-x position] [-y position] " 63ffda99cdSnicm "[shell-command]", 640cac3d2dSnicm 650cac3d2dSnicm .target = { 't', CMD_FIND_PANE, 0 }, 660cac3d2dSnicm 67035dc73dSnicm .flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG, 680cac3d2dSnicm .exec = cmd_display_popup_exec 690cac3d2dSnicm }; 700cac3d2dSnicm 71e4c0b811Snicm static enum args_parse_type 72e4c0b811Snicm cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause) 73e4c0b811Snicm { 74e4c0b811Snicm u_int i = 0; 75e4c0b811Snicm enum args_parse_type type = ARGS_PARSE_STRING; 76e4c0b811Snicm 77e4c0b811Snicm for (;;) { 78e4c0b811Snicm type = ARGS_PARSE_STRING; 79e4c0b811Snicm if (i == idx) 80e4c0b811Snicm break; 81e4c0b811Snicm if (*args_string(args, i++) == '\0') 82e4c0b811Snicm continue; 83e4c0b811Snicm 84e4c0b811Snicm type = ARGS_PARSE_STRING; 85e4c0b811Snicm if (i++ == idx) 86e4c0b811Snicm break; 87e4c0b811Snicm 88e4c0b811Snicm type = ARGS_PARSE_COMMANDS_OR_STRING; 89e4c0b811Snicm if (i++ == idx) 90e4c0b811Snicm break; 91e4c0b811Snicm } 92e4c0b811Snicm return (type); 93e4c0b811Snicm } 94e4c0b811Snicm 955c4a047fSnicm static int 96035dc73dSnicm cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, 9734371d11Snicm struct args *args, u_int *px, u_int *py, u_int w, u_int h) 9834371d11Snicm { 99035dc73dSnicm struct tty *tty = &tc->tty; 100040343aeSnicm struct cmd_find_state *target = cmdq_get_target(item); 101823b6d6dSnicm struct key_event *event = cmdq_get_event(item); 102035dc73dSnicm struct session *s = tc->session; 103040343aeSnicm struct winlink *wl = target->wl; 104040343aeSnicm struct window_pane *wp = target->wp; 1055c4a047fSnicm struct style_ranges *ranges = NULL; 1065c4a047fSnicm struct style_range *sr = NULL; 10734371d11Snicm const char *xp, *yp; 1085c4a047fSnicm char *p; 1095c4a047fSnicm int top; 1105c4a047fSnicm u_int line, ox, oy, sx, sy, lines, position; 1115c4a047fSnicm long n; 1125c4a047fSnicm struct format_tree *ft; 1135fa6c50aSnicm 1145c4a047fSnicm /* 1155c4a047fSnicm * Work out the position from the -x and -y arguments. This is the 1165c4a047fSnicm * bottom-left position. 1175c4a047fSnicm */ 1185c4a047fSnicm 1195c4a047fSnicm /* If the popup is too big, stop now. */ 1205c4a047fSnicm if (w > tty->sx || h > tty->sy) 1215c4a047fSnicm return (0); 1225c4a047fSnicm 1235c4a047fSnicm /* Create format with mouse position if any. */ 1245c4a047fSnicm ft = format_create_from_target(item); 1255c4a047fSnicm if (event->m.valid) { 1265c4a047fSnicm format_add(ft, "popup_mouse_x", "%u", event->m.x); 1275c4a047fSnicm format_add(ft, "popup_mouse_y", "%u", event->m.y); 1285c4a047fSnicm } 1295c4a047fSnicm 1305c4a047fSnicm /* 1315c4a047fSnicm * If there are any status lines, add this window position and the 1325c4a047fSnicm * status line position. 1335c4a047fSnicm */ 1345c4a047fSnicm top = status_at_line(tc); 1355c4a047fSnicm if (top != -1) { 136035dc73dSnicm lines = status_line_size(tc); 1375c4a047fSnicm if (top == 0) 1385c4a047fSnicm top = lines; 1395c4a047fSnicm else 1405c4a047fSnicm top = 0; 1415c4a047fSnicm position = options_get_number(s->options, "status-position"); 1425c4a047fSnicm 1435fa6c50aSnicm for (line = 0; line < lines; line++) { 144035dc73dSnicm ranges = &tc->status.entries[line].ranges; 1455fa6c50aSnicm TAILQ_FOREACH(sr, ranges, entry) { 1465c4a047fSnicm if (sr->type != STYLE_RANGE_WINDOW) 1475c4a047fSnicm continue; 1485c4a047fSnicm if (sr->argument == (u_int)wl->idx) 1495fa6c50aSnicm break; 1505fa6c50aSnicm } 1515fa6c50aSnicm if (sr != NULL) 1525fa6c50aSnicm break; 1535fa6c50aSnicm } 15434371d11Snicm 1555c4a047fSnicm if (sr != NULL) { 1565c4a047fSnicm format_add(ft, "popup_window_status_line_x", "%u", 1575c4a047fSnicm sr->start); 1585c4a047fSnicm if (position == 0) { 1595c4a047fSnicm format_add(ft, "popup_window_status_line_y", 1605c4a047fSnicm "%u", line + 1 + h); 1615c4a047fSnicm } else { 1625c4a047fSnicm format_add(ft, "popup_window_status_line_y", 1635c4a047fSnicm "%u", tty->sy - lines + line); 1645c4a047fSnicm } 1655c4a047fSnicm } 1665c4a047fSnicm 1675c4a047fSnicm if (position == 0) 1685c4a047fSnicm format_add(ft, "popup_status_line_y", "%u", lines + h); 1695c4a047fSnicm else { 1705c4a047fSnicm format_add(ft, "popup_status_line_y", "%u", 1715c4a047fSnicm tty->sy - lines); 1725c4a047fSnicm } 1735c4a047fSnicm } else 1745c4a047fSnicm top = 0; 1755c4a047fSnicm 1765c4a047fSnicm /* Popup width and height. */ 1775c4a047fSnicm format_add(ft, "popup_width", "%u", w); 1785c4a047fSnicm format_add(ft, "popup_height", "%u", h); 1795c4a047fSnicm 1805c4a047fSnicm /* Position so popup is in the centre. */ 1815c4a047fSnicm n = (long)(tty->sx - 1) / 2 - w / 2; 1825c4a047fSnicm if (n < 0) 1835c4a047fSnicm format_add(ft, "popup_centre_x", "%u", 0); 1845c4a047fSnicm else 1855c4a047fSnicm format_add(ft, "popup_centre_x", "%ld", n); 1865c4a047fSnicm n = (tty->sy - 1) / 2 + h / 2; 1879c7ce6d0Snicm if (n >= tty->sy) 1885c4a047fSnicm format_add(ft, "popup_centre_y", "%u", tty->sy - h); 1895c4a047fSnicm else 1905c4a047fSnicm format_add(ft, "popup_centre_y", "%ld", n); 1915c4a047fSnicm 1925c4a047fSnicm /* Position of popup relative to mouse. */ 1935c4a047fSnicm if (event->m.valid) { 1945c4a047fSnicm n = (long)event->m.x - w / 2; 1955c4a047fSnicm if (n < 0) 1965c4a047fSnicm format_add(ft, "popup_mouse_centre_x", "%u", 0); 1975c4a047fSnicm else 1985c4a047fSnicm format_add(ft, "popup_mouse_centre_x", "%ld", n); 1995c4a047fSnicm n = event->m.y - h / 2; 2005c4a047fSnicm if (n + h >= tty->sy) { 2015c4a047fSnicm format_add(ft, "popup_mouse_centre_y", "%u", 2025c4a047fSnicm tty->sy - h); 2035c4a047fSnicm } else 2045c4a047fSnicm format_add(ft, "popup_mouse_centre_y", "%ld", n); 2055c4a047fSnicm n = (long)event->m.y + h; 20690aa0eb2Snicm if (n >= tty->sy) 2070711c05bSnicm format_add(ft, "popup_mouse_top", "%u", tty->sy - 1); 2085c4a047fSnicm else 2095c4a047fSnicm format_add(ft, "popup_mouse_top", "%ld", n); 2105c4a047fSnicm n = event->m.y - h; 2115c4a047fSnicm if (n < 0) 2125c4a047fSnicm format_add(ft, "popup_mouse_bottom", "%u", 0); 2135c4a047fSnicm else 2145c4a047fSnicm format_add(ft, "popup_mouse_bottom", "%ld", n); 2155c4a047fSnicm } 2165c4a047fSnicm 2175c4a047fSnicm /* Position in pane. */ 2185c4a047fSnicm tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy); 2195c4a047fSnicm n = top + wp->yoff - oy + h; 2205c4a047fSnicm if (n >= tty->sy) 2215c4a047fSnicm format_add(ft, "popup_pane_top", "%u", tty->sy - h); 2225c4a047fSnicm else 2235c4a047fSnicm format_add(ft, "popup_pane_top", "%ld", n); 2245c4a047fSnicm format_add(ft, "popup_pane_bottom", "%u", top + wp->yoff + wp->sy - oy); 2255c4a047fSnicm format_add(ft, "popup_pane_left", "%u", wp->xoff - ox); 2265c4a047fSnicm n = (long)wp->xoff + wp->sx - ox - w; 2275c4a047fSnicm if (n < 0) 2285c4a047fSnicm format_add(ft, "popup_pane_right", "%u", 0); 2295c4a047fSnicm else 2305c4a047fSnicm format_add(ft, "popup_pane_right", "%ld", n); 2315c4a047fSnicm 2325c4a047fSnicm /* Expand horizontal position. */ 23334371d11Snicm xp = args_get(args, 'x'); 234386b1589Snicm if (xp == NULL || strcmp(xp, "C") == 0) 2355c4a047fSnicm xp = "#{popup_centre_x}"; 23634371d11Snicm else if (strcmp(xp, "R") == 0) 2377eff34acSnicm xp = "#{popup_pane_right}"; 2385c4a047fSnicm else if (strcmp(xp, "P") == 0) 2395c4a047fSnicm xp = "#{popup_pane_left}"; 2405c4a047fSnicm else if (strcmp(xp, "M") == 0) 2415c4a047fSnicm xp = "#{popup_mouse_centre_x}"; 2425c4a047fSnicm else if (strcmp(xp, "W") == 0) 2435c4a047fSnicm xp = "#{popup_window_status_line_x}"; 2445c4a047fSnicm p = format_expand(ft, xp); 2455c4a047fSnicm n = strtol(p, NULL, 10); 2465c4a047fSnicm if (n + w >= tty->sx) 2475c4a047fSnicm n = tty->sx - w; 2485c4a047fSnicm else if (n < 0) 2495c4a047fSnicm n = 0; 2505c4a047fSnicm *px = n; 2512ce14837Snicm log_debug("%s: -x: %s = %s = %u (-w %u)", __func__, xp, p, *px, w); 2525c4a047fSnicm free(p); 25334371d11Snicm 2545c4a047fSnicm /* Expand vertical position */ 25534371d11Snicm yp = args_get(args, 'y'); 256386b1589Snicm if (yp == NULL || strcmp(yp, "C") == 0) 2575c4a047fSnicm yp = "#{popup_centre_y}"; 2585c4a047fSnicm else if (strcmp(yp, "P") == 0) 2595c4a047fSnicm yp = "#{popup_pane_bottom}"; 2605c4a047fSnicm else if (strcmp(yp, "M") == 0) 2615c4a047fSnicm yp = "#{popup_mouse_top}"; 2625c4a047fSnicm else if (strcmp(yp, "S") == 0) 2635c4a047fSnicm yp = "#{popup_status_line_y}"; 2645c4a047fSnicm else if (strcmp(yp, "W") == 0) 2655c4a047fSnicm yp = "#{popup_window_status_line_y}"; 2665c4a047fSnicm p = format_expand(ft, yp); 2675c4a047fSnicm n = strtol(p, NULL, 10); 2685c4a047fSnicm if (n < h) 2695c4a047fSnicm n = 0; 27034371d11Snicm else 2715c4a047fSnicm n -= h; 2725c4a047fSnicm if (n + h >= tty->sy) 2735c4a047fSnicm n = tty->sy - h; 2745c4a047fSnicm else if (n < 0) 2755c4a047fSnicm n = 0; 2765c4a047fSnicm *py = n; 2772ce14837Snicm log_debug("%s: -y: %s = %s = %u (-h %u)", __func__, yp, p, *py, h); 2785c4a047fSnicm free(p); 2795c4a047fSnicm 2806987aaaaSnicm format_free(ft); 2815c4a047fSnicm return (1); 28234371d11Snicm } 28334371d11Snicm 2843546f4c9Snicm static enum cmd_retval 2853546f4c9Snicm cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) 2863546f4c9Snicm { 28790d7ba38Snicm struct args *args = cmd_get_args(self); 288040343aeSnicm struct cmd_find_state *target = cmdq_get_target(item); 289823b6d6dSnicm struct key_event *event = cmdq_get_event(item); 290035dc73dSnicm struct client *tc = cmdq_get_target_client(item); 2913546f4c9Snicm struct menu *menu = NULL; 2921335341aSnicm struct menu_item menu_item; 29317d7ce67Snicm const char *key, *name, *value; 29417d7ce67Snicm const char *style = args_get(args, 's'); 29517d7ce67Snicm const char *border_style = args_get(args, 'S'); 29619c94b00Snicm const char *selected_style = args_get(args, 'H'); 29717d7ce67Snicm enum box_lines lines = BOX_LINES_DEFAULT; 298009dd187Snicm char *title, *cause; 299009dd187Snicm int flags = 0, starting_choice = 0; 3001693b10bSnicm u_int px, py, i, count = args_count(args); 30117d7ce67Snicm struct options *o = target->s->curw->window->options; 30217d7ce67Snicm struct options_entry *oe; 30317d7ce67Snicm 3043546f4c9Snicm 305035dc73dSnicm if (tc->overlay_draw != NULL) 3063546f4c9Snicm return (CMD_RETURN_NORMAL); 3073546f4c9Snicm 30817d7ce67Snicm if (args_has(args, 'C')) { 30917d7ce67Snicm if (strcmp(args_get(args, 'C'), "-") == 0) 310009dd187Snicm starting_choice = -1; 311009dd187Snicm else { 31217d7ce67Snicm starting_choice = args_strtonum(args, 'C', 0, UINT_MAX, 313009dd187Snicm &cause); 314009dd187Snicm if (cause != NULL) { 315009dd187Snicm cmdq_error(item, "starting choice %s", cause); 316009dd187Snicm free(cause); 317009dd187Snicm return (CMD_RETURN_ERROR); 318009dd187Snicm } 319009dd187Snicm } 320009dd187Snicm } 321009dd187Snicm 3223546f4c9Snicm if (args_has(args, 'T')) 323035dc73dSnicm title = format_single_from_target(item, args_get(args, 'T')); 3243546f4c9Snicm else 3253546f4c9Snicm title = xstrdup(""); 3261335341aSnicm menu = menu_create(title); 3274b5f3832Snicm free(title); 3281335341aSnicm 3291693b10bSnicm for (i = 0; i != count; /* nothing */) { 3301693b10bSnicm name = args_string(args, i++); 3311335341aSnicm if (*name == '\0') { 332035dc73dSnicm menu_add_item(menu, NULL, item, tc, target); 3331335341aSnicm continue; 3341335341aSnicm } 3351335341aSnicm 3361693b10bSnicm if (count - i < 2) { 3371335341aSnicm cmdq_error(item, "not enough arguments"); 3381335341aSnicm menu_free(menu); 3391335341aSnicm return (CMD_RETURN_ERROR); 3401335341aSnicm } 3411693b10bSnicm key = args_string(args, i++); 3421335341aSnicm 3431335341aSnicm menu_item.name = name; 3441335341aSnicm menu_item.key = key_string_lookup_string(key); 3451693b10bSnicm menu_item.command = args_string(args, i++); 3461335341aSnicm 347035dc73dSnicm menu_add_item(menu, &menu_item, item, tc, target); 3481335341aSnicm } 3493546f4c9Snicm if (menu == NULL) { 3501335341aSnicm cmdq_error(item, "invalid menu arguments"); 3513546f4c9Snicm return (CMD_RETURN_ERROR); 3523546f4c9Snicm } 3533546f4c9Snicm if (menu->count == 0) { 3543546f4c9Snicm menu_free(menu); 3553546f4c9Snicm return (CMD_RETURN_NORMAL); 3563546f4c9Snicm } 3575c4a047fSnicm if (!cmd_display_menu_get_position(tc, item, args, &px, &py, 3585c4a047fSnicm menu->width + 4, menu->count + 2)) { 3595c4a047fSnicm menu_free(menu); 3605c4a047fSnicm return (CMD_RETURN_NORMAL); 3615c4a047fSnicm } 3623546f4c9Snicm 36317d7ce67Snicm value = args_get(args, 'b'); 36417d7ce67Snicm if (value != NULL) { 36517d7ce67Snicm oe = options_get(o, "menu-border-lines"); 36617d7ce67Snicm lines = options_find_choice(options_table_entry(oe), value, 36717d7ce67Snicm &cause); 36817d7ce67Snicm if (lines == -1) { 36917d7ce67Snicm cmdq_error(item, "menu-border-lines %s", cause); 37017d7ce67Snicm free(cause); 37117d7ce67Snicm return (CMD_RETURN_ERROR); 37217d7ce67Snicm } 37317d7ce67Snicm } 37417d7ce67Snicm 3755971ac85Snicm if (args_has(args, 'O')) 3765971ac85Snicm flags |= MENU_STAYOPEN; 377324571b2Snicm if (!event->m.valid && !args_has(args, 'M')) 3783546f4c9Snicm flags |= MENU_NOMOUSE; 37917d7ce67Snicm if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines, 38019c94b00Snicm style, selected_style, border_style, target, NULL, NULL) != 0) 3813546f4c9Snicm return (CMD_RETURN_NORMAL); 3823546f4c9Snicm return (CMD_RETURN_WAIT); 3833546f4c9Snicm } 3840cac3d2dSnicm 3850cac3d2dSnicm static enum cmd_retval 3860cac3d2dSnicm cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) 3870cac3d2dSnicm { 38890d7ba38Snicm struct args *args = cmd_get_args(self); 389040343aeSnicm struct cmd_find_state *target = cmdq_get_target(item); 390309e6403Snicm struct session *s = target->s; 391035dc73dSnicm struct client *tc = cmdq_get_target_client(item); 392035dc73dSnicm struct tty *tty = &tc->tty; 3931693b10bSnicm const char *value, *shell, *shellcmd = NULL; 394ffda99cdSnicm const char *style = args_get(args, 's'); 395ffda99cdSnicm const char *border_style = args_get(args, 'S'); 396dad8e5c0Snicm char *cwd, *cause = NULL, **argv = NULL, *title; 3971693b10bSnicm int flags = 0, argc = 0; 398ccb627cdSnicm enum box_lines lines = BOX_LINES_DEFAULT; 3991693b10bSnicm u_int px, py, w, h, count = args_count(args); 40003a1f8ddSnicm struct args_value *av; 40103a1f8ddSnicm struct environ *env = NULL; 402ccb627cdSnicm struct options *o = s->curw->window->options; 403ccb627cdSnicm struct options_entry *oe; 4040cac3d2dSnicm 4050cac3d2dSnicm if (args_has(args, 'C')) { 406035dc73dSnicm server_client_clear_overlay(tc); 4070cac3d2dSnicm return (CMD_RETURN_NORMAL); 4080cac3d2dSnicm } 409035dc73dSnicm if (tc->overlay_draw != NULL) 4100cac3d2dSnicm return (CMD_RETURN_NORMAL); 4110cac3d2dSnicm 412035dc73dSnicm h = tty->sy / 2; 4130cac3d2dSnicm if (args_has(args, 'h')) { 414035dc73dSnicm h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause); 4150cac3d2dSnicm if (cause != NULL) { 4160cac3d2dSnicm cmdq_error(item, "height %s", cause); 4170cac3d2dSnicm free(cause); 4180cac3d2dSnicm return (CMD_RETURN_ERROR); 4190cac3d2dSnicm } 4200cac3d2dSnicm } 4210cac3d2dSnicm 422035dc73dSnicm w = tty->sx / 2; 4230cac3d2dSnicm if (args_has(args, 'w')) { 424035dc73dSnicm w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause); 4250cac3d2dSnicm if (cause != NULL) { 4260cac3d2dSnicm cmdq_error(item, "width %s", cause); 4270cac3d2dSnicm free(cause); 4280cac3d2dSnicm return (CMD_RETURN_ERROR); 4290cac3d2dSnicm } 4300cac3d2dSnicm } 4310cac3d2dSnicm 4322ce14837Snicm if (w > tty->sx) 4332ce14837Snicm w = tty->sx; 4342ce14837Snicm if (h > tty->sy) 4352ce14837Snicm h = tty->sy; 4365c4a047fSnicm if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h)) 4375c4a047fSnicm return (CMD_RETURN_NORMAL); 4380cac3d2dSnicm 439ccb627cdSnicm value = args_get(args, 'b'); 440ccb627cdSnicm if (args_has(args, 'B')) 441ccb627cdSnicm lines = BOX_LINES_NONE; 442ccb627cdSnicm else if (value != NULL) { 443ccb627cdSnicm oe = options_get(o, "popup-border-lines"); 444ccb627cdSnicm lines = options_find_choice(options_table_entry(oe), value, 445ccb627cdSnicm &cause); 446ccb627cdSnicm if (cause != NULL) { 447ccb627cdSnicm cmdq_error(item, "popup-border-lines %s", cause); 448ccb627cdSnicm free(cause); 449ccb627cdSnicm return (CMD_RETURN_ERROR); 450ccb627cdSnicm } 451ccb627cdSnicm } 452ccb627cdSnicm 4530cac3d2dSnicm value = args_get(args, 'd'); 4540cac3d2dSnicm if (value != NULL) 455035dc73dSnicm cwd = format_single_from_target(item, value); 4560cac3d2dSnicm else 457309e6403Snicm cwd = xstrdup(server_client_get_cwd(tc, s)); 4581693b10bSnicm if (count == 0) 459309e6403Snicm shellcmd = options_get_string(s->options, "default-command"); 4601693b10bSnicm else if (count == 1) 4611693b10bSnicm shellcmd = args_string(args, 0); 4621693b10bSnicm if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { 463309e6403Snicm shellcmd = NULL; 4641693b10bSnicm shell = options_get_string(s->options, "default-shell"); 4651693b10bSnicm if (!checkshell(shell)) 4661693b10bSnicm shell = _PATH_BSHELL; 4671693b10bSnicm cmd_append_argv(&argc, &argv, shell); 4681693b10bSnicm } else 469d8b32369Snicm args_to_vector(args, &argc, &argv); 4700cac3d2dSnicm 47103a1f8ddSnicm if (args_has(args, 'e') >= 1) { 47203a1f8ddSnicm env = environ_create(); 47303a1f8ddSnicm av = args_first_value(args, 'e'); 47403a1f8ddSnicm while (av != NULL) { 47503a1f8ddSnicm environ_put(env, av->string, 0); 47603a1f8ddSnicm av = args_next_value(av); 47703a1f8ddSnicm } 47803a1f8ddSnicm } 47903a1f8ddSnicm 480dad8e5c0Snicm if (args_has(args, 'T')) 481dad8e5c0Snicm title = format_single_from_target(item, args_get(args, 'T')); 482dad8e5c0Snicm else 483dad8e5c0Snicm title = xstrdup(""); 4849a253fadSnicm if (args_has(args, 'E') > 1) 4859a253fadSnicm flags |= POPUP_CLOSEEXITZERO; 4869a253fadSnicm else if (args_has(args, 'E')) 4870cac3d2dSnicm flags |= POPUP_CLOSEEXIT; 488ccb627cdSnicm if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc, 489ffda99cdSnicm argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) { 4901693b10bSnicm cmd_free_argv(argc, argv); 49103a1f8ddSnicm if (env != NULL) 49203a1f8ddSnicm environ_free(env); 4936987aaaaSnicm free(cwd); 494dad8e5c0Snicm free(title); 4950cac3d2dSnicm return (CMD_RETURN_NORMAL); 4961693b10bSnicm } 49703a1f8ddSnicm if (env != NULL) 49803a1f8ddSnicm environ_free(env); 4996987aaaaSnicm free(cwd); 500dad8e5c0Snicm free(title); 5011693b10bSnicm cmd_free_argv(argc, argv); 5020cac3d2dSnicm return (CMD_RETURN_WAIT); 5030cac3d2dSnicm } 504