[BACK]Return to window-tree.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/window-tree.c, Revision 1.39

1.39    ! nicm        1: /* $OpenBSD: window-tree.c,v 1.38 2019/05/12 08:58:09 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
1.30      nicm       21: #include <ctype.h>
1.1       nicm       22: #include <stdlib.h>
                     23: #include <string.h>
                     24:
                     25: #include "tmux.h"
                     26:
1.33      nicm       27: static struct screen   *window_tree_init(struct window_mode_entry *,
1.1       nicm       28:                             struct cmd_find_state *, struct args *);
1.33      nicm       29: static void             window_tree_free(struct window_mode_entry *);
                     30: static void             window_tree_resize(struct window_mode_entry *, u_int,
                     31:                             u_int);
                     32: static void             window_tree_key(struct window_mode_entry *,
1.32      nicm       33:                             struct client *, struct session *,
                     34:                             struct winlink *, key_code, struct mouse_event *);
1.1       nicm       35:
                     36: #define WINDOW_TREE_DEFAULT_COMMAND "switch-client -t '%%'"
                     37:
1.15      nicm       38: #define WINDOW_TREE_DEFAULT_FORMAT \
                     39:        "#{?pane_format," \
                     40:                "#{pane_current_command} \"#{pane_title}\"" \
                     41:        "," \
                     42:                "#{?window_format," \
                     43:                        "#{window_name}#{window_flags} " \
                     44:                        "(#{window_panes} panes)" \
                     45:                        "#{?#{==:#{window_panes},1}, \"#{pane_title}\",}" \
                     46:                "," \
                     47:                        "#{session_windows} windows" \
1.23      nicm       48:                        "#{?session_grouped, " \
1.25      nicm       49:                                "(group #{session_group}: " \
                     50:                                "#{session_group_list})," \
1.23      nicm       51:                        "}" \
1.15      nicm       52:                        "#{?session_attached, (attached),}" \
                     53:                "}" \
                     54:        "}"
                     55:
1.39    ! nicm       56: static const struct menu_item window_tree_menu_items[] = {
        !            57:        { "Select", 'E', NULL },
        !            58:        { "Expand", 'R', NULL },
        !            59:        { "", KEYC_NONE, NULL },
        !            60:        { "Tag", 't', NULL },
        !            61:        { "Tag All", '\024', NULL },
        !            62:        { "Tag None", 'T', NULL },
        !            63:        { "", KEYC_NONE, NULL },
        !            64:        { "Kill", 'x', NULL },
        !            65:        { "Kill Tagged", 'X', NULL },
        !            66:        { "", KEYC_NONE, NULL },
        !            67:        { "Cancel", 'q', NULL },
        !            68:
        !            69:        { NULL, KEYC_NONE, NULL }
        !            70: };
1.38      nicm       71:
1.1       nicm       72: const struct window_mode window_tree_mode = {
                     73:        .name = "tree-mode",
1.35      nicm       74:        .default_format = WINDOW_TREE_DEFAULT_FORMAT,
1.1       nicm       75:
                     76:        .init = window_tree_init,
                     77:        .free = window_tree_free,
                     78:        .resize = window_tree_resize,
                     79:        .key = window_tree_key,
                     80: };
                     81:
                     82: enum window_tree_sort_type {
                     83:        WINDOW_TREE_BY_INDEX,
                     84:        WINDOW_TREE_BY_NAME,
                     85:        WINDOW_TREE_BY_TIME,
                     86: };
                     87: static const char *window_tree_sort_list[] = {
                     88:        "index",
                     89:        "name",
                     90:        "time"
                     91: };
                     92:
                     93: enum window_tree_type {
                     94:        WINDOW_TREE_NONE,
                     95:        WINDOW_TREE_SESSION,
                     96:        WINDOW_TREE_WINDOW,
                     97:        WINDOW_TREE_PANE,
                     98: };
                     99:
                    100: struct window_tree_itemdata {
                    101:        enum window_tree_type   type;
                    102:        int                     session;
                    103:        int                     winlink;
                    104:        int                     pane;
                    105: };
                    106:
                    107: struct window_tree_modedata {
                    108:        struct window_pane               *wp;
                    109:        int                               dead;
                    110:        int                               references;
                    111:
                    112:        struct mode_tree_data            *data;
1.15      nicm      113:        char                             *format;
1.1       nicm      114:        char                             *command;
1.23      nicm      115:        int                               squash_groups;
1.1       nicm      116:
                    117:        struct window_tree_itemdata     **item_list;
                    118:        u_int                             item_size;
                    119:
                    120:        const char                       *entered;
                    121:
                    122:        struct cmd_find_state             fs;
                    123:        enum window_tree_type             type;
1.11      nicm      124:
                    125:        int                               offset;
1.27      nicm      126:
                    127:        int                               left;
                    128:        int                               right;
                    129:        u_int                             start;
                    130:        u_int                             end;
                    131:        u_int                             each;
1.1       nicm      132: };
                    133:
                    134: static void
                    135: window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
                    136:     struct winlink **wlp, struct window_pane **wp)
                    137: {
                    138:        *wp = NULL;
                    139:        *wlp = NULL;
                    140:        *sp = session_find_by_id(item->session);
                    141:        if (*sp == NULL)
                    142:                return;
                    143:        if (item->type == WINDOW_TREE_SESSION) {
                    144:                *wlp = (*sp)->curw;
                    145:                *wp = (*wlp)->window->active;
                    146:                return;
                    147:        }
                    148:
                    149:        *wlp = winlink_find_by_index(&(*sp)->windows, item->winlink);
                    150:        if (*wlp == NULL) {
                    151:                *sp = NULL;
                    152:                return;
                    153:        }
                    154:        if (item->type == WINDOW_TREE_WINDOW) {
                    155:                *wp = (*wlp)->window->active;
                    156:                return;
                    157:        }
                    158:
                    159:        *wp = window_pane_find_by_id(item->pane);
                    160:        if (!window_has_pane((*wlp)->window, *wp))
                    161:                *wp = NULL;
                    162:        if (*wp == NULL) {
                    163:                *sp = NULL;
                    164:                *wlp = NULL;
                    165:                return;
                    166:        }
                    167: }
                    168:
                    169: static struct window_tree_itemdata *
                    170: window_tree_add_item(struct window_tree_modedata *data)
                    171: {
                    172:        struct window_tree_itemdata     *item;
                    173:
                    174:        data->item_list = xreallocarray(data->item_list, data->item_size + 1,
                    175:            sizeof *data->item_list);
                    176:        item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
                    177:        return (item);
                    178: }
                    179:
                    180: static void
                    181: window_tree_free_item(struct window_tree_itemdata *item)
                    182: {
                    183:        free(item);
                    184: }
                    185:
                    186: static int
                    187: window_tree_cmp_session_name(const void *a0, const void *b0)
                    188: {
                    189:        const struct session *const *a = a0;
                    190:        const struct session *const *b = b0;
                    191:
                    192:        return (strcmp((*a)->name, (*b)->name));
                    193: }
                    194:
                    195: static int
                    196: window_tree_cmp_session_time(const void *a0, const void *b0)
                    197: {
                    198:        const struct session *const *a = a0;
                    199:        const struct session *const *b = b0;
                    200:
                    201:        if (timercmp(&(*a)->activity_time, &(*b)->activity_time, >))
                    202:                return (-1);
                    203:        if (timercmp(&(*a)->activity_time, &(*b)->activity_time, <))
                    204:                return (1);
                    205:        return (strcmp((*a)->name, (*b)->name));
                    206: }
                    207:
                    208: static int
                    209: window_tree_cmp_window_name(const void *a0, const void *b0)
                    210: {
                    211:        const struct winlink *const *a = a0;
                    212:        const struct winlink *const *b = b0;
                    213:
                    214:        return (strcmp((*a)->window->name, (*b)->window->name));
                    215: }
                    216:
                    217: static int
                    218: window_tree_cmp_window_time(const void *a0, const void *b0)
                    219: {
                    220:        const struct winlink *const *a = a0;
                    221:        const struct winlink *const *b = b0;
                    222:
                    223:        if (timercmp(&(*a)->window->activity_time,
                    224:            &(*b)->window->activity_time, >))
                    225:                return (-1);
                    226:        if (timercmp(&(*a)->window->activity_time,
                    227:            &(*b)->window->activity_time, <))
                    228:                return (1);
                    229:        return (strcmp((*a)->window->name, (*b)->window->name));
                    230: }
                    231:
                    232: static int
                    233: window_tree_cmp_pane_time(const void *a0, const void *b0)
                    234: {
                    235:        const struct window_pane *const *a = a0;
                    236:        const struct window_pane *const *b = b0;
                    237:
                    238:        if ((*a)->active_point < (*b)->active_point)
                    239:                return (-1);
                    240:        if ((*a)->active_point > (*b)->active_point)
                    241:                return (1);
                    242:        return (0);
                    243: }
                    244:
                    245: static void
                    246: window_tree_build_pane(struct session *s, struct winlink *wl,
                    247:     struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
                    248: {
                    249:        struct window_tree_modedata     *data = modedata;
                    250:        struct window_tree_itemdata     *item;
                    251:        char                            *name, *text;
                    252:        u_int                            idx;
                    253:
                    254:        window_pane_index(wp, &idx);
                    255:
                    256:        item = window_tree_add_item(data);
                    257:        item->type = WINDOW_TREE_PANE;
                    258:        item->session = s->id;
                    259:        item->winlink = wl->idx;
                    260:        item->pane = wp->id;
                    261:
1.15      nicm      262:        text = format_single(NULL, data->format, NULL, s, wl, wp);
1.1       nicm      263:        xasprintf(&name, "%u", idx);
                    264:
                    265:        mode_tree_add(data->data, parent, item, (uint64_t)wp, name, text, -1);
                    266:        free(text);
                    267:        free(name);
                    268: }
                    269:
                    270: static int
1.16      nicm      271: window_tree_filter_pane(struct session *s, struct winlink *wl,
                    272:     struct window_pane *wp, const char *filter)
                    273: {
                    274:        char    *cp;
                    275:        int      result;
                    276:
                    277:        if (filter == NULL)
                    278:                return (1);
                    279:
                    280:        cp = format_single(NULL, filter, NULL, s, wl, wp);
                    281:        result = format_true(cp);
                    282:        free(cp);
                    283:
                    284:        return (result);
                    285: }
                    286:
                    287: static int
1.1       nicm      288: window_tree_build_window(struct session *s, struct winlink *wl, void* modedata,
1.5       nicm      289:     u_int sort_type, struct mode_tree_item *parent, const char *filter)
1.1       nicm      290: {
                    291:        struct window_tree_modedata     *data = modedata;
                    292:        struct window_tree_itemdata     *item;
                    293:        struct mode_tree_item           *mti;
1.16      nicm      294:        char                            *name, *text;
1.1       nicm      295:        struct window_pane              *wp, **l;
                    296:        u_int                            n, i;
                    297:        int                              expanded;
                    298:
                    299:        item = window_tree_add_item(data);
                    300:        item->type = WINDOW_TREE_WINDOW;
                    301:        item->session = s->id;
                    302:        item->winlink = wl->idx;
                    303:        item->pane = -1;
                    304:
1.15      nicm      305:        text = format_single(NULL, data->format, NULL, s, wl, NULL);
1.1       nicm      306:        xasprintf(&name, "%u", wl->idx);
                    307:
                    308:        if (data->type == WINDOW_TREE_SESSION ||
                    309:            data->type == WINDOW_TREE_WINDOW)
                    310:                expanded = 0;
                    311:        else
                    312:                expanded = 1;
                    313:        mti = mode_tree_add(data->data, parent, item, (uint64_t)wl, name, text,
                    314:            expanded);
                    315:        free(text);
                    316:        free(name);
                    317:
1.29      nicm      318:        if ((wp = TAILQ_FIRST(&wl->window->panes)) == NULL)
                    319:                goto empty;
1.16      nicm      320:        if (TAILQ_NEXT(wp, entry) == NULL) {
                    321:                if (!window_tree_filter_pane(s, wl, wp, filter))
                    322:                        goto empty;
1.13      nicm      323:                return (1);
1.16      nicm      324:        }
1.13      nicm      325:
1.1       nicm      326:        l = NULL;
                    327:        n = 0;
1.13      nicm      328:
1.1       nicm      329:        TAILQ_FOREACH(wp, &wl->window->panes, entry) {
1.16      nicm      330:                if (!window_tree_filter_pane(s, wl, wp, filter))
                    331:                        continue;
1.1       nicm      332:                l = xreallocarray(l, n + 1, sizeof *l);
                    333:                l[n++] = wp;
                    334:        }
1.16      nicm      335:        if (n == 0)
                    336:                goto empty;
1.1       nicm      337:
                    338:        switch (sort_type) {
                    339:        case WINDOW_TREE_BY_INDEX:
                    340:                break;
                    341:        case WINDOW_TREE_BY_NAME:
                    342:                /* Panes don't have names, so leave in number order. */
                    343:                break;
                    344:        case WINDOW_TREE_BY_TIME:
                    345:                qsort(l, n, sizeof *l, window_tree_cmp_pane_time);
                    346:                break;
                    347:        }
                    348:
                    349:        for (i = 0; i < n; i++)
                    350:                window_tree_build_pane(s, wl, l[i], modedata, mti);
                    351:        free(l);
                    352:        return (1);
