Add popup-border-lines option to set popup line style, from Alexis
authornicm <nicm@openbsd.org>
Thu, 14 Oct 2021 13:19:01 +0000 (13:19 +0000)
committernicm <nicm@openbsd.org>
Thu, 14 Oct 2021 13:19:01 +0000 (13:19 +0000)
Hildebrandt, GitHub issue 2930.

usr.bin/tmux/cmd-display-menu.c
usr.bin/tmux/mode-tree.c
usr.bin/tmux/options-table.c
usr.bin/tmux/options.c
usr.bin/tmux/popup.c
usr.bin/tmux/screen-redraw.c
usr.bin/tmux/screen-write.c
usr.bin/tmux/tmux.1
usr.bin/tmux/tmux.h
usr.bin/tmux/tty-acs.c
usr.bin/tmux/window-tree.c

index cb23c34..480fe4f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-display-menu.c,v 1.34 2021/10/11 10:55:30 nicm Exp $ */
+/* $OpenBSD: cmd-display-menu.c,v 1.35 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -53,9 +53,10 @@ const struct cmd_entry cmd_display_popup_entry = {
        .name = "display-popup",
        .alias = "popup",
 
-       .args = { "BCc:d:e:Eh:t:w:x:y:", 0, -1, NULL },
-       .usage = "[-BCE] [-c target-client] [-d start-directory] "
-                "[-e environment] [-h height] " CMD_TARGET_PANE_USAGE " "
+       .args = { "Bb:Cc:d:e:Eh:t:w:x:y:", 0, -1, NULL },
+       .usage = "[-BCE] [-b border-lines] [-c target-client] "
+                "[-d start-directory] [-e environment] [-h height] "
+                CMD_TARGET_PANE_USAGE " "
                 "[-w width] [-x position] [-y position] [shell-command]",
 
        .target = { 't', CMD_FIND_PANE, 0 },
@@ -354,11 +355,14 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
        struct client           *tc = cmdq_get_target_client(item);
        struct tty              *tty = &tc->tty;
        const char              *value, *shell, *shellcmd = NULL;
-       char                    *cwd, *cause, **argv = NULL;
+       char                    *cwd, *cause = NULL, **argv = NULL;
        int                      flags = 0, argc = 0;
+       enum box_lines           lines = BOX_LINES_DEFAULT;
        u_int                    px, py, w, h, count = args_count(args);
        struct args_value       *av;
        struct environ          *env = NULL;
+       struct options          *o = s->curw->window->options;
+       struct options_entry    *oe;
 
        if (args_has(args, 'C')) {
                server_client_clear_overlay(tc);
@@ -394,6 +398,20 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
        if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
                return (CMD_RETURN_NORMAL);
 
+       value = args_get(args, 'b');
+       if (args_has(args, 'B'))
+               lines = BOX_LINES_NONE;
+       else if (value != NULL) {
+               oe = options_get(o, "popup-border-lines");
+               lines = options_find_choice(options_table_entry(oe), value,
+                   &cause);
+               if (cause != NULL) {
+                       cmdq_error(item, "popup-border-lines %s", cause);
+                       free(cause);
+                       return (CMD_RETURN_ERROR);
+               }
+       }
+
        value = args_get(args, 'd');
        if (value != NULL)
                cwd = format_single_from_target(item, value);
@@ -425,10 +443,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
                flags |= POPUP_CLOSEEXITZERO;
        else if (args_has(args, 'E'))
                flags |= POPUP_CLOSEEXIT;
-       if (args_has(args, 'B'))
-               flags |= POPUP_NOBORDER;
-       if (popup_display(flags, item, px, py, w, h, env, shellcmd, argc, argv,
-           cwd, tc, s, NULL, NULL) != 0) {
+       if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
+           argv, cwd, tc, s, NULL, NULL) != 0) {
                cmd_free_argv(argc, argv);
                if (env != NULL)
                        environ_free(env);
index 4ff093a..64114f1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mode-tree.c,v 1.56 2021/10/13 09:28:36 nicm Exp $ */
+/* $OpenBSD: mode-tree.c,v 1.57 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -747,7 +747,7 @@ mode_tree_draw(struct mode_tree_data *mtd)
                mti = mti->parent;
 
        screen_write_cursormove(&ctx, 0, h, 0);
-       screen_write_box(&ctx, w, sy - h, NULL);
+       screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL);
 
        if (mtd->sort_list != NULL) {
                xasprintf(&text, " %s (sort: %s%s)", mti->name,
index 3223063..c435480 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: options-table.c,v 1.151 2021/10/13 09:28:36 nicm Exp $ */
+/* $OpenBSD: options-table.c,v 1.152 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -60,9 +60,12 @@ static const char *options_table_visual_bell_list[] = {
 static const char *options_table_pane_status_list[] = {
        "off", "top", "bottom", NULL
 };
-static const char *options_table_pane_lines_list[] = {
+static const char *options_table_pane_border_lines_list[] = {
        "single", "double", "heavy", "simple", "number", NULL
 };
+static const char *options_table_popup_border_lines_list[] = {
+       "single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
+};
 static const char *options_table_set_clipboard_list[] = {
        "off", "external", "on", NULL
 };
@@ -951,7 +954,7 @@ const struct options_table_entry options_table[] = {
        { .name = "pane-border-lines",
          .type = OPTIONS_TABLE_CHOICE,
          .scope = OPTIONS_TABLE_WINDOW,
-         .choices = options_table_pane_lines_list,
+         .choices = options_table_pane_border_lines_list,
          .default_num = PANE_LINES_SINGLE,
          .text = "Type of characters used to draw pane border lines. Some of "
                  "these are only supported on terminals with UTF-8 support."
@@ -1000,6 +1003,15 @@ const struct options_table_entry options_table[] = {
          .text = "Default style of popup borders."
        },
 
+       { .name = "popup-border-lines",
+         .type = OPTIONS_TABLE_CHOICE,
+         .scope = OPTIONS_TABLE_WINDOW,
+         .choices = options_table_popup_border_lines_list,
+         .default_num = BOX_LINES_SINGLE,
+         .text = "Type of characters used to draw popup border lines. Some of "
+                 "these are only supported on terminals with UTF-8 support."
+       },
+
        { .name = "remain-on-exit",
          .type = OPTIONS_TABLE_CHOICE,
          .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
index c429f31..10bb1f3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.64 2021/08/21 17:25:32 nicm Exp $ */
+/* $OpenBSD: options.c,v 1.65 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -989,28 +989,39 @@ options_from_string_flag(struct options *oo, const char *name,
        return (0);
 }
 
+int
+options_find_choice(const struct options_table_entry *oe, const char *value,
+    char **cause)
+{
+       const char      **cp;
+       int               n = 0, choice = -1;
+
+       for (cp = oe->choices; *cp != NULL; cp++) {
+               if (strcmp(*cp, value) == 0)
+                       choice = n;
+               n++;
+       }
+       if (choice == -1) {
+               xasprintf(cause, "unknown value: %s", value);
+               return (-1);
+       }
+       return (choice);
+}
+
 static int
 options_from_string_choice(const struct options_table_entry *oe,
     struct options *oo, const char *name, const char *value, char **cause)
 {
-       const char      **cp;
-       int               n, choice = -1;
+       int     choice = -1;
 
        if (value == NULL) {
                choice = options_get_number(oo, name);
                if (choice < 2)
                        choice = !choice;
        } else {
-               n = 0;
-               for (cp = oe->choices; *cp != NULL; cp++) {
-                       if (strcmp(*cp, value) == 0)
-                               choice = n;
-                       n++;
-               }
-               if (choice == -1) {
-                       xasprintf(cause, "unknown value: %s", value);
+               choice = options_find_choice(oe, value, cause);
+               if (choice < 0)
                        return (-1);
-               }
        }
        options_set_number(oo, name, choice);
        return (0);
index 7a8220b..331b77b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: popup.c,v 1.37 2021/10/13 09:28:36 nicm Exp $ */
+/* $OpenBSD: popup.c,v 1.38 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -31,6 +31,7 @@ struct popup_data {
        struct client            *c;
        struct cmdq_item         *item;
        int                       flags;
+       enum box_lines            lines;
 
        struct screen             s;
        struct colour_palette     palette;
@@ -117,7 +118,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->lines == BOX_LINES_NONE) {
                ttyctx->xoff = ttyctx->rxoff = pd->px;
                ttyctx->yoff = ttyctx->ryoff = pd->py;
        } else {
@@ -147,7 +148,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->lines == BOX_LINES_NONE) {
                *cx = pd->px + pd->s.cx;
                *cy = pd->py + pd->s.cy;
        } else {
@@ -220,14 +221,15 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
        screen_write_clearscreen(&ctx, 8);
 
        memcpy(&bgc, &grid_default_cell, sizeof bgc);
+       bgc.attr = 0;
        style_apply(&bgc, o, "popup-border-style", NULL);
        bgc.attr = 0;
 
-       if (pd->flags & POPUP_NOBORDER) {
+       if (pd->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, &bgc);
+               screen_write_box(&ctx, pd->sx, pd->sy, pd->lines, &bgc);
                screen_write_cursormove(&ctx, 1, 1, 0);
                screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2,
                    pd->sy - 2);
@@ -318,7 +320,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->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 );
@@ -444,7 +446,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->lines == BOX_LINES_NONE) {
                        if (m->x < pd->px + 1)
                                return;
                        if (m->y < pd->py + 1)
@@ -460,7 +462,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->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);
@@ -508,7 +510,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
                                goto menu;
                        return (0);
                }
-               if (~pd->flags & POPUP_NOBORDER) {
+               if (pd->lines != BOX_LINES_NONE) {
                        if (m->x == pd->px)
                                border = LEFT;
                        else if (m->x == pd->px + pd->sx - 1)
@@ -542,7 +544,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->lines == BOX_LINES_NONE) {
                                px = m->x - pd->px;
                                py = m->y - pd->py;
                        } else {
@@ -628,15 +630,23 @@ 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, struct environ *env, 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, struct client *c, struct session *s,
+    popup_close_cb cb, void *arg)
 {
        struct popup_data       *pd;
        u_int                    jx, jy;
+       struct options          *o;
 
-       if (flags & POPUP_NOBORDER) {
+       if (lines == BOX_LINES_DEFAULT) {
+               if (s != NULL)
+                       o = s->curw->window->options;
+               else
+                       o = c->session->curw->window->options;
+               lines = options_get_number(o, "popup-border-lines");
+       }
+       if (lines == BOX_LINES_NONE) {
                if (sx < 1 || sy < 1)
                        return (-1);
                jx = sx;
@@ -653,6 +663,7 @@ 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;
+       pd->lines = lines;
 
        pd->c = c;
        pd->c->references++;
@@ -764,8 +775,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,
-           NULL, 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, c, NULL,
+           popup_editor_close_cb, pe) != 0) {
                popup_editor_free(pe);
                free(cmd);
                return (-1);
index 2608d11..5297062 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: screen-redraw.c,v 1.89 2021/10/11 13:27:50 nicm Exp $ */
+/* $OpenBSD: screen-redraw.c,v 1.90 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -31,57 +31,9 @@ static void  screen_redraw_draw_pane(struct screen_redraw_ctx *,
 static void    screen_redraw_set_context(struct client *,
                    struct screen_redraw_ctx *);
 
-#define CELL_INSIDE 0
-#define CELL_TOPBOTTOM 1
-#define CELL_LEFTRIGHT 2
-#define CELL_TOPLEFT 3
-#define CELL_TOPRIGHT 4
-#define CELL_BOTTOMLEFT 5
-#define CELL_BOTTOMRIGHT 6
-#define CELL_TOPJOIN 7
-#define CELL_BOTTOMJOIN 8
-#define CELL_LEFTJOIN 9
-#define CELL_RIGHTJOIN 10
-#define CELL_JOIN 11
-#define CELL_OUTSIDE 12
-
-#define CELL_BORDERS " xqlkmjwvtun~"
-
 #define START_ISOLATE "\342\201\246"
 #define END_ISOLATE   "\342\201\251"
 
-static const struct utf8_data screen_redraw_double_borders[] = {
-       { "", 0, 0, 0 },
-       { "\342\225\221", 0, 3, 1 }, /* U+2551 */
-       { "\342\225\220", 0, 3, 1 }, /* U+2550 */
-       { "\342\225\224", 0, 3, 1 }, /* U+2554 */
-       { "\342\225\227", 0, 3, 1 }, /* U+2557 */
-       { "\342\225\232", 0, 3, 1 }, /* U+255A */
-       { "\342\225\235", 0, 3, 1 }, /* U+255D */
-       { "\342\225\246", 0, 3, 1 }, /* U+2566 */
-       { "\342\225\251", 0, 3, 1 }, /* U+2569 */
-       { "\342\225\240", 0, 3, 1 }, /* U+2560 */
-       { "\342\225\243", 0, 3, 1 }, /* U+2563 */
-       { "\342\225\254", 0, 3, 1 }, /* U+256C */
-       { "\302\267",     0, 2, 1 }  /* U+00B7 */
-};
-
-static const struct utf8_data screen_redraw_heavy_borders[] = {
-       { "", 0, 0, 0 },
-       { "\342\224\203", 0, 3, 1 }, /* U+2503 */
-       { "\342\224\201", 0, 3, 1 }, /* U+2501 */
-       { "\342\224\223", 0, 3, 1 }, /* U+2513 */
-       { "\342\224\217", 0, 3, 1 }, /* U+250F */
-       { "\342\224\227", 0, 3, 1 }, /* U+2517 */
-       { "\342\224\233", 0, 3, 1 }, /* U+251B */
-       { "\342\224\263", 0, 3, 1 }, /* U+2533 */
-       { "\342\224\273", 0, 3, 1 }, /* U+253B */
-       { "\342\224\243", 0, 3, 1 }, /* U+2523 */
-       { "\342\224\253", 0, 3, 1 }, /* U+252B */
-       { "\342\225\213", 0, 3, 1 }, /* U+254B */
-       { "\302\267",     0, 2, 1 }  /* U+00B7 */
-};
-
 enum screen_redraw_border_type {
        SCREEN_REDRAW_OUTSIDE,
        SCREEN_REDRAW_INSIDE,
@@ -90,8 +42,8 @@ enum screen_redraw_border_type {
 
 /* Get cell border character. */
 static void
-screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type,
-    struct grid_cell *gc)
+screen_redraw_border_set(struct window_pane *wp, enum pane_lines pane_lines,
+    int cell_type, struct grid_cell *gc)
 {
        u_int   idx;
 
@@ -110,15 +62,15 @@ screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type,
                break;
        case PANE_LINES_DOUBLE:
                gc->attr &= ~GRID_ATTR_CHARSET;
-               utf8_copy(&gc->data, &screen_redraw_double_borders[cell_type]);
+               utf8_copy(&gc->data, tty_acs_double_borders(cell_type));
                break;
        case PANE_LINES_HEAVY:
                gc->attr &= ~GRID_ATTR_CHARSET;
-               utf8_copy(&gc->data, &screen_redraw_heavy_borders[cell_type]);
+               utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
                break;
        case PANE_LINES_SIMPLE:
                gc->attr &= ~GRID_ATTR_CHARSET;
-               utf8_set(&gc->data, " |-+++++++++."[cell_type]);
+               utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
                break;
        default:
                gc->attr |= GRID_ATTR_CHARSET;
@@ -402,7 +354,7 @@ screen_redraw_check_is(u_int px, u_int py, int pane_status,
 /* Update pane status. */
 static int
 screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
-    struct screen_redraw_ctx *rctx, int pane_lines)
+    struct screen_redraw_ctx *rctx, enum pane_lines pane_lines)
 {
        struct window           *w = wp->window;
        struct grid_cell         gc;
@@ -527,11 +479,12 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
 static int
 screen_redraw_update(struct client *c, int flags)
 {
-       struct window           *w = c->session->curw->window;
-       struct window_pane      *wp;
-       struct options          *wo = w->options;
-       int                      redraw, lines;
-       struct screen_redraw_ctx ctx;
+       struct window                   *w = c->session->curw->window;
+       struct window_pane              *wp;
+       struct options                  *wo = w->options;
+       int                              redraw;
+       enum pane_lines                  lines;
+       struct screen_redraw_ctx         ctx;
 
        if (c->message_string != NULL)
                redraw = status_message_redraw(c);
index fa7d23f..9e01b4b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: screen-write.c,v 1.200 2021/10/13 09:28:36 nicm Exp $ */
+/* $OpenBSD: screen-write.c,v 1.201 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -645,7 +645,8 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu,
 
        memcpy(&default_gc, &grid_default_cell, sizeof default_gc);
 
-       screen_write_box(ctx, menu->width + 4, menu->count + 2, NULL);
+       screen_write_box(ctx, menu->width + 4, menu->count + 2,
+           BOX_LINES_DEFAULT, NULL);
        screen_write_cursormove(ctx, cx + 2, cy, 0);
        format_draw(ctx, &default_gc, menu->width, menu->title, NULL);
 
@@ -675,10 +676,45 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu,
        screen_write_set_cursor(ctx, cx, cy);
 }
 
+static void
+screen_write_box_border_set(enum box_lines box_lines, int cell_type,
+    struct grid_cell *gc)
+{
+       switch (box_lines) {
+        case BOX_LINES_NONE:
+               break;
+        case BOX_LINES_DOUBLE:
+                gc->attr &= ~GRID_ATTR_CHARSET;
+                utf8_copy(&gc->data, tty_acs_double_borders(cell_type));
+               break;
+        case BOX_LINES_HEAVY:
+                gc->attr &= ~GRID_ATTR_CHARSET;
+                utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
+               break;
+        case BOX_LINES_ROUNDED:
+                gc->attr &= ~GRID_ATTR_CHARSET;
+                utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type));
+               break;
+        case BOX_LINES_SIMPLE:
+                gc->attr &= ~GRID_ATTR_CHARSET;
+                utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
+                break;
+        case BOX_LINES_PADDED:
+                gc->attr &= ~GRID_ATTR_CHARSET;
+                utf8_set(&gc->data, PADDED_BORDERS[cell_type]);
+                break;
+       case BOX_LINES_SINGLE:
+       case BOX_LINES_DEFAULT:
+               gc->attr |= GRID_ATTR_CHARSET;
+               utf8_set(&gc->data, CELL_BORDERS[cell_type]);
+               break;
+       }
+}
+
 /* Draw a box on screen. */
 void
 screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny,
-    const struct grid_cell *gcp)
+    enum box_lines l, const struct grid_cell *gcp)
 {
        struct screen           *s = ctx->s;
        struct grid_cell         gc;
@@ -694,24 +730,34 @@ screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny,
        gc.attr |= GRID_ATTR_CHARSET;
        gc.flags |= GRID_FLAG_NOPALETTE;
 
-       screen_write_putc(ctx, &gc, 'l');
+       /* Draw top border */
+       screen_write_box_border_set(l, CELL_TOPLEFT, &gc);
+       screen_write_cell(ctx, &gc);
+       screen_write_box_border_set(l, CELL_LEFTRIGHT, &gc);
        for (i = 1; i < nx - 1; i++)
-               screen_write_putc(ctx, &gc, 'q');
-       screen_write_putc(ctx, &gc, 'k');
+               screen_write_cell(ctx, &gc);
+       screen_write_box_border_set(l, CELL_TOPRIGHT, &gc);
+       screen_write_cell(ctx, &gc);
 
+       /* Draw bottom border */
        screen_write_set_cursor(ctx, cx, cy + ny - 1);
-       screen_write_putc(ctx, &gc, 'm');
+       screen_write_box_border_set(l, CELL_BOTTOMLEFT, &gc);
+       screen_write_cell(ctx, &gc);
+       screen_write_box_border_set(l, CELL_LEFTRIGHT, &gc);
        for (i = 1; i < nx - 1; i++)
-               screen_write_putc(ctx, &gc, 'q');
-       screen_write_putc(ctx, &gc, 'j');
+               screen_write_cell(ctx, &gc);
+       screen_write_box_border_set(l, CELL_BOTTOMRIGHT, &gc);
+       screen_write_cell(ctx, &gc);
 
+       /* Draw sides */
+       screen_write_box_border_set(l, CELL_TOPBOTTOM, &gc);
        for (i = 1; i < ny - 1; i++) {
+               /* left side */
                screen_write_set_cursor(ctx, cx, cy + i);
-               screen_write_putc(ctx, &gc, 'x');
-       }
-       for (i = 1; i < ny - 1; i++) {
+               screen_write_cell(ctx, &gc);
+               /* right side */
                screen_write_set_cursor(ctx, cx + nx - 1, cy + i);
-               screen_write_putc(ctx, &gc, 'x');
+               screen_write_cell(ctx, &gc);
        }
 
        screen_write_set_cursor(ctx, cx, cy);
index d2ae3eb..78026d2 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.861 2021/10/13 09:28:36 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.862 2021/10/14 13:19:01 nicm Exp $
 .\"
 .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
 .\"
@@ -14,7 +14,7 @@
 .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: October 13 2021 $
+.Dd $Mdocdate: October 14 2021 $
 .Dt TMUX 1
 .Os
 .Sh NAME
@@ -4276,6 +4276,50 @@ see the
 section.
 Attributes are ignored.
 .Pp
+.It Ic popup-style Ar style
+Set the popup style.
+For how to specify
+.Ar style ,
+see the
+.Sx STYLES
+section.
+Attributes are ignored.
+.Pp
+.It Ic popup-border-style Ar style
+Set the popup border style.
+For how to specify
+.Ar style ,
+see the
+.Sx STYLES
+section.
+Attributes are ignored.
+.Pp
+.It Ic popup-border-lines Ar type
+Set the type of characters used for drawing popup borders.
+.Ar type
+may be one of:
+.Bl -tag -width Ds
+.It single
+single lines using ACS or UTF-8 characters (default)
+.It rounded
+variation of single with rounded corners using UTF-8 characters
+.It double
+double lines using UTF-8 characters
+.It heavy
+heavy lines using UTF-8 characters
+.It simple
+simple ASCII characters
+.It padded
+simple ASCII space character
+.It none
+no border
+.El
+.Pp
+.Ql double
+and
+.Ql heavy
+will fall back to standard ACS line drawing when UTF-8 is not supported.
+.Pp
 .It Ic window-status-activity-style Ar style
 Set status line style for windows with an activity alert.
 For how to specify
@@ -5769,6 +5813,7 @@ forwards any input read from stdin to the empty pane given by
 .Tg popup
 .It Xo Ic display-popup
 .Op Fl BCE
+.Op Fl b Ar border-lines
 .Op Fl c Ar target-client
 .Op Fl d Ar start-directory
 .Op Fl e Ar environment
@@ -5809,9 +5854,22 @@ and
 give the width and height - both may be a percentage (followed by
 .Ql % ) .
 If omitted, half of the terminal size is used.
+.Pp
 .Fl B
 does not surround the popup by a border.
 .Pp
+.Fl b
+sets the type of border line for the popup.
+When
+.Fl B
+is specified the
+.Fl b
+option is ignored.
+See
+.Ic popup-border-lines
+for possible values for
+.Ar border-lines .
+.Pp
 .Fl e
 takes the form
 .Ql VARIABLE=value
index 874cb06..bb0e4ee 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1146 2021/10/13 09:28:36 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1147 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -613,6 +613,24 @@ struct colour_palette {
 #define GRID_LINE_EXTENDED 0x2
 #define GRID_LINE_DEAD 0x4
 
+#define CELL_INSIDE 0
+#define CELL_TOPBOTTOM 1
+#define CELL_LEFTRIGHT 2
+#define CELL_TOPLEFT 3
+#define CELL_TOPRIGHT 4
+#define CELL_BOTTOMLEFT 5
+#define CELL_BOTTOMRIGHT 6
+#define CELL_TOPJOIN 7
+#define CELL_BOTTOMJOIN 8
+#define CELL_LEFTJOIN 9
+#define CELL_RIGHTJOIN 10
+#define CELL_JOIN 11
+#define CELL_OUTSIDE 12
+
+#define CELL_BORDERS " xqlkmjwvtun~"
+#define SIMPLE_BORDERS " |-+++++++++."
+#define PADDED_BORDERS "             "
+
 /* Grid cell data. */
 struct grid_cell {
        struct utf8_data        data;
@@ -799,6 +817,27 @@ struct screen_write_ctx {
        u_int                            bg;
 };
 
+/* Box border lines option. */
+enum box_lines {
+       BOX_LINES_DEFAULT = -1,
+       BOX_LINES_SINGLE,
+       BOX_LINES_DOUBLE,
+       BOX_LINES_HEAVY,
+       BOX_LINES_SIMPLE,
+       BOX_LINES_ROUNDED,
+       BOX_LINES_PADDED,
+       BOX_LINES_NONE
+};
+
+/* Pane border lines option. */
+enum pane_lines {
+       PANE_LINES_SINGLE,
+       PANE_LINES_DOUBLE,
+       PANE_LINES_HEAVY,
+       PANE_LINES_SIMPLE,
+       PANE_LINES_NUMBER
+};
+
 /* Screen redraw context. */
 struct screen_redraw_ctx {
        struct client   *c;
@@ -807,7 +846,7 @@ struct screen_redraw_ctx {
        int              statustop;
 
        int              pane_status;
-       int              pane_lines;
+       enum pane_lines  pane_lines;
 
        struct grid_cell no_pane_gc;
        int              no_pane_gc_set;
@@ -1061,13 +1100,6 @@ TAILQ_HEAD(winlink_stack, winlink);
 #define PANE_STATUS_TOP 1
 #define PANE_STATUS_BOTTOM 2
 
-/* Pane border lines option. */
-#define PANE_LINES_SINGLE 0
-#define PANE_LINES_DOUBLE 1
-#define PANE_LINES_HEAVY 2
-#define PANE_LINES_SIMPLE 3
-#define PANE_LINES_NUMBER 4
-
 /* Layout direction. */
 enum layout_type {
        LAYOUT_LEFTRIGHT,
@@ -2066,6 +2098,8 @@ struct style      *options_string_to_style(struct options *, const char *,
 int             options_from_string(struct options *,
                     const struct options_table_entry *, const char *,
                     const char *, int, char **);
+int             options_find_choice(const struct options_table_entry *,
+                    const char *, char **);
 void            options_push_changes(const char *);
 int             options_remove_or_default(struct options_entry *, int,
                     char **);
@@ -2216,6 +2250,9 @@ void               tty_default_features(int *, const char *, u_int);
 int             tty_acs_needed(struct tty *);
 const char     *tty_acs_get(struct tty *, u_char);
 int             tty_acs_reverse_get(struct tty *, const char *, size_t);
+const struct utf8_data *tty_acs_double_borders(int);
+const struct utf8_data *tty_acs_heavy_borders(int);
+const struct utf8_data *tty_acs_rounded_borders(int);
 
 /* tty-keys.c */
 void           tty_keys_build(struct tty *);
@@ -2699,8 +2736,8 @@ void       screen_write_hline(struct screen_write_ctx *, u_int, int, int);
 void    screen_write_vline(struct screen_write_ctx *, u_int, int, int);
 void    screen_write_menu(struct screen_write_ctx *, struct menu *, int,
             const struct grid_cell *);
-void    screen_write_box(struct screen_write_ctx *, u_int, u_int,
-            const struct grid_cell *gc);
+void    screen_write_box(struct screen_write_ctx *, u_int, u_int, int,
+            const struct grid_cell *);
 void    screen_write_preview(struct screen_write_ctx *, struct screen *, u_int,
             u_int);
 void    screen_write_backspace(struct screen_write_ctx *);
@@ -3112,12 +3149,11 @@ int              menu_key_cb(struct client *, void *, struct key_event *);
 /* popup.c */
 #define POPUP_CLOSEEXIT 0x1
 #define POPUP_CLOSEEXITZERO 0x2
-#define POPUP_NOBORDER 0x4
-#define POPUP_INTERNAL 0x8
+#define POPUP_INTERNAL 0x4
 typedef void (*popup_close_cb)(int, void *);
 typedef void (*popup_finish_edit_cb)(char *, size_t, void *);
-int             popup_display(int, struct cmdq_item *, u_int, u_int, u_int,
-                   u_int, struct environ *, const char *, int, char **,
+int             popup_display(int, int, struct cmdq_item *, u_int, u_int,
+                   u_int, u_int, struct environ *, const char *, int, char **,
                    const char *, struct client *, struct session *,
                    popup_close_cb, void *);
 int             popup_editor(struct client *, const char *, size_t,
index 546360c..2db97d5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty-acs.c,v 1.10 2020/05/16 16:26:34 nicm Exp $ */
+/* $OpenBSD: tty-acs.c,v 1.11 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -110,6 +110,78 @@ static const struct tty_acs_reverse_entry tty_acs_reverse3[] = {
        { "\342\225\254", 'n' },
 };
 
+/* UTF-8 double borders. */
+static const struct utf8_data tty_acs_double_borders_list[] = {
+       { "", 0, 0, 0 },
+       { "\342\225\221", 0, 3, 1 }, /* U+2551 */
+       { "\342\225\220", 0, 3, 1 }, /* U+2550 */
+       { "\342\225\224", 0, 3, 1 }, /* U+2554 */
+       { "\342\225\227", 0, 3, 1 }, /* U+2557 */
+       { "\342\225\232", 0, 3, 1 }, /* U+255A */
+       { "\342\225\235", 0, 3, 1 }, /* U+255D */
+       { "\342\225\246", 0, 3, 1 }, /* U+2566 */
+       { "\342\225\251", 0, 3, 1 }, /* U+2569 */
+       { "\342\225\240", 0, 3, 1 }, /* U+2560 */
+       { "\342\225\243", 0, 3, 1 }, /* U+2563 */
+       { "\342\225\254", 0, 3, 1 }, /* U+256C */
+       { "\302\267",     0, 2, 1 }  /* U+00B7 */
+};
+
+/* UTF-8 heavy borders. */
+static const struct utf8_data tty_acs_heavy_borders_list[] = {
+       { "", 0, 0, 0 },
+       { "\342\224\203", 0, 3, 1 }, /* U+2503 */
+       { "\342\224\201", 0, 3, 1 }, /* U+2501 */
+       { "\342\224\217", 0, 3, 1 }, /* U+250F */
+       { "\342\224\223", 0, 3, 1 }, /* U+2513 */
+       { "\342\224\227", 0, 3, 1 }, /* U+2517 */
+       { "\342\224\233", 0, 3, 1 }, /* U+251B */
+       { "\342\224\263", 0, 3, 1 }, /* U+2533 */
+       { "\342\224\273", 0, 3, 1 }, /* U+253B */
+       { "\342\224\243", 0, 3, 1 }, /* U+2523 */
+       { "\342\224\253", 0, 3, 1 }, /* U+252B */
+       { "\342\225\213", 0, 3, 1 }, /* U+254B */
+       { "\302\267",     0, 2, 1 }  /* U+00B7 */
+};
+
+/* UTF-8 rounded borders. */
+static const struct utf8_data tty_acs_rounded_borders_list[] = {
+       { "", 0, 0, 0 },
+       { "\342\224\202", 0, 3, 1 }, /* U+2502 */
+       { "\342\224\200", 0, 3, 1 }, /* U+2500 */
+       { "\342\225\255", 0, 3, 1 }, /* U+256D */
+       { "\342\225\256", 0, 3, 1 }, /* U+256E */
+       { "\342\225\260", 0, 3, 1 }, /* U+2570 */
+       { "\342\225\257", 0, 3, 1 }, /* U+256F */
+       { "\342\224\263", 0, 3, 1 }, /* U+2533 */
+       { "\342\224\273", 0, 3, 1 }, /* U+253B */
+       { "\342\224\243", 0, 3, 1 }, /* U+2523 */
+       { "\342\224\253", 0, 3, 1 }, /* U+252B */
+       { "\342\225\213", 0, 3, 1 }, /* U+254B */
+       { "\302\267",     0, 2, 1 }  /* U+00B7 */
+};
+
+/* Get cell border character for double style. */
+const struct utf8_data *
+tty_acs_double_borders(int cell_type)
+{
+       return (&tty_acs_double_borders_list[cell_type]);
+}
+
+/* Get cell border character for heavy style. */
+const struct utf8_data *
+tty_acs_heavy_borders(int cell_type)
+{
+       return (&tty_acs_heavy_borders_list[cell_type]);
+}
+
+/* Get cell border character for rounded style. */
+const struct utf8_data *
+tty_acs_rounded_borders(int cell_type)
+{
+       return (&tty_acs_rounded_borders_list[cell_type]);
+}
+
 static int
 tty_acs_cmp(const void *key, const void *value)
 {
index 8339209..b100fc1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-tree.c,v 1.57 2021/10/13 09:28:36 nicm Exp $ */
+/* $OpenBSD: window-tree.c,v 1.58 2021/10/14 13:19:01 nicm Exp $ */
 
 /*
  * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -519,7 +519,7 @@ window_tree_draw_label(struct screen_write_ctx *ctx, u_int px, u_int py,
 
        if (ox > 1 && ox + len < sx - 1 && sy >= 3) {
                screen_write_cursormove(ctx, px + ox - 1, py + oy - 1, 0);
-               screen_write_box(ctx, len + 2, 3, NULL);
+               screen_write_box(ctx, len + 2, 3, BOX_LINES_DEFAULT, NULL);
        }
        screen_write_cursormove(ctx, px + ox, py + oy, 0);
        screen_write_puts(ctx, gc, "%s", label);