xref: /openbsd-src/usr.bin/tmux/format.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /* $OpenBSD: format.c,v 1.264 2020/10/06 07:36:42 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 <regex.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 
34 #include "tmux.h"
35 
36 /*
37  * Build a list of key-value pairs and use them to expand #{key} entries in a
38  * string.
39  */
40 
41 struct format_expand_state;
42 
43 static char	*format_job_get(struct format_expand_state *, const char *);
44 static void	 format_job_timer(int, short, void *);
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 struct event format_job_event;
73 static int format_job_cmp(struct format_job *, struct format_job *);
74 static RB_HEAD(format_job_tree, format_job) format_jobs = RB_INITIALIZER();
75 RB_GENERATE_STATIC(format_job_tree, format_job, entry, format_job_cmp);
76 
77 /* Format job tree comparison function. */
78 static int
79 format_job_cmp(struct format_job *fj1, struct format_job *fj2)
80 {
81 	if (fj1->tag < fj2->tag)
82 		return (-1);
83 	if (fj1->tag > fj2->tag)
84 		return (1);
85 	return (strcmp(fj1->cmd, fj2->cmd));
86 }
87 
88 /* Format modifiers. */
89 #define FORMAT_TIMESTRING 0x1
90 #define FORMAT_BASENAME 0x2
91 #define FORMAT_DIRNAME 0x4
92 #define FORMAT_QUOTE 0x8
93 #define FORMAT_LITERAL 0x10
94 #define FORMAT_EXPAND 0x20
95 #define FORMAT_EXPANDTIME 0x40
96 #define FORMAT_SESSIONS 0x80
97 #define FORMAT_WINDOWS 0x100
98 #define FORMAT_PANES 0x200
99 #define FORMAT_PRETTY 0x400
100 #define FORMAT_LENGTH 0x800
101 
102 /* Limit on recursion. */
103 #define FORMAT_LOOP_LIMIT 10
104 
105 /* Format expand flags. */
106 #define FORMAT_EXPAND_TIME 0x1
107 #define FORMAT_EXPAND_NOJOBS 0x2
108 
109 /* Entry in format tree. */
110 struct format_entry {
111 	char			*key;
112 	char			*value;
113 	time_t			 time;
114 	format_cb		 cb;
115 	RB_ENTRY(format_entry)	 entry;
116 };
117 
118 /* Format entry tree. */
119 struct format_tree {
120 	struct client		*c;
121 	struct session		*s;
122 	struct winlink		*wl;
123 	struct window		*w;
124 	struct window_pane	*wp;
125 
126 	struct cmdq_item	*item;
127 	struct client		*client;
128 	int			 flags;
129 	u_int			 tag;
130 
131 	struct mouse_event	 m;
132 
133 	RB_HEAD(format_entry_tree, format_entry) tree;
134 };
135 static int format_entry_cmp(struct format_entry *, struct format_entry *);
136 RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp);
137 
138 /* Format expand state. */
139 struct format_expand_state {
140 	struct format_tree	*ft;
141 	u_int			 loop;
142 	time_t			 time;
143 	int			 flags;
144 };
145 
146 /* Format modifier. */
147 struct format_modifier {
148 	char	  modifier[3];
149 	u_int	  size;
150 
151 	char	**argv;
152 	int	  argc;
153 };
154 
155 /* Format entry tree comparison function. */
156 static int
157 format_entry_cmp(struct format_entry *fe1, struct format_entry *fe2)
158 {
159 	return (strcmp(fe1->key, fe2->key));
160 }
161 
162 /* Single-character uppercase aliases. */
163 static const char *format_upper[] = {
164 	NULL,		/* A */
165 	NULL,		/* B */
166 	NULL,		/* C */
167 	"pane_id",	/* D */
168 	NULL,		/* E */
169 	"window_flags",	/* F */
170 	NULL,		/* G */
171 	"host",		/* H */
172 	"window_index",	/* I */
173 	NULL,		/* J */
174 	NULL,		/* K */
175 	NULL,		/* L */
176 	NULL,		/* M */
177 	NULL,		/* N */
178 	NULL,		/* O */
179 	"pane_index",	/* P */
180 	NULL,		/* Q */
181 	NULL,		/* R */
182 	"session_name",	/* S */
183 	"pane_title",	/* T */
184 	NULL,		/* U */
185 	NULL,		/* V */
186 	"window_name",	/* W */
187 	NULL,		/* X */
188 	NULL,		/* Y */
189 	NULL 		/* Z */
190 };
191 
192 /* Single-character lowercase aliases. */
193 static const char *format_lower[] = {
194 	NULL,		/* a */
195 	NULL,		/* b */
196 	NULL,		/* c */
197 	NULL,		/* d */
198 	NULL,		/* e */
199 	NULL,		/* f */
200 	NULL,		/* g */
201 	"host_short",	/* h */
202 	NULL,		/* i */
203 	NULL,		/* j */
204 	NULL,		/* k */
205 	NULL,		/* l */
206 	NULL,		/* m */
207 	NULL,		/* n */
208 	NULL,		/* o */
209 	NULL,		/* p */
210 	NULL,		/* q */
211 	NULL,		/* r */
212 	NULL,		/* s */
213 	NULL,		/* t */
214 	NULL,		/* u */
215 	NULL,		/* v */
216 	NULL,		/* w */
217 	NULL,		/* x */
218 	NULL,		/* y */
219 	NULL		/* z */
220 };
221 
222 /* Is logging enabled? */
223 static inline int
224 format_logging(struct format_tree *ft)
225 {
226 	return (log_get_level() != 0 || (ft->flags & FORMAT_VERBOSE));
227 }
228 
229 /* Log a message if verbose. */
230 static void printflike(3, 4)
231 format_log1(struct format_expand_state *es, const char *from, const char *fmt,
232     ...)
233 {
234 	struct format_tree	*ft = es->ft;
235 	va_list			 ap;
236 	char			*s;
237 	static const char	 spaces[] = "          ";
238 
239 	if (!format_logging(ft))
240 		return;
241 
242 	va_start(ap, fmt);
243 	xvasprintf(&s, fmt, ap);
244 	va_end(ap);
245 
246 	log_debug("%s: %s", from, s);
247 	if (ft->item != NULL && (ft->flags & FORMAT_VERBOSE))
248 		cmdq_print(ft->item, "#%.*s%s", es->loop, spaces, s);
249 
250 	free(s);
251 }
252 #define format_log(es, fmt, ...) format_log1(es, __func__, fmt, ##__VA_ARGS__)
253 
254 /* Copy expand state. */
255 static void
256 format_copy_state(struct format_expand_state *to,
257     struct format_expand_state *from, int flags)
258 {
259 	to->ft = from->ft;
260 	to->loop = from->loop;
261 	to->time = from->time;
262 	to->flags = from->flags|flags;
263 }
264 
265 /* Format job update callback. */
266 static void
267 format_job_update(struct job *job)
268 {
269 	struct format_job	*fj = job_get_data(job);
270 	struct evbuffer		*evb = job_get_event(job)->input;
271 	char			*line = NULL, *next;
272 	time_t			 t;
273 
274 	while ((next = evbuffer_readline(evb)) != NULL) {
275 		free(line);
276 		line = next;
277 	}
278 	if (line == NULL)
279 		return;
280 	fj->updated = 1;
281 
282 	free(fj->out);
283 	fj->out = line;
284 
285 	log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, fj->out);
286 
287 	t = time(NULL);
288 	if (fj->status && fj->last != t) {
289 		if (fj->client != NULL)
290 			server_status_client(fj->client);
291 		fj->last = t;
292 	}
293 }
294 
295 /* Format job complete callback. */
296 static void
297 format_job_complete(struct job *job)
298 {
299 	struct format_job	*fj = job_get_data(job);
300 	struct evbuffer		*evb = job_get_event(job)->input;
301 	char			*line, *buf;
302 	size_t			 len;
303 
304 	fj->job = NULL;
305 
306 	buf = NULL;
307 	if ((line = evbuffer_readline(evb)) == NULL) {
308 		len = EVBUFFER_LENGTH(evb);
309 		buf = xmalloc(len + 1);
310 		if (len != 0)
311 			memcpy(buf, EVBUFFER_DATA(evb), len);
312 		buf[len] = '\0';
313 	} else
314 		buf = line;
315 
316 	log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, buf);
317 
318 	if (*buf != '\0' || !fj->updated) {
319 		free(fj->out);
320 		fj->out = buf;
321 	} else
322 		free(buf);
323 
324 	if (fj->status) {
325 		if (fj->client != NULL)
326 			server_status_client(fj->client);
327 		fj->status = 0;
328 	}
329 }
330 
331 /* Find a job. */
332 static char *
333 format_job_get(struct format_expand_state *es, const char *cmd)
334 {
335 	struct format_tree		*ft = es->ft;
336 	struct format_job_tree		*jobs;
337 	struct format_job		 fj0, *fj;
338 	time_t				 t;
339 	char				*expanded;
340 	int				 force;
341 	struct format_expand_state	 next;
342 
343 	if (ft->client == NULL)
344 		jobs = &format_jobs;
345 	else if (ft->client->jobs != NULL)
346 		jobs = ft->client->jobs;
347 	else {
348 		jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs);
349 		RB_INIT(jobs);
350 	}
351 
352 	fj0.tag = ft->tag;
353 	fj0.cmd = cmd;
354 	if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) {
355 		fj = xcalloc(1, sizeof *fj);
356 		fj->client = ft->client;
357 		fj->tag = ft->tag;
358 		fj->cmd = xstrdup(cmd);
359 		fj->expanded = NULL;
360 
361 		xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
362 
363 		RB_INSERT(format_job_tree, jobs, fj);
364 	}
365 
366 	expanded = format_expand1(es, cmd);
367 	if (fj->expanded == NULL || strcmp(expanded, fj->expanded) != 0) {
368 		free((void *)fj->expanded);
369 		fj->expanded = xstrdup(expanded);
370 		force = 1;
371 	} else
372 		force = (ft->flags & FORMAT_FORCE);
373 
374 	t = time(NULL);
375 	if (force && fj->job != NULL)
376 	       job_free(fj->job);
377 	if (force || (fj->job == NULL && fj->last != t)) {
378 		fj->job = job_run(expanded, NULL,
379 		    server_client_get_cwd(ft->client, NULL), format_job_update,
380 		    format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1);
381 		if (fj->job == NULL) {
382 			free(fj->out);
383 			xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
384 		}
385 		fj->last = t;
386 		fj->updated = 0;
387 	}
388 	free(expanded);
389 
390 	if (ft->flags & FORMAT_STATUS)
391 		fj->status = 1;
392 	format_copy_state(&next, es, FORMAT_EXPAND_NOJOBS);
393 	return (format_expand1(&next, fj->out));
394 }
395 
396 /* Remove old jobs. */
397 static void
398 format_job_tidy(struct format_job_tree *jobs, int force)
399 {
400 	struct format_job	*fj, *fj1;
401 	time_t			 now;
402 
403 	now = time(NULL);
404 	RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) {
405 		if (!force && (fj->last > now || now - fj->last < 3600))
406 			continue;
407 		RB_REMOVE(format_job_tree, jobs, fj);
408 
409 		log_debug("%s: %s", __func__, fj->cmd);
410 
411 		if (fj->job != NULL)
412 			job_free(fj->job);
413 
414 		free((void *)fj->expanded);
415 		free((void *)fj->cmd);
416 		free(fj->out);
417 
418 		free(fj);
419 	}
420 }
421 
422 /* Remove old jobs for client. */
423 void
424 format_lost_client(struct client *c)
425 {
426 	if (c->jobs != NULL)
427 		format_job_tidy(c->jobs, 1);
428 	free(c->jobs);
429 }
430 
431 /* Remove old jobs periodically. */
432 static void
433 format_job_timer(__unused int fd, __unused short events, __unused void *arg)
434 {
435 	struct client	*c;
436 	struct timeval	 tv = { .tv_sec = 60 };
437 
438 	format_job_tidy(&format_jobs, 0);
439 	TAILQ_FOREACH(c, &clients, entry) {
440 		if (c->jobs != NULL)
441 			format_job_tidy(c->jobs, 0);
442 	}
443 
444 	evtimer_del(&format_job_event);
445 	evtimer_add(&format_job_event, &tv);
446 }
447 
448 /* Callback for host. */
449 static char *
450 format_cb_host(__unused struct format_tree *ft)
451 {
452 	char host[HOST_NAME_MAX + 1];
453 
454 	if (gethostname(host, sizeof host) != 0)
455 		return (xstrdup(""));
456 	return (xstrdup(host));
457 }
458 
459 /* Callback for host_short. */
460 static char *
461 format_cb_host_short(__unused struct format_tree *ft)
462 {
463 	char host[HOST_NAME_MAX + 1], *cp;
464 
465 	if (gethostname(host, sizeof host) != 0)
466 		return (xstrdup(""));
467 	if ((cp = strchr(host, '.')) != NULL)
468 		*cp = '\0';
469 	return (xstrdup(host));
470 }
471 
472 /* Callback for pid. */
473 static char *
474 format_cb_pid(__unused struct format_tree *ft)
475 {
476 	char	*value;
477 
478 	xasprintf(&value, "%ld", (long)getpid());
479 	return (value);
480 }
481 
482 /* Callback for session_attached_list. */
483 static char *
484 format_cb_session_attached_list(struct format_tree *ft)
485 {
486 	struct session	*s = ft->s;
487 	struct client	*loop;
488 	struct evbuffer	*buffer;
489 	int		 size;
490 	char		*value = NULL;
491 
492 	if (s == NULL)
493 		return (NULL);
494 
495 	buffer = evbuffer_new();
496 	if (buffer == NULL)
497 		fatalx("out of memory");
498 
499 	TAILQ_FOREACH(loop, &clients, entry) {
500 		if (loop->session == s) {
501 			if (EVBUFFER_LENGTH(buffer) > 0)
502 				evbuffer_add(buffer, ",", 1);
503 			evbuffer_add_printf(buffer, "%s", loop->name);
504 		}
505 	}
506 
507 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
508 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
509 	evbuffer_free(buffer);
510 	return (value);
511 }
512 
513 /* Callback for session_alerts. */
514 static char *
515 format_cb_session_alerts(struct format_tree *ft)
516 {
517 	struct session	*s = ft->s;
518 	struct winlink	*wl;
519 	char		 alerts[1024], tmp[16];
520 
521 	if (s == NULL)
522 		return (NULL);
523 
524 	*alerts = '\0';
525 	RB_FOREACH(wl, winlinks, &s->windows) {
526 		if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
527 			continue;
528 		xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
529 
530 		if (*alerts != '\0')
531 			strlcat(alerts, ",", sizeof alerts);
532 		strlcat(alerts, tmp, sizeof alerts);
533 		if (wl->flags & WINLINK_ACTIVITY)
534 			strlcat(alerts, "#", sizeof alerts);
535 		if (wl->flags & WINLINK_BELL)
536 			strlcat(alerts, "!", sizeof alerts);
537 		if (wl->flags & WINLINK_SILENCE)
538 			strlcat(alerts, "~", sizeof alerts);
539 	}
540 	return (xstrdup(alerts));
541 }
542 
543 /* Callback for session_stack. */
544 static char *
545 format_cb_session_stack(struct format_tree *ft)
546 {
547 	struct session	*s = ft->s;
548 	struct winlink	*wl;
549 	char		 result[1024], tmp[16];
550 
551 	if (s == NULL)
552 		return (NULL);
553 
554 	xsnprintf(result, sizeof result, "%u", s->curw->idx);
555 	TAILQ_FOREACH(wl, &s->lastw, sentry) {
556 		xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
557 
558 		if (*result != '\0')
559 			strlcat(result, ",", sizeof result);
560 		strlcat(result, tmp, sizeof result);
561 	}
562 	return (xstrdup(result));
563 }
564 
565 /* Callback for window_stack_index. */
566 static char *
567 format_cb_window_stack_index(struct format_tree *ft)
568 {
569 	struct session	*s = ft->wl->session;
570 	struct winlink	*wl;
571 	u_int		 idx;
572 	char		*value = NULL;
573 
574 	idx = 0;
575 	TAILQ_FOREACH(wl, &s->lastw, sentry) {
576 		idx++;
577 		if (wl == ft->wl)
578 			break;
579 	}
580 	if (wl == NULL)
581 		return (xstrdup("0"));
582 	xasprintf(&value, "%u", idx);
583 	return (value);
584 }
585 
586 /* Callback for window_linked_sessions_list. */
587 static char *
588 format_cb_window_linked_sessions_list(struct format_tree *ft)
589 {
590 	struct window	*w = ft->wl->window;
591 	struct winlink	*wl;
592 	struct evbuffer	*buffer;
593 	int		 size;
594 	char		*value = NULL;
595 
596 	buffer = evbuffer_new();
597 	if (buffer == NULL)
598 		fatalx("out of memory");
599 
600 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
601 		if (EVBUFFER_LENGTH(buffer) > 0)
602 			evbuffer_add(buffer, ",", 1);
603 		evbuffer_add_printf(buffer, "%s", wl->session->name);
604 	}
605 
606 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
607 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
608 	evbuffer_free(buffer);
609 	return (value);
610 }
611 
612 /* Callback for window_active_sessions. */
613 static char *
614 format_cb_window_active_sessions(struct format_tree *ft)
615 {
616 	struct window	*w = ft->wl->window;
617 	struct winlink	*wl;
618 	u_int		 n = 0;
619 	char		*value;
620 
621 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
622 		if (wl->session->curw == wl)
623 			n++;
624 	}
625 
626 	xasprintf(&value, "%u", n);
627 	return (value);
628 }
629 
630 /* Callback for window_active_sessions_list. */
631 static char *
632 format_cb_window_active_sessions_list(struct format_tree *ft)
633 {
634 	struct window	*w = ft->wl->window;
635 	struct winlink	*wl;
636 	struct evbuffer	*buffer;
637 	int		 size;
638 	char		*value = NULL;
639 
640 	buffer = evbuffer_new();
641 	if (buffer == NULL)
642 		fatalx("out of memory");
643 
644 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
645 		if (wl->session->curw == wl) {
646 			if (EVBUFFER_LENGTH(buffer) > 0)
647 				evbuffer_add(buffer, ",", 1);
648 			evbuffer_add_printf(buffer, "%s", wl->session->name);
649 		}
650 	}
651 
652 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
653 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
654 	evbuffer_free(buffer);
655 	return (value);
656 }
657 
658 /* Callback for window_active_clients. */
659 static char *
660 format_cb_window_active_clients(struct format_tree *ft)
661 {
662 	struct window	*w = ft->wl->window;
663 	struct client	*loop;
664 	struct session	*client_session;
665 	u_int		 n = 0;
666 	char		*value;
667 
668 	TAILQ_FOREACH(loop, &clients, entry) {
669 		client_session = loop->session;
670 		if (client_session == NULL)
671 			continue;
672 
673 		if (w == client_session->curw->window)
674 			n++;
675 	}
676 
677 	xasprintf(&value, "%u", n);
678 	return (value);
679 }
680 
681 /* Callback for window_active_clients_list. */
682 static char *
683 format_cb_window_active_clients_list(struct format_tree *ft)
684 {
685 	struct window	*w = ft->wl->window;
686 	struct client	*loop;
687 	struct session	*client_session;
688 	struct evbuffer	*buffer;
689 	int		 size;
690 	char		*value = NULL;
691 
692 	buffer = evbuffer_new();
693 	if (buffer == NULL)
694 		fatalx("out of memory");
695 
696 	TAILQ_FOREACH(loop, &clients, entry) {
697 		client_session = loop->session;
698 		if (client_session == NULL)
699 			continue;
700 
701 		if (w == client_session->curw->window) {
702 			if (EVBUFFER_LENGTH(buffer) > 0)
703 				evbuffer_add(buffer, ",", 1);
704 			evbuffer_add_printf(buffer, "%s", loop->name);
705 		}
706 	}
707 
708 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
709 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
710 	evbuffer_free(buffer);
711 	return (value);
712 }
713 
714 /* Callback for window_layout. */
715 static char *
716 format_cb_window_layout(struct format_tree *ft)
717 {
718 	struct window	*w = ft->w;
719 
720 	if (w == NULL)
721 		return (NULL);
722 
723 	if (w->saved_layout_root != NULL)
724 		return (layout_dump(w->saved_layout_root));
725 	return (layout_dump(w->layout_root));
726 }
727 
728 /* Callback for window_visible_layout. */
729 static char *
730 format_cb_window_visible_layout(struct format_tree *ft)
731 {
732 	struct window	*w = ft->w;
733 
734 	if (w == NULL)
735 		return (NULL);
736 
737 	return (layout_dump(w->layout_root));
738 }
739 
740 /* Callback for pane_start_command. */
741 static char *
742 format_cb_start_command(struct format_tree *ft)
743 {
744 	struct window_pane	*wp = ft->wp;
745 
746 	if (wp == NULL)
747 		return (NULL);
748 
749 	return (cmd_stringify_argv(wp->argc, wp->argv));
750 }
751 
752 /* Callback for pane_current_command. */
753 static char *
754 format_cb_current_command(struct format_tree *ft)
755 {
756 	struct window_pane	*wp = ft->wp;
757 	char			*cmd, *value;
758 
759 	if (wp == NULL || wp->shell == NULL)
760 		return (NULL);
761 
762 	cmd = get_proc_name(wp->fd, wp->tty);
763 	if (cmd == NULL || *cmd == '\0') {
764 		free(cmd);
765 		cmd = cmd_stringify_argv(wp->argc, wp->argv);
766 		if (cmd == NULL || *cmd == '\0') {
767 			free(cmd);
768 			cmd = xstrdup(wp->shell);
769 		}
770 	}
771 	value = parse_window_name(cmd);
772 	free(cmd);
773 	return (value);
774 }
775 
776 /* Callback for pane_current_path. */
777 static char *
778 format_cb_current_path(struct format_tree *ft)
779 {
780 	struct window_pane	*wp = ft->wp;
781 	char			*cwd;
782 
783 	if (wp == NULL)
784 		return (NULL);
785 
786 	cwd = get_proc_cwd(wp->fd);
787 	if (cwd == NULL)
788 		return (NULL);
789 	return (xstrdup(cwd));
790 }
791 
792 /* Callback for history_bytes. */
793 static char *
794 format_cb_history_bytes(struct format_tree *ft)
795 {
796 	struct window_pane	*wp = ft->wp;
797 	struct grid		*gd;
798 	struct grid_line	*gl;
799 	size_t		         size = 0;
800 	u_int			 i;
801 	char			*value;
802 
803 	if (wp == NULL)
804 		return (NULL);
805 	gd = wp->base.grid;
806 
807 	for (i = 0; i < gd->hsize + gd->sy; i++) {
808 		gl = grid_get_line(gd, i);
809 		size += gl->cellsize * sizeof *gl->celldata;
810 		size += gl->extdsize * sizeof *gl->extddata;
811 	}
812 	size += (gd->hsize + gd->sy) * sizeof *gl;
813 
814 	xasprintf(&value, "%zu", size);
815 	return (value);
816 }
817 
818 /* Callback for history_all_bytes. */
819 static char *
820 format_cb_history_all_bytes(struct format_tree *ft)
821 {
822 	struct window_pane	*wp = ft->wp;
823 	struct grid		*gd;
824 	struct grid_line	*gl;
825 	u_int			 i, lines, cells = 0, extended_cells = 0;
826 	char			*value;
827 
828 	if (wp == NULL)
829 		return (NULL);
830 	gd = wp->base.grid;
831 
832 	lines = gd->hsize + gd->sy;
833 	for (i = 0; i < lines; i++) {
834 		gl = grid_get_line(gd, i);
835 		cells += gl->cellsize;
836 		extended_cells += gl->extdsize;
837 	}
838 
839 	xasprintf(&value, "%u,%zu,%u,%zu,%u,%zu", lines,
840 	    lines * sizeof *gl, cells, cells * sizeof *gl->celldata,
841 	    extended_cells, extended_cells * sizeof *gl->extddata);
842 	return (value);
843 }
844 
845 /* Callback for pane_tabs. */
846 static char *
847 format_cb_pane_tabs(struct format_tree *ft)
848 {
849 	struct window_pane	*wp = ft->wp;
850 	struct evbuffer		*buffer;
851 	u_int			 i;
852 	int			 size;
853 	char			*value = NULL;
854 
855 	if (wp == NULL)
856 		return (NULL);
857 
858 	buffer = evbuffer_new();
859 	if (buffer == NULL)
860 		fatalx("out of memory");
861 	for (i = 0; i < wp->base.grid->sx; i++) {
862 		if (!bit_test(wp->base.tabs, i))
863 			continue;
864 
865 		if (EVBUFFER_LENGTH(buffer) > 0)
866 			evbuffer_add(buffer, ",", 1);
867 		evbuffer_add_printf(buffer, "%u", i);
868 	}
869 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
870 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
871 	evbuffer_free(buffer);
872 	return (value);
873 }
874 
875 /* Callback for session_group_list. */
876 static char *
877 format_cb_session_group_list(struct format_tree *ft)
878 {
879 	struct session		*s = ft->s;
880 	struct session_group	*sg;
881 	struct session		*loop;
882 	struct evbuffer		*buffer;
883 	int			 size;
884 	char			*value = NULL;
885 
886 	if (s == NULL)
887 		return (NULL);
888 	sg = session_group_contains(s);
889 	if (sg == NULL)
890 		return (NULL);
891 
892 	buffer = evbuffer_new();
893 	if (buffer == NULL)
894 		fatalx("out of memory");
895 
896 	TAILQ_FOREACH(loop, &sg->sessions, gentry) {
897 		if (EVBUFFER_LENGTH(buffer) > 0)
898 			evbuffer_add(buffer, ",", 1);
899 		evbuffer_add_printf(buffer, "%s", loop->name);
900 	}
901 
902 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
903 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
904 	evbuffer_free(buffer);
905 	return (value);
906 }
907 
908 /* Callback for session_group_attached_list. */
909 static char *
910 format_cb_session_group_attached_list(struct format_tree *ft)
911 {
912 	struct session		*s = ft->s, *client_session, *session_loop;
913 	struct session_group	*sg;
914 	struct client		*loop;
915 	struct evbuffer		*buffer;
916 	int			 size;
917 	char			*value = NULL;
918 
919 	if (s == NULL)
920 		return (NULL);
921 	sg = session_group_contains(s);
922 	if (sg == NULL)
923 		return (NULL);
924 
925 	buffer = evbuffer_new();
926 	if (buffer == NULL)
927 		fatalx("out of memory");
928 
929 	TAILQ_FOREACH(loop, &clients, entry) {
930 		client_session = loop->session;
931 		if (client_session == NULL)
932 			continue;
933 		TAILQ_FOREACH(session_loop, &sg->sessions, gentry) {
934 			if (session_loop == client_session){
935 				if (EVBUFFER_LENGTH(buffer) > 0)
936 					evbuffer_add(buffer, ",", 1);
937 				evbuffer_add_printf(buffer, "%s", loop->name);
938 			}
939 		}
940 	}
941 
942 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
943 		xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
944 	evbuffer_free(buffer);
945 	return (value);
946 }
947 
948 /* Callback for pane_in_mode. */
949 static char *
950 format_cb_pane_in_mode(struct format_tree *ft)
951 {
952 	struct window_pane		*wp = ft->wp;
953 	u_int				 n = 0;
954 	struct window_mode_entry	*wme;
955 	char				*value;
956 
957 	if (wp == NULL)
958 		return (NULL);
959 
960 	TAILQ_FOREACH(wme, &wp->modes, entry)
961 	    n++;
962 	xasprintf(&value, "%u", n);
963 	return (value);
964 }
965 
966 /* Callback for pane_at_top. */
967 static char *
968 format_cb_pane_at_top(struct format_tree *ft)
969 {
970 	struct window_pane	*wp = ft->wp;
971 	struct window		*w;
972 	int			 status, flag;
973 	char			*value;
974 
975 	if (wp == NULL)
976 		return (NULL);
977 	w = wp->window;
978 
979 	status = options_get_number(w->options, "pane-border-status");
980 	if (status == PANE_STATUS_TOP)
981 		flag = (wp->yoff == 1);
982 	else
983 		flag = (wp->yoff == 0);
984 	xasprintf(&value, "%d", flag);
985 	return (value);
986 }
987 
988 /* Callback for pane_at_bottom. */
989 static char *
990 format_cb_pane_at_bottom(struct format_tree *ft)
991 {
992 	struct window_pane	*wp = ft->wp;
993 	struct window		*w;
994 	int			 status, flag;
995 	char			*value;
996 
997 	if (wp == NULL)
998 		return (NULL);
999 	w = wp->window;
1000 
1001 	status = options_get_number(w->options, "pane-border-status");
1002 	if (status == PANE_STATUS_BOTTOM)
1003 		flag = (wp->yoff + wp->sy == w->sy - 1);
1004 	else
1005 		flag = (wp->yoff + wp->sy == w->sy);
1006 	xasprintf(&value, "%d", flag);
1007 	return (value);
1008 }
1009 
1010 /* Callback for cursor_character. */
1011 static char *
1012 format_cb_cursor_character(struct format_tree *ft)
1013 {
1014 	struct window_pane	*wp = ft->wp;
1015 	struct grid_cell	 gc;
1016 	char			*value = NULL;
1017 
1018 	if (wp == NULL)
1019 		return (NULL);
1020 
1021 	grid_view_get_cell(wp->base.grid, wp->base.cx, wp->base.cy, &gc);
1022 	if (~gc.flags & GRID_FLAG_PADDING)
1023 		xasprintf(&value, "%.*s", (int)gc.data.size, gc.data.data);
1024 	return (value);
1025 }
1026 
1027 /* Return word at given coordinates. Caller frees. */
1028 char *
1029 format_grid_word(struct grid *gd, u_int x, u_int y)
1030 {
1031 	const struct grid_line	*gl;
1032 	struct grid_cell	 gc;
1033 	const char		*ws;
1034 	struct utf8_data	*ud = NULL;
1035 	u_int			 end;
1036 	size_t			 size = 0;
1037 	int			 found = 0;
1038 	char			*s = NULL;
1039 
1040 	ws = options_get_string(global_s_options, "word-separators");
1041 
1042 	for (;;) {
1043 		grid_get_cell(gd, x, y, &gc);
1044 		if (gc.flags & GRID_FLAG_PADDING)
1045 			break;
1046 		if (utf8_cstrhas(ws, &gc.data)) {
1047 			found = 1;
1048 			break;
1049 		}
1050 
1051 		if (x == 0) {
1052 			if (y == 0)
1053 				break;
1054 			gl = grid_peek_line(gd, y - 1);
1055 			if (~gl->flags & GRID_LINE_WRAPPED)
1056 				break;
1057 			y--;
1058 			x = grid_line_length(gd, y);
1059 			if (x == 0)
1060 				break;
1061 		}
1062 		x--;
1063 	}
1064 	for (;;) {
1065 		if (found) {
1066 			end = grid_line_length(gd, y);
1067 			if (end == 0 || x == end - 1) {
1068 				if (y == gd->hsize + gd->sy - 1)
1069 					break;
1070 				gl = grid_peek_line(gd, y);
1071 				if (~gl->flags & GRID_LINE_WRAPPED)
1072 					break;
1073 				y++;
1074 				x = 0;
1075 			} else
1076 				x++;
1077 		}
1078 		found = 1;
1079 
1080 		grid_get_cell(gd, x, y, &gc);
1081 		if (gc.flags & GRID_FLAG_PADDING)
1082 			break;
1083 		if (utf8_cstrhas(ws, &gc.data))
1084 			break;
1085 
1086 		ud = xreallocarray(ud, size + 2, sizeof *ud);
1087 		memcpy(&ud[size++], &gc.data, sizeof *ud);
1088 	}
1089 	if (size != 0) {
1090 		ud[size].size = 0;
1091 		s = utf8_tocstr(ud);
1092 		free(ud);
1093 	}
1094 	return (s);
1095 }
1096 
1097 /* Callback for mouse_word. */
1098 static char *
1099 format_cb_mouse_word(struct format_tree *ft)
1100 {
1101 	struct window_pane	*wp;
1102 	struct grid		*gd;
1103 	u_int			 x, y;
1104 	char			*s;
1105 
1106 	if (!ft->m.valid)
1107 		return (NULL);
1108 	wp = cmd_mouse_pane(&ft->m, NULL, NULL);
1109 	if (wp == NULL)
1110 		return (NULL);
1111 	if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
1112 		return (NULL);
1113 
1114 	if (!TAILQ_EMPTY(&wp->modes)) {
1115 		if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode ||
1116 		    TAILQ_FIRST(&wp->modes)->mode == &window_view_mode)
1117 			return (s = window_copy_get_word(wp, x, y));
1118 		return (NULL);
1119 	}
1120 	gd = wp->base.grid;
1121 	return (format_grid_word(gd, x, gd->hsize + y));
1122 }
1123 
1124 /* Return line at given coordinates. Caller frees. */
1125 char *
1126 format_grid_line(struct grid *gd, u_int y)
1127 {
1128 	struct grid_cell	 gc;
1129 	struct utf8_data	*ud = NULL;
1130 	u_int			 x;
1131 	size_t			 size = 0;
1132 	char			*s = NULL;
1133 
1134 	for (x = 0; x < grid_line_length(gd, y); x++) {
1135 		grid_get_cell(gd, x, y, &gc);
1136 		if (gc.flags & GRID_FLAG_PADDING)
1137 			break;
1138 
1139 		ud = xreallocarray(ud, size + 2, sizeof *ud);
1140 		memcpy(&ud[size++], &gc.data, sizeof *ud);
1141 	}
1142 	if (size != 0) {
1143 		ud[size].size = 0;
1144 		s = utf8_tocstr(ud);
1145 		free(ud);
1146 	}
1147 	return (s);
1148 }
1149 
1150 /* Callback for mouse_line. */
1151 static char *
1152 format_cb_mouse_line(struct format_tree *ft)
1153 {
1154 	struct window_pane	*wp;
1155 	struct grid		*gd;
1156 	u_int			 x, y;
1157 
1158 	if (!ft->m.valid)
1159 		return (NULL);
1160 	wp = cmd_mouse_pane(&ft->m, NULL, NULL);
1161 	if (wp == NULL)
1162 		return (NULL);
1163 	if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
1164 		return (NULL);
1165 
1166 	if (!TAILQ_EMPTY(&wp->modes)) {
1167 		if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode ||
1168 		    TAILQ_FIRST(&wp->modes)->mode == &window_view_mode)
1169 			return (window_copy_get_line(wp, y));
1170 		return (NULL);
1171 	}
1172 	gd = wp->base.grid;
1173 	return (format_grid_line(gd, gd->hsize + y));
1174 }
1175 
1176 /* Merge one format tree into another. */
1177 void
1178 format_merge(struct format_tree *ft, struct format_tree *from)
1179 {
1180 	struct format_entry	*fe;
1181 
1182 	RB_FOREACH(fe, format_entry_tree, &from->tree) {
1183 		if (fe->value != NULL)
1184 			format_add(ft, fe->key, "%s", fe->value);
1185 	}
1186 }
1187 
1188 /* Get format pane. */
1189 struct window_pane *
1190 format_get_pane(struct format_tree *ft)
1191 {
1192 	return (ft->wp);
1193 }
1194 
1195 /* Add item bits to tree. */
1196 static void
1197 format_create_add_item(struct format_tree *ft, struct cmdq_item *item)
1198 {
1199 	struct key_event	*event = cmdq_get_event(item);
1200 	struct mouse_event	*m = &event->m;
1201 	struct window_pane	*wp;
1202 	u_int			 x, y;
1203 
1204 	cmdq_merge_formats(item, ft);
1205 
1206 	if (m->valid && ((wp = cmd_mouse_pane(m, NULL, NULL)) != NULL)) {
1207 		format_add(ft, "mouse_pane", "%%%u", wp->id);
1208 		if (cmd_mouse_at(wp, m, &x, &y, 0) == 0) {
1209 			format_add(ft, "mouse_x", "%u", x);
1210 			format_add(ft, "mouse_y", "%u", y);
1211 			format_add_cb(ft, "mouse_word", format_cb_mouse_word);
1212 			format_add_cb(ft, "mouse_line", format_cb_mouse_line);
1213 		}
1214 	}
1215 	memcpy(&ft->m, m, sizeof ft->m);
1216 }
1217 
1218 /* Create a new tree. */
1219 struct format_tree *
1220 format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
1221 {
1222 	struct format_tree		 *ft;
1223 	const struct window_mode	**wm;
1224 	char				  tmp[64];
1225 
1226 	if (!event_initialized(&format_job_event)) {
1227 		evtimer_set(&format_job_event, format_job_timer, NULL);
1228 		format_job_timer(-1, 0, NULL);
1229 	}
1230 
1231 	ft = xcalloc(1, sizeof *ft);
1232 	RB_INIT(&ft->tree);
1233 
1234 	if (c != NULL) {
1235 		ft->client = c;
1236 		ft->client->references++;
1237 	}
1238 	ft->item = item;
1239 
1240 	ft->tag = tag;
1241 	ft->flags = flags;
1242 
1243 	format_add(ft, "version", "%s", getversion());
1244 	format_add_cb(ft, "host", format_cb_host);
1245 	format_add_cb(ft, "host_short", format_cb_host_short);
1246 	format_add_cb(ft, "pid", format_cb_pid);
1247 	format_add(ft, "socket_path", "%s", socket_path);
1248 	format_add_tv(ft, "start_time", &start_time);
1249 
1250 	for (wm = all_window_modes; *wm != NULL; wm++) {
1251 		if ((*wm)->default_format != NULL) {
1252 			xsnprintf(tmp, sizeof tmp, "%s_format", (*wm)->name);
1253 			tmp[strcspn(tmp, "-")] = '_';
1254 			format_add(ft, tmp, "%s", (*wm)->default_format);
1255 		}
1256 	}
1257 
1258 	if (item != NULL)
1259 		format_create_add_item(ft, item);
1260 
1261 	return (ft);
1262 }
1263 
1264 /* Free a tree. */
1265 void
1266 format_free(struct format_tree *ft)
1267 {
1268 	struct format_entry	*fe, *fe1;
1269 
1270 	RB_FOREACH_SAFE(fe, format_entry_tree, &ft->tree, fe1) {
1271 		RB_REMOVE(format_entry_tree, &ft->tree, fe);
1272 		free(fe->value);
1273 		free(fe->key);
1274 		free(fe);
1275 	}
1276 
1277 	if (ft->client != NULL)
1278 		server_client_unref(ft->client);
1279 	free(ft);
1280 }
1281 
1282 /* Walk each format. */
1283 void
1284 format_each(struct format_tree *ft, void (*cb)(const char *, const char *,
1285     void *), void *arg)
1286 {
1287 	struct format_entry	*fe;
1288 	char			 s[64];
1289 
1290 	RB_FOREACH(fe, format_entry_tree, &ft->tree) {
1291 		if (fe->time != 0) {
1292 			xsnprintf(s, sizeof s, "%lld", (long long)fe->time);
1293 			cb(fe->key, s, arg);
1294 		} else {
1295 			if (fe->value == NULL && fe->cb != NULL) {
1296 				fe->value = fe->cb(ft);
1297 				if (fe->value == NULL)
1298 					fe->value = xstrdup("");
1299 			}
1300 			cb(fe->key, fe->value, arg);
1301 		}
1302 	}
1303 }
1304 
1305 /* Add a key-value pair. */
1306 void
1307 format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
1308 {
1309 	struct format_entry	*fe;
1310 	struct format_entry	*fe_now;
1311 	va_list			 ap;
1312 
1313 	fe = xmalloc(sizeof *fe);
1314 	fe->key = xstrdup(key);
1315 
1316 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
1317 	if (fe_now != NULL) {
1318 		free(fe->key);
1319 		free(fe);
1320 		free(fe_now->value);
1321 		fe = fe_now;
1322 	}
1323 
1324 	fe->cb = NULL;
1325 	fe->time = 0;
1326 
1327 	va_start(ap, fmt);
1328 	xvasprintf(&fe->value, fmt, ap);
1329 	va_end(ap);
1330 }
1331 
1332 /* Add a key and time. */
1333 void
1334 format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
1335 {
1336 	struct format_entry	*fe, *fe_now;
1337 
1338 	fe = xmalloc(sizeof *fe);
1339 	fe->key = xstrdup(key);
1340 
1341 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
1342 	if (fe_now != NULL) {
1343 		free(fe->key);
1344 		free(fe);
1345 		free(fe_now->value);
1346 		fe = fe_now;
1347 	}
1348 
1349 	fe->cb = NULL;
1350 	fe->time = tv->tv_sec;
1351 
1352 	fe->value = NULL;
1353 }
1354 
1355 /* Add a key and function. */
1356 void
1357 format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
1358 {
1359 	struct format_entry	*fe;
1360 	struct format_entry	*fe_now;
1361 
1362 	fe = xmalloc(sizeof *fe);
1363 	fe->key = xstrdup(key);
1364 
1365 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
1366 	if (fe_now != NULL) {
1367 		free(fe->key);
1368 		free(fe);
1369 		free(fe_now->value);
1370 		fe = fe_now;
1371 	}
1372 
1373 	fe->cb = cb;
1374 	fe->time = 0;
1375 
1376 	fe->value = NULL;
1377 }
1378 
1379 /* Quote special characters in string. */
1380 static char *
1381 format_quote(const char *s)
1382 {
1383 	const char	*cp;
1384 	char		*out, *at;
1385 
1386 	at = out = xmalloc(strlen(s) * 2 + 1);
1387 	for (cp = s; *cp != '\0'; cp++) {
1388 		if (strchr("|&;<>()$`\\\"'*?[# =%", *cp) != NULL)
1389 			*at++ = '\\';
1390 		*at++ = *cp;
1391 	}
1392 	*at = '\0';
1393 	return (out);
1394 }
1395 
1396 /* Make a prettier time. */
1397 static char *
1398 format_pretty_time(time_t t)
1399 {
1400 	struct tm       now_tm, tm;
1401 	time_t		now, age;
1402 	char		s[6];
1403 
1404 	time(&now);
1405 	if (now < t)
1406 		now = t;
1407 	age = now - t;
1408 
1409 	localtime_r(&now, &now_tm);
1410 	localtime_r(&t, &tm);
1411 
1412 	/* Last 24 hours. */
1413 	if (age < 24 * 3600) {
1414 		strftime(s, sizeof s, "%H:%M", &tm);
1415 		return (xstrdup(s));
1416 	}
1417 
1418 	/* This month or last 28 days. */
1419 	if ((tm.tm_year == now_tm.tm_year && tm.tm_mon == now_tm.tm_mon) ||
1420 	    age < 28 * 24 * 3600) {
1421 		strftime(s, sizeof s, "%a%d", &tm);
1422 		return (xstrdup(s));
1423 	}
1424 
1425 	/* Last 12 months. */
1426 	if ((tm.tm_year == now_tm.tm_year && tm.tm_mon < now_tm.tm_mon) ||
1427 	    (tm.tm_year == now_tm.tm_year - 1 && tm.tm_mon > now_tm.tm_mon)) {
1428 		strftime(s, sizeof s, "%d%b", &tm);
1429 		return (xstrdup(s));
1430 	}
1431 
1432 	/* Older than that. */
1433 	strftime(s, sizeof s, "%h%y", &tm);
1434 	return (xstrdup(s));
1435 }
1436 
1437 /* Find a format entry. */
1438 static char *
1439 format_find(struct format_tree *ft, const char *key, int modifiers,
1440     const char *time_format)
1441 {
1442 	struct format_entry	*fe, fe_find;
1443 	struct environ_entry	*envent;
1444 	struct options_entry	*o;
1445 	int			 idx;
1446 	char			*found = NULL, *saved, s[512];
1447 	const char		*errstr;
1448 	time_t			 t = 0;
1449 	struct tm		 tm;
1450 
1451 	o = options_parse_get(global_options, key, &idx, 0);
1452 	if (o == NULL && ft->wp != NULL)
1453 		o = options_parse_get(ft->wp->options, key, &idx, 0);
1454 	if (o == NULL && ft->w != NULL)
1455 		o = options_parse_get(ft->w->options, key, &idx, 0);
1456 	if (o == NULL)
1457 		o = options_parse_get(global_w_options, key, &idx, 0);
1458 	if (o == NULL && ft->s != NULL)
1459 		o = options_parse_get(ft->s->options, key, &idx, 0);
1460 	if (o == NULL)
1461 		o = options_parse_get(global_s_options, key, &idx, 0);
1462 	if (o != NULL) {
1463 		found = options_to_string(o, idx, 1);
1464 		goto found;
1465 	}
1466 
1467 	fe_find.key = (char *)key;
1468 	fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
1469 	if (fe != NULL) {
1470 		if (fe->time != 0) {
1471 			t = fe->time;
1472 			goto found;
1473 		}
1474 		if (fe->value == NULL && fe->cb != NULL) {
1475 			fe->value = fe->cb(ft);
1476 			if (fe->value == NULL)
1477 				fe->value = xstrdup("");
1478 		}
1479 		found = xstrdup(fe->value);
1480 		goto found;
1481 	}
1482 
1483 	if (~modifiers & FORMAT_TIMESTRING) {
1484 		envent = NULL;
1485 		if (ft->s != NULL)
1486 			envent = environ_find(ft->s->environ, key);
1487 		if (envent == NULL)
1488 			envent = environ_find(global_environ, key);
1489 		if (envent != NULL && envent->value != NULL) {
1490 			found = xstrdup(envent->value);
1491 			goto found;
1492 		}
1493 	}
1494 
1495 	return (NULL);
1496 
1497 found:
1498 	if (modifiers & FORMAT_TIMESTRING) {
1499 		if (t == 0 && found != NULL) {
1500 			t = strtonum(found, 0, INT64_MAX, &errstr);
1501 			if (errstr != NULL)
1502 				t = 0;
1503 			free(found);
1504 		}
1505 		if (t == 0)
1506 			return (NULL);
1507 		if (modifiers & FORMAT_PRETTY)
1508 			found = format_pretty_time(t);
1509 		else {
1510 			if (time_format != NULL) {
1511 				localtime_r(&t, &tm);
1512 				strftime(s, sizeof s, time_format, &tm);
1513 			} else {
1514 				ctime_r(&t, s);
1515 				s[strcspn(s, "\n")] = '\0';
1516 			}
1517 			found = xstrdup(s);
1518 		}
1519 		return (found);
1520 	}
1521 
1522 	if (t != 0)
1523 		xasprintf(&found, "%lld", (long long)t);
1524 	else if (found == NULL)
1525 		return (NULL);
1526 	if (modifiers & FORMAT_BASENAME) {
1527 		saved = found;
1528 		found = xstrdup(basename(saved));
1529 		free(saved);
1530 	}
1531 	if (modifiers & FORMAT_DIRNAME) {
1532 		saved = found;
1533 		found = xstrdup(dirname(saved));
1534 		free(saved);
1535 	}
1536 	if (modifiers & FORMAT_QUOTE) {
1537 		saved = found;
1538 		found = xstrdup(format_quote(saved));
1539 		free(saved);
1540 	}
1541 	return (found);
1542 }
1543 
1544 /* Remove escaped characters from string. */
1545 static char *
1546 format_strip(const char *s)
1547 {
1548 	char	*out, *cp;
1549 	int	 brackets = 0;
1550 
1551 	cp = out = xmalloc(strlen(s) + 1);
1552 	for (; *s != '\0'; s++) {
1553 		if (*s == '#' && s[1] == '{')
1554 			brackets++;
1555 		if (*s == '#' && strchr(",#{}:", s[1]) != NULL) {
1556 			if (brackets != 0)
1557 				*cp++ = *s;
1558 			continue;
1559 		}
1560 		if (*s == '}')
1561 			brackets--;
1562 		*cp++ = *s;
1563 	}
1564 	*cp = '\0';
1565 	return (out);
1566 }
1567 
1568 /* Skip until end. */
1569 const char *
1570 format_skip(const char *s, const char *end)
1571 {
1572 	int	brackets = 0;
1573 
1574 	for (; *s != '\0'; s++) {
1575 		if (*s == '#' && s[1] == '{')
1576 			brackets++;
1577 		if (*s == '#' && strchr(",#{}:", s[1]) != NULL) {
1578 			s++;
1579 			continue;
1580 		}
1581 		if (*s == '}')
1582 			brackets--;
1583 		if (strchr(end, *s) != NULL && brackets == 0)
1584 			break;
1585 	}
1586 	if (*s == '\0')
1587 		return (NULL);
1588 	return (s);
1589 }
1590 
1591 /* Return left and right alternatives separated by commas. */
1592 static int
1593 format_choose(struct format_expand_state *es, const char *s, char **left,
1594     char **right, int expand)
1595 {
1596 	const char	*cp;
1597 	char		*left0, *right0;
1598 
1599 	cp = format_skip(s, ",");
1600 	if (cp == NULL)
1601 		return (-1);
1602 	left0 = xstrndup(s, cp - s);
1603 	right0 = xstrdup(cp + 1);
1604 
1605 	if (expand) {
1606 		*left = format_expand1(es, left0);
1607 		free(left0);
1608 		*right = format_expand1(es, right0);
1609 		free(right0);
1610 	} else {
1611 		*left = left0;
1612 		*right = right0;
1613 	}
1614 	return (0);
1615 }
1616 
1617 /* Is this true? */
1618 int
1619 format_true(const char *s)
1620 {
1621 	if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0'))
1622 		return (1);
1623 	return (0);
1624 }
1625 
1626 /* Check if modifier end. */
1627 static int
1628 format_is_end(char c)
1629 {
1630 	return (c == ';' || c == ':');
1631 }
1632 
1633 /* Add to modifier list. */
1634 static void
1635 format_add_modifier(struct format_modifier **list, u_int *count,
1636     const char *c, size_t n, char **argv, int argc)
1637 {
1638 	struct format_modifier *fm;
1639 
1640 	*list = xreallocarray(*list, (*count) + 1, sizeof **list);
1641 	fm = &(*list)[(*count)++];
1642 
1643 	memcpy(fm->modifier, c, n);
1644 	fm->modifier[n] = '\0';
1645 	fm->size = n;
1646 
1647 	fm->argv = argv;
1648 	fm->argc = argc;
1649 }
1650 
1651 /* Free modifier list. */
1652 static void
1653 format_free_modifiers(struct format_modifier *list, u_int count)
1654 {
1655 	u_int	i;
1656 
1657 	for (i = 0; i < count; i++)
1658 		cmd_free_argv(list[i].argc, list[i].argv);
1659 	free(list);
1660 }
1661 
1662 /* Build modifier list. */
1663 static struct format_modifier *
1664 format_build_modifiers(struct format_expand_state *es, const char **s,
1665     u_int *count)
1666 {
1667 	const char		*cp = *s, *end;
1668 	struct format_modifier	*list = NULL;
1669 	char			 c, last[] = "X;:", **argv, *value;
1670 	int			 argc;
1671 
1672 	/*
1673 	 * Modifiers are a ; separated list of the forms:
1674 	 *      l,m,C,b,d,n,t,q,E,T,S,W,P,<,>
1675 	 *	=a
1676 	 *	=/a
1677 	 *      =/a/
1678 	 *	s/a/b/
1679 	 *	s/a/b
1680 	 *	||,&&,!=,==,<=,>=
1681 	 */
1682 
1683 	*count = 0;
1684 
1685 	while (*cp != '\0' && *cp != ':') {
1686 		/* Skip any separator character. */
1687 		if (*cp == ';')
1688 			cp++;
1689 
1690 		/* Check single character modifiers with no arguments. */
1691 		if (strchr("lbdnqETSWP<>", cp[0]) != NULL &&
1692 		    format_is_end(cp[1])) {
1693 			format_add_modifier(&list, count, cp, 1, NULL, 0);
1694 			cp++;
1695 			continue;
1696 		}
1697 
1698 		/* Then try double character with no arguments. */
1699 		if ((memcmp("||", cp, 2) == 0 ||
1700 		    memcmp("&&", cp, 2) == 0 ||
1701 		    memcmp("!=", cp, 2) == 0 ||
1702 		    memcmp("==", cp, 2) == 0 ||
1703 		    memcmp("<=", cp, 2) == 0 ||
1704 		    memcmp(">=", cp, 2) == 0) &&
1705 		    format_is_end(cp[2])) {
1706 			format_add_modifier(&list, count, cp, 2, NULL, 0);
1707 			cp += 2;
1708 			continue;
1709 		}
1710 
1711 		/* Now try single character with arguments. */
1712 		if (strchr("mCst=pe", cp[0]) == NULL)
1713 			break;
1714 		c = cp[0];
1715 
1716 		/* No arguments provided. */
1717 		if (format_is_end(cp[1])) {
1718 			format_add_modifier(&list, count, cp, 1, NULL, 0);
1719 			cp++;
1720 			continue;
1721 		}
1722 		argv = NULL;
1723 		argc = 0;
1724 
1725 		/* Single argument with no wrapper character. */
1726 		if (!ispunct(cp[1]) || cp[1] == '-') {
1727 			end = format_skip(cp + 1, ":;");
1728 			if (end == NULL)
1729 				break;
1730 
1731 			argv = xcalloc(1, sizeof *argv);
1732 			value = xstrndup(cp + 1, end - (cp + 1));
1733 			argv[0] = format_expand1(es, value);
1734 			free(value);
1735 			argc = 1;
1736 
1737 			format_add_modifier(&list, count, &c, 1, argv, argc);
1738 			cp = end;
1739 			continue;
1740 		}
1741 
1742 		/* Multiple arguments with a wrapper character. */
1743 		last[0] = cp[1];
1744 		cp++;
1745 		do {
1746 			if (cp[0] == last[0] && format_is_end(cp[1])) {
1747 				cp++;
1748 				break;
1749 			}
1750 			end = format_skip(cp + 1, last);
1751 			if (end == NULL)
1752 				break;
1753 			cp++;
1754 
1755 			argv = xreallocarray (argv, argc + 1, sizeof *argv);
1756 			value = xstrndup(cp, end - cp);
1757 			argv[argc++] = format_expand1(es, value);
1758 			free(value);
1759 
1760 			cp = end;
1761 		} while (!format_is_end(cp[0]));
1762 		format_add_modifier(&list, count, &c, 1, argv, argc);
1763 	}
1764 	if (*cp != ':') {
1765 		format_free_modifiers(list, *count);
1766 		*count = 0;
1767 		return (NULL);
1768 	}
1769 	*s = cp + 1;
1770 	return (list);
1771 }
1772 
1773 /* Match against an fnmatch(3) pattern or regular expression. */
1774 static char *
1775 format_match(struct format_modifier *fm, const char *pattern, const char *text)
1776 {
1777 	const char	*s = "";
1778 	regex_t		 r;
1779 	int		 flags = 0;
1780 
1781 	if (fm->argc >= 1)
1782 		s = fm->argv[0];
1783 	if (strchr(s, 'r') == NULL) {
1784 		if (strchr(s, 'i') != NULL)
1785 			flags |= FNM_CASEFOLD;
1786 		if (fnmatch(pattern, text, flags) != 0)
1787 			return (xstrdup("0"));
1788 	} else {
1789 		flags = REG_EXTENDED|REG_NOSUB;
1790 		if (strchr(s, 'i') != NULL)
1791 			flags |= REG_ICASE;
1792 		if (regcomp(&r, pattern, flags) != 0)
1793 			return (xstrdup("0"));
1794 		if (regexec(&r, text, 0, NULL, 0) != 0) {
1795 			regfree(&r);
1796 			return (xstrdup("0"));
1797 		}
1798 		regfree(&r);
1799 	}
1800 	return (xstrdup("1"));
1801 }
1802 
1803 /* Perform substitution in string. */
1804 static char *
1805 format_sub(struct format_modifier *fm, const char *text, const char *pattern,
1806     const char *with)
1807 {
1808 	char	*value;
1809 	int	 flags = REG_EXTENDED;
1810 
1811 	if (fm->argc >= 3 && strchr(fm->argv[2], 'i') != NULL)
1812 		flags |= REG_ICASE;
1813 	value = regsub(pattern, with, text, flags);
1814 	if (value == NULL)
1815 		return (xstrdup(text));
1816 	return (value);
1817 }
1818 
1819 /* Search inside pane. */
1820 static char *
1821 format_search(struct format_modifier *fm, struct window_pane *wp, const char *s)
1822 {
1823 	int	 ignore = 0, regex = 0;
1824 	char	*value;
1825 
1826 	if (fm->argc >= 1) {
1827 		if (strchr(fm->argv[0], 'i') != NULL)
1828 			ignore = 1;
1829 		if (strchr(fm->argv[0], 'r') != NULL)
1830 			regex = 1;
1831 	}
1832 	xasprintf(&value, "%u", window_pane_search(wp, s, regex, ignore));
1833 	return (value);
1834 }
1835 
1836 /* Loop over sessions. */
1837 static char *
1838 format_loop_sessions(struct format_expand_state *es, const char *fmt)
1839 {
1840 	struct format_tree		*ft = es->ft;
1841 	struct client			*c = ft->client;
1842 	struct cmdq_item		*item = ft->item;
1843 	struct format_tree		*nft;
1844 	struct format_expand_state	 next;
1845 	char				*expanded, *value;
1846 	size_t				 valuelen;
1847 	struct session			*s;
1848 
1849 	value = xcalloc(1, 1);
1850 	valuelen = 1;
1851 
1852 	RB_FOREACH(s, sessions, &sessions) {
1853 		format_log(es, "session loop: $%u", s->id);
1854 		nft = format_create(c, item, FORMAT_NONE, ft->flags);
1855 		format_defaults(next.ft, ft->c, s, NULL, NULL);
1856 		format_copy_state(&next, es, 0);
1857 		next.ft = nft;
1858 		expanded = format_expand1(&next, fmt);
1859 		format_free(next.ft);
1860 
1861 		valuelen += strlen(expanded);
1862 		value = xrealloc(value, valuelen);
1863 
1864 		strlcat(value, expanded, valuelen);
1865 		free(expanded);
1866 	}
1867 
1868 	return (value);
1869 }
1870 
1871 /* Loop over windows. */
1872 static char *
1873 format_loop_windows(struct format_expand_state *es, const char *fmt)
1874 {
1875 	struct format_tree		*ft = es->ft;
1876 	struct client			*c = ft->client;
1877 	struct cmdq_item		*item = ft->item;
1878 	struct format_tree		*nft;
1879 	struct format_expand_state	 next;
1880 	char				*all, *active, *use, *expanded, *value;
1881 	size_t				 valuelen;
1882 	struct winlink			*wl;
1883 	struct window			*w;
1884 
1885 	if (ft->s == NULL) {
1886 		format_log(es, "window loop but no session");
1887 		return (NULL);
1888 	}
1889 
1890 	if (format_choose(es, fmt, &all, &active, 0) != 0) {
1891 		all = xstrdup(fmt);
1892 		active = NULL;
1893 	}
1894 
1895 	value = xcalloc(1, 1);
1896 	valuelen = 1;
1897 
1898 	RB_FOREACH(wl, winlinks, &ft->s->windows) {
1899 		w = wl->window;
1900 		format_log(es, "window loop: %u @%u", wl->idx, w->id);
1901 		if (active != NULL && wl == ft->s->curw)
1902 			use = active;
1903 		else
1904 			use = all;
1905 		nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags);
1906 		format_defaults(nft, ft->c, ft->s, wl, NULL);
1907 		format_copy_state(&next, es, 0);
1908 		next.ft = nft;
1909 		expanded = format_expand1(&next, use);
1910 		format_free(nft);
1911 
1912 		valuelen += strlen(expanded);
1913 		value = xrealloc(value, valuelen);
1914 
1915 		strlcat(value, expanded, valuelen);
1916 		free(expanded);
1917 	}
1918 
1919 	free(active);
1920 	free(all);
1921 
1922 	return (value);
1923 }
1924 
1925 /* Loop over panes. */
1926 static char *
1927 format_loop_panes(struct format_expand_state *es, const char *fmt)
1928 {
1929 	struct format_tree		*ft = es->ft;
1930 	struct client			*c = ft->client;
1931 	struct cmdq_item		*item = ft->item;
1932 	struct format_tree		*nft;
1933 	struct format_expand_state	 next;
1934 	char				*all, *active, *use, *expanded, *value;
1935 	size_t				 valuelen;
1936 	struct window_pane		*wp;
1937 
1938 	if (ft->w == NULL) {
1939 		format_log(es, "pane loop but no window");
1940 		return (NULL);
1941 	}
1942 
1943 	if (format_choose(es, fmt, &all, &active, 0) != 0) {
1944 		all = xstrdup(fmt);
1945 		active = NULL;
1946 	}
1947 
1948 	value = xcalloc(1, 1);
1949 	valuelen = 1;
1950 
1951 	TAILQ_FOREACH(wp, &ft->w->panes, entry) {
1952 		format_log(es, "pane loop: %%%u", wp->id);
1953 		if (active != NULL && wp == ft->w->active)
1954 			use = active;
1955 		else
1956 			use = all;
1957 		nft = format_create(c, item, FORMAT_PANE|wp->id, ft->flags);
1958 		format_defaults(nft, ft->c, ft->s, ft->wl, wp);
1959 		format_copy_state(&next, es, 0);
1960 		next.ft = nft;
1961 		expanded = format_expand1(&next, use);
1962 		format_free(nft);
1963 
1964 		valuelen += strlen(expanded);
1965 		value = xrealloc(value, valuelen);
1966 
1967 		strlcat(value, expanded, valuelen);
1968 		free(expanded);
1969 	}
1970 
1971 	free(active);
1972 	free(all);
1973 
1974 	return (value);
1975 }
1976 
1977 static char *
1978 format_replace_expression(struct format_modifier *mexp,
1979     struct format_expand_state *es, const char *copy)
1980 {
1981 	int			 argc = mexp->argc;
1982 	const char		*errstr;
1983 	char			*endch, *value, *left = NULL, *right = NULL;
1984 	int			 use_fp = 0;
1985 	u_int			 prec = 0;
1986 	double			 mleft, mright, result;
1987 	enum { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULUS } operator;
1988 
1989 	if (strcmp(mexp->argv[0], "+") == 0)
1990 		operator = ADD;
1991 	else if (strcmp(mexp->argv[0], "-") == 0)
1992 		operator = SUBTRACT;
1993 	else if (strcmp(mexp->argv[0], "*") == 0)
1994 		operator = MULTIPLY;
1995 	else if (strcmp(mexp->argv[0], "/") == 0)
1996 		operator = DIVIDE;
1997 	else if (strcmp(mexp->argv[0], "%") == 0 ||
1998 	    strcmp(mexp->argv[0], "m") == 0)
1999 		operator = MODULUS;
2000 	else {
2001 		format_log(es, "expression has no valid operator: '%s'",
2002 		    mexp->argv[0]);
2003 		goto fail;
2004 	}
2005 
2006 	/* The second argument may be flags. */
2007 	if (argc >= 2 && strchr(mexp->argv[1], 'f') != NULL) {
2008 		use_fp = 1;
2009 		prec = 2;
2010 	}
2011 
2012 	/* The third argument may be precision. */
2013 	if (argc >= 3) {
2014 		prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr);
2015 		if (errstr != NULL) {
2016 			format_log(es, "expression precision %s: %s", errstr,
2017 			    mexp->argv[2]);
2018 			goto fail;
2019 		}
2020 	}
2021 
2022 	if (format_choose(es, copy, &left, &right, 1) != 0) {
2023 		format_log(es, "expression syntax error");
2024 		goto fail;
2025 	}
2026 
2027 	mleft = strtod(left, &endch);
2028 	if (*endch != '\0') {
2029 		format_log(es, "expression left side is invalid: %s", left);
2030 		goto fail;
2031 	}
2032 
2033 	mright = strtod(right, &endch);
2034 	if (*endch != '\0') {
2035 		format_log(es, "expression right side is invalid: %s", right);
2036 		goto fail;
2037 	}
2038 
2039 	if (!use_fp) {
2040 		mleft = (long long)mleft;
2041 		mright = (long long)mright;
2042 	}
2043 	format_log(es, "expression left side is: %.*f", prec, mleft);
2044 	format_log(es, "expression right side is:  %.*f", prec, mright);
2045 
2046 	switch (operator) {
2047 	case ADD:
2048 		result = mleft + mright;
2049 		break;
2050 	case SUBTRACT:
2051 		result = mleft - mright;
2052 		break;
2053 	case MULTIPLY:
2054 		result = mleft * mright;
2055 		break;
2056 	case DIVIDE:
2057 		result = mleft / mright;
2058 		break;
2059 	case MODULUS:
2060 		result = fmod(mleft, mright);
2061 		break;
2062 	}
2063 	if (use_fp)
2064 		xasprintf(&value, "%.*f", prec, result);
2065 	else
2066 		xasprintf(&value, "%.*f", prec, (double)(long long)result);
2067 	format_log(es, "expression result is %s", value);
2068 
2069 	free(right);
2070 	free(left);
2071 	return (value);
2072 
2073 fail:
2074 	free(right);
2075 	free(left);
2076 	return (NULL);
2077 }
2078 
2079 /* Replace a key. */
2080 static int
2081 format_replace(struct format_expand_state *es, const char *key, size_t keylen,
2082     char **buf, size_t *len, size_t *off)
2083 {
2084 	struct format_tree		 *ft = es->ft;
2085 	struct window_pane		 *wp = ft->wp;
2086 	const char			 *errptr, *copy, *cp, *marker = NULL;
2087 	const char			 *time_format = NULL;
2088 	char				 *copy0, *condition, *found, *new;
2089 	char				 *value, *left, *right;
2090 	size_t				  valuelen;
2091 	int				  modifiers = 0, limit = 0, width = 0;
2092 	int				  j;
2093 	struct format_modifier		 *list, *cmp = NULL, *search = NULL;
2094 	struct format_modifier		**sub = NULL, *mexp = NULL, *fm;
2095 	u_int				  i, count, nsub = 0;
2096 	struct format_expand_state	  next;
2097 
2098 	/* Make a copy of the key. */
2099 	copy = copy0 = xstrndup(key, keylen);
2100 
2101 	/* Process modifier list. */
2102 	list = format_build_modifiers(es, &copy, &count);
2103 	for (i = 0; i < count; i++) {
2104 		fm = &list[i];
2105 		if (format_logging(ft)) {
2106 			format_log(es, "modifier %u is %s", i, fm->modifier);
2107 			for (j = 0; j < fm->argc; j++) {
2108 				format_log(es, "modifier %u argument %d: %s", i,
2109 				    j, fm->argv[j]);
2110 			}
2111 		}
2112 		if (fm->size == 1) {
2113 			switch (fm->modifier[0]) {
2114 			case 'm':
2115 			case '<':
2116 			case '>':
2117 				cmp = fm;
2118 				break;
2119 			case 'C':
2120 				search = fm;
2121 				break;
2122 			case 's':
2123 				if (fm->argc < 2)
2124 					break;
2125 				sub = xreallocarray (sub, nsub + 1,
2126 				    sizeof *sub);
2127 				sub[nsub++] = fm;
2128 				break;
2129 			case '=':
2130 				if (fm->argc < 1)
2131 					break;
2132 				limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
2133 				    &errptr);
2134 				if (errptr != NULL)
2135 					limit = 0;
2136 				if (fm->argc >= 2 && fm->argv[1] != NULL)
2137 					marker = fm->argv[1];
2138 				break;
2139 			case 'p':
2140 				if (fm->argc < 1)
2141 					break;
2142 				width = strtonum(fm->argv[0], INT_MIN, INT_MAX,
2143 				    &errptr);
2144 				if (errptr != NULL)
2145 					width = 0;
2146 				break;
2147 			case 'e':
2148 				if (fm->argc < 1 || fm->argc > 3)
2149 					break;
2150 				mexp = fm;
2151 				break;
2152 			case 'l':
2153 				modifiers |= FORMAT_LITERAL;
2154 				break;
2155 			case 'b':
2156 				modifiers |= FORMAT_BASENAME;
2157 				break;
2158 			case 'd':
2159 				modifiers |= FORMAT_DIRNAME;
2160 				break;
2161 			case 'n':
2162 				modifiers |= FORMAT_LENGTH;
2163 				break;
2164 			case 't':
2165 				modifiers |= FORMAT_TIMESTRING;
2166 				if (fm->argc < 1)
2167 					break;
2168 				if (strchr(fm->argv[0], 'p') != NULL)
2169 					modifiers |= FORMAT_PRETTY;
2170 				else if (fm->argc >= 2 &&
2171 				    strchr(fm->argv[0], 'f') != NULL)
2172 					time_format = format_strip(fm->argv[1]);
2173 				break;
2174 			case 'q':
2175 				modifiers |= FORMAT_QUOTE;
2176 				break;
2177 			case 'E':
2178 				modifiers |= FORMAT_EXPAND;
2179 				break;
2180 			case 'T':
2181 				modifiers |= FORMAT_EXPANDTIME;
2182 				break;
2183 			case 'S':
2184 				modifiers |= FORMAT_SESSIONS;
2185 				break;
2186 			case 'W':
2187 				modifiers |= FORMAT_WINDOWS;
2188 				break;
2189 			case 'P':
2190 				modifiers |= FORMAT_PANES;
2191 				break;
2192 			}
2193 		} else if (fm->size == 2) {
2194 			if (strcmp(fm->modifier, "||") == 0 ||
2195 			    strcmp(fm->modifier, "&&") == 0 ||
2196 			    strcmp(fm->modifier, "==") == 0 ||
2197 			    strcmp(fm->modifier, "!=") == 0 ||
2198 			    strcmp(fm->modifier, ">=") == 0 ||
2199 			    strcmp(fm->modifier, "<=") == 0)
2200 				cmp = fm;
2201 		}
2202 	}
2203 
2204 	/* Is this a literal string? */
2205 	if (modifiers & FORMAT_LITERAL) {
2206 		value = xstrdup(copy);
2207 		goto done;
2208 	}
2209 
2210 	/* Is this a loop, comparison or condition? */
2211 	if (modifiers & FORMAT_SESSIONS) {
2212 		value = format_loop_sessions(es, copy);
2213 		if (value == NULL)
2214 			goto fail;
2215 	} else if (modifiers & FORMAT_WINDOWS) {
2216 		value = format_loop_windows(es, copy);
2217 		if (value == NULL)
2218 			goto fail;
2219 	} else if (modifiers & FORMAT_PANES) {
2220 		value = format_loop_panes(es, copy);
2221 		if (value == NULL)
2222 			goto fail;
2223 	} else if (search != NULL) {
2224 		/* Search in pane. */
2225 		new = format_expand1(es, copy);
2226 		if (wp == NULL) {
2227 			format_log(es, "search '%s' but no pane", new);
2228 			value = xstrdup("0");
2229 		} else {
2230 			format_log(es, "search '%s' pane %%%u", new, wp->id);
2231 			value = format_search(fm, wp, new);
2232 		}
2233 		free(new);
2234 	} else if (cmp != NULL) {
2235 		/* Comparison of left and right. */
2236 		if (format_choose(es, copy, &left, &right, 1) != 0) {
2237 			format_log(es, "compare %s syntax error: %s",
2238 			    cmp->modifier, copy);
2239 			goto fail;
2240 		}
2241 		format_log(es, "compare %s left is: %s", cmp->modifier, left);
2242 		format_log(es, "compare %s right is: %s", cmp->modifier, right);
2243 
2244 		if (strcmp(cmp->modifier, "||") == 0) {
2245 			if (format_true(left) || format_true(right))
2246 				value = xstrdup("1");
2247 			else
2248 				value = xstrdup("0");
2249 		} else if (strcmp(cmp->modifier, "&&") == 0) {
2250 			if (format_true(left) && format_true(right))
2251 				value = xstrdup("1");
2252 			else
2253 				value = xstrdup("0");
2254 		} else if (strcmp(cmp->modifier, "==") == 0) {
2255 			if (strcmp(left, right) == 0)
2256 				value = xstrdup("1");
2257 			else
2258 				value = xstrdup("0");
2259 		} else if (strcmp(cmp->modifier, "!=") == 0) {
2260 			if (strcmp(left, right) != 0)
2261 				value = xstrdup("1");
2262 			else
2263 				value = xstrdup("0");
2264 		} else if (strcmp(cmp->modifier, "<") == 0) {
2265 			if (strcmp(left, right) < 0)
2266 				value = xstrdup("1");
2267 			else
2268 				value = xstrdup("0");
2269 		} else if (strcmp(cmp->modifier, ">") == 0) {
2270 			if (strcmp(left, right) > 0)
2271 				value = xstrdup("1");
2272 			else
2273 				value = xstrdup("0");
2274 		} else if (strcmp(cmp->modifier, "<=") == 0) {
2275 			if (strcmp(left, right) <= 0)
2276 				value = xstrdup("1");
2277 			else
2278 				value = xstrdup("0");
2279 		} else if (strcmp(cmp->modifier, ">=") == 0) {
2280 			if (strcmp(left, right) >= 0)
2281 				value = xstrdup("1");
2282 			else
2283 				value = xstrdup("0");
2284 		} else if (strcmp(cmp->modifier, "m") == 0)
2285 			value = format_match(cmp, left, right);
2286 
2287 		free(right);
2288 		free(left);
2289 	} else if (*copy == '?') {
2290 		/* Conditional: check first and choose second or third. */
2291 		cp = format_skip(copy + 1, ",");
2292 		if (cp == NULL) {
2293 			format_log(es, "condition syntax error: %s", copy + 1);
2294 			goto fail;
2295 		}
2296 		condition = xstrndup(copy + 1, cp - (copy + 1));
2297 		format_log(es, "condition is: %s", condition);
2298 
2299 		found = format_find(ft, condition, modifiers, time_format);
2300 		if (found == NULL) {
2301 			/*
2302 			 * If the condition not found, try to expand it. If
2303 			 * the expansion doesn't have any effect, then assume
2304 			 * false.
2305 			 */
2306 			found = format_expand1(es, condition);
2307 			if (strcmp(found, condition) == 0) {
2308 				free(found);
2309 				found = xstrdup("");
2310 				format_log(es, "condition '%s' found: %s",
2311 				    condition, found);
2312 			} else {
2313 				format_log(es,
2314 				    "condition '%s' not found; assuming false",
2315 				    condition);
2316 			}
2317 		} else
2318 			format_log(es, "condition '%s' found", condition);
2319 
2320 		if (format_choose(es, cp + 1, &left, &right, 0) != 0) {
2321 			format_log(es, "condition '%s' syntax error: %s",
2322 			    condition, cp + 1);
2323 			free(found);
2324 			goto fail;
2325 		}
2326 		if (format_true(found)) {
2327 			format_log(es, "condition '%s' is true", condition);
2328 			value = format_expand1(es, left);
2329 		} else {
2330 			format_log(es, "condition '%s' is false", condition);
2331 			value = format_expand1(es, right);
2332 		}
2333 		free(right);
2334 		free(left);
2335 
2336 		free(condition);
2337 		free(found);
2338 	} else if (mexp != NULL) {
2339 		value = format_replace_expression(mexp, es, copy);
2340 		if (value == NULL)
2341 			value = xstrdup("");
2342 	} else {
2343 		if (strstr(copy, "#{") != 0) {
2344 			format_log(es, "expanding inner format '%s'", copy);
2345 			value = format_expand1(es, copy);
2346 		} else {
2347 			value = format_find(ft, copy, modifiers, time_format);
2348 			if (value == NULL) {
2349 				format_log(es, "format '%s' not found", copy);
2350 				value = xstrdup("");
2351 			} else {
2352 				format_log(es, "format '%s' found: %s", copy,
2353 				    value);
2354 			}
2355 		}
2356 	}
2357 
2358 done:
2359 	/* Expand again if required. */
2360 	if (modifiers & FORMAT_EXPAND) {
2361 		new = format_expand1(es, value);
2362 		free(value);
2363 		value = new;
2364 	} else if (modifiers & FORMAT_EXPANDTIME) {
2365 		format_copy_state(&next, es, FORMAT_EXPAND_TIME);
2366 		new = format_expand1(&next, value);
2367 		free(value);
2368 		value = new;
2369 	}
2370 
2371 	/* Perform substitution if any. */
2372 	for (i = 0; i < nsub; i++) {
2373 		left = format_expand1(es, sub[i]->argv[0]);
2374 		right = format_expand1(es, sub[i]->argv[1]);
2375 		new = format_sub(sub[i], value, left, right);
2376 		format_log(es, "substitute '%s' to '%s': %s", left, right, new);
2377 		free(value);
2378 		value = new;
2379 		free(right);
2380 		free(left);
2381 	}
2382 
2383 	/* Truncate the value if needed. */
2384 	if (limit > 0) {
2385 		new = format_trim_left(value, limit);
2386 		if (marker != NULL && strcmp(new, value) != 0) {
2387 			free(value);
2388 			xasprintf(&value, "%s%s", new, marker);
2389 		} else {
2390 			free(value);
2391 			value = new;
2392 		}
2393 		format_log(es, "applied length limit %d: %s", limit, value);
2394 	} else if (limit < 0) {
2395 		new = format_trim_right(value, -limit);
2396 		if (marker != NULL && strcmp(new, value) != 0) {
2397 			free(value);
2398 			xasprintf(&value, "%s%s", marker, new);
2399 		} else {
2400 			free(value);
2401 			value = new;
2402 		}
2403 		format_log(es, "applied length limit %d: %s", limit, value);
2404 	}
2405 
2406 	/* Pad the value if needed. */
2407 	if (width > 0) {
2408 		new = utf8_padcstr(value, width);
2409 		free(value);
2410 		value = new;
2411 		format_log(es, "applied padding width %d: %s", width, value);
2412 	} else if (width < 0) {
2413 		new = utf8_rpadcstr(value, -width);
2414 		free(value);
2415 		value = new;
2416 		format_log(es, "applied padding width %d: %s", width, value);
2417 	}
2418 
2419 	/* Replace with the length if needed. */
2420 	if (modifiers & FORMAT_LENGTH) {
2421 		xasprintf(&new, "%zu", strlen(value));
2422 		free(value);
2423 		value = new;
2424 		format_log(es, "replacing with length: %s", new);
2425 	}
2426 
2427 	/* Expand the buffer and copy in the value. */
2428 	valuelen = strlen(value);
2429 	while (*len - *off < valuelen + 1) {
2430 		*buf = xreallocarray(*buf, 2, *len);
2431 		*len *= 2;
2432 	}
2433 	memcpy(*buf + *off, value, valuelen);
2434 	*off += valuelen;
2435 
2436 	format_log(es, "replaced '%s' with '%s'", copy0, value);
2437 	free(value);
2438 
2439 	free(sub);
2440 	format_free_modifiers(list, count);
2441 	free(copy0);
2442 	return (0);
2443 
2444 fail:
2445 	format_log(es, "failed %s", copy0);
2446 
2447 	free(sub);
2448 	format_free_modifiers(list, count);
2449 	free(copy0);
2450 	return (-1);
2451 }
2452 
2453 /* Expand keys in a template. */
2454 static char *
2455 format_expand1(struct format_expand_state *es, const char *fmt)
2456 {
2457 	struct format_tree	*ft = es->ft;
2458 	char			*buf, *out, *name;
2459 	const char		*ptr, *s;
2460 	size_t			 off, len, n, outlen;
2461 	int     		 ch, brackets;
2462 	struct tm		*tm;
2463 	char			 expanded[8192];
2464 
2465 	if (fmt == NULL || *fmt == '\0')
2466 		return (xstrdup(""));
2467 
2468 	if (es->loop == FORMAT_LOOP_LIMIT)
2469 		return (xstrdup(""));
2470 	es->loop++;
2471 
2472 	format_log(es, "expanding format: %s", fmt);
2473 
2474 	if (es->flags & FORMAT_EXPAND_TIME) {
2475 		if (es->time == 0)
2476 			es->time = time(NULL);
2477 		tm = localtime(&es->time);
2478 		if (strftime(expanded, sizeof expanded, fmt, tm) == 0) {
2479 			format_log(es, "format is too long");
2480 			return (xstrdup(""));
2481 		}
2482 		if (format_logging(ft) && strcmp(expanded, fmt) != 0)
2483 			format_log(es, "after time expanded: %s", expanded);
2484 		fmt = expanded;
2485 	}
2486 
2487 	len = 64;
2488 	buf = xmalloc(len);
2489 	off = 0;
2490 
2491 	while (*fmt != '\0') {
2492 		if (*fmt != '#') {
2493 			while (len - off < 2) {
2494 				buf = xreallocarray(buf, 2, len);
2495 				len *= 2;
2496 			}
2497 			buf[off++] = *fmt++;
2498 			continue;
2499 		}
2500 		fmt++;
2501 
2502 		ch = (u_char)*fmt++;
2503 		switch (ch) {
2504 		case '(':
2505 			brackets = 1;
2506 			for (ptr = fmt; *ptr != '\0'; ptr++) {
2507 				if (*ptr == '(')
2508 					brackets++;
2509 				if (*ptr == ')' && --brackets == 0)
2510 					break;
2511 			}
2512 			if (*ptr != ')' || brackets != 0)
2513 				break;
2514 			n = ptr - fmt;
2515 
2516 			name = xstrndup(fmt, n);
2517 			format_log(es, "found #(): %s", name);
2518 
2519 			if ((ft->flags & FORMAT_NOJOBS) ||
2520 			    (es->flags & FORMAT_EXPAND_NOJOBS)) {
2521 				out = xstrdup("");
2522 				format_log(es, "#() is disabled");
2523 			} else {
2524 				out = format_job_get(es, name);
2525 				format_log(es, "#() result: %s", out);
2526 			}
2527 			free(name);
2528 
2529 			outlen = strlen(out);
2530 			while (len - off < outlen + 1) {
2531 				buf = xreallocarray(buf, 2, len);
2532 				len *= 2;
2533 			}
2534 			memcpy(buf + off, out, outlen);
2535 			off += outlen;
2536 
2537 			free(out);
2538 
2539 			fmt += n + 1;
2540 			continue;
2541 		case '{':
2542 			ptr = format_skip((char *)fmt - 2, "}");
2543 			if (ptr == NULL)
2544 				break;
2545 			n = ptr - fmt;
2546 
2547 			format_log(es, "found #{}: %.*s", (int)n, fmt);
2548 			if (format_replace(es, fmt, n, &buf, &len, &off) != 0)
2549 				break;
2550 			fmt += n + 1;
2551 			continue;
2552 		case '}':
2553 		case '#':
2554 		case ',':
2555 			format_log(es, "found #%c", ch);
2556 			while (len - off < 2) {
2557 				buf = xreallocarray(buf, 2, len);
2558 				len *= 2;
2559 			}
2560 			buf[off++] = ch;
2561 			continue;
2562 		default:
2563 			s = NULL;
2564 			if (ch >= 'A' && ch <= 'Z')
2565 				s = format_upper[ch - 'A'];
2566 			else if (ch >= 'a' && ch <= 'z')
2567 				s = format_lower[ch - 'a'];
2568 			if (s == NULL) {
2569 				while (len - off < 3) {
2570 					buf = xreallocarray(buf, 2, len);
2571 					len *= 2;
2572 				}
2573 				buf[off++] = '#';
2574 				buf[off++] = ch;
2575 				continue;
2576 			}
2577 			n = strlen(s);
2578 			format_log(es, "found #%c: %s", ch, s);
2579 			if (format_replace(es, s, n, &buf, &len, &off) != 0)
2580 				break;
2581 			continue;
2582 		}
2583 
2584 		break;
2585 	}
2586 	buf[off] = '\0';
2587 
2588 	format_log(es, "result is: %s", buf);
2589 	es->loop--;
2590 
2591 	return (buf);
2592 }
2593 
2594 /* Expand keys in a template, passing through strftime first. */
2595 char *
2596 format_expand_time(struct format_tree *ft, const char *fmt)
2597 {
2598 	struct format_expand_state	es;
2599 
2600 	memset(&es, 0, sizeof es);
2601 	es.ft = ft;
2602 	es.flags = FORMAT_EXPAND_TIME;
2603 	return (format_expand1(&es, fmt));
2604 }
2605 
2606 /* Expand keys in a template. */
2607 char *
2608 format_expand(struct format_tree *ft, const char *fmt)
2609 {
2610 	struct format_expand_state	es;
2611 
2612 	memset(&es, 0, sizeof es);
2613 	es.ft = ft;
2614 	es.flags = 0;
2615 	return (format_expand1(&es, fmt));
2616 }
2617 
2618 /* Expand a single string. */
2619 char *
2620 format_single(struct cmdq_item *item, const char *fmt, struct client *c,
2621     struct session *s, struct winlink *wl, struct window_pane *wp)
2622 {
2623 	struct format_tree	*ft;
2624 	char			*expanded;
2625 
2626 	ft = format_create_defaults(item, c, s, wl, wp);
2627 	expanded = format_expand(ft, fmt);
2628 	format_free(ft);
2629 	return (expanded);
2630 }
2631 
2632 /* Expand a single string using state. */
2633 char *
2634 format_single_from_state(struct cmdq_item *item, const char *fmt,
2635     struct client *c, struct cmd_find_state *fs)
2636 {
2637 	return (format_single(item, fmt, c, fs->s, fs->wl, fs->wp));
2638 }
2639 
2640 /* Expand a single string using target. */
2641 char *
2642 format_single_from_target(struct cmdq_item *item, const char *fmt)
2643 {
2644 	struct client	*tc = cmdq_get_target_client(item);
2645 
2646 	return (format_single_from_state(item, fmt, tc, cmdq_get_target(item)));
2647 }
2648 
2649 /* Create and add defaults. */
2650 struct format_tree *
2651 format_create_defaults(struct cmdq_item *item, struct client *c,
2652     struct session *s, struct winlink *wl, struct window_pane *wp)
2653 {
2654 	struct format_tree	*ft;
2655 
2656 	if (item != NULL)
2657 		ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
2658 	else
2659 		ft = format_create(NULL, item, FORMAT_NONE, 0);
2660 	format_defaults(ft, c, s, wl, wp);
2661 	return (ft);
2662 }
2663 
2664 /* Create and add defaults using state. */
2665 struct format_tree *
2666 format_create_from_state(struct cmdq_item *item, struct client *c,
2667     struct cmd_find_state *fs)
2668 {
2669 	return (format_create_defaults(item, c, fs->s, fs->wl, fs->wp));
2670 }
2671 
2672 /* Create and add defaults using target. */
2673 struct format_tree *
2674 format_create_from_target(struct cmdq_item *item)
2675 {
2676 	struct client	*tc = cmdq_get_target_client(item);
2677 
2678 	return (format_create_from_state(item, tc, cmdq_get_target(item)));
2679 }
2680 
2681 /* Set defaults for any of arguments that are not NULL. */
2682 void
2683 format_defaults(struct format_tree *ft, struct client *c, struct session *s,
2684     struct winlink *wl, struct window_pane *wp)
2685 {
2686 	struct paste_buffer	*pb;
2687 
2688 	if (c != NULL && c->name != NULL)
2689 		log_debug("%s: c=%s", __func__, c->name);
2690 	else
2691 		log_debug("%s: c=none", __func__);
2692 	if (s != NULL)
2693 		log_debug("%s: s=$%u", __func__, s->id);
2694 	else
2695 		log_debug("%s: s=none", __func__);
2696 	if (wl != NULL)
2697 		log_debug("%s: wl=%u", __func__, wl->idx);
2698 	else
2699 		log_debug("%s: wl=none", __func__);
2700 	if (wp != NULL)
2701 		log_debug("%s: wp=%%%u", __func__, wp->id);
2702 	else
2703 		log_debug("%s: wp=none", __func__);
2704 
2705 	if (c != NULL && s != NULL && c->session != s)
2706 		log_debug("%s: session does not match", __func__);
2707 
2708 	format_add(ft, "session_format", "%d", s != NULL);
2709 	format_add(ft, "window_format", "%d", wl != NULL);
2710 	format_add(ft, "pane_format", "%d", wp != NULL);
2711 
2712 	if (s == NULL && c != NULL)
2713 		s = c->session;
2714 	if (wl == NULL && s != NULL)
2715 		wl = s->curw;
2716 	if (wp == NULL && wl != NULL)
2717 		wp = wl->window->active;
2718 
2719 	if (c != NULL)
2720 		format_defaults_client(ft, c);
2721 	if (s != NULL)
2722 		format_defaults_session(ft, s);
2723 	if (wl != NULL)
2724 		format_defaults_winlink(ft, wl);
2725 	if (wp != NULL)
2726 		format_defaults_pane(ft, wp);
2727 
2728 	pb = paste_get_top (NULL);
2729 	if (pb != NULL)
2730 		format_defaults_paste_buffer(ft, pb);
2731 }
2732 
2733 /* Set default format keys for a session. */
2734 static void
2735 format_defaults_session(struct format_tree *ft, struct session *s)
2736 {
2737 	struct session_group	*sg;
2738 
2739 	ft->s = s;
2740 
2741 	format_add(ft, "session_name", "%s", s->name);
2742 	format_add(ft, "session_path", "%s", s->cwd);
2743 	format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
2744 	format_add(ft, "session_id", "$%u", s->id);
2745 
2746 	sg = session_group_contains(s);
2747 	format_add(ft, "session_grouped", "%d", sg != NULL);
2748 	if (sg != NULL) {
2749 		format_add(ft, "session_group", "%s", sg->name);
2750 		format_add(ft, "session_group_size", "%u",
2751 		    session_group_count (sg));
2752 		format_add(ft, "session_group_attached", "%u",
2753 		    session_group_attached_count (sg));
2754 		format_add(ft, "session_group_many_attached", "%u",
2755 		    session_group_attached_count (sg) > 1);
2756 		format_add_cb(ft, "session_group_list",
2757 		    format_cb_session_group_list);
2758 		format_add_cb(ft, "session_group_attached_list",
2759 		    format_cb_session_group_attached_list);
2760 	}
2761 
2762 	format_add_tv(ft, "session_created", &s->creation_time);
2763 	format_add_tv(ft, "session_last_attached", &s->last_attached_time);
2764 	format_add_tv(ft, "session_activity", &s->activity_time);
2765 
2766 	format_add(ft, "session_attached", "%u", s->attached);
2767 	format_add(ft, "session_many_attached", "%d", s->attached > 1);
2768 	format_add_cb(ft, "session_attached_list",
2769 	    format_cb_session_attached_list);
2770 
2771 	format_add_cb(ft, "session_alerts", format_cb_session_alerts);
2772 	format_add_cb(ft, "session_stack", format_cb_session_stack);
2773 
2774 	if (server_check_marked() && marked_pane.s == s)
2775 	    format_add(ft, "session_marked", "1");
2776 	else
2777 	    format_add(ft, "session_marked", "0");
2778 }
2779 
2780 /* Set default format keys for a client. */
2781 static void
2782 format_defaults_client(struct format_tree *ft, struct client *c)
2783 {
2784 	struct session	*s;
2785 	const char	*name;
2786 	struct tty	*tty = &c->tty;
2787 
2788 	if (ft->s == NULL)
2789 		ft->s = c->session;
2790 	ft->c = c;
2791 
2792 	format_add(ft, "client_name", "%s", c->name);
2793 	format_add(ft, "client_pid", "%ld", (long) c->pid);
2794 	format_add(ft, "client_height", "%u", tty->sy);
2795 	format_add(ft, "client_width", "%u", tty->sx);
2796 	format_add(ft, "client_cell_width", "%u", tty->xpixel);
2797 	format_add(ft, "client_cell_height", "%u", tty->ypixel);
2798 	format_add(ft, "client_tty", "%s", c->ttyname);
2799 	format_add(ft, "client_control_mode", "%d",
2800 		!!(c->flags & CLIENT_CONTROL));
2801 
2802 	format_add(ft, "client_termname", "%s", c->term_name);
2803 	format_add(ft, "client_termfeatures", "%s",
2804 	    tty_get_features(c->term_features));
2805 	if (c->term_type != NULL)
2806 		format_add(ft, "client_termtype", "%s", c->term_type);
2807 
2808 	format_add_tv(ft, "client_created", &c->creation_time);
2809 	format_add_tv(ft, "client_activity", &c->activity_time);
2810 
2811 	format_add(ft, "client_written", "%zu", c->written);
2812 	format_add(ft, "client_discarded", "%zu", c->discarded);
2813 
2814 	name = server_client_get_key_table(c);
2815 	if (strcmp(c->keytable->name, name) == 0)
2816 		format_add(ft, "client_prefix", "%d", 0);
2817 	else
2818 		format_add(ft, "client_prefix", "%d", 1);
2819 	format_add(ft, "client_key_table", "%s", c->keytable->name);
2820 
2821 	if (c->flags & CLIENT_UTF8)
2822 		format_add(ft, "client_utf8", "%d", 1);
2823 	else
2824 		format_add(ft, "client_utf8", "%d", 0);
2825 	if (c->flags & CLIENT_READONLY)
2826 		format_add(ft, "client_readonly", "%d", 1);
2827 	else
2828 		format_add(ft, "client_readonly", "%d", 0);
2829 	format_add(ft, "client_flags", "%s", server_client_get_flags(c));
2830 
2831 	s = c->session;
2832 	if (s != NULL)
2833 		format_add(ft, "client_session", "%s", s->name);
2834 	s = c->last_session;
2835 	if (s != NULL && session_alive(s))
2836 		format_add(ft, "client_last_session", "%s", s->name);
2837 }
2838 
2839 /* Set default format keys for a window. */
2840 void
2841 format_defaults_window(struct format_tree *ft, struct window *w)
2842 {
2843 	ft->w = w;
2844 
2845 	format_add_tv(ft, "window_activity", &w->activity_time);
2846 	format_add(ft, "window_id", "@%u", w->id);
2847 	format_add(ft, "window_name", "%s", w->name);
2848 	format_add(ft, "window_width", "%u", w->sx);
2849 	format_add(ft, "window_height", "%u", w->sy);
2850 	format_add(ft, "window_cell_width", "%u", w->xpixel);
2851 	format_add(ft, "window_cell_height", "%u", w->ypixel);
2852 	format_add_cb(ft, "window_layout", format_cb_window_layout);
2853 	format_add_cb(ft, "window_visible_layout",
2854 	    format_cb_window_visible_layout);
2855 	format_add(ft, "window_panes", "%u", window_count_panes(w));
2856 	format_add(ft, "window_zoomed_flag", "%d",
2857 	    !!(w->flags & WINDOW_ZOOMED));
2858 }
2859 
2860 /* Set default format keys for a winlink. */
2861 static void
2862 format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
2863 {
2864 	struct client	*c = ft->c;
2865 	struct session	*s = wl->session;
2866 	struct window	*w = wl->window;
2867 	int		 flag;
2868 	u_int		 ox, oy, sx, sy;
2869 
2870 	if (ft->w == NULL)
2871 		format_defaults_window(ft, w);
2872 	ft->wl = wl;
2873 
2874 	if (c != NULL) {
2875 		flag = tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
2876 		format_add(ft, "window_bigger", "%d", flag);
2877 		if (flag) {
2878 			format_add(ft, "window_offset_x", "%u", ox);
2879 			format_add(ft, "window_offset_y", "%u", oy);
2880 		}
2881 	}
2882 
2883 	format_add(ft, "window_index", "%d", wl->idx);
2884 	format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
2885 	format_add(ft, "window_flags", "%s", window_printable_flags(wl));
2886 	format_add(ft, "window_active", "%d", wl == s->curw);
2887 	format_add_cb(ft, "window_active_sessions",
2888 	    format_cb_window_active_sessions);
2889 	format_add_cb(ft, "window_active_sessions_list",
2890 	    format_cb_window_active_sessions_list);
2891 	format_add_cb(ft, "window_active_clients",
2892 	    format_cb_window_active_clients);
2893 	format_add_cb(ft, "window_active_clients_list",
2894 	    format_cb_window_active_clients_list);
2895 
2896 	format_add(ft, "window_start_flag", "%d",
2897 	    !!(wl == RB_MIN(winlinks, &s->windows)));
2898 	format_add(ft, "window_end_flag", "%d",
2899 	    !!(wl == RB_MAX(winlinks, &s->windows)));
2900 
2901 	if (server_check_marked() && marked_pane.wl == wl)
2902 	    format_add(ft, "window_marked_flag", "1");
2903 	else
2904 	    format_add(ft, "window_marked_flag", "0");
2905 
2906 	format_add(ft, "window_bell_flag", "%d",
2907 	    !!(wl->flags & WINLINK_BELL));
2908 	format_add(ft, "window_activity_flag", "%d",
2909 	    !!(wl->flags & WINLINK_ACTIVITY));
2910 	format_add(ft, "window_silence_flag", "%d",
2911 	    !!(wl->flags & WINLINK_SILENCE));
2912 	format_add(ft, "window_last_flag", "%d",
2913 	    !!(wl == TAILQ_FIRST(&s->lastw)));
2914 	format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
2915 
2916 	format_add_cb(ft, "window_linked_sessions_list",
2917 	    format_cb_window_linked_sessions_list);
2918 	format_add(ft, "window_linked_sessions", "%u",
2919 	    wl->window->references);
2920 }
2921 
2922 /* Set default format keys for a window pane. */
2923 void
2924 format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
2925 {
2926 	struct window			*w = wp->window;
2927 	struct grid			*gd = wp->base.grid;
2928 	int  				 status = wp->status;
2929 	u_int				 idx;
2930 	struct window_mode_entry	*wme;
2931 
2932 	if (ft->w == NULL)
2933 		format_defaults_window(ft, w);
2934 	ft->wp = wp;
2935 
2936 	format_add(ft, "history_size", "%u", gd->hsize);
2937 	format_add(ft, "history_limit", "%u", gd->hlimit);
2938 	format_add_cb(ft, "history_bytes", format_cb_history_bytes);
2939 	format_add_cb(ft, "history_all_bytes", format_cb_history_all_bytes);
2940 
2941 	format_add(ft, "pane_written", "%zu", wp->written);
2942 	format_add(ft, "pane_skipped", "%zu", wp->skipped);
2943 
2944 	if (window_pane_index(wp, &idx) != 0)
2945 		fatalx("index not found");
2946 	format_add(ft, "pane_index", "%u", idx);
2947 
2948 	format_add(ft, "pane_width", "%u", wp->sx);
2949 	format_add(ft, "pane_height", "%u", wp->sy);
2950 	format_add(ft, "pane_title", "%s", wp->base.title);
2951 	if (wp->base.path != NULL)
2952 	    format_add(ft, "pane_path", "%s", wp->base.path);
2953 	format_add(ft, "pane_id", "%%%u", wp->id);
2954 	format_add(ft, "pane_active", "%d", wp == w->active);
2955 	format_add(ft, "pane_input_off", "%d", !!(wp->flags & PANE_INPUTOFF));
2956 	format_add(ft, "pane_pipe", "%d", wp->pipe_fd != -1);
2957 
2958 	if ((wp->flags & PANE_STATUSREADY) && WIFEXITED(status))
2959 		format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
2960 	if (~wp->flags & PANE_EMPTY)
2961 		format_add(ft, "pane_dead", "%d", wp->fd == -1);
2962 	else
2963 		format_add(ft, "pane_dead", "0");
2964 	format_add(ft, "pane_last", "%d", wp == w->last);
2965 
2966 	if (server_check_marked() && marked_pane.wp == wp)
2967 		format_add(ft, "pane_marked", "1");
2968 	else
2969 		format_add(ft, "pane_marked", "0");
2970 	format_add(ft, "pane_marked_set", "%d", server_check_marked());
2971 
2972 	format_add(ft, "pane_left", "%u", wp->xoff);
2973 	format_add(ft, "pane_top", "%u", wp->yoff);
2974 	format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
2975 	format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
2976 	format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
2977 	format_add_cb(ft, "pane_at_top", format_cb_pane_at_top);
2978 	format_add(ft, "pane_at_right", "%d", wp->xoff + wp->sx == w->sx);
2979 	format_add_cb(ft, "pane_at_bottom", format_cb_pane_at_bottom);
2980 
2981 	wme = TAILQ_FIRST(&wp->modes);
2982 	if (wme != NULL) {
2983 		format_add(ft, "pane_mode", "%s", wme->mode->name);
2984 		if (wme->mode->formats != NULL)
2985 			wme->mode->formats(wme, ft);
2986 	}
2987 	format_add_cb(ft, "pane_in_mode", format_cb_pane_in_mode);
2988 
2989 	format_add(ft, "pane_synchronized", "%d",
2990 	    !!options_get_number(w->options, "synchronize-panes"));
2991 	if (wp->searchstr != NULL)
2992 		format_add(ft, "pane_search_string", "%s", wp->searchstr);
2993 
2994 	format_add(ft, "pane_tty", "%s", wp->tty);
2995 	format_add(ft, "pane_pid", "%ld", (long) wp->pid);
2996 	format_add_cb(ft, "pane_start_command", format_cb_start_command);
2997 	format_add_cb(ft, "pane_current_command", format_cb_current_command);
2998 	format_add_cb(ft, "pane_current_path", format_cb_current_path);
2999 
3000 	format_add(ft, "cursor_x", "%u", wp->base.cx);
3001 	format_add(ft, "cursor_y", "%u", wp->base.cy);
3002 	format_add_cb(ft, "cursor_character", format_cb_cursor_character);
3003 
3004 	format_add(ft, "scroll_region_upper", "%u", wp->base.rupper);
3005 	format_add(ft, "scroll_region_lower", "%u", wp->base.rlower);
3006 
3007 	format_add(ft, "alternate_on", "%d", wp->base.saved_grid != NULL);
3008 	if (wp->base.saved_cx != UINT_MAX)
3009 		format_add(ft, "alternate_saved_x", "%u", wp->base.saved_cx);
3010 	if (wp->base.saved_cy != UINT_MAX)
3011 		format_add(ft, "alternate_saved_y", "%u", wp->base.saved_cy);
3012 
3013 	format_add(ft, "cursor_flag", "%d",
3014 	    !!(wp->base.mode & MODE_CURSOR));
3015 	format_add(ft, "insert_flag", "%d",
3016 	    !!(wp->base.mode & MODE_INSERT));
3017 	format_add(ft, "keypad_cursor_flag", "%d",
3018 	    !!(wp->base.mode & MODE_KCURSOR));
3019 	format_add(ft, "keypad_flag", "%d",
3020 	    !!(wp->base.mode & MODE_KKEYPAD));
3021 	format_add(ft, "wrap_flag", "%d",
3022 	    !!(wp->base.mode & MODE_WRAP));
3023 	format_add(ft, "origin_flag", "%d",
3024 	    !!(wp->base.mode & MODE_ORIGIN));
3025 
3026 	format_add(ft, "mouse_any_flag", "%d",
3027 	    !!(wp->base.mode & ALL_MOUSE_MODES));
3028 	format_add(ft, "mouse_standard_flag", "%d",
3029 	    !!(wp->base.mode & MODE_MOUSE_STANDARD));
3030 	format_add(ft, "mouse_button_flag", "%d",
3031 	    !!(wp->base.mode & MODE_MOUSE_BUTTON));
3032 	format_add(ft, "mouse_all_flag", "%d",
3033 	    !!(wp->base.mode & MODE_MOUSE_ALL));
3034 	format_add(ft, "mouse_utf8_flag", "%d",
3035 	    !!(wp->base.mode & MODE_MOUSE_UTF8));
3036 	format_add(ft, "mouse_sgr_flag", "%d",
3037 	    !!(wp->base.mode & MODE_MOUSE_SGR));
3038 
3039 	format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
3040 }
3041 
3042 /* Set default format keys for paste buffer. */
3043 void
3044 format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
3045 {
3046 	struct timeval	 tv;
3047 	size_t		 size;
3048 	char		*s;
3049 
3050 	timerclear(&tv);
3051 	tv.tv_sec = paste_buffer_created(pb);
3052 	paste_buffer_data(pb, &size);
3053 
3054 	format_add(ft, "buffer_size", "%zu", size);
3055 	format_add(ft, "buffer_name", "%s", paste_buffer_name(pb));
3056 	format_add_tv(ft, "buffer_created", &tv);
3057 
3058 	s = paste_make_sample(pb);
3059 	format_add(ft, "buffer_sample", "%s", s);
3060 	free(s);
3061 }
3062