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

1.8     ! nicm        1: /* $OpenBSD: window-tree.c,v 1.7 2017/06/30 22:36:11 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:
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23:
                     24: #include "tmux.h"
                     25:
                     26: static struct screen   *window_tree_init(struct window_pane *,
                     27:                             struct cmd_find_state *, struct args *);
                     28: static void             window_tree_free(struct window_pane *);
                     29: static void             window_tree_resize(struct window_pane *, u_int, u_int);
                     30: static void             window_tree_key(struct window_pane *,
                     31:                             struct client *, struct session *, key_code,
                     32:                             struct mouse_event *);
                     33:
                     34: #define WINDOW_TREE_DEFAULT_COMMAND "switch-client -t '%%'"
                     35:
                     36: const struct window_mode window_tree_mode = {
                     37:        .name = "tree-mode",
                     38:
                     39:        .init = window_tree_init,
                     40:        .free = window_tree_free,
                     41:        .resize = window_tree_resize,
                     42:        .key = window_tree_key,
                     43: };
                     44:
                     45: enum window_tree_sort_type {
                     46:        WINDOW_TREE_BY_INDEX,
                     47:        WINDOW_TREE_BY_NAME,
                     48:        WINDOW_TREE_BY_TIME,
                     49: };
                     50: static const char *window_tree_sort_list[] = {
                     51:        "index",
                     52:        "name",
                     53:        "time"
                     54: };
                     55:
                     56: enum window_tree_type {
                     57:        WINDOW_TREE_NONE,
                     58:        WINDOW_TREE_SESSION,
                     59:        WINDOW_TREE_WINDOW,
                     60:        WINDOW_TREE_PANE,
                     61: };
                     62:
                     63: struct window_tree_itemdata {
                     64:        enum window_tree_type   type;
                     65:        int                     session;
                     66:        int                     winlink;
                     67:        int                     pane;
                     68: };
                     69:
                     70: struct window_tree_modedata {
                     71:        struct window_pane               *wp;
                     72:        int                               dead;
                     73:        int                               references;
                     74:
                     75:        struct mode_tree_data            *data;
                     76:        char                             *command;
                     77:
                     78:        struct window_tree_itemdata     **item_list;
                     79:        u_int                             item_size;
                     80:
                     81:        struct client                    *client;
                     82:        const char                       *entered;
                     83:
                     84:        struct cmd_find_state             fs;
                     85:        enum window_tree_type             type;
                     86: };
                     87:
                     88: static void
                     89: window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
                     90:     struct winlink **wlp, struct window_pane **wp)
                     91: {
                     92:        *wp = NULL;
                     93:        *wlp = NULL;
                     94:        *sp = session_find_by_id(item->session);
                     95:        if (*sp == NULL)
                     96:                return;
                     97:        if (item->type == WINDOW_TREE_SESSION) {
                     98:                *wlp = (*sp)->curw;
                     99:                *wp = (*wlp)->window->active;
                    100:                return;
                    101:        }
                    102:
                    103:        *wlp = winlink_find_by_index(&(*sp)->windows, item->winlink);
                    104:        if (*wlp == NULL) {
                    105:                *sp = NULL;
                    106:                return;
                    107:        }
                    108:        if (item->type == WINDOW_TREE_WINDOW) {
                    109:                *wp = (*wlp)->window->active;
                    110:                return;
                    111:        }
                    112:
                    113:        *wp = window_pane_find_by_id(item->pane);
                    114:        if (!window_has_pane((*wlp)->window, *wp))
                    115:                *wp = NULL;
                    116:        if (*wp == NULL) {
                    117:                *sp = NULL;
                    118:                *wlp = NULL;
                    119:                return;
                    120:        }
                    121: }
                    122:
                    123: static struct window_tree_itemdata *
                    124: window_tree_add_item(struct window_tree_modedata *data)
                    125: {
                    126:        struct window_tree_itemdata     *item;
                    127:
                    128:        data->item_list = xreallocarray(data->item_list, data->item_size + 1,
                    129:            sizeof *data->item_list);
                    130:        item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
                    131:        return (item);
                    132: }
                    133:
                    134: static void
                    135: window_tree_free_item(struct window_tree_itemdata *item)
                    136: {
                    137:        free(item);
                    138: }
                    139:
                    140: static int
                    141: window_tree_cmp_session_name(const void *a0, const void *b0)
                    142: {
                    143:        const struct session *const *a = a0;
                    144:        const struct session *const *b = b0;
                    145:
                    146:        return (strcmp((*a)->name, (*b)->name));
                    147: }
                    148:
                    149: static int
                    150: window_tree_cmp_session_time(const void *a0, const void *b0)
                    151: {
                    152:        const struct session *const *a = a0;
                    153:        const struct session *const *b = b0;
                    154:
                    155:        if (timercmp(&(*a)->activity_time, &(*b)->activity_time, >))
                    156:                return (-1);
                    157:        if (timercmp(&(*a)->activity_time, &(*b)->activity_time, <))
                    158:                return (1);
                    159:        return (strcmp((*a)->name, (*b)->name));
                    160: }
                    161:
                    162: static int
                    163: window_tree_cmp_window_name(const void *a0, const void *b0)
                    164: {
                    165:        const struct winlink *const *a = a0;
                    166:        const struct winlink *const *b = b0;
                    167:
                    168:        return (strcmp((*a)->window->name, (*b)->window->name));
                    169: }
                    170:
                    171: static int
                    172: window_tree_cmp_window_time(const void *a0, const void *b0)
                    173: {
                    174:        const struct winlink *const *a = a0;
                    175:        const struct winlink *const *b = b0;
                    176:
                    177:        if (timercmp(&(*a)->window->activity_time,
                    178:            &(*b)->window->activity_time, >))
                    179:                return (-1);
                    180:        if (timercmp(&(*a)->window->activity_time,
                    181:            &(*b)->window->activity_time, <))
                    182:                return (1);
                    183:        return (strcmp((*a)->window->name, (*b)->window->name));
                    184: }
                    185:
                    186: static int
                    187: window_tree_cmp_pane_time(const void *a0, const void *b0)
                    188: {
                    189:        const struct window_pane *const *a = a0;
                    190:        const struct window_pane *const *b = b0;
                    191:
                    192:        if ((*a)->active_point < (*b)->active_point)
                    193:                return (-1);
                    194:        if ((*a)->active_point > (*b)->active_point)
                    195:                return (1);
                    196:        return (0);
                    197: }
                    198:
                    199: static void
                    200: window_tree_build_pane(struct session *s, struct winlink *wl,
                    201:     struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
                    202: {
                    203:        struct window_tree_modedata     *data = modedata;
                    204:        struct window_tree_itemdata     *item;
                    205:        char                            *name, *text;
                    206:        u_int                            idx;
                    207:
                    208:        window_pane_index(wp, &idx);
                    209:
                    210:        item = window_tree_add_item(data);
                    211:        item->type = WINDOW_TREE_PANE;
                    212:        item->session = s->id;
                    213:        item->winlink = wl->idx;
                    214:        item->pane = wp->id;
                    215:
                    216:        text = format_single(NULL,
                    217:            "#{pane_current_command} \"#{pane_title}\"",
                    218:            NULL, s, wl, wp);
                    219:        xasprintf(&name, "%u", idx);
                    220:
                    221:        mode_tree_add(data->data, parent, item, (uint64_t)wp, name, text, -1);
                    222:        free(text);
                    223:        free(name);
                    224: }
                    225:
                    226: static int
                    227: window_tree_build_window(struct session *s, struct winlink *wl, void* modedata,
1.5       nicm      228:     u_int sort_type, struct mode_tree_item *parent, const char *filter)
1.1       nicm      229: {
                    230:        struct window_tree_modedata     *data = modedata;
                    231:        struct window_tree_itemdata     *item;
                    232:        struct mode_tree_item           *mti;
                    233:        char                            *name, *text, *cp;
                    234:        struct window_pane              *wp, **l;
                    235:        u_int                            n, i;
                    236:        int                              expanded;
                    237:
                    238:        item = window_tree_add_item(data);
                    239:        item->type = WINDOW_TREE_WINDOW;
                    240:        item->session = s->id;
                    241:        item->winlink = wl->idx;
                    242:        item->pane = -1;
                    243:
                    244:        text = format_single(NULL,
                    245:            "#{window_name}#{window_flags} (#{window_panes} panes)",
                    246:            NULL, s, wl, NULL);
                    247:        xasprintf(&name, "%u", wl->idx);
                    248:
                    249:        if (data->type == WINDOW_TREE_SESSION ||
                    250:            data->type == WINDOW_TREE_WINDOW)
                    251:                expanded = 0;
                    252:        else
                    253:                expanded = 1;
                    254:        mti = mode_tree_add(data->data, parent, item, (uint64_t)wl, name, text,
                    255:            expanded);
                    256:        free(text);
                    257:        free(name);
                    258:
                    259:        l = NULL;
                    260:        n = 0;
                    261:        TAILQ_FOREACH(wp, &wl->window->panes, entry) {
1.5       nicm      262:                if (filter != NULL) {
                    263:                        cp = format_single(NULL, filter, NULL, s, wl, wp);
1.1       nicm      264:                        if (!format_true(cp)) {
                    265:                                free(cp);
                    266:                                continue;
                    267:                        }
                    268:                        free(cp);
                    269:                }
                    270:                l = xreallocarray(l, n + 1, sizeof *l);
                    271:                l[n++] = wp;
                    272:        }
                    273:        if (n == 0) {
                    274:                window_tree_free_item(item);
                    275:                data->item_size--;
                    276:                mode_tree_remove(data->data, mti);
                    277:                return (0);
                    278:        }
                    279:
                    280:        switch (sort_type) {
                    281:        case WINDOW_TREE_BY_INDEX:
                    282:                break;
                    283:        case WINDOW_TREE_BY_NAME:
                    284:                /* Panes don't have names, so leave in number order. */
                    285:                break;
                    286:        case WINDOW_TREE_BY_TIME:
                    287:                qsort(l, n, sizeof *l, window_tree_cmp_pane_time);
                    288:                break;
                    289:        }
                    290:
                    291:        for (i = 0; i < n; i++)
                    292:                window_tree_build_pane(s, wl, l[i], modedata, mti);
                    293:        free(l);
                    294:        return (1);
                    295: }
                    296:
                    297: static void
                    298: window_tree_build_session(struct session *s, void* modedata,
1.5       nicm      299:     u_int sort_type, const char *filter)
1.1       nicm      300: {
                    301:        struct window_tree_modedata     *data = modedata;
                    302:        struct window_tree_itemdata     *item;
                    303:        struct mode_tree_item           *mti;
                    304:        char                            *text;
                    305:        struct winlink                  *wl, **l;
                    306:        u_int                            n, i, empty;
                    307:        int                              expanded;
                    308:
                    309:        item = window_tree_add_item(data);
                    310:        item->type = WINDOW_TREE_SESSION;
                    311:        item->session = s->id;
                    312:        item->winlink = -1;
                    313:        item->pane = -1;
                    314:
                    315:        text = format_single(NULL,
                    316:            "#{session_windows} windows"
                    317:            "#{?session_grouped, (group ,}"
                    318:            "#{session_group}#{?session_grouped,),}"
                    319:            "#{?session_attached, (attached),}",
                    320:            NULL, s, NULL, NULL);
                    321:
                    322:        if (data->type == WINDOW_TREE_SESSION)
                    323:                expanded = 0;
                    324:        else
                    325:                expanded = 1;
                    326:        mti = mode_tree_add(data->data, NULL, item, (uint64_t)s, s->name, text,
                    327:            expanded);
                    328:        free(text);
                    329:
                    330:        l = NULL;
                    331:        n = 0;
                    332:        RB_FOREACH(wl, winlinks, &s->windows) {
                    333:                l = xreallocarray(l, n + 1, sizeof *l);
                    334:                l[n++] = wl;
                    335:        }
                    336:        switch (sort_type) {
                    337:        case WINDOW_TREE_BY_INDEX:
                    338:                break;
                    339:        case WINDOW_TREE_BY_NAME:
                    340:                qsort(l, n, sizeof *l, window_tree_cmp_window_name);
                    341:                break;
                    342:        case WINDOW_TREE_BY_TIME:
                    343:                qsort(l, n, sizeof *l, window_tree_cmp_window_time);
                    344:                break;
                    345:        }
                    346:
                    347:        empty = 0;
                    348:        for (i = 0; i < n; i++) {
                    349:                if (!window_tree_build_window(s, l[i], modedata, sort_type, mti,
1.5       nicm      350:                    filter))
1.1       nicm      351:                        empty++;
                    352:        }
                    353:        if (empty == n) {
                    354:                window_tree_free_item(item);
                    355:                data->item_size--;
                    356:                mode_tree_remove(data->data, mti);
                    357:        }
                    358:        free(l);
                    359: }
                    360:
                    361: static void
