GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/control-notify.c Lines: 0 59 0.0 %
Date: 2016-12-06 Branches: 0 76 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: control-notify.c,v 1.16 2016/01/19 15:59:12 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
5
 * Copyright (c) 2012 George Nachman <tmux@georgester.com>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
22
#include <stdlib.h>
23
24
#include "tmux.h"
25
26
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
27
	((c) != NULL && ((c)->flags & CLIENT_CONTROL))
28
29
void
30
control_notify_input(struct client *c, struct window_pane *wp,
31
    struct evbuffer *input)
32
{
33
	u_char		*buf;
34
	size_t		 len;
35
	struct evbuffer *message;
36
	u_int		 i;
37
38
	if (c->session == NULL)
39
	    return;
40
41
	buf = EVBUFFER_DATA(input);
42
	len = EVBUFFER_LENGTH(input);
43
44
	/*
45
	 * Only write input if the window pane is linked to a window belonging
46
	 * to the client's session.
47
	 */
48
	if (winlink_find_by_window(&c->session->windows, wp->window) != NULL) {
49
		message = evbuffer_new();
50
		evbuffer_add_printf(message, "%%output %%%u ", wp->id);
51
		for (i = 0; i < len; i++) {
52
			if (buf[i] < ' ' || buf[i] == '\\')
53
			    evbuffer_add_printf(message, "\\%03o", buf[i]);
54
			else
55
			    evbuffer_add_printf(message, "%c", buf[i]);
56
		}
57
		control_write_buffer(c, message);
58
		evbuffer_free(message);
59
	}
60
}
61
62
void
63
control_notify_window_layout_changed(struct window *w)
64
{
65
	struct client		*c;
66
	struct session		*s;
67
	struct format_tree	*ft;
68
	struct winlink		*wl;
69
	const char		*template;
70
	char			*expanded;
71
72
	template = "%layout-change #{window_id} #{window_layout} "
73
	    "#{window_visible_layout} #{window_flags}";
74
75
	TAILQ_FOREACH(c, &clients, entry) {
76
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
77
			continue;
78
		s = c->session;
79
80
		if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
81
			continue;
82
83
		/*
84
		 * When the last pane in a window is closed it won't have a
85
		 * layout root and we don't need to inform the client about the
86
		 * layout change because the whole window will go away soon.
87
		 */
88
		if (w->layout_root == NULL)
89
			continue;
90
91
		ft = format_create(NULL, 0);
92
		wl = winlink_find_by_window(&s->windows, w);
93
		if (wl != NULL) {
94
			format_defaults(ft, c, NULL, wl, NULL);
95
			expanded = format_expand(ft, template);
96
			control_write(c, "%s", expanded);
97
			free(expanded);
98
		}
99
		format_free(ft);
100
	}
101
}
102
103
void
104
control_notify_window_unlinked(__unused struct session *s, struct window *w)
105
{
106
	struct client	*c;
107
	struct session	*cs;
108
109
	TAILQ_FOREACH(c, &clients, entry) {
110
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
111
			continue;
112
		cs = c->session;
113
114
		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
115
			control_write(c, "%%window-close @%u", w->id);
116
		else
117
			control_write(c, "%%unlinked-window-close @%u", w->id);
118
	}
119
}
120
121
void
122
control_notify_window_linked(__unused struct session *s, struct window *w)
123
{
124
	struct client	*c;
125
	struct session	*cs;
126
127
	TAILQ_FOREACH(c, &clients, entry) {
128
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
129
			continue;
130
		cs = c->session;
131
132
		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
133
			control_write(c, "%%window-add @%u", w->id);
134
		else
135
			control_write(c, "%%unlinked-window-add @%u", w->id);
136
	}
137
}
138
139
void
140
control_notify_window_renamed(struct window *w)
141
{
142
	struct client	*c;
143
	struct session	*cs;
144
145
	TAILQ_FOREACH(c, &clients, entry) {
146
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
147
			continue;
148
		cs = c->session;
149
150
		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
151
			control_write(c, "%%window-renamed @%u %s", w->id,
152
			    w->name);
153
		} else {
154
			control_write(c, "%%unlinked-window-renamed @%u %s",
155
			    w->id, w->name);
156
		}
157
	}
158
}
159
160
void
161
control_notify_attached_session_changed(struct client *c)
162
{
163
	struct session	*s;
164
165
	if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
166
		return;
167
	s = c->session;
168
169
	control_write(c, "%%session-changed $%u %s", s->id, s->name);
170
}
171
172
void
173
control_notify_session_renamed(struct session *s)
174
{
175
	struct client	*c;
176
177
	TAILQ_FOREACH(c, &clients, entry) {
178
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
179
			continue;
180
181
		control_write(c, "%%session-renamed $%u %s", s->id, s->name);
182
	}
183
}
184
185
void
186
control_notify_session_created(__unused struct session *s)
187
{
188
	struct client	*c;
189
190
	TAILQ_FOREACH(c, &clients, entry) {
191
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
192
			continue;
193
194
		control_write(c, "%%sessions-changed");
195
	}
196
}
197
198
void
199
control_notify_session_close(__unused struct session *s)
200
{
201
	struct client	*c;
202
203
	TAILQ_FOREACH(c, &clients, entry) {
204
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
205
			continue;
206
207
		control_write(c, "%%sessions-changed");
208
	}
209
}