xref: /openbsd-src/usr.bin/tmux/format.c (revision c7e8ea31cd41a963f06f0a8ba93948b06aa6b4a4)
1 /* $OpenBSD: format.c,v 1.146 2017/08/09 11:43:45 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 <errno.h>
23 #include <fnmatch.h>
24 #include <libgen.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <unistd.h>
30 
31 #include "tmux.h"
32 
33 /*
34  * Build a list of key-value pairs and use them to expand #{key} entries in a
35  * string.
36  */
37 
38 struct format_entry;
39 typedef void (*format_cb)(struct format_tree *, struct format_entry *);
40 
41 static char	*format_job_get(struct format_tree *, const char *);
42 static void	 format_job_timer(int, short, void *);
43 
44 static char	*format_find(struct format_tree *, const char *, int);
45 static void	 format_add_cb(struct format_tree *, const char *, format_cb);
46 static void	 format_add_tv(struct format_tree *, const char *,
47 		     struct timeval *);
48 static int	 format_replace(struct format_tree *, const char *, size_t,
49 		     char **, size_t *, size_t *);
50 
51 static void	 format_defaults_session(struct format_tree *,
52 		     struct session *);
53 static void	 format_defaults_client(struct format_tree *, struct client *);
54 static void	 format_defaults_winlink(struct format_tree *,
55 		     struct winlink *);
56 
57 /* Entry in format job tree. */
58 struct format_job {
59 	struct client		*client;
60 	u_int			 tag;
61 	const char		*cmd;
62 	const char		*expanded;
63 
64 	time_t			 last;
65 	char			*out;
66 	int			 updated;
67 
68 	struct job		*job;
69 	int			 status;
70 
71 	RB_ENTRY(format_job)	 entry;
72 };
73 
74 /* Format job tree. */
75 static struct event format_job_event;
76 static int format_job_cmp(struct format_job *, struct format_job *);
77 static RB_HEAD(format_job_tree, format_job) format_jobs = RB_INITIALIZER();
78 RB_GENERATE_STATIC(format_job_tree, format_job, entry, format_job_cmp);
79 
80 /* Format job tree comparison function. */
81 static int
82 format_job_cmp(struct format_job *fj1, struct format_job *fj2)
83 {
84 	if (fj1->tag < fj2->tag)
85 		return (-1);
86 	if (fj1->tag > fj2->tag)
87 		return (1);
88 	return (strcmp(fj1->cmd, fj2->cmd));
89 }
90 
91 /* Format modifiers. */
92 #define FORMAT_TIMESTRING 0x1
93 #define FORMAT_BASENAME 0x2
94 #define FORMAT_DIRNAME 0x4
95 #define FORMAT_SUBSTITUTE 0x8
96 
97 /* Entry in format tree. */
98 struct format_entry {
99 	char			*key;
100 	char			*value;
101 	time_t			 t;
102 	format_cb		 cb;
103 	RB_ENTRY(format_entry)	 entry;
104 };
105 
106 /* Format entry tree. */
107 struct format_tree {
108 	struct window		*w;
109 	struct winlink		*wl;
110 	struct session		*s;
111 	struct window_pane	*wp;
112 
113 	struct client		*client;
114 	u_int			 tag;
115 	int			 flags;
116 
117 	RB_HEAD(format_entry_tree, format_entry) tree;
118 };
119 static int format_entry_cmp(struct format_entry *, struct format_entry *);
120 RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp);
121 
122 /* Format entry tree comparison function. */
123 static int
124 format_entry_cmp(struct format_entry *fe1, struct format_entry *fe2)
125 {
126 	return (strcmp(fe1->key, fe2->key));
127 }
128 
129 /* Single-character uppercase aliases. */
130 static const char *format_upper[] = {
131 	NULL,		/* A */
132 	NULL,		/* B */
133 	NULL,		/* C */
134 	"pane_id",	/* D */
135 	NULL,		/* E */
136 	"window_flags",	/* F */
137 	NULL,		/* G */
138 	"host",		/* H */
139 	"window_index",	/* I */
140 	NULL,		/* J */
141 	NULL,		/* K */
142 	NULL,		/* L */
143 	NULL,		/* M */
144 	NULL,		/* N */
145 	NULL,		/* O */
146 	"pane_index",	/* P */
147 	NULL,		/* Q */
148 	NULL,		/* R */
149 	"session_name",	/* S */
150 	"pane_title",	/* T */
151 	NULL,		/* U */
152 	NULL,		/* V */
153 	"window_name",	/* W */
154 	NULL,		/* X */
155 	NULL,		/* Y */
156 	NULL 		/* Z */
157 };
158 
159 /* Single-character lowercase aliases. */
160 static const char *format_lower[] = {
161 	NULL,		/* a */
162 	NULL,		/* b */
163 	NULL,		/* c */
164 	NULL,		/* d */
165 	NULL,		/* e */
166 	NULL,		/* f */
167 	NULL,		/* g */
168 	"host_short",	/* h */
169 	NULL,		/* i */
170 	NULL,		/* j */
171 	NULL,		/* k */
172 	NULL,		/* l */
173 	NULL,		/* m */
174 	NULL,		/* n */
175 	NULL,		/* o */
176 	NULL,		/* p */
177 	NULL,		/* q */
178 	NULL,		/* r */
179 	NULL,		/* s */
180 	NULL,		/* t */
181 	NULL,		/* u */
182 	NULL,		/* v */
183 	NULL,		/* w */
184 	NULL,		/* x */
185 	NULL,		/* y */
186 	NULL		/* z */
187 };
188 
189 /* Format job update callback. */
190 static void
191 format_job_update(struct job *job)
192 {
193 	struct format_job	*fj = job->data;
194 	char			*line;
195 	time_t			 t;
196 
197 	if ((line = evbuffer_readline(job->event->input)) == NULL)
198 		return;
199 	fj->updated = 1;
200 
201 	free(fj->out);
202 	fj->out = line;
203 
204 	log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, fj->out);
205 
206 	t = time(NULL);
207 	if (fj->status && fj->last != t) {
208 		if (fj->client != NULL)
209 			server_status_client(fj->client);
210 		fj->last = t;
211 	}
212 }
213 
214 /* Format job complete callback. */
215 static void
216 format_job_complete(struct job *job)
217 {
218 	struct format_job	*fj = job->data;
219 	char			*line, *buf;
220 	size_t			 len;
221 
222 	fj->job = NULL;
223 
224 	buf = NULL;
225 	if ((line = evbuffer_readline(job->event->input)) == NULL) {
226 		len = EVBUFFER_LENGTH(job->event->input);
227 		buf = xmalloc(len + 1);
228 		if (len != 0)
229 			memcpy(buf, EVBUFFER_DATA(job->event->input), len);
230 		buf[len] = '\0';
231 	} else
232 		buf = line;
233 
234 	log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, buf);
235 
236 	if (*buf != '\0' || !fj->updated) {
237 		free(fj->out);
238 		fj->out = buf;
239 	} else
240 		free(buf);
241 
242 	if (fj->status) {
243 		if (fj->client != NULL)
244 			server_status_client(fj->client);
245 		fj->status = 0;
246 	}
247 }
248 
249 /* Find a job. */
250 static char *
251 format_job_get(struct format_tree *ft, const char *cmd)
252 {
253 	struct format_job_tree	*jobs;
254 	struct format_job	 fj0, *fj;
255 	time_t			 t;
256 	char			*expanded;
257 	int			 force;
258 
259 	if (ft->client == NULL)
260 		jobs = &format_jobs;
261 	else if (ft->client->jobs != NULL)
262 		jobs = ft->client->jobs;
263 	else {
264 		jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs);
265 		RB_INIT(jobs);
266 	}
267 
268 	fj0.tag = ft->tag;
269 	fj0.cmd = cmd;
270 	if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) {
271 		fj = xcalloc(1, sizeof *fj);
272 		fj->client = ft->client;
273 		fj->tag = ft->tag;
274 		fj->cmd = xstrdup(cmd);
275 		fj->expanded = NULL;
276 
277 		xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
278 
279 		RB_INSERT(format_job_tree, jobs, fj);
280 	}
281 
282 	expanded = format_expand(ft, cmd);
283 	if (fj->expanded == NULL || strcmp(expanded, fj->expanded) != 0) {
284 		free((void *)fj->expanded);
285 		fj->expanded = xstrdup(expanded);
286 		force = 1;
287 	} else
288 		force = (ft->flags & FORMAT_FORCE);
289 
290 	t = time(NULL);
291 	if (fj->job == NULL && (force || fj->last != t)) {
292 		fj->job = job_run(expanded, NULL, NULL, format_job_update,
293 		    format_job_complete, NULL, fj);
294 		if (fj->job == NULL) {
295 			free(fj->out);
296 			xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
297 		}
298 		fj->last = t;
299 		fj->updated = 0;
300 	}
301 
302 	if (ft->flags & FORMAT_STATUS)
303 		fj->status = 1;
304 
305 	free(expanded);
306 	return (format_expand(ft, fj->out));
307 }
308 
309 /* Remove old jobs. */
310 static void
311 format_job_tidy(struct format_job_tree *jobs, int force)
312 {
313 	struct format_job	*fj, *fj1;
314 	time_t			 now;
315 
316 	now = time(NULL);
317 	RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) {
318 		if (!force && (fj->last > now || now - fj->last < 3600))
319 			continue;
320 		RB_REMOVE(format_job_tree, jobs, fj);
321 
322 		log_debug("%s: %s", __func__, fj->cmd);
323 
324 		if (fj->job != NULL)
325 			job_free(fj->job);
326 
327 		free((void *)fj->expanded);
328 		free((void *)fj->cmd);
329 		free(fj->out);
330 
331 		free(fj);
332 	}
333 }
334 
335 /* Remove old jobs for client. */
336 void
337 format_lost_client(struct client *c)
338 {
339 	if (c->jobs != NULL)
340 		format_job_tidy(c->jobs, 1);
341 	free(c->jobs);
342 }
343 
344 /* Remove old jobs periodically. */
345 static void
346 format_job_timer(__unused int fd, __unused short events, __unused void *arg)
347 {
348 	struct client	*c;
349 	struct timeval	 tv = { .tv_sec = 60 };
350 
351 	format_job_tidy(&format_jobs, 0);
352 	TAILQ_FOREACH(c, &clients, entry) {
353 		if (c->jobs != NULL)
354 			format_job_tidy(c->jobs, 0);
355 	}
356 
357 	evtimer_del(&format_job_event);
358 	evtimer_add(&format_job_event, &tv);
359 }
360 
361 /* Callback for host. */
362 static void
363 format_cb_host(__unused struct format_tree *ft, struct format_entry *fe)
364 {
365 	char host[HOST_NAME_MAX + 1];
366 
367 	if (gethostname(host, sizeof host) != 0)
368 		fe->value = xstrdup("");
369 	else
370 		fe->value = xstrdup(host);
371 }
372 
373 /* Callback for host_short. */
374 static void
375 format_cb_host_short(__unused struct format_tree *ft, struct format_entry *fe)
376 {
377 	char host[HOST_NAME_MAX + 1], *cp;
378 
379 	if (gethostname(host, sizeof host) != 0)
380 		fe->value = xstrdup("");
381 	else {
382 		if ((cp = strchr(host, '.')) != NULL)
383 			*cp = '\0';
384 		fe->value = xstrdup(host);
385 	}
386 }
387 
388 /* Callback for pid. */
389 static void
390 format_cb_pid(__unused struct format_tree *ft, struct format_entry *fe)
391 {
392 	xasprintf(&fe->value, "%ld", (long)getpid());
393 }
394 
395 /* Callback for session_alerts. */
396 static void
397 format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe)
398 {
399 	struct session	*s = ft->s;
400 	struct winlink	*wl;
401 	char		 alerts[1024], tmp[16];
402 
403 	if (s == NULL)
404 		return;
405 
406 	*alerts = '\0';
407 	RB_FOREACH(wl, winlinks, &s->windows) {
408 		if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
409 			continue;
410 		xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
411 
412 		if (*alerts != '\0')
413 			strlcat(alerts, ",", sizeof alerts);
414 		strlcat(alerts, tmp, sizeof alerts);
415 		if (wl->flags & WINLINK_ACTIVITY)
416 			strlcat(alerts, "#", sizeof alerts);
417 		if (wl->flags & WINLINK_BELL)
418 			strlcat(alerts, "!", sizeof alerts);
419 		if (wl->flags & WINLINK_SILENCE)
420 			strlcat(alerts, "~", sizeof alerts);
421 	}
422 	fe->value = xstrdup(alerts);
423 }
424 
425 /* Callback for session_stack. */
426 static void
427 format_cb_session_stack(struct format_tree *ft, struct format_entry *fe)
428 {
429 	struct session	*s = ft->s;
430 	struct winlink	*wl;
431 	char		 result[1024], tmp[16];
432 
433 	if (s == NULL)
434 		return;
435 
436 	xsnprintf(result, sizeof result, "%u", s->curw->idx);
437 	TAILQ_FOREACH(wl, &s->lastw, sentry) {
438 		xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
439 
440 		if (*result != '\0')
441 			strlcat(result, ",", sizeof result);
442 		strlcat(result, tmp, sizeof result);
443 	}
444 	fe->value = xstrdup(result);
445 }
446 
447 /* Callback for window_stack_index. */
448 static void
449 format_cb_window_stack_index(struct format_tree *ft, struct format_entry *fe)
450 {
451 	struct session	*s = ft->wl->session;
452 	struct winlink	*wl;
453 	u_int		 idx;
454 
455 	idx = 0;
456 	TAILQ_FOREACH(wl, &s->lastw, sentry) {
457 		idx++;
458 		if (wl == ft->wl)
459 			break;
460 	}
461 	if (wl != NULL)
462 		xasprintf(&fe->value, "%u", idx);
463 	else
464 		fe->value = xstrdup("0");
465 }
466 
467 /* Callback for window_layout. */
468 static void
469 format_cb_window_layout(struct format_tree *ft, struct format_entry *fe)
470 {
471 	struct window	*w = ft->w;
472 
473 	if (w == NULL)
474 		return;
475 
476 	if (w->saved_layout_root != NULL)
477 		fe->value = layout_dump(w->saved_layout_root);
478 	else
479 		fe->value = layout_dump(w->layout_root);
480 }
481 
482 /* Callback for window_visible_layout. */
483 static void
484 format_cb_window_visible_layout(struct format_tree *ft, struct format_entry *fe)
485 {
486 	struct window	*w = ft->w;
487 
488 	if (w == NULL)
489 		return;
490 
491 	fe->value = layout_dump(w->layout_root);
492 }
493 
494 /* Callback for pane_start_command. */
495 static void
496 format_cb_start_command(struct format_tree *ft, struct format_entry *fe)
497 {
498 	struct window_pane	*wp = ft->wp;
499 
500 	if (wp == NULL)
501 		return;
502 
503 	fe->value = cmd_stringify_argv(wp->argc, wp->argv);
504 }
505 
506 /* Callback for pane_current_command. */
507 static void
508 format_cb_current_command(struct format_tree *ft, struct format_entry *fe)
509 {
510 	struct window_pane	*wp = ft->wp;
511 	char			*cmd;
512 
513 	if (wp == NULL)
514 		return;
515 
516 	cmd = get_proc_name(wp->fd, wp->tty);
517 	if (cmd == NULL || *cmd == '\0') {
518 		free(cmd);
519 		cmd = cmd_stringify_argv(wp->argc, wp->argv);
520 		if (cmd == NULL || *cmd == '\0') {
521 			free(cmd);
522 			cmd = xstrdup(wp->shell);
523 		}
524 	}
525 	fe->value = parse_window_name(cmd);
526 	free(cmd);
527 }
528 
529 /* Callback for history_bytes. */
530 static void
531 format_cb_history_bytes(struct format_tree *ft, struct format_entry *fe)
532 {
533 	struct window_pane	*wp = ft->wp;
534 	struct grid		*gd;
535 	struct grid_line	*gl;
536 	unsigned long long	 size;
537 	u_int			 i;
538 
539 	if (wp == NULL)
540 		return;
541 	gd = wp->base.grid;
542 
543 	size = 0;
544 	for (i = 0; i < gd->hsize; i++) {
545 		gl = &gd->linedata[i];
546 		size += gl->cellsize * sizeof *gl->celldata;
547 		size += gl->extdsize * sizeof *gl->extddata;
548 	}
549 	size += gd->hsize * sizeof *gd->linedata;
550 
551 	xasprintf(&fe->value, "%llu", size);
552 }
553 
554 /* Callback for pane_tabs. */
555 static void
556 format_cb_pane_tabs(struct format_tree *ft, struct format_entry *fe)
557 {
558 	struct window_pane	*wp = ft->wp;
559 	struct evbuffer		*buffer;
560 	u_int			 i;
561 	int			 size;
562 
563 	if (wp == NULL)
564 		return;
565 
566 	buffer = evbuffer_new();
567 	for (i = 0; i < wp->base.grid->sx; i++) {
568 		if (!bit_test(wp->base.tabs, i))
569 			continue;
570 
571 		if (EVBUFFER_LENGTH(buffer) > 0)
572 			evbuffer_add(buffer, ",", 1);
573 		evbuffer_add_printf(buffer, "%u", i);
574 	}
575 	size = EVBUFFER_LENGTH(buffer);
576 	xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
577 	evbuffer_free(buffer);
578 }
579 
580 /* Merge a format tree. */
581 static void
582 format_merge(struct format_tree *ft, struct format_tree *from)
583 {
584 	struct format_entry	*fe;
585 
586 	RB_FOREACH(fe, format_entry_tree, &from->tree) {
587 		if (fe->value != NULL)
588 			format_add(ft, fe->key, "%s", fe->value);
589 	}
590 }
591 
592 /* Create a new tree. */
593 struct format_tree *
594 format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
595 {
596 	struct format_tree	*ft;
597 
598 	if (!event_initialized(&format_job_event)) {
599 		evtimer_set(&format_job_event, format_job_timer, NULL);
600 		format_job_timer(-1, 0, NULL);
601 	}
602 
603 	ft = xcalloc(1, sizeof *ft);
604 	RB_INIT(&ft->tree);
605 
606 	if (c != NULL) {
607 		ft->client = c;
608 		ft->client->references++;
609 	}
610 
611 	ft->tag = tag;
612 	ft->flags = flags;
613 
614 	format_add_cb(ft, "host", format_cb_host);
615 	format_add_cb(ft, "host_short", format_cb_host_short);
616 	format_add_cb(ft, "pid", format_cb_pid);
617 	format_add(ft, "socket_path", "%s", socket_path);
618 	format_add_tv(ft, "start_time", &start_time);
619 
620 	if (item != NULL) {
621 		if (item->cmd != NULL)
622 			format_add(ft, "command", "%s", item->cmd->entry->name);
623 		if (item->shared != NULL && item->shared->formats != NULL)
624 			format_merge(ft, item->shared->formats);
625 	}
626 
627 	return (ft);
628 }
629 
630 /* Free a tree. */
631 void
632 format_free(struct format_tree *ft)
633 {
634 	struct format_entry	*fe, *fe1;
635 
636 	RB_FOREACH_SAFE(fe, format_entry_tree, &ft->tree, fe1) {
637 		RB_REMOVE(format_entry_tree, &ft->tree, fe);
638 		free(fe->value);
639 		free(fe->key);
640 		free(fe);
641 	}
642 
643 	if (ft->client != NULL)
644 		server_client_unref(ft->client);
645 	free(ft);
646 }
647 
648 /* Add a key-value pair. */
649 void
650 format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
651 {
652 	struct format_entry	*fe;
653 	struct format_entry	*fe_now;
654 	va_list			 ap;
655 
656 	fe = xmalloc(sizeof *fe);
657 	fe->key = xstrdup(key);
658 
659 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
660 	if (fe_now != NULL) {
661 		free(fe->key);
662 		free(fe);
663 		free(fe_now->value);
664 		fe = fe_now;
665 	}
666 
667 	fe->cb = NULL;
668 	fe->t = 0;
669 
670 	va_start(ap, fmt);
671 	xvasprintf(&fe->value, fmt, ap);
672 	va_end(ap);
673 }
674 
675 /* Add a key and time. */
676 static void
677 format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
678 {
679 	struct format_entry	*fe;
680 	struct format_entry	*fe_now;
681 
682 	fe = xmalloc(sizeof *fe);
683 	fe->key = xstrdup(key);
684 
685 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
686 	if (fe_now != NULL) {
687 		free(fe->key);
688 		free(fe);
689 		free(fe_now->value);
690 		fe = fe_now;
691 	}
692 
693 	fe->cb = NULL;
694 	fe->t = tv->tv_sec;
695 
696 	fe->value = NULL;
697 }
698 
699 /* Add a key and function. */
700 static void
701 format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
702 {
703 	struct format_entry	*fe;
704 	struct format_entry	*fe_now;
705 
706 	fe = xmalloc(sizeof *fe);
707 	fe->key = xstrdup(key);
708 
709 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
710 	if (fe_now != NULL) {
711 		free(fe->key);
712 		free(fe);
713 		free(fe_now->value);
714 		fe = fe_now;
715 	}
716 
717 	fe->cb = cb;
718 	fe->t = 0;
719 
720 	fe->value = NULL;
721 }
722 
723 /* Find a format entry. */
724 static char *
725 format_find(struct format_tree *ft, const char *key, int modifiers)
726 {
727 	struct format_entry	*fe, fe_find;
728 	struct environ_entry	*envent;
729 	static char		 s[64];
730 	struct options_entry	*o;
731 	const char		*found;
732 	int			 idx;
733 	char			*copy, *saved;
734 
735 	if (~modifiers & FORMAT_TIMESTRING) {
736 		o = options_parse_get(global_options, key, &idx, 0);
737 		if (o == NULL && ft->w != NULL)
738 			o = options_parse_get(ft->w->options, key, &idx, 0);
739 		if (o == NULL)
740 			o = options_parse_get(global_w_options, key, &idx, 0);
741 		if (o == NULL && ft->s != NULL)
742 			o = options_parse_get(ft->s->options, key, &idx, 0);
743 		if (o == NULL)
744 			o = options_parse_get(global_s_options, key, &idx, 0);
745 		if (o != NULL) {
746 			found = options_tostring(o, idx, 1);
747 			goto found;
748 		}
749 	}
750 	found = NULL;
751 
752 	fe_find.key = (char *) key;
753 	fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
754 	if (fe != NULL) {
755 		if (modifiers & FORMAT_TIMESTRING) {
756 			if (fe->t == 0)
757 				return (NULL);
758 			ctime_r(&fe->t, s);
759 			s[strcspn(s, "\n")] = '\0';
760 			found = s;
761 			goto found;
762 		}
763 		if (fe->t != 0) {
764 			xsnprintf(s, sizeof s, "%lld", (long long)fe->t);
765 			found = s;
766 			goto found;
767 		}
768 		if (fe->value == NULL && fe->cb != NULL)
769 			fe->cb(ft, fe);
770 		found = fe->value;
771 		goto found;
772 	}
773 
774 	if (~modifiers & FORMAT_TIMESTRING) {
775 		envent = NULL;
776 		if (ft->s != NULL)
777 			envent = environ_find(ft->s->environ, key);
778 		if (envent == NULL)
779 			envent = environ_find(global_environ, key);
780 		if (envent != NULL) {
781 			found = envent->value;
782 			goto found;
783 		}
784 	}
785 
786 	return (NULL);
787 
788 found:
789 	if (found == NULL)
790 		return (NULL);
791 	copy = xstrdup(found);
792 	if (modifiers & FORMAT_BASENAME) {
793 		saved = copy;
794 		copy = xstrdup(basename(saved));
795 		free(saved);
796 	}
797 	if (modifiers & FORMAT_DIRNAME) {
798 		saved = copy;
799 		copy = xstrdup(dirname(saved));
800 		free(saved);
801 	}
802 	return (copy);
803 }
804 
805 /* Skip until comma. */
806 static char *
807 format_skip(char *s)
808 {
809 	int	brackets = 0;
810 
811 	for (; *s != '\0'; s++) {
812 		if (*s == '{')
813 			brackets++;
814 		if (*s == '}')
815 			brackets--;
816 		if (*s == ',' && brackets == 0)
817 			break;
818 	}
819 	if (*s == '\0')
820 		return (NULL);
821 	return (s);
822 }
823 
824 /* Return left and right alternatives separated by commas. */
825 static int
826 format_choose(char *s, char **left, char **right)
827 {
828 	char	*cp;
829 
830 	cp = format_skip(s);
831 	if (cp == NULL)
832 		return (-1);
833 	*cp = '\0';
834 
835 	*left = s;
836 	*right = cp + 1;
837 	return (0);
838 }
839 
840 /* Is this true? */
841 int
842 format_true(const char *s)
843 {
844 	if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0'))
845 		return (1);
846 	return (0);
847 }
848 
849 /* Replace a key. */
850 static int
851 format_replace(struct format_tree *ft, const char *key, size_t keylen,
852     char **buf, size_t *len, size_t *off)
853 {
854 	struct window_pane	*wp = ft->wp;
855 	char			*copy, *copy0, *endptr, *ptr, *found, *new;
856 	char			*value, *from = NULL, *to = NULL, *left, *right;
857 	size_t			 valuelen, newlen, fromlen, tolen, used;
858 	long			 limit = 0;
859 	int			 modifiers = 0, compare = 0, search = 0;
860 
861 	/* Make a copy of the key. */
862 	copy0 = copy = xmalloc(keylen + 1);
863 	memcpy(copy, key, keylen);
864 	copy[keylen] = '\0';
865 
866 	/* Is there a length limit or whatnot? */
867 	switch (copy[0]) {
868 	case 'm':
869 		if (copy[1] != ':')
870 			break;
871 		compare = -2;
872 		copy += 2;
873 		break;
874 	case 'C':
875 		if (copy[1] != ':')
876 			break;
877 		search = 1;
878 		copy += 2;
879 		break;
880 	case '|':
881 		if (copy[1] != '|' || copy[2] != ':')
882 			break;
883 		compare = -3;
884 		copy += 3;
885 		break;
886 	case '&':
887 		if (copy[1] != '&' || copy[2] != ':')
888 			break;
889 		compare = -4;
890 		copy += 3;
891 		break;
892 	case '!':
893 		if (copy[1] == '=' && copy[2] == ':') {
894 			compare = -1;
895 			copy += 3;
896 			break;
897 		}
898 		break;
899 	case '=':
900 		if (copy[1] == '=' && copy[2] == ':') {
901 			compare = 1;
902 			copy += 3;
903 			break;
904 		}
905 		errno = 0;
906 		limit = strtol(copy + 1, &endptr, 10);
907 		if (errno == ERANGE && (limit == LONG_MIN || limit == LONG_MAX))
908 			break;
909 		if (*endptr != ':')
910 			break;
911 		copy = endptr + 1;
912 		break;
913 	case 'b':
914 		if (copy[1] != ':')
915 			break;
916 		modifiers |= FORMAT_BASENAME;
917 		copy += 2;
918 		break;
919 	case 'd':
920 		if (copy[1] != ':')
921 			break;
922 		modifiers |= FORMAT_DIRNAME;
923 		copy += 2;
924 		break;
925 	case 't':
926 		if (copy[1] != ':')
927 			break;
928 		modifiers |= FORMAT_TIMESTRING;
929 		copy += 2;
930 		break;
931 	case 's':
932 		if (copy[1] != '/')
933 			break;
934 		from = copy + 2;
935 		for (copy = from; *copy != '\0' && *copy != '/'; copy++)
936 			/* nothing */;
937 		if (copy[0] != '/' || copy == from) {
938 			copy = copy0;
939 			break;
940 		}
941 		copy[0] = '\0';
942 		to = copy + 1;
943 		for (copy = to; *copy != '\0' && *copy != '/'; copy++)
944 			/* nothing */;
945 		if (copy[0] != '/' || copy[1] != ':') {
946 			copy = copy0;
947 			break;
948 		}
949 		copy[0] = '\0';
950 
951 		modifiers |= FORMAT_SUBSTITUTE;
952 		copy += 2;
953 		break;
954 	}
955 
956 	/* Is this a comparison or a conditional? */
957 	if (search) {
958 		/* Search in pane. */
959 		if (wp == NULL)
960 			value = xstrdup("0");
961 		else
962 			xasprintf(&value, "%u", window_pane_search(wp, copy));
963 	} else if (compare != 0) {
964 		/* Comparison: compare comma-separated left and right. */
965 		if (format_choose(copy, &left, &right) != 0)
966 			goto fail;
967 		left = format_expand(ft, left);
968 		right = format_expand(ft, right);
969 		if (compare == -3 &&
970 		    (format_true(left) || format_true(right)))
971 			value = xstrdup("1");
972 		else if (compare == -4 &&
973 		    (format_true(left) && format_true(right)))
974 			value = xstrdup("1");
975 		else if (compare == 1 && strcmp(left, right) == 0)
976 			value = xstrdup("1");
977 		else if (compare == -1 && strcmp(left, right) != 0)
978 			value = xstrdup("1");
979 		else if (compare == -2 && fnmatch(left, right, 0) == 0)
980 			value = xstrdup("1");
981 		else
982 			value = xstrdup("0");
983 		free(right);
984 		free(left);
985 	} else if (*copy == '?') {
986 		/* Conditional: check first and choose second or third. */
987 		ptr = format_skip(copy);
988 		if (ptr == NULL)
989 			goto fail;
990 		*ptr = '\0';
991 
992 		found = format_find(ft, copy + 1, modifiers);
993 		if (found == NULL)
994 			found = format_expand(ft, copy + 1);
995 		if (format_choose(ptr + 1, &left, &right) != 0)
996 			goto fail;
997 
998 		if (format_true(found))
999 			value = format_expand(ft, left);
1000 		else
1001 			value = format_expand(ft, right);
1002 		free(found);
1003 	} else {
1004 		/* Neither: look up directly. */
1005 		value = format_find(ft, copy, modifiers);
1006 		if (value == NULL)
1007 			value = xstrdup("");
1008 	}
1009 
1010 	/* Perform substitution if any. */
1011 	if (modifiers & FORMAT_SUBSTITUTE) {
1012 		fromlen = strlen(from);
1013 		tolen = strlen(to);
1014 
1015 		newlen = strlen(value) + 1;
1016 		copy = new = xmalloc(newlen);
1017 		for (ptr = value; *ptr != '\0'; /* nothing */) {
1018 			if (strncmp(ptr, from, fromlen) != 0) {
1019 				*new++ = *ptr++;
1020 				continue;
1021 			}
1022 			used = new - copy;
1023 
1024 			newlen += tolen;
1025 			copy = xrealloc(copy, newlen);
1026 
1027 			new = copy + used;
1028 			memcpy(new, to, tolen);
1029 
1030 			new += tolen;
1031 			ptr += fromlen;
1032 		}
1033 		*new = '\0';
1034 		free(value);
1035 		value = copy;
1036 	}
1037 
1038 	/* Truncate the value if needed. */
1039 	if (limit > 0) {
1040 		new = utf8_trimcstr(value, limit);
1041 		free(value);
1042 		value = new;
1043 	} else if (limit < 0) {
1044 		new = utf8_rtrimcstr(value, -limit);
1045 		free(value);
1046 		value = new;
1047 	}
1048 
1049 	/* Expand the buffer and copy in the value. */
1050 	valuelen = strlen(value);
1051 	while (*len - *off < valuelen + 1) {
1052 		*buf = xreallocarray(*buf, 2, *len);
1053 		*len *= 2;
1054 	}
1055 	memcpy(*buf + *off, value, valuelen);
1056 	*off += valuelen;
1057 
1058 	free(value);
1059 	free(copy0);
1060 	return (0);
1061 
1062 fail:
1063 	free(copy0);
1064 	return (-1);
1065 }
1066 
1067 /* Expand keys in a template, passing through strftime first. */
1068 char *
1069 format_expand_time(struct format_tree *ft, const char *fmt, time_t t)
1070 {
1071 	struct tm	*tm;
1072 	char		 s[2048];
1073 
1074 	if (fmt == NULL || *fmt == '\0')
1075 		return (xstrdup(""));
1076 
1077 	tm = localtime(&t);
1078 
1079 	if (strftime(s, sizeof s, fmt, tm) == 0)
1080 		return (xstrdup(""));
1081 
1082 	return (format_expand(ft, s));
1083 }
1084 
1085 /* Expand keys in a template. */
1086 char *
1087 format_expand(struct format_tree *ft, const char *fmt)
1088 {
1089 	char		*buf, *out;
1090 	const char	*ptr, *s, *saved = fmt;
1091 	size_t		 off, len, n, outlen;
1092 	int     	 ch, brackets;
1093 
1094 	if (fmt == NULL)
1095 		return (xstrdup(""));
1096 
1097 	len = 64;
1098 	buf = xmalloc(len);
1099 	off = 0;
1100 
1101 	while (*fmt != '\0') {
1102 		if (*fmt != '#') {
1103 			while (len - off < 2) {
1104 				buf = xreallocarray(buf, 2, len);
1105 				len *= 2;
1106 			}
1107 			buf[off++] = *fmt++;
1108 			continue;
1109 		}
1110 		fmt++;
1111 
1112 		ch = (u_char) *fmt++;
1113 		switch (ch) {
1114 		case '(':
1115 			brackets = 1;
1116 			for (ptr = fmt; *ptr != '\0'; ptr++) {
1117 				if (*ptr == '(')
1118 					brackets++;
1119 				if (*ptr == ')' && --brackets == 0)
1120 					break;
1121 			}
1122 			if (*ptr != ')' || brackets != 0)
1123 				break;
1124 			n = ptr - fmt;
1125 
1126 			if (ft->flags & FORMAT_NOJOBS)
1127 				out = xstrdup("");
1128 			else
1129 				out = format_job_get(ft, xstrndup(fmt, n));
1130 			outlen = strlen(out);
1131 
1132 			while (len - off < outlen + 1) {
1133 				buf = xreallocarray(buf, 2, len);
1134 				len *= 2;
1135 			}
1136 			memcpy(buf + off, out, outlen);
1137 			off += outlen;
1138 
1139 			free(out);
1140 
1141 			fmt += n + 1;
1142 			continue;
1143 		case '{':
1144 			brackets = 1;
1145 			for (ptr = fmt; *ptr != '\0'; ptr++) {
1146 				if (*ptr == '{')
1147 					brackets++;
1148 				if (*ptr == '}' && --brackets == 0)
1149 					break;
1150 			}
1151 			if (*ptr != '}' || brackets != 0)
1152 				break;
1153 			n = ptr - fmt;
1154 
1155 			if (format_replace(ft, fmt, n, &buf, &len, &off) != 0)
1156 				break;
1157 			fmt += n + 1;
1158 			continue;
1159 		case '#':
1160 			while (len - off < 2) {
1161 				buf = xreallocarray(buf, 2, len);
1162 				len *= 2;
1163 			}
1164 			buf[off++] = '#';
1165 			continue;
1166 		default:
1167 			s = NULL;
1168 			if (ch >= 'A' && ch <= 'Z')
1169 				s = format_upper[ch - 'A'];
1170 			else if (ch >= 'a' && ch <= 'z')
1171 				s = format_lower[ch - 'a'];
1172 			if (s == NULL) {
1173 				while (len - off < 3) {
1174 					buf = xreallocarray(buf, 2, len);
1175 					len *= 2;
1176 				}
1177 				buf[off++] = '#';
1178 				buf[off++] = ch;
1179 				continue;
1180 			}
1181 			n = strlen(s);
1182 			if (format_replace(ft, s, n, &buf, &len, &off) != 0)
1183 				break;
1184 			continue;
1185 		}
1186 
1187 		break;
1188 	}
1189 	buf[off] = '\0';
1190 
1191 	log_debug("format '%s' -> '%s'", saved, buf);
1192 	return (buf);
1193 }
1194 
1195 /* Expand a single string. */
1196 char *
1197 format_single(struct cmdq_item *item, const char *fmt, struct client *c,
1198     struct session *s, struct winlink *wl, struct window_pane *wp)
1199 {
1200 	struct format_tree	*ft;
1201 	char			*expanded;
1202 
1203 	if (item != NULL)
1204 		ft = format_create(item->client, item, FORMAT_NONE, 0);
1205 	else
1206 		ft = format_create(NULL, item, FORMAT_NONE, 0);
1207 	format_defaults(ft, c, s, wl, wp);
1208 
1209 	expanded = format_expand(ft, fmt);
1210 	format_free(ft);
1211 	return (expanded);
1212 }
1213 
1214 /* Set defaults for any of arguments that are not NULL. */
1215 void
1216 format_defaults(struct format_tree *ft, struct client *c, struct session *s,
1217     struct winlink *wl, struct window_pane *wp)
1218 {
1219 	format_add(ft, "session_format", "%d", s != NULL);
1220 	format_add(ft, "window_format", "%d", wl != NULL);
1221 	format_add(ft, "pane_format", "%d", wp != NULL);
1222 
1223 	if (s == NULL && c != NULL)
1224 		s = c->session;
1225 	if (wl == NULL && s != NULL)
1226 		wl = s->curw;
1227 	if (wp == NULL && wl != NULL)
1228 		wp = wl->window->active;
1229 
1230 	if (c != NULL)
1231 		format_defaults_client(ft, c);
1232 	if (s != NULL)
1233 		format_defaults_session(ft, s);
1234 	if (wl != NULL)
1235 		format_defaults_winlink(ft, wl);
1236 	if (wp != NULL)
1237 		format_defaults_pane(ft, wp);
1238 }
1239 
1240 /* Set default format keys for a session. */
1241 static void
1242 format_defaults_session(struct format_tree *ft, struct session *s)
1243 {
1244 	struct session_group	*sg;
1245 
1246 	ft->s = s;
1247 
1248 	format_add(ft, "session_name", "%s", s->name);
1249 	format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
1250 	format_add(ft, "session_width", "%u", s->sx);
1251 	format_add(ft, "session_height", "%u", s->sy);
1252 	format_add(ft, "session_id", "$%u", s->id);
1253 
1254 	sg = session_group_contains(s);
1255 	format_add(ft, "session_grouped", "%d", sg != NULL);
1256 	if (sg != NULL)
1257 		format_add(ft, "session_group", "%s", sg->name);
1258 
1259 	format_add_tv(ft, "session_created", &s->creation_time);
1260 	format_add_tv(ft, "session_last_attached", &s->last_attached_time);
1261 	format_add_tv(ft, "session_activity", &s->activity_time);
1262 
1263 	format_add(ft, "session_attached", "%u", s->attached);
1264 	format_add(ft, "session_many_attached", "%d", s->attached > 1);
1265 
1266 	format_add_cb(ft, "session_alerts", format_cb_session_alerts);
1267 	format_add_cb(ft, "session_stack", format_cb_session_stack);
1268 }
1269 
1270 /* Set default format keys for a client. */
1271 static void
1272 format_defaults_client(struct format_tree *ft, struct client *c)
1273 {
1274 	struct session	*s;
1275 	const char	*name;
1276 	struct tty	*tty = &c->tty;
1277 	const char	*types[] = TTY_TYPES;
1278 
1279 	if (ft->s == NULL)
1280 		ft->s = c->session;
1281 
1282 	format_add(ft, "client_name", "%s", c->name);
1283 	format_add(ft, "client_pid", "%ld", (long) c->pid);
1284 	format_add(ft, "client_height", "%u", tty->sy);
1285 	format_add(ft, "client_width", "%u", tty->sx);
1286 	format_add(ft, "client_tty", "%s", c->ttyname);
1287 	format_add(ft, "client_control_mode", "%d",
1288 		!!(c->flags & CLIENT_CONTROL));
1289 
1290 	if (tty->term_name != NULL)
1291 		format_add(ft, "client_termname", "%s", tty->term_name);
1292 	if (tty->term_name != NULL)
1293 		format_add(ft, "client_termtype", "%s", types[tty->term_type]);
1294 
1295 	format_add_tv(ft, "client_created", &c->creation_time);
1296 	format_add_tv(ft, "client_activity", &c->activity_time);
1297 
1298 	format_add(ft, "client_written", "%zu", c->written);
1299 	format_add(ft, "client_discarded", "%zu", c->discarded);
1300 
1301 	name = server_client_get_key_table(c);
1302 	if (strcmp(c->keytable->name, name) == 0)
1303 		format_add(ft, "client_prefix", "%d", 0);
1304 	else
1305 		format_add(ft, "client_prefix", "%d", 1);
1306 	format_add(ft, "client_key_table", "%s", c->keytable->name);
1307 
1308 	if (tty->flags & TTY_UTF8)
1309 		format_add(ft, "client_utf8", "%d", 1);
1310 	else
1311 		format_add(ft, "client_utf8", "%d", 0);
1312 
1313 	if (c->flags & CLIENT_READONLY)
1314 		format_add(ft, "client_readonly", "%d", 1);
1315 	else
1316 		format_add(ft, "client_readonly", "%d", 0);
1317 
1318 	s = c->session;
1319 	if (s != NULL)
1320 		format_add(ft, "client_session", "%s", s->name);
1321 	s = c->last_session;
1322 	if (s != NULL && session_alive(s))
1323 		format_add(ft, "client_last_session", "%s", s->name);
1324 }
1325 
1326 /* Set default format keys for a window. */
1327 void
1328 format_defaults_window(struct format_tree *ft, struct window *w)
1329 {
1330 	ft->w = w;
1331 
1332 	format_add_tv(ft, "window_activity", &w->activity_time);
1333 	format_add(ft, "window_id", "@%u", w->id);
1334 	format_add(ft, "window_name", "%s", w->name);
1335 	format_add(ft, "window_width", "%u", w->sx);
1336 	format_add(ft, "window_height", "%u", w->sy);
1337 	format_add_cb(ft, "window_layout", format_cb_window_layout);
1338 	format_add_cb(ft, "window_visible_layout",
1339 	    format_cb_window_visible_layout);
1340 	format_add(ft, "window_panes", "%u", window_count_panes(w));
1341 	format_add(ft, "window_zoomed_flag", "%d",
1342 	    !!(w->flags & WINDOW_ZOOMED));
1343 }
1344 
1345 /* Set default format keys for a winlink. */
1346 static void
1347 format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
1348 {
1349 	struct session	*s = wl->session;
1350 	struct window	*w = wl->window;
1351 
1352 	if (ft->w == NULL)
1353 		ft->w = wl->window;
1354 	ft->wl = wl;
1355 
1356 	format_defaults_window(ft, w);
1357 
1358 	format_add(ft, "window_index", "%d", wl->idx);
1359 	format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
1360 	format_add(ft, "window_flags", "%s", window_printable_flags(wl));
1361 	format_add(ft, "window_active", "%d", wl == s->curw);
1362 
1363 	format_add(ft, "window_bell_flag", "%d",
1364 	    !!(wl->flags & WINLINK_BELL));
1365 	format_add(ft, "window_activity_flag", "%d",
1366 	    !!(wl->flags & WINLINK_ACTIVITY));
1367 	format_add(ft, "window_silence_flag", "%d",
1368 	    !!(wl->flags & WINLINK_SILENCE));
1369 	format_add(ft, "window_last_flag", "%d",
1370 	    !!(wl == TAILQ_FIRST(&s->lastw)));
1371 	format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
1372 }
1373 
1374 /* Set default format keys for a window pane. */
1375 void
1376 format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
1377 {
1378 	struct grid	*gd = wp->base.grid;
1379 	u_int		 idx;
1380 	int  		 status;
1381 
1382 	if (ft->w == NULL)
1383 		ft->w = wp->window;
1384 	ft->wp = wp;
1385 
1386 	format_add(ft, "history_size", "%u", gd->hsize);
1387 	format_add(ft, "history_limit", "%u", gd->hlimit);
1388 	format_add_cb(ft, "history_bytes", format_cb_history_bytes);
1389 
1390 	if (window_pane_index(wp, &idx) != 0)
1391 		fatalx("index not found");
1392 	format_add(ft, "pane_index", "%u", idx);
1393 
1394 	format_add(ft, "pane_width", "%u", wp->sx);
1395 	format_add(ft, "pane_height", "%u", wp->sy);
1396 	format_add(ft, "pane_title", "%s", wp->base.title);
1397 	format_add(ft, "pane_id", "%%%u", wp->id);
1398 	format_add(ft, "pane_active", "%d", wp == wp->window->active);
1399 	format_add(ft, "pane_input_off", "%d", !!(wp->flags & PANE_INPUTOFF));
1400 	format_add(ft, "pane_pipe", "%d", wp->pipe_fd != -1);
1401 
1402 	status = wp->status;
1403 	if (wp->fd == -1 && WIFEXITED(status))
1404 		format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
1405 	format_add(ft, "pane_dead", "%d", wp->fd == -1);
1406 
1407 	if (window_pane_visible(wp)) {
1408 		format_add(ft, "pane_left", "%u", wp->xoff);
1409 		format_add(ft, "pane_top", "%u", wp->yoff);
1410 		format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
1411 		format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
1412 		format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
1413 		format_add(ft, "pane_at_top", "%d", wp->yoff == 0);
1414 		format_add(ft, "pane_at_right", "%d", wp->xoff + wp->sx == wp->window->sx);
1415 		format_add(ft, "pane_at_bottom", "%d", wp->yoff + wp->sy == wp->window->sy);
1416 	}
1417 
1418 	format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
1419 	if (wp->mode != NULL)
1420 		format_add(ft, "pane_mode", "%s", wp->mode->name);
1421 
1422 	format_add(ft, "pane_synchronized", "%d",
1423 	    !!options_get_number(wp->window->options, "synchronize-panes"));
1424 	if (wp->searchstr != NULL)
1425 		format_add(ft, "pane_search_string", "%s", wp->searchstr);
1426 
1427 	format_add(ft, "pane_tty", "%s", wp->tty);
1428 	format_add(ft, "pane_pid", "%ld", (long) wp->pid);
1429 	format_add_cb(ft, "pane_start_command", format_cb_start_command);
1430 	format_add_cb(ft, "pane_current_command", format_cb_current_command);
1431 
1432 	format_add(ft, "cursor_x", "%u", wp->base.cx);
1433 	format_add(ft, "cursor_y", "%u", wp->base.cy);
1434 	format_add(ft, "scroll_region_upper", "%u", wp->base.rupper);
1435 	format_add(ft, "scroll_region_lower", "%u", wp->base.rlower);
1436 
1437 	window_copy_add_formats(wp, ft);
1438 
1439 	format_add(ft, "alternate_on", "%d", wp->saved_grid ? 1 : 0);
1440 	format_add(ft, "alternate_saved_x", "%u", wp->saved_cx);
1441 	format_add(ft, "alternate_saved_y", "%u", wp->saved_cy);
1442 
1443 	format_add(ft, "cursor_flag", "%d",
1444 	    !!(wp->base.mode & MODE_CURSOR));
1445 	format_add(ft, "insert_flag", "%d",
1446 	    !!(wp->base.mode & MODE_INSERT));
1447 	format_add(ft, "keypad_cursor_flag", "%d",
1448 	    !!(wp->base.mode & MODE_KCURSOR));
1449 	format_add(ft, "keypad_flag", "%d",
1450 	    !!(wp->base.mode & MODE_KKEYPAD));
1451 	format_add(ft, "wrap_flag", "%d",
1452 	    !!(wp->base.mode & MODE_WRAP));
1453 
1454 	format_add(ft, "mouse_any_flag", "%d",
1455 	    !!(wp->base.mode & ALL_MOUSE_MODES));
1456 	format_add(ft, "mouse_standard_flag", "%d",
1457 	    !!(wp->base.mode & MODE_MOUSE_STANDARD));
1458 	format_add(ft, "mouse_button_flag", "%d",
1459 	    !!(wp->base.mode & MODE_MOUSE_BUTTON));
1460 	format_add(ft, "mouse_all_flag", "%d",
1461 	    !!(wp->base.mode & MODE_MOUSE_ALL));
1462 
1463 	format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
1464 }
1465 
1466 /* Set default format keys for paste buffer. */
1467 void
1468 format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
1469 {
1470 	struct timeval	 tv;
1471 	size_t		 size;
1472 	char		*s;
1473 
1474 	timerclear(&tv);
1475 	tv.tv_sec = paste_buffer_created(pb);
1476 	paste_buffer_data(pb, &size);
1477 
1478 	format_add(ft, "buffer_size", "%zu", size);
1479 	format_add(ft, "buffer_name", "%s", paste_buffer_name(pb));
1480 	format_add_tv(ft, "buffer_created", &tv);
1481 
1482 	s = paste_make_sample(pb);
1483 	format_add(ft, "buffer_sample", "%s", s);
1484 	free(s);
1485 }
1486