1.5       nicm      362: window_tree_build(void *modedata, u_int sort_type, uint64_t *tag,
                    363:     const char *filter)
1.1       nicm      364: {
                    365:        struct window_tree_modedata     *data = modedata;
                    366:        struct session                  *s, **l;
                    367:        u_int                            n, i;
                    368:
                    369:        for (i = 0; i < data->item_size; i++)
                    370:                window_tree_free_item(data->item_list[i]);
                    371:        free(data->item_list);
                    372:        data->item_list = NULL;
                    373:        data->item_size = 0;
                    374:
                    375:        l = NULL;
                    376:        n = 0;
                    377:        RB_FOREACH(s, sessions, &sessions) {
                    378:                l = xreallocarray(l, n + 1, sizeof *l);
                    379:                l[n++] = s;
                    380:        }
                    381:        switch (sort_type) {
                    382:        case WINDOW_TREE_BY_INDEX:
                    383:                break;
                    384:        case WINDOW_TREE_BY_NAME:
                    385:                qsort(l, n, sizeof *l, window_tree_cmp_session_name);
                    386:                break;
                    387:        case WINDOW_TREE_BY_TIME:
                    388:                qsort(l, n, sizeof *l, window_tree_cmp_session_time);
                    389:                break;
                    390:        }
                    391:
                    392:        for (i = 0; i < n; i++)
1.5       nicm      393:                window_tree_build_session(l[i], modedata, sort_type, filter);
1.1       nicm      394:        free(l);
                    395:
                    396:        switch (data->type) {
                    397:        case WINDOW_TREE_NONE:
                    398:                break;
                    399:        case WINDOW_TREE_SESSION:
                    400:                *tag = (uint64_t)data->fs.s;
                    401:                break;
                    402:        case WINDOW_TREE_WINDOW:
                    403:                *tag = (uint64_t)data->fs.wl;
                    404:                break;
                    405:        case WINDOW_TREE_PANE:
                    406:                *tag = (uint64_t)data->fs.wp;
                    407:                break;
                    408:        }
                    409: }
                    410:
