xref: /openbsd-src/usr.bin/tmux/format.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /* $OpenBSD: format.c,v 1.150 2017/11/02 18:52:05 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 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
576 		xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
577 	evbuffer_free(buffer);
578 }
579 
580 /* Callback for session_group_list. */
581 static void
582 format_cb_session_group_list(struct format_tree *ft, struct format_entry *fe)
583 {
584 	struct session		*s = ft->s;
585 	struct session_group	*sg;
586 	struct session		*loop;
587 	struct evbuffer		*buffer;
588 	int			 size;
589 
590 	if (s == NULL)
591 		return;
592 	sg = session_group_contains(s);
593 	if (sg == NULL)
594 		return;
595 
596 	buffer = evbuffer_new();
597 	TAILQ_FOREACH(loop, &sg->sessions, gentry) {
598 		if (EVBUFFER_LENGTH(buffer) > 0)
599 			evbuffer_add(buffer, ",", 1);
600 		evbuffer_add_printf(buffer, "%s", loop->name);
601 	}
602 	if ((size = EVBUFFER_LENGTH(buffer)) != 0)
603 		xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
604 	evbuffer_free(buffer);
605 }
606 
607 /* Merge a format tree. */
608 static void
609 format_merge(struct format_tree *ft, struct format_tree *from)
610 {
611 	struct format_entry	*fe;
612 
613 	RB_FOREACH(fe, format_entry_tree, &from->tree) {
614 		if (fe->value != NULL)
615 			format_add(ft, fe->key, "%s", fe->value);
616 	}
617 }
618 
619 /* Create a new tree. */
620 struct format_tree *
621 format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
622 {
623 	struct format_tree	*ft;
624 
625 	if (!event_initialized(&format_job_event)) {
626 		evtimer_set(&format_job_event, format_job_timer, NULL);
627 		format_job_timer(-1, 0, NULL);
628 	}
629 
630 	ft = xcalloc(1, sizeof *ft);
631 	RB_INIT(&ft->tree);
632 
633 	if (c != NULL) {
634 		ft->client = c;
635 		ft->client->references++;
636 	}
637 
638 	ft->tag = tag;
639 	ft->flags = flags;
640 
641 	format_add_cb(ft, "host", format_cb_host);
642 	format_add_cb(ft, "host_short", format_cb_host_short);
643 	format_add_cb(ft, "pid", format_cb_pid);
644 	format_add(ft, "socket_path", "%s", socket_path);
645 	format_add_tv(ft, "start_time", &start_time);
646 
647 	if (item != NULL) {
648 		if (item->cmd != NULL)
649 			format_add(ft, "command", "%s", item->cmd->entry->name);
650 		if (item->shared != NULL && item->shared->formats != NULL)
651 			format_merge(ft, item->shared->formats);
652 	}
653 
654 	return (ft);
655 }
656 
657 /* Free a tree. */
658 void
659 format_free(struct format_tree *ft)
660 {
661 	struct format_entry	*fe, *fe1;
662 
663 	RB_FOREACH_SAFE(fe, format_entry_tree, &ft->tree, fe1) {
664 		RB_REMOVE(format_entry_tree, &ft->tree, fe);
665 		free(fe->value);
666 		free(fe->key);
667 		free(fe);
668 	}
669 
670 	if (ft->client != NULL)
671 		server_client_unref(ft->client);
672 	free(ft);
673 }
674 
675 /* Add a key-value pair. */
676 void
677 format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
678 {
679 	struct format_entry	*fe;
680 	struct format_entry	*fe_now;
681 	va_list			 ap;
682 
683 	fe = xmalloc(sizeof *fe);
684 	fe->key = xstrdup(key);
685 
686 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
687 	if (fe_now != NULL) {
688 		free(fe->key);
689 		free(fe);
690 		free(fe_now->value);
691 		fe = fe_now;
692 	}
693 
694 	fe->cb = NULL;
695 	fe->t = 0;
696 
697 	va_start(ap, fmt);
698 	xvasprintf(&fe->value, fmt, ap);
699 	va_end(ap);
700 }
701 
702 /* Add a key and time. */
703 static void
704 format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
705 {
706 	struct format_entry	*fe;
707 	struct format_entry	*fe_now;
708 
709 	fe = xmalloc(sizeof *fe);
710 	fe->key = xstrdup(key);
711 
712 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
713 	if (fe_now != NULL) {
714 		free(fe->key);
715 		free(fe);
716 		free(fe_now->value);
717 		fe = fe_now;
718 	}
719 
720 	fe->cb = NULL;
721 	fe->t = tv->tv_sec;
722 
723 	fe->value = NULL;
724 }
725 
726 /* Add a key and function. */
727 static void
728 format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
729 {
730 	struct format_entry	*fe;
731 	struct format_entry	*fe_now;
732 
733 	fe = xmalloc(sizeof *fe);
734 	fe->key = xstrdup(key);
735 
736 	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
737 	if (fe_now != NULL) {
738 		free(fe->key);
739 		free(fe);
740 		free(fe_now->value);
741 		fe = fe_now;
742 	}
743 
744 	fe->cb = cb;
745 	fe->t = 0;
746 
747 	fe->value = NULL;
748 }
749 
750 /* Find a format entry. */
751 static char *
752 format_find(struct format_tree *ft, const char *key, int modifiers)
753 {
754 	struct format_entry	*fe, fe_find;
755 	struct environ_entry	*envent;
756 	static char		 s[64];
757 	struct options_entry	*o;
758 	const char		*found;
759 	int			 idx;
760 	char			*copy, *saved;
761 
762 	if (~modifiers & FORMAT_TIMESTRING) {
763 		o = options_parse_get(global_options, key, &idx, 0);
764 		if (o == NULL && ft->w != NULL)
765 			o = options_parse_get(ft->w->options, key, &idx, 0);
766 		if (o == NULL)
767 			o = options_parse_get(global_w_options, key, &idx, 0);
768 		if (o == NULL && ft->s != NULL)
769 			o = options_parse_get(ft->s->options, key, &idx, 0);
770 		if (o == NULL)
771 			o = options_parse_get(global_s_options, key, &idx, 0);
772 		if (o != NULL) {
773 			found = options_tostring(o, idx, 1);
774 			goto found;
775 		}
776 	}
777 	found = NULL;
778 
779 	fe_find.key = (char *) key;
780 	fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
781 	if (fe != NULL) {
782 		if (modifiers & FORMAT_TIMESTRING) {
783 			if (fe->t == 0)
784 				return (NULL);
785 			ctime_r(&fe->t, s);
786 			s[strcspn(s, "\n")] = '\0';
787 			found = s;
788 			goto found;
789 		}
790 		if (fe->t != 0) {
791 			xsnprintf(s, sizeof s, "%lld", (long long)fe->t);
792 			found = s;
793 			goto found;
794 		}
795 		if (fe->value == NULL && fe->cb != NULL) {
796 			fe->cb(ft, fe);
797 			if (fe->value == NULL)
798 				fe->value = xstrdup("");
799 		}
800 		found = fe->value;
801 		goto found;
802 	}
803 
804 	if (~modifiers & FORMAT_TIMESTRING) {
805 		envent = NULL;
806 		if (ft->s != NULL)
807 			envent = environ_find(ft->s->environ, key);
808 		if (envent == NULL)
809 			envent = environ_find(global_environ, key);
810 		if (envent != NULL) {
811 			found = envent->value;
812 			goto found;
813 		}
814 	}
815 
816 	return (NULL);
817 
818 found:
819 	if (found == NULL)
820 		return (NULL);
821 	copy = xstrdup(found);
822 	if (modifiers & FORMAT_BASENAME) {
823 		saved = copy;
824 		copy = xstrdup(basename(saved));
825 		free(saved);
826 	}
827 	if (modifiers & FORMAT_DIRNAME) {
828 		saved = copy;
829 		copy = xstrdup(dirname(saved));
830 		free(saved);
831 	}
832 	return (copy);
833 }
834 
835 /* Skip until comma. */
836 static char *
837 format_skip(char *s)
838 {
839 	int	brackets = 0;
840 
841 	for (; *s != '\0'; s++) {
842 		if (*s == '{')
843 			brackets++;
844 		if (*s == '}')
845 			brackets--;
846 		if (*s == ',' && brackets == 0)
847 			break;
848 	}
849 	if (*s == '\0')
850 		return (NULL);
851 	return (s);
852 }
853 
854 /* Return left and right alternatives separated by commas. */
855 static int
856 format_choose(char *s, char **left, char **right)
857 {
858 	char	*cp;
859 
860 	cp = format_skip(s);
861 	if (cp == NULL)
862 		return (-1);
863 	*cp = '\0';
864 
865 	*left = s;
866 	*right = cp + 1;
867 	return (0);
868 }
869 
870 /* Is this true? */
871 int
872 format_true(const char *s)
873 {
874 	if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0'))
875 		return (1);
876 	return (0);
877 }
878 
879 /* Replace a key. */
880 static int
881 format_replace(struct format_tree *ft, const char *key, size_t keylen,
882     char **buf, size_t *len, size_t *off)
883 {
884 	struct window_pane	*wp = ft->wp;
885 	char			*copy, *copy0, *endptr, *ptr, *found, *new;
886 	char			*value, *from = NULL, *to = NULL, *left, *right;
887 	size_t			 valuelen, newlen, fromlen, tolen, used;
888 	long			 limit = 0;
889 	int			 modifiers = 0, compare = 0, search = 0;
890 
891 	/* Make a copy of the key. */
892 	copy0 = copy = xmalloc(keylen + 1);
893 	memcpy(copy, key, keylen);
894 	copy[keylen] = '\0';
895 
896 	/* Is there a length limit or whatnot? */
897 	switch (copy[0]) {
898 	case 'm':
899 		if (copy[1] != ':')
900 			break;
901 		compare = -2;
902 		copy += 2;
903 		break;
904 	case 'C':
905 		if (copy[1] != ':')
906 			break;
907 		search = 1;
908 		copy += 2;
909 		break;
910 	case '|':
911 		if (copy[1] != '|' || copy[2] != ':')
912 			break;
913 		compare = -3;
914 		copy += 3;
915 		break;
916 	case '&':
917 		if (copy[1] != '&' || copy[2] != ':')
918 			break;
919 		compare = -4;
920 		copy += 3;
921 		break;
922 	case '!':
923 		if (copy[1] == '=' && copy[2] == ':') {
924 			compare = -1;
925 			copy += 3;
926 			break;
927 		}
928 		break;
929 	case '=':
930 		if (copy[1] == '=' && copy[2] == ':') {
931 			compare = 1;
932 			copy += 3;
933 			break;
934 		}
935 		errno = 0;
936 		limit = strtol(copy + 1, &endptr, 10);
937 		if (errno == ERANGE && (limit == LONG_MIN || limit == LONG_MAX))
938 			break;
939 		if (*endptr != ':')
940 			break;
941 		copy = endptr + 1;
942 		break;
943 	case 'b':
944 		if (copy[1] != ':')
945 			break;
946 		modifiers |= FORMAT_BASENAME;
947 		copy += 2;
948 		break;
949 	case 'd':
950 		if (copy[1] != ':')
951 			break;
952 		modifiers |= FORMAT_DIRNAME;
953 		copy += 2;
954 		break;
955 	case 't':
956 		if (copy[1] != ':')
957 			break;
958 		modifiers |= FORMAT_TIMESTRING;
959 		copy += 2;
960 		break;
961 	case 's':
962 		if (copy[1] != '/')
963 			break;
964 		from = copy + 2;
965 		for (copy = from; *copy != '\0' && *copy != '/'; copy++)
966 			/* nothing */;
967 		if (copy[0] != '/' || copy == from) {
968 			copy = copy0;
969 			break;
970 		}
971 		copy[0] = '\0';
972 		to = copy + 1;
973 		for (copy = to; *copy != '\0' && *copy != '/'; copy++)
974 			/* nothing */;
975 		if (copy[0] != '/' || copy[1] != ':') {
976 			copy = copy0;
977 			break;
978 		}
979 		copy[0] = '\0';
980 
981 		modifiers |= FORMAT_SUBSTITUTE;
982 		copy += 2;
983 		break;
984 	}
985 
986 	/* Is this a comparison or a conditional? */
987 	if (search) {
988 		/* Search in pane. */
989 		if (wp == NULL)
990 			value = xstrdup("0");
991 		else
992 			xasprintf(&value, "%u", window_pane_search(wp, copy));
993 	} else if (compare != 0) {
994 		/* Comparison: compare comma-separated left and right. */
995 		if (format_choose(copy, &left, &right) != 0)
996 			goto fail;
997 		left = format_expand(ft, left);
998 		right = format_expand(ft, right);
999 		if (compare == -3 &&
1000 		    (format_true(left) || format_true(right)))
1001 			value = xstrdup("1");
1002 		else if (compare == -4 &&
1003 		    (format_true(left) && format_true(right)))
1004 			value = xstrdup("1");
1005 		else if (compare == 1 && strcmp(left, right) == 0)
1006 			value = xstrdup("1");
1007 		else if (compare == -1 && strcmp(left, right) != 0)
1008 			value = xstrdup("1");
1009 		else if (compare == -2 && fnmatch(left, right, 0) == 0)
1010 			value = xstrdup("1");
1011 		else
1012 			value = xstrdup("0");
1013 		free(right);
1014 		free(left);
1015 	} else if (*copy == '?') {
1016 		/* Conditional: check first and choose second or third. */
1017 		ptr = format_skip(copy);
1018 		if (ptr == NULL)
1019 			goto fail;
1020 		*ptr = '\0';
1021 
1022 		found = format_find(ft, copy + 1, modifiers);
1023 		if (found == NULL)
1024 			found = format_expand(ft, copy + 1);
1025 		if (format_choose(ptr + 1, &left, &right) != 0)
1026 			goto fail;
1027 
1028 		if (format_true(found))
1029 			value = format_expand(ft, left);
1030 		else
1031 			value = format_expand(ft, right);
1032 		free(found);
1033 	} else {
1034 		/* Neither: look up directly. */
1035 		value = format_find(ft, copy, modifiers);
1036 		if (value == NULL)
1037 			value = xstrdup("");
1038 	}
1039 
1040 	/* Perform substitution if any. */
1041 	if (modifiers & FORMAT_SUBSTITUTE) {
1042 		fromlen = strlen(from);
1043 		tolen = strlen(to);
1044 
1045 		newlen = strlen(value) + 1;
1046 		copy = new = xmalloc(newlen);
1047 		for (ptr = value; *ptr != '\0'; /* nothing */) {
1048 			if (strncmp(ptr, from, fromlen) != 0) {
1049 				*new++ = *ptr++;
1050 				continue;
1051 			}
1052 			used = new - copy;
1053 
1054 			newlen += tolen;
1055 			copy = xrealloc(copy, newlen);
1056 
1057 			new = copy + used;
1058 			memcpy(new, to, tolen);
1059 
1060 			new += tolen;
1061 			ptr += fromlen;
1062 		}
1063 		*new = '\0';
1064 		free(value);
1065 		value = copy;
1066 	}
1067 
1068 	/* Truncate the value if needed. */
1069 	if (limit > 0) {
1070 		new = utf8_trimcstr(value, limit);
1071 		free(value);
1072 		value = new;
1073 	} else if (limit < 0) {
1074 		new = utf8_rtrimcstr(value, -limit);
1075 		free(value);
1076 		value = new;
1077 	}
1078 
1079 	/* Expand the buffer and copy in the value. */
1080 	valuelen = strlen(value);
1081 	while (*len - *off < valuelen + 1) {
1082 		*buf = xreallocarray(*buf, 2, *len);
1083 		*len *= 2;
1084 	}
1085 	memcpy(*buf + *off, value, valuelen);
1086 	*off += valuelen;
1087 
1088 	free(value);
1089 	free(copy0);
1090 	return (0);
1091 
1092 fail:
1093 	free(copy0);
1094 	return (-1);
1095 }
1096 
1097 /* Expand keys in a template, passing through strftime first. */
1098 char *
1099 format_expand_time(struct format_tree *ft, const char *fmt, time_t t)
1100 {
1101 	struct tm	*tm;
1102 	char		 s[2048];
1103 
1104 	if (fmt == NULL || *fmt == '\0')
1105 		return (xstrdup(""));
1106 
1107 	tm = localtime(&t);
1108 
1109 	if (strftime(s, sizeof s, fmt, tm) == 0)
1110 		return (xstrdup(""));
1111 
1112 	return (format_expand(ft, s));
1113 }
1114 
1115 /* Expand keys in a template. */
1116 char *
1117 format_expand(struct format_tree *ft, const char *fmt)
1118 {
1119 	char		*buf, *out;
1120 	const char	*ptr, *s, *saved = fmt;
1121 	size_t		 off, len, n, outlen;
1122 	int     	 ch, brackets;
1123 
1124 	if (fmt == NULL)
1125 		return (xstrdup(""));
1126 
1127 	len = 64;
1128 	buf = xmalloc(len);
1129 	off = 0;
1130 
1131 	while (*fmt != '\0') {
1132 		if (*fmt != '#') {
1133 			while (len - off < 2) {
1134 				buf = xreallocarray(buf, 2, len);
1135 				len *= 2;
1136 			}
1137 			buf[off++] = *fmt++;
1138 			continue;
1139 		}
1140 		fmt++;
1141 
1142 		ch = (u_char) *fmt++;
1143 		switch (ch) {
1144 		case '(':
1145 			brackets = 1;
1146 			for (ptr = fmt; *ptr != '\0'; ptr++) {
1147 				if (*ptr == '(')
1148 					brackets++;
1149 				if (*ptr == ')' && --brackets == 0)
1150 					break;
1151 			}
1152 			if (*ptr != ')' || brackets != 0)
1153 				break;
1154 			n = ptr - fmt;
1155 
1156 			if (ft->flags & FORMAT_NOJOBS)
1157 				out = xstrdup("");
1158 			else
1159 				out = format_job_get(ft, xstrndup(fmt, n));
1160 			outlen = strlen(out);
1161 
1162 			while (len - off < outlen + 1) {
1163 				buf = xreallocarray(buf, 2, len);
1164 				len *= 2;
1165 			}
1166 			memcpy(buf + off, out, outlen);
1167 			off += outlen;
1168 
1169 			free(out);
1170 
1171 			fmt += n + 1;
1172 			continue;
1173 		case '{':
1174 			brackets = 1;
1175 			for (ptr = fmt; *ptr != '\0'; ptr++) {
1176 				if (*ptr == '{')
1177 					brackets++;
1178 				if (*ptr == '}' && --brackets == 0)
1179 					break;
1180 			}
1181 			if (*ptr != '}' || brackets != 0)
1182 				break;
1183 			n = ptr - fmt;
1184 
1185 			if (format_replace(ft, fmt, n, &buf, &len, &off) != 0)
1186 				break;
1187 			fmt += n + 1;
1188 			continue;
1189 		case '#':
1190 			while (len - off < 2) {
1191 				buf = xreallocarray(buf, 2, len);
1192 				len *= 2;
1193 			}
1194 			buf[off++] = '#';
1195 			continue;
1196 		default:
1197 			s = NULL;
1198 			if (ch >= 'A' && ch <= 'Z')
1199 				s = format_upper[ch - 'A'];
1200 			else if (ch >= 'a' && ch <= 'z')
1201 				s = format_lower[ch - 'a'];
1202 			if (s == NULL) {
1203 				while (len - off < 3) {
1204 					buf = xreallocarray(buf, 2, len);
1205 					len *= 2;
1206 				}
1207 				buf[off++] = '#';
1208 				buf[off++] = ch;
1209 				continue;
1210 			}
1211 			n = strlen(s);
1212 			if (format_replace(ft, s, n, &buf, &len, &off) != 0)
1213 				break;
1214 			continue;
1215 		}
1216 
1217 		break;
1218 	}
1219 	buf[off] = '\0';
1220 
1221 	log_debug("format '%s' -> '%s'", saved, buf);
1222 	return (buf);
1223 }
1224 
1225 /* Expand a single string. */
1226 char *
1227 format_single(struct cmdq_item *item, const char *fmt, struct client *c,
1228     struct session *s, struct winlink *wl, struct window_pane *wp)
1229 {
1230 	struct format_tree	*ft;
1231 	char			*expanded;
1232 
1233 	if (item != NULL)
1234 		ft = format_create(item->client, item, FORMAT_NONE, 0);
1235 	else
1236 		ft = format_create(NULL, item, FORMAT_NONE, 0);
1237 	format_defaults(ft, c, s, wl, wp);
1238 
1239 	expanded = format_expand(ft, fmt);
1240 	format_free(ft);
1241 	return (expanded);
1242 }
1243 
1244 /* Set defaults for any of arguments that are not NULL. */
1245 void
1246 format_defaults(struct format_tree *ft, struct client *c, struct session *s,
1247     struct winlink *wl, struct window_pane *wp)
1248 {
1249 	format_add(ft, "session_format", "%d", s != NULL);
1250 	format_add(ft, "window_format", "%d", wl != NULL);
1251 	format_add(ft, "pane_format", "%d", wp != NULL);
1252 
1253 	if (s == NULL && c != NULL)
1254 		s = c->session;
1255 	if (wl == NULL && s != NULL)
1256 		wl = s->curw;
1257 	if (wp == NULL && wl != NULL)
1258 		wp = wl->window->active;
1259 
1260 	if (c != NULL)
1261 		format_defaults_client(ft, c);
1262 	if (s != NULL)
1263 		format_defaults_session(ft, s);
1264 	if (wl != NULL)
1265 		format_defaults_winlink(ft, wl);
1266 	if (wp != NULL)
1267 		format_defaults_pane(ft, wp);
1268 }
1269 
1270 /* Set default format keys for a session. */
1271 static void
1272 format_defaults_session(struct format_tree *ft, struct session *s)
1273 {
1274 	struct session_group	*sg;
1275 
1276 	ft->s = s;
1277 
1278 	format_add(ft, "session_name", "%s", s->name);
1279 	format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
1280 	format_add(ft, "session_width", "%u", s->sx);
1281 	format_add(ft, "session_height", "%u", s->sy);
1282 	format_add(ft, "session_id", "$%u", s->id);
1283 
1284 	sg = session_group_contains(s);
1285 	format_add(ft, "session_grouped", "%d", sg != NULL);
1286 	if (sg != NULL) {
1287 		format_add(ft, "session_group", "%s", sg->name);
1288 		format_add(ft, "session_group_size", "%u",
1289 		    session_group_count (sg));
1290 		format_add_cb(ft, "session_group_list",
1291 		    format_cb_session_group_list);
1292 	}
1293 
1294 	format_add_tv(ft, "session_created", &s->creation_time);
1295 	format_add_tv(ft, "session_last_attached", &s->last_attached_time);
1296 	format_add_tv(ft, "session_activity", &s->activity_time);
1297 
1298 	format_add(ft, "session_attached", "%u", s->attached);
1299 	format_add(ft, "session_many_attached", "%d", s->attached > 1);
1300 
1301 	format_add_cb(ft, "session_alerts", format_cb_session_alerts);
1302 	format_add_cb(ft, "session_stack", format_cb_session_stack);
1303 }
1304 
1305 /* Set default format keys for a client. */
1306 static void
1307 format_defaults_client(struct format_tree *ft, struct client *c)
1308 {
1309 	struct session	*s;
1310 	const char	*name;
1311 	struct tty	*tty = &c->tty;
1312 	const char	*types[] = TTY_TYPES;
1313 
1314 	if (ft->s == NULL)
1315 		ft->s = c->session;
1316 
1317 	format_add(ft, "client_name", "%s", c->name);
1318 	format_add(ft, "client_pid", "%ld", (long) c->pid);
1319 	format_add(ft, "client_height", "%u", tty->sy);
1320 	format_add(ft, "client_width", "%u", tty->sx);
1321 	format_add(ft, "client_tty", "%s", c->ttyname);
1322 	format_add(ft, "client_control_mode", "%d",
1323 		!!(c->flags & CLIENT_CONTROL));
1324 
1325 	if (tty->term_name != NULL)
1326 		format_add(ft, "client_termname", "%s", tty->term_name);
1327 	if (tty->term_name != NULL)
1328 		format_add(ft, "client_termtype", "%s", types[tty->term_type]);
1329 
1330 	format_add_tv(ft, "client_created", &c->creation_time);
1331 	format_add_tv(ft, "client_activity", &c->activity_time);
1332 
1333 	format_add(ft, "client_written", "%zu", c->written);
1334 	format_add(ft, "client_discarded", "%zu", c->discarded);
1335 
1336 	name = server_client_get_key_table(c);
1337 	if (strcmp(c->keytable->name, name) == 0)
1338 		format_add(ft, "client_prefix", "%d", 0);
1339 	else
1340 		format_add(ft, "client_prefix", "%d", 1);
1341 	format_add(ft, "client_key_table", "%s", c->keytable->name);
1342 
1343 	if (tty->flags & TTY_UTF8)
1344 		format_add(ft, "client_utf8", "%d", 1);
1345 	else
1346 		format_add(ft, "client_utf8", "%d", 0);
1347 
1348 	if (c->flags & CLIENT_READONLY)
1349 		format_add(ft, "client_readonly", "%d", 1);
1350 	else
1351 		format_add(ft, "client_readonly", "%d", 0);
1352 
1353 	s = c->session;
1354 	if (s != NULL)
1355 		format_add(ft, "client_session", "%s", s->name);
1356 	s = c->last_session;
1357 	if (s != NULL && session_alive(s))
1358 		format_add(ft, "client_last_session", "%s", s->name);
1359 }
1360 
1361 /* Set default format keys for a window. */
1362 void
1363 format_defaults_window(struct format_tree *ft, struct window *w)
1364 {
1365 	ft->w = w;
1366 
1367 	format_add_tv(ft, "window_activity", &w->activity_time);
1368 	format_add(ft, "window_id", "@%u", w->id);
1369 	format_add(ft, "window_name", "%s", w->name);
1370 	format_add(ft, "window_width", "%u", w->sx);
1371 	format_add(ft, "window_height", "%u", w->sy);
1372 	format_add_cb(ft, "window_layout", format_cb_window_layout);
1373 	format_add_cb(ft, "window_visible_layout",
1374 	    format_cb_window_visible_layout);
1375 	format_add(ft, "window_panes", "%u", window_count_panes(w));
1376 	format_add(ft, "window_zoomed_flag", "%d",
1377 	    !!(w->flags & WINDOW_ZOOMED));
1378 }
1379 
1380 /* Set default format keys for a winlink. */
1381 static void
1382 format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
1383 {
1384 	struct session	*s = wl->session;
1385 	struct window	*w = wl->window;
1386 
1387 	if (ft->w == NULL)
1388 		ft->w = wl->window;
1389 	ft->wl = wl;
1390 
1391 	format_defaults_window(ft, w);
1392 
1393 	format_add(ft, "window_index", "%d", wl->idx);
1394 	format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
1395 	format_add(ft, "window_flags", "%s", window_printable_flags(wl));
1396 	format_add(ft, "window_active", "%d", wl == s->curw);
1397 
1398 	format_add(ft, "window_bell_flag", "%d",
1399 	    !!(wl->flags & WINLINK_BELL));
1400 	format_add(ft, "window_activity_flag", "%d",
1401 	    !!(wl->flags & WINLINK_ACTIVITY));
1402 	format_add(ft, "window_silence_flag", "%d",
1403 	    !!(wl->flags & WINLINK_SILENCE));
1404 	format_add(ft, "window_last_flag", "%d",
1405 	    !!(wl == TAILQ_FIRST(&s->lastw)));
1406 	format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
1407 }
1408 
1409 /* Set default format keys for a window pane. */
1410 void
1411 format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
1412 {
1413 	struct grid	*gd = wp->base.grid;
1414 	int  		 status = wp->status;
1415 	u_int		 idx;
1416 
1417 	if (ft->w == NULL)
1418 		ft->w = wp->window;
1419 	ft->wp = wp;
1420 
1421 	format_add(ft, "history_size", "%u", gd->hsize);
1422 	format_add(ft, "history_limit", "%u", gd->hlimit);
1423 	format_add_cb(ft, "history_bytes", format_cb_history_bytes);
1424 
1425 	if (window_pane_index(wp, &idx) != 0)
1426 		fatalx("index not found");
1427 	format_add(ft, "pane_index", "%u", idx);
1428 
1429 	format_add(ft, "pane_width", "%u", wp->sx);
1430 	format_add(ft, "pane_height", "%u", wp->sy);
1431 	format_add(ft, "pane_title", "%s", wp->base.title);
1432 	format_add(ft, "pane_id", "%%%u", wp->id);
1433 	format_add(ft, "pane_active", "%d", wp == wp->window->active);
1434 	format_add(ft, "pane_input_off", "%d", !!(wp->flags & PANE_INPUTOFF));
1435 	format_add(ft, "pane_pipe", "%d", wp->pipe_fd != -1);
1436 
1437 	if ((wp->flags & PANE_STATUSREADY) && WIFEXITED(status))
1438 		format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
1439 	format_add(ft, "pane_dead", "%d", wp->fd == -1);
1440 
1441 	if (window_pane_visible(wp)) {
1442 		format_add(ft, "pane_left", "%u", wp->xoff);
1443 		format_add(ft, "pane_top", "%u", wp->yoff);
1444 		format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
1445 		format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
1446 		format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
1447 		format_add(ft, "pane_at_top", "%d", wp->yoff == 0);
1448 		format_add(ft, "pane_at_right", "%d",
1449 		    wp->xoff + wp->sx == wp->window->sx);
1450 		format_add(ft, "pane_at_bottom", "%d",
1451 		    wp->yoff + wp->sy == wp->window->sy);
1452 	}
1453 
1454 	format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
1455 	if (wp->mode != NULL)
1456 		format_add(ft, "pane_mode", "%s", wp->mode->name);
1457 
1458 	format_add(ft, "pane_synchronized", "%d",
1459 	    !!options_get_number(wp->window->options, "synchronize-panes"));
1460 	if (wp->searchstr != NULL)
1461 		format_add(ft, "pane_search_string", "%s", wp->searchstr);
1462 
1463 	format_add(ft, "pane_tty", "%s", wp->tty);
1464 	format_add(ft, "pane_pid", "%ld", (long) wp->pid);
1465 	format_add_cb(ft, "pane_start_command", format_cb_start_command);
1466 	format_add_cb(ft, "pane_current_command", format_cb_current_command);
1467 
1468 	format_add(ft, "cursor_x", "%u", wp->base.cx);
1469 	format_add(ft, "cursor_y", "%u", wp->base.cy);
1470 	format_add(ft, "scroll_region_upper", "%u", wp->base.rupper);
1471 	format_add(ft, "scroll_region_lower", "%u", wp->base.rlower);
1472 
1473 	window_copy_add_formats(wp, ft);
1474 
1475 	format_add(ft, "alternate_on", "%d", wp->saved_grid ? 1 : 0);
1476 	format_add(ft, "alternate_saved_x", "%u", wp->saved_cx);
1477 	format_add(ft, "alternate_saved_y", "%u", wp->saved_cy);
1478 
1479 	format_add(ft, "cursor_flag", "%d",
1480 	    !!(wp->base.mode & MODE_CURSOR));
1481 	format_add(ft, "insert_flag", "%d",
1482 	    !!(wp->base.mode & MODE_INSERT));
1483 	format_add(ft, "keypad_cursor_flag", "%d",
1484 	    !!(wp->base.mode & MODE_KCURSOR));
1485 	format_add(ft, "keypad_flag", "%d",
1486 	    !!(wp->base.mode & MODE_KKEYPAD));
1487 	format_add(ft, "wrap_flag", "%d",
1488 	    !!(wp->base.mode & MODE_WRAP));
1489 
1490 	format_add(ft, "mouse_any_flag", "%d",
1491 	    !!(wp->base.mode & ALL_MOUSE_MODES));
1492 	format_add(ft, "mouse_standard_flag", "%d",
1493 	    !!(wp->base.mode & MODE_MOUSE_STANDARD));
1494 	format_add(ft, "mouse_button_flag", "%d",
1495 	    !!(wp->base.mode & MODE_MOUSE_BUTTON));
1496 	format_add(ft, "mouse_all_flag", "%d",
1497 	    !!(wp->base.mode & MODE_MOUSE_ALL));
1498 
1499 	format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
1500 }
1501 
1502 /* Set default format keys for paste buffer. */
1503 void
1504 format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
1505 {
1506 	struct timeval	 tv;
1507 	size_t		 size;
1508 	char		*s;
1509 
1510 	timerclear(&tv);
1511 	tv.tv_sec = paste_buffer_created(pb);
1512 	paste_buffer_data(pb, &size);
1513 
1514 	format_add(ft, "buffer_size", "%zu", size);
1515 	format_add(ft, "buffer_name", "%s", paste_buffer_name(pb));
1516 	format_add_tv(ft, "buffer_created", &tv);
1517 
1518 	s = paste_make_sample(pb);
1519 	format_add(ft, "buffer_sample", "%s", s);
1520 	free(s);
1521 }
1522