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