1.6       nicm      411: static void
                    412: window_tree_draw_session(struct session *s, struct screen_write_ctx *ctx,
                    413:     u_int sx, u_int sy)
                    414: {
                    415:        struct options          *oo = s->options;
                    416:        struct winlink          *wl;
                    417:        struct window           *w;
                    418:        u_int                    i, n, each, width, left;
                    419:        struct grid_cell         gc;
                    420:        int                      colour, active_colour;
                    421:        char                    *label;
                    422:        size_t                   len;
                    423:
                    424:        if (sx < 6)
                    425:                return;
                    426:        n = winlink_count(&s->windows);
                    427:
                    428:        memcpy(&gc, &grid_default_cell, sizeof gc);
                    429:        colour = options_get_number(oo, "display-panes-colour");
                    430:        active_colour = options_get_number(oo, "display-panes-active-colour");
                    431:
                    432:        each = sx / n;
                    433:        if (each < 24) {
                    434:                n = (sx - 6) / 24;
1.7       nicm      435:                if (n == 0)
                    436:                        n = 1;
1.6       nicm      437:                each = (sx - 6) / n;
                    438:                left = sx - (n * each);
                    439:
                    440:                screen_write_cursormove(ctx, sx - left, 0);
                    441:                screen_write_vline(ctx, sy, 0, 0);
                    442:                screen_write_cursormove(ctx, sx - left + left / 2, sy / 2);
                    443:                screen_write_puts(ctx, &grid_default_cell, "...");
                    444:
1.7       nicm      445:                if (each == 0)
1.6       nicm      446:                        return;
                    447:                left = 0;
                    448:        } else
                    449:                left = sx - (n * each);
                    450:
                    451:        wl = RB_MIN(winlinks, &s->windows);
                    452:        for (i = 0; i < n; i++) {
                    453:                if (wl == s->curw)
                    454:                        gc.fg = active_colour;
                    455:                else
                    456:                        gc.fg = colour;
                    457:                if (i == n - 1)
                    458:                        width = each + left;
                    459:                else
                    460:                        width = each - 1;
                    461:                w = wl->window;
                    462:
                    463:                screen_write_cursormove(ctx, i * each, 0);
                    464:                screen_write_preview(ctx, &w->active->base, width, sy);
                    465:
                    466:                xasprintf(&label, " %u:%s ", wl->idx, w->name);
                    467:                if (strlen(label) > width)
                    468:                        xasprintf(&label, " %u ", wl->idx);
                    469:                len = strlen(label) / 2;
                    470:                screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
1.8     ! nicm      471:                if (len < width)
1.7       nicm      472:                        screen_write_puts(ctx, &gc, "%s", label);
1.6       nicm      473:                free(label);
                    474:
                    475:                if (i != n - 1) {
                    476:                        screen_write_cursormove(ctx, i * each + width, 0);
                    477:                        screen_write_vline(ctx, sy, 0, 0);
                    478:                }
                    479:                wl = RB_NEXT(winlinks, &s->windows, wl);
                    480:        }
                    481: }
                    482:
                    483: static void
                    484: window_tree_draw_window(struct session *s, struct window *w,
                    485:     struct screen_write_ctx *ctx, u_int sx, u_int sy)
                    486: {
                    487:        struct options          *oo = s->options;
                    488:        struct window_pane      *wp;
                    489:        u_int                    i, n, each, width, left;
                    490:        struct grid_cell         gc;
                    491:        int                      colour, active_colour;
                    492:        char                    *label;
                    493:        size_t                   len;
                    494:
                    495:        if (sx < 6)
                    496:                return;
                    497:        n = window_count_panes(w);
                    498:
                    499:        memcpy(&gc, &grid_default_cell, sizeof gc);
                    500:        colour = options_get_number(oo, "display-panes-colour");
                    501:        active_colour = options_get_number(oo, "display-panes-active-colour");
                    502:
                    503:        each = sx / n;
                    504:        if (each < 24) {
                    505:                n = (sx - 6) / 24;
1.7       nicm      506:                if (n == 0)
                    507:                        n = 1;
1.6       nicm      508:                each = (sx - 6) / n;
                    509:                left = sx - (n * each);
                    510:
                    511:                screen_write_cursormove(ctx, sx - left, 0);
                    512:                screen_write_vline(ctx, sy, 0, 0);
                    513:                screen_write_cursormove(ctx, sx - left + left / 2, sy / 2);
                    514:                screen_write_puts(ctx, &grid_default_cell, "...");
                    515:
1.7       nicm      516:                if (each == 0)
1.6       nicm      517:                        return;
                    518:                left = 0;
                    519:        } else
                    520:                left = sx - (n * each);
                    521:
                    522:        wp = TAILQ_FIRST(&w->panes);
                    523:        for (i = 0; i < n; i++) {
                    524:                if (wp == w->active)
                    525:                        gc.fg = active_colour;
                    526:                else
                    527:                        gc.fg = colour;
                    528:                if (i == n - 1)
                    529:                        width = each + left;
                    530:                else
                    531:                        width = each - 1;
                    532:
                    533:                screen_write_cursormove(ctx, i * each, 0);
                    534:                screen_write_preview(ctx, &wp->base, width, sy);
                    535:
                    536:                xasprintf(&label, " %u ", i);
                    537:                len = strlen(label) / 2;
                    538:                screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
1.8     ! nicm      539:                if (len < width)
1.7       nicm      540:                        screen_write_puts(ctx, &gc, "%s", label);
1.6       nicm      541:                free(label);
                    542:
                    543:                if (i != n - 1) {
                    544:                        screen_write_cursormove(ctx, i * each + width, 0);
                    545:                        screen_write_vline(ctx, sy, 0, 0);
                    546:                }
                    547:                wp = TAILQ_NEXT(wp, entry);
                    548:        }
                    549: }
                    550:
1.1       nicm      551: static struct screen *
                    552: window_tree_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
                    553: {
                    554:        struct window_tree_itemdata     *item = itemdata;
                    555:        struct session                  *sp;
                    556:        struct winlink                  *wlp;
                    557:        struct window_pane              *wp;
                    558:        static struct screen             s;
                    559:        struct screen_write_ctx          ctx;
                    560:
                    561:        window_tree_pull_item(item, &sp, &wlp, &wp);
                    562:        if (wp == NULL)
                    563:                return (NULL);
                    564:
                    565:        screen_init(&s, sx, sy, 0);
                    566:        screen_write_start(&ctx, NULL, &s);
                    567:
1.6       nicm      568:        switch (item->type) {
                    569:        case WINDOW_TREE_NONE:
                    570:                return (0);
                    571:        case WINDOW_TREE_SESSION:
                    572:                window_tree_draw_session(sp, &ctx, sx, sy);
                    573:                break;
                    574:        case WINDOW_TREE_WINDOW:
                    575:                window_tree_draw_window(sp, wlp->window, &ctx, sx, sy);
                    576:                break;
                    577:        case WINDOW_TREE_PANE:
                    578:                screen_write_preview(&ctx, &wp->base, sx, sy);
                    579:                break;
                    580:        }
1.1       nicm      581:
                    582:        screen_write_stop(&ctx);
                    583:        return (&s);
                    584: }
                    585:
1.3       nicm      586: static int
                    587: window_tree_search(__unused void *modedata, void *itemdata, const char *ss)
                    588: {
                    589:        struct window_tree_itemdata     *item = itemdata;
                    590:        struct session                  *s;
                    591:        struct winlink                  *wl;
                    592:        struct window_pane              *wp;
                    593:        const char                      *cmd;
                    594:
                    595:        window_tree_pull_item(item, &s, &wl, &wp);
                    596:
                    597:        switch (item->type) {
                    598:        case WINDOW_TREE_NONE:
                    599:                return (0);
                    600:        case WINDOW_TREE_SESSION:
                    601:                if (s == NULL)
                    602:                        return (0);
                    603:                return (strstr(s->name, ss) != NULL);
                    604:        case WINDOW_TREE_WINDOW:
                    605:                if (s == NULL || wl == NULL)
                    606:                        return (0);
                    607:                return (strstr(wl->window->name, ss) != NULL);
                    608:        case WINDOW_TREE_PANE:
                    609:                if (s == NULL || wl == NULL || wp == NULL)
                    610:                        break;
                    611:                cmd = get_proc_name(wp->fd, wp->tty);
                    612:                if (cmd == NULL || *cmd == '\0')
                    613:                        return (0);
                    614:                return (strstr(cmd, ss) != NULL);
                    615:        }
                    616:        return (0);
                    617: }
                    618:
1.1       nicm      619: static struct screen *
                    620: window_tree_init(struct window_pane *wp, struct cmd_find_state *fs,
                    621:     struct args *args)
                    622: {
                    623:        struct window_tree_modedata     *data;
                    624:        struct screen                   *s;
                    625:
                    626:        wp->modedata = data = xcalloc(1, sizeof *data);
                    627:
                    628:        if (args_has(args, 's'))
                    629:                data->type = WINDOW_TREE_SESSION;
                    630:        else if (args_has(args, 'w'))
                    631:                data->type = WINDOW_TREE_WINDOW;
                    632:        else
                    633:                data->type = WINDOW_TREE_PANE;
                    634:        memcpy(&data->fs, fs, sizeof data->fs);
                    635:
                    636:        data->wp = wp;
                    637:        data->references = 1;
                    638:
                    639:        if (args == NULL || args->argc == 0)
                    640:                data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND);
                    641:        else
                    642:                data->command = xstrdup(args->argv[0]);
                    643:
1.4       nicm      644:        data->data = mode_tree_start(wp, args, window_tree_build,
                    645:            window_tree_draw, window_tree_search, data, window_tree_sort_list,
1.1       nicm      646:            nitems(window_tree_sort_list), &s);
                    647:
                    648:        mode_tree_build(data->data);
                    649:        mode_tree_draw(data->data);
                    650:
                    651:        data->type = WINDOW_TREE_NONE;
                    652:
                    653:        return (s);
                    654: }
                    655:
                    656: static void
                    657: window_tree_destroy(struct window_tree_modedata *data)
                    658: {
                    659:        u_int   i;
                    660:
                    661:        if (--data->references != 0)
                    662:                return;
                    663:
                    664:        mode_tree_free(data->data);
                    665:
                    666:        for (i = 0; i < data->item_size; i++)
                    667:                window_tree_free_item(data->item_list[i]);
                    668:        free(data->item_list);
                    669:
                    670:        free(data->command);
                    671:        free(data);
                    672: }
                    673:
                    674: static void
                    675: window_tree_free(struct window_pane *wp)
                    676: {
                    677:        struct window_tree_modedata *data = wp->modedata;
                    678:
                    679:        if (data == NULL)
                    680:                return;
                    681:
                    682:        data->dead = 1;
                    683:        window_tree_destroy(data);
                    684: }
                    685:
                    686: static void
                    687: window_tree_resize(struct window_pane *wp, u_int sx, u_int sy)
                    688: {
                    689:        struct window_tree_modedata     *data = wp->modedata;
                    690:
                    691:        mode_tree_resize(data->data, sx, sy);
                    692: }
                    693:
                    694: static char *
                    695: window_tree_get_target(struct window_tree_itemdata *item,
                    696:     struct cmd_find_state *fs)
                    697: {
                    698:        struct session          *s;
                    699:        struct winlink          *wl;
                    700:        struct window_pane      *wp;
                    701:        char                    *target;
                    702:
                    703:        window_tree_pull_item(item, &s, &wl, &wp);
                    704:
                    705:        target = NULL;
                    706:        switch (item->type) {
                    707:        case WINDOW_TREE_NONE:
                    708:                break;
                    709:        case WINDOW_TREE_SESSION:
                    710:                if (s == NULL)
                    711:                        break;
                    712:                xasprintf(&target, "=%s:", s->name);
                    713:                break;
                    714:        case WINDOW_TREE_WINDOW:
                    715:                if (s == NULL || wl == NULL)
                    716:                        break;
                    717:                xasprintf(&target, "=%s:%u.", s->name, wl->idx);
                    718:                break;
                    719:        case WINDOW_TREE_PANE:
                    720:                if (s == NULL || wl == NULL || wp == NULL)
                    721:                        break;
                    722:                xasprintf(&target, "=%s:%u.%%%u", s->name, wl->idx, wp->id);
                    723:                break;
                    724:        }
                    725:        if (target == NULL)
                    726:                cmd_find_clear_state(fs, 0);
                    727:        else
                    728:                cmd_find_from_winlink_pane(fs, wl, wp);
                    729:        return (target);
                    730: }
                    731:
                    732: static void
                    733: window_tree_command_each(void* modedata, void* itemdata, __unused key_code key)
                    734: {
                    735:        struct window_tree_modedata     *data = modedata;
                    736:        struct window_tree_itemdata     *item = itemdata;
                    737:        char                            *name;
                    738:        struct cmd_find_state            fs;
                    739:
                    740:        name = window_tree_get_target(item, &fs);
                    741:        if (name != NULL)
                    742:                mode_tree_run_command(data->client, &fs, data->entered, name);
                    743:        free(name);
                    744: }
                    745:
                    746: static enum cmd_retval
                    747: window_tree_command_done(__unused struct cmdq_item *item, void *modedata)
                    748: {
                    749:        struct window_tree_modedata     *data = modedata;
                    750:
                    751:        if (!data->dead) {
                    752:                mode_tree_build(data->data);
                    753:                mode_tree_draw(data->data);
                    754:                data->wp->flags |= PANE_REDRAW;
                    755:        }
                    756:        window_tree_destroy(data);
                    757:        return (CMD_RETURN_NORMAL);
                    758: }
                    759:
                    760: static int
                    761: window_tree_command_callback(struct client *c, void *modedata, const char *s,
                    762:     __unused int done)
                    763: {
                    764:        struct window_tree_modedata     *data = modedata;
                    765:
                    766:        if (data->dead)
                    767:                return (0);
                    768:
                    769:        data->client = c;
                    770:        data->entered = s;
                    771:
                    772:        mode_tree_each_tagged(data->data, window_tree_command_each, KEYC_NONE,
                    773:            1);
                    774:
                    775:        data->client = NULL;
                    776:        data->entered = NULL;
                    777:
                    778:        data->references++;
                    779:        cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
                    780:
                    781:        return (0);
                    782: }
                    783:
                    784: static void
                    785: window_tree_command_free(void *modedata)
                    786: {
                    787:        struct window_tree_modedata     *data = modedata;
                    788:
                    789:        window_tree_destroy(data);
                    790: }
                    791:
                    792: static void
                    793: window_tree_key(struct window_pane *wp, struct client *c,
                    794:     __unused struct session *s, key_code key, struct mouse_event *m)
                    795: {
                    796:        struct window_tree_modedata     *data = wp->modedata;
                    797:        struct window_tree_itemdata     *item;
                    798:        char                            *command, *name, *prompt;
                    799:        struct cmd_find_state            fs;
                    800:        int                              finished;
                    801:        u_int                            tagged;
                    802:
1.3       nicm      803:        finished = mode_tree_key(data->data, c, &key, m);
1.1       nicm      804:        switch (key) {
                    805:        case ':':
                    806:                tagged = mode_tree_count_tagged(data->data);
                    807:                if (tagged != 0)
                    808:                        xasprintf(&prompt, "(%u tagged) ", tagged);
                    809:                else
                    810:                        xasprintf(&prompt, "(current) ");
                    811:                data->references++;
                    812:                status_prompt_set(c, prompt, "", window_tree_command_callback,
                    813:                    window_tree_command_free, data, PROMPT_NOFORMAT);
                    814:                free(prompt);
                    815:                break;
                    816:        case '\r':
                    817:                item = mode_tree_get_current(data->data);
                    818:                command = xstrdup(data->command);
                    819:                name = window_tree_get_target(item, &fs);
                    820:                window_pane_reset_mode(wp);
                    821:                if (name != NULL)
1.2       nicm      822:                        mode_tree_run_command(c, NULL, command, name);
1.1       nicm      823:                free(name);
                    824:                free(command);
                    825:                return;
                    826:        }
                    827:        if (finished)
                    828:                window_pane_reset_mode(wp);
                    829:        else {
                    830:                mode_tree_draw(data->data);
                    831:                wp->flags |= PANE_REDRAW;
                    832:        }
                    833: }