1.16      nicm      353:
                    354: empty:
                    355:        window_tree_free_item(item);
                    356:        data->item_size--;
                    357:        mode_tree_remove(data->data, mti);
                    358:        return (0);
1.1       nicm      359: }
                    360:
                    361: static void
                    362: window_tree_build_session(struct session *s, void* modedata,
1.5       nicm      363:     u_int sort_type, const char *filter)
1.1       nicm      364: {
                    365:        struct window_tree_modedata     *data = modedata;
                    366:        struct window_tree_itemdata     *item;
                    367:        struct mode_tree_item           *mti;
                    368:        char                            *text;
                    369:        struct winlink                  *wl, **l;
                    370:        u_int                            n, i, empty;
                    371:        int                              expanded;
                    372:
                    373:        item = window_tree_add_item(data);
                    374:        item->type = WINDOW_TREE_SESSION;
                    375:        item->session = s->id;
                    376:        item->winlink = -1;
                    377:        item->pane = -1;
                    378:
1.15      nicm      379:        text = format_single(NULL, data->format, NULL, s, NULL, NULL);
1.1       nicm      380:
                    381:        if (data->type == WINDOW_TREE_SESSION)
                    382:                expanded = 0;
                    383:        else
                    384:                expanded = 1;
                    385:        mti = mode_tree_add(data->data, NULL, item, (uint64_t)s, s->name, text,
                    386:            expanded);
                    387:        free(text);
                    388:
                    389:        l = NULL;
                    390:        n = 0;
                    391:        RB_FOREACH(wl, winlinks, &s->windows) {
                    392:                l = xreallocarray(l, n + 1, sizeof *l);
                    393:                l[n++] = wl;
                    394:        }
                    395:        switch (sort_type) {
                    396:        case WINDOW_TREE_BY_INDEX:
                    397:                break;
                    398:        case WINDOW_TREE_BY_NAME:
                    399:                qsort(l, n, sizeof *l, window_tree_cmp_window_name);
                    400:                break;
                    401:        case WINDOW_TREE_BY_TIME:
                    402:                qsort(l, n, sizeof *l, window_tree_cmp_window_time);
                    403:                break;
                    404:        }
                    405:
                    406:        empty = 0;
                    407:        for (i = 0; i < n; i++) {
                    408:                if (!window_tree_build_window(s, l[i], modedata, sort_type, mti,
1.5       nicm      409:                    filter))
1.1       nicm      410:                        empty++;
                    411:        }
                    412:        if (empty == n) {
                    413:                window_tree_free_item(item);
                    414:                data->item_size--;
                    415:                mode_tree_remove(data->data, mti);
                    416:        }
                    417:        free(l);
                    418: }
                    419:
                    420: static void
