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