1*b52f0cbfSnicm /* $OpenBSD: names.c,v 1.45 2021/08/20 17:50:42 nicm Exp $ */
2311827fbSnicm
3311827fbSnicm /*
498ca8272Snicm * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5311827fbSnicm *
6311827fbSnicm * Permission to use, copy, modify, and distribute this software for any
7311827fbSnicm * purpose with or without fee is hereby granted, provided that the above
8311827fbSnicm * copyright notice and this permission notice appear in all copies.
9311827fbSnicm *
10311827fbSnicm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11311827fbSnicm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12311827fbSnicm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13311827fbSnicm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14311827fbSnicm * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15311827fbSnicm * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16311827fbSnicm * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17311827fbSnicm */
18311827fbSnicm
19311827fbSnicm #include <sys/types.h>
20311827fbSnicm
21311827fbSnicm #include <ctype.h>
22311827fbSnicm #include <libgen.h>
237d053cf9Snicm #include <stdlib.h>
24311827fbSnicm #include <string.h>
25311827fbSnicm
26311827fbSnicm #include "tmux.h"
27311827fbSnicm
289883b791Snicm static void name_time_callback(int, short, void *);
299883b791Snicm static int name_time_expired(struct window *, struct timeval *);
30f5015e68Snicm
31ced21769Snicm static char *format_window_name(struct window *);
32ced21769Snicm
339883b791Snicm static void
name_time_callback(__unused int fd,__unused short events,void * arg)34d0e2e7f1Snicm name_time_callback(__unused int fd, __unused short events, void *arg)
35311827fbSnicm {
3600b2deccSnicm struct window *w = arg;
37f5015e68Snicm
3800b2deccSnicm /* The event loop will call check_window_name for us on the way out. */
3900b2deccSnicm log_debug("@%u name timer expired", w->id);
4000b2deccSnicm }
41f5015e68Snicm
429883b791Snicm static int
name_time_expired(struct window * w,struct timeval * tv)4300b2deccSnicm name_time_expired(struct window *w, struct timeval *tv)
4400b2deccSnicm {
4500b2deccSnicm struct timeval offset;
4600b2deccSnicm
4700b2deccSnicm timersub(tv, &w->name_time, &offset);
4800b2deccSnicm if (offset.tv_sec != 0 || offset.tv_usec > NAME_INTERVAL)
4900b2deccSnicm return (0);
5000b2deccSnicm return (NAME_INTERVAL - offset.tv_usec);
51f5015e68Snicm }
52f5015e68Snicm
53f5015e68Snicm void
check_window_name(struct window * w)5400b2deccSnicm check_window_name(struct window *w)
55f5015e68Snicm {
5600b2deccSnicm struct timeval tv, next;
57203ea44bSnicm char *name;
5800b2deccSnicm int left;
59311827fbSnicm
60a3560846Snicm if (w->active == NULL)
61a3560846Snicm return;
62a3560846Snicm
63d89252e5Snicm if (!options_get_number(w->options, "automatic-rename"))
6400b2deccSnicm return;
6500b2deccSnicm
6600b2deccSnicm if (~w->active->flags & PANE_CHANGED) {
6700b2deccSnicm log_debug("@%u active pane not changed", w->id);
6891e80530Snicm return;
69f5015e68Snicm }
7000b2deccSnicm log_debug("@%u active pane changed", w->id);
71b0b8e5bfSnicm
7200b2deccSnicm gettimeofday(&tv, NULL);
7300b2deccSnicm left = name_time_expired(w, &tv);
7400b2deccSnicm if (left != 0) {
7500b2deccSnicm if (!event_initialized(&w->name_event))
7600b2deccSnicm evtimer_set(&w->name_event, name_time_callback, w);
7700b2deccSnicm if (!evtimer_pending(&w->name_event, NULL)) {
786ae61da3Snicm log_debug("@%u name timer queued (%d left)", w->id,
796ae61da3Snicm left);
8000b2deccSnicm timerclear(&next);
8100b2deccSnicm next.tv_usec = left;
8200b2deccSnicm event_add(&w->name_event, &next);
836ae61da3Snicm } else {
846ae61da3Snicm log_debug("@%u name timer already queued (%d left)",
856ae61da3Snicm w->id, left);
866ae61da3Snicm }
875b9cc8aaSnicm return;
8800b2deccSnicm }
8900b2deccSnicm memcpy(&w->name_time, &tv, sizeof w->name_time);
9000b2deccSnicm if (event_initialized(&w->name_event))
9100b2deccSnicm evtimer_del(&w->name_event);
9200b2deccSnicm
935b9cc8aaSnicm w->active->flags &= ~PANE_CHANGED;
945b9cc8aaSnicm
95203ea44bSnicm name = format_window_name(w);
96203ea44bSnicm if (strcmp(name, w->name) != 0) {
9700b2deccSnicm log_debug("@%u new name %s (was %s)", w->id, name, w->name);
98203ea44bSnicm window_set_name(w, name);
9901c0c428Snicm server_redraw_window_borders(w);
100311827fbSnicm server_status_window(w);
10100b2deccSnicm } else
10200b2deccSnicm log_debug("@%u name not changed (still %s)", w->id, w->name);
10300b2deccSnicm
104203ea44bSnicm free(name);
105311827fbSnicm }
106311827fbSnicm
107311827fbSnicm char *
default_window_name(struct window * w)108311827fbSnicm default_window_name(struct window *w)
109311827fbSnicm {
11058034113Snicm char *cmd, *s;
11158034113Snicm
112c6ae5393Snicm if (w->active == NULL)
113c6ae5393Snicm return (xstrdup(""));
11458034113Snicm cmd = cmd_stringify_argv(w->active->argc, w->active->argv);
11558034113Snicm if (cmd != NULL && *cmd != '\0')
11658034113Snicm s = parse_window_name(cmd);
11758034113Snicm else
11858034113Snicm s = parse_window_name(w->active->shell);
11958034113Snicm free(cmd);
12058034113Snicm return (s);
121311827fbSnicm }
122311827fbSnicm
123ced21769Snicm static char *
format_window_name(struct window * w)124203ea44bSnicm format_window_name(struct window *w)
125203ea44bSnicm {
126203ea44bSnicm struct format_tree *ft;
12724a64db7Snicm const char *fmt;
12824a64db7Snicm char *name;
129203ea44bSnicm
130d559dd45Snicm ft = format_create(NULL, NULL, FORMAT_WINDOW|w->id, 0);
131f426771eSnicm format_defaults_window(ft, w);
132f426771eSnicm format_defaults_pane(ft, w->active);
133203ea44bSnicm
134d89252e5Snicm fmt = options_get_string(w->options, "automatic-rename-format");
135203ea44bSnicm name = format_expand(ft, fmt);
136203ea44bSnicm
137203ea44bSnicm format_free(ft);
138203ea44bSnicm return (name);
139203ea44bSnicm }
140203ea44bSnicm
141203ea44bSnicm char *
parse_window_name(const char * in)14266fd4858Snicm parse_window_name(const char *in)
143311827fbSnicm {
14466fd4858Snicm char *copy, *name, *ptr;
145311827fbSnicm
146311827fbSnicm name = copy = xstrdup(in);
1473fa4d618Snicm if (*name == '"')
1483fa4d618Snicm name++;
1493fa4d618Snicm name[strcspn(name, "\"")] = '\0';
1503fa4d618Snicm
15166fd4858Snicm if (strncmp(name, "exec ", (sizeof "exec ") - 1) == 0)
15266fd4858Snicm name = name + (sizeof "exec ") - 1;
153311827fbSnicm
154203ea44bSnicm while (*name == ' ' || *name == '-')
155311827fbSnicm name++;
156311827fbSnicm if ((ptr = strchr(name, ' ')) != NULL)
157311827fbSnicm *ptr = '\0';
158311827fbSnicm
159311827fbSnicm if (*name != '\0') {
160311827fbSnicm ptr = name + strlen(name) - 1;
161d4dc61b7Snicm while (ptr > name &&
162d4dc61b7Snicm !isalnum((u_char)*ptr) &&
163d4dc61b7Snicm !ispunct((u_char)*ptr))
164311827fbSnicm *ptr-- = '\0';
165311827fbSnicm }
166311827fbSnicm
167311827fbSnicm if (*name == '/')
168311827fbSnicm name = basename(name);
169311827fbSnicm name = xstrdup(name);
1707d053cf9Snicm free(copy);
171311827fbSnicm return (name);
172311827fbSnicm }
173