1.5       nicm      421: window_tree_build(void *modedata, u_int sort_type, uint64_t *tag,
                    422:     const char *filter)
1.1       nicm      423: {
                    424:        struct window_tree_modedata     *data = modedata;
                    425:        struct session                  *s, **l;
1.24      nicm      426:        struct session_group            *sg, *current;
1.1       nicm      427:        u_int                            n, i;
                    428:
1.24      nicm      429:        current = session_group_contains(data->fs.s);
                    430:
1.1       nicm      431:        for (i = 0; i < data->item_size; i++)
                    432:                window_tree_free_item(data->item_list[i]);
                    433:        free(data->item_list);
                    434:        data->item_list = NULL;
                    435:        data->item_size = 0;
                    436:
                    437:        l = NULL;
                    438:        n = 0;
                    439:        RB_FOREACH(s, sessions, &sessions) {
1.23      nicm      440:                if (data->squash_groups &&
1.24      nicm      441:                    (sg = session_group_contains(s)) != NULL) {
                    442:                        if ((sg == current && s != data->fs.s) ||
                    443:                            (sg != current && s != TAILQ_FIRST(&sg->sessions)))
                    444:                                continue;
                    445:                }
1.1       nicm      446:                l = xreallocarray(l, n + 1, sizeof *l);
                    447:                l[n++] = s;
                    448:        }
                    449:        switch (sort_type) {
                    450:        case WINDOW_TREE_BY_INDEX:
                    451:                break;
                    452:        case WINDOW_TREE_BY_NAME:
                    453:                qsort(l, n, sizeof *l, window_tree_cmp_session_name);
                    454:                break;
                    455:        case WINDOW_TREE_BY_TIME:
                    456:                qsort(l, n, sizeof *l, window_tree_cmp_session_time);
                    457:                break;
                    458:        }
                    459:
                    460:        for (i = 0; i < n; i++)
1.5       nicm      461:                window_tree_build_session(l[i], modedata, sort_type, filter);
1.1       nicm      462:        free(l);
                    463:
                    464:        switch (data->type) {
                    465:        case WINDOW_TREE_NONE:
                    466:                break;
                    467:        case WINDOW_TREE_SESSION:
                    468:                *tag = (uint64_t)data->fs.s;
                    469:                break;
                    470:        case WINDOW_TREE_WINDOW:
                    471:                *tag = (uint64_t)data->fs.wl;
                    472:                break;
                    473:        case WINDOW_TREE_PANE:
1.18      nicm      474:                if (window_count_panes(data->fs.wl->window) == 1)
                    475:                        *tag = (uint64_t)data->fs.wl;
                    476:                else
                    477:                        *tag = (uint64_t)data->fs.wp;
1.1       nicm      478:                break;
                    479:        }
                    480: }
1.19      nicm      481:
                    482: static void
                    483: window_tree_draw_label(struct screen_write_ctx *ctx, u_int px, u_int py,
                    484:     u_int sx, u_int sy, const struct grid_cell *gc, const char *label)
                    485: {
                    486:        size_t   len;
                    487:        u_int    ox, oy;
                    488:
                    489:        len = strlen(label);
                    490:        if (sx == 0 || sy == 1 || len > sx)
                    491:                return;
                    492:        ox = (sx - len + 1) / 2;
                    493:        oy = (sy + 1) / 2;
                    494:
                    495:        if (ox > 1 && ox + len < sx - 1 && sy >= 3) {
1.34      nicm      496:                screen_write_cursormove(ctx, px + ox - 1, py + oy - 1, 0);
1.19      nicm      497:                screen_write_box(ctx, len + 2, 3);
                    498:        }
1.34      nicm      499:        screen_write_cursormove(ctx, px + ox, py + oy, 0);
1.19      nicm      500:        screen_write_puts(ctx, gc, "%s", label);
                    501: }
                    502:
1.6       nicm      503: static void
1.11      nicm      504: window_tree_draw_session(struct window_tree_modedata *data, struct session *s,
                    505:     struct screen_write_ctx *ctx, u_int sx, u_int sy)
1.6       nicm      506: {
                    507:        struct options          *oo = s->options;
                    508:        struct winlink          *wl;
                    509:        struct window           *w;
1.26      nicm      510:        u_int                    cx = ctx->s->cx, cy = ctx->s->cy;
1.9       nicm      511:        u_int                    loop, total, visible, each, width, offset;
                    512:        u_int                    current, start, end, remaining, i;
1.6       nicm      513:        struct grid_cell         gc;
1.9       nicm      514:        int                      colour, active_colour, left, right;
1.6       nicm      515:        char                    *label;
                    516:
1.9       nicm      517:        total = winlink_count(&s->windows);
1.6       nicm      518:
                    519:        memcpy(&gc, &grid_default_cell, sizeof gc);
                    520:        colour = options_get_number(oo, "display-panes-colour");
                    521:        active_colour = options_get_number(oo, "display-panes-active-colour");
                    522:
1.9       nicm      523:        if (sx / total < 24) {
                    524:                visible = sx / 24;
                    525:                if (visible == 0)
                    526:                        visible = 1;
                    527:        } else
                    528:                visible = total;
                    529:
                    530:        current = 0;
                    531:        RB_FOREACH(wl, winlinks, &s->windows) {
                    532:                if (wl == s->curw)
                    533:                        break;
                    534:                current++;
                    535:        }
1.6       nicm      536:
1.9       nicm      537:        if (current < visible) {
                    538:                start = 0;
                    539:                end = visible;
                    540:        } else if (current >= total - visible) {
                    541:                start = total - visible;
                    542:                end = total;
                    543:        } else {
                    544:                start = current - (visible / 2);
                    545:                end = start + visible;
                    546:        }
                    547:
1.11      nicm      548:        if (data->offset < -(int)start)
                    549:                data->offset = -(int)start;
                    550:        if (data->offset > (int)(total - end))
                    551:                data->offset = (int)(total - end);
                    552:        start += data->offset;
                    553:        end += data->offset;
                    554:
1.9       nicm      555:        left = (start != 0);
                    556:        right = (end != total);
                    557:        if (((left && right) && sx <= 6) || ((left || right) && sx <= 3))
                    558:                left = right = 0;
                    559:        if (left && right) {
                    560:                each = (sx - 6) / visible;
                    561:                remaining = (sx - 6) - (visible * each);
                    562:        } else if (left || right) {
                    563:                each = (sx - 3) / visible;
                    564:                remaining = (sx - 3) - (visible * each);
                    565:        } else {
                    566:                each = sx / visible;
                    567:                remaining = sx - (visible * each);
                    568:        }
                    569:        if (each == 0)
                    570:                return;
                    571:
                    572:        if (left) {
1.27      nicm      573:                data->left = cx + 2;
1.34      nicm      574:                screen_write_cursormove(ctx, cx + 2, cy, 0);
1.9       nicm      575:                screen_write_vline(ctx, sy, 0, 0);
1.34      nicm      576:                screen_write_cursormove(ctx, cx, cy + sy / 2, 0);
1.9       nicm      577:                screen_write_puts(ctx, &grid_default_cell, "<");
1.27      nicm      578:        } else
                    579:                data->left = -1;
1.9       nicm      580:        if (right) {
1.27      nicm      581:                data->right = cx + sx - 3;
1.34      nicm      582:                screen_write_cursormove(ctx, cx + sx - 3, cy, 0);
1.6       nicm      583:                screen_write_vline(ctx, sy, 0, 0);
1.34      nicm      584:                screen_write_cursormove(ctx, cx + sx - 1, cy + sy / 2, 0);
1.9       nicm      585:                screen_write_puts(ctx, &grid_default_cell, ">");
1.27      nicm      586:        } else
                    587:                data->right = -1;
                    588:
                    589:        data->start = start;
                    590:        data->end = end;
                    591:        data->each = each;
1.6       nicm      592:
1.9       nicm      593:        i = loop = 0;
                    594:        RB_FOREACH(wl, winlinks, &s->windows) {
                    595:                if (loop == end)
                    596:                        break;
                    597:                if (loop < start) {
                    598:                        loop++;
                    599:                        continue;
                    600:                }
                    601:                w = wl->window;
1.6       nicm      602:
                    603:                if (wl == s->curw)
                    604:                        gc.fg = active_colour;
                    605:                else
                    606:                        gc.fg = colour;
1.9       nicm      607:
                    608:                if (left)
                    609:                        offset = 3 + (i * each);
                    610:                else
                    611:                        offset = (i * each);
                    612:                if (loop == end - 1)
1.12      nicm      613:                        width = each + remaining;
1.6       nicm      614:                else
                    615:                        width = each - 1;
                    616:
1.34      nicm      617:                screen_write_cursormove(ctx, cx + offset, cy, 0);
1.6       nicm      618:                screen_write_preview(ctx, &w->active->base, width, sy);
                    619:
                    620:                xasprintf(&label, " %u:%s ", wl->idx, w->name);
                    621:                if (strlen(label) > width)
                    622:                        xasprintf(&label, " %u ", wl->idx);
1.26      nicm      623:                window_tree_draw_label(ctx, cx + offset, cy, width, sy, &gc,
                    624:                    label);
1.6       nicm      625:                free(label);
                    626:
1.9       nicm      627:                if (loop != end - 1) {
1.34      nicm      628:                        screen_write_cursormove(ctx, cx + offset + width, cy, 0);
1.6       nicm      629:                        screen_write_vline(ctx, sy, 0, 0);
                    630:                }
1.9       nicm      631:                loop++;
                    632:
                    633:                i++;
1.6       nicm      634:        }
                    635: }
                    636:
                    637: static void
1.11      nicm      638: window_tree_draw_window(struct window_tree_modedata *data, struct session *s,
                    639:     struct window *w, struct screen_write_ctx *ctx, u_int sx, u_int sy)
