"Fossies" - the Fresh Open Source Software Archive

Member "tmux-3.2a/format.c" (10 Jun 2021, 107661 Bytes) of package /linux/misc/tmux-3.2a.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "format.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.2_vs_3.2a.

    1 /* $OpenBSD$ */
    2 
    3 /*
    4  * Copyright (c) 2011 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 #include <sys/wait.h>
   21 
   22 #include <ctype.h>
   23 #include <errno.h>
   24 #include <fnmatch.h>
   25 #include <libgen.h>
   26 #include <math.h>
   27 #include <regex.h>
   28 #include <stdarg.h>
   29 #include <stdlib.h>
   30 #include <string.h>
   31 #include <time.h>
   32 #include <unistd.h>
   33 
   34 #include "tmux.h"
   35 
   36 /*
   37  * Build a list of key-value pairs and use them to expand #{key} entries in a
   38  * string.
   39  */
   40 
   41 struct format_expand_state;
   42 
   43 static char *format_job_get(struct format_expand_state *, const char *);
   44 static char *format_expand1(struct format_expand_state *, const char *);
   45 static int   format_replace(struct format_expand_state *, const char *,
   46              size_t, char **, size_t *, size_t *);
   47 static void  format_defaults_session(struct format_tree *,
   48              struct session *);
   49 static void  format_defaults_client(struct format_tree *, struct client *);
   50 static void  format_defaults_winlink(struct format_tree *,
   51              struct winlink *);
   52 
   53 /* Entry in format job tree. */
   54 struct format_job {
   55     struct client       *client;
   56     u_int            tag;
   57     const char      *cmd;
   58     const char      *expanded;
   59 
   60     time_t           last;
   61     char            *out;
   62     int          updated;
   63 
   64     struct job      *job;
   65     int          status;
   66 
   67     RB_ENTRY(format_job)     entry;
   68 };
   69 
   70 /* Format job tree. */
   71 static int format_job_cmp(struct format_job *, struct format_job *);
   72 static RB_HEAD(format_job_tree, format_job) format_jobs = RB_INITIALIZER();
   73 RB_GENERATE_STATIC(format_job_tree, format_job, entry, format_job_cmp);
   74 
   75 /* Format job tree comparison function. */
   76 static int
   77 format_job_cmp(struct format_job *fj1, struct format_job *fj2)
   78 {
   79     if (fj1->tag < fj2->tag)
   80         return (-1);
   81     if (fj1->tag > fj2->tag)
   82         return (1);
   83     return (strcmp(fj1->cmd, fj2->cmd));
   84 }
   85 
   86 /* Format modifiers. */
   87 #define FORMAT_TIMESTRING 0x1
   88 #define FORMAT_BASENAME 0x2
   89 #define FORMAT_DIRNAME 0x4
   90 #define FORMAT_QUOTE_SHELL 0x8
   91 #define FORMAT_LITERAL 0x10
   92 #define FORMAT_EXPAND 0x20
   93 #define FORMAT_EXPANDTIME 0x40
   94 #define FORMAT_SESSIONS 0x80
   95 #define FORMAT_WINDOWS 0x100
   96 #define FORMAT_PANES 0x200
   97 #define FORMAT_PRETTY 0x400
   98 #define FORMAT_LENGTH 0x800
   99 #define FORMAT_WIDTH 0x1000
  100 #define FORMAT_QUOTE_STYLE 0x2000
  101 #define FORMAT_WINDOW_NAME 0x4000
  102 #define FORMAT_SESSION_NAME 0x8000
  103 #define FORMAT_CHARACTER 0x10000
  104 
  105 /* Limit on recursion. */
  106 #define FORMAT_LOOP_LIMIT 100
  107 
  108 /* Format expand flags. */
  109 #define FORMAT_EXPAND_TIME 0x1
  110 #define FORMAT_EXPAND_NOJOBS 0x2
  111 
  112 /* Entry in format tree. */
  113 struct format_entry {
  114     char            *key;
  115     char            *value;
  116     time_t           time;
  117     format_cb        cb;
  118     RB_ENTRY(format_entry)   entry;
  119 };
  120 
  121 /* Format type. */
  122 enum format_type {
  123     FORMAT_TYPE_UNKNOWN,
  124     FORMAT_TYPE_SESSION,
  125     FORMAT_TYPE_WINDOW,
  126     FORMAT_TYPE_PANE
  127 };
  128 
  129 struct format_tree {
  130     enum format_type     type;
  131 
  132     struct client       *c;
  133     struct session      *s;
  134     struct winlink      *wl;
  135     struct window       *w;
  136     struct window_pane  *wp;
  137     struct paste_buffer *pb;
  138 
  139     struct cmdq_item    *item;
  140     struct client       *client;
  141     int          flags;
  142     u_int            tag;
  143 
  144     struct mouse_event   m;
  145 
  146     RB_HEAD(format_entry_tree, format_entry) tree;
  147 };
  148 static int format_entry_cmp(struct format_entry *, struct format_entry *);
  149 RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp);
  150 
  151 /* Format expand state. */
  152 struct format_expand_state {
  153     struct format_tree  *ft;
  154     u_int            loop;
  155     time_t           time;
  156     struct tm        tm;
  157     int          flags;
  158 };
  159 
  160 /* Format modifier. */
  161 struct format_modifier {
  162     char      modifier[3];
  163     u_int     size;
  164 
  165     char    **argv;
  166     int   argc;
  167 };
  168 
  169 /* Format entry tree comparison function. */
  170 static int
  171 format_entry_cmp(struct format_entry *fe1, struct format_entry *fe2)
  172 {
  173     return (strcmp(fe1->key, fe2->key));
  174 }
  175 
  176 /* Single-character uppercase aliases. */
  177 static const char *format_upper[] = {
  178     NULL,       /* A */
  179     NULL,       /* B */
  180     NULL,       /* C */
  181     "pane_id",  /* D */
  182     NULL,       /* E */
  183     "window_flags", /* F */
  184     NULL,       /* G */
  185     "host",     /* H */
  186     "window_index", /* I */
  187     NULL,       /* J */
  188     NULL,       /* K */
  189     NULL,       /* L */
  190     NULL,       /* M */
  191     NULL,       /* N */
  192     NULL,       /* O */
  193     "pane_index",   /* P */
  194     NULL,       /* Q */
  195     NULL,       /* R */
  196     "session_name", /* S */
  197     "pane_title",   /* T */
  198     NULL,       /* U */
  199     NULL,       /* V */
  200     "window_name",  /* W */
  201     NULL,       /* X */
  202     NULL,       /* Y */
  203     NULL        /* Z */
  204 };
  205 
  206 /* Single-character lowercase aliases. */
  207 static const char *format_lower[] = {
  208     NULL,       /* a */
  209     NULL,       /* b */
  210     NULL,       /* c */
  211     NULL,       /* d */
  212     NULL,       /* e */
  213     NULL,       /* f */
  214     NULL,       /* g */
  215     "host_short",   /* h */
  216     NULL,       /* i */
  217     NULL,       /* j */
  218     NULL,       /* k */
  219     NULL,       /* l */
  220     NULL,       /* m */
  221     NULL,       /* n */
  222     NULL,       /* o */
  223     NULL,       /* p */
  224     NULL,       /* q */
  225     NULL,       /* r */
  226     NULL,       /* s */
  227     NULL,       /* t */
  228     NULL,       /* u */
  229     NULL,       /* v */
  230     NULL,       /* w */
  231     NULL,       /* x */
  232     NULL,       /* y */
  233     NULL        /* z */
  234 };
  235 
  236 /* Is logging enabled? */
  237 static inline int
  238 format_logging(struct format_tree *ft)
  239 {
  240     return (log_get_level() != 0 || (ft->flags & FORMAT_VERBOSE));
  241 }
  242 
  243 /* Log a message if verbose. */
  244 static void printflike(3, 4)
  245 format_log1(struct format_expand_state *es, const char *from, const char *fmt,
  246     ...)
  247 {
  248     struct format_tree  *ft = es->ft;
  249     va_list          ap;
  250     char            *s;
  251     static const char    spaces[] = "          ";
  252 
  253     if (!format_logging(ft))
  254         return;
  255 
  256     va_start(ap, fmt);
  257     xvasprintf(&s, fmt, ap);
  258     va_end(ap);
  259 
  260     log_debug("%s: %s", from, s);
  261     if (ft->item != NULL && (ft->flags & FORMAT_VERBOSE))
  262         cmdq_print(ft->item, "#%.*s%s", es->loop, spaces, s);
  263 
  264     free(s);
  265 }
  266 #define format_log(es, fmt, ...) format_log1(es, __func__, fmt, ##__VA_ARGS__)
  267 
  268 /* Copy expand state. */
  269 static void
  270 format_copy_state(struct format_expand_state *to,
  271     struct format_expand_state *from, int flags)
  272 {
  273     to->ft = from->ft;
  274     to->loop = from->loop;
  275     to->time = from->time;
  276     memcpy(&to->tm, &from->tm, sizeof to->tm);
  277     to->flags = from->flags|flags;
  278 }
  279 
  280 /* Format job update callback. */
  281 static void
  282 format_job_update(struct job *job)
  283 {
  284     struct format_job   *fj = job_get_data(job);
  285     struct evbuffer     *evb = job_get_event(job)->input;
  286     char            *line = NULL, *next;
  287     time_t           t;
  288 
  289     while ((next = evbuffer_readline(evb)) != NULL) {
  290         free(line);
  291         line = next;
  292     }
  293     if (line == NULL)
  294         return;
  295     fj->updated = 1;
  296 
  297     free(fj->out);
  298     fj->out = line;
  299 
  300     log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, fj->out);
  301 
  302     t = time(NULL);
  303     if (fj->status && fj->last != t) {
  304         if (fj->client != NULL)
  305             server_status_client(fj->client);
  306         fj->last = t;
  307     }
  308 }
  309 
  310 /* Format job complete callback. */
  311 static void
  312 format_job_complete(struct job *job)
  313 {
  314     struct format_job   *fj = job_get_data(job);
  315     struct evbuffer     *evb = job_get_event(job)->input;
  316     char            *line, *buf;
  317     size_t           len;
  318 
  319     fj->job = NULL;
  320 
  321     buf = NULL;
  322     if ((line = evbuffer_readline(evb)) == NULL) {
  323         len = EVBUFFER_LENGTH(evb);
  324         buf = xmalloc(len + 1);
  325         if (len != 0)
  326             memcpy(buf, EVBUFFER_DATA(evb), len);
  327         buf[len] = '\0';
  328     } else
  329         buf = line;
  330 
  331     log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, buf);
  332 
  333     if (*buf != '\0' || !fj->updated) {
  334         free(fj->out);
  335         fj->out = buf;
  336     } else
  337         free(buf);
  338 
  339     if (fj->status) {
  340         if (fj->client != NULL)
  341             server_status_client(fj->client);
  342         fj->status = 0;
  343     }
  344 }
  345 
  346 /* Find a job. */
  347 static char *
  348 format_job_get(struct format_expand_state *es, const char *cmd)
  349 {
  350     struct format_tree      *ft = es->ft;
  351     struct format_job_tree      *jobs;
  352     struct format_job        fj0, *fj;
  353     time_t               t;
  354     char                *expanded;
  355     int              force;
  356     struct format_expand_state   next;
  357 
  358     if (ft->client == NULL)
  359         jobs = &format_jobs;
  360     else if (ft->client->jobs != NULL)
  361         jobs = ft->client->jobs;
  362     else {
  363         jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs);
  364         RB_INIT(jobs);
  365     }
  366 
  367     fj0.tag = ft->tag;
  368     fj0.cmd = cmd;
  369     if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) {
  370         fj = xcalloc(1, sizeof *fj);
  371         fj->client = ft->client;
  372         fj->tag = ft->tag;
  373         fj->cmd = xstrdup(cmd);
  374         fj->expanded = NULL;
  375 
  376         xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
  377 
  378         RB_INSERT(format_job_tree, jobs, fj);
  379     }
  380 
  381     format_copy_state(&next, es, FORMAT_EXPAND_NOJOBS);
  382     next.flags &= ~FORMAT_EXPAND_TIME;
  383 
  384     expanded = format_expand1(&next, cmd);
  385     if (fj->expanded == NULL || strcmp(expanded, fj->expanded) != 0) {
  386         free((void *)fj->expanded);
  387         fj->expanded = xstrdup(expanded);
  388         force = 1;
  389     } else
  390         force = (ft->flags & FORMAT_FORCE);
  391 
  392     t = time(NULL);
  393     if (force && fj->job != NULL)
  394            job_free(fj->job);
  395     if (force || (fj->job == NULL && fj->last != t)) {
  396         fj->job = job_run(expanded, 0, NULL, NULL,
  397             server_client_get_cwd(ft->client, NULL), format_job_update,
  398             format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1);
  399         if (fj->job == NULL) {
  400             free(fj->out);
  401             xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
  402         }
  403         fj->last = t;
  404         fj->updated = 0;
  405     }
  406     free(expanded);
  407 
  408     if (ft->flags & FORMAT_STATUS)
  409         fj->status = 1;
  410     return (format_expand1(&next, fj->out));
  411 }
  412 
  413 /* Remove old jobs. */
  414 static void
  415 format_job_tidy(struct format_job_tree *jobs, int force)
  416 {
  417     struct format_job   *fj, *fj1;
  418     time_t           now;
  419 
  420     now = time(NULL);
  421     RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) {
  422         if (!force && (fj->last > now || now - fj->last < 3600))
  423             continue;
  424         RB_REMOVE(format_job_tree, jobs, fj);
  425 
  426         log_debug("%s: %s", __func__, fj->cmd);
  427 
  428         if (fj->job != NULL)
  429             job_free(fj->job);
  430 
  431         free((void *)fj->expanded);
  432         free((void *)fj->cmd);
  433         free(fj->out);
  434 
  435         free(fj);
  436     }
  437 }
  438 
  439 /* Tidy old jobs for all clients. */
  440 void
  441 format_tidy_jobs(void)
  442 {
  443     struct client   *c;
  444 
  445     format_job_tidy(&format_jobs, 0);
  446     TAILQ_FOREACH(c, &clients, entry) {
  447         if (c->jobs != NULL)
  448             format_job_tidy(c->jobs, 0);
  449     }
  450 }
  451 
  452 /* Remove old jobs for client. */
  453 void
  454 format_lost_client(struct client *c)
  455 {
  456     if (c->jobs != NULL)
  457         format_job_tidy(c->jobs, 1);
  458     free(c->jobs);
  459 }
  460 
  461 /* Wrapper for asprintf. */
  462 static char * printflike(1, 2)
  463 format_printf(const char *fmt, ...)
  464 {
  465     va_list  ap;
  466     char    *s;
  467 
  468     va_start(ap, fmt);
  469     xvasprintf(&s, fmt, ap);
  470     va_end(ap);
  471     return (s);
  472 }
  473 
  474 /* Callback for host. */
  475 static void *
  476 format_cb_host(__unused struct format_tree *ft)
  477 {
  478     char host[HOST_NAME_MAX + 1];
  479 
  480     if (gethostname(host, sizeof host) != 0)
  481         return (xstrdup(""));
  482     return (xstrdup(host));
  483 }
  484 
  485 /* Callback for host_short. */
  486 static void *
  487 format_cb_host_short(__unused struct format_tree *ft)
  488 {
  489     char host[HOST_NAME_MAX + 1], *cp;
  490 
  491     if (gethostname(host, sizeof host) != 0)
  492         return (xstrdup(""));
  493     if ((cp = strchr(host, '.')) != NULL)
  494         *cp = '\0';
  495     return (xstrdup(host));
  496 }
  497 
  498 /* Callback for pid. */
  499 static void *
  500 format_cb_pid(__unused struct format_tree *ft)
  501 {
  502     char    *value;
  503 
  504     xasprintf(&value, "%ld", (long)getpid());
  505     return (value);
  506 }
  507 
  508 /* Callback for session_attached_list. */
  509 static void *
  510 format_cb_session_attached_list(struct format_tree *ft)
  511 {
  512     struct session  *s = ft->s;
  513     struct client   *loop;
  514     struct evbuffer *buffer;
  515     int      size;
  516     char        *value = NULL;
  517 
  518     if (s == NULL)
  519         return (NULL);
  520 
  521     buffer = evbuffer_new();
  522     if (buffer == NULL)
  523         fatalx("out of memory");
  524 
  525     TAILQ_FOREACH(loop, &clients, entry) {
  526         if (loop->session == s) {
  527             if (EVBUFFER_LENGTH(buffer) > 0)
  528                 evbuffer_add(buffer, ",", 1);
  529             evbuffer_add_printf(buffer, "%s", loop->name);
  530         }
  531     }
  532 
  533     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
  534         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
  535     evbuffer_free(buffer);
  536     return (value);
  537 }
  538 
  539 /* Callback for session_alerts. */
  540 static void *
  541 format_cb_session_alerts(struct format_tree *ft)
  542 {
  543     struct session  *s = ft->s;
  544     struct winlink  *wl;
  545     char         alerts[1024], tmp[16];
  546 
  547     if (s == NULL)
  548         return (NULL);
  549 
  550     *alerts = '\0';
  551     RB_FOREACH(wl, winlinks, &s->windows) {
  552         if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
  553             continue;
  554         xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
  555 
  556         if (*alerts != '\0')
  557             strlcat(alerts, ",", sizeof alerts);
  558         strlcat(alerts, tmp, sizeof alerts);
  559         if (wl->flags & WINLINK_ACTIVITY)
  560             strlcat(alerts, "#", sizeof alerts);
  561         if (wl->flags & WINLINK_BELL)
  562             strlcat(alerts, "!", sizeof alerts);
  563         if (wl->flags & WINLINK_SILENCE)
  564             strlcat(alerts, "~", sizeof alerts);
  565     }
  566     return (xstrdup(alerts));
  567 }
  568 
  569 /* Callback for session_stack. */
  570 static void *
  571 format_cb_session_stack(struct format_tree *ft)
  572 {
  573     struct session  *s = ft->s;
  574     struct winlink  *wl;
  575     char         result[1024], tmp[16];
  576 
  577     if (s == NULL)
  578         return (NULL);
  579 
  580     xsnprintf(result, sizeof result, "%u", s->curw->idx);
  581     TAILQ_FOREACH(wl, &s->lastw, sentry) {
  582         xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
  583 
  584         if (*result != '\0')
  585             strlcat(result, ",", sizeof result);
  586         strlcat(result, tmp, sizeof result);
  587     }
  588     return (xstrdup(result));
  589 }
  590 
  591 /* Callback for window_stack_index. */
  592 static void *
  593 format_cb_window_stack_index(struct format_tree *ft)
  594 {
  595     struct session  *s;
  596     struct winlink  *wl;
  597     u_int        idx;
  598     char        *value = NULL;
  599 
  600     if (ft->wl == NULL)
  601         return (NULL);
  602     s = ft->wl->session;
  603 
  604     idx = 0;
  605     TAILQ_FOREACH(wl, &s->lastw, sentry) {
  606         idx++;
  607         if (wl == ft->wl)
  608             break;
  609     }
  610     if (wl == NULL)
  611         return (xstrdup("0"));
  612     xasprintf(&value, "%u", idx);
  613     return (value);
  614 }
  615 
  616 /* Callback for window_linked_sessions_list. */
  617 static void *
  618 format_cb_window_linked_sessions_list(struct format_tree *ft)
  619 {
  620     struct window   *w;
  621     struct winlink  *wl;
  622     struct evbuffer *buffer;
  623     int      size;
  624     char        *value = NULL;
  625 
  626     if (ft->wl == NULL)
  627         return (NULL);
  628     w = ft->wl->window;
  629 
  630     buffer = evbuffer_new();
  631     if (buffer == NULL)
  632         fatalx("out of memory");
  633 
  634     TAILQ_FOREACH(wl, &w->winlinks, wentry) {
  635         if (EVBUFFER_LENGTH(buffer) > 0)
  636             evbuffer_add(buffer, ",", 1);
  637         evbuffer_add_printf(buffer, "%s", wl->session->name);
  638     }
  639 
  640     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
  641         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
  642     evbuffer_free(buffer);
  643     return (value);
  644 }
  645 
  646 /* Callback for window_active_sessions. */
  647 static void *
  648 format_cb_window_active_sessions(struct format_tree *ft)
  649 {
  650     struct window   *w;
  651     struct winlink  *wl;
  652     u_int        n = 0;
  653     char        *value;
  654 
  655     if (ft->wl == NULL)
  656         return (NULL);
  657     w = ft->wl->window;
  658 
  659     TAILQ_FOREACH(wl, &w->winlinks, wentry) {
  660         if (wl->session->curw == wl)
  661             n++;
  662     }
  663 
  664     xasprintf(&value, "%u", n);
  665     return (value);
  666 }
  667 
  668 /* Callback for window_active_sessions_list. */
  669 static void *
  670 format_cb_window_active_sessions_list(struct format_tree *ft)
  671 {
  672     struct window   *w;
  673     struct winlink  *wl;
  674     struct evbuffer *buffer;
  675     int      size;
  676     char        *value = NULL;
  677 
  678     if (ft->wl == NULL)
  679         return (NULL);
  680     w = ft->wl->window;
  681 
  682     buffer = evbuffer_new();
  683     if (buffer == NULL)
  684         fatalx("out of memory");
  685 
  686     TAILQ_FOREACH(wl, &w->winlinks, wentry) {
  687         if (wl->session->curw == wl) {
  688             if (EVBUFFER_LENGTH(buffer) > 0)
  689                 evbuffer_add(buffer, ",", 1);
  690             evbuffer_add_printf(buffer, "%s", wl->session->name);
  691         }
  692     }
  693 
  694     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
  695         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
  696     evbuffer_free(buffer);
  697     return (value);
  698 }
  699 
  700 /* Callback for window_active_clients. */
  701 static void *
  702 format_cb_window_active_clients(struct format_tree *ft)
  703 {
  704     struct window   *w;
  705     struct client   *loop;
  706     struct session  *client_session;
  707     u_int        n = 0;
  708     char        *value;
  709 
  710     if (ft->wl == NULL)
  711         return (NULL);
  712     w = ft->wl->window;
  713 
  714     TAILQ_FOREACH(loop, &clients, entry) {
  715         client_session = loop->session;
  716         if (client_session == NULL)
  717             continue;
  718 
  719         if (w == client_session->curw->window)
  720             n++;
  721     }
  722 
  723     xasprintf(&value, "%u", n);
  724     return (value);
  725 }
  726 
  727 /* Callback for window_active_clients_list. */
  728 static void *
  729 format_cb_window_active_clients_list(struct format_tree *ft)
  730 {
  731     struct window   *w;
  732     struct client   *loop;
  733     struct session  *client_session;
  734     struct evbuffer *buffer;
  735     int      size;
  736     char        *value = NULL;
  737 
  738     if (ft->wl == NULL)
  739         return (NULL);
  740     w = ft->wl->window;
  741 
  742     buffer = evbuffer_new();
  743     if (buffer == NULL)
  744         fatalx("out of memory");
  745 
  746     TAILQ_FOREACH(loop, &clients, entry) {
  747         client_session = loop->session;
  748         if (client_session == NULL)
  749             continue;
  750 
  751         if (w == client_session->curw->window) {
  752             if (EVBUFFER_LENGTH(buffer) > 0)
  753                 evbuffer_add(buffer, ",", 1);
  754             evbuffer_add_printf(buffer, "%s", loop->name);
  755         }
  756     }
  757 
  758     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
  759         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
  760     evbuffer_free(buffer);
  761     return (value);
  762 }
  763 
  764 /* Callback for window_layout. */
  765 static void *
  766 format_cb_window_layout(struct format_tree *ft)
  767 {
  768     struct window   *w = ft->w;
  769 
  770     if (w == NULL)
  771         return (NULL);
  772 
  773     if (w->saved_layout_root != NULL)
  774         return (layout_dump(w->saved_layout_root));
  775     return (layout_dump(w->layout_root));
  776 }
  777 
  778 /* Callback for window_visible_layout. */
  779 static void *
  780 format_cb_window_visible_layout(struct format_tree *ft)
  781 {
  782     struct window   *w = ft->w;
  783 
  784     if (w == NULL)
  785         return (NULL);
  786 
  787     return (layout_dump(w->layout_root));
  788 }
  789 
  790 /* Callback for pane_start_command. */
  791 static void *
  792 format_cb_start_command(struct format_tree *ft)
  793 {
  794     struct window_pane  *wp = ft->wp;
  795 
  796     if (wp == NULL)
  797         return (NULL);
  798 
  799     return (cmd_stringify_argv(wp->argc, wp->argv));
  800 }
  801 
  802 /* Callback for pane_current_command. */
  803 static void *
  804 format_cb_current_command(struct format_tree *ft)
  805 {
  806     struct window_pane  *wp = ft->wp;
  807     char            *cmd, *value;
  808 
  809     if (wp == NULL || wp->shell == NULL)
  810         return (NULL);
  811 
  812     cmd = osdep_get_name(wp->fd, wp->tty);
  813     if (cmd == NULL || *cmd == '\0') {
  814         free(cmd);
  815         cmd = cmd_stringify_argv(wp->argc, wp->argv);
  816         if (cmd == NULL || *cmd == '\0') {
  817             free(cmd);
  818             cmd = xstrdup(wp->shell);
  819         }
  820     }
  821     value = parse_window_name(cmd);
  822     free(cmd);
  823     return (value);
  824 }
  825 
  826 /* Callback for pane_current_path. */
  827 static void *
  828 format_cb_current_path(struct format_tree *ft)
  829 {
  830     struct window_pane  *wp = ft->wp;
  831     char            *cwd;
  832 
  833     if (wp == NULL)
  834         return (NULL);
  835 
  836     cwd = osdep_get_cwd(wp->fd);
  837     if (cwd == NULL)
  838         return (NULL);
  839     return (xstrdup(cwd));
  840 }
  841 
  842 /* Callback for history_bytes. */
  843 static void *
  844 format_cb_history_bytes(struct format_tree *ft)
  845 {
  846     struct window_pane  *wp = ft->wp;
  847     struct grid     *gd;
  848     struct grid_line    *gl;
  849     size_t               size = 0;
  850     u_int            i;
  851     char            *value;
  852 
  853     if (wp == NULL)
  854         return (NULL);
  855     gd = wp->base.grid;
  856 
  857     for (i = 0; i < gd->hsize + gd->sy; i++) {
  858         gl = grid_get_line(gd, i);
  859         size += gl->cellsize * sizeof *gl->celldata;
  860         size += gl->extdsize * sizeof *gl->extddata;
  861     }
  862     size += (gd->hsize + gd->sy) * sizeof *gl;
  863 
  864     xasprintf(&value, "%zu", size);
  865     return (value);
  866 }
  867 
  868 /* Callback for history_all_bytes. */
  869 static void *
  870 format_cb_history_all_bytes(struct format_tree *ft)
  871 {
  872     struct window_pane  *wp = ft->wp;
  873     struct grid     *gd;
  874     struct grid_line    *gl;
  875     u_int            i, lines, cells = 0, extended_cells = 0;
  876     char            *value;
  877 
  878     if (wp == NULL)
  879         return (NULL);
  880     gd = wp->base.grid;
  881 
  882     lines = gd->hsize + gd->sy;
  883     for (i = 0; i < lines; i++) {
  884         gl = grid_get_line(gd, i);
  885         cells += gl->cellsize;
  886         extended_cells += gl->extdsize;
  887     }
  888 
  889     xasprintf(&value, "%u,%zu,%u,%zu,%u,%zu", lines,
  890         lines * sizeof *gl, cells, cells * sizeof *gl->celldata,
  891         extended_cells, extended_cells * sizeof *gl->extddata);
  892     return (value);
  893 }
  894 
  895 /* Callback for pane_tabs. */
  896 static void *
  897 format_cb_pane_tabs(struct format_tree *ft)
  898 {
  899     struct window_pane  *wp = ft->wp;
  900     struct evbuffer     *buffer;
  901     u_int            i;
  902     int          size;
  903     char            *value = NULL;
  904 
  905     if (wp == NULL)
  906         return (NULL);
  907 
  908     buffer = evbuffer_new();
  909     if (buffer == NULL)
  910         fatalx("out of memory");
  911     for (i = 0; i < wp->base.grid->sx; i++) {
  912         if (!bit_test(wp->base.tabs, i))
  913             continue;
  914 
  915         if (EVBUFFER_LENGTH(buffer) > 0)
  916             evbuffer_add(buffer, ",", 1);
  917         evbuffer_add_printf(buffer, "%u", i);
  918     }
  919     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
  920         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
  921     evbuffer_free(buffer);
  922     return (value);
  923 }
  924 
  925 /* Callback for pane_fg. */
  926 static void *
  927 format_cb_pane_fg(struct format_tree *ft)
  928 {
  929     struct window_pane  *wp = ft->wp;
  930     struct grid_cell     gc;
  931 
  932     tty_default_colours(&gc, wp);
  933     return (xstrdup(colour_tostring(gc.fg)));
  934 }
  935 
  936 /* Callback for pane_bg. */
  937 static void *
  938 format_cb_pane_bg(struct format_tree *ft)
  939 {
  940     struct window_pane  *wp = ft->wp;
  941     struct grid_cell     gc;
  942 
  943     tty_default_colours(&gc, wp);
  944     return (xstrdup(colour_tostring(gc.bg)));
  945 }
  946 
  947 /* Callback for session_group_list. */
  948 static void *
  949 format_cb_session_group_list(struct format_tree *ft)
  950 {
  951     struct session      *s = ft->s;
  952     struct session_group    *sg;
  953     struct session      *loop;
  954     struct evbuffer     *buffer;
  955     int          size;
  956     char            *value = NULL;
  957 
  958     if (s == NULL)
  959         return (NULL);
  960     sg = session_group_contains(s);
  961     if (sg == NULL)
  962         return (NULL);
  963 
  964     buffer = evbuffer_new();
  965     if (buffer == NULL)
  966         fatalx("out of memory");
  967 
  968     TAILQ_FOREACH(loop, &sg->sessions, gentry) {
  969         if (EVBUFFER_LENGTH(buffer) > 0)
  970             evbuffer_add(buffer, ",", 1);
  971         evbuffer_add_printf(buffer, "%s", loop->name);
  972     }
  973 
  974     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
  975         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
  976     evbuffer_free(buffer);
  977     return (value);
  978 }
  979 
  980 /* Callback for session_group_attached_list. */
  981 static void *
  982 format_cb_session_group_attached_list(struct format_tree *ft)
  983 {
  984     struct session      *s = ft->s, *client_session, *session_loop;
  985     struct session_group    *sg;
  986     struct client       *loop;
  987     struct evbuffer     *buffer;
  988     int          size;
  989     char            *value = NULL;
  990 
  991     if (s == NULL)
  992         return (NULL);
  993     sg = session_group_contains(s);
  994     if (sg == NULL)
  995         return (NULL);
  996 
  997     buffer = evbuffer_new();
  998     if (buffer == NULL)
  999         fatalx("out of memory");
 1000 
 1001     TAILQ_FOREACH(loop, &clients, entry) {
 1002         client_session = loop->session;
 1003         if (client_session == NULL)
 1004             continue;
 1005         TAILQ_FOREACH(session_loop, &sg->sessions, gentry) {
 1006             if (session_loop == client_session){
 1007                 if (EVBUFFER_LENGTH(buffer) > 0)
 1008                     evbuffer_add(buffer, ",", 1);
 1009                 evbuffer_add_printf(buffer, "%s", loop->name);
 1010             }
 1011         }
 1012     }
 1013 
 1014     if ((size = EVBUFFER_LENGTH(buffer)) != 0)
 1015         xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
 1016     evbuffer_free(buffer);
 1017     return (value);
 1018 }
 1019 
 1020 /* Callback for pane_in_mode. */
 1021 static void *
 1022 format_cb_pane_in_mode(struct format_tree *ft)
 1023 {
 1024     struct window_pane      *wp = ft->wp;
 1025     u_int                n = 0;
 1026     struct window_mode_entry    *wme;
 1027     char                *value;
 1028 
 1029     if (wp == NULL)
 1030         return (NULL);
 1031 
 1032     TAILQ_FOREACH(wme, &wp->modes, entry)
 1033         n++;
 1034     xasprintf(&value, "%u", n);
 1035     return (value);
 1036 }
 1037 
 1038 /* Callback for pane_at_top. */
 1039 static void *
 1040 format_cb_pane_at_top(struct format_tree *ft)
 1041 {
 1042     struct window_pane  *wp = ft->wp;
 1043     struct window       *w;
 1044     int          status, flag;
 1045     char            *value;
 1046 
 1047     if (wp == NULL)
 1048         return (NULL);
 1049     w = wp->window;
 1050 
 1051     status = options_get_number(w->options, "pane-border-status");
 1052     if (status == PANE_STATUS_TOP)
 1053         flag = (wp->yoff == 1);
 1054     else
 1055         flag = (wp->yoff == 0);
 1056     xasprintf(&value, "%d", flag);
 1057     return (value);
 1058 }
 1059 
 1060 /* Callback for pane_at_bottom. */
 1061 static void *
 1062 format_cb_pane_at_bottom(struct format_tree *ft)
 1063 {
 1064     struct window_pane  *wp = ft->wp;
 1065     struct window       *w;
 1066     int          status, flag;
 1067     char            *value;
 1068 
 1069     if (wp == NULL)
 1070         return (NULL);
 1071     w = wp->window;
 1072 
 1073     status = options_get_number(w->options, "pane-border-status");
 1074     if (status == PANE_STATUS_BOTTOM)
 1075         flag = (wp->yoff + wp->sy == w->sy - 1);
 1076     else
 1077         flag = (wp->yoff + wp->sy == w->sy);
 1078     xasprintf(&value, "%d", flag);
 1079     return (value);
 1080 }
 1081 
 1082 /* Callback for cursor_character. */
 1083 static void *
 1084 format_cb_cursor_character(struct format_tree *ft)
 1085 {
 1086     struct window_pane  *wp = ft->wp;
 1087     struct grid_cell     gc;
 1088     char            *value = NULL;
 1089 
 1090     if (wp == NULL)
 1091         return (NULL);
 1092 
 1093     grid_view_get_cell(wp->base.grid, wp->base.cx, wp->base.cy, &gc);
 1094     if (~gc.flags & GRID_FLAG_PADDING)
 1095         xasprintf(&value, "%.*s", (int)gc.data.size, gc.data.data);
 1096     return (value);
 1097 }
 1098 
 1099 /* Callback for mouse_word. */
 1100 static void *
 1101 format_cb_mouse_word(struct format_tree *ft)
 1102 {
 1103     struct window_pane  *wp;
 1104     struct grid     *gd;
 1105     u_int            x, y;
 1106     char            *s;
 1107 
 1108     if (!ft->m.valid)
 1109         return (NULL);
 1110     wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 1111     if (wp == NULL)
 1112         return (NULL);
 1113     if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
 1114         return (NULL);
 1115 
 1116     if (!TAILQ_EMPTY(&wp->modes)) {
 1117         if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode ||
 1118             TAILQ_FIRST(&wp->modes)->mode == &window_view_mode)
 1119             return (s = window_copy_get_word(wp, x, y));
 1120         return (NULL);
 1121     }
 1122     gd = wp->base.grid;
 1123     return (format_grid_word(gd, x, gd->hsize + y));
 1124 }
 1125 
 1126 /* Callback for mouse_line. */
 1127 static void *
 1128 format_cb_mouse_line(struct format_tree *ft)
 1129 {
 1130     struct window_pane  *wp;
 1131     struct grid     *gd;
 1132     u_int            x, y;
 1133 
 1134     if (!ft->m.valid)
 1135         return (NULL);
 1136     wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 1137     if (wp == NULL)
 1138         return (NULL);
 1139     if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
 1140         return (NULL);
 1141 
 1142     if (!TAILQ_EMPTY(&wp->modes)) {
 1143         if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode ||
 1144             TAILQ_FIRST(&wp->modes)->mode == &window_view_mode)
 1145             return (window_copy_get_line(wp, y));
 1146         return (NULL);
 1147     }
 1148     gd = wp->base.grid;
 1149     return (format_grid_line(gd, gd->hsize + y));
 1150 }
 1151 
 1152 /* Callback for alternate_on. */
 1153 static void *
 1154 format_cb_alternate_on(struct format_tree *ft)
 1155 {
 1156     if (ft->wp != NULL) {
 1157         if (ft->wp->base.saved_grid != NULL)
 1158             return (xstrdup("1"));
 1159         return (xstrdup("0"));
 1160     }
 1161     return (NULL);
 1162 }
 1163 
 1164 /* Callback for alternate_saved_x. */
 1165 static void *
 1166 format_cb_alternate_saved_x(struct format_tree *ft)
 1167 {
 1168     if (ft->wp != NULL)
 1169         return (format_printf("%u", ft->wp->base.saved_cx));
 1170     return (NULL);
 1171 }
 1172 
 1173 /* Callback for alternate_saved_y. */
 1174 static void *
 1175 format_cb_alternate_saved_y(struct format_tree *ft)
 1176 {
 1177     if (ft->wp != NULL)
 1178         return (format_printf("%u", ft->wp->base.saved_cy));
 1179     return (NULL);
 1180 }
 1181 
 1182 /* Callback for buffer_name. */
 1183 static void *
 1184 format_cb_buffer_name(struct format_tree *ft)
 1185 {
 1186     if (ft->pb != NULL)
 1187         return (xstrdup(paste_buffer_name(ft->pb)));
 1188     return (NULL);
 1189 }
 1190 
 1191 /* Callback for buffer_sample. */
 1192 static void *
 1193 format_cb_buffer_sample(struct format_tree *ft)
 1194 {
 1195     if (ft->pb != NULL)
 1196         return (paste_make_sample(ft->pb));
 1197     return (NULL);
 1198 }
 1199 
 1200 /* Callback for buffer_size. */
 1201 static void *
 1202 format_cb_buffer_size(struct format_tree *ft)
 1203 {
 1204     size_t  size;
 1205 
 1206     if (ft->pb != NULL) {
 1207         paste_buffer_data(ft->pb, &size);
 1208         return (format_printf("%zu", size));
 1209     }
 1210     return (NULL);
 1211 }
 1212 
 1213 /* Callback for client_cell_height. */
 1214 static void *
 1215 format_cb_client_cell_height(struct format_tree *ft)
 1216 {
 1217     if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED))
 1218         return (format_printf("%u", ft->c->tty.ypixel));
 1219     return (NULL);
 1220 }
 1221 
 1222 /* Callback for client_cell_width. */
 1223 static void *
 1224 format_cb_client_cell_width(struct format_tree *ft)
 1225 {
 1226     if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED))
 1227         return (format_printf("%u", ft->c->tty.xpixel));
 1228     return (NULL);
 1229 }
 1230 
 1231 /* Callback for client_control_mode. */
 1232 static void *
 1233 format_cb_client_control_mode(struct format_tree *ft)
 1234 {
 1235     if (ft->c != NULL) {
 1236         if (ft->c->flags & CLIENT_CONTROL)
 1237             return (xstrdup("1"));
 1238         return (xstrdup("0"));
 1239     }
 1240     return (NULL);
 1241 }
 1242 
 1243 /* Callback for client_discarded. */
 1244 static void *
 1245 format_cb_client_discarded(struct format_tree *ft)
 1246 {
 1247     if (ft->c != NULL)
 1248         return (format_printf("%zu", ft->c->discarded));
 1249     return (NULL);
 1250 }
 1251 
 1252 /* Callback for client_flags. */
 1253 static void *
 1254 format_cb_client_flags(struct format_tree *ft)
 1255 {
 1256     if (ft->c != NULL)
 1257         return (xstrdup(server_client_get_flags(ft->c)));
 1258     return (NULL);
 1259 }
 1260 
 1261 /* Callback for client_height. */
 1262 static void *
 1263 format_cb_client_height(struct format_tree *ft)
 1264 {
 1265     if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED))
 1266         return (format_printf("%u", ft->c->tty.sy));
 1267     return (NULL);
 1268 }
 1269 
 1270 /* Callback for client_key_table. */
 1271 static void *
 1272 format_cb_client_key_table(struct format_tree *ft)
 1273 {
 1274     if (ft->c != NULL)
 1275         return (xstrdup(ft->c->keytable->name));
 1276     return (NULL);
 1277 }
 1278 
 1279 /* Callback for client_last_session. */
 1280 static void *
 1281 format_cb_client_last_session(struct format_tree *ft)
 1282 {
 1283     if (ft->c != NULL &&
 1284         ft->c->last_session != NULL &&
 1285         session_alive(ft->c->last_session))
 1286         return (xstrdup(ft->c->last_session->name));
 1287     return (NULL);
 1288 }
 1289 
 1290 /* Callback for client_name. */
 1291 static void *
 1292 format_cb_client_name(struct format_tree *ft)
 1293 {
 1294     if (ft->c != NULL)
 1295         return (xstrdup(ft->c->name));
 1296     return (NULL);
 1297 }
 1298 
 1299 /* Callback for client_pid. */
 1300 static void *
 1301 format_cb_client_pid(struct format_tree *ft)
 1302 {
 1303     if (ft->c != NULL)
 1304         return (format_printf("%ld", (long)ft->c->pid));
 1305     return (NULL);
 1306 }
 1307 
 1308 /* Callback for client_prefix. */
 1309 static void *
 1310 format_cb_client_prefix(struct format_tree *ft)
 1311 {
 1312     const char  *name;
 1313 
 1314     if (ft->c != NULL) {
 1315         name = server_client_get_key_table(ft->c);
 1316         if (strcmp(ft->c->keytable->name, name) == 0)
 1317             return (xstrdup("0"));
 1318         return (xstrdup("1"));
 1319     }
 1320     return (NULL);
 1321 }
 1322 
 1323 /* Callback for client_readonly. */
 1324 static void *
 1325 format_cb_client_readonly(struct format_tree *ft)
 1326 {
 1327     if (ft->c != NULL) {
 1328         if (ft->c->flags & CLIENT_READONLY)
 1329             return (xstrdup("1"));
 1330         return (xstrdup("0"));
 1331     }
 1332     return (NULL);
 1333 }
 1334 
 1335 /* Callback for client_session. */
 1336 static void *
 1337 format_cb_client_session(struct format_tree *ft)
 1338 {
 1339     if (ft->c != NULL && ft->c->session != NULL)
 1340         return (xstrdup(ft->c->session->name));
 1341     return (NULL);
 1342 }
 1343 
 1344 /* Callback for client_termfeatures. */
 1345 static void *
 1346 format_cb_client_termfeatures(struct format_tree *ft)
 1347 {
 1348     if (ft->c != NULL)
 1349         return (xstrdup(tty_get_features(ft->c->term_features)));
 1350     return (NULL);
 1351 }
 1352 
 1353 /* Callback for client_termname. */
 1354 static void *
 1355 format_cb_client_termname(struct format_tree *ft)
 1356 {
 1357     if (ft->c != NULL)
 1358         return (xstrdup(ft->c->term_name));
 1359     return (NULL);
 1360 }
 1361 
 1362 /* Callback for client_termtype. */
 1363 static void *
 1364 format_cb_client_termtype(struct format_tree *ft)
 1365 {
 1366     if (ft->c != NULL) {
 1367         if (ft->c->term_type == NULL)
 1368             return (xstrdup(""));
 1369         return (xstrdup(ft->c->term_type));
 1370     }
 1371     return (NULL);
 1372 }
 1373 
 1374 /* Callback for client_tty. */
 1375 static void *
 1376 format_cb_client_tty(struct format_tree *ft)
 1377 {
 1378     if (ft->c != NULL)
 1379         return (xstrdup(ft->c->ttyname));
 1380     return (NULL);
 1381 }
 1382 
 1383 /* Callback for client_utf8. */
 1384 static void *
 1385 format_cb_client_utf8(struct format_tree *ft)
 1386 {
 1387     if (ft->c != NULL) {
 1388         if (ft->c->flags & CLIENT_UTF8)
 1389             return (xstrdup("1"));
 1390         return (xstrdup("0"));
 1391     }
 1392     return (NULL);
 1393 }
 1394 
 1395 /* Callback for client_width. */
 1396 static void *
 1397 format_cb_client_width(struct format_tree *ft)
 1398 {
 1399     if (ft->c != NULL)
 1400         return (format_printf("%u", ft->c->tty.sx));
 1401     return (NULL);
 1402 }
 1403 
 1404 /* Callback for client_written. */
 1405 static void *
 1406 format_cb_client_written(struct format_tree *ft)
 1407 {
 1408     if (ft->c != NULL)
 1409         return (format_printf("%zu", ft->c->written));
 1410     return (NULL);
 1411 }
 1412 
 1413 /* Callback for config_files. */
 1414 static void *
 1415 format_cb_config_files(__unused struct format_tree *ft)
 1416 {
 1417     char    *s = NULL;
 1418     size_t   slen = 0;
 1419     u_int    i;
 1420     size_t   n;
 1421 
 1422     for (i = 0; i < cfg_nfiles; i++) {
 1423         n = strlen(cfg_files[i]) + 1;
 1424         s = xrealloc(s, slen + n + 1);
 1425         slen += xsnprintf(s + slen, n + 1, "%s,", cfg_files[i]);
 1426     }
 1427     if (s == NULL)
 1428         return (xstrdup(""));
 1429     s[slen - 1] = '\0';
 1430     return (s);
 1431 }
 1432 
 1433 /* Callback for cursor_flag. */
 1434 static void *
 1435 format_cb_cursor_flag(struct format_tree *ft)
 1436 {
 1437     if (ft->wp != NULL) {
 1438         if (ft->wp->base.mode & MODE_CURSOR)
 1439             return (xstrdup("1"));
 1440         return (xstrdup("0"));
 1441     }
 1442     return (NULL);
 1443 }
 1444 
 1445 /* Callback for cursor_x. */
 1446 static void *
 1447 format_cb_cursor_x(struct format_tree *ft)
 1448 {
 1449     if (ft->wp != NULL)
 1450         return (format_printf("%u", ft->wp->base.cx));
 1451     return (NULL);
 1452 }
 1453 
 1454 /* Callback for cursor_y. */
 1455 static void *
 1456 format_cb_cursor_y(struct format_tree *ft)
 1457 {
 1458     if (ft->wp != NULL)
 1459         return (format_printf("%u", ft->wp->base.cy));
 1460     return (NULL);
 1461 }
 1462 
 1463 /* Callback for history_limit. */
 1464 static void *
 1465 format_cb_history_limit(struct format_tree *ft)
 1466 {
 1467     if (ft->wp != NULL)
 1468         return (format_printf("%u", ft->wp->base.grid->hlimit));
 1469     return (NULL);
 1470 }
 1471 
 1472 /* Callback for history_size. */
 1473 static void *
 1474 format_cb_history_size(struct format_tree *ft)
 1475 {
 1476     if (ft->wp != NULL)
 1477         return (format_printf("%u", ft->wp->base.grid->hsize));
 1478     return (NULL);
 1479 }
 1480 
 1481 /* Callback for insert_flag. */
 1482 static void *
 1483 format_cb_insert_flag(struct format_tree *ft)
 1484 {
 1485     if (ft->wp != NULL) {
 1486         if (ft->wp->base.mode & MODE_INSERT)
 1487             return (xstrdup("1"));
 1488         return (xstrdup("0"));
 1489     }
 1490     return (NULL);
 1491 }
 1492 
 1493 /* Callback for keypad_cursor_flag. */
 1494 static void *
 1495 format_cb_keypad_cursor_flag(struct format_tree *ft)
 1496 {
 1497     if (ft->wp != NULL) {
 1498         if (ft->wp->base.mode & MODE_KCURSOR)
 1499             return (xstrdup("1"));
 1500         return (xstrdup("0"));
 1501     }
 1502     return (NULL);
 1503 }
 1504 
 1505 /* Callback for keypad_flag. */
 1506 static void *
 1507 format_cb_keypad_flag(struct format_tree *ft)
 1508 {
 1509     if (ft->wp != NULL) {
 1510         if (ft->wp->base.mode & MODE_KKEYPAD)
 1511             return (xstrdup("1"));
 1512         return (xstrdup("0"));
 1513     }
 1514     return (NULL);
 1515 }
 1516 
 1517 /* Callback for mouse_all_flag. */
 1518 static void *
 1519 format_cb_mouse_all_flag(struct format_tree *ft)
 1520 {
 1521     if (ft->wp != NULL) {
 1522         if (ft->wp->base.mode & MODE_MOUSE_ALL)
 1523             return (xstrdup("1"));
 1524         return (xstrdup("0"));
 1525     }
 1526     return (NULL);
 1527 }
 1528 
 1529 /* Callback for mouse_any_flag. */
 1530 static void *
 1531 format_cb_mouse_any_flag(struct format_tree *ft)
 1532 {
 1533     if (ft->wp != NULL) {
 1534         if (ft->wp->base.mode & ALL_MOUSE_MODES)
 1535             return (xstrdup("1"));
 1536         return (xstrdup("0"));
 1537     }
 1538     return (NULL);
 1539 }
 1540 
 1541 /* Callback for mouse_button_flag. */
 1542 static void *
 1543 format_cb_mouse_button_flag(struct format_tree *ft)
 1544 {
 1545     if (ft->wp != NULL) {
 1546         if (ft->wp->base.mode & MODE_MOUSE_BUTTON)
 1547             return (xstrdup("1"));
 1548         return (xstrdup("0"));
 1549     }
 1550     return (NULL);
 1551 }
 1552 
 1553 /* Callback for mouse_pane. */
 1554 static void *
 1555 format_cb_mouse_pane(struct format_tree *ft)
 1556 {
 1557     struct window_pane  *wp;
 1558 
 1559     if (ft->m.valid) {
 1560         wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 1561         if (wp != NULL)
 1562             return (format_printf("%%%u", wp->id));
 1563         return (NULL);
 1564     }
 1565     return (NULL);
 1566 }
 1567 
 1568 /* Callback for mouse_sgr_flag. */
 1569 static void *
 1570 format_cb_mouse_sgr_flag(struct format_tree *ft)
 1571 {
 1572     if (ft->wp != NULL) {
 1573         if (ft->wp->base.mode & MODE_MOUSE_SGR)
 1574             return (xstrdup("1"));
 1575         return (xstrdup("0"));
 1576     }
 1577     return (NULL);
 1578 }
 1579 
 1580 /* Callback for mouse_standard_flag. */
 1581 static void *
 1582 format_cb_mouse_standard_flag(struct format_tree *ft)
 1583 {
 1584     if (ft->wp != NULL) {
 1585         if (ft->wp->base.mode & MODE_MOUSE_STANDARD)
 1586             return (xstrdup("1"));
 1587         return (xstrdup("0"));
 1588     }
 1589     return (NULL);
 1590 }
 1591 
 1592 /* Callback for mouse_utf8_flag. */
 1593 static void *
 1594 format_cb_mouse_utf8_flag(struct format_tree *ft)
 1595 {
 1596     if (ft->wp != NULL) {
 1597         if (ft->wp->base.mode & MODE_MOUSE_UTF8)
 1598             return (xstrdup("1"));
 1599         return (xstrdup("0"));
 1600     }
 1601     return (NULL);
 1602 }
 1603 
 1604 /* Callback for mouse_x. */
 1605 static void *
 1606 format_cb_mouse_x(struct format_tree *ft)
 1607 {
 1608     struct window_pane  *wp;
 1609     u_int            x, y;
 1610 
 1611     if (ft->m.valid) {
 1612         wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 1613         if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0)
 1614             return (format_printf("%u", x));
 1615         return (NULL);
 1616     }
 1617     return (NULL);
 1618 }
 1619 
 1620 /* Callback for mouse_y. */
 1621 static void *
 1622 format_cb_mouse_y(struct format_tree *ft)
 1623 {
 1624     struct window_pane  *wp;
 1625     u_int            x, y;
 1626 
 1627     if (ft->m.valid) {
 1628         wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 1629         if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0)
 1630             return (format_printf("%u", y));
 1631         return (NULL);
 1632     }
 1633     return (NULL);
 1634 }
 1635 
 1636 /* Callback for origin_flag. */
 1637 static void *
 1638 format_cb_origin_flag(struct format_tree *ft)
 1639 {
 1640     if (ft->wp != NULL) {
 1641         if (ft->wp->base.mode & MODE_ORIGIN)
 1642             return (xstrdup("1"));
 1643         return (xstrdup("0"));
 1644     }
 1645     return (NULL);
 1646 }
 1647 
 1648 /* Callback for pane_active. */
 1649 static void *
 1650 format_cb_pane_active(struct format_tree *ft)
 1651 {
 1652     if (ft->wp != NULL) {
 1653         if (ft->wp == ft->wp->window->active)
 1654             return (xstrdup("1"));
 1655         return (xstrdup("0"));
 1656     }
 1657     return (NULL);
 1658 }
 1659 
 1660 /* Callback for pane_at_left. */
 1661 static void *
 1662 format_cb_pane_at_left(struct format_tree *ft)
 1663 {
 1664     if (ft->wp != NULL) {
 1665         if (ft->wp->xoff == 0)
 1666             return (xstrdup("1"));
 1667         return (xstrdup("0"));
 1668     }
 1669     return (NULL);
 1670 }
 1671 
 1672 /* Callback for pane_at_right. */
 1673 static void *
 1674 format_cb_pane_at_right(struct format_tree *ft)
 1675 {
 1676     if (ft->wp != NULL) {
 1677         if (ft->wp->xoff + ft->wp->sx == ft->wp->window->sx)
 1678             return (xstrdup("1"));
 1679         return (xstrdup("0"));
 1680     }
 1681     return (NULL);
 1682 }
 1683 
 1684 /* Callback for pane_bottom. */
 1685 static void *
 1686 format_cb_pane_bottom(struct format_tree *ft)
 1687 {
 1688     if (ft->wp != NULL)
 1689         return (format_printf("%u", ft->wp->yoff + ft->wp->sy - 1));
 1690     return (NULL);
 1691 }
 1692 
 1693 /* Callback for pane_dead. */
 1694 static void *
 1695 format_cb_pane_dead(struct format_tree *ft)
 1696 {
 1697     if (ft->wp != NULL) {
 1698         if (ft->wp->fd == -1)
 1699             return (xstrdup("1"));
 1700         return (xstrdup("0"));
 1701     }
 1702     return (NULL);
 1703 }
 1704 
 1705 /* Callback for pane_dead_status. */
 1706 static void *
 1707 format_cb_pane_dead_status(struct format_tree *ft)
 1708 {
 1709     struct window_pane  *wp = ft->wp;
 1710 
 1711     if (wp != NULL) {
 1712         if ((wp->flags & PANE_STATUSREADY) && WIFEXITED(wp->status))
 1713             return (format_printf("%d", WEXITSTATUS(wp->status)));
 1714         return (NULL);
 1715     }
 1716     return (NULL);
 1717 }
 1718 
 1719 /* Callback for pane_format. */
 1720 static void *
 1721 format_cb_pane_format(struct format_tree *ft)
 1722 {
 1723     if (ft->type == FORMAT_TYPE_PANE)
 1724         return (xstrdup("1"));
 1725     return (xstrdup("0"));
 1726 }
 1727 
 1728 /* Callback for pane_height. */
 1729 static void *
 1730 format_cb_pane_height(struct format_tree *ft)
 1731 {
 1732     if (ft->wp != NULL)
 1733         return (format_printf("%u", ft->wp->sy));
 1734     return (NULL);
 1735 }
 1736 
 1737 /* Callback for pane_id. */
 1738 static void *
 1739 format_cb_pane_id(struct format_tree *ft)
 1740 {
 1741     if (ft->wp != NULL)
 1742         return (format_printf("%%%u", ft->wp->id));
 1743     return (NULL);
 1744 }
 1745 
 1746 /* Callback for pane_index. */
 1747 static void *
 1748 format_cb_pane_index(struct format_tree *ft)
 1749 {
 1750     u_int   idx;
 1751 
 1752     if (ft->wp != NULL && window_pane_index(ft->wp, &idx) == 0)
 1753         return (format_printf("%u", idx));
 1754     return (NULL);
 1755 }
 1756 
 1757 /* Callback for pane_input_off. */
 1758 static void *
 1759 format_cb_pane_input_off(struct format_tree *ft)
 1760 {
 1761     if (ft->wp != NULL) {
 1762         if (ft->wp->flags & PANE_INPUTOFF)
 1763             return (xstrdup("1"));
 1764         return (xstrdup("0"));
 1765     }
 1766     return (NULL);
 1767 }
 1768 
 1769 /* Callback for pane_last. */
 1770 static void *
 1771 format_cb_pane_last(struct format_tree *ft)
 1772 {
 1773     if (ft->wp != NULL) {
 1774         if (ft->wp == ft->wp->window->last)
 1775             return (xstrdup("1"));
 1776         return (xstrdup("0"));
 1777     }
 1778     return (NULL);
 1779 }
 1780 
 1781 /* Callback for pane_left. */
 1782 static void *
 1783 format_cb_pane_left(struct format_tree *ft)
 1784 {
 1785     if (ft->wp != NULL)
 1786         return (format_printf("%u", ft->wp->xoff));
 1787     return (NULL);
 1788 }
 1789 
 1790 /* Callback for pane_marked. */
 1791 static void *
 1792 format_cb_pane_marked(struct format_tree *ft)
 1793 {
 1794     if (ft->wp != NULL) {
 1795         if (server_check_marked() && marked_pane.wp == ft->wp)
 1796             return (xstrdup("1"));
 1797         return (xstrdup("0"));
 1798     }
 1799     return (NULL);
 1800 }
 1801 
 1802 /* Callback for pane_marked_set. */
 1803 static void *
 1804 format_cb_pane_marked_set(struct format_tree *ft)
 1805 {
 1806     if (ft->wp != NULL) {
 1807         if (server_check_marked())
 1808             return (xstrdup("1"));
 1809         return (xstrdup("0"));
 1810     }
 1811     return (NULL);
 1812 }
 1813 
 1814 /* Callback for pane_mode. */
 1815 static void *
 1816 format_cb_pane_mode(struct format_tree *ft)
 1817 {
 1818     struct window_mode_entry    *wme;
 1819 
 1820     if (ft->wp != NULL) {
 1821         wme = TAILQ_FIRST(&ft->wp->modes);
 1822         if (wme != NULL)
 1823             return (xstrdup(wme->mode->name));
 1824         return (NULL);
 1825     }
 1826     return (NULL);
 1827 }
 1828 
 1829 /* Callback for pane_path. */
 1830 static void *
 1831 format_cb_pane_path(struct format_tree *ft)
 1832 {
 1833     if (ft->wp != NULL) {
 1834         if (ft->wp->base.path == NULL)
 1835             return (xstrdup(""));
 1836         return (xstrdup(ft->wp->base.path));
 1837     }
 1838     return (NULL);
 1839 }
 1840 
 1841 /* Callback for pane_pid. */
 1842 static void *
 1843 format_cb_pane_pid(struct format_tree *ft)
 1844 {
 1845     if (ft->wp != NULL)
 1846         return (format_printf("%ld", (long)ft->wp->pid));
 1847     return (NULL);
 1848 }
 1849 
 1850 /* Callback for pane_pipe. */
 1851 static void *
 1852 format_cb_pane_pipe(struct format_tree *ft)
 1853 {
 1854     if (ft->wp != NULL) {
 1855         if (ft->wp->pipe_fd != -1)
 1856             return (xstrdup("1"));
 1857         return (xstrdup("0"));
 1858     }
 1859     return (NULL);
 1860 }
 1861 
 1862 /* Callback for pane_right. */
 1863 static void *
 1864 format_cb_pane_right(struct format_tree *ft)
 1865 {
 1866     if (ft->wp != NULL)
 1867         return (format_printf("%u", ft->wp->xoff + ft->wp->sx - 1));
 1868     return (NULL);
 1869 }
 1870 
 1871 /* Callback for pane_search_string. */
 1872 static void *
 1873 format_cb_pane_search_string(struct format_tree *ft)
 1874 {
 1875     if (ft->wp != NULL) {
 1876         if (ft->wp->searchstr == NULL)
 1877             return (xstrdup(""));
 1878         return (xstrdup(ft->wp->searchstr));
 1879     }
 1880     return (NULL);
 1881 }
 1882 
 1883 /* Callback for pane_synchronized. */
 1884 static void *
 1885 format_cb_pane_synchronized(struct format_tree *ft)
 1886 {
 1887     if (ft->wp != NULL) {
 1888         if (options_get_number(ft->wp->options, "synchronize-panes"))
 1889             return (xstrdup("1"));
 1890         return (xstrdup("0"));
 1891     }
 1892     return (NULL);
 1893 }
 1894 
 1895 /* Callback for pane_title. */
 1896 static void *
 1897 format_cb_pane_title(struct format_tree *ft)
 1898 {
 1899     if (ft->wp != NULL)
 1900         return (xstrdup(ft->wp->base.title));
 1901     return (NULL);
 1902 }
 1903 
 1904 /* Callback for pane_top. */
 1905 static void *
 1906 format_cb_pane_top(struct format_tree *ft)
 1907 {
 1908     if (ft->wp != NULL)
 1909         return (format_printf("%u", ft->wp->yoff));
 1910     return (NULL);
 1911 }
 1912 
 1913 /* Callback for pane_tty. */
 1914 static void *
 1915 format_cb_pane_tty(struct format_tree *ft)
 1916 {
 1917     if (ft->wp != NULL)
 1918         return (xstrdup(ft->wp->tty));
 1919     return (NULL);
 1920 }
 1921 
 1922 /* Callback for pane_width. */
 1923 static void *
 1924 format_cb_pane_width(struct format_tree *ft)
 1925 {
 1926     if (ft->wp != NULL)
 1927         return (format_printf("%u", ft->wp->sx));
 1928     return (NULL);
 1929 }
 1930 
 1931 /* Callback for scroll_region_lower. */
 1932 static void *
 1933 format_cb_scroll_region_lower(struct format_tree *ft)
 1934 {
 1935     if (ft->wp != NULL)
 1936         return (format_printf("%u", ft->wp->base.rlower));
 1937     return (NULL);
 1938 }
 1939 
 1940 /* Callback for scroll_region_upper. */
 1941 static void *
 1942 format_cb_scroll_region_upper(struct format_tree *ft)
 1943 {
 1944     if (ft->wp != NULL)
 1945         return (format_printf("%u", ft->wp->base.rupper));
 1946     return (NULL);
 1947 }
 1948 
 1949 /* Callback for session_attached. */
 1950 static void *
 1951 format_cb_session_attached(struct format_tree *ft)
 1952 {
 1953     if (ft->s != NULL)
 1954         return (format_printf("%u", ft->s->attached));
 1955     return (NULL);
 1956 }
 1957 
 1958 /* Callback for session_format. */
 1959 static void *
 1960 format_cb_session_format(struct format_tree *ft)
 1961 {
 1962     if (ft->type == FORMAT_TYPE_SESSION)
 1963         return (xstrdup("1"));
 1964     return (xstrdup("0"));
 1965 }
 1966 
 1967 /* Callback for session_group. */
 1968 static void *
 1969 format_cb_session_group(struct format_tree *ft)
 1970 {
 1971     struct session_group    *sg;
 1972 
 1973     if (ft->s != NULL && (sg = session_group_contains(ft->s)) != NULL)
 1974         return (xstrdup(sg->name));
 1975     return (NULL);
 1976 }
 1977 
 1978 /* Callback for session_group_attached. */
 1979 static void *
 1980 format_cb_session_group_attached(struct format_tree *ft)
 1981 {
 1982     struct session_group    *sg;
 1983 
 1984     if (ft->s != NULL && (sg = session_group_contains(ft->s)) != NULL)
 1985         return (format_printf("%u", session_group_attached_count (sg)));
 1986     return (NULL);
 1987 }
 1988 
 1989 /* Callback for session_group_many_attached. */
 1990 static void *
 1991 format_cb_session_group_many_attached(struct format_tree *ft)
 1992 {
 1993     struct session_group    *sg;
 1994 
 1995     if (ft->s != NULL && (sg = session_group_contains(ft->s)) != NULL) {
 1996         if (session_group_attached_count (sg) > 1)
 1997             return (xstrdup("1"));
 1998         return (xstrdup("0"));
 1999     }
 2000     return (NULL);
 2001 }
 2002 
 2003 /* Callback for session_group_size. */
 2004 static void *
 2005 format_cb_session_group_size(struct format_tree *ft)
 2006 {
 2007     struct session_group    *sg;
 2008 
 2009     if (ft->s != NULL && (sg = session_group_contains(ft->s)) != NULL)
 2010         return (format_printf("%u", session_group_count (sg)));
 2011     return (NULL);
 2012 }
 2013 
 2014 /* Callback for session_grouped. */
 2015 static void *
 2016 format_cb_session_grouped(struct format_tree *ft)
 2017 {
 2018     if (ft->s != NULL) {
 2019         if (session_group_contains(ft->s) != NULL)
 2020             return (xstrdup("1"));
 2021         return (xstrdup("0"));
 2022     }
 2023     return (NULL);
 2024 }
 2025 
 2026 /* Callback for session_id. */
 2027 static void *
 2028 format_cb_session_id(struct format_tree *ft)
 2029 {
 2030     if (ft->s != NULL)
 2031         return (format_printf("$%u", ft->s->id));
 2032     return (NULL);
 2033 }
 2034 
 2035 /* Callback for session_many_attached. */
 2036 static void *
 2037 format_cb_session_many_attached(struct format_tree *ft)
 2038 {
 2039     if (ft->s != NULL) {
 2040         if (ft->s->attached > 1)
 2041             return (xstrdup("1"));
 2042         return (xstrdup("0"));
 2043     }
 2044     return (NULL);
 2045 }
 2046 
 2047 /* Callback for session_marked. */
 2048 static void *
 2049 format_cb_session_marked(struct format_tree *ft)
 2050 {
 2051     if (ft->s != NULL) {
 2052         if (server_check_marked() && marked_pane.s == ft->s)
 2053             return (xstrdup("1"));
 2054         return (xstrdup("0"));
 2055     }
 2056     return (NULL);
 2057 }
 2058 
 2059 /* Callback for session_name. */
 2060 static void *
 2061 format_cb_session_name(struct format_tree *ft)
 2062 {
 2063     if (ft->s != NULL)
 2064         return (xstrdup(ft->s->name));
 2065     return (NULL);
 2066 }
 2067 
 2068 /* Callback for session_path. */
 2069 static void *
 2070 format_cb_session_path(struct format_tree *ft)
 2071 {
 2072     if (ft->s != NULL)
 2073         return (xstrdup(ft->s->cwd));
 2074     return (NULL);
 2075 }
 2076 
 2077 /* Callback for session_windows. */
 2078 static void *
 2079 format_cb_session_windows(struct format_tree *ft)
 2080 {
 2081     if (ft->s != NULL)
 2082         return (format_printf ("%u", winlink_count(&ft->s->windows)));
 2083     return (NULL);
 2084 }
 2085 
 2086 /* Callback for socket_path. */
 2087 static void *
 2088 format_cb_socket_path(__unused struct format_tree *ft)
 2089 {
 2090     return (xstrdup(socket_path));
 2091 }
 2092 
 2093 /* Callback for version. */
 2094 static void *
 2095 format_cb_version(__unused struct format_tree *ft)
 2096 {
 2097     return (xstrdup(getversion()));
 2098 }
 2099 
 2100 /* Callback for active_window_index. */
 2101 static void *
 2102 format_cb_active_window_index(struct format_tree *ft)
 2103 {
 2104     if (ft->s != NULL)
 2105         return (format_printf("%u", ft->s->curw->idx));
 2106     return (NULL);
 2107 }
 2108 
 2109 /* Callback for last_window_index. */
 2110 static void *
 2111 format_cb_last_window_index(struct format_tree *ft)
 2112 {
 2113     struct winlink  *wl;
 2114 
 2115     if (ft->s != NULL) {
 2116         wl = RB_MAX(winlinks, &ft->s->windows);
 2117         return (format_printf("%u", wl->idx));
 2118     }
 2119     return (NULL);
 2120 }
 2121 
 2122 /* Callback for window_active. */
 2123 static void *
 2124 format_cb_window_active(struct format_tree *ft)
 2125 {
 2126     if (ft->wl != NULL) {
 2127         if (ft->wl == ft->wl->session->curw)
 2128             return (xstrdup("1"));
 2129         return (xstrdup("0"));
 2130     }
 2131     return (NULL);
 2132 }
 2133 
 2134 /* Callback for window_activity_flag. */
 2135 static void *
 2136 format_cb_window_activity_flag(struct format_tree *ft)
 2137 {
 2138     if (ft->wl != NULL) {
 2139         if (ft->wl->flags & WINLINK_ACTIVITY)
 2140             return (xstrdup("1"));
 2141         return (xstrdup("0"));
 2142     }
 2143     return (NULL);
 2144 }
 2145 
 2146 /* Callback for window_bell_flag. */
 2147 static void *
 2148 format_cb_window_bell_flag(struct format_tree *ft)
 2149 {
 2150     if (ft->wl != NULL) {
 2151         if (ft->wl->flags & WINLINK_BELL)
 2152             return (xstrdup("1"));
 2153         return (xstrdup("0"));
 2154     }
 2155     return (NULL);
 2156 }
 2157 
 2158 /* Callback for window_bigger. */
 2159 static void *
 2160 format_cb_window_bigger(struct format_tree *ft)
 2161 {
 2162     u_int   ox, oy, sx, sy;
 2163 
 2164     if (ft->c != NULL) {
 2165         if (tty_window_offset(&ft->c->tty, &ox, &oy, &sx, &sy))
 2166             return (xstrdup("1"));
 2167         return (xstrdup("0"));
 2168     }
 2169     return (NULL);
 2170 }
 2171 
 2172 /* Callback for window_cell_height. */
 2173 static void *
 2174 format_cb_window_cell_height(struct format_tree *ft)
 2175 {
 2176     if (ft->w != NULL)
 2177         return (format_printf("%u", ft->w->ypixel));
 2178     return (NULL);
 2179 }
 2180 
 2181 /* Callback for window_cell_width. */
 2182 static void *
 2183 format_cb_window_cell_width(struct format_tree *ft)
 2184 {
 2185     if (ft->w != NULL)
 2186         return (format_printf("%u", ft->w->xpixel));
 2187     return (NULL);
 2188 }
 2189 
 2190 /* Callback for window_end_flag. */
 2191 static void *
 2192 format_cb_window_end_flag(struct format_tree *ft)
 2193 {
 2194     if (ft->wl != NULL) {
 2195         if (ft->wl == RB_MAX(winlinks, &ft->wl->session->windows))
 2196             return (xstrdup("1"));
 2197         return (xstrdup("0"));
 2198     }
 2199     return (NULL);
 2200 }
 2201 
 2202 /* Callback for window_flags. */
 2203 static void *
 2204 format_cb_window_flags(struct format_tree *ft)
 2205 {
 2206     if (ft->wl != NULL)
 2207         return (xstrdup(window_printable_flags(ft->wl, 1)));
 2208     return (NULL);
 2209 }
 2210 
 2211 /* Callback for window_format. */
 2212 static void *
 2213 format_cb_window_format(struct format_tree *ft)
 2214 {
 2215     if (ft->type == FORMAT_TYPE_WINDOW)
 2216         return (xstrdup("1"));
 2217     return (xstrdup("0"));
 2218 }
 2219 
 2220 /* Callback for window_height. */
 2221 static void *
 2222 format_cb_window_height(struct format_tree *ft)
 2223 {
 2224     if (ft->w != NULL)
 2225         return (format_printf("%u", ft->w->sy));
 2226     return (NULL);
 2227 }
 2228 
 2229 /* Callback for window_id. */
 2230 static void *
 2231 format_cb_window_id(struct format_tree *ft)
 2232 {
 2233     if (ft->w != NULL)
 2234         return (format_printf("@%u", ft->w->id));
 2235     return (NULL);
 2236 }
 2237 
 2238 /* Callback for window_index. */
 2239 static void *
 2240 format_cb_window_index(struct format_tree *ft)
 2241 {
 2242     if (ft->wl != NULL)
 2243         return (format_printf("%d", ft->wl->idx));
 2244     return (NULL);
 2245 }
 2246 
 2247 /* Callback for window_last_flag. */
 2248 static void *
 2249 format_cb_window_last_flag(struct format_tree *ft)
 2250 {
 2251     if (ft->wl != NULL) {
 2252         if (ft->wl == TAILQ_FIRST(&ft->wl->session->lastw))
 2253             return (xstrdup("1"));
 2254         return (xstrdup("0"));
 2255     }
 2256     return (NULL);
 2257 }
 2258 
 2259 /* Callback for window_linked. */
 2260 static void *
 2261 format_cb_window_linked(struct format_tree *ft)
 2262 {
 2263     if (ft->wl != NULL) {
 2264         if (session_is_linked(ft->wl->session, ft->wl->window))
 2265             return (xstrdup("1"));
 2266         return (xstrdup("0"));
 2267     }
 2268     return (NULL);
 2269 }
 2270 
 2271 /* Callback for window_linked_sessions. */
 2272 static void *
 2273 format_cb_window_linked_sessions(struct format_tree *ft)
 2274 {
 2275     if (ft->wl != NULL)
 2276         return (format_printf("%u", ft->wl->window->references));
 2277     return (NULL);
 2278 }
 2279 
 2280 /* Callback for window_marked_flag. */
 2281 static void *
 2282 format_cb_window_marked_flag(struct format_tree *ft)
 2283 {
 2284     if (ft->wl != NULL) {
 2285         if (server_check_marked() && marked_pane.wl == ft->wl)
 2286             return (xstrdup("1"));
 2287         return (xstrdup("0"));
 2288     }
 2289     return (NULL);
 2290 }
 2291 
 2292 /* Callback for window_name. */
 2293 static void *
 2294 format_cb_window_name(struct format_tree *ft)
 2295 {
 2296     if (ft->w != NULL)
 2297         return (format_printf("%s", ft->w->name));
 2298     return (NULL);
 2299 }
 2300 
 2301 /* Callback for window_offset_x. */
 2302 static void *
 2303 format_cb_window_offset_x(struct format_tree *ft)
 2304 {
 2305     u_int   ox, oy, sx, sy;
 2306 
 2307     if (ft->c != NULL) {
 2308         if (tty_window_offset(&ft->c->tty, &ox, &oy, &sx, &sy))
 2309             return (format_printf("%u", ox));
 2310         return (NULL);
 2311     }
 2312     return (NULL);
 2313 }
 2314 
 2315 /* Callback for window_offset_y. */
 2316 static void *
 2317 format_cb_window_offset_y(struct format_tree *ft)
 2318 {
 2319     u_int   ox, oy, sx, sy;
 2320 
 2321     if (ft->c != NULL) {
 2322         if (tty_window_offset(&ft->c->tty, &ox, &oy, &sx, &sy))
 2323             return (format_printf("%u", oy));
 2324         return (NULL);
 2325     }
 2326     return (NULL);
 2327 }
 2328 
 2329 /* Callback for window_panes. */
 2330 static void *
 2331 format_cb_window_panes(struct format_tree *ft)
 2332 {
 2333     if (ft->w != NULL)
 2334         return (format_printf("%u", window_count_panes(ft->w)));
 2335     return (NULL);
 2336 }
 2337 
 2338 /* Callback for window_raw_flags. */
 2339 static void *
 2340 format_cb_window_raw_flags(struct format_tree *ft)
 2341 {
 2342     if (ft->wl != NULL)
 2343         return (xstrdup(window_printable_flags(ft->wl, 0)));
 2344     return (NULL);
 2345 }
 2346 
 2347 /* Callback for window_silence_flag. */
 2348 static void *
 2349 format_cb_window_silence_flag(struct format_tree *ft)
 2350 {
 2351     if (ft->wl != NULL) {
 2352         if (ft->wl->flags & WINLINK_SILENCE)
 2353             return (xstrdup("1"));
 2354         return (xstrdup("0"));
 2355     }
 2356     return (NULL);
 2357 }
 2358 
 2359 /* Callback for window_start_flag. */
 2360 static void *
 2361 format_cb_window_start_flag(struct format_tree *ft)
 2362 {
 2363     if (ft->wl != NULL) {
 2364         if (ft->wl == RB_MIN(winlinks, &ft->wl->session->windows))
 2365             return (xstrdup("1"));
 2366         return (xstrdup("0"));
 2367     }
 2368     return (NULL);
 2369 }
 2370 
 2371 /* Callback for window_width. */
 2372 static void *
 2373 format_cb_window_width(struct format_tree *ft)
 2374 {
 2375     if (ft->w != NULL)
 2376         return (format_printf("%u", ft->w->sx));
 2377     return (NULL);
 2378 }
 2379 
 2380 /* Callback for window_zoomed_flag. */
 2381 static void *
 2382 format_cb_window_zoomed_flag(struct format_tree *ft)
 2383 {
 2384     if (ft->w != NULL) {
 2385         if (ft->w->flags & WINDOW_ZOOMED)
 2386             return (xstrdup("1"));
 2387         return (xstrdup("0"));
 2388     }
 2389     return (NULL);
 2390 }
 2391 
 2392 /* Callback for wrap_flag. */
 2393 static void *
 2394 format_cb_wrap_flag(struct format_tree *ft)
 2395 {
 2396     if (ft->wp != NULL) {
 2397         if (ft->wp->base.mode & MODE_WRAP)
 2398             return (xstrdup("1"));
 2399         return (xstrdup("0"));
 2400     }
 2401     return (NULL);
 2402 }
 2403 
 2404 /* Callback for buffer_created. */
 2405 static void *
 2406 format_cb_buffer_created(struct format_tree *ft)
 2407 {
 2408     static struct timeval    tv;
 2409 
 2410     if (ft->pb != NULL) {
 2411         timerclear(&tv);
 2412         tv.tv_sec = paste_buffer_created(ft->pb);
 2413         return (&tv);
 2414     }
 2415     return (NULL);
 2416 }
 2417 
 2418 /* Callback for client_activity. */
 2419 static void *
 2420 format_cb_client_activity(struct format_tree *ft)
 2421 {
 2422     if (ft->c != NULL)
 2423         return (&ft->c->activity_time);
 2424     return (NULL);
 2425 }
 2426 
 2427 /* Callback for client_created. */
 2428 static void *
 2429 format_cb_client_created(struct format_tree *ft)
 2430 {
 2431     if (ft->c != NULL)
 2432         return (&ft->c->creation_time);
 2433     return (NULL);
 2434 }
 2435 
 2436 /* Callback for session_activity. */
 2437 static void *
 2438 format_cb_session_activity(struct format_tree *ft)
 2439 {
 2440     if (ft->s != NULL)
 2441         return (&ft->s->activity_time);
 2442     return (NULL);
 2443 }
 2444 
 2445 /* Callback for session_created. */
 2446 static void *
 2447 format_cb_session_created(struct format_tree *ft)
 2448 {
 2449     if (ft->s != NULL)
 2450         return (&ft->s->creation_time);
 2451     return (NULL);
 2452 }
 2453 
 2454 /* Callback for session_last_attached. */
 2455 static void *
 2456 format_cb_session_last_attached(struct format_tree *ft)
 2457 {
 2458     if (ft->s != NULL)
 2459         return (&ft->s->last_attached_time);
 2460     return (NULL);
 2461 }
 2462 
 2463 /* Callback for start_time. */
 2464 static void *
 2465 format_cb_start_time(__unused struct format_tree *ft)
 2466 {
 2467     return (&start_time);
 2468 }
 2469 
 2470 /* Callback for window_activity. */
 2471 static void *
 2472 format_cb_window_activity(struct format_tree *ft)
 2473 {
 2474     if (ft->w != NULL)
 2475         return (&ft->w->activity_time);
 2476     return (NULL);
 2477 }
 2478 
 2479 /* Callback for buffer_mode_format, */
 2480 static void *
 2481 format_cb_buffer_mode_format(__unused struct format_tree *ft)
 2482 {
 2483     return (xstrdup(window_buffer_mode.default_format));
 2484 }
 2485 
 2486 /* Callback for client_mode_format, */
 2487 static void *
 2488 format_cb_client_mode_format(__unused struct format_tree *ft)
 2489 {
 2490     return (xstrdup(window_client_mode.default_format));
 2491 }
 2492 
 2493 /* Callback for tree_mode_format, */
 2494 static void *
 2495 format_cb_tree_mode_format(__unused struct format_tree *ft)
 2496 {
 2497     return (xstrdup(window_tree_mode.default_format));
 2498 }
 2499 
 2500 /* Format table type. */
 2501 enum format_table_type {
 2502     FORMAT_TABLE_STRING,
 2503     FORMAT_TABLE_TIME
 2504 };
 2505 
 2506 /* Format table entry. */
 2507 struct format_table_entry {
 2508     const char      *key;
 2509     enum format_table_type   type;
 2510     format_cb        cb;
 2511 };
 2512 
 2513 /*
 2514  * Format table. Default format variables (that are almost always in the tree
 2515  * and where the value is expanded by a callback in this file) are listed here.
 2516  * Only variables which are added by the caller go into the tree.
 2517  */
 2518 static const struct format_table_entry format_table[] = {
 2519     { "active_window_index", FORMAT_TABLE_STRING,
 2520       format_cb_active_window_index
 2521     },
 2522     { "alternate_on", FORMAT_TABLE_STRING,
 2523       format_cb_alternate_on
 2524     },
 2525     { "alternate_saved_x", FORMAT_TABLE_STRING,
 2526       format_cb_alternate_saved_x
 2527     },
 2528     { "alternate_saved_y", FORMAT_TABLE_STRING,
 2529       format_cb_alternate_saved_y
 2530     },
 2531     { "buffer_created", FORMAT_TABLE_TIME,
 2532       format_cb_buffer_created
 2533     },
 2534     { "buffer_mode_format", FORMAT_TABLE_STRING,
 2535       format_cb_buffer_mode_format
 2536     },
 2537     { "buffer_name", FORMAT_TABLE_STRING,
 2538       format_cb_buffer_name
 2539     },
 2540     { "buffer_sample", FORMAT_TABLE_STRING,
 2541       format_cb_buffer_sample
 2542     },
 2543     { "buffer_size", FORMAT_TABLE_STRING,
 2544       format_cb_buffer_size
 2545     },
 2546     { "client_activity", FORMAT_TABLE_TIME,
 2547       format_cb_client_activity
 2548     },
 2549     { "client_cell_height", FORMAT_TABLE_STRING,
 2550       format_cb_client_cell_height
 2551     },
 2552     { "client_cell_width", FORMAT_TABLE_STRING,
 2553       format_cb_client_cell_width
 2554     },
 2555     { "client_control_mode", FORMAT_TABLE_STRING,
 2556       format_cb_client_control_mode
 2557     },
 2558     { "client_created", FORMAT_TABLE_TIME,
 2559       format_cb_client_created
 2560     },
 2561     { "client_discarded", FORMAT_TABLE_STRING,
 2562       format_cb_client_discarded
 2563     },
 2564     { "client_flags", FORMAT_TABLE_STRING,
 2565       format_cb_client_flags
 2566     },
 2567     { "client_height", FORMAT_TABLE_STRING,
 2568       format_cb_client_height
 2569     },
 2570     { "client_key_table", FORMAT_TABLE_STRING,
 2571       format_cb_client_key_table
 2572     },
 2573     { "client_last_session", FORMAT_TABLE_STRING,
 2574       format_cb_client_last_session
 2575     },
 2576     { "client_mode_format", FORMAT_TABLE_STRING,
 2577       format_cb_client_mode_format
 2578     },
 2579     { "client_name", FORMAT_TABLE_STRING,
 2580       format_cb_client_name
 2581     },
 2582     { "client_pid", FORMAT_TABLE_STRING,
 2583       format_cb_client_pid
 2584     },
 2585     { "client_prefix", FORMAT_TABLE_STRING,
 2586       format_cb_client_prefix
 2587     },
 2588     { "client_readonly", FORMAT_TABLE_STRING,
 2589       format_cb_client_readonly
 2590     },
 2591     { "client_session", FORMAT_TABLE_STRING,
 2592       format_cb_client_session
 2593     },
 2594     { "client_termfeatures", FORMAT_TABLE_STRING,
 2595       format_cb_client_termfeatures
 2596     },
 2597     { "client_termname", FORMAT_TABLE_STRING,
 2598       format_cb_client_termname
 2599     },
 2600     { "client_termtype", FORMAT_TABLE_STRING,
 2601       format_cb_client_termtype
 2602     },
 2603     { "client_tty", FORMAT_TABLE_STRING,
 2604       format_cb_client_tty
 2605     },
 2606     { "client_utf8", FORMAT_TABLE_STRING,
 2607       format_cb_client_utf8
 2608     },
 2609     { "client_width", FORMAT_TABLE_STRING,
 2610       format_cb_client_width
 2611     },
 2612     { "client_written", FORMAT_TABLE_STRING,
 2613       format_cb_client_written
 2614     },
 2615     { "config_files", FORMAT_TABLE_STRING,
 2616       format_cb_config_files
 2617     },
 2618     { "cursor_character", FORMAT_TABLE_STRING,
 2619       format_cb_cursor_character
 2620     },
 2621     { "cursor_flag", FORMAT_TABLE_STRING,
 2622       format_cb_cursor_flag
 2623     },
 2624     { "cursor_x", FORMAT_TABLE_STRING,
 2625       format_cb_cursor_x
 2626     },
 2627     { "cursor_y", FORMAT_TABLE_STRING,
 2628       format_cb_cursor_y
 2629     },
 2630     { "history_all_bytes", FORMAT_TABLE_STRING,
 2631       format_cb_history_all_bytes
 2632     },
 2633     { "history_bytes", FORMAT_TABLE_STRING,
 2634       format_cb_history_bytes
 2635     },
 2636     { "history_limit", FORMAT_TABLE_STRING,
 2637       format_cb_history_limit
 2638     },
 2639     { "history_size", FORMAT_TABLE_STRING,
 2640       format_cb_history_size
 2641     },
 2642     { "host", FORMAT_TABLE_STRING,
 2643       format_cb_host
 2644     },
 2645     { "host_short", FORMAT_TABLE_STRING,
 2646       format_cb_host_short
 2647     },
 2648     { "insert_flag", FORMAT_TABLE_STRING,
 2649       format_cb_insert_flag
 2650     },
 2651     { "keypad_cursor_flag", FORMAT_TABLE_STRING,
 2652       format_cb_keypad_cursor_flag
 2653     },
 2654     { "keypad_flag", FORMAT_TABLE_STRING,
 2655       format_cb_keypad_flag
 2656     },
 2657     { "last_window_index", FORMAT_TABLE_STRING,
 2658       format_cb_last_window_index
 2659     },
 2660     { "mouse_all_flag", FORMAT_TABLE_STRING,
 2661       format_cb_mouse_all_flag
 2662     },
 2663     { "mouse_any_flag", FORMAT_TABLE_STRING,
 2664       format_cb_mouse_any_flag
 2665     },
 2666     { "mouse_button_flag", FORMAT_TABLE_STRING,
 2667       format_cb_mouse_button_flag
 2668     },
 2669     { "mouse_line", FORMAT_TABLE_STRING,
 2670       format_cb_mouse_line
 2671     },
 2672     { "mouse_pane", FORMAT_TABLE_STRING,
 2673       format_cb_mouse_pane
 2674     },
 2675     { "mouse_sgr_flag", FORMAT_TABLE_STRING,
 2676       format_cb_mouse_sgr_flag
 2677     },
 2678     { "mouse_standard_flag", FORMAT_TABLE_STRING,
 2679       format_cb_mouse_standard_flag
 2680     },
 2681     { "mouse_utf8_flag", FORMAT_TABLE_STRING,
 2682       format_cb_mouse_utf8_flag
 2683     },
 2684     { "mouse_word", FORMAT_TABLE_STRING,
 2685       format_cb_mouse_word
 2686     },
 2687     { "mouse_x", FORMAT_TABLE_STRING,
 2688       format_cb_mouse_x
 2689     },
 2690     { "mouse_y", FORMAT_TABLE_STRING,
 2691       format_cb_mouse_y
 2692     },
 2693     { "origin_flag", FORMAT_TABLE_STRING,
 2694       format_cb_origin_flag
 2695     },
 2696     { "pane_active", FORMAT_TABLE_STRING,
 2697       format_cb_pane_active
 2698     },
 2699     { "pane_at_bottom", FORMAT_TABLE_STRING,
 2700       format_cb_pane_at_bottom
 2701     },
 2702     { "pane_at_left", FORMAT_TABLE_STRING,
 2703       format_cb_pane_at_left
 2704     },
 2705     { "pane_at_right", FORMAT_TABLE_STRING,
 2706       format_cb_pane_at_right
 2707     },
 2708     { "pane_at_top", FORMAT_TABLE_STRING,
 2709       format_cb_pane_at_top
 2710     },
 2711     { "pane_bg", FORMAT_TABLE_STRING,
 2712       format_cb_pane_bg
 2713     },
 2714     { "pane_bottom", FORMAT_TABLE_STRING,
 2715       format_cb_pane_bottom
 2716     },
 2717     { "pane_current_command", FORMAT_TABLE_STRING,
 2718       format_cb_current_command
 2719     },
 2720     { "pane_current_path", FORMAT_TABLE_STRING,
 2721       format_cb_current_path
 2722     },
 2723     { "pane_dead", FORMAT_TABLE_STRING,
 2724       format_cb_pane_dead
 2725     },
 2726     { "pane_dead_status", FORMAT_TABLE_STRING,
 2727       format_cb_pane_dead_status
 2728     },
 2729     { "pane_fg", FORMAT_TABLE_STRING,
 2730       format_cb_pane_fg
 2731     },
 2732     { "pane_format", FORMAT_TABLE_STRING,
 2733       format_cb_pane_format
 2734     },
 2735     { "pane_height", FORMAT_TABLE_STRING,
 2736       format_cb_pane_height
 2737     },
 2738     { "pane_id", FORMAT_TABLE_STRING,
 2739       format_cb_pane_id
 2740     },
 2741     { "pane_in_mode", FORMAT_TABLE_STRING,
 2742       format_cb_pane_in_mode
 2743     },
 2744     { "pane_index", FORMAT_TABLE_STRING,
 2745       format_cb_pane_index
 2746     },
 2747     { "pane_input_off", FORMAT_TABLE_STRING,
 2748       format_cb_pane_input_off
 2749     },
 2750     { "pane_last", FORMAT_TABLE_STRING,
 2751       format_cb_pane_last
 2752     },
 2753     { "pane_left", FORMAT_TABLE_STRING,
 2754       format_cb_pane_left
 2755     },
 2756     { "pane_marked", FORMAT_TABLE_STRING,
 2757       format_cb_pane_marked
 2758     },
 2759     { "pane_marked_set", FORMAT_TABLE_STRING,
 2760       format_cb_pane_marked_set
 2761     },
 2762     { "pane_mode", FORMAT_TABLE_STRING,
 2763       format_cb_pane_mode
 2764     },
 2765     { "pane_path", FORMAT_TABLE_STRING,
 2766       format_cb_pane_path
 2767     },
 2768     { "pane_pid", FORMAT_TABLE_STRING,
 2769       format_cb_pane_pid
 2770     },
 2771     { "pane_pipe", FORMAT_TABLE_STRING,
 2772       format_cb_pane_pipe
 2773     },
 2774     { "pane_right", FORMAT_TABLE_STRING,
 2775       format_cb_pane_right
 2776     },
 2777     { "pane_search_string", FORMAT_TABLE_STRING,
 2778       format_cb_pane_search_string
 2779     },
 2780     { "pane_start_command", FORMAT_TABLE_STRING,
 2781       format_cb_start_command
 2782     },
 2783     { "pane_synchronized", FORMAT_TABLE_STRING,
 2784       format_cb_pane_synchronized
 2785     },
 2786     { "pane_tabs", FORMAT_TABLE_STRING,
 2787       format_cb_pane_tabs
 2788     },
 2789     { "pane_title", FORMAT_TABLE_STRING,
 2790       format_cb_pane_title
 2791     },
 2792     { "pane_top", FORMAT_TABLE_STRING,
 2793       format_cb_pane_top
 2794     },
 2795     { "pane_tty", FORMAT_TABLE_STRING,
 2796       format_cb_pane_tty
 2797     },
 2798     { "pane_width", FORMAT_TABLE_STRING,
 2799       format_cb_pane_width
 2800     },
 2801     { "pid", FORMAT_TABLE_STRING,
 2802       format_cb_pid
 2803     },
 2804     { "scroll_region_lower", FORMAT_TABLE_STRING,
 2805       format_cb_scroll_region_lower
 2806     },
 2807     { "scroll_region_upper", FORMAT_TABLE_STRING,
 2808       format_cb_scroll_region_upper
 2809     },
 2810     { "session_activity", FORMAT_TABLE_TIME,
 2811       format_cb_session_activity
 2812     },
 2813     { "session_alerts", FORMAT_TABLE_STRING,
 2814       format_cb_session_alerts
 2815     },
 2816     { "session_attached", FORMAT_TABLE_STRING,
 2817       format_cb_session_attached
 2818     },
 2819     { "session_attached_list", FORMAT_TABLE_STRING,
 2820       format_cb_session_attached_list
 2821     },
 2822     { "session_created", FORMAT_TABLE_TIME,
 2823       format_cb_session_created
 2824     },
 2825     { "session_format", FORMAT_TABLE_STRING,
 2826       format_cb_session_format
 2827     },
 2828     { "session_group", FORMAT_TABLE_STRING,
 2829       format_cb_session_group
 2830     },
 2831     { "session_group_attached", FORMAT_TABLE_STRING,
 2832       format_cb_session_group_attached
 2833     },
 2834     { "session_group_attached_list", FORMAT_TABLE_STRING,
 2835       format_cb_session_group_attached_list
 2836     },
 2837     { "session_group_list", FORMAT_TABLE_STRING,
 2838       format_cb_session_group_list
 2839     },
 2840     { "session_group_many_attached", FORMAT_TABLE_STRING,
 2841       format_cb_session_group_many_attached
 2842     },
 2843     { "session_group_size", FORMAT_TABLE_STRING,
 2844       format_cb_session_group_size
 2845     },
 2846     { "session_grouped", FORMAT_TABLE_STRING,
 2847       format_cb_session_grouped
 2848     },
 2849     { "session_id", FORMAT_TABLE_STRING,
 2850       format_cb_session_id
 2851     },
 2852     { "session_last_attached", FORMAT_TABLE_TIME,
 2853       format_cb_session_last_attached
 2854     },
 2855     { "session_many_attached", FORMAT_TABLE_STRING,
 2856       format_cb_session_many_attached
 2857     },
 2858     { "session_marked", FORMAT_TABLE_STRING,
 2859       format_cb_session_marked,
 2860     },
 2861     { "session_name", FORMAT_TABLE_STRING,
 2862       format_cb_session_name
 2863     },
 2864     { "session_path", FORMAT_TABLE_STRING,
 2865       format_cb_session_path
 2866     },
 2867     { "session_stack", FORMAT_TABLE_STRING,
 2868       format_cb_session_stack
 2869     },
 2870     { "session_windows", FORMAT_TABLE_STRING,
 2871       format_cb_session_windows
 2872     },
 2873     { "socket_path", FORMAT_TABLE_STRING,
 2874       format_cb_socket_path
 2875     },
 2876     { "start_time", FORMAT_TABLE_TIME,
 2877       format_cb_start_time
 2878     },
 2879     { "tree_mode_format", FORMAT_TABLE_STRING,
 2880       format_cb_tree_mode_format
 2881     },
 2882     { "version", FORMAT_TABLE_STRING,
 2883       format_cb_version
 2884     },
 2885     { "window_active", FORMAT_TABLE_STRING,
 2886       format_cb_window_active
 2887     },
 2888     { "window_active_clients", FORMAT_TABLE_STRING,
 2889       format_cb_window_active_clients
 2890     },
 2891     { "window_active_clients_list", FORMAT_TABLE_STRING,
 2892       format_cb_window_active_clients_list
 2893     },
 2894     { "window_active_sessions", FORMAT_TABLE_STRING,
 2895       format_cb_window_active_sessions
 2896     },
 2897     { "window_active_sessions_list", FORMAT_TABLE_STRING,
 2898       format_cb_window_active_sessions_list
 2899     },
 2900     { "window_activity", FORMAT_TABLE_TIME,
 2901       format_cb_window_activity
 2902     },
 2903     { "window_activity_flag", FORMAT_TABLE_STRING,
 2904       format_cb_window_activity_flag
 2905     },
 2906     { "window_bell_flag", FORMAT_TABLE_STRING,
 2907       format_cb_window_bell_flag
 2908     },
 2909     { "window_bigger", FORMAT_TABLE_STRING,
 2910       format_cb_window_bigger
 2911     },
 2912     { "window_cell_height", FORMAT_TABLE_STRING,
 2913       format_cb_window_cell_height
 2914     },
 2915     { "window_cell_width", FORMAT_TABLE_STRING,
 2916       format_cb_window_cell_width
 2917     },
 2918     { "window_end_flag", FORMAT_TABLE_STRING,
 2919       format_cb_window_end_flag
 2920     },
 2921     { "window_flags", FORMAT_TABLE_STRING,
 2922       format_cb_window_flags
 2923     },
 2924     { "window_format", FORMAT_TABLE_STRING,
 2925       format_cb_window_format
 2926     },
 2927     { "window_height", FORMAT_TABLE_STRING,
 2928       format_cb_window_height
 2929     },
 2930     { "window_id", FORMAT_TABLE_STRING,
 2931       format_cb_window_id
 2932     },
 2933     { "window_index", FORMAT_TABLE_STRING,
 2934       format_cb_window_index
 2935     },
 2936     { "window_last_flag", FORMAT_TABLE_STRING,
 2937       format_cb_window_last_flag
 2938     },
 2939     { "window_layout", FORMAT_TABLE_STRING,
 2940       format_cb_window_layout
 2941     },
 2942     { "window_linked", FORMAT_TABLE_STRING,
 2943       format_cb_window_linked
 2944     },
 2945     { "window_linked_sessions", FORMAT_TABLE_STRING,
 2946       format_cb_window_linked_sessions
 2947     },
 2948     { "window_linked_sessions_list", FORMAT_TABLE_STRING,
 2949       format_cb_window_linked_sessions_list
 2950     },
 2951     { "window_marked_flag", FORMAT_TABLE_STRING,
 2952       format_cb_window_marked_flag
 2953     },
 2954     { "window_name", FORMAT_TABLE_STRING,
 2955       format_cb_window_name
 2956     },
 2957     { "window_offset_x", FORMAT_TABLE_STRING,
 2958       format_cb_window_offset_x
 2959     },
 2960     { "window_offset_y", FORMAT_TABLE_STRING,
 2961       format_cb_window_offset_y
 2962     },
 2963     { "window_panes", FORMAT_TABLE_STRING,
 2964       format_cb_window_panes
 2965     },
 2966     { "window_raw_flags", FORMAT_TABLE_STRING,
 2967       format_cb_window_raw_flags
 2968     },
 2969     { "window_silence_flag", FORMAT_TABLE_STRING,
 2970       format_cb_window_silence_flag
 2971     },
 2972     { "window_stack_index", FORMAT_TABLE_STRING,
 2973       format_cb_window_stack_index
 2974     },
 2975     { "window_start_flag", FORMAT_TABLE_STRING,
 2976       format_cb_window_start_flag
 2977     },
 2978     { "window_visible_layout", FORMAT_TABLE_STRING,
 2979       format_cb_window_visible_layout
 2980     },
 2981     { "window_width", FORMAT_TABLE_STRING,
 2982       format_cb_window_width
 2983     },
 2984     { "window_zoomed_flag", FORMAT_TABLE_STRING,
 2985       format_cb_window_zoomed_flag
 2986     },
 2987     { "wrap_flag", FORMAT_TABLE_STRING,
 2988       format_cb_wrap_flag
 2989     }
 2990 };
 2991 
 2992 /* Compare format table entries. */
 2993 static int
 2994 format_table_compare(const void *key0, const void *entry0)
 2995 {
 2996     const char          *key = key0;
 2997     const struct format_table_entry *entry = entry0;
 2998 
 2999     return (strcmp(key, entry->key));
 3000 }
 3001 
 3002 /* Get a format callback. */
 3003 static struct format_table_entry *
 3004 format_table_get(const char *key)
 3005 {
 3006     return (bsearch(key, format_table, nitems(format_table),
 3007         sizeof *format_table, format_table_compare));
 3008 }
 3009 
 3010 /* Merge one format tree into another. */
 3011 void
 3012 format_merge(struct format_tree *ft, struct format_tree *from)
 3013 {
 3014     struct format_entry *fe;
 3015 
 3016     RB_FOREACH(fe, format_entry_tree, &from->tree) {
 3017         if (fe->value != NULL)
 3018             format_add(ft, fe->key, "%s", fe->value);
 3019     }
 3020 }
 3021 
 3022 /* Get format pane. */
 3023 struct window_pane *
 3024 format_get_pane(struct format_tree *ft)
 3025 {
 3026     return (ft->wp);
 3027 }
 3028 
 3029 /* Add item bits to tree. */
 3030 static void
 3031 format_create_add_item(struct format_tree *ft, struct cmdq_item *item)
 3032 {
 3033     struct key_event    *event = cmdq_get_event(item);
 3034     struct mouse_event  *m = &event->m;
 3035 
 3036     cmdq_merge_formats(item, ft);
 3037     memcpy(&ft->m, m, sizeof ft->m);
 3038 }
 3039 
 3040 /* Create a new tree. */
 3041 struct format_tree *
 3042 format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
 3043 {
 3044     struct format_tree  *ft;
 3045 
 3046     ft = xcalloc(1, sizeof *ft);
 3047     RB_INIT(&ft->tree);
 3048 
 3049     if (c != NULL) {
 3050         ft->client = c;
 3051         ft->client->references++;
 3052     }
 3053     ft->item = item;
 3054 
 3055     ft->tag = tag;
 3056     ft->flags = flags;
 3057 
 3058     if (item != NULL)
 3059         format_create_add_item(ft, item);
 3060 
 3061     return (ft);
 3062 }
 3063 
 3064 /* Free a tree. */
 3065 void
 3066 format_free(struct format_tree *ft)
 3067 {
 3068     struct format_entry *fe, *fe1;
 3069 
 3070     RB_FOREACH_SAFE(fe, format_entry_tree, &ft->tree, fe1) {
 3071         RB_REMOVE(format_entry_tree, &ft->tree, fe);
 3072         free(fe->value);
 3073         free(fe->key);
 3074         free(fe);
 3075     }
 3076 
 3077     if (ft->client != NULL)
 3078         server_client_unref(ft->client);
 3079     free(ft);
 3080 }
 3081 
 3082 /* Walk each format. */
 3083 void
 3084 format_each(struct format_tree *ft, void (*cb)(const char *, const char *,
 3085     void *), void *arg)
 3086 {
 3087     const struct format_table_entry *fte;
 3088     struct format_entry     *fe;
 3089     u_int                i;
 3090     char                 s[64];
 3091     void                *value;
 3092     struct timeval          *tv;
 3093 
 3094     for (i = 0; i < nitems(format_table); i++) {
 3095         fte = &format_table[i];
 3096 
 3097         value = fte->cb(ft);
 3098         if (value == NULL)
 3099             continue;
 3100         if (fte->type == FORMAT_TABLE_TIME) {
 3101             tv = value;
 3102             xsnprintf(s, sizeof s, "%lld", (long long)tv->tv_sec);
 3103             cb(fte->key, s, arg);
 3104         } else {
 3105             cb(fte->key, value, arg);
 3106             free(value);
 3107         }
 3108     }
 3109     RB_FOREACH(fe, format_entry_tree, &ft->tree) {
 3110         if (fe->time != 0) {
 3111             xsnprintf(s, sizeof s, "%lld", (long long)fe->time);
 3112             cb(fe->key, s, arg);
 3113         } else {
 3114             if (fe->value == NULL && fe->cb != NULL) {
 3115                 fe->value = fe->cb(ft);
 3116                 if (fe->value == NULL)
 3117                     fe->value = xstrdup("");
 3118             }
 3119             cb(fe->key, fe->value, arg);
 3120         }
 3121     }
 3122 }
 3123 
 3124 /* Add a key-value pair. */
 3125 void
 3126 format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
 3127 {
 3128     struct format_entry *fe;
 3129     struct format_entry *fe_now;
 3130     va_list          ap;
 3131 
 3132     fe = xmalloc(sizeof *fe);
 3133     fe->key = xstrdup(key);
 3134 
 3135     fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
 3136     if (fe_now != NULL) {
 3137         free(fe->key);
 3138         free(fe);
 3139         free(fe_now->value);
 3140         fe = fe_now;
 3141     }
 3142 
 3143     fe->cb = NULL;
 3144     fe->time = 0;
 3145 
 3146     va_start(ap, fmt);
 3147     xvasprintf(&fe->value, fmt, ap);
 3148     va_end(ap);
 3149 }
 3150 
 3151 /* Add a key and time. */
 3152 void
 3153 format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
 3154 {
 3155     struct format_entry *fe, *fe_now;
 3156 
 3157     fe = xmalloc(sizeof *fe);
 3158     fe->key = xstrdup(key);
 3159 
 3160     fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
 3161     if (fe_now != NULL) {
 3162         free(fe->key);
 3163         free(fe);
 3164         free(fe_now->value);
 3165         fe = fe_now;
 3166     }
 3167 
 3168     fe->cb = NULL;
 3169     fe->time = tv->tv_sec;
 3170 
 3171     fe->value = NULL;
 3172 }
 3173 
 3174 /* Add a key and function. */
 3175 void
 3176 format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
 3177 {
 3178     struct format_entry *fe;
 3179     struct format_entry *fe_now;
 3180 
 3181     fe = xmalloc(sizeof *fe);
 3182     fe->key = xstrdup(key);
 3183 
 3184     fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
 3185     if (fe_now != NULL) {
 3186         free(fe->key);
 3187         free(fe);
 3188         free(fe_now->value);
 3189         fe = fe_now;
 3190     }
 3191 
 3192     fe->cb = cb;
 3193     fe->time = 0;
 3194 
 3195     fe->value = NULL;
 3196 }
 3197 
 3198 /* Quote shell special characters in string. */
 3199 static char *
 3200 format_quote_shell(const char *s)
 3201 {
 3202     const char  *cp;
 3203     char        *out, *at;
 3204 
 3205     at = out = xmalloc(strlen(s) * 2 + 1);
 3206     for (cp = s; *cp != '\0'; cp++) {
 3207         if (strchr("|&;<>()$`\\\"'*?[# =%", *cp) != NULL)
 3208             *at++ = '\\';
 3209         *at++ = *cp;
 3210     }
 3211     *at = '\0';
 3212     return (out);
 3213 }
 3214 
 3215 /* Quote #s in string. */
 3216 static char *
 3217 format_quote_style(const char *s)
 3218 {
 3219     const char  *cp;
 3220     char        *out, *at;
 3221 
 3222     at = out = xmalloc(strlen(s) * 2 + 1);
 3223     for (cp = s; *cp != '\0'; cp++) {
 3224         if (*cp == '#')
 3225             *at++ = '#';
 3226         *at++ = *cp;
 3227     }
 3228     *at = '\0';
 3229     return (out);
 3230 }
 3231 
 3232 /* Make a prettier time. */
 3233 static char *
 3234 format_pretty_time(time_t t)
 3235 {
 3236     struct tm       now_tm, tm;
 3237     time_t      now, age;
 3238     char        s[6];
 3239 
 3240     time(&now);
 3241     if (now < t)
 3242         now = t;
 3243     age = now - t;
 3244 
 3245     localtime_r(&now, &now_tm);
 3246     localtime_r(&t, &tm);
 3247 
 3248     /* Last 24 hours. */
 3249     if (age < 24 * 3600) {
 3250         strftime(s, sizeof s, "%H:%M", &tm);
 3251         return (xstrdup(s));
 3252     }
 3253 
 3254     /* This month or last 28 days. */
 3255     if ((tm.tm_year == now_tm.tm_year && tm.tm_mon == now_tm.tm_mon) ||
 3256         age < 28 * 24 * 3600) {
 3257         strftime(s, sizeof s, "%a%d", &tm);
 3258         return (xstrdup(s));
 3259     }
 3260 
 3261     /* Last 12 months. */
 3262     if ((tm.tm_year == now_tm.tm_year && tm.tm_mon < now_tm.tm_mon) ||
 3263         (tm.tm_year == now_tm.tm_year - 1 && tm.tm_mon > now_tm.tm_mon)) {
 3264         strftime(s, sizeof s, "%d%b", &tm);
 3265         return (xstrdup(s));
 3266     }
 3267 
 3268     /* Older than that. */
 3269     strftime(s, sizeof s, "%h%y", &tm);
 3270     return (xstrdup(s));
 3271 }
 3272 
 3273 /* Find a format entry. */
 3274 static char *
 3275 format_find(struct format_tree *ft, const char *key, int modifiers,
 3276     const char *time_format)
 3277 {
 3278     struct format_table_entry   *fte;
 3279     void                *value;
 3280     struct format_entry     *fe, fe_find;
 3281     struct environ_entry        *envent;
 3282     struct options_entry        *o;
 3283     int              idx;
 3284     char                *found = NULL, *saved, s[512];
 3285     const char          *errstr;
 3286     time_t               t = 0;
 3287     struct tm            tm;
 3288 
 3289     o = options_parse_get(global_options, key, &idx, 0);
 3290     if (o == NULL && ft->wp != NULL)
 3291         o = options_parse_get(ft->wp->options, key, &idx, 0);
 3292     if (o == NULL && ft->w != NULL)
 3293         o = options_parse_get(ft->w->options, key, &idx, 0);
 3294     if (o == NULL)
 3295         o = options_parse_get(global_w_options, key, &idx, 0);
 3296     if (o == NULL && ft->s != NULL)
 3297         o = options_parse_get(ft->s->options, key, &idx, 0);
 3298     if (o == NULL)
 3299         o = options_parse_get(global_s_options, key, &idx, 0);
 3300     if (o != NULL) {
 3301         found = options_to_string(o, idx, 1);
 3302         goto found;
 3303     }
 3304 
 3305     fte = format_table_get(key);
 3306     if (fte != NULL) {
 3307         value = fte->cb(ft);
 3308         if (fte->type == FORMAT_TABLE_TIME)
 3309             t = ((struct timeval *)value)->tv_sec;
 3310         else
 3311             found = value;
 3312         goto found;
 3313     }
 3314     fe_find.key = (char *)key;
 3315     fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
 3316     if (fe != NULL) {
 3317         if (fe->time != 0) {
 3318             t = fe->time;
 3319             goto found;
 3320         }
 3321         if (fe->value == NULL && fe->cb != NULL) {
 3322             fe->value = fe->cb(ft);
 3323             if (fe->value == NULL)
 3324                 fe->value = xstrdup("");
 3325         }
 3326         found = xstrdup(fe->value);
 3327         goto found;
 3328     }
 3329 
 3330     if (~modifiers & FORMAT_TIMESTRING) {
 3331         envent = NULL;
 3332         if (ft->s != NULL)
 3333             envent = environ_find(ft->s->environ, key);
 3334         if (envent == NULL)
 3335             envent = environ_find(global_environ, key);
 3336         if (envent != NULL && envent->value != NULL) {
 3337             found = xstrdup(envent->value);
 3338             goto found;
 3339         }
 3340     }
 3341 
 3342     return (NULL);
 3343 
 3344 found:
 3345     if (modifiers & FORMAT_TIMESTRING) {
 3346         if (t == 0 && found != NULL) {
 3347             t = strtonum(found, 0, INT64_MAX, &errstr);
 3348             if (errstr != NULL)
 3349                 t = 0;
 3350             free(found);
 3351         }
 3352         if (t == 0)
 3353             return (NULL);
 3354         if (modifiers & FORMAT_PRETTY)
 3355             found = format_pretty_time(t);
 3356         else {
 3357             if (time_format != NULL) {
 3358                 localtime_r(&t, &tm);
 3359                 strftime(s, sizeof s, time_format, &tm);
 3360             } else {
 3361                 ctime_r(&t, s);
 3362                 s[strcspn(s, "\n")] = '\0';
 3363             }
 3364             found = xstrdup(s);
 3365         }
 3366         return (found);
 3367     }
 3368 
 3369     if (t != 0)
 3370         xasprintf(&found, "%lld", (long long)t);
 3371     else if (found == NULL)
 3372         return (NULL);
 3373     if (modifiers & FORMAT_BASENAME) {
 3374         saved = found;
 3375         found = xstrdup(basename(saved));
 3376         free(saved);
 3377     }
 3378     if (modifiers & FORMAT_DIRNAME) {
 3379         saved = found;
 3380         found = xstrdup(dirname(saved));
 3381         free(saved);
 3382     }
 3383     if (modifiers & FORMAT_QUOTE_SHELL) {
 3384         saved = found;
 3385         found = xstrdup(format_quote_shell(saved));
 3386         free(saved);
 3387     }
 3388     if (modifiers & FORMAT_QUOTE_STYLE) {
 3389         saved = found;
 3390         found = xstrdup(format_quote_style(saved));
 3391         free(saved);
 3392     }
 3393     return (found);
 3394 }
 3395 
 3396 /* Remove escaped characters from string. */
 3397 static char *
 3398 format_strip(const char *s)
 3399 {
 3400     char    *out, *cp;
 3401     int  brackets = 0;
 3402 
 3403     cp = out = xmalloc(strlen(s) + 1);
 3404     for (; *s != '\0'; s++) {
 3405         if (*s == '#' && s[1] == '{')
 3406             brackets++;
 3407         if (*s == '#' && strchr(",#{}:", s[1]) != NULL) {
 3408             if (brackets != 0)
 3409                 *cp++ = *s;
 3410             continue;
 3411         }
 3412         if (*s == '}')
 3413             brackets--;
 3414         *cp++ = *s;
 3415     }
 3416     *cp = '\0';
 3417     return (out);
 3418 }
 3419 
 3420 /* Skip until end. */
 3421 const char *
 3422 format_skip(const char *s, const char *end)
 3423 {
 3424     int brackets = 0;
 3425 
 3426     for (; *s != '\0'; s++) {
 3427         if (*s == '#' && s[1] == '{')
 3428             brackets++;
 3429         if (*s == '#' && strchr(",#{}:", s[1]) != NULL) {
 3430             s++;
 3431             continue;
 3432         }
 3433         if (*s == '}')
 3434             brackets--;
 3435         if (strchr(end, *s) != NULL && brackets == 0)
 3436             break;
 3437     }
 3438     if (*s == '\0')
 3439         return (NULL);
 3440     return (s);
 3441 }
 3442 
 3443 /* Return left and right alternatives separated by commas. */
 3444 static int
 3445 format_choose(struct format_expand_state *es, const char *s, char **left,
 3446     char **right, int expand)
 3447 {
 3448     const char  *cp;
 3449     char        *left0, *right0;
 3450 
 3451     cp = format_skip(s, ",");
 3452     if (cp == NULL)
 3453         return (-1);
 3454     left0 = xstrndup(s, cp - s);
 3455     right0 = xstrdup(cp + 1);
 3456 
 3457     if (expand) {
 3458         *left = format_expand1(es, left0);
 3459         free(left0);
 3460         *right = format_expand1(es, right0);
 3461         free(right0);
 3462     } else {
 3463         *left = left0;
 3464         *right = right0;
 3465     }
 3466     return (0);
 3467 }
 3468 
 3469 /* Is this true? */
 3470 int
 3471 format_true(const char *s)
 3472 {
 3473     if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0'))
 3474         return (1);
 3475     return (0);
 3476 }
 3477 
 3478 /* Check if modifier end. */
 3479 static int
 3480 format_is_end(char c)
 3481 {
 3482     return (c == ';' || c == ':');
 3483 }
 3484 
 3485 /* Add to modifier list. */
 3486 static void
 3487 format_add_modifier(struct format_modifier **list, u_int *count,
 3488     const char *c, size_t n, char **argv, int argc)
 3489 {
 3490     struct format_modifier *fm;
 3491 
 3492     *list = xreallocarray(*list, (*count) + 1, sizeof **list);
 3493     fm = &(*list)[(*count)++];
 3494 
 3495     memcpy(fm->modifier, c, n);
 3496     fm->modifier[n] = '\0';
 3497     fm->size = n;
 3498 
 3499     fm->argv = argv;
 3500     fm->argc = argc;
 3501 }
 3502 
 3503 /* Free modifier list. */
 3504 static void
 3505 format_free_modifiers(struct format_modifier *list, u_int count)
 3506 {
 3507     u_int   i;
 3508 
 3509     for (i = 0; i < count; i++)
 3510         cmd_free_argv(list[i].argc, list[i].argv);
 3511     free(list);
 3512 }
 3513 
 3514 /* Build modifier list. */
 3515 static struct format_modifier *
 3516 format_build_modifiers(struct format_expand_state *es, const char **s,
 3517     u_int *count)
 3518 {
 3519     const char      *cp = *s, *end;
 3520     struct format_modifier  *list = NULL;
 3521     char             c, last[] = "X;:", **argv, *value;
 3522     int          argc;
 3523 
 3524     /*
 3525      * Modifiers are a ; separated list of the forms:
 3526      *      l,m,C,a,b,d,n,t,w,q,E,T,S,W,P,<,>
 3527      *  =a
 3528      *  =/a
 3529      *      =/a/
 3530      *  s/a/b/
 3531      *  s/a/b
 3532      *  ||,&&,!=,==,<=,>=
 3533      */
 3534 
 3535     *count = 0;
 3536 
 3537     while (*cp != '\0' && *cp != ':') {
 3538         /* Skip any separator character. */
 3539         if (*cp == ';')
 3540             cp++;
 3541 
 3542         /* Check single character modifiers with no arguments. */
 3543         if (strchr("labdnwETSWP<>", cp[0]) != NULL &&
 3544             format_is_end(cp[1])) {
 3545             format_add_modifier(&list, count, cp, 1, NULL, 0);
 3546             cp++;
 3547             continue;
 3548         }
 3549 
 3550         /* Then try double character with no arguments. */
 3551         if ((memcmp("||", cp, 2) == 0 ||
 3552             memcmp("&&", cp, 2) == 0 ||
 3553             memcmp("!=", cp, 2) == 0 ||
 3554             memcmp("==", cp, 2) == 0 ||
 3555             memcmp("<=", cp, 2) == 0 ||
 3556             memcmp(">=", cp, 2) == 0) &&
 3557             format_is_end(cp[2])) {
 3558             format_add_modifier(&list, count, cp, 2, NULL, 0);
 3559             cp += 2;
 3560             continue;
 3561         }
 3562 
 3563         /* Now try single character with arguments. */
 3564         if (strchr("mCNst=peq", cp[0]) == NULL)
 3565             break;
 3566         c = cp[0];
 3567 
 3568         /* No arguments provided. */
 3569         if (format_is_end(cp[1])) {
 3570             format_add_modifier(&list, count, cp, 1, NULL, 0);
 3571             cp++;
 3572             continue;
 3573         }
 3574         argv = NULL;
 3575         argc = 0;
 3576 
 3577         /* Single argument with no wrapper character. */
 3578         if (!ispunct(cp[1]) || cp[1] == '-') {
 3579             end = format_skip(cp + 1, ":;");
 3580             if (end == NULL)
 3581                 break;
 3582 
 3583             argv = xcalloc(1, sizeof *argv);
 3584             value = xstrndup(cp + 1, end - (cp + 1));
 3585             argv[0] = format_expand1(es, value);
 3586             free(value);
 3587             argc = 1;
 3588 
 3589             format_add_modifier(&list, count, &c, 1, argv, argc);
 3590             cp = end;
 3591             continue;
 3592         }
 3593 
 3594         /* Multiple arguments with a wrapper character. */
 3595         last[0] = cp[1];
 3596         cp++;
 3597         do {
 3598             if (cp[0] == last[0] && format_is_end(cp[1])) {
 3599                 cp++;
 3600                 break;
 3601             }
 3602             end = format_skip(cp + 1, last);
 3603             if (end == NULL)
 3604                 break;
 3605             cp++;
 3606 
 3607             argv = xreallocarray (argv, argc + 1, sizeof *argv);
 3608             value = xstrndup(cp, end - cp);
 3609             argv[argc++] = format_expand1(es, value);
 3610             free(value);
 3611 
 3612             cp = end;
 3613         } while (!format_is_end(cp[0]));
 3614         format_add_modifier(&list, count, &c, 1, argv, argc);
 3615     }
 3616     if (*cp != ':') {
 3617         format_free_modifiers(list, *count);
 3618         *count = 0;
 3619         return (NULL);
 3620     }
 3621     *s = cp + 1;
 3622     return (list);
 3623 }
 3624 
 3625 /* Match against an fnmatch(3) pattern or regular expression. */
 3626 static char *
 3627 format_match(struct format_modifier *fm, const char *pattern, const char *text)
 3628 {
 3629     const char  *s = "";
 3630     regex_t      r;
 3631     int      flags = 0;
 3632 
 3633     if (fm->argc >= 1)
 3634         s = fm->argv[0];
 3635     if (strchr(s, 'r') == NULL) {
 3636         if (strchr(s, 'i') != NULL)
 3637             flags |= FNM_CASEFOLD;
 3638         if (fnmatch(pattern, text, flags) != 0)
 3639             return (xstrdup("0"));
 3640     } else {
 3641         flags = REG_EXTENDED|REG_NOSUB;
 3642         if (strchr(s, 'i') != NULL)
 3643             flags |= REG_ICASE;
 3644         if (regcomp(&r, pattern, flags) != 0)
 3645             return (xstrdup("0"));
 3646         if (regexec(&r, text, 0, NULL, 0) != 0) {
 3647             regfree(&r);
 3648             return (xstrdup("0"));
 3649         }
 3650         regfree(&r);
 3651     }
 3652     return (xstrdup("1"));
 3653 }
 3654 
 3655 /* Perform substitution in string. */
 3656 static char *
 3657 format_sub(struct format_modifier *fm, const char *text, const char *pattern,
 3658     const char *with)
 3659 {
 3660     char    *value;
 3661     int  flags = REG_EXTENDED;
 3662 
 3663     if (fm->argc >= 3 && strchr(fm->argv[2], 'i') != NULL)
 3664         flags |= REG_ICASE;
 3665     value = regsub(pattern, with, text, flags);
 3666     if (value == NULL)
 3667         return (xstrdup(text));
 3668     return (value);
 3669 }
 3670 
 3671 /* Search inside pane. */
 3672 static char *
 3673 format_search(struct format_modifier *fm, struct window_pane *wp, const char *s)
 3674 {
 3675     int  ignore = 0, regex = 0;
 3676     char    *value;
 3677 
 3678     if (fm->argc >= 1) {
 3679         if (strchr(fm->argv[0], 'i') != NULL)
 3680             ignore = 1;
 3681         if (strchr(fm->argv[0], 'r') != NULL)
 3682             regex = 1;
 3683     }
 3684     xasprintf(&value, "%u", window_pane_search(wp, s, regex, ignore));
 3685     return (value);
 3686 }
 3687 
 3688 /* Does session name exist? */
 3689 static char *
 3690 format_session_name(struct format_expand_state *es, const char *fmt)
 3691 {
 3692     char        *name;
 3693     struct session  *s;
 3694 
 3695     name = format_expand1(es, fmt);
 3696     RB_FOREACH(s, sessions, &sessions) {
 3697         if (strcmp(s->name, name) == 0) {
 3698             free(name);
 3699             return (xstrdup("1"));
 3700         }
 3701     }
 3702     free(name);
 3703     return (xstrdup("0"));
 3704 }
 3705 
 3706 /* Loop over sessions. */
 3707 static char *
 3708 format_loop_sessions(struct format_expand_state *es, const char *fmt)
 3709 {
 3710     struct format_tree      *ft = es->ft;
 3711     struct client           *c = ft->client;
 3712     struct cmdq_item        *item = ft->item;
 3713     struct format_tree      *nft;
 3714     struct format_expand_state   next;
 3715     char                *expanded, *value;
 3716     size_t               valuelen;
 3717     struct session          *s;
 3718 
 3719     value = xcalloc(1, 1);
 3720     valuelen = 1;
 3721 
 3722     RB_FOREACH(s, sessions, &sessions) {
 3723         format_log(es, "session loop: $%u", s->id);
 3724         nft = format_create(c, item, FORMAT_NONE, ft->flags);
 3725         format_defaults(nft, ft->c, s, NULL, NULL);
 3726         format_copy_state(&next, es, 0);
 3727         next.ft = nft;
 3728         expanded = format_expand1(&next, fmt);
 3729         format_free(next.ft);
 3730 
 3731         valuelen += strlen(expanded);
 3732         value = xrealloc(value, valuelen);
 3733 
 3734         strlcat(value, expanded, valuelen);
 3735         free(expanded);
 3736     }
 3737 
 3738     return (value);
 3739 }
 3740 
 3741 /* Does window name exist? */
 3742 static char *
 3743 format_window_name(struct format_expand_state *es, const char *fmt)
 3744 {
 3745     struct format_tree  *ft = es->ft;
 3746     char            *name;
 3747     struct winlink      *wl;
 3748 
 3749     if (ft->s == NULL) {
 3750         format_log(es, "window name but no session");
 3751         return (NULL);
 3752     }
 3753 
 3754     name = format_expand1(es, fmt);
 3755     RB_FOREACH(wl, winlinks, &ft->s->windows) {
 3756         if (strcmp(wl->window->name, name) == 0) {
 3757             free(name);
 3758             return (xstrdup("1"));
 3759         }
 3760     }
 3761     free(name);
 3762     return (xstrdup("0"));
 3763 }
 3764 
 3765 /* Loop over windows. */
 3766 static char *
 3767 format_loop_windows(struct format_expand_state *es, const char *fmt)
 3768 {
 3769     struct format_tree      *ft = es->ft;
 3770     struct client           *c = ft->client;
 3771     struct cmdq_item        *item = ft->item;
 3772     struct format_tree      *nft;
 3773     struct format_expand_state   next;
 3774     char                *all, *active, *use, *expanded, *value;
 3775     size_t               valuelen;
 3776     struct winlink          *wl;
 3777     struct window           *w;
 3778 
 3779     if (ft->s == NULL) {
 3780         format_log(es, "window loop but no session");
 3781         return (NULL);
 3782     }
 3783 
 3784     if (format_choose(es, fmt, &all, &active, 0) != 0) {
 3785         all = xstrdup(fmt);
 3786         active = NULL;
 3787     }
 3788 
 3789     value = xcalloc(1, 1);
 3790     valuelen = 1;
 3791 
 3792     RB_FOREACH(wl, winlinks, &ft->s->windows) {
 3793         w = wl->window;
 3794         format_log(es, "window loop: %u @%u", wl->idx, w->id);
 3795         if (active != NULL && wl == ft->s->curw)
 3796             use = active;
 3797         else
 3798             use = all;
 3799         nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags);
 3800         format_defaults(nft, ft->c, ft->s, wl, NULL);
 3801         format_copy_state(&next, es, 0);
 3802         next.ft = nft;
 3803         expanded = format_expand1(&next, use);
 3804         format_free(nft);
 3805 
 3806         valuelen += strlen(expanded);
 3807         value = xrealloc(value, valuelen);
 3808 
 3809         strlcat(value, expanded, valuelen);
 3810         free(expanded);
 3811     }
 3812 
 3813     free(active);
 3814     free(all);
 3815 
 3816     return (value);
 3817 }
 3818 
 3819 /* Loop over panes. */
 3820 static char *
 3821 format_loop_panes(struct format_expand_state *es, const char *fmt)
 3822 {
 3823     struct format_tree      *ft = es->ft;
 3824     struct client           *c = ft->client;
 3825     struct cmdq_item        *item = ft->item;
 3826     struct format_tree      *nft;
 3827     struct format_expand_state   next;
 3828     char                *all, *active, *use, *expanded, *value;
 3829     size_t               valuelen;
 3830     struct window_pane      *wp;
 3831 
 3832     if (ft->w == NULL) {
 3833         format_log(es, "pane loop but no window");
 3834         return (NULL);
 3835     }
 3836 
 3837     if (format_choose(es, fmt, &all, &active, 0) != 0) {
 3838         all = xstrdup(fmt);
 3839         active = NULL;
 3840     }
 3841 
 3842     value = xcalloc(1, 1);
 3843     valuelen = 1;
 3844 
 3845     TAILQ_FOREACH(wp, &ft->w->panes, entry) {
 3846         format_log(es, "pane loop: %%%u", wp->id);
 3847         if (active != NULL && wp == ft->w->active)
 3848             use = active;
 3849         else
 3850             use = all;
 3851         nft = format_create(c, item, FORMAT_PANE|wp->id, ft->flags);
 3852         format_defaults(nft, ft->c, ft->s, ft->wl, wp);
 3853         format_copy_state(&next, es, 0);
 3854         next.ft = nft;
 3855         expanded = format_expand1(&next, use);
 3856         format_free(nft);
 3857 
 3858         valuelen += strlen(expanded);
 3859         value = xrealloc(value, valuelen);
 3860 
 3861         strlcat(value, expanded, valuelen);
 3862         free(expanded);
 3863     }
 3864 
 3865     free(active);
 3866     free(all);
 3867 
 3868     return (value);
 3869 }
 3870 
 3871 static char *
 3872 format_replace_expression(struct format_modifier *mexp,
 3873     struct format_expand_state *es, const char *copy)
 3874 {
 3875     int          argc = mexp->argc;
 3876     const char      *errstr;
 3877     char            *endch, *value, *left = NULL, *right = NULL;
 3878     int          use_fp = 0;
 3879     u_int            prec = 0;
 3880     double           mleft, mright, result;
 3881     enum { ADD,
 3882            SUBTRACT,
 3883            MULTIPLY,
 3884            DIVIDE,
 3885            MODULUS,
 3886            EQUAL,
 3887            NOT_EQUAL,
 3888            GREATER_THAN,
 3889            GREATER_THAN_EQUAL,
 3890            LESS_THAN,
 3891            LESS_THAN_EQUAL } operator;
 3892 
 3893     if (strcmp(mexp->argv[0], "+") == 0)
 3894         operator = ADD;
 3895     else if (strcmp(mexp->argv[0], "-") == 0)
 3896         operator = SUBTRACT;
 3897     else if (strcmp(mexp->argv[0], "*") == 0)
 3898         operator = MULTIPLY;
 3899     else if (strcmp(mexp->argv[0], "/") == 0)
 3900         operator = DIVIDE;
 3901     else if (strcmp(mexp->argv[0], "%") == 0 ||
 3902         strcmp(mexp->argv[0], "m") == 0)
 3903         operator = MODULUS;
 3904     else if (strcmp(mexp->argv[0], "==") == 0)
 3905         operator = EQUAL;
 3906     else if (strcmp(mexp->argv[0], "!=") == 0)
 3907         operator = NOT_EQUAL;
 3908     else if (strcmp(mexp->argv[0], ">") == 0)
 3909         operator = GREATER_THAN;
 3910     else if (strcmp(mexp->argv[0], "<") == 0)
 3911         operator = LESS_THAN;
 3912     else if (strcmp(mexp->argv[0], ">=") == 0)
 3913         operator = GREATER_THAN_EQUAL;
 3914     else if (strcmp(mexp->argv[0], "<=") == 0)
 3915         operator = LESS_THAN_EQUAL;
 3916     else {
 3917         format_log(es, "expression has no valid operator: '%s'",
 3918             mexp->argv[0]);
 3919         goto fail;
 3920     }
 3921 
 3922     /* The second argument may be flags. */
 3923     if (argc >= 2 && strchr(mexp->argv[1], 'f') != NULL) {
 3924         use_fp = 1;
 3925         prec = 2;
 3926     }
 3927 
 3928     /* The third argument may be precision. */
 3929     if (argc >= 3) {
 3930         prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr);
 3931         if (errstr != NULL) {
 3932             format_log(es, "expression precision %s: %s", errstr,
 3933                 mexp->argv[2]);
 3934             goto fail;
 3935         }
 3936     }
 3937 
 3938     if (format_choose(es, copy, &left, &right, 1) != 0) {
 3939         format_log(es, "expression syntax error");
 3940         goto fail;
 3941     }
 3942 
 3943     mleft = strtod(left, &endch);
 3944     if (*endch != '\0') {
 3945         format_log(es, "expression left side is invalid: %s", left);
 3946         goto fail;
 3947     }
 3948 
 3949     mright = strtod(right, &endch);
 3950     if (*endch != '\0') {
 3951         format_log(es, "expression right side is invalid: %s", right);
 3952         goto fail;
 3953     }
 3954 
 3955     if (!use_fp) {
 3956         mleft = (long long)mleft;
 3957         mright = (long long)mright;
 3958     }
 3959     format_log(es, "expression left side is: %.*f", prec, mleft);
 3960     format_log(es, "expression right side is: %.*f", prec, mright);
 3961 
 3962     switch (operator) {
 3963     case ADD:
 3964         result = mleft + mright;
 3965         break;
 3966     case SUBTRACT:
 3967         result = mleft - mright;
 3968         break;
 3969     case MULTIPLY:
 3970         result = mleft * mright;
 3971         break;
 3972     case DIVIDE:
 3973         result = mleft / mright;
 3974         break;
 3975     case MODULUS:
 3976         result = fmod(mleft, mright);
 3977         break;
 3978     case EQUAL:
 3979         result = fabs(mleft - mright) < 1e-9;
 3980         break;
 3981     case NOT_EQUAL:
 3982         result = fabs(mleft - mright) > 1e-9;
 3983         break;
 3984     case GREATER_THAN:
 3985         result = (mleft > mright);
 3986         break;
 3987     case GREATER_THAN_EQUAL:
 3988         result = (mleft >= mright);
 3989         break;
 3990     case LESS_THAN:
 3991         result = (mleft < mright);
 3992         break;
 3993     case LESS_THAN_EQUAL:
 3994         result = (mleft <= mright);
 3995         break;
 3996     }
 3997     if (use_fp)
 3998         xasprintf(&value, "%.*f", prec, result);
 3999     else
 4000         xasprintf(&value, "%.*f", prec, (double)(long long)result);
 4001     format_log(es, "expression result is %s", value);
 4002 
 4003     free(right);
 4004     free(left);
 4005     return (value);
 4006 
 4007 fail:
 4008     free(right);
 4009     free(left);
 4010     return (NULL);
 4011 }
 4012 
 4013 /* Replace a key. */
 4014 static int
 4015 format_replace(struct format_expand_state *es, const char *key, size_t keylen,
 4016     char **buf, size_t *len, size_t *off)
 4017 {
 4018     struct format_tree       *ft = es->ft;
 4019     struct window_pane       *wp = ft->wp;
 4020     const char           *errstr, *copy, *cp, *marker = NULL;
 4021     const char           *time_format = NULL;
 4022     char                 *copy0, *condition, *found, *new;
 4023     char                 *value, *left, *right, c;
 4024     size_t                valuelen;
 4025     int               modifiers = 0, limit = 0, width = 0;
 4026     int               j;
 4027     struct format_modifier       *list, *cmp = NULL, *search = NULL;
 4028     struct format_modifier      **sub = NULL, *mexp = NULL, *fm;
 4029     u_int                 i, count, nsub = 0;
 4030     struct format_expand_state    next;
 4031 
 4032     /* Make a copy of the key. */
 4033     copy = copy0 = xstrndup(key, keylen);
 4034 
 4035     /* Process modifier list. */
 4036     list = format_build_modifiers(es, &copy, &count);
 4037     for (i = 0; i < count; i++) {
 4038         fm = &list[i];
 4039         if (format_logging(ft)) {
 4040             format_log(es, "modifier %u is %s", i, fm->modifier);
 4041             for (j = 0; j < fm->argc; j++) {
 4042                 format_log(es, "modifier %u argument %d: %s", i,
 4043                     j, fm->argv[j]);
 4044             }
 4045         }
 4046         if (fm->size == 1) {
 4047             switch (fm->modifier[0]) {
 4048             case 'm':
 4049             case '<':
 4050             case '>':
 4051                 cmp = fm;
 4052                 break;
 4053             case 'C':
 4054                 search = fm;
 4055                 break;
 4056             case 's':
 4057                 if (fm->argc < 2)
 4058                     break;
 4059                 sub = xreallocarray (sub, nsub + 1,
 4060                     sizeof *sub);
 4061                 sub[nsub++] = fm;
 4062                 break;
 4063             case '=':
 4064                 if (fm->argc < 1)
 4065                     break;
 4066                 limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
 4067                     &errstr);
 4068                 if (errstr != NULL)
 4069                     limit = 0;
 4070                 if (fm->argc >= 2 && fm->argv[1] != NULL)
 4071                     marker = fm->argv[1];
 4072                 break;
 4073             case 'p':
 4074                 if (fm->argc < 1)
 4075                     break;
 4076                 width = strtonum(fm->argv[0], INT_MIN, INT_MAX,
 4077                     &errstr);
 4078                 if (errstr != NULL)
 4079                     width = 0;
 4080                 break;
 4081             case 'w':
 4082                 modifiers |= FORMAT_WIDTH;
 4083                 break;
 4084             case 'e':
 4085                 if (fm->argc < 1 || fm->argc > 3)
 4086                     break;
 4087                 mexp = fm;
 4088                 break;
 4089             case 'l':
 4090                 modifiers |= FORMAT_LITERAL;
 4091                 break;
 4092             case 'a':
 4093                 modifiers |= FORMAT_CHARACTER;
 4094                 break;
 4095             case 'b':
 4096                 modifiers |= FORMAT_BASENAME;
 4097                 break;
 4098             case 'd':
 4099                 modifiers |= FORMAT_DIRNAME;
 4100                 break;
 4101             case 'n':
 4102                 modifiers |= FORMAT_LENGTH;
 4103                 break;
 4104             case 't':
 4105                 modifiers |= FORMAT_TIMESTRING;
 4106                 if (fm->argc < 1)
 4107                     break;
 4108                 if (strchr(fm->argv[0], 'p') != NULL)
 4109                     modifiers |= FORMAT_PRETTY;
 4110                 else if (fm->argc >= 2 &&
 4111                     strchr(fm->argv[0], 'f') != NULL)
 4112                     time_format = format_strip(fm->argv[1]);
 4113                 break;
 4114             case 'q':
 4115                 if (fm->argc < 1)
 4116                     modifiers |= FORMAT_QUOTE_SHELL;
 4117                 else if (strchr(fm->argv[0], 'e') != NULL ||
 4118                     strchr(fm->argv[0], 'h') != NULL)
 4119                     modifiers |= FORMAT_QUOTE_STYLE;
 4120                 break;
 4121             case 'E':
 4122                 modifiers |= FORMAT_EXPAND;
 4123                 break;
 4124             case 'T':
 4125                 modifiers |= FORMAT_EXPANDTIME;
 4126                 break;
 4127             case 'N':
 4128                 if (fm->argc < 1 ||
 4129                     strchr(fm->argv[0], 'w') != NULL)
 4130                     modifiers |= FORMAT_WINDOW_NAME;
 4131                 else if (strchr(fm->argv[0], 's') != NULL)
 4132                     modifiers |= FORMAT_SESSION_NAME;
 4133                 break;
 4134             case 'S':
 4135                 modifiers |= FORMAT_SESSIONS;
 4136                 break;
 4137             case 'W':
 4138                 modifiers |= FORMAT_WINDOWS;
 4139                 break;
 4140             case 'P':
 4141                 modifiers |= FORMAT_PANES;
 4142                 break;
 4143             }
 4144         } else if (fm->size == 2) {
 4145             if (strcmp(fm->modifier, "||") == 0 ||
 4146                 strcmp(fm->modifier, "&&") == 0 ||
 4147                 strcmp(fm->modifier, "==") == 0 ||
 4148                 strcmp(fm->modifier, "!=") == 0 ||
 4149                 strcmp(fm->modifier, ">=") == 0 ||
 4150                 strcmp(fm->modifier, "<=") == 0)
 4151                 cmp = fm;
 4152         }
 4153     }
 4154 
 4155     /* Is this a literal string? */
 4156     if (modifiers & FORMAT_LITERAL) {
 4157         value = xstrdup(copy);
 4158         goto done;
 4159     }
 4160 
 4161     /* Is this a character? */
 4162     if (modifiers & FORMAT_CHARACTER) {
 4163         new = format_expand1(es, copy);
 4164         c = strtonum(new, 32, 126, &errstr);
 4165         if (errstr != NULL)
 4166             value = xstrdup("");
 4167         else
 4168             xasprintf(&value, "%c", c);
 4169         free (new);
 4170         goto done;
 4171     }
 4172 
 4173     /* Is this a loop, comparison or condition? */
 4174     if (modifiers & FORMAT_SESSIONS) {
 4175         value = format_loop_sessions(es, copy);
 4176         if (value == NULL)
 4177             goto fail;
 4178     } else if (modifiers & FORMAT_WINDOWS) {
 4179         value = format_loop_windows(es, copy);
 4180         if (value == NULL)
 4181             goto fail;
 4182     } else if (modifiers & FORMAT_PANES) {
 4183         value = format_loop_panes(es, copy);
 4184         if (value == NULL)
 4185             goto fail;
 4186     } else if (modifiers & FORMAT_WINDOW_NAME) {
 4187         value = format_window_name(es, copy);
 4188         if (value == NULL)
 4189             goto fail;
 4190     } else if (modifiers & FORMAT_SESSION_NAME) {
 4191         value = format_session_name(es, copy);
 4192         if (value == NULL)
 4193             goto fail;
 4194     } else if (search != NULL) {
 4195         /* Search in pane. */
 4196         new = format_expand1(es, copy);
 4197         if (wp == NULL) {
 4198             format_log(es, "search '%s' but no pane", new);
 4199             value = xstrdup("0");
 4200         } else {
 4201             format_log(es, "search '%s' pane %%%u", new, wp->id);
 4202             value = format_search(search, wp, new);
 4203         }
 4204         free(new);
 4205     } else if (cmp != NULL) {
 4206         /* Comparison of left and right. */
 4207         if (format_choose(es, copy, &left, &right, 1) != 0) {
 4208             format_log(es, "compare %s syntax error: %s",
 4209                 cmp->modifier, copy);
 4210             goto fail;
 4211         }
 4212         format_log(es, "compare %s left is: %s", cmp->modifier, left);
 4213         format_log(es, "compare %s right is: %s", cmp->modifier, right);
 4214 
 4215         if (strcmp(cmp->modifier, "||") == 0) {
 4216             if (format_true(left) || format_true(right))
 4217                 value = xstrdup("1");
 4218             else
 4219                 value = xstrdup("0");
 4220         } else if (strcmp(cmp->modifier, "&&") == 0) {
 4221             if (format_true(left) && format_true(right))
 4222                 value = xstrdup("1");
 4223             else
 4224                 value = xstrdup("0");
 4225         } else if (strcmp(cmp->modifier, "==") == 0) {
 4226             if (strcmp(left, right) == 0)
 4227                 value = xstrdup("1");
 4228             else
 4229                 value = xstrdup("0");
 4230         } else if (strcmp(cmp->modifier, "!=") == 0) {
 4231             if (strcmp(left, right) != 0)
 4232                 value = xstrdup("1");
 4233             else
 4234                 value = xstrdup("0");
 4235         } else if (strcmp(cmp->modifier, "<") == 0) {
 4236             if (strcmp(left, right) < 0)
 4237                 value = xstrdup("1");
 4238             else
 4239                 value = xstrdup("0");
 4240         } else if (strcmp(cmp->modifier, ">") == 0) {
 4241             if (strcmp(left, right) > 0)
 4242                 value = xstrdup("1");
 4243             else
 4244                 value = xstrdup("0");
 4245         } else if (strcmp(cmp->modifier, "<=") == 0) {
 4246             if (strcmp(left, right) <= 0)
 4247                 value = xstrdup("1");
 4248             else
 4249                 value = xstrdup("0");
 4250         } else if (strcmp(cmp->modifier, ">=") == 0) {
 4251             if (strcmp(left, right) >= 0)
 4252                 value = xstrdup("1");
 4253             else
 4254                 value = xstrdup("0");
 4255         } else if (strcmp(cmp->modifier, "m") == 0)
 4256             value = format_match(cmp, left, right);
 4257 
 4258         free(right);
 4259         free(left);
 4260     } else if (*copy == '?') {
 4261         /* Conditional: check first and choose second or third. */
 4262         cp = format_skip(copy + 1, ",");
 4263         if (cp == NULL) {
 4264             format_log(es, "condition syntax error: %s", copy + 1);
 4265             goto fail;
 4266         }
 4267         condition = xstrndup(copy + 1, cp - (copy + 1));
 4268         format_log(es, "condition is: %s", condition);
 4269 
 4270         found = format_find(ft, condition, modifiers, time_format);
 4271         if (found == NULL) {
 4272             /*
 4273              * If the condition not found, try to expand it. If
 4274              * the expansion doesn't have any effect, then assume
 4275              * false.
 4276              */
 4277             found = format_expand1(es, condition);
 4278             if (strcmp(found, condition) == 0) {
 4279                 free(found);
 4280                 found = xstrdup("");
 4281                 format_log(es, "condition '%s' found: %s",
 4282                     condition, found);
 4283             } else {
 4284                 format_log(es,
 4285                     "condition '%s' not found; assuming false",
 4286                     condition);
 4287             }
 4288         } else
 4289             format_log(es, "condition '%s' found", condition);
 4290 
 4291         if (format_choose(es, cp + 1, &left, &right, 0) != 0) {
 4292             format_log(es, "condition '%s' syntax error: %s",
 4293                 condition, cp + 1);
 4294             free(found);
 4295             goto fail;
 4296         }
 4297         if (format_true(found)) {
 4298             format_log(es, "condition '%s' is true", condition);
 4299             value = format_expand1(es, left);
 4300         } else {
 4301             format_log(es, "condition '%s' is false", condition);
 4302             value = format_expand1(es, right);
 4303         }
 4304         free(right);
 4305         free(left);
 4306 
 4307         free(condition);
 4308         free(found);
 4309     } else if (mexp != NULL) {
 4310         value = format_replace_expression(mexp, es, copy);
 4311         if (value == NULL)
 4312             value = xstrdup("");
 4313     } else {
 4314         if (strstr(copy, "#{") != 0) {
 4315             format_log(es, "expanding inner format '%s'", copy);
 4316             value = format_expand1(es, copy);
 4317         } else {
 4318             value = format_find(ft, copy, modifiers, time_format);
 4319             if (value == NULL) {
 4320                 format_log(es, "format '%s' not found", copy);
 4321                 value = xstrdup("");
 4322             } else {
 4323                 format_log(es, "format '%s' found: %s", copy,
 4324                     value);
 4325             }
 4326         }
 4327     }
 4328 
 4329 done:
 4330     /* Expand again if required. */
 4331     if (modifiers & FORMAT_EXPAND) {
 4332         new = format_expand1(es, value);
 4333         free(value);
 4334         value = new;
 4335     } else if (modifiers & FORMAT_EXPANDTIME) {
 4336         format_copy_state(&next, es, FORMAT_EXPAND_TIME);
 4337         new = format_expand1(&next, value);
 4338         free(value);
 4339         value = new;
 4340     }
 4341 
 4342     /* Perform substitution if any. */
 4343     for (i = 0; i < nsub; i++) {
 4344         left = format_expand1(es, sub[i]->argv[0]);
 4345         right = format_expand1(es, sub[i]->argv[1]);
 4346         new = format_sub(sub[i], value, left, right);
 4347         format_log(es, "substitute '%s' to '%s': %s", left, right, new);
 4348         free(value);
 4349         value = new;
 4350         free(right);
 4351         free(left);
 4352     }
 4353 
 4354     /* Truncate the value if needed. */
 4355     if (limit > 0) {
 4356         new = format_trim_left(value, limit);
 4357         if (marker != NULL && strcmp(new, value) != 0) {
 4358             free(value);
 4359             xasprintf(&value, "%s%s", new, marker);
 4360         } else {
 4361             free(value);
 4362             value = new;
 4363         }
 4364         format_log(es, "applied length limit %d: %s", limit, value);
 4365     } else if (limit < 0) {
 4366         new = format_trim_right(value, -limit);
 4367         if (marker != NULL && strcmp(new, value) != 0) {
 4368             free(value);
 4369             xasprintf(&value, "%s%s", marker, new);
 4370         } else {
 4371             free(value);
 4372             value = new;
 4373         }
 4374         format_log(es, "applied length limit %d: %s", limit, value);
 4375     }
 4376 
 4377     /* Pad the value if needed. */
 4378     if (width > 0) {
 4379         new = utf8_padcstr(value, width);
 4380         free(value);
 4381         value = new;
 4382         format_log(es, "applied padding width %d: %s", width, value);
 4383     } else if (width < 0) {
 4384         new = utf8_rpadcstr(value, -width);
 4385         free(value);
 4386         value = new;
 4387         format_log(es, "applied padding width %d: %s", width, value);
 4388     }
 4389 
 4390     /* Replace with the length or width if needed. */
 4391     if (modifiers & FORMAT_LENGTH) {
 4392         xasprintf(&new, "%zu", strlen(value));
 4393         free(value);
 4394         value = new;
 4395         format_log(es, "replacing with length: %s", new);
 4396     }
 4397     if (modifiers & FORMAT_WIDTH) {
 4398         xasprintf(&new, "%u", format_width(value));
 4399         free(value);
 4400         value = new;
 4401         format_log(es, "replacing with width: %s", new);
 4402     }
 4403 
 4404     /* Expand the buffer and copy in the value. */
 4405     valuelen = strlen(value);
 4406     while (*len - *off < valuelen + 1) {
 4407         *buf = xreallocarray(*buf, 2, *len);
 4408         *len *= 2;
 4409     }
 4410     memcpy(*buf + *off, value, valuelen);
 4411     *off += valuelen;
 4412 
 4413     format_log(es, "replaced '%s' with '%s'", copy0, value);
 4414     free(value);
 4415 
 4416     free(sub);
 4417     format_free_modifiers(list, count);
 4418     free(copy0);
 4419     return (0);
 4420 
 4421 fail:
 4422     format_log(es, "failed %s", copy0);
 4423 
 4424     free(sub);
 4425     format_free_modifiers(list, count);
 4426     free(copy0);
 4427     return (-1);
 4428 }
 4429 
 4430 /* Expand keys in a template. */
 4431 static char *
 4432 format_expand1(struct format_expand_state *es, const char *fmt)
 4433 {
 4434     struct format_tree  *ft = es->ft;
 4435     char            *buf, *out, *name;
 4436     const char      *ptr, *s;
 4437     size_t           off, len, n, outlen;
 4438     int              ch, brackets;
 4439     char             expanded[8192];
 4440 
 4441     if (fmt == NULL || *fmt == '\0')
 4442         return (xstrdup(""));
 4443 
 4444     if (es->loop == FORMAT_LOOP_LIMIT) {
 4445         format_log(es, "reached loop limit (%u)", FORMAT_LOOP_LIMIT);
 4446         return (xstrdup(""));
 4447     }
 4448     es->loop++;
 4449 
 4450     format_log(es, "expanding format: %s", fmt);
 4451 
 4452     if ((es->flags & FORMAT_EXPAND_TIME) && strchr(fmt, '%') != NULL) {
 4453         if (es->time == 0) {
 4454             es->time = time(NULL);
 4455             localtime_r(&es->time, &es->tm);
 4456         }
 4457         if (strftime(expanded, sizeof expanded, fmt, &es->tm) == 0) {
 4458             format_log(es, "format is too long");
 4459             return (xstrdup(""));
 4460         }
 4461         if (format_logging(ft) && strcmp(expanded, fmt) != 0)
 4462             format_log(es, "after time expanded: %s", expanded);
 4463         fmt = expanded;
 4464     }
 4465 
 4466     len = 64;
 4467     buf = xmalloc(len);
 4468     off = 0;
 4469 
 4470     while (*fmt != '\0') {
 4471         if (*fmt != '#') {
 4472             while (len - off < 2) {
 4473                 buf = xreallocarray(buf, 2, len);
 4474                 len *= 2;
 4475             }
 4476             buf[off++] = *fmt++;
 4477             continue;
 4478         }
 4479         fmt++;
 4480 
 4481         ch = (u_char)*fmt++;
 4482         switch (ch) {
 4483         case '(':
 4484             brackets = 1;
 4485             for (ptr = fmt; *ptr != '\0'; ptr++) {
 4486                 if (*ptr == '(')
 4487                     brackets++;
 4488                 if (*ptr == ')' && --brackets == 0)
 4489                     break;
 4490             }
 4491             if (*ptr != ')' || brackets != 0)
 4492                 break;
 4493             n = ptr - fmt;
 4494 
 4495             name = xstrndup(fmt, n);
 4496             format_log(es, "found #(): %s", name);
 4497 
 4498             if ((ft->flags & FORMAT_NOJOBS) ||
 4499                 (es->flags & FORMAT_EXPAND_NOJOBS)) {
 4500                 out = xstrdup("");
 4501                 format_log(es, "#() is disabled");
 4502             } else {
 4503                 out = format_job_get(es, name);
 4504                 format_log(es, "#() result: %s", out);
 4505             }
 4506             free(name);
 4507 
 4508             outlen = strlen(out);
 4509             while (len - off < outlen + 1) {
 4510                 buf = xreallocarray(buf, 2, len);
 4511                 len *= 2;
 4512             }
 4513             memcpy(buf + off, out, outlen);
 4514             off += outlen;
 4515 
 4516             free(out);
 4517 
 4518             fmt += n + 1;
 4519             continue;
 4520         case '{':
 4521             ptr = format_skip((char *)fmt - 2, "}");
 4522             if (ptr == NULL)
 4523                 break;
 4524             n = ptr - fmt;
 4525 
 4526             format_log(es, "found #{}: %.*s", (int)n, fmt);
 4527             if (format_replace(es, fmt, n, &buf, &len, &off) != 0)
 4528                 break;
 4529             fmt += n + 1;
 4530             continue;
 4531         case '#':
 4532             /*
 4533              * If ##[ (with two or more #s), then it is a style and
 4534              * can be left for format_draw to handle.
 4535              */
 4536             ptr = fmt;
 4537             n = 2;
 4538             while (*ptr == '#') {
 4539                 ptr++;
 4540                 n++;
 4541             }
 4542             if (*ptr == '[') {
 4543                 format_log(es, "found #*%zu[", n);
 4544                 while (len - off < n + 2) {
 4545                     buf = xreallocarray(buf, 2, len);
 4546                     len *= 2;
 4547                 }
 4548                 memcpy(buf + off, fmt - 2, n + 1);
 4549                 off += n + 1;
 4550                 fmt = ptr + 1;
 4551                 continue;
 4552             }
 4553             /* FALLTHROUGH */
 4554         case '}':
 4555         case ',':
 4556             format_log(es, "found #%c", ch);
 4557             while (len - off < 2) {
 4558                 buf = xreallocarray(buf, 2, len);
 4559                 len *= 2;
 4560             }
 4561             buf[off++] = ch;
 4562             continue;
 4563         default:
 4564             s = NULL;
 4565             if (ch >= 'A' && ch <= 'Z')
 4566                 s = format_upper[ch - 'A'];
 4567             else if (ch >= 'a' && ch <= 'z')
 4568                 s = format_lower[ch - 'a'];
 4569             if (s == NULL) {
 4570                 while (len - off < 3) {
 4571                     buf = xreallocarray(buf, 2, len);
 4572                     len *= 2;
 4573                 }
 4574                 buf[off++] = '#';
 4575                 buf[off++] = ch;
 4576                 continue;
 4577             }
 4578             n = strlen(s);
 4579             format_log(es, "found #%c: %s", ch, s);
 4580             if (format_replace(es, s, n, &buf, &len, &off) != 0)
 4581                 break;
 4582             continue;
 4583         }
 4584 
 4585         break;
 4586     }
 4587     buf[off] = '\0';
 4588 
 4589     format_log(es, "result is: %s", buf);
 4590     es->loop--;
 4591 
 4592     return (buf);
 4593 }
 4594 
 4595 /* Expand keys in a template, passing through strftime first. */
 4596 char *
 4597 format_expand_time(struct format_tree *ft, const char *fmt)
 4598 {
 4599     struct format_expand_state  es;
 4600 
 4601     memset(&es, 0, sizeof es);
 4602     es.ft = ft;
 4603     es.flags = FORMAT_EXPAND_TIME;
 4604     return (format_expand1(&es, fmt));
 4605 }
 4606 
 4607 /* Expand keys in a template. */
 4608 char *
 4609 format_expand(struct format_tree *ft, const char *fmt)
 4610 {
 4611     struct format_expand_state  es;
 4612 
 4613     memset(&es, 0, sizeof es);
 4614     es.ft = ft;
 4615     es.flags = 0;
 4616     return (format_expand1(&es, fmt));
 4617 }
 4618 
 4619 /* Expand a single string. */
 4620 char *
 4621 format_single(struct cmdq_item *item, const char *fmt, struct client *c,
 4622     struct session *s, struct winlink *wl, struct window_pane *wp)
 4623 {
 4624     struct format_tree  *ft;
 4625     char            *expanded;
 4626 
 4627     ft = format_create_defaults(item, c, s, wl, wp);
 4628     expanded = format_expand(ft, fmt);
 4629     format_free(ft);
 4630     return (expanded);
 4631 }
 4632 
 4633 /* Expand a single string using state. */
 4634 char *
 4635 format_single_from_state(struct cmdq_item *item, const char *fmt,
 4636     struct client *c, struct cmd_find_state *fs)
 4637 {
 4638     return (format_single(item, fmt, c, fs->s, fs->wl, fs->wp));
 4639 }
 4640 
 4641 /* Expand a single string using target. */
 4642 char *
 4643 format_single_from_target(struct cmdq_item *item, const char *fmt)
 4644 {
 4645     struct client   *tc = cmdq_get_target_client(item);
 4646 
 4647     return (format_single_from_state(item, fmt, tc, cmdq_get_target(item)));
 4648 }
 4649 
 4650 /* Create and add defaults. */
 4651 struct format_tree *
 4652 format_create_defaults(struct cmdq_item *item, struct client *c,
 4653     struct session *s, struct winlink *wl, struct window_pane *wp)
 4654 {
 4655     struct format_tree  *ft;
 4656 
 4657     if (item != NULL)
 4658         ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
 4659     else
 4660         ft = format_create(NULL, item, FORMAT_NONE, 0);
 4661     format_defaults(ft, c, s, wl, wp);
 4662     return (ft);
 4663 }
 4664 
 4665 /* Create and add defaults using state. */
 4666 struct format_tree *
 4667 format_create_from_state(struct cmdq_item *item, struct client *c,
 4668     struct cmd_find_state *fs)
 4669 {
 4670     return (format_create_defaults(item, c, fs->s, fs->wl, fs->wp));
 4671 }
 4672 
 4673 /* Create and add defaults using target. */
 4674 struct format_tree *
 4675 format_create_from_target(struct cmdq_item *item)
 4676 {
 4677     struct client   *tc = cmdq_get_target_client(item);
 4678 
 4679     return (format_create_from_state(item, tc, cmdq_get_target(item)));
 4680 }
 4681 
 4682 /* Set defaults for any of arguments that are not NULL. */
 4683 void
 4684 format_defaults(struct format_tree *ft, struct client *c, struct session *s,
 4685     struct winlink *wl, struct window_pane *wp)
 4686 {
 4687     struct paste_buffer *pb;
 4688 
 4689     if (c != NULL && c->name != NULL)
 4690         log_debug("%s: c=%s", __func__, c->name);
 4691     else
 4692         log_debug("%s: c=none", __func__);
 4693     if (s != NULL)
 4694         log_debug("%s: s=$%u", __func__, s->id);
 4695     else
 4696         log_debug("%s: s=none", __func__);
 4697     if (wl != NULL)
 4698         log_debug("%s: wl=%u", __func__, wl->idx);
 4699     else
 4700         log_debug("%s: wl=none", __func__);
 4701     if (wp != NULL)
 4702         log_debug("%s: wp=%%%u", __func__, wp->id);
 4703     else
 4704         log_debug("%s: wp=none", __func__);
 4705 
 4706     if (c != NULL && s != NULL && c->session != s)
 4707         log_debug("%s: session does not match", __func__);
 4708 
 4709     if (wp != NULL)
 4710         ft->type = FORMAT_TYPE_PANE;
 4711     else if (wl != NULL)
 4712         ft->type = FORMAT_TYPE_WINDOW;
 4713     else if (s != NULL)
 4714         ft->type = FORMAT_TYPE_SESSION;
 4715     else
 4716         ft->type = FORMAT_TYPE_UNKNOWN;
 4717 
 4718     if (s == NULL && c != NULL)
 4719         s = c->session;
 4720     if (wl == NULL && s != NULL)
 4721         wl = s->curw;
 4722     if (wp == NULL && wl != NULL)
 4723         wp = wl->window->active;
 4724 
 4725     if (c != NULL)
 4726         format_defaults_client(ft, c);
 4727     if (s != NULL)
 4728         format_defaults_session(ft, s);
 4729     if (wl != NULL)
 4730         format_defaults_winlink(ft, wl);
 4731     if (wp != NULL)
 4732         format_defaults_pane(ft, wp);
 4733 
 4734     pb = paste_get_top (NULL);
 4735     if (pb != NULL)
 4736         format_defaults_paste_buffer(ft, pb);
 4737 }
 4738 
 4739 /* Set default format keys for a session. */
 4740 static void
 4741 format_defaults_session(struct format_tree *ft, struct session *s)
 4742 {
 4743     ft->s = s;
 4744 }
 4745 
 4746 /* Set default format keys for a client. */
 4747 static void
 4748 format_defaults_client(struct format_tree *ft, struct client *c)
 4749 {
 4750     if (ft->s == NULL)
 4751         ft->s = c->session;
 4752     ft->c = c;
 4753 }
 4754 
 4755 /* Set default format keys for a window. */
 4756 void
 4757 format_defaults_window(struct format_tree *ft, struct window *w)
 4758 {
 4759     ft->w = w;
 4760 }
 4761 
 4762 /* Set default format keys for a winlink. */
 4763 static void
 4764 format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
 4765 {
 4766     if (ft->w == NULL)
 4767         format_defaults_window(ft, wl->window);
 4768     ft->wl = wl;
 4769 }
 4770 
 4771 /* Set default format keys for a window pane. */
 4772 void
 4773 format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
 4774 {
 4775     struct window_mode_entry    *wme;
 4776 
 4777     if (ft->w == NULL)
 4778         format_defaults_window(ft, wp->window);
 4779     ft->wp = wp;
 4780 
 4781     wme = TAILQ_FIRST(&wp->modes);
 4782     if (wme != NULL && wme->mode->formats != NULL)
 4783         wme->mode->formats(wme, ft);
 4784 }
 4785 
 4786 /* Set default format keys for paste buffer. */
 4787 void
 4788 format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
 4789 {
 4790     ft->pb = pb;
 4791 }
 4792 
 4793 /* Return word at given coordinates. Caller frees. */
 4794 char *
 4795 format_grid_word(struct grid *gd, u_int x, u_int y)
 4796 {
 4797     const struct grid_line  *gl;
 4798     struct grid_cell     gc;
 4799     const char      *ws;
 4800     struct utf8_data    *ud = NULL;
 4801     u_int            end;
 4802     size_t           size = 0;
 4803     int          found = 0;
 4804     char            *s = NULL;
 4805 
 4806     ws = options_get_string(global_s_options, "word-separators");
 4807 
 4808     for (;;) {
 4809         grid_get_cell(gd, x, y, &gc);
 4810         if (gc.flags & GRID_FLAG_PADDING)
 4811             break;
 4812         if (utf8_cstrhas(ws, &gc.data)) {
 4813             found = 1;
 4814             break;
 4815         }
 4816 
 4817         if (x == 0) {
 4818             if (y == 0)
 4819                 break;
 4820             gl = grid_peek_line(gd, y - 1);
 4821             if (~gl->flags & GRID_LINE_WRAPPED)
 4822                 break;
 4823             y--;
 4824             x = grid_line_length(gd, y);
 4825             if (x == 0)
 4826                 break;
 4827         }
 4828         x--;
 4829     }
 4830     for (;;) {
 4831         if (found) {
 4832             end = grid_line_length(gd, y);
 4833             if (end == 0 || x == end - 1) {
 4834                 if (y == gd->hsize + gd->sy - 1)
 4835                     break;
 4836                 gl = grid_peek_line(gd, y);
 4837                 if (~gl->flags & GRID_LINE_WRAPPED)
 4838                     break;
 4839                 y++;
 4840                 x = 0;
 4841             } else
 4842                 x++;
 4843         }
 4844         found = 1;
 4845 
 4846         grid_get_cell(gd, x, y, &gc);
 4847         if (gc.flags & GRID_FLAG_PADDING)
 4848             break;
 4849         if (utf8_cstrhas(ws, &gc.data))
 4850             break;
 4851 
 4852         ud = xreallocarray(ud, size + 2, sizeof *ud);
 4853         memcpy(&ud[size++], &gc.data, sizeof *ud);
 4854     }
 4855     if (size != 0) {
 4856         ud[size].size = 0;
 4857         s = utf8_tocstr(ud);
 4858         free(ud);
 4859     }
 4860     return (s);
 4861 }
 4862 
 4863 /* Return line at given coordinates. Caller frees. */
 4864 char *
 4865 format_grid_line(struct grid *gd, u_int y)
 4866 {
 4867     struct grid_cell     gc;
 4868     struct utf8_data    *ud = NULL;
 4869     u_int            x;
 4870     size_t           size = 0;
 4871     char            *s = NULL;
 4872 
 4873     for (x = 0; x < grid_line_length(gd, y); x++) {
 4874         grid_get_cell(gd, x, y, &gc);
 4875         if (gc.flags & GRID_FLAG_PADDING)
 4876             break;
 4877 
 4878         ud = xreallocarray(ud, size + 2, sizeof *ud);
 4879         memcpy(&ud[size++], &gc.data, sizeof *ud);
 4880     }
 4881     if (size != 0) {
 4882         ud[size].size = 0;
 4883         s = utf8_tocstr(ud);
 4884         free(ud);
 4885     }
 4886     return (s);
 4887 }