[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.30

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