1.6       nicm      640: {
                    641:        struct options          *oo = s->options;
                    642:        struct window_pane      *wp;
1.26      nicm      643:        u_int                    cx = ctx->s->cx, cy = ctx->s->cy;
1.9       nicm      644:        u_int                    loop, total, visible, each, width, offset;
                    645:        u_int                    current, start, end, remaining, i;
1.6       nicm      646:        struct grid_cell         gc;
1.20      nicm      647:        int                      colour, active_colour, left, right, pane_idx;
1.6       nicm      648:        char                    *label;
                    649:
1.9       nicm      650:        total = window_count_panes(w);
1.6       nicm      651:
                    652:        memcpy(&gc, &grid_default_cell, sizeof gc);
                    653:        colour = options_get_number(oo, "display-panes-colour");
                    654:        active_colour = options_get_number(oo, "display-panes-active-colour");
                    655:
1.9       nicm      656:        if (sx / total < 24) {
                    657:                visible = sx / 24;
                    658:                if (visible == 0)
                    659:                        visible = 1;
                    660:        } else
                    661:                visible = total;
                    662:
                    663:        current = 0;
                    664:        TAILQ_FOREACH(wp, &w->panes, entry) {
                    665:                if (wp == w->active)
                    666:                        break;
                    667:                current++;
                    668:        }
                    669:
                    670:        if (current < visible) {
                    671:                start = 0;
                    672:                end = visible;
                    673:        } else if (current >= total - visible) {
                    674:                start = total - visible;
                    675:                end = total;
                    676:        } else {
                    677:                start = current - (visible / 2);
                    678:                end = start + visible;
                    679:        }
                    680:
1.11      nicm      681:        if (data->offset < -(int)start)
                    682:                data->offset = -(int)start;
                    683:        if (data->offset > (int)(total - end))
                    684:                data->offset = (int)(total - end);
                    685:        start += data->offset;
                    686:        end += data->offset;
                    687:
1.9       nicm      688:        left = (start != 0);
                    689:        right = (end != total);
                    690:        if (((left && right) && sx <= 6) || ((left || right) && sx <= 3))
                    691:                left = right = 0;
                    692:        if (left && right) {
                    693:                each = (sx - 6) / visible;
                    694:                remaining = (sx - 6) - (visible * each);
                    695:        } else if (left || right) {
                    696:                each = (sx - 3) / visible;
                    697:                remaining = (sx - 3) - (visible * each);
                    698:        } else {
                    699:                each = sx / visible;
                    700:                remaining = sx - (visible * each);
                    701:        }
                    702:        if (each == 0)
                    703:                return;
1.6       nicm      704:
1.9       nicm      705:        if (left) {
1.27      nicm      706:                data->left = cx + 2;
1.34      nicm      707:                screen_write_cursormove(ctx, cx + 2, cy, 0);
1.6       nicm      708:                screen_write_vline(ctx, sy, 0, 0);
1.34      nicm      709:                screen_write_cursormove(ctx, cx, cy + sy / 2, 0);
1.9       nicm      710:                screen_write_puts(ctx, &grid_default_cell, "<");
1.27      nicm      711:        } else
                    712:                data->left = -1;
1.9       nicm      713:        if (right) {
1.27      nicm      714:                data->right = cx + sx - 3;
1.34      nicm      715:                screen_write_cursormove(ctx, cx + sx - 3, cy, 0);
1.9       nicm      716:                screen_write_vline(ctx, sy, 0, 0);
1.34      nicm      717:                screen_write_cursormove(ctx, cx + sx - 1, cy + sy / 2, 0);
1.9       nicm      718:                screen_write_puts(ctx, &grid_default_cell, ">");
1.27      nicm      719:        } else
                    720:                data->right = -1;
                    721:
                    722:        data->start = start;
                    723:        data->end = end;
                    724:        data->each = each;
1.6       nicm      725:
1.9       nicm      726:        i = loop = 0;
                    727:        TAILQ_FOREACH(wp, &w->panes, entry) {
                    728:                if (loop == end)
                    729:                        break;
                    730:                if (loop < start) {
                    731:                        loop++;
                    732:                        continue;
                    733:                }
1.6       nicm      734:
                    735:                if (wp == w->active)
                    736:                        gc.fg = active_colour;
                    737:                else
                    738:                        gc.fg = colour;
1.9       nicm      739:
                    740:                if (left)
                    741:                        offset = 3 + (i * each);
                    742:                else
                    743:                        offset = (i * each);
                    744:                if (loop == end - 1)
1.12      nicm      745:                        width = each + remaining;
1.6       nicm      746:                else
                    747:                        width = each - 1;
                    748:
1.34      nicm      749:                screen_write_cursormove(ctx, cx + offset, cy, 0);
1.6       nicm      750:                screen_write_preview(ctx, &wp->base, width, sy);
                    751:
1.20      nicm      752:                if (window_pane_index(wp, &pane_idx) != 0)
                    753:                        pane_idx = loop;
                    754:                xasprintf(&label, " %u ", pane_idx);
1.26      nicm      755:                window_tree_draw_label(ctx, cx + offset, cy, each, sy, &gc,
                    756:                    label);
1.6       nicm      757:                free(label);
                    758:
1.9       nicm      759:                if (loop != end - 1) {
1.34      nicm      760:                        screen_write_cursormove(ctx, cx + offset + width, cy, 0);
1.6       nicm      761:                        screen_write_vline(ctx, sy, 0, 0);
                    762:                }
1.9       nicm      763:                loop++;
                    764:
                    765:                i++;
1.6       nicm      766:        }
                    767: }
                    768:
1.26      nicm      769: static void
                    770: window_tree_draw(void *modedata, void *itemdata, struct screen_write_ctx *ctx,
                    771:     u_int sx, u_int sy)
1.1       nicm      772: {
                    773:        struct window_tree_itemdata     *item = itemdata;
                    774:        struct session                  *sp;
                    775:        struct winlink                  *wlp;
                    776:        struct window_pane              *wp;
                    777:
                    778:        window_tree_pull_item(item, &sp, &wlp, &wp);
                    779:        if (wp == NULL)
1.26      nicm      780:                return;
1.1       nicm      781:
1.6       nicm      782:        switch (item->type) {
                    783:        case WINDOW_TREE_NONE:
1.26      nicm      784:                break;
1.6       nicm      785:        case WINDOW_TREE_SESSION:
1.26      nicm      786:                window_tree_draw_session(modedata, sp, ctx, sx, sy);
1.6       nicm      787:                break;
                    788:        case WINDOW_TREE_WINDOW:
1.26      nicm      789:                window_tree_draw_window(modedata, sp, wlp->window, ctx, sx, sy);
1.6       nicm      790:                break;
                    791:        case WINDOW_TREE_PANE:
1.26      nicm      792:                screen_write_preview(ctx, &wp->base, sx, sy);
1.6       nicm      793:                break;
                    794:        }
1.1       nicm      795: }
                    796:
