tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

format.c
Go to the documentation of this file.
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;
118  RB_ENTRY(format_entry) entry;
119 };
120 
121 /* Format type. */
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 *);
150 
151 /* 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. */
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
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
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
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)
306  fj->last = t;
307  }
308 }
309 
310 /* Format job complete callback. */
311 static void
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)
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 
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,
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
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
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
1282 {
1283  if (ft->c != NULL &&
1284  ft->c->last_session != NULL &&
1286  return (xstrdup(ft->c->last_session->name));
1287  return (NULL);
1288 }
1289 
1290 /* Callback for client_name. */
1291 static void *
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 *
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 *
1311 {
1312  const char *name;
1313 
1314  if (ft->c != NULL) {
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
2089 {
2090  return (xstrdup(socket_path));
2091 }
2092 
2093 /* Callback for version. */
2094 static void *
2096 {
2097  return (xstrdup(getversion()));
2098 }
2099 
2100 /* Callback for active_window_index. */
2101 static void *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
2466 {
2467  return (&start_time);
2468 }
2469 
2470 /* Callback for window_activity. */
2471 static void *
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 *
2482 {
2484 }
2485 
2486 /* Callback for client_mode_format, */
2487 static void *
2489 {
2491 }
2492 
2493 /* Callback for tree_mode_format, */
2494 static void *
2496 {
2498 }
2499 
2500 /* Format table type. */
2504 };
2505 
2506 /* Format table entry. */
2508  const char *key;
2509  enum format_table_type type;
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,
2521  },
2522  { "alternate_on", FORMAT_TABLE_STRING,
2524  },
2525  { "alternate_saved_x", FORMAT_TABLE_STRING,
2527  },
2528  { "alternate_saved_y", FORMAT_TABLE_STRING,
2530  },
2531  { "buffer_created", FORMAT_TABLE_TIME,
2533  },
2534  { "buffer_mode_format", FORMAT_TABLE_STRING,
2536  },
2537  { "buffer_name", FORMAT_TABLE_STRING,
2539  },
2540  { "buffer_sample", FORMAT_TABLE_STRING,
2542  },
2543  { "buffer_size", FORMAT_TABLE_STRING,
2545  },
2546  { "client_activity", FORMAT_TABLE_TIME,
2548  },
2549  { "client_cell_height", FORMAT_TABLE_STRING,
2551  },
2552  { "client_cell_width", FORMAT_TABLE_STRING,
2554  },
2555  { "client_control_mode", FORMAT_TABLE_STRING,
2557  },
2558  { "client_created", FORMAT_TABLE_TIME,
2560  },
2561  { "client_discarded", FORMAT_TABLE_STRING,
2563  },
2564  { "client_flags", FORMAT_TABLE_STRING,
2566  },
2567  { "client_height", FORMAT_TABLE_STRING,
2569  },
2570  { "client_key_table", FORMAT_TABLE_STRING,
2572  },
2573  { "client_last_session", FORMAT_TABLE_STRING,
2575  },
2576  { "client_mode_format", FORMAT_TABLE_STRING,
2578  },
2579  { "client_name", FORMAT_TABLE_STRING,
2581  },
2582  { "client_pid", FORMAT_TABLE_STRING,
2584  },
2585  { "client_prefix", FORMAT_TABLE_STRING,
2587  },
2588  { "client_readonly", FORMAT_TABLE_STRING,
2590  },
2591  { "client_session", FORMAT_TABLE_STRING,
2593  },
2594  { "client_termfeatures", FORMAT_TABLE_STRING,
2596  },
2597  { "client_termname", FORMAT_TABLE_STRING,
2599  },
2600  { "client_termtype", FORMAT_TABLE_STRING,
2602  },
2603  { "client_tty", FORMAT_TABLE_STRING,
2605  },
2606  { "client_utf8", FORMAT_TABLE_STRING,
2608  },
2609  { "client_width", FORMAT_TABLE_STRING,
2611  },
2612  { "client_written", FORMAT_TABLE_STRING,
2614  },
2615  { "config_files", FORMAT_TABLE_STRING,
2617  },
2618  { "cursor_character", FORMAT_TABLE_STRING,
2620  },
2621  { "cursor_flag", FORMAT_TABLE_STRING,
2623  },
2624  { "cursor_x", FORMAT_TABLE_STRING,
2626  },
2627  { "cursor_y", FORMAT_TABLE_STRING,
2629  },
2630  { "history_all_bytes", FORMAT_TABLE_STRING,
2632  },
2633  { "history_bytes", FORMAT_TABLE_STRING,
2635  },
2636  { "history_limit", FORMAT_TABLE_STRING,
2638  },
2639  { "history_size", FORMAT_TABLE_STRING,
2641  },
2642  { "host", FORMAT_TABLE_STRING,
2644  },
2645  { "host_short", FORMAT_TABLE_STRING,
2647  },
2648  { "insert_flag", FORMAT_TABLE_STRING,
2650  },
2651  { "keypad_cursor_flag", FORMAT_TABLE_STRING,
2653  },
2654  { "keypad_flag", FORMAT_TABLE_STRING,
2656  },
2657  { "last_window_index", FORMAT_TABLE_STRING,
2659  },
2660  { "mouse_all_flag", FORMAT_TABLE_STRING,
2662  },
2663  { "mouse_any_flag", FORMAT_TABLE_STRING,
2665  },
2666  { "mouse_button_flag", FORMAT_TABLE_STRING,
2668  },
2669  { "mouse_line", FORMAT_TABLE_STRING,
2671  },
2672  { "mouse_pane", FORMAT_TABLE_STRING,
2674  },
2675  { "mouse_sgr_flag", FORMAT_TABLE_STRING,
2677  },
2678  { "mouse_standard_flag", FORMAT_TABLE_STRING,
2680  },
2681  { "mouse_utf8_flag", FORMAT_TABLE_STRING,
2683  },
2684  { "mouse_word", FORMAT_TABLE_STRING,
2686  },
2687  { "mouse_x", FORMAT_TABLE_STRING,
2689  },
2690  { "mouse_y", FORMAT_TABLE_STRING,
2692  },
2693  { "origin_flag", FORMAT_TABLE_STRING,
2695  },
2696  { "pane_active", FORMAT_TABLE_STRING,
2698  },
2699  { "pane_at_bottom", FORMAT_TABLE_STRING,
2701  },
2702  { "pane_at_left", FORMAT_TABLE_STRING,
2704  },
2705  { "pane_at_right", FORMAT_TABLE_STRING,
2707  },
2708  { "pane_at_top", FORMAT_TABLE_STRING,
2710  },
2711  { "pane_bg", FORMAT_TABLE_STRING,
2713  },
2714  { "pane_bottom", FORMAT_TABLE_STRING,
2716  },
2717  { "pane_current_command", FORMAT_TABLE_STRING,
2719  },
2720  { "pane_current_path", FORMAT_TABLE_STRING,
2722  },
2723  { "pane_dead", FORMAT_TABLE_STRING,
2725  },
2726  { "pane_dead_status", FORMAT_TABLE_STRING,
2728  },
2729  { "pane_fg", FORMAT_TABLE_STRING,
2731  },
2732  { "pane_format", FORMAT_TABLE_STRING,
2734  },
2735  { "pane_height", FORMAT_TABLE_STRING,
2737  },
2738  { "pane_id", FORMAT_TABLE_STRING,
2740  },
2741  { "pane_in_mode", FORMAT_TABLE_STRING,
2743  },
2744  { "pane_index", FORMAT_TABLE_STRING,
2746  },
2747  { "pane_input_off", FORMAT_TABLE_STRING,
2749  },
2750  { "pane_last", FORMAT_TABLE_STRING,
2752  },
2753  { "pane_left", FORMAT_TABLE_STRING,
2755  },
2756  { "pane_marked", FORMAT_TABLE_STRING,
2758  },
2759  { "pane_marked_set", FORMAT_TABLE_STRING,
2761  },
2762  { "pane_mode", FORMAT_TABLE_STRING,
2764  },
2765  { "pane_path", FORMAT_TABLE_STRING,
2767  },
2768  { "pane_pid", FORMAT_TABLE_STRING,
2770  },
2771  { "pane_pipe", FORMAT_TABLE_STRING,
2773  },
2774  { "pane_right", FORMAT_TABLE_STRING,
2776  },
2777  { "pane_search_string", FORMAT_TABLE_STRING,
2779  },
2780  { "pane_start_command", FORMAT_TABLE_STRING,
2782  },
2783  { "pane_synchronized", FORMAT_TABLE_STRING,
2785  },
2786  { "pane_tabs", FORMAT_TABLE_STRING,
2788  },
2789  { "pane_title", FORMAT_TABLE_STRING,
2791  },
2792  { "pane_top", FORMAT_TABLE_STRING,
2794  },
2795  { "pane_tty", FORMAT_TABLE_STRING,
2797  },
2798  { "pane_width", FORMAT_TABLE_STRING,
2800  },
2801  { "pid", FORMAT_TABLE_STRING,
2803  },
2804  { "scroll_region_lower", FORMAT_TABLE_STRING,
2806  },
2807  { "scroll_region_upper", FORMAT_TABLE_STRING,
2809  },
2810  { "session_activity", FORMAT_TABLE_TIME,
2812  },
2813  { "session_alerts", FORMAT_TABLE_STRING,
2815  },
2816  { "session_attached", FORMAT_TABLE_STRING,
2818  },
2819  { "session_attached_list", FORMAT_TABLE_STRING,
2821  },
2822  { "session_created", FORMAT_TABLE_TIME,
2824  },
2825  { "session_format", FORMAT_TABLE_STRING,
2827  },
2828  { "session_group", FORMAT_TABLE_STRING,
2830  },
2831  { "session_group_attached", FORMAT_TABLE_STRING,
2833  },
2834  { "session_group_attached_list", FORMAT_TABLE_STRING,
2836  },
2837  { "session_group_list", FORMAT_TABLE_STRING,
2839  },
2840  { "session_group_many_attached", FORMAT_TABLE_STRING,
2842  },
2843  { "session_group_size", FORMAT_TABLE_STRING,
2845  },
2846  { "session_grouped", FORMAT_TABLE_STRING,
2848  },
2849  { "session_id", FORMAT_TABLE_STRING,
2851  },
2852  { "session_last_attached", FORMAT_TABLE_TIME,
2854  },
2855  { "session_many_attached", FORMAT_TABLE_STRING,
2857  },
2858  { "session_marked", FORMAT_TABLE_STRING,
2860  },
2861  { "session_name", FORMAT_TABLE_STRING,
2863  },
2864  { "session_path", FORMAT_TABLE_STRING,
2866  },
2867  { "session_stack", FORMAT_TABLE_STRING,
2869  },
2870  { "session_windows", FORMAT_TABLE_STRING,
2872  },
2873  { "socket_path", FORMAT_TABLE_STRING,
2875  },
2876  { "start_time", FORMAT_TABLE_TIME,
2878  },
2879  { "tree_mode_format", FORMAT_TABLE_STRING,
2881  },
2882  { "version", FORMAT_TABLE_STRING,
2884  },
2885  { "window_active", FORMAT_TABLE_STRING,
2887  },
2888  { "window_active_clients", FORMAT_TABLE_STRING,
2890  },
2891  { "window_active_clients_list", FORMAT_TABLE_STRING,
2893  },
2894  { "window_active_sessions", FORMAT_TABLE_STRING,
2896  },
2897  { "window_active_sessions_list", FORMAT_TABLE_STRING,
2899  },
2900  { "window_activity", FORMAT_TABLE_TIME,
2902  },
2903  { "window_activity_flag", FORMAT_TABLE_STRING,
2905  },
2906  { "window_bell_flag", FORMAT_TABLE_STRING,
2908  },
2909  { "window_bigger", FORMAT_TABLE_STRING,
2911  },
2912  { "window_cell_height", FORMAT_TABLE_STRING,
2914  },
2915  { "window_cell_width", FORMAT_TABLE_STRING,
2917  },
2918  { "window_end_flag", FORMAT_TABLE_STRING,
2920  },
2921  { "window_flags", FORMAT_TABLE_STRING,
2923  },
2924  { "window_format", FORMAT_TABLE_STRING,
2926  },
2927  { "window_height", FORMAT_TABLE_STRING,
2929  },
2930  { "window_id", FORMAT_TABLE_STRING,
2932  },
2933  { "window_index", FORMAT_TABLE_STRING,
2935  },
2936  { "window_last_flag", FORMAT_TABLE_STRING,
2938  },
2939  { "window_layout", FORMAT_TABLE_STRING,
2941  },
2942  { "window_linked", FORMAT_TABLE_STRING,
2944  },
2945  { "window_linked_sessions", FORMAT_TABLE_STRING,
2947  },
2948  { "window_linked_sessions_list", FORMAT_TABLE_STRING,
2950  },
2951  { "window_marked_flag", FORMAT_TABLE_STRING,
2953  },
2954  { "window_name", FORMAT_TABLE_STRING,
2956  },
2957  { "window_offset_x", FORMAT_TABLE_STRING,
2959  },
2960  { "window_offset_y", FORMAT_TABLE_STRING,
2962  },
2963  { "window_panes", FORMAT_TABLE_STRING,
2965  },
2966  { "window_raw_flags", FORMAT_TABLE_STRING,
2968  },
2969  { "window_silence_flag", FORMAT_TABLE_STRING,
2971  },
2972  { "window_stack_index", FORMAT_TABLE_STRING,
2974  },
2975  { "window_start_flag", FORMAT_TABLE_STRING,
2977  },
2978  { "window_visible_layout", FORMAT_TABLE_STRING,
2980  },
2981  { "window_width", FORMAT_TABLE_STRING,
2983  },
2984  { "window_zoomed_flag", FORMAT_TABLE_STRING,
2986  },
2987  { "wrap_flag", FORMAT_TABLE_STRING,
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),
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 *
3025 {
3026  return (ft->wp);
3027 }
3028 
3029 /* Add item bits to tree. */
3030 static void
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)
3060 
3061  return (ft);
3062 }
3063 
3064 /* Free a tree. */
3065 void
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)
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 *
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
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 *
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) {
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;
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 *
4653  struct session *s, struct winlink *wl, struct window_pane *wp)
4654 {
4655  struct format_tree *ft;
4656 
4657  if (item != NULL)
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 *
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 *
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)
4737 }
4738 
4739 /* Set default format keys for a session. */
4740 static void
4742 {
4743  ft->s = s;
4744 }
4745 
4746 /* Set default format keys for a client. */
4747 static void
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
4758 {
4759  ft->w = w;
4760 }
4761 
4762 /* Set default format keys for a winlink. */
4763 static void
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
4774 {
4775  struct window_mode_entry *wme;
4776 
4777  if (ft->w == NULL)
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
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 }
u_int cfg_nfiles
Definition: cfg.c:37
char ** cfg_files
Definition: cfg.c:36
void cmdq_print(struct cmdq_item *item, const char *fmt,...)
Definition: cmd-queue.c:792
struct client * cmdq_get_target_client(struct cmdq_item *item)
Definition: cmd-queue.c:157
void cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft)
Definition: cmd-queue.c:274
struct client * cmdq_get_client(struct cmdq_item *item)
Definition: cmd-queue.c:150
struct cmd_find_state * cmdq_get_target(struct cmdq_item *item)
Definition: cmd-queue.c:171
struct key_event * cmdq_get_event(struct cmdq_item *item)
Definition: cmd-queue.c:185
char * cmd_stringify_argv(int argc, char **argv)
Definition: cmd.c:357
int cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp, u_int *yp, int last)
Definition: cmd.c:703
struct window_pane * cmd_mouse_pane(struct mouse_event *m, struct session **sp, struct winlink **wlp)
Definition: cmd.c:758
void cmd_free_argv(int argc, char **argv)
Definition: cmd.c:344
const char * colour_tostring(int c)
Definition: colour.c:110
#define __unused
Definition: compat.h:60
size_t strlcat(char *, const char *, size_t)
long long strtonum(const char *, long long, long long, const char **)
#define HOST_NAME_MAX
Definition: compat.h:265
#define FNM_CASEFOLD
Definition: compat.h:213
struct environ_entry * environ_find(struct environ *env, const char *name)
Definition: environ.c:99
char * format_trim_right(const char *expanded, u_int limit)
Definition: format-draw.c:1136
u_int format_width(const char *expanded)
Definition: format-draw.c:1002
char * format_trim_left(const char *expanded, u_int limit)
Definition: format-draw.c:1058
static void * format_cb_window_start_flag(struct format_tree *ft)
Definition: format.c:2361
static char * format_match(struct format_modifier *fm, const char *pattern, const char *text)
Definition: format.c:3627
#define FORMAT_QUOTE_STYLE
Definition: format.c:100
char * format_grid_line(struct grid *gd, u_int y)
Definition: format.c:4865
static void * format_cb_pane_active(struct format_tree *ft)
Definition: format.c:1650
static char * format_strip(const char *s)
Definition: format.c:3398
static void * format_cb_buffer_sample(struct format_tree *ft)
Definition: format.c:1193
static void * format_cb_window_silence_flag(struct format_tree *ft)
Definition: format.c:2349
static void * format_cb_window_raw_flags(struct format_tree *ft)
Definition: format.c:2340
static void * format_cb_pid(struct format_tree *ft)
Definition: format.c:500
#define FORMAT_LITERAL
Definition: format.c:91
static void format_add_modifier(struct format_modifier **list, u_int *count, const char *c, size_t n, char **argv, int argc)
Definition: format.c:3487
static const char * format_upper[]
Definition: format.c:177
#define FORMAT_PRETTY
Definition: format.c:97
static void * format_cb_pane_bottom(struct format_tree *ft)
Definition: format.c:1686
static void * format_cb_pane_height(struct format_tree *ft)
Definition: format.c:1730
static void * format_cb_session_group_list(struct format_tree *ft)
Definition: format.c:949
struct format_tree * format_create_defaults(struct cmdq_item *item, struct client *c, struct session *s, struct winlink *wl, struct window_pane *wp)
Definition: format.c:4652
static void * format_cb_pane_path(struct format_tree *ft)
Definition: format.c:1831
static void * format_cb_client_termtype(struct format_tree *ft)
Definition: format.c:1364
static void * format_cb_session_activity(struct format_tree *ft)
Definition: format.c:2438
static void * format_cb_client_cell_width(struct format_tree *ft)
Definition: format.c:1224
static void * format_cb_pane_dead_status(struct format_tree *ft)
Definition: format.c:1707
static void * format_cb_active_window_index(struct format_tree *ft)
Definition: format.c:2102
static void * format_cb_mouse_x(struct format_tree *ft)
Definition: format.c:1606
static int format_replace(struct format_expand_state *, const char *, size_t, char **, size_t *, size_t *)
Definition: format.c:4015
static char * format_sub(struct format_modifier *fm, const char *text, const char *pattern, const char *with)
Definition: format.c:3657
static void * format_cb_pane_pid(struct format_tree *ft)
Definition: format.c:1843
static void * format_cb_alternate_on(struct format_tree *ft)
Definition: format.c:1154
static int format_choose(struct format_expand_state *es, const char *s, char **left, char **right, int expand)
Definition: format.c:3445
static char * format_pretty_time(time_t t)
Definition: format.c:3234
static void * format_cb_window_width(struct format_tree *ft)
Definition: format.c:2373
static void * format_cb_host_short(struct format_tree *ft)
Definition: format.c:487
static void * format_cb_client_activity(struct format_tree *ft)
Definition: format.c:2420
static void * format_cb_window_bell_flag(struct format_tree *ft)
Definition: format.c:2148
static void * format_cb_pane_format(struct format_tree *ft)
Definition: format.c:1721
void format_merge(struct format_tree *ft, struct format_tree *from)
Definition: format.c:3012
static void * format_cb_window_cell_height(struct format_tree *ft)
Definition: format.c:2174
static void * format_cb_last_window_index(struct format_tree *ft)
Definition: format.c:2111
#define FORMAT_EXPAND_TIME
Definition: format.c:109
static void * format_cb_pane_in_mode(struct format_tree *ft)
Definition: format.c:1022
static void * format_cb_buffer_name(struct format_tree *ft)
Definition: format.c:1184
static void * format_cb_session_many_attached(struct format_tree *ft)
Definition: format.c:2037
static RB_HEAD(RB_GENERATE_STATIC(format_job_tree, RB_GENERATE_STATIC(format_job)
Definition: format.c:72
static void * format_cb_pane_marked_set(struct format_tree *ft)
Definition: format.c:1804
#define FORMAT_BASENAME
Definition: format.c:88
static int format_table_compare(const void *key0, const void *entry0)
Definition: format.c:2994
static char * format_loop_sessions(struct format_expand_state *es, const char *fmt)
Definition: format.c:3708
static void * format_cb_buffer_size(struct format_tree *ft)
Definition: format.c:1202
static void * format_cb_window_offset_y(struct format_tree *ft)
Definition: format.c:2317
static void * format_cb_window_cell_width(struct format_tree *ft)
Definition: format.c:2183
static void * format_cb_mouse_sgr_flag(struct format_tree *ft)
Definition: format.c:1570
format_table_type
Definition: format.c:2501
@ FORMAT_TABLE_STRING
Definition: format.c:2502
@ FORMAT_TABLE_TIME
Definition: format.c:2503
void format_defaults(struct format_tree *ft, struct client *c, struct session *s, struct winlink *wl, struct window_pane *wp)
Definition: format.c:4684
static void * format_cb_client_control_mode(struct format_tree *ft)
Definition: format.c:1233
static void * format_cb_pane_last(struct format_tree *ft)
Definition: format.c:1771
static void * format_cb_mouse_utf8_flag(struct format_tree *ft)
Definition: format.c:1594
#define FORMAT_DIRNAME
Definition: format.c:89
struct format_tree * format_create_from_state(struct cmdq_item *item, struct client *c, struct cmd_find_state *fs)
Definition: format.c:4667
char * format_single_from_target(struct cmdq_item *item, const char *fmt)
Definition: format.c:4643
static void * format_cb_session_group_attached(struct format_tree *ft)
Definition: format.c:1980
static void * format_cb_keypad_flag(struct format_tree *ft)
Definition: format.c:1507
static void * format_cb_session_group_attached_list(struct format_tree *ft)
Definition: format.c:982
static void * format_cb_window_stack_index(struct format_tree *ft)
Definition: format.c:593
char * format_single(struct cmdq_item *item, const char *fmt, struct client *c, struct session *s, struct winlink *wl, struct window_pane *wp)
Definition: format.c:4621
static void * format_cb_session_attached_list(struct format_tree *ft)
Definition: format.c:510
static const char * format_lower[]
Definition: format.c:207
static void * format_cb_mouse_line(struct format_tree *ft)
Definition: format.c:1128
#define FORMAT_TIMESTRING
Definition: format.c:87
static void * format_cb_window_active_clients_list(struct format_tree *ft)
Definition: format.c:729
static char * format_replace_expression(struct format_modifier *mexp, struct format_expand_state *es, const char *copy)
Definition: format.c:3872
static void * format_cb_mouse_any_flag(struct format_tree *ft)
Definition: format.c:1531
static void * format_cb_client_name(struct format_tree *ft)
Definition: format.c:1292
void format_add(struct format_tree *ft, const char *key, const char *fmt,...)
Definition: format.c:3126
static void * format_cb_pane_pipe(struct format_tree *ft)
Definition: format.c:1852
static void * format_cb_session_group_size(struct format_tree *ft)
Definition: format.c:2005
void format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
Definition: format.c:3176
static void * format_cb_session_created(struct format_tree *ft)
Definition: format.c:2447
static void * format_cb_client_key_table(struct format_tree *ft)
Definition: format.c:1272
#define format_log(es, fmt,...)
Definition: format.c:266
static int format_is_end(char c)
Definition: format.c:3480
static void * format_cb_window_active_sessions(struct format_tree *ft)
Definition: format.c:648
#define FORMAT_WIDTH
Definition: format.c:99
const char * format_skip(const char *s, const char *end)
Definition: format.c:3422
static void * format_cb_window_layout(struct format_tree *ft)
Definition: format.c:766
static void * format_cb_window_linked_sessions_list(struct format_tree *ft)
Definition: format.c:618
static char * format_printf(const char *fmt,...)
Definition: format.c:463
struct window_pane * format_get_pane(struct format_tree *ft)
Definition: format.c:3024
static void * format_cb_session_alerts(struct format_tree *ft)
Definition: format.c:541
static void * format_cb_host(struct format_tree *ft)
Definition: format.c:476
static void * format_cb_socket_path(struct format_tree *ft)
Definition: format.c:2088
static void * format_cb_client_session(struct format_tree *ft)
Definition: format.c:1337
static void * format_cb_session_group_many_attached(struct format_tree *ft)
Definition: format.c:1991
static char * format_loop_panes(struct format_expand_state *es, const char *fmt)
Definition: format.c:3821
static void * format_cb_scroll_region_upper(struct format_tree *ft)
Definition: format.c:1942
static void * format_cb_pane_title(struct format_tree *ft)
Definition: format.c:1897
static void * format_cb_session_path(struct format_tree *ft)
Definition: format.c:2070
static void format_log1(struct format_expand_state *es, const char *from, const char *fmt,...)
Definition: format.c:245
static void format_job_tidy(struct format_job_tree *jobs, int force)
Definition: format.c:415
static void * format_cb_pane_fg(struct format_tree *ft)
Definition: format.c:927
static void * format_cb_history_limit(struct format_tree *ft)
Definition: format.c:1465
static void * format_cb_pane_width(struct format_tree *ft)
Definition: format.c:1924
static void * format_cb_client_cell_height(struct format_tree *ft)
Definition: format.c:1215
static void * format_cb_pane_at_left(struct format_tree *ft)
Definition: format.c:1662
static void format_job_update(struct job *job)
Definition: format.c:282
static void * format_cb_window_visible_layout(struct format_tree *ft)
Definition: format.c:780
static void * format_cb_mouse_standard_flag(struct format_tree *ft)
Definition: format.c:1582
struct format_tree * format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
Definition: format.c:3042
static void * format_cb_mouse_word(struct format_tree *ft)
Definition: format.c:1101
static int format_entry_cmp(struct format_entry *, struct format_entry *)
Definition: format.c:171
#define FORMAT_WINDOWS
Definition: format.c:95
static void * format_cb_insert_flag(struct format_tree *ft)
Definition: format.c:1483
static void * format_cb_pane_at_right(struct format_tree *ft)
Definition: format.c:1674
#define FORMAT_CHARACTER
Definition: format.c:103
static void format_copy_state(struct format_expand_state *to, struct format_expand_state *from, int flags)
Definition: format.c:270
static void * format_cb_window_index(struct format_tree *ft)
Definition: format.c:2240
void format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
Definition: format.c:3153
static void * format_cb_client_mode_format(struct format_tree *ft)
Definition: format.c:2488
static void * format_cb_window_id(struct format_tree *ft)
Definition: format.c:2231
static void * format_cb_pane_id(struct format_tree *ft)
Definition: format.c:1739
static void * format_cb_window_panes(struct format_tree *ft)
Definition: format.c:2331
static void format_job_complete(struct job *job)
Definition: format.c:312
char * format_grid_word(struct grid *gd, u_int x, u_int y)
Definition: format.c:4795
static void * format_cb_client_width(struct format_tree *ft)
Definition: format.c:1397
static void * format_cb_client_created(struct format_tree *ft)
Definition: format.c:2429
static void * format_cb_session_name(struct format_tree *ft)
Definition: format.c:2061
static void * format_cb_pane_marked(struct format_tree *ft)
Definition: format.c:1792
static char * format_quote_style(const char *s)
Definition: format.c:3217
static void * format_cb_client_discarded(struct format_tree *ft)
Definition: format.c:1245
static void * format_cb_pane_at_bottom(struct format_tree *ft)
Definition: format.c:1062
static void * format_cb_pane_synchronized(struct format_tree *ft)
Definition: format.c:1885
static void format_defaults_client(struct format_tree *, struct client *)
Definition: format.c:4748
static void * format_cb_window_end_flag(struct format_tree *ft)
Definition: format.c:2192
static void * format_cb_window_activity(struct format_tree *ft)
Definition: format.c:2472
static void * format_cb_mouse_all_flag(struct format_tree *ft)
Definition: format.c:1519
static char * format_job_get(struct format_expand_state *, const char *)
Definition: format.c:348
static char * format_find(struct format_tree *ft, const char *key, int modifiers, const char *time_format)
Definition: format.c:3275
char * format_expand(struct format_tree *ft, const char *fmt)
Definition: format.c:4609
static void * format_cb_session_marked(struct format_tree *ft)
Definition: format.c:2049
static void * format_cb_pane_tabs(struct format_tree *ft)
Definition: format.c:897
static void * format_cb_client_pid(struct format_tree *ft)
Definition: format.c:1301
static void * format_cb_client_prefix(struct format_tree *ft)
Definition: format.c:1310
static char * format_quote_shell(const char *s)
Definition: format.c:3200
void format_free(struct format_tree *ft)
Definition: format.c:3066
static int format_job_cmp(struct format_job *, struct format_job *)
static void * format_cb_start_command(struct format_tree *ft)
Definition: format.c:792
static void * format_cb_buffer_created(struct format_tree *ft)
Definition: format.c:2406
static void * format_cb_alternate_saved_y(struct format_tree *ft)
Definition: format.c:1175
static void * format_cb_mouse_pane(struct format_tree *ft)
Definition: format.c:1555
#define FORMAT_WINDOW_NAME
Definition: format.c:101
static void * format_cb_client_height(struct format_tree *ft)
Definition: format.c:1263
static void * format_cb_client_flags(struct format_tree *ft)
Definition: format.c:1254
static void * format_cb_session_grouped(struct format_tree *ft)
Definition: format.c:2016
static void * format_cb_client_tty(struct format_tree *ft)
Definition: format.c:1376
static void * format_cb_version(struct format_tree *ft)
Definition: format.c:2095
static void format_free_modifiers(struct format_modifier *list, u_int count)
Definition: format.c:3505
#define FORMAT_QUOTE_SHELL
Definition: format.c:90
static void * format_cb_client_termfeatures(struct format_tree *ft)
Definition: format.c:1346
void format_each(struct format_tree *ft, void(*cb)(const char *, const char *, void *), void *arg)
Definition: format.c:3084
static void * format_cb_session_last_attached(struct format_tree *ft)
Definition: format.c:2456
static void * format_cb_session_stack(struct format_tree *ft)
Definition: format.c:571
static void * format_cb_wrap_flag(struct format_tree *ft)
Definition: format.c:2394
#define FORMAT_EXPAND
Definition: format.c:92
static char * format_expand1(struct format_expand_state *, const char *)
Definition: format.c:4432
static void * format_cb_keypad_cursor_flag(struct format_tree *ft)
Definition: format.c:1495
static void * format_cb_current_path(struct format_tree *ft)
Definition: format.c:828
format_type
Definition: format.c:122
@ FORMAT_TYPE_SESSION
Definition: format.c:124
@ FORMAT_TYPE_PANE
Definition: format.c:126
@ FORMAT_TYPE_WINDOW
Definition: format.c:125
@ FORMAT_TYPE_UNKNOWN
Definition: format.c:123
static void * format_cb_client_readonly(struct format_tree *ft)
Definition: format.c:1325
static void * format_cb_client_last_session(struct format_tree *ft)
Definition: format.c:1281
char * format_expand_time(struct format_tree *ft, const char *fmt)
Definition: format.c:4597
static void * format_cb_window_zoomed_flag(struct format_tree *ft)
Definition: format.c:2382
static void * format_cb_window_flags(struct format_tree *ft)
Definition: format.c:2204
static void * format_cb_window_format(struct format_tree *ft)
Definition: format.c:2213
static void * format_cb_cursor_y(struct format_tree *ft)
Definition: format.c:1456
static void * format_cb_client_utf8(struct format_tree *ft)
Definition: format.c:1385
static void * format_cb_window_marked_flag(struct format_tree *ft)
Definition: format.c:2282
void format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
Definition: format.c:4788
static void * format_cb_session_attached(struct format_tree *ft)
Definition: format.c:1951
static char * format_session_name(struct format_expand_state *es, const char *fmt)
Definition: format.c:3690
static void * format_cb_scroll_region_lower(struct format_tree *ft)
Definition: format.c:1933
int format_true(const char *s)
Definition: format.c:3471
static void * format_cb_start_time(struct format_tree *ft)
Definition: format.c:2465
static void * format_cb_session_group(struct format_tree *ft)
Definition: format.c:1969
static void * format_cb_pane_search_string(struct format_tree *ft)
Definition: format.c:1873
static void * format_cb_pane_tty(struct format_tree *ft)
Definition: format.c:1915
static void * format_cb_cursor_character(struct format_tree *ft)
Definition: format.c:1084
static void * format_cb_history_bytes(struct format_tree *ft)
Definition: format.c:844
static void format_defaults_session(struct format_tree *, struct session *)
Definition: format.c:4741
static void * format_cb_cursor_x(struct format_tree *ft)
Definition: format.c:1447
static void * format_cb_window_offset_x(struct format_tree *ft)
Definition: format.c:2303
static void * format_cb_pane_mode(struct format_tree *ft)
Definition: format.c:1816
static void * format_cb_client_written(struct format_tree *ft)
Definition: format.c:1406
static void * format_cb_mouse_button_flag(struct format_tree *ft)
Definition: format.c:1543
static void * format_cb_pane_index(struct format_tree *ft)
Definition: format.c:1748
static void * format_cb_config_files(struct format_tree *ft)
Definition: format.c:1415
static void * format_cb_window_name(struct format_tree *ft)
Definition: format.c:2294
static void * format_cb_history_all_bytes(struct format_tree *ft)
Definition: format.c:870
char * format_single_from_state(struct cmdq_item *item, const char *fmt, struct client *c, struct cmd_find_state *fs)
Definition: format.c:4635
static int format_logging(struct format_tree *ft)
Definition: format.c:238
static void * format_cb_window_active_sessions_list(struct format_tree *ft)
Definition: format.c:670
static void * format_cb_pane_right(struct format_tree *ft)
Definition: format.c:1864
static void * format_cb_pane_input_off(struct format_tree *ft)
Definition: format.c:1759
struct format_tree * format_create_from_target(struct cmdq_item *item)
Definition: format.c:4675
#define FORMAT_LENGTH
Definition: format.c:98
void format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
Definition: format.c:4773
void format_lost_client(struct client *c)
Definition: format.c:454
static void * format_cb_window_linked(struct format_tree *ft)
Definition: format.c:2261
#define FORMAT_LOOP_LIMIT
Definition: format.c:106
void format_defaults_window(struct format_tree *ft, struct window *w)
Definition: format.c:4757
static void * format_cb_pane_left(struct format_tree *ft)
Definition: format.c:1783
#define FORMAT_SESSIONS
Definition: format.c:94
static void * format_cb_tree_mode_format(struct format_tree *ft)
Definition: format.c:2495
static void format_defaults_winlink(struct format_tree *, struct winlink *)
Definition: format.c:4764
static void * format_cb_client_termname(struct format_tree *ft)
Definition: format.c:1355
#define FORMAT_EXPAND_NOJOBS
Definition: format.c:110
static void * format_cb_window_active_clients(struct format_tree *ft)
Definition: format.c:702
static void * format_cb_window_activity_flag(struct format_tree *ft)
Definition: format.c:2136
static void * format_cb_window_height(struct format_tree *ft)
Definition: format.c:2222
static void * format_cb_session_format(struct format_tree *ft)
Definition: format.c:1960
static void * format_cb_window_bigger(struct format_tree *ft)
Definition: format.c:2160
static void * format_cb_window_active(struct format_tree *ft)
Definition: format.c:2124
void format_tidy_jobs(void)
Definition: format.c:441
static const struct format_table_entry format_table[]
Definition: format.c:2518
static void * format_cb_origin_flag(struct format_tree *ft)
Definition: format.c:1638
static void * format_cb_history_size(struct format_tree *ft)
Definition: format.c:1474
static void * format_cb_current_command(struct format_tree *ft)
Definition: format.c:804
static void * format_cb_pane_bg(struct format_tree *ft)
Definition: format.c:938
RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp)
static void * format_cb_mouse_y(struct format_tree *ft)
Definition: format.c:1622
static void * format_cb_session_windows(struct format_tree *ft)
Definition: format.c:2079
static void * format_cb_alternate_saved_x(struct format_tree *ft)
Definition: format.c:1166
static void * format_cb_session_id(struct format_tree *ft)
Definition: format.c:2028
static void * format_cb_pane_dead(struct format_tree *ft)
Definition: format.c:1695
static char * format_loop_windows(struct format_expand_state *es, const char *fmt)
Definition: format.c:3767
static struct format_modifier * format_build_modifiers(struct format_expand_state *es, const char **s, u_int *count)
Definition: format.c:3516
static char * format_search(struct format_modifier *fm, struct window_pane *wp, const char *s)
Definition: format.c:3673
#define FORMAT_SESSION_NAME
Definition: format.c:102
static void format_create_add_item(struct format_tree *ft, struct cmdq_item *item)
Definition: format.c:3031
static char * format_window_name(struct format_expand_state *es, const char *fmt)
Definition: format.c:3743
static struct format_table_entry * format_table_get(const char *key)
Definition: format.c:3004
#define FORMAT_PANES
Definition: format.c:96
static void * format_cb_window_last_flag(struct format_tree *ft)
Definition: format.c:2249
static void * format_cb_cursor_flag(struct format_tree *ft)
Definition: format.c:1435
#define FORMAT_EXPANDTIME
Definition: format.c:93
static void * format_cb_buffer_mode_format(struct format_tree *ft)
Definition: format.c:2481
static void * format_cb_pane_top(struct format_tree *ft)
Definition: format.c:1906
static void * format_cb_window_linked_sessions(struct format_tree *ft)
Definition: format.c:2273
static void * format_cb_pane_at_top(struct format_tree *ft)
Definition: format.c:1040
void grid_view_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
Definition: grid-view.c:35
void grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
Definition: grid.c:529
struct grid_line * grid_get_line(struct grid *gd, u_int line)
Definition: grid.c:181
u_int grid_line_length(struct grid *gd, u_int py)
Definition: grid.c:1414
const struct grid_line * grid_peek_line(struct grid *gd, u_int py)
Definition: grid.c:486
void * job_get_data(struct job *job)
Definition: job.c:332
void job_free(struct job *job)
Definition: job.c:204
struct bufferevent * job_get_event(struct job *job)
Definition: job.c:339
key_code key
Definition: key-string.c:32
char * layout_dump(struct layout_cell *root)
Definition: layout-custom.c:61
const char * name
Definition: layout-set.c:38
void fatalx(const char *msg,...)
Definition: log.c:159
int log_get_level(void)
Definition: log.c:51
void log_debug(const char *msg,...)
Definition: log.c:130
char * parse_window_name(const char *in)
Definition: names.c:142
const char * options_get_string(struct options *oo, const char *name)
Definition: options.c:686
long long options_get_number(struct options *oo, const char *name)
Definition: options.c:699
char * options_to_string(struct options_entry *o, int idx, int numeric)
Definition: options.c:567
struct options_entry * options_parse_get(struct options *oo, const char *s, int *idx, int only)
Definition: options.c:608
char * osdep_get_name(int fd, char *tty)
Definition: osdep-aix.c:29
char * osdep_get_cwd(int fd)
Definition: osdep-aix.c:60
#define nitems(_a)
const char * paste_buffer_name(struct paste_buffer *pb)
Definition: paste.c:77
time_t paste_buffer_created(struct paste_buffer *pb)
Definition: paste.c:91
struct paste_buffer * paste_get_top(const char **name)
Definition: paste.c:116
char * paste_make_sample(struct paste_buffer *pb)
Definition: paste.c:310
const char * paste_buffer_data(struct paste_buffer *pb, size_t *size)
Definition: paste.c:98
char * regsub(const char *pattern, const char *with, const char *text, int flags)
Definition: regsub.c:61
void server_client_unref(struct client *c)
const char * server_client_get_flags(struct client *c)
const char * server_client_get_cwd(struct client *c, struct session *s)
const char * server_client_get_key_table(struct client *c)
void server_status_client(struct client *c)
Definition: server-fn.c:40
int server_check_marked(void)
Definition: server.c:97
struct cmd_find_state marked_pane
Definition: server.c:51
struct clients clients
Definition: server.c:42
struct sessions sessions
Definition: session.c:29
int session_alive(struct session *s)
Definition: session.c:62
struct session_group * session_group_contains(struct session *target)
Definition: session.c:505
int session_is_linked(struct session *s, struct window *w)
Definition: session.c:388
u_int session_group_attached_count(struct session_group *sg)
Definition: session.c:585
u_int session_group_count(struct session_group *sg)
Definition: session.c:572
Definition: tmux.h:1608
char * term_name
Definition: tmux.h:1633
struct tty tty
Definition: tmux.h:1640
struct session * last_session
Definition: tmux.h:1744
char * ttyname
Definition: tmux.h:1639
char * term_type
Definition: tmux.h:1635
int references
Definition: tmux.h:1746
struct timeval creation_time
Definition: tmux.h:1624
struct timeval activity_time
Definition: tmux.h:1625
const char * name
Definition: tmux.h:1609
struct session * session
Definition: tmux.h:1743
struct format_job_tree * jobs
Definition: tmux.h:1628
size_t discarded
Definition: tmux.h:1643
uint64_t flags
Definition: tmux.h:1703
size_t written
Definition: tmux.h:1642
pid_t pid
Definition: tmux.h:1618
struct key_table * keytable
Definition: tmux.h:1714
int term_features
Definition: tmux.h:1634
struct window_pane * wp
Definition: tmux.h:1454
struct session * s
Definition: tmux.h:1451
struct winlink * wl
Definition: tmux.h:1452
Definition: cmd.c:212
Definition: tmux.h:1160
char * value
Definition: tmux.h:1162
Definition: format.c:113
format_cb cb
Definition: format.c:117
char * value
Definition: format.c:115
time_t time
Definition: format.c:116
char * key
Definition: format.c:114
struct format_tree * ft
Definition: format.c:153
struct tm tm
Definition: format.c:156
struct job * job
Definition: format.c:64
u_int tag
Definition: format.c:56
int updated
Definition: format.c:62
char * out
Definition: format.c:61
int status
Definition: format.c:65
time_t last
Definition: format.c:60
const char * cmd
Definition: format.c:57
struct client * client
Definition: format.c:55
const char * expanded
Definition: format.c:58
u_int size
Definition: format.c:163
char ** argv
Definition: format.c:165
char modifier[3]
Definition: format.c:162
Definition: format.c:2507
const char * key
Definition: format.c:2508
format_cb cb
Definition: format.c:2510
enum format_table_type type
Definition: format.c:2509
int flags
Definition: format.c:141
u_int tag
Definition: format.c:142
struct window_pane * wp
Definition: format.c:136
struct paste_buffer * pb
Definition: format.c:137
struct session * s
Definition: format.c:133
struct winlink * wl
Definition: format.c:134
struct client * client
Definition: format.c:140
struct client * c
Definition: format.c:132
enum format_type type
Definition: format.c:130
struct window * w
Definition: format.c:135
struct cmdq_item * item
Definition: format.c:139
struct mouse_event m
Definition: format.c:144