1.3       nicm      797: static int
                    798: window_tree_search(__unused void *modedata, void *itemdata, const char *ss)
                    799: {
                    800:        struct window_tree_itemdata     *item = itemdata;
                    801:        struct session                  *s;
                    802:        struct winlink                  *wl;
                    803:        struct window_pane              *wp;
1.37      nicm      804:        char                            *cmd;
                    805:        int                              retval;
1.3       nicm      806:
                    807:        window_tree_pull_item(item, &s, &wl, &wp);
                    808:
                    809:        switch (item->type) {
                    810:        case WINDOW_TREE_NONE:
                    811:                return (0);
                    812:        case WINDOW_TREE_SESSION:
                    813:                if (s == NULL)
                    814:                        return (0);
                    815:                return (strstr(s->name, ss) != NULL);
                    816:        case WINDOW_TREE_WINDOW:
                    817:                if (s == NULL || wl == NULL)
                    818:                        return (0);
                    819:                return (strstr(wl->window->name, ss) != NULL);
                    820:        case WINDOW_TREE_PANE:
                    821:                if (s == NULL || wl == NULL || wp == NULL)
                    822:                        break;
                    823:                cmd = get_proc_name(wp->fd, wp->tty);
                    824:                if (cmd == NULL || *cmd == '\0')
                    825:                        return (0);
1.37      nicm      826:                retval = (strstr(cmd, ss) != NULL);
                    827:                free(cmd);
                    828:                return retval;
1.3       nicm      829:        }
                    830:        return (0);
                    831: }
                    832:
1.38      nicm      833: static void
                    834: window_tree_menu(void *modedata, struct client *c, key_code key)
                    835: {
                    836:        struct window_tree_modedata     *data = modedata;
                    837:        struct window_pane              *wp = data->wp;
                    838:        struct window_mode_entry        *wme;
                    839:
                    840:        wme = TAILQ_FIRST(&wp->modes);
                    841:        if (wme == NULL || wme->data != modedata)
                    842:                return;
                    843:        window_tree_key(wme, c, NULL, NULL, key, NULL);
                    844: }
                    845:
1.1       nicm      846: static struct screen *
1.33      nicm      847: window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
1.1       nicm      848:     struct args *args)
                    849: {
1.33      nicm      850:        struct window_pane              *wp = wme->wp;
1.1       nicm      851:        struct window_tree_modedata     *data;
                    852:        struct screen                   *s;
                    853:
1.33      nicm      854:        wme->data = data = xcalloc(1, sizeof *data);
1.38      nicm      855:        data->wp = wp;
                    856:        data->references = 1;
1.1       nicm      857:
                    858:        if (args_has(args, 's'))
                    859:                data->type = WINDOW_TREE_SESSION;
                    860:        else if (args_has(args, 'w'))
                    861:                data->type = WINDOW_TREE_WINDOW;
                    862:        else
                    863:                data->type = WINDOW_TREE_PANE;
                    864:        memcpy(&data->fs, fs, sizeof data->fs);
                    865:
1.15      nicm      866:        if (args == NULL || !args_has(args, 'F'))
                    867:                data->format = xstrdup(WINDOW_TREE_DEFAULT_FORMAT);
                    868:        else
                    869:                data->format = xstrdup(args_get(args, 'F'));
1.1       nicm      870:        if (args == NULL || args->argc == 0)
                    871:                data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND);
                    872:        else
                    873:                data->command = xstrdup(args->argv[0]);
1.23      nicm      874:        data->squash_groups = !args_has(args, 'G');
1.1       nicm      875:
1.4       nicm      876:        data->data = mode_tree_start(wp, args, window_tree_build,
1.38      nicm      877:            window_tree_draw, window_tree_search, window_tree_menu, data,
1.39    ! nicm      878:            window_tree_menu_items, window_tree_sort_list,
1.1       nicm      879:            nitems(window_tree_sort_list), &s);
1.28      nicm      880:        mode_tree_zoom(data->data, args);
1.1       nicm      881:
                    882:        mode_tree_build(data->data);
                    883:        mode_tree_draw(data->data);
                    884:
                    885:        data->type = WINDOW_TREE_NONE;
                    886:
                    887:        return (s);
                    888: }
                    889:
                    890: static void
                    891: window_tree_destroy(struct window_tree_modedata *data)
                    892: {
                    893:        u_int   i;
                    894:
                    895:        if (--data->references != 0)
                    896:                return;
                    897:
                    898:        for (i = 0; i < data->item_size; i++)
                    899:                window_tree_free_item(data->item_list[i]);
                    900:        free(data->item_list);
                    901:
1.15      nicm      902:        free(data->format);
1.1       nicm      903:        free(data->command);
1.15      nicm      904:
1.1       nicm      905:        free(data);
                    906: }
                    907:
                    908: static void
1.33      nicm      909: window_tree_free(struct window_mode_entry *wme)
1.1       nicm      910: {
1.33      nicm      911:        struct window_tree_modedata *data = wme->data;
1.1       nicm      912:
                    913:        if (data == NULL)
                    914:                return;
                    915:
                    916:        data->dead = 1;
1.30      nicm      917:        mode_tree_free(data->data);
1.1       nicm      918:        window_tree_destroy(data);
                    919: }
                    920:
                    921: static void
1.33      nicm      922: window_tree_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
1.1       nicm      923: {
1.33      nicm      924:        struct window_tree_modedata     *data = wme->data;
1.1       nicm      925:
                    926:        mode_tree_resize(data->data, sx, sy);
                    927: }
                    928:
                    929: static char *
                    930: window_tree_get_target(struct window_tree_itemdata *item,
                    931:     struct cmd_find_state *fs)
                    932: {
                    933:        struct session          *s;
                    934:        struct winlink          *wl;
                    935:        struct window_pane      *wp;
                    936:        char                    *target;
                    937:
                    938:        window_tree_pull_item(item, &s, &wl, &wp);
                    939:
                    940:        target = NULL;
                    941:        switch (item->type) {
                    942:        case WINDOW_TREE_NONE:
                    943:                break;
                    944:        case WINDOW_TREE_SESSION:
                    945:                if (s == NULL)
                    946:                        break;
                    947:                xasprintf(&target, "=%s:", s->name);
                    948:                break;
                    949:        case WINDOW_TREE_WINDOW:
                    950:                if (s == NULL || wl == NULL)
                    951:                        break;
                    952:                xasprintf(&target, "=%s:%u.", s->name, wl->idx);
                    953:                break;
                    954:        case WINDOW_TREE_PANE:
                    955:                if (s == NULL || wl == NULL || wp == NULL)
                    956:                        break;
                    957:                xasprintf(&target, "=%s:%u.%%%u", s->name, wl->idx, wp->id);
                    958:                break;
                    959:        }
                    960:        if (target == NULL)
                    961:                cmd_find_clear_state(fs, 0);
                    962:        else
1.17      nicm      963:                cmd_find_from_winlink_pane(fs, wl, wp, 0);
1.1       nicm      964:        return (target);
                    965: }
                    966:
                    967: static void
1.21      nicm      968: window_tree_command_each(void* modedata, void* itemdata, struct client *c,
                    969:     __unused key_code key)
1.1       nicm      970: {
                    971:        struct window_tree_modedata     *data = modedata;
                    972:        struct window_tree_itemdata     *item = itemdata;
                    973:        char                            *name;
                    974:        struct cmd_find_state            fs;
                    975:
                    976:        name = window_tree_get_target(item, &fs);
                    977:        if (name != NULL)
1.21      nicm      978:                mode_tree_run_command(c, &fs, data->entered, name);
1.1       nicm      979:        free(name);
                    980: }
                    981:
                    982: static enum cmd_retval
                    983: window_tree_command_done(__unused struct cmdq_item *item, void *modedata)
                    984: {
                    985:        struct window_tree_modedata     *data = modedata;
                    986:
                    987:        if (!data->dead) {
                    988:                mode_tree_build(data->data);
                    989:                mode_tree_draw(data->data);
                    990:                data->wp->flags |= PANE_REDRAW;
                    991:        }
                    992:        window_tree_destroy(data);
                    993:        return (CMD_RETURN_NORMAL);
                    994: }
                    995:
                    996: static int
                    997: window_tree_command_callback(struct client *c, void *modedata, const char *s,
                    998:     __unused int done)
                    999: {
                   1000:        struct window_tree_modedata     *data = modedata;
                   1001:
1.30      nicm     1002:        if (s == NULL || *s == '\0' || data->dead)
1.1       nicm     1003:                return (0);
                   1004:
                   1005:        data->entered = s;
1.21      nicm     1006:        mode_tree_each_tagged(data->data, window_tree_command_each, c,
                   1007:            KEYC_NONE, 1);
1.1       nicm     1008:        data->entered = NULL;
                   1009:
                   1010:        data->references++;
                   1011:        cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
                   1012:
                   1013:        return (0);
                   1014: }
                   1015:
                   1016: static void
                   1017: window_tree_command_free(void *modedata)
                   1018: {
                   1019:        struct window_tree_modedata     *data = modedata;
                   1020:
                   1021:        window_tree_destroy(data);
                   1022: }
                   1023:
1.30      nicm     1024: static void
                   1025: window_tree_kill_each(__unused void* modedata, void* itemdata,
                   1026:     __unused struct client *c, __unused key_code key)
                   1027: {
                   1028:        struct window_tree_itemdata     *item = itemdata;
                   1029:        struct session                  *s;
                   1030:        struct winlink                  *wl;
                   1031:        struct window_pane              *wp;
                   1032:
                   1033:        window_tree_pull_item(item, &s, &wl, &wp);
                   1034:
                   1035:        switch (item->type) {
                   1036:        case WINDOW_TREE_NONE:
                   1037:                break;
                   1038:        case WINDOW_TREE_SESSION:
                   1039:                if (s != NULL) {
                   1040:                        server_destroy_session(s);
1.36      nicm     1041:                        session_destroy(s, 1, __func__);
1.30      nicm     1042:                }
                   1043:                break;
                   1044:        case WINDOW_TREE_WINDOW:
                   1045:                if (wl != NULL)
                   1046:                        server_kill_window(wl->window);
                   1047:                break;
                   1048:        case WINDOW_TREE_PANE:
                   1049:                if (wp != NULL)
                   1050:                        server_kill_pane(wp);
                   1051:                break;
                   1052:        }
                   1053: }
                   1054:
                   1055: static int
                   1056: window_tree_kill_current_callback(struct client *c, void *modedata,
                   1057:     const char *s, __unused int done)
                   1058: {
                   1059:        struct window_tree_modedata     *data = modedata;
                   1060:        struct mode_tree_data           *mtd = data->data;
                   1061:
                   1062:        if (s == NULL || *s == '\0' || data->dead)
                   1063:                return (0);
                   1064:        if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
                   1065:                return (0);
                   1066:
                   1067:        window_tree_kill_each(data, mode_tree_get_current(mtd), c, KEYC_NONE);
                   1068:
                   1069:        data->references++;
                   1070:        cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
                   1071:
                   1072:        return (0);
                   1073: }
                   1074:
                   1075: static int
                   1076: window_tree_kill_tagged_callback(struct client *c, void *modedata,
                   1077:     const char *s, __unused int done)
                   1078: {
                   1079:        struct window_tree_modedata     *data = modedata;
                   1080:        struct mode_tree_data           *mtd = data->data;
                   1081:
                   1082:        if (s == NULL || *s == '\0' || data->dead)
                   1083:                return (0);
                   1084:        if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
                   1085:                return (0);
                   1086:
                   1087:        mode_tree_each_tagged(mtd, window_tree_kill_each, c, KEYC_NONE, 1);
                   1088:
                   1089:        data->references++;
                   1090:        cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
                   1091:
                   1092:        return (0);
                   1093: }
                   1094:
1.27      nicm     1095: static key_code
                   1096: window_tree_mouse(struct window_tree_modedata *data, key_code key, u_int x,
                   1097:     struct window_tree_itemdata *item)
                   1098: {
                   1099:        struct session          *s;
                   1100:        struct winlink          *wl;
                   1101:        struct window_pane      *wp;
                   1102:        u_int                    loop;
                   1103:
                   1104:        if (key != KEYC_MOUSEDOWN1_PANE)
                   1105:                return (KEYC_NONE);
                   1106:
                   1107:        if (data->left != -1 && x <= (u_int)data->left)
                   1108:                return ('<');
                   1109:        if (data->right != -1 && x >= (u_int)data->right)
                   1110:                return ('>');
                   1111:
                   1112:        if (data->left != -1)
                   1113:                x -= data->left;
                   1114:        else if (x != 0)
                   1115:                x--;
                   1116:        if (x == 0 || data->end == 0)
                   1117:                x = 0;
                   1118:        else {
                   1119:                x = x / data->each;
                   1120:                if (data->start + x >= data->end)
                   1121:                        x = data->end - 1;
                   1122:        }
                   1123:
                   1124:        window_tree_pull_item(item, &s, &wl, &wp);
                   1125:        if (item->type == WINDOW_TREE_SESSION) {
                   1126:                if (s == NULL)
                   1127:                        return (KEYC_NONE);
                   1128:                mode_tree_expand_current(data->data);
                   1129:                loop = 0;
                   1130:                RB_FOREACH(wl, winlinks, &s->windows) {
                   1131:                        if (loop == data->start + x)
                   1132:                                break;
                   1133:                        loop++;
                   1134:                }
                   1135:                if (wl != NULL)
                   1136:                        mode_tree_set_current(data->data, (uint64_t)wl);
                   1137:                return ('\r');
                   1138:        }
                   1139:        if (item->type == WINDOW_TREE_WINDOW) {
                   1140:                if (wl == NULL)
                   1141:                        return (KEYC_NONE);
                   1142:                mode_tree_expand_current(data->data);
                   1143:                loop = 0;
                   1144:                TAILQ_FOREACH(wp, &wl->window->panes, entry) {
                   1145:                        if (loop == data->start + x)
                   1146:                                break;
                   1147:                        loop++;
                   1148:                }
                   1149:                if (wp != NULL)
                   1150:                        mode_tree_set_current(data->data, (uint64_t)wp);
                   1151:                return ('\r');
                   1152:        }
                   1153:        return (KEYC_NONE);
                   1154: }
                   1155:
1.1       nicm     1156: static void
1.33      nicm     1157: window_tree_key(struct window_mode_entry *wme, struct client *c,
1.32      nicm     1158:     __unused struct session *s, __unused struct winlink *wl, key_code key,
                   1159:     struct mouse_event *m)
1.1       nicm     1160: {
1.33      nicm     1161:        struct window_pane              *wp = wme->wp;
                   1162:        struct window_tree_modedata     *data = wme->data;
1.27      nicm     1163:        struct window_tree_itemdata     *item, *new_item;
1.30      nicm     1164:        char                            *name, *prompt = NULL;
1.1       nicm     1165:        struct cmd_find_state            fs;
                   1166:        int                              finished;
1.30      nicm     1167:        u_int                            tagged, x, y, idx;
                   1168:        struct session                  *ns;
                   1169:        struct winlink                  *nwl;
                   1170:        struct window_pane              *nwp;
1.1       nicm     1171:
1.11      nicm     1172:        item = mode_tree_get_current(data->data);
1.27      nicm     1173:        finished = mode_tree_key(data->data, c, &key, m, &x, &y);
                   1174:        if (item != (new_item = mode_tree_get_current(data->data))) {
                   1175:                item = new_item;
1.11      nicm     1176:                data->offset = 0;
1.27      nicm     1177:        }
1.38      nicm     1178:        if (KEYC_IS_MOUSE(key) && m != NULL)
1.27      nicm     1179:                key = window_tree_mouse(data, key, x, item);
1.1       nicm     1180:        switch (key) {
1.11      nicm     1181:        case '<':
                   1182:                data->offset--;
                   1183:                break;
                   1184:        case '>':
                   1185:                data->offset++;
1.30      nicm     1186:                break;
                   1187:        case 'x':
                   1188:                window_tree_pull_item(item, &ns, &nwl, &nwp);
                   1189:                switch (item->type) {
                   1190:                case WINDOW_TREE_NONE:
                   1191:                        break;
                   1192:                case WINDOW_TREE_SESSION:
                   1193:                        if (ns == NULL)
                   1194:                                break;
                   1195:                        xasprintf(&prompt, "Kill session %s? ", ns->name);
                   1196:                        break;
                   1197:                case WINDOW_TREE_WINDOW:
                   1198:                        if (nwl == NULL)
                   1199:                                break;
                   1200:                        xasprintf(&prompt, "Kill window %u? ", nwl->idx);
                   1201:                        break;
                   1202:                case WINDOW_TREE_PANE:
                   1203:                        if (nwp == NULL || window_pane_index(nwp, &idx) != 0)
                   1204:                                break;
                   1205:                        xasprintf(&prompt, "Kill pane %u? ", idx);
                   1206:                        break;
                   1207:                }
                   1208:                if (prompt == NULL)
                   1209:                        break;
                   1210:                data->references++;
                   1211:                status_prompt_set(c, prompt, "",
                   1212:                    window_tree_kill_current_callback, window_tree_command_free,
                   1213:                    data, PROMPT_SINGLE|PROMPT_NOFORMAT);
                   1214:                free(prompt);
                   1215:                break;
                   1216:        case 'X':
                   1217:                tagged = mode_tree_count_tagged(data->data);
                   1218:                if (tagged == 0)
                   1219:                        break;
                   1220:                xasprintf(&prompt, "Kill %u tagged? ", tagged);
                   1221:                data->references++;
                   1222:                status_prompt_set(c, prompt, "",
                   1223:                    window_tree_kill_tagged_callback, window_tree_command_free,
                   1224:                    data, PROMPT_SINGLE|PROMPT_NOFORMAT);
                   1225:                free(prompt);
1.11      nicm     1226:                break;
1.1       nicm     1227:        case ':':
                   1228:                tagged = mode_tree_count_tagged(data->data);
                   1229:                if (tagged != 0)
                   1230:                        xasprintf(&prompt, "(%u tagged) ", tagged);
                   1231:                else
                   1232:                        xasprintf(&prompt, "(current) ");
                   1233:                data->references++;
                   1234:                status_prompt_set(c, prompt, "", window_tree_command_callback,
                   1235:                    window_tree_command_free, data, PROMPT_NOFORMAT);
                   1236:                free(prompt);
                   1237:                break;
                   1238:        case '\r':
                   1239:                name = window_tree_get_target(item, &fs);
                   1240:                if (name != NULL)
1.21      nicm     1241:                        mode_tree_run_command(c, NULL, data->command, name);
                   1242:                finished = 1;
1.1       nicm     1243:                free(name);
1.21      nicm     1244:                break;
1.1       nicm     1245:        }
                   1246:        if (finished)
                   1247:                window_pane_reset_mode(wp);
                   1248:        else {
                   1249:                mode_tree_draw(data->data);
                   1250:                wp->flags |= PANE_REDRAW;
                   1251:        }
